/*! *****************************************************************************
 * Copyright (c) 2026 AllPlayCoach, Inc. All rights reserved.
 *
 * This software and all associated documentation files (the "Software") are the
 * proprietary property of AllPlayCoach.
 *
 * Unauthorized copying, modification, distribution, or reverse engineering
 * of this file, via any medium, is strictly prohibited.
 ******************************************************************************/

/* ═══════════════════════════════════════════════════════════════════════════
   ALL PLAY COACH — the marketing page.

   Every colour, size, space and radius here comes from kit/apc-tokens.css —
   the brand kit, generated from Figma, read-only. The page is DARK ONLY: the
   <html> element carries data-theme="dark", so every --apc-* token is the
   kit's own dark value. Two groups of fixed values are the exception, both
   declared once below and nowhere else:

     --screen-*   the product's dark theme, pinned, for the lineup board.
     .pos-*       the app's position colours (packages/core/src/positions.ts):
                  the product's data, drawn so the HTML board matches the app.

   Two layers. The hero is sharp: full bleed, the darkest value, square
   corners. Everything after it (.soft) is soft — rounded cards, rounded
   photographs — and scrolls up over the hero. Sections alternate the page
   dark (.band) and a lighter dark (.band--lift), never two alike in a row.

   Orange, three places only: .eyebrow, .btn--primary, .card__icon.
   ═══════════════════════════════════════════════════════════════════════════ */

:root {
  color-scheme: dark;
  --wrap: 1180px;
  --gutter: var(--apc-space-5);
  --section-y: var(--apc-space-9);
  --step-ink: var(--apc-brand);

  /* The product's dark theme — the kit's dark values, pinned. */
  --screen-bg: #0d1411;
  --screen-surface: #161f1b;
  --screen-surface-2: #1f2b26;
  --screen-text: #ebf2ef;
  --screen-muted: #a4b4ae;
  --screen-border: #2a3833;
  --screen-border-strong: #3c4f48;
  --screen-brand: #1aa98b;
  --screen-on-brand: #04140f;
  --screen-warning: #f2b52e;
  --screen-warning-soft: #382c0a;
}
@media (min-width: 768px) { :root { --gutter: var(--apc-space-7); } }

/* The app's position colours (positions.ts), one class each. */
.pos-P { --pos: #dc3b3b; } .pos-C { --pos: #8a5cf6; } .pos-1B { --pos: #2c7be5; }
.pos-2B { --pos: #0ea5b5; } .pos-3B { --pos: #e8730c; } .pos-SS { --pos: #c026a3; }
.pos-LF { --pos: #1f9d55; } .pos-LCF { --pos: #3f9e3f; } .pos-CF { --pos: #679436; }
.pos-RCF { --pos: #8a9a2b; } .pos-RF { --pos: #b8860b; } .pos-SF { --pos: #0d9488; }

/* ── Base ─────────────────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--apc-bg);
  color: var(--apc-text);
  font-family: var(--apc-font);
  font-weight: var(--apc-weight-regular);
  font-size: var(--apc-size-md);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}
img { display: block; max-width: 100%; height: auto; }
h1, h2, h3, p, figure { margin: 0; }
h1, h2, h3 { font-weight: var(--apc-weight-heavy); line-height: 1.12; letter-spacing: -0.02em; text-wrap: balance; }
a { color: var(--apc-brand); }
:focus-visible { outline: 3px solid var(--apc-focus-ring); outline-offset: 3px; }
.sr-only {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.skip {
  position: absolute; left: var(--apc-space-4); top: calc(-1 * var(--apc-space-10));
  z-index: 10; padding: var(--apc-space-2) var(--apc-space-4);
  background: var(--apc-surface); border-radius: var(--apc-radius-sm); font-weight: var(--apc-weight-bold);
}
.skip:focus { top: var(--apc-space-4); }
.wrap { max-width: var(--wrap); margin-inline: auto; padding-inline: var(--gutter); }

/* ── Buttons ── every one at least the kit's 48px: outdoors, one hand, gloves.
   The primary is orange with near-black words: --apc-text-on-accent on
   --apc-accent is about 7.5:1. White on that orange would fail AA. */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--apc-space-2);
  min-height: var(--apc-tap-min); padding: 0 var(--apc-space-5);
  border: 2px solid transparent; border-radius: var(--apc-radius-pill);
  font: inherit; font-size: var(--apc-size-sm); font-weight: var(--apc-weight-bold);
  line-height: 1.2; text-align: center; text-decoration: none; cursor: pointer;
  transition: background-color 0.15s ease, border-color 0.15s ease;
}
.btn--lg { min-height: var(--apc-tap-comfortable); padding: 0 var(--apc-space-6); font-size: var(--apc-size-md); }
.btn--primary { background: var(--apc-accent); color: var(--apc-text-on-accent); }
.btn--primary:hover { background: color-mix(in srgb, var(--apc-accent) 86%, var(--apc-text)); }
.btn--ghost { border-color: var(--apc-border-strong); color: var(--apc-text); }
.btn--ghost:hover { border-color: var(--apc-text-muted); }
.btn--quiet { color: var(--apc-text); }
.btn--quiet:hover { background: var(--apc-surface); }

/* ── Header ── on the hero's ground, part of the sharp layer. */
.top { padding-block: var(--apc-space-3); }
.top__row { display: flex; align-items: center; justify-content: space-between; gap: var(--apc-space-4); }
.top__logo { display: inline-flex; align-items: center; min-height: var(--apc-tap-min); }
.top__logo img { height: 36px; width: auto; }
.top__nav { display: flex; align-items: center; gap: var(--apc-space-1); }
@media (max-width: 419px) { .top__nav .btn--quiet:first-child { display: none; } }

/* ── The eyebrow ── a star and a few words in capitals, in orange. */
.eyebrow {
  display: flex; align-items: center; gap: var(--apc-space-2); margin-bottom: var(--apc-space-4);
  font-size: var(--apc-size-sm); font-weight: var(--apc-weight-heavy); letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--apc-accent);
}

/* ── Section rhythm ── the soft layer and its two darks. */
.band { padding-block: var(--section-y); background: var(--apc-bg); }
.band--lift { background: var(--apc-surface); }
.section-head { max-width: 46rem; margin-bottom: var(--apc-space-8); }
.section-head h2 { font-size: clamp(var(--apc-size-2xl), 2vw + 1.25rem, var(--apc-size-4xl)); }
.section-sub { margin-top: var(--apc-space-3); font-size: var(--apc-size-lg); color: var(--apc-text-muted); }
/* The soft layer rides over the hero: rounded on top, and pulled up by its own
   radius so the hero's ground shows in the corners. */
.soft { position: relative; z-index: 1; }
.soft > .band:first-child { margin-top: calc(-1 * var(--apc-radius-xl)); border-radius: var(--apc-radius-xl) var(--apc-radius-xl) 0 0; }

/* ═══ 0 · Bring your own tablet ══ a slim strip on the hero's ground, between
   hairlines: part of the sharp layer, so square. Three short points, a green
   check each — not orange, which is kept for its three places. */
.byo { background: var(--apc-bg); }
/* Pinned under the top of the window where it is one row; everything scrolls
   under it. Its height is --byo-h, which the pinned tablets and anchor jumps
   allow for. On a phone it is three lines: pinned, it would eat the screen. */
:root { --byo-h: 0px; }
@media (min-width: 900px) {
  :root { --byo-h: 78px; scroll-padding-top: calc(var(--byo-h) + var(--apc-space-4)); }
  .byo { position: sticky; top: 0; z-index: 5; }
}
.byo__list {
  display: grid; gap: var(--apc-space-2) var(--apc-space-7); padding: var(--apc-space-4) 0; list-style: none;
  /* Lined up with the page's content, hairlines and all: the width of .wrap
     less its gutters, centred. */
  width: calc(100% - 2 * var(--gutter)); max-width: calc(var(--wrap) - 2 * var(--gutter)); margin: 0 auto;
  border-block: 1px solid var(--apc-border); font-size: var(--apc-size-sm); color: var(--apc-text-muted);
}
@media (min-width: 900px) { .byo__list { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.byo__list li { position: relative; padding-left: var(--apc-space-6); }
.byo__list li::before {
  content: ''; position: absolute; left: 2px; top: 0.35em; width: 0.7em; height: 0.4em;
  border-left: 2px solid var(--apc-brand); border-bottom: 2px solid var(--apc-brand); rotate: -45deg;
}
.byo__list strong { color: var(--apc-text); font-weight: var(--apc-weight-bold); }

/* ═══ 1 · Hero — the sharp layer, and the app's story ═════════════════════════
   A spine (§3): the headline and the trial are its first step, the app's four
   jobs the rest. The tablet is big — up to 58% of the window, running off its
   right edge — and stays put, centred in the window below the pinned strip,
   while the words scroll past and its screen changes. It is the spine's
   .device with a lighter bezel, so it has an edge on the ink. The shots are
   1400px wide: a touch soft on a retina screen at this size. */
.hero { position: relative; overflow-x: clip; padding-block: var(--apc-space-7) calc(var(--apc-space-10) + var(--apc-radius-xl)); background: var(--apc-bg); }
.hero h1 { max-width: 13ch; font-size: clamp(var(--apc-size-3xl), 3.6vw + 1.5rem, 64px); }
.lede { margin-top: var(--apc-space-5); max-width: 34em; font-size: var(--apc-size-lg); line-height: 1.5; color: var(--apc-text-muted); }
.spine--hero .device {
  padding: var(--apc-space-3); border-radius: var(--apc-radius-xl); background: var(--apc-surface-2);
  box-shadow: 0 0 0 1px var(--apc-border-strong), 0 50px 100px -40px rgb(0 0 0 / 0.9);
}
.spine--hero .device img { border-radius: var(--apc-radius-md); }
/* The eyebrow is a paragraph inside a step: keep its orange over the steps' grey. */
.spine--hero .step > .eyebrow { color: var(--apc-accent); }
@media (min-width: 1024px) {
  .js .spine--hero .spine__body { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); }
  .js .spine--hero .step { min-height: 64vh; }
  .js .spine--hero .step--intro { min-height: calc(100svh - var(--apc-space-10) - var(--byo-h)); }
  .js .spine--hero .spine__device .device {
    --w: min(58vw, (100svh - var(--byo-h) - 2 * var(--apc-space-8)) * 4 / 3);
    width: var(--w); max-width: none; margin: 0;
    top: calc(var(--byo-h) + (100svh - var(--byo-h)) / 2 - var(--w) * 3 / 8 - var(--apc-space-3));
  }
}

/* The sport control. Hidden until site.js shows it: without JavaScript there
   is nothing for it to switch, so there is no control to find broken.
   .opt is one radio drawn as a pill — the sport control and the size survey's
   answers both. The input covers its pill, so the whole pill is the target. */
.sport {
  display: inline-flex; gap: var(--apc-space-1); margin: 0 0 var(--apc-space-5); padding: var(--apc-space-1);
  border: 0; border-radius: var(--apc-radius-pill); background: var(--apc-bg); box-shadow: 0 0 0 1px var(--apc-border);
}
.sport[hidden] { display: none; }
.opt { position: relative; display: block; }
.opt input { position: absolute; inset: 0; margin: 0; opacity: 0; cursor: pointer; }
.opt span {
  display: inline-flex; align-items: center; min-height: var(--apc-tap-min); padding: 0 var(--apc-space-5);
  border-radius: var(--apc-radius-pill); font-size: var(--apc-size-sm); font-weight: var(--apc-weight-bold); color: var(--apc-text-muted);
}
.opt input:checked + span { background: var(--apc-brand); color: var(--apc-text-on-brand); }
.opt input:focus-visible + span { outline: 3px solid var(--apc-focus-ring); outline-offset: 2px; }

/* The board — the app's lineup grid, dark, as real HTML. */
.board {
  padding: var(--apc-space-4); border-radius: var(--apc-radius-md);
  background: var(--screen-bg); color: var(--screen-text);
  box-shadow: 0 0 0 1px var(--apc-border), 0 2px 6px rgb(16 34 29 / 0.1), 0 32px 64px -28px rgb(16 34 29 / 0.5);
}
.board__bar { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--apc-space-1) var(--apc-space-3); padding: 0 var(--apc-space-2) var(--apc-space-4); }
.board__title { font-size: var(--apc-size-lg); font-weight: var(--apc-weight-heavy); }
.board__when { font-size: var(--apc-size-sm); color: var(--screen-muted); }
/* Positioned, so the screen-reader-only labels inside it are clipped by its
   scroll and cannot widen the page (the hero used to hide that). */
.board__scroll { position: relative; overflow-x: auto; border-radius: var(--apc-radius-sm); background: var(--screen-surface); }
.board__scroll:focus-visible { outline-offset: -3px; }
.board__table { min-width: 33rem; }
.brow { display: grid; grid-template-columns: minmax(8.5rem, 1.7fr) repeat(6, minmax(3.4rem, 1fr)); border-top: 1px solid var(--screen-border); }
.brow--head { border-top: 0; }
.bcell { display: grid; place-items: center; min-height: 2.75rem; padding: var(--apc-space-1); }
.bcell--name { grid-auto-flow: column; justify-content: start; align-items: center; gap: var(--apc-space-2); padding-inline: var(--apc-space-3); }
.bcell--name b { font-size: var(--apc-size-sm); font-weight: var(--apc-weight-bold); white-space: nowrap; }
.bcell--name small { font-size: var(--apc-size-xs); color: var(--screen-muted); }
.brow--head .bcell { min-height: 2.5rem; font-size: var(--apc-size-xs); font-weight: var(--apc-weight-heavy); color: var(--screen-muted); }
.brow--head .bcell--name { letter-spacing: 0.06em; text-transform: uppercase; white-space: nowrap; }
.chip {
  display: grid; place-items: center; inline-size: 2.25rem; block-size: 2.25rem; border-radius: 50%;
  background: var(--pos); color: #fff; font-size: var(--apc-size-xs); font-weight: var(--apc-weight-heavy); letter-spacing: -0.01em;
}
.chip--b { background: transparent; color: var(--screen-muted); font-weight: var(--apc-weight-bold); }
.bench { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: start; gap: var(--apc-space-3); padding: var(--apc-space-4) var(--apc-space-2) 0; }
.bench__label { padding-top: 0.3rem; font-size: var(--apc-size-xs); font-weight: var(--apc-weight-heavy); letter-spacing: 0.08em; text-transform: uppercase; color: var(--screen-muted); }
.bench__list { display: grid; grid-template-columns: repeat(auto-fill, minmax(12.5rem, 1fr)); gap: var(--apc-space-2) var(--apc-space-4); margin: 0; padding: 0; list-style: none; }
.bench__inn { display: flex; flex-wrap: wrap; align-items: center; gap: var(--apc-space-1); }
.bench__n { min-width: 2.6rem; font-size: var(--apc-size-xs); font-weight: var(--apc-weight-bold); color: var(--screen-muted); }
.pill { padding: 0.1rem 0.6rem; border: 1px dashed var(--screen-border-strong); border-radius: var(--apc-radius-pill); font-size: var(--apc-size-xs); font-weight: var(--apc-weight-bold); white-space: nowrap; }
@media (max-width: 767px) {
  .board { margin-inline: calc(-1 * var(--gutter)); padding-inline: var(--gutter); border-radius: 0; }
}

/* ═══ 2 · What it does ══ three across, then one. A title with its icon, a
   hairline, two short lines. The icon is the card's one spot of orange. */
.cards { display: grid; gap: var(--apc-space-4); margin: 0; padding: 0; list-style: none; }
@media (min-width: 768px) { .cards { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.card { padding: var(--apc-space-6); border: 1px solid var(--apc-border); border-radius: var(--apc-radius-md); }
.card__head { display: flex; align-items: center; justify-content: space-between; gap: var(--apc-space-4); padding-bottom: var(--apc-space-4); border-bottom: 1px solid var(--apc-border); }
.card h3 { font-size: var(--apc-size-lg); }
.card__icon { flex: none; width: 28px; height: 28px; fill: none; stroke: var(--apc-accent); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.card p { margin-top: var(--apc-space-4); color: var(--apc-text-muted); }

/* ═══ 3 · The spine ═════════════════════════════════════════════════════════════
   Built for the app's six steps; the Coach Board (§8) is the one that uses it
   now, and changes only its ratio. The rest of this comment is how it works.

   By default, and always without JavaScript, each step carries its own
   screenshot underneath it. From 1024px with JavaScript, a tablet sits beside
   the steps and stays put while they scroll past; the per-step screenshots are
   kept for screen readers but taken off the screen.

   The tablet sticks in the MIDDLE of the window, not a fixed distance from its
   top. Pinned 12vh down, it sat 74–155px above centre on laptop and iPad
   windows, beside text that was centred — so it read as off-centre.

   It is the tablet itself that sticks, inside a column as tall as the steps,
   so it arrives right under the section heading and stops right above the
   next section — not centred in a window-tall box, which left 160px of empty
   space above it and 270px below. Its sticky `top` is half the window less
   half its own height: the width is the column (100cqw, the column is the
   container) or the window cap, whichever is smaller, and the height follows
   from the 4:3 screen plus the frame's padding. */
.steps { display: grid; gap: var(--apc-space-9); margin: 0; padding: 0; list-style: none; }
.step__title { display: flex; align-items: center; gap: var(--apc-space-3); font-size: var(--apc-size-2xl); }
.step__n {
  display: grid; flex: none; place-items: center; inline-size: 2.5rem; block-size: 2.5rem; border-radius: 50%;
  background: var(--apc-brand-soft); color: var(--step-ink); font-size: var(--apc-size-md); letter-spacing: 0;
}
.step > p { margin-top: var(--apc-space-3); max-width: 34em; color: var(--apc-text-muted); }
.step__shot { margin-top: var(--apc-space-6); }
/* Every dark frame carries a hairline in the page's own border colour, so it
   keeps an edge on the dark page, where its shadow and its ground are both ink. */
.device { padding: var(--apc-space-2); border-radius: var(--apc-radius-md); background: var(--screen-bg); box-shadow: 0 0 0 1px var(--apc-border), 0 30px 60px -30px rgb(16 34 29 / 0.55); }
.device img { width: 100%; border-radius: var(--apc-radius-md); aspect-ratio: 4 / 3; }
.step__shot figcaption { margin-top: var(--apc-space-3); font-size: var(--apc-size-sm); color: var(--apc-text-muted); }
/* The tablet's captions hang below its frame, out of the flow. In the flow,
   the stacked screens all took the height of the tallest — a screenshot plus
   a caption — and the three without one showed a black band underneath. */
.screen { position: relative; }
.screen figcaption { position: absolute; top: 100%; left: 0; right: 0; margin-top: var(--apc-space-3); font-size: var(--apc-size-sm); color: var(--apc-text-muted); }
.spine__device { display: none; }
@media (max-width: 767px) {
  .step__shot .device { margin-inline: calc(-1 * var(--gutter)); border-radius: 0; }
  .step__shot figcaption { margin-inline: 0; }
}
@media (min-width: 1024px) {
  .js .spine__body { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: var(--apc-space-9); align-items: start; }
  .js .steps { gap: 0; }
  .js .step { display: flex; flex-direction: column; justify-content: center; min-height: 72vh; }
  .js .step__shot { position: absolute; width: 1px; height: 1px; margin: 0; overflow: hidden; clip: rect(0 0 0 0); }
  .js .spine__device { display: block; align-self: stretch; container-type: inline-size; }
  /* Never taller than the window, with room for a caption underneath. */
  .js .spine__device .device {
    position: sticky; width: 100%; margin-inline: auto;
    max-width: calc((100vh - 2 * var(--apc-space-10)) * 4 / 3);
    max-width: calc((100svh - 2 * var(--apc-space-10)) * 4 / 3);
    /* Without container units (iPadOS 15) both lines below are dropped; this
       keeps the tablet sticking near the top instead of left behind. */
    top: var(--apc-space-10);
    top: calc(50vh - (min(100cqw, (100vh - 2 * var(--apc-space-10)) * 4 / 3) - 2 * var(--apc-space-2)) * 3 / 8 - var(--apc-space-2));
    top: calc(50svh - (min(100cqw, (100svh - 2 * var(--apc-space-10)) * 4 / 3) - 2 * var(--apc-space-2)) * 3 / 8 - var(--apc-space-2));
  }
  .js .screens { display: grid; }
  .js .screen { grid-area: 1 / 1; }
  /* The cut: only the current step's screen is shown. site.js marks the step;
     the crossfade below, where it applies, overrides this. */
  .js .spine .screen { visibility: hidden; }
  .js .spine[data-screen='1'] .screen:nth-child(1),
  .js .spine[data-screen='2'] .screen:nth-child(2),
  .js .spine[data-screen='3'] .screen:nth-child(3),
  .js .spine[data-screen='4'] .screen:nth-child(4),
  .js .spine[data-screen='5'] .screen:nth-child(5),
  .js .spine[data-screen='6'] .screen:nth-child(6) { visibility: visible; }
}
/* On a laptop the tablet is the point of the section, and 618px of it was too
   small. The band is 56px wider each side than the page and the text column
   gives up a twelfth, so the tablet grows about a fifth while the text keeps
   the width it had. */
@media (min-width: 1180px) {
  .js .spine > .wrap { max-width: calc(var(--wrap) + 2 * var(--apc-space-9)); }
  .js .spine__body { grid-template-columns: minmax(0, 4fr) minmax(0, 7fr); }
}

/* ═══ 5 · Pricing ═══ still, on purpose. Cards are outlines on the lighter dark. */
.plans { display: grid; gap: var(--apc-space-4); align-items: stretch; }
/* Four cards: four across, then two, then one — never three and a leftover. */
@media (min-width: 640px) { .plans { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1100px) { .plans { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.plan { display: flex; flex-direction: column; gap: var(--apc-space-3); padding: var(--apc-space-6); border: 1px solid var(--apc-border); border-radius: var(--apc-radius-md); }
/*
  THE CARDS SHARE THEIR ROWS, SO THE PRICES LINE UP.

  Each card was its own column box, so every row inside it started wherever
  the row above happened to end: a two-line audience line pushed one $ sign
  below its neighbour, and four cards disagreed four ways. The founder read
  that as noise before reading it as misalignment, which is exactly what it
  is (2026-10-21).

  Subgrid is the fix rather than a set of min-heights, because the browser
  measures the tallest name, the tallest audience line and the tallest price
  across all four and gives every card those same rows. Add a fifth card or
  a longer word and it stays true with no numbers to re-tune.

  Rows: name, audience, price, claims (the one that absorbs the slack),
  note, button. A card that has no note or no button leaves that row empty
  rather than pulling everything up a line. Where subgrid is not supported
  the whole block is ignored and the cards fall back to the column they are
  above - looser, never broken.
*/
@media (min-width: 640px) {
  .plans { grid-template-rows: auto auto auto 1fr auto auto; }
  .plan {
    display: grid;
    grid-template-rows: subgrid;
    grid-row: span 6;
  }
  .plan__name { grid-row: 1; }
  .plan__for { grid-row: 2; }
  .plan__price { grid-row: 3; }
  .plan ul { grid-row: 4; align-self: start; }
  .plan__note { grid-row: 5; }
  .plan .btn { grid-row: 6; margin-top: 0; }
}
.plan__for { font-size: var(--apc-size-sm); color: var(--apc-text-muted); }
.plan__name { font-size: var(--apc-size-xl); }
.plan__price { font-size: var(--apc-size-3xl); font-weight: var(--apc-weight-heavy); line-height: 1.1; letter-spacing: -0.02em; }
.plan__price--soon { font-size: var(--apc-size-lg); font-weight: var(--apc-weight-bold); letter-spacing: 0; color: var(--apc-text-muted); }
.plan ul { display: grid; gap: var(--apc-space-2); margin: var(--apc-space-2) 0 0; padding: 0; list-style: none; font-size: var(--apc-size-sm); }
.plan li { position: relative; padding-left: var(--apc-space-5); }
.plan li::before { content: ''; position: absolute; left: 0; top: 0.6em; width: 0.45rem; height: 0.45rem; border-radius: 50%; background: var(--apc-brand); }
.plan .btn { margin-top: auto; }
.plan ul + .btn { margin-top: var(--apc-space-5); }
.plan__note { font-size: var(--apc-size-sm); font-weight: var(--apc-weight-bold); }
.plans__note { max-width: 44rem; margin-top: var(--apc-space-6); font-size: var(--apc-size-sm); color: var(--apc-text-muted); }

/* ── Forms ── the trial's email and the size survey. Real forms: they post
   without JavaScript and come back to a :target message; site.js upgrades
   them to fetch and shows the same message with .is-shown. */
.signup { display: flex; flex-wrap: wrap; align-items: center; gap: var(--apc-space-3) var(--apc-space-5); margin-top: var(--apc-space-7); }
.q__email { font-size: var(--apc-size-sm); font-weight: var(--apc-weight-bold); }
.signup input, .board-sec__ask input[type='email'] {
  min-height: var(--apc-tap-comfortable); padding: 0 var(--apc-space-5); width: 100%;
  border: 1px solid var(--apc-border-strong); border-radius: var(--apc-radius-pill);
  background: var(--apc-surface); color: var(--apc-text); font: inherit;
}
.signup input { flex: 1 1 11rem; width: auto; }
/* The secondary: words, no box. */
.signup__alt { min-height: var(--apc-tap-min); display: inline-flex; align-items: center; color: var(--apc-text); font-weight: var(--apc-weight-bold); }
.signup__micro { margin-top: var(--apc-space-3); font-size: var(--apc-size-sm); color: var(--apc-text-muted); }
/* The giveaway, from the first screen. Deliberately quieter than the trial
   button it sits under: the page's offer is the app, and this is the aside
   that carries someone to the survey. Muted line, accent only on the promise,
   so it reads as a sentence and not a second button competing with the CTA. */
.signup__win { margin-top: var(--apc-space-2); font-size: var(--apc-size-sm); }
/* inline-BLOCK, not inline-flex: a flex container drops the whitespace text
   node between the question and the promise, and the line rendered as
   "board size?There's one to win." The padding is what makes the tap target,
   since a block cannot centre itself into a min-height. */
.signup__win a {
  display: inline-block;
  padding-block: 12px;
  color: var(--apc-text-muted);
  text-decoration: none;
}
.signup__win strong { color: var(--apc-accent); }
.signup__win a:hover { color: var(--apc-text); }
.signup__win a:hover strong { text-decoration: underline; }
/* The honeypot: off the screen and out of the tab order; a person never sees it. */
.hp { position: absolute; left: -100vw; width: 1px; height: 1px; overflow: hidden; }
.done { display: none; margin-top: var(--apc-space-4); padding: var(--apc-space-4); border-left: 3px solid var(--apc-brand); font-weight: var(--apc-weight-bold); }
.done--err { border-color: var(--apc-danger); }
.done:target, .done.is-shown { display: block; }
.is-sent { display: none; }

/* ── Footer ── the stacked lockup, on the page dark. */
.foot { padding-block: var(--apc-space-8) var(--apc-space-9); }
.foot .wrap { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--apc-space-4); }
.foot__logo img { width: 148px; height: auto; }
.foot__legal { font-size: var(--apc-size-sm); color: var(--apc-text-muted); }
.foot__legal a { color: inherit; }

/* ═══ MOTION ═════════════════════════════════════════════════════════════════
   Three places, nothing else moves. The page above is complete without any
   of this; everything here is layered on top.

   Scroll-driven effects live inside @supports (animation-timeline: view()).
   Browsers without it — older iPads, Firefox — never enter the block and see
   the finished page, still. Nothing starts invisible: headline words start
   grey, not hidden; the board's innings start dimmed; the bench shows
   inning 1 at rest. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    /* 1 · Section headlines fill word by word, grey to white. The same
       apc-fill the board uses: its grey is --screen-muted and its ground
       --screen-surface-2, so a headline sets those to a fainter grey and to
       nothing — and the scale in it never touches an inline word. Each word
       runs a little behind the one before it (--i). */
    .fill { --screen-muted: var(--apc-text-faint); --screen-surface-2: transparent; }
    .fill > span { animation: apc-fill linear both; animation-timeline: view(); animation-range: cover calc(8% + var(--i) * 3%) cover calc(20% + var(--i) * 3%); }

    /* 2 · The board fills itself — innings two to six, one after another, as
       it rises into the window. Its own view timeline, now that it is not at
       the top of the page. */
    .board { view-timeline: --apc-board block; }
    .board [data-fill] .chip { animation: apc-fill linear both; animation-timeline: --apc-board; animation-range: cover calc((var(--i) - 1) * 7%) cover calc(var(--i) * 7%); }

    /* …and the bench follows along: the kids sitting out the inning that has
       just filled. Without this block, all six innings' benches are listed. */
    .bench__list { grid-template-columns: minmax(0, 1fr); }
    .bench__inn { grid-area: 1 / 1; animation: apc-bench linear both; animation-timeline: --apc-board; animation-range: cover calc((var(--i) - 0.5) * 7%) cover calc((var(--i) + 0.5) * 7%); }
    .bench__inn:last-child { animation-name: apc-bench-last; }

    /* 3 · The spine crossfades — each screen follows its step through the window. */
    @media (min-width: 1024px) {
      .js .spine__body { timeline-scope: --apc-s1, --apc-s2, --apc-s3, --apc-s4, --apc-s5, --apc-s6; }
      .js .step:nth-child(1) { view-timeline: --apc-s1 block; }
      .js .step:nth-child(2) { view-timeline: --apc-s2 block; }
      .js .step:nth-child(3) { view-timeline: --apc-s3 block; }
      .js .step:nth-child(4) { view-timeline: --apc-s4 block; }
      .js .step:nth-child(5) { view-timeline: --apc-s5 block; }
      .js .step:nth-child(6) { view-timeline: --apc-s6 block; }
      .js .spine .screen { visibility: visible; animation: apc-screen linear both; animation-range: cover 15% cover 85%; }
      .js .spine .screen:nth-child(1) { animation-name: apc-screen-first; animation-timeline: --apc-s1; }
      .js .spine .screen:nth-child(2) { animation-timeline: --apc-s2; }
      .js .spine .screen:nth-child(3) { animation-timeline: --apc-s3; }
      .js .spine .screen:nth-child(4) { animation-timeline: --apc-s4; }
      .js .spine .screen:nth-child(5) { animation-timeline: --apc-s5; }
      .js .spine .screen:nth-child(6) { animation-timeline: --apc-s6; }
    }
  }
  @keyframes apc-fill { from { background: var(--screen-surface-2); color: var(--screen-muted); scale: 0.8; } }
  @keyframes apc-bench { 0%, 100% { opacity: 0; } 50% { opacity: 1; } }
  @keyframes apc-bench-last { 0% { opacity: 0; } 50%, 100% { opacity: 1; } }
  /*
    EVERY SCREEN FADES IN AND STAYS (founder, 2026-09-27: "I noticed some
    images broken on the site").

    They used to fade in AND back out, which left a gap between one step and
    the next where every screen was transparent and the viewer was an empty
    frame. It had been patched twice already, per spine, for the LAST screen
    of each — but the gap is between every pair, not only at the end.

    The screens are stacked in one grid cell, so the one furthest down the
    document wins wherever two are opaque. Fading in and holding is therefore
    enough on its own: the next screen covers the one before it, and scrolling
    back up reverses the fade and uncovers it again. There is no moment when
    nothing is painted, so no per-spine rule about which screen is last.
  */
  @keyframes apc-screen { 0% { opacity: 0; } 25%, 100% { opacity: 1; } }
  @keyframes apc-screen-first { 0%, 100% { opacity: 1; } }
}

/* The giveaway's prize arrives: as the section rises into the window the
   render grows into place and brightens, from the section's own view
   timeline (the picture is sticky, so it cannot time itself). */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .giveaway { view-timeline: --apc-give block; }
    .giveaway__bg picture { animation: apc-prize linear both; animation-timeline: --apc-give; animation-range: entry 0% entry 100%; }
  }
  @keyframes apc-prize { from { scale: 0.82; opacity: 0.25; } }
}

/* One switch turns all of it off. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
}

/* ═══ 8 · The Coach Board ═════════════════════════════════════════════════════
   The same spine as §3 — a frame that sticks beside the steps while they scroll
   past — but holding photographs of the hardware rather than screenshots of the
   app. Three differences and no more:

   · the pictures are 16:9, not the app's 4:3, so the frame's aspect and the
     sticky centring maths both change ratio (the 3/8 below is half of 3/4; for
     16:9 it is half of 9/16, which is 9/32);
   · the frame has no inner bezel — a photograph of a tablet inside a drawing of
     a tablet reads as a mistake;
   · three screens, not six, so the third is the last one and must stay up at
     the end of the section instead of fading out.

   Everything else — timeline-scope on .spine__body, view-timeline per .step,
   the IntersectionObserver cut underneath — is inherited unchanged, which is
   why this section is short. */
.board-sec { color: var(--screen-text); }
.board-sec .section-sub,
.board-sec .step > p { color: var(--screen-muted); }
.board-sec .step__n { background: var(--apc-brand); color: var(--screen-text); }
.board-sec .device--photo { padding: 0; background: none; box-shadow: none; }
.board-sec .device--photo img { aspect-ratio: 16 / 9; border-radius: var(--apc-radius-md); box-shadow: 0 0 0 1px var(--apc-border), 0 30px 60px -30px rgb(0 0 0 / 0.8); }

/* The render disclaimer. It is part of the section, not decoration: these are
   pictures of a thing that cannot yet be bought. It never hides, at any width,
   with or without JavaScript. */
.board-sec__render { margin-top: var(--apc-space-6); font-size: var(--apc-size-sm); color: var(--screen-muted); }

.board-sec__ask { margin-top: var(--apc-space-9); padding-top: var(--apc-space-8); border-top: 1px solid var(--screen-border); }
.qs { display: grid; gap: var(--apc-space-5); max-width: 46rem; margin-block: var(--apc-space-7); }
.q { display: flex; flex-wrap: wrap; gap: var(--apc-space-2); min-width: 0; margin: 0; padding: 0; border: 0; }
.q legend { margin-bottom: var(--apc-space-3); padding: 0; font-weight: var(--apc-weight-bold); }
/* On the always-dark ground the pills take the product's dark tokens, and
   the kit's brand-on-dark when chosen — never --apc-brand on ink. */
.q .opt span { box-shadow: inset 0 0 0 1px var(--screen-border-strong); color: var(--screen-text); font-weight: var(--apc-weight-medium); }
.q .opt input:checked + span { background: var(--apc-brand-on-dark); color: var(--screen-on-brand); box-shadow: none; }
.board-sec__ask input[type='email'] { display: block; max-width: 28rem; margin-top: var(--apc-space-2); border-color: var(--screen-border-strong); background: var(--screen-surface); color: var(--screen-text); }
.board-sec .done { border-color: var(--apc-brand-on-dark); }
.board-sec .done--err { border-color: var(--apc-danger); }
.board-sec__ask h3 { font-size: var(--apc-size-2xl); }
/* The giveaway: its headline is the section's second big line, and the
   short-form legal line sits right under it, in full, never in small grey. */
.board-sec__ask .board-sec__win { font-size: clamp(var(--apc-size-2xl), 2vw + 1.25rem, var(--apc-size-4xl)); }
/* The prize is the headline: the lead-in steps down, "Win a Coach Board."
   goes as big as the page gets, the prize's name in the brand green. Its
   words fill in with the other headlines (apc-fill). */
.win__lead { display: block; margin-bottom: var(--apc-space-2); font-size: var(--apc-size-xl); color: var(--screen-muted); }
.win__big { display: block; font-size: clamp(var(--apc-size-4xl), 6vw + 1rem, 104px); line-height: 0.98; letter-spacing: -0.035em; text-shadow: 0 2px 30px rgb(0 0 0 / 0.6); }
.win__prize { color: var(--apc-brand-on-dark); }
.q__hint { font-weight: var(--apc-weight-regular); color: var(--screen-muted); }
.board-sec__ask .board-sec__rules { max-width: 46em; color: var(--screen-text); }
.board-sec__ask .eyebrow { color: var(--apc-accent); }
.board-sec__rules a { color: inherit; }
.check { display: flex; align-items: center; gap: var(--apc-space-3); min-height: var(--apc-tap-min); max-width: 36rem; cursor: pointer; }
.check input { flex: none; width: 24px; height: 24px; margin: 0; accent-color: var(--apc-brand); }
.check + .q__email { display: block; margin-top: var(--apc-space-4); }
.board-sec__ask p { margin-top: var(--apc-space-3); max-width: 46em; color: var(--screen-muted); }
.board-sec__cta { display: inline-flex; margin-top: var(--apc-space-6); }
.board-sec__micro { margin-top: var(--apc-space-3); font-size: var(--apc-size-sm); color: var(--screen-muted); }

@media (min-width: 1024px) {
  .js .spine--board .spine__device .device {
    max-width: calc((100vh - 2 * var(--apc-space-10)) * 16 / 9);
    max-width: calc((100svh - 2 * var(--apc-space-10)) * 16 / 9);
    top: var(--apc-space-10);
    top: calc(50vh - min(100cqw, (100vh - 2 * var(--apc-space-10)) * 16 / 9) * 9 / 32);
    top: calc(50svh - min(100cqw, (100svh - 2 * var(--apc-space-10)) * 16 / 9) * 9 / 32);
  }
}
/* The disclaimer has to be on screen whenever a render is. In the flow it only
   arrives at the end of the section, by which point the reader has scrolled
   past three photographs without it. So where the spine applies it rides
   inside the sticky frame, under the photograph — inside, so the two stop
   together at the end of the section instead of the caption sliding up over
   the picture. The copy in the flow is then for screen readers only (the
   frame is aria-hidden); everywhere else it is the visible one. */
.board-sec__render--pinned { display: none; }
@media (min-width: 1024px) {
  .js .spine--board .board-sec__render--pinned { display: block; margin-top: var(--apc-space-4); }
  .js .spine--board .board-sec__render--flow { position: absolute; width: 1px; height: 1px; margin: 0; overflow: hidden; clip: rect(0 0 0 0); }
  /* The photographs take two-thirds, to sit at the size of the hero's
     tablet; the words keep a third, which their short steps fit. */
  .js .spine--board .spine__body { grid-template-columns: minmax(0, 4fr) minmax(0, 8fr); }
  /* Three short steps: the app spine's 72vh each left step 1 a screen below
     the heading, and the page has eight screens to fit in. */
  .js .spine--board .step { min-height: 40vh; }
  .js .spine--board .step:first-child { justify-content: flex-start; }
}

/* ═══ 9 · Privacy and terms ═══ the same shell, a column of text. */
.legal { max-width: 44rem; }
.legal h1 { font-size: var(--apc-size-3xl); }
/* Privacy and Terms share one page (founder, 2026-09-24), so each is an h2
   that reads as a title of its own, and their own headings stepped down to h3.
   The rule gives the sections the weight the h1 used to carry. */
.legal h2 { margin-top: var(--apc-space-9, var(--apc-space-8)); font-size: var(--apc-size-2xl, var(--apc-size-xl)); }
.legal h3 { margin-top: var(--apc-space-8); font-size: var(--apc-size-xl); }
/* Landing from another page's link: the section's heading must clear the top
   of the window, not sit against it. */
.legal section { scroll-margin-top: var(--apc-space-6); }
.legal__jump { display: flex; gap: var(--apc-space-5); margin-top: var(--apc-space-4); font-weight: var(--apc-weight-bold); }
.legal__jump a { min-height: var(--apc-tap-min); display: inline-flex; align-items: center; }
.legal p, .legal li { margin-top: var(--apc-space-3); color: var(--apc-text-muted); }
.legal__draft { margin-block: var(--apc-space-5); padding: var(--apc-space-4); border-left: 3px solid var(--apc-border-strong); background: var(--apc-surface); }

/* ═══ 10 · The giveaway ══════════════════════════════════════════════════════
   The prize, big, stays put behind the whole section while the questions
   scroll over it: sticky, a window tall, and pulled back out of the flow by
   its own height. It sits right of centre and fades out hard to the left, so
   the form's words are on dark. Its disclaimer is pinned in its corner.
   On a phone: the picture first, faded at its edges, then the form. */
.giveaway__bg img {
  width: 100%;
  -webkit-mask-image: linear-gradient(to right, transparent, black 16%, black 84%, transparent), linear-gradient(to bottom, transparent, black 14%, black 80%, transparent);
  -webkit-mask-composite: source-in;
          mask-image: linear-gradient(to right, transparent, black 16%, black 84%, transparent), linear-gradient(to bottom, transparent, black 14%, black 80%, transparent);
          mask-composite: intersect;
}
.giveaway__note { margin: var(--apc-space-2) var(--gutter) 0; font-size: var(--apc-size-xs); color: var(--screen-muted); }
.giveaway .board-sec__ask { margin-top: var(--apc-space-7); padding-top: 0; border-top: 0; }
@media (min-width: 1024px) {
  .giveaway { padding-block: 0; }
  .giveaway__bg {
    position: sticky; top: 0; z-index: 0; height: 100svh; margin-bottom: -100svh;
    display: flex; align-items: center; justify-content: flex-end; pointer-events: none;
  }
  .giveaway__bg picture { width: 80vw; }
  .giveaway__bg img {
    -webkit-mask-image: linear-gradient(to right, transparent 28%, black 80%), linear-gradient(to bottom, transparent, black 14%, black 86%, transparent);
            mask-image: linear-gradient(to right, transparent 28%, black 80%), linear-gradient(to bottom, transparent, black 14%, black 86%, transparent);
  }
  .giveaway__note { position: absolute; right: var(--gutter); bottom: var(--apc-space-5); margin: 0; padding: var(--apc-space-1) var(--apc-space-2); background: var(--apc-bg); }
  .giveaway__body { position: relative; z-index: 1; padding-block: calc(var(--byo-h) + var(--apc-space-9)) var(--section-y); }
  .giveaway .board-sec__ask { max-width: 36rem; margin-top: 0; }
  /* The big line is allowed wider than the form, out over the faded prize. */
  .giveaway .win__big { width: min(52vw, 46rem); }
  /* Over the picture, an unpicked answer keeps an ink ground so it reads. */
  .giveaway .q .opt span { background: var(--apc-bg); }
  .giveaway .q .opt input:checked + span { background: var(--apc-brand-on-dark); }
}

/* ── Leagues, on the homepage (brief 08) ────────────────────────────────────
   Three lines and a link. It sits between two of the page's biggest sections
   and its whole job is to be short enough that the founder does not feel the
   page grew — so: no cards, no columns, no second spine, nothing that invites
   a fourth line later. The list is set at reading size, not display size,
   because a board member skims it and a commissioner reads it. */
.leagues__lines { list-style: none; margin: 0; padding: 0; max-width: 46rem; }
.leagues__lines li {
  padding-block: var(--apc-space-4);
  border-top: 1px solid var(--apc-border);
  font-size: var(--apc-size-lg);
}
.leagues__lines li:first-child { border-top: 0; padding-top: 0; }
.leagues__cta { margin-top: var(--apc-space-6); }
