/* compoundfit.app: one road down the page. Layout and states for the two-phone hero, the road layer,
   the verb stops, the close, the FAQ and the footer. Tokens come from tokens.css (constants/theme.ts). */

:root {
  --gutter: 32px;
  --max: 1200px;
  --container: 1240px;
}
@media (max-width: 899px) { :root { --gutter: 20px; } }

html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }
body { overflow-x: hidden; }
::selection { background: rgba(225,203,255,.32); color: var(--on-surface); }
:focus-visible { outline: 2px solid var(--primary); outline-offset: 3px; border-radius: 6px; }
.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; }
.page { position: relative; }
.wrap { position: relative; max-width: var(--container); margin: 0 auto; padding: 0 var(--gutter); }
section { scroll-margin-top: 72px; }

/* ---------- type ---------- */
.cap {
  margin: 0;
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: clamp(34px, 5vw, 68px);
  line-height: 1.04;
  letter-spacing: -0.035em;
  color: var(--on-surface);
  white-space: pre-line;
  text-wrap: balance;
}
.body {
  margin: 20px 0 0;
  font-family: var(--font-sans);
  font-size: clamp(17px, 1.25vw, 19px);
  line-height: 1.55;
  color: var(--on-surface-variant);
  max-width: 44ch;
  text-wrap: pretty;
}

/* ---------- the nav, on every page ---------- */
/* three columns with equal sides, so the links sit on the viewport's centre whatever the logo and the
   badges weigh (founder, 2026-10-12: space-between had pushed them left of centre) */
.nav { position: fixed; top: 0; left: 0; right: 0; z-index: 50; padding: 16px 32px; display: grid; grid-template-columns: 1fr auto 1fr; align-items: center;
  background: linear-gradient(180deg, rgba(14,14,14,.92) 0%, rgba(14,14,14,.6) 60%, rgba(14,14,14,0) 100%); }
/* explicit columns: when the links are display: none on a phone, auto-placement would move the badges
   into the middle column, right after the logo */
.nav-logo { grid-column: 1; justify-self: start; display: flex; align-items: center; gap: 10px; text-decoration: none; }
.nav-links { grid-column: 2; justify-self: center; }
.nav-badges { grid-column: 3; justify-self: end; }
.nav-logo img { width: 28px; height: 28px; border-radius: 6px; }
.nav-logo span { font-family: var(--font-sans); font-weight: 600; font-size: 17px; letter-spacing: -0.01em; color: var(--on-surface); }
.nav-links { display: flex; gap: 28px; }
.nav-links a { font-family: var(--font-sans); font-size: 14px; font-weight: 500; color: var(--on-surface-variant); text-decoration: none; transition: color 150ms; }
.nav-links a:hover { color: var(--on-surface); }
/* the nav's store badges take the CTA's place (R40, the ToneAdapt nav): 42 px tall, both from 460 px
   up, none on a phone (R41) */
.nav-badges { display: flex; align-items: center; min-height: 42px; }
@media (max-width: 899px) { .nav { padding: 14px 20px; } .nav-links { display: none; } }

/* ---------- hero: the copy beside the two phones ---------- */
/* the hero is as tall as its pair, not the viewport: the copy and the phones start just under the nav
   and the first stop follows where the phones end, so no dead ground sits above the headline on a
   tall window (founder, 2026-10-11). The hero paints above the road layer so the phones cover the
   road's start; its ground is the page's, never a fill of its own */
.hero { position: relative; z-index: 2; overflow-x: clip; overflow-y: visible; padding-top: 120px; }
.hero-grid { display: grid; grid-template-columns: minmax(360px, 560px) minmax(0, 1fr); grid-template-rows: auto; column-gap: 40px; align-items: start; }
.hero-copy { grid-row: 1; align-self: start; padding-top: 56px; position: relative; z-index: 12; max-width: 560px; }
.hero-h1 {
  margin: 0;
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: clamp(44px, 5.3vw, 76px);
  line-height: 1.02;
  letter-spacing: -0.035em;
  color: var(--on-surface);
  text-wrap: balance;
}
.hero-sub {
  margin: 24px 0 0;
  font-family: var(--font-sans);
  font-size: clamp(17px, 1.3vw, 18px);
  line-height: 1.55;
  color: var(--on-surface-variant);
  max-width: 34em;
  text-wrap: pretty;
}
.hero-badges { margin-top: 24px; }
.hero-trial, .summit .hero-trial {
  margin: 16px 0 0;
  font-family: var(--font-sans);
  font-size: 13px;
  line-height: 1.4;
  color: var(--on-surface-variant);
}
.hero-copy { animation: copyIn 700ms cubic-bezier(.2,.7,.2,1) both; }
@keyframes copyIn { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .hero-copy { animation: none; } }

/* the twin phones: the near phone (home) in front, the far phone (the map) the same size, higher and
   behind (R40, the ToneAdapt pair), both tilted a few degrees apart. --shift seats the far phone so the
   map's frontier (572 pt down its screen) sits --rise above the near screen's workout card (300 pt),
   the stroke's rise; --pad keeps a far phone that rises above the near one inside the pair's box.
   Beside the copy the pair scales with the viewport; at 1440 the far phone runs 23 px past the gutter,
   well inside the viewport's edge. */
.twin {
  --sw-near: clamp(200px, 16.3vw - 10px, 232px); --sw-far: var(--sw-near);
  --gap: clamp(80px, 8vw - 20px, 96px); --rise: 25px; --spill: 28px;
  --kn: calc(var(--sw-near) / 402); --kf: calc(var(--sw-far) / 402);
  --inn: calc(var(--sw-near) * 93 / 1606); --inf: calc(var(--sw-far) * 93 / 1606);
  --own: calc(var(--sw-near) * 1800 / 1606); --ohn: calc(var(--sw-near) * 3680 / 1606);
  --owf: calc(var(--sw-far) * 1800 / 1606); --ohf: calc(var(--sw-far) * 3680 / 1606);
  --shift: calc(var(--inn) + 300 * var(--kn) - var(--inf) - 572 * var(--kf) - var(--rise));
  --pad: max(0px, calc(-1 * var(--shift)));
  grid-row: 1; align-self: start; justify-self: start;
  position: relative; width: calc(var(--own) + var(--gap) + var(--owf) + var(--spill));
  height: calc(var(--pad) + max(var(--ohn), var(--shift) + var(--ohf)) + 24px);
}
.twin .phone { position: absolute; }
.twin .phone-far { --sw: var(--sw-far); left: calc(var(--own) + var(--gap)); top: calc(var(--pad) + var(--shift)); z-index: 1; transform: perspective(1800px) rotateZ(7deg) rotateY(-9deg); }
.twin .phone-near { --sw: var(--sw-near); left: 0; top: var(--pad); z-index: 3; transform: perspective(1800px) rotateZ(-6deg) rotateY(8deg); }
.twin-road { position: absolute; inset: 0; z-index: 2; pointer-events: none; }
.twin-road > * { position: absolute; }
.twin-glow {
  position: absolute; left: 18%; width: 82%; top: 28%; height: 48%; border-radius: 50%; z-index: 0;
  background: radial-gradient(50% 50% at 50% 50%, rgba(225,203,255,.14) 0%, rgba(225,203,255,.05) 45%, rgba(225,203,255,0) 72%);
}
@media (max-width: 1199px) {
  .hero { padding-top: 112px; }
  /* minmax(0, 1fr), not 1fr: a 1fr track's floor is its content's min width, and the twin phones are
     wider than a narrow screen's column (345 px at 360), so the track and the copy in it were pushed past
     the gutter and the page scrolled sideways; the phones spill past the column by design (R39) */
  .hero-grid { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto auto; row-gap: 40px; justify-items: center; }
  .hero-copy { max-width: 600px; justify-self: start; padding-top: 0; }
  .twin { grid-row: 2; justify-self: center; --sw-near: 220px; --sw-far: 220px; --gap: 90px; --rise: 20px; }
}
@media (max-width: 767px) { .twin { --sw-near: 190px; --sw-far: 190px; --gap: 60px; } }
@media (max-width: 599px) {
  .hero { padding-top: 96px; }
  .hero-h1 { font-size: 42px; }
  .hero-sub { margin-top: 18px; font-size: 16px; }
  .hero-trial { margin-top: 12px; }
  .hero-grid { row-gap: 32px; }
  /* on a phone the badge pair is centred (R41), the trial line under its middle (R42); the pair sits on
     one row down to 375 px and wraps, each row centred, below that */
  .hero-badges { justify-content: center; }
  .hero .hero-trial { text-align: center; }
  /* no stroke under 600 px, so the equal phones tuck together: the far one higher and 36 px behind the
     near one's edge, the pair 300 px wide so it fits a 320 px screen */
  .twin { --sw-near: 150px; --sw-far: 150px; --gap: -36px; --spill: 0px; }
}

/* ---------- the phone: Apple's iPhone 16 Pro frame over the screen (assets/iphone-16-pro-noisland; its
   Dynamic Island is punched out because every screen draws its own). Measured from the PNG's alpha: the
   frame is 1800 x 3680 and the screen cutout 1606 x 3494 at (97, 93), with 248 px corners. --sw is the
   screen's width (402 pt at 1x), so every point on a screen holds. ---------- */
.phone {
  position: relative; flex: none;
  width: calc(var(--sw) * 1800 / 1606); height: calc(var(--sw) * 3680 / 1606);
}
/* the black drop shadows: box shadows on a rounded box under the frame (the bezel's silhouette is a
   rounded rectangle), which WebKit caches, where drop-shadow filters re-blurred the whole frame every
   time a tile holding a phone was painted and made scrolling back up stutter (R48) */
.phone::before { content: ''; position: absolute; inset: 0; z-index: 0; border-radius: calc(var(--sw) * 330 / 1606); box-shadow: 0 60px 140px rgba(0,0,0,.55), 0 18px 40px rgba(0,0,0,.45); }
.phone::after { content: ''; position: absolute; inset: 0; z-index: 2; pointer-events: none; background: url(assets/iphone-16-pro-noisland.webp) 0 0 / 100% 100% no-repeat; }
.phone-screen { position: absolute; left: 5.389%; top: 2.527%; width: 89.222%; height: 94.946%; border-radius: calc(var(--sw) * 248 / 1606); z-index: 1; overflow: hidden; background: var(--background); }
/* only the hero's tilted phones need their screens on a layer of their own (the rounded clip under a
   3D transform); the stops' phones paint like the rest of the page (R48) */
.twin .phone-screen { transform: translateZ(0); }
.phone-screen img { display: block; width: 100%; height: 100%; }
/* a 1 px point inside a screen, read back through the phone's tilt to place the stroke exactly */
.mark { position: absolute; width: 1px; height: 1px; visibility: hidden; pointer-events: none; }

/* ---------- the road layer: one path for the whole page, under everything after it ---------- */
/* no z-index: the layer is not a stacking context, so the road paints under the stops while the pin
   inside it rises above them (z 1, under the hero's 2) and passes over every level node (R38) */
.road-layer { position: absolute; left: 0; top: 0; pointer-events: none; overflow: clip; }
/* The road is drawn once per segment (one segment per leg between nodes) as static SVGs, and the
   scroll loop never repaints them: the lit tube, the bright band behind the edge and the leak are
   revealed through windows made of two opposite translates (a clipping wrapper moved up, its content
   moved back down), so every frame is compositor work. Only the segments touching the edge carry
   transforms; a fully lit segment is a plain painted layer, a segment ahead is display: none. */
.road-seg { position: absolute; }
.seg-win { position: absolute; overflow: hidden; display: none; }
.seg-win.on { display: block; }
/* a moving window and the drawing inside it are both layers of their own, so the two translates
   compose and nothing re-rasterizes (a 2D transform alone does not promote an element in WebKit);
   a window shown whole carries no transform and paints like any other element */
.seg-win.moving, .seg-win.moving > svg { will-change: transform; }
.seg-win > svg { position: absolute; left: 0; display: block; }
/* the leak fades back into the stipple over its window, a mask that rides with the wrapper */
.seg-leak { -webkit-mask-image: linear-gradient(to bottom, #000, transparent); mask-image: linear-gradient(to bottom, #000, transparent); }
/* The fade under the pin's crest (R48): along the road, not round. A moving lit window's bottom is the
   edge (the pin's tip), so a mask anchored there rides with it for free: nothing from the tip up to the
   crest's top (--fade-b), the tube easing back to full over --fade-len (an eased ramp: a linear one
   reads as lit until its last third on a bright line over black). The bright band's window has the
   same bottom and the same mask. */
.seg-lit.moving, .seg-bright.moving {
  --fade: linear-gradient(to top, transparent 0, transparent var(--fade-b), rgba(0,0,0,.05) calc(var(--fade-b) + .3 * var(--fade-len)), rgba(0,0,0,.22) calc(var(--fade-b) + .55 * var(--fade-len)), rgba(0,0,0,.58) calc(var(--fade-b) + .8 * var(--fade-len)), #000 calc(var(--fade-b) + var(--fade-len)));
  -webkit-mask-image: var(--fade); mask-image: var(--fade);
}
/* overflow: clip keeps the pin's 6-crest rank frame (the room the shatter needs) from widening the
   page: on a phone the lane runs 58 px from the right edge and the frame reaches 86 px past it (R39) */
.road-layer > svg { position: absolute; left: 0; top: 0; overflow: visible; }
/* the light scrubs with the scroll (R34): the lit run and the pin are set every frame, never transitioned */
.road-layer .road-lit { transition: none; }
/* the pin rides the reading line by sticking to it inside a track the length of the road (its top is
   inline: the line in svh less the pin's tip); only its x is animated */
.pin-track { position: absolute; left: 0; z-index: 1; }
.pin.road-pin { position: sticky; z-index: auto; will-change: transform; transition: opacity 300ms ease; }
/* the rank the pin carries (R35): its crest, and the rank-up rig when one fires, live in a frame
   centred above the pin's head; the frame's origin is the pin's top centre */
.road-pin .pin-rank { position: absolute; left: 50%; top: 0; width: 0; height: 0; }
.road-pin .pin-rank img { pointer-events: none; }
/* a node pops as the edge passes it: the app's litPop (0.8 to 1.22 to 1 on the punch ease) */
.node-pop { animation: nodePop 320ms cubic-bezier(.2,1.6,.4,1) both; }
@keyframes nodePop { from { transform: scale(.8); } 55% { transform: scale(1.22); } to { transform: scale(1); } }
@media (prefers-reduced-motion: reduce) { .node-pop { animation: none; } .road-pin { transition: none; } }

/* ---------- the stops ---------- */
.climb { position: static; }
.stop { position: relative; isolation: isolate; }
.stop-grid { position: relative; z-index: 3; max-width: var(--max); margin: 0 auto; padding: 0 var(--gutter); display: grid; align-items: center; }
.stop-copy { max-width: 440px; }
.stop-phone { display: flex; justify-content: center; }
/* desktop: two equal columns, the phone on its side, the road meandering through the gap between; the
   bottom padding is the run of road that carries the node and the next gate */
@media (min-width: 900px) {
  .stop { padding: 140px 0 310px; }
  .stop-grid { grid-template-columns: 1fr 1fr; column-gap: 40px; }
  .side-right .stop-copy { grid-column: 1; justify-self: start; }
  .side-right .stop-phone { grid-column: 2; justify-self: end; }
  .side-left .stop-phone { grid-column: 1; grid-row: 1; justify-self: start; }
  .side-left .stop-copy { grid-column: 2; grid-row: 1; justify-self: end; }
}
/* a phone: the copy keeps a right inset so the road's lane runs beside it, never through it */
@media (max-width: 899px) {
  .stop { padding: 72px 0 250px; }
  .stop-grid { grid-template-columns: 1fr; row-gap: 36px; }
  .stop-copy { max-width: none; padding-right: 64px; }
  /* the phone sits at the left gutter so the lane, the pin and its crest have the right of the
     screen to themselves while the page scrolls (founder, 2026-10-11) */
  .stop-phone { justify-content: flex-start; }
}

/* level nodes and the pin */
.level { position: absolute; z-index: 6; border-radius: 50%; display: grid; place-items: center; transition: background 400ms ease, box-shadow 400ms ease; }
.pin { position: absolute; z-index: 9; }
.pin-pop { animation: pinPop 600ms cubic-bezier(.2,1.6,.4,1) both; }
@keyframes pinPop { from { transform: scale(.3); } 55% { transform: scale(1.18); } to { transform: scale(1); } }

/* gates on the seams (drawn by the road layer, at the road's crossing) */
.seam-gate { position: absolute; z-index: 7; width: 0; height: 0; }
.seam-gate > * { position: absolute; display: block; }
.gate-art { transition: opacity 500ms ease; }
.seam-gate.ahead .gate-art { opacity: .66; }
.gate-ground { border-radius: 50%; background: radial-gradient(50% 50% at 50% 50%, rgba(0,0,0,.62) 0%, rgba(0,0,0,.25) 45%, rgba(0,0,0,0) 72%); filter: blur(4px); z-index: -1; }
/* the map's gate hit: a white ring and a lavender bloom that play once and end gone;
   outside those 700 ms nothing rings the art */
.gate-ring { border-radius: 50%; border-style: solid; border-color: #ffffff; opacity: 0; visibility: hidden; z-index: 2; }
.gate-bloom { border-radius: 50%; background: radial-gradient(closest-side, rgba(225,203,255,.45) 0%, rgba(225,203,255,.16) 52%, rgba(225,203,255,0) 85%); opacity: 0; visibility: hidden; z-index: -2; }
.seam-gate.lit .gate-ring { animation: gatePulse 500ms ease-out forwards; }
.seam-gate.lit .gate-bloom { animation: gateBloom 700ms ease-out forwards; }
.seam-gate.lit .gate-art { animation: gateShake 350ms linear both; }
@keyframes gatePulse { 0% { opacity: 0; visibility: visible; transform: scale(.96); } 50% { opacity: 1; transform: scale(1); } 99% { opacity: 0; visibility: visible; } 100% { opacity: 0; visibility: hidden; transform: scale(1.02); } }
@keyframes gateBloom { 0% { opacity: 0; visibility: visible; transform: scale(.4); } 40% { opacity: 1; } 99% { opacity: 0; visibility: visible; } 100% { opacity: 0; visibility: hidden; transform: scale(1.3); } }
@keyframes gateShake { 0% { transform: none; } 25% { transform: translateX(-3px); } 50% { transform: translateX(3px); } 75% { transform: translateX(-2px); } 100% { transform: none; } }
@media (prefers-reduced-motion: reduce) {
  .pin-pop, .seam-gate.lit .gate-ring, .seam-gate.lit .gate-bloom, .seam-gate.lit .gate-art { animation: none; }
}

/* ---------- the close: the pin arrives ---------- */
.summit { position: relative; isolation: isolate; padding: 40px 0 140px; text-align: center; }
@media (max-width: 899px) { .summit { padding: 24px 0 96px; } }
.summit-inner { position: relative; z-index: 3; margin: 0 auto; display: flex; flex-direction: column; align-items: center; }
.summit-inner > .cap, .summit-inner > .body, .summit-inner > .summit-badges, .summit-inner > .hero-trial { padding-left: var(--gutter); padding-right: var(--gutter); max-width: 640px; }
/* the last node stands at the end of a run of road, above the headline */
.summit-node.level { position: relative; margin: 300px auto 20px; }
@media (max-width: 899px) { .summit-node.level { margin: 220px auto 16px; } }
.summit-pool { position: absolute; z-index: 2; border-radius: 50%; pointer-events: none; opacity: 0; transition: opacity 600ms ease;
  background: radial-gradient(50% 50% at 50% 50%, rgba(225,203,255,.20) 0%, rgba(225,203,255,.06) 45%, rgba(225,203,255,0) 72%); }
.summit-pool.on { opacity: 1; }
@media (prefers-reduced-motion: reduce) { .summit-pool { transition: none; } }
.summit .cap { margin-top: 8px; }
.summit .body { max-width: 36ch; }
.summit-badges { margin-top: 32px; justify-content: center; }

/* ---------- FAQ ---------- */
.faq { position: relative; z-index: 1; padding: 140px var(--gutter) 120px; max-width: var(--max); margin: 0 auto; }
.faq-grid { display: grid; grid-template-columns: minmax(240px, 360px) 1fr; gap: 64px; align-items: flex-start; }
.faq-head { position: sticky; top: 96px; }
.faq-head .cap { font-size: clamp(36px, 4vw, 52px); }
.faq-list { display: flex; flex-direction: column; }
/* no card for the open answer: the x in primary and the answer itself carry the open state */
.faq-row { border-radius: 14px; margin-bottom: 4px; transition: background 200ms ease; }
.faq-row:hover { background: var(--surface-container-low); }
.faq-q { width: 100%; display: flex; justify-content: space-between; align-items: center; gap: 24px; padding: 20px 24px; background: none; border: 0; cursor: pointer; text-align: left;
  font-family: var(--font-sans); font-size: 18px; font-weight: 500; letter-spacing: -0.005em; line-height: 1.3; color: var(--on-surface); }
.faq-plus { width: 28px; height: 28px; border-radius: 50%; background: var(--surface-container-high); display: grid; place-items: center; flex-shrink: 0; transition: background 200ms ease, transform 300ms cubic-bezier(.2,.7,.2,1); }
.faq-plus svg path { stroke: var(--on-surface); }
.faq-row.open .faq-plus { background: var(--primary); transform: rotate(45deg); }
.faq-row.open .faq-plus svg path { stroke: var(--on-primary); }
.faq-a { display: grid; grid-template-rows: 0fr; transition: grid-template-rows 400ms cubic-bezier(.2,.7,.2,1); }
.faq-row.open .faq-a { grid-template-rows: 1fr; }
.faq-a-inner { overflow: hidden; min-height: 0; max-width: 580px; }
.faq-a-inner p { padding: 0 24px 24px; }
@media (prefers-reduced-motion: reduce) { .faq-a { transition: none; } }
.faq-a-inner p { margin: 0; font-family: var(--font-sans); font-size: 16px; line-height: 1.6; color: var(--on-surface-variant); }
@media (max-width: 899px) {
  .faq { padding: 72px var(--gutter) 64px; }
  .faq-grid { grid-template-columns: 1fr; gap: 32px; }
  .faq-head { position: static; }
}

/* ---------- footer ---------- */
.site-footer { position: relative; z-index: 1; padding: 80px var(--gutter) 48px; margin-top: 40px; background: var(--surface-container-lowest); }
.footer-inner { max-width: var(--max); margin: 0 auto; }
.footer-grid { display: grid; grid-template-columns: 2fr 1fr 1fr 1fr; gap: 32px; margin-bottom: 64px; }
.footer-brand { display: flex; align-items: center; gap: 12px; margin-bottom: 16px; }
.footer-brand img { width: 36px; height: 36px; border-radius: 8px; }
.footer-brand span { font-family: var(--font-sans); font-size: 22px; font-weight: 600; letter-spacing: -0.01em; color: var(--on-surface); }
.footer-line { margin: 0; font-family: var(--font-sans); font-size: 15px; line-height: 1.6; color: var(--on-surface-variant); max-width: 320px; }
.footer-title { margin: 0 0 16px; font-family: var(--font-sans); font-size: 14px; font-weight: 600; color: var(--on-surface-variant); }
.footer-links { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.footer-links a { font-family: var(--font-sans); font-size: 14px; color: var(--on-surface); text-decoration: none; transition: color 150ms; }
.footer-links a:hover { color: var(--primary); }
.footer-foot { display: flex; justify-content: space-between; align-items: flex-end; gap: 32px; flex-wrap: wrap; font-family: var(--font-sans); font-size: 12px; color: var(--on-surface-variant); }
.footer-foot span:last-child { font-size: 11px; opacity: .7; }
@media (max-width: 899px) {
  .site-footer { padding: 48px var(--gutter) 40px; margin-top: 16px; }
  .footer-grid { grid-template-columns: 1fr 1fr; margin-bottom: 40px; }
  .footer-grid > *:first-child { grid-column: 1 / -1; }
}
