/* Wisploft — the public site.
 *
 * Written by hand rather than built: the deploy target has no Node, and
 * skipping the build removes a whole class of deployment failure.
 *
 * The page commits to one light world: crisp paper, navy ink and one calm
 * Dutch-blue accent. It should feel more trusted and premium than decorative,
 * without becoming a banking dashboard.
 *
 * Two rules hold the layout together:
 *   1. One accent. If a second colour is needed to explain something, the
 *      explanation is wrong.
 *   2. Vertical rhythm comes from --act-y and nothing else, so the page can be
 *      made tighter or looser in one place.
 */

/* ============================================================ tokens ==== */

:root {
  /* Dutch Trust Navy: cool paper, white surfaces, deep navy type. */
  --paper:      #F8FAFC;
  --paper-2:    #E8ECF1;
  --surface:    #FFFFFF;

  --ink:        #020617;
  --ink-soft:   #475569;
  --ink-faint:  #64748B;

  /* Hairlines carry the structure, so shadows barely have to. */
  --edge:       rgba(15, 23, 42, .13);
  --edge-soft:  rgba(15, 23, 42, .065);

  /* Calm enough for trust, deep enough to stay premium. */
  --accent:      #235A88;
  --accent-deep: #09253C;
  --accent-soft: #EAF1F8;

  --shadow-sm: 0 1px 2px rgba(15,23,42,.04), 0 4px 10px -6px rgba(15,23,42,.12);
  --shadow-lg: 0 2px 4px rgba(15,23,42,.03), 0 24px 48px -32px rgba(15,23,42,.30);

  --font-sans: "Instrument Sans", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  --ease: cubic-bezier(.22, .61, .36, 1);

  --gutter-base: clamp(1.25rem, 5vw, 4.5rem);
  --gutter: max(var(--gutter-base), env(safe-area-inset-left), env(safe-area-inset-right));

  /* The whole page's pace lives here. It used to be twice this, which is why
     the site read as six and a half screens of mostly nothing. */
  --act-y: clamp(3.5rem, 7.5vh, 5.5rem);
}

* { box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
  scroll-padding-top: 2rem;
}
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background:
    radial-gradient(circle at 50% -18rem, rgba(35,90,136,.08), transparent 34rem),
    var(--paper);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: 16.5px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}


/* ======================================================== typography ==== */

/* The scale is deliberately short. A 112px headline was not confidence, it was
   a headline with nothing under it — and it pushed everything else off screen. */
h1, h2, h3 { margin: 0; font-weight: 500; letter-spacing: -.032em; text-wrap: balance; }

h1 { font-size: clamp(2.5rem, 1.9rem + 2.9vw, 4.15rem); line-height: 1.03; }
h2 { font-size: clamp(1.7rem, 1.4rem + 1.5vw, 2.45rem); line-height: 1.12; }
h3 { font-size: clamp(1.05rem, 1rem + .3vw, 1.22rem); line-height: 1.25; letter-spacing: -.018em; }
p  { margin: 0; }

.lede    { font-size: clamp(1.02rem, .97rem + .35vw, 1.22rem); line-height: 1.5; color: var(--ink-soft); max-width: 34ch; }
.body    { font-size: 1rem; line-height: 1.62; color: var(--ink-soft); max-width: 46ch; }
.caption { font-size: .875rem; line-height: 1.55; color: var(--ink-faint); max-width: 40ch; }

.eyebrow {
  font-family: var(--font-mono);
  font-size: .7rem;
  letter-spacing: .17em;
  text-transform: uppercase;
  color: var(--accent);
}

.mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }

a { color: var(--accent); }
.text-link {
  color: var(--accent);
  font-weight: 500;
  text-decoration: none;
  border-bottom: 1px solid rgba(31, 77, 122, .28);
}
.text-link:hover { border-color: currentColor; }

.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}
.trap { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* ============================================================= acts ===== */

.act { position: relative; padding: var(--act-y) var(--gutter); }
.act--tint { background: var(--paper-2); }

/* A hairline instead of a colour change, where the sections are close enough
   in tone that a band would be too much. */
.act--ruled { border-top: 1px solid var(--edge-soft); }

.inner { max-width: 72rem; margin: 0 auto; width: 100%; }

.act__head { display: flex; flex-direction: column; gap: .9rem; margin-bottom: clamp(2rem, 4vh, 3rem); }
.act__head h2 { max-width: 20ch; }

/* ============================================================ motion ==== */

/* Reveal-on-scroll was here and has been taken out. Two reasons, and the
   second is the real one:
     1. It leaves content at opacity 0 until a scroll timeline says otherwise,
        so any browser that reads the range differently renders a blank page.
     2. It reads as a template. A page that withholds its own text until you
        scroll is performing, and the whole point of this design is restraint.
   What is left is one entrance, once, on what is already on screen. */
@media (prefers-reduced-motion: no-preference) {
  .hero .rise {
    animation: rise .65s var(--ease) both;
  }
  .hero .rise:nth-child(2) { animation-delay: .05s; }
  .hero .rise:nth-child(3) { animation-delay: .10s; }
  .hero .rise:nth-child(4) { animation-delay: .15s; }
  .hero .rise:nth-child(5) { animation-delay: .20s; }
  .hero__stage.rise        { animation-delay: .12s; }
}

@keyframes rise {
  from { opacity: 0; transform: translateY(.85rem); }
  to   { opacity: 1; transform: none; }
}

/* ============================================================ buttons === */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .45rem;
  min-height: 3rem;
  padding: .76rem 1.48rem;
  border-radius: 999px;
  border: 1px solid transparent;
  font: inherit; font-weight: 500; font-size: .95rem;
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  box-shadow: 0 1px 1px rgba(15,23,42,.04);
  transition:
    background-color .2s var(--ease),
    border-color .2s var(--ease),
    color .2s var(--ease),
    box-shadow .2s var(--ease),
    transform .2s var(--ease);
}
.btn--primary {
  background: linear-gradient(180deg, #0D1728, var(--accent-deep));
  color: #FFFFFF;
  box-shadow: 0 18px 42px -28px rgba(9,37,60,.82), inset 0 1px 0 rgba(255,255,255,.12);
}
.btn--primary:hover {
  background: linear-gradient(180deg, #12385C, var(--accent));
  box-shadow: 0 20px 46px -30px rgba(35,90,136,.78), inset 0 1px 0 rgba(255,255,255,.16);
}
.btn--ghost { background: rgba(255,255,255,.4); color: var(--ink); border-color: var(--edge); }
.btn--ghost:hover { border-color: var(--accent); color: var(--accent); }
.btn:active { transform: scale(.985); }
.btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

@media (prefers-reduced-motion: reduce) { .btn { transition: none; } }

/* ============================================================== form ==== */

.startform { display: flex; flex-wrap: wrap; gap: .7rem; align-items: center; }

.startform input[type=text] {
  font: inherit;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--edge);
  border-radius: 999px;
  padding: .8rem 1.3rem;
  min-height: 3rem;
  min-width: 0;
  flex: 1 1 17rem;
  box-shadow: var(--shadow-sm);
}
.startform input::placeholder { color: var(--ink-faint); }
.startform input:focus-visible {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

@media (max-width: 32rem) {
  .startform { flex-direction: column; align-items: stretch; }
  .startform .btn { width: 100%; }

  /* Once the row becomes a column, flex-basis stops meaning width and starts
     meaning height — which turned a 17rem basis into a field the size of a
     dinner plate. */
  .startform input[type=text] { flex: 0 0 auto; width: 100%; }
}

/* ============================================================== hero ==== */

.hero {
  min-height: min(48rem, calc(100svh - 4.2rem));
  display: flex;
  align-items: center;
  padding-top: clamp(2.4rem, 5.5vh, 4.2rem);
  padding-bottom: clamp(3.75rem, 7vh, 5.75rem);
}

.hero__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr);
  gap: clamp(2rem, 5vw, 5rem);
  align-items: center;
}
@media (max-width: 58rem) {
  .hero__grid { grid-template-columns: minmax(0, 1fr); gap: 2.75rem; }
}

.hero__copy { display: flex; flex-direction: column; gap: 1.45rem; max-width: 34rem; }
.hero h1 em { font-style: italic; font-weight: 400; color: var(--accent); }

.hero__stage { justify-self: center; }
.hero__actions { display: flex; flex-wrap: wrap; gap: .8rem; align-items: center; }

/* The headline and the form come first on a phone, always. This is a
   mobile-first product (brief §15) and the mock is an illustration — putting
   it above the fold pushed the one sentence that explains the product, and the
   field that starts it, off the bottom of the screen. */
@media (max-width: 58rem) {
  .hero__stage { order: 1; }
  .phone { width: min(15.5rem, 62vw); }
}
@media (max-width: 44rem) {
  .hero {
    min-height: calc(100svh + 1.8rem);
    align-items: flex-start;
    padding-top: 1.95rem;
    padding-bottom: 7.2rem;
  }
  .hero__copy { gap: 1.22rem; }
  .hero__grid { gap: 1.35rem; }
  .hero__stage { display: none; }
}

@media (orientation: landscape) and (max-height: 30rem) {
  .hero {
    min-height: auto;
    align-items: flex-start;
    padding-top: 1.25rem;
    padding-bottom: 1.6rem;
  }
  .hero__grid {
    grid-template-columns: minmax(0, 1fr);
    gap: 1rem;
  }
  .hero__copy { gap: .7rem; max-width: 35rem; }
  .hero h1 { font-size: clamp(2.2rem, 5.2vw, 2.75rem); line-height: .98; }
  .hero .lede { max-width: 43ch; line-height: 1.42; }
  .hero__stage,
  .hero .caption,
  .hero .proof-strip {
    display: none;
  }
}

.proof-strip {
  display: flex;
  flex-wrap: wrap;
  gap: .45rem;
  max-width: 34rem;
}
.proof-strip span {
  border: 1px solid rgba(15,23,42,.11);
  background: rgba(255, 255, 255, .58);
  border-radius: .5rem;
  color: var(--ink-soft);
  font-size: .78rem;
  padding: .32rem .6rem;
}

/* ============================================================= phone ==== */

/* The product, shown rather than described. Kept because a wishlist is a
   visual thing and one honest screenshot argues better than a paragraph. */
.phone {
  width: min(19rem, 78vw);
  aspect-ratio: 9 / 15.8;
  border-radius: 2.4rem;
  padding: .5rem;
  background: linear-gradient(170deg, #FFFFFF, var(--paper-2));
  border: 1px solid var(--edge);
  box-shadow: var(--shadow-lg);
}

.phone__glass {
  height: 100%;
  border-radius: 2rem;
  background: var(--surface);
  border: 1px solid var(--edge-soft);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.status {
  display: flex; justify-content: space-between;
  padding: .7rem 1.1rem .3rem;
  font-family: var(--font-mono);
  font-size: .62rem;
  color: var(--ink-faint);
}

.screen { padding: .85rem 1rem 1rem; display: flex; flex-direction: column; gap: .7rem; flex: 1; min-height: 0; }
/* The masthead a dressed list actually renders: occasion above the name, a
   short rule under it. The hero used to show a plainer page than the product
   makes. */
.screen__head { display: flex; flex-direction: column; gap: .18rem; }
.screen__occasion {
  color: var(--accent);
  font-size: .56rem;
  font-weight: 600;
  letter-spacing: .18em;
  text-transform: uppercase;
}
.screen__title { font-size: 1.08rem; font-weight: 500; letter-spacing: -.025em; line-height: 1.15; }
.screen__rule { width: 1.9rem; height: 1px; margin-top: .3rem; background: var(--accent); }
.screen__sub { font-size: .78rem; color: var(--ink-faint); }

.gift {
  display: grid; grid-template-columns: 2.1rem minmax(0, 1fr); gap: .6rem;
  align-items: center;
  padding: .55rem .6rem;
  border-radius: .7rem;
  background: var(--paper);
  border: 1px solid var(--edge-soft);
}
/* The same drawn mark the real gift card falls back to. It used to be an
   emoji, and emoji appear nowhere else in the product. */
.gift__thumb {
  position: relative;
  width: 2.1rem; height: 2.1rem;
  border-radius: .45rem;
  background: var(--paper-2, #F2EFE9);
  border: 1px solid var(--edge-soft);
  display: grid; place-items: center;
}
.gift__thumb::before {
  content: "";
  width: .82rem; height: .68rem;
  border: 1.4px solid var(--accent);
  border-radius: .16rem;
  opacity: .55;
}
.gift__thumb i {
  position: absolute;
  width: .38rem; height: .26rem;
  margin-top: -.62rem;
  border: 1.4px solid var(--accent);
  border-bottom: 0;
  border-radius: .28rem .28rem 0 0;
  opacity: .55;
}
.gift__name { font-size: .8rem; font-weight: 500; letter-spacing: -.01em; }
.gift__meta { font-size: .7rem; color: var(--ink-faint); display: flex; gap: .45rem; align-items: baseline; flex-wrap: wrap; }

.tag {
  display: inline-flex; align-items: center; align-self: flex-start;
  font-size: .66rem; padding: .16rem .5rem; border-radius: 999px;
  border: 1px solid var(--edge); color: var(--ink-faint); white-space: nowrap;
}
.tag--held { border-color: transparent; background: #F6EEDF; color: #7A5717; }
.tag--open { border-color: rgba(31,77,122,.35); color: var(--accent); }

.linkbox {
  margin-top: auto;
  border-radius: .7rem;
  padding: .6rem .7rem;
  background: var(--accent-soft);
  display: flex; flex-direction: column; gap: .15rem;
}
.linkbox .k { font-size: .6rem; letter-spacing: .11em; text-transform: uppercase; color: var(--accent); }
.linkbox .v { font-family: var(--font-mono); font-size: .74rem; word-break: break-all; }

/* ============================================================= steps ==== */

/* Three beats, side by side. They used to be a sticky scroll three screens
   tall, which spent a great deal of the reader's patience on three sentences. */
.steps { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: clamp(1.5rem, 3vw, 3rem); }
@media (max-width: 54rem) { .steps { grid-template-columns: minmax(0, 1fr); gap: 2rem; } }

.step { display: flex; flex-direction: column; gap: .55rem; padding-top: 1.1rem; border-top: 1px solid var(--edge); }
.step__n { font-family: var(--font-mono); font-size: .7rem; letter-spacing: .17em; text-transform: uppercase; color: var(--accent); }
.step .caption { max-width: 34ch; }

/* ============================================================== duo ===== */

.duo { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: clamp(1.75rem, 4vw, 3.5rem); align-items: start; }
@media (max-width: 54rem) { .duo { grid-template-columns: minmax(0, 1fr); gap: 2.25rem; } }

.shops { display: flex; flex-wrap: wrap; gap: .45rem; margin-top: 1.25rem; }
.shops span {
  font-size: .8rem;
  padding: .35rem .75rem;
  border-radius: 999px;
  border: 1px solid var(--edge);
  color: var(--ink-soft);
  background: var(--surface);
}
.shops span:last-child { border-style: dashed; color: var(--ink-faint); }

/* =========================================================== compare ==== */

.compare { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .8rem; margin-top: 1.5rem; }
@media (max-width: 30rem) { .compare { grid-template-columns: minmax(0, 1fr); } }

.compare__col {
  background: var(--surface);
  border: 1px solid var(--edge-soft);
  border-radius: .9rem;
  padding: .95rem;
  display: flex; flex-direction: column; gap: .55rem;
  box-shadow: var(--shadow-sm);
}
.compare__who { display: flex; flex-direction: column; gap: .1rem; }
.compare__who span { font-size: .82rem; font-weight: 500; }
.compare__who .mono { font-size: .68rem; color: var(--ink-faint); font-weight: 400; }

/* ======================================================= product proof == */

.product-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1rem;
}
.product-card {
  border-top: 1px solid var(--edge);
  padding-top: 1rem;
  display: flex;
  flex-direction: column;
  gap: .7rem;
}
.product-card__icon {
  width: 2.4rem;
  height: 2.4rem;
  border-radius: .5rem;
  display: grid;
  place-items: center;
  background: var(--accent-soft);
  color: var(--accent);
  font-family: var(--font-mono);
  font-size: .75rem;
}
.product-card .body { font-size: .94rem; }

@media (max-width: 64rem) {
  .product-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 38rem) {
  .product-grid { grid-template-columns: minmax(0, 1fr); }
}

/* ========================================================== services ==== */

.services { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: clamp(1rem, 2.5vw, 1.75rem); }
@media (max-width: 54rem) { .services { grid-template-columns: minmax(0, 1fr); } }

.service {
  background: var(--surface);
  border: 1px solid var(--edge);
  border-radius: .5rem;
  padding: clamp(1.4rem, 3vw, 2rem);
  display: flex; flex-direction: column; gap: .8rem;
  box-shadow: var(--shadow-sm);
}
.service__mark { display: flex; gap: .3rem; align-items: center; margin-bottom: .2rem; }
.service__mark i {
  display: block; width: .5rem; height: .5rem; border-radius: 999px;
  background: var(--accent); opacity: .3; font-style: normal;
}
.service__mark i:first-child { opacity: 1; }
.service__mark i:nth-child(2) { opacity: .6; }
.service .caption { margin-top: auto; padding-top: .4rem; }

/* The six looks, drawn the way the manage page draws them.

   This used to be three empty gradient rectangles standing in for a feature
   whose whole point is that it is visual — the section sold six templates and
   showed nothing at all. These are the same scenes the owner picks from. */
.theme-proof {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: .45rem;
  margin-bottom: .3rem;
}
.look-chip {
  position: relative;
  display: block;
  aspect-ratio: 1 / 1.25;
  border-radius: .5rem;
  overflow: hidden;
  background: #F5F2ED;
}
.look-chip > span {
  position: absolute;
  inset: .32rem .28rem;
  display: block;
  border: 1px solid rgba(25,23,20,.1);
  border-radius: .34rem;
  background: #fff;
  box-shadow: 0 6px 14px -12px rgba(25,23,20,.45);
}
.look-chip i { position: absolute; top: 34%; left: 50%; width: 52%; height: .16rem; border-radius: 1rem; background: #302D29; transform: translateX(-50%); }
.look-chip b, .look-chip em { position: absolute; top: 56%; left: 50%; width: 36%; height: .11rem; border-radius: 1rem; background: #87817A; transform: translateX(-50%); }
.look-chip em { top: 70%; width: 20%; background: #38644A; }

.look-chip--plain > span { display: flex; align-items: flex-end; border: 0; background: linear-gradient(145deg, #fff 65%, #E4EBE5); }
.look-chip--plain i { top: auto; bottom: .6rem; left: .4rem; width: 54%; transform: none; }
.look-chip--plain b { top: auto; bottom: .35rem; left: .4rem; transform: none; }
.look-chip--plain em { display: none; }
.look-chip--birthday > span { border: 0; background: #38644A; }
.look-chip--birthday i, .look-chip--birthday b, .look-chip--birthday em { background: #fff; }
.look-chip--wedding > span { border-color: #A8425C; border-radius: .6rem; box-shadow: inset 0 0 0 .13rem #fff, inset 0 0 0 calc(.13rem + 1px) #EFDDD7; }
.look-chip--baby > span { border-radius: .9rem; background: linear-gradient(145deg, #fff, #E2EDF9); }
.look-chip--baby::after { content: ""; position: absolute; right: .1rem; bottom: 0; width: 1.4rem; height: 1.4rem; border-radius: 50%; background: rgba(49,94,130,.1); }
.look-chip--housewarming > span { border: 0; border-radius: .6rem; background: #1D1D1F; }
.look-chip--housewarming i, .look-chip--housewarming b { left: .34rem; background: #fff; transform: none; }
.look-chip--housewarming em { left: .34rem; width: 26%; background: #fff; transform: none; }
.look-chip--christmas > span { border: 0; background: #345E43; }
.look-chip--christmas i, .look-chip--christmas b { background: #fff; }
.look-chip--christmas em { background: #F6EEDF; }

/* A small invitation rather than an empty box with a caption under it. The
   card next to it now shows six real looks; this one used to be the last
   placeholder left in the section. */
.invite-proof {
  min-height: 7rem;
  border-radius: .5rem;
  padding: 1.1rem 1rem;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: .5rem;
  text-align: center;
  color: #F4EAD2;
  background: radial-gradient(125% 95% at 50% 0%, #2E2B26, #171614);
  box-shadow: inset 0 0 0 1px rgba(212,180,111, .28);
}
.invite-proof span { font-size: 1.15rem; font-weight: 500; }
.invite-proof i {
  width: 3.2rem;
  height: 1px;
  background: rgba(212, 180, 111, .8);
}
.invite-proof small {
  color: rgba(244, 234, 210, .72);
  font-size: .68rem;
  letter-spacing: .16em;
  text-transform: uppercase;
}

/* ============================================== invitation showcase ==== */

.invitation-showcase {
  overflow: hidden;
  background:
    radial-gradient(circle at 80% 20%, rgba(31,77,122,.12), transparent 32rem),
    radial-gradient(circle at 10% 85%, rgba(166,106,23,.10), transparent 28rem),
    var(--surface);
}
.invitation-showcase__grid {
  display: grid;
  grid-template-columns: minmax(0, .9fr) minmax(18rem, 1.1fr);
  gap: clamp(2.25rem, 6vw, 5rem);
  align-items: center;
}
@media (max-width: 58rem) {
  .invitation-showcase__grid { grid-template-columns: minmax(0, 1fr); }
}
.invitation-showcase__copy { display: flex; flex-direction: column; gap: 1.15rem; }
.invitation-showcase__copy h2 { max-width: 13ch; }
.invitation-showcase__copy .body { max-width: 38rem; }

.invite-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: .5rem;
  margin-top: .35rem;
}
.invite-tab {
  appearance: none;
  border: 1px solid rgba(35,35,38,.09);
  border-radius: 999px;
  background: rgba(255,255,255,.72);
  color: var(--ink-soft);
  padding: .62rem .9rem;
  font: inherit;
  font-size: .86rem;
  font-weight: 600;
  box-shadow: 0 8px 24px -22px rgba(29,29,31,.7);
  cursor: pointer;
  transition: transform .18s ease, border-color .18s ease, background .18s ease, color .18s ease;
}
.invite-tab:hover { transform: translateY(-1px); color: var(--ink); }
.invite-tab:focus-visible { outline: 3px solid rgba(31,77,122,.2); outline-offset: 2px; }
.invite-tab.is-active {
  border-color: rgba(29,29,31,.82);
  background: #1D1D1F;
  color: white;
}

.invite-how {
  display: grid;
  gap: .65rem;
  margin-top: .5rem;
}
.invite-how p {
  display: grid;
  grid-template-columns: 2.4rem minmax(0, 1fr);
  gap: .7rem;
  align-items: center;
  margin: 0;
  color: var(--ink-soft);
  line-height: 1.45;
}
.invite-how span {
  display: grid;
  place-items: center;
  width: 2.1rem;
  height: 2.1rem;
  border-radius: 999px;
  background: var(--paper-2);
  color: var(--accent);
  font: 600 .72rem/1 var(--font-mono);
}

.invite-phone {
  position: relative;
  justify-self: center;
  width: min(100%, 32rem);
  border-radius: 3.4rem;
  padding: .8rem;
  background: linear-gradient(145deg, #FDFCF9, #E9E6DF);
  border: 1px solid rgba(29,29,31,.12);
  box-shadow:
    0 34px 90px -58px rgba(29,29,31,.72),
    inset 0 1px 0 rgba(255,255,255,.92);
}
.invite-phone::before {
  content: "";
  position: absolute;
  inset: .42rem;
  border-radius: 3rem;
  border: 1px solid rgba(255,255,255,.8);
  pointer-events: none;
}
.invite-phone__chrome {
  position: absolute;
  z-index: 2;
  top: 1.25rem;
  left: 50%;
  width: 6.1rem;
  height: 1.45rem;
  border-radius: 999px;
  background: rgba(29,29,31,.88);
  transform: translateX(-50%);
  box-shadow: inset 0 -1px 0 rgba(255,255,255,.16);
}
.invite-phone__chrome span {
  position: absolute;
  top: .48rem;
  right: .72rem;
  width: .48rem;
  height: .48rem;
  border-radius: 50%;
  background: rgba(255,255,255,.18);
}
.invite-phone__screen {
  --invite-card-size: min(22rem, calc(100vw - 4rem));
  position: relative;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: var(--invite-card-size);
  justify-content: start;
  gap: 1rem;
  /* One invitation inside the frame at a time.

     The next card used to be chopped off square by the phone's bezel with its
     caption cut mid-word, which reads as a rendering fault rather than as a
     row you can swipe. Masking the gutters rather than widening the gap keeps
     the scroll geometry — and the swipe — exactly as it was. The stops are
     the gutters themselves, so the centred card is never touched, including
     on a phone where those gutters are a few pixels wide. */
  --invite-fade: calc((100% - var(--invite-card-size)) / 2);
  --invite-fade-blend: max(0px, calc(var(--invite-fade) - 1.5rem));
  -webkit-mask-image: linear-gradient(to right, transparent 0, transparent var(--invite-fade-blend), #000 var(--invite-fade), #000 calc(100% - var(--invite-fade)), transparent calc(100% - var(--invite-fade-blend)), transparent 100%);
  mask-image: linear-gradient(to right, transparent 0, transparent var(--invite-fade-blend), #000 var(--invite-fade), #000 calc(100% - var(--invite-fade)), transparent calc(100% - var(--invite-fade-blend)), transparent 100%);
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scroll-padding-inline: calc((100% - var(--invite-card-size)) / 2);
  scrollbar-width: none;
  min-height: 34rem;
  border-radius: 2.65rem;
  padding: 3.6rem calc((100% - var(--invite-card-size)) / 2) 1rem;
  background:
    linear-gradient(180deg, rgba(255,255,255,.82), rgba(255,255,255,.58)),
    #F6F3EE;
}
.invite-phone__screen::-webkit-scrollbar { display: none; }
.invite-slide {
  display: flex;
  flex-direction: column;
  gap: .75rem;
  width: 100%;
  scroll-snap-align: center;
  transition: opacity .18s ease, transform .18s ease;
}
.invite-slide.is-hidden {
  display: none;
}
.invite-slide img,
.invite-art {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 2 / 3;
  border-radius: 2rem;
  object-fit: cover;
  box-shadow: 0 24px 56px -38px rgba(29,29,31,.7);
}
.invite-art {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  overflow: hidden;
  padding: 1.35rem;
  color: #1D1D1F;
  background:
    radial-gradient(circle at 25% 18%, rgba(255,255,255,.78), transparent 7rem),
    linear-gradient(145deg, #F7E2D2, #FDF8F0 46%, #D7E6D9);
}
.invite-art::before,
.invite-art::after {
  content: "";
  position: absolute;
  border-radius: 999px;
  pointer-events: none;
}
.invite-art::before {
  top: 1rem;
  right: -2.5rem;
  width: 9rem;
  height: 9rem;
  background: rgba(255,255,255,.42);
}
.invite-art::after {
  left: 1.1rem;
  bottom: 1.1rem;
  width: 44%;
  height: .42rem;
  background: currentColor;
  opacity: .12;
}
.invite-art span {
  position: absolute;
  top: 1.35rem;
  left: 1.35rem;
  font: 600 .66rem/1 var(--font-mono);
  letter-spacing: .16em;
  text-transform: uppercase;
  opacity: .58;
}
.invite-art strong {
  position: relative;
  z-index: 1;
  max-width: 9ch;
  font-family: "Playfair Display", Georgia, serif;
  font-size: clamp(2.05rem, 8vw, 3.35rem);
  line-height: .92;
  letter-spacing: -.055em;
}
.invite-art i {
  position: relative;
  z-index: 1;
  display: block;
  width: 4.25rem;
  height: 1px;
  margin: 1rem 0 .7rem;
  background: currentColor;
  opacity: .35;
}
.invite-art small {
  position: relative;
  z-index: 1;
  max-width: 16ch;
  color: currentColor;
  opacity: .68;
}
.invite-slide--wedding .invite-art {
  color: #2E2525;
  background:
    radial-gradient(circle at 70% 20%, rgba(166,106,23,.14), transparent 7rem),
    linear-gradient(145deg, #FFFDF8, #EFE1DB);
}
.invite-slide--baby .invite-art {
  color: #263E56;
  background:
    radial-gradient(circle at 80% 78%, rgba(255,255,255,.62), transparent 7rem),
    linear-gradient(145deg, #FDFBF7, #DDEBF8);
}
.invite-slide--home .invite-art {
  color: #F9F4EA;
  background:
    radial-gradient(circle at 72% 20%, rgba(255,255,255,.12), transparent 8rem),
    linear-gradient(145deg, #24372E, #102019);
}
.invite-slide--party .invite-art {
  color: #F8F2E5;
  background:
    radial-gradient(circle at 24% 18%, rgba(246,207,121,.34), transparent 7rem),
    linear-gradient(145deg, #17213D, #485C88);
}
.invite-slide--holiday .invite-art {
  color: #FFF8EC;
  background:
    radial-gradient(circle at 45% 16%, rgba(255,255,255,.22), transparent 6rem),
    linear-gradient(145deg, #234A38, #8B2F35);
}
.invite-slide__caption {
  display: flex;
  flex-direction: column;
  gap: .18rem;
  padding: 0 .25rem;
}
.invite-slide__caption strong { font-size: .95rem; letter-spacing: -.015em; }
.invite-slide__caption span { color: var(--ink-faint); font-size: .78rem; line-height: 1.35; }

.invite-controls {
  display: flex;
  justify-content: center;
  gap: .72rem;
  margin-top: 1rem;
}
.invite-control {
  appearance: none;
  display: grid;
  place-items: center;
  width: 3rem;
  height: 3rem;
  border: 1px solid rgba(29,29,31,.1);
  border-radius: 999px;
  background:
    linear-gradient(180deg, rgba(255,255,255,.94), rgba(246,243,238,.9)),
    #fff;
  color: var(--ink);
  font: inherit;
  font-size: 1.08rem;
  font-weight: 700;
  box-shadow:
    0 18px 44px -30px rgba(29,29,31,.75),
    inset 0 1px 0 rgba(255,255,255,.92);
  cursor: pointer;
  transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease, opacity .18s ease;
}
.invite-control:hover,
.invite-control:focus-visible {
  transform: translateY(-1px);
  border-color: rgba(29,29,31,.22);
  box-shadow:
    0 22px 48px -30px rgba(29,29,31,.9),
    inset 0 1px 0 rgba(255,255,255,.95);
}
.invite-control:focus-visible {
  outline: 3px solid rgba(31,77,122,.2);
  outline-offset: 3px;
}
.invite-control:disabled {
  opacity: .38;
  cursor: default;
  transform: none;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.65);
}

@media (max-width: 38rem) {
  .invitation-showcase {
    border-radius: 2rem 2rem 0 0;
  }
  .invitation-showcase__grid {
    gap: 1.6rem;
  }
  .invitation-showcase__copy {
    gap: .95rem;
  }
  .invitation-showcase__copy h2 {
    max-width: 11ch;
  }
  .invite-tabs {
    flex-wrap: nowrap;
    gap: .45rem;
    margin-inline: calc(var(--gutter) * -1);
    padding: .1rem var(--gutter) .35rem;
    overflow-x: auto;
    scroll-padding-inline: var(--gutter);
    scrollbar-width: none;
  }
  .invite-tabs::-webkit-scrollbar {
    display: none;
  }
  .invite-tab {
    flex: 0 0 auto;
    padding: .58rem .82rem;
    background: rgba(255,255,255,.86);
    box-shadow: 0 12px 26px -22px rgba(29,29,31,.85);
  }
  .invite-how {
    display: none;
  }
  .invite-phone {
    width: min(100%, 22.5rem);
    border: 0;
    border-radius: 0;
    padding: 0;
    background: transparent;
    box-shadow: none;
  }
  .invite-phone::before {
    display: none;
  }
  .invite-phone__chrome {
    display: none;
  }
  .invite-phone__screen {
    min-height: 0;
    grid-auto-columns: 100%;
    gap: .85rem;
    scroll-padding-inline: 0;
    border-radius: 0;
    padding: .2rem 0 .85rem;
    background: transparent;
  }
  .invite-slide {
    scroll-snap-align: start;
    gap: .62rem;
  }
  .invite-slide img,
  .invite-art {
    border: 1px solid rgba(25, 23, 20, .07);
    border-radius: 1.65rem;
    object-fit: cover;
    background: #fff;
    box-shadow:
      0 2px 6px rgba(25,23,20,.04),
      0 28px 62px -42px rgba(25,23,20,.5);
  }
  .invite-slide__caption {
    min-height: 3.15rem;
    padding: .05rem .25rem 0;
  }
  .invite-controls {
    margin-top: .8rem;
    padding-bottom: .2rem;
  }
  .invite-control {
    width: 2.85rem;
    height: 2.85rem;
    background: rgba(29,29,31,.92);
    border-color: rgba(255,255,255,.12);
    color: #fff;
    box-shadow: 0 18px 36px -28px rgba(29,29,31,.85);
  }
}
@media (prefers-reduced-motion: reduce) {
  .invite-tab,
  .invite-slide,
  .invite-control { transition: none; }
}

/* ============================================================= guides === */

.act__head--row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: end;
}
.guide-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1rem;
}
.guide-card {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: .7rem;
}
.guide-card__image {
  display: block;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  border-radius: .5rem;
  border: 1px solid var(--edge);
  background: var(--paper-2);
}
.guide-card__image img {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
}
.guide-card h3 a {
  color: var(--ink);
  text-decoration: none;
}
.guide-card h3 a:hover { color: var(--accent); }
.guide-card p:not(.eyebrow) { color: var(--ink-soft); font-size: .92rem; }
.guide-card .text-link { align-self: flex-start; margin-top: auto; }

@media (max-width: 64rem) {
  .guide-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 42rem) {
  .act__head--row { grid-template-columns: minmax(0, 1fr); }
  .guide-grid { grid-template-columns: minmax(0, 1fr); }
}

/* =========================================================== reviews ==== */

.reviews__head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 1.5rem;
  align-items: end;
}
.reviews__head .body { max-width: 58ch; margin-top: .8rem; }
.reviews__score {
  min-width: 9rem;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: .15rem;
}
.reviews__score strong { font-size: 2rem; line-height: 1; }
.reviews__score small { color: var(--ink-faint); }
.reviews__stars { color: #A66A17; letter-spacing: .08em; white-space: nowrap; }

.reviews__grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1rem;
}
.review-card, .review-mine, .review-form {
  border: 1px solid var(--edge);
  border-radius: .5rem;
  background: var(--surface);
  box-shadow: var(--shadow-sm);
}
.review-card { padding: 1.15rem; display: flex; flex-direction: column; gap: .8rem; }
.review-card__top { display: flex; justify-content: space-between; gap: .75rem; align-items: baseline; }
.review-card p { color: var(--ink-soft); white-space: pre-line; }
.review-card__delete {
  appearance: none;
  border: 0;
  border-bottom: 1px solid var(--edge);
  padding: 0 0 .1rem;
  background: transparent;
  color: var(--ink-faint);
  font: inherit;
  font-size: .78rem;
  cursor: pointer;
}
.reviews__empty { margin-bottom: 1.5rem; }

.review-mine {
  margin-top: 1rem;
  padding: 1rem 1.15rem;
  display: grid;
  grid-template-columns: minmax(9rem, auto) minmax(0, 1fr) auto;
  gap: 1rem;
  align-items: center;
  border-style: dashed;
}
.review-mine > div { display: flex; flex-direction: column; gap: .2rem; }
.review-mine p { color: var(--ink-soft); }

.review-form {
  margin-top: 1.5rem;
  padding: clamp(1.2rem, 3vw, 1.8rem);
  display: flex;
  flex-direction: column;
  gap: .8rem;
}
.review-form label, .review-form legend { color: var(--ink-soft); font-size: .84rem; }

/* These used to inherit nothing at all and rendered as raw browser widgets:
   inset grey borders, Arial 13px, a monospace textarea. The only styled field
   on the page was the hero's, and this one sat right under it. */
.review-form input[type=text],
.review-form textarea {
  font: inherit;
  width: 100%;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--edge);
  border-radius: .8rem;
  padding: .7rem .9rem;
  min-height: 3rem;
  box-shadow: var(--shadow-sm);
}
.review-form textarea {
  min-height: 7.5rem;
  resize: vertical;
  line-height: 1.55;
}
.review-form input[type=text]::placeholder,
.review-form textarea::placeholder { color: var(--ink-faint); }
.review-form input[type=text]:focus-visible,
.review-form textarea:focus-visible {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.review-form__fields { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 1rem; align-items: end; }
.review-form__name { display: flex; flex-direction: column; gap: .35rem; }
.review-form__rating { border: 0; padding: 0; margin: 0; }
.rating-input { display: flex; justify-content: flex-start; min-height: 3rem; align-items: center; }
.rating-input input { position: absolute; opacity: 0; pointer-events: none; }
.rating-input label {
  padding: .2rem;
  color: #C9C1B5;
  font-size: 1.8rem;
  line-height: 1;
  cursor: pointer;
}
.rating-input:has(#review-star-1:checked) label[for="review-star-1"],
.rating-input:has(#review-star-2:checked) label[for="review-star-1"],
.rating-input:has(#review-star-2:checked) label[for="review-star-2"],
.rating-input:has(#review-star-3:checked) label[for="review-star-1"],
.rating-input:has(#review-star-3:checked) label[for="review-star-2"],
.rating-input:has(#review-star-3:checked) label[for="review-star-3"],
.rating-input:has(#review-star-4:checked) label[for="review-star-1"],
.rating-input:has(#review-star-4:checked) label[for="review-star-2"],
.rating-input:has(#review-star-4:checked) label[for="review-star-3"],
.rating-input:has(#review-star-4:checked) label[for="review-star-4"],
.rating-input:has(#review-star-5:checked) label { color: #A66A17; }
.rating-input:has(label[for="review-star-1"]:hover) label[for="review-star-1"],
.rating-input:has(label[for="review-star-2"]:hover) label[for="review-star-1"],
.rating-input:has(label[for="review-star-2"]:hover) label[for="review-star-2"],
.rating-input:has(label[for="review-star-3"]:hover) label[for="review-star-1"],
.rating-input:has(label[for="review-star-3"]:hover) label[for="review-star-2"],
.rating-input:has(label[for="review-star-3"]:hover) label[for="review-star-3"],
.rating-input:has(label[for="review-star-4"]:hover) label[for="review-star-1"],
.rating-input:has(label[for="review-star-4"]:hover) label[for="review-star-2"],
.rating-input:has(label[for="review-star-4"]:hover) label[for="review-star-3"],
.rating-input:has(label[for="review-star-4"]:hover) label[for="review-star-4"],
.rating-input:has(label[for="review-star-5"]:hover) label { color: #A66A17; }
.rating-input input:focus-visible + label { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: .25rem; }
.review-form__foot { display: flex; gap: 1rem; justify-content: space-between; align-items: center; }
.review-form__foot .caption { max-width: 62ch; }

@media (max-width: 54rem) {
  .reviews__grid { grid-template-columns: minmax(0, 1fr); }
  .reviews__head, .review-form__fields { grid-template-columns: minmax(0, 1fr); }
  .reviews__score { align-items: flex-start; }
  .review-mine { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 36rem) {
  .review-form__foot { flex-direction: column; align-items: stretch; }
}

/* ============================================================= close ==== */

.close { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 1.1rem; }
.close .lede { max-width: 42ch; }
.close .startform { justify-content: center; width: min(34rem, 100%); }

/* ============================================================= foot ===== */

.foot {
  border-top: 1px solid var(--edge);
  padding: 2rem var(--gutter) calc(2rem + env(safe-area-inset-bottom));
  color: var(--ink-faint);
  font-size: .85rem;
  background: var(--paper);
}
.foot__inner {
  max-width: 72rem; margin: 0 auto;
  display: flex; flex-wrap: wrap; gap: .5rem 1.5rem;
  justify-content: space-between; align-items: center;
}
.foot nav { display: flex; flex-wrap: wrap; gap: .25rem 1.25rem; align-items: center; }
.foot a {
  color: var(--ink-faint); text-decoration: none;
  display: inline-flex; align-items: center; min-height: 44px;
}
.foot a span { border-bottom: 1px solid var(--edge); padding-bottom: 1px; }
.foot a:hover span { color: var(--accent); border-color: var(--accent); }
.foot .language-switch__link {
  min-height: 2.35rem;
  color: var(--ink-soft);
}
.foot .language-switch__link span { border-bottom: 0; padding-bottom: 0; }

/* ============================================================ notice ==== */

.notice {
  max-width: 72rem; margin: 0 auto 1.5rem;
  border: 1px solid #C08A8A;
  border-radius: .7rem;
  padding: .75rem .9rem;
  color: #8E3232;
  font-size: .9rem;
}
.notice--success { border-color: #7D9A79; color: #3F6844; }

/* The colofon. Quiet on purpose — it is a legal requirement rather than
   something a visitor came for — but present on every page, which is what
   "easily, directly and permanently accessible" asks for. */
.foot__colofon {
  max-width: 72rem;
  margin: .9rem auto 0;
  font-size: .78rem;
  line-height: 1.6;
  color: var(--ink-faint);
  opacity: .85;
}
