/* Yoke — hero → real Today screen (YK-32 / W5).
   Light → dark: eggshell hero, then the canvas turns warm brown-black as the phone arrives.
   Progressive enhancement: the BASE styles are the static layout (reduced motion / unsupported
   browsers). The scroll-driven version is added inside @supports + prefers-reduced-motion.

   One coordinate system: .stage is a size container, so every geometry value below is in
   cqw/cqh. The phone is sized so its screen has the screenshot's exact aspect (1179 × 2556), and the
   gauge SVG is drawn in screenshot pixels, so "landing" = scale to the screen width, no estimation. */

:root {
  color-scheme: light;
  --canvas: #F7F2E7;
  --canvas-dark: #1C1917;
  --yolk: #F5A623;
  --ink: #242019;
  --muted: #6B6459;
  --card: #FDFBF6;
  --field-border: #8A8275;
  --ink-dark: #F5F0E6;
  --muted-dark: #B8B0A3;
  /* Measured from the Today screenshot: arc fill, arc track and screen background as the app renders them. */
  --gauge-fill: #E9A944;
  --gauge-track-light: #D4CFC3;   /* Ink-muted at 25% on Canvas, opaque */
  --gauge-track-dark: #373430;
  --screen-bg: #1B1917;
  --bezel: #0B0A09;
  --on-yolk: #242019;
  --rounded: ui-rounded, "SF Pro Rounded", "SF Compact Rounded", -apple-system, BlinkMacSystemFont, system-ui, "Helvetica Neue", Arial, sans-serif;
  --text: var(--rounded);

  --travel: 160svh;   /* scroll distance the animations are spread over */
  --hold: 110svh;      /* extra pinned dwell after everything has landed */
  --ease: cubic-bezier(.45, 0, .1, 1);
}
.dark { --ink: var(--ink-dark); --muted: var(--muted-dark); color: var(--ink); }

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body { margin: 0; background: var(--canvas); color: var(--ink); font: 17px/1.5 var(--rounded); }
button, input { font-family: inherit; }
:focus-visible { outline: 3px solid var(--ink); outline-offset: 3px; border-radius: 6px; }

/* ---------- Stage geometry (desktop / landscape default) ---------- */
.stage {
  position: relative; height: 100svh; overflow: clip;
  container-type: size;
  perspective: 1600px; perspective-origin: 50% 85%;

  --phk: 90;                                  /* phone height, in cqh */
  --ph: calc(var(--phk) * 1cqh);
  --pw: calc(var(--ph) * .47456);             /* screen aspect 1179:2556 + .026 bezel → ph = 2.1072 pw */
  --px: 70cqw;                                /* phone centre x */
  --pt: 5cqh;                                 /* phone top */
  --b: calc(var(--pw) * .026);                /* bezel */
  --sw: calc(var(--pw) * .948);               /* screen width = gauge width at landing */
  /* Gauge crest (centre of the stroke) sits 423 of 1179 screenshot-px below the screen top. */
  --crest-y: calc(var(--pt) + var(--b) + var(--sw) * .35878);

  --gk: 300;                                  /* hero gauge width, in cqh */
  --gw: calc(var(--gk) * 1cqh);
  --cx0: 67cqw;                               /* hero crest position */
  --cy0: 86cqh;
  --g-scale: calc(.44988 * var(--phk) / var(--gk));   /* landing width (.44988·phk cqh) ÷ hero width */
}

.gauge {
  position: absolute; z-index: 3;
  width: var(--gw); aspect-ratio: 1179 / 810;
  left: calc(var(--cx0) - var(--gw) / 2);
  top: calc(var(--cy0) - var(--gw) * .3079);   /* crest is 44.81% down the 810-unit viewBox */
  transform-origin: 50% 44.81%;                /* scale about the crest, so translate = crest movement */
  transform: translate(0, 0);
}
.gauge svg { display: block; width: 100%; height: 100%; overflow: visible; }
.gauge-track { fill: none; stroke: var(--gauge-track-light); stroke-width: 66; stroke-linecap: round; }
.gauge-track-dark { stroke: var(--gauge-track-dark); opacity: 0; }
.canvas-dark { position: absolute; inset: 0; background: var(--canvas-dark); opacity: 0; pointer-events: none; }
.gauge .mascot { transform: translateY(10px); }   /* hero only: body visibly rests on the oversized arc; eases to 0 (the exact in-app seat) by landing */
.gauge-fill  { fill: none; stroke: var(--gauge-fill); stroke-width: 66; stroke-linecap: round;
  stroke-dasharray: 1 2; stroke-dashoffset: 1.05; }   /* empty in the hero; fills to the app's 34% as it lands */

.phone {
  position: absolute; z-index: 2;
  left: calc(var(--px) - var(--pw) / 2); top: var(--pt);
  width: var(--pw); height: var(--ph);
  border-radius: calc(var(--pw) * .163);     /* = screen radius .137 + bezel .026 (concentric) */
  background: var(--bezel);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.22), 0 0 0 1px rgba(245,240,230,.10);
  transform-origin: 50% 100%;
}
.phone::before {                              /* ground shadow */
  content: ""; position: absolute; inset: 0; border-radius: inherit; z-index: -1;
  box-shadow: 0 1cqh 3cqh rgba(0, 0, 0, .5);
}
.phone::after {                               /* faint warm halo so the dark phone separates from the dark canvas */
  content: ""; position: absolute; inset: -4% -55% 0; z-index: -2; pointer-events: none;
  background: radial-gradient(closest-side, rgba(245,166,35,.13), rgba(245,166,35,0));
}
.screen {
  position: absolute; inset: var(--b); border-radius: calc(var(--pw) * .137);
  background: var(--screen-bg); overflow: clip;
}
.ui { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.island {
  position: absolute; top: calc(var(--pw) * .03); left: 50%; transform: translateX(-50%);
  width: calc(var(--pw) * .285); height: calc(var(--pw) * .082); border-radius: 999px; background: #000;
}

.scene-copy {
  position: absolute; z-index: 2; left: 8cqw; top: 50cqh; translate: 0 -50%; width: 40cqw;
}
.scene-copy h2 {
  margin: 0; font-family: var(--rounded); font-weight: 700; letter-spacing: -.035em; line-height: 1.06;
  font-size: clamp(1.75rem, 3.7cqw, 4.25rem); text-wrap: balance;
}
.soft { color: var(--muted); }

/* ---------- Hero copy ---------- */
.hero-copy {
  position: relative; z-index: 4; min-height: 100svh;      /* flows in the static layout */
  display: flex; flex-direction: column;
  padding: 1.75rem clamp(1.25rem, 6vw, 6rem) 0;
  pointer-events: none;
}
.hero-copy a, .hero-copy form, .hero-copy .avail { pointer-events: auto; }
.brand { display: inline-flex; align-items: center; gap: .6rem; align-self: flex-start; min-height: 44px;
  text-decoration: none; color: inherit; font: 700 1.35rem/1 var(--rounded); letter-spacing: -.01em; }
.yolk { width: .95rem; height: .95rem; border-radius: 50%; background: var(--yolk); }
.hero-main { flex: 1; display: flex; flex-direction: column; justify-content: center; max-width: 46vw; padding-bottom: 8svh; }
h1 {
  margin: 0; font-family: var(--rounded); font-weight: 700; line-height: 1.02; letter-spacing: -.04em;
  font-size: clamp(3rem, 5.4vw, 6.4rem);
}
.lede { margin: 1.4rem 0 0; font-size: 1.2rem; line-height: 1.45; max-width: 24rem; text-wrap: balance; }
.signup { margin-top: 1.75rem; max-width: 29rem; }
.signup label { display: block; margin-bottom: .5rem; font: 600 .95rem/1 var(--rounded); }
.field { display: flex; gap: .5rem; }
input[type="email"] {
  flex: 1; min-width: 0; min-height: 56px; padding: 0 1rem; border-radius: 16px;
  border: 1.5px solid var(--field-border); background: var(--card); color: var(--ink);
  font: 400 1.0625rem/1 var(--text);            /* >=16px: no iOS focus zoom */
}
input::placeholder { color: var(--muted); opacity: 1; }
input:focus-visible { outline: 3px solid var(--ink); outline-offset: 2px; }
button {
  flex: none; min-height: 56px; padding: 0 1.4rem; border: 0; border-radius: 16px; cursor: pointer;
  background: var(--yolk); color: var(--on-yolk); font: 700 1.0625rem/1 var(--rounded);
  touch-action: manipulation; transition: transform .15s ease;
}
button:active { transform: scale(.98); }
.msg { margin: .6rem 0 0; font-weight: 600; font-size: .9375rem; }
.msg:empty { display: none; }
.note { margin: .6rem 0 0; font-size: .9rem; line-height: 1.4; color: var(--muted); }
.pill { display: inline-block; margin-right: .35rem; padding: .05rem .5rem; border-radius: 999px; border: 1px solid var(--muted);
  font: 600 .7rem/1.5 var(--rounded); letter-spacing: .06em; text-transform: uppercase; color: var(--ink); }
.avail { margin: 1.1rem 0 0; font: 600 .9375rem/1 var(--rounded); letter-spacing: .02em; color: var(--muted); }


/* ---------- Mobile / portrait composition (designed, not shrunk) ---------- */
@media (max-aspect-ratio: 1/1) {
  :root { --travel: 130svh; --hold: 80svh; }
  .stage {
    --pw: min(76cqw, 54cqh);
    --ph: calc(var(--pw) * 2.1072);
    --px: 50cqw; --pt: 30cqh;                /* phone bleeds off the bottom; the gauge, total and Log button stay fully in view */
    --gm: 3.4;                               /* hero gauge width ÷ phone width */
    --gw: calc(var(--pw) * var(--gm));
    --cx0: 50cqw; --cy0: 89cqh;
    --g-scale: calc(.948 / var(--gm));
  }
  .scene-copy { left: 6cqw; top: 4.5cqh; translate: none; width: 88cqw; }
  .scene-copy h2 { font-size: clamp(1.4rem, 6.2cqw, 2.6rem); }
  .hero-copy { padding-top: 1rem; }
  .hero-main { max-width: none; justify-content: flex-start; padding: 3.5svh 0 0; }
  h1 { font-size: clamp(2rem, 10vw, 3.4rem); letter-spacing: -.035em; }
  .lede { margin-top: 1rem; font-size: 1.0625rem; }
  .signup { margin-top: 1.1rem; max-width: none; }
  input[type="email"], button { min-height: 52px; }
  button { padding: 0 1rem; font-size: 1rem; }
  .avail { margin-top: .8rem; }
}
/* Short portrait viewports (iPhone SE, in-app browsers with toolbars): smaller, lower gauge and a
   tighter hero so the mascot never meets the form. */
@media (max-aspect-ratio: 1/1) and (max-height: 620px) {
  .stage { --gm: 2.8; --cy0: 95cqh; }
  .hero-main { padding-top: 1.5svh; }
}
/* Squarer landscape (e.g. 1024×768): nudge the gauge right and narrow the text column. */
@media (min-aspect-ratio: 1/1) and (max-aspect-ratio: 3/2) {
  .stage { --cx0: 75cqw; --px: 72cqw; }
  .hero-main { max-width: 42vw; }
}
/* Landscape phones: static flowing layout (no pinned scene); keep the mascot clear of the form. */
@media (min-aspect-ratio: 1/1) and (max-height: 520px) {
  .stage { --cx0: 76cqw; }
  .hero-main { max-width: 45vw; }
}
@media (max-width: 359px) {
  input[type="email"] { padding: 0 .75rem; font-size: 1rem; }
  button { padding: 0 .75rem; font-size: .9375rem; }
}

/* ---------- STATIC layout (base): reduced motion / unsupported browsers ---------- */
.track { position: relative; }
.track > .stage { position: absolute; inset: 0; height: auto; }   /* fills the track behind the flowing hero copy */
.track .phone, .track .scene-copy { display: none; }   /* hero frame shows only gauge + copy */
.frame-end { display: block; background: var(--canvas-dark); }
.frame-end .stage { background: var(--canvas-dark); }

/* ---------- SCROLL-DRIVEN layout ---------- */
@supports (animation-timeline: scroll()) {
  /* min-height: short viewports (landscape phones) keep the flowing static layout so the form is always reachable. */
  @media (prefers-reduced-motion: no-preference) and (min-height: 521px) {
    :root {
      --r-end:   calc(var(--travel) * .8);            /* gauge + phone arrive here */
      --r-phone: calc(var(--travel) * .04);
      --r-hero:  calc(var(--travel) * .3);            /* hero copy gone */
      --r-canvas-a: calc(var(--travel) * .32);  --r-canvas-b: calc(var(--travel) * .7);
      --r-fill-a:   calc(var(--travel) * .5);
      --r-copy-a: calc(var(--travel) * .56);    --r-copy-b: calc(var(--travel) * .8);
      --r-ui-a:   calc(var(--travel) * .9);     /* UI is fully in (fades in .8 → .9 beneath the opaque hero gauge) … */
      --r-ui-b:   calc(var(--travel) * .97);    /* … then the hero gauge + mascot fade out over identical art */
    }
    .track { height: calc(100svh + var(--travel) + var(--hold)); }
    .track > .stage { position: sticky; inset: 0 auto auto auto; height: 100svh; }
    .track .hero-copy { position: absolute; top: 0; left: 0; right: 0; height: 100svh; min-height: 0; }
    .track .phone, .track .scene-copy { display: block; }
    .frame-end { display: none; }

    .track .canvas-dark, .track .gauge, .track .gauge svg, .track .gauge-track-dark, .track .gauge-fill, .track .mascot, .track .island,
    .track .phone, .track .phone::before, .track .phone::after, .track .ui, .track .scene-copy, .track .hero-copy {
      animation-timeline: scroll(root block);
      animation-fill-mode: both;
      animation-timing-function: linear;
    }
    /* Page canvas: eggshell → warm brown-black while the phone arrives. */
    .track .canvas-dark { animation-name: fade-in; animation-range: var(--r-canvas-a) var(--r-canvas-b); }
    .track .gauge-track-dark { animation-name: fade-in; animation-range: var(--r-canvas-a) var(--r-canvas-b); }
    .track .phone::after { animation-name: fade-in; animation-range: var(--r-canvas-a) var(--r-canvas-b); }
    .track .phone::before { animation-name: fade-in; animation-range: calc(var(--travel) * .3) var(--r-end); }

    .track .gauge { animation-name: gauge-travel; animation-timing-function: var(--ease);
      animation-range: 0px var(--r-end); will-change: transform; }
    .track .phone { animation-name: phone-rise; animation-timing-function: var(--ease);
      animation-range: var(--r-phone) var(--r-end); will-change: transform; }
    .track .mascot { animation-name: seat; animation-timing-function: var(--ease); animation-range: 0px var(--r-end); }
    .track .island { animation-name: fade-in; animation-range: var(--r-end) var(--r-ui-a); }   /* island arrives with the UI, so the mascot never crosses it */
    .track .gauge-fill { animation-name: fill-in; animation-range: var(--r-fill-a) var(--r-end); }
    /* Hand-over: the UI (which carries its own gauge, exactly underneath) fades in as the hero gauge fades out. */
    .track .ui { animation-name: fade-in; animation-range: var(--r-end) var(--r-ui-a); }
    .track .gauge svg { animation-name: fade-out; animation-range: var(--r-ui-a) var(--r-ui-b); }
    .track .scene-copy { animation-name: scene-in; animation-timing-function: ease-out;
      animation-range: var(--r-copy-a) var(--r-copy-b); }
    .track .hero-copy { animation-name: fade-out; animation-range: 0px var(--r-hero); }
    /* Keyboard users who Shift+Tab back to the form must never meet it half-faded. */
    .track .hero-copy:focus-within { animation: none; opacity: 1; }

    /* Section 02: the three messages share one slot and appear one after another while the phone stays pinned. */
    .track .points { display: grid; min-height: 3.2em; align-items: start; }
    .track .points li { grid-area: 1 / 1; animation-timeline: scroll(root block); animation-timing-function: linear; opacity: 0; }
    .track .points li:nth-child(1) { animation-name: pt-in, pt-out; animation-fill-mode: both, forwards;
      animation-range: calc(var(--travel) * .86) calc(var(--travel) * .96), calc(var(--travel) + var(--hold) * .3) calc(var(--travel) + var(--hold) * .38); }
    .track .points li:nth-child(2) { animation-name: pt-in, pt-out; animation-fill-mode: both, forwards;
      animation-range: calc(var(--travel) + var(--hold) * .3) calc(var(--travel) + var(--hold) * .4), calc(var(--travel) + var(--hold) * .62) calc(var(--travel) + var(--hold) * .7); }
    .track .points li:nth-child(3) { animation-name: pt-in; animation-fill-mode: both;
      animation-range: calc(var(--travel) + var(--hold) * .62) calc(var(--travel) + var(--hold) * .72); }
    @keyframes pt-in  { from { opacity: 0; transform: translateY(1.2cqh); } to { opacity: 1; transform: none; } }
    @keyframes pt-out { from { opacity: 1; } to { opacity: 0; } }
    @keyframes gauge-travel {
      to { transform: translate(calc(var(--px) - var(--cx0)), calc(var(--crest-y) - var(--cy0))) scale(var(--g-scale)); }
    }
    @keyframes phone-rise {
      from { transform: translateY(calc(100cqh - var(--pt) + 2cqh)) scale(.84) rotateX(9deg); }
      to   { transform: none; }
    }
    @keyframes seat      { to { transform: none; } }
    @keyframes fill-in   { from { stroke-dashoffset: 1.05; } to { stroke-dashoffset: 0; } }
    @keyframes fade-in   { from { opacity: 0; } to { opacity: 1; } }
    @keyframes fade-out  { from { opacity: 1; } to { opacity: 0; } }
    @keyframes scene-in  { from { opacity: 0; transform: translateY(4cqh); } to { opacity: 1; transform: none; } }
  }
}


/* =====================================================================
   Sections after the pinned scene: logging (dark) → progress (light) → final CTA (dark) → footer.
   Normal flow, native scrolling. Colour changes are soft gradients, not hard cuts.
   ===================================================================== */
.skip { position: absolute; left: .75rem; top: -4rem; z-index: 10; padding: .6rem 1rem; border-radius: 10px;
  background: var(--yolk); color: var(--on-yolk); font: 700 1rem/1 var(--rounded); text-decoration: none; }
.skip:focus { top: .75rem; }
.wrap { width: min(100%, 76rem); margin-inline: auto; padding-inline: clamp(1.25rem, 6vw, 4rem); }
.center { text-align: center; }
section h2 { margin: 0; font-family: var(--rounded); font-weight: 700; letter-spacing: -.04em; line-height: 1.04;
  font-size: clamp(2.25rem, 6vw, 5rem); text-wrap: balance; }
.sub { margin: 1.25rem auto 0; max-width: 32rem; font-size: clamp(1.0625rem, 1.6vw, 1.3rem); line-height: 1.5; color: var(--muted); }
.logging, .result, .final, .site-footer { background: var(--canvas-dark); color: var(--ink); }
.progress { background: linear-gradient(to bottom, var(--canvas-dark), var(--canvas) 16svh); color: var(--ink); padding-top: calc(16svh + 1rem); }
.companion { background: var(--canvas); color: var(--ink); isolation: isolate; padding-block: clamp(6rem, 16svh, 9rem) clamp(3rem, 8svh, 5rem); }
.final { background: linear-gradient(to bottom, var(--canvas), var(--canvas-dark) 16svh); padding-top: calc(16svh + 1rem); }
.progress { padding-bottom: clamp(5rem, 12svh, 9rem); }
.final { padding-bottom: clamp(4rem, 10svh, 8rem); }
.progress h2, .progress .sub { position: relative; }

/* Logging: three distinct moments (photo / voice / text) built from CSS only: no fabricated app UI. */
.logging { padding-block: clamp(3rem, 8svh, 6rem) clamp(3rem, 8svh, 6rem); }
.moments { list-style: none; margin: clamp(2.5rem, 7svh, 5rem) 0 0; padding: 0; display: grid; gap: 2.5rem; }
.moment h3 { margin: 1.25rem 0 0; font: 700 1.75rem/1.1 var(--rounded); letter-spacing: -.025em; }
.moment p { margin: .35rem 0 0; color: var(--muted); font-size: 1.0625rem; }
.tile { position: relative; aspect-ratio: 4 / 4.4; border-radius: 28px; overflow: hidden; background: #26221F; border: 1px solid #3A3530;
  display: grid; place-items: center; }
.photo .vf { position: absolute; inset: 14%; border-radius: 12px; --c: var(--yolk);
  background:
    linear-gradient(var(--c), var(--c)) 0 0 / 28px 3px, linear-gradient(var(--c), var(--c)) 0 0 / 3px 28px,
    linear-gradient(var(--c), var(--c)) 100% 0 / 28px 3px, linear-gradient(var(--c), var(--c)) 100% 0 / 3px 28px,
    linear-gradient(var(--c), var(--c)) 0 100% / 28px 3px, linear-gradient(var(--c), var(--c)) 0 100% / 3px 28px,
    linear-gradient(var(--c), var(--c)) 100% 100% / 28px 3px, linear-gradient(var(--c), var(--c)) 100% 100% / 3px 28px;
  background-repeat: no-repeat; }
.photo .focus { position: absolute; width: 26%; aspect-ratio: 1; border: 2px solid var(--yolk); border-radius: 8px; }
.photo .shutter { position: absolute; left: 0; right: 0; height: 51%; background: #0E0C0B; }
.photo .s1 { top: 0; transform: translateY(-101%); } .photo .s2 { bottom: 0; transform: translateY(101%); }
.photo .flash { position: absolute; inset: 0; background: #FFF6DE; opacity: 0; }
.photo .badge { position: absolute; right: 9%; bottom: 8%; width: 2.1rem; height: 2.1rem; }
.badge circle { fill: var(--yolk); } .badge path { fill: none; stroke: var(--on-yolk); stroke-width: 2.6; stroke-linecap: round; stroke-linejoin: round; }
/* Voice: the completed state is the base (bars settled, "Recorded"). */
.rec { position: absolute; top: 9%; left: 9%; display: flex; align-items: center; gap: .55rem; font: 600 .9rem/1 var(--rounded); color: var(--ink-dark); }
.rec .dot { width: .7rem; height: .7rem; border-radius: 50%; background: #7C746A; }
.rec .lab { display: grid; } .rec .lab b { grid-area: 1 / 1; font-weight: 600; }
.rec .l1 { opacity: 0; }
.wave { display: flex; align-items: center; gap: 7px; height: 42%; }
.wave i { display: block; width: 7px; height: 100%; border-radius: 99px; background: var(--yolk); transform: scaleY(var(--h)); }
.wave i:nth-child(1) { --p1:0.2; --p2:0.5; --p3:0.35; --p4:0.6; --p5:0.3; --h:0.25 }
.wave i:nth-child(2) { --p1:0.45; --p2:0.9; --p3:0.5; --p4:0.8; --p5:0.4; --h:0.45 }
.wave i:nth-child(3) { --p1:0.7; --p2:0.4; --p3:1; --p4:0.5; --p5:0.9; --h:0.7 }
.wave i:nth-child(4) { --p1:0.5; --p2:1; --p3:0.6; --p4:0.9; --p5:0.55; --h:0.5 }
.wave i:nth-child(5) { --p1:1; --p2:0.55; --p3:0.85; --p4:0.4; --p5:1; --h:0.9 }
.wave i:nth-child(6) { --p1:0.62; --p2:0.8; --p3:0.45; --p4:1; --p5:0.6; --h:0.62 }
.wave i:nth-child(7) { --p1:0.8; --p2:0.35; --p3:0.9; --p4:0.7; --p5:0.8; --h:0.8 }
.wave i:nth-child(8) { --p1:0.4; --p2:0.7; --p3:0.55; --p4:0.95; --p5:0.45; --h:0.4 }
.wave i:nth-child(9) { --p1:0.9; --p2:0.5; --p3:1; --p4:0.45; --p5:0.7; --h:0.85 }
.wave i:nth-child(10) { --p1:0.55; --p2:0.95; --p3:0.4; --p4:0.75; --p5:0.9; --h:0.55 }
.wave i:nth-child(11) { --p1:0.35; --p2:0.6; --p3:0.8; --p4:0.5; --p5:0.35; --h:0.3 }
.wave i:nth-child(12) { --p1:0.75; --p2:0.4; --p3:0.65; --p4:1; --p5:0.5; --h:0.7 }
.wave i:nth-child(13) { --p1:0.5; --p2:0.85; --p3:0.5; --p4:0.6; --p5:0.85; --h:0.45 }
.wave i:nth-child(14) { --p1:0.3; --p2:0.55; --p3:0.9; --p4:0.35; --p5:0.5; --h:0.3 }
.wave i:nth-child(15) { --p1:0.2; --p2:0.4; --p3:0.3; --p4:0.5; --p5:0.25; --h:0.2 }
/* Text: the completed phrase is the base. */
.text .line { display: inline-flex; align-items: center; gap: 3px; }
.typed { display: inline-block; white-space: nowrap; font: 600 clamp(1.05rem, 1.9vw, 1.35rem)/1.3 var(--rounded); color: var(--ink-dark); }
.caret { width: 2px; height: 1.4em; background: var(--yolk); opacity: 0; }

/* Demos play once on entry (class .play added by main.js); without it, the completed states above show. */
.js-anim .photo:not(.play) .vf { opacity: .3; transform: scale(1.14); }
.js-anim .photo:not(.play) .focus, .js-anim .photo:not(.play) .badge { opacity: 0; }
.js-anim .photo.play .vf { animation: vf-in .7s cubic-bezier(.2,.7,.2,1) both; }
.js-anim .photo.play .focus { animation: focus 1s .55s ease-out both; }
.js-anim .photo.play .s1 { animation: close-top .5s 1.7s ease-in-out both; }
.js-anim .photo.play .s2 { animation: close-bot .5s 1.7s ease-in-out both; }
.js-anim .photo.play .flash { animation: flash .55s 2.1s ease-out both; }
.js-anim .photo.play .badge { animation: badge .4s 2.5s cubic-bezier(.2,.9,.3,1.3) both; }
@keyframes vf-in { from { opacity: .3; transform: scale(1.14); } to { opacity: 1; transform: none; } }
@keyframes focus { 0% { opacity: 0; transform: scale(1.8); } 35% { opacity: 1; transform: scale(1.12); } 60% { transform: scale(.94); } 80% { transform: scale(1.03); } 100% { opacity: 1; transform: none; } }
@keyframes close-top { 0% { transform: translateY(-101%); } 45% { transform: none; } 55% { transform: none; } 100% { transform: translateY(-101%); } }
@keyframes close-bot { 0% { transform: translateY(101%); } 45% { transform: none; } 55% { transform: none; } 100% { transform: translateY(101%); } }
@keyframes flash { 0% { opacity: 0; } 18% { opacity: .75; } 100% { opacity: 0; } }
@keyframes badge { from { opacity: 0; transform: scale(.5); } to { opacity: 1; transform: none; } }

.js-anim .voice:not(.play) .wave i { transform: scaleY(.08); }
.js-anim .voice:not(.play) .rec { opacity: 0; }
.js-anim .voice.play .rec { animation: l-in .3s both; }
.js-anim .voice.play .dot { animation: rec-pulse .8s 4 both, dot-off .01s 3.2s forwards; background: #FF5A4F; }
.js-anim .voice.play .l1 { opacity: 1; animation: l-out .3s 3.2s forwards; }
.js-anim .voice.play .l2 { opacity: 0; animation: l-in .3s 3.35s forwards; }
.js-anim .voice.play .wave i { animation: bar 3.2s .3s ease-in-out both; }
@keyframes l-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes l-out { to { opacity: 0; } }
@keyframes rec-pulse { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: .45; transform: scale(.8); } }
@keyframes dot-off { to { background: #7C746A; } }
@keyframes bar { 0% { transform: scaleY(.08); } 12% { transform: scaleY(var(--p1)); } 30% { transform: scaleY(var(--p2)); } 48% { transform: scaleY(var(--p3)); } 66% { transform: scaleY(var(--p4)); } 82% { transform: scaleY(var(--p5)); } 100% { transform: scaleY(var(--h)); } }

.js-anim .text.play .caret { animation: blink .8s steps(1) infinite; }
.js-anim .text:not(.play) .caret { opacity: 0; }
.js-anim .text.done .caret { animation: caret-off .4s forwards; }
@keyframes blink { 50% { opacity: 0; } 0%, 100% { opacity: 1; } }
@keyframes caret-off { to { opacity: 0; } }

/* Result: the founder's New Log screenshot goes in .device .screen (placeholder until supplied). */
.result { padding-block: clamp(2rem, 5svh, 4rem) clamp(2rem, 6svh, 4rem); }
.result-grid { display: grid; gap: 2.5rem; align-items: center; justify-items: center; text-align: center; }
.result h2 { font-size: clamp(2.5rem, 7vw, 6rem); }
.result .sub { margin-left: auto; margin-right: auto; color: var(--muted-dark); }
.result-device { margin: 0; }
.device {
  --pw: min(300px, 72vw); --b: calc(var(--pw) * .026);
  position: relative; width: var(--pw); height: calc(var(--pw) * 2.1072); flex: none;
  border-radius: calc(var(--pw) * .163); background: var(--bezel); box-shadow: inset 0 0 0 1px rgba(255,255,255,.22), 0 0 0 1px rgba(245,240,230,.10), 0 24px 60px rgba(0,0,0,.45);
}
.screen.pending { display: grid; place-content: center; justify-items: center; gap: .75rem; text-align: center; padding: 1rem;
  border: 1.5px dashed #5A534A; color: var(--muted-dark); font-size: .95rem; }
.screen.pending p { margin: 0; }
@media (min-width: 900px) {
  .moments { grid-template-columns: repeat(3, 1fr); gap: 2rem; }
  .result-grid { grid-template-columns: 1fr 1fr; text-align: left; justify-items: start; gap: 4rem; }
  .result-copy { justify-self: start; }
  .result .sub { margin-left: 0; }
  .result-device { justify-self: center; }
  .device { --pw: min(360px, 46svh); }
}

/* Progress: the same gauge language as the app and hero (track, yolk fill to 34 %, seated mascot). */
.gauge-art { display: block; width: min(100%, 44rem); max-height: 62svh; height: auto; margin: clamp(2rem, 6svh, 4rem) auto 0; overflow: visible; }
.g-track { fill: none; stroke: var(--gauge-track-light); stroke-width: 66; stroke-linecap: round; }
.g-fill { fill: none; stroke: var(--gauge-fill); stroke-width: 66; stroke-linecap: round; stroke-dasharray: 1 2; stroke-dashoffset: 0; }
.final .g-track { stroke: var(--gauge-track-dark); }
.final .art { width: min(100%, 26rem); margin: 0 auto clamp(1.5rem, 4svh, 2.5rem); }
.final .gauge-art { margin: 0 auto; }
.final .sub { color: var(--muted-dark); }
.cta { margin-top: 2.25rem; display: flex; flex-direction: column; align-items: center; }
.cta-btn { min-height: 64px; padding: 0 2.4rem; border-radius: 999px; font-size: 1.25rem; box-shadow: 0 10px 40px rgba(245,166,35,.25); }
.cta .msg, .cta .note { text-align: center; }

.site-footer { padding-block: 2.5rem 3rem; border-top: 1px solid #2C2824; }
.foot { display: flex; flex-wrap: wrap; align-items: center; gap: 1rem 2rem; justify-content: space-between; }
.foot nav { display: flex; gap: 1.5rem; }
.foot nav a { color: var(--muted-dark); font-weight: 600; min-height: 44px; display: inline-flex; align-items: center; text-underline-offset: 4px; }
.foot nav a:hover { color: var(--ink-dark); }
.foot p { margin: 0; color: var(--muted-dark); font-size: .9375rem; }
.site-footer .brand { color: var(--ink-dark); }

/* Gentle scroll reveals + method emphasis (view timelines; content is fully visible without them). */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .reveal { animation: rise both linear; animation-timeline: view(); animation-range: entry 0% entry 55%; }
    .progress .fill { animation: fill-in both linear; animation-timeline: view(); animation-range: entry 35% cover 45%; }
    .final .fill { animation: fill-in both linear; animation-timeline: view(); animation-range: entry 35% cover 45%; }
    @media (min-width: 900px) {
      .method { animation: spot both linear; animation-timeline: view(); animation-range: cover 5% cover 95%; }
    }
    @keyframes rise { from { opacity: 0; transform: translateY(28px); } to { opacity: 1; transform: none; } }
    @keyframes spot { 0%, 100% { opacity: .35; } 35%, 65% { opacity: 1; } }
    @keyframes fill-in { from { stroke-dashoffset: 1.05; } to { stroke-dashoffset: 0; } }
  }
}

/* Hero entrance, scene points, companion cast. */
h1 { font-size: clamp(3.4rem, 7vw, 7.5rem); }
.tagline { margin: .9rem 0 0; font: 700 clamp(1.4rem, 2.4vw, 2.2rem)/1.15 var(--rounded); letter-spacing: -.025em; color: var(--muted); }
.lede { margin-top: 1.1rem; max-width: 30rem; text-wrap: pretty; font-size: 1.125rem; }
@media (max-aspect-ratio: 1/1) { h1 { font-size: clamp(2.6rem, 14vw, 4rem); } .lede { font-size: 1rem; line-height: 1.4; margin-top: .8rem; } .tagline { margin-top: .5rem; } }
.points { list-style: none; margin: 1.1rem 0 0; padding: 0; display: grid; gap: .5rem; font-size: clamp(1.0625rem, 1.5cqw, 1.4rem); color: var(--ink); }
.frame-end .points { color: var(--muted-dark); }
/* Companion: a visible panel. The peeking mascot's body is cut flat and meets the panel's left edge, its hands curl over the edge;
   the waving mascot stands on the panel's top edge. */
.board { position: relative; width: min(100% - 2 * clamp(1.25rem, 6vw, 4rem), 54rem); margin: 0 auto; }
.panel { position: relative; padding: clamp(3.5rem, 9vw, 6.5rem) clamp(1.5rem, 6vw, 4.5rem); text-align: center; border-radius: 40px;
  background: var(--card); border: 1px solid #E6DDCB; box-shadow: 0 40px 70px -40px rgba(36,32,25,.35); }
.panel h2 { font-size: clamp(2rem, 5.5vw, 4.25rem); }
.board figure { position: absolute; margin: 0; z-index: 1; }
.board img { display: block; width: 100%; height: auto; }
.wave-fig { right: 7%; bottom: 100%; width: clamp(8rem, 24vw, 17rem); translate: 0 4.9%; }   /* soles end 4 % above the image bottom; +0.9 % so they press onto the panel edge */
.peek-fig { right: 100%; top: 18%; width: clamp(6.5rem, 20vw, 15rem); translate: 6.1% 0; }   /* the body is cut flat at 93.9 % of the artwork width: that edge sits exactly on the panel edge, the hands (to 98.7 %) curl over it */
@media (max-width: 1100px) { .board { margin-left: calc(clamp(1.25rem, 6vw, 4rem) + 19vw); margin-right: clamp(1.25rem, 6vw, 4rem); width: auto; } }
@media (max-width: 599px) { .board { margin-left: calc(clamp(1.25rem, 6vw, 4rem) + 26vw); width: auto; margin-right: clamp(1.25rem, 6vw, 4rem); }
  .peek-fig { width: 30vw; top: 22%; } .wave-fig { width: 38vw; right: 4%; } }

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .in { animation: rise both cubic-bezier(.2,.7,.2,1) .9s; }
    .tagline.in { animation-delay: .12s; } .lede.in { animation-delay: .24s; } .signup.in { animation-delay: .36s; }
    @keyframes rise { from { opacity: 0; transform: translateY(22px); } to { opacity: 1; transform: none; } }
    /* --- Section handoffs (all scroll-linked, so they run in reverse too) --- */
    /* 02 → 03: the pinned phone recedes through the release, as the logging scene rises beneath it. */
    .track .phone { animation-name: phone-rise, phone-away; animation-fill-mode: both, forwards; animation-timing-function: var(--ease), linear;
      animation-range: var(--r-phone) var(--r-end), calc(var(--travel) + var(--hold) * .7) calc(var(--travel) + var(--hold) + 45svh); }
    @keyframes phone-away { to { transform: translateY(-5cqh) scale(.86); opacity: .15; } }
    /* 03 → result: the three demos recede while the result phone comes forward. */
    .moments { animation: sink both linear; animation-timeline: view(); animation-range: exit 5% exit 85%; }
    @keyframes sink { to { transform: scale(.93) translateY(-5svh); opacity: .2; } }
    .moment:nth-child(2) { animation-range: entry 8% entry 63%; } .moment:nth-child(3) { animation-range: entry 16% entry 71%; }
    .result-device { animation: pop both linear, away forwards linear; animation-timeline: view(), view(); animation-range: entry 0% cover 38%, exit 5% exit 85%; }
    .result-device::before { content: ""; position: absolute; inset: -18% -45%; z-index: -1; pointer-events: none;
      background: radial-gradient(closest-side, rgba(245,166,35,.16), rgba(245,166,35,0));
      animation: fade-in both linear; animation-timeline: view(); animation-range: entry 10% cover 40%; }
    .result-device { position: relative; }
    @keyframes pop { from { opacity: 0; transform: translateY(14svh) scale(.84); } to { opacity: 1; transform: none; } }
    @keyframes away { to { transform: translateY(-6svh) scale(.9); opacity: 0; } }
    @keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }
    /* result → 04: the gauge emerges as the light canvas arrives; 04 → 05: it sinks as the panel rises. */
    .progress .art { animation: emerge both linear; animation-timeline: view(); animation-range: entry 0% cover 40%; }
    @keyframes emerge { from { opacity: 0; transform: translateY(10svh) scale(.82); } to { opacity: 1; transform: none; } }
    .recede { animation: recede both linear; animation-timeline: view(); animation-range: exit 0% exit 95%; transform-origin: 50% 100%; }
    @keyframes recede { to { transform: scale(.84) translateY(4svh); opacity: .2; } }
    .board { animation: board-in both linear; animation-timeline: view(); animation-range: entry 0% entry 70%; }
    @keyframes board-in { from { opacity: 0; transform: translateY(12svh) scale(.95); } to { opacity: 1; transform: none; } }
    .peek-fig { animation: emerge-x both linear; animation-timeline: view(); animation-range: entry 35% cover 30%; }
    .wave-fig { animation: emerge-y both linear; animation-timeline: view(); animation-range: entry 45% cover 35%; }
    @keyframes emerge-x { from { opacity: 0; transform: translateX(-12%); } to { opacity: 1; transform: none; } }
    @keyframes emerge-y { from { opacity: 0; transform: translateY(12%); } to { opacity: 1; transform: none; } }
    /* 05 → 06: the light scene quietens as the dark finale arrives as one sequence. */
    .board { animation: board-in both linear, board-out forwards linear; animation-timeline: view(), view(); animation-range: entry 0% entry 70%, exit 10% exit 95%; }
    @keyframes board-out { to { transform: scale(.94); opacity: 0; } }
    .final h2.reveal { animation-range: entry 10% entry 65%; } .final .sub.reveal { animation-range: entry 20% entry 75%; } .final .cta.reveal { animation-range: entry 30% entry 85%; }
    .final .art.reveal { animation: emerge both linear; animation-timeline: view(); animation-range: entry 0% cover 35%; }
  }
}
@media (max-width: 899px) { .tile { aspect-ratio: 16 / 10; } }
@media (max-aspect-ratio: 1/1) and (max-height: 700px) { .lede { font-size: .9375rem; line-height: 1.35; } .avail { display: none; } h1 { font-size: clamp(2.4rem, 12vw, 3.2rem); } }
.result .device { height: calc(var(--pw) * 2.1131); }   /* the New Log capture is 1206×2622 (screen aspect .4599), shown uncropped */
.result, .companion, .final { overflow-x: clip; }

/* ---- Seamless section changes (replaces the gradient bands) ----
   Fixed full-viewport colour layers cross-fade in step with the scroll, so the whole viewport changes colour at once (no spatial band).
   The outgoing scene recedes first, the colour turns, then the incoming scene enters. Everything is a function of scroll position,
   so it plays identically in reverse. Unsupported browsers / reduced motion keep the short static bands above. */
@supports (timeline-scope: --a) and (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) and (min-height: 521px) {
    body { timeline-scope: --to-light, --to-dark; }
    .bg i { position: fixed; inset: 0; z-index: -1; pointer-events: none; opacity: 0; animation: bg-in both linear; }
    .bg .b1 { background: var(--canvas-dark); animation-timeline: scroll(root block); animation-range: calc(var(--travel) * .7) calc(var(--travel) * .76); }   /* only after the hero stage's own canvas is fully opaque, so the approved hero fade is untouched */
    .bg .b2 { background: var(--canvas); animation-timeline: --to-light; animation-range: entry 24% entry 58%; }
    .bg .b3 { background: var(--canvas-dark); animation-timeline: --to-dark; animation-range: entry 24% entry 58%; }
    .logging, .result, .progress, .companion, .final { background: transparent; }
    .progress, .final { position: relative; padding-top: 4svh; }
    .result { padding-bottom: 12svh; }       /* dwell: the scene stays readable before it recedes */
    .companion { padding-bottom: 34svh; }
    .seam { position: absolute; left: 0; top: 0; width: 1px; height: 60svh; pointer-events: none; }
    .progress .seam { view-timeline: --to-light block; }
    .final .seam { view-timeline: --to-dark block; }
    /* outgoing scenes recede in the first part of the change */
    .result-copy { animation: seam-out both linear; animation-timeline: --to-light; animation-range: entry 8% entry 35%; }
    .result-device { animation-timeline: view(), --to-light; animation-range: entry 0% cover 38%, entry 8% entry 35%; }
    .board { animation-timeline: view(), --to-dark; animation-range: entry 0% entry 70%, entry 8% entry 35%; }
    /* incoming scenes enter once the colour has mostly turned, so text is never set on a half-tone */
    section.progress #prog-h.reveal { animation-timeline: --to-light; animation-range: entry 30% entry 52%; }
    section.progress .sub.reveal { animation-timeline: --to-light; animation-range: entry 34% entry 56%; }
    section.progress .art.reveal { animation-timeline: --to-light; animation-range: entry 32% entry 60%; }
    section.final .art.reveal { animation-timeline: --to-dark; animation-range: entry 28% entry 56%; }
    section.final #cta-h.reveal { animation-timeline: --to-dark; animation-range: entry 34% entry 56%; }
    section.final .sub.reveal { animation-timeline: --to-dark; animation-range: entry 38% entry 60%; }
    section.final .cta.reveal { animation-timeline: --to-dark; animation-range: entry 42% entry 64%; }
    @keyframes bg-in { from { opacity: 0; } to { opacity: 1; } }
    @keyframes seam-out { to { opacity: 0; transform: translateY(-4svh) scale(.96); } }
  }
}

/* Production: email sign-up is unavailable (no backend yet). A disabled, plainly-labelled control; no form, no input. */
.signup .soon { width: 100%; }
button.soon:disabled { cursor: not-allowed; background: transparent; color: var(--muted); border: 1.5px solid var(--muted); box-shadow: none; }
button.soon:disabled:active { transform: none; }
.cta-btn.soon { max-width: 100%; padding: 0 1.5rem; font-size: 1.125rem; }
