/* ============================================================================
   Public marketing page for ghw.care — styles.

   Extracted verbatim from the two inline <style> blocks that used to live in
   landing.html. Split out so the contact card's animation had somewhere to go
   that was not a 440-line inline block; nothing here changed in the move.

   Loaded AFTER console.css, which is where the design tokens come from. The
   :root block below overrides some of them, so the order is load-bearing.
   ============================================================================ */

/* ---------------------------------------------------------------------------
   Public marketing page for ghw.care.

   Company = Geometry Neuroscience. Product = Cuneate. (No "ReThrive" anywhere —
   that name is retired.) Tokens come from console.css so the site, the clinical
   console and the iOS app stay one visual system. The site takes the app's own Mist palette
   (AppPalettes.mist in GeometryNeuroScienceApp.swift): a light hero on #DAE6E2, bands that step
   down through #E8EFEC / #F6F9F8 / #FCFDFD instead of being drawn with hairlines or shadows, and
   the app's Deep water for the dark bands. No warm beige, no warm greys, no all-caps eyebrows (the
   app's own CLAUDE.md calls both the stock look of generated UI). Text is ink #0F1F1D and sub
   #4C5D5A; #0E767A is a FILL colour, text and buttons use #0A585B.
--------------------------------------------------------------------------- */
:root{
  --mist-deep:#DAE6E2; --mist:#E8EFEC; --surf:#F6F9F8; --raised:#FCFDFD; --badge:#D7E7E3;
  --ground:#E8EFEC; --card:#FCFDFD; --line:#D3DEDA;
  --ink:#0F1F1D; --sub:#4C5D5A; --faint:#4C5D5A;
  --accent:#0E767A; --accent-ink:#0A585B; --accent-soft:#D7E7E3;
  /* Deep water, the app's dark palette. --night-accent is for text and buttons on it only. */
  --night:#07191E; --night-2:#0E252B; --night-line:#16313A; --night-sub:#9AB2B0; --night-accent:#17CED4;
  --shadow-s:0 1px 2px rgba(15,31,29,.05), 0 2px 8px -2px rgba(15,31,29,.07);
  --shadow-m:0 2px 4px rgba(15,31,29,.05), 0 14px 30px -14px rgba(15,31,29,.20);
  --shadow-l:0 26px 60px -20px rgba(15,31,29,.40), 0 4px 12px rgba(15,31,29,.10);
}
/* Do NOT put overflow-x:hidden on <body> — it makes body the scroll container,
   which breaks position:sticky on the nav and stops the IntersectionObserver
   reveals from ever firing. Horizontal overflow is contained per-section instead
   (see .hero{overflow:hidden}). */
html{scroll-behavior:smooth;overflow-x:hidden}
body{background:var(--surf);-webkit-font-smoothing:antialiased}
/* height:auto is load-bearing — every <img> carries width/height attributes for
   CLS, and without this the attribute height wins and the screenshots stretch. */
img{max-width:100%;height:auto}
.w{max-width:1140px;margin:0 auto;padding:0 24px}
.w-narrow{max-width:840px;margin:0 auto;padding:0 24px}

/* ---------- type ---------- */
.eyebrow-c{font-size:13px;color:var(--accent-ink);font-weight:600;display:block;margin-bottom:14px}
.eyebrow-c.ctr{text-align:center}
h2.sec{font-size:clamp(25px,3.1vw,34px);letter-spacing:-.024em;margin:0 0 14px;line-height:1.16;
       text-wrap:balance}
h2.sec.ctr{text-align:center;margin-left:auto;margin-right:auto;max-width:26ch}
p.sec-sub{color:var(--sub);font-size:16px;line-height:1.68;max-width:64ch;margin:0 0 44px;
          text-wrap:pretty}
p.sec-sub.ctr{text-align:center;margin-left:auto;margin-right:auto}

/* ---------- buttons ---------- */
.btn{display:inline-flex;align-items:center;gap:8px;padding:13px 22px;border-radius:10px;
     font-size:14.5px;font-weight:600;text-decoration:none;border:1px solid transparent;
     transition:transform .15s,background .15s,border-color .15s,box-shadow .15s;white-space:nowrap}
.btn-sm{padding:8px 15px;font-size:13px;border-radius:8px}
.btn-p{background:var(--accent-ink);color:#fff;box-shadow:var(--shadow-s)}
.btn-p:hover{background:#08494C;transform:translateY(-1px);box-shadow:var(--shadow-m)}
.btn-q{background:var(--card);color:var(--ink);border-color:var(--line)}
.btn-q:hover{border-color:var(--accent);color:var(--accent-ink);transform:translateY(-1px)}
.btn-i{background:rgba(255,255,255,.08);color:#fff;border-color:rgba(255,255,255,.24)}
.btn-i:hover{background:rgba(255,255,255,.16);transform:translateY(-1px)}
.btn-w{background:var(--night-accent);color:#04161A}
.btn-w:hover{transform:translateY(-1px);box-shadow:var(--shadow-m)}

/* ---------- nav ---------- */
/* The nav is Mist from the first pixel: it sits on the light hero (#DAE6E2, the same colour, so
   there is no seam) and, once the hero has cleared, picks up a translucent blur so the page
   scrolls under it. landing.js only toggles .stuck; nothing here changes colour scheme. */
nav.top{position:sticky;top:0;z-index:50;background:var(--mist-deep);
        transition:background .25s,box-shadow .25s}
/* Horizontal padding matters here and was missing: `.w` sets `0 24px`, and this rule's own
   `12px 0` replaced it outright, so the nav ran edge to edge while every other band on the
   page was inset by 24px. On a desktop that showed as a wordmark sitting left of the content
   it labels; on a phone the menu button ended up flush against the screen edge with nothing
   to breathe into. Keep both values whenever this padding is touched. */
nav.top .inner{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:12px 24px}
.brandlock{display:flex;align-items:center;gap:10px;text-decoration:none;color:var(--ink)}
.brandlock img{width:30px;height:30px;border-radius:8px;flex:none;box-shadow:var(--shadow-s)}
.brandlock .bn{line-height:1.15}
.brandlock .bn b{display:block;font-size:14.5px;letter-spacing:-.01em;font-weight:650}
.brandlock .bn span{display:block;font-size:10.5px;color:var(--faint);letter-spacing:.03em}
nav.top .links{display:flex;align-items:center;gap:22px}
nav.top .links a{text-decoration:none;font-weight:500;font-size:13.5px;color:var(--sub)}
nav.top .links a:hover{color:var(--accent-ink)}
nav.top .btn-q{background:var(--raised);color:var(--ink);border-color:transparent;
               box-shadow:0 0 0 1px rgba(15,31,29,.12)}
nav.top .btn-q:hover{background:var(--raised);color:var(--accent-ink);box-shadow:0 0 0 1px var(--accent-ink)}

/* clear of the hero */
nav.top.stuck{background:rgba(246,249,248,.88);
        backdrop-filter:saturate(180%) blur(14px);-webkit-backdrop-filter:saturate(180%) blur(14px);
        box-shadow:0 6px 16px -14px rgba(15,31,29,.22)}
@media(max-width:900px){nav.top .links a:not(.btn){display:none}}

/* ---------- sections ---------- */
/* margin-top:0 resets console.css's `section{margin-top:22px}`, which would
   otherwise leave a seam between every tinted/dark band. 64px, not 88 (2026-10-21): two bands
   meeting put ~175px of empty ground between their content, and the pages read as all scroll. */
section{margin-top:0;padding:64px 0;scroll-margin-top:70px}
/* Retired section ids live on as empty anchors so old links, bookmarks and the hero CTA keep
   landing somewhere sensible. Same offset as a section so the target clears the sticky nav. */
.anchor{display:block;height:0;scroll-margin-top:70px}

section.tint{background:var(--ground)}
section.night{background:var(--night);color:#fff}
section.night h2.sec{color:#fff}
section.night p.sec-sub{color:var(--night-sub)}
section.night .eyebrow-c{color:var(--night-accent)}

/* ---------- cards ---------- */
.grid-3{display:grid;grid-template-columns:repeat(3,1fr);gap:18px}
.grid-2{display:grid;grid-template-columns:repeat(2,1fr);gap:18px}
.grid-4{display:grid;grid-template-columns:repeat(4,1fr);gap:16px}
.tile{background:var(--card);border:1px solid var(--line);border-radius:14px;padding:26px 24px;
      transition:transform .28s cubic-bezier(.22,1,.36,1),box-shadow .18s,border-color .18s}
.tile:hover{transform:translateY(-3px);box-shadow:var(--shadow-m);border-color:#BFD0CB}
.tile h3{font-size:16px;margin:0 0 8px;letter-spacing:-.012em}
.tile p{margin:0;color:var(--sub);font-size:14px;line-height:1.68}
.tile .ic{width:38px;height:38px;border-radius:10px;background:var(--accent-soft);color:var(--accent-ink);
          display:flex;align-items:center;justify-content:center;margin-bottom:15px;flex:none}
.tile .ic svg{width:19px;height:19px;stroke:currentColor;fill:none;stroke-width:1.7;
              stroke-linecap:round;stroke-linejoin:round}
.tile .n{width:32px;height:32px;border-radius:9px;background:var(--badge);color:var(--accent-ink);
         display:flex;align-items:center;justify-content:center;font-weight:700;font-size:13.5px;margin-bottom:15px}

/* ---------- device frame ---------- */
.device{position:relative;border-radius:32px;background:#101F22;padding:7px;
        box-shadow:var(--shadow-l);flex:none}
.device img{display:block;width:100%;height:auto;border-radius:26px}
.device.lift{transition:transform .3s}
.device.lift:hover{transform:translateY(-6px)}

/* ---------- reveal ---------- */
/* The reveal. `ease` on both properties was serviceable and slightly mechanical; this curve
   decelerates late, which reads as something settling into place rather than sliding to a
   stop. The scale is deliberately tiny — at .985 you feel it and do not see it. Keep every
   motion value in step with the reduced-motion block further down. */
.rv{opacity:0;transform:translateY(20px) scale(.985);
    transition:opacity .72s cubic-bezier(.22,1,.36,1),transform .72s cubic-bezier(.22,1,.36,1)}
.rv.in{opacity:1;transform:translateY(0) scale(1)}
@media(prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  .rv{opacity:1;transform:none;transition:none}
  .tile:hover,.device.lift:hover,.btn{transition:transform .22s cubic-bezier(.22,1,.36,1),box-shadow .22s,background .22s,border-color .22s}
.btn:hover{transform:translateY(-2px)}
.btn:active{transform:translateY(0);transition-duration:.06s}
}

/* ---------- hero ----------
   Light by design (2026-10-20): the app is Mist, and the hero now is too, one step deeper
   (#DAE6E2) than the app's own page so the phone's screen reads lighter than the ground it
   floats on. Depth is background steps, not shadows: only the phone casts one. The dark comes
   back at the bottom, in the proof strip, and in #why and the close. The nav above is the same
   colour, so there is no seam. */
.hero{position:relative;background:var(--mist-deep);color:var(--ink);overflow:hidden}
.hero .inner{position:relative;z-index:2;display:grid;grid-template-columns:1.05fr .95fr;
             gap:56px;align-items:center;padding:72px 24px 84px}

/* Status badge: a tinted sentence-case pill. The pulsing green dot that used to sit here was
   removed on 2026-09-14 (FINDINGS F-01): it rendered a claim about a business stage as a live
   system indicator. Text only — if a dot ever comes back it must not animate. The hairline ring
   is there because #D7E7E3 is a hair away from the hero's own #DAE6E2. */
.hero-live{display:inline-flex;align-items:center;padding:6px 13px;border-radius:999px;
           background:var(--badge);box-shadow:inset 0 0 0 1px rgba(10,88,91,.16);margin-bottom:24px}
.hero-live span{font-size:13.5px;font-weight:600;color:var(--accent-ink)}

.hero h1{font-size:clamp(34px,4.6vw,56px);font-weight:650;line-height:1.04;letter-spacing:-.035em;margin:0 0 24px;
         max-width:15ch;text-wrap:balance;color:var(--ink)}
.hero .lede{font-size:18px;line-height:1.65;color:var(--sub);max-width:50ch;margin:0 0 34px;
            text-wrap:pretty}
.hero .lede b{color:var(--ink);font-weight:600}
.hero .cta{display:flex;gap:26px;flex-wrap:wrap;align-items:center}
.hero .cta .btn svg,.cta-link svg{width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:2;
                    stroke-linecap:round;stroke-linejoin:round}
/* The second action is a text link, not a second button: one thing is being asked for. */
.cta-link{display:inline-flex;align-items:center;gap:8px;color:var(--accent-ink);font-size:15px;font-weight:600;
          text-decoration:underline;text-underline-offset:4px;text-decoration-thickness:1.5px}
.cta-link:hover{color:#08494C}
.cta-link svg{transition:transform .22s cubic-bezier(.22,1,.36,1)}
.cta-link:hover svg{transform:translateX(3px)}

/* "Join the movement" — the hero's primary action. Bigger than every other button on the site
   on purpose: it is the one thing this page asks for. On hover, rings pulse out of it (a new
   ring every 0.9s, each fading over 2.7s) and a teal sheen crosses its face on a 45° diagonal,
   eased in and out so it lingers at the edges and moves fastest through the middle.
   landing.js adds the hover sound.

   Rings and sheen are spans, not pseudo-elements: the ring needs three staggered copies, and
   the sheen needs its own clip (overflow:hidden on .join-face) while the rings must spill
   outside the button. Only transform and opacity animate, and every animation here is
   switched off in the reduced-motion block further down. */
.hero .cta .btn-join{position:relative;isolation:isolate;gap:12px;padding:20px 34px;min-height:66px;
  border-radius:14px;font-size:18px;font-weight:650;letter-spacing:-.012em;
  transition:transform .22s cubic-bezier(.22,1,.36,1),box-shadow .22s}
.hero .cta .btn-join svg{width:20px;height:20px;stroke-width:2.2;
  transition:transform .3s cubic-bezier(.22,1,.36,1)}
.hero .cta .btn-join:hover,.hero .cta .btn-join:focus-visible{transform:translateY(-2px);
  box-shadow:0 0 0 6px rgba(14,118,122,.16),0 22px 44px -14px rgba(10,88,91,.7)}
.hero .cta .btn-join:focus-visible{outline:2px solid var(--accent-ink);outline-offset:5px}
.hero .cta .btn-join:hover svg,.hero .cta .btn-join:focus-visible svg{transform:translateX(4px)}
.btn-join .join-ring{position:absolute;inset:0;border-radius:inherit;border:1.5px solid var(--accent);
  opacity:0;z-index:-2;pointer-events:none}
.btn-join .join-face{position:absolute;inset:0;border-radius:inherit;overflow:hidden;z-index:-1;
  pointer-events:none}
.btn-join .join-face::before{content:"";position:absolute;inset:0;transform:translateX(-110%);
  background:linear-gradient(135deg,transparent 30%,rgba(23,206,212,.38) 50%,transparent 70%)}
.btn-join:hover .join-ring,.btn-join:focus-visible .join-ring{
  animation:join-sonar 2.7s cubic-bezier(.2,.6,.3,1) infinite}
.btn-join:hover .join-ring.r2,.btn-join:focus-visible .join-ring.r2{animation-delay:.9s}
.btn-join:hover .join-ring.r3,.btn-join:focus-visible .join-ring.r3{animation-delay:1.8s}
.btn-join:hover .join-face::before,.btn-join:focus-visible .join-face::before{
  animation:join-sheen 1.2s cubic-bezier(.65,0,.35,1) both}
@keyframes join-sonar{0%{opacity:.85;transform:scale(1)}100%{opacity:0;transform:scale(1.16,1.8)}}
@keyframes join-sheen{from{transform:translateX(-110%)}to{transform:translateX(110%)}}

/* ---------- hero fits the window (desktop only) ----------
   Nav + hero + the proof strip are the first screen, and the strip was cut off on any window
   under ~930px, its labels below the fold. The hero is now at least the window minus the 63px
   nav, capped at 1000px so a tall monitor does not stretch it into a void. min-height, never
   height: on a window too short for the content the hero keeps its natural size and the strip
   moves below the fold, rather than the strip overlapping the hero. The vertical padding
   shrinks with the window, and two height steps tighten the headline and shrink the phone
   (--k, the one size knob), moving the chip with it, keeping its right edge ~36px inside the phone (see .hero-console).
   The .hero prefix is load-bearing: these sit above the base stage/phone/chip rules. */
@media(min-width:961px){
  .hero{display:flex;flex-direction:column;min-height:min(calc(100vh - 63px),1000px);
        min-height:min(calc(100svh - 63px),1000px)}
  .hero .inner{flex:1;width:100%;box-sizing:border-box;
               padding-top:clamp(28px,6svh,72px);padding-bottom:clamp(32px,7svh,84px)}
  /* The page headers on /how-it-works, /for-clinics and /company share .hero for its ground and
     were stretched to a full window by the rule above: an eyebrow, a title and one line on a
     1000px band. Only the home hero has a proof strip to bring above the fold. */
  .hero.hero-slim{min-height:0}
}
@media(min-width:961px) and (max-height:880px){
  .hero .hero-stage{min-height:530px}
  .hero .hero-phone{--k:.5}
  .hero .hero-console{right:202px}
  .hero .hero-live{margin-bottom:18px}
  .hero h1{font-size:min(4.6vw,48px);margin-bottom:18px}
  .hero .lede{margin-bottom:26px}
}
@media(min-width:961px) and (max-height:820px){
  .hero .hero-stage{min-height:472px}
  .hero .hero-phone{--k:.44}
  .hero .hero-console{right:176px}
  .hero h1{font-size:min(4.6vw,44px)}
  .hero .lede{font-size:17px}
}

/* ---------- hero stage: phone + the console card it feeds ---------- */
.hero-stage{position:relative;width:100%;max-width:520px;margin:0 auto;min-height:582px}
/* The clinician chip (refactoring-ui pass, 2026-10-20): structure A (the phone leads, the
   dashboard becomes one finding), density 2 with 1's wording, surface B (top-lit bevel + brand
   teal), plus the teal stripe the app's own clinician-note card carries on the screen beside it.
   It crosses the phone's left bezel at the lower third, in FRONT of the phone, like a
   notification sliding out of it: right:226px puts its right edge ~36px inside the 262px phone
   box, which is ~25px onto the glass at the phone's 17deg turn, over the left edge of the streak
   tile and the empty "Scroll for more" band, never the dial or the Up next card. Light from above: inset top highlight, then a tight
   contact shadow and a soft ambient one. */
.hero-console{position:absolute;right:226px;top:67%;z-index:3;width:min(280px,calc(100% - 210px));box-sizing:border-box;
              padding:16px 16px 14px 20px;border-radius:16px;overflow:hidden;color:var(--ink);
              background:linear-gradient(#FFFFFF,#F6F9F8);
              box-shadow:inset 0 1px 0 #fff,0 1px 2px rgba(15,31,29,.22),0 18px 36px -12px rgba(15,31,29,.45);
              transition:opacity .45s cubic-bezier(.22,1,.36,1),transform .55s cubic-bezier(.22,1,.36,1)}
/* Waiting for the phone's next result: tucked a little back toward the phone and hidden. Only
   landing.js adds this, so with JS off the chip is simply there. */
.hero-console.is-waiting{opacity:0;transform:translateX(24px) scale(.96)}
.hc-stripe{position:absolute;left:0;top:14px;bottom:14px;width:4px;border-radius:0 2px 2px 0;background:var(--accent)}
.hc-eyebrow{display:flex;align-items:center;gap:6px;font-size:12px;font-weight:600;color:var(--accent-ink)}
.hc-tag{padding:1px 7px;border-radius:9px;background:var(--accent-soft);color:var(--accent-ink);
        font-size:11px;font-weight:600}
.hc-find{display:block;margin-top:8px;font-size:15px;font-weight:600;line-height:1.35;letter-spacing:-.01em}
.hc-bot{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:10px}
.hc-token{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;color:var(--sub)}
.hc-spark{display:block;flex:none;width:64px;height:22px}
.hc-spark polyline{fill:none;stroke:var(--accent);stroke-width:1.8;stroke-linejoin:round;stroke-linecap:round}
.hc-spark circle{fill:var(--accent)}
.hc-spark rect{fill:var(--badge)}

/* ---------- hero phone: the drawn 3D device ----------
   Ported from design/mockups/hero-phone-3d.html (light Mist only). Everything is namespaced
   `hp-` because the prototype's class names (.card, .bar, .nav, .tabs …) are generic enough
   to collide with the rest of this file. The wrapper roles are documented in landing.html.

   Size is two numbers: --k scales the 440×956-point screen (the size of the app's store screenshots), --bez is the bezel. The frame's
   box is computed from them, so the mobile rule below changes --k and nothing else. */
.hero-phone{--k:.5547;--bez:9px;--pw:calc(440px*var(--k) + 2*var(--bez));--ph:calc(956px*var(--k) + 2*var(--bez));
            position:absolute;top:0;right:0;z-index:2;width:var(--pw);height:var(--ph)}
.hp-view{position:relative;width:100%;height:100%;perspective:1700px;perspective-origin:50% 40%}
.hp-exit,.hp-enter,.hp-float,.hp-phone{position:absolute;inset:0;transform-style:preserve-3d}
/* The scroll exit tips the phone back about its foot, so it reads as laid down, not flung. */
.hp-exit{transform-origin:50% 100%}
/* The resting pose. Everything that moves is layered on top of this, never instead of it. */
.hp-phone{transform:rotateY(17deg) rotateX(5deg) rotateZ(-1.2deg)}
/* Thickness: the frame repeated a pixel at a time behind the face. Handles the rounded
   corners for free, which a single rotated side panel cannot. */
.hp-slab{position:absolute;inset:0;border-radius:46px;
         background:linear-gradient(100deg,#55666b 0%,#2a393d 18%,#1a272a 60%,#3b4b50 100%)}
.hp-slab:nth-child(1){transform:translateZ(-1px)}.hp-slab:nth-child(2){transform:translateZ(-2px)}
.hp-slab:nth-child(3){transform:translateZ(-3px)}.hp-slab:nth-child(4){transform:translateZ(-4px)}
.hp-slab:nth-child(5){transform:translateZ(-5px)}.hp-slab:nth-child(6){transform:translateZ(-6px)}
.hp-slab:nth-child(7){transform:translateZ(-7px)}.hp-slab:nth-child(8){transform:translateZ(-8px)}
.hp-slab:nth-child(9){transform:translateZ(-9px)}.hp-slab:nth-child(10){transform:translateZ(-10px)}
.hp-face{position:absolute;inset:0;border-radius:46px;padding:var(--bez);transform:translateZ(1px);
         background:#0b1416;box-shadow:inset 0 0 0 1.5px #4d5f64,inset 0 0 0 3px #0b1416}
.hp-glass{position:relative;width:100%;height:100%;border-radius:37px;overflow:hidden;background:var(--page)}
.hp-glass::after{content:"";position:absolute;inset:0;pointer-events:none;z-index:9;
  background:linear-gradient(118deg,rgba(255,255,255,.22) 0%,rgba(255,255,255,.05) 28%,transparent 46%)}
.hp-side{position:absolute;left:-3px;width:4px;border-radius:2px;background:#3e4f54;transform:translateZ(-4px)}
.hp-side-1{top:112px;height:26px}.hp-side-2{top:156px;height:46px}
.hp-shadow{position:absolute;left:6%;right:4%;top:calc(100% - 8px);height:30px;border-radius:50%;
           background:rgba(15,31,29,.34);filter:blur(16px)}

/* ---------- the screen, in iPhone points (light Mist, AppPalettes.mist) ---------- */
.hp-phone{--page:#E8EFEC;--surf:#F6F9F8;--raised:#FCFDFD;--ink:#0F1F1D;--sub:#4C5D5A;--onfill:#fff;
          --acc:#0A585B;--acc2:#0E767A;--good:#199B6C;--warn:#BA7B0F;--track:#D3DEDA;--bar:#C6D3CF}
.hp-scr{position:absolute;left:0;top:0;width:440px;height:956px;transform:scale(var(--k));transform-origin:0 0;
        color:var(--ink);font-family:-apple-system,BlinkMacSystemFont,"SF Pro Text","Inter",system-ui,sans-serif;
        font-size:15px;line-height:1.3;letter-spacing:-.01em;text-align:left}
.hp-scr b{font-weight:600}
.hp-status{position:absolute;inset:0 0 auto;height:60px;z-index:8;font-weight:600;font-size:17px}
.hp-time{position:absolute;left:60px;top:21px;line-height:22px}
.hp-island{position:absolute;left:50%;top:14.2px;width:125px;height:36px;margin-left:-62.5px;border-radius:18px;background:#000}
.hp-status .hp-x{color:var(--ink)}
.hp-bat{position:absolute;left:368.7px;top:26.4px;width:28px;height:12.5px;border-radius:4px;box-shadow:inset 0 0 0 1px rgba(15,31,29,.35)}
.hp-bat::before{content:"";position:absolute;inset:2px;border-radius:2.5px;background:#34C759}
.hp-bat::after{content:"";position:absolute;right:-2.6px;top:4px;width:1.6px;height:4.5px;border-radius:0 1px 1px 0;background:rgba(15,31,29,.4)}
.hp-bat i{position:absolute;left:10px;top:2px;width:8px;height:8.5px;z-index:1;background:#fff;
          clip-path:polygon(60% 0,0 58%,42% 58%,30% 100%,100% 38%,55% 38%)}
.hp-scene{position:absolute;inset:0;background:var(--page);transform:translateX(100%);opacity:0}
/* The inner screens were drawn on the older 393×852 screen. They sit in a page of that size,
   scaled once to the 440-point screen, so they look as they did and nothing in them moved. */
.hp-pg{position:absolute;left:0;top:0;width:393px;height:852px;padding-top:54px;box-sizing:border-box;
       transform:scale(1.1196);transform-origin:0 0}
/* An SF Symbol: the app's own art, rendered once to a small PNG (img/hero/) and used as a mask,
   so it takes whatever colour the palette gives it. Sized and placed inline, in screen points. */
.hp-x{position:absolute;display:block;background:currentColor;
      -webkit-mask:var(--ms) center/100% 100% no-repeat;mask:var(--ms) center/100% 100% no-repeat}
.hp-nav .hp-circ .hp-x{position:static;width:8.8px;height:15px;color:var(--acc)}
.hp-scene.is-on{transform:none;opacity:1}
.hp-card{background:linear-gradient(var(--raised),var(--surf));border-radius:20px;
         box-shadow:0 1px 2px rgba(0,0,0,.05),0 6px 18px -10px rgba(0,0,0,.18)}
.hp-bar{display:block;height:9px;border-radius:5px;background:var(--bar)}
.hp-bar.w40{width:40%}.hp-bar.w46{width:46%}.hp-bar.w52{width:52%}.hp-bar.w54{width:54%}.hp-bar.w62{width:62%}
.hp-bar.w64{width:64%}.hp-bar.w70{width:70%}.hp-bar.w74{width:74%}.hp-bar.w76{width:76%}.hp-bar.w84{width:84%}
.hp-bar.w88{width:88%}.hp-bar.w90{width:90%}.hp-bar.w92{width:92%}.hp-bar.w94{width:94%}.hp-bar.w96{width:96%}
.hp-sm{font-size:12.5px;color:var(--sub);font-weight:500}
.hp-pill{background:var(--acc);color:var(--onfill);font-weight:650;border-radius:22px;padding:10px 20px;font-size:16px}
.hp-circ{width:34px;height:34px;border-radius:50%;background:var(--surf);display:grid;place-items:center;
         box-shadow:0 1px 3px rgba(0,0,0,.1)}

/* home: the app's Home (00_home_week_dial_light.png), every piece placed in screen points.
   Symbols are masks (img/hero/, rendered from SF Symbols and the app's own assets; the
   per-symbol size is the art's size at the app's point size). Done fills, the outlined "next"
   slot and the icons' ink-to-white swap are opacity only, toggled by landing.js. */
.hp-hello{position:absolute;left:76.5px;top:72.5px;font-size:17px;line-height:22px}
.hp-scene[data-s=home] .hp-circ{position:absolute;width:44px;height:44px;background:var(--raised);
  box-shadow:0 1px 3px rgba(0,0,0,.1),0 6px 14px -8px rgba(0,0,0,.2)}
.hp-note{position:absolute;left:17px;top:116.5px;width:406px;height:91px;border-radius:24px}
.hp-stripe{position:absolute;left:-1px;top:15.8px;width:4px;height:59px;border-radius:2px;background:var(--acc2)}
.hp-av{position:absolute;left:12.7px;top:13.8px;width:42px;height:42px;border-radius:50%;background:#D3E6E6;
       color:var(--acc);font-weight:600;font-size:17px;display:grid;place-items:center}
.hp-av i{position:absolute;left:31.2px;top:1.2px;width:9.5px;height:9.5px;border-radius:50%;background:var(--acc2);
         box-shadow:0 0 0 2px var(--raised)}
.hp-who{position:absolute;left:67.6px;top:12.5px;font-size:16.5px;line-height:22px;font-weight:600}
.hp-ago{position:absolute;left:183px;top:12.5px;font-size:15px;line-height:22px;color:var(--sub)}
.hp-new{position:absolute;left:351.3px;top:15px;width:41px;height:19.8px;border-radius:10px;background:var(--acc);
        color:var(--onfill);font-size:12.5px;font-weight:700;line-height:19.8px;text-align:center}
.hp-scene[data-s=home] .hp-bar{position:absolute;height:10px}
.hp-dial{position:absolute;left:0;top:0;width:440px;height:600px;overflow:visible}
.hp-dial path,.hp-dial circle{fill:none;stroke-linecap:round}
.hp-groove{stroke:#DBE3E0;stroke-width:30}
.hp-hull{stroke:#F5F8F7;stroke-width:27}
.hp-pip{stroke:rgba(76,93,90,.22);stroke-width:4}
.hp-pip.on{stroke:var(--acc2)}
.hp-nx{stroke:var(--acc);stroke-width:29;opacity:0}
.hp-nx-in{stroke:#F5F8F7;stroke-width:25;opacity:0}
.hp-nx.on,.hp-nx-in.on{opacity:1}
.hp-seg{stroke-width:27;opacity:0;filter:drop-shadow(0 1.5px 2px rgba(0,0,0,.2))}
.hp-seg.done{opacity:1}
.hp-ico-o,.hp-ico-n,.hp-ico-w{color:var(--sub)}
.hp-ico-o[data-i="1"]{color:var(--acc)}
.hp-ico-n{color:var(--acc);opacity:0}
.hp-ico-n.on{opacity:1}
.hp-ico-w{color:#fff;opacity:0}
.hp-ico-w.done{opacity:1}
.hp-ico-o.done,.hp-ico-n.done{opacity:0}
.hp-seg,.hp-ico-o,.hp-ico-n,.hp-ico-w,.hp-nx,.hp-nx-in{transition:opacity .5s cubic-bezier(.22,1,.36,1)}
.hp-lock{color:var(--ink)}
.hp-day{position:absolute;width:60px;text-align:center;font-size:12px;font-weight:600;line-height:15px;color:var(--sub)}
.hp-day em{display:block;font-style:normal;font-weight:700;font-size:11px;color:var(--ink)}
.hp-count{position:absolute;left:0;width:440px;top:340px;text-align:center;font-size:86px;font-weight:700;
          letter-spacing:-.03em;line-height:86px}
.hp-of{position:absolute;left:0;width:440px;top:432px;text-align:center;font-size:17px;line-height:22px;font-weight:600;
       color:var(--sub)}
.hp-up{position:absolute;left:17px;top:574.4px;width:406px;height:82px;border-radius:26px}
.hp-sw{position:absolute;inset:0}
.hp-sw > div{position:absolute;inset:0;transition:opacity .35s cubic-bezier(.22,1,.36,1),transform .35s cubic-bezier(.22,1,.36,1)}
.hp-sw span,.hp-sw b{position:absolute}
.hp-sw b{font-size:17.5px;line-height:22px;font-weight:600;white-space:nowrap}
.hp-sw .hp-sm{font-size:13.5px;line-height:18px;font-weight:500}
.hp-sw .hp-glyph{color:var(--acc)}
.hp-up2,.hp-sw.next .hp-up1{opacity:0;transform:translateY(8px)}
.hp-sw.next .hp-up1{transform:translateY(-8px)}
.hp-sw.next .hp-up2{opacity:1;transform:none}
.hp-pill{position:absolute;left:323.2px;top:19.6px;width:70px;height:43px;border-radius:22px;padding:0;
         background:linear-gradient(var(--acc2),var(--acc));color:var(--onfill);font-size:18px;font-weight:600;
         display:grid;place-items:center;box-shadow:0 2px 5px -2px rgba(10,88,91,.5)}
.hp-st,.hp-ad{position:absolute;top:669.7px;width:196.5px;height:78.3px;border-radius:24px}
.hp-st{left:17px}.hp-ad{left:226.5px}
.hp-st .hp-sm,.hp-ad .hp-sm{position:absolute;left:16.4px;top:11.9px;font-size:15.5px;line-height:18px}
.hp-st p,.hp-ad p{position:absolute;left:14px;top:33.8px;margin:0;display:flex;align-items:baseline;gap:5px;line-height:34px}
.hp-st b,.hp-ad b{font-size:28px;font-weight:700;letter-spacing:-.02em}
.hp-st b{color:#0F5A3F}
.hp-st small,.hp-ad small{font-size:15px;font-weight:500;color:var(--sub)}
.hp-st .hp-x-tree{color:var(--acc)}
.hp-more{position:absolute;inset:0;pointer-events:none;color:var(--acc)}
.hp-more .hp-x{width:16.6px;height:6.1px;left:211.7px}
.hp-more .hp-x:nth-child(1){top:820.4px}
.hp-more .hp-x:nth-child(2){top:825.1px;opacity:.78}
.hp-more .hp-x:nth-child(3){top:829.8px;opacity:.62}
.hp-more span{position:absolute;left:0;width:440px;top:841px;text-align:center;font-size:15px;line-height:24px;font-weight:600}

/* tab bar: the app's, in its own point size. Labels are ink; the current tab is teal on a pill. */
.hp-tabs{position:absolute;left:21px;top:873.2px;width:398px;height:62px;border-radius:31px;z-index:7;box-sizing:border-box;
         padding-left:9px;background:color-mix(in srgb,var(--raised) 88%,transparent);
         display:grid;grid-template-columns:repeat(4,95px);
         box-shadow:0 8px 26px -10px rgba(0,0,0,.35),0 0 0 .5px rgba(0,0,0,.06);
         transition:opacity .3s cubic-bezier(.22,1,.36,1),transform .4s cubic-bezier(.32,.72,0,1)}
.hp-tabs.off{opacity:0;transform:translateY(24px)}
.hp-sel{position:absolute;left:4px;top:4px;width:105px;height:53.4px;border-radius:27px;
        background:#DEE8E4;transition:transform .45s cubic-bezier(.3,1.25,.5,1)}
.hp-tab{position:relative}
.hp-tab .hp-x,.hp-tab b{color:var(--ink)}
.hp-tab.cur .hp-x,.hp-tab.cur b{color:#006A6D}
.hp-tab b{position:absolute;left:0;right:0;top:37.9px;text-align:center;font-size:10px;line-height:14px;font-weight:600}

.hp-x-stand{--ms:url("img/hero/stand.png");width:5.76px;height:13.19px}
.hp-x-wave{--ms:url("img/hero/wave.png");width:11.23px;height:12.44px}
.hp-x-walk{--ms:url("img/hero/walk.png");width:8.41px;height:13.48px}
.hp-x-scribble{--ms:url("img/hero/scribble.png");width:12.33px;height:11.34px}
.hp-x-tap{--ms:url("img/hero/tap.png");width:11.86px;height:13.94px}
.hp-x-arrive{--ms:url("img/hero/arrive.png");width:12.27px;height:13.54px}
.hp-x-lock{--ms:url("img/hero/lock.png");width:5.83px;height:8.16px}
.hp-x-home{--ms:url("img/hero/home.png");width:28.08px;height:24.72px}
.hp-x-chart{--ms:url("img/hero/chart.png");width:25.2px;height:21.72px}
.hp-x-msg{--ms:url("img/hero/msg.png");width:27.12px;height:22.56px}
.hp-x-game{--ms:url("img/hero/game.png");width:33.84px;height:21.24px}
.hp-x-prof{--ms:url("img/hero/prof.png");width:22.0px;height:22.0px}
.hp-x-gear{--ms:url("img/hero/gear.png");width:22.99px;height:22.99px}
.hp-x-tree{--ms:url("img/hero/tree.png");width:45.54px;height:45.9px}
.hp-x-chev{--ms:url("img/hero/chev.png");width:12.32px;height:7.21px}
.hp-x-cell{--ms:url("img/hero/cell.png");width:21.16px;height:14.45px}
.hp-x-wifi{--ms:url("img/hero/wifi.png");width:19.21px;height:13.86px}
.hp-x-back{--ms:url("img/hero/back.png");width:8.76px;height:14.96px}
.hp-x-scribble-l{--ms:url("img/hero/scribble.png");width:22.47px;height:20.68px}
.hp-x-arrive-l{--ms:url("img/hero/arrive.png");width:22.36px;height:24.68px}

/* test intro */
.hp-nav{display:flex;align-items:center;padding:4px 14px}
.hp-t{flex:1;text-align:center;font-weight:600;font-size:15px;margin-right:34px}
.hp-t-only{margin-right:0}
.hp-h1{font-size:28px;font-weight:700;letter-spacing:-.025em;text-align:center;margin:26px 0 14px}
.hp-course{display:block;width:300px;margin:0 auto;fill:none;stroke:var(--acc);stroke-width:2.5;stroke-linecap:round}
.hp-course .hp-ink{stroke-width:3}
.hp-course .hp-head{fill:var(--surf)}
.hp-course .hp-marks{fill:var(--acc);stroke:none}
.hp-course text{fill:var(--sub);stroke:none;font-size:11px;font-weight:600}
.hp-steps{margin:6px 24px 0;display:grid;gap:15px}
.hp-steps > div{display:grid;grid-template-columns:22px 1fr;gap:10px;align-items:start}
.hp-steps > div > span{display:grid;gap:7px;margin-top:5px}
.hp-steps em{font-style:normal;width:20px;height:20px;border-radius:50%;background:var(--acc);color:var(--onfill);
             font-size:11.5px;font-weight:700;display:grid;place-items:center}
.hp-go{position:absolute;left:50%;bottom:62px;width:124px;height:124px;margin-left:-62px}
.hp-core{position:absolute;inset:10px;border-radius:50%;background:var(--acc);color:var(--onfill);
         display:grid;place-items:center;font-size:34px;font-weight:700;box-shadow:0 10px 24px -8px rgba(10,88,91,.6)}
.hp-ping{position:absolute;inset:0;border-radius:50%;border:3px solid color-mix(in srgb,var(--acc2) 45%,transparent);
         animation:hp-ping 1.8s cubic-bezier(.22,1,.36,1) infinite}
@keyframes hp-ping{0%{transform:scale(.9);opacity:1}100%{transform:scale(1.18);opacity:0}}
/* While the test runs, an arc circles the button. The prototype drew it in with
   stroke-dashoffset; on this page only transform and opacity animate, so it turns instead. */
.hp-go svg{position:absolute;inset:-6px;width:136px;height:136px;opacity:0;transform:rotate(-90deg);
           transition:opacity .2s cubic-bezier(.22,1,.36,1)}
.hp-go svg circle{fill:none;stroke:var(--acc2);stroke-width:6;stroke-linecap:round;stroke-dasharray:110 408}
.hp-running .hp-ping{animation:none;opacity:0}
.hp-running .hp-go svg{opacity:1;animation:hp-spin 1.1s linear infinite}
@keyframes hp-spin{from{transform:rotate(-90deg)}to{transform:rotate(270deg)}}
.hp-running .hp-core{font-size:28px;font-variant-numeric:tabular-nums}

/* result */
.hp-res-top{display:flex;align-items:center;gap:20px;padding:20px 24px 0}
.hp-medal{width:120px;height:120px;flex:none}
.hp-medal text{font-size:14px;font-weight:700;fill:#4A3305;text-anchor:middle}
.hp-res-top b{display:block;font-size:30px;font-weight:700;letter-spacing:-.02em}
.hp-gold{color:var(--warn)}
.hp-res-h{font-size:24px;font-weight:700;letter-spacing:-.02em;margin:22px 24px 0}
.hp-metrics{display:grid;grid-template-columns:1fr 1fr;margin:20px 24px 0;gap:14px}
.hp-metrics > div{border-left:2px solid var(--acc2);padding-left:10px;display:grid;gap:8px}
.hp-big{height:20px;width:80%;background:var(--ink);opacity:.8}
.hp-big.w70{width:70%}
.hp-sheet{position:absolute;left:0;right:0;bottom:0;padding:16px 16px 34px;background:var(--raised);
          border-radius:26px 26px 0 0;display:grid;gap:10px;box-shadow:0 -6px 20px -12px rgba(0,0,0,.25)}
.hp-lite{height:48px;border-radius:14px;background:color-mix(in srgb,var(--acc2) 16%,var(--raised));
         display:grid;place-items:center;font-weight:600;color:var(--acc);font-size:15px}
.hp-done{height:58px;border-radius:16px;background:var(--acc);color:var(--onfill);display:grid;place-items:center;
         font-size:19px;font-weight:650}

/* progress */
.hp-big-t{font-size:32px;font-weight:700;letter-spacing:-.03em;margin:22px 20px 14px}
.hp-gauge{margin:0 14px;padding:16px 16px 18px;text-align:center}
.hp-gauge svg{display:block;margin:0 auto;width:260px;height:150px}
.hp-gauge b{display:block;font-size:19px;font-weight:650;margin:2px 0 8px}
.hp-g-track{fill:none;stroke:var(--track);stroke-width:22}
.hp-g-zone{fill:none;stroke:var(--acc2);stroke-opacity:.45;stroke-width:22}
.hp-g-hub{fill:var(--surf);stroke:var(--acc);stroke-width:4}
.hp-needle path{stroke:var(--acc);stroke-width:4;stroke-linecap:round}
.hp-needle{transform-box:view-box;transform-origin:130px 130px;transform:rotate(-78deg);
           transition:transform 1.4s cubic-bezier(.3,1.35,.45,1)}
.hp-gauge.on .hp-needle{transform:rotate(58deg)}
.hp-mid{margin:0 auto}
.hp-by{margin:18px 20px 0;font-weight:600}
.hp-rows{margin:8px 14px 0;padding:4px 0}
.hp-rows > div{display:flex;align-items:center;gap:12px;padding:13px 16px;opacity:0;transform:translateY(8px);
               transition:opacity .4s cubic-bezier(.22,1,.36,1),transform .4s cubic-bezier(.22,1,.36,1)}
.hp-rows > div:nth-child(2){transition-delay:.06s}.hp-rows > div:nth-child(3){transition-delay:.12s}
.hp-rows > div:nth-child(4){transition-delay:.18s}
.hp-rows > div + div{border-top:1px solid var(--track)}
.hp-rows.on > div{opacity:1;transform:none}
.hp-rows b{flex:1;font-size:15.5px}
.hp-chip{font-size:11.5px;font-weight:650;padding:3px 9px;border-radius:9px;background:var(--track);color:var(--sub)}
.hp-chip.g{background:color-mix(in srgb,var(--good) 18%,var(--raised));color:var(--acc)}

/* the finger */
.hp-touch{position:absolute;z-index:10;width:44px;height:44px;margin:-22px 0 0 -22px;border-radius:50%;pointer-events:none;
          background:rgba(120,130,130,.35);box-shadow:0 0 0 2px rgba(255,255,255,.7);opacity:0}
.hp-touch.tap{animation:hp-tap .62s cubic-bezier(.22,1,.36,1)}
@keyframes hp-tap{0%{opacity:0;transform:scale(1.5)}25%{opacity:1;transform:scale(1)}45%{transform:scale(.82)}100%{opacity:0;transform:scale(1.1)}}

/* ---------- hero phone: entrance, idle, pause ----------
   The entrance plays once on load, in CSS so it runs off the main thread while the page is
   still busy, and so it needs no script: with JS off the phone still lands at rest. It rises
   from below and further back, lying flatter and turned away, and turns in to the resting
   pose. 1.2s on the page's own ease-out (.22,1,.36,1): long for UI, right for the one
   marketing moment on the page, and it settles late so the last few degrees read as the
   phone coming to rest. The fade is half that, so the phone is solid well before it stops.
   It starts .25s in, after the copy's own entrance (heroIn) has begun, so the headline
   lands first. landing.js waits for this animation's end before tapping anything. */
@keyframes hp-enter{from{transform:translate3d(0,90px,-180px) rotateX(22deg) rotateY(30deg)}to{transform:none}}
@keyframes hp-fade{from{opacity:0}to{opacity:1}}
.hp-enter{animation:hp-enter 1.2s cubic-bezier(.22,1,.36,1) .25s both}
.hp-view{animation:hp-fade .6s cubic-bezier(.22,1,.36,1) .25s both}
/* A slow bob once it has landed, with its shadow breathing under it. */
@keyframes hp-float{0%,100%{transform:translateY(0)}50%{transform:translateY(-9px)}}
@keyframes hp-shadow{0%,100%{transform:scale(1);opacity:.9}50%{transform:scale(.93);opacity:.7}}
.hp-float{animation:hp-float 7s ease-in-out 1.45s infinite}
.hp-shadow{animation:hp-shadow 7s ease-in-out 1.45s infinite}
/* Off screen, or scrolled away: nothing ticks (landing.js sets .is-paused). */
.hero-phone.is-paused .hp-float,.hero-phone.is-paused .hp-shadow,.hero-phone.is-paused .hp-ping{animation-play-state:paused}

/* ---------- slim hero, for the pages that are not the home page ----------
   Same light band as the home hero, without the phone/console stage or the proof strip:
   an inner page needs a title and one line, not a pitch. */
.hero-slim{padding:0}
.hero-slim .inner-slim{position:relative;z-index:2;padding:64px 24px 58px;max-width:760px}
.hero-slim h1{font-size:clamp(30px,3.8vw,46px);line-height:1.06;letter-spacing:-.032em;
              margin:0 0 18px;color:var(--ink);text-wrap:balance}
.hero-slim .lede{font-size:17.5px;line-height:1.66;color:var(--sub);max-width:52ch;margin:0}
@media(max-width:720px){.hero-slim .inner-slim{padding:44px 20px 40px}}

/* Hero entrance. The hero is the one thing on the page that is never scrolled into view, so
   it never had a reveal at all — it simply existed. Each element arrives on a short stagger
   on load. Motion is off entirely under prefers-reduced-motion (see the block at the end of
   this file), where these elements are painted in their final position instead. */
@keyframes heroIn{from{opacity:0;transform:translateY(16px)}to{opacity:1;transform:none}}
.hero-live,.hero h1,.hero .lede,.hero .cta,.hero-stage,.hero-proof,
.hero-slim h1,.hero-slim .lede{
  animation:heroIn .8s cubic-bezier(.22,1,.36,1) both}
.hero h1,.hero-slim h1{animation-delay:.06s}
.hero .lede,.hero-slim .lede{animation-delay:.13s}
.hero .cta{animation-delay:.2s}
.hero-stage{animation-delay:.16s}
.hero-proof{animation-delay:.3s}

/* Anchor jumps glide instead of teleporting. Guarded, because a forced smooth scroll is
   genuinely unpleasant for anyone who asked for less motion. */
@media(prefers-reduced-motion:no-preference){html{scroll-behavior:smooth}}

/* ---------- how it works: split illustration ----------
   The source illustration showed two scenes side by side. It is cut at the gutter between
   them (measured, not guessed: the quietest column is 43.8% across) and each half now sits
   beside the audience it depicts. The halves are real files, not background-position crops,
   so each ships only the pixels it uses.

   The two bands step raised -> surface rather than being divided by a rule. The artwork's own
   paper is a warm near-white, so each half is multiplied into whatever band it sits on: the
   paper takes the band's colour and only the drawing stays, which is what keeps the crops
   edgeless on a cool ground. The feathered mask below does the rest at the edges. */

.hero-slim .hero-eyebrow{display:block;margin-bottom:14px}

.hiw-band{background:var(--raised)}
.hiw-band + .hiw-band{background:var(--surf)}
/* Copy gets the narrower column. A 50/50 split left the text running to ~70 characters,
   which is past comfortable, and gave the illustration more weight than the words. */
.split{display:grid;grid-template-columns:minmax(0,.92fr) minmax(0,1.08fr);gap:clamp(32px,5vw,72px);
       align-items:center}
.split-art-left{grid-template-columns:minmax(0,1.08fr) minmax(0,.92fr)}
.split-art-left .split-art{order:-1}
.split-copy{max-width:46ch}
.split-copy .sec{margin-top:6px;font-size:clamp(23px,2.5vw,31px)}
.split-copy .sec-sub{margin-bottom:0}

.split-art{width:100%;mix-blend-mode:multiply;background-repeat:no-repeat;background-position:center;
           background-size:contain;
           /* Each crop carries the illustration's own pale backdrop shapes, and those stop
              dead at the cut — a soft rectangle, even though the paper colour matches. The
              outer edge is feathered so the backdrop dissolves into the band instead of
              ending on a line. Small radius: enough to kill the edge, not so much that it
              vignettes the figures. */
           /* The feather has to be sized to the PICTURE, not the box: the box is wider than the
              letterboxed art, so a mask sized to the box left the art's own edge at full
              strength and a pale rectangle showed. The radii are set per class below. */
           -webkit-mask-image:var(--feather);mask-image:var(--feather)}
.art-clinic{--feather:radial-gradient(ellipse 44% 62% at 50% 50%, #000 68%, rgba(0,0,0,.45) 88%, transparent 100%)}
.art-patient{--feather:radial-gradient(ellipse 37% 62% at 50% 50%, #000 68%, rgba(0,0,0,.45) 88%, transparent 100%)}
/* Ratios are the crops' own, so neither half is ever squashed or cropped again. */
/* Neither illustration is a background. The doctor is an inline <svg> rig: a plate (the picture
   with her forearm painted out) plus the forearm redrawn as shapes that landing.js turns with
   scroll; its viewBox letterboxes exactly as background-size:contain did, and its default pose is
   the original picture. The walker is a stack of stills: the poster <img> (frame 0) and, once
   landing.js has a frame to draw, a canvas of the same size laid over it (room, floor, man). Both are letterboxed
   with object-fit:contain so they line up with each other; width/height 100% here outranks the
   site-wide img{height:auto}. No-JS and reduced motion show the markup: her original pose, his
   frame 0. */
.art-patient{aspect-ratio:754/880;max-height:440px;position:relative}
.art-patient img,.art-patient canvas{position:absolute;inset:0;width:100%;height:100%;
  object-fit:contain;display:block}
.art-clinic{aspect-ratio:824/780;max-height:400px}
svg.split-art{display:block;height:auto;overflow:hidden}

/* Numbered steps, without the numbers looking like a form. */
.steps{list-style:none;counter-reset:s;margin:22px 0 0;padding:0}
.steps li{counter-increment:s;position:relative;padding-left:38px;margin:0 0 18px;
          font-size:15.2px;line-height:1.66;color:var(--sub)}
.steps li::before{content:counter(s);position:absolute;left:0;top:1px;width:25px;height:25px;
                  border-radius:50%;background:var(--badge);
                  color:var(--accent-ink);font-size:12.5px;font-weight:700;
                  display:flex;align-items:center;justify-content:center}
.steps li b{color:var(--ink);font-weight:600}


/* The illustrations sit on their own paper with no card, no border and no shadow — a frame
   would undo the point of matching the background. They lift very slightly on hover instead,
   which is the whole interaction. */
.split-art{transition:transform .5s cubic-bezier(.22,1,.36,1)}
.split:hover .split-art{transform:translateY(-4px)}
@media(prefers-reduced-motion:reduce){.split:hover .split-art{transform:none}}

/* Hero: no artwork here any more, so it needs to stop being a tall empty field. Tighter, and
   the eyebrow gives the eye something to start on. */

@media(max-width:860px){
  /* Stacked, art first so the scene introduces the words rather than trailing them. */
  .split{grid-template-columns:1fr;gap:26px}
  .split-art{order:-1;max-height:300px}
  }

/* ---------- hero proof band ---------- */
.hero-proof{position:relative;z-index:2;background:var(--night)}
.hero-proof .row{display:grid;grid-template-columns:repeat(4,1fr);gap:36px;padding:22px 24px}
.hero-proof b{display:block;font-size:20px;font-weight:600;letter-spacing:-.02em;color:#fff;margin-bottom:3px}
.hero-proof span{display:block;font-size:12.5px;color:var(--night-sub);line-height:1.55}
.hero-proof .proof-tag{display:inline-block;margin-top:8px;padding:2px 9px;border:1px solid rgba(157,189,192,.35);
                       border-radius:999px;font-size:11.5px;color:#C9DCDD;text-decoration:none}
.hero-proof .proof-tag:hover,.hero-proof .proof-tag:focus-visible{border-color:#C9DCDD;text-decoration:underline}

/* ---------- story (kept: the patient-story block below is commented out in the
      body, and these rules are what it needs the day it comes back) ---------- */
.story{position:relative;padding-left:32px}
.story::before{content:"";position:absolute;left:5px;top:10px;bottom:34px;width:2px;
               background:linear-gradient(var(--line),var(--line) 62%,color-mix(in srgb,var(--bad) 40%,var(--line)) 100%)}
.story li{position:relative;list-style:none;margin:0 0 26px;font-size:16px;line-height:1.6;color:var(--ink)}
.story li::before{content:"";position:absolute;left:-32px;top:6px;width:12px;height:12px;border-radius:50%;
                  background:var(--card);border:2.5px solid var(--line)}
.story li.hit::before{border-color:var(--bad);background:var(--bad)}
.story li small{display:block;font-size:13.5px;color:var(--sub);margin-top:4px;line-height:1.62}
.story li.hit{color:#8F3517;font-weight:600}
.story-note{margin:8px 0 0;padding:20px 22px 20px 26px;background:var(--surf);border:0;
            border-left:4px solid var(--accent);border-radius:0 12px 12px 0;
            font-size:15px;line-height:1.68;color:var(--sub)}
.story-note b{color:var(--ink)}
/* "What the clinician gets from it", the note under the one-week story on /how-it-works. */
.gets-h{margin:0 0 8px;font-size:15px;font-weight:600;letter-spacing:-.01em;color:var(--ink)}
.gets{margin:0;padding-left:20px}
.gets li{margin:0 0 6px}
.gets li:last-child{margin-bottom:0}
.gets li::marker{color:var(--accent-ink)}

/* ---------- trajectory figure ---------- */
.traj{margin:0;background:var(--card);border:1px solid var(--line);border-radius:14px;
      padding:24px 22px 20px}
.traj svg{display:block;width:100%;height:auto}
.traj-axis{display:flex;justify-content:space-between;gap:12px;margin-top:8px;
           font-size:12.5px;color:var(--faint);font-weight:500}
.traj-key{display:flex;gap:10px 26px;flex-wrap:wrap;margin-top:18px;padding-top:16px;
          border-top:1px solid var(--line)}
.traj-key span{display:flex;align-items:center;gap:9px;font-size:13px;color:var(--sub)}
.traj-key i{width:24px;border-top:2.5px dashed currentColor;flex:none}
.traj-key .k1{color:var(--good)} .traj-key .k2{color:var(--warn)} .traj-key .k3{color:var(--bad)}
/* The "could have reached" line is illustrative, not a recovery: thinner, dotted, quietest ink. */
.traj-key .k4{color:var(--faint)} .traj-key .k4 i{border-top:2px dotted currentColor}
.traj figcaption{margin:16px 0 0;font-size:13.5px;line-height:1.68;color:var(--faint)}
.traj figcaption b{color:var(--sub);font-weight:600}

/* ---------- stats ---------- */
.stats{display:grid;grid-template-columns:repeat(3,1fr);gap:18px}
.statbox{background:var(--night-2);border:1px solid var(--night-line);border-radius:14px;padding:28px 26px}
.statbox .big{font-size:clamp(38px,5vw,52px);font-weight:700;letter-spacing:-.035em;line-height:1;
              color:#fff;margin-bottom:12px}
.statbox .big.words{font-size:clamp(23px,2.7vw,29px);letter-spacing:-.022em;line-height:1.22}
.statbox p{margin:0;color:var(--night-sub);font-size:14px;line-height:1.65}
.statbox.lead{background:transparent;border-style:dashed;display:flex;flex-direction:column;justify-content:center}
.statbox.lead .big{font-size:22px;letter-spacing:-.02em;line-height:1.3}
.src{margin:26px 0 0;font-size:12px;color:#7EA3A6}

.split{display:grid;grid-template-columns:.95fr 1.05fr;gap:56px;align-items:center}
.split.flip .col-a{order:2}
.split .device{width:250px;margin:0 auto}

/* ---------- triage ---------- */

/* ---------- what it measures (/how-it-works) ---------- */
/* Two raised cards on the tint band, one per source: what the phone measures and what the
   patient reports. Each family is a <details>, so it opens with no script; the tests that
   feed it are the chips one tap down. Depth is the background step alone, never a shadow.
   The row's hover is instant on purpose: only transform and opacity animate on this site. */
.measures{display:grid;grid-template-columns:1fr 1fr;gap:20px;align-items:start}
.m-group{background:var(--raised);border-radius:16px;padding:24px 14px 10px}
.m-head{display:flex;align-items:baseline;justify-content:space-between;gap:12px;margin:0 12px 6px}
.m-head h3{font-size:14px;font-weight:600;margin:0;letter-spacing:-.005em}
.m-head span{font-size:14px;color:var(--sub)}
.m-fam{border-top:1px solid var(--line)}
.m-fam:has(> summary:hover),.m-fam:has(> summary:hover) + .m-fam{border-top-color:transparent}
.m-fam summary{display:flex;align-items:center;gap:12px;padding:16px 12px;border-radius:10px;
               cursor:pointer;list-style:none}
.m-fam summary::-webkit-details-marker{display:none}
.m-fam summary:hover{background:var(--surf)}
.m-fam summary:focus-visible{outline:2px solid var(--accent-ink);outline-offset:-2px}
.m-nm{flex:1;min-width:0;font-size:17px;font-weight:600;letter-spacing:-.012em;line-height:1.4}
.m-ds{font-size:15px;font-weight:400;color:var(--sub);margin-left:4px;letter-spacing:0}
.m-ct{flex:none;font-size:13px;color:var(--sub)}
.m-cv{flex:none;width:26px;height:26px;border-radius:50%;background:var(--badge);color:var(--accent-ink);
      display:grid;place-items:center}
.m-cv svg{width:12px;height:12px;fill:none;stroke:currentColor;stroke-width:2.2;
          stroke-linecap:round;stroke-linejoin:round}
.m-fam[open] .m-cv{background:var(--accent);color:#fff}
.m-fam[open] .m-cv svg{transform:rotate(180deg)}
.m-chips{display:flex;flex-wrap:wrap;gap:6px;list-style:none;margin:0;padding:0 12px 16px}
.m-chips li{font-size:13px;font-weight:500;padding:4px 11px;border-radius:999px;
            background:var(--badge);color:var(--accent-ink)}
/* Opening a family: the chevron turns and the chips arrive one after another, 25ms apart.
   Under reduced motion none of this is declared, so nothing can move. */
@media(prefers-reduced-motion:no-preference){
  .m-cv svg{transition:transform .25s cubic-bezier(.22,1,.36,1)}
  .m-fam[open] .m-chips li{animation:m-chip .25s cubic-bezier(.22,1,.36,1) both}
  .m-fam[open] .m-chips li:nth-child(2){animation-delay:25ms}
  .m-fam[open] .m-chips li:nth-child(3){animation-delay:50ms}
  .m-fam[open] .m-chips li:nth-child(4){animation-delay:75ms}
  .m-fam[open] .m-chips li:nth-child(5){animation-delay:100ms}
  .m-fam[open] .m-chips li:nth-child(6){animation-delay:125ms}
  .m-fam[open] .m-chips li:nth-child(7){animation-delay:150ms}
}
@keyframes m-chip{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}

/* ---------- callout ---------- */
.callout{margin-top:22px;background:var(--accent-soft);border:0;border-radius:14px;
         padding:26px 28px;display:flex;gap:20px;align-items:flex-start}
.callout .cq{font-size:34px;line-height:1;color:var(--accent-ink);font-weight:700;flex:none}
.callout h3{font-size:16px;margin:0 0 7px;color:var(--accent-ink)}
.callout p{margin:0;font-size:14.2px;line-height:1.7;color:#244A4C}

/* ---------- timeline ---------- */
.tl{display:grid;grid-template-columns:repeat(5,1fr);gap:0;position:relative;margin-top:14px}
.tl::before{content:"";position:absolute;left:0;right:0;top:19px;height:2px;
            background:linear-gradient(90deg,var(--accent) 0%,var(--accent) 58%,var(--line) 58%,var(--line) 100%)}
.tl-col{position:relative;padding:0 12px}
.tl-col::before{content:"";position:absolute;left:12px;top:12px;width:16px;height:16px;border-radius:50%;
                background:var(--accent);border:4px solid var(--card);box-shadow:0 0 0 1px var(--accent)}
.tl-col.future::before{background:var(--card);box-shadow:0 0 0 1px var(--line)}
.tl-col.nowcol::before{background:var(--accent);box-shadow:0 0 0 1px var(--accent),0 0 0 7px rgba(14,118,122,.15)}
.tl-col .when{display:block;margin:48px 0 10px;font-size:13px;font-weight:700;color:var(--accent-ink)}
.tl-col.future .when{color:var(--faint)}
.tl-col ul{margin:0;padding:0;list-style:none}
.tl-col li{font-size:13.4px;line-height:1.55;color:var(--sub);padding:7px 0 7px 17px;position:relative}
.tl-col li::before{content:"";position:absolute;left:0;top:14px;width:6px;height:6px;border-radius:50%;
                   background:#C3D3D3}
.tl-col.done li{color:var(--ink)}
.tl-col.done li::before{background:var(--good)}
.tl-col.nowcol li::before{background:var(--accent)}

/* ---------- phases ---------- */
.phase{background:var(--card);border:1px solid var(--line);border-radius:14px;padding:26px 24px;
       position:relative;overflow:hidden}
.phase .pn{font-size:13px;font-weight:700;color:var(--accent-ink);margin-bottom:10px;display:block}
.phase h3{font-size:17px;margin:0 0 9px;letter-spacing:-.015em}
.phase ul{margin:0;padding-left:17px;color:var(--sub);font-size:13.8px;line-height:1.8}
.phase.now-p{border-color:var(--accent);box-shadow:0 0 0 3px rgba(14,118,122,.09)}
.phase .tagnow{position:absolute;top:16px;right:16px;background:var(--accent-soft);color:var(--accent-ink);
               font-size:11.5px;font-weight:700;padding:3px 9px;border-radius:5px}

/* ---------- market ---------- */
.mkt-stat{background:var(--accent-ink);color:#fff;border-radius:14px;padding:30px 28px;
          display:flex;align-items:center;gap:24px;margin-top:20px;flex-wrap:wrap}
.mkt-stat .big{font-size:clamp(40px,6vw,58px);font-weight:700;letter-spacing:-.035em;line-height:1}
.mkt-stat p{margin:0;font-size:15.5px;line-height:1.62;color:#D3EAEB;max-width:44ch}
.mkt-stat p b{color:#fff;font-weight:600}

/* ---------- team ---------- */
.person{background:var(--card);border:1px solid var(--line);border-radius:14px;padding:24px 22px;
        text-align:center;transition:transform .28s cubic-bezier(.22,1,.36,1),box-shadow .18s}
.person:hover{transform:translateY(-3px);box-shadow:var(--shadow-m)}
.person .av{width:58px;height:58px;border-radius:50%;margin:0 auto 14px;display:flex;
            align-items:center;justify-content:center;font-size:18px;font-weight:700;
            background:var(--accent-soft);color:var(--accent-ink);letter-spacing:.02em}
.person b{display:block;font-size:15.5px;letter-spacing:-.012em;margin-bottom:4px}
.person span{display:block;font-size:13px;color:var(--sub);line-height:1.55}
.person em{display:block;font-size:11.5px;color:var(--faint);font-style:normal;margin-top:6px;
           font-weight:600}
/* Was a centred grey box with a tracked byline, which is the single most templated
   shape a page like this can end on. A pull-quote set larger than body copy and held by
   one accent rule reads as something a person said. */
.quote{margin:44px 0 0;padding:2px 0 2px 26px;border-left:2px solid var(--accent);max-width:62ch}
.quote p{margin:0;font-size:clamp(18px,2.2vw,22px);line-height:1.5;letter-spacing:-.016em;
         color:var(--ink);text-wrap:pretty}
.quote footer{margin-top:14px;font-size:13px;color:var(--faint);font-weight:600}

/* Figures that sit next to each other or animate need fixed-width digits, or a 66
   next to a 41 wobbles the baseline grid. */
.hc-token,.hero-proof b,.statbox .big,.mkt-stat .big{
  font-variant-numeric:tabular-nums}

/* ---------- close + footer ---------- */
.close{text-align:center;padding:96px 0}
.close h2{font-size:clamp(28px,3.6vw,38px);letter-spacing:-.028em;margin:0 0 16px;color:#fff}
.close p{color:var(--night-sub);font-size:16.5px;max-width:54ch;margin:0 auto 32px;line-height:1.68}
.close .cta{display:flex;gap:12px;justify-content:center;flex-wrap:wrap}
footer.f{border-top:1px solid var(--line);padding:32px 0 52px;color:var(--faint);font-size:12px;
         display:flex;justify-content:space-between;gap:20px;flex-wrap:wrap;line-height:1.65}
footer.f a{color:var(--sub);text-decoration:none}
footer.f a:hover{color:var(--accent-ink)}
footer.f .nav-f{display:flex;gap:16px;flex-wrap:wrap}

/* ---------- responsive ---------- */
/* Four text tiles need an intermediate step. Without this they were 4-up down to 960px —
   about 210px each once the gap is taken out, too narrow for a sentence — and then dropped
   straight to a single column. Two-up covers the laptop and tablet range between. This must
   stay ABOVE the 960 block, which takes them to one column further down. */
@media(max-width:1180px){.grid-4{grid-template-columns:repeat(2,1fr)}}

@media(max-width:960px){
  section{padding:48px 0}
  .hero .inner{grid-template-columns:1fr;gap:36px;padding:48px 24px 52px}
  .hero h1{max-width:none}
  .hero .lede{max-width:none;font-size:17px}
  /* The stage stops being a collage below this: the phone flows, and the console card
     sits under it with just enough overlap to keep them reading as one object. */
  .hero-stage{max-width:420px;min-height:0}
  .hero-phone{position:relative;top:auto;right:auto;margin:0 auto;--k:.527}
  .hero-console{position:relative;top:auto;right:auto;margin:-64px auto 0}
  .hero-proof .row{grid-template-columns:1fr 1fr;gap:22px 30px}
  .grid-3,.grid-2,.grid-4,.measures,.stats{grid-template-columns:1fr}
  .split,.split.flip{grid-template-columns:1fr;gap:36px}
  .split.flip .col-a{order:0}
  .tl{grid-template-columns:1fr;gap:0}
  .tl::before{left:19px;right:auto;top:0;bottom:0;width:2px;height:auto;
              background:linear-gradient(180deg,var(--accent) 0%,var(--accent) 58%,var(--line) 58%)}
  .tl-col{padding:0 0 22px 46px}
  .tl-col::before{left:12px;top:6px}
  .tl-col .when{margin:2px 0 8px}
  .mkt-stat{gap:16px}
}
@media(max-width:700px){
  .hero-proof .row{grid-template-columns:1fr;gap:16px;padding:20px 24px}
}

/* ---------- phone one-pager ----------
   900px matches the nav menu breakpoint: below it the home page is the whole site as one
   scroll (see the PHONE ONE-PAGER block in landing.html), and it is trimmed to the argument —
   the decorative console card, half the proof band, the closing note and the validation
   callout are desktop-only. */
.m-only{display:none !important}
@media(max-width:900px){
  section.m-only{display:block !important}
  a.m-only{display:inline-flex !important}
  .d-only{display:none !important}
  .hero-console,
  .hero-proof .row > div:nth-child(n+3),
  #problem .story-note,
  #why .callout{display:none}
  .m-gap{margin-top:40px}
}
@media(max-width:560px){
  .hero .cta{flex-direction:column;gap:10px}
  .hero .cta .btn{justify-content:center;padding:15px 22px;font-size:15.5px}
  .traj{padding:18px 16px 16px}
  .traj-axis{font-size:11.5px}
  /* Only the team stays 2-up this narrow — avatar cards are compact enough.
     The differentiator cards carry a paragraph and need the full width. */
  #team .grid-4{grid-template-columns:1fr 1fr}
  .shot{width:158px}
  .callout{flex-direction:column;gap:10px}
}

/* ============================================================================
   CONTACT CARD
   ============================================================================
   Replaces the three mailto: links. Corner bubble -> card, with a paper plane
   flying from whichever button was clicked.

   Two rules govern everything below and re-break silently if ignored:

   1. **Only `transform` and `opacity` animate.** Both are composited; `top`,
      `left`, `width` and `height` are not, and animating them puts layout on the
      main thread for the length of the flight. The plane travels by
      `translate()` from a fixed origin, not by moving its coordinates.
   2. **The flight is driven by two CSS custom properties** (`--fx`, `--fy`) that
      landing.js sets from the clicked button's bounding rect. The keyframes are
      static and live here; only the destination delta comes from script. That is
      what keeps a real arc possible without generating keyframes in JS.
   ============================================================================ */

#contactRoot{position:fixed;inset:0;z-index:1000;pointer-events:none}
#contactRoot > *{pointer-events:auto}
#contactRoot[hidden]{display:none}

/* ---------- backdrop (mobile only; see the media query at the end) ---------- */
#contactBackdrop{position:absolute;inset:0;background:rgba(7,25,30,.55);
  opacity:0;transition:opacity .22s ease;display:none}
#contactBackdrop.on{opacity:1}
/* The mobile rule below sets display:block, which beats the `hidden` attribute landing.js
   uses to close it. Without these two lines a closed backdrop stayed as an invisible
   full-screen layer at z-index 1000 and ate every tap on the page after the card had been
   opened once. */
#contactBackdrop[hidden]{display:none !important}
#contactBackdrop:not(.on){pointer-events:none}

/* ---------- the corner bubble ---------- */
#contactBubble{position:absolute;right:24px;bottom:24px;width:56px;height:56px;
  border:0;border-radius:50%;background:var(--accent);color:#fff;cursor:pointer;
  display:grid;place-items:center;box-shadow:var(--shadow-m);
  transition:transform .18s ease,background .18s ease,box-shadow .18s ease}
#contactBubble:hover{background:var(--accent-ink);transform:translateY(-2px);box-shadow:var(--shadow-l)}
#contactBubble:focus-visible{outline:3px solid var(--accent);outline-offset:3px}
#contactBubble[hidden]{display:none}
/* The morph target. The plane's flight ends exactly here, and this scales up from
   nothing underneath it so the two read as one motion rather than a handoff. */
#contactBubble.pop{animation:cc-pop .22s cubic-bezier(.34,1.4,.64,1) both}
@keyframes cc-pop{from{transform:scale(0);opacity:0}to{transform:scale(1);opacity:1}}

/* ---------- the card ---------- */
/* The open/close animation is plane-send.js's, not this file's. It drives `clip-path`,
   `transform` and `opacity` directly through the Web Animations API, so the card must
   start hidden HERE and carry no transition or keyframe on those three — a competing
   rule doesn't merely look wrong, it wins over the script's fill:forwards and leaves
   the card stuck part-grown. The .opening/.fading/.leaving keyframes that used to live
   here are gone with the classes that drove them. */
/* Surface: a white card lifted by a hairline ring and a two-part shadow (contact + ambient),
   no border. Padding lives on .cc-body so the .cc-foot strip can run edge to edge. */
#contactCard{position:absolute;right:24px;bottom:24px;width:384px;max-width:calc(100vw - 32px);
  background:#fff;border-radius:16px;overflow:hidden;
  box-shadow:0 0 0 1px rgba(15,31,29,.06),0 2px 4px rgba(15,31,29,.06),
    0 24px 48px -16px rgba(15,31,29,.32);
  opacity:0;pointer-events:none}
#contactCard[hidden]{display:none}
.cc-body{padding:24px}

/* Every gap below is a multiple of 4: 24 card, 20 under the subtitle, 16 between fields,
   12 inside the name/email row, 6 label to field. */
.cc-head{display:flex;align-items:center;gap:12px}
.cc-badge{flex:none;width:36px;height:36px;border-radius:50%;background:var(--accent-soft);
  color:var(--accent-ink);display:grid;place-items:center}
.cc-head h2{flex:1;margin:0;font-size:18px;font-weight:600;letter-spacing:-.02em;line-height:1.25}
.cc-min{flex:none;align-self:flex-start;width:28px;height:28px;margin:0 -6px 0 0;border:0;
  border-radius:8px;background:transparent;color:var(--sub);cursor:pointer;
  display:grid;place-items:center;transition:background .15s,color .15s}
.cc-min:hover{background:var(--ground);color:var(--ink)}
.cc-min:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.cc-sub{margin:12px 0 20px;font-size:13px;line-height:1.5;color:var(--sub)}

.cc-row{display:grid;grid-template-columns:1fr 1fr;gap:12px}
.cc-field{margin-bottom:16px;min-width:0}
/* margin in full: console.css gives every label a 12px top margin. */
.cc-field label{display:block;font-size:12px;font-weight:600;color:var(--sub);margin:0 0 6px}
/* White fields with a recessed top edge. The border is #869893, 3.0:1 on white: a field's
   outline is the only thing that shows where to type, so WCAG 1.4.11 applies to it. */
.cc-field input,.cc-field textarea{width:100%;box-sizing:border-box;font:inherit;font-size:14px;
  color:var(--ink);background:#fff;border:1px solid #869893;border-radius:8px;
  box-shadow:inset 0 1px 2px rgba(15,31,29,.05);
  padding:9px 12px;transition:border-color .15s,box-shadow .15s}
.cc-field input{height:40px}
.cc-field textarea{display:block;resize:vertical;min-height:88px;line-height:1.5}
/* "(optional)" rides the label rather than sitting in it: same line, lighter weight,
   so the field name still scans as the label. --faint is a text colour and passes. */
.cc-opt{font-weight:400;text-transform:none;letter-spacing:0;color:var(--faint)}
.cc-field input:focus,.cc-field textarea:focus{outline:0;border-color:var(--accent);
  box-shadow:0 0 0 3px var(--accent-soft)}
/* A red ring alone would be the only carrier of "this one is wrong" — the message
   below it is the signal, and .cc-err is what a screen reader announces. */
.cc-field.bad input,.cc-field.bad textarea{border-color:var(--bad)}
.cc-err{margin:6px 0 0;font-size:12px;line-height:1.45;color:#8F3517;font-weight:500}
.cc-err[hidden]{display:none}
.cc-count{margin:6px 0 0;font-size:12px;color:var(--sub);text-align:right}
.cc-count[hidden]{display:none}
.cc-count.near{color:#8A551A;font-weight:600}

.cc-note{margin:0 0 16px;font-size:13px;line-height:1.5;padding:8px 12px;border-radius:8px;
  background:var(--warn-soft);color:#8A551A}
.cc-note[hidden]{display:none}
.cc-note a{color:inherit;font-weight:700}

.cc-send{display:block;width:100%;height:44px;margin-top:4px;padding:0 16px;border:0;
  border-radius:10px;background:var(--accent-ink);color:#fff;font:inherit;font-size:14px;
  font-weight:600;cursor:pointer;transition:background .15s,transform .15s}
.cc-send:hover{background:#08494C;transform:translateY(-1px)}
.cc-send:focus-visible{outline:3px solid var(--accent);outline-offset:2px}
.cc-send.busy{opacity:.7;cursor:progress}
/* The reply promise sits where the visitor decides whether to send. */
.cc-promise{display:flex;align-items:center;justify-content:center;gap:6px;margin:8px 0 0;
  font-size:12px;line-height:1.5;color:var(--sub)}
.cc-promise svg{flex:none;color:var(--accent)}

/* The escape hatch and the policy, in their own strip so neither competes with the button.
   It has to be findable when a rate limit points at it. */
.cc-foot{display:flex;align-items:baseline;justify-content:space-between;gap:12px;
  padding:12px 24px;background:var(--surf);border-top:1px solid var(--mist);
  font-size:12px;line-height:1.5;color:var(--sub)}
.cc-mail{margin:0;min-width:0;overflow-wrap:anywhere}
.cc-foot a{color:var(--accent-ink);font-weight:600}

/* Honeypot: off-screen, not display:none — bots skip fields they can tell are hidden. */
.cc-hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}

/* ---------- the plane ---------- */
/* There is no plane in the markup and no flight keyframes in this file any more. Both
   belong to plane-send.js, which appends its own <svg> to <body> and animates it through
   the Web Animations API — it needs a `d` morph between two paths with matching command
   counts, which CSS keyframes over a static markup plane cannot express.
   The only plane rule left here is the reduced-motion `display:none` at the end of the
   file, matched on the .planesend-plane class the script sets. */

/* ---------- the toast ---------- */
/* Rises ~34px over 4.5s while fading. Deliberately slow: it is the only confirmation the
   visitor gets, and it has to outlast a glance away from the screen. */
#contactToast{position:absolute;right:24px;bottom:96px;max-width:270px;
  background:var(--night);color:#fff;font-size:13.5px;font-weight:600;line-height:1.45;
  padding:11px 16px;border-radius:11px;box-shadow:var(--shadow-l);text-align:center}
#contactToast[hidden]{display:none}
#contactToast.show{animation:cc-toast 4.5s ease-out both}
@keyframes cc-toast{
  0%  {transform:translateY(10px);opacity:0}
  8%  {transform:translateY(0);opacity:1}
  55% {opacity:1}
  100%{transform:translateY(-34px);opacity:0}
}

/* ---------- mobile: centered modal over a dimmed page ---------- */
@media(max-width:640px){
  #contactBackdrop{display:block}
  /* Centered with margin:auto against all four insets, NOT with translate(-50%,-50%).
     plane-send.js animates `transform` on this element, so a centering transform here
     is overwritten the moment the card opens and the card jumps to the bottom-right.
     The inset+margin form centers through layout instead and leaves transform free. */
  #contactCard{right:0;bottom:0;left:0;top:0;margin:auto;
    width:calc(100vw - 32px);height:max-content;max-height:calc(100vh - 32px);
    overflow-y:auto}
  #contactToast{left:16px;right:16px;bottom:92px;max-width:none}
}
/* Two half-width fields would cut most real addresses off below this width. */
@media(max-width:420px){
  .cc-row{grid-template-columns:1fr;gap:0}
  .cc-body{padding:20px}
  .cc-foot{padding:12px 20px}
}

/* ---------- reduced motion ---------- */
/* Same states, same feedback, no travel. The plane is never drawn at all — landing.js
   also skips the flight, but this is the belt to that braces: a `display:none` here means
   a stale `.flying` class can't produce motion. The card and toast keep their appear and
   disappear as plain fades, because losing the confirmation entirely would be worse. */
@media(prefers-reduced-motion:reduce){
  /* plane-send.js checks the same media query and skips both flights and the clip-path
     growth on its own, cross-fading the card instead. This block is the belt to that
     braces: the plane it appends carries .planesend-plane, so a scripted flight that
     somehow started anyway still cannot produce motion. */
  .planesend-plane,.planesend-trail{display:none!important}
  #contactBubble.pop{animation:none}
  #contactToast.show{animation:cc-toast-still 4.5s linear both}
  @keyframes cc-toast-still{0%{opacity:0}4%{opacity:1}80%{opacity:1}100%{opacity:0}}
  #contactBubble:hover,.cc-send:hover{transform:none}
}

/* Reduced motion: no entrance, no hover travel, no smooth scroll. These have to mirror every
   animation added above — a new effect that is not listed here is a bug. */
@media(prefers-reduced-motion:reduce){
  .hero-live,.hero h1,.hero .lede,.hero .cta,.hero-stage,.hero-proof,
  .hero-slim h1,.hero-slim .lede{animation:none}
  .hero-console{transition:none}
  /* The hero phone: painted in its resting pose, still. The script's scroll exit and tap
     loop are skipped in landing.js too; the !important lines are the guarantee that a
     stale inline style from it can never move or hide the phone. */
  .hp-view,.hp-enter,.hp-float,.hp-shadow,.hp-ping{animation:none}
  .hp-exit{transform:none!important}
  .hero-phone{opacity:1!important}
  .tile:hover,.btn:hover,.btn:active{transform:none}
  html{scroll-behavior:auto}
}

/* ---------- slideshow controls (the "What your team sees" strip on /for-clinics) ----------
   The arrows and dots under the console slideshow. They were the phone carousel's before it was
   removed from /how-it-works; only the controls survive, renamed. The dot you see is 7px; the
   thing you tap is 34px (44px on a phone, via the block below). Drawn as a pseudo-element inside
   a transparent button, because a 7px tap target is not a target. */
.cshow-btn{width:36px;height:36px;border-radius:50%;border:1px solid var(--line);
           background:var(--card);color:var(--ink);cursor:pointer;display:flex;
           align-items:center;justify-content:center;
           transition:transform .22s cubic-bezier(.22,1,.36,1),border-color .22s,opacity .22s}
/* flex:none is load-bearing. The button is display:flex, so the icon is a flex item and the
   default flex-shrink squashed it along the main axis: it computed to 2px wide by 17px
   tall, which rendered as two empty circles. */
.cshow-btn svg{flex:none;width:17px;height:17px;fill:none;stroke:currentColor;stroke-width:2;
               stroke-linecap:round;stroke-linejoin:round}
.cshow-btn:hover{transform:translateY(-2px);border-color:var(--accent)}
.cshow-btn[disabled]{opacity:.32;cursor:default;transform:none}
.cshow-dot{width:34px;height:34px;padding:0;border:0;background:none;cursor:pointer;
           display:flex;align-items:center;justify-content:center;-webkit-tap-highlight-color:transparent}
.cshow-dot::before{content:"";width:7px;height:7px;border-radius:50%;background:#C6D3CF;
                   transition:background .25s,transform .25s}
.cshow-dot[aria-selected="true"]::before{background:var(--accent);transform:scale(1.35)}
.cshow-dot:focus-visible{outline:2px solid var(--accent);outline-offset:-4px;border-radius:50%}
@media(prefers-reduced-motion:reduce){.cshow-btn:hover{transform:none}}

/* ---------- phone: touch and legibility ----------
   Found by auditing the rendered page rather than by reading the CSS, which is the only way
   these show up: every one of them is correct at desktop width and wrong on a phone.

   1. Footer links measured 20px tall. A finger is about 44px, so they were a lottery to hit
      — and on a phone the footer is the second way to reach the other pages, after the menu.
   2. The smallest labels were 10.5px. That is a deliberate, legible size on a desktop
      monitor and simply small on a handset held at arm's length. */
@media(max-width:700px){
  /* Two tidy columns rather than a wrapped inline row. Giving each link a 44px touch target
     inside a flex row left them floating with ragged gaps — correct to tap, a mess to read.
     A grid gives the same target with alignment. */
  /* Selector must match `footer.f .nav-f` above (0,2,1) — a bare `.nav-f` here loses on
     specificity no matter where in the file it sits, and the grid silently never applies. */
  footer.f .nav-f{display:grid;grid-template-columns:1fr 1fr;gap:0 12px;width:100%}
  footer.f .nav-f a{display:flex;align-items:center;min-height:44px;padding:0}
  footer.f{align-items:flex-start;gap:6px}
  /* The close CTA had desktop-sized breathing room under it, which on a phone read as the
     page having ended twice. */
  .close{padding-bottom:34px}

  .brandlock .bn span{font-size:11.5px}
  .hc-eyebrow,.hc-tag{font-size:11.5px}
  .traj-axis span{font-size:12.5px}
  .traj-key span{font-size:12.5px}
  nav.top .btn-sm{min-height:42px}
  .cshow-dot{width:44px;height:44px}
  .cshow-btn{width:42px;height:42px}
  /* The wordmark is a link home, and at 30px it was the smallest target in the nav. */
  .brandlock{min-height:44px;align-items:center}
}

/* ---------- phone menu ----------
   Hidden at desktop widths, where the full link row is visible; the only thing on show below
   900px, where that row is not. Built on <details>, so it works with scripts disabled. */
.navmenu{display:none;position:relative}
.navmenu > summary{list-style:none;cursor:pointer;width:42px;height:42px;border-radius:10px;
                   display:flex;align-items:center;justify-content:center;
                   border:1px solid rgba(15,31,29,.16);background:var(--raised)}
.navmenu > summary::-webkit-details-marker{display:none}
.navmenu > summary svg{width:20px;height:20px;flex:none;fill:none;stroke:var(--ink);stroke-width:2;
                       stroke-linecap:round}
.navmenu[open] > summary{background:var(--badge)}

.navmenu-panel{position:absolute;right:0;top:calc(100% + 10px);min-width:216px;z-index:60;
               background:var(--card);border:1px solid var(--line);border-radius:14px;
               box-shadow:var(--shadow-l);padding:8px;display:flex;flex-direction:column}
.navmenu-panel a{display:block;padding:11px 14px;border-radius:9px;text-decoration:none;
                 font-size:15px;font-weight:500;color:var(--ink)}
.navmenu-panel a:hover,.navmenu-panel a:focus-visible{background:var(--ground)}
.navmenu-panel .navmenu-cta{margin-top:4px;background:var(--accent);color:#fff;text-align:center;
                            font-weight:600}
.navmenu-panel .navmenu-cta:hover{background:var(--accent-ink);color:#fff}

.navmenu-panel .navmenu-signin{border-top:1px solid var(--line);margin-top:6px;padding-top:15px;
                               border-radius:0;color:var(--sub)}

@media(max-width:900px){
  .navmenu{display:block}
}
/* Below this the nav row cannot hold the wordmark, a button and the menu at once — measured,
   not guessed: 171 + 126 + 42 = 339px of a 375px screen, before any padding. Sign-in moves
   into the menu panel, which is where a phone user expects to find it anyway. */
@media(max-width:760px){
  nav.top .links .btn{display:none}
  /* Tap targets: 42px is under Apple's 44px guidance on its own, but the summary has the
     nav's own 12px vertical padding around it, so the touchable area clears it. */
}

/* ---------- for-clinics banner ----------
   Shown WHOLE. The artwork is drawn 8:3 for this slot, so it needs no cropping and gets
   none: the height comes from the aspect ratio rather than being fixed, and object-fit is
   left alone. An earlier square-ish source had to be cover-cropped here, which is what made
   the framing a fight — this one was made to fit, so the correct handling is to get out of
   its way.

   It still emerges from the header rather than starting under it: the band runs a gradient
   from the hero's own Mist down to the surface the next section begins on, and the image
   fades to nothing top and bottom. Where it fades at the top the hero's colour shows through. Both
   colours are read from the tokens either side — if the hero or .tint changes surface,
   change them here or the seam returns. */
.clinic-banner{margin:0;width:100%;overflow:hidden;
               background:linear-gradient(to bottom,
                          var(--mist-deep) 0%, var(--mist-deep) 5%,
                          var(--ground) 62%, var(--ground) 100%)}
.clinic-banner img{display:block;width:100%;height:auto;aspect-ratio:2048/768;
                   -webkit-mask-image:linear-gradient(to bottom, transparent 0%, #000 16%, #000 82%, transparent 99%);
                           mask-image:linear-gradient(to bottom, transparent 0%, #000 16%, #000 82%, transparent 99%)}

/* ---------- stock photos (_stock_photo.html) ----------
   Placeholders until real clinic photos exist. No caption: the disclosure is the footer line in
   site_base.html. The image keeps its width/height attributes for layout, so aspect-ratio comes
   from them and nothing jumps while it loads. */
.photo{margin:0 0 44px}
.photo img{display:block;width:100%;height:auto;border-radius:14px;
           box-shadow:0 18px 44px -24px rgba(12,38,42,.45)}
.night .photo img{box-shadow:0 18px 50px -20px rgba(0,0,0,.6)}
.photo-after{margin:36px 0 0}
.story + .photo{margin-top:36px}
/* The full-width ones are cut to a 2:1 strip: at 16:9 and container width a photo outweighs
   the section it illustrates. Faces sit in the top third of all three, hence 32%. */
.photo-band img{aspect-ratio:2/1;object-fit:cover;object-position:50% 32%}

/* ---------- problem band: notebook beside the figure ----------
   The handwritten week and the three-trajectory chart make the same argument, one as a
   person and one as a shape. Side by side they read as a pair; stacked they read as the
   same point made twice. The figure gets the wider column because it carries a chart. */
/* align-items:start, not center. Centred, the notebook (387px) and the chart (412px) floated
   at different heights and neither top lined up with the other — the eye reads two modules
   that should start together as misaligned. */
.problem-split{display:grid;grid-template-columns:minmax(0,.86fr) minmax(0,1.14fr);
               gap:clamp(30px,4.5vw,60px);align-items:start;margin-top:28px}
.problem-split .story{margin:0}
.problem-split .traj{margin:0}
@media(max-width:900px){
  .problem-split{grid-template-columns:1fr;gap:34px}
}

/* The closing line runs the full width under both columns, and carries more weight than the
   rest of the band: it is the turn from "here is the problem" to "this is the job". Left
   accent rather than a full box — a second bordered card next to the chart would read as
   more evidence rather than as the conclusion. */
#problem .story-note{width:100%;max-width:none;margin:clamp(30px,4vw,46px) 0 0;
                     padding:26px 30px 26px 34px;background:var(--surf);border:0;
                     border-left:4px solid var(--accent);border-radius:0 12px 12px 0;
                     font-size:clamp(16px,1.6vw,18.5px);line-height:1.62;color:var(--sub)}
#problem .story-note b{color:var(--ink);font-weight:600}
@media(max-width:900px){#problem .story-note{padding:22px 20px}}

/* ---------- the console, as a slideshow (how it works) ----------
   Studio-light treatment: console ground behind a straight white card, serif headline with the
   console lockup beside it. The card is authored on a fixed 880x640 canvas and scaled to the
   stage by landing.js (`--k`), so it keeps the proportions of a picture at every width instead
   of reflowing into a cramped table. Without the script there is no scale: each stage scrolls
   sideways and the four slides stack. */
.cshow{margin-top:56px;padding-bottom:28px}
.cshow-slide + .cshow-slide{margin-top:48px}
.cshow-head{display:flex;justify-content:space-between;align-items:flex-start;gap:24px;margin-bottom:6px}
.cshow-title{font-family:Georgia,"Iowan Old Style","Times New Roman",serif;font-weight:400;
             font-size:clamp(24px,2.8vw,34px);line-height:1.08;letter-spacing:-.02em;margin:0;
             color:var(--ink);max-width:22ch;text-wrap:balance}
.cshow-lock{display:flex;align-items:center;gap:9px;flex:none;font-size:13.5px;font-weight:650;
            color:var(--ink);padding-top:8px}
.cshow-bn{display:block;line-height:1.25}
.cshow-bn b{display:block;font-size:14px;letter-spacing:-.01em}
.cshow-bn{font-size:10.5px;font-weight:500;color:var(--sub);letter-spacing:.03em}
.cshow-mark{width:22px;height:22px;border-radius:6px;background:var(--accent);display:flex;
            align-items:center;justify-content:center}
.cshow-mark::after{content:"";width:10px;height:10px;border:2px solid #fff;border-radius:50%;box-sizing:border-box}
.cshow-stage{overflow-x:auto}
.cshow-canvas{width:880px;height:640px;display:flex;align-items:center;justify-content:center}

.cshow.is-live .cshow-slides{display:grid}
.cshow.is-live .cshow-slide{grid-area:1/1;margin:0;opacity:0;visibility:hidden;
  transition:opacity .6s cubic-bezier(.33,1,.68,1),visibility 0s linear .6s}
.cshow.is-live .cshow-slide.is-on{opacity:1;visibility:visible;transition-delay:0s}
.cshow.is-live .cshow-slide .cs-card{transform:translateY(10px);transition:transform .8s cubic-bezier(.22,1,.36,1)}
.cshow.is-live .cshow-slide.is-on .cs-card{transform:none}
/* Live: each card is scaled to its own stage (`--k`, per slide), and every stage takes the tallest
   card's height (`--sh`, on the root) so the section never changes height between slides. */
.cshow.is-live .cshow-stage{overflow:hidden;position:relative;height:var(--sh,640px)}
.cshow.is-live .cshow-canvas{position:absolute;left:50%;top:28px;width:auto;height:auto;
  transform-origin:50% 0;transform:translateX(-50%) scale(var(--k,1))}

.cshow-bar{display:flex;align-items:center;justify-content:space-between;gap:16px;margin-top:0}
.cshow-caption{margin:0;font-size:12.5px;color:var(--sub);flex:1}
.cshow-dots{display:flex}
.cshow-nav{display:flex;gap:8px;flex:1;justify-content:flex-end}

/* the redrawn card: Mist tokens, sentence-case labels, status as glyph + word */
.cs-card{background:var(--card);border:1px solid var(--line);border-radius:12px;color:var(--ink);text-align:left;
  box-shadow:var(--shadow-s);font-size:13.5px;line-height:1.45}
.cs-eb{display:block;font-size:12.5px;color:var(--accent-ink);font-weight:600}
.cs-h{display:block;font-size:19px;font-weight:600;letter-spacing:-.01em;margin-top:4px}
.cs-sub{color:var(--sub);font-size:12.5px}
.cs-top{display:flex;justify-content:space-between;align-items:center;gap:16px}
.cs-tok{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:13px;font-weight:600}

.cs-triage{width:780px;overflow:hidden}
.cs-triage .cs-top{padding:18px 22px}
.cs-row{display:grid;grid-template-columns:160px minmax(0,1fr) 96px 72px;gap:16px;align-items:center;
  padding:12px 22px;border-top:1px solid var(--line)}
.cs-th{font-size:12.5px;color:var(--sub);font-weight:600;border:0;padding-top:0;padding-bottom:6px}
.cs-lane{display:flex;align-items:center;gap:10px;padding:12px 22px 4px;border-top:1px solid var(--line);background:var(--surf)}

.cs-rep,.cs-plan{padding:26px 28px}
.cs-rep{width:640px}
.cs-gap{margin-top:14px}
.cs-flag{display:flex;align-items:center;gap:10px;flex-wrap:wrap;border:1px solid var(--line);
  border-left:4px solid var(--st-bad);border-radius:8px;padding:9px 12px;margin-top:6px;background:var(--raised)}
.cs-flag .cs-sub{flex-basis:100%}
.cs-item{display:flex;gap:10px;align-items:baseline;flex-wrap:wrap;padding:9px 0;border-top:1px solid var(--line);margin-top:6px}
.cs-item .cs-sub{flex:1 1 0;min-width:0}
.cs-cite{display:inline-block;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px;
  padding:1px 6px;border-radius:5px;background:var(--badge);color:var(--accent-ink)}
.cs-fold{margin-top:14px;padding:10px 12px;border:1px solid var(--line);border-radius:8px;background:var(--raised)}

.cs-plan{width:680px}
.cs-ring{width:80px;height:80px}
.cs-ring circle{fill:none;stroke:var(--badge);stroke-width:7}
.cs-ring circle.on{stroke:var(--accent);stroke-linecap:round}
.cs-ring text{font-size:15px;font-weight:700;fill:var(--ink)}
.cs-wk{display:grid;grid-template-columns:170px repeat(7,minmax(0,1fr));align-items:center;justify-items:center;
  padding:12px 0;border-top:1px solid var(--line)}
.cs-wk > div{justify-self:start}
.cs-wk b,.cs-wk .cs-sub{display:block}
.cs-wk.cs-th{margin-top:16px}
.cs-plan i{width:30px;height:30px;border-radius:50%;box-sizing:border-box}
.cs-plan i.d{background:var(--accent) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3.5 8.5l3 3 6-7' fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center/14px no-repeat}
.cs-plan i.t{border:2px dashed var(--accent)}
.cs-plan i.u{border:2px solid var(--line)}
.cs-legend{display:flex;gap:18px;margin-top:14px;font-size:12px;color:var(--sub)}
.cs-legend span{display:flex;align-items:center;gap:6px}
.cs-legend i{width:14px;height:14px}
.cs-legend i.d{background-size:9px}

@media(max-width:640px){
  /* A phone can't show a four-column table legibly at any scale: keep patient and why. */
  .cs-triage{width:540px}
  .cs-row{grid-template-columns:150px minmax(0,1fr)}
  .cs-row > :nth-child(n+3){display:none}
  .cs-rep{width:520px}
  .cs-plan{width:540px}
  .cs-wk{grid-template-columns:140px repeat(7,minmax(0,1fr))}
  .cs-plan i{width:26px;height:26px}
  .cshow-head{flex-direction:column;gap:14px}
  .cshow-caption{display:none}
  .cshow-nav{flex:none}
}
@media(prefers-reduced-motion:reduce){
  .cshow.is-live .cshow-slide,.cshow.is-live .cshow-slide .cs-card{transition:none;transform:none}
}

/* ---------- status chips: a glyph and a word, never colour alone ----------
   Shared by the how-it-works panels (.cp) and the /for-clinics slides (.cs-card). The text is ink;
   only the glyph and the tint carry the hue, so the word still passes as text. Greens, ambers and
   reds are the app's Mist status colours. */
:root{--st-good:#199B6C; --st-warn:#BA7B0F; --st-bad:#DF623C}
.cp-st{display:inline-flex;align-items:center;gap:5px;font-weight:600;font-size:12.5px;line-height:1;
  padding:4px 9px;border-radius:999px;background:var(--badge);color:var(--ink);white-space:nowrap;font-style:normal}
.cp-st i{font-style:normal;font-size:11px;color:var(--sub)}
.cp-st.good{background:color-mix(in srgb,var(--st-good) 15%,var(--raised))}.cp-st.good i{color:var(--st-good)}
.cp-st.warn{background:color-mix(in srgb,var(--st-warn) 16%,var(--raised))}.cp-st.warn i{color:var(--st-warn)}
.cp-st.bad{background:color-mix(in srgb,var(--st-bad) 15%,var(--raised))}.cp-st.bad i{color:var(--st-bad)}

/* ---------- how it works: the weeks between visits, as four beats ----------
   Each beat: a day pill and one sentence, the phone beside it, one cut-out panel of the dashboard.
   The phone is the only thing here with a shadow. These rules are the no-script layout (and the
   base under the timeline below): .beat-scene is display:contents, so a beat's phone and panel sit
   in its own grid, and on a phone-width screen a beat stacks: sentence, phone, panel. */
.beats{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:64px}
.beat{display:grid;grid-template-columns:minmax(0,.8fr) auto minmax(0,1.5fr);gap:clamp(24px,3.4vw,44px);align-items:center}
/* Week five has no phone: the panel takes the phone's column too. */
.beat-panel{grid-template-columns:minmax(0,.8fr) minmax(0,1.9fr)}
.beat-panel .cp{max-width:620px}
.day{display:inline-block;font-weight:600;font-size:13px;color:var(--accent-ink);background:var(--badge);
  padding:3px 12px;border-radius:999px;margin-bottom:12px}
.beat-line{margin:0;font-size:clamp(18px,1.7vw,21px);line-height:1.35;font-weight:600;color:var(--ink);
  letter-spacing:-.012em;text-wrap:balance}
.beat-lbl{display:block;font-size:13px;font-weight:600;color:var(--sub);margin-bottom:10px}
.hiw-phone{--pw:224px;width:var(--pw);padding:calc(var(--pw)*.034);background:#101F22;
  border-radius:calc(var(--pw)*.17);box-shadow:var(--shadow-m)}
.hiw-phone img{display:block;width:100%;height:auto;border-radius:calc(var(--pw)*.14);background:var(--raised)}
.cp{background:var(--card);border:1px solid var(--line);border-radius:12px;padding:14px 18px 8px;font-size:14px;line-height:1.4}
.cp-head{display:flex;justify-content:space-between;align-items:center;gap:12px;padding-bottom:10px;
  border-bottom:1px solid var(--line)}
.cp-tok{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12.5px;color:var(--sub)}
.cp-smp{font-size:12px;color:var(--sub);background:var(--badge);padding:1px 9px;border-radius:999px}
.cp-sub{color:var(--sub);font-size:13px}
.cp-row{display:grid;grid-template-columns:minmax(0,1fr) auto minmax(0,.7fr);gap:6px 14px;align-items:center;
  padding:12px 0;border-bottom:1px solid var(--line)}
.cp-row:last-child{border-bottom:0}
.cp-measure{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:6px 14px;align-items:center;padding:12px 0}
.cp-measure .cp-sub{grid-column:1}
.cp-spark{grid-column:1/3;display:block;width:100%;max-width:300px;height:auto;margin-top:4px}
.cp-spark .band,.cp-chart .band{fill:color-mix(in srgb,var(--accent) 14%,transparent)}
.cp-spark polyline,.cp-chart polyline{fill:none;stroke:var(--sub);stroke-width:1.8;stroke-linejoin:round;stroke-linecap:round}
.cp-spark circle,.cp-chart circle{fill:var(--sub)}
.cp-chart .warn{fill:var(--st-warn)}.cp-chart .bad{fill:var(--st-bad)}
.cp-flag{display:flex;flex-wrap:wrap;align-items:center;gap:6px 10px;margin-top:12px;padding:10px 12px;
  border:1px solid var(--line);border-left:4px solid var(--st-bad);border-radius:8px;background:var(--raised)}
.cp-flag .cp-sub{flex-basis:100%}
.cp-chart{display:block;width:100%;height:auto;margin-top:12px}
.cp-key{display:flex;flex-wrap:wrap;gap:8px 12px;align-items:center;padding:6px 0 10px;font-size:12.5px;color:var(--sub)}
.hiw-cap{margin:30px 0 0;font-size:13px;color:var(--sub)}
.hiw-after{max-width:840px;margin:0 auto}
.hiw-after .photo-after{margin-top:40px}
@media(max-width:900px){
  .beats{gap:52px}
  .beat,.beat-solo,.beat-panel{grid-template-columns:minmax(0,1fr);gap:22px}
  .beat-side:has(.hiw-phone){justify-self:center}
}

/* ---------- how it works: the beats as a timeline (landing.js adds .is-live) ----------
   The sentences are a vertical rail; the scenes (phone + panel) share one stage beside it and
   crossfade, so the stage is as tall as the tallest scene and nothing below it moves. The rail's
   gaps follow the calendar: Monday to "a minute later" is the tightest, Thursday to week five is
   dashed and labelled. The open beat's segment fills over its --dwell; that CSS animation IS the
   timer (landing.js advances on animationend), so pausing is animation-play-state and resumes
   where it stopped. Only transform and opacity animate. */
.beat-scene{display:contents}
.beats-tl.is-live .beat-text{position:relative;padding-left:34px}
.beat-btn{display:block;width:100%;margin:0;padding:0;border:0;border-radius:10px;background:none;
  color:inherit;font:inherit;text-align:left;cursor:pointer;min-height:0}
.beat-btn:hover{background:none}
.beat-btn:focus-visible{outline:2px solid var(--accent-ink);outline-offset:6px}
.beat-btn::before{content:"";position:absolute;left:1px;top:6px;width:12px;height:12px;border-radius:50%;
  background:var(--raised);box-shadow:inset 0 0 0 2px color-mix(in srgb,var(--sub) 45%,transparent);
  transition:background-color .3s,box-shadow .3s}
.beat.is-past .beat-btn::before{background:color-mix(in srgb,var(--accent-ink) 55%,var(--raised));box-shadow:none}
.beat.is-on .beat-btn::before{background:var(--accent-ink);
  box-shadow:0 0 0 5px color-mix(in srgb,var(--accent) 18%,transparent)}
.beats-tl.is-live .day{margin-bottom:6px}
/* The open sentence grows 16px -> 19px by transform, not font-size, so it eases instead of
   snapping and nothing reflows. Every line wraps at the width it will have when scaled (84.2% =
   1/1.1875), and landing.js reserves the scaled height, so the rail never moves. */
.beats-tl.is-live .beat-line{font-size:16px;font-weight:500;color:var(--sub);letter-spacing:0;max-width:84.2%;
  transform-origin:0 0;transition:color .3s ease,transform .45s cubic-bezier(.2,.7,.2,1)}
.beats-tl.is-live .beat-btn:hover .beat-line{color:var(--ink)}
.beats-tl.is-live .beat.is-on .beat-line{transform:scale(1.1875);font-weight:600;color:var(--ink)}
.beats-tl.is-measuring .beat-line{font-weight:600}
.beat-track{position:absolute;left:6px;top:12px;bottom:-12px;width:2px;overflow:hidden;
  background:color-mix(in srgb,var(--sub) 22%,transparent)}
.beat-fill{position:absolute;inset:0;background:var(--accent-ink);transform:scaleY(0);transform-origin:top}
.beat.is-past .beat-fill{transform:none}
.beats-tl.is-playing .beat.is-on .beat-fill{animation:beat-fill var(--dwell,6s) linear forwards}
.beats-tl.is-held .beat.is-on .beat-fill{animation-play-state:paused}
@keyframes beat-fill{from{transform:scaleY(0)}to{transform:scaleY(1)}}
.beats-tl.is-live .beat:nth-child(1) .beat-text{padding-bottom:12px}
.beats-tl.is-live .beat:nth-child(2) .beat-text{padding-bottom:28px}
.beats-tl.is-live .beat:nth-child(3) .beat-text{padding-bottom:64px}
.beats-tl.is-live .beat:nth-child(3) .beat-track{background:repeating-linear-gradient(to bottom,
  color-mix(in srgb,var(--sub) 34%,transparent) 0 4px,transparent 4px 9px)}
.beats-tl.is-live .beat:nth-child(3) .beat-text::after{content:"4 weeks later" / "";position:absolute;left:34px;
  bottom:22px;font-size:12.5px;color:var(--sub)}
.beat-ctl{display:inline-flex;align-items:center;gap:8px;margin:0;padding:8px 2px;border:0;border-radius:8px;
  background:none;color:var(--accent-ink);font:inherit;font-size:13.5px;font-weight:600;cursor:pointer;min-height:0}
.beat-ctl:hover{background:none;text-decoration:underline;text-underline-offset:3px}
.beat-ctl:focus-visible{outline:2px solid var(--accent-ink);outline-offset:3px}
.beat-ctl i{font-style:normal;font-size:11px}
@media(min-width:901px){
  .beats-tl.is-live{display:grid;grid-template-columns:minmax(300px,.85fr) minmax(0,1.5fr);
    grid-template-rows:1fr repeat(4,auto) auto 1fr;column-gap:clamp(36px,5vw,72px)}
  .beats-tl.is-live .beats,.beats-tl.is-live .beat{display:contents}
  .beats-tl.is-live .beat-text{grid-column:1}
  .beats-tl.is-live .beat:nth-child(1) .beat-text{grid-row:2}
  .beats-tl.is-live .beat:nth-child(2) .beat-text{grid-row:3}
  .beats-tl.is-live .beat:nth-child(3) .beat-text{grid-row:4}
  .beats-tl.is-live .beat:nth-child(4) .beat-text{grid-row:5}
  .beats-tl.is-live .beat-ctl{grid-column:1;grid-row:6;justify-self:start;margin:22px 0 0 28px}
  /* Out, then in: the leaving scene fades in 180ms with no delay, the arriving one waits 160ms and
     rises 12px, phone first and panel 70ms after. A transition takes the timing of the state it is
     going TO, so the inactive rule is the exit and the .is-on rule the entrance. A plain crossfade
     put Thursday's phone and week five's panel on the same spot at half opacity each.
     Two backstops, because a browser left Thursday's phone painted behind week five's panel (user,
     2026-10-21): each side fades out on its own as well as with its scene, and once the fade is
     over the scene is clipped to nothing. Clipped, not visibility:hidden, so a screen reader still
     reads all four days. The clip lifts at once on the way in (0s, no delay). Both ends are inset()
     so the clip interpolates and the delay holds: against none it would be discrete and cut the fade
     off at its first frame. The open one is negative so the phone's shadow is not cut. */
  .beats-tl.is-live .beat-scene{grid-column:2;grid-row:1/-1;align-self:center;display:flex;justify-content:center;
    align-items:center;gap:clamp(24px,3vw,40px);opacity:0;pointer-events:none;clip-path:inset(0 0 100% 0);
    transition:opacity .18s ease-in,clip-path 0s linear .2s}
  .beats-tl.is-live .beat.is-on .beat-scene{opacity:1;pointer-events:auto;clip-path:inset(-120px);
    transition:opacity .35s ease-out .16s,clip-path 0s}
  .beats-tl.is-live .beat-scene > .beat-side{opacity:0;transform:translateY(12px);
    transition:opacity .18s ease-in,transform .18s ease-in}
  .beats-tl.is-live .beat.is-on .beat-scene > .beat-side{opacity:1;transform:none;
    transition:opacity .35s ease-out .16s,transform .55s cubic-bezier(.2,.7,.2,1) .16s}
  .beats-tl.is-live .beat.is-on .beat-scene > .beat-side + .beat-side{transition-delay:.23s}
  .beats-tl.is-live .beat-side:has(.cp){flex:1 1 0;max-width:400px;min-width:0}
  .beats-tl.is-live .beat-panel .beat-side{max-width:600px}
}
@media(max-width:900px){
  /* An accordion, no timer: tap a day, its phone and panel open under it. */
  .beats-tl.is-live .beats{gap:18px}
  .beats-tl.is-live .beat{display:block}
  .beats-tl.is-live .beat-scene{display:none}
  .beats-tl.is-live .beat.is-on .beat-scene{display:flex;flex-direction:column;align-items:center;gap:22px;
    padding:20px 0 12px}
  .beats-tl.is-live .beat-side{width:100%}
  .beats-tl.is-live .beat-scene > .beat-side{transform:none}
  /* The accordion reflows anyway, so the open line is simply set larger here; no reserve. */
  .beats-tl.is-live .beat-line{max-width:none}
  .beats-tl.is-live .beat.is-on .beat-line{transform:none;font-size:19px}
  .beats-tl.is-live .beat-side:has(.hiw-phone){width:auto}
  .beats-tl.is-live .beat:nth-child(n) .beat-text{padding-bottom:0}
  .beats-tl.is-live .beat:nth-child(3) .beat-text::after,.beat-track,.beat-ctl{display:none}
}
@media(prefers-reduced-motion:reduce){
  .beats-tl.is-live .beat-scene,.beats-tl.is-live .beat-scene > .beat-side,.beat-btn::before,
  .beats-tl.is-live .beat-line{transition:none!important}
  .beats-tl.is-live .beat-scene > .beat-side{transform:none}
  .beat-ctl{display:none}
}
