/* ==========================================================================
   MEAN TRUTH FITNESS
   Implements DESIGN.md. Palette, typefaces, motifs and motion rules are
   treated as locked. Mobile first, authored against 390px.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Tokens
   Neutral ramp and text colours are brand level. The accent is written per
   page by build.js onto [data-protocol], so a new protocol is a colourway
   swap and nothing else (DESIGN.md section 9).
   -------------------------------------------------------------------------- */
:root {
  /* DESIGN.md section 2. Seven colours. Locked. */
  --black: #070707;      /* page background            */
  --onyx: #0d0d0d;       /* alternating sections, cards */
  --carbon: #1b1b1b;     /* hairlines, borders          */
  --parchment: #f2efe9;  /* headlines, primary text     */
  --olive: #8b8681;      /* body copy                   */
  --struck: #4a4642;     /* darkened olive, struck text */

  /* Fallbacks. build.js overrides these on the page root. */
  --accent: #dd0a0a;     /* Racing Red */
  --accent-deep: #8c0808;/* Blood Red  */

  --display: 'Anton', 'Arial Narrow', 'Haettenschweiler', sans-serif;
  --body: 'Barlow Condensed', 'Arial Narrow', sans-serif;

  /* Motion. MOTION_INTENSITY 5: heavy and deliberate, never elastic.
     No spring, no overshoot, no bounce (DESIGN.md section 6). */
  --ease: cubic-bezier(0.2, 0.6, 0.2, 1);
  --t-fast: 180ms;
  --t-mid: 320ms;
  --t-reveal: 620ms;

  --gut: 20px;           /* mobile gutter */
  --maxw: 1240px;

  /* Height of the fixed buy bar: 1px top border, 10px padding, a 44px control,
     10px padding, plus the home indicator inset. Measured at 65px, not the 64
     the padding and control alone suggest. Sections reserve this much at their
     foot so nothing, the proof caption included, can come to rest underneath
     it. Declared once here and consumed once, in the .sec rule. */
  --buybar-h: calc(65px + env(safe-area-inset-bottom, 0px));

  --z-grain: 60;
  --z-nav: 70;
  --z-buybar: 80;
  --z-skip: 90;
}

/* --------------------------------------------------------------------------
   2. Reset
   -------------------------------------------------------------------------- */
*,
*::before,
*::after { box-sizing: border-box; }

* { margin: 0; padding: 0; }

/* DESIGN.md section 4: square corners only. No rounded corners anywhere. */
*,
input,
button,
select,
textarea { border-radius: 0; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;   /* native only. No smooth scroll library. */
  scroll-padding-top: 76px;
}

body {
  background: var(--black);
  color: var(--olive);
  font-family: var(--body);
  font-size: 17px;
  font-weight: 400;
  line-height: 1.5;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

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

button,
input { font: inherit; color: inherit; background: none; border: none; }

button { cursor: pointer; }

a { color: inherit; text-decoration: none; }

ul, ol { list-style: none; }

::selection { background: var(--accent); color: var(--parchment); }

/* Keyboard focus. Visible against near black without using a new hue. */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}

/* --------------------------------------------------------------------------
   3. Type primitives
   DESIGN.md section 3. Two families only. Anton always uppercase, 0.92
   line height. Barlow Condensed for everything else.
   -------------------------------------------------------------------------- */
.display {
  font-family: var(--display);
  font-weight: 400;
  text-transform: uppercase;
  line-height: 0.92;
  letter-spacing: 0.005em;
  color: var(--parchment);
}

/* Eyebrow: Barlow Condensed 13px / 700 / .3em / uppercase / Blood red. */
.eyebrow {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--accent-deep);
  /* Blood Red on near black is low contrast at this size, so the eyebrow is
     never the only carrier of meaning. It always sits above a Parchment
     heading that repeats it. */
}

.num { font-variant-numeric: tabular-nums; }

/* Two part heading construction (DESIGN.md section 3).
   Line one upright in Parchment. Line two red and skewed -9deg, backed by a
   Blood Red offset so the red carries depth rather than sitting flat. */
.h2 { margin-bottom: 22px; }

.h2 .h-top,
.hero-lockup .h-top {
  display: block;
  color: var(--parchment);
}

.h2 .h-bot,
.hero-lockup .h-bot {
  display: block;
  color: var(--accent);
  transform: skewX(-9deg);
  transform-origin: left bottom;
  text-shadow: 2px 3px 0 var(--accent-deep);
}

.h2 .h-top,
.h2 .h-bot {
  font-family: var(--display);
  font-weight: 400;
  text-transform: uppercase;
  line-height: 0.92;
  font-size: clamp(1.95rem, 8.8vw, 4.75rem);
}

.h2 .h-bot { margin-top: 0.02em; }

.lede {
  max-width: 62ch;
  font-size: 17px;
  line-height: 1.55;
  color: var(--olive);
  text-wrap: pretty;
}

/* --------------------------------------------------------------------------
   4. Motifs
   DESIGN.md section 4.
   -------------------------------------------------------------------------- */

/* Claw marks. The primary structural marker above each section heading.
   Traced from the supplied artwork to a single path, defined once as
   #mt-claw and referenced here. Box height and the 16px below it are
   unchanged; width now follows the artwork's own aspect. */
.claw {
  display: flex;
  align-items: flex-end;
  height: 30px;
  margin-bottom: 16px;
  color: var(--accent);
}
/* currentColor, so the mark inherits `color` above. That is the page accent
   by default and the Lean Blueprint accent inside #lean-blueprint, which
   already overrides --accent for its own subtree. */
.claw__i {
  height: 100%;
  width: auto;
  overflow: visible;
}

/* The symbol definition itself must never occupy layout. */
.sprite {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}

/* Red slash rule. A 74px red bar, skewed, under headings. */
.slash {
  width: 74px;
  height: 5px;
  background: var(--accent);
  transform: skewX(-22deg);
  margin: 20px 0 22px 3px;
}
.slash--sm { width: 46px; height: 3px; margin: 14px 0 16px 2px; }

/* Cell scale claw, for the spec grid. Same mark, smaller box. */
.claw--sm { height: 19px; margin-bottom: 11px; }

/* Grain. A fine noise overlay across the whole page at roughly 9%.
   Fixed, non interactive, and switched off for reduced motion users only
   where it would otherwise animate. It never animates here. */
.grain {
  position: fixed;
  inset: 0;
  z-index: var(--z-grain);
  pointer-events: none;
  opacity: 0.09;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.82' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 180px 180px;
}

/* Hairline panels. 1px Carbon Black borders on near black fills. */
.panel {
  border: 1px solid var(--carbon);
  background: var(--onyx);
}

/* Grid determinism: a 1px gap over a Carbon parent draws razor thin rules
   without per cell border maths. */
.hairgrid {
  display: grid;
  gap: 1px;
  background: var(--carbon);
  border: 1px solid var(--carbon);
}
.hairgrid > * { background: var(--onyx); }

/* --------------------------------------------------------------------------
   5. Layout
   -------------------------------------------------------------------------- */
.wrap {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--gut);
}

section { position: relative; }

/* Bottom padding carries the buy bar clearance. One rule, every section. */
.sec { padding-block: 68px calc(68px + var(--buybar-h)); }

/* The newsletter is the last section before the footer, and the buy bar is
   never shown below the buy section, so its clearance was dead space sitting
   directly on the footer divider. The footer keeps its own clearance. */
#newsletter { padding-bottom: 44px; }

/* The buy bar hides once the join section is in view and stays hidden below
   it, so the join section's bar clearance was dead space too. With join and
   the newsletter both on the black page it read as one tall gap above the
   newsletter. */
#join { padding-bottom: 68px; }

/* Alternating sections use Onyx over the Black page (DESIGN.md section 2).
   Backgrounds stay near black throughout. There are no light sections. */
.sec--onyx { background: var(--onyx); }
.sec--onyx .hairgrid > * { background: var(--black); }

.sec-head { margin-bottom: 34px; }

/* Clipped to nothing until focused, rather than moved off screen with a
   transform. A transform is fragile: any rule that neutralises transforms,
   and some capture tools, put it back on screen. Clip cannot be undone by
   accident, and it is the technique the rest of the site already uses for
   .visually-hidden. */
.skip {
  position: fixed;
  top: 8px;
  left: 8px;
  z-index: var(--z-skip);
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  background: var(--accent);
  color: var(--parchment);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-size: 13px;
}
.skip:focus {
  width: auto;
  height: auto;
  padding: 10px 16px;
  margin: 0;
  overflow: visible;
  clip: auto;
  clip-path: none;
}

/* --------------------------------------------------------------------------
   6. Buttons
   -------------------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 52px;
  padding: 0 26px;
  font-family: var(--display);
  font-size: 20px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  line-height: 1;
  border: 1px solid transparent;
  transition: background var(--t-fast) var(--ease),
              color var(--t-fast) var(--ease),
              border-color var(--t-fast) var(--ease),
              transform var(--t-fast) var(--ease);
}

/* Parchment on Racing Red is 5.1:1. Safe. */
.btn--primary {
  background: var(--accent);
  color: var(--parchment);
}
.btn--primary:hover { background: var(--accent-deep); }
.btn--primary:active { transform: translateY(1px); }

.btn--ghost {
  border-color: var(--carbon);
  color: var(--parchment);
  background: transparent;
}
.btn--ghost:hover { border-color: var(--accent); color: var(--accent); }
.btn--ghost:active { transform: translateY(1px); }

/* Hairline panel. DESIGN.md section 2 reserves Racing Red fills for buy
   actions, so a control that needs weight without being one takes section 4's
   panel instead: 1px Carbon Black on a near-black fill, Parchment label. */
.btn--panel {
  background: var(--onyx);
  border-color: var(--carbon);
  color: var(--parchment);
}
.btn--panel:hover { background: var(--carbon); }
.btn--panel:active { transform: translateY(1px); }


/* --------------------------------------------------------------------------
   7. Navigation
   -------------------------------------------------------------------------- */
/* Solid, and edge to edge. No translucency, no blur, no gradient and no
   hairline: the bar is a black band, and anything lighter along its edge read
   as a seam against the page it sits on. */
.nav {
  position: sticky;
  top: 0;
  z-index: var(--z-nav);
  background: #070707;
  border-bottom: 0;
}
.nav__in {
  display: flex;
  align-items: center;
  gap: 14px;
  min-height: 58px;
}
.nav__brand {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-right: auto;
}
.nav__mark { width: 26px; height: 26px; object-fit: contain; }
.nav__name {
  font-family: var(--display);
  font-size: 17px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--parchment);
  line-height: 1;
}
.nav__name b { color: var(--accent); font-weight: 400; }
.nav__links { display: none; gap: 26px; }
.nav__links a {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--olive);
  transition: color var(--t-fast) var(--ease);
}
.nav__links a:hover,
.nav__links a[aria-current='true'] { color: var(--parchment); }
.nav__cta {
  min-height: 38px;
  padding: 0 18px;
  font-size: 16px;
}
/* Login in the header carries no outline at all. It is the same solid black
   as the bar it sits in, with Parchment type, and it answers a hover or a
   focus by turning the type Racing Red rather than by drawing a border back
   in. The focus ring is the one exception, because that is the browser's
   accessibility affordance and not decoration. */
.nav .btn--ghost.nav__cta {
  background: #070707;
  border-color: transparent;
  color: var(--parchment);
}
.nav .btn--ghost.nav__cta:hover,
.nav .btn--ghost.nav__cta:focus,
.nav .btn--ghost.nav__cta:focus-visible,
.nav .btn--ghost.nav__cta:active {
  background: #070707;
  border-color: transparent;
  color: var(--accent);
}

/* --------------------------------------------------------------------------
   8. Hero
   Buy button is inside the first viewport. DESIGN.md section 6 target:
   reachable within three scrolls.
   -------------------------------------------------------------------------- */
.hero {
  position: relative;
  overflow: hidden;
  padding-block: 44px 54px;
  border-bottom: 1px solid var(--carbon);
}

/* Static background plate. No parallax, no scroll transform. */
.hero__plate {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  /* The video is 1280 native. 1280 x 1.15 = 1472, so past this the plate
     stops growing and the black page background extends either side rather
     than the video stretching further. margin-inline centres it against the
     inset. */
  max-width: 1472px;
  margin-inline: auto;
}
/* Still and video share one rule, so the crop, position, opacity and filter
   are identical whichever one is showing. The gradient is an ::after and
   paints over whichever it is. */
/* <picture> is only a selector wrapper here; the img is absolutely positioned,
   so the picture box itself must not participate in layout. */
.hero__plate picture { display: contents; }

/* Top aligned, not centred, because the animal is right at the top of its own
   frame. Measured rather than judged: across every frame of the loop the
   whitest fur of the ears never starts lower than 1.11% down the frame, and
   the two stills are the same at 1.11% and 0.83%. A centred cover crop takes
   2.84% off the top at 1280 and 8.99% from 1600 up, so the ears were being
   cut at every desktop width. At 0% the crop comes off the bottom instead,
   where the frame is the floor of the gym, and the head is whole at any
   width the plate is ever given. */
.hero__plate img,
.hero__plate video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 0%;
  opacity: 0.42;
  filter: grayscale(0.3) contrast(1.08);
}

.hero__plate video {
  /* Let the compositor resample normally. Any smoothing hint here would only
     make an upscaled frame look worse, not sharper. */
  image-rendering: auto;
}

/* Exactly one layer renders at a time. The still is the background on its own
   below 768px and under reduced motion; once the video mounts the still is
   taken out entirely rather than left underneath it. Nothing is stacked and
   nothing is composited, so the subject cannot ghost against itself.
   The video carries the same file as its poster attribute, so it has an image
   to show from the moment it exists and hiding the still cannot flash. */
.hero__plate.has-video img {
  display: none;
}

/* Belt and braces. The script is what actually keeps the video off small
   screens and reduced-motion sessions, by never giving it a source. These
   only matter if that ever fails. */
@media (max-width: 767px) {
  .hero__plate video { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .hero__plate video { display: none; }
}
/* The mask is horizontal now, not a flat vertical darkener plus a vignette.
   The old pair dimmed the whole frame evenly across its width, which is what
   washed the subject out: the right side was paying for contrast the headline
   needed on the left.

   Layer one carries the headline. It holds roughly the darkening the old mask
   produced where the type sits, about 0.55 effective at 26% across, then
   falls away through the centre to almost nothing over the right half so the
   tiger and the red rim light keep their saturation.

   Layer two is bottom only. It grounds the section into the black page and
   keeps the telemetry strip legible. It starts at 62%, well below the
   headline, so it costs the subject nothing.

   The stats are unaffected either way: their cells are opaque Onyx, so their
   contrast never depended on this mask. */
.hero__plate::after {
  content: '';
  position: absolute;
  inset: 0;
  background:
    linear-gradient(90deg,
      rgba(7,7,7,0.60) 0%,
      rgba(7,7,7,0.54) 32%,
      rgba(7,7,7,0.30) 50%,
      rgba(7,7,7,0.12) 66%,
      rgba(7,7,7,0.04) 82%,
      rgba(7,7,7,0.02) 100%),
    /* Bottom fade. It reaches full black at the last pixel rather than
       stopping short, so the plate meets the page instead of ending on a
       visible edge. Only the last stretch changes; the stop at 88% is where
       it was, so the subject is not darkened any further. */
    linear-gradient(180deg,
      rgba(7,7,7,0) 62%,
      rgba(7,7,7,0.45) 88%,
      rgba(7,7,7,0.78) 96%,
      rgba(7,7,7,1) 100%);
}

/* Past the cap the plate no longer reaches the viewport edges, so its own left
   and right edges would read as hard vertical seams against the black. This
   feathers them, and only at the widths where those edges exist: at 1472 and
   below the plate is full bleed and this never applies. z-index lifts it over
   the video, which is a positioned sibling painted after it. */
@media (min-width: 1473px) {
  .hero__plate::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 2;
    pointer-events: none;
    background: linear-gradient(90deg,
      rgba(7,7,7,0.92) 0%,
      rgba(7,7,7,0) 4.5%,
      rgba(7,7,7,0) 92%,
      rgba(7,7,7,0.92) 100%);
  }
}

.hero__in { position: relative; z-index: 1; }

.hero-lockup { margin: 14px 0 0; }
/* One scale for both lines, so they read as a block rather than a stepped
   pair.

   Derived by measurement, not by eye: a binary search for the largest size at
   which both parts still fit the lead column, at 320, 360, 390, 430, 768,
   1024, 1280 and 1600. The vw term comes from the 320px case, which binds,
   and the ceiling from the widest layout, where the lead column stops growing.

   Each part wraps within itself. The two parts are 27 and 21 characters now,
   and holding each on a single line, as the ten character lines this replaced
   did, would put the heading at about 30px on a phone. Wrapping keeps it at
   about 55px there, at two rows per part. Neither part may overflow its
   column: tools/probe-hero.js reports the room left at every width.

   The ceiling is a desktop measurement, not a round number. Above 76px the
   second part wraps and the heading becomes four rows, which pushes the
   subtext and the buttons past the fold at 1280x800, where the sticky buy bar
   takes the bottom 65px of the screen. That 76px was found by walking the
   band at 1280x800 and at 1440x900; the ceiling sits just under it, so a
   difference in font metrics cannot tip the second part onto a second line. */
/* One row, three parts: YOU in Parchment, VS skewed in Racing Red, YOU again.
   Ten characters, which is what the size below was derived for.

   The parts are inline-block rather than block, because the whole lockup is
   one line now. Neither of the two rules they inherit from the h2 pair still
   fits a row, so both are restated here.

   The skew does not change the box the browser lays out, only what is drawn
   in it, so VS is given its own side margins: at the top of a 140px line a
   -9deg lean reaches about 22px sideways, which is enough to touch the Y
   beside it. The margins carry that in em, so the clearance scales with the
   type. */
/* One size drives the lockup and the three lines under it, so they cannot
   drift apart. It is the size this heading had when it was last ten
   characters: derived by measurement, the vw term from the 320px case and the
   ceiling from the 1100px layout, where the lead column stops growing at
   638px. tools/probe-hero.js asserts the row never wraps at any width, and
   reports the room left in the column. */
.hero__lead {
  --lockup: clamp(3.2rem, 19.6vw, 140px);
}
.hero-lockup {
  font-size: var(--lockup);
  white-space: nowrap;
}
.hero-lockup .h-top,
.hero-lockup .h-bot {
  display: inline-block;
  font-family: var(--display);
  text-transform: uppercase;
  white-space: nowrap;
  vertical-align: baseline;
}
.hero-lockup .h-top {
  font-size: 1em;
  line-height: 0.9;
  letter-spacing: -0.005em;
}
.hero-lockup .h-bot {
  font-size: 1em;
  line-height: 0.9;
  margin: 0 0.2em 0 0.16em;
  transform-origin: 50% 50%;
  /* The Blood Red offset was drawn for a 45px line. At 140px it doubles the
     red area of the largest red element on the page, so it scales with the
     type rather than staying a fixed 3px slab. */
  text-shadow: 0.015em 0.02em 0 var(--accent-deep);
}

/* The three lines under the lockup, read as one block with it.

   Barlow Condensed rather than Anton, so the lockup keeps the weight, and
   sized by the same measurement: the longest of the three, FOUR TRAINING
   SEASONS, fills the lead column the way YOU VS YOU does above it, which is
   what gives the heading, these lines and the paragraph below one right edge.

   The last line is the skewed Racing Red line the hero already had. It keeps
   its lean, its colour and its offset, and takes the size of the block it now
   sits in. */
.hero__sub {
  margin: 0.12em 0 0;
  font-family: var(--body);
  font-weight: 700;
  /* 0.43 of the lockup, which is the ratio at which the longest of the three,
     FOUR TRAINING SEASONS, comes out the same width as YOU VS YOU above it.
     Measured at both ends of the range, 0.430 at 320px and 0.433 at 1280px,
     so one fraction holds everywhere and the two read as a single block with
     a shared right edge. */
  font-size: calc(var(--lockup) * 0.43);
  line-height: 1.04;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--parchment);
}
.hero__sub-l {
  display: block;
  white-space: nowrap;
}
.hero__sub-red {
  color: var(--accent);
  transform: skewX(-9deg);
  transform-origin: left bottom;
  text-shadow: 0.015em 0.02em 0 var(--accent-deep);
}

/* Full width of the lead column, so its right edge lands where the lockup and
   the three lines above it end rather than stopping short of them. */
.hero__positioning {
  margin-top: 18px;
  font-size: 17px;
  line-height: 1.5;
  color: var(--olive);
}
/* Stacked on mobile so neither label truncates, and so the primary action is
   a full width tap target. Side by side from 800px. */
/* Content width, not full bleed. A 350px solid red slab across a 390px
   screen is the wallpaper DESIGN.md section 2 rules out, and on its own it
   was 5.5% of the viewport against a 10% budget for the whole page. The
   buttons still clear 44px and still sit one per row on a phone. */
.hero__cta {
  margin-top: 26px;
  display: grid;
  gap: 12px;
  /* One action now. It takes the width of its own label and sits at the left
     edge of the column, which is where the lockup, the three lines and the
     paragraph all start. On a phone it is the full column instead, so the tap
     target is the whole width rather than a label sized slab. */
  width: 100%;
  max-width: 100%;
  justify-items: stretch;
}
.hero__cta .btn { width: 100%; }

@media (min-width: 560px) {
  .hero__cta { width: max-content; }
}

/* Key stats. Hairline grid, 2 up on mobile. */
.stats {
  margin-top: 34px;
  grid-template-columns: repeat(2, 1fr);
}
/* Source order is semantic (term then value). Reversed here so the numeral
   reads first, which is what the eye wants. */
.stat {
  display: flex;
  flex-direction: column-reverse;
  justify-content: flex-end;
  padding: 16px 14px;
}
.stat__v {
  font-family: var(--display);
  font-size: clamp(2.1rem, 10vw, 3.1rem);
  line-height: 0.9;
  color: var(--accent-deep);       /* Blood Red carries numerals */
  font-variant-numeric: tabular-nums;
}
.stat__l {
  margin-bottom: 6px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--olive);
  line-height: 1.25;
}

/* --------------------------------------------------------------------------
   9. Strikethrough. The signature interaction (DESIGN.md section 5).
   -------------------------------------------------------------------------- */
.strikes { margin-top: 8px; }

.strike {
  padding: 26px 0;
  border-top: 1px solid var(--carbon);
}
.strike:last-child { border-bottom: 1px solid var(--carbon); }

/* inline-block, not inline: the red rule is absolutely positioned against
   this box, and an inline box that wraps would only be covered on its first
   line fragment. */
.strike__lie {
  position: relative;
  display: inline-block;
  font-family: var(--display);
  font-size: clamp(1.5rem, 7.2vw, 2.6rem);
  line-height: 1.06;
  text-transform: uppercase;
  color: var(--struck);            /* darkened Grey Olive, same hue family */
}

/* The red line is a separate element so it can draw across, rather than a
   text-decoration which cannot be animated. */
.strike__rule {
  position: absolute;
  left: -2px;
  right: -2px;
  top: 52%;
  height: 4px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left center;
  pointer-events: none;
}
.strike.is-in .strike__rule {
  transform: scaleX(1);
  transition: transform 460ms var(--ease);
}

.strike__truth { margin-top: 14px; }
/* Each sentence is its own inline-block, so a pair sits on one line wherever
   the column is wide enough and the second drops whole when it is not. A
   sentence cannot break in the middle that way: it only wraps inside itself
   if it is wider than the column on its own. Flush left, unbalanced, which is
   what keeps the left edge hard against the rule above it. */
.strike__truth span {
  display: inline-block;
  margin-right: 0.3em;
  font-family: var(--display);
  font-size: clamp(1.25rem, 5.8vw, 2rem);
  line-height: 1.04;
  text-transform: uppercase;
  color: var(--parchment);
  opacity: 0;
  transform: translateY(10px);
}
/* The correction lands after the strike, not with it. */
.strike.is-in .strike__truth span {
  opacity: 1;
  transform: none;
  transition: opacity 380ms var(--ease), transform 380ms var(--ease);
  transition-delay: calc(420ms + var(--i, 0) * 90ms);
}

/* --------------------------------------------------------------------------
   8b. The platform. The introduction video.

   A poster and a play button until it is asked for, then the browser's own
   player in the same box. Square corners, no rounding, and no custom controls:
   seeking, volume and full screen are the platform's, which is also what makes
   them keyboard accessible without a line of script.
   -------------------------------------------------------------------------- */
.player {
  margin: 26px 0 0;
  border: 1px solid var(--carbon);
  background: var(--black);
  line-height: 0;
}
.player__go {
  position: relative;
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
}
.player__poster { display: block; width: 100%; height: auto; }
/* A veil under the mark, so the mark holds against a bright frame without
   dimming the whole still. */
.player__go::after {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(closest-side at 50% 50%, rgba(7, 7, 7, 0.55), rgba(7, 7, 7, 0) 70%);
}
.player__mark {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  z-index: 1;
  display: grid;
  place-items: center;
  width: 84px;
  height: 84px;
  background: var(--accent);
  color: var(--parchment);
}
.player__mark svg { width: 38px; height: 38px; }
.player__go:hover .player__mark { background: var(--accent-deep); }
.player__go:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.player video {
  display: block;
  width: 100%;
  height: auto;
  background: var(--black);
}

@media (min-width: 800px) {
  .player { margin-top: 30px; }
  .player__mark { width: 104px; height: 104px; }
  .player__mark svg { width: 46px; height: 46px; }
}

/* --------------------------------------------------------------------------
   9b. The trial band. A call to action, not a section of the argument, so it
   carries no claw mark and no rule under its heading.

   The artwork is placed, not decorated: on a phone it is a band of its own
   above the copy, which is the only arrangement where type can never be read
   over the animal. From 800px it takes the right half and is cropped from the
   right, so the tiger, who stands in the right of the frame, stays whole. The
   copy is held to 46% of the wrap, and the crop puts his leading edge at
   about 63% of the viewport, so the two cannot meet at any width.

   The veil is a horizontal gradient rather than a flat darkener, for the same
   reason the hero's is: a flat one would take the contrast out of the subject
   to buy legibility the left side already has.
   -------------------------------------------------------------------------- */
.cta-band {
  position: relative;
  overflow: hidden;
  background: var(--black);
}
.cta-band__art { position: relative; }
.cta-band__art img {
  display: block;
  width: 100%;
  height: auto;
}
/* Phone: the band sits above the copy, under a veil that keeps it in the
   page's register rather than glowing out of it. */
.cta-band__art::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(7,7,7,0.30) 0%, rgba(7,7,7,0.45) 55%, var(--black) 100%);
}
.cta-band__in { position: relative; z-index: 1; padding-top: 30px; }
.cta-band__copy { margin-top: 16px; }
.cta-band__act {
  margin-top: 28px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px 18px;
}
.cta-band__act .btn { width: 100%; }
.cta-band__note {
  margin: 0;
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: 15px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--olive);
}
.cta-band__note .tick {
  width: 16px;
  height: 16px;
  flex: none;
  color: var(--accent);
}

@media (min-width: 560px) {
  .cta-band__act .btn { width: auto; }
}

@media (min-width: 800px) {
  .cta-band__art {
    position: absolute;
    inset: 0 0 0 auto;
    width: 50%;
  }
  .cta-band__art picture,
  .cta-band__art img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: 100% 50%;
  }
  .cta-band__art::after {
    background: linear-gradient(90deg,
      var(--black) 0%,
      rgba(7,7,7,0.86) 18%,
      rgba(7,7,7,0.42) 44%,
      rgba(7,7,7,0.10) 74%,
      rgba(7,7,7,0.00) 100%);
  }
  .cta-band__in { padding-top: 0; }
  .cta-band__in > * { max-width: 46%; }
}

/* --------------------------------------------------------------------------
   9c. The questions. Native details and summary, one column.

   No script. The open and closed states, the keyboard, the focus ring and the
   screen reader announcement are all the element's own; this only draws the
   plus and turns it into a minus, from the open attribute, which cannot fall
   out of step with the thing it describes.
   -------------------------------------------------------------------------- */
.qa {
  margin-top: 26px;
  border-top: 1px solid var(--carbon);
}
.qa__item { border-bottom: 1px solid var(--carbon); }
.qa__q {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 18px;
  padding: 18px 0;
  cursor: pointer;
  list-style: none;
  font-family: var(--display);
  font-size: clamp(1.1rem, 4.6vw, 1.45rem);
  line-height: 1.15;
  text-transform: uppercase;
  color: var(--parchment);
}
/* Safari draws its own triangle without this, on top of the mark. */
.qa__q::-webkit-details-marker { display: none; }
.qa__q:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.qa__item:hover .qa__q { color: var(--accent); }
.qa__text { min-width: 0; }

/* The plus: two bars, the upright one rotated away when the item opens, which
   leaves the minus. Racing Red only while it is open, so a page of closed
   questions carries no red at all. */
.qa__mark {
  position: relative;
  flex: none;
  width: 18px;
  height: 18px;
}
.qa__mark::before,
.qa__mark::after {
  content: '';
  position: absolute;
  left: 0;
  top: 8px;
  width: 18px;
  height: 2px;
  background: var(--parchment);
  transition: transform var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
.qa__mark::after { transform: rotate(90deg); }
.qa__item[open] .qa__mark::before,
.qa__item[open] .qa__mark::after { background: var(--accent); }
.qa__item[open] .qa__mark::after { transform: rotate(0deg); }

.qa__a {
  margin: 0;
  padding: 0 0 20px;
  max-width: 68ch;
  font-size: 16px;
  line-height: 1.55;
  color: var(--olive);
}

@media (prefers-reduced-motion: reduce) {
  .qa__mark::before,
  .qa__mark::after { transition: none; }
}

@media (min-width: 800px) {
  .qa__q { padding: 22px 0; }
  .qa__a { padding-bottom: 24px; font-size: 17px; }
}

/* --------------------------------------------------------------------------
   10. Contents. The 18 chapters.
   -------------------------------------------------------------------------- */
.chapters { border-top: 1px solid var(--carbon); }

/* The cover sits in the space beside the heading, so it only shows from
   900px, where there is space to sit in. Below that the section is exactly as
   it was.

   Note this hides it but does not stop it downloading: measured at 390px the
   image still loads despite display: none and loading="lazy". Gating the
   fetch would mean the data-attribute and script treatment the hero video
   uses. See README. */
.contents__cover { display: none; }
.chapter {
  display: grid;
  grid-template-columns: 34px 1fr auto;
  align-items: baseline;
  gap: 12px;
  padding: 13px 4px;
  border-bottom: 1px solid var(--carbon);
  transition: background var(--t-fast) var(--ease);
}
.chapter:hover { background: var(--onyx); }
.sec--onyx .chapter:hover { background: var(--black); }
.chapter__n {
  font-family: var(--display);
  font-size: 19px;
  color: var(--accent-deep);
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
.chapter__t {
  font-family: var(--display);
  font-size: clamp(1rem, 4.4vw, 1.35rem);
  text-transform: uppercase;
  color: var(--parchment);
  line-height: 1.08;
  transition: color var(--t-fast) var(--ease);
}
.chapter:hover .chapter__t { color: var(--accent); }
.chapter__p {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.14em;
  color: var(--olive);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* --------------------------------------------------------------------------
   11. What you get. One anchor card, then a grid of cropped details.
   -------------------------------------------------------------------------- */

/* The intro sits directly on the anchor, with no gap between them. The 34px
   is on the shared .sec-head, so it is zeroed for this section only. */
#inside .sec-head { margin-bottom: 0; }

/* The anchor: the single large proof card. */
.anchor {
  border: 1px solid var(--carbon);
  background: var(--black);
  padding: 26px 20px 30px;
}
/* Plain eyebrow text, not a pill. A bordered chip reads as a control, and
   this is a label. */
.anchor__tag {
  display: block;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--olive);
  margin-bottom: 10px;
}
.anchor__t {
  font-family: var(--display);
  font-size: clamp(1.5rem, 6.6vw, 2.3rem);
  text-transform: uppercase;
  line-height: 0.96;
  color: var(--parchment);
  margin-bottom: 16px;
}
.anchor__list li {
  position: relative;
  padding: 9px 0 9px 24px;
  border-top: 1px solid var(--carbon);
  font-size: 16px;
  color: var(--olive);
  line-height: 1.4;
}
.anchor__list li::before {
  content: '';
  position: absolute;
  left: 2px;
  top: 17px;
  width: 9px;
  height: 3px;
  background: var(--accent);
  transform: skewX(-22deg);
}

.anchor__fig { margin-top: 24px; border: 1px solid var(--carbon); background: var(--black); }
.anchor__link { display: block; }
.anchor__link img { width: 100%; }
.anchor__cap {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding: 9px 12px;
  border-top: 1px solid var(--carbon);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--olive);
}
/* Signals that the card opens, with no script and no library behind it. */
.anchor__open {
  color: var(--accent);
  white-space: nowrap;
  transition: color var(--t-fast) var(--ease);
}
.anchor__fig:hover .anchor__open { color: var(--parchment); }

/* Part 2. The measurement grid. Heading is the two part construction at block
   scale, so it reads as a heading without competing with the section h2. */
.h2--block .h-top,
.h2--block .h-bot { font-size: clamp(1.5rem, 6.6vw, 2.3rem); }
.h2--block { margin-bottom: 14px; }

.measure {
  border: 1px solid var(--carbon);
  border-top: 0;
  background: var(--black);
  padding: 26px 20px 30px;
}
.measure__line {
  font-size: 16px;
  line-height: 1.45;
  color: var(--olive);
  max-width: 52ch;
}
/* The crop is wide, so it runs the full width of the block rather than sitting
   in a column beside the copy. */
.measure__fig {
  margin-top: 22px;
  border: 1px solid var(--carbon);
  background: var(--black);
}
.measure__fig img { width: 100%; }

/* Part 3. Text only. Six hairline panels: claw mark, Anton label, one line of
   Barlow Condensed. One column here, two from 560px, three from 900px. */
.spec {
  display: grid;
  gap: 1px;
  background: var(--carbon);
  border: 1px solid var(--carbon);
  border-top: 0;
}
.spec__cell {
  background: var(--onyx);
  padding: 20px 18px 22px;
}
/* The numeral the claw used to occupy, in the corner, as the member area
   does it. Racing Red, tabular, so a column of them lines up. */
.spec__n {
  font-family: var(--display);
  font-size: 0.95rem;
  line-height: 1;
  letter-spacing: 0.04em;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
  margin-bottom: 12px;
}
.spec__label {
  font-family: var(--display);
  font-size: 1.15rem;
  text-transform: uppercase;
  line-height: 1;
  color: var(--parchment);
}
.spec__line {
  margin-top: 7px;
  font-size: 15px;
  line-height: 1.4;
  color: var(--olive);
}

.route {
  margin-top: 22px;
  padding: 16px 18px;
  border: 1px solid var(--carbon);
  background: var(--onyx);
}
.sec--onyx .route { background: var(--black); }
.route p { color: var(--olive); font-size: 16px; }
.route a {
  display: inline-block;
  margin-top: 6px;
  font-family: var(--display);
  font-size: 1.05rem;
  text-transform: uppercase;
  color: var(--parchment);
  border-bottom: 2px solid var(--accent);
  padding-bottom: 2px;
  transition: color var(--t-fast) var(--ease);
}
.route a:hover { color: var(--accent); }

/* --------------------------------------------------------------------------
   13. Buy
   -------------------------------------------------------------------------- */
.buy { display: grid; gap: 1px; background: var(--carbon); border: 1px solid var(--carbon); }
.buy__col { background: var(--black); padding: 26px 20px 30px; }
.sec--onyx .buy__col { background: var(--onyx); }

.price {
  font-family: var(--display);
  font-size: clamp(2.4rem, 12vw, 4rem);
  line-height: 0.92;
  text-transform: uppercase;
  color: var(--parchment);
}
/* The left column reads price, button, reassurance, refund, tight together. */
.buy__cta {
  display: flex;
  width: 100%;
  margin-top: 18px;
}
.buy__format {
  margin-top: 12px;
  font-size: 16px;
  color: var(--olive);
}
.buy__includes li {
  position: relative;
  padding: 10px 0 10px 26px;
  border-top: 1px solid var(--carbon);
  font-size: 16px;
  color: var(--parchment);
  line-height: 1.4;
}
.buy__includes li::before {
  content: '';
  position: absolute;
  left: 3px;
  top: 18px;
  width: 10px;
  height: 3px;
  background: var(--accent);
  transform: skewX(-22deg);
}
.buy__smallprint {
  margin-top: 8px;
  font-size: 14px;
  color: var(--olive);
  line-height: 1.5;
  max-width: 52ch;
}

/* --------------------------------------------------------------------------
   14. Lean Blueprint
   DESIGN.md section 2: the Lean Blueprint blue colourway never appears on a
   Mass Protocol page. This teaser therefore runs in the Mass Protocol
   neutrals and is deliberately quieter than everything above it.
   -------------------------------------------------------------------------- */
.lean { border-top: 1px solid var(--carbon); }
.lean .h2 .h-bot { text-shadow: 2px 3px 0 var(--accent-deep); }
.lean__tag {
  font-family: var(--display);
  font-size: clamp(1rem, 4.4vw, 1.3rem);
  text-transform: uppercase;
  color: var(--parchment);
  margin-bottom: 12px;
}
.phases { margin-top: 26px; grid-template-columns: 1fr; }
.phase { padding: 20px 18px 22px; }
.phase__n {
  font-family: var(--display);
  font-size: 2.6rem;
  line-height: 0.86;
  color: var(--accent-deep);
  font-variant-numeric: tabular-nums;
}
.phase__name {
  margin-top: 6px;
  font-family: var(--display);
  font-size: 1.4rem;
  text-transform: uppercase;
  color: var(--parchment);
  line-height: 1;
}
.phase__weeks {
  margin-top: 5px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.19em;
  text-transform: uppercase;
  color: var(--olive);
}
.phase__points { margin-top: 14px; }
.phase__points li {
  padding: 7px 0 7px 20px;
  border-top: 1px solid var(--carbon);
  font-size: 15px;
  color: var(--olive);
  position: relative;
}
.phase__points li::before {
  content: '';
  position: absolute;
  left: 2px;
  top: 15px;
  width: 8px;
  height: 2px;
  background: var(--accent-deep);
  transform: skewX(-22deg);
}

/* --------------------------------------------------------------------------
   15. Forms. Newsletter and notify.
   -------------------------------------------------------------------------- */
.form { margin-top: 22px; max-width: 480px; }
.form__row { display: grid; gap: 10px; }
.form__field {
  width: 100%;
  min-height: 52px;
  padding: 0 15px;
  background: var(--black);
  border: 1px solid var(--carbon);
  color: var(--parchment);
  font-size: 17px;
  transition: border-color var(--t-fast) var(--ease);
}
.sec--onyx .form__field { background: var(--black); }
.form__field::placeholder { color: var(--olive); }
.form__field:hover { border-color: var(--olive); }
.form__field:focus { border-color: var(--accent); outline: none; }
.form__field[aria-invalid='true'] { border-color: var(--accent); }

.form__err,
.form__ok {
  margin-top: 10px;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0.06em;
  min-height: 1.2em;
}
.form__err { color: var(--accent); }
.form__ok { color: var(--parchment); }

.form__smallprint {
  margin-top: 12px;
  font-size: 13px;
  color: var(--olive);
}

/* Replaces the form on success. Parchment, per DESIGN.md section 2. */
.form__done {
  margin-top: 22px;
  font-family: var(--display);
  font-size: clamp(1.25rem, 5.4vw, 1.6rem);
  text-transform: uppercase;
  line-height: 1;
  color: var(--parchment);
}

/* --------------------------------------------------------------------------
   16. Footer
   -------------------------------------------------------------------------- */
.footer {
  border-top: 1px solid var(--carbon);
  background: var(--black);
  padding-block: 44px calc(40px + var(--buybar-h));
}
.footer__top { display: grid; gap: 30px; }
.footer__brand { display: flex; align-items: center; gap: 10px; }
.footer__mark { width: 34px; height: 34px; object-fit: contain; }
.footer__name {
  font-family: var(--display);
  font-size: 1.2rem;
  text-transform: uppercase;
  color: var(--parchment);
  line-height: 1;
}
.footer__name b { color: var(--accent); font-weight: 400; }

.footer__colh {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--olive);
  margin-bottom: 12px;
}
.footer__list li { padding: 5px 0; }
.footer__list a {
  font-size: 16px;
  color: var(--parchment);
  transition: color var(--t-fast) var(--ease);
}
.footer__list a:hover { color: var(--accent); }

.legal {
  margin-top: 34px;
  padding-top: 26px;
  border-top: 1px solid var(--carbon);
  display: grid;
  gap: 20px;
}
.legal h3 {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--olive);
  margin-bottom: 8px;
}
.legal p,
.legal li {
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--olive);
  max-width: 68ch;
}
.footer__copy {
  margin-top: 26px;
  padding-top: 18px;
  border-top: 1px solid var(--carbon);
  font-size: 13px;
  color: var(--olive);
  letter-spacing: 0.06em;
}

/* --------------------------------------------------------------------------
   17. Sticky buy bar. Keeps the buy action one tap away on mobile without
   hijacking the scroll.
   -------------------------------------------------------------------------- */
.buybar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: var(--z-buybar);
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px var(--gut) calc(10px + env(safe-area-inset-bottom, 0px));
  /* Solid, for the same reason as the header. */
  background: #070707;
  border-top: 0;
  transform: translateY(110%);
  transition: transform var(--t-mid) var(--ease);
}
.buybar.is-shown { transform: translateY(0); }
.buybar__l { flex: 1; min-width: 0; }
.buybar__t {
  font-family: var(--display);
  font-size: 1.05rem;
  text-transform: uppercase;
  color: var(--parchment);
  line-height: 1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.buybar__s {
  margin-top: 3px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--olive);
}
.buybar .btn { min-height: 44px; padding: 0 20px; font-size: 17px; }

/* --------------------------------------------------------------------------
   18. Motion
   DESIGN.md section 6. Permitted: scroll triggered reveals, the strike
   animation, hover transitions, staggered entrances. Everything here is
   opacity and transform only. There is no parallax, no scroll jacking, no
   scroll sequence, no cursor follower and no preloader.
   -------------------------------------------------------------------------- */
.reveal {
  opacity: 0;
  transform: translateY(16px);
  will-change: opacity, transform;
}
.reveal.is-in {
  opacity: 1;
  transform: none;
  transition: opacity var(--t-reveal) var(--ease),
              transform var(--t-reveal) var(--ease);
  transition-delay: calc(var(--i, 0) * 70ms);
}

/* Reduced motion: content still appears, it simply does not travel. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    transition-delay: 0ms !important;
    scroll-behavior: auto !important;
  }

  .reveal { opacity: 1; transform: none; }
  .strike__rule { transform: scaleX(1); }
  .strike__truth span { opacity: 1; transform: none; }

  /* The buy bar is NOT forced open here. It used to be, which pinned it over
     the hero from the top of the page for anyone with reduced motion set: a
     second buy button eighty pixels under the first, and the observer that
     decides when the bar is useful bypassed entirely.

     Its transform is its visibility, not an animation. The animation is the
     transition, and the blanket rule above has already reduced that to
     nothing, so the bar now appears instantly at the point it should rather
     than being visible from the start. */
}

/* --------------------------------------------------------------------------
   19. Breakpoints
   Authored at 390px first. Everything below is an addition, never a repair.
   -------------------------------------------------------------------------- */
@media (min-width: 560px) {
  :root { --gut: 28px; }
  .stats { grid-template-columns: repeat(4, 1fr); }
  .spec { grid-template-columns: repeat(2, 1fr); }   /* tablet */
  .form__row { grid-template-columns: 1fr auto; }
  .footer__top { grid-template-columns: 1.4fr 1fr 1fr; }
  .legal { grid-template-columns: repeat(2, 1fr); gap: 26px 34px; }
}

@media (min-width: 800px) {
  :root { --gut: 40px; }
  .sec { padding-block: 96px calc(96px + var(--buybar-h)); }
  #join { padding-bottom: 96px; }
  body { font-size: 18px; }

  .nav__links { display: flex; }
  .nav__in { min-height: 68px; }
  html { scroll-padding-top: 86px; }

  /* The hero carries three more lines of type than it did, so it takes less
     air above them. 54px is what keeps the paragraph and the button inside
     1280x800, which is the tightest desktop the design is held to, with the
     sticky buy bar taking the bottom 65px. */
  .hero { padding-block: 54px 90px; }
  .hero__positioning { font-size: 19px; }

  /* Contents runs two up. The list is long and the density is the point. */
  /* Column major. The explicit row track count plus grid-auto-flow: column
     fills the left column top to bottom before starting the right, instead of
     the default row major flow which ran the numbering across the pair.
     --rows comes from build.js, so the split follows the chapter count. */
  .chapters {
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-rows: repeat(var(--rows, 9), auto);
    grid-auto-flow: column;
    column-gap: 40px;
  }

  /* Anchor. The card column is sized by the card, not by a 50/50 split, and
     the card is capped by height so the two columns finish close together.
     The copy then stretches to meet it, which is what removes the dead space:
     previously the text ran 259px inside an 803px row. */
  .anchor {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 44px;
    padding: 42px 36px 46px;
  }
  .anchor__body { display: flex; flex-direction: column; }
  /* Flex children stretch by default, which pulled the chip's border across
     the whole column. It is a label, so it sizes to its text. */
  .anchor__tag { align-self: flex-start; }
  .anchor__list { flex: 1; display: flex; flex-direction: column; }
  .anchor__list li { flex: 1; display: flex; align-items: center; padding-block: 0; }
  .anchor__list li::before { top: 50%; margin-top: -1.5px; }
  .anchor__fig { margin-top: 0; align-self: start; }
  .anchor__link img { max-height: 430px; width: auto; }

  .measure { padding: 42px 36px 46px; }

  .spec__cell { padding: 24px 22px 26px; }
  .spec__label { font-size: 1.3rem; }
  .spec__line { font-size: 15px; }


  .buy { grid-template-columns: 1fr 1fr; }
  .buy__col { padding: 42px 36px 46px; }

  .phases { grid-template-columns: repeat(3, 1fr); }

  .strike { padding: 40px 0; }
}

/* The signature pair reads across instead of down: the struck lie on the left,
   the correction level with it on the right, across the full content width.
   Columns are uneven because the content is: the lies are short, the
   corrections run to two lines.

   align-items: baseline, not start. The two sit at different type sizes, so
   sharing a baseline is what actually reads as aligned. The initial
   translateY on the correction is a transform, so it does not disturb the
   baseline it is measured from.

   Nothing here touches the strike rule or the correction's entrance: the
   animation is driven by .is-in on .strike, which is unaffected by the
   container becoming a grid. */
@media (min-width: 900px) {
  .spec { grid-template-columns: repeat(3, 1fr); }   /* desktop */

  .strike {
    display: grid;
    grid-template-columns: 1fr 1.2fr;
    gap: 44px;
    align-items: baseline;
  }
  .strike__truth { margin-top: 0; }

  /* Contents: the cover fills the space to the right of the heading. Sized to
     land near the height of the heading block beside it, so it reads as a
     product shot rather than an image the section is built around. The bottom
     margin moves to the wrapper so the gap before the chapter list is the same
     34px whichever of the two columns is taller. */
  .contents__head {
    display: grid;
    grid-template-columns: 1fr auto;
    gap: 48px;
    align-items: start;
    margin-bottom: 34px;
  }
  .contents__head .sec-head { margin-bottom: 0; }

  .contents__cover {
    display: block;
    justify-self: end;
    /* Its real aspect is 692:1000, so width alone drives it and the cover is
       never stretched. */
    width: clamp(185px, 16vw, 240px);
    border: 1px solid var(--carbon);
  }
  .contents__cover img { width: 100%; }
}

@media (min-width: 1100px) {
  .hero__in { display: grid; grid-template-columns: 1.35fr 1fr; gap: 50px; align-items: end; }
  .hero__lead { grid-column: 1; }
  .hero__side { grid-column: 2; }
  .stats { margin-top: 0; grid-template-columns: repeat(2, 1fr); }
}

/* From 1600 up the plate has stopped growing: it is capped at 1472, the video's
   own width plus the 15% it takes without falling apart. A 1472 wide frame is
   828 tall at 16:9, so a hero that tall shows the whole thing and crops
   nothing at all, top or bottom. Below 1600 the hero keeps the height it has,
   because the fold at 1280x800 and 1440x900 is what sets it and the buttons
   have only 142px of room to spare there.

   The content is centred in the taller section rather than left at the top,
   so the extra height reads as air around the lockup instead of a gap under
   it. The plate is positioned absolutely, so it is not a flex item and the
   centring cannot move it. */
@media (min-width: 1600px) {
  .hero {
    min-height: 828px;
    display: flex;
    align-items: center;
  }
  .hero__in { width: 100%; }
}

/* --------------------------------------------------------------------------
   20. Mobile pass
   Everything here is scoped to max-width so no desktop rule is touched. Two
   things only: a 16px floor on body copy, and 44px touch targets.

   Not raised, because they are labels and micro type rather than body copy:
   .eyebrow (DESIGN.md section 3 fixes it at 13px), .tele, .stat__l,
   .chapter__p, .anchor__tag, .anchor__cap, .phase__weeks, .footer__colh,
   .legal h3, .footer__copy, and .form__smallprint (specified at 13px).
   -------------------------------------------------------------------------- */
@media (max-width: 767px) {
  /* Portrait crop. Wherever the plate is taller than 3:4 the full image height
     is already shown and this is inert, which is the case at every phone width
     measured. It takes over on short viewports, a landscape phone or heavy
     in-app browser chrome, where it keeps the head in the upper third instead
     of centring on the torso. */
  .hero__plate img { object-position: 50% 22%; }
}

@media (max-width: 799px) {
  .spec__line,
  .phase__points li,
  .buy__smallprint,
  .legal p,
  .legal li { font-size: 16px; }

  /* The route link keeps its underline hugging the text; the hit area is
     grown behind it instead, so the design does not change. */
  .route a { position: relative; }
  .route a::after {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    top: 50%;
    height: 44px;
    transform: translateY(-50%);
  }

  /* Footer links cannot use the same trick: at a 29px pitch, 44px hit areas
     would overlap each other. They are spaced out instead. The 5px li padding
     leaves 10px between adjacent targets. */
  .footer__list a {
    display: flex;
    align-items: center;
    min-height: 44px;
  }

  /* The nav sits outside every <section>, so the section-by-section audit
     never reached it and these were left at 38px and 26px. Both are tappable
     links and both were under the minimum. */
  .nav__cta { min-height: 44px; }
  .nav__brand { min-height: 44px; }
}

/* --------------------------------------------------------------------------
   21. Legal documents
   Long form prose, which no marketing section needed. Parchment headings,
   Grey Olive body, Carbon hairlines on near black, square corners. No new
   colour and no third typeface: headings are Anton, everything else Barlow
   Condensed, exactly as DESIGN.md section 3 requires.
   -------------------------------------------------------------------------- */
.doc { max-width: 70ch; }

.doc__meta {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.19em;
  text-transform: uppercase;
  color: var(--olive);
  padding-bottom: 18px;
  border-bottom: 1px solid var(--carbon);
}

.doc__sec { padding-top: 34px; }

.doc__h2 {
  font-family: var(--display);
  font-size: clamp(1.35rem, 5.6vw, 1.7rem);
  text-transform: uppercase;
  line-height: 1;
  color: var(--parchment);
  margin-bottom: 14px;
}

.doc__h3 {
  font-family: var(--body);
  font-size: 17px;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--parchment);
  margin: 22px 0 8px;
}

.doc p {
  font-size: 17px;
  line-height: 1.62;
  color: var(--olive);
  margin-bottom: 14px;
  text-wrap: pretty;
}

/* The clauses that decide whether someone gets their money back. A hairline
   panel, not a colour, because Racing Red is reserved for buy actions. */
.doc__note {
  padding: 18px 20px;
  margin: 6px 0 20px;
  border: 1px solid var(--carbon);
  border-left: 3px solid var(--accent);
  background: var(--onyx);
  color: var(--parchment);
}

.doc__list { margin: 4px 0 18px; }
.doc__list li {
  position: relative;
  padding: 9px 0 9px 24px;
  border-top: 1px solid var(--carbon);
  font-size: 17px;
  line-height: 1.45;
  color: var(--olive);
}
.doc__list li::before {
  content: '';
  position: absolute;
  left: 2px;
  top: 17px;
  width: 9px;
  height: 3px;
  background: var(--accent);
  transform: skewX(-22deg);
}

.doc__company {
  margin-top: 4px;
  border-top: 1px solid var(--carbon);
}
.doc__company li {
  padding: 9px 0;
  border-bottom: 1px solid var(--carbon);
  font-size: 17px;
  color: var(--parchment);
}

@media (min-width: 800px) {
  .doc__sec { padding-top: 44px; }
  .doc__meta { padding-bottom: 22px; }
}

/* --------------------------------------------------------------------------
   18. The year. The map, and the six panels named.

   The artwork is the same file the member area renders on a member's
   dashboard, so what a buyer is shown before joining is what they get after.
   -------------------------------------------------------------------------- */
.map {
  margin-top: 26px;
  border: 1px solid var(--carbon);
  background: var(--black);
  overflow: hidden;
}
.map img { display: block; width: 100%; height: auto; }
.map__hint { display: none; }

/* Under 768px the map becomes a horizontally scrollable strip rather than a
   1600px wide image squeezed to 350px, where six panels of detail collapse
   into a smear. Each of the six panels gets about 220px, so the artwork is
   1320px wide and keeps its own proportions.

   Native scrolling only. No snap points, no drag handler, no momentum
   library: DESIGN.md section 6 rules out anything that takes the scroll away
   from the reader, and that applies sideways as well as down. */
@media (max-width: 767px) {
  .map {
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
  }
  .map img {
    width: 1320px;
    max-width: none;
    height: auto;
  }
  .map__hint {
    display: block;
    margin-top: 8px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.24em;
    text-transform: uppercase;
    color: var(--olive);
  }
}

.seasons {
  margin-top: 26px;
  border: 1px solid var(--carbon);
  border-bottom: 0;
  list-style: none;
}
.season {
  padding: 20px 18px 22px;
  border-bottom: 1px solid var(--carbon);
  background: var(--black);
}
.season:nth-child(even) { background: var(--onyx); }

.season__range {
  margin-top: 7px;
  font-family: var(--display);
  font-size: 0.95rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--accent-deep);        /* Blood Red carries numerals */
  font-variant-numeric: tabular-nums;
}
/* The name is Parchment for every season. Nothing here says one of them is the
   one you can train today, because the card describes the year rather than the
   build. */
.season__name {
  margin-top: 4px;
  font-family: var(--display);
  font-size: clamp(1.35rem, 6vw, 1.9rem);
  line-height: 1;
  text-transform: uppercase;
  color: var(--parchment);
}
/* The ordinal carries the season's own identity colour, the four from
   DESIGN.md section 2, which is the one place on this page they appear: the
   same colour a member meets when the map and the member area hand them that
   season. It is a label, not chrome, and it is the smallest type on the card,
   so four hues here read as identity rather than as noise. */
.season__ord {
  display: block;
  font-family: var(--body);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--olive);
}
.season[data-season='mass-protocol'] .season__ord { color: #DD0A0A; }
.season[data-season='lean-blueprint'] .season__ord { color: #2B6EE3; }
.season[data-season='hybrid-method'] .season__ord { color: #25A05A; }
.season[data-season='fighting-fit'] .season__ord { color: #E07A1B; }
.season__line {
  margin-top: 9px;
  font-size: 15px;
  line-height: 1.45;
  color: var(--olive);
  max-width: 58ch;
}
.seasons__closer {
  margin-top: 20px;
  font-size: 16px;
  line-height: 1.45;
  color: var(--parchment);
  max-width: 52ch;
}

/* One order at every width: the ordinal, the name, the levels it covers, then
   what the season is. The timetable layout that put the range in a left hand
   column is gone with it, because the ordinal now leads the card. */
@media (min-width: 700px) {
  .season { padding: 26px 24px 28px; }
  .season__line { margin-top: 11px; }
}

/* --------------------------------------------------------------------------
   19a. The screens deck. One screen at a time, in the pattern the member area
   already uses for Today's Protocol: a counter, two arrows, and a track that
   moves one slide at a time.

   It moves by scrolling its own track, not by transforming it, so a swipe is
   the browser's native scroll with snapping rather than a gesture this file
   has to reimplement. That is also why there is no scroll jacking here: the
   page's own scrolling is never touched, only this element's.

   Nothing plays on its own, the arrows are the desktop control, and the track
   itself takes focus and answers the arrow keys.
   -------------------------------------------------------------------------- */
.deck { margin-top: 26px; }
.deck__head {
  display: none;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 14px;
}
.deck__count {
  margin: 0;
  font-family: var(--display);
  font-size: 15px;
  letter-spacing: 0.14em;
  color: var(--olive);
  font-variant-numeric: tabular-nums;
}
.deck__count [data-deck-now] { color: var(--parchment); }
.deck__arrows { display: flex; gap: 10px; }
.deck__arrow {
  width: 44px;
  height: 44px;
  border: 1px solid var(--carbon);
  background: var(--onyx);
  color: var(--parchment);
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
}
.deck__arrow:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.deck__arrow:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.deck__arrow:disabled { opacity: 0.35; cursor: default; }

.deck__track {
  display: flex;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  border: 1px solid var(--carbon);
  /* The scrollbar is the platform's own, so it is hidden rather than styled.
     The track still scrolls by touch, by wheel and by key. */
  scrollbar-width: none;
}
.deck__track::-webkit-scrollbar { display: none; }
.deck__track:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* --panel is the slide's own background, and the crop fades into it. Declared
   per slide so the fade cannot end on the wrong colour in the alternating
   pattern. */
.deck__slide {
  flex: 0 0 100%;
  min-width: 0;
  scroll-snap-align: start;
  scroll-snap-stop: always;
  /* No left padding: the copy starts on the same grid line as the section
     heading above it rather than inset from it. */
  padding: 24px 20px 26px 0;
  --panel: var(--black);
  background: var(--panel);
}
.deck__slide:nth-child(even) { --panel: var(--onyx); }
.deck__n {
  font-family: var(--display);
  font-size: 13px;
  letter-spacing: 0.06em;
  color: var(--accent-deep);
  font-variant-numeric: tabular-nums;
}
.deck__copy { align-self: start; }
.deck__copy .anchor__tag { margin-top: 6px; font-size: 13px; }
.deck__copy .h2--block { margin-top: 8px; margin-bottom: 0; }
/* The slide headline is set here rather than inherited, because the block
   heading's clamp was drawn for a section head and reads as a caption at the
   size this column gives it. */
.deck__copy .h2--block .h-top,
.deck__copy .h2--block .h-bot { font-size: 28px; }
.deck__line {
  margin-top: 12px;
  font-size: 19px;
  line-height: 1.45;
  color: var(--olive);
  max-width: 46ch;
}

/* The screen is a crop, not a whole phone page: it is top aligned and cut off
   at the bottom, with a short fade into the slide so the cut reads as an edge
   rather than as a mistake. That is what keeps a slide the height of its copy
   instead of the height of a screenshot. */
.deck .phone {
  margin-top: 20px;
  padding-bottom: 0;
}
.deck .phone__screen {
  position: relative;
  height: 300px;
  overflow: hidden;
}
.deck .phone__screen img { height: auto; }
.deck .phone__screen::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 70px;
  background: linear-gradient(180deg, rgba(7, 7, 7, 0) 0%, var(--panel) 100%);
}

@media (prefers-reduced-motion: reduce) {
  .deck__track { scroll-behavior: auto; }
}

/* From 800px the counter and the arrows appear, and each slide becomes the
   copy beside the screen rather than above it. */
@media (min-width: 800px) {
  .deck__head { display: flex; }
  /* 560px, so the slide is the height of its copy with room to breathe rather
     than the height of a phone page. The screen fills that height and is
     cropped into it. */
  .deck__slide {
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: start;
    column-gap: 44px;
    height: 560px;
    padding: 40px 38px 40px 0;
  }
  .deck__copy .h2--block .h-top,
  .deck__copy .h2--block .h-bot { font-size: 42px; }
  .deck .phone {
    margin-top: 0;
    align-self: start;
  }
  /* 560 slide, less 40 of padding top and bottom, less the frame's own 12 at
     the top: the screen is the rest, and the capture is cropped into it. A
     percentage here would resolve against a grid area that is sized to its
     content, which is the screenshot, and crop nothing. */
  .deck .phone__screen { height: 468px; }
}

/* --------------------------------------------------------------------------
   19. Every screen has a job. A feature beside a phone frame.

   The frame is CSS, so the screenshot stays a plain 390x844 export that
   tools/screenshot-app.js can regenerate rather than something retouched by
   hand. Square corners: DESIGN.md section 4 allows none anywhere.
   -------------------------------------------------------------------------- */
.feature {
  border: 1px solid var(--carbon);
  border-bottom: 0;
  background: var(--black);
  padding: 26px 20px 30px;
}
.feature:first-of-type { margin-top: 26px; }
/* The text column. Structural: .feature is a two column grid and this div
   is one of its two children, so without it the tag, title and line would each
   become a column of their own.

   min-width: 0 because a grid child defaults to auto, which refuses to shrink
   below its longest unbreakable word and pushes the phone frame out of the
   row. */
.feature__body {
  min-width: 0;
}
.feature__line {
  font-size: 16px;
  line-height: 1.5;
  color: var(--olive);
  max-width: 54ch;
}
/* One frame for both captures: a 12px Carbon bezel, square corners, no
   shadow. Identical on each card so the two read as the same device rather
   than as two different treatments. */
.phone {
  margin-top: 24px;
  /* The captures are 390 wide. Never scale one up past its own pixels: an
     upscaled screenshot of type looks like a photograph of a screen. */
  max-width: 342px;
  padding: 12px;
  background: var(--carbon);
}
.phone__screen {
  background: var(--black);
  overflow: hidden;
}
.phone__screen img { display: block; width: 100%; height: auto; }
/* The figures on these captures are seeded demo data, so they are labelled.
   Grey Olive, outside the frame, so it reads as a caption rather than as part
   of the screen it sits under. */
.phone__cap {
  margin-top: 10px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--olive);
}

@media (min-width: 900px) {
  .feature {
    display: grid;
    grid-template-columns: 1fr 320px;
    column-gap: 40px;
    /* Centred, not top aligned. The phone is roughly 690px tall and the copy
       beside it is three lines, so top alignment leaves a void the width of
       the column. */
    align-items: center;
  }
  .phone { margin-top: 0; }
}

/* --------------------------------------------------------------------------
   20. Join. The two states of the price column, and the retry line.
   -------------------------------------------------------------------------- */

/* Doors shut. The launch date replaces the price as the headline, and the
   price drops to the supporting line, so nothing looks clickable that is not. */
/* One display heading per section, and the section heading is already the
   skewed red one. So the launch line is Anton in Parchment, upright, with no
   red: it is a statement of fact, not a second headline competing with the
   first. Balanced wrapping keeps it to one line on desktop and two on a
   phone rather than breaking after a single word. */
.price--soon {
  font-family: var(--display);
  font-size: clamp(1.45rem, 5.6vw, 2rem);
  line-height: 1.04;
  text-transform: uppercase;
  color: var(--parchment);
  text-wrap: balance;
}

/* The includes list takes a Grey Olive eyebrow rather than a second skewed
   heading inside the card. */
.buy__includes-label {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--olive);
  margin-bottom: 14px;
}

.form--join { margin-top: 18px; }

.buy__retry {
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid var(--carbon);
  font-size: 14px;
  line-height: 1.45;
  color: var(--olive);
}


/* The Companies Act trading disclosure on /terms and /contact. */
.doc__trader {
  padding: 14px 16px;
  border: 1px solid var(--carbon);
  background: var(--onyx);
  font-size: 15px;
  line-height: 1.5;
  color: var(--parchment);
}

/* --------------------------------------------------------------------------
   21. The newsletter slide-in.

   A card bottom right on desktop, a bottom sheet on a phone. Deliberately not
   a modal: no scroll lock, no focus trap, no full page dim. DESIGN.md section
   6 is blunt that anything getting between a reader and the page costs sales,
   and most of this traffic arrives inside an in-app browser.

   It ships with the `hidden` attribute and the script removes it at the
   trigger point, so with JavaScript off it never appears rather than sitting
   open with no way to shut it.
   -------------------------------------------------------------------------- */
.slidein {
  position: fixed;
  z-index: 60;
  background: var(--carbon);
  /* The one red on the panel. A 3px top border, not a fill: the red fill is
     reserved for buy actions. */
  border-top: 3px solid var(--accent);
  color: var(--parchment);
  padding: 20px 18px 18px;
  box-shadow: 0 -8px 28px rgba(0, 0, 0, 0.55);
}
.slidein[hidden] { display: none; }

/* Phone: a bottom sheet, full width, never taller than 40% of the viewport.
   The cap is the point. A sheet that grows past its content would cover the
   page a reader is in the middle of. */
@media (max-width: 719px) {
  .slidein {
    left: 0;
    right: 0;
    /* Above the sticky buy bar, never under it. The script publishes the
       bar's height as --mt-bar and sets it to 0 when the bar is hidden. */
    bottom: var(--mt-bar, 0px);
    max-height: 40vh;
    overflow-y: auto;
    /* Clear of the sticky buy bar, and of the home indicator on an iPhone. */
    padding-bottom: calc(18px + env(safe-area-inset-bottom, 0px));
    transform: translateY(100%);
  }
}

/* Desktop: a 360px card in the bottom right corner. */
@media (min-width: 720px) {
  .slidein {
    right: 20px;
    bottom: calc(20px + var(--mt-bar, 0px));
    width: 360px;
    max-width: calc(100vw - 40px);
    border: 1px solid var(--carbon);
    border-top: 3px solid var(--accent);
    transform: translateY(calc(100% + 28px));
  }
}

/* 200ms, under the 250ms ceiling. Transform and opacity only, so it composites
   rather than reflowing the page under it. */
.slidein {
  opacity: 0;
  transition: transform 200ms ease, opacity 200ms ease;
  will-change: transform;
}
.slidein.is-open {
  transform: translateY(0);
  opacity: 1;
}

.slidein__x {
  position: absolute;
  top: 8px;
  right: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  /* 44px target, per the mobile pass. */
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--olive);
  cursor: pointer;
}
.slidein__x:hover,
.slidein__x:focus-visible { color: var(--parchment); }

.slidein__eyebrow {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--accent-deep);
  padding-right: 40px;
}
.slidein__h {
  margin-top: 8px;
  font-family: var(--display);
  font-size: clamp(1.3rem, 5vw, 1.6rem);
  line-height: 0.98;
  text-transform: uppercase;
  color: var(--parchment);
  padding-right: 40px;
}
.slidein__line {
  margin-top: 8px;
  font-size: 14px;
  line-height: 1.45;
  color: var(--olive);
}
.slidein__form {
  display: grid;
  gap: 9px;
  margin-top: 14px;
}
.slidein__form .form__field { width: 100%; }
.slidein__form .form__err:empty { display: none; }

/* Parchment on Carbon with a Racing Red hairline. Not a red fill: DESIGN.md
   section 2 reserves that for buy actions, and this is not one. */
.btn--outline {
  background: var(--carbon);
  border-color: var(--accent);
  color: var(--parchment);
}
.btn--outline:hover { background: var(--black); }
.btn--outline:active { transform: translateY(1px); }

@media (prefers-reduced-motion: reduce) {
  .slidein { transition: none; }
}

/* The line that stands where a form would be while its list is unconfigured.
   Stated plainly, in Parchment: the visitor is told when it opens rather than
   given a field that accepts an address and discards it. */
.news__launch {
  margin-top: 20px;
  font-family: var(--display);
  font-size: clamp(1.3rem, 5vw, 1.75rem);
  line-height: 1.05;
  text-transform: uppercase;
  color: var(--parchment);
}

/* The hero's second slot while the waitlist is gated. There is no second
   action to offer, only a date, so it is stated as text rather than dressed as
   a button that goes nowhere useful. */
.hero__when {
  font-family: var(--display);
  font-size: clamp(1rem, 3.6vw, 1.2rem);
  line-height: 1.1;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: var(--olive);
  padding: 6px 0;
}

/* ==========================================================================
   The mobile pass.

   One block, at the end, so it wins over the rules above it without raising
   their specificity, and so the whole pass reads in one place. Everything
   that changes a phone is inside max-width: 799px; the type floor is the one
   rule that applies at every width, because nothing anywhere goes under 13px.
   tools/verify-mobile.js holds all of it in place.
   ========================================================================== */

/* The type floor. Labels and eyebrows are 13px at the smallest. */
.stat__l,
.season__ord,
.map__hint,
.buy__includes-label,
.buybar__s,
.footer__colh,
.legal h3,
.slidein__eyebrow { font-size: 13px; }

/* A button label never wraps. */
.btn { white-space: nowrap; }

/* The slide-in carries the newsletter heading's two part treatment at the
   panel's own size, not the section's display size. */
.slidein .h2 { margin-bottom: 0; }
.slidein .h2 .h-top,
.slidein .h2 .h-bot { font-size: inherit; line-height: inherit; }

@media (max-width: 799px) {
  /* Section rhythm. Every section carried the bottom bar's height in its own
     bottom padding, which stacked about 130px of dead space under each one.
     The clearance belongs to the end of the page only, so sections take the
     same 36px top and bottom and the footer clears whatever is on the
     bottom edge. */
  .sec { padding-block: 36px; }
  #join,
  #newsletter { padding-bottom: 36px; }
  /* The hero ends on its stats, and 35px under them meets the platform's
     36px to make the same 72px as every other join between sections. */
  .hero { padding-bottom: 35px; }
  .footer { padding-bottom: calc(40px + var(--mt-bottom, var(--buybar-h))); }

  /* Body copy: 17px and a 1.5 line height on the marketing pages. */
  .season__line,
  .seasons__closer { font-size: 17px; line-height: 1.5; }
  .deck__line,
  .lede,
  .legal p,
  .doc p,
  .doc li { line-height: 1.5; }

  /* FAQ questions sit 8px apart, so a thumb meant for one does not land on
     the next. */
  .qa__item + .qa__item { margin-top: 8px; }

  /* The slide-in on a phone: the bottom bar's place, one compact block no
     taller than 120px. Eyebrow and heading above, the address and SUBSCRIBE
     on one line, no body. */
  .slidein {
    left: 0;
    right: 0;
    width: auto;
    max-width: none;
    bottom: 0;
    max-height: 120px;
    overflow: hidden;
    border: 0;
    border-top: 3px solid var(--accent);
    padding: 10px var(--gut) calc(10px + env(safe-area-inset-bottom, 0px));
    transform: translateY(100%);
  }
  .slidein__x { top: 2px; right: 4px; }
  .slidein__eyebrow { padding-right: 48px; line-height: 1.2; }
  .slidein__h {
    margin-top: 3px;
    padding-right: 48px;
    font-size: clamp(15px, 4.6vw, 20px);
    line-height: 1.15;
    white-space: nowrap;
  }
  .slidein .h2 .h-top { display: inline; }
  .slidein .h2 .h-bot { display: inline-block; margin-left: 0.3em; text-shadow: none; }
  .slidein__line { display: none; }
  .slidein__form {
    grid-template-columns: 1fr auto;
    gap: 8px;
    margin-top: 8px;
  }
  .slidein__form .form__field { min-height: 44px; font-size: 16px; }
  .slidein__form .btn { min-height: 44px; padding: 0 14px; font-size: 16px; }
  body.mt-slidein-open .buybar { transform: translateY(110%); }
  /* A 120px sheet and a header cannot both fit inside 22% of a 568px or
     740px screen. The sheet only ever shows past the FAQ, at the end of the
     page, so the header steps out of the way while it is open and returns
     the moment it is dismissed or tucked away. */
  .nav { transition: transform var(--t-mid) var(--ease); }
  body.mt-slidein-open .nav { transform: translateY(-100%); }
}

@media (max-width: 599px) {
  /* The header is one row: the logo on one line and LOGIN. JOIN FREE lives
     in the bottom bar on a phone. */
  .nav__cta--join { display: none; }
  .nav__name { white-space: nowrap; }
  /* 52px holds LOGIN at 44 and keeps the header and the bottom bar inside
     22% of a 320 by 568 screen together. */
  .nav__in { min-height: 52px; }

  /* Primary buttons are the full width of their column, 52px tall, with a
     label of at least 16px on one line. */
  .btn--primary {
    width: 100%;
    min-height: 52px;
    padding-inline: 16px;
    font-size: clamp(16px, 5.2vw, 20px);
  }
  /* The bar's button sits beside the bar's text, so its column is its own. */
  .buybar { padding-block: 6px calc(6px + env(safe-area-inset-bottom, 0px)); }
  .buybar .btn--primary { width: auto; min-height: 52px; font-size: 17px; padding-inline: 18px; }
}

/* A phone turned on its side. The platform player followed the page width to
   764 by 390 at 844 by 390, taller than the space under the 68px header, so
   its top was always covered. Here it takes the width the height allows, at
   the poster's own 1240 by 632, and sits centred. */
@media (orientation: landscape) and (max-height: 500px) {
  .player {
    width: min(100%, calc((100vh - 92px) * 1240 / 632));
    margin-inline: auto;
  }
}

/* ==========================================================================
   Homepage and login changes.
   ========================================================================== */

/* Each part of a two part heading is unbreakable: under 800 a heading may
   break between its parts and nowhere else. */
.h2 .h-top,
.h2 .h-bot { white-space: nowrap; }

/* The trial band's heading is exactly two lines at every width:
   START WITH 7 DAYS in Parchment, ON US FOR FREE. skewed in Racing Red. */
.cta-band .h2 .h-top,
.cta-band .h2 .h-bot { display: block; }

/* The artwork under START THE PRIMER: the width of the pricing column,
   square corners. */
.buy__art {
  display: block;
  width: 100%;
  height: auto;
  margin-top: 22px;
  border-radius: 0;
}

/* FAQ answers run the full width of their item: from the question's left
   edge to the plus sign's right edge. */
.qa__a { max-width: none; }

/* The newsletter, centred as one block: claw, eyebrow, heading, body and a
   form no wider than 560px. */
#newsletter .sec-head {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}
#newsletter .h2 .h-bot { transform-origin: center bottom; }
#newsletter .form {
  max-width: 560px;
  margin-inline: auto;
  text-align: center;
}

@media (min-width: 800px) {
  /* Every two part section heading on one line: Parchment, then the skewed
     Racing Red part inline. The newsletter's ONE HARD TRUTH. NO SUGAR
     COATING. is the longest, and holds one line at 1024 at 66.5px, so the
     size is the content column times 0.0705, never above the 76px it was. */
  .sec-head .h2 .h-top,
  .sec-head .h2 .h-bot {
    display: inline;
    font-size: min(76px, calc((min(100vw, 1240px) - 80px) * 0.0705));
  }
  .sec-head .h2 .h-bot {
    display: inline-block;
    margin-left: 0.25em;
  }

  /* Standfirsts run the full width of the content column, at 22px so the
     longer line stays readable. No empty right hand half under a heading. */
  .sec-head .lede {
    max-width: none;
    font-size: 22px;
    line-height: 1.5;
  }

  /* The trial band's two lines share its 46% text column with the art, so
     they scale with that column: START WITH 7 DAYS is the longer line. */
  .cta-band .h2 .h-top,
  .cta-band .h2 .h-bot {
    font-size: min(76px, calc((min(100vw, 1240px) - 80px) * 0.0636));
  }
}

/* THE PLATFORM video plays muted on its own, and this is the way to sound: a
   square Racing Red button in the player's lower left, 48px tall, gone once
   the sound is on. It is a single small block, so it stays well inside the
   page's red budget. */
.player { position: relative; }
.player__sound {
  position: absolute;
  left: 12px;
  bottom: 56px;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  min-height: 48px;
  padding: 0 18px;
  border: 0;
  border-radius: 0;
  background: var(--accent);
  color: var(--parchment);
  font-family: var(--display);
  font-size: 18px;
  letter-spacing: 0.04em;
  line-height: 1;
  text-transform: uppercase;
  white-space: nowrap;
  cursor: pointer;
}
.player__sound:hover { background: var(--accent-deep); }
.player__sound:focus-visible { outline: 2px solid var(--parchment); outline-offset: 2px; }

/* ==========================================================================
   Every screen has a job: the slide rework.
   ========================================================================== */

/* The slide number and the screen's name: 14px, letter spaced. */
.deck__n,
.deck__copy .anchor__tag { font-size: 14px; letter-spacing: 0.16em; }

/* Three spec lines under a Carbon hairline, from the slide's data. Barlow
   Condensed, uppercase and Parchment, each after an 8px Racing Red square. */
.deck__specs {
  list-style: none;
  margin: 22px 0 0;
  padding: 18px 0 0;
  border-top: 1px solid var(--carbon);
  display: grid;
  gap: 12px;
}
.deck__specs li {
  position: relative;
  padding-left: 20px;
  font-family: var(--body);
  font-size: 16px;
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--parchment);
}
.deck__specs li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.32em;
  width: 8px;
  height: 8px;
  background: var(--accent);
}

@media (max-width: 799px) {
  .deck__copy .h2--block .h-top,
  .deck__copy .h2--block .h-bot { font-size: 30px; }
  .deck__line { font-size: 18px; }
  .deck__specs li { font-size: 15px; }
  /* Never taller than one screen: the copy keeps its height and the capture
     gives way, cropped at the bottom with its fade. */
  .deck__slide {
    display: flex;
    flex-direction: column;
    max-height: 100svh;
  }
  .deck__copy { flex: none; }
  .deck .phone {
    flex: 0 1 auto;
    min-height: 120px;
    display: flex;
    flex-direction: column;
  }
  .deck .phone__screen { flex: 1 1 auto; min-height: 0; height: 300px; }
}

@media (min-width: 800px) {
  /* Copy and capture side by side, 1.1 to 0.9, 64px apart, with 56px of air
     top, right and bottom. The left stays at 0 so the copy starts on the
     same grid line as the section heading above it; 56px there would move it
     56px inside that line. The copy is centred against the capture. */
  .deck__slide {
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
    column-gap: 64px;
    align-items: center;
    height: auto;
    max-height: 640px;
    padding: 56px 56px 56px 0;
  }
  .deck__copy { align-self: center; }
  .deck__copy .h2--block .h-top,
  .deck__copy .h2--block .h-bot { font-size: clamp(44px, 5vw, 68px); }
  .deck__line { font-size: 22px; line-height: 1.45; max-width: 520px; }

  /* The capture at 420px, centred in its column, top aligned and cropped at
     the bottom. 504px of crop, plus the frame's 12px top and bottom and the
     slide's 56px, is the 640px the slide may grow to. */
  .deck .phone {
    justify-self: center;
    align-self: start;
    width: 100%;
    max-width: 444px;
  }
  .deck .phone__screen { height: 504px; }
}
