/* ==========================================================================
   Blooming Baby — marketing site
   Brand tokens mirror the 2026-07-23 design system (docs/blooming-baby-design-mockup.html
   and lib/core/theme/bloom_ui.dart): pale-lavender surfaces, white cards,
   coral primary CTAs, violet brand/accent, pastel pink + mint tints.
   Where the app palette fails WCAG on the web, a web-only variant is defined
   and noted inline — never silently substituted.

   Motion: GSAP + ScrollTrigger (assets/js/vendor). This file owns the *resting*
   state of every animated element; GSAP owns the transition between states.
   Anything hidden for animation is hidden behind `.js` only, so the page is
   fully readable if the scripts never load.
   ========================================================================== */

/* --- Tokens --------------------------------------------------------------- */
:root {
  /* Brand — 1:1 with the design system */
  --lavender-bg: #fdf8ff;   /* page background */
  --surface: #ffffff;       /* cards, header, nav */
  --violet: #7c3aed;        /* brand: links, active states, primary buttons */
  --violet-deep: #6b21a8;   /* emphasis labels, button hover */
  --violet-soft: #a78bfa;   /* decorative only — see contrast note below */
  --violet-tint: #ddd6fe;   /* selected pills, tint fills */
  --coral: #ff9c85;         /* primary CTA fill */
  --coral-deep: #f87456;    /* CTA pressed */
  --pink: #f6b1c3;          /* pastel chip */
  --mint: #dcf2e5;          /* pastel mint container */
  --card-border: #e8d7f6;   /* card + field borders */
  --hairline: #ede9fe;      /* dividers */
  --marigold: #ffb454;      /* warm reward accent */
  --ink: #45375a;           /* primary text (plum ink) */
  --ink-soft: #785589;      /* secondary text (mauve) */

  /* Brand mark — the five petals of the Blooming Baby flower in ROTATION order,
     clockwise from the top (0deg, 72deg, 144deg, 216deg, 288deg), plus its core.
     Source: Figma node 130:475. Not a light-to-dark ramp — the sequence is the
     flower's own arrangement, so re-sorting these by lightness rotates the mark's
     colours out of alignment with assets/img/favicon.svg.
     The mark itself cannot use these: the favicon is a standalone SVG document and
     the header .brand__mark is inlined into four pages, so both carry the hexes
     literally. These tokens exist for the mark's descendants in-page — currently
     the "How it works" step blooms. Change one, change all. */
  --bloom-petal-1: #a663f2;
  --bloom-petal-2: #b176f4;
  --bloom-petal-3: #bc89f5;
  --bloom-petal-4: #c69cf7;
  --bloom-petal-5: #d1aff8;
  --bloom-core: #7c3aed;

  /* Filled CTAs never paint a pastel — the same rule the app follows (see
     CLAUDE.md and test/cta_contrast_test.dart). --coral behind a white label is
     2.0:1, so every filled button paints --cta-fill instead, which is
     BloomColors.ctaGold (#C64F2E) verbatim: 4.6:1 with white, 5.7:1 on hover.
     The pastel keeps its identity role — tints, accents, the nudge card, the
     glow shadows.
     One more web-only note: --violet-soft on white is 2.7:1, so it is
     decorative only. Secondary copy uses --ink-soft (6.1:1 on white, 5.8:1 on
     the lavender background). */
  --cta-fill: #c64f2e;         /* = BloomColors.ctaGold */
  --cta-fill-hover: #ae4527;

  /* Spacing — density dial 3/10 (spacious) */
  --space-2xs: 0.5rem;
  --space-xs: 0.75rem;
  --space-sm: 1rem;
  --space-md: 1.5rem;
  --space-lg: 2.5rem;
  --space-xl: 4rem;
  --space-2xl: 6rem;
  --space-3xl: 8rem;

  /* Radii — rounder than the old sage system; the app's cards are 20-24px and
     the softness is load-bearing for the brand. */
  --radius-sm: 14px;
  --radius-md: 18px;
  --radius-lg: 24px;
  --radius-xl: 32px;
  --radius-pill: 999px;

  /* Shadows tinted with the plum ink rather than neutral black */
  --shadow-sm: 0 1px 2px rgba(69, 55, 90, 0.04), 0 2px 8px rgba(69, 55, 90, 0.05);
  --shadow-md: 0 2px 4px rgba(69, 55, 90, 0.05), 0 10px 26px rgba(69, 55, 90, 0.08);
  --shadow-lg: 0 4px 8px rgba(69, 55, 90, 0.06), 0 20px 52px rgba(69, 55, 90, 0.12);
  --shadow-violet: 0 6px 20px rgba(124, 58, 237, 0.22);
  --shadow-coral: 0 6px 20px rgba(248, 116, 86, 0.28);

  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --dur-fast: 180ms;
  --dur-mid: 280ms;

  --measure: 65ch;
  --container: 1140px;

  /* Form-field label metrics. Split out so a control sitting beside a labelled
     field (the waitlist submit button) can clear the label by exactly its
     height instead of a hand-tuned margin. */
  --label-size: 0.875rem;
  --label-line: 1.65;
  --label-gap: 0.35rem;
  --label-block: calc(var(--label-size) * var(--label-line) + var(--label-gap));

  /* Both the input and the button are pinned to this so they match exactly;
     leaving them to compute their own heights left them ~1px apart. */
  --control-height: 54px;

  --font-display: "Baloo 2", ui-rounded, "Segoe UI", system-ui, sans-serif;
  --font-body: Nunito, system-ui, -apple-system, "Segoe UI", sans-serif;
}

/* --- Reset ---------------------------------------------------------------- */
*,
*::before,
*::after { box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--lavender-bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 1.0625rem;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img, svg { max-width: 100%; display: block; }

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 1.15;
  margin: 0 0 var(--space-sm);
  letter-spacing: -0.005em;
}

h1 { font-size: clamp(2.4rem, 6vw, 3.9rem); font-weight: 700; }
h2 { font-size: clamp(1.9rem, 4vw, 2.75rem); }
h3 { font-size: clamp(1.2rem, 2vw, 1.4rem); font-weight: 700; }

p { margin: 0 0 var(--space-sm); max-width: var(--measure); }

/* `:not(.btn)` keeps these off anchors that are styled as buttons. `a:hover` is
   (0,1,1) and outranks `.btn--primary` at (0,1,0), so without it a link-button
   took --violet-deep for its label on hover — the same colour .btn--primary
   :hover paints its background, i.e. an invisible label at 1:1. The buttons own
   their own colour in every state; these rules are for text links only. */
a:not(.btn) { color: var(--violet); text-decoration-thickness: 1px; text-underline-offset: 3px; }
a:not(.btn):hover { color: var(--violet-deep); }

:focus-visible {
  outline: 3px solid var(--violet);
  outline-offset: 3px;
  border-radius: 6px;
}

.visually-hidden {
  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: -100px; left: var(--space-sm);
  z-index: 200; padding: 0.75rem 1.25rem;
  background: var(--surface); color: var(--violet-deep);
  border-radius: var(--radius-sm); box-shadow: var(--shadow-md);
  font-weight: 800; text-decoration: none;
}
.skip-link:focus { top: var(--space-sm); }

/* --- Layout --------------------------------------------------------------- */
.container {
  width: min(100% - 2.5rem, var(--container));
  margin-inline: auto;
}

.section { padding-block: var(--space-2xl); }
.section--tight { padding-block: var(--space-xl); }

.section__head {
  max-width: 44rem;
  margin-bottom: var(--space-lg);
}
.section__head--center {
  margin-inline: auto;
  text-align: center;
}
.section__head--center p { margin-inline: auto; }

.eyebrow {
  display: inline-block;
  font-size: 0.8125rem;
  font-weight: 800;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--violet-deep);      /* 6.3:1 on the tint pill */
  background: var(--violet-tint);
  padding: 0.4rem 0.85rem;
  border-radius: var(--radius-pill);
  margin-bottom: var(--space-sm);
}

.lede {
  font-size: 1.1875rem;
  color: var(--ink-soft);
}

/* --- Buttons -------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  min-height: var(--control-height);
  padding: 0.85rem 1.6rem;
  border: 0;
  border-radius: var(--radius-md);
  font-family: var(--font-body);
  font-size: 1rem;
  font-weight: 800;
  text-decoration: none;
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-out),
              transform var(--dur-fast) var(--ease-out),
              box-shadow var(--dur-fast) var(--ease-out);
}

/* The deepened coral, never the pastel — see the token note. */
.btn--accent {
  background: var(--cta-fill);
  color: var(--surface);          /* 4.6:1 */
  box-shadow: var(--shadow-sm);
}
.btn--accent:hover {
  background: var(--cta-fill-hover); /* 5.7:1 */
  box-shadow: var(--shadow-coral);
  transform: translateY(-1px);
}
.btn--accent:active { transform: scale(0.985); }

.btn--primary {
  background: var(--violet);
  color: var(--surface);          /* 5.7:1 */
  box-shadow: var(--shadow-sm);
}
.btn--primary:hover {
  background: var(--violet-deep); /* 8.7:1 */
  box-shadow: var(--shadow-violet);
  transform: translateY(-1px);
}
.btn--primary:active { transform: scale(0.985); }

.btn--ghost {
  background: transparent;
  color: var(--violet);
  border: 1.5px solid var(--card-border);
}
.btn--ghost:hover { background: var(--violet-tint); border-color: var(--violet-soft); }

.btn[disabled] { opacity: 0.45; cursor: not-allowed; transform: none; }

/* --- Header --------------------------------------------------------------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: rgba(253, 248, 255, 0.82);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-bottom: 1px solid transparent;
  transition: border-color var(--dur-mid) var(--ease-out),
              box-shadow var(--dur-mid) var(--ease-out),
              background var(--dur-mid) var(--ease-out);
}
.site-header.is-stuck {
  background: rgba(253, 248, 255, 0.93);
  border-bottom-color: var(--hairline);
  box-shadow: var(--shadow-sm);
}

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm);
  min-height: 72px;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  font-family: var(--font-display);
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--ink);
  text-decoration: none;
}
.brand:hover { color: var(--violet-deep); }
.brand__mark { width: 36px; height: 36px; flex: none; }

.site-nav { display: flex; align-items: center; gap: var(--space-md); }

/* `:not(.btn)` is load-bearing. `.site-nav a` is (0,1,1) and outranks
   `.btn--primary` at (0,1,0), so without it the CTA in the header inherits
   --ink-soft and renders at 1.1:1 on the violet fill — a button with an
   invisible label. Excluding buttons from the link rule lets .btn--* win
   outright, in both the resting and hover states. */
.site-nav a:not(.btn) {
  color: var(--ink-soft);
  text-decoration: none;
  font-weight: 700;
  font-size: 0.9375rem;
  transition: color var(--dur-fast) var(--ease-out);
}
.site-nav a:not(.btn):hover { color: var(--violet); }
.site-nav .btn { min-height: 44px; padding: 0.55rem 1.15rem; font-size: 0.9375rem; }

/* `display: contents` lets the four links sit directly in the nav's flex row.
   It lives here rather than in a style="" attribute on the span: an inline
   declaration beats every stylesheet rule including the media query below, so
   the mobile nav could never collapse while it was inline. */
.site-nav__links { display: contents; }

@media (max-width: 720px) {
  .site-nav__links { display: none; }
}

/* --- Hero ----------------------------------------------------------------- */
/* `overflow: hidden` used to cut the blurred blooms off at the hero's bottom
   edge, leaving a hard seam across the page. `overflow-x: clip` contains them
   horizontally without making the hero a scroll container, which is the one
   combination that leaves overflow-y genuinely `visible` — so the blooms bleed
   softly into the next section instead of ending in a straight line. */
.hero {
  position: relative;
  padding-block: var(--space-2xl) var(--space-xl);
  overflow-x: clip;
}

.hero__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-xl);
  align-items: center;
}
@media (min-width: 960px) {
  .hero__grid { grid-template-columns: 1.05fr 0.95fr; gap: var(--space-2xl); }
}

.hero h1 { margin-bottom: var(--space-md); }
.hero h1 .accent { color: var(--violet); white-space: nowrap; }
.hero__lede { font-size: 1.25rem; color: var(--ink-soft); }

/* Word wrappers written by the splitter in main.js. The inner span is what
   moves; the outer clips it so words rise out of nothing. The padding/negative
   margin pair widens the clip box enough for Baloo 2's ascenders and
   descenders without shifting the baseline. */
.word {
  display: inline-block;
  overflow: hidden;
  vertical-align: bottom;
  padding: 0.1em 0 0.18em;
  margin: -0.1em 0 -0.18em;
}
.word__inner { display: inline-block; }

/* Decorative background blooms. Idle drift is CSS; scroll parallax is GSAP. */
.bloom {
  position: absolute;
  border-radius: 50%;
  filter: blur(64px);
  opacity: 0.55;
  pointer-events: none;
  z-index: -1;
}
.bloom--1 { width: 440px; height: 440px; background: var(--violet-tint); top: -130px; right: -80px; animation: drift 22s ease-in-out infinite; }
.bloom--2 { width: 320px; height: 320px; background: var(--pink); bottom: -110px; left: -70px; animation: drift 18s ease-in-out infinite reverse; }
.bloom--3 { width: 260px; height: 260px; background: var(--mint); top: 45%; left: 42%; animation: drift 26s ease-in-out infinite; }

@keyframes drift {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1); }
  50%      { transform: translate3d(0, -28px, 0) scale(1.06); }
}

/* Kawaii glyphs drifting behind the hero copy */
.hero__glyphs { position: absolute; inset: 0; pointer-events: none; z-index: 0; }
.hero__glyph {
  position: absolute;
  width: 46px; height: 46px;
  opacity: 0.85;
  filter: drop-shadow(0 6px 14px rgba(69, 55, 90, 0.14));
}
.hero__glyph--star  { top: 14%; right: 6%; width: 40px; height: 40px; }
.hero__glyph--heart { top: 62%; right: 44%; width: 34px; height: 34px; }
.hero__glyph--moon  { bottom: 12%; left: 3%; width: 42px; height: 42px; }
/* One drifting glyph is charm, three in a single column is clutter — and at
   this width the star lands on top of the headline. */
@media (max-width: 959px) {
  .hero__glyph--heart,
  .hero__glyph--star { display: none; }
}

/* --- Waitlist form -------------------------------------------------------- */
.waitlist-form {
  margin-top: var(--space-md);
  max-width: 30rem;
  position: relative;
  z-index: 1;
}

.field-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2xs);
}
.field-row .field { flex: 1 1 15rem; }

/* The submit button has to line up with the input, not with the .field column
   that wraps it — that column is taller, because it also reserves a line for
   the inline error under the input.
     · `align-self: flex-start` opts the button out of the row's default
       `stretch`, which was pulling its bottom edge all the way down to the
       error line and rendering a button half again as tall as the input.
     · `margin-top` then drops it by exactly the space the label occupies.
   This used to be a `style="margin-top:1.6rem"` in the markup, which fixed the
   top edge but could not stop the stretch. --label-block is derived from the
   label's own metrics below, so the two stay in step if the type scale moves. */
.field-row .btn {
  flex: 0 0 auto;
  align-self: flex-start;
  margin-top: var(--label-block);
}

/* Stacked below this width, and the break is declared rather than left to
   `flex-wrap` to discover. Once the button is on its own line the two rules
   above stop describing anything real: it is no longer clearing a label beside
   it, so --label-block becomes ~1.8rem of dead space *under* the input, and
   `flex: 0 0 auto` leaves a label-width button stranded at the left margin.
   Together they put 63px between the field and its own CTA on every phone.
   The breakpoint sits above the point where the row would wrap on its own —
   including inside .cta-panel, which loses a further 5rem of width to its own
   padding — so the emergent wrap can never fire first and reintroduce it. */
@media (max-width: 37.5rem) {
  .field-row .field { flex: 1 1 100%; }
  .field-row .btn {
    flex: 1 1 100%;
    align-self: stretch;
    margin-top: 0;
  }
}

.field label {
  display: block;
  font-size: var(--label-size);
  line-height: var(--label-line);
  font-weight: 800;
  margin-bottom: var(--label-gap);
  color: var(--ink);
}

.field input {
  width: 100%;
  min-height: var(--control-height);
  padding: 0.8rem 1rem;
  font-family: var(--font-body);
  font-size: 1rem;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--card-border);
  border-radius: var(--radius-sm);
  transition: border-color var(--dur-fast) var(--ease-out),
              box-shadow var(--dur-fast) var(--ease-out);
}
.field input::placeholder { color: #9b86ab; } /* 4.6:1 on white — placeholders stay legible */
.field input:focus {
  outline: none;
  border-color: var(--violet);
  box-shadow: 0 0 0 3px rgba(124, 58, 237, 0.18);
}
.field input[aria-invalid="true"] {
  border-color: #ba1a1a;
  box-shadow: 0 0 0 3px rgba(186, 26, 26, 0.12);
}

.field__error {
  display: block;
  min-height: 1.25rem;
  margin-top: 0.35rem;
  font-size: 0.875rem;
  font-weight: 700;
  color: #a01414;
}

.form-note {
  margin-top: var(--space-2xs);
  font-size: 0.875rem;
  color: var(--ink-soft);
  max-width: none;
}

.form-status {
  margin-top: var(--space-sm);
  padding: var(--space-sm) var(--space-md);
  border-radius: var(--radius-md);
  font-weight: 700;
  display: none;
}
.form-status.is-visible { display: block; }
.form-status--ok {
  background: var(--mint);
  color: #1f5137;             /* 7.6:1 on mint */
  border: 1px solid #a9dcc2;
}
.form-status--err {
  background: #fdecec;
  color: #8c1414;
  border: 1px solid #e5a3a3;
}

/* Spinner shown while submitting — sits inside a filled button, next to the
   white label. */
.spinner {
  width: 16px; height: 16px;
  border: 2px solid rgba(255, 255, 255, 0.45);
  border-top-color: var(--surface);
  border-radius: 50%;
  animation: spin 700ms linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* --- Phone mockup --------------------------------------------------------- */
/* Mirrors the 2026-07-23 Home screen: lavender canvas, white cards, violet
   active states, coral nudge CTA, kawaii PNGs for every content glyph. */
.phone-stage { position: relative; }

.phone {
  position: relative;
  width: min(300px, 78vw);
  margin-inline: auto;
  aspect-ratio: 9 / 19;
  background: var(--ink);
  border-radius: 46px;
  padding: 11px;
  box-shadow: var(--shadow-lg);
}
/* Idle float is CSS on a wrapper so GSAP can own `transform` on .phone itself
   without the two fighting over the same property. */
.phone-float { animation: float 7s ease-in-out infinite; }
@keyframes float {
  0%, 100% { transform: translate3d(0, 0, 0); }
  50%      { transform: translate3d(0, -14px, 0); }
}

.phone__screen {
  height: 100%;
  background: var(--lavender-bg);
  border-radius: 36px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  padding: 1.4rem 0.85rem 0.7rem;
}

.phone__notch {
  position: absolute;
  top: 11px; left: 50%;
  transform: translateX(-50%);
  width: 92px; height: 22px;
  background: var(--ink);
  border-radius: 0 0 14px 14px;
  z-index: 2;
}

.phone__greeting {
  font-family: var(--font-display);
  font-size: 1rem;
  font-weight: 700;
  margin: 0.4rem 0 0.5rem;
}

.phone__chips { display: flex; gap: 0.3rem; margin-bottom: 0.7rem; }
.phone__chip {
  padding: 0.28rem 0.6rem;
  border-radius: var(--radius-pill);
  font-size: 0.6rem;
  font-weight: 800;
  background: var(--surface);
  color: var(--ink-soft);
  border: 1px solid var(--card-border);
}
.phone__chip.is-active {
  background: var(--violet);
  color: var(--surface);
  border-color: var(--violet);
}

.phone__label {
  font-family: var(--font-display);
  font-size: 0.68rem;
  font-weight: 700;
  color: var(--ink);
  margin: 0.15rem 0 0.35rem;
}

.phone__quick {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.35rem;
  margin-bottom: 0.5rem;
}
.phone__quick div {
  background: var(--surface);
  border-radius: var(--radius-sm);
  padding: 0.45rem 0.2rem;
  text-align: center;
  font-size: 0.55rem;
  font-weight: 800;
  box-shadow: var(--shadow-sm);
}
.phone__quick img { width: 22px; height: 22px; margin: 0 auto 0.15rem; }

.phone__nudge {
  background: var(--pink);
  border-radius: var(--radius-sm);
  padding: 0.45rem 0.5rem 0.45rem 0.65rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.4rem;
  font-size: 0.58rem;
  font-weight: 700;
  color: var(--ink);           /* 6.2:1 on pink */
  margin-bottom: 0.55rem;
}
.phone__nudge b {
  background: var(--cta-fill);   /* filled action → deepened coral, white label */
  color: var(--surface);
  border-radius: var(--radius-pill);
  padding: 0.22rem 0.55rem;
  font-size: 0.55rem;
  font-weight: 800;
  white-space: nowrap;
}

.phone__card {
  background: var(--surface);
  border-radius: var(--radius-sm);
  padding: 0.5rem 0.6rem;
  margin-bottom: 0.35rem;
  box-shadow: var(--shadow-sm);
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.phone__dot {
  width: 28px; height: 28px; flex: none;
  border-radius: 50%;
  display: grid;
  place-items: center;
}
.phone__dot img { width: 18px; height: 18px; }
.phone__dot--violet { background: var(--violet-tint); }
.phone__dot--mint { background: var(--mint); }
.phone__dot--pink { background: var(--pink); }
.phone__card-title { display: block; font-size: 0.62rem; font-weight: 800; line-height: 1.3; }
.phone__card-meta { display: block; font-size: 0.55rem; color: var(--ink-soft); line-height: 1.3; }

.phone__nav {
  margin-top: auto;
  background: var(--surface);
  border-radius: var(--radius-md);
  padding: 0.45rem;
  display: flex;
  justify-content: space-around;
  box-shadow: var(--shadow-sm);
}
.phone__nav span {
  width: 18px; height: 4px;
  border-radius: 3px;
  background: var(--hairline);
}
.phone__nav span:first-child { background: var(--violet); width: 26px; }

/* --- Cards / features ----------------------------------------------------- */
.grid {
  display: grid;
  gap: var(--space-md);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
}

.card {
  background: var(--surface);
  border: 1px solid var(--card-border);
  border-radius: var(--radius-lg);
  padding: var(--space-md);
  box-shadow: var(--shadow-sm);
  transition: transform var(--dur-mid) var(--ease-out),
              box-shadow var(--dur-mid) var(--ease-out),
              border-color var(--dur-mid) var(--ease-out);
}
.card:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-md);
  border-color: var(--violet-soft);
}
.card h3 { margin-bottom: 0.4rem; }
.card p { font-size: 0.9375rem; color: var(--ink-soft); margin-bottom: 0; }

.card__icon {
  width: 58px; height: 58px;
  border-radius: var(--radius-md);
  display: grid;
  place-items: center;
  margin-bottom: var(--space-sm);
}
.card__icon img { width: 36px; height: 36px; }

.tint--violet { background: var(--violet-tint); }
.tint--pink { background: var(--pink); }
.tint--mint { background: var(--mint); }
.tint--peach { background: #ffe3da; }

/* --- Steps — "the stem", the page's signature ----------------------------- */
/* The three steps are a real sequence, so they get a real stem: a violet line
   that grows down the section as you scroll, opening each bloom as it reaches
   it. Bud → bloom is the app's own milestone metaphor, borrowed for the page. */
.steps { position: relative; padding-left: 4.75rem; }

/* Track + growing fill. `.steps__fill` is scaled by ScrollTrigger; without JS
   it simply sits at full height, so the stem is drawn rather than missing. */
.steps__track,
.steps__fill {
  position: absolute;
  left: 23px;
  top: 8px;
  bottom: 8px;
  width: 3px;
  border-radius: 2px;
}
.steps__track { background: var(--hairline); }
.steps__fill {
  background: linear-gradient(180deg, var(--violet-soft), var(--violet));
  transform-origin: top center;
}

.step { position: relative; margin-bottom: var(--space-lg); }
.step:last-child { margin-bottom: 0; }
.step h3 { margin-bottom: 0.25rem; }
.step p { color: var(--ink-soft); margin-bottom: 0; }

.step__bloom {
  position: absolute;
  left: -4.75rem;
  top: -0.35rem;
  width: 48px; height: 48px;
  display: grid;
  place-items: center;
}
.step__bloom svg { width: 48px; height: 48px; }
/* No `transform-origin` here on purpose. SVG's `transform` attribute maps onto
   the CSS `transform` property, so a CSS transform-origin would be applied on
   top of the rotate()'s own centre and each petal would be flung outward by
   twice the offset — the flower comes apart. The rotate(deg cx cy) in the
   markup already carries its centre. */
.step__bloom .petal {
  fill: var(--violet-tint);
  transition: fill var(--dur-mid) var(--ease-out);
}
.step__bloom .core {
  fill: var(--surface);
  stroke: var(--violet-soft);
  stroke-width: 2;
  transition: fill var(--dur-mid) var(--ease-out),
              stroke var(--dur-mid) var(--ease-out);
}
/* Opened, the step bloom lands on the brand mark's own colours (Figma node
   130:475), so the flower a parent scrolls past is the flower in the header.
   `nth-of-type` counts per element type, and the petals are the only <ellipse>
   children — the <circle> core is numbered separately and never matches here.
   Petal n carries rotate(72n), so these must stay in markup order: reordering
   them spins the mark's colours around the flower. */
.step__bloom.is-open .petal:nth-of-type(1) { fill: var(--bloom-petal-1); }
.step__bloom.is-open .petal:nth-of-type(2) { fill: var(--bloom-petal-2); }
.step__bloom.is-open .petal:nth-of-type(3) { fill: var(--bloom-petal-3); }
.step__bloom.is-open .petal:nth-of-type(4) { fill: var(--bloom-petal-4); }
.step__bloom.is-open .petal:nth-of-type(5) { fill: var(--bloom-petal-5); }
.step__bloom.is-open .core { fill: var(--bloom-core); stroke: var(--bloom-core); }

@media (max-width: 560px) {
  .steps { padding-left: 3.5rem; }
  .steps__track, .steps__fill { left: 17px; }
  .step__bloom { left: -3.5rem; width: 36px; height: 36px; }
  .step__bloom svg { width: 36px; height: 36px; }
}

/* --- Bands ---------------------------------------------------------------- */
.band {
  background: var(--violet-tint);
  border-radius: var(--radius-xl);
  padding: var(--space-xl) var(--space-lg);
}
.band--mint { background: var(--mint); }
.band--surface { background: var(--surface); border: 1px solid var(--card-border); }

.trust-list { list-style: none; padding: 0; margin: 0; display: grid; gap: var(--space-md); }
@media (min-width: 760px) { .trust-list { grid-template-columns: 1fr 1fr; } }

.trust-list li {
  display: flex;
  gap: 0.75rem;
  align-items: flex-start;
}
.trust-list svg {
  width: 22px; height: 22px; flex: none;
  margin-top: 0.2rem;
  color: var(--violet-deep);
}
.trust-list strong { display: block; margin-bottom: 0.1rem; }
.trust-list span { font-size: 0.9375rem; color: #5c4470; } /* 6.0:1 on the mint band */

/* --- FAQ ------------------------------------------------------------------ */
.faq { max-width: 46rem; margin-inline: auto; }

.faq details {
  background: var(--surface);
  border: 1px solid var(--card-border);
  border-radius: var(--radius-md);
  margin-bottom: var(--space-2xs);
  overflow: hidden;
}
.faq summary {
  cursor: pointer;
  padding: var(--space-sm) var(--space-md);
  font-weight: 800;
  font-size: 1.0625rem;
  list-style: none;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-sm);
  min-height: 56px;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: "";
  width: 11px; height: 11px;
  flex: none;
  border-right: 2.5px solid var(--violet);
  border-bottom: 2.5px solid var(--violet);
  transform: rotate(45deg);
  transition: transform var(--dur-mid) var(--ease-out);
}
.faq details[open] summary::after { transform: rotate(-135deg); }
.faq summary:hover { background: var(--lavender-bg); }
.faq .faq__body { padding: 0 var(--space-md) var(--space-md); }
.faq .faq__body p { color: var(--ink-soft); font-size: 0.9375rem; margin-bottom: 0.75rem; }
.faq .faq__body p:last-child { margin-bottom: 0; }

/* --- Final CTA ------------------------------------------------------------ */
.cta-panel {
  position: relative;
  overflow: hidden;
  background: linear-gradient(150deg, #5b21b6 0%, var(--ink) 100%);
  border-radius: var(--radius-xl);
  padding: var(--space-xl) var(--space-lg);
  text-align: center;
  color: var(--surface);
}
.cta-panel h2 { color: var(--surface); }               /* 9.0:1 on the gradient */
.cta-panel p { color: var(--violet-tint); margin-inline: auto; } /* 7.8:1 */
.cta-panel .waitlist-form { margin-inline: auto; }
.cta-panel .field label { color: var(--surface); }
.cta-panel .form-note { color: var(--violet-tint); }
.cta-panel .form-status--ok { color: #1f5137; }

/* Soft petals in the panel corners — decoration, drifts with scroll via GSAP */
.cta-panel__petal {
  position: absolute;
  border-radius: 50%;
  filter: blur(48px);
  pointer-events: none;
}
.cta-panel__petal--a { width: 260px; height: 260px; background: rgba(255, 156, 133, 0.5); top: -90px; left: -70px; }
.cta-panel__petal--b { width: 220px; height: 220px; background: rgba(167, 139, 250, 0.55); bottom: -90px; right: -60px; }

/* --- Footer --------------------------------------------------------------- */
.site-footer {
  border-top: 1px solid var(--hairline);
  padding-block: var(--space-lg);
  margin-top: var(--space-2xl);
}
.site-footer__inner {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-md);
  justify-content: space-between;
  align-items: center;
}
.site-footer p { font-size: 0.875rem; color: var(--ink-soft); margin: 0; }
.footer-nav { display: flex; flex-wrap: wrap; gap: var(--space-md); }
.footer-nav a { font-size: 0.875rem; font-weight: 700; }

.disclaimer {
  margin-top: var(--space-md);
  padding-top: var(--space-md);
  border-top: 1px solid var(--hairline);
  font-size: 0.8125rem;
  color: var(--ink-soft);
  max-width: none;
}

/* --- Legal pages ---------------------------------------------------------- */
.legal { padding-block: var(--space-xl) var(--space-2xl); }
.legal__body { max-width: 46rem; }
.legal__body h2 {
  font-size: clamp(1.35rem, 2.4vw, 1.7rem);
  margin-top: var(--space-lg);
  padding-top: var(--space-sm);
  border-top: 1px solid var(--hairline);
}
.legal__body h3 { font-size: 1.1rem; margin-top: var(--space-md); }
.legal__body ul { padding-left: 1.15rem; margin-bottom: var(--space-sm); }
.legal__body li { margin-bottom: 0.4rem; max-width: var(--measure); }
.legal__body table {
  width: 100%;
  border-collapse: collapse;
  margin-bottom: var(--space-md);
  font-size: 0.9375rem;
}
.legal__body th, .legal__body td {
  text-align: left;
  padding: 0.7rem 0.6rem;
  border-bottom: 1px solid var(--hairline);
  vertical-align: top;
}
.legal__body th { font-weight: 800; background: var(--violet-tint); }
.table-wrap { overflow-x: auto; }

.meta-line {
  font-size: 0.875rem;
  color: var(--ink-soft);
  margin-bottom: var(--space-lg);
}

.callout {
  background: var(--surface);
  border: 1px solid var(--card-border);
  border-left: 4px solid var(--coral);
  border-radius: var(--radius-sm);
  padding: var(--space-sm) var(--space-md);
  margin-bottom: var(--space-md);
}
.callout p { margin-bottom: 0; font-size: 0.9375rem; }

/* --- Motion resting states ------------------------------------------------
   Everything below is gated on `.js`, which boot.js adds to <html> before the
   first paint. If the scripts fail or are blocked, none of these rules apply
   and the page renders complete and static. GSAP animates from these states. */
.js .reveal { opacity: 0; }
.js .hero__glyph { opacity: 0; }
.js .steps__fill { transform: scaleY(0); }
.js .step__bloom svg { opacity: 0; transform: scale(0.4); }
.js .phone__chip,
.js .phone__quick div,
.js .phone__nudge,
.js .phone__card { opacity: 0; }

/* --- Reduced motion -------------------------------------------------------
   main.js checks the same query and skips every tween, jumping straight to the
   resting-visible state, so this block only has to neutralise the CSS loops. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  .js .reveal,
  .js .hero__glyph,
  .js .phone__chip,
  .js .phone__quick div,
  .js .phone__nudge,
  .js .phone__card { opacity: 1; }
  .js .steps__fill { transform: scaleY(1); }
  .js .step__bloom svg { opacity: 1; transform: none; }
  .phone-float, .bloom { animation: none; }
}
