/* ==========================================================================
   BLACK BELT RESULTS — the funnel
   --------------------------------------------------------------------------
   HOW THIS FILE IS ORGANISED. Search for the numbered headings.

     01  TOKENS ............ every colour, size and space value. Change here.
     02  FONTS ............. the three typefaces, loaded from /assets/fonts/
     03  RESET + BASE ...... browser defaults, page ground, body text
     04  TYPE ROLES ........ headings, eyebrows, beats, lead paragraphs
     05  LAYOUT ............ the measure, the vertical rhythm, dividers
     06  BELT TRACK ........ the rail down the left edge (the signature element)
     07  BUTTONS ........... the ENTER THE DOJO buttons
     08  IMAGES ............ picture blocks + the duotone treatment
     09  SECTIONS .......... hero, story, dojo/kanji, cases, guarantee, bonus
     10  FORM .............. the three fields, labels, errors, status
     11  STICKY CTA ........ the mobile bar that appears after 40% scroll
     12  FOOTER
     13  MOTION ............ scroll reveal, hero entrance, reduced-motion
     14  ACCESSIBILITY ..... focus rings, skip link, screen-reader helpers
     15  PRINT
     16  FUNNEL ............ players, steps, promise, one fold, reasons, offer

   No colour value (#hex) appears anywhere below section 01. If you want to
   change a colour, change it once at the top and it changes everywhere.
   ========================================================================== */


/* ==========================================================================
   01  TOKENS
   ========================================================================== */

:root {

  /* --- Palette ---------------------------------------------------------
     sumi   = warm black. Ink, not navy. The page ground.
     canvas = aged washi. Primary text on dark. Never pure white.
     tatami = straw. Eyebrows, rules, secondary text.
     obi    = brown belt. Mid-progression, borders, hovers.
     seal   = the one loud colour. CTA and the seal mark ONLY. Nothing else. */
  --sumi:        #141110;
  --sumi-deep:   #0B0908;   /* darkest point of the page — cost of doing nothing */
  --sumi-lift:   #1C1817;   /* barely-there lift for cards and boxes */
  --canvas:      #EBE4D6;
  --bone:        #E8E0D4;   /* light section ground */
  --paper:       #FFFFFF;   /* the first fold — white */
  --tatami:      #B9A57C;
  --obi:         #7A4A24;
  --seal:        #9B2A1F;
  --seal-hot:    #B33325;   /* hover only */
  --oxblood:     #47141A;   /* the opt-in section ground */

  /* --- Semantic roles. Sections re-point these; nothing else should. --- */
  --ground:      var(--sumi);
  --ink:         var(--canvas);
  --ink-2:       var(--tatami);   /* secondary text */
  --rule:        var(--tatami);   /* hairlines */
  --rule-alpha:  0.2;

  /* --- Type scale. Fluid between 375px and 1440px. ---------------------- */
  --step--2:  0.75rem;                                  /* 12px  belt labels */
  --step--1:  0.8125rem;                                /* 13px  eyebrows    */
  --step-0:   1.125rem;                                     /* 18px mobile   */
  --step-1:   1.25rem;                                      /* lead para     */
  --step-2:   clamp(1.5rem,   1.30rem + 0.85vw, 2.125rem);  /* beats         */
  --step-3:   clamp(2rem,     1.55rem + 1.92vw, 3.5rem);    /* h2            */
  --step-4:   clamp(1.875rem, 1.55rem + 1.39vw, 3rem);      /* h1 / hero     */

  /* Display leading. Title Case has ascenders AND descenders on every line,
     so it needs real room — anything under 1.0 and the lines collide. */
  --leading-tight:  1.08;
  --leading-body:   1.75;   /* body — long copy, wide leading, easy on the eye */
  --tracking-tight: 0.005em;
  --tracking-wide:  0.16em;

  /* --- Space. ma — the empty training floor. ---------------------------- */
  --space-3xs:  4px;
  --space-2xs:  8px;
  --space-xs:  12px;
  --space-s:   20px;
  --space-m:   32px;
  --space-l:   56px;
  --space-xl:  88px;
  /* One flat section rhythm, top and bottom, the whole way down the page. */
  --space-2xl: clamp(88px, 6vw + 56px, 116px);

  /* --- Measure. A fixed centred column, not a character count. ---------- */
  --measure:      min(610px, 100%);
  --measure-wide: min(760px, 100%);
  --gutter:       clamp(20px, 5vw, 64px);
  --rail-w:       72px;     /* left gutter reserved for the belt rail, desktop */
  --shell:        1240px;

  /* --- Misc ------------------------------------------------------------ */
  --radius:     2px;
  --hairline:   1px;
  --ease:       cubic-bezier(0.16, 0.84, 0.44, 1);
  --dur-fast:   140ms;
  --dur:        420ms;
}


/* ==========================================================================
   02  FONTS
   Self-hosted, latin subset, woff2 only. ~96KB for all three.
   Display = Oswald (variable). Body = Fira Sans. Utility = IBM Plex Mono.
   ========================================================================== */

/* Oswald, variable. One file covers every display weight we use. */
@font-face {
  font-family: 'Oswald';
  src: url('assets/fonts/oswald-var.woff2') format('woff2-variations');
  font-weight: 200 700; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Fira Sans';
  src: url('assets/fonts/fira-sans-400.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Fira Sans';
  src: url('assets/fonts/fira-sans-500.woff2') format('woff2');
  font-weight: 500; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Fira Sans';
  src: url('assets/fonts/fira-sans-600.woff2') format('woff2');
  font-weight: 600; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'IBM Plex Mono';
  src: url('assets/fonts/ibm-plex-mono-500.woff2') format('woff2');
  font-weight: 500; font-style: normal; font-display: swap;
}

:root {
  --font-display: 'Oswald', 'Arial Narrow', 'Helvetica Neue Condensed', sans-serif;
  --font-body:    'Fira Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --font-mono:    'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
}


/* ==========================================================================
   03  RESET + BASE
   ========================================================================== */

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

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

body {
  margin: 0;
  background: var(--sumi);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--step-0);
  font-weight: 400;
  line-height: var(--leading-body);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

/* The grain. One tiled PNG so flat dark areas have some tooth to them.
   It sits UNDER the content as a background layer, never over it — a blended
   overlay on top washes out every word on the page.
   Delete the two background-image lines below for a clean flat page. */
body {
  background-image: url('assets/images/texture-canvas.png');
  background-repeat: repeat;
}
.section--light,
.section--deep,
.final,
.card {
  background-image: url('assets/images/texture-canvas.png');
  background-repeat: repeat;
}

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

p { margin: 0 0 1.15em; max-width: var(--measure); }
p:last-child { margin-bottom: 0; }

h1, h2, h3 { margin: 0; font-weight: 400; }

a { color: inherit; }

::selection { background: var(--seal); color: var(--canvas); }


/* ==========================================================================
   04  TYPE ROLES
   ========================================================================== */

/* --- Display: headings. Blunt, condensed, set big and tight. ------------
   Headings and beats are Title Case — first letter of each word capitalised,
   never all-caps. All-caps is reserved for the mono utility marks (eyebrows,
   belt labels, grading marks, card feet, buttons). */
.h1, .h2 {
  font-family: var(--font-display);
  font-weight: 500;
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
  text-transform: capitalize;
  text-wrap: balance;
  max-width: 18ch;
}
.h1, .h2 { margin-bottom: var(--space-m); }
.h1 { font-size: var(--step-4); max-width: 14ch; }
.h2 { font-size: var(--step-3); }
.h2--wide { max-width: 24ch; }

/* The hero headline is one long line of copy. Setting all of it at h1 size
   would fill two screens, so the opening sentence carries the display size
   and the rest steps down inside the same heading. The words are untouched. */
/* The sub-headline. A deck, not a second headline — body face, regular
   weight, comfortable leading, so the eye drops straight out of the display
   type into something easy to read. */
.h1__sub {
  display: block;
  margin: var(--space-m) auto 0;
  font-family: var(--font-body);
  font-size: clamp(1.125rem, 1.02rem + 0.44vw, 1.375rem);
  font-weight: 400;
  line-height: 1.5;
  max-width: min(700px, 100%);
  color: var(--ink);
}

/* Draft five, designer note 7: the three questions in the sub-head sit
   together on one line — the rhythm is the point. These breaks do that from
   900px up and vanish on mobile, where the line has to wrap regardless. */
.br-wide { display: none; }
@media (min-width: 900px) { .br-wide { display: inline; } }
/* The deck needs to clear the body copy that follows it. */
.hero .h1__sub { margin-bottom: var(--space-xl); }

/* Spacing utilities. Used sparingly, only where a section needs one extra
   beat of air that the section rhythm does not already give it. */
.mt-l  { margin-top: var(--space-l); }
.mt-xl { margin-top: var(--space-xl); }
.my-l  { margin-block: var(--space-l); }
.my-xl { margin-block: var(--space-xl); }

/* --- Utility: eyebrows, belt labels, grading marks. -------------------- */
.eyebrow,
.belt-label,
.grade-mark,
.card__beat {
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: var(--step--1);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--ink-2);
  line-height: 1.4;
}
/* Section eyebrows carry a leading slash — "/ THE PREMISE" — as the spine of
   the page. Every one of these labels is NEW COPY, not from COPY.md.
   See NOTES.md, open item 6. */
.eyebrow {
  display: block;
  margin-bottom: var(--space-m);
  font-size: var(--step--2);
  opacity: 0.9;
}

/* --- Lead paragraph: the first para after a heading. ------------------- */
.lead {
  font-size: var(--step-1);
  color: var(--ink);
  font-weight: 400;
}

/* --- Beats. The bold single lines. Not body copy — give them air. ------ */
.beat {
  font-family: var(--font-display);
  font-size: var(--step-2);
  font-weight: 500;
  line-height: 1.25;
  letter-spacing: var(--tracking-tight);
  text-transform: capitalize;
  color: var(--ink);
  max-width: 20ch;
  margin: var(--space-l) 0;
  padding-left: var(--space-s);
  border-left: 3px solid var(--seal);
}

/* The rule of three. Three beats stacked as one block, so they read as a set
   rather than as three interruptions. */
.beats { margin-block: var(--space-xl); }
.beats .beat { margin-block: 0 var(--space-l); }
.beats .beat:last-child { margin-bottom: 0; }

/* A quieter beat: no rule, tatami, used mid-flow. */
.beat--quiet {
  border-left-color: var(--obi);
  color: var(--ink-2);
}

/* Secondary/aside text. */
.muted { color: var(--ink-2); }


/* ==========================================================================
   05  LAYOUT
   ========================================================================== */

.shell {
  max-width: var(--shell);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* Every section gets the same generous vertical breathing room. */
.section {
  position: relative;
  padding-block: var(--space-2xl);
  z-index: 2;
  /* Re-declare the text colour from this section's own token scope. A section
     that re-points --ink (see .section--light) must restate `color` here, or
     its children just inherit the colour body already computed. */
  color: var(--ink);
}
.section > .shell { position: relative; }

/* Sections sit on a strong left axis. Only the hero and the CTAs centre. */
.section__body { max-width: var(--measure); }
.section__body--wide { max-width: var(--measure-wide); }

/* Consecutive copy blocks need a breath between them, or they read as one
   undifferentiated wall. */
.section__body + .section__body { margin-top: var(--space-l); }


/* --- CENTRED LAYOUT ---------------------------------------------------
   Everything on the page is centred on one vertical axis: headings, body
   copy, beats, cards, the form and the footer.

   To go back to a left-aligned page, delete this one block. Nothing else
   depends on it. */

.section,
.masthead,
.footer { text-align: center; }

.section__body,
.h1, .h2, .beat, .lead,
.pledge, .form-wrap, .grades, .gloss,
.section p { margin-inline: auto; }

.h1, .h2 { max-width: 22ch; }
.h1 { max-width: 24ch; }
.beat { max-width: 28ch; }

.masthead .shell,
.footer__grid { justify-content: center; }
.masthead__logo, .footer__logo { margin-inline: auto; }
.footer__links { justify-content: center; width: 100%; }

/* A centred beat cannot carry a rule down its left edge — the rule sits
   above it instead, short and centred. */
.beat {
  border-left: 0;
  padding-left: 0;
  padding-top: var(--space-m);
  border-top: 3px solid var(--seal);
  width: -moz-fit-content;
  width: fit-content;
}
.beat--quiet { border-top-color: var(--obi); }

/* Rows that were two columns become stacked and centred. */
.grades li,
.gloss__row { grid-template-columns: 1fr; gap: var(--space-2xs); }

/* Form: labels, errors and status centre with everything else. The value
   the user types stays left-aligned — centred text jumping around inside a
   field while you type is horrible to use. */
.field label, .field__error, .form__status, .form__privacy { text-align: center; }
.field input { text-align: left; }

/* Section dividers.
   Where the ground changes — dark to bone, bone to oxblood — the change of
   ground IS the divider and a rule on top of it would be noise. A hairline is
   only drawn between two sections that share the same ground. */
.section + .section {
  border-top: var(--hairline) solid color-mix(in srgb, var(--tatami) 16%, transparent);
}
.section--light + .section--light {
  border-top-color: color-mix(in srgb, var(--obi) 22%, transparent);
}
.section--light + .section:not(.section--light),
.section:not(.section--light) + .section--light,
.section + .section--seal,
.section--seal + .section,
.section + .section--deep,
.section--deep + .section {
  border-top: 0;
}

/* Divider: a single hairline. Nothing decorative. */
.rule {
  border: 0;
  height: var(--hairline);
  background: var(--rule);
  opacity: var(--rule-alpha);
  margin: 0;
}

/* Section ground variants ------------------------------------------------ */
.section--deep  { background-color: var(--sumi-deep); }

/* The one light break. Canvas ground, sumi type. Secondary text has to move
   from tatami to obi here or it fails contrast. */
/* Light (bone) sections. The page alternates dark and bone the whole way
   down rather than running one long dark scroll. Secondary text moves from
   tatami to obi here — tatami on bone fails contrast. */
.section--light {
  background-color: var(--bone);
  --ground: var(--bone);
  --ink:    var(--sumi);
  --ink-2:  var(--obi);
  --rule:   var(--obi);
  --rule-alpha: 0.28;
}

/* The opt-in section. Deep oxblood ground — the one section that is neither
   dark nor bone, so the form reads as the destination. */
.section--seal {
  background-color: var(--oxblood);
  --ground: var(--oxblood);
  --ink:    var(--canvas);
  --ink-2:  color-mix(in srgb, var(--canvas) 72%, var(--oxblood));
  --rule:   var(--canvas);
  --rule-alpha: 0.3;
}

/* Desktop: reserve the left gutter so nothing collides with the rail, and
   step the body copy down a touch — the measure is fixed, so a smaller size
   simply puts more words on each line. */
@media (min-width: 900px) {
  body { padding-left: var(--rail-w); font-size: 1.0625rem; }
  :root { --step-0: 1.0625rem; --step-1: 1.1875rem; }
}


/* ==========================================================================
   06  BELT TRACK  — the signature element
   A hairline rail down the left edge that fills as he scrolls, changing
   colour through the belt order: canvas → tatami → obi → black.
   Mobile: a 2px bar under the header instead.
   The fill amount is set by main.js as --belt-progress (0 to 1).
   ========================================================================== */

.belt {
  position: fixed;
  z-index: 40;
  pointer-events: none;
  --belt-progress: 0;
  --belt-colour: var(--canvas);
}

/* --- Desktop rail ------------------------------------------------------- */
@media (min-width: 900px) {
  .belt {
    top: 0; left: 0; bottom: 0;
    width: var(--rail-w);
  }
  /* the unfilled track */
  .belt__track {
    position: absolute;
    top: 0; bottom: 0;
    left: calc(var(--rail-w) / 2);
    width: var(--hairline);
    background: var(--tatami);
    opacity: 0.22;
    transition: background-color var(--dur) var(--ease),
                opacity var(--dur) var(--ease);
  }
  /* the fill */
  .belt__fill {
    position: absolute;
    top: 0;
    left: calc(var(--rail-w) / 2 - 1px);
    width: 3px;
    height: calc(var(--belt-progress) * 100%);
    background: var(--belt-colour);
    transition: background-color var(--dur) var(--ease);
  }
  /* The black belt is the same value as the ground, so it would vanish.
     Give it a hairline outline so it still reads as "the belt went black". */
  .belt[data-belt='black'] .belt__fill {
    background: var(--sumi-deep);
    box-shadow: inset 0 0 0 1px var(--tatami);
  }
  /* White belt on the white fold would disappear the same way black does on
     black. Both ends of the belt order carry a hairline edge. */
  .belt[data-belt='white'] .belt__fill {
    box-shadow: inset 0 0 0 1px var(--obi);
  }

  /* --- The rail over the white fold ---------------------------------
     While the paper hero fills the screen the rail is sitting on white, so
     its hairline and labels invert to dark. main.js sets data-ground. */
  .belt[data-ground='paper'] .belt__track { background: var(--sumi); opacity: 0.16; }
  .belt[data-ground='paper'] .belt__label { color: var(--obi); }
  .belt[data-ground='paper'] .belt__label[data-active='true'] { color: var(--sumi); }

  .belt__labels { position: absolute; inset: 0; }
  .belt__label {
    position: absolute;
    left: calc(var(--rail-w) / 2 + 10px);
    transform: translateY(-50%);
    writing-mode: vertical-rl;
    font-family: var(--font-mono);
    font-weight: 500;
    font-size: var(--step--2);
    letter-spacing: var(--tracking-wide);
    text-transform: uppercase;
    color: var(--tatami);
    opacity: 0.35;
    white-space: nowrap;
    transition: opacity var(--dur) var(--ease), color var(--dur) var(--ease);
  }
  .belt__label[data-active='true'] { opacity: 1; color: var(--canvas); }

  /* tick at each belt boundary */
  .belt__label::before {
    content: '';
    position: absolute;
    left: -10px;
    top: 50%;
    width: 9px;
    height: var(--hairline);
    background: currentColor;
  }

  .belt__bar { display: none; }
}

/* --- Mobile bar --------------------------------------------------------- */
@media (max-width: 899px) {
  .belt {
    top: 0; left: 0; right: 0;
    height: 2px;
  }
  .belt__track, .belt__labels { display: none; }
  .belt__bar {
    position: absolute;
    inset: 0;
    background: color-mix(in srgb, var(--tatami) 22%, transparent);
  }
  .belt__bar::after {
    content: '';
    position: absolute;
    inset: 0 auto 0 0;
    width: calc(var(--belt-progress) * 100%);
    background: var(--belt-colour);
    transition: background-color var(--dur) var(--ease);
  }
  .belt[data-belt='black'] .belt__bar::after {
    background: var(--sumi-deep);
    box-shadow: inset 0 0 0 1px var(--tatami);
  }
  .belt[data-belt='white'] .belt__bar::after {
    box-shadow: inset 0 0 0 1px var(--obi);
  }
  .belt__fill { display: none; }
}

/* The belt name is only ever shown on the desktop rail, where it has room and
   a consistent dark ground behind it. On mobile the bar carries the belt in
   colour alone — a floating label over a section that may be light or dark
   was never legible in both, and it was not doing enough work to keep. */
.belt__current { display: none; }


/* ==========================================================================
   07  BUTTONS
   ========================================================================== */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-xs);
  min-height: 60px;
  padding: var(--space-s) clamp(28px, 6vw, 56px);
  border: 0;
  border-radius: var(--radius);
  background: var(--seal);
  color: var(--canvas);
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: var(--step--1);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease),
              transform var(--dur-fast) var(--ease);
}
.btn:hover  { background: var(--seal-hot); }
.btn:active { transform: translateY(1px); }
.btn[disabled] { opacity: 0.55; cursor: progress; }
.btn--block { width: 100%; }

/* In-page CTAs are underlined text links, not filled buttons. The filled
   seal button is kept for the one place it is a real button: the form. */
.cta__link {
  display: inline-flex;
  align-items: baseline;
  gap: 0.6em;
  padding-bottom: var(--space-2xs);
  border-bottom: var(--hairline) solid currentColor;
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: var(--step--1);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  text-decoration: none;
  color: var(--ink);
  transition: color var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease);
}
.cta__link:hover { color: var(--tatami); border-color: var(--tatami); }
.section--light .cta__link:hover { color: var(--seal); border-color: var(--seal); }

/* The CTA sits centred with air around it. */
.cta {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--space-s);
  margin-block: var(--space-xl);
}
.cta__note {
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-2);
  opacity: 0.8;
}


/* ==========================================================================
   08  IMAGES + DUOTONE
   --------------------------------------------------------------------------
   REMOVING THE DUOTONE: delete the single `.duotone` rule block below and
   every photo goes back to full colour. Nothing else needs to change.
   ========================================================================== */

.fig {
  margin: 0 auto;
  position: relative;
  max-width: var(--measure);
}
.fig img { width: 100%; height: auto; object-fit: cover; }

/* DUOTONE — OFF. Photos run in full colour.

   The `duotone` class is still on every picture in the HTML, so the treatment
   can be switched back on by deleting the two comment markers below and
   nothing else. It pushes shadows to --sumi and highlights to --tatami, which
   makes mixed-quality phone photos read as one set.

.duotone { position: relative; isolation: isolate; }
.duotone img { filter: grayscale(1) contrast(1.06) brightness(0.94); }
.duotone::before,
.duotone::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
}
.duotone::before { background: var(--sumi);   mix-blend-mode: lighten; }
.duotone::after  { background: var(--tatami); mix-blend-mode: multiply; }

   ---- end of the duotone block ---- */


/* ==========================================================================
   09  SECTIONS
   ========================================================================== */

/* --- Masthead ----------------------------------------------------------- */
.masthead {
  position: relative;
  z-index: 30;
  padding-block: var(--space-l) 0;
}
/* The logo is a 1.52:1 lockup with the belt beneath the type, not a wide
   wordmark — so it needs real height. Transparent PNG, so it sits on the
   white fold and the dark footer without a box around it. */
.masthead__logo { width: clamp(150px, 18vw, 210px); height: auto; }

/* --- 1. Hero ------------------------------------------------------------ */
.hero {
  position: relative;
  padding-block: var(--space-xl) var(--space-2xl);
  overflow: hidden;
}

/* --- The first fold is white with black type. ---------------------------
   The masthead carries the same ground so the whole opening screen is one
   clean white field before the page drops into the dark.
   To go back to the dark photographic hero: remove `hero--paper` from the
   <section> and `masthead--paper` from the <header> in index.html. */
.masthead--paper,
.hero--paper {
  background-color: var(--paper);
  --ground: var(--paper);
  --ink:    var(--sumi);
  --ink-2:  var(--obi);
  --rule:   var(--obi);
  --rule-alpha: 0.28;
}
.masthead--paper { color: var(--sumi); }

/* No photograph on a white fold — the type is the whole hero. The markup is
   left in place, so deleting this one line brings the image back. */
.hero--paper .hero__media { display: none; }

/* Desktop only: run the white all the way to the left edge, underneath the
   belt rail. The negative margin widens the box and the matching left padding
   puts the content back where it was, so the hero stays aligned with every
   section below it. */
@media (min-width: 900px) {
  .masthead--paper,
  .hero--paper {
    margin-left: calc(-1 * var(--rail-w));
    padding-left: var(--rail-w);
  }
}
.hero__media {
  position: absolute;
  inset: 0;
  z-index: 0;
}
.hero__media img { width: 100%; height: 100%; object-fit: cover; }

/* The scrim. Two layers so text contrast stays above 7:1 across the whole
   headline, not just where the photo happens to be dark. */
.hero__media::after {
  content: '';
  position: absolute;
  inset: 0;
  background:
    linear-gradient(180deg,
      color-mix(in srgb, var(--sumi) 60%, transparent) 0%,
      color-mix(in srgb, var(--sumi) 78%, transparent) 55%,
      var(--sumi) 100%),
    linear-gradient(90deg,
      color-mix(in srgb, var(--sumi) 88%, transparent) 0%,
      color-mix(in srgb, var(--sumi) 68%, transparent) 55%,
      color-mix(in srgb, var(--sumi) 45%, transparent) 100%);
}
.hero__inner { position: relative; z-index: 2; }
.hero .h1 { margin-bottom: var(--space-l); }

/* --- 2. Dojo / kanji ---------------------------------------------------- */
/* The one correct use of kanji on the page: 道 (dō, the way) 場 (jō, place).
   Large, low opacity, behind the section. Nowhere else. */
.dojo { position: relative; overflow: hidden; }
.dojo__kanji {
  position: absolute;
  top: 50%;
  right: -0.08em;
  transform: translateY(-50%);
  font-family: var(--font-body);
  font-weight: 400;
  font-size: clamp(14rem, 42vw, 34rem);
  line-height: 0.8;
  color: var(--canvas);
  opacity: 0.05;
  pointer-events: none;
  user-select: none;
  z-index: 0;
}
.dojo .shell { position: relative; z-index: 2; }
.dojo .section__body { max-width: var(--measure); }

/* The two-word etymology, set as a small definition list. */
.gloss {
  margin: var(--space-l) 0;
  display: grid;
  gap: var(--space-m);
  max-width: var(--measure);
}
.gloss__row {
  display: grid;
  grid-template-columns: 2.4em 1fr;
  gap: var(--space-s);
  align-items: baseline;
  padding-top: var(--space-s);
  border-top: var(--hairline) solid color-mix(in srgb, var(--rule) 30%, transparent);
}
.gloss__char {
  font-size: 2em;
  line-height: 1;
  color: var(--ink-2);
}

/* --- 3. Mitchy's story -------------------------------------------------- */
.story__grid {
  display: grid;
  gap: var(--space-l);
  align-items: start;
}
/* The page flows top to bottom the whole way down. Images sit above the copy
   they belong to, never beside it — at every width, including desktop. */
.story__grid > * { margin-inline: auto; }
.story__grid .fig { max-width: var(--measure); }

/* The shotgun paragraph and the one after it. Full width, nothing beside it,
   nothing decorating it. Do not put an image here. */
.isolate {
  margin-block: var(--space-2xl);
  padding-block: var(--space-xl);
  border-top:    var(--hairline) solid color-mix(in srgb, var(--tatami) 26%, transparent);
  border-bottom: var(--hairline) solid color-mix(in srgb, var(--tatami) 26%, transparent);
}
.isolate p {
  font-size: var(--step-1);
  max-width: 34ch;
  line-height: 1.45;
}
.isolate p + p { margin-top: 1em; }

/* --- 5. Ninety-day grading. Numbered steps are legitimate HERE only. ---- */
.grades {
  list-style: none;
  margin: var(--space-l) 0 0;
  padding: 0;
  display: grid;
  gap: 0;
  max-width: var(--measure);
}
.grades li {
  display: grid;
  grid-template-columns: 5.5rem 1fr;
  gap: var(--space-s);
  align-items: baseline;
  padding-block: var(--space-m);
  border-top: var(--hairline) solid color-mix(in srgb, var(--rule) 26%, transparent);
}
.grades li:last-child {
  border-bottom: var(--hairline) solid color-mix(in srgb, var(--rule) 26%, transparent);
}
.grades p { margin: 0; }

/* --- 7. Case studies: Adam / Maddy / Camo ------------------------------- */
.cases {
  display: grid;
  gap: var(--space-l);
  margin-top: var(--space-xl);
}
/* Stacked, one above the other, at every width. Not three-up, not a slider. */
.cases > * { max-width: var(--measure); margin-inline: auto; width: 100%; }
.card {
  display: flex;
  flex-direction: column;
  background-color: var(--sumi-lift);
  border: var(--hairline) solid color-mix(in srgb, var(--tatami) 18%, transparent);
  border-radius: var(--radius);
}
.card__media { border-bottom: var(--hairline) solid color-mix(in srgb, var(--tatami) 18%, transparent); }
.card__body  { padding: var(--space-m); flex: 1; }
.card__name  {
  font-family: var(--font-display);
  font-size: var(--step-2);
  font-weight: 500;
  line-height: 1.15;
  text-transform: capitalize;
  letter-spacing: var(--tracking-tight);
  margin-bottom: var(--space-s);
}
.card__body p { font-size: 1rem; max-width: none; }
.card__beat {
  padding: var(--space-s) var(--space-m);
  border-top: var(--hairline) solid color-mix(in srgb, var(--tatami) 18%, transparent);
  color: var(--tatami);
}

/* --- 8. Ten hours / guarantee. Hairline box. No shadow, no badge. ------- */
.pledge {
  margin-top: var(--space-xl);
  padding: clamp(28px, 5vw, 56px);
  border: var(--hairline) solid color-mix(in srgb, var(--tatami) 40%, transparent);
  border-radius: var(--radius);
  max-width: var(--measure-wide);
}
.pledge p { max-width: var(--measure); }

/* --- 9. Bonus: four times a year --------------------------------------- */
.quad {
  display: grid;
  gap: var(--space-m);
  margin-top: var(--space-xl);
}
.quad > * { max-width: var(--measure); margin-inline: auto; width: 100%; }
.quad__item {
  border-top: var(--hairline) solid color-mix(in srgb, var(--rule) 30%, transparent);
  padding-top: var(--space-s);
}
.quad__item .fig { margin-bottom: var(--space-s); }
.quad__item p { font-size: 1rem; }

/* --- 11. Final CTA ------------------------------------------------------ */
.final { position: relative; overflow: hidden; background-color: var(--sumi-deep); }
.final__media { position: absolute; inset: 0; z-index: 0; opacity: 0.22; }
.final__media img { width: 100%; height: 100%; object-fit: cover; }
.final__media::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg,
    var(--sumi-deep) 0%,
    color-mix(in srgb, var(--sumi-deep) 72%, transparent) 45%,
    var(--sumi-deep) 100%);
}
.final .shell { position: relative; z-index: 2; }


/* ==========================================================================
   10  FORM
   ========================================================================== */

.form-wrap {
  margin-top: var(--space-xl);
  max-width: 560px;
}

.field { margin-bottom: var(--space-m); }

/* Labels are always visible, above the field. Never placeholder-only. */
.field label {
  display: block;
  margin-bottom: var(--space-2xs);
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: var(--step--1);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--ink-2);
}

.field input {
  width: 100%;
  min-height: 60px;
  padding: var(--space-xs) var(--space-s);
  background: color-mix(in srgb, var(--canvas) 5%, transparent);
  border: var(--hairline) solid color-mix(in srgb, var(--tatami) 42%, transparent);
  border-radius: var(--radius);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 1.0625rem;   /* 17px — never below 16px or iOS zooms on focus */
  line-height: 1.4;
  transition: border-color var(--dur-fast) var(--ease),
              background-color var(--dur-fast) var(--ease);
}
.field input::placeholder { color: color-mix(in srgb, var(--ink-2) 60%, transparent); }
.field input:hover { border-color: var(--obi); }
.field input:focus {
  outline: none;
  border-color: var(--tatami);
  background: color-mix(in srgb, var(--canvas) 9%, transparent);
}

.field[data-invalid='true'] input { border-color: var(--seal); }

.field__error {
  display: none;
  margin-top: var(--space-2xs);
  color: var(--seal);
  font-size: 0.9375rem;
  line-height: 1.45;
}
/* On the dark ground the seal is too dim for small text — lift it. */
.field__error { color: color-mix(in srgb, var(--seal) 55%, var(--canvas)); }
.field[data-invalid='true'] .field__error { display: block; }

/* --- The qualifying question ----------------------------------------
   A radio group, not a dropdown — every option visible without a tap, and
   the whole row is the target so it works with a thumb. */
.field--choice {
  margin: 0 0 var(--space-m);
  padding: 0;
  border: 0;
}
.field--choice legend {
  display: block;
  margin-bottom: var(--space-xs);
  padding: 0;
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: var(--step--1);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--ink-2);
}
.choice {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  min-height: 56px;
  margin-bottom: var(--space-2xs);
  padding: var(--space-xs) var(--space-s);
  background: color-mix(in srgb, var(--canvas) 5%, transparent);
  border: var(--hairline) solid color-mix(in srgb, var(--tatami) 42%, transparent);
  border-radius: var(--radius);
  text-align: left;
  cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease),
              background-color var(--dur-fast) var(--ease);
}
.choice:hover { border-color: var(--obi); }
.choice input { flex: none; width: 20px; height: 20px; accent-color: var(--seal); }
.choice:has(input:checked) {
  border-color: var(--canvas);
  background: color-mix(in srgb, var(--canvas) 12%, transparent);
}
.field--choice[data-invalid='true'] .choice { border-color: var(--seal); }

.form__foot {
  margin-top: var(--space-l);
  display: grid;
  gap: var(--space-s);
}
.form__privacy {
  font-size: 0.9375rem;
  color: var(--ink-2);
  max-width: var(--measure);
}

/* The status region. aria-live, so it must be present in the DOM at all
   times — it is only ever empty, never display:none. */
.form__status {
  min-height: 1.5em;
  font-family: var(--font-mono);
  font-size: var(--step--1);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-2);
}
.form__status[data-tone='error']   { color: color-mix(in srgb, var(--seal) 55%, var(--canvas)); }
.form__status[data-tone='success'] { color: var(--tatami); }

/* Honeypot. Off-screen, not display:none, so bots still fill it. */
.hp {
  position: absolute !important;
  left: -9999px !important;
  width: 1px; height: 1px;
  overflow: hidden;
}


/* ==========================================================================
   11  STICKY MOBILE CTA
   Appears after 40% scroll. Anchors to the form. Mobile only.
   ========================================================================== */

.sticky-cta {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 50;
  padding: var(--space-xs) var(--gutter)
           calc(var(--space-xs) + env(safe-area-inset-bottom, 0px));
  background: color-mix(in srgb, var(--sumi) 94%, transparent);
  backdrop-filter: blur(6px);
  border-top: var(--hairline) solid color-mix(in srgb, var(--tatami) 22%, transparent);
  transform: translateY(110%);
  transition: transform var(--dur) var(--ease);
}
.sticky-cta[data-shown='true'] { transform: translateY(0); }
.sticky-cta .btn { min-height: 54px; }

@media (min-width: 900px) { .sticky-cta { display: none; } }


/* ==========================================================================
   12  FOOTER
   ========================================================================== */

.footer {
  position: relative;
  z-index: 2;
  padding-block: var(--space-xl);
  border-top: var(--hairline) solid color-mix(in srgb, var(--tatami) 18%, transparent);
  padding-bottom: calc(var(--space-xl) + 80px);   /* clear the sticky bar */
}
.footer__grid {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-m);
  align-items: center;
  justify-content: space-between;
}
.footer__logo { width: 150px; height: auto; }
.footer__links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-m);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
}
.footer a { color: var(--tatami); text-decoration: none; }
.footer a:hover { color: var(--canvas); text-decoration: underline; text-underline-offset: 4px; }
.footer__fine {
  margin-top: var(--space-l);
  font-size: 0.875rem;
  color: var(--ink-2);
  opacity: 0.75;
}
@media (min-width: 900px) { .footer { padding-bottom: var(--space-xl); } }


/* ==========================================================================
   13  MOTION
   One hero entrance. One scroll-reveal threshold. Nothing else.
   ========================================================================== */

/* Scroll reveal */
.reveal {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 560ms var(--ease), transform 560ms var(--ease);
}
.reveal.is-in { opacity: 1; transform: none; }

/* Hero entrance — staggered fade-up, ~600ms total */
.hero-in > * {
  opacity: 0;
  transform: translateY(14px);
  animation: hero-rise 520ms var(--ease) forwards;
}
.hero-in > *:nth-child(1) { animation-delay:  40ms; }
.hero-in > *:nth-child(2) { animation-delay: 110ms; }
.hero-in > *:nth-child(3) { animation-delay: 190ms; }
.hero-in > *:nth-child(4) { animation-delay: 260ms; }
.hero-in > *:nth-child(5) { animation-delay: 320ms; }

@keyframes hero-rise { to { opacity: 1; transform: none; } }

/* Respect the setting. The belt track still shows position — it just
   doesn't animate, and nothing fades in. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
  }
  .reveal { opacity: 1; transform: none; }
  .hero-in > * { opacity: 1; transform: none; animation: none; }
}


/* ==========================================================================
   14  ACCESSIBILITY
   ========================================================================== */

:where(a, button, input, [tabindex]):focus-visible {
  outline: 2px solid var(--tatami);
  outline-offset: 3px;
  border-radius: var(--radius);
}

.skip {
  position: absolute;
  left: var(--gutter);
  top: -100px;
  z-index: 100;
  padding: var(--space-xs) var(--space-s);
  background: var(--canvas);
  color: var(--sumi);
  font-family: var(--font-mono);
  font-size: var(--step--1);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  text-decoration: none;
  transition: top var(--dur-fast) var(--ease);
}
.skip:focus { top: var(--space-s); }

.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}


/* ==========================================================================
   15  PRINT
   ========================================================================== */

@media print {
  .belt, .sticky-cta, .hero__media, .final__media, body::before { display: none !important; }
  body { background: #fff; color: #000; padding-left: 0; }
  .section { padding-block: 24px; }
}


/* ==========================================================================
   16  FUNNEL
   --------------------------------------------------------------------------
   Everything the funnel pages add on top of the original page: the video
   players, the step rail, the quiz, the offer box, the vault list, and the
   two "not filled in yet" treatments.

   Same rule as the rest of this file — no #hex below section 01. Every colour
   here is a token or a mix of tokens.
   ========================================================================== */


/* --- 16.1  VIDEO PLAYER ------------------------------------------------
   A 16:9 box that holds a poster first and an embed after it is clicked. */

.player {
  position: relative;
  width: 100%;
  max-width: var(--measure-wide);
  margin-inline: auto;
  aspect-ratio: 16 / 9;
  background: var(--sumi-deep);
  border: var(--hairline) solid color-mix(in srgb, var(--tatami) 22%, transparent);
  border-radius: var(--radius);
  overflow: hidden;
}

.player__frame,
.player__frame iframe,
.player__frame video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
}

/* The poster is a button, so it is keyboard-reachable and announces itself. */
.player__poster {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  padding: 0;
  border: 0;
  cursor: pointer;
  background: var(--sumi-deep);
  display: grid;
  place-items: center;
}

.player__poster img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Dimmed so the play mark reads over any still. */
  filter: brightness(0.66);
  transition: filter var(--dur) var(--ease);
}

.player__poster:hover img { filter: brightness(0.78); }

/* The play mark: the seal colour, the one loud colour on the page. */
.player__play {
  position: relative;
  z-index: 2;
  width: clamp(56px, 9vw, 82px);
  aspect-ratio: 1;
  border-radius: 50%;
  background: var(--seal);
  display: block;
  transition: transform var(--dur) var(--ease), background var(--dur-fast) var(--ease);
}

.player__play::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 54%;
  translate: -50% -50%;
  border-style: solid;
  border-width: 0.62em 0 0.62em 1.02em;
  border-color: transparent transparent transparent var(--canvas);
  font-size: clamp(16px, 2.4vw, 22px);
}

.player__poster:hover .player__play { background: var(--seal-hot); transform: scale(1.06); }
.player__poster:active .player__play { transform: scale(0.98); }

.player__length {
  position: absolute;
  z-index: 2;
  right: var(--space-xs);
  bottom: var(--space-xs);
  font-family: 'IBM Plex Mono', monospace;
  font-size: var(--step--2);
  letter-spacing: var(--tracking-wide);
  color: var(--canvas);
  background: color-mix(in srgb, var(--sumi-deep) 78%, transparent);
  padding: var(--space-3xs) var(--space-2xs);
  border-radius: var(--radius);
}

/* The caption under a player. */
.player-caption {
  max-width: var(--measure-wide);
  margin: var(--space-s) auto 0;
  color: var(--ink-2);
  font-size: var(--step--1);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  font-family: 'IBM Plex Mono', monospace;
}


/* --- 16.2  NOT FILLED IN YET -------------------------------------------
   Two treatments, both deliberately ugly. They are meant to be impossible to
   miss on your own screen and impossible to ship by accident. */

.player__missing {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  gap: var(--space-2xs);
  padding: var(--space-m);
  text-align: center;
  color: var(--ink-2);
  background:
    repeating-linear-gradient(
      45deg,
      transparent 0 12px,
      color-mix(in srgb, var(--tatami) 8%, transparent) 12px 24px
    );
}

.player__missing p { margin: 0; }
.player__missing code,
.checkpanel code {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.92em;
  color: var(--canvas);
  background: color-mix(in srgb, var(--tatami) 16%, transparent);
  padding: 1px 5px;
  border-radius: var(--radius);
}

[data-unset] {
  background: color-mix(in srgb, var(--seal) 22%, transparent);
  outline: 1px dashed var(--seal);
  outline-offset: 2px;
  cursor: not-allowed;
}


/* --- 16.3  STEP RAIL ---------------------------------------------------
   Where they are in the funnel. Four dots across the top of the short pages.
   The belt rail already does this job on the long page, so the two are never
   shown together. */

.steps {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: var(--space-2xs);
  list-style: none;
  margin: 0 0 var(--space-l);
  padding: 0;
}

.steps li {
  width: 26px;
  height: 3px;
  background: color-mix(in srgb, var(--tatami) 26%, transparent);
  border-radius: var(--radius);
}

.steps li[data-state="done"] { background: var(--tatami); }
.steps li[data-state="here"] { background: var(--seal); width: 46px; }


/* --- 16.4  QUIZ --------------------------------------------------------
   One question at a time. The answers are buttons, not radios, because
   choosing IS the submit — there is nothing else to press. */

.quiz {
  max-width: var(--measure);
  margin-inline: auto;
  min-height: 46vh;
}

.quiz__q {
  font-size: var(--step-2);
  max-width: 26ch;
  margin-inline: auto;
}

.quiz__q:focus-visible { outline: none; }

.quiz__answers {
  display: grid;
  gap: var(--space-xs);
  margin-top: var(--space-l);
}

.quiz__a {
  width: 100%;
  padding: var(--space-s) var(--space-m);
  font-family: 'Fira Sans', sans-serif;
  font-size: var(--step-0);
  line-height: 1.4;
  text-align: left;
  color: var(--ink);
  background: var(--sumi-lift);
  border: var(--hairline) solid color-mix(in srgb, var(--tatami) 26%, transparent);
  border-radius: var(--radius);
  cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease),
              background var(--dur-fast) var(--ease),
              transform var(--dur-fast) var(--ease);
}

.quiz__a:hover {
  border-color: var(--tatami);
  background: color-mix(in srgb, var(--tatami) 10%, var(--sumi-lift));
}

.quiz__a:active { transform: translateY(1px); }

.quiz__a[data-chosen="true"] {
  border-color: var(--seal);
  background: color-mix(in srgb, var(--seal) 14%, var(--sumi-lift));
}

.quiz__back {
  margin-top: var(--space-l);
  padding: var(--space-2xs) 0;
  background: none;
  border: 0;
  border-bottom: var(--hairline) solid color-mix(in srgb, var(--tatami) 40%, transparent);
  color: var(--ink-2);
  font-family: 'IBM Plex Mono', monospace;
  font-size: var(--step--1);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  cursor: pointer;
}

.quiz__back:hover { color: var(--ink); border-color: var(--tatami); }

/* The progress bar above the quiz. */
.quiz-progress {
  max-width: var(--measure);
  margin: 0 auto var(--space-m);
}

.quiz-progress__bar {
  height: 3px;
  background: color-mix(in srgb, var(--tatami) 24%, transparent);
  border-radius: var(--radius);
  overflow: hidden;
}

.quiz-progress__bar::after {
  content: '';
  display: block;
  height: 100%;
  width: 100%;
  background: var(--seal);
  transform-origin: left;
  transform: scaleX(var(--quiz-progress, 0));
  transition: transform var(--dur) var(--ease);
}

.quiz-progress__count {
  margin: var(--space-2xs) 0 0;
  font-family: 'IBM Plex Mono', monospace;
  font-size: var(--step--2);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--ink-2);
}


/* --- 16.5  THE OFFER BOX ----------------------------------------------- */

.offer {
  max-width: var(--measure);
  margin: var(--space-l) auto 0;
  padding: var(--space-l) var(--space-m);
  background: var(--sumi-lift);
  border: var(--hairline) solid color-mix(in srgb, var(--tatami) 30%, transparent);
  border-radius: var(--radius);
}

.offer__price {
  font-family: 'Oswald', sans-serif;
  font-weight: 500;
  font-size: var(--step-3);
  line-height: var(--leading-tight);
  margin: 0;
}

.offer__interval {
  font-family: 'IBM Plex Mono', monospace;
  font-size: var(--step--1);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--ink-2);
  margin: var(--space-2xs) 0 var(--space-m);
}

.offer__list {
  list-style: none;
  margin: 0 0 var(--space-l);
  padding: 0;
  text-align: left;
  display: grid;
  gap: var(--space-xs);
}

.offer__list li {
  padding-left: 1.6em;
  position: relative;
  line-height: 1.5;
}

.offer__list li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 0.8em;
  height: 1px;
  background: var(--seal);
}

.offer__fine {
  margin: var(--space-s) 0 0;
  font-size: var(--step--1);
  color: var(--ink-2);
}


/* --- 16.6  THE VAULT ---------------------------------------------------
   The six-part series, stacked. Each part is a player with its number, its
   title and its own space. */

.parts {
  display: grid;
  gap: var(--space-xl);
  margin-top: var(--space-l);
}

.part { max-width: var(--measure-wide); margin-inline: auto; width: 100%; }

.part__no {
  font-family: 'IBM Plex Mono', monospace;
  font-size: var(--step--2);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--seal);
  display: block;
  margin-bottom: var(--space-2xs);
}

.part__title {
  font-family: 'Oswald', sans-serif;
  font-weight: 500;
  font-size: var(--step-2);
  line-height: var(--leading-tight);
  margin: 0 0 var(--space-s);
}


/* --- 16.7  READINESS PANEL  (?check=1) ---------------------------------
   Yours, never theirs. Only ever rendered when ?check=1 is in the URL. */

.checkpanel {
  position: fixed;
  right: var(--space-s);
  bottom: var(--space-s);
  z-index: 60;
  max-width: min(380px, calc(100vw - var(--space-m)));
  max-height: 60vh;
  overflow: auto;
  padding: var(--space-m);
  text-align: left;
  background: var(--sumi-deep);
  color: var(--ink);
  border: var(--hairline) solid var(--seal);
  border-radius: var(--radius);
  box-shadow: 0 10px 40px color-mix(in srgb, var(--sumi-deep) 70%, transparent);
  font-size: var(--step--1);
}

.checkpanel ul { margin: var(--space-2xs) 0 0; padding-left: 1.2em; }
.checkpanel li { margin-bottom: var(--space-3xs); line-height: 1.4; }

.checkpanel__close {
  position: absolute;
  top: var(--space-2xs);
  right: var(--space-2xs);
  width: 32px;
  height: 32px;
  background: none;
  border: 0;
  color: var(--ink-2);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
}

.checkpanel__close:hover { color: var(--ink); }


/* --- 16.8  MOTION ------------------------------------------------------ */

@media (prefers-reduced-motion: reduce) {
  .player__poster img,
  .player__play,
  .quiz__a,
  .quiz-progress__bar::after { transition: none; }
  .player__poster:hover .player__play { transform: none; }
}


/* --- 16.9  THREE REASONS ----------------------------------------------
   The one fold between the video and the form. Three lines, side by side
   from 760px up, stacked below it. Deliberately plain — this block is a
   reason to scroll down, not a section in its own right. */

.reasons {
  list-style: none;
  margin: var(--space-l) auto 0;
  padding: 0;
  max-width: var(--measure-wide);
  display: grid;
  gap: var(--space-l);
  text-align: left;
}

.reasons li {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-s);
  align-items: start;
}

.reasons p { margin: 0; line-height: 1.5; }

.reasons__no {
  font-family: 'IBM Plex Mono', monospace;
  font-size: var(--step--1);
  letter-spacing: var(--tracking-wide);
  color: var(--seal);
  padding-top: 0.25em;
}

@media (min-width: 760px) {
  .reasons {
    grid-template-columns: repeat(3, 1fr);
    gap: var(--space-m);
  }
  .reasons li {
    grid-template-columns: 1fr;
    gap: var(--space-2xs);
  }
  .reasons__no { padding-top: 0; }
}


/* --- 16.10  SET UP TELEGRAM --------------------------------------------
   The second button on the hand-off page. It is deliberately quieter than
   the seal-red primary — it is the answer to a problem, not the thing we
   want most people pressing. The panel it opens stays on the page. */

.btn--ghost {
  background: transparent;
  color: var(--ink);
  border: var(--hairline) solid color-mix(in srgb, var(--tatami) 45%, transparent);
}

.btn--ghost:hover {
  background: color-mix(in srgb, var(--tatami) 12%, transparent);
  border-color: var(--tatami);
}

.setup {
  max-width: var(--measure);
  margin: var(--space-xl) auto 0;
  padding-top: var(--space-l);
  border-top: var(--hairline) solid color-mix(in srgb, var(--tatami) 22%, transparent);
}

.setup__lead { margin: 0 0 var(--space-s); }

.setup__panel {
  margin-top: var(--space-l);
  text-align: left;
}

.setup__panel .player { max-width: 100%; }
.setup__panel .muted  { text-align: center; }

.setup__note {
  margin-top: var(--space-l);
  font-size: var(--step--1);
}


/* --- 16.11  THE PROMISE STRIP ------------------------------------------
   The third line of the promise, under the headline and the sub. Mono and
   small on purpose: after two lines of selling it reads as a plain statement
   of what you get, which is exactly the job it has to do. Not upper-case —
   it is a full sentence, and caps would make it shout over the headline. */

.promise__strip {
  max-width: var(--measure);
  margin: var(--space-m) auto var(--space-xl);
  font-family: 'IBM Plex Mono', monospace;
  font-size: var(--step--1);
  letter-spacing: 0.06em;
  line-height: 1.9;
  color: var(--tatami);
}

.hero .promise__strip { margin-bottom: var(--space-l); }


/* --- 16.12  THE LONG PROMISE HEADLINE ----------------------------------
   A full-sentence promise, not a three-word hook. At the standard h1 size
   and 24ch measure it runs seven lines and stops being a headline at all,
   so it steps down a size and widens out. Still the biggest thing on the
   page, still the first thing read — just no longer a wall. */

.h1--long {
  font-size: var(--step-3);
  max-width: 30ch;
  text-wrap: balance;         /* ignored where unsupported; no fallback needed */
}

@media (max-width: 560px) {
  .h1--long {
    font-size: var(--step-2);
    max-width: 22ch;
  }
}


/* --- 16.13  THE SETUP STEPS --------------------------------------------
   Five numbered steps inside the Telegram how-to panel. Left-aligned and
   loose, because this is read by somebody actually doing it on a phone with
   the app store already open in another window. */

.setup__steps {
  list-style: none;
  margin: var(--space-l) 0 0;
  padding: 0;
  display: grid;
  gap: var(--space-m);
  text-align: left;
}

.setup__steps li {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-s);
  align-items: start;
}

.setup__steps p { margin: 0; line-height: 1.6; }

.setup__no {
  font-family: 'IBM Plex Mono', monospace;
  font-size: var(--step--2);
  letter-spacing: var(--tracking-wide);
  color: var(--seal);
  padding-top: 0.35em;
}

.setup__steps a {
  color: var(--tatami);
  text-decoration: none;
  border-bottom: var(--hairline) solid color-mix(in srgb, var(--tatami) 45%, transparent);
  line-height: 2.2;
}

.setup__steps a:hover { color: var(--ink); border-color: var(--ink); }


/* --- 16.14  THE PRE-HEADLINE -------------------------------------------
   The line that sets the stakes, sitting above the promise. It replaces the
   eyebrow rather than joining it — two small things stacked over a headline
   fight each other and neither gets read.

   Big enough to be read first, small enough that the headline still wins. */

.pre-headline {
  max-width: 34ch;
  margin: 0 auto var(--space-m);
  font-size: var(--step-1);
  line-height: 1.45;
  color: var(--tatami);
}

@media (max-width: 560px) {
  .pre-headline {
    font-size: var(--step-0);
    max-width: 28ch;
  }
}


/* --- 16.15  ONE FOLD ---------------------------------------------------
   The opt-in page's first screen carries the whole pitch: stakes, promise,
   what you get, the video and the button. All of it visible without a
   scroll, on a phone.

   Everything here is a MINIMUM height and a clamped size, never a fixed one.
   On a short phone, an accessibility text size, or a landscape screen it
   simply goes back to scrolling — nothing is ever clipped or hidden to make
   the fold fit. A fold that eats its own call to action is worse than a
   scroll.
   ------------------------------------------------------------------------ */

.page-fold .masthead {
  padding-block: clamp(12px, 3vh, 28px);
}

.page-fold .masthead__logo {
  width: clamp(96px, 26vw, 150px);
}

.fold {
  /* svh, not vh — on a phone, vh is the height WITHOUT the browser's address
     bar, so a 100vh fold spends its last 60px underneath it. */
  min-height: calc(100svh - 2 * clamp(12px, 3vh, 28px) - clamp(60px, 17vw, 96px));
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding-block: clamp(8px, 2vh, 24px);
}

.fold > .shell { width: 100%; }

/* Type and rhythm, compressed just for this screen. */
.fold .pre-headline {
  font-size: clamp(0.95rem, 3.4vw, 1.25rem);
  margin-bottom: clamp(10px, 1.8vh, 20px);
}

.fold .h1--long {
  font-size: clamp(1.35rem, 5.6vw, 2.5rem);
  line-height: 1.12;
  margin-bottom: clamp(10px, 1.8vh, 20px);
  max-width: 26ch;
}

.fold .promise__strip {
  font-size: clamp(0.72rem, 2.9vw, 0.8125rem);
  line-height: 1.65;
  margin-block: 0 clamp(14px, 2.4vh, 28px);
}

/* The player keeps its 16:9 shape but is capped so it can never push the
   button off the screen — on a short phone it gives up width, not the CTA. */
.fold .player {
  max-height: min(34vh, 260px);
  max-width: min(100%, calc(min(34vh, 260px) * 16 / 9));
}

.fold .cta {
  margin-top: clamp(14px, 2.6vh, 32px);
  margin-bottom: 0;
}

.fold .cta__note { margin-top: var(--space-2xs); }

/* Landscape, and anything genuinely too short: stop pretending. */
@media (max-height: 560px), (orientation: landscape) and (max-height: 700px) {
  .fold { min-height: 0; display: block; padding-block: var(--space-l); }
  .fold .player { max-height: none; max-width: var(--measure-wide); }
}

/* On a wide screen the headline has room it isn't using: at 26ch it runs six
   lines and pushes the button off the bottom. Widen the measure so it reads
   in four, and take the height back off the player rather than the CTA. */
@media (min-width: 760px) {
  .page-fold .masthead__logo { width: clamp(96px, 9vw, 124px); }
  .fold .h1--long   { max-width: 34ch; font-size: clamp(1.6rem, 2.6vw, 2.2rem); }
  .fold .pre-headline { max-width: 42ch; }
  .fold .promise__strip { max-width: 56ch; }
  .fold .player { max-height: min(30vh, 232px); }
}
