/* ==========================================================================
   KalaBond — marketing site stylesheet

   Tokens mirror the app's own design system (kalabond/src/theme.ts, which in
   turn comes from the coastal revision of the style guide). Nothing here
   invents a colour, radius or face that the app doesn't already use — the
   site and the product should look like the same thing.

   Signature motif: the overdue ring. In the app, a soft ring around each
   contact's avatar shifts turquoise → coral as it becomes a better time to
   reach out (src/components/Avatar.tsx). It is deliberately not a red badge.
   That ring is reused here as the site's recurring visual device: bullets,
   section markers, the hero, and the logo mark.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Tokens
   -------------------------------------------------------------------------- */
:root {
  /* Palette — exact hex from the app's theme.ts */
  --teal:         #02667F;  /* deep teal   · headings, nav, structure */
  --teal-soft:    #3D8299;
  --turquoise:    #3FBFBB;  /* secondary   · confirmations, "settled" */
  --turquoise-soft: #7FD3D0;
  --ice:          #EDF6F9;  /* background  */
  --ice-deep:     #DCEBEF;  /* quiet fills, avatar faces, pressed states */
  --peach:        #FFDDD2;  /* soft cards, tag chips */
  --peach-deep:   #F7C9BB;
  --coral:        #E29578;  /* primary accent · the one action colour */
  --coral-soft:   #EAAF98;
  --ink:          #123543;  /* body text */
  --ink-soft:     #4C7484;  /* secondary text */
  --tag-text:     #8A4A32;  /* legible text on peach */
  --white:        #FFFFFF;

  /* Derived — opacity only, no new hues */
  --line:          rgba(2, 102, 127, 0.13);
  --line-soft:     rgba(2, 102, 127, 0.07);
  --line-dark:     rgba(255, 255, 255, 0.16);
  --coral-wash:    rgba(226, 149, 120, 0.13);
  --turq-wash:     rgba(63, 191, 187, 0.14);
  --teal-deep:     #01566B;  /* one step under --teal, for the footer band */

  /* Shadow — teal-tinted, never neutral grey. Matches theme.ts cardStyle. */
  --shadow-sm: 0 2px 8px rgba(2, 102, 127, 0.06);
  --shadow:    0 4px 16px rgba(2, 102, 127, 0.08);
  --shadow-lg: 0 18px 48px rgba(2, 102, 127, 0.14);

  /* Spacing */
  --s-xs:   6px;
  --s-sm:  10px;
  --s-md:  16px;
  --s-lg:  24px;
  --s-xl:  36px;
  --s-2xl: 56px;
  --s-3xl: 80px;
  --s-4xl: 112px;

  /* Radius — soft corners throughout; the brief rules out 0px as "clinical" */
  --r-sm:   12px;
  --r-card: 20px;
  --r-lg:   28px;
  --r-pill: 100px;

  /* Layout */
  --maxw:   1120px;
  --narrow: 780px;
  --gutter: 24px;

  /* Type */
  --display: "Playfair Display", Georgia, "Times New Roman", serif;
  --body:    "Manrope", system-ui, -apple-system, sans-serif;

  /* Motion */
  --ease:      cubic-bezier(0.22, 0.68, 0.28, 1);
  --ease-soft: cubic-bezier(0.33, 0.05, 0.2, 1);
}

/* --------------------------------------------------------------------------
   2. Reset & base
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 104px;
}

body {
  margin: 0;
  background: var(--ice);
  color: var(--ink);
  font-family: var(--body);
  font-size: 16px;
  line-height: 1.65;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

img { max-width: 100%; display: block; height: auto; }

h1, h2, h3, h4 {
  font-family: var(--display);
  font-weight: 600;
  color: var(--teal);
  margin: 0;
  text-wrap: balance;
}

p { margin: 0; }
ul, ol { margin: 0; padding: 0; list-style: none; }
a { color: inherit; text-decoration: none; }

::selection { background: var(--coral); color: var(--white); }

:focus-visible {
  outline: 2.5px solid var(--coral);
  outline-offset: 3px;
  border-radius: 4px;
}

/* --------------------------------------------------------------------------
   3. Type scale
   Playfair carries the display sizes only — never body copy or UI labels,
   per the brief. Manrope does all the functional work.
   -------------------------------------------------------------------------- */
.t-display {
  font-family: var(--display);
  font-weight: 600;
  font-size: clamp(2.6rem, 1.5rem + 4.4vw, 4.35rem);
  line-height: 1.04;
  letter-spacing: -0.021em;
  color: var(--teal);
}

.t-h1 {
  font-family: var(--display);
  font-weight: 600;
  font-size: clamp(1.95rem, 1.35rem + 2.3vw, 2.9rem);
  line-height: 1.14;
  letter-spacing: -0.016em;
}

.t-h2 {
  font-family: var(--display);
  font-weight: 600;
  font-size: clamp(1.375rem, 1.18rem + 0.78vw, 1.7rem);
  line-height: 1.28;
  letter-spacing: -0.01em;
}

/* h3 steps down to Manrope — small serif at UI scale reads fussy, not elegant */
.t-h3 {
  font-family: var(--body);
  font-weight: 700;
  font-size: 1.0625rem;
  line-height: 1.45;
  letter-spacing: -0.006em;
  color: var(--teal);
}

.t-lead {
  font-size: clamp(1.0625rem, 1rem + 0.34vw, 1.25rem);
  line-height: 1.62;
  color: var(--ink-soft);
  max-width: 60ch;
}

.t-body { font-size: 1rem; line-height: 1.68; color: var(--ink-soft); max-width: 66ch; }
/* Card-scale body. Was repeated as an inline `font-size:.9375rem` on nearly
   every card on the landing page; named here so it is set in one place. */
.t-body--sm { font-size: 0.9375rem; }
.t-cap  { font-size: 0.8125rem; line-height: 1.5; color: var(--ink-soft); }

.t-body strong, .t-lead strong, .flist strong, .flist b {
  color: var(--teal);
  font-weight: 700;
}

/* Eyebrow — a small ring dot, then spaced caps. The ring is the motif. */
.eyebrow {
  display: flex;
  align-items: center;
  gap: var(--s-sm);
  font-family: var(--body);
  font-weight: 700;
  font-size: 0.75rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--teal);
}

.eyebrow::before {
  content: "";
  width: 11px;
  height: 11px;
  border-radius: 50%;
  border: 2.5px solid var(--coral);
  flex: none;
}

.eyebrow--center { justify-content: center; }

/* Reversed, for teal bands. Pair `on-dark` with `section--teal` in the markup
   (the sibling kala-x.com site uses the same convention).

   The rule below is a safety net for forgetting it: headings default to teal,
   so a teal band without `on-dark` renders its heading teal-on-teal and the
   text simply vanishes. Cheap to guard against, expensive to spot. */
.section--teal :is(h1, h2, h3, h4) { color: var(--white); }

.on-dark { color: var(--white); }
.on-dark h1, .on-dark h2, .on-dark h3, .on-dark h4 { color: var(--white); }
.on-dark .t-lead, .on-dark .t-body, .on-dark .t-cap { color: rgba(255, 255, 255, 0.76); }
.on-dark .t-body strong, .on-dark .t-lead strong, .on-dark .flist b { color: var(--white); }
.on-dark .eyebrow { color: var(--white); }
.on-dark .eyebrow::before { border-color: var(--peach); }

/* --------------------------------------------------------------------------
   4. Layout primitives
   -------------------------------------------------------------------------- */
.wrap {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.wrap--narrow { max-width: var(--narrow); }

.section { padding-block: clamp(64px, 8.5vw, 104px); position: relative; }
.section--tight { padding-block: clamp(48px, 6vw, 68px); }

.section--teal {
  background: var(--teal);
  color: var(--white);
}
.section--peach { background: var(--peach); }
.section--white { background: var(--white); }
.section--deep  { background: var(--ice-deep); }

.stack { display: flex; flex-direction: column; }
.stack-sm  > * + * { margin-top: var(--s-sm); }
.stack-md  > * + * { margin-top: var(--s-md); }
.stack-lg  > * + * { margin-top: var(--s-lg); }
.stack-xl  > * + * { margin-top: var(--s-xl); }
.stack-2xl > * + * { margin-top: var(--s-2xl); }

.grid { display: grid; gap: var(--s-lg); }
.grid-2 { grid-template-columns: repeat(2, 1fr); }
.grid-3 { grid-template-columns: repeat(3, 1fr); }
.grid-4 { grid-template-columns: repeat(4, 1fr); }

/* Section head — title left, supporting copy right */
.sec-head {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  gap: var(--s-xl) var(--s-2xl);
  align-items: end;
  margin-bottom: var(--s-2xl);
}
.sec-head--center {
  grid-template-columns: minmax(0, 1fr);
  justify-items: center;
  text-align: center;
  max-width: 44rem;
  margin-inline: auto;
  /* The two-column head nests its eyebrow and heading inside one grid item, so
     only the heading's own margin separates them. Centred, they are siblings —
     and the 36px row gap then stacked on top of that margin, opening 60px of
     accidental air between an eyebrow and the heading it belongs to. */
  row-gap: 0;
  margin-bottom: var(--s-lg);
}
/* The eyebrow-to-heading step is a hierarchy cue, not a paragraph break. */
.sec-head--center .t-h1 { margin-top: var(--s-md); }

/* Atmosphere: soft off-palette glows rather than a flat fill. Very low
   opacity — this should register as light, not as a gradient. */
.glow { position: relative; isolation: isolate; }
.glow::before {
  content: "";
  position: absolute;
  /* Stays inside the section's own width on purpose — bleeding it sideways
     widens the document and gives the whole page a horizontal scrollbar.
     The gradients fade out well before the edges anyway. */
  inset: -20% 0 auto 0;
  height: 80%;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(42% 60% at 18% 30%, rgba(63, 191, 187, 0.16), transparent 70%),
    radial-gradient(46% 64% at 84% 18%, rgba(255, 221, 210, 0.7), transparent 72%);
}

/* --------------------------------------------------------------------------
   5. The ring — signature motif
   A face inside a ring whose colour says how long it's been. Reproduced from
   the app: turquoise when you're up to date, coral when it's a good moment.
   -------------------------------------------------------------------------- */
.ring {
  --ring-c: var(--turquoise-soft);
  --ring-size: 56px;
  width: var(--ring-size);
  height: var(--ring-size);
  border-radius: 50%;
  border: calc(var(--ring-size) * 0.055) solid var(--ring-c);
  display: grid;
  place-items: center;
  flex: none;
  background: transparent;
}

.ring__face {
  width: calc(100% - 5px);
  height: calc(100% - 5px);
  border-radius: 50%;
  background: var(--ice-deep);
  display: grid;
  place-items: center;
  font-family: var(--display);
  font-weight: 600;
  color: var(--teal);
  font-size: calc(var(--ring-size) * 0.3);
  line-height: 1;
  letter-spacing: 0.01em;
}

/* The four states, straight out of ringColor() in Avatar.tsx */
.ring--fresh { --ring-c: var(--turquoise-soft); }
.ring--soon  { --ring-c: #B2C3B4; }          /* mid-mix, turquoise → coral */
.ring--due   { --ring-c: var(--coral-soft); }
.ring--now   { --ring-c: var(--coral); }

.ring--lg { --ring-size: 76px; }
.ring--sm { --ring-size: 40px; }

.on-dark .ring__face { background: rgba(255, 255, 255, 0.92); }

/* --------------------------------------------------------------------------
   6. Buttons — exactly one coral action per view; everything else stays quiet
   -------------------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-sm);
  padding: 14px 26px;
  border: 1.5px solid transparent;
  border-radius: var(--r-pill);
  background: var(--coral);
  color: var(--white);
  font-family: var(--body);
  font-weight: 700;
  font-size: 0.9375rem;
  letter-spacing: -0.002em;
  line-height: 1;
  cursor: pointer;
  transition: background .24s var(--ease), border-color .24s var(--ease),
              color .24s var(--ease), transform .24s var(--ease),
              box-shadow .24s var(--ease);
}

.btn--primary { box-shadow: 0 6px 18px rgba(226, 149, 120, 0.34); }
.btn--primary:hover {
  background: #D8825F;
  transform: translateY(-2px);
  box-shadow: 0 10px 24px rgba(226, 149, 120, 0.4);
}
.btn--primary:active { transform: translateY(0); }

.btn--outline {
  background: transparent;
  color: var(--teal);
  border-color: var(--line);
}
.btn--outline:hover { border-color: var(--teal); background: rgba(2, 102, 127, 0.04); }

.btn--ghost {
  background: transparent;
  color: var(--teal);
  padding-inline: 0;
  border-radius: 4px;
}
.btn--ghost .btn__arrow { transition: transform .24s var(--ease); }
.btn--ghost:hover .btn__arrow { transform: translateX(4px); }

.on-dark .btn--outline { color: var(--white); border-color: var(--line-dark); }
.on-dark .btn--outline:hover { border-color: var(--white); background: rgba(255, 255, 255, 0.08); }

.btn-row { display: flex; flex-wrap: wrap; gap: var(--s-md); align-items: center; }

.link {
  color: var(--teal);
  font-weight: 600;
  border-bottom: 1.5px solid var(--coral);
  padding-bottom: 1px;
  transition: color .2s var(--ease), border-color .2s var(--ease);
}
.link:hover { color: var(--coral); }
.on-dark .link { color: var(--white); border-bottom-color: var(--peach); }
.on-dark .link:hover { color: var(--peach); }

/* --------------------------------------------------------------------------
   7. Header & nav
   -------------------------------------------------------------------------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 60;
  background: rgba(237, 246, 249, 0.86);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-bottom: 1px solid transparent;
  transition: border-color .3s var(--ease), background .3s var(--ease);
}
.site-header.is-stuck {
  border-bottom-color: var(--line);
  background: rgba(237, 246, 249, 0.94);
}

.nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-lg);
  min-height: 76px;
}

.nav__logo { display: flex; align-items: center; gap: 11px; }
.nav__logo img { width: 34px; height: 34px; border-radius: 9px; }
.nav__word {
  font-family: var(--display);
  font-weight: 600;
  font-size: 1.3rem;
  color: var(--teal);
  letter-spacing: -0.015em;
}

.nav__links {
  display: flex;
  align-items: center;
  gap: var(--s-lg);
}

.nav__link {
  font-size: 0.9375rem;
  font-weight: 500;
  color: var(--ink-soft);
  position: relative;
  padding-block: 6px;
  transition: color .22s var(--ease);
}
.nav__link::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 2px;
  border-radius: 2px;
  background: var(--coral);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .26s var(--ease);
}
.nav__link:hover { color: var(--teal); }
.nav__link:hover::after,
.nav__link[aria-current="page"]::after { transform: scaleX(1); }
.nav__link[aria-current="page"] { color: var(--teal); font-weight: 600; }

.nav__cta { margin-left: var(--s-xs); padding: 11px 20px; font-size: 0.875rem; }

.nav__toggle {
  display: none;
  width: 42px; height: 42px;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
  position: relative;
}
.nav__toggle span,
.nav__toggle span::before,
.nav__toggle span::after {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 17px;
  height: 2px;
  border-radius: 2px;
  background: var(--teal);
  transform: translate(-50%, -50%);
  transition: transform .26s var(--ease), background .26s var(--ease);
}
.nav__toggle span::before,
.nav__toggle span::after { content: ""; left: 0; transform: none; }
.nav__toggle span::before { top: -5.5px; }
.nav__toggle span::after  { top: 5.5px; }
.nav__toggle[aria-expanded="true"] span { background: transparent; }
.nav__toggle[aria-expanded="true"] span::before { top: 0; transform: rotate(45deg); }
.nav__toggle[aria-expanded="true"] span::after  { top: 0; transform: rotate(-45deg); }

/* --------------------------------------------------------------------------
   8. Hero
   -------------------------------------------------------------------------- */
/* The top is a constant, not a viewport-scaled value, and that is the point:
   it is the gap under a sticky header whose own height is fixed at 76px, so
   scaling it with the viewport only opened dead space on the machines with the
   most of it — 90px at 1280 and 92px at 1600, on top of the ~64px the centred
   grid already puts above the badge. Small screens are unaffected: the old
   clamp bottomed out at 56px there anyway. The bottom still scales, because
   that one is a band transition rather than a header offset. */
.hero { padding-block: 48px clamp(64px, 8vw, 104px); }

.hero__inner {
  display: grid;
  grid-template-columns: minmax(0, 1.06fr) minmax(0, 0.94fr);
  gap: var(--s-2xl) var(--s-3xl);
  align-items: center;
}

.hero__title { margin-block: var(--s-lg) var(--s-lg); }
.hero__title em {
  font-style: italic;
  color: var(--coral);
}

.hero__form { margin-top: var(--s-xl); max-width: 30rem; }

/* Secondary action + the reassurance line, on one row above 620px. The
   waitlist button is the only coral thing here; "See how it works" is a ghost
   link so the hierarchy reads at a glance rather than as two equal buttons. */
/* Spacing does the grouping here. The secondary link sits close under the
   waitlist button so the two read as one action area, and the reassurance line
   is pushed further down — previously it was the other way round, which is
   what made the link look detached from the CTA it belongs to. */
.hero__second {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  row-gap: var(--s-md);
  column-gap: var(--s-lg);
  margin-top: var(--s-sm);
}
.hero__second .btn--ghost { padding-block: 6px; }
/* A coral arrow, teal label: enough to read as an action without competing
   with the one filled button above it. */
.hero__second .btn__arrow { color: var(--coral); }
/* The reassurance line takes a row of its own rather than being squeezed into
   three lines beside the link. */
.hero__second .t-cap { flex: 1 0 100%; }

/* Phone-ish panel holding the real product surface: a check-in list */
.showcase {
  position: relative;
  background: var(--white);
  border-radius: var(--r-lg);
  /* Deep bottom padding on purpose: .float-card is anchored to this edge and
     overlaps upward, so without the clearance it lands on top of the last
     person in the list and covers their name. 104px was not quite enough once
     that person's meta line wrapped to two lines — the card clipped the corner
     of their tag on a 1280px screen — so it is 132px. */
  padding: var(--s-xl) var(--s-lg) 132px;
  box-shadow: var(--shadow-lg);
  max-width: 400px;
  margin-inline: auto;
}

.showcase__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-md);
  margin-bottom: var(--s-lg);
  padding-inline: var(--s-xs);
}
.showcase__title { font-family: var(--display); font-weight: 600; font-size: 1.4rem; color: var(--teal); }

.showcase__chips { display: flex; gap: 7px; flex-wrap: wrap; margin-bottom: var(--s-md); padding-inline: var(--s-xs); }

.chip {
  font-size: 0.75rem;
  font-weight: 600;
  padding: 6px 13px;
  border-radius: var(--r-pill);
  background: var(--ice);
  color: var(--ink-soft);
  white-space: nowrap;
}
.chip--on { background: var(--peach); color: var(--tag-text); }

/* One person in the list */
.person {
  display: flex;
  align-items: center;
  gap: var(--s-md);
  padding: 11px var(--s-xs);
  border-radius: var(--r-sm);
  transition: background .24s var(--ease);
}
.person + .person { margin-top: 2px; }
.person:hover { background: var(--ice); }

/* The name/meta pair is marked up with spans (they sit inside a span so the
   whole row can stay one aria-hidden decorative block) — so they have to be
   made block-level here or they run together on one line. */
.person > span:not([class]) { min-width: 0; display: block; }
.person__name {
  display: block;
  font-weight: 600;
  font-size: 0.9688rem;
  color: var(--ink);
  line-height: 1.3;
}
.person__meta {
  display: block;
  font-size: 0.8125rem;
  color: var(--ink-soft);
  margin-top: 2px;
  line-height: 1.35;
}
.person__tag {
  margin-left: auto;
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--tag-text);
  background: var(--peach);
  padding: 5px 11px;
  border-radius: var(--r-pill);
  white-space: nowrap;
}
.person__tag--quiet { background: var(--ice-deep); color: var(--teal-soft); }

/* A floating card that overlaps the showcase — depth, and it tells the story:
   the reminder becomes a plan. */
.float-card {
  position: absolute;
  right: -26px;
  bottom: -30px;
  width: 232px;
  background: var(--white);
  border-radius: var(--r-card);
  padding: var(--s-md);
  box-shadow: var(--shadow-lg);
  border: 1px solid var(--line-soft);
}
.float-card__k {
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--turquoise);
  margin-bottom: 7px;
  display: flex;
  align-items: center;
  gap: 6px;
}
.float-card__k::before {
  content: "";
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--turquoise);
}
.float-card__t { font-weight: 700; font-size: 0.9375rem; color: var(--ink); line-height: 1.35; }

.vote-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-sm);
  margin-top: 9px;
  font-size: 0.8125rem;
  color: var(--ink-soft);
}
.vote-row__n {
  font-weight: 700;
  color: var(--teal);
  background: var(--ice);
  border-radius: var(--r-pill);
  padding: 2px 9px;
  font-size: 0.75rem;
}
.vote-row--won .vote-row__n { background: var(--turq-wash); color: #1D7C79; }

/* --------------------------------------------------------------------------
   8b. Product surfaces reused outside the hero

   The landing page shows three more of the app's own screens — a contact, a
   plan, and the guest voting link as it looks in a browser. They are built
   from the same tokens as the hero showcase rather than as screenshots: there
   are no product screenshots in this repository, and a hand-built surface
   stays truthful as long as it only shows what the app actually does. Every
   one carries role="img" with a description, and its innards are aria-hidden.
   -------------------------------------------------------------------------- */

/* The hero's showcase reserves deep bottom padding for the overlapping
   .float-card. These ones have nothing overlapping them, so they don't. */
/* Founder-approved 10-15% reduction (FINAL SPACING). The footprint comes down
   through padding and row rhythm, never type: every label, name and figure in
   these cards is still at its full size, so they read exactly as before in a
   smaller box. Height 334->~286 and 428->~376, width 400->360. */
.showcase--flat { padding: var(--s-md); max-width: 360px; }
/* The hero's ring is the page's signature and stays at 76px. Inside a contact
   card it is one field among several, so it steps down a size — still the
   largest thing in the card, and still clearly the motif. */
.showcase--flat .ring--lg { --ring-size: 56px; }
/* The hero's showcase sets a 24px rule under its header; these cards are
   shorter overall, so they carry a tighter one. Scoped so the hero is
   untouched. */
.showcase--flat .showcase__head { margin-bottom: var(--s-sm); }

/* A small caps label inside a mock — the app's own section headers */
.mock-k {
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  /* --teal-soft would only reach 4.3:1 on white at this size; --teal is the
     same family at 6.5:1. */
  color: var(--teal);
  margin-bottom: 7px;
}
.mock-k--spaced { margin-top: var(--s-sm); }

/* Contact header: the ring at full size, name, and when you last caught up */
.mock-person {
  display: flex;
  align-items: center;
  gap: var(--s-md);
  padding-bottom: 12px;
  border-bottom: 1px solid var(--line-soft);
}
.mock-person > span:not([class]) { min-width: 0; display: block; }
.mock-person__name {
  display: block;
  font-family: var(--display);
  font-weight: 600;
  font-size: 1.25rem;
  color: var(--teal);
  line-height: 1.25;
}

.mock-list > div {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-md);
  padding: 7px 0;
  border-bottom: 1px solid var(--line-soft);
}
.mock-list dt {
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--teal);
  flex: none;
}
.mock-list dd {
  margin: 0;
  font-size: 0.9375rem;
  font-weight: 600;
  color: var(--ink);
  text-align: right;
}

.mock-actions { display: flex; flex-wrap: wrap; gap: var(--s-sm); margin-top: 12px; }
.mock-btn {
  font-size: 0.8125rem;
  font-weight: 700;
  padding: 9px 15px;
  border-radius: var(--r-pill);
  background: var(--ice);
  color: var(--teal);
}
.mock-btn--primary { background: var(--coral); color: var(--white); }

/* A votable option — a proposed time or a suggested place */
.opt {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-sm);
  padding: 9px 13px;
  border-radius: var(--r-sm);
  background: var(--ice);
}
.opt + .opt { margin-top: 6px; }
/* Only the two editorial cards tighten; the guest browser keeps the rhythm it
   was approved with, since it is not what made the section tall. */
.showcase--flat .opt { padding: 7px 12px; }
.showcase--flat .opt + .opt { margin-top: 5px; }
.opt--won { background: var(--turq-wash); }
.opt__t {
  font-weight: 600;
  font-size: 0.9063rem;
  color: var(--ink);
  line-height: 1.35;
  min-width: 0;
}
.opt__sub {
  display: block;
  font-weight: 500;
  font-size: 0.75rem;
  color: var(--ink-soft);
  margin-top: 2px;
}
/* Guest rows stack the answer buttons under the time on narrow surfaces */
.opt--stack { flex-wrap: wrap; row-gap: var(--s-sm); }

.pick { display: flex; gap: 5px; margin-left: auto; }
.pick__b {
  font-size: 0.75rem;
  font-weight: 700;
  padding: 5px 11px;
  border-radius: var(--r-pill);
  background: var(--white);
  color: var(--ink-soft);
  white-space: nowrap;
}
/* Selected reads as the app's "settled" treatment — the wash plus a turquoise
   edge — rather than white on flat turquoise, which is only 2.2:1. */
.pick__b--on    { background: var(--turq-wash); color: var(--teal); box-shadow: inset 0 0 0 1.5px var(--turquoise); }
.pick__b--maybe { background: var(--peach-deep); color: var(--tag-text); }
.pick__b--no    { background: var(--ice-deep); color: var(--teal); }

/* The guest link as a guest sees it: a browser, not a phone. That framing is
   the whole point of the section it sits in. */
.browser {
  background: var(--white);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
  max-width: 460px;
  margin-inline: auto;
}
.browser__bar {
  display: flex;
  align-items: center;
  gap: var(--s-md);
  padding: 12px var(--s-md);
  background: var(--ice-deep);
}
.browser__dots { display: flex; gap: 5px; flex: none; }
.browser__dot {
  width: 9px; height: 9px;
  border-radius: 50%;
  background: rgba(2, 102, 127, 0.2);
}
.browser__url {
  flex: 1;
  min-width: 0;
  background: var(--white);
  border-radius: var(--r-pill);
  padding: 5px 14px;
  font-size: 0.75rem;
  color: var(--ink-soft);
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.browser__body { padding: var(--s-lg) var(--s-md) var(--s-xl); }
.browser__who {
  font-family: var(--display);
  font-weight: 600;
  font-size: 1.2rem;
  color: var(--teal);
  line-height: 1.3;
}
.browser__who span {
  font-family: var(--body);
  font-weight: 500;
  font-size: 0.8125rem;
  color: var(--ink-soft);
}
.browser__note {
  margin-top: var(--s-md);
  font-size: 0.8125rem;
  line-height: 1.5;
  color: var(--ink-soft);
}

/* Trust strip under the hero */
.strip {
  border-top: 1px solid var(--line);
  padding-top: var(--s-lg);
  margin-top: var(--s-3xl);
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-md) var(--s-2xl);
  align-items: center;
  justify-content: space-between;
}
.strip__item {
  display: flex;
  align-items: center;
  gap: var(--s-sm);
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--teal);
}
.strip__dot {
  width: 13px; height: 13px;
  border-radius: 50%;
  border: 2.5px solid var(--turquoise-soft);
  flex: none;
}

/* Four claims rather than three: space-between leaves ugly gaps once the row
   is this full, so it packs from the left and wraps evenly instead. */
.strip--4 {
  justify-content: flex-start;
  gap: var(--s-md) var(--s-xl);
}

/* --------------------------------------------------------------------------
   9. Cards
   -------------------------------------------------------------------------- */
.card {
  background: var(--white);
  border-radius: var(--r-card);
  padding: var(--s-xl);
  box-shadow: var(--shadow);
  transition: transform .3s var(--ease), box-shadow .3s var(--ease);
  height: 100%;
}
.card:hover { transform: translateY(-3px); box-shadow: var(--shadow-lg); }

.card--peach { background: var(--peach); box-shadow: none; }
.card--peach .t-body { color: #7A5344; }

.card--quiet { background: var(--white); box-shadow: var(--shadow-sm); }

.card__icon {
  width: 46px; height: 46px;
  border-radius: 14px;
  background: var(--ice);
  display: grid;
  place-items: center;
  margin-bottom: var(--s-md);
  color: var(--teal);
}
.card--peach .card__icon { background: rgba(255, 255, 255, 0.6); }

.card__title { margin-bottom: var(--s-sm); }

/* The one card in a row that is the answer rather than the problem. Was an
   inline border on the landing page; named so the other pages can use it. */
.card--outlined { border: 1.5px solid var(--coral); }
.card__icon--coral { background: var(--coral-wash); color: var(--coral); }

/* Primary feature. Three of these carry the weight of the feature section;
   everything else drops to .mini underneath, which is the whole hierarchy. */
.card--lead {
  padding: var(--s-2xl) var(--s-xl);
  border: 1.5px solid var(--line);
}
.card--lead .card__icon {
  width: 54px; height: 54px;
  border-radius: 16px;
  margin-bottom: var(--s-lg);
}
.card--lead .card__title { margin-bottom: var(--s-sm); }

/* Supporting capabilities — deliberately quieter than .card--lead: no
   surface, no shadow, just a ring bullet and two lines. */
.mini-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--s-xl) var(--s-2xl);
  margin-top: var(--s-2xl);
  padding-top: var(--s-2xl);
  border-top: 1px solid var(--line);
}
.mini__t {
  display: flex;
  align-items: baseline;
  gap: var(--s-sm);
  font-family: var(--body);
  font-weight: 700;
  font-size: 0.9375rem;
  color: var(--teal);
  line-height: 1.4;
}
.mini__t::before {
  content: "";
  width: 11px; height: 11px;
  border-radius: 50%;
  border: 2.5px solid var(--turquoise-soft);
  flex: none;
  transform: translateY(1px);
}
.mini p {
  margin-top: 5px;
  padding-left: calc(11px + var(--s-sm));
  font-size: 0.875rem;
  line-height: 1.55;
  color: var(--ink-soft);
}

.on-dark .card {
  background: rgba(255, 255, 255, 0.07);
  box-shadow: none;
  border: 1px solid var(--line-dark);
}
.on-dark .card:hover { background: rgba(255, 255, 255, 0.11); transform: translateY(-3px); box-shadow: none; }
.on-dark .card__icon { background: rgba(255, 255, 255, 0.12); color: var(--peach); }

/* Feature list — ring bullets, soft separators, no hard rules */
.flist > li {
  position: relative;
  padding: var(--s-md) 0 var(--s-md) 34px;
  color: var(--ink-soft);
  font-size: 0.9688rem;
  line-height: 1.62;
}
.flist > li + li { border-top: 1px solid var(--line-soft); }
.flist > li::before {
  content: "";
  position: absolute;
  left: 0;
  top: calc(var(--s-md) + 0.52em);
  width: 13px; height: 13px;
  border-radius: 50%;
  border: 2.5px solid var(--turquoise-soft);
}
.flist--coral > li::before { border-color: var(--coral-soft); }
.on-dark .flist > li + li { border-top-color: var(--line-dark); }
.on-dark .flist > li::before { border-color: var(--peach); }

/* Numbered steps */
.steps { display: grid; gap: var(--s-lg); }
.step {
  display: grid;
  grid-template-columns: 58px minmax(0, 1fr);
  gap: var(--s-lg);
  align-items: start;
  padding: var(--s-lg) 0;
  border-top: 1px solid var(--line);
}
.step:last-child { border-bottom: 1px solid var(--line); }
.step__n {
  font-family: var(--display);
  font-weight: 600;
  font-size: 1.6rem;
  color: var(--coral);
  line-height: 1;
  padding-top: 3px;
}
.step__t { margin-bottom: 5px; }

/* --------------------------------------------------------------------------
   9b. Moments — an editorial text/product row that alternates side to side

   The counterweight to the card grids: full-height product surfaces with a
   short line of copy beside them, so the screen carries the explaining. Media
   sits second in the DOM so the heading is still read first; `order` moves it
   left on the flipped rows, and is reset in the single-column layout.
   -------------------------------------------------------------------------- */
.moment {
  display: grid;
  /* The visual is a fixed-width card; the copy is three short lines. Splitting
     the row 50/50 gave the copy a 500px column to hold 140px of text, which is
     what made the two halves read as unrelated objects. The copy column is now
     the wider one and the media column is sized near the card itself. */
  grid-template-columns: minmax(0, 1.12fr) minmax(0, 0.88fr);
  gap: var(--s-xl) var(--s-2xl);
  /* Top-aligned, not centred. Centring parked a 140px block in the middle of a
     400-500px row, so the copy started ~130px below the card it describes and
     floated. Aligned to the top, the number and the card share an edge and the
     row reads as one thing. The small offset is optical: it drops the "01"
     cap-height onto the card's top rule rather than its border. */
  align-items: start;
}
.moment__text { padding-top: var(--s-sm); }
/* `01  Know who to reconnect with` on one line, with the supporting sentence
   indented under the heading — the number is an ordinal marker, not a line of
   its own. The guest band keeps its stacked number, because a display-italic
   statement will not sit on a baseline beside a numeral. */
.moment:not(.moment--wide) .moment__text {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  column-gap: var(--s-md);
  align-items: baseline;
}
.moment:not(.moment--wide) .moment__n { grid-column: 1; margin-bottom: 0; }
.moment:not(.moment--wide) .moment__t,
.moment:not(.moment--wide) .moment__text > .t-body { grid-column: 2; }
.moment + .moment { margin-top: var(--s-xl); }
.moment--flip .moment__media { order: -1; }

/* The guest band keeps the composition it was approved with: the copy has a
   list to carry, so it is much taller than the browser beside it and centring
   is right there. Only the two "in action" rows had the floating problem. */
.moment--wide {
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
  gap: var(--s-2xl) var(--s-3xl);
  align-items: center;
}
.moment--wide .moment__text { padding-top: 0; }

.moment__n {
  font-family: var(--display);
  font-weight: 600;
  font-size: 1.6rem;
  line-height: 1;
  color: var(--coral);
  margin-bottom: var(--s-sm);
}
.moment__n--warm { color: var(--tag-text); }
.moment__t { margin-bottom: var(--s-md); }
.moment__body { max-width: 46ch; }
.moment__list { max-width: 46ch; }

/* Two editorial rows already carry their own air, so the standard band padding
   double-counts here and leaves the section reading as empty viewport rather
   than as intentional space. Still inside the spacing scale, just a step down.
   Scoped to this one section — nothing else on the site is compressed. */
#in-action { padding-block: clamp(36px, 3.4vw, 44px); }

/* Peach band — the ink-soft defaults are too cool against peach, so the
   warm-brown pair used elsewhere on this background takes over here. */
.section--peach .t-body { color: #7A5344; }
.section--peach .flist > li { color: #7A5344; }
.section--peach .flist > li + li { border-top-color: rgba(138, 74, 50, 0.16); }
.section--peach .flist b { color: var(--tag-text); }

/* Closing claim under a card grid — full measure, not the 60ch lead default */
.closing-line { margin-top: var(--s-2xl); max-width: 74ch; }

/* Pill / status */
.pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 7px 15px;
  border-radius: var(--r-pill);
  border: 1px solid var(--line);
  background: var(--white);
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--ink-soft);
}
.pill__dot {
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--coral);
  flex: none;
}
.on-dark .pill {
  background: rgba(255, 255, 255, 0.08);
  border-color: var(--line-dark);
  color: rgba(255, 255, 255, 0.82);
}
.on-dark .pill__dot { background: var(--peach); }

/* Definition list */
.deflist > div {
  display: grid;
  grid-template-columns: 116px minmax(0, 1fr);
  gap: var(--s-md);
  padding: 13px 0;
  border-bottom: 1px solid var(--line-soft);
}
.deflist > div:first-child { border-top: 1px solid var(--line-soft); }
.deflist dt {
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--teal);
  padding-top: 2px;
}
.deflist dd { margin: 0; font-size: 0.9375rem; color: var(--ink-soft); line-height: 1.55; }
.on-dark .deflist > div { border-bottom-color: var(--line-dark); }
.on-dark .deflist > div:first-child { border-top-color: var(--line-dark); }
.on-dark .deflist dt { color: var(--peach); }
.on-dark .deflist dd { color: rgba(255, 255, 255, 0.78); }

/* Pull quote / statement — Playfair earning its keep */
.statement {
  font-family: var(--display);
  font-weight: 500;
  font-style: italic;
  font-size: clamp(1.5rem, 1.1rem + 1.7vw, 2.3rem);
  line-height: 1.34;
  letter-spacing: -0.014em;
  color: var(--teal);
  max-width: 22ch;
}
.on-dark .statement { color: var(--white); }

/* --------------------------------------------------------------------------
   9b. Screenshots (guide.html)

   The one place on this site that shows real pixels rather than a surface
   drawn from these tokens. They are captured from the app itself by
   `npm run capture:screens` in kala-x/kalabond-mobile, which writes them into
   assets/img/guide/ — so a screenshot going stale here is fixed by re-running
   that command, not by editing anything below.

   The frame is a phone, deliberately: every image in it is a 390x844 capture,
   and drawing it as anything else would claim a layout the app does not have.
   Contrast with `.browser`, which frames the guest link — that one is a
   browser because the whole point of the guest link is that a guest has no app.
   -------------------------------------------------------------------------- */
.shot {
  max-width: 300px;
  margin-inline: auto;
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--white);
  box-shadow: var(--shadow-lg);
  /* A hairline inside the radius rather than a border, so the corner keeps the
     radius above it and does not gain a second, slightly larger one. */
  outline: 1px solid var(--line);
  outline-offset: -1px;
}
/* The captures are 2x, so `width` is what stops them rendering at double size;
   `display:block` removes the inline-image baseline gap that would otherwise
   leave a pale strip along the bottom of the frame. */
.shot img {
  display: block;
  width: 100%;
  height: auto;
}
/* Two shots side by side, for the one step that needs both halves of it. Falls
   to one column with the rest of the layout below 860px. */
.shot-pair {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s-md);
  max-width: 620px;
  margin-inline: auto;
}
.shot-pair .shot { max-width: none; }

/* --------------------------------------------------------------------------
   10. Forms
   -------------------------------------------------------------------------- */
.field { display: block; }
.field__label {
  display: block;
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  color: var(--teal);
  margin-bottom: 7px;
}
.field__hint { display: block; font-size: 0.8125rem; color: var(--ink-soft); margin-top: 7px; }

.input, .textarea, .select {
  width: 100%;
  font-family: var(--body);
  font-size: 1rem;
  color: var(--ink);
  background: var(--white);
  border: 1.5px solid var(--line);
  border-radius: var(--r-sm);
  padding: 13px 16px;
  transition: border-color .22s var(--ease), box-shadow .22s var(--ease);
  appearance: none;
}
.input::placeholder, .textarea::placeholder { color: #9DB4BE; }
.input:focus, .textarea:focus, .select:focus {
  outline: none;
  border-color: var(--turquoise);
  box-shadow: 0 0 0 4px var(--turq-wash);
}
.textarea { min-height: 150px; resize: vertical; line-height: 1.6; }

.select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='9' viewBox='0 0 14 9' fill='none'%3E%3Cpath d='M1 1.5L7 7.5L13 1.5' stroke='%2302667F' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 16px center;
  padding-right: 44px;
  cursor: pointer;
}

.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-lg); }
.form-grid .span-2 { grid-column: 1 / -1; }

/* Inline waitlist form — email + button on one line above 560px */
.signup { display: flex; gap: var(--s-sm); align-items: stretch; }
.signup .input { flex: 1; min-width: 0; border-radius: var(--r-pill); padding-inline: 20px; }
.signup .btn { flex: none; white-space: nowrap; }

.form-status {
  margin-top: var(--s-md);
  font-size: 0.9375rem;
  line-height: 1.55;
  padding: 13px 16px;
  border-radius: var(--r-sm);
  background: var(--turq-wash);
  color: #135F5D;
  font-weight: 500;
}
.form-status[data-state="error"] { background: var(--coral-wash); color: #96422A; }
.form-status[data-state="working"] { background: var(--ice-deep); color: var(--teal-soft); }
.on-dark .form-status { background: rgba(255, 255, 255, 0.13); color: var(--white); }

/* Honeypot — a field only a bot fills in. Collapsed to nothing in place
   rather than parked at left:-9999px, which widens the document and gives
   the whole page a horizontal scroll. */
.hp {
  position: absolute !important;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  border: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
}

/* --------------------------------------------------------------------------
   11. CTA band
   -------------------------------------------------------------------------- */
.cta {
  background: var(--teal);
  border-radius: var(--r-lg);
  padding: clamp(var(--s-xl), 5vw, var(--s-3xl));
  position: relative;
  overflow: hidden;
}
.cta::after {
  /* An oversized ring, half off the edge — the motif at architectural scale */
  content: "";
  position: absolute;
  right: -110px;
  top: 50%;
  transform: translateY(-50%);
  width: 340px;
  height: 340px;
  border-radius: 50%;
  border: 40px solid rgba(255, 255, 255, 0.055);
  pointer-events: none;
}
.cta > * { position: relative; z-index: 1; }

/* --------------------------------------------------------------------------
   12. Page head (interior pages)
   -------------------------------------------------------------------------- */
.page-head {
  padding-block: clamp(48px, 6vw, 76px) clamp(40px, 5vw, 60px);
}
.page-head__inner {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
  gap: var(--s-xl) var(--s-2xl);
  align-items: end;
}

/* Contact page split */
.contact-layout {
  display: grid;
  grid-template-columns: minmax(0, 1.18fr) minmax(0, 0.82fr);
  gap: var(--s-2xl) var(--s-3xl);
  align-items: start;
}
.contact-panel {
  background: var(--teal);
  color: var(--white);
  border-radius: var(--r-lg);
  padding: var(--s-xl);
  position: sticky;
  top: 104px;
}
.contact-line {
  display: grid;
  grid-template-columns: 92px minmax(0, 1fr);
  gap: var(--s-md);
  padding: 15px 0;
  border-top: 1px solid var(--line-dark);
  align-items: baseline;
}
.contact-line:first-of-type { border-top: 0; }
.contact-line__k {
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--peach);
}
.contact-line__v { color: var(--white); font-size: 1rem; }

/* --------------------------------------------------------------------------
   12b. Legal prose (privacy policy)
   Long-form reading, so: one narrow measure, real paragraph rhythm, and
   headings that stay scannable when someone is hunting for one clause.
   -------------------------------------------------------------------------- */
.legal { max-width: 68ch; }

.legal h2 {
  font-size: clamp(1.3rem, 1.15rem + 0.6vw, 1.55rem);
  line-height: 1.3;
  margin-top: var(--s-2xl);
  margin-bottom: var(--s-md);
  scroll-margin-top: 104px;
}
.legal h2:first-of-type { margin-top: 0; }

.legal h3 {
  font-family: var(--body);
  font-weight: 700;
  font-size: 1rem;
  color: var(--teal);
  margin-top: var(--s-xl);
  margin-bottom: var(--s-xs);
}

.legal p,
.legal ul { color: var(--ink-soft); font-size: 1rem; line-height: 1.72; }
.legal p + p { margin-top: var(--s-md); }
.legal h2 + p, .legal h3 + p { margin-top: 0; }

.legal ul { margin-top: var(--s-md); }
.legal ul > li {
  position: relative;
  padding-left: 26px;
  margin-top: var(--s-sm);
}
.legal ul > li::before {
  content: "";
  position: absolute;
  left: 2px;
  top: 0.62em;
  width: 9px; height: 9px;
  border-radius: 50%;
  border: 2px solid var(--turquoise-soft);
}
.legal strong { color: var(--teal); font-weight: 700; }

/* Section numbering, so a clause can be cited by number */
.legal { counter-reset: clause; }
.legal h2::before {
  counter-increment: clause;
  content: counter(clause) ". ";
  color: var(--coral);
  font-family: var(--body);
  font-weight: 700;
  font-size: 0.8em;
}

/* Contents list at the top */
.toc {
  background: var(--white);
  border-radius: var(--r-card);
  padding: var(--s-lg) var(--s-xl);
  box-shadow: var(--shadow-sm);
  margin-bottom: var(--s-2xl);
  counter-reset: toc;
}
.toc__h {
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--teal);
  margin-bottom: var(--s-md);
}
.toc ol { display: grid; gap: 7px; }
.toc li { counter-increment: toc; }
.toc a {
  font-size: 0.9375rem;
  color: var(--ink-soft);
  transition: color .2s var(--ease);
}
.toc a::before { content: counter(toc) ". "; color: var(--coral); font-weight: 700; }
.toc a:hover { color: var(--teal); }

/* A callout for the things the reader most wants to know */
.note {
  background: var(--peach);
  border-radius: var(--r-card);
  padding: var(--s-lg) var(--s-xl);
  margin: var(--s-xl) 0;
}
.note p { color: #7A5344; }
.note strong { color: var(--tag-text); }

/* Draft banner — remove once the policy has been reviewed and signed off */
.draft-banner {
  background: var(--coral-wash);
  border: 1.5px dashed var(--coral);
  border-radius: var(--r-card);
  padding: var(--s-lg) var(--s-xl);
  margin-bottom: var(--s-2xl);
}
.draft-banner p { color: #8A4A32; font-size: 0.9375rem; line-height: 1.6; }
.draft-banner strong { color: #7A3A22; }

/* --------------------------------------------------------------------------
   13. Footer
   Four regions on desktop — brand, then Product / Company / Legal — with the
   brand block separated from the link columns by a single hairline. That one
   rule is the only border here on purpose: the composition is carried by
   alignment and column width, not by drawing boxes.
   -------------------------------------------------------------------------- */
.site-footer {
  background: var(--teal-deep);
  color: var(--white);
  padding-block: clamp(40px, 3.4vw, 48px) var(--s-lg);
}

.footer-top {
  display: grid;
  grid-template-columns: minmax(0, 1.45fr) minmax(0, 2.1fr);
  gap: var(--s-2xl);
  padding-bottom: clamp(28px, 2.4vw, 32px);
}

/* The grid column is the real constraint on desktop; this only binds once
   the brand block goes full width below 1000px. */
.footer-brand { max-width: 56ch; }
.footer__logo { display: flex; align-items: center; gap: 11px; margin-bottom: var(--s-md); }
.footer__logo img { width: 36px; height: 36px; border-radius: 10px; }
.footer__word { font-family: var(--display); font-weight: 600; font-size: 1.35rem; color: var(--white); }

.footer__tag {
  font-size: 1rem;
  line-height: 1.55;
  max-width: 27ch;         /* two balanced lines beside the rule, never an orphan */
  text-wrap: balance;
  color: rgba(255, 255, 255, 0.92);
}
.footer__meta {
  margin-top: var(--s-sm);
  font-size: 0.875rem;
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.70);
}
/* Underlined, not colour-only, so the outbound link is identifiable inside
   a sentence without borrowing the peach used by the column headings. */
.footer__meta a {
  color: rgba(255, 255, 255, 0.86);
  text-decoration: underline;
  text-decoration-color: rgba(255, 255, 255, 0.34);
  text-underline-offset: 3px;
  transition: color .22s var(--ease), text-decoration-color .22s var(--ease);
}
.footer__meta a:hover { color: var(--white); text-decoration-color: var(--peach-deep); }

.footer-nav {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--s-xl);
  border-left: 1px solid rgba(255, 255, 255, 0.11);
  padding-left: var(--s-2xl);
}

.footer__h {
  font-family: var(--body);
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--peach);
  margin-bottom: 14px;
}

.footer__list a {
  display: inline-block;
  padding-block: 6px;   /* the tap target, not the type size; 12px below 620px */
  font-size: 0.9375rem;
  line-height: 1.35;
  color: rgba(255, 255, 255, 0.82);
  text-decoration: underline;
  text-decoration-color: transparent;
  text-decoration-thickness: 1.5px;
  text-underline-offset: 5px;
  transition: color .22s var(--ease), text-decoration-color .22s var(--ease);
}
.footer__list a:hover {
  color: var(--white);
  text-decoration-color: var(--peach-deep);
}

.footer-bottom {
  border-top: 1px solid var(--line-dark);
  padding-top: var(--s-md);
  display: grid;
  gap: var(--s-sm);
  font-size: 0.8125rem;
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.72);
}
.footer-bottom__row {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 2px var(--s-lg);
}
/* One step quieter than the lines beside it, but still >4.5:1 on the band. */
.footer-bottom__domain { letter-spacing: 0.02em; color: rgba(255, 255, 255, 0.70); }

/* --------------------------------------------------------------------------
   14. Motion
   -------------------------------------------------------------------------- */
[data-reveal] { opacity: 1; }

.js [data-reveal] {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity .7s var(--ease-soft), transform .7s var(--ease-soft);
  transition-delay: var(--d, 0ms);
}
.js [data-reveal].is-in { opacity: 1; transform: none; }

/* Hero load-in: one orchestrated sequence, not scattered micro-animations */
@keyframes rise {
  from { opacity: 0; transform: translateY(22px); }
  to   { opacity: 1; transform: none; }
}
@keyframes settle {
  from { opacity: 0; transform: translateY(26px) scale(.975); }
  to   { opacity: 1; transform: none; }
}
.js .hero [data-lift] {
  opacity: 0;
  animation: rise .82s var(--ease-soft) forwards;
  animation-delay: var(--d, 0ms);
}
.js .hero [data-lift="panel"] { animation-name: settle; }

/* The ring quietly breathes from turquoise toward coral — the whole product
   idea in one loop. Slow enough to be felt rather than watched. */
@keyframes ring-shift {
  0%, 100% { border-color: var(--turquoise-soft); }
  50%      { border-color: var(--coral); }
}
.js .ring--live { animation: ring-shift 7s var(--ease-soft) infinite; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .js [data-reveal] { opacity: 1; transform: none; transition: none; }
  .js .hero [data-lift] { opacity: 1; animation: none; }
  .js .ring--live { animation: none; }
  .btn:hover, .card:hover { transform: none; }
  *, *::before, *::after { transition-duration: .01ms !important; }
}

/* --------------------------------------------------------------------------
   15. Utilities
   -------------------------------------------------------------------------- */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.skip-link {
  position: absolute;
  top: -60px;
  left: var(--s-md);
  z-index: 200;
  background: var(--coral);
  color: var(--white);
  padding: 11px 18px;
  border-radius: var(--r-pill);
  font-weight: 700;
  font-size: 0.875rem;
  transition: top .22s var(--ease);
}
.skip-link:focus { top: var(--s-md); }

.center     { text-align: center; }
.mx-auto    { margin-inline: auto; }
.measure    { max-width: 62ch; }
.mt-sm  { margin-top: var(--s-sm); }
.mt-md  { margin-top: var(--s-md); }
.mt-lg  { margin-top: var(--s-lg); }
.mt-xl  { margin-top: var(--s-xl); }
.mt-2xl { margin-top: var(--s-2xl); }

/* --------------------------------------------------------------------------
   16. Responsive
   -------------------------------------------------------------------------- */
@media (max-width: 1000px) {
  /* `minmax(0, 1fr)`, not a bare `1fr`, and the zero is the whole fix.
     `1fr` is shorthand for `minmax(auto, 1fr)`, so the track keeps a
     content-based minimum — and the widest min-content in this column is the
     email <input>, whose default `size` gives it an intrinsic ~336px. Below
     ~356px that forced the hero column wider than the viewport and gave the
     page a horizontal scrollbar. Capping the track minimum at 0 lets the
     column shrink. `min-width: 0` on the input does *not* help: a grid item's
     automatic minimum only stops applying once the track itself has an
     explicit zero minimum. The two-column rule above always had the minmax;
     this single-column one was the one place it was dropped. */
  .hero__inner { grid-template-columns: minmax(0, 1fr); gap: var(--s-2xl); }
  .hero__form { max-width: 34rem; }
  .showcase { margin-inline: 0; }
  .float-card { right: 0; }
  .sec-head { grid-template-columns: 1fr; align-items: start; }
  .page-head__inner { grid-template-columns: 1fr; align-items: start; }
  .contact-layout { grid-template-columns: 1fr; }
  .contact-panel { position: static; }
  .grid-4 { grid-template-columns: repeat(2, 1fr); }
  /* The rule between brand and links only reads as intentional while the
     four regions sit on one line; below that the brand block goes full width. */
  .footer-top { grid-template-columns: 1fr; gap: var(--s-xl); }
  .footer__tag { max-width: none; }
  .footer-nav { border-left: 0; padding-left: 0; }

  /* Moments go single-column. The flip has to be undone or the media would
     jump above the heading on one row and below it on the next. */
  .moment, .moment--wide { grid-template-columns: 1fr; gap: var(--s-xl); }
  .moment--flip .moment__media { order: 0; }
  /* .showcase loses its auto margin above (the hero wants it flush left);
     inside a moment there is no text beside it, so it centres again. */
  .moment__media .showcase { margin-inline: auto; }
  .mini-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-lg) var(--s-xl); }
}

@media (max-width: 860px) {
  .nav__toggle { display: block; }
  .nav__links {
    position: absolute;
    left: var(--gutter);
    right: var(--gutter);
    top: calc(100% + 8px);
    flex-direction: column;
    align-items: stretch;
    gap: 2px;
    background: var(--white);
    border-radius: var(--r-card);
    padding: var(--s-md);
    box-shadow: var(--shadow-lg);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-8px);
    transition: opacity .24s var(--ease), transform .24s var(--ease), visibility .24s;
  }
  .nav__links.is-open { opacity: 1; visibility: visible; transform: none; }
  .nav__link { padding: 11px var(--s-sm); font-size: 1rem; }
  .nav__link::after { display: none; }
  .nav__cta { margin: var(--s-sm) 0 0; width: 100%; padding-block: 14px; }

  .grid-2, .grid-3 { grid-template-columns: 1fr; }
  .statement { max-width: none; }
}

@media (max-width: 620px) {
  :root { --gutter: 20px; }
  .grid-4 { grid-template-columns: 1fr; }
  .footer-nav { grid-template-columns: 1fr; gap: var(--s-lg); }
  .footer__list a { padding-block: 12px; }   /* 44px tap target */
  .footer-bottom__row { display: block; }
  .footer-bottom__domain { margin-top: var(--s-xs); }
  .form-grid { grid-template-columns: 1fr; }
  .signup { flex-direction: column; }
  .signup .btn { width: 100%; padding-block: 15px; }
  .step { grid-template-columns: 40px minmax(0, 1fr); gap: var(--s-md); }
  .step__n { font-size: 1.3rem; }
  /* Card drops into normal flow here, so the clearance above is dead space */
  .float-card { position: static; width: auto; margin-top: var(--s-md); }
  .showcase { padding: var(--s-lg) var(--s-md); }
  .deflist > div { grid-template-columns: 1fr; gap: 3px; }
  .contact-line { grid-template-columns: 1fr; gap: 3px; }
  .cta::after { display: none; }

  .mini-grid { grid-template-columns: 1fr; gap: var(--s-lg); }

  /* Three answer buttons plus a time will not sit on one 350px line */
  .opt--stack { flex-direction: column; align-items: stretch; }
  .opt--stack .pick { margin-left: 0; }
  .pick__b { flex: 1; text-align: center; }
}

/* Below ~430px the check-in list runs out of row: a 76px ring, a name, a
   cadence line and a status chip cannot share ~250px without the name
   hyphenating and the chip crowding the meta line. Rather than compress it
   into mush, the illustration sheds its redundant furniture — the ring is the
   status signal in this product, so the chip repeating it is the first thing
   that can go, and the sort caption is a label on a label. Names and cadences,
   which are what the picture is actually saying, keep their space.

   Only reachable below 430px; the approved desktop and tablet composition is
   untouched. Before the hero grid gained its zero track minimum this never
   showed, because the column was overflowing the viewport instead of fitting
   inside it. */
@media (max-width: 430px) {
  .showcase__head .t-cap { display: none; }
  .showcase .ring--lg { --ring-size: 60px; }
  .person__tag { display: none; }
}

@media print {
  .site-header, .skip-link, .nav__toggle, .cta { display: none; }
  body { background: #fff; }
  .js [data-reveal] { opacity: 1; transform: none; }
}
