/* ==========================================================================
   tokens.css — fonts, reset, design tokens, dark theme, shared primitives.
   Loaded on every page before any page-specific sheet.

   The token values here are the same set as the Flutter app's app_tokens.dart.
   If one changes there it changes here; they are one design system, not two.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. FONTS — self-hosted, zero third-party requests.
   Two faces per family/weight: latin and latin-ext, split by unicode-range so
   a page that never types a diacritic never downloads the -ext file.
   22 rules: Barlow 400/500/600/700, Barlow Condensed 400/500/600/700,
   Roboto Mono 400/600/700 — each x2.
   -------------------------------------------------------------------------- */

/* Barlow — prose */
@font-face{font-family:'Barlow';font-style:normal;font-weight:400;font-display:swap;src:url('/fonts/Barlow-400.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+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:'Barlow';font-style:normal;font-weight:400;font-display:swap;src:url('/fonts/Barlow-400-ext.woff2') format('woff2');unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}
@font-face{font-family:'Barlow';font-style:normal;font-weight:500;font-display:swap;src:url('/fonts/Barlow-500.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+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:'Barlow';font-style:normal;font-weight:500;font-display:swap;src:url('/fonts/Barlow-500-ext.woff2') format('woff2');unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}
@font-face{font-family:'Barlow';font-style:normal;font-weight:600;font-display:swap;src:url('/fonts/Barlow-600.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+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:'Barlow';font-style:normal;font-weight:600;font-display:swap;src:url('/fonts/Barlow-600-ext.woff2') format('woff2');unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}
@font-face{font-family:'Barlow';font-style:normal;font-weight:700;font-display:swap;src:url('/fonts/Barlow-700.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+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:'Barlow';font-style:normal;font-weight:700;font-display:swap;src:url('/fonts/Barlow-700-ext.woff2') format('woff2');unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}

/* Barlow Condensed — every heading and button label */
@font-face{font-family:'Barlow Condensed';font-style:normal;font-weight:400;font-display:swap;src:url('/fonts/BarlowCondensed-400.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+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:'Barlow Condensed';font-style:normal;font-weight:400;font-display:swap;src:url('/fonts/BarlowCondensed-400-ext.woff2') format('woff2');unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}
@font-face{font-family:'Barlow Condensed';font-style:normal;font-weight:500;font-display:swap;src:url('/fonts/BarlowCondensed-500.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+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:'Barlow Condensed';font-style:normal;font-weight:500;font-display:swap;src:url('/fonts/BarlowCondensed-500-ext.woff2') format('woff2');unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}
@font-face{font-family:'Barlow Condensed';font-style:normal;font-weight:600;font-display:swap;src:url('/fonts/BarlowCondensed-600.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+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:'Barlow Condensed';font-style:normal;font-weight:600;font-display:swap;src:url('/fonts/BarlowCondensed-600-ext.woff2') format('woff2');unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}
@font-face{font-family:'Barlow Condensed';font-style:normal;font-weight:700;font-display:swap;src:url('/fonts/BarlowCondensed-700.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+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:'Barlow Condensed';font-style:normal;font-weight:700;font-display:swap;src:url('/fonts/BarlowCondensed-700-ext.woff2') format('woff2');unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}

/* Roboto Mono — kickers (700) and data (600) */
@font-face{font-family:'Roboto Mono';font-style:normal;font-weight:400;font-display:swap;src:url('/fonts/RobotoMono-400.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+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:'Roboto Mono';font-style:normal;font-weight:400;font-display:swap;src:url('/fonts/RobotoMono-400-ext.woff2') format('woff2');unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}
@font-face{font-family:'Roboto Mono';font-style:normal;font-weight:600;font-display:swap;src:url('/fonts/RobotoMono-600.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+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:'Roboto Mono';font-style:normal;font-weight:600;font-display:swap;src:url('/fonts/RobotoMono-600-ext.woff2') format('woff2');unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}
@font-face{font-family:'Roboto Mono';font-style:normal;font-weight:700;font-display:swap;src:url('/fonts/RobotoMono-700.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+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:'Roboto Mono';font-style:normal;font-weight:700;font-display:swap;src:url('/fonts/RobotoMono-700-ext.woff2') format('woff2');unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}


/* --------------------------------------------------------------------------
   2. TOKENS
   -------------------------------------------------------------------------- */

:root {
  color-scheme: light dark;

  /* -- surfaces & ink (light) -- */
  --bg: #F2F2F3;
  --surface: #E9E9EA;
  --text: #1D1F20;

  /* --text-muted and --text-faint are the app's raw tokens (app_tokens.dart:
     65% and 50%), kept here so the two design systems stay one system; the
     drift check in tools/verify.mjs reads both files. MEASURE BEFORE YOU USE
     --text-faint: on --bg it lands at 3.15:1 (light) and 4.32:1 (dark), i.e.
     BELOW the 4.5:1 this site holds itself to, so it is for decorative marks
     and disabled states only. --text-muted now measures 4.93 / 4.77 (light)
     and 6.21 / 4.80 (dark) on --bg / --surface, the same as --text-secondary.
     For anything a person has to read, still prefer --text-copy /
     --text-secondary below (or the .muted / .fine / .prose classes). */
  --text-muted: rgba(29, 31, 32, .65);
  --text-faint: rgba(29, 31, 32, .50);

  /* Contrast-safe secondary ink. Verified against both --bg and --surface:
     copy 6.18 / 5.93, secondary 4.93 / 4.77. */
  --text-copy: rgba(29, 31, 32, .72);
  --text-secondary: rgba(29, 31, 32, .65);

  --divider: rgba(29, 31, 32, .16);
  --hairline: rgba(29, 31, 32, .08);

  /* -- accent --
     --accent is the brand blue. At 3.71:1 on --bg it clears the 3:1 bar for
     borders, focus rings, icons and other non-text UI, but it FAILS for small
     text and for a solid button carrying a label. Anything with type on or in
     it uses --accent-strong, which is the next step down the same ramp
     (a700, 5.78:1 with --on-accent). In dark both resolve to the same value
     because the ramp has already turned over. */
  --accent: #5980A6;
  --accent-hover: #416180;
  --accent-strong: #416180;
  --accent-strong-hover: #2C455D;
  --accent-soft: #EEF6FF;          /* the tinted card ground used by the featured tier */
  --on-accent: #F2F2F3;

  /* The one secondary button (app D8, AdaptSoftButton): a soft fill with an
     accent label. Light a200 / a700 (5.29:1); hover a300 / a800. The -raised
     pair is what it wears on a tinted panel (.card): light is the same pair,
     dark steps up so it does not dissolve into the panel it sits on. */
  --soft-fill: #D6EBFF;
  --soft-ink: #416180;
  --soft-fill-hover: #B5D9FD;
  --soft-ink-hover: #2C455D;
  --soft-fill-raised: #D6EBFF;
  --soft-ink-raised: #416180;
  /* A panel hovered: the next step up from --accent-soft. */
  --accent-soft-hover: #D6EBFF;

  /* -- the blue ramp. These NEVER change between themes. -- */
  --a100: #EEF6FF;
  --a200: #D6EBFF;
  --a300: #B5D9FD;
  --a400: #94BCE3;
  --a500: #749DC4;
  --a600: #597EA3;
  --a700: #416180;
  --a800: #2C455D;
  --a900: #1D2D3D;

  /* -- neutrals -- */
  --n300: #D4D4D7;
  --n600: #7A7A7D;

  /* -- inverted block ("plate") + progress track -- */
  --plate: #1D2D3D;
  --on-plate: #F2F2F3;
  /* Accent ink FOR USE ON A PLATE. The plate inverts between themes, so a
     fixed --a400 kicker that reads 7.06:1 on the light theme's dark plate
     collapses to 1.78:1 on the dark theme's light plate. Use this, never a
     hard-coded ramp step, for accent type inside .plate / .on-plate. */
  --on-plate-accent: #94BCE3;
  --track: #D4D4D7;
  /* The intensity bar's own track. Light: --track. Dark: see the note in the
     dark block — --track collides exactly with zone 4. */
  --intensity-track: var(--track);

  /* -- radii -- */
  --r-chip: 10px;
  --r-control: 14px;
  --r-surface: 20px;
  --r-pill: 999px;

  /* -- intensity ramp, zones 1-5.
        Identical in both themes, so these reference the fixed ramp and never
        --accent (which DOES flip). --accent-fixed is the light-theme accent
        pinned so zone 3 stays the same colour in dark. -- */
  --accent-fixed: #5980A6;
  --z1-fill: 20%;  --z1-color: var(--a400);
  --z2-fill: 40%;  --z2-color: var(--a500);
  --z3-fill: 60%;  --z3-color: var(--accent-fixed);
  --z4-fill: 80%;  --z4-color: var(--a700);
  --z5-fill: 100%; --z5-color: var(--a900);

  /* -- layout -- */
  --wrap: 1240px;
  --gutter: 64px;
  --section-y: 88px;

  /* -- type -- */
  --font-head: 'Barlow Condensed', 'Barlow', system-ui, -apple-system, sans-serif;
  --font-body: 'Barlow', system-ui, -apple-system, sans-serif;
  --font-mono: 'Roboto Mono', ui-monospace, SFMono-Regular, Menlo, monospace;

  --fs-display: clamp(46px, 5.9vw, 82px);   /* hero h1 */
  --fs-h1: clamp(40px, 4.6vw, 62px);        /* hub / event page h1 */
  --fs-h2: clamp(34px, 4.0vw, 56px);
  --fs-h3: clamp(24px, 2.1vw, 28px);
  --fs-h4: clamp(19px, 1.7vw, 23px);
  --fs-lede: clamp(17px, 1.4vw, 19px);
  --fs-body: 16px;
  --fs-small: 14.5px;
  --fs-fine: 13px;

  /* -- motion. Two durations, two curves. Nothing bounces. -- */
  --dur-state: 140ms;   /* something already on screen changing state */
  --dur-enter: 240ms;   /* something entering or leaving */
  --ease-out: cubic-bezier(.215, .61, .355, 1);    /* easeOutCubic — in  */
  --ease-in:  cubic-bezier(.55, .055, .675, .19);  /* easeInCubic  — out */
}

/* DARK — the same ramp turned over, not a second palette. */
@media (prefers-color-scheme: dark) {
  :root {
    --bg: #1D2D3D;
    --surface: #2C455D;
    --text: #F2F2F3;            /* never pure white */
    --text-muted: rgba(242, 242, 243, .65);
    --text-faint: rgba(242, 242, 243, .50);
    /* copy 7.74 on --bg / 5.81 on --surface; secondary 6.95 / 5.29 */
    --text-copy: rgba(242, 242, 243, .75);
    --text-secondary: rgba(242, 242, 243, .70);
    --divider: rgba(242, 242, 243, .12);
    --hairline: rgba(242, 242, 243, .08);

    --accent: #94BCE3;
    --accent-hover: #B5D9FD;
    --accent-strong: #94BCE3;          /* 7.06 with --on-accent; no step needed here */
    --accent-strong-hover: #B5D9FD;
    --accent-soft: rgba(148, 188, 227, .12);
    --on-accent: #1D2D3D;

    /* Soft button, dark: Scheme.surface fill, accent label (4.99:1); on a
       tinted panel the tint composited over the surface (#38536D) with an
       a300 label (5.45:1). */
    --soft-fill: #2C455D;
    --soft-ink: #94BCE3;
    --soft-fill-hover: #416180;
    --soft-ink-hover: #D6EBFF;
    --soft-fill-raised: #38536D;
    --soft-ink-raised: #B5D9FD;
    --accent-soft-hover: rgba(148, 188, 227, .20);

    --plate: #F2F2F3;
    --on-plate: #1D2D3D;
    --on-plate-accent: #416180;   /* 5.78 on the light plate this theme uses */
    --track: #416180;

    /* The intensity track is --track (#416180 = --a700), exactly as the design's
       role-swap table says and exactly what Scheme.dark.track is in the app.
       It USED to step down to --a800 here, because the dark ramp had been left
       at its light values and zone 4 was also --a700 — a fill drawn at 1.00:1
       against its own track. Turning the whole ramp over (below) moved zone 4
       to --a300 and dissolved that collision, so the workaround is gone and the
       three surfaces agree again. Contrast against the track now RISES
       monotonically with the zone, which is the encoding working with the
       colour rather than against it: the harder the day, the more the bar
       separates from its track. */
    --intensity-track: var(--track);

    /* THE WHOLE INTENSITY RAMP TURNS OVER IN DARK, not just its top step.
       This MUST stay identical to Intensity._darkRamp in the Flutter app's
       lib/core/theme/app_tokens.dart — one design system, and a bar that means
       "threshold" on the website has to mean it in the app.

       Flipping zone 5 alone was the obvious fix and it was wrong twice over:
       zone 4 stayed on --a700, which IS --track in dark, so the hardest-but-one
       day drew an invisible bar against its own track; and zone 3 stayed on the
       light accent (#5980A6), which is barely separable from the #1D2D3D
       ground. Light DARKENS as the day gets harder and ends on the plate
       colour; dark LIGHTENS as the day gets harder and ends on the far end of
       the same ramp. Same gesture, turned over. Every value is a named step. */
    --z1-color: var(--a600);
    --z2-color: var(--a500);
    --z3-color: var(--a400);
    --z4-color: var(--a300);
    --z5-color: var(--a200);
  }
}


/* --------------------------------------------------------------------------
   3. RESET
   -------------------------------------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: auto; }

@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

h1, h2, h3, h4, h5, h6 {
  margin: 0;
  font-family: var(--font-head);
  font-weight: 600;
  line-height: 1.02;
  letter-spacing: -.02em;
}
h1 { font-size: var(--fs-h1); }
h2 { font-size: var(--fs-h2); }
h3 { font-size: var(--fs-h3); letter-spacing: -.01em; line-height: 1.1; }
h4 { font-size: var(--fs-h4); letter-spacing: 0; line-height: 1.15; }

p, ul, ol, dl, figure, blockquote { margin: 0; }
ul, ol { padding: 0; list-style: none; }

a { color: var(--accent-strong); text-decoration-thickness: 1px; text-underline-offset: 3px; }
a:hover { color: var(--accent-strong-hover); }

img, svg, video { max-width: 100%; height: auto; display: block; }

button, input, select, textarea { font: inherit; color: inherit; }
button { background: none; border: 0; cursor: pointer; }

hr { border: 0; height: 1px; background: var(--divider); margin: 0; }

strong, b { font-weight: 600; }

table { border-collapse: collapse; width: 100%; }

::selection { background: var(--a300); color: #1D2D3D; }


/* --------------------------------------------------------------------------
   4. FOCUS — one ring, everywhere, both themes.
   -------------------------------------------------------------------------- */

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 4px;
}
/* Inside a plate the ground is inverted, and in dark theme that ground is
   #F2F2F3 — where the normal --accent ring falls to 1.78:1 and effectively
   disappears. The plate's own accent ink clears 3:1 in both themes. */
.plate :focus-visible,
.on-plate :focus-visible,
.plate-band :focus-visible {
  outline-color: var(--on-plate-accent);
}
:focus:not(:focus-visible) { outline: none; }

.skip-link {
  position: absolute;
  left: 12px;
  top: -100px;
  z-index: 100;
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 18px;
  background: var(--accent-strong);
  color: var(--on-accent);
  border-radius: var(--r-control);
  font-family: var(--font-head);
  font-weight: 600;
  letter-spacing: .04em;
  text-decoration: none;
}
.skip-link:focus { top: 12px; color: var(--on-accent); }

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
/* The waitlist's honeypot field: out of sight and out of the tab order, but present in the DOM for a form-filling bot. */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* --------------------------------------------------------------------------
   5. LAYOUT PRIMITIVES
   -------------------------------------------------------------------------- */

/* Content is 1240px wide with 64px gutters at desktop, one column with 20px
   gutters below 860px. Nothing may scroll horizontally at 360px. */
.wrap {
  width: 100%;
  max-width: calc(var(--wrap) + var(--gutter) * 2);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.section {
  padding-block: clamp(56px, 7vw, var(--section-y)) clamp(60px, 7.4vw, 92px);
}
.section-rule { border-bottom: 1px solid var(--divider); }

/* A full-width 1px line, drawn inside the wrap. */
.rule { height: 1px; background: var(--divider); border: 0; margin: 0; }
.rule-faint { height: 1px; background: var(--hairline); border: 0; margin: 0; }

.grid { display: grid; gap: var(--gap, 24px); }
.grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

@media (max-width: 1100px) {
  .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 860px) {
  :root { --gutter: 20px; }
  .grid-2, .grid-3 { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 560px) {
  .grid-4 { grid-template-columns: minmax(0, 1fr); }
}

/* Anything wide (tables, code, a fixed-width diagram) goes in one of these
   rather than pushing the body sideways. */
.scroll-x { overflow-x: auto; -webkit-overflow-scrolling: touch; }


/* --------------------------------------------------------------------------
   6. TYPE PRIMITIVES
   -------------------------------------------------------------------------- */

/* Kickers are typed in uppercase AT THE CALL SITE. Never text-transform them —
   condensed/mono caps need the real characters for the letter-spacing to sit
   right, and screen readers read spelled-out capitals differently. */
.kicker {
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: 11px;
  line-height: 1;
  letter-spacing: .16em;
  color: var(--accent-strong);
}
.kicker-lg { font-size: 11px; }            /* the section kickers in the design */
.kicker-muted { color: var(--text-secondary); }
.kicker-on-plate,
.data-on-plate { color: var(--on-plate-accent); }

.display { font-family: var(--font-head); font-weight: 600; font-size: var(--fs-display); line-height: .98; letter-spacing: -.025em; }

.lede { font-size: var(--fs-lede); line-height: 1.55; color: var(--text-copy); }
.prose { font-size: var(--fs-body); line-height: 1.62; color: var(--text-copy); }
.prose strong { color: var(--text); font-weight: 600; }
.fine { font-size: var(--fs-fine); color: var(--text-secondary); }

/* Numbers, times, distances, zone labels. */
.data {
  font-family: var(--font-mono);
  font-weight: 600;
  font-size: 11px;
  line-height: 1;
  letter-spacing: .08em;
}
.data-lg { font-size: 12px; letter-spacing: .06em; }

/* .muted / .faint deliberately resolve to the contrast-safe pair, NOT to the
   raw --text-muted / --text-faint tokens. See the note on those tokens. */
.muted { color: var(--text-copy); }
.faint { color: var(--text-secondary); }
.nowrap { white-space: nowrap; }


/* --------------------------------------------------------------------------
   7. ICONS
   Stroke settings live here, on the parent <svg>, not on the symbols.
   -------------------------------------------------------------------------- */

.icon-sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

.ico {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  flex: none;
  display: inline-block;
  vertical-align: middle;
}
.ico-bold { stroke-width: 2.5; }   /* the 16px checkmarks in the pricing table */
.ico-accent { color: var(--accent); }


/* --------------------------------------------------------------------------
   8. BUTTONS — 44px minimum touch target on every variant.
   -------------------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  min-height: 46px;
  padding: 0 22px;
  border: 1px solid transparent;
  border-radius: var(--r-control);
  background: transparent;
  color: var(--text);
  font-family: var(--font-head);
  font-weight: 600;
  font-size: 17px;                 /* the app's secondary label: 17 / 600 */
  line-height: 1;
  letter-spacing: .04em;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
}
.btn-sm { min-height: 44px; padding: 0 20px; font-size: 15px; }
.btn-lg { min-height: 54px; padding: 0 28px; }
.btn-block { display: flex; width: 100%; }

/* The PRIMARY label is the app's 19px / 700 (T.buttonPrimary): bold from 18.66px
   is what lets a #F2F2F3 label on the accent fill count as large text. The
   small button stays at 15px so a nav bar CTA does not shout. */
.btn-accent {
  background: var(--accent-strong);
  border-color: var(--accent-strong);
  color: var(--on-accent);
  font-size: 19px;
  font-weight: 700;
  letter-spacing: .03em;
}
.btn-accent.btn-sm { font-size: 15px; }
.btn-accent:hover { background: var(--accent-strong-hover); border-color: var(--accent-strong-hover); color: var(--on-accent); }

/* The one secondary button: a soft fill, no outline (app D8; the outlined
   "ghost" is retired). */
.btn-soft { background: var(--soft-fill); border-color: var(--soft-fill); color: var(--soft-ink); }
.btn-soft:hover { background: var(--soft-fill-hover); border-color: var(--soft-fill-hover); color: var(--soft-ink-hover); }
.card .btn-soft,
.card-tint .btn-soft { background: var(--soft-fill-raised); border-color: var(--soft-fill-raised); color: var(--soft-ink-raised); }
.card .btn-soft:hover,
.card-tint .btn-soft:hover,
a.card:hover .btn-soft { background: var(--soft-fill-hover); border-color: var(--soft-fill-hover); color: var(--soft-ink-hover); }

/* On a plate (inverted block) the soft fill has to come from the plate ink. */
.on-plate .btn-soft { background: rgba(242, 242, 243, .16); border-color: transparent; color: var(--on-plate); }
.on-plate .btn-soft:hover { background: rgba(242, 242, 243, .26); border-color: transparent; color: var(--on-plate); }
@media (prefers-color-scheme: dark) {
  .on-plate .btn-soft { background: rgba(29, 31, 32, .12); }
  .on-plate .btn-soft:hover { background: rgba(29, 31, 32, .20); }
}


/* --------------------------------------------------------------------------
   9. SURFACES
   Elevation goes UP the ramp — a lighter/darker step, and a panel is a tint with no outline.
   There are no box-shadows anywhere in this system.
   -------------------------------------------------------------------------- */

/* A panel, as the app draws it (AppPanel): the tint, radius 20, no outline.
   The border stays as a transparent 1px so every card keeps its metrics. */
.card {
  border: 1px solid transparent;
  border-radius: var(--r-surface);
  padding: 22px 24px;
  background: var(--accent-soft);
}
.card-sm { border-radius: 16px; padding: 18px 20px; }
/* The featured card keeps the accent outline: it is the one emphasis on a row
   of panels, and it is not a button. */
.card-tint { background: var(--accent-soft); border-color: var(--accent); }
/* An empty or placeholder state: bare ground and a dashed edge, on purpose. */
.card-dashed { background: transparent; border-style: dashed; border-color: var(--divider); }

/* Link cards: the whole card is the hit area. */
a.card { display: block; color: inherit; text-decoration: none; }
a.card:hover { background: var(--accent-soft-hover); color: inherit; }
a.card.card-tint:hover { border-color: var(--accent); }

/* The inverted block. Sets its own ink so children can just use currentColor. */
.plate,
.on-plate {
  background: var(--plate);
  color: var(--on-plate);
  border-radius: var(--r-surface);
}
/* On a plate the ground is inverted, so secondary ink has to invert too.
   .72 over #1D2D3D = 7.26; .72 over #F2F2F3 = 6.18. */
.plate .muted, .on-plate .muted,
.plate .fine, .on-plate .fine { color: rgba(242, 242, 243, .72); }
@media (prefers-color-scheme: dark) {
  .plate .muted, .on-plate .muted,
  .plate .fine, .on-plate .fine { color: rgba(29, 31, 32, .72); }
}

/* A section-wide inverted band (the waitlist block) — no radius, full bleed. */
.plate-band {
  background: var(--plate);
  color: var(--on-plate);
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 10px;
  border-radius: var(--r-pill);
  border: 1px solid var(--divider);
  background: transparent;
  font-family: var(--font-mono);
  font-weight: 600;
  font-size: 11px;
  line-height: 1;
  letter-spacing: .10em;
  color: var(--text-secondary);
  white-space: nowrap;
}
.chip-accent { background: var(--accent-strong); border-color: var(--accent-strong); color: var(--on-accent); }
.chip-soft { background: var(--accent-soft); border-color: transparent; color: var(--accent-strong); }
.chip-square { border-radius: 6px; }

/* Rows separated by hairlines, last row bare. Used by the plan mock, the FAQ
   list and the sample week. */
.hairline-list > * + * { border-top: 1px solid var(--hairline); }
.hairline-list.is-boxed { border-top: 1px solid var(--divider); }
.hairline-list > * { padding-block: 14px; }
.hairline-list.is-tight > * { padding-block: 0; min-height: 44px; display: flex; align-items: center; }


/* --------------------------------------------------------------------------
   10. INTENSITY BAR
   A 4x24 vertical track with a bottom-aligned fill. Drive it with --fill
   (a percentage) and --zone-color, or just add .z1 … .z5.
   Zone words, for labels: Recovery / Easy / Steady / Threshold / Max.

   THE BAR IS NEVER THE ONLY CARRIER OF THE ZONE. It encodes intensity twice —
   by fill height and by colour — but at the dark end of the ramp the fill sits
   very close to its own track (zone 4 reaches only 1.53:1 there). So the zone
   must ALSO appear as text in the same row: either visible copy that names it
   ("Z4 THRESHOLD") or a .sr-only span. The bar itself is decorative and
   carries aria-hidden.
   -------------------------------------------------------------------------- */

.intensity {
  --fill: 0%;
  --zone-color: var(--accent);
  position: relative;
  flex: none;
  display: inline-block;
  width: 4px;
  height: 24px;
  border-radius: 2px;
  background: var(--intensity-track);
  vertical-align: middle;
}
.intensity::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 4px;
  height: var(--fill);
  border-radius: 2px;
  background: var(--zone-color);
}
.z1 { --fill: var(--z1-fill); --zone-color: var(--z1-color); }
.z2 { --fill: var(--z2-fill); --zone-color: var(--z2-color); }
.z3 { --fill: var(--z3-fill); --zone-color: var(--z3-color); }
.z4 { --fill: var(--z4-fill); --zone-color: var(--z4-color); }
.z5 { --fill: var(--z5-fill); --zone-color: var(--z5-color); }


/* --------------------------------------------------------------------------
   11. HEADER / NAV / FOOTER  (nav.mjs, footer.mjs)
   -------------------------------------------------------------------------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 20;
  background: var(--bg);
  border-bottom: 1px solid var(--divider);
}
.nav-wrap {
  min-height: 74px;
  display: flex;
  align-items: center;
  gap: 26px;
}

.brand {
  display: inline-flex;
  align-items: center;
  min-height: 44px;          /* it is a link in the header — full touch target */
  font-family: var(--font-head);
  font-weight: 600;
  font-size: 23px;
  line-height: 1;
  letter-spacing: .03em;
  color: var(--text);
  text-decoration: none;
  flex: none;
}
.brand:hover { color: var(--text); }
/* The brand (brand/README.md): ADAPT in the text colour, LETE in the accent, and the mark in front of it in
   the header. The mark's markup is GENERATED (src/brand-mark.mjs); its colours and weights are set here. */
.brand-lete { color: var(--accent); }
.brand-mark { width: 1.3em; height: 1.3em; flex: none; margin-right: .32em; color: var(--text); }
.brand-mark .bm-bar { stroke: var(--accent); }
.brand-mark .bm-plate { fill: var(--accent); }
/* Light strokes on a dark ground look heavier than dark on light; the dark cut is drawn 12% thinner. */
@media (prefers-color-scheme: dark) {
  .brand-mark .bm-line { stroke-width: 7.48; }
  .brand-mark .bm-wheel { stroke-width: 5.72; }
  .brand-mark .bm-bar { stroke-width: 4.4; }
}

.nav-desktop { display: flex; align-items: center; }
.nav-links { display: flex; align-items: center; gap: 28px; font-size: 14.5px; }
.nav-links > li { position: relative; }

.nav-link {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  min-height: 44px;
  color: var(--text);
  text-decoration: none;
}
.nav-link:hover { color: var(--accent-strong); }
.nav-link[aria-current="page"],
.nav-link.is-active { color: var(--accent-strong); font-weight: 600; }

/* Sport-hub dropdown. Opens on hover AND on focus-within, so it is reachable
   by keyboard with no script. */
.nav-menu {
  position: absolute;
  top: 100%;
  left: -14px;
  min-width: 208px;
  margin: 0;
  padding: 8px;
  background: var(--bg);
  border: 1px solid var(--divider);
  border-radius: var(--r-surface);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-4px);
}
.nav-has-menu:hover > .nav-menu,
.nav-has-menu:focus-within > .nav-menu {
  opacity: 1;
  visibility: visible;
  transform: none;
}
.nav-menu a {
  display: flex;
  align-items: center;
  min-height: 44px;
  padding: 0 12px;
  border-radius: var(--r-chip);
  color: var(--text);
  text-decoration: none;
  font-size: 14.5px;
}
.nav-menu a:hover { background: var(--accent-soft); color: var(--text); }

.nav-end { margin-left: auto; display: flex; align-items: center; gap: 16px; }
.nav-badge {
  font-family: var(--font-mono);
  font-weight: 600;
  font-size: 11px;
  line-height: 1;
  letter-spacing: .12em;
  color: var(--text-secondary);
}

/* Mobile disclosure. Rendered at every width but only displayed below 860px;
   the desktop <nav> is display:none there, so exactly one nav landmark and one
   copy of each link is ever in the accessibility tree. */
.nav-mobile { display: none; margin-left: auto; }
.nav-summary {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border: 1px solid var(--divider);
  border-radius: var(--r-control);
  list-style: none;
  cursor: pointer;
  color: var(--text);
}
.nav-summary::-webkit-details-marker { display: none; }
.nav-mobile[open] .nav-summary { border-color: var(--accent); color: var(--accent-strong); }
.nav-panel {
  position: absolute;
  left: 0;
  right: 0;
  top: 100%;
  padding: 8px var(--gutter) 20px;
  background: var(--bg);
  border-bottom: 1px solid var(--divider);
}
/* Scoped to the link LIST, not to every <a> in the panel — the panel also
   holds the CTA, and a bare `.nav-panel a` rule outranks `.btn-accent`
   (0,1,1 beats 0,1,0). That put --text ink on the accent ground at 2.56:1
   and stamped a hairline border across the top of the button. */
.nav-panel ul a {
  display: flex;
  align-items: center;
  min-height: 48px;
  color: var(--text);
  text-decoration: none;
  font-size: 16px;
  border-top: 1px solid var(--hairline);
}
.nav-panel .nav-sub a { padding-left: 18px; color: var(--text-copy); font-size: 15px; }
.nav-panel .btn { margin-top: 16px; }

@media (max-width: 860px) {
  .nav-desktop, .nav-end { display: none; }
  .nav-mobile { display: block; }
  .site-header { position: sticky; }
  .nav-wrap { min-height: 64px; position: relative; }
}

.site-footer { border-top: 1px solid var(--divider); }
.footer-top {
  display: flex;
  gap: 80px;
  align-items: flex-start;
  padding-block: 52px 44px;
}
.footer-brand { flex: 1; min-width: 220px; }
.footer-cols { display: flex; gap: 64px; flex-wrap: wrap; font-size: 14px; }
.footer-col { display: flex; flex-direction: column; }
.footer-col h2 {
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: 11px;
  line-height: 1;
  letter-spacing: .12em;
  color: var(--text-secondary);
  margin-bottom: 6px;
}
.footer-col a {
  display: flex;
  align-items: center;
  min-height: 44px;
  color: var(--text);
  text-decoration: none;
}
.footer-col a:hover { color: var(--accent-strong); }
.footer-legal {
  border-top: 1px solid var(--divider);
  padding-block: 20px 40px;
  display: flex;
  gap: 16px;
  justify-content: space-between;
  flex-wrap: wrap;
  font-size: 12.5px;
  color: var(--text-secondary);
}
.footer-legal .mono { font-family: var(--font-mono); }
.footer-trademark {
  padding-block: 20px 0;
  border-top: 1px solid var(--hairline);
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--text-secondary);
  max-width: 900px;
}

@media (max-width: 860px) {
  .footer-top { flex-direction: column; gap: 36px; padding-block: 40px 28px; }
  .footer-cols { gap: 28px 40px; }
}


/* --------------------------------------------------------------------------
   12. MOTION
   Two durations only. Every transition is inside this guard, so a visitor who
   asked for reduced motion gets a site with no transitions at all.
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: no-preference) {
  a,
  .btn,
  .nav-link,
  .nav-summary,
  a.card,
  .chip,
  .footer-col a {
    transition:
      color var(--dur-state) var(--ease-out),
      background-color var(--dur-state) var(--ease-out),
      border-color var(--dur-state) var(--ease-out);
  }

  .nav-menu {
    transition:
      opacity var(--dur-enter) var(--ease-out),
      transform var(--dur-enter) var(--ease-out),
      visibility 0s linear var(--dur-enter);
  }
  .nav-has-menu:hover > .nav-menu,
  .nav-has-menu:focus-within > .nav-menu {
    transition:
      opacity var(--dur-enter) var(--ease-out),
      transform var(--dur-enter) var(--ease-out),
      visibility 0s;
  }

  /* Scroll reveal. Add .reveal to a block; build.mjs may add the tiny
     IntersectionObserver as an inlineScript. With no script the element is
     visible anyway — the observer only ever removes .reveal. */
  .reveal {
    opacity: 0;
    transform: translateY(10px);
    transition:
      opacity var(--dur-enter) var(--ease-out),
      transform var(--dur-enter) var(--ease-out);
  }
  .reveal.is-in { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}

/* Print: never waste ink on the sticky chrome. */
@media print {
  .site-header, .site-footer, .skip-link { display: none; }
  body { background: #fff; color: #000; }
  /* A panel is a tint on screen; on paper the tint is gone, so it keeps a box. */
  .card { border-color: #767676; }
}
