/* Web fonts, self-hosted: the latin subsets of the variable fonts (one file covers every weight used) */
@font-face {
  font-family: "Plus Jakarta Sans"; font-style: normal; font-weight: 400 800; font-display: swap;
  src: url("assets/fonts/plus-jakarta-sans-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Inter"; font-style: normal; font-weight: 400 600; font-display: swap;
  src: url("assets/fonts/inter-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  --paper: #ffffff;
  --charcoal: #1f2025;
  --ink: #222326;
  --cloud: #ebf0f8;
  --gray: #747679;
  --line: #e1e5ec;
  --sky: #d2e5ff;
  --cream: #fff9ee;
  --green: #31ce01;
  --gold: #ffca00;
  --coral: #ffab94;
  --font: -apple-system, BlinkMacSystemFont, "SF Pro Display", "Inter", system-ui, sans-serif;
  /* Never less than the safe area: in landscape on iPhones with a notch or Dynamic Island the page runs edge to
     edge (viewport-fit=cover, so the bands fill the sides), and the content keeps clear of the sensor housing */
  --gutter: max(clamp(16px, 4vw, 48px), env(safe-area-inset-left, 0px), env(safe-area-inset-right, 0px));
  --max: 1216px;
  --ease: cubic-bezier(.16, 1, .3, 1);
}
/* The wider safe-area inset, as a length main.js can read (the hero's side phones never fan out under the notch) */
@property --safe-x { syntax: "<length>"; inherits: false; initial-value: 0px; }
/* Body gray, one step deeper on tinted surfaces so it keeps 4.5:1 there */
.top-band, .panel, .cta, .card, .checkin-panel, .nav-wrap { --gray: #63656a; }

* { box-sizing: border-box; }
html { scroll-padding-top: 96px; } /* anchors and focused controls clear the sticky nav */
html.smooth { scroll-behavior: smooth; } /* set by main.js after load, so #hash links open in place */
body {
  margin: 0;
  font-family: var(--font);
  color: var(--ink);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
img { display: block; max-width: 100%; height: auto; }
a { color: inherit; text-decoration: none; }
h1, h2, h3, p, figure, dl, dd, ul, ol { margin: 0; }
ul, ol { padding: 0; list-style: none; }

/* Type */
.display {
  font-weight: 600;
  font-size: clamp(40px, 5.6vw, 80px);
  line-height: 1;
  letter-spacing: -0.03em;
}
.display-md { font-size: clamp(36px, 4.2vw, 56px); line-height: 1.04; }
.display-xl { font-size: clamp(44px, 5.6vw, 80px); }
.lead { font-size: clamp(18px, 1.6vw, 22px); line-height: 1.38; color: var(--gray); }
.eyebrow {
  font-size: 14px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--gray); text-align: center; margin-bottom: 16px;
}
.eyebrow.left { text-align: left; }
.center { text-align: center; }

/* Pills */
.pill {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 13px 22px; border-radius: 128px;
  font-size: 16px; font-weight: 500; white-space: nowrap;
  transition: transform .2s ease, background-color .2s ease;
}
.pill-dark { background: var(--charcoal); color: var(--cloud); }
.pill-light { background: rgba(255,255,255,.72); color: var(--ink); }
/* Hover only where there is a real pointer: iOS keeps :hover after a tap, which left a tapped pill lifted and white */
@media (hover: hover) {
  .pill:hover { transform: translateY(-1px); }
  .pill-light:hover { background: #fff; }
}
/* Touch screens: the pills, the menu button and the FAQ's +/- give their own pressed state instead of the browser's
   square tap flash (main.js adds the touchstart listener iOS Safari needs before it applies :active). Every other
   link keeps the platform's highlight. */
@media (hover: none) {
  .pill, .nav-menu, .faq-list summary { -webkit-tap-highlight-color: transparent; }
  .pill:active { transform: scale(.97); }
  .pill-light:active { background: #fff; }
  .nav-menu:active { background: rgba(31,32,37,.12); }
  .faq-list summary:active .pm { background: #dde4ef; }
  .faq-list details[open] summary:active .pm { background: #3a3b40; }
}
.pill-sm { padding: 10px 18px; }
.ico-arrow { width: 14px; height: 14px; }
.actions { display: flex; flex-wrap: wrap; gap: 12px; justify-content: center; }
.actions.left { justify-content: flex-start; }

/* Nav */
.nav-wrap { position: sticky; top: 16px; z-index: 50; padding: 0 var(--gutter); margin-top: 16px; }
/* iPhone Safari: once the page scrolls, a frosted strip sits at the top so text never runs under the clock. Safari 26
   tints the status bar from a fixed element touching the top edge, but only one tall enough: 12px ends just above the nav.
   (-webkit-touch-callout is only supported on iOS, so other browsers never draw it.) */
.status-shield { display: none; }
@supports (-webkit-touch-callout: none) {
  .status-shield {
    position: fixed; top: 0; left: 0; right: 0; z-index: 49; pointer-events: none;
    height: calc(12px + env(safe-area-inset-top, 0px)); background: rgba(255,255,255,.85);
    -webkit-backdrop-filter: blur(16px); backdrop-filter: blur(16px); display: none;
  }
  html.scrolled .status-shield { display: block; }
  .nav-wrap { top: calc(16px + env(safe-area-inset-top, 0px)); }
}
.nav {
  max-width: 1080px; margin: 0 auto;
  display: flex; align-items: center; justify-content: space-between;
  padding: 10px 10px 10px 24px; border-radius: 32px;
  background: rgba(255,255,255,.78);
  backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px);
  box-shadow: 0 1px 0 rgba(255,255,255,.6) inset, 0 8px 24px -16px rgba(31,32,37,.25);
}
.brand { display: inline-flex; align-items: center; }
.brand img { display: block; height: 26px; width: auto; }
.nav-links { display: flex; gap: 32px; }
.nav-links a { font-size: 16px; font-weight: 500; color: var(--gray); transition: color .2s; }
.nav-links a:hover { color: var(--ink); }
.nav-menu { display: none; }

.nav-menu:focus-visible { outline: 2px solid var(--charcoal); outline-offset: 3px; }

/* Continuous gradient: sky to cream to white, ending before the trainers panel */
.top-band {
  /* Full bleed: reaches the window's top and side edges (the nav floats over it with its 16px top margin) */
  margin: -88px 0 0;
  padding-top: 88px;
  overflow-x: clip;
  /* Stops pinned in px from the top (and from the end), so the sky over the hero always looks the same and
     the band evens out to white over the same distance before the trainers panel, whatever the sections' heights */
  background: linear-gradient(180deg, var(--sky) 0, #e7eef9 780px, var(--cream) 2020px, #fffdf8 calc(100% - 2130px), var(--paper) 100%);
}

/* Hero */
.hero { padding: clamp(56px, 7vw, 88px) var(--gutter) 0; text-align: center; }
.hero-title { max-width: 980px; margin: 0 auto; }
.hero-lead { max-width: 640px; margin: 20px auto 28px; }
.hero-note { margin-top: 16px; font-size: 13px; color: var(--gray); }

/* Phones: frame matches the screenshot's 402:874 screen, so nothing is cropped */
.phone {
  position: relative; flex-shrink: 0;
  padding: 10px; border-radius: 50px;
  background: var(--charcoal);
  box-shadow: 0 40px 60px -30px rgba(31,32,37,.35), 0 1px 0 rgba(255,255,255,.18) inset;
}
.phone img { width: 100%; aspect-ratio: 402 / 874; border-radius: 40px; background: #f5f7fb; }
.phone::after {
  content: ""; position: absolute; left: 50%; top: 21px;
  width: 29%; aspect-ratio: 3.6; transform: translateX(-50%);
  border-radius: 20px; background: var(--charcoal);
}
.hero-phones {
  --safe-x: max(env(safe-area-inset-left, 0px), env(safe-area-inset-right, 0px));
  position: relative; display: flex; justify-content: center; align-items: flex-start;
  gap: clamp(16px, 2.4vw, 32px);
  margin-top: clamp(48px, 6vw, 88px); /* also the room the centre phone floats up into (main.js) */
}
.phone-main { width: clamp(240px, 25vw, 360px); }
/* Just above the phone layout the row would overflow the hero: the sides give way so it always fits the content box */
.phone-side {
  width: min(clamp(200px, 21vw, 300px), (100vw - 32px - 2 * var(--gutter) - clamp(240px, 25vw, 360px) - 2 * clamp(16px, 2.4vw, 32px)) / 2);
  margin-top: 120px;
}

@media (min-width: 960px) {
  .top-band { background: linear-gradient(180deg, var(--sky) 0, #e7eef9 620px, var(--cream) 1600px, #fffdf8 calc(100% - 1700px), var(--paper) 100%); }
}
@media (min-width: 1280px) {
  .top-band { background: linear-gradient(180deg, var(--sky) 0, #e7eef9 567px, var(--cream) 1458px, #fffdf8 calc(100% - 1540px), var(--paper) 100%); }
}

/* ---------- How it works: one story (Dana and Maya), told with a sticky phone on large screens ----------
   Base (phones, tablets, no JS): each step is its copy and its own uncropped phone, stacked.
   Large screens with JS (.is-live): the steps scroll on the left and one sticky phone on the right shows the
   screen for the step crossing the middle of the viewport. Nothing animates in on its own. */
.how { padding: 120px var(--gutter) 40px; max-width: calc(var(--max) + 2 * var(--gutter)); margin: 0 auto; }
.hw { --hw-stage-h: min(calc(100vh - 120px), 860px); }
@supports (height: 100svh) { .hw { --hw-stage-h: min(calc(100svh - 120px), 860px); } }
.hw-grid { margin-top: 72px; }
.hw-steps { display: grid; gap: 72px; }
.hw-step { position: relative; display: grid; gap: 32px; }
.hw-meta {
  display: flex; align-items: center; gap: 12px;
  font-size: 14px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--gray);
}
.hw-n {
  width: 32px; height: 32px; border-radius: 50%; flex-shrink: 0; display: grid; place-items: center;
  background: var(--charcoal); color: var(--cloud);
  font-size: 13px; letter-spacing: 0; font-variant-numeric: tabular-nums;
  transition: background-color .3s var(--ease), color .3s var(--ease);
}
.hw-n svg { width: 12px; height: 12px; }
.hw-step h3 {
  margin-top: 20px; font-size: clamp(32px, 3.2vw, 44px); font-weight: 600; line-height: 1.04; letter-spacing: -0.03em;
  transition: color .3s var(--ease);
}
.hw-text { margin-top: 14px; max-width: 460px; font-size: clamp(18px, 1.45vw, 20px); line-height: 1.45; color: var(--gray); }
.hw-detail { margin-top: 32px; max-width: 460px; transition: opacity .3s var(--ease); }
.hw-note { margin-top: 12px; font-size: 15px; color: var(--gray); }
/* 01 · the team code, as the athlete's six-box code entry */
.hw-code { display: flex; gap: 8px; }
.hw-code > span {
  position: relative; flex: 0 1 52px; height: 62px; border-radius: 16px; display: grid; place-items: center;
  background: #fff; box-shadow: inset 0 0 0 1px var(--line);
  font-size: 26px; font-weight: 600; color: var(--ink);
  transition: box-shadow .12s ease;
}
.hw-code i { font-style: normal; }
/* main.js types the code in, one box at a time: the box being typed into has a ring and a blinking caret */
.hw-code > span.at { box-shadow: inset 0 0 0 1.5px var(--charcoal); }
.hw-code > span.at::after {
  content: ""; position: absolute; left: 50%; top: 50%; width: 2px; height: 26px; margin: -13px 0 0 -1px;
  border-radius: 1px; background: var(--charcoal); animation: hw-blink 1.06s step-end infinite;
}
/* 02 · the athlete landing on the trainer's roster */
.hw-roster {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 16px 12px 12px; border-radius: 20px; background: #fff; box-shadow: inset 0 0 0 1px var(--line);
}
.hw-av { width: 40px; height: 40px; border-radius: 50%; flex-shrink: 0; display: grid; place-items: center; background: var(--cloud); font-size: 15px; font-weight: 600; }
.hw-who { flex: 1; min-width: 0; }
.hw-who b { display: block; font-size: 16px; font-weight: 600; }
.hw-who small { display: block; margin-top: 2px; font-size: 14px; color: var(--gray); }
.hw-short { display: none; }
.hw-tag { flex-shrink: 0; padding: 6px 12px; border-radius: 128px; background: var(--charcoal); color: var(--cloud); font-size: 13px; font-weight: 500; white-space: nowrap; }
/* 03 · the five phases (Strengthen just opened), then the day they're cleared */
.hw-phases { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 8px; } /* equal, like the app's phase bar */
.hw-phases li { font-size: 13px; color: var(--gray); white-space: nowrap; }
.hw-phases i { position: relative; display: block; height: 6px; margin-bottom: 10px; border-radius: 3px; background: #dfe3ea; overflow: hidden; }
.hw-phases .done i { background: var(--charcoal); }
.hw-phases .cur i::after { content: ""; position: absolute; inset: 0 70% 0 0; border-radius: 3px; background: var(--charcoal); }
.hw-phases .cur { color: var(--ink); font-weight: 600; }
.hw-end { display: flex; align-items: center; gap: 12px; margin-top: 24px; padding-top: 20px; border-top: 1px solid var(--line); font-size: 16px; font-weight: 600; }
.hw-end .hw-n { width: 28px; height: 28px; }

/* Each step's own phone (the base layout, and what screen readers read on large screens) */
.hw-shot { display: grid; justify-items: center; gap: 20px; padding: 40px 24px 24px; border-radius: 32px; background: var(--cloud); }
.hw-shot figcaption { font-size: 14px; font-weight: 500; color: var(--gray); }
.hw-phone { width: min(300px, 72vw); }
.hw-screens { position: relative; z-index: 0; overflow: hidden; aspect-ratio: 402 / 874; border-radius: 40px; background: #fff; }
.hw-screens .live-wrap { position: absolute; inset: 0; }
.hw-over { pointer-events: none; }

/* App screens, laid out at the app's 402 × 874 and zoomed to the phone by main.js */
.hw .a-screen { padding-bottom: 50px; background: #fff; } /* the home indicator inset (34) plus the app Screen's 16 */
.hw .a-screen .a-status { background: transparent; }
.hw-eyebrow { margin-top: 12px; font-size: 12px; font-weight: 700; letter-spacing: 1.4px; color: var(--a-faint); }
/* Admin setup (admin/setup.tsx) */
.hw .hw-setup { background: #F5F7FB; }
.hw-screens .live-wrap:has(> .hw-setup) { background: #F5F7FB; } /* and behind it, for a stepped zoom (its own rule: a browser without :has() drops only this) */
.hw-h1 { margin-top: 14px; font-size: 30px; line-height: 34px; font-weight: 800; letter-spacing: -0.9px; }
.hw-sub { margin-top: 8px; font-size: 14.5px; line-height: 22px; color: var(--a-muted); }
.hw-fields { display: grid; gap: 18px; margin-top: 28px; }
.hw-fields small { display: block; font-size: 12px; font-weight: 700; letter-spacing: .7px; color: var(--a-muted); }
.hw-input {
  display: flex; align-items: center; min-height: 53px; margin-top: 8px; padding: 14px 18px; border-radius: 18px;
  background: #fff; border: 1px solid var(--a-line); font-size: 16px; line-height: 22px; font-weight: 600;
}
.hw-val { white-space: pre; } /* a typed space moves the caret on, as on the phone */
.hw-caret { display: none; width: 2px; height: 20px; margin-left: 2px; border-radius: 1px; background: var(--a-blue); }
.hw-input.focus .hw-caret { display: block; animation: hw-blink 1.06s step-end 4; } /* then it rests, solid */
.hw-input.hot .hw-caret { animation: none; } /* solid while keys are landing, like the real caret */
@keyframes hw-blink { 50% { opacity: 0; } }
.hw .hw-btn { margin-top: auto; }
/* Create team waits for a team name (disabled at .4, as ui.tsx draws it). The keyboard comes up over the foot of
   the screen and covers the button, as it does in the app (setup.tsx doesn't move it); main.js starts with it
   down (.kb-off), raises it with the first tap and lowers it again with the tap on return. */
.hw-setup.unnamed .hw-btn, .js:not(.ready) .hw-setup .hw-btn { opacity: .4; }
/* Until main.js has rewound the screens (.ready), CSS draws each one at its start, so a slow script never shows
   the end first and then takes it back: nothing typed in yet, no code, no injury picked, no result */
.js:not(.ready) .hw-setup .hw-val[data-type], .js:not(.ready) .hw-code > span { color: transparent; }
.hw-kb {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 2; padding: 8px 3px 46px; display: grid; gap: 11px;
  background: #D2D5DB; font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", var(--font);
  transition: transform .4s cubic-bezier(.32, .72, 0, 1); /* the iOS keyboard curve */
}
.hw-setup.kb-off .hw-kb { transform: translateY(100%); }
.kb-r { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 6px; }
.kb-r2 { padding: 0 19px; }
.kb-r3 { grid-template-columns: 44px repeat(7, 1fr) 44px; }
.kb-r3 > i:nth-child(2) { margin-left: 8px; }
.kb-r3 > i:nth-child(8) { margin-right: 8px; }
.kb-r4 { grid-template-columns: 88px 1fr 88px; }
.hw-kb i {
  position: relative; height: 42px; display: grid; place-items: center; border-radius: 5px; background: #fff;
  box-shadow: 0 1px 0 #898A8D; font-style: normal; font-size: 22px; color: #0a0a0b;
}
.hw-kb .kb-fn, .kb-r4 i { font-size: 16px; }
.hw-kb .kb-fn { background: #ABB0BA; }
/* Words start with a capital (autoCapitalize="words"): shift lights up and the letters show in capitals */
.hw-kb.up .kb-shift { background: #fff; }
.hw-kb.up .kb-r:not(.kb-r4) i:not(.kb-fn) { text-transform: uppercase; }
.hw-kb .kb-space.down { background: #ABB0BA; }
.hw-kb .kb-fn.down { background: #fff; }
/* The key preview iOS shows while a letter is held: a balloon that grows up out of the key (covering its letter),
   with the letter large in the bulb. Keys at the ends of a row lean their bulb inward. */
.kb-pop {
  position: absolute; z-index: 3; left: -9px; right: -9px; bottom: 0; height: 100px; pointer-events: none;
  display: grid; justify-items: center; align-content: start; padding-top: 12px;
  font-size: 32px; line-height: 36px; font-weight: 400; color: #0a0a0b; text-transform: none;
}
.kb-pop::before, .kb-pop::after { content: ""; position: absolute; z-index: -1; background: #fff; }
.kb-pop::before { left: 0; right: 0; top: 0; height: 60px; border-radius: 10px; box-shadow: 0 0 0 .5px rgba(0, 0, 0, .12), 0 6px 12px -4px rgba(0, 0, 0, .3); }
.kb-pop::after { left: 9px; right: 9px; bottom: 0; height: 52px; border-radius: 0 0 5px 5px; box-shadow: 0 1px 0 #898A8D; }
.kb-r > i:first-child > .kb-pop { left: 0; right: -18px; }
.kb-r > i:first-child > .kb-pop::after { left: 0; right: 18px; }
.kb-r > i:last-child > .kb-pop { left: -18px; right: 0; }
.kb-r > i:last-child > .kb-pop::after { left: 18px; right: 0; }
/* Under the keys: emoji on the left, dictation on the right */
.kb-foot { position: absolute; left: 0; right: 0; bottom: 8px; display: flex; justify-content: space-between; padding: 0 26px; pointer-events: none; }
.kb-foot svg { width: 26px; height: 26px; }
/* A fingertip on the glass, the way a screen recording shows touches: a frosted disc that lands, presses and
   lifts. main.js places it in the screen's own 402px space, so it sits right at any zoom. */
.tp {
  position: absolute; left: 0; top: 0; z-index: 4; width: 44px; height: 44px; margin: -22px 0 0 -22px;
  border-radius: 50%; pointer-events: none; opacity: 0;
  background: rgba(120, 128, 140, .35);
  box-shadow: 0 0 0 2px rgba(255, 255, 255, .9), 0 4px 12px -2px rgba(20, 38, 74, .35);
}
.tp.sm { width: 34px; height: 34px; margin: -17px 0 0 -17px; }
.hw-kb .tp { left: 50%; top: 50%; width: 32px; height: 32px; margin: -16px 0 0 -16px; }
/* Injury picker (onboarding/injury.tsx) */
.hw-pick .a-stephead { margin-top: 14px; }
.hw-pick .a-q { margin-top: 26px; font-size: 26px; line-height: 30px; letter-spacing: -0.78px; }
.hw-body { position: relative; flex: 1; display: grid; place-items: center; min-height: 220px; }
.hw-man { width: 140px; height: 308px; overflow: visible; }
.hw-tap { opacity: 0; transform-box: fill-box; transform-origin: center; }
.hw-pick.tapped .hw-tap { animation: hw-tap 1.1s cubic-bezier(.2, .7, .3, 1) forwards; }
@keyframes hw-tap { 0% { opacity: .45; transform: scale(.6); } 100% { opacity: 0; transform: scale(2.4); } }
.hw-spot { transition: opacity .25s ease; }
.hw-glow { transform-box: fill-box; transform-origin: center; transition: transform .7s var(--ease); }
/* main.js starts the screen before the tap (.pre): no spot on the body, neither side picked, no injury picked */
.hw-pick.pre .hw-spot, .js:not(.ready) .hw-pick .hw-spot { opacity: 0; }
.hw-pick.pre .hw-glow, .js:not(.ready) .hw-pick .hw-glow { transform: scale(.4); }
.hw-side {
  position: absolute; bottom: 34px; padding: 8px 12px; border-radius: 999px;
  background: #fff; box-shadow: inset 0 0 0 1px var(--a-border); font-size: 12px; font-weight: 600; color: var(--a-muted);
  transition: background-color .25s ease, box-shadow .25s ease, color .25s ease;
}
.hw-side:first-of-type { left: 26px; }
.hw-side:last-of-type { right: 26px; }
.hw-side.on { background: var(--a-ink); box-shadow: inset 0 0 0 1px var(--a-ink); color: #fff; font-weight: 700; }
.hw-pick.pre .hw-side.on, .js:not(.ready) .hw-pick .hw-side.on { background: #fff; box-shadow: inset 0 0 0 1px var(--a-border); color: var(--a-muted); }
.hw-inj { display: grid; gap: 8px; }
.hw-opt {
  display: flex; align-items: center; justify-content: space-between; padding: 14px 16px; border-radius: 18px; background: #F5F7FB;
  box-shadow: inset 0 0 0 1.5px transparent; transition: background-color .25s ease, box-shadow .25s ease;
}
.hw-opt b { display: block; font-size: 15px; }
.hw-opt small { display: block; margin-top: 1px; font-size: 12px; font-weight: 600; color: var(--a-muted); transition: color .25s ease; }
.hw-opt.on { background: var(--a-blue-tint); box-shadow: inset 0 0 0 1.5px var(--a-blue); }
.hw-opt.on small { color: var(--a-blue-deep); }
.hw-ok {
  width: 20px; height: 20px; border-radius: 50%; flex-shrink: 0; background: var(--a-blue)
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2.5 6.2l2.3 2.3 4.7-5' fill='none' stroke='%23fff' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / 56% no-repeat;
  transition: transform .4s cubic-bezier(.34, 1.56, .64, 1) .05s;
}
.hw-opt:not(.on) .hw-ok { transform: scale(0); transition-duration: .15s; transition-delay: 0s; }
.js:not(.ready) .hw-opt.on { background: #F5F7FB; box-shadow: inset 0 0 0 1.5px transparent; }
.js:not(.ready) .hw-opt.on small { color: var(--a-muted); }
.js:not(.ready) .hw-opt.on .hw-ok { transform: scale(0); }
.hw-pick .a-cta { margin-top: 16px; }
/* A dark button dims a touch while it is held, as the app's Pressable does */
.hw .a-cta { transition: opacity .12s ease; }
.hw .a-cta.down { opacity: .85; }
/* Check-in result (checkin-result.tsx), green; the top stays clear for the trainer's notification */
.hw-res { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 22px; text-align: center; }
.hw-badge { position: relative; width: 120px; height: 120px; display: grid; place-items: center; }
.hw-badge i { position: absolute; border-radius: 50%; background: var(--a-green); }
.hw-badge i:first-child { width: 120px; height: 120px; opacity: .1; }
.hw-badge i + i { width: 86px; height: 86px; opacity: .18; }
.hw-badge b { position: relative; width: 53px; height: 53px; border-radius: 50%; display: grid; place-items: center; background: var(--a-green); }
.hw-badge svg { width: 26px; height: 26px; }
.hw-res-t { font-size: 32px; line-height: 36px; font-weight: 800; letter-spacing: -1px; }
.hw-res-b { margin-top: -10px; max-width: 300px; font-size: 15px; line-height: 23px; color: var(--a-muted); }
.hw-chips { display: flex; gap: 8px; }
.hw-chips span { padding: 8px 12px; border-radius: 999px; background: #F5F7FB; font-size: 12.5px; font-weight: 700; color: #3B4A6B; }
.hw-result .a-cta { margin-top: 0; }
.hw-foot { margin-top: 14px; text-align: center; font-size: 13px; color: var(--a-faint); }
.hw-badge path { stroke-dasharray: 1 1.2; } /* pathLength="1": offset 1.1 is all gap (not even the round cap shows), 0 is drawn */
/* main.js plays the result in (.pre, then .go): the badge pops, its tick draws and the rings bloom out behind
   it, then the words rise in under it, top to bottom */
.hw-badge b, .hw-badge i { transition: transform .6s cubic-bezier(.34, 1.5, .64, 1), opacity .4s ease; }
.hw-result.pre .hw-badge b, .js:not(.ready) .hw-result .hw-badge b { transform: scale(0); }
.hw-result.pre .hw-badge i, .js:not(.ready) .hw-result .hw-badge i { opacity: 0; transform: scale(.4); }
.hw-result.pre .hw-badge path, .js:not(.ready) .hw-result .hw-badge path { stroke-dashoffset: 1.1; }
.hw-result.pre .hw-res-t, .hw-result.pre .hw-res-b, .hw-result.pre .hw-chips,
.js:not(.ready) .hw-result .hw-res-t, .js:not(.ready) .hw-result .hw-res-b, .js:not(.ready) .hw-result .hw-chips { opacity: 0; transform: translateY(12px); }
.hw-result.go .hw-badge b { transform: none; transition-delay: .05s; }
.hw-result.go .hw-badge i + i { opacity: .18; transform: none; transition: transform .9s var(--ease) .2s, opacity .5s ease .2s; }
.hw-result.go .hw-badge i:first-child { opacity: .1; transform: none; transition: transform 1.1s var(--ease) .28s, opacity .6s ease .28s; }
.hw-result.go .hw-badge path { stroke-dashoffset: 0; transition: stroke-dashoffset .38s cubic-bezier(.3, .55, .3, 1) .32s; }
.hw-result.go .hw-res-t, .hw-result.go .hw-res-b, .hw-result.go .hw-chips { opacity: 1; transform: none; transition: opacity .45s ease, transform .8s var(--ease); }
.hw-result.go .hw-res-t { transition-delay: .5s; }
.hw-result.go .hw-res-b { transition-delay: .62s; }
.hw-result.go .hw-chips { transition-delay: .74s; }
/* The trainer's phase approval, as the app's activity row (team.tsx). With the result played in, it drops into
   the open band under the eyebrow a beat after the words have landed. */
.hw-notes { height: 874px; background: none; }
.hw-notes.pre .hw-banner, .js:not(.ready) .hw-notes .hw-banner { opacity: 0; transform: translateY(-14px) scale(.97); }
.hw-notes.go .hw-banner { opacity: 1; transform: none; transition: transform .7s cubic-bezier(.2, .9, .25, 1.04), opacity .35s ease; }
.hw-banner {
  position: absolute; top: 104px; left: 24px; right: 24px;
  display: flex; align-items: center; gap: 12px;
  padding: 14px 18px; border-radius: 22px; background: #fff; border: 1px solid #E6EBF4;
  box-shadow: 0 14px 32px -18px rgba(20, 38, 74, .3);
  font-family: "Plus Jakarta Sans", var(--font); color: #14264A;
}
.hw-bav { width: 30px; height: 30px; border-radius: 50%; flex-shrink: 0; display: grid; place-items: center; background: #E7EFFE; color: #2A63D4; font-size: 13px; font-weight: 700; }
.hw-bt { flex: 1; min-width: 0; }
.hw-bb { display: block; font-size: 14px; line-height: 20px; }
.hw-bb b { font-weight: 700; }
.hw-bt small { display: block; margin-top: 2px; font-size: 12px; color: #8B98B3; }

.hw-stage-col { display: none; }
@media (min-width: 960px) {
  /* Without JS, large screens still read as a line of steps: copy left, its phone right */
  .hw-steps { gap: 24px; }
  .hw-step { grid-template-columns: minmax(0, 1fr) minmax(0, 520px); gap: 80px; align-items: center; }
  .hw-shot { padding: 48px 24px 28px; }

  /* Live: two columns, the phone column sticks. Each step gets well under a screen of scroll, centred on the stage. */
  /* Same 1120px box as the Levels stage above: the copy lines up with the level names (inside their 24px rail
     inset) and the stage ends on the Levels panel's right edge */
  .hw.is-live .hw-grid {
    display: grid; grid-template-columns: minmax(0, 540px) minmax(0, clamp(400px, 34vw, 500px)); column-gap: clamp(48px, 7vw, 112px);
    justify-content: space-between; max-width: 1120px; margin: 56px auto 0;
  }
  .hw.is-live .hw-steps { gap: 0; padding-left: 24px; }
  .hw.is-live .hw-step { display: flex; align-items: center; min-height: calc(var(--hw-stage-h) * .56); }
  /* The first step is tall enough that the whole phone is on screen while it is centred; the last holds the stage
     stuck until it is centred (the stage only lets go once the column's end reaches its bottom). */
  .hw.is-live .hw-step:first-child { min-height: max(calc(var(--hw-stage-h) * .72), calc(var(--hw-stage-h) - 96px)); }
  .hw.is-live .hw-step:last-child { min-height: calc(var(--hw-stage-h) + 96px); }
  .hw.is-live .hw-shot { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .hw.is-live .hw-step:not(.is-on) h3 { color: var(--gray); }
  .hw.is-live .hw-step:not(.is-on) .hw-meta .hw-n { background: rgba(31, 32, 37, .08); color: var(--gray); }

  .hw.is-live .hw-stage-col { display: block; }
  .hw-stage {
    position: sticky; top: 96px; height: var(--hw-stage-h);
    display: flex; flex-direction: column; padding: 24px 28px 0; border-radius: 32px; background: var(--cloud);
    container-type: size;
  }
  .hw-bar { display: flex; align-items: center; justify-content: space-between; gap: 16px; height: 32px; }
  /* One line tall and clipped: the old label leaves upward before the new one arrives, never both at once */
  .hw-who-roll { display: grid; height: 20px; overflow: hidden; font-size: 14px; line-height: 20px; font-weight: 500; color: var(--gray); }
  .hw-who-roll > span { grid-area: 1 / 1; white-space: nowrap; transform: translateY(100%); opacity: 0; transition: transform .45s var(--ease), opacity .12s ease; }
  .hw-pager { display: flex; gap: 2px; }
  .hw-pager button { width: 32px; height: 32px; padding: 0; border: 0; background: none; cursor: pointer; display: grid; place-items: center; }
  .hw-pager i { width: 22px; height: 4px; border-radius: 2px; background: rgba(31, 32, 37, .14); transition: background-color .3s var(--ease); }
  .hw-pager button:hover i { background: rgba(31, 32, 37, .32); }
  .hw-stage-phone { flex: 1; min-height: 0; display: grid; place-items: center; padding-bottom: 8px; }
  /* As tall as the stage allows (never cropped), at most 370px wide: 100px of the stage height goes to the label
     row and breathing room, 20px to the frame, and the screen is 402 wide for every 874 tall (.46) */
  .hw-stage .hw-phone { width: min(370px, calc((var(--hw-stage-h) - 100px) * .46 + 20px)); }
  @supports (width: 1cqh) { .hw-stage .hw-phone { width: min(370px, calc((100cqh - 100px) * .46 + 20px)); } }
  /* A dissolve: the new screen fades up over the old one, which stays put underneath until it is covered, so the
     phone never shows an empty screen between steps */
  .hw-screen {
    position: absolute; inset: 0; visibility: hidden;
    opacity: 0; transform: translateY(3%);
    transition: opacity 0s linear .45s, transform 0s linear .45s, visibility 0s linear .45s;
  }
  .hw-screen.past { transform: translateY(-3%); }
  .hw-screen.on { z-index: 1; opacity: 1; transform: none; visibility: visible; transition: opacity .3s ease, transform .5s var(--ease), visibility 0s; }
  .hw-stage[data-on="0"] .hw-who-roll > span:nth-child(1),
  .hw-stage[data-on="1"] .hw-who-roll > span:nth-child(2),
  .hw-stage[data-on="2"] .hw-who-roll > span:nth-child(3) { transform: none; opacity: 1; transition: transform .45s var(--ease) .1s, opacity .2s ease .12s; }
  .hw-stage[data-on="1"] .hw-who-roll > span:nth-child(1),
  .hw-stage[data-on="2"] .hw-who-roll > span:nth-child(-n+2) { transform: translateY(-100%); }
  .hw-stage[data-on="0"] .hw-pager button:nth-child(1) i,
  .hw-stage[data-on="1"] .hw-pager button:nth-child(2) i,
  .hw-stage[data-on="2"] .hw-pager button:nth-child(3) i { background: var(--charcoal); }
  .hw-stage.instant, .hw-stage.instant * { transition: none !important; }
}
/* Short laptop screens: the stage gives the phone every pixel of height it can (a slimmer label row, less air
   above and below), so the screens stay as large as a whole, uncropped phone allows */
@media (min-width: 960px) and (max-height: 820px) {
  .hw { --hw-stage-h: calc(100vh - 100px); }
  @supports (height: 100svh) { .hw { --hw-stage-h: calc(100svh - 100px); } }
  .hw-stage { top: 88px; padding: 12px 24px 0; }
  .hw-bar { height: 28px; }
  .hw-stage-phone { padding-bottom: 10px; }
  .hw-stage .hw-phone { width: min(370px, calc((var(--hw-stage-h) - 70px) * .46 + 20px)); }
  @supports (width: 1cqh) { .hw-stage .hw-phone { width: min(370px, calc((100cqh - 70px) * .46 + 20px)); } }
}

@media (max-width: 720px) {
  .hw-grid { margin-top: 48px; }
  .hw-steps { gap: 56px; }
  .hw-step { gap: 28px; }
  .hw-step h3 { margin-top: 16px; }
  .hw-code { gap: 6px; }
  .hw-code > span { flex: 1 1 0; max-width: 52px; height: 56px; border-radius: 14px; font-size: 23px; }
  .hw-phases { gap: 6px; }
  .hw-phases li { font-size: 12px; }
  .hw-shot { padding: 32px 16px 20px; border-radius: 28px; }
  .hw-screens { border-radius: 29px; }
  .hw-tag { padding: 5px 10px; font-size: 12px; }
  #how-title { text-wrap: balance; }
  .hw-note, .hw-text { text-wrap: pretty; }
  /* The step screens are zoomed to ~0.55-0.7 here: lift their smallest labels to ~9-11px on screen, as the
     feature cards' are (the stage's copies on large screens keep the app's own sizes) */
  .hw-step .hw-eyebrow { font-size: 14px; }
  .hw-step .hw-sub { font-size: 16px; line-height: 23px; }
  .hw-step .hw-fields small, .hw-step .hw-opt small, .hw-step .hw-side { font-size: 13.5px; }
  .hw-step .hw-chips span { font-size: 14px; }
  .hw-step .hw-foot { font-size: 14.5px; }
  .hw-step .hw-bb { font-size: 17px; line-height: 23px; }
  .hw-step .hw-bt small { font-size: 14px; }
}
/* Upright phones: each step's phone fits whole under the nav, with Safari's toolbar up or down */
@media (max-width: 720px) and (orientation: portrait) {
  .hw-phone { width: min(300px, 72vw, max(200px, calc((100svh - 100px) * .46 + 14px))); }
}
/* Phones on their side: each step's copy on the left and its whole phone beside it */
@media (min-width: 560px) and (max-width: 959px) and (orientation: landscape) and (max-height: 520px) {
  .hw-step { grid-template-columns: minmax(0, 1fr) auto; column-gap: 32px; align-items: center; }
  .hw-shot { padding: 16px 16px 12px; gap: 10px; }
  .hw-phone { width: calc((100lvh - 110px) * .46 + 14px); }
}
/* The narrowest of those (568-639 wide) leave the copy about as wide as a small phone held upright: the same
   short roster tag and roomier phase labels */
@media (min-width: 560px) and (max-width: 639px) and (orientation: landscape) and (max-height: 520px) {
  .hw-long { display: none; }
  .hw-short { display: inline; }
  .hw-phases { gap: 8px; }
  .hw-phases li { font-size: 11px; }
}
@media (max-width: 480px) {
  .hw-long { display: none; }
  .hw-short { display: inline; }
  .hw-phases li { font-size: 11.5px; letter-spacing: -0.01em; }
}
@media (max-width: 400px) {
  .hw-phases { gap: 8px; } /* "Strength" never runs into "Run" */
  .hw-phases li { font-size: 11px; }
}
@media (max-width: 359px) {
  #how-title { font-size: min(40px, 11.2vw); } /* four lines, not five */
  .hw-roster { gap: 10px; padding: 12px 12px 12px 10px; } /* "Left Achilles · Protect" stays on one line */
  .hw-av { width: 36px; height: 36px; }
}
@media (prefers-reduced-motion: reduce) {
  .hw-screen, .hw-who-roll > span, .hw-n, .hw-step h3, .hw-detail, .hw-pager i { transition: none !important; }
  .hw-input.focus .hw-caret { animation: none; }
}

/* Feature cards */
.features { padding: 40px var(--gutter) 120px; max-width: calc(var(--max) + 2 * var(--gutter)); margin: 0 auto; }
.features .lead { max-width: 760px; margin: 16px auto 0; }
.cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; margin-top: 48px; }
.card {
  display: flex; flex-direction: column; gap: 12px;
  padding: 32px 32px 0; border-radius: 32px; background: var(--cloud); overflow: hidden;
}
.card h3 { font-size: clamp(28px, 2.6vw, 36px); font-weight: 600; letter-spacing: -0.03em; line-height: 1.05; }
.card > p { font-size: 19px; line-height: 1.45; color: var(--gray); }
.card > p { margin-bottom: 8px; }
/* The screen sits on the card's bottom edge (so all three line up) and its height follows the content, set in main.js */
.card-shot {
  /* Never wider than 382px, so its height is exactly width × cardH / 402. Reserving that here (main.js only
     refines --ch) means filling in the screens never moves the page, e.g. on a load straight to #faq. */
  aspect-ratio: 402 / var(--ch, 614);
  margin: auto -16px 0;
  border-radius: 24px 24px 0 0; background: #f5f7fb;
  box-shadow: 0 0 16px -8px rgba(0,0,0,.25);
}

/* Trainers panel: its own gradient, which reads as a new chapter */
.panel {
  margin: 0 max(16px, env(safe-area-inset-right, 0px)) 0 max(16px, env(safe-area-inset-left, 0px)); border-radius: 32px;
  background: linear-gradient(180deg, var(--sky) 0%, var(--cream) 100%);
}
.trainers {
  display: grid; grid-template-columns: minmax(0, 520px) 1fr; gap: 40px; align-items: center;
  padding: 96px 0 96px clamp(24px, 6vw, 80px);
  overflow: hidden;
}
.panel-copy .lead { margin-top: 20px; }
.checks { display: grid; gap: 14px; margin: 28px 0 32px; }
.checks li { display: flex; align-items: center; gap: 12px; font-size: 18px; font-weight: 500; }
.checks span { width: 24px; height: 24px; border-radius: 50%; background: var(--charcoal); color: var(--cloud); display: grid; place-items: center; flex-shrink: 0; }
.checks svg { width: 12px; height: 12px; }
.panel-phones { display: flex; justify-content: center; align-items: flex-start; gap: 28px; padding-right: clamp(16px, 4vw, 56px); }
.panel-phones .phone { width: clamp(220px, 21vw, 300px); }
.panel-phones .phone-low { margin-top: 80px; }

/* Safety */
.safety {
  display: grid; grid-template-columns: minmax(0, 540px) 1fr; gap: clamp(40px, 6vw, 80px); align-items: center;
  max-width: calc(var(--max) + 2 * var(--gutter)); margin: 0 auto; padding: 160px var(--gutter) 80px;
}
.safety-shot { display: flex; justify-content: center; padding: 56px 24px; border-radius: 32px; background: var(--cloud); }
.safety-shot .phone { width: min(300px, 70%); }
.rules { margin-top: 40px; border-top: 1px solid var(--line); }
.rules div { padding: 20px 0; border-bottom: 1px solid var(--line); }
.rules dt { font-size: 20px; font-weight: 600; }
.rules dd { margin-top: 6px; font-size: 17px; line-height: 1.47; color: var(--gray); }

/* Check-in */
.checkin { padding: 80px var(--gutter); max-width: calc(var(--max) + 2 * var(--gutter)); margin: 0 auto; }
.checkin .lead { max-width: 720px; margin: 16px auto 0; }
/* The headline number counts down to 30 (main.js). An invisible "30" sizes the box; the live digits are centred
   in it. Before the count main.js widens the box to fit "100", and as the count starts it glides back to "30",
   so the line is centred and evenly spaced the whole time (no digit hanging out of its slot). */
.count { position: relative; display: inline-block; font-variant-numeric: tabular-nums; }
.count.go { transition: width .8s var(--ease); }
.count-hold { visibility: hidden; }
.count-n { position: absolute; left: 50%; top: 0; transform: translateX(-50%); white-space: nowrap; }
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.checkin-panel {
  margin-top: 56px; border-radius: 32px; background: var(--cloud);
  padding: 64px 48px;
  display: grid; grid-template-columns: 1fr auto 1fr; gap: 56px; align-items: center;
}
.checkin-panel .phone { width: clamp(240px, 24vw, 330px); }
.legend { display: grid; gap: 14px; justify-self: end; max-width: 320px; }
.legend li { display: flex; gap: 14px; padding: 18px; border-radius: 20px; background: #fff; }
.legend strong { display: block; font-size: 17px; font-weight: 600; }
.legend span { display: block; margin-top: 4px; font-size: 15px; line-height: 1.4; color: var(--gray); }
.dot { width: 12px; height: 12px; border-radius: 50%; margin-top: 5px; flex-shrink: 0; }
.dot-green { background: #2F9E6A; } /* the app's own status colours (theme.ts), matching the screen beside them */
.dot-yellow { background: #B27A12; }
.dot-red { background: #D9534F; }
.multi { max-width: 300px; }
.multi h3 { font-size: 28px; font-weight: 600; letter-spacing: -0.02em; line-height: 1.15; }
.multi p { margin-top: 14px; font-size: 17px; line-height: 1.47; color: var(--gray); }
.chips { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 20px; }
.chip { padding: 8px 14px; border-radius: 128px; background: #fff; font-size: 14px; font-weight: 500; white-space: nowrap; }
.chip-dark { background: var(--charcoal); color: var(--cloud); font-weight: 600; }
.chip-add { background: transparent; border: 1px dashed #b8c0cc; color: var(--gray); }

/* FAQ */
.faq {
  display: grid; grid-template-columns: minmax(0, 400px) 1fr; gap: clamp(40px, 6vw, 96px);
  max-width: calc(var(--max) + 2 * var(--gutter)); margin: 0 auto; padding: 160px var(--gutter) 120px;
}
.faq-side { align-self: start; position: sticky; top: 120px; }
.faq-side .lead { margin: 20px 0 28px; }
.faq-list { border-top: 1px solid var(--line); }
.faq-list details { border-bottom: 1px solid var(--line); }
.faq-list summary {
  display: flex; align-items: center; justify-content: space-between; gap: 24px;
  padding: 28px 0; cursor: pointer; list-style: none;
  font-size: clamp(18px, 1.6vw, 21px); font-weight: 600; letter-spacing: -0.01em;
}
.faq-list summary::-webkit-details-marker { display: none; }
.pm {
  position: relative; width: 36px; height: 36px; flex-shrink: 0;
  border-radius: 50%; background: var(--cloud); transition: background-color .25s, transform .25s;
}
.pm::before, .pm::after {
  content: ""; position: absolute; left: 50%; top: 50%;
  width: 13px; height: 1.6px; border-radius: 2px; background: var(--charcoal);
  transform: translate(-50%, -50%); transition: transform .25s;
}
.pm::after { transform: translate(-50%, -50%) rotate(90deg); }
details[open] .pm { background: var(--charcoal); }
details[open] .pm::before, details[open] .pm::after { background: var(--cloud); }
details[open] .pm::after { transform: translate(-50%, -50%) rotate(0deg); }
.faq-list details p { padding: 0 64px 28px 0; font-size: 17px; line-height: 1.5; color: var(--gray); }
summary:focus-visible { outline: 2px solid var(--charcoal); outline-offset: 4px; border-radius: 8px; }

/* Final CTA */
.cta {
  margin: 0 max(16px, env(safe-area-inset-right, 0px)) 0 max(16px, env(safe-area-inset-left, 0px)); padding: clamp(56px, 7vw, 96px) clamp(24px, 8vw, 112px);
  border-radius: 32px; background: linear-gradient(180deg, var(--sky) 0%, var(--cream) 100%);
  display: flex; align-items: center; justify-content: space-between; gap: 48px;
}
.cta-copy { max-width: 680px; }
.cta-copy .lead { margin: 24px 0 32px; max-width: 560px; }
.qr-card {
  flex-shrink: 0; display: grid; justify-items: center; gap: 16px;
  padding: 24px; border-radius: 24px; background: var(--charcoal);
  box-shadow: 0 2px 16px rgba(0,0,0,.15);
}
.qr { padding: 14px; border-radius: 16px; background: #fff; }
.qr svg { width: 168px; height: 168px; display: block; }
.qr-card p { color: var(--cloud); font-size: 15px; font-weight: 500; }

/* Footer */
.footer { max-width: calc(var(--max) + 2 * var(--gutter)); margin: 0 auto; padding: 96px var(--gutter) 48px; }
.footer-top { display: flex; justify-content: space-between; gap: 48px; }
.footer-brand { max-width: 320px; }
.footer-brand .brand img { height: 32px; }
.footer-brand p:last-child { margin-top: 12px; font-size: 16px; line-height: 1.5; color: var(--gray); }
.footer-cols { display: flex; gap: clamp(40px, 7vw, 96px); }
.footer-cols div { display: grid; gap: 16px; align-content: start; }
.footer-h { font-size: 14px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--gray); }
.footer-cols a { font-size: 18px; font-weight: 500; }
.footer-bottom { display: flex; justify-content: space-between; gap: 24px; margin-top: 64px; padding-top: 24px; border-top: 1px solid var(--line); font-size: 14px; color: var(--gray); }
.footer-bottom p:first-child { flex-shrink: 0; } /* "© 2026 Tendonly" stays on one line */

@media (prefers-reduced-motion: reduce) {
  html, html.smooth { scroll-behavior: auto; }
  .nav-links, .nav-menu .bars i { transition: none !important; }
  .phone[data-hero] { transform: none !important; opacity: 1 !important; }
  .app *, .app *::before, .app *::after { transition: none !important; animation: none !important; }
  .js .hero-phones { opacity: 1 !important; }
  .pill { transition: none; }
}

/* Tablet */
@media (max-width: 1080px) {
  .nav-links { gap: 20px; }
  .trainers { grid-template-columns: minmax(0, 1fr); padding: 72px clamp(24px, 6vw, 80px); }
  .panel-phones { padding-right: 0; }
  .safety { grid-template-columns: 1fr; padding-top: 120px; }
  /* Stacked, Safety reads heading first: eyebrow, title, then the phone, then the rules (no DOM change) */
  .safety { gap: 0; }
  .safety-copy { display: contents; }
  .safety-copy .eyebrow { order: -2; }
  #safety-title { order: -1; margin-bottom: 32px; }
  .checkin-panel { grid-template-columns: 1fr 1fr; padding: 48px 32px; }
  .checkin-panel .phone { grid-row: span 2; justify-self: center; width: clamp(300px, 34vw, 330px); }
  .legend, .multi { justify-self: start; max-width: none; }
  .faq { grid-template-columns: 1fr; padding-top: 120px; }
  .faq-side { position: static; }
}

@media (max-width: 860px) {
  .cta { flex-direction: column; align-items: flex-start; }
}

/* Feature cards: below three comfortable columns, each card turns into a row (copy left, screen right) */
@media (max-width: 1180px) {
  .cards { grid-template-columns: 1fr; max-width: 880px; margin-left: auto; margin-right: auto; gap: 16px; }
  .card { display: grid; grid-template-columns: minmax(0, 1fr) clamp(320px, 48%, 382px); column-gap: 32px; padding: 32px 32px 0; }
  .card h3, .card > p { grid-column: 1; }
  .card h3 { align-self: end; }
  .card > p { align-self: start; margin-bottom: 40px; }
  .card-shot { grid-column: 2; grid-row: 1 / span 2; margin: 0; }
}

/* Tablets and phones on their side (below the desktop layout) */
@media (max-width: 959px) {
  /* The footer's link columns get the full width instead of squeezing in beside the brand */
  .footer-top { flex-direction: column; }
  .footer-cols { flex-wrap: wrap; }
}
/* Small laptops and tablets on their side: the columns still sit beside the brand, so no link breaks mid-phrase */
@media (min-width: 960px) and (max-width: 1279px) {
  .footer-cols { gap: 32px 40px; }
  .footer-cols a { white-space: nowrap; }
}
@media (min-width: 721px) and (max-width: 959px) {
  .panel-phones .phone { width: clamp(220px, 34vw, 300px); }
}
/* Touch screens wide enough for the inline section links (phones on their side, tablets): each link gets a 44px
   tall hit area at the same look (mouse desktops don't match) */
@media (pointer: coarse) and (min-width: 721px) {
  .nav-links a { padding: 12px 0; margin: -12px 0; }
  /* The logo and Book a demo too, and the nav stays 60px tall (8 + 44 + 8) */
  .nav { padding: 8px 8px 8px 24px; }
  .nav .brand { min-height: 44px; }
  .nav > .pill-sm { padding-top: 12px; padding-bottom: 12px; }
  /* Each footer link is a 45px row to tap, as on phones */
  .footer-cols div { gap: 0; }
  .footer-h { margin-bottom: 4px; }
  .footer-cols a { padding: 12px 0; }
}
/* Phones on their side can't scan their own screen either */
@media (pointer: coarse) and (max-height: 540px) {
  .qr-card { display: none; }
}
/* Phones on their side keep the phone spacing between sections: on a screen under 440px tall, the desktop's
   120-200px gaps would fill most of the view */
@media (max-width: 959px) and (orientation: landscape) and (max-height: 540px) {
  .features { padding-bottom: 48px; }
  .safety { padding: 80px var(--gutter) 16px; }
  .checkin { padding: 40px var(--gutter) 24px; }
  .faq { padding-top: 72px; padding-bottom: 96px; }
  .footer { padding-top: 72px; }
}

/* Phone */
@media (max-width: 720px) {
  .cards { max-width: 560px; }
  .card { display: flex; padding: 24px 20px 0; } /* the screen keeps an 8px rim: the card's width less 16px */
  .card h3 { align-self: auto; text-wrap: balance; }
  .card > p { margin-bottom: 8px; text-wrap: balance; text-wrap: pretty; } /* no one-word last lines */
  /* The screen keeps its own height (not stretched to the frame), so main.js measures what it really needs.
     The reserve starts at what phones measure (616-619), so that check barely moves the page. */
  .card-shot { align-self: center; width: min(calc(100% + 24px), 382px); margin: auto 0 0; align-items: flex-start; --ch: 618; }
  /* Section links fold into a small menu under the nav pill. Every control is a 44px touch target and the nav
     stays 60px tall (8 + 44 + 8), as on large screens; nothing in the row is ever squeezed out of shape. */
  .nav { position: relative; padding: 8px 8px 8px 20px; }
  .brand, .nav-menu, .nav > .pill { flex-shrink: 0; }
  .brand { min-height: 44px; }
  .nav > .pill-sm { padding: 12px 18px; }
  .nav-menu {
    display: grid; place-items: center; margin: 0 8px 0 auto;
    width: 44px; height: 44px; padding: 0; border: 0; border-radius: 50%; cursor: pointer;
    background: rgba(31,32,37,.06); color: var(--charcoal);
  }
  .nav-menu .bars { position: relative; width: 16px; height: 12px; }
  .nav-menu .bars i {
    position: absolute; left: 0; top: 5.2px; width: 16px; height: 1.6px; border-radius: 2px; background: currentColor;
    transition: transform .35s var(--ease);
  }
  .nav-menu .bars i:first-child { transform: translateY(-3.5px); }
  .nav-menu .bars i:last-child { transform: translateY(3.5px); }
  .nav.open .nav-menu .bars i:first-child { transform: rotate(45deg); }
  .nav.open .nav-menu .bars i:last-child { transform: rotate(-45deg); }
  .nav-links {
    position: absolute; left: 0; right: 0; top: calc(100% + 8px);
    flex-direction: column; gap: 2px; padding: 8px; border-radius: 24px;
    background: #fff; /* opaque: a backdrop blur inside the nav pill's own blur can't reach the page */
    box-shadow: 0 16px 40px -16px rgba(31,32,37,.3), 0 0 0 1px rgba(31,32,37,.04);
    visibility: hidden; opacity: 0; transform: translateY(-6px) scale(.98); transform-origin: 50% 0;
    transition: opacity .2s ease, transform .35s var(--ease), visibility 0s linear .35s;
  }
  .nav.open .nav-links { visibility: visible; opacity: 1; transform: none; transition-delay: 0s; }
  /* While it fades out it still shows for a moment, but a tap there must reach the page, not a hidden link */
  .nav-links { pointer-events: none; }
  .nav.open .nav-links { pointer-events: auto; }
  .nav-links a { padding: 14px 16px; border-radius: 16px; font-size: 17px; color: var(--ink); }
  .nav-links a:hover, .nav-links a:focus-visible { background: var(--cloud); }
  .panel, .cta { margin: 0 max(8px, env(safe-area-inset-right, 0px)) 0 max(8px, env(safe-area-inset-left, 0px)); }
  /* The first screen shows the product: a tighter top, a two-line headline, both pills on one row (from about
     360px) and the phones starting well inside the first screen. The band itself runs to the screen's edges. */
  .hero { padding-top: 32px; }
  .hero-title { font-size: min(40px, 10vw); text-wrap: balance; }
  .hero-lead { margin: 16px auto 24px; }
  .hero .actions { gap: 10px; }
  .hero .actions .pill { padding-inline: 16px; }
  .hero-note { text-wrap: balance; }
  /* Side phones tuck behind the centre one. --peek is how much of each shows past it: as much as fits
     24px inside the band edge (main.js lets them out to 16px), at most 45% of the phone, so they always show
     and never get cropped. This is the fully separated pose; main.js tucks the sides further in at rest and
     releases them on scroll. The centre phone is kept to 60vw so that release has real room on a phone. */
  .hero-phones {
    gap: 0; margin-top: 40px; --mw: min(300px, 60vw); --sw: min(220px, 47vw);
    --peek: min(calc((100vw - var(--mw)) / 2 - 24px - var(--safe-x)), calc(var(--sw) * .45));
  }
  .phone-main { width: var(--mw); position: relative; z-index: 2; }
  .phone-side { width: var(--sw); margin-top: 72px; }
  .phone-side:first-child { margin-right: calc(var(--peek) - var(--sw)); }
  .phone-side:last-child { margin-left: calc(var(--peek) - var(--sw)); }
  .how { padding-top: 96px; }
  .features { padding-bottom: 48px; } /* the band's stops count from its end, so its colours don't move */
  .trainers { padding-top: 56px; }
  /* The roster and the athlete screen stack, each as large as the check-in phone, so both can be read */
  .panel-phones { flex-direction: column; align-items: center; gap: 24px; }
  .panel-phones .phone { width: min(300px, 78vw); }
  .panel-phones .phone-low { margin-top: 0; }
  /* Each check sits on its item's first line when the item wraps */
  .checks li { align-items: flex-start; line-height: 24px; }
  /* Safety opens with its heading (eyebrow, title, then the phone, then the rules) at less of the desktop spacing */
  .safety { padding: 80px var(--gutter) 16px; }
  .safety-shot { padding: 40px 20px; }
  .safety-shot .phone, .checkin-panel .phone { width: min(300px, 78vw, 100%); }
  .rules dt, .checkin .lead { text-wrap: balance; }
  .legend span, .rules dd { text-wrap: pretty; }
  /* No one-word last lines: short items even out their lines (balance, which iOS Safari has had since 17.5),
     paragraphs keep a word or two company on the last one */
  .checks li, .faq-list summary, .checkin-panel h3, .footer-cols a { text-wrap: balance; }
  .lead, .faq-list details p, .footer-brand p, .footer-bottom p { text-wrap: pretty; }
  .checkin { padding: 40px var(--gutter) 24px; }
  .checkin-panel { grid-template-columns: 1fr; padding: 40px 20px; gap: 32px; }
  .checkin-panel .phone { grid-row: auto; }
  .faq { padding-top: 72px; padding-bottom: 96px; }
  .faq-list summary { -webkit-tap-highlight-color: transparent; }
  .qr-card { display: none; } /* a phone can't scan its own screen */
  .footer { padding-top: 72px; }
  .footer-top { flex-direction: column; }
  /* Each footer link is a 45px row to tap, at the same look */
  .footer-cols div { gap: 0; }
  .footer-h { margin-bottom: 4px; }
  .footer-cols a { padding: 12px 0; }
  .footer-bottom { margin-top: 32px; }
  .footer-bottom p:last-child { line-height: 1.5; }
  .display br { display: none; }
  #checkin-title br { display: inline; }
  #checkin-title { font-size: min(40px, 11.2vw); }
  #trainers-title br { display: inline; }
  #trainers-title { font-size: min(36px, 9.6vw); }
  #features-title { font-size: min(40px, 10.4vw); text-wrap: balance; }
  #cta-title { font-size: min(44px, 9.6vw); text-wrap: balance; } /* "Start the / comeback today." */
  .phone { padding: 7px; border-radius: 36px; }
  .phone img { border-radius: 29px; }
  .phone::after { top: 14px; }
  .phone.phone-live .live-wrap { border-radius: 29px; } /* matches the frame (36 - 7), as .phone img; must outrank the 40px base rule below */
  .footer-cols { flex-wrap: wrap; gap: 32px 48px; }
  .footer-bottom { flex-direction: column; }
  .faq-list details p { padding-right: 0; }
}
/* The narrowest phones (320px, or Display Zoom): the nav row needs a little more room to keep a clear gap */
@media (max-width: 359px) {
  .nav-wrap { padding: 0 10px; }
  .nav { padding-left: 16px; }
  .brand img { height: 22px; }
  .nav > .pill-sm { padding: 12px 14px; }
}
/* 200% text zoom on a phone (Safari's aA menu lays the page out about 195px wide) and other very narrow windows:
   nothing may run off the screen. Real phones are never this narrow. */
@media (max-width: 300px) {
  .nav > .pill-sm { display: none; } /* Book a demo is in the page further down */
  .display-md, .display-xl { font-size: 12.5vw; }
  .eyebrow { letter-spacing: .04em; } /* "ORGANIZATIONS" fits the line */
  .pill { white-space: normal; text-align: center; }
  .hw-step { grid-template-columns: minmax(0, 1fr); }
  .hw-code > span { min-width: 0; font-size: 18px; }
  .hw-phases { grid-template-columns: repeat(3, minmax(0, 1fr)); row-gap: 12px; }
  .hw-tag { display: none; }
}


/* ---------- Hero phones: transforms are driven by main.js (entrance + scroll) ---------- */
.phone[data-hero] { will-change: transform; }
/* Side phones pivot on their outer top corner, so tilting never pushes them past the band edge */
.phone[data-hero="left"] { transform-origin: 0 0; }
.phone[data-hero="right"] { transform-origin: 100% 0; }
.phone[data-hero="center"] { z-index: 2; }
.js .hero-phones { opacity: 0; }
/* Phones: the hero phones show from the first paint, already in main.js's resting pose (each side phone tucked in
   behind the centre one by what main.js computes: --peek less what shows of it, the larger of 24px and 70% of
   --peek), and fade in once, so the first screen never waits on the script. main.js takes over from the same pose
   for the scroll and switches the fade off once it has played (a rotation back to this layout never replays it). */
@media (max-width: 720px) {
  .hero-phones { --rest: max(0px, var(--peek) - max(24px, var(--peek) * .7)); }
  .hero-phones .phone-side:first-child { transform: translateX(var(--rest)); }
  .hero-phones .phone-side:last-child { transform: translateX(calc(-1 * var(--rest))); }
  .js .hero-phones { opacity: 1; animation: hero-in .7s cubic-bezier(.16, 1, .3, 1) both; }
}
@keyframes hero-in { from { opacity: 0; } }
@media (max-width: 720px) and (prefers-reduced-motion: reduce) {
  .js .hero-phones { animation: none; }
}

/* ---------- Live app UI (copies of the app's screens, laid out at its 402px width and zoomed to fit) ---------- */
.live-wrap { position: relative; overflow: hidden; display: flex; justify-content: center; }
.phone-live .live-wrap { aspect-ratio: 402 / 874; border-radius: 40px; }
.live { position: relative; flex-shrink: 0; width: 402px; zoom: var(--z, .8); }
/* Until main.js sets the exact zoom (or with scripts off), a phone's screen still fits inside its frame: the zoom
   steps down with the frame's width, 10px at a time, and the screen's own colour fills the sliver it leaves */
.phone-live .live-wrap, .hw-screens .live-wrap { container: live / inline-size; }
.phone-live .live, .hw-screens .live { zoom: var(--z, var(--zf, 1)); }
/* The feature cards' screens too (their frame is at most 382px wide, so they start from the step for that) */
.card-shot { container: live / inline-size; }
.card-shot .live { zoom: var(--z, var(--zf, .945)); }
.phone-live .live-wrap { background: #F5F7FB; }
.phone-live .live-wrap:has(> #live-checkin) { background: #fff; }
@container live (max-width: 400px) { .live { --zf: 0.970; } }
@container live (max-width: 390px) { .live { --zf: 0.945; } }
@container live (max-width: 380px) { .live { --zf: 0.920; } }
@container live (max-width: 370px) { .live { --zf: 0.895; } }
@container live (max-width: 360px) { .live { --zf: 0.870; } }
@container live (max-width: 350px) { .live { --zf: 0.845; } }
@container live (max-width: 340px) { .live { --zf: 0.820; } }
@container live (max-width: 330px) { .live { --zf: 0.796; } }
@container live (max-width: 320px) { .live { --zf: 0.771; } }
@container live (max-width: 310px) { .live { --zf: 0.746; } }
@container live (max-width: 300px) { .live { --zf: 0.721; } }
@container live (max-width: 290px) { .live { --zf: 0.696; } }
@container live (max-width: 280px) { .live { --zf: 0.671; } }
@container live (max-width: 270px) { .live { --zf: 0.646; } }
@container live (max-width: 260px) { .live { --zf: 0.621; } }
@container live (max-width: 250px) { .live { --zf: 0.597; } }
@container live (max-width: 240px) { .live { --zf: 0.572; } }
@container live (max-width: 230px) { .live { --zf: 0.547; } }
@container live (max-width: 220px) { .live { --zf: 0.522; } }
@container live (max-width: 210px) { .live { --zf: 0.497; } }
@container live (max-width: 200px) { .live { --zf: 0.472; } }
@container live (max-width: 190px) { .live { --zf: 0.447; } }
@container live (max-width: 180px) { .live { --zf: 0.422; } }
@container live (max-width: 170px) { .live { --zf: 0.398; } }
@container live (max-width: 160px) { .live { --zf: 0.373; } }
@container live (max-width: 150px) { .live { --zf: 0.348; } }
@container live (max-width: 140px) { .live { --zf: 0.323; } }
@container live (max-width: 130px) { .live { --zf: 0.298; } }
@container live (max-width: 120px) { .live { --zf: 0.273; } }
@container live (max-width: 110px) { .live { --zf: 0.248; } }
@container live (max-width: 100px) { .live { --zf: 0.223; } }
.card-shot .live { height: calc(var(--ch, 614) * 1px); }
.live.scaled { position: absolute; top: 0; left: 0; zoom: normal; transform-origin: 0 0; } /* fallback where CSS zoom is missing */
.app {
  /* muted and faint run a step darker than the app's (#6B7A99, #8B98B3) so the small labels keep 4.5:1 here */
  --a-ink: #14264A; --a-muted: #56647F; --a-faint: #62708C; --a-ghost: #B8C3D9; --a-line: #E6EBF4; --a-soft: #EEF2F8;
  --a-border: #DDE4F0; --a-blue: #3D7BF7; --a-blue-deep: #2A63D4; --a-blue-tint: #E7EFFE; --a-green: #2F9E6A; --a-red: #D9534F;
  font-family: "Plus Jakarta Sans", var(--font); font-weight: 400; color: var(--a-ink); background: #F5F7FB;
  padding: 24px 20px 20px; overflow: hidden;
  font-kerning: normal; text-rendering: geometricPrecision;
}
.app b { font-weight: 700; }
.a-kicker { padding: 0 4px; font-size: 12.5px; font-weight: 600; color: var(--a-muted); }
.a-h1 { margin-top: 2px; padding: 0 4px; font-size: 28px; line-height: 32px; font-weight: 800; letter-spacing: -0.84px; }
.a-sub { margin-top: 10px; font-size: 14.5px; line-height: 22px; color: var(--a-muted); }
.a-sub-sm { margin-top: 6px; padding: 0 4px; font-size: 13.5px; line-height: 20px; }
.a-card { background: #fff; border: 1px solid var(--a-line); border-radius: 22px; }

/* Session (session.tsx) */
.a-list { margin-top: 16px; padding: 4px 14px; }
.js .a-row { opacity: 0; transform: translateY(14px); }
/* A card that left the screen rewinds in one frame, never by running its transitions backwards */
.rewind, .rewind *, .rewind *::before, .rewind *::after { transition: none !important; }
.a-row { display: flex; align-items: center; gap: 12px; padding: 12px 0; border-bottom: 1px solid var(--a-soft); }
.a-row:last-child { border-bottom: 0; }
.a-thumb { width: 64px; height: 44px; border-radius: 12px; flex-shrink: 0; background: repeating-linear-gradient(135deg, #E6EBF4 0 6px, #F3F6FB 6px 12px); } /* the app's 12pt VideoPlaceholder stripes */
.a-txt { flex: 1; }
.a-txt b { display: block; font-size: 14.5px; text-decoration: line-through transparent; transition: color .35s, text-decoration-color .25s ease .18s; }
.a-txt small { display: block; margin-top: 2px; font-size: 12px; color: var(--a-muted); }
.a-row.done .a-txt b { color: var(--a-faint); text-decoration-color: currentColor; } /* the strike follows the check */
.a-check, .a-box { position: relative; width: 22px; height: 22px; border-radius: 50%; border: 2px solid var(--a-border); flex-shrink: 0; transition: background-color .35s var(--ease), border-color .35s var(--ease); }
.a-check::after, .a-box::after { content: ""; position: absolute; inset: -2px; background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2.5 6.2l2.3 2.3 4.7-5' fill='none' stroke='%23fff' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / 54% no-repeat; transform: scale(0); transition: transform .4s cubic-bezier(.34, 1.56, .64, 1) .05s; }
.a-row.done .a-check, .a-meal.on .a-box { background: var(--a-ink); border-color: var(--a-ink); }
.a-row.done .a-check::after, .a-meal.on .a-box::after { transform: scale(1); }
#live-session { display: flex; flex-direction: column; }
#live-session .a-list { margin-bottom: 20px; }
.a-go { display: block; margin-top: auto; height: 54px; line-height: 54px; border-radius: 999px; background: var(--a-ink); color: #fff; text-align: center; font-size: 15px; font-weight: 700; }
.a-go > .roll { display: grid; }
.a-go .roll .roll { justify-items: center; font-variant-numeric: tabular-nums; } /* only the count rolls */
.play .a-row { animation: rowIn .8s var(--ease) forwards; }
@keyframes rowIn { to { opacity: 1; transform: none; } }

/* Fuel (fuel.tsx) */
.a-protein { display: flex; align-items: center; gap: 20px; margin-top: 14px; padding: 20px; border-radius: 26px; }
.a-protein > div:last-child { flex: 1; }
.a-protein > div:last-child b { font-size: 16px; }
.a-protein > div:last-child small { display: block; margin-top: 4px; font-size: 13px; line-height: 19px; color: var(--a-muted); }
.a-ring { position: relative; width: 120px; height: 120px; flex-shrink: 0; }
.a-ring svg { width: 100%; height: 100%; transform: rotate(-90deg); }
.ring-track, .ring-fill { fill: none; stroke-width: 12; }
.ring-track { stroke: var(--a-soft); }
.ring-fill { stroke: var(--a-blue); stroke-dasharray: 339.29; stroke-dashoffset: 339.29; }
.a-ring span { position: absolute; inset: 0; display: grid; place-content: center; text-align: center; }
.a-ring b { font-size: 26px; line-height: 28px; font-weight: 800; letter-spacing: -0.8px; font-variant-numeric: tabular-nums; }
.a-ring small { font-size: 11px; font-weight: 600; color: var(--a-muted); }
.a-meals { margin-top: 14px; padding: 4px 18px; }
.a-meal { display: flex; align-items: center; gap: 12px; padding: 13px 0; border-bottom: 1px solid var(--a-soft); }
.a-meal:last-child { border-bottom: 0; }
.a-meal .a-box { width: 24px; height: 24px; }
.a-meal b { flex: 1; font-size: 14.5px; font-weight: 600; text-decoration: line-through transparent; transition: color .35s, text-decoration-color .25s ease .18s; }
.a-meal.on b { color: var(--a-faint); text-decoration-color: currentColor; }
.a-meal small { font-size: 13px; font-weight: 600; color: var(--a-muted); }
.a-meal small i { font-style: normal; }
.a-meal.on small i { display: none; }
.a-pair { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-top: 14px; }
.a-meter { padding: 16px; }
.a-meter small { display: block; font-size: 12px; line-height: 15px; font-weight: 600; color: var(--a-muted); }
.a-meter > b { display: block; margin-top: 2px; font-size: 20px; font-weight: 800; letter-spacing: -0.4px; font-variant-numeric: tabular-nums; }
.a-meter i { font-style: normal; font-size: 13px; font-weight: 600; letter-spacing: 0; color: var(--a-faint); }
.a-segs { display: flex; gap: 4px; margin-top: 12px; }
.a-segs span { position: relative; flex: 1; height: 14px; border-radius: 4px; background: var(--a-soft); overflow: hidden; }
.a-segs span::after { content: ""; position: absolute; inset: 0; border-radius: inherit; transform: scaleX(0); transform-origin: left; transition: transform .42s cubic-bezier(.5, 0, .2, 1); }
.a-segs.blue span::after { background: var(--a-blue); }
.a-segs.green span::after { background: var(--a-green); }
.a-segs span.on::after { transform: none; }

/* Road back (road.tsx) */
#live-road { background: linear-gradient(180deg, #EAF0FA 0%, #F7F9FC 40%); }
/* The phase list runs past the frame like the app's scroll view: fade it out rather than slicing a line of text */
#live-road { -webkit-mask-image: linear-gradient(#000 calc(100% - 56px), transparent); mask-image: linear-gradient(#000 calc(100% - 56px), transparent); }
/* A roll is one grid cell: every string it can show sits in it (hidden sizers), so its size never changes,
   and it clips so the outgoing line leaves upward out of view as the new one rises in. */
.roll { display: inline-grid; vertical-align: top; overflow: hidden; }
.roll > span { grid-area: 1 / 1; white-space: nowrap; }
.roll > span.sz { visibility: hidden; }
.roll > span.out { pointer-events: none; }
.road-n, .road-day { justify-items: center; }
p.roll { display: grid; }
p.roll > span { white-space: normal; }
.a-stepper { position: relative; margin-top: 14px; padding: 18px 16px 14px; border-radius: 26px; }
.a-rail { position: absolute; left: 44px; right: 44px; top: 33px; height: 3px; background: var(--a-border); }
.a-rail-fill { position: absolute; inset: 0; background: var(--a-ink); transform: scaleX(0); transform-origin: left; transition: transform .42s cubic-bezier(.65, 0, .35, 1); }
.a-nodes { position: relative; display: flex; justify-content: space-between; }
.a-node { display: grid; justify-items: center; gap: 8px; width: 56px; }
.a-node i {
  position: relative; width: 32px; height: 32px; border-radius: 50%; display: grid; place-items: center;
  font-style: normal; font-size: 12px; color: var(--a-ghost);
  background: #fff; box-shadow: inset 0 0 0 2px var(--a-border);
  transition: background-color .5s var(--ease), box-shadow .5s var(--ease), color .3s;
}
.a-node i b { grid-area: 1 / 1; display: grid; place-items: center; font-weight: 800; transition: opacity .3s, transform .45s var(--ease); }
.a-node i svg { width: 15px; height: 15px; }
.a-node i b + b { opacity: 0; transform: scale(.4); }
.a-node small { font-size: 11px; font-weight: 700; color: var(--a-faint); transition: color .4s; } /* a step up from the app's 10px ghost: it's shown shrunk here */
.a-node.done i { background: var(--a-ink); box-shadow: inset 0 0 0 0 var(--a-ink); color: #fff; }
.a-node.done i b:first-child { opacity: 0; transform: scale(.4); }
.a-node.done i b + b { opacity: 1; transform: none; }
.a-node.done small { color: var(--a-muted); }
.a-node.cur i { background: var(--a-blue); box-shadow: 0 0 0 6px var(--a-blue-tint); color: #fff; }
.a-node.cur small { color: var(--a-blue-deep); }
.a-phase { margin-top: 14px; padding: 18px 20px; border-radius: 24px; background: var(--a-ink); color: #fff; box-shadow: 0 14px 36px rgba(20, 38, 74, .2); }
.a-phase-top { display: flex; align-items: center; justify-content: space-between; }
.a-phase-top b { font-size: 18px; font-weight: 800; letter-spacing: -0.4px; }
.a-pill { padding: 5px 10px; border-radius: 999px; background: rgba(255,255,255,.14); font-size: 11px; font-weight: 700; }
.road-goal { margin-top: 4px; font-size: 13px; line-height: 19px; color: rgba(255,255,255,.65); }
.a-gates { display: grid; grid-auto-rows: 1fr; gap: 6px; margin-top: 14px; } /* equal rows: two of the five phases' tests wrap */
.a-gate { display: flex; align-items: center; gap: 12px; padding: 12px 14px; border-radius: 14px; background: rgba(255,255,255,.06); box-shadow: inset 0 0 0 1px transparent; font-size: 13.5px; font-weight: 600; color: rgba(255,255,255,.7); transition: background-color .4s, box-shadow .4s, color .4s; }
.a-gate .roll { display: grid; flex: 1; min-width: 0; }
/* Each line fills the whole cell (so a roll moves it by a full box height) and centres its text in it */
.a-gate .roll > span { white-space: normal; display: flex; align-items: center; }
.a-gc { position: relative; width: 20px; height: 20px; border-radius: 50%; flex-shrink: 0; box-shadow: inset 0 0 0 2px rgba(255,255,255,.25); transition: background-color .35s var(--ease), box-shadow .35s; }
.a-gc::after { content: ""; position: absolute; inset: 0; background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2.5 6.2l2.3 2.3 4.7-5' fill='none' stroke='%2314264A' stroke-width='2.1' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / 62% no-repeat; transform: scale(0); transition: transform .18s cubic-bezier(.4, 0, 1, 1); }
.a-gate em { opacity: 0; transform: translateX(-4px); transition: opacity .5s var(--ease), transform .5s var(--ease); font-style: normal; font-size: 11px; font-weight: 700; color: #9DBDFF; }
.a-gate.ok { background: rgba(255,255,255,.08); color: rgba(255,255,255,.6); }
.a-gate.ok .a-gc { background: #fff; box-shadow: inset 0 0 0 2px #fff; }
.a-gate.ok .a-gc::after { transform: none; transition: transform .35s cubic-bezier(.34, 1.56, .64, 1); } /* springs in, never overshoots on the way out */
.a-gate.next { background: rgba(255,255,255,.14); box-shadow: inset 0 0 0 1px rgba(255,255,255,.18); color: #fff; }
.a-gate.next .a-gc { box-shadow: inset 0 0 0 2px #6FA0FF; }
.a-gate.next .roll { font-weight: 700; }
.a-gate.next em { opacity: 1; transform: none; } /* always in the layout, so nothing reflows when it appears */
/* Only the first test can become the next one; the others get the full row width, as in road.tsx */
.a-gate:not(:first-child) em { display: none; }
.a-action { display: block; margin-top: 14px; padding: 12px; border-radius: 999px; background: #fff; color: var(--a-ink); text-align: center; font-size: 13.5px; font-weight: 700; }
.a-plist { margin-top: 14px; padding: 4px 18px; }
.a-pl { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding: 12px 0; border-bottom: 1px solid var(--a-soft); }
.a-pl:last-child { border-bottom: 0; }
.a-pl b { font-size: 14px; color: var(--a-ghost); transition: color .4s; }
.a-pl.done b { color: var(--a-muted); }
.a-pl small { justify-items: end; font-size: 12px; font-weight: 600; color: var(--a-faint); }

/* Check-in screen (checkin.tsx): white screen, grey status bar */
#live-checkin { background: #fff; }
.a-screen { height: 874px; display: flex; flex-direction: column; padding: 0 24px 28px; }
.a-status { display: flex; justify-content: space-between; align-items: center; height: 62px; margin: 0 -24px; padding: 0 22px 0 52px; background: #F5F7FB; font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", var(--font); font-size: 17px; color: #0a0a0b; }
.a-status b { font-weight: 600; }
.a-sicons { display: block; }
.a-stephead { display: flex; align-items: center; gap: 14px; margin-top: 32px; }
.a-x { width: 36px; height: 36px; border-radius: 50%; display: grid; place-items: center; background: #F5F7FB; font-size: 18px; line-height: 20px; color: var(--a-muted); }
.a-prog { flex: 1; display: flex; gap: 6px; }
.a-prog i { flex: 1; height: 4px; border-radius: 2px; background: var(--a-line); }
.a-prog i.on { background: var(--a-blue); }
.a-stephead small { font-size: 12px; font-weight: 600; color: var(--a-faint); }
.a-q { margin-top: 40px; font-size: 28px; font-weight: 800; letter-spacing: -0.84px; line-height: 32px; }
.a-big { margin-top: auto; display: flex; align-items: baseline; justify-content: center; gap: 4px; }
.a-big b { font-size: 112px; font-weight: 800; letter-spacing: -6px; line-height: 118px; color: var(--a-blue); font-variant-numeric: tabular-nums; } /* colour snaps at 7, as in the app: a crossfade passes through violet */
.a-big small { font-size: 22px; font-weight: 600; color: var(--a-ghost); }
.a-word { align-self: center; margin: 6px 0 auto; padding: 7px 14px; border-radius: 999px; background: var(--a-blue-tint); color: var(--a-blue-deep); font-size: 13px; font-weight: 700; }
.app.hot .a-big b { color: var(--a-red); }
.app.hot .a-word { background: #FBEDEC; color: #A63A36; }
.a-nums { display: flex; justify-content: space-between; padding: 0 2px; }
.a-nums span { width: 28px; height: 36px; display: grid; place-items: center; border-radius: 10px; font-size: 14px; font-weight: 600; color: var(--a-faint); }
.a-nums span.on { background: var(--a-blue); color: #fff; font-weight: 800; box-shadow: 0 6px 16px rgba(61,123,247,.35); }
.a-track { position: relative; display: flex; height: 6px; margin: 10px 2px 0; }
.a-track .t1 { flex: 6; background: var(--a-blue-tint); border-radius: 3px 0 0 3px; }
.a-track .t2 { flex: 3; background: var(--a-border); }
.a-track .t3 { flex: 2; background: #F3D9D8; border-radius: 0 3px 3px 0; }
.a-knob { position: absolute; inset: 0; will-change: transform; } /* translated by a share of the track's own width */
.a-thumb-dot { position: absolute; top: -5px; left: -8px; width: 16px; height: 16px; border-radius: 50%; background: #fff; border: 3px solid var(--a-blue); }
.a-last { margin-top: 18px; text-align: center; font-size: 12.5px; color: var(--a-faint); }
.a-cta { margin-top: 20px; height: 54px; border-radius: 999px; display: grid; place-items: center; background: var(--a-ink); color: #fff; font-size: 15px; font-weight: 700; }

/* Trainer home (coach/index.tsx, components/staff.tsx). The status bar stays put and the page under it scrolls:
   main.js drags the roster down to Dana's code and back up once it is in view. */
.co { padding: 0 20px; }
.co .a-status { margin: 0 -20px; }
.co-view { position: relative; flex: 1; min-height: 0; margin: 0 -20px; overflow: hidden; }
.co-list { display: grid; grid-template-columns: minmax(0, 1fr); gap: 12px; padding: 10px 20px 50px; } /* long lines ellipsize, never widen the page */
.co-hi { padding: 0 4px; }
.co-hi small { display: block; font-size: 12.5px; font-weight: 600; color: var(--a-muted); }
.co-hi .a-h1 { padding: 0; }
.co-stats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
.co-stats .a-card { padding: 14px; }
.co-stats b { display: block; font-size: 24px; line-height: 30px; font-weight: 800; letter-spacing: -0.6px; }
.co-stats b.is-blue { color: var(--a-blue-deep); }
.co-stats small { display: block; margin-top: 2px; font-size: 11.5px; font-weight: 600; color: var(--a-muted); }
.co-label { display: flex; align-items: center; padding: 8px 4px 0; font-size: 12px; font-weight: 700; letter-spacing: .7px; color: var(--a-muted); }
.co-label span { margin-left: auto; font-weight: 400; letter-spacing: 0; color: var(--a-faint); }
.co-card { padding: 2px 16px; }
.co-row { display: flex; align-items: center; gap: 12px; padding: 12px 0; border-bottom: 1px solid var(--a-soft); }
.co-row:last-child { border-bottom: 0; }
.co-av {
  position: relative; width: 38px; height: 38px; border-radius: 50%; flex-shrink: 0; display: grid; place-items: center;
  background: var(--a-blue-tint); color: var(--a-blue-deep); font-size: 13px; font-weight: 700;
}
/* Today's check-in: green, yellow, or not in yet */
.co-av i { position: absolute; right: -1px; bottom: -1px; width: 12px; height: 12px; border-radius: 50%; border: 2px solid #fff; background: var(--a-border); }
.co-av i.g { background: var(--a-green); }
.co-av i.y { background: #E0A526; }
.co-who { flex: 1; min-width: 0; }
.co-who b, .co-who small { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.co-who b { font-size: 14.5px; }
.co-who small { margin-top: 1px; font-size: 12px; color: var(--a-muted); }
.co-go { font-size: 18px; color: var(--a-ghost); }
.co-pill { flex-shrink: 0; padding: 5px 10px; border-radius: 999px; background: var(--a-blue-tint); color: var(--a-blue-deep); font-size: 11px; font-weight: 700; }
.co-code { margin-top: 4px; padding: 16px; border-radius: 22px; background: var(--a-ink); color: #fff; }
.co-code small { display: block; font-size: 11px; font-weight: 700; letter-spacing: .8px; color: rgba(255, 255, 255, .6); }
.co-code b { display: block; margin-top: 6px; font-size: 24px; line-height: 30px; font-weight: 800; letter-spacing: 2px; }
.co-code p { margin-top: 4px; font-size: 11.5px; line-height: 16px; color: rgba(255, 255, 255, .55); }
.co-code span { display: block; margin-top: 12px; padding: 8px; border-radius: 999px; background: #fff; color: var(--a-ink); text-align: center; font-size: 12px; font-weight: 700; }
.co-switch { padding: 10px 0; text-align: center; font-size: 12px; font-weight: 600; color: var(--a-faint); }
/* The scroll indicator iOS shows only while the page moves */
.co-bar { position: absolute; top: 0; right: 3px; width: 3px; border-radius: 2px; background: rgba(20, 38, 74, .35); opacity: 0; transition: opacity .4s ease; }
.co-bar.on { opacity: 1; transition-duration: .12s; }

/* Athlete's Team tab ((tabs)/team.tsx, Toggle in components/ui.tsx). main.js flips the sharing switches on and
   off once it is in view. */
.tm { gap: 12px; padding: 0 20px; }
.tm .a-status { margin: 0 -20px; }
.tm-h1 { margin-top: -2px; }
.tm-card { padding: 18px; border-radius: 24px; }
.tm-row { display: flex; align-items: center; gap: 14px; }
.tm-av { width: 48px; height: 48px; border-radius: 50%; flex-shrink: 0; display: grid; place-items: center; background: var(--a-blue-tint); color: var(--a-blue-deep); font-size: 16px; font-weight: 700; }
.tm-av.is-plain { background: #F5F7FB; color: var(--a-muted); }
.tm-who { flex: 1; min-width: 0; }
.tm-who b { display: block; font-size: 16px; }
.tm-who small { display: block; margin-top: 1px; font-size: 12.5px; color: var(--a-muted); }
.tm-pill { padding: 5px 10px; border-radius: 999px; background: #F5F7FB; color: var(--a-muted); font-size: 11px; font-weight: 700; }
.tm-pill.is-green { background: #E3F5EC; color: #22794F; }
.tm-btns { display: flex; gap: 8px; margin-top: 14px; }
.tm-btns span { flex: 1; padding: 10px 16px; border-radius: 999px; background: var(--a-ink); color: #fff; text-align: center; font-size: 12.5px; line-height: 16px; font-weight: 700; }
.tm-btns .is-soft { background: #F5F7FB; color: var(--a-ink); }
.tm-share { padding: 4px 18px; }
.tm-sw { display: flex; align-items: center; justify-content: space-between; padding: 13px 0; border-bottom: 1px solid var(--a-soft); font-size: 14px; font-weight: 600; }
.tm-sw:last-child { border-bottom: 0; }
.tg { position: relative; width: 42px; height: 26px; border-radius: 13px; flex-shrink: 0; background: var(--a-border); transition: background-color .25s ease; }
.tg::after { content: ""; position: absolute; top: 3px; left: 3px; width: 20px; height: 20px; border-radius: 10px; background: #fff; transition: transform .3s cubic-bezier(.3, .7, .2, 1), width .2s ease; }
.tg.on { background: var(--a-ink); }
.tg.on::after { transform: translateX(16px); }
.tg.held::after { width: 26px; }
.tg.on.held::after { transform: translateX(10px); }
.tm-note { padding: 0 4px; font-size: 12px; line-height: 18px; color: var(--a-faint); }
.tm-link { padding: 4px; }
.tm-link b { color: var(--a-ink); }
.tm-act-h { padding-top: 6px; }
.tm-act { padding: 4px 18px; }
.tm-act p { padding: 30px 0 14px; font-size: 13.5px; color: var(--a-muted); } /* fully under the tab bar, like a list scrolled beneath it */
/* The tab bar ((tabs)/_layout.tsx) sits over the foot of the page, as in the app */
.tm-tabs {
  position: absolute; left: 0; right: 0; bottom: 0; display: flex; justify-content: space-around; align-items: center;
  padding: 10px 22px 40px; background: #fff; border-top: 1px solid var(--a-line);
}
.tm-tabs span { display: grid; justify-items: center; gap: 5px; min-width: 52px; font-size: 10px; font-weight: 600; color: var(--a-faint); }
.tm-tabs i { width: 22px; height: 22px; border-radius: 8px; box-shadow: inset 0 0 0 2px var(--a-ghost); }
.tm-tabs .on { color: var(--a-ink); }
.tm-tabs .on i { background: var(--a-ink); box-shadow: none; }
/* Phones: the side phones fan open about their inner bottom corner, like a hand of cards, so the outer edge
   swings out and the bottom never closes in (main.js keeps the outermost point 16px inside the band edge) */
@media (max-width: 720px) {
  /* The app screens are zoomed to ~0.7-0.8 here: lift their smallest labels to ~9-10px on screen */
  .a-node small { font-size: 11.75px; } /* any larger and "Strengthen" crowds "Run" */
  .a-ring small { font-size: 12.5px; }
  .a-stephead small, .a-last { font-size: 13.5px; }
  /* and the feature cards' details: exercise sets, grams, meters, the phase card and its tests */
  .a-kicker { font-size: 14px; }
  .a-sub-sm { font-size: 14.5px; }
  .a-txt small, .a-meter small, .a-pl small { font-size: 13.5px; }
  .a-meal small { font-size: 14px; }
  .a-pill, .a-gate em { font-size: 13px; }
  .road-goal { font-size: 14px; }
  .a-action { font-size: 14.5px; }
  .phone[data-hero="left"] { transform-origin: 100% 100%; }
  .phone[data-hero="right"] { transform-origin: 0 100%; }
}
