/* ==========================================================================
   Strandly — teaser landing page
   Design tokens lifted verbatim from the Claude Design handoff.
   ========================================================================== */

/* --------------------------------------------------------------- fonts --
   Self-hosted, deliberately. No Google Fonts request means no third-party
   sees a visitor's IP — which is what the privacy page promises — and it
   removes a DNS + TLS round trip to another origin from the critical path.

   Satoshi      Indian Type Foundry, ITF Free Font License (commercial OK)
   Chakra Petch Cadson Demak, SIL Open Font License 1.1
   ---------------------------------------------------------------------- */

@font-face {
  font-family: 'Satoshi';
  /* Nothing on the page sets weight 400 — body is 500. This face exists only
     so a UA default (form controls that don't inherit) can't fall off Satoshi. */
  src: url('assets/fonts/satoshi-400.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Satoshi';
  src: url('assets/fonts/satoshi-500.woff2') format('woff2');
  font-weight: 500; font-style: normal; font-display: swap;
}
/* Satoshi has no 600; 700 covers every heavier use on the page. */
@font-face {
  font-family: 'Satoshi';
  src: url('assets/fonts/satoshi-700.woff2') format('woff2');
  font-weight: 600 700; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Chakra Petch';
  src: url('assets/fonts/chakra-500.woff2') format('woff2');
  font-weight: 500; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Chakra Petch';
  src: url('assets/fonts/chakra-600.woff2') format('woff2');
  font-weight: 600; font-style: normal; font-display: swap;
}

:root {
  /* Surfaces, darkest → lightest */
  /* Steps are ΔL* 2.0-5.6 apart, computed in Lab. The old ramp stepped by
     0.60-1.10, which is below the threshold where a surface reads as raised at
     all — so the page had eight tokens and one apparent colour. --deep and --bg
     are unchanged: the base was never the problem. */
  --deep:      #05070D;   /* L*  1.93 */
  --bg:        #070A12;   /* L*  2.76 */
  --bg-2:      #0C141F;   /* L*  6.12 */
  --panel-2:   #111824;   /* L*  8.13 */
  --panel:     #161D28;   /* L* 10.58 */
  --raised:    #202631;   /* L* 15.03 */
  --raised-2:  #2C323D;   /* L* 20.65 */

  /* Ink */
  --ink:       #F3F1EE;   /* bone, not blue-white. 17.55:1, matched luminance */
  --muted:     #A9B6CE;
  --dim:       #7385A0;   /* 5.0:1 on card bg; #6E7C97 was 4.47 */
  --faint:     #57648A;   /* 3.4:1 — #525F80 sat at 3.12, no headroom under a section wash */

  /* Accent */
  --cyan:      #4DC3FF;
  --violet:    #645BC6;
  --link:      #57A9EE;
  --link-hover:#6FBBFB;
  --error:     #FF9B8A;   /* 9.71:1 — the only warm hue on the page */

  /* Lines */
  --line:      rgba(122, 162, 224, .10);
  --line-2:    rgba(122, 162, 224, .14);
  --line-hi:   rgba(122, 162, 224, .22);   /* was 130,170,235 — hover shifted hue, not just alpha */
  /* Interactive controls only. WCAG 1.4.11 wants 3:1 for the visible boundary
     of a component; .65 measures 3.77:1 on --deep. Decorative card edges stay
     whisper-thin, but a form field is not decoration. */
  --line-input: rgba(122, 162, 224, .65);

  /* Type — Satoshi is geometric like the logo wordmark; Chakra Petch keeps
     the technical edge on headings. Two families, no system fallback voice. */
  --display: 'Chakra Petch', 'Satoshi', -apple-system, system-ui, sans-serif;
  --body:    'Satoshi', -apple-system, system-ui, sans-serif;

  /* Motion — one easing curve everywhere */
  --ease: cubic-bezier(.16, 1, .3, 1);
  --ease-io: cubic-bezier(.65, 0, .35, 1);

  --shell: 1180px;
  --gutter: 32px;
  --header-h: 68px;   /* measured; scroll offsets derive from this */
}

/* --------------------------------------------------------------- reset -- */

* { box-sizing: border-box; }

html, body { margin: 0; padding: 0; background: var(--bg); }
html { scroll-behavior: smooth; }

body {
  -webkit-font-smoothing: antialiased;
  /* `clip`, never `hidden`. overflow-x:hidden turns body into a scroll container
     and silently breaks position:sticky on iOS — which unpins the hero and
     leaves a screen of emptiness behind it. Nothing actually overflows anyway;
     the wide blooms are clipped by their own sections. */
  overflow-x: clip;
  color: var(--ink);
  font-family: var(--body);
  font-size: 15px;
  line-height: 1.6;          /* peers measure 1.60-1.63 on dark; 1.5 is a light-mode value */
  font-weight: 500;          /* Satoshi 500 ~= the 510 variable weight peers use on dark */
  letter-spacing: -.004em;
  min-height: 100vh;
}

::selection { background: rgba(77, 195, 255, .28); color: var(--ink); }

a { color: var(--link); text-decoration: none; transition: color .18s var(--ease); }
a:hover { color: var(--link-hover); }

/* outline, not box-shadow: .btn--primary owns its box-shadow for the glow,
   and at equal specificity it won — leaving every primary CTA with no focus
   indicator at all. outline also survives forced-colors mode. */
:focus-visible { outline: 3px solid var(--cyan); outline-offset: 3px; }

img { display: block; }

/* The `hidden` attribute only sets display:none in the UA stylesheet, so ANY
   author rule with a display value silently beats it. .success__row and
   .success__share are display:flex, so el.hidden = true did nothing and their
   placeholder dashes stayed on screen. Global, so it can never bite again. */
[hidden] { display: none !important; }
input::placeholder { color: var(--dim); }

.shell { max-width: var(--shell); margin: 0 auto; }
.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;
}

/* Keyboard users shouldn't have to tab the whole header on every page. */
.skip {
  position: fixed; left: 12px; top: -100px; z-index: 100;
  padding: 12px 20px; border-radius: 999px;
  background: var(--cyan); color: #061019;
  font-size: 14px; font-weight: 600;
  transition: top .18s var(--ease);
}
.skip:focus { top: 12px; color: #061019; }

/* ----------------------------------------------------------- keyframes -- */

@keyframes sVeil    { 0%, 34% { opacity: 1 } 100% { opacity: 0; visibility: hidden } }
@keyframes sPreload {
  0%   { opacity: 0; transform: scale(.93) }
  24%  { opacity: 1; transform: scale(1) }
  72%  { opacity: 1; transform: scale(1) }
  100% { opacity: 0; transform: scale(1.05) }
}
@keyframes sBloom { 0%, 100% { opacity: .55; transform: scale(1) } 50% { opacity: 1; transform: scale(1.09) } }
/* Masked rise. The word is never transparent, only out of frame, which is
   what keeps the h1 eligible as an LCP candidate from the first paint. */
@keyframes sRise  { to { transform: translateY(0) } }
@keyframes sFade  { from { opacity: 0; transform: translateY(14px) } to { opacity: 1; transform: translateY(0) } }
@keyframes sCue   { 0%, 100% { opacity: .30; transform: translateY(0) } 50% { opacity: .85; transform: translateY(7px) } }
@keyframes sResolved {
  0%   { text-shadow: none }
  35%  { text-shadow: 0 0 14px rgba(77, 195, 255, .75) }
  100% { text-shadow: none }
}

/* ----------------------------------------------------------- preloader -- */

.preloader {
  position: fixed; inset: 0; z-index: 90;
  display: flex; align-items: center; justify-content: center;
  background: var(--bg); pointer-events: none;
  animation: sVeil .78s var(--ease) forwards;
}
.preloader__inner {
  position: relative; display: flex; align-items: center; justify-content: center;
  animation: sPreload .78s var(--ease) forwards;
}
.preloader__bloom {
  position: absolute; width: 420px; height: 420px; border-radius: 50%;
  background: radial-gradient(circle, rgba(77,195,255,.22), rgba(100,91,198,.13) 45%, rgba(100,91,198,0) 72%);
  filter: blur(28px);
}
.preloader__logo { position: relative; width: 208px; height: auto; }


/* ---------------------------------------------------------------- grain --
   One fixed layer, topmost, so it dithers every gradient on the page at once.
   Near-black surfaces only step 2-7 RGB levels apart here, which is exactly the
   range that bands visibly on an OLED phone in a dark room.

   Four details that are easy to get wrong:
   · color-interpolation-filters='sRGB' is required — the SVG default is
     linearRGB, which renders this roughly twice as bright and blotchy.
   · no mix-blend-mode. overlay/soft-light are anchored on mid-grey and nearly
     vanish at our lightness, which pushes the opacity up until it blows out
     over the panels. White at 3.5% composited normally is additive and free.
   · fractalNoise, not turbulence — turbulence takes an absolute value and
     produces dark creased veins that read as dirt.
   · pointer-events: none, or this silently swallows every tap on the page.
   -------------------------------------------------------------------------- */

.grain {
  position: fixed; inset: 0; z-index: 60;
  pointer-events: none;
  opacity: .035;
  background-repeat: repeat;
  background-size: 220px 220px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n' x='0' y='0' width='100%25' height='100%25' color-interpolation-filters='sRGB'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='matrix' values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0.2126 0.7152 0.0722 0 0'/%3E%3CfeComponentTransfer%3E%3CfeFuncA type='linear' slope='0.55'/%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
@media (prefers-reduced-transparency: reduce) { .grain { display: none; } }

/* Scroll progress. CSS-only and compositor-driven; absent rather than
   polyfilled where unsupported, since a JS scroll handler costs more than the
   feature is worth. */
.progress {
  position: fixed; inset: 0 0 auto 0; height: 2px; z-index: 70;
  transform: scaleX(0); transform-origin: 0 50%;
  background: linear-gradient(90deg, var(--cyan), var(--violet));
  pointer-events: none;
}
@supports (animation-timeline: scroll()) {
  @keyframes sProgress { to { transform: scaleX(1); } }
  .progress {
    animation: sProgress linear both;
    animation-timeline: scroll(root block);   /* must follow the shorthand */
  }
}
@media (prefers-reduced-motion: reduce) { .progress { display: none; } }

/* -------------------------------------------------------------- header -- */

@supports (animation-timeline: scroll()) {
  @media (prefers-reduced-motion: no-preference) {
    @keyframes sHeaderIn {
      from { background-color: rgba(7, 10, 18, 0); border-bottom-color: transparent }
      to   { background-color: rgba(7, 10, 18, .72); border-bottom-color: var(--line) }
    }
    .header {
      animation: sHeaderIn linear both;
      animation-timeline: scroll(root block);
      animation-range: 0 150px;
    }
  }
}
.header {
  position: sticky; top: 0; z-index: 40;
  background: rgba(7, 10, 18, .72);
  backdrop-filter: saturate(140%) blur(18px);
  -webkit-backdrop-filter: saturate(140%) blur(18px);
  border-bottom: 1px solid var(--line);
}
.header__inner {
  max-width: var(--shell); margin: 0 auto; padding: 13px var(--gutter);
  display: flex; align-items: center; justify-content: space-between; gap: 32px;
}
.brand { display: flex; align-items: center; gap: 13px; flex: 0 0 auto; }
.brand__mark {
  width: 36px; height: 36px; object-fit: contain;
  filter: drop-shadow(0 0 10px rgba(77, 195, 255, .25));
}
.brand__text { display: block; }

/* The wordmark's Y is a custom letterform — no typeface reproduces it, so the
   header uses the logo artwork itself rather than an approximation. */
.brand__wordmark { width: auto; height: 20px; }
.brand__mark { transition: filter .25s var(--ease); }
.brand:hover .brand__mark { filter: drop-shadow(0 0 15px rgba(77, 195, 255, .5)); }
.brand__tag {
  font-family: var(--body); font-weight: 500; font-size: 9px;
  letter-spacing: .18em; text-transform: uppercase; color: var(--dim); margin-top: 5px;
}

.nav { display: flex; align-items: center; gap: 6px; font-size: 14px; font-weight: 500; }
.nav__link {
  display: none; padding: 9px 14px; border-radius: 14px; color: var(--muted);
  transition: color .18s var(--ease), background .18s var(--ease);
}
.nav__link:hover { color: var(--ink); background: var(--panel); }
@media (min-width: 900px) { .nav__link { display: inline-flex; } }

/* --------------------------------------------------------------- icons --
   Every glyph inherits currentColor and a 1.25 stroke — thinner than Lucide's
   1.5 default, to match the hairline weight of the logo mark. The four card
   icons are drawn for Strandly rather than pulled from the stock set. */

.ico { flex: 0 0 auto; }
.ico--no    { color: var(--faint); }
.ico--yes   { color: var(--cyan); }
/* transform must be here, not on `summary svg`: this rule is more specific and
   `transition` is a shorthand, so it replaced the whole declaration and the
   chevron snapped 180deg with no animation. */
.ico--chev  { color: var(--dim); transition: color .18s var(--ease), transform .3s var(--ease); }
.ico--trust { color: var(--dim); }
.ico--card  { color: var(--cyan); }

/* -------------------------------------------------------------- buttons -- */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  min-height: 54px; padding: 16px 30px; border: 0; border-radius: 999px;
  font-family: var(--body); font-size: 15px; font-weight: 600; letter-spacing: .01em;
  cursor: pointer; white-space: nowrap;
}
@property --btn-angle { syntax: "<angle>";  inherits: false; initial-value: 135deg }
@property --btn-glow  { syntax: "<number>"; inherits: false; initial-value: 0 }

.btn--primary {
  /* The original gradient ran to #645BC6, which put the label at 3.52:1 — and
     hover slid it further onto the violet, so the button got *less* readable the
     moment you touched it. This keeps the cyan→violet direction but stops at a
     light periwinkle, so both ends clear AA (9.6:1 and 7.0:1). */
  background: linear-gradient(var(--btn-angle), #4DC3FF 0%, #8B9AD6 100%);
  color: #061019;
  box-shadow:
    0 0 calc(22px * var(--btn-glow)) rgba(77, 195, 255, calc(.22 * var(--btn-glow))),
    0 0 calc(46px * var(--btn-glow)) rgba(100, 91, 198, calc(.12 * var(--btn-glow)));
  transition:
    --btn-angle .55s var(--ease), --btn-glow .3s var(--ease),
    background .28s var(--ease), transform .12s var(--ease);
}
/* Gated so a touch device can't latch into the hover state on tap. */
@media (hover: hover) and (pointer: fine) {
  .btn--primary:hover {
    --btn-angle: 205deg; --btn-glow: 1;
    background: linear-gradient(var(--btn-angle), #6FD0FF 0%, #9DAAE0 100%);
    transform: translateY(-1px);
  }
}
.btn--primary:active { transform: scale(.975); }

.btn--ghost {
  min-height: 44px; padding: 11px 20px;
  border: 1px solid var(--line); background: var(--panel); color: var(--muted);
  font-weight: 500; margin-left: 10px;
  transition: border-color .18s var(--ease), background .18s var(--ease), color .18s var(--ease);
}
.btn--ghost:hover { border-color: var(--line-hi); background: var(--raised); color: var(--ink); }

.btn--quiet {
  flex: 0 0 auto; min-height: 54px; padding: 15px 26px;
  border: 1px solid var(--line); background: var(--raised); color: var(--ink);
  font-weight: 500;
  transition: border-color .18s var(--ease), background .18s var(--ease);
}
.btn--quiet:hover { border-color: var(--line-hi); background: var(--raised-2); }
/* The label grows to "Copied. Send it." — reserve the width so nothing jumps. */
#waitlist-copy { min-width: 168px; }

/* ---------------------------------------------------------------- hero -- */

.hero { position: relative; height: 230vh; height: 230svh; }
.hero__stage {
  position: sticky; top: 0; height: 100vh; height: 100svh; overflow: hidden;
  display: flex; align-items: center;
}
.hero__canvas {
  position: absolute; inset: 0; width: 100%; height: 100%;
  display: block; opacity: .45;
}
/* Permanent, not gated on a class nothing applied. main.js writes a
   full-viewport blur on scroll; without this it has no compositor hint. */
.hero__canvas { will-change: filter, opacity; }
.hero__vignette {
  position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(130% 95% at 50% 42%, rgba(7, 10, 18, 0) 0%, rgba(7, 10, 18, .55) 58%, var(--bg) 100%);
}
.hero__fade {
  position: absolute; left: 0; right: 0; bottom: 0; height: 34vh; pointer-events: none;
  background: linear-gradient(to bottom, rgba(7, 10, 18, 0), var(--bg));
}
.hero__content {
  position: relative; z-index: 2; width: 100%; max-width: var(--shell);
  margin: 0 auto; padding: 0 var(--gutter) 84px;
}

.eyebrow {
  display: inline-flex; align-items: center; gap: 10px;
  padding: 7px 15px 7px 11px; border: 1px solid var(--line-2); border-radius: 999px;
  background: rgba(12, 17, 32, .6);
  margin-bottom: clamp(16px, 3.2vh, 30px);
  animation: sFade .6s var(--ease) .04s both;
}
.eyebrow__dot {
  width: 7px; height: 7px; border-radius: 50%; background: var(--cyan);
  box-shadow: 0 0 10px rgba(77, 195, 255, .9); flex: 0 0 auto;
}
.eyebrow__text {
  font-family: var(--display); font-size: 11.5px; font-weight: 500;
  letter-spacing: .14em; text-transform: uppercase; color: var(--muted);
}
/* Naming the customer costs characters; shorten rather than wrap the pill. */
.eyebrow__short { display: none; }
@media (max-width: 620px) {
  .eyebrow__long  { display: none; }
  .eyebrow__short { display: inline; }
}

.hero__title {
  margin: 0; max-width: 14ch;
  font-family: var(--display); font-weight: 600;
  font-size: clamp(46px, 1.30rem + 8.4vw, 104px);
  line-height: .95; color: var(--ink);
  /* Tracking tightens in lockstep with size. Check: at 300px vw,
     0.576 - 1.497 = -0.92px; at 992px, 0.576 - 4.951 = -4.37px. */
  letter-spacing: clamp(-4.37px, 0.576px - 0.499vw, -0.92px);
  text-wrap: balance;
  text-shadow: 0 0 104px rgba(77, 195, 255, .17), 0 0 46px rgba(122, 162, 224, .09);
}
.hero__title .w {
  display: inline-block; overflow: hidden; vertical-align: bottom;
  /* Reclaim the padding that keeps the mask edge off ascenders and the comma. */
  padding-block: .10em .20em; margin-block: -.10em -.20em;
}
.hero__title .w > i {
  display: inline-block; font-style: inherit;
  transform: translateY(112%);
  animation: sRise .80s var(--ease) both;
}
.hero__title .w:nth-child(1) > i { animation-delay: .10s }
.hero__title .w:nth-child(2) > i { animation-delay: .17s }
.hero__title .w:nth-child(3) > i { animation-delay: .24s }
.hero__title .w:nth-child(4) > i { animation-delay: .31s }

.hero__sub {
  margin: clamp(16px, 3vh, 30px) 0 0; max-width: 44ch;
  font-size: clamp(16px, 0.9rem + 0.5vw, 19px); line-height: 1.62; color: var(--muted);
  text-wrap: pretty; animation: sFade .6s var(--ease) .48s both;
}
.hero__actions {
  /* Was a row holding one button. Now it stacks form / error / microcopy. */
  display: flex; flex-direction: column; align-items: flex-start;
  gap: 13px;
  margin-top: clamp(20px, 4vh, 40px);
  animation: sFade .6s var(--ease) .60s both;
}
/* Same shape as the section 9 form so the two read as one control, not two
   designs. The input yields before the button does, so the label never wraps. */
.hero__form {
  display: flex; flex-wrap: wrap; gap: 12px;
  width: 100%; max-width: 520px;
}
.hero__form .field { min-width: 0; }   /* inherits flex: 1 1 260px, same as §9 */
.hero__form .btn { flex: 0 0 auto; }
.hero__form .btn[disabled] { opacity: .6; cursor: default; }
.hero__micro {
  font-size: 13.5px; color: var(--dim); letter-spacing: 0;
  max-width: 32ch; text-wrap: pretty;
}

.hero__scrub {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 3;
  padding: 0 var(--gutter) 26px; pointer-events: none;
}
.hero__scrub-row {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 24px; margin-bottom: 14px;
}
.hero__labels { position: relative; height: 18px; min-width: 210px; }
.hero__labels span {
  position: absolute; left: 0; top: 0; white-space: nowrap;
  font-family: var(--display); font-size: 12px; font-weight: 500;
  letter-spacing: .12em; text-transform: uppercase;
}
.hero__label--before { color: var(--dim); }
.hero__label--after  { color: var(--cyan); opacity: 0; }
.hero__label--after.is-resolved { animation: sResolved 1.1s var(--ease) 1; }
.hero__cue {
  font-family: var(--display); font-size: 11px; font-weight: 500;
  letter-spacing: .14em; text-transform: uppercase; color: var(--dim);
  animation: sCue 2.6s var(--ease-io) infinite;
}
.hero__track { position: relative; height: 1px; background: var(--line-2); overflow: hidden; }
.hero__bar {
  position: absolute; left: 0; top: 0; height: 100%; width: 100%;
  transform: scaleX(0); transform-origin: 0 50%;
  background: linear-gradient(90deg, var(--cyan), var(--violet));
}

@supports (text-box: trim-both cap alphabetic) {
  .hero__title, .h2, .premise__line, .closing__h, .stop__h, .statement p {
    text-box: trim-both cap alphabetic;
  }
}

/* ------------------------------------------------------------ sections -- */

.section {
  position: relative;
  /* Asymmetric on purpose — equal top and bottom is what makes sections read
     as identical boxes. Floors are authored at the phone value first, so an
     airy section can't collapse into a tight one on the device that needs the
     contrast most. */
  padding-block: clamp(72px, 9vh, 112px) clamp(104px, 14vh, 156px);
  padding-inline: var(--gutter);

  /* Differentiate by a hue wash that FADES OUT within the section, never by a
     flat background step. Two near-blacks meeting at a hard edge produce a
     change nobody can name and a line everybody can see; a wash lets adjacent
     sections meet gradient-to-gradient. */
  background-image: linear-gradient(180deg,
    rgba(77, 195, 255, .045) 0%, rgba(77, 195, 255, .012) 32%, rgba(77, 195, 255, 0) 62%);
}
.section:nth-of-type(even) {
  background-image: linear-gradient(180deg,
    rgba(100, 91, 198, .05) 0%, rgba(100, 91, 198, .014) 32%, rgba(100, 91, 198, 0) 62%);
}

/* Density is a narrative decision, not a position one. A deliberately dense
   section reads as confident when the next one is deliberately sparse. */
.section--tight { padding-block: clamp(56px, 7vh, 84px) clamp(68px, 9vh, 100px); }
.section--airy  { padding-block: clamp(108px, 15vh, 168px) clamp(128px, 18vh, 200px); }
.section--anchor { scroll-margin-top: calc(var(--header-h) + 16px); }
.section--top { border-top: 1px solid var(--line); }
/* No top border and less air than a bordered section — but not zero. At
   padding-top:0 these were the two tightest joins on the page (140px vs the
   186-289px elsewhere), which reads as a collision rather than as rhythm. */
.section--flush-top { padding-top: clamp(40px, 5vh, 64px); }
.section--clip { overflow: hidden; }

.bloom {
  position: absolute; border-radius: 50%; pointer-events: none;
  animation: sBloom 14s var(--ease-io) infinite alternate;
}
.bloom--violet {
  left: -30vw; top: -14%; width: 86vw; height: 86vw; max-width: 1040px; max-height: 1040px;
  background: radial-gradient(circle at 42% 38%,
    rgba(100, 91, 198, .11) 0%, rgba(100, 91, 198, .062) 24%,
    rgba(100, 91, 198, .038) 46%, rgba(100, 91, 198, .012) 66%, rgba(100, 91, 198, 0) 82%);
  -webkit-mask-image: radial-gradient(72% 66% at 50% 44%, #000 0%, #000 42%, rgba(0,0,0,.5) 68%, transparent 88%);
          mask-image: radial-gradient(72% 66% at 50% 44%, #000 0%, #000 42%, rgba(0,0,0,.5) 68%, transparent 88%);
}
.bloom--cyan {
  right: -32vw; top: -22%; width: 88vw; height: 88vw; max-width: 1060px; max-height: 1060px;
  background: radial-gradient(circle at 58% 40%,
    rgba(77, 195, 255, .10) 0%, rgba(77, 195, 255, .056) 24%,
    rgba(77, 195, 255, .034) 46%, rgba(77, 195, 255, .011) 66%, rgba(77, 195, 255, 0) 82%);
  -webkit-mask-image: radial-gradient(72% 66% at 50% 44%, #000 0%, #000 42%, rgba(0,0,0,.5) 68%, transparent 88%);
          mask-image: radial-gradient(72% 66% at 50% 44%, #000 0%, #000 42%, rgba(0,0,0,.5) 68%, transparent 88%);
  animation-duration: 16s;
}

.kicker {
  font-family: var(--display); font-size: 12px; font-weight: 500;
  letter-spacing: .12em; text-transform: uppercase; color: var(--dim);
}
.kicker--cyan { color: var(--cyan); }

.rule-row {
  display: flex; align-items: baseline; gap: 16px; margin-bottom: 52px; flex-wrap: wrap;
}
.rule {
  flex: 1 1 120px; height: 1px;
  background: linear-gradient(90deg, var(--line-2), var(--line-2) 62%, transparent);
}
.rule-row__note { font-size: 13px; color: var(--dim); }

.h2 {
  margin: 0; font-family: var(--display); font-weight: 600;
  font-size: clamp(34px, 1.20rem + 5.2vw, 50px); line-height: 1.04;
  letter-spacing: clamp(-2.00px, 0.34px - 0.24vw, -0.55px);
  color: var(--ink); text-wrap: balance;
}

/* §premise — the tension */
.premise__grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 56px 72px; align-items: end;
}
@media (min-width: 760px) {
  /* Explicit two columns — auto-fit would have made the figure a third one. */
  .premise__grid { grid-template-columns: 1fr 1fr; }
  /* Explicit placement. Auto-placement dropped the body into row 3 column 1
     and left column 2 empty down the whole section. */
  .premise__grid > :first-child { grid-column: 1; grid-row: 1; }
  .premise__grid > .premise__body { grid-column: 2; grid-row: 1; }
  .premise__grid > .plate { grid-column: 1 / -1; grid-row: 2; }
}
.premise__line {
  margin: 0; max-width: 17ch; font-family: var(--display); font-weight: 600;
  font-size: clamp(38px, 1.10rem + 6.2vw, 70px); line-height: 1.0;
  letter-spacing: -.02em; text-wrap: balance;
}
.premise__line--dim { color: var(--faint); }
.premise__line--lit { color: var(--ink); margin-top: 22px; }
.premise__body { display: flex; flex-direction: column; gap: 22px; padding-bottom: 8px; }
.lede {
  font-size: clamp(19px, 1.00rem + 1.5vw, 24px);
  line-height: 1.38;
  letter-spacing: -.011em;
  color: var(--ink);
  max-width: 22ch;
  text-wrap: pretty;
}
.premise__body p {
  margin: 0; font-size: 18px; line-height: 1.66; color: var(--muted);
  max-width: 42ch; text-wrap: pretty;
}
/* .lede is declared earlier, so restate it here to beat the element+class
   specificity above. The narrower measure is the whole point — a lede that is
   wider than its body reads as an accident, narrower reads as a decision. */
.premise__body p.lede,
.trust__intro p.lede {
  font-size: clamp(20px, 1.05rem + 1.7vw, 25px);
  line-height: 1.36;
  color: var(--ink);
  max-width: 24ch;
}
/* The category claim. Short paragraph, brighter ink — it should land on its own
   rather than dissolve into the paragraph around it. */
.premise__claim { color: var(--ink); }

/* ----------------------------------------------------------------- plate --
   The one thing on this page that cannot be faked: a real photograph of the
   world the product lives in. Not product UI — the chair, the mirror, the cape,
   the moment before the cut. It discloses no mechanism and it grounds every
   abstract claim above it in something physical.

   Treatment is what keeps a photograph from looking bolted onto a dark page:
   · full-bleed, so it breaks the gutter line like the cards do
   · graded most of the way to monochrome and darkened, so it sits inside the
     palette rather than fighting it
   · one colour pass toward the brand cyan, not a saturated duotone
   · edges dissolved into the page top and bottom, so it reads as a moment in
     the scroll rather than as a rectangle dropped in
   · the page grain sits on top of it, which is what unifies photo and page
   -------------------------------------------------------------------------- */

.plate {
  position: relative;
  margin: 40px calc(var(--gutter) * -1) 44px;
  overflow: hidden;
  isolation: isolate;
  /* The frame decides the height, not the file. A portrait source left at
     width:100% became a 1941px tower on a laptop — over two screens. */
  aspect-ratio: 4 / 5;
}
.plate img {
  width: 100%; height: 100%; display: block;
  object-fit: cover;
  object-position: 50% 26%;   /* hold the face as the frame gets wider */
  /* Was grayscale(.86) brightness(.66) — which threw away a third of the
     brightness and nearly all the skin tone. Dark surrounds already reduce
     perceived image contrast (Bartleson-Breneman), so a photograph needs a
     LIFT here, not a cut. */
  filter: grayscale(.34) contrast(1.10) brightness(.92) saturate(1.06);
}
/* One colour pass. `color` keeps the photograph's luminance and borrows only
   its hue, which is why it reads as graded rather than tinted. */
.plate::before {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(170deg, rgba(77, 195, 255, .16), rgba(100, 91, 198, .12));
  mix-blend-mode: color;
}
/* Dissolve the top and bottom edges into the page. */
.plate::after {
  content: ""; position: absolute; inset: 0; z-index: 2; pointer-events: none;
  background: linear-gradient(180deg,
    var(--bg) 0%, rgba(7, 10, 18, .34) 16%, rgba(7, 10, 18, .10) 42%,
    rgba(7, 10, 18, .34) 82%, var(--bg) 100%);
}
.plate figcaption {
  position: absolute; left: var(--gutter); bottom: 16px; z-index: 3;
  margin: 0;
  font-family: var(--display);
  font-size: 10.5px; font-weight: 500;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--muted);
  text-shadow: 0 1px 12px rgba(3, 6, 14, .9);
}

@media (min-width: 760px) {
  .plate { margin-inline: 0; border-radius: 18px; }
  /* Wider frame, so less of the portrait fits. 16:9 is as wide as this crop
     survives, and the anchor moves down to keep the face in frame. */
  .plate { aspect-ratio: 16 / 9; }
  .plate img { object-position: 50% 62%; }
}

/* ---------------------------------------------------------------- thread --
   The copy claims "one thread, three moments" and then shows three
   disconnected blocks. This is the visual finally agreeing with it.

   Two attributes do the heavy lifting:
   · pathLength="1" makes dash units fractions of the path, so the draw needs
     no JS measurement and cannot desync from a resize.
   · vector-effect="non-scaling-stroke" keeps a 1.4px hairline at 1.4px whether
     the figure renders at 340px or 700px wide. Without it the line thickens
     into a rope on desktop and stops reading as drafted.
   -------------------------------------------------------------------------- */

.journey { position: relative; margin: 26px 0 0; }

/* The strand spans the full measure so the three stations land on the same
   x as the three columns beneath them: the midpoint of each cubic segment
   falls at 16.67%, 50% and 83.33%, which are exactly the column centres. */
.journey__svg {
  display: block; width: 100%; height: auto; overflow: visible;
}

/* Finished is the DEFAULT state. No JS, no support, or reduced motion all show
   a complete diagram — a half-drawn thread would be a content failure, not
   merely an unanimated one. main.js opts into the undrawn state. */
.thread__line { stroke-dashoffset: 0; }

.station__core  { fill: #EAF6FF; }

.journey__stops {
  list-style: none; margin: 0; padding: 0;
  /* gap must be 0: a column gap moves the column centres off 16.67/50/83.33,
     which is where the strand's three stations sit. Spacing comes from the
     stop's own padding instead, so the alignment survives. */
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 0;
}
.stop {
  display: flex; flex-direction: column; gap: 12px;
  padding: 26px 44px 0 0;
  /* No top rule. The strand above IS the connector — a border here would
     chop the three stops back into the separate boxes the copy denies. */
}
.stop__n {
  font-family: var(--display); font-size: 30px; font-weight: 600;
  line-height: .85; letter-spacing: -.03em;
  font-variant-numeric: tabular-nums;
  /* transparent fill + stroke keeps the mass and loses the brightness */
  color: transparent; -webkit-text-stroke: 1px rgba(122, 162, 224, .65);   /* .42 measured 2.21:1; large text needs 3:1 */
}
.stop__who {
  font-family: var(--display); font-size: 10.5px; font-weight: 500;
  letter-spacing: .16em; text-transform: uppercase; color: var(--cyan);
  opacity: .85;
}
.stop__h {
  margin: 0; font-family: var(--display); font-weight: 600;
  font-size: clamp(22px, 1.05rem + 1.5vw, 28px);
  line-height: 1.12; letter-spacing: -.018em; color: var(--ink);
  text-wrap: balance;
}
.stop__p {
  margin: 0; font-size: 16px; line-height: 1.62; color: var(--muted);
  max-width: 34ch; text-wrap: pretty;
}

/* Under ~760px a 1200-wide S-curve becomes an illegible squiggle, so the
   strand becomes a vertical rail down the left and the stops hang off it.
   Same argument — one unbroken line through three moments — different shape. */
@media (max-width: 760px) {
  .journey__svg { display: none; }
  .journey__stops {
    grid-template-columns: 1fr; gap: 0;
    position: relative; padding-left: 30px;
  }
  .journey__stops::before {
    content: ""; position: absolute; left: 5px; top: 10px; bottom: 10px;
    width: 1.5px; border-radius: 2px;
    background: linear-gradient(180deg, var(--cyan), #8FA8E8 52%, var(--violet));
    opacity: .5;
  }
  .stop { padding: 30px 0 30px 0; }
  .stop:first-child { padding-top: 6px; }
  .stop::before {
    content: ""; position: absolute; left: 0; width: 11px; height: 11px;
    border-radius: 50%; background: #EAF6FF;
    margin-top: 6px;
    box-shadow: 0 0 0 5px rgba(77, 195, 255, .16), 0 0 18px 3px rgba(77, 195, 255, .5);
  }
}

/* ------------------------------------------------- §inside — the product --
   The screenshots need no darkening, no scrim and no colour correction: the
   app renders on #070A12 with the same cyan and violet accents as this page,
   so a screen sits inside the composition rather than glaring out of it. The
   usual advice — Apple's "soften the color of white backgrounds", the
   brightness(.8) contrast(1.2) trick — exists for bright UI on dark pages and
   would only crush this one.

   What a raster still needs is a seat: an inner hairline so the edge reads as
   deliberate, a top-edge specular so light appears to come from above, an
   outer dark ring to cut it from the background, and a contact shadow tinted
   with the page colour rather than black. Four layers, the same structure
   Linear and Vercel both ship.
   -------------------------------------------------------------------------- */

.shot__lede { margin: 0 0 34px; max-width: 44ch; }

.shot { position: relative; margin: 0; }
.shot img {
  display: block; width: 100%; height: auto;
  border-radius: 18px; background: var(--deep);
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, .05),
    inset 0 1px 0 rgba(255, 255, 255, .06),
    0 0 0 1px rgba(3, 6, 14, .55),
    0 20px 52px rgba(7, 10, 18, .62),
    0 0 72px rgba(7, 10, 18, .42);
}
/* The screen throws light onto the page around it. Without this the image
   reads as a rectangle laid on top rather than a lit object in the scene. */
.shot::before {
  content: ""; position: absolute; inset: 8% -6% 22% -6%;
  z-index: -1; pointer-events: none;
  background: radial-gradient(60% 100% at 50% 0%,
    rgba(77, 195, 255, .13), rgba(100, 91, 198, .07) 45%, transparent 72%);
  filter: blur(28px);
}
.shot--wide { isolation: isolate; }
.shot figcaption {
  margin-top: 15px; font-size: 14.5px; line-height: 1.6;
  color: var(--dim); max-width: 62ch; text-wrap: pretty;
}

/* The numerals carry the claim, so they get the display face and real size.
   Tabular figures so 478 and 3 sit on the same rhythm. */
.specs {
  list-style: none; margin: 56px 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 40px 48px;
}
.spec { display: flex; flex-direction: column; gap: 10px; padding-top: 24px; border-top: 1px solid var(--line-2); }
.spec__n {
  font-family: var(--display); font-weight: 600;
  font-size: clamp(46px, 1.4rem + 1.6vw, 60px); line-height: .9;
  letter-spacing: -.03em; font-variant-numeric: tabular-nums;
  background: linear-gradient(160deg, var(--cyan), #8FA8E8 60%, var(--violet));
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.spec__unit { font-size: .5em; letter-spacing: 0; }
.spec__h {
  margin: 0; font-family: var(--display); font-weight: 600; font-size: 17px;
  letter-spacing: .02em; text-transform: lowercase; color: var(--ink);
}
.spec__p { margin: 0; font-size: 15.5px; line-height: 1.62; color: var(--muted); max-width: 34ch; text-wrap: pretty; }

/* Photo one side, a single UI element the other — the alternating rhythm the
   better product pages use below the fold. Never a full dashboard. */
.aside {
  margin-top: 72px;
  display: grid; grid-template-columns: minmax(0, 400px) minmax(0, 1fr);
  gap: 44px; align-items: center;
}
.aside__body { display: flex; flex-direction: column; gap: 16px; }
.aside__h {
  margin: 0; font-family: var(--display); font-weight: 600;
  font-size: clamp(24px, 1.1rem + 1.6vw, 32px); line-height: 1.14;
  letter-spacing: -.018em; color: var(--ink); text-wrap: balance; max-width: 22ch;
}
.aside__p { margin: 0; font-size: 16.5px; line-height: 1.64; color: var(--muted); max-width: 46ch; text-wrap: pretty; }
.aside__p--dim { font-size: 15px; color: var(--dim); }

@media (max-width: 760px) {
  .specs { gap: 32px; margin-top: 44px; }
  .aside { grid-template-columns: 1fr; gap: 28px; margin-top: 52px; }
  /* justify-self, NOT margin-inline:auto — auto margins make a grid item
     shrink-to-fit, and since .shot img is width:100% of that parent the
     sizing is circular, so a lazy image that hasn't loaded collapses the
     whole figure to 0x0. */
  .shot--tall { max-width: 320px; width: 100%; justify-self: center; }

  /* The composite carries wide black margins, so inside the gutter the face
     lands around 130px and the whole point is lost. Break the gutter like
     .plate does and square the corners at the page edge. */
  .shot--wide { margin-inline: calc(var(--gutter) * -1); }
  .shot--wide img { border-radius: 0; box-shadow: none; }
  .shot--wide figcaption { padding-inline: var(--gutter); }
}

/* §statement */
.statement {
  border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
  background: linear-gradient(180deg, var(--bg-2), var(--bg));
  padding: clamp(84px, 11vh, 130px) var(--gutter);
}
.statement p {
  margin: 0; max-width: 24ch; font-family: var(--display); font-weight: 500;
  font-size: clamp(32px, 1.05rem + 4.6vw, 52px); line-height: 1.1;
  letter-spacing: -.018em; color: var(--ink); text-wrap: balance;
}
.statement em { font-style: normal; color: var(--dim); }

/* §is / isn't */
.contrast {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 44px 64px;
}
.contrast__col { display: flex; flex-direction: column; gap: 22px; }
.contrast__h {
  margin: 0; font-family: var(--display); font-weight: 600; font-size: 26px; line-height: 1.2;
}
.contrast__h--dim { color: var(--dim); }
.contrast__h--lit { color: var(--ink); }
.contrast__list { display: flex; flex-direction: column; gap: 14px; }
.contrast__item { display: flex; gap: 13px; align-items: flex-start; }
.contrast__item svg { flex: 0 0 auto; margin-top: 3px; }
.contrast__item span { font-size: 16.5px; line-height: 1.55; }
.contrast__col--no .contrast__item span { color: var(--dim); }
.contrast__col--yes .contrast__item span { color: var(--muted); }

/* §trust */
.trust__intro {
  max-width: 640px; margin-bottom: 56px; display: flex; flex-direction: column; gap: 20px;
}
.trust__intro p { margin: 0; font-size: 17.5px; line-height: 1.65; color: var(--muted); text-wrap: pretty; }
.trust__grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 22px;
}
/* Four equal cards is the single most recognisable generated-grid shape. On wide
   screens the strongest and last claims span two columns, filling a 3-col grid
   asymmetrically. */
@media (min-width: 1020px) {
  .trust__grid { grid-template-columns: repeat(3, 1fr); }
  .trust__grid > .card:first-child,
  .trust__grid > .card:last-child { grid-column: span 2; }
}
.card {
  /* 18px/24px — deliberately below the 22px primary cards (founder, waitlist)
     so the page has a size hierarchy rather than one uniform radius. */
  position: relative; padding: 24px; border: 1px solid var(--line); border-radius: 18px;
  background: linear-gradient(180deg, var(--panel), var(--panel-2));
  display: flex; flex-direction: column; gap: 14px;
  transition: border-color .22s var(--ease), transform .22s var(--ease);
}
.card::before {
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .05); pointer-events: none;
}
.card:hover { border-color: var(--line-hi); transform: translateY(-2px); }
.card__h { margin: 0; font-size: 17px; font-weight: 600; color: var(--ink); letter-spacing: -.008em; }
/* The two-column cards would otherwise run ~110 characters per line. */
.card__p { margin: 0; font-size: 14.5px; line-height: 1.62; color: var(--dim); max-width: 44ch; text-wrap: pretty; }
.trust__foot { margin: 30px 0 0; font-size: 14px; color: var(--dim); max-width: 60ch; text-wrap: pretty; }

/* §cohort */
.cohort__intro { max-width: 600px; margin-bottom: 56px; display: flex; flex-direction: column; gap: 20px; }
.cohort__who {
  margin: 0; max-width: 46ch; font-size: 17px; line-height: 1.62;
  color: var(--muted); text-wrap: pretty;
}
.steps { display: grid; grid-template-columns: repeat(auto-fit, minmax(268px, 1fr)); gap: 44px 48px; }
.step { display: flex; flex-direction: column; gap: 14px; }
.step__head { display: flex; align-items: center; gap: 14px; }
.step__num {
  display: flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; border-radius: 50%;
  border: 1px solid var(--line-2); background: var(--panel);
  font-family: var(--display); font-size: 13px; font-weight: 600;
  letter-spacing: .06em; color: var(--muted); flex: 0 0 auto;
}
.step__rule { flex: 1 1 auto; height: 1px; background: var(--line-2); }
.step__num { transition: border-color .22s var(--ease), color .22s var(--ease); }
.step:hover .step__num { border-color: rgba(77, 195, 255, .45); color: var(--cyan); }
.step__h { margin: 0; font-size: 19px; font-weight: 600; color: var(--ink); letter-spacing: -.012em; }
.step__p { margin: 0; font-size: 15.5px; line-height: 1.62; color: var(--muted); max-width: 34ch; text-wrap: pretty; }

/* §founder */
.founder {
  position: relative; max-width: 820px; margin-inline: auto;
  padding: clamp(30px, 4vw, 52px);
  border: 1px solid var(--line); border-radius: 22px;
  background: linear-gradient(180deg, var(--raised), var(--panel));
  display: flex; flex-direction: column; gap: 24px;
}
.inset-hi {
  position: absolute; inset: 0; border-radius: inherit;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .05); pointer-events: none;
}
.founder > * { position: relative; }
.founder__lead { margin: 0; max-width: 46ch; font-size: 20px; line-height: 1.62; color: var(--ink); text-wrap: pretty; }
.founder__body { margin: 0; max-width: 46ch; font-size: 18px; line-height: 1.62; color: var(--muted); text-wrap: pretty; }
.founder__body em { font-style: normal; color: var(--ink); }
.founder__sign { display: flex; align-items: center; gap: 13px; padding-top: 6px; }
.founder__sign img { width: 30px; height: 30px; object-fit: contain; opacity: .9; }
.founder__sign span {
  font-family: var(--display); font-size: 12px; font-weight: 500;
  letter-spacing: .14em; text-transform: uppercase; color: var(--dim);
}

/* A promoted sentence. Narrower measure than the body it sits in, which is what
   makes it read as a different object rather than an emphasised paragraph. */
.pull {
  margin: 26px 0 0;
  padding-left: 18px;
  border-left: 2px solid rgba(77, 195, 255, .55);
  font-family: var(--display);
  font-weight: 500;
  font-size: clamp(21px, 1.00rem + 1.9vw, 27px);
  line-height: 1.26;
  letter-spacing: -.012em;
  color: var(--ink);
  max-width: 25ch;      /* narrow enough to read as a different object, wide
                           enough that text-wrap: balance has room to work */
  text-wrap: balance;
}

/* §waitlist */
.waitlist {
  border-top: 1px solid var(--line);
  background: linear-gradient(180deg, var(--bg-2), var(--bg));
}
.waitlist__card {
  position: relative; max-width: 780px; margin-inline: auto;
  padding: clamp(30px, 4vw, 52px);
  border: 1px solid var(--line); border-radius: 22px;
  background: linear-gradient(180deg, var(--panel), var(--panel-2));
  box-shadow: 0 18px 48px rgba(3, 6, 14, .55), 0 6px 16px rgba(3, 6, 14, .4);
}
.waitlist__pane { position: relative; display: flex; flex-direction: column; gap: 22px; }
.waitlist__pane[hidden] { display: none; }
.pill-live {
  display: inline-flex; align-items: center; gap: 9px; align-self: flex-start;
  padding: 6px 13px 6px 10px; border: 1px solid rgba(77, 195, 255, .24);
  border-radius: 999px; background: rgba(77, 195, 255, .08);
}
.pill-live__dot {
  width: 6px; height: 6px; border-radius: 50%; background: var(--cyan);
  box-shadow: 0 0 8px rgba(77, 195, 255, .9);
}
.pill-live__text {
  font-family: var(--display); font-size: 11px; font-weight: 500;
  letter-spacing: .14em; text-transform: uppercase; color: var(--cyan);
}
.waitlist__h { max-width: 18ch; }
.waitlist__p { margin: 0; max-width: 46ch; font-size: 17px; line-height: 1.62; color: var(--muted); text-wrap: pretty; }
.waitlist__form { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 4px; }
.field {
  flex: 1 1 260px; min-height: 54px; padding: 15px 22px;
  border: 1px solid var(--line-input); border-radius: 999px;
  background: var(--deep); color: var(--ink);
  font-family: var(--body); font-size: 16px; letter-spacing: -.004em;
  outline: none; transition: border-color .18s var(--ease);
}
.field:hover { border-color: var(--line-hi); }
.field:focus { border-color: var(--cyan); }   /* 10.13:1; the old rgba was 3.04:1, dimmer than at rest */
.waitlist__form .btn { flex: 0 0 auto; }
.waitlist__form .btn[disabled] { opacity: .6; cursor: default; }

.trustline {
  display: flex; align-items: flex-start; gap: 11px;
  color: var(--dim); font-size: 13.5px; line-height: 1.55; max-width: 52ch;
}
.trustline svg { flex: 0 0 auto; margin-top: 2px; }

.hp-field {
  position: absolute; left: -9999px; top: auto;
  width: 1px; height: 1px; overflow: hidden;
}
.formerror { margin: 0; font-size: 13.5px; line-height: 1.55; color: var(--error); }
/* :empty, not [hidden] — the node must stay in the accessibility tree for the
   live region to announce, so it is emptied rather than hidden. */
.formerror:empty { display: none; }

/* §waitlist — success pane */
.success__row { display: flex; align-items: baseline; gap: 14px; flex-wrap: wrap; }
.success__pos {
  font-family: var(--display); font-weight: 500;
  font-size: clamp(44px, 7vw, 72px); line-height: 1;
  background: linear-gradient(120deg, #6FD0FF 0%, #8B8CE6 100%);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.success__pos { font-variant-numeric: tabular-nums; }
.success__row span:last-child { font-size: 15px; color: var(--muted); }
.success__p { margin: 0; font-size: 17px; line-height: 1.6; color: var(--muted); max-width: 44ch; text-wrap: pretty; }
.success__share { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; margin-top: 2px; }
.success__link {
  flex: 1 1 260px; min-height: 54px; display: flex; align-items: center;
  padding: 15px 22px; border: 1px solid var(--line); border-radius: 999px;
  background: var(--deep); color: var(--muted); font-size: 14.5px;
  font-variant-numeric: tabular-nums; overflow: hidden;
  white-space: nowrap; text-overflow: ellipsis;
}
.success__note { margin: 6px 0 0; font-size: 13.5px; line-height: 1.55; color: var(--dim); max-width: 52ch; text-wrap: pretty; }

/* §faq */
.faq__grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 48px 72px; align-items: start;
}
.faq__intro { display: flex; flex-direction: column; gap: 20px; position: sticky; top: 110px; }
.faq__intro .h2 { max-width: 13ch; }
.faq__intro p { margin: 0; max-width: 34ch; font-size: 16px; line-height: 1.62; color: var(--dim); text-wrap: pretty; }
.faq__list { display: flex; flex-direction: column; }

details { border-top: 1px solid var(--line-2); }
details:last-child { border-bottom: 1px solid var(--line-2); }
summary {
  display: flex; align-items: center; justify-content: space-between; gap: 24px;
  padding: 24px 0; font-size: 17.5px; font-weight: 500; color: var(--ink);
  letter-spacing: -.008em; list-style: none; cursor: pointer;
}
summary::-webkit-details-marker { display: none; }
summary svg { flex: 0 0 auto; }
details[open] summary svg { transform: rotate(180deg); }

/* A clickable row with no hover state is the clearest "nobody touched this" tell. */
summary { transition: translate .22s var(--ease); }
summary:hover { translate: 6px 0; }

/* Animated disclosure. A panel that snaps is the second such tell. */
details::details-content {
  block-size: 0; overflow: clip;
  transition: block-size .38s var(--ease), content-visibility .38s allow-discrete;
}
details[open]::details-content { block-size: auto; }
@supports (interpolate-size: allow-keywords) {
  html { interpolate-size: allow-keywords; }
}
summary:hover .ico--chev { color: var(--cyan); }
details p {
  margin: 0; padding: 0 0 26px; max-width: 52ch;
  font-size: 16px; line-height: 1.65; color: var(--muted); text-wrap: pretty;
}

/* §closing */
.closing { padding-inline: var(--gutter);   /* block padding comes from .section--airy */ overflow: hidden; }
.closing__bloom {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: 80vw; height: 44vw; max-width: 1100px; border-radius: 50%;
  background: radial-gradient(circle, rgba(100,91,198,.12), rgba(77,195,255,.06) 45%, rgba(77,195,255,0) 72%);
  filter: blur(50px); pointer-events: none;
}
.closing__inner {
  position: relative; display: flex; flex-direction: column;
  align-items: center; text-align: center; gap: 26px;
}
.closing__mark {
  width: 52px; height: 52px; object-fit: contain;
  filter: drop-shadow(0 0 16px rgba(77, 195, 255, .28));
}
.closing__h {
  margin: 0; max-width: 17ch; font-family: var(--display); font-weight: 600;
  font-size: clamp(36px, 1.15rem + 5.4vw, 64px);
  letter-spacing: clamp(-2.70px, 0.42px - 0.32vw, -0.70px); line-height: 1.0;
  color: var(--ink); text-wrap: balance;
}
.closing__p { margin: 0; max-width: 44ch; font-size: 17.5px; line-height: 1.62; color: var(--muted); text-wrap: pretty; }
.closing__inner .btn { margin-top: 6px; }

/* -------------------------------------------------------------- footer -- */

.footer {
  border-top: 1px solid var(--line);
  padding: 60px var(--gutter) 40px; background: var(--deep);
}
.footer__grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 44px 40px;
}
.footer__brand { display: flex; flex-direction: column; gap: 16px; min-width: 220px; }
.footer__logo { width: 150px; height: auto; }
.footer__brand p { margin: 0; max-width: 30ch; font-size: 13.5px; line-height: 1.6; color: var(--dim); text-wrap: pretty; }
.footer__col { display: flex; flex-direction: column; gap: 14px; }
.footer__h { margin: 0;
  font-family: var(--display); font-size: 11px; font-weight: 500;
  letter-spacing: .14em; text-transform: uppercase; color: var(--dim);
}
.footer__col a { font-size: 14px; color: var(--muted); padding-block: 4px; }   /* 22px -> 30px tall, clears SC 2.5.8 */
.footer__col a:hover { color: var(--ink); }
.footer__base {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: 16px; margin-top: 52px; padding-top: 24px; border-top: 1px solid var(--line);
}
.footer__base span:first-child { font-size: 12.5px; color: var(--dim); }
.footer__base span:last-child {
  font-family: var(--display); font-size: 11.5px; font-weight: 500;
  letter-spacing: .14em; text-transform: uppercase; color: var(--dim);
}

/* ------------------------------------------------------------ mobile -- */

/* The header carries a wordmark and a CTA; below ~600px both have to give
   ground or the CTA gets clipped off the right edge. */
.btn__short { display: none; }

@media (max-width: 600px) {
  :root { --gutter: 20px; }

  .header__inner { gap: 12px; padding: 11px var(--gutter); }
  .brand { gap: 10px; }
  .brand__mark { width: 30px; height: 30px; }
  .brand__wordmark { height: 17px; }
  .brand__tag { display: none; }
  .btn--ghost { margin-left: 0; padding: 10px 16px; font-size: 13px; }
  .btn__long { display: none; }
  .btn__short { display: inline; }

  .hero { height: 170vh; height: 170svh; }
  .hero__cue { display: none; }
  .hero__content { padding-bottom: 96px; }
  .faq__intro { position: static; }

  /* A 54px pill plus a 54px field won't sit side by side at this width. */
  .waitlist__form .btn,
  .success__share .btn { flex: 1 1 100%; }
}

@media (max-width: 380px) {
  .brand__wordmark { height: 15px; }
}

/* --------------------------------------------------- reduced motion -- */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  /* Movement goes; a short opacity fade stays. Removing every transition also
     removes the feedback that a press registered, and 2.3.3 targets motion. */
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-delay: 0s !important;      /* fill:both holds the from-state through any delay */
    animation-iteration-count: 1 !important;
    transition-duration: .12s !important;
    transition-property: opacity, color, background-color, border-color !important;
  }
}

/* ------------------------------------------------- mobile structure --
   The root cause of "every section looks the same": seven grids all use
   repeat(auto-fit, minmax(250-320px, 1fr)), and a 390px phone leaves 350px of
   content width — below every one of those floors. So they all collapse at the
   same moment into identical single columns.

   The fix is a fixed narrow column plus a flexible one. `2.5rem 1fr` survives
   at 350px where minmax(268px, 1fr) cannot, so the index/icon keeps its own
   vertical rail and the sections stay structurally distinct.
   -------------------------------------------------------------------------- */

@media (max-width: 700px) {

  /* Cohort steps — same rail, so the two numbered sections rhyme structurally
     while their type treatments stay different. */
  .step {
    display: grid;
    grid-template-columns: 2.75rem 1fr;
    column-gap: 14px;
    row-gap: 10px;
    align-items: start;
  }
  .step__head { display: contents; }
  .step__num  { grid-column: 1; grid-row: 1 / -1; align-self: start; }
  .step__rule { grid-column: 2; grid-row: 1; align-self: center; }
  .step__h,
  .step__p    { grid-column: 2; }

  /* Privacy cards — the icon takes the rail, so the card reads as a record
     rather than a stack. */
  .card {
    display: grid;
    grid-template-columns: 2.25rem 1fr;
    column-gap: 12px;
    row-gap: 8px;
    align-items: start;
  }
  .card > .ico { grid-column: 1; grid-row: 1 / -1; margin-top: .15em; }
  .card__h,
  .card__p     { grid-column: 2; }

  /* ---- SILHOUETTE ----
     Asymmetry on a phone isn't left vs right, it's which elements share an edge
     with the viewport and which don't. With everything at one gutter there is a
     single vertical line running the whole page, and it reads as a stack of
     identical slabs. Breaking that line a few times is the strongest available
     move — it changes the page's outline as you scroll, not just its contents.

     Surfaces bleed; text never does. */

  .trust__grid { margin-inline: calc(var(--gutter) * -1); gap: 0; }
  .card {
    border-radius: 0;
    border-inline: 0;
    border-top: 1px solid var(--line);
    padding-inline: var(--gutter);
    padding-block: 22px;
  }
  .card:last-child { border-bottom: 1px solid var(--line); }
  .card:hover { transform: none; }          /* no lift on a full-bleed row */

  /* Four stacked link columns is a long, monotonous footer on a phone. */
  .footer__grid { grid-template-columns: 1fr 1fr; gap: 32px 24px; }
  .footer__brand { grid-column: 1 / -1; }

  /* The is/isn't lists get the same left rail from their existing icons. */
  .contrast__item { column-gap: 14px; }
}

/* --------------------------------------------------- legal subpages -- */

.legal { max-width: 760px; margin: 0 auto; padding: 56px var(--gutter) 96px; }
.legal h1 {
  margin: 0 0 10px; font-family: var(--display); font-weight: 600;
  font-size: clamp(32px, 5vw, 52px); line-height: 1.1;
  letter-spacing: .005em; color: var(--ink);
}
.legal__meta { margin: 0 0 48px; font-size: 14px; color: var(--dim); }
.legal h2 {
  margin: 44px 0 16px; font-family: var(--display); font-weight: 600;
  font-size: 22px; line-height: 1.25; color: var(--ink);
}
.legal p, .legal li { font-size: 16px; line-height: 1.7; color: var(--muted); text-wrap: pretty; }
.legal p { margin: 0 0 16px; max-width: 68ch; }
.legal ul { margin: 0 0 16px; padding-left: 20px; max-width: 68ch; }
.legal li { margin-bottom: 10px; }
.legal__back {
  display: inline-flex; align-items: center; gap: 7px;
  margin-bottom: 40px; font-size: 14px;
}
.legal__back svg { transition: transform .22s var(--ease); }
.legal__back:hover svg { transform: translateX(-3px); }

/* 404 only. Exists so the CSP can drop 'unsafe-inline' from style-src. */
.success__note--center { text-align: center; }

/* Deep links from the index (/privacy#consent) landed under the sticky header. */
.legal :target,
.legal h2[id] { scroll-margin-top: calc(var(--header-h) + 28px); }
