/* start.css — working notes page (/start). Deliberately plain: this is a
 * scratchpad for the belief work, not a designed surface. */

*{margin:0;padding:0;box-sizing:border-box}

body{
  background:#111315;
  color:#e6e7e9;
  font:19px/1.65 -apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;
}

/* 63ch measured out at ~72 characters per line in this font, inside the
 * 50-75 band. It is NOT 70ch: ch is the width of a zero, which is narrower
 * than this font's average character, so 70ch measured 81 CPL and broke the
 * WCAG ceiling of 80. Measure the rendered line, do not trust the unit.
 * (superseded note) 70ch keeps the measure inside the 50-75 characters-per-line band the
 * readability research points at, and it re-derives itself if the body
 * size ever changes again. WCAG's ceiling is 80. */
.nt{max-width:63ch;margin:0 auto;padding:56px 24px 96px}

.nt h1{
  font-size:18px;
  font-weight:600;
  letter-spacing:.10em;
  text-transform:uppercase;
  color:#8e9095;
  margin-bottom:32px;
  text-align:center;
}

.nt h2{
  font-size:26px;
  line-height:1.3;
  font-weight:600;
  color:#fff;
  margin:0 0 14px;
  text-align:center;
}

.nt h3{
  font-size:15.5px;
  font-weight:600;
  letter-spacing:.08em;
  text-transform:uppercase;
  color:#8e9095;
  margin:30px 0 12px;
}

.nt-note{color:#b7b9bd;margin-bottom:14px}

.nt b{color:#fff;font-weight:600}

.nt ul{list-style:none;margin:0 0 14px}

.nt li{
  color:#e6e7e9;
  padding-left:20px;
  position:relative;
  margin-bottom:8px;
}

.nt li::before{
  content:"";
  position:absolute;
  left:2px;
  top:.68em;
  width:5px;
  height:5px;
  border-radius:50%;
  background:#6f7276;
}

@media (max-width:480px){
  .nt{padding:32px 18px 72px}
}

/* ── Diagrams. Plain CSS boxes + arrows; no library. Stacks to a vertical
 *    chain under 560px (arrows rotate) so it stays legible on a phone. */
.dg{
  border:1px solid #2b2e31;
  border-radius:10px;
  padding:18px 16px 14px;
  margin:0 0 18px;
  background:#16181a;
}

.dg-row{display:flex;align-items:stretch;gap:10px;flex-wrap:nowrap}

.dg-box{
  flex:1 1 0;
  min-width:0;
  border:1px solid #33373b;
  border-radius:8px;
  padding:12px 12px;
  background:#1d2023;
}

.dg-box b{display:block;color:#fff;font-size:18px;font-weight:600;line-height:1.3}
.dg-box i{display:block;font-style:normal;color:#8e9095;font-size:14px;margin-top:4px}

.dg-box--test{border-color:#4a3c2a;background:#221c14}
.dg-box--test b{color:#f0c07a}

.dg-box--live{border-color:#274a33;background:#14211a}
.dg-box--live b{color:#7ad69b}

.dg-arrow{
  flex:0 0 auto;
  align-self:center;
  color:#6f7276;
  font-size:21.5px;
  line-height:1;
}

.dg-h{
  font-size:21px;color:#fff;font-weight:700;margin:0 0 18px;
  text-align:center;line-height:1.3;
}
.dg-cap{
  margin:14px 0 0;
  color:#b7b9bd;
  font-size:16.5px;
  line-height:1.5;
}

.dg-cap b{color:#fff;font-weight:600}

@media (max-width:560px){
  .dg-row{flex-direction:column;gap:8px}
  .dg-arrow{transform:rotate(90deg);align-self:flex-start;margin-left:14px}
}

/* Return path for the cyclical diagram — a real U drawn with three borders and
 * a bottom radius, so the loop reads as a circuit rather than a stray arrow.
 * Inset by 56px each side so its uprights land under the middle of each box.
 * The arrowhead is a CSS triangle pointing UP into the left box. */
.dg-return{
  position:relative;
  height:26px;
  margin:0 56px;
  border-left:1px dashed #5a4a32;
  border-right:1px dashed #5a4a32;
  border-bottom:1px dashed #5a4a32;
  border-radius:0 0 14px 14px;
}

.dg-return__head{
  position:absolute;
  left:-5px;
  top:-1px;
  width:0;
  height:0;
  border-left:5px solid transparent;
  border-right:5px solid transparent;
  border-bottom:7px solid #f0c07a;
}

.dg-return__label{
  margin:8px 0 0;
  text-align:center;
  color:#9a9da1;
  font-size:15.5px;
  line-height:1.4;
}

@media (max-width:560px){
  /* Boxes stack vertically, so a horizontal U maps to nothing — its arrowhead
   * lands under the SECOND box pointing up at it, which reads as that box
   * looping to itself. Drop the drawn path and state the cycle instead. */
  .dg-return{display:none}
  .dg-return__label{
    text-align:left;
    margin:10px 0 0;
    padding:8px 12px;
    border:1px dashed #5a4a32;
    border-radius:8px;
    color:#9a9da1;
  }
  .dg-return__label::before{
    content:"\21BA";
    color:#f0c07a;
    margin-right:8px;
    font-size:18px;
  }
}

.nt h4{
  font-size:19px;
  font-weight:600;
  color:#fff;
  margin:24px 0 10px;
}

/* upvote count */
.nt s{
  text-decoration:none;
  color:#f0c07a;
  font-size:14px;
  margin-left:4px;
  white-space:nowrap;
}
.nt s::before{content:"\2191"}

/* Stacked "what would have to be stored" list — deliberately reads as a pile
 * that keeps growing, which is the point. */
.dg-stack{display:flex;flex-direction:column;gap:6px}

.dg-lay{
  border:1px solid #33373b;
  border-left:3px solid #4b5157;
  border-radius:6px;
  padding:9px 12px;
  background:#1d2023;
}
.dg-lay b{display:block;color:#fff;font-size:16.5px;font-weight:600}
.dg-lay i{display:block;font-style:normal;color:#8e9095;font-size:14px;margin-top:2px}

.dg-lay--x{border-left-color:#8a5a2a;background:#221c14}
.dg-lay--x b{color:#f0c07a}

/* Combinatorics counter — joints light up one at a time and the number runs
 * away. The point is the exponent, so the number is the loudest thing here. */
.ct{text-align:center}

.ct-joints{
  display:flex;flex-wrap:wrap;gap:5px;justify-content:center;margin-bottom:18px;
}
.ct-joints span{
  font-size:13px;padding:3px 7px;border-radius:5px;
  border:1px solid #2f3337;color:#55585c;background:#191b1d;
  transition:color .18s,border-color .18s,background .18s;
}
.ct-joints span.on{color:#fff;border-color:#4b8ef0;background:#1b2740}

.ct-num{
  font-size:clamp(30px,8vw,52px);line-height:1.05;font-weight:700;
  color:#f0c07a;font-variant-numeric:tabular-nums;letter-spacing:-.02em;
  word-break:break-all;
}
.ct-num sup{font-size:.5em;vertical-align:super}

.ct-sub{color:#9a9da1;font-size:15.5px;margin-top:8px;min-height:1.4em}

.ct-compare{
  margin:14px 0 0;color:#fff;font-size:18px;line-height:1.5;min-height:3em;
}

.ct-replay{
  margin-top:14px;background:none;border:1px solid #33373b;border-radius:6px;
  color:#8e9095;font-size:14px;padding:5px 12px;cursor:pointer;
}
.ct-replay:hover{color:#fff;border-color:#55585c}

@media (prefers-reduced-motion:reduce){
  .ct-joints span{transition:none}
}

/* multiplier */
.dg-row--mult{align-items:center}
.dg-times{flex:0 0 auto;color:#f0c07a;font-size:26px;line-height:1;align-self:center}

/* retrieval problem */
.rt-live{
  border:1px solid #33373b;border-radius:8px;padding:10px 12px;
  background:#1d2023;color:#fff;font-size:16.5px;font-weight:600;text-align:center;
}
.rt-down{text-align:center;color:#6f7276;font-size:19px;line-height:1.6}
.rt-files{display:flex;flex-wrap:wrap;gap:6px;justify-content:center}
.rt-files span{
  font-size:13px;padding:4px 8px;border-radius:5px;
  border:1px dashed #3a3e42;color:#6f7276;background:#191b1d;
  position:relative;
}
.rt-files span::after{
  content:"\2717";position:absolute;right:-2px;top:-7px;color:#c56a6a;font-size:13px;
}
.rt-none{text-align:center;color:#c56a6a;font-size:14px;margin:8px 0 0}
.rt-matcher{
  border:1px solid #274a33;border-radius:8px;padding:10px 12px;background:#14211a;
}
.rt-matcher b{display:block;color:#7ad69b;font-size:16.5px;font-weight:600}
.rt-matcher i{display:block;font-style:normal;color:#8e9095;font-size:14px;margin-top:3px}

/* section heading inside a diagram block */
.pl-h{
  font-size:13px;letter-spacing:.09em;text-transform:uppercase;
  color:#8e9095;margin:0 0 8px;font-weight:600;
}
.pl-h--ours{color:#7ad69b;margin-top:18px}

/* Sensor: every channel arriving at once, converging on one reaction.
 * Deliberately NOT a chain — the arrows fire simultaneously, because the claim
 * is that nothing queues and nothing is retrieved. */
.sns{display:flex;align-items:center;gap:10px;flex-wrap:nowrap}
.sns-col{flex:1 1 auto;min-width:0}
.sns-lab{
  font-size:12px;letter-spacing:.09em;text-transform:uppercase;
  color:#7e8a83;margin:0 0 6px;font-weight:600;
}
.sns-col .sns-in + .sns-lab{margin-top:12px}

.sns-in{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:6px;flex:1 1 auto;min-width:0}
.sns-in li{
  border:1px solid #2b2e31;border-radius:7px;padding:7px 10px;background:#1a1c1e;
}
.sns-in li.on{border-color:#274a33;background:#14211a}
.sns-in li.off{opacity:.45}
.sns-in li.off i{display:none}
.sns-in b{display:block;color:#b7b9bd;font-size:15.5px;font-weight:600}
.sns-in li.on b{color:#9fd8b4}
.sns-in i{display:block;font-style:normal;color:#7e8a83;font-size:13px;margin-top:2px}

.sns-arrows{
  flex:0 0 26px;display:flex;flex-direction:column;justify-content:space-around;
  align-self:stretch;
}
.sns-arrows span{
  display:block;height:1px;background:#3d6b4f;position:relative;
  animation:snsPulse 1.6s ease-in-out infinite;
}
.sns-arrows span::after{
  content:"";position:absolute;right:-1px;top:-3px;
  border-left:5px solid #7ad69b;border-top:3.5px solid transparent;border-bottom:3.5px solid transparent;
}

.sns-out{
  flex:0 0 auto;border:1px solid #7ad69b;border-radius:9px;
  padding:14px 16px;background:#14211a;text-align:center;
}
.sns-out b{display:block;color:#7ad69b;font-size:20px;font-weight:700}
.sns-out i{display:block;font-style:normal;color:#7e8a83;font-size:13px;margin-top:3px}

/* every channel pulses together — simultaneity is the whole point */
@keyframes snsPulse{0%,100%{opacity:.45}50%{opacity:1}}

@media (prefers-reduced-motion:reduce){
  .sns-arrows span{animation:none;opacity:1}
}

@media (max-width:560px){
  .sns{flex-wrap:wrap}
  .sns-arrows{flex-direction:row;align-self:auto;width:100%;flex:1 1 100%;height:18px}
  .sns-arrows span{width:100%;height:1px;align-self:center}
  .sns-arrows span::after{right:auto;left:50%;top:-3px;
    border-left:3.5px solid transparent;border-right:3.5px solid transparent;
    border-top:5px solid #7ad69b;border-bottom:none}
  .sns-out{flex:1 1 100%}
}

/* Interactive: the reader IS the opponent. Move the pointer and watch whether
 * the sensor is coupled to it. In drill mode it runs a rehearsed path and
 * ignores the pointer entirely — that decoupling is the whole argument, and it
 * has to be felt rather than read. */
.lab-modes button{
  flex:1 1 0;padding:8px 10px;border-radius:7px;cursor:pointer;
  border:1px solid #33373b;background:#1a1c1e;color:#8e9095;
  font-size:15.5px;font-weight:600;
}
.lab-modes button.on{border-color:#7ad69b;background:#14211a;color:#9fd8b4}
.lab-modes button:focus-visible{outline:2px solid #7ad69b;outline-offset:2px}

.lab-stage.is-drill .lab-you{border-color:#c56a6a;background:rgba(197,106,106,.08)}

.lab-read b{color:#fff}

/* Two dials. The reader finds out by dragging that only one of them keeps the
 * information alive — turning resistance down kills it, turning the problem
 * down does not. */
.dl-row label{flex:0 0 150px;font-size:15.5px;color:#e6e7e9}
.dl-row input[type=range]{flex:1 1 auto;min-width:0;accent-color:#7ad69b}
.dl-row output{flex:0 0 96px;text-align:right;font-size:14px;color:#9a9da1}

.dl-bar span{display:block;font-size:14px;color:#8e9095;margin-bottom:4px}
.dl-bar i{
  display:block;height:10px;border-radius:5px;background:#1f2225;overflow:hidden;
}
.dl-bar i b{
  display:block;height:100%;width:0;border-radius:5px;background:#7ad69b;
  transition:width .12s linear,background .12s linear;
}

.dl-verdict b{color:#fff}
.dl-verdict.good{border-color:#274a33;background:#14211a;color:#9fd8b4}
.dl-verdict.bad{border-color:#4a2a2e;background:#221416;color:#e09a9a}

@media (max-width:560px){
  .dl-row{flex-wrap:wrap}
  .dl-row label{flex:1 1 100%}
  .dl-row output{flex:0 0 auto}
}

/* The layered-weeks examples. Each week card shows what they START holding and
 * the single thing added — the point being that every row is a live task. */
.wk-tabs{display:flex;gap:6px;margin-bottom:14px;flex-wrap:wrap}
.wk-tabs button{
  padding:8px 12px;border-radius:7px;cursor:pointer;
  border:1px solid #33373b;background:#1a1c1e;color:#8e9095;
  font-size:15.5px;font-weight:600;
}
.wk-tabs button.on{border-color:#7ad69b;background:#14211a;color:#9fd8b4}
.wk-tabs button:focus-visible{outline:2px solid #7ad69b;outline-offset:2px}

.wk-steps{display:flex;flex-direction:column;gap:8px}

/* Every card is the same labelled spec: starting position, win condition,
   task focus. Naming the parts with level one's own vocabulary is what makes
   the card readable; before, five kinds of content ran together with only one
   label between them. */
.wk-card{
  border:1px solid #2b2e31;border-left:3px solid #7ad69b;border-radius:8px;
  padding:13px 15px 15px;background:#1a1c1e;
}
/* Week number and "what changed this week" on one line, so the answer to
   "what is new here" is the first thing read, not a chip buried at the foot. */
.wk-head{
  display:flex;align-items:baseline;justify-content:space-between;gap:10px;
  flex-wrap:wrap;margin-bottom:12px;
}
.wk-card .wk-w{
  font-size:12px;letter-spacing:.09em;text-transform:uppercase;
  color:#7ad69b;font-weight:700;
}
.wk-card .wk-add{
  font-size:12.5px;padding:3px 9px;border-radius:999px;
  background:#14211a;border:1px solid #274a33;color:#9fd8b4;white-space:nowrap;
}

.wk-f{margin-top:12px}
.wk-f:first-of-type{margin-top:0}
.wk-f-lab{
  margin:0 0 4px;font-size:11.5px;letter-spacing:.08em;text-transform:uppercase;
  color:#7e8489;font-weight:700;
}
.wk-card .wk-start{font-size:15px;color:#b7b9bd;line-height:1.45;margin:0}
.wk-card .wk-goal{font-size:16.5px;color:#fff;line-height:1.45;margin:0}

.wk-note{margin:14px 0 0;color:#b7b9bd;font-size:15.5px;line-height:1.5}
.wk-note b{color:#fff}

/* Sub-goals inside a week card — the things they're holding at the same time. */
.wk-subs{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:4px}
.wk-subs li{
  font-size:14px;color:#9fd8b4;padding-left:16px;position:relative;line-height:1.4;
}
.wk-subs li::before{
  content:"";position:absolute;left:3px;top:.55em;
  width:4px;height:4px;border-radius:50%;background:#7ad69b;
}



/* Position difficulty — the second dial, separate from the weekly layers. */
/* Two dials stacked in one block need their own labels, or the reader reads six
   boxes as one six-step progression. */
.ax-lab{margin:0 0 9px;color:#8d9297;font-size:13px;font-weight:700;letter-spacing:.06em;text-transform:uppercase}
.ax-lab--2{margin-top:20px}
.ax{display:flex;align-items:stretch;gap:10px;flex-wrap:nowrap}
.ax-step{
  flex:1 1 0;min-width:0;border:1px solid #274a33;border-radius:8px;
  padding:11px 12px;background:#14211a;
}
.ax-step b{display:block;color:#9fd8b4;font-size:15.5px;font-weight:600;line-height:1.35}
.ax-step i{display:block;font-style:normal;color:#7e8a83;font-size:13px;margin-top:4px}
.ax-step--hard{border-color:#5a4a32;background:#221c14}
.ax-step--hard b{color:#f0c07a}
.ax-arrow{flex:0 0 auto;align-self:center;color:#6f7276;font-size:21.5px;line-height:1}

@media (max-width:560px){
  .ax{flex-direction:column;gap:8px}
  .ax-arrow{transform:rotate(90deg);align-self:flex-start;margin-left:14px}
}

/* The full set of win conditions available that week. Earlier ones stay —
 * greyed rather than removed — because which one is on offer depends on the
 * opponent, not on the syllabus. */
.wk-wins{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:5px}
.wk-wins li{
  font-size:15.5px;line-height:1.4;color:#8e9095;padding-left:16px;position:relative;
}
.wk-wins li::before{
  content:"";position:absolute;left:2px;top:.52em;
  width:5px;height:5px;border-radius:50%;background:#4b5157;
}
.wk-wins li.new{color:#fff}
.wk-wins li.new::before{background:#7ad69b}
.wk-wins li em{
  font-style:normal;font-size:12px;letter-spacing:.06em;text-transform:uppercase;
  color:#7ad69b;margin-left:7px;
}

/* Two-column contrast. Re-added: the earlier user of these classes was removed
 * and took the rules with it. Must stay readable side by side above 560px —
 * the argument IS the comparison. */
.tn{display:flex;gap:12px;align-items:stretch}
.tn-side{flex:1 1 0;min-width:0}

/* Neutral for BOTH columns. Red was the base colour here, so it was not only
   the green override that argued the case — removing that override made both
   labels red, which is still a verdict. Neither method gets a colour. */
.tn-lab{
  font-size:13px;letter-spacing:.09em;text-transform:uppercase;
  color:#9a9da2;margin:0 0 8px;font-weight:600;
}

.tn-ch{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:5px}
.tn-ch li{
  border:1px solid #2b2e31;border-left:3px solid #3a3e42;border-radius:6px;
  padding:8px 10px;background:#1a1c1e;
}
.tn-ch b{display:block;font-size:15.5px;font-weight:600;color:#b7b9bd}
.tn-ch i{display:block;font-style:normal;font-size:13px;color:#7e8a83;margin-top:3px}

/* Both methods get IDENTICAL treatment here. This grid used to colour
   technique-first red at opacity .62 and CLA green on a tinted card, which
   argued the case before the case had been made — a coach whose own method
   is being sneered at in level one does not read level two. The steelman is
   level 2's job and the argument is levels 3 onward; level one only defines.
   (The .62 opacity was also the documented contrast trap: opacity composites
   the text against the background before contrast is measured.) */

@media (max-width:560px){
  .tn{flex-direction:column;gap:18px}
}

/* Complaints accordion. Answers are hidden so the list reads as a list first. */
.cx{display:flex;flex-direction:column;gap:6px}

.cx-item{border:1px solid #2b2e31;border-radius:8px;background:#1a1c1e;overflow:hidden}

.cx-q{
  display:flex;width:100%;gap:12px;align-items:flex-start;text-align:left;
  background:none;border:0;padding:12px 14px;cursor:pointer;color:#e6e7e9;
  font-size:16.5px;line-height:1.45;font-family:inherit;
}
.cx-q span{flex:1 1 auto}
.cx-q i{flex:0 0 auto;font-style:normal;color:#7ad69b;font-size:19px;line-height:1.3}
.cx-q:hover{color:#fff}
.cx-q:focus-visible{outline:2px solid #7ad69b;outline-offset:-2px}

.cx-a{
  padding:0 14px 14px;color:#b7b9bd;font-size:15.5px;line-height:1.6;
  border-top:1px solid #2b2e31;margin-top:2px;padding-top:12px;
}
.cx-a b{color:#fff}

.cx-fig{margin:12px 0 0}
.cx-fig img{width:100%;max-width:420px;border-radius:8px;display:block}
.cx-fig figcaption{margin-top:6px;font-size:13px;color:#7e8a83}

/* an open question, deliberately visible rather than quietly omitted */
.cx-todo{
  margin:12px 0 0;padding:8px 10px;border:1px dashed #5a4a32;border-radius:6px;
  color:#f0c07a;font-size:14px;line-height:1.45;
}

/* ── Cover ("level 0") ───────────────────────────────────────────────────
 * The screen before level 1. It is the only part of this page that is sold
 * rather than argued, so it is the only part allowed to be laid out.
 *
 * While it is up, body.is-cover removes the level chrome. Hiding the jump rail
 * matters: it is position:fixed on a laptop, so leaving it up would float a
 * "Levels" stepper over a cover that has no current level. */
/* The booking widget is a LEVEL 7+ surface. It lives outside the levels
   because the level 7 and 8 CTAs have to reach it, which also means a level
   switch cannot hide it — this rule is what does. Default-hidden: start.js
   adds .is-booking, so a browser with JS broken shows the argument and no
   half-wired form. */
body:not(.is-booking) #book{display:none}

/* Level 0 keeps the level chrome — the progress bar reads 0 of 9, the rail
   lists it as its own row, and Back/Next step through it like any other level.
   The ONE thing it drops is the offer: the booking calendar lives outside the
   levels (level 7 and 8 have to reach it) so nothing else takes it down, and a
   screen that opens with "you do not have to agree with any of it" must not
   put a calendar under that sentence. */
body.is-cover #book{display:none}

.cv-kick{
  font-size:13px;font-weight:600;letter-spacing:.12em;text-transform:uppercase;
  color:#7ad69b;text-align:center;margin:0 0 12px;
}

/* Bigger than a level h2 — this is the one line that has to be read. clamp so
 * it does not have to be re-tuned per breakpoint. */
.cv h2{font-size:clamp(28px,6.4vw,38px);line-height:1.18;margin-bottom:16px}

.cv-deck{
  color:#b7b9bd;font-size:19px;line-height:1.55;text-align:center;
  margin:0 auto 32px;max-width:36em;
}

.cv-proof{
  background:#1a1c1e;border:1px solid #26292c;border-radius:12px;
  padding:22px 20px 18px;text-align:center;
}
.cv-proof-h{
  font-size:13px;font-weight:600;letter-spacing:.11em;text-transform:uppercase;
  color:#8e9095;margin:0 0 6px;
}
.cv-proof-n{
  font-size:46px;line-height:1;font-weight:700;color:#7ad69b;margin:0 0 8px;
  font-variant-numeric:tabular-nums;
}
.cv-proof-s{color:#e6e7e9;font-size:17px;line-height:1.45;margin:0 0 18px}

/* Region counts. A LIST, not a table: it is five labelled figures, and a table
 * would promise rows and columns that do not exist. The .nt li dot and its
 * indent are both cancelled — a bullet in front of a centred figure reads as
 * a rendering fault. */
.cv-reg{display:flex;flex-wrap:wrap;gap:8px;margin:0 0 14px;justify-content:center}
.cv-reg li{
  flex:1 1 92px;min-width:92px;max-width:150px;margin:0;padding:10px 6px;
  background:#111315;border:1px solid #26292c;border-radius:9px;
}
.cv-reg li::before{display:none}
.cv-reg b{display:block;font-size:20px;line-height:1.2;color:#fff}
.cv-reg span{display:block;font-size:13px;line-height:1.3;color:#b7b9bd;margin-top:2px}

/* Provenance sits ON the claim, not in a footnote nobody scrolls to. */
.cv-src{font-size:13px;line-height:1.45;color:#8e9095;margin:0}

.cv-who{display:flex;gap:14px;align-items:center;margin:22px 0 4px}
.cv-who img{
  width:76px;height:76px;flex:0 0 76px;border-radius:50%;object-fit:cover;
  background:#1a1c1e;border:2px solid #3f8f60;
}
/* Without min-width:0 a long sentence pushes the portrait off the row instead
 * of wrapping — the same trap as .off-head-t. */
.cv-who p{min-width:0;color:#b7b9bd;font-size:16px;line-height:1.5;margin:0}

.cv-list li{margin-bottom:10px;line-height:1.55}

.cv-open{
  margin:26px 0 24px;padding:14px 16px;border-left:3px solid #7ad69b;
  background:#16191b;border-radius:0 8px 8px 0;
  color:#b7b9bd;font-size:16.5px;line-height:1.55;
}


@media (max-width:560px){
  .cv-deck{font-size:17.5px;text-align:left}
  .cv-proof{padding:18px 14px 14px}
  .cv-proof-n{font-size:38px}
  .cv-who{gap:12px}
  .cv-who img{width:60px;height:60px;flex:0 0 60px}
}

/* book.css is written against the design-system tokens, whose accent is the
   product blue. This page is green, and a blue island inside it reads as a
   widget someone pasted in. Custom properties inherit, so re-declaring them on
   #book re-themes the whole widget without touching book.css (shared with five
   other pages).

   --text-on-accent MUST go dark with the fill. White on #7ad69b measures
   1.76:1 and fails WCAG 1.4.3 outright; #111315 on it measures 10.57:1. Never
   re-theme the fill without re-theming the label. */
#book{
  --accent:#7ad69b;
  --accent-hover:#9fd8b4;
  --accent-text:#9fd8b4;
  --accent-light:rgba(122,214,155,.15);
  --accent-rgb:122,214,155;
  --text-on-accent:#111315;
}

/* The SMS consent block is legal boilerplate, not copy anyone reads by
   choice — it sits under the button at the size the carriers require it to be
   legible at, and no larger. Scoped to #book because book.css is shared with
   five other pages whose layouts are built around its own sizing. */
#book .book-consent__text{font-size:11px;line-height:1.4}
#book .book-consent__text a{text-decoration:underline}

/* ── Levels ─────────────────────────────────────────────────────────────── */
.lv-head{margin-bottom:28px}
.lv-head h1{margin-bottom:14px}

.lv-bar{
  height:3px;border-radius:2px;background:#26292c;position:relative;overflow:hidden;
}
.lv-bar::after{
  content:"";position:absolute;inset:0 auto 0 0;width:var(--p,10%);
  background:#7ad69b;border-radius:2px;transition:width .25s ease;
}

.lv-num{
  font-size:12px;letter-spacing:.11em;text-transform:uppercase;
  color:#6f7276;margin:0 0 8px;font-weight:600;text-align:center;
}
.lv h2{margin-bottom:18px}

.lv-nav{display:flex;gap:10px;margin-top:36px;padding-top:20px;border-top:1px solid #26292c}

.lv-btn{
  flex:1 1 auto;padding:13px 18px;border-radius:9px;cursor:pointer;
  border:1px solid #7ad69b;background:#14211a;color:#9fd8b4;
  font-size:18px;font-weight:600;font-family:inherit;
}
.lv-btn:hover:not(:disabled){background:#1a2c21;color:#fff}
.lv-btn:focus-visible{outline:2px solid #7ad69b;outline-offset:2px}
.lv-btn:disabled{opacity:.35;cursor:default}
.lv-btn--ghost{flex:0 0 auto;border-color:#33373b;background:#1a1c1e;color:#8e9095}
.lv-btn--ghost:hover:not(:disabled){color:#fff;border-color:#55585c;background:#1a1c1e}

/* ── Question ───────────────────────────────────────────────────────────── */
.qz{margin-top:32px;padding-top:22px;border-top:1px solid #26292c}

.qz-q{margin:0 0 14px;font-size:20px;line-height:1.4;font-weight:600;color:#fff}

.qz-opts{display:flex;flex-direction:column;gap:8px}
.qz-opt{
  text-align:left;padding:12px 14px;border-radius:8px;cursor:pointer;
  border:1px solid #33373b;background:#1a1c1e;color:#e6e7e9;
  font-size:16.5px;line-height:1.45;font-family:inherit;
}
.qz-opt:hover:not(:disabled){border-color:#55585c;color:#fff}
.qz-opt:focus-visible{outline:2px solid #7ad69b;outline-offset:2px}
/* Kept for the pre-solve states only. NOTHING is disabled after a right
   answer — see applyPick in start.js for why. */
.qz-opt:disabled{cursor:default;opacity:.5}

.qz-more{
  display:none;margin:10px 0 0;font-size:14px;line-height:1.5;color:#8e9095;
}
.qz--solved .qz-more{display:block}
.qz-opt.picked{opacity:1;border-color:#55585c;color:#fff}
.qz-opt.picked--ok{border-color:#7ad69b;background:#14211a;color:#9fd8b4}

.qz-r{
  margin-top:14px;padding:12px 14px;border-radius:8px;
  border:1px solid #2b2e31;background:#16181a;
  color:#b7b9bd;font-size:16.5px;line-height:1.6;
}
.qz-r b{color:#fff}

/* Resistance as a switch, not a percentage (2026-09-15). A 0-100 slider asks
   the reader to invent what 40% resistance means. Coaches do not think in
   percentages; they think about whether the partner is letting you do it, and
   if not, how hard he is going. */
.dl-seg button{appearance:none;background:transparent;border:0;cursor:pointer;
  font:inherit;font-size:16px;font-weight:600;color:var(--text-secondary);
  padding:9px 15px;border-right:1px solid var(--border-subtle);white-space:nowrap}
.dl-seg button:last-child{border-right:0}
.dl-seg button.on{background:var(--accent);color:#fff}
.dl-seg button:focus-visible{outline:2px solid var(--accent-hover);outline-offset:-2px}
/* the intensity row only means anything when he is actually resisting */
#dlHardRow[data-off="1"]{opacity:.32;pointer-events:none}
@media (max-width:560px){.dl-lab{min-width:0;flex:1 0 100%}
  .dl-seg{width:100%}.dl-seg button{flex:1}}

/* The belief swap. This is level 5's anchor: the reader has just had the
 * storage model taken off them in levels 3 and 4, and needs to see plainly
 * what replaces it before any of the rest will land. Left panel states their
 * position honestly; right panel is ours. */
.sw{
  display:flex;align-items:stretch;gap:12px;margin:16px 0 18px;
}
.sw-side{
  flex:1 1 0;min-width:0;
  border:1px solid #33373b;border-radius:10px;
  padding:14px 16px;background:#1a1c1e;
}
.sw-side--ours{border-color:#274a33;background:#14211a}

.sw-lab{
  font-size:14px;letter-spacing:.05em;text-transform:uppercase;
  color:#8e9095;margin:0 0 10px;font-weight:700;
  text-align:center;line-height:1.35;
}
.sw-side--ours .sw-lab{color:#7ad69b}

.sw-txt{margin:0;color:#b7b9bd;font-size:16.5px;line-height:1.55}
.sw-side--ours .sw-txt{color:#e6e7e9}
.sw-txt b{color:#fff;font-weight:600}
.sw-side--ours .sw-txt b{color:#9fd8b4}

.sw-arrow{
  flex:0 0 22px;display:flex;align-items:center;justify-content:center;
}
.sw-arrow span{
  display:block;width:100%;height:1px;background:#3d6b4f;position:relative;
}
.sw-arrow span::after{
  content:"";position:absolute;right:-1px;top:-4px;
  border-left:6px solid #7ad69b;
  border-top:4px solid transparent;border-bottom:4px solid transparent;
}

@media (max-width:560px){
  .sw{flex-direction:column;gap:8px}
  .sw-arrow{flex:0 0 18px;height:18px}
  .sw-arrow span{width:1px;height:100%}
  .sw-arrow span::after{
    right:auto;top:auto;left:-4px;bottom:-1px;
    border-left:4px solid transparent;border-right:4px solid transparent;
    border-top:6px solid #7ad69b;border-bottom:none;
  }
}

/* Attention and intention, the two things every movement comes out of.
 * One row each, drilling on the left and a game on the right, so the reader
 * sees that both get set either way. The argument is never that drilling does
 * nothing, it is that it sets both of them pointing inward. */
.ai{display:flex;flex-direction:column;gap:12px;margin:0 0 16px}

.ai-name{
  margin:0 0 7px;font-size:15.5px;font-weight:600;color:#e6e7e9;
}
.ai-name span{
  font-weight:400;color:#8e9095;font-size:14px;margin-left:7px;
}

.ai-pair{display:flex;gap:10px}
.ai-cell{
  flex:1 1 0;min-width:0;
  border:1px solid #2b2e31;border-radius:8px;background:#1a1c1e;
  padding:10px 12px;
}
.ai-cell--ours{border-color:#274a33;background:#14211a}
.ai-cell b{
  display:block;font-size:12px;letter-spacing:.09em;text-transform:uppercase;
  color:#8e9095;font-weight:600;margin-bottom:5px;
}
.ai-cell--ours b{color:#7ad69b}
.ai-cell i{
  display:block;font-style:normal;color:#b7b9bd;font-size:15.5px;line-height:1.5;
}
.ai-cell--ours i{color:#e6e7e9}

@media (max-width:560px){
  .ai-pair{flex-direction:column;gap:6px}
}
/* The three things a movement comes out of. A numbered list rather than prose
 * because the reader has to be able to hold all three at once; the rest of the
 * page is built on separating them (intention is set, attention and capacity
 * are grown). */
.thr{
  list-style:none;counter-reset:thr;margin:0 0 16px;padding:0;
  display:flex;flex-direction:column;gap:8px;
}
.thr li{
  position:relative;counter-increment:thr;
  border:1px solid #2b2e31;border-radius:8px;background:#1a1c1e;
  padding:11px 13px 11px 44px;
}
.thr li::before{
  content:counter(thr);position:absolute;left:13px;top:11px;
  width:20px;height:20px;border-radius:50%;
  background:#14211a;border:1px solid #274a33;color:#7ad69b;
  font-size:13px;font-weight:700;line-height:19px;text-align:center;
}
.thr b{display:block;color:#e6e7e9;font-size:16.5px;font-weight:600}
.thr i{display:block;font-style:normal;color:#8e9095;font-size:15.5px;line-height:1.5;margin-top:2px}
/* a bold inside the description must stay inline; .thr b is display:block for
   the item titles, which would otherwise break the line mid-sentence */
.thr i b{display:inline;color:#e6e7e9}

/* Drilling vs live, scored on the same three things level 5 introduced. A
 * scoreboard rather than a list, because the argument is comparative: nobody
 * is claiming drilling scores zero, only that it scores lower on each one. */
.vs{display:flex;flex-direction:column;gap:6px;margin:0 0 16px}

/* The cells carry their own border and padding now, so the header has to be
 * inset by the same amount or the labels sit left of the text they label. */
.vs-head{
  display:grid;grid-template-columns:.75fr 1.1fr 1.1fr;gap:8px;padding:0;
}
.vs-head span{padding-left:14px}
.vs-head span:first-child{padding-left:2px}
.vs-head span{
  font-size:12px;letter-spacing:.09em;text-transform:uppercase;
  color:#8e9095;font-weight:600;
}
.vs-head span:last-child{color:#7ad69b}

/* Cells are the boxes, not the row, so the winning side of each comparison can
 * be tinted. The table is a scoreboard and the reader should be able to read
 * the score without reading the cells, including the row drilling wins. */
.vs-row{
  display:grid;grid-template-columns:.75fr 1.1fr 1.1fr;gap:8px;align-items:stretch;
}
.vs-row > b{
  color:#e6e7e9;font-size:16px;font-weight:600;align-self:center;padding-left:2px;
}
.vs-row > i{
  font-style:normal;color:#8e9095;font-size:15.5px;line-height:1.45;
  border:1px solid #2b2e31;border-radius:8px;background:#191b1d;padding:11px 13px;
}
.vs-row > i.vs-win{border-color:#2f5a3e;background:#16241b;color:#dfe3e0}
.vs-row i b{display:inline;color:#9fd8b4;font-weight:600}

@media (max-width:620px){
  .vs-head{display:none}
  .vs-row{grid-template-columns:1fr;gap:5px}
  .vs-row > i::before{
    content:"drilling: ";color:#8e9095;
    font-size:12px;letter-spacing:.09em;text-transform:uppercase;
  }
  .vs-row > i:last-child::before{content:"live: ";color:#7ad69b}
}

/* Bookends. The same question opens level 1 and is answered at the end of the
 * last one, so the reader can measure themselves against it. The ruled-out
 * answers are the ones every coach reaches for first; striking them is what
 * makes the question feel like a real one rather than rhetorical. */
.chal{
  border:1px solid #3a4147;border-radius:10px;background:#1d2023;
  padding:16px 18px;margin:0 0 18px;
}
.chal--done{border-color:#274a33;background:#14211a;margin:18px 0 0}

.chal-q{margin:0;color:#fff;font-size:19px;line-height:1.5;font-weight:600}

.chal-lab{
  font-size:12px;letter-spacing:.09em;text-transform:uppercase;
  color:#8e9095;margin:16px 0 8px;font-weight:600;
}
.chal-lab--ours{color:#7ad69b;margin-top:0;margin-bottom:8px}

.chal-no{
  list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;gap:6px;
}
.chal-no li{
  border:1px solid #2b2e31;border-radius:999px;padding:5px 11px;
  background:#16181a;color:#6f7276;font-size:15px;
  text-decoration:line-through;text-decoration-color:#55585c;
}

.chal-note{margin:14px 0 0;color:#b7b9bd;font-size:16px;line-height:1.6}

/* ── saved place ──────────────────────────────────────────────────────────
   Offered, never applied. Hidden in markup and revealed by start.js only when
   there is somewhere to go back to. */
/* Hex, not var(--token): start.html loads ONLY start.css, which has no :root
   block, so every design-system token on this page resolves to nothing. */
.lv-resume { margin: 14px 0 0; padding: 14px 16px; border-radius: 10px;
  background: #16181a; border: 1px solid #2b2e31; }
.lv-resume p { margin: 0 0 12px; font-size: 15px; line-height: 1.5;
  color: #e6e7e9; }
.lv-resume__acts { display: flex; flex-wrap: wrap; gap: 10px; }
.lv-resume .lv-btn { margin: 0; }
@media (max-width: 420px) { .lv-resume .lv-btn { flex: 1 1 100%; } }

/* The one claim on the page the reader can falsify in four seconds, so it gets
   lifted out of the prose and made the payoff of its level. */
.key{
  border:1px solid #274a33;border-left-width:3px;border-radius:10px;
  background:#14211a;padding:16px 18px;margin:18px 0 0;
}
.key-q{margin:0;color:#fff;font-size:20px;line-height:1.45;font-weight:700}
.key-n{margin:10px 0 0;color:#b7b9bd;font-size:16.5px;line-height:1.6}
.key-n b{color:#9fd8b4;font-weight:600}
/* A stacked intention: the black belt is not chasing one goal, he is chasing a
   chain of them. Rendering it as a chain rather than a sentence is the point. */
.ch{display:block;position:relative;padding-left:14px}
.ch + .ch{margin-top:3px}
.ch::before{
  content:"";position:absolute;left:2px;top:.55em;
  width:5px;height:5px;border-right:1.5px solid #4e7a5f;border-bottom:1.5px solid #4e7a5f;
  transform:rotate(-45deg);
}
.ch:first-child::before{transform:rotate(-45deg);opacity:.45}
/* Names the position a comparison grid is about, so the reader knows which
   situation the two columns are describing rather than inferring it. */
.vs-title{
  margin:26px 0 14px;color:#e6e7e9;font-size:23px;font-weight:600;
  text-align:center;line-height:1.3;
}

/* How much another person is continuously shaping what you do. The point
 * travels it on its own, and the two bars trade places as it goes, because the
 * argument is not "instruction is bad" but "what instruction is worth depends
 * on where the task sits". Watching the trade is the whole point, so it is
 * animated rather than a static scale. */
.sp{margin:0}

.sp-row{
  display:grid;grid-template-columns:repeat(4,1fr);position:relative;
  padding-top:6px;margin-bottom:20px;
}
.sp-row::before{
  content:"";position:absolute;left:12.5%;right:12.5%;top:11px;height:2px;
  background:linear-gradient(90deg,#33373b,#2f5a3e);
}
.sp-stop{position:relative;text-align:center;z-index:1}
.sp-stop > span{
  display:block;width:11px;height:11px;border-radius:50%;margin:0 auto 9px;
  background:#1d2023;border:2px solid #4a4f55;transition:all .45s ease;
}
.sp-stop > b{
  display:block;font-size:13px;color:#6f7276;font-weight:600;line-height:1.3;
  transition:color .45s ease;
}
.sp-stop.on > span{
  background:#14211a;border-color:#7ad69b;transform:scale(1.55);
  box-shadow:0 0 0 5px rgba(122,214,155,.13);
}
.sp-stop.on > b{color:#9fd8b4}

.sp-bars{display:flex;flex-direction:column;gap:10px;margin-bottom:14px}
.sp-bar b{
  display:block;font-size:12px;letter-spacing:.05em;text-transform:uppercase;
  color:#8e9095;font-weight:600;margin-bottom:6px;
}
.sp-bar--ours b{color:#7ad69b}
.sp-bar > span{
  display:block;height:10px;border-radius:999px;background:#1d2023;overflow:hidden;
}
.sp-bar > span > i{
  display:block;height:100%;width:0;border-radius:999px;background:#55595e;
  transition:width .6s cubic-bezier(.4,0,.2,1);
}
.sp-bar--ours > span > i{background:#7ad69b}

.sp-say{
  margin:0;color:#b7b9bd;font-size:15px;line-height:1.55;min-height:3.1em;
}

@media (max-width:620px){
  .sp-stop > b{font-size:12px}
  .sp-say{min-height:4.7em}
}
@media (prefers-reduced-motion:reduce){
  .sp-stop > span,.sp-stop > b,.sp-bar > span > i{transition:none}
}
.sp-stop{cursor:pointer}
.sp-stop:hover > b{color:#b7b9bd}

/* Naming the axis. Without it a reader assumes the line means "complexity" and
   then correctly objects that boxing is faster and busier than grappling. It is
   not complexity, it is how continuously another person is shaping what you do. */
.sp-axis{
  display:flex;justify-content:space-between;margin:0 0 4px;
  font-size:12px;letter-spacing:.05em;text-transform:uppercase;font-weight:600;
}
.sp-axis span:first-child{color:#6f7276}
.sp-axis span:last-child{color:#7ad69b}
/* Plain-English gloss next to the term. "Intention" carries a slightly
   different shade here (how much can be handed to you) than in level 5 (the
   goal you are chasing), so the bracket says which one this is. */
.sp-bar b em{
  font-style:normal;text-transform:none;letter-spacing:0;
  font-weight:400;color:#6f7276;
}
.sp-bar--ours b em{color:#6f8f7a}

/* The partner bank. Hidden through the whole count, then it appears all at once
   at the end, because the argument is not that you have a lot of joints. It is
   that there is a second person and every one of your states multiplies by
   every one of his. */
.ct-them{margin:14px 0 4px}
.ct-them-lab{
  margin:0 0 8px;font-size:12px;letter-spacing:.05em;text-transform:uppercase;
  color:#f0c07a;font-weight:700;text-align:center;
}
.ct-joints--them span{border-color:#5a4a32;background:#221c14;color:#8e9095}
.ct-joints--them span.on{border-color:#f0c07a;background:#2a2114;color:#f0c07a}

/* A claim restated VERBATIM from an earlier level, so the reader can see it is
   the same sentence being answered and not a strawman rebuilt for the occasion. */
.thr-claim{
  margin:2px 0 8px;padding-left:12px;border-left:2px solid #3a4147;
  color:#d0d2d6;font-size:16.5px;line-height:1.5;font-style:italic;
}

/* A week card's start photo. Fixed 16/9 via padding-ratio, NOT aspect-ratio:
   these are flex/grid children and Safari 18.x collapses an aspect-ratio flex
   item to zero height (the same trap the classroom cover cards hit). */
.wk-shot{margin:0 0 14px;width:100%}
.wk-shot img,
.wk-shot video{
  display:block;width:100%;height:auto;border-radius:8px;
  border:1px solid #2b2e31;background:#15181a;
}
/* An autoplaying loop is motion the reader did not ask for. Respect the OS
   setting: freeze it on its poster frame rather than hiding the card. */
@media (prefers-reduced-motion:reduce){
  .wk-shot video{ animation:none }
}


/* A forward pointer at the foot of every level except the last. It sits AFTER
   the question, not before it, because the moment that decides whether someone
   carries on is the one right above the Next button, not the one before the
   gate. Deliberately quiet: this is a nudge, not a heading. */
.nxt{
  margin:22px 0 0;padding-top:16px;border-top:1px dashed #2a2e32;
  color:#8e9095;font-size:15px;line-height:1.45;text-align:center;
}
.nxt::before{content:"\2193";display:block;color:#5f6266;font-size:15px;margin-bottom:5px}


/* ── Demo CTA ─────────────────────────────────────────────────────────────
   Three placements (levels 7, 8 and the last one), ONE component. The page is
   an argument, not a sales page, so the two mid-course blocks are a single
   quiet line plus a button; only the final one states the offer in full.

   Hex, not var(--token): start.html loads ONLY start.css, which has no :root
   block, so every design-system token on this page resolves to nothing (same
   note as .lv-resume above). Do not reach for a design-system name here.

   THE BUTTON IS A FILLED ACCENT WITH DARK TEXT. #111315 on #7ad69b measures
   10.66:1; WHITE on #7ad69b measures 1.76:1 and fails WCAG 1.4.3 outright. An
   accent this light can only ever carry dark text — never "fix" the button by
   switching the label to white.

   Every rule is scoped under `.off` so it outranks the page's own `.nt ul` /
   `.nt li` / `.nt h3` defaults, which would otherwise win on specificity and
   silently restyle the list and the heading. */
.off{
  border:1px solid #274a33;border-radius:10px;background:#14211a;
  padding:18px 20px;margin:22px 0;
}
/* Greg's portrait sits BESIDE the heading, not above it, so the offer reads as
   "this is his program" at a glance. `min-width:0` on the text column is
   load-bearing: a flex item's default `min-width:auto` refuses to shrink below
   its own min-content width, so without it a long heading pushes the portrait
   off the row instead of wrapping. */
.off .off-head{display:flex;align-items:center;gap:16px;margin:0 0 12px}
.off .off-pic{
  flex:0 0 auto;width:88px;height:88px;border-radius:50%;
  object-fit:cover;border:2px solid #3f8f60;background:#16181a;
}
.off .off-head-t{min-width:0}
.off .off-head-t .off-lab{margin:0 0 4px}
.off .off-head-t .off-h{margin:0}

.off .off-lab{
  font-size:12px;letter-spacing:.09em;text-transform:uppercase;
  color:#7ad69b;font-weight:600;margin:0 0 8px;
}
.off .off-h{
  font-size:21px;line-height:1.3;font-weight:700;color:#fff;
  letter-spacing:normal;text-transform:none;margin:0 0 10px;
}
.off .off-p{margin:0 0 14px;color:#b7b9bd;font-size:16.5px;line-height:1.6}
.off .off-p b,.off .off-slim-t b,.off .off-list b{color:#fff;font-weight:600}

.off .off-list{list-style:none;margin:0 0 18px;padding:0}
.off .off-list li{
  position:relative;padding-left:22px;margin:0 0 9px;
  color:#b7b9bd;font-size:16px;line-height:1.55;
}
.off .off-list li:last-child{margin-bottom:0}
.off .off-list li::before{
  content:"";position:absolute;left:4px;top:.58em;
  width:6px;height:6px;border-radius:50%;background:#4f9b6e;
}

.off .off-cta{
  /* inline-FLEX, not inline-block, so `min-height` actually applies and the
     label stays centred. 44px is the WCAG 2.5.8 / iOS touch-target floor —
     the slim variant's smaller padding measured 43px without it, which is the
     kind of miss no visual review catches. */
  display:inline-flex;align-items:center;justify-content:center;
  min-height:44px;box-sizing:border-box;
  padding:13px 22px;border-radius:9px;
  border:1px solid #7ad69b;background:#7ad69b;color:#111315;
  font-size:17px;font-weight:700;line-height:1.2;text-decoration:none;
}
.off .off-cta:hover{background:#93e0af;border-color:#93e0af;color:#111315}
.off .off-cta:focus-visible{outline:2px solid #7ad69b;outline-offset:3px}

/* The two mid-course placements. One line, one button, no offer detail — the
   reader is mid-argument and the full pitch belongs at the end.
   `min-width:0` on the text is load-bearing: a flex item's default
   `min-width:auto` refuses to shrink below its own min-content width, so
   without it the line would push the button off the row instead of wrapping. */
.off--slim{
  display:flex;align-items:center;gap:16px;flex-wrap:wrap;
  border-color:#2b3a32;background:#141a17;padding:15px 18px;
}
.off--slim .off-slim-t{
  flex:1 1 260px;min-width:0;margin:0;
  color:#b7b9bd;font-size:16px;line-height:1.5;
}
.off--slim .off-cta{flex:0 0 auto;padding:11px 18px;font-size:16px}

/* Restated opening question on the last level, directly above the answer.
   Deliberately the NEUTRAL `.chal` surface, not the green `--done` one: it is
   the question again, and it should look the way it looked on level 1. */
.chal--recall{margin:0 0 4px}
.chal--recall .chal-q{font-size:18.5px}

@media (max-width:560px){
  .off{padding:16px}
  .off .off-h{font-size:19px}
  .off .off-cta{display:flex;width:100%}
  .off--slim{gap:12px}
  .off--slim .off-cta{width:100%}
}

/* ── Social proof ─────────────────────────────────────────────────────────
   The same two video testimonials /class-planning and /retention carry, ported
   into this page's own stylesheet. It is a PORT, not a reuse: those pages get
   `.rt-tm` from styles/lp.css, which is written entirely in design-system
   tokens, and start.html loads ONLY start.css (no :root block) so every one of
   those tokens would resolve to nothing here.

   THE POSTER BOX USES A PADDING-RATIO, NOT `aspect-ratio`. It is a flex/grid
   child, and Safari 18.x does not resolve `aspect-ratio` height for a flex item
   whose cross-size comes from stretch — it collapses to 0 and the thumbnail
   vanishes. Playwright's bundled WebKit renders the broken version FINE, so
   this cannot be caught in the harness; see the classroom cover-card entry in
   .claude/rules/gotchas-frontend.md. 177.78% = 1280/720, the thumbs' own 9:16.
   A padding-ratio box has a 0px content box, so the img and the button inside
   it must be absolutely positioned. */
.pf{margin:22px 0 0}
.pf .pf-lab{
  font-size:12px;letter-spacing:.09em;text-transform:uppercase;
  color:#8e9095;font-weight:600;margin:0 0 6px;
}
.pf .pf-h{
  font-size:19px;line-height:1.3;font-weight:700;color:#fff;
  letter-spacing:normal;text-transform:none;margin:0 0 16px;
}
.pf .pf-grid{display:flex;flex-direction:column;gap:16px}
.pf .pf-card{
  /* CENTRE, not flex-start: the 9:16 poster is taller than a short quote, so
     top-aligning leaves a visible well of empty space under the attribution. */
  display:flex;gap:16px;align-items:center;
  border:1px solid #2b2e31;border-radius:10px;background:#16181a;padding:14px;
}
.pf .pf-v{
  flex:0 0 132px;position:relative;width:132px;height:0;padding-top:234px;
  border-radius:8px;overflow:hidden;background:#0d0f11;
}
/* Video-ONLY cards (Daniel, Jay). Neither has a written quote anywhere in the
   codebase and we do not invent testimonial copy, so they render as a 2-up
   poster row under the two quote cards — the same split /class-planning uses.
   The modifier must sit AFTER `.pf .pf-v`: equal specificity, so source order
   is the only thing deciding it. */
.pf .pf-v--sm{flex:0 0 auto;width:100%;padding-top:177.78%}

.pf .pf-lab--more{margin:18px 0 8px}
.pf .pf-more{display:flex;gap:12px}
/* CAPPED, and left-aligned rather than stretched. `flex:1 1 0` alone lets each
   card take half the 703px column, which renders a 346px poster 615px tall —
   two video-only cards ending up nearly 3x the size of the quote cards they
   sit under. The cap keeps them a secondary row; `flex-shrink` still lets them
   compress on a phone. */
.pf .pf-mcard{flex:1 1 0;min-width:0;max-width:168px;margin:0}
.pf .pf-cap{
  margin:8px 0 0;color:#8e9095;font-size:13.5px;line-height:1.4;
}
.pf .pf-cap b{display:block;color:#e6e7e9;font-size:14.5px;font-weight:700}

.pf .pf-v img,.pf .pf-v iframe{
  position:absolute;inset:0;width:100%;height:100%;border:0;
  object-fit:cover;display:block;
}
.pf .pf-play{
  position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
  width:46px;height:46px;border-radius:50%;cursor:pointer;
  border:2px solid #fff;background:rgba(0,0,0,.55);padding:0;
}
/* CSS triangle, nudged right of centre so it reads as centred optically. */
.pf .pf-play::before{
  content:"";position:absolute;left:52%;top:50%;transform:translate(-50%,-50%);
  border-left:14px solid #fff;border-top:9px solid transparent;
  border-bottom:9px solid transparent;
}
.pf .pf-play:hover{background:rgba(0,0,0,.75)}
.pf .pf-play:focus-visible{outline:2px solid #7ad69b;outline-offset:3px}

.pf .pf-body{flex:1 1 240px;min-width:0}
.pf .pf-stars{
  /* #f59e0b on #16181a = 8.4:1. `aria-hidden` does NOT exempt an element from
     a contrast audit — axe measures rendered colour regardless. */
  margin:0 0 8px;color:#f59e0b;font-size:15px;letter-spacing:3px;line-height:1;
}
.pf .pf-q{
  margin:0 0 10px;padding:0;border:0;
  color:#d0d2d6;font-size:15.5px;line-height:1.55;font-style:normal;
}
.pf .pf-q b{color:#fff;font-weight:600}
.pf .pf-who{margin:0;color:#8e9095;font-size:14px;line-height:1.45}
.pf .pf-who b{display:block;color:#e6e7e9;font-size:15px;font-weight:700}

@media (max-width:560px){
  .off .off-pic{width:64px;height:64px}
  .off .off-head{gap:12px}
  /* Flipping `flex-direction` flips which axis `flex-basis` and `align-items`
     act on, so BOTH have to be reset here or they silently mean the wrong
     thing: `flex:1 1 240px` would become a 240px MIN-HEIGHT, and the
     `align-items:center` above would centre the quote horizontally instead of
     letting it fill the card. Any future direction flip owns this reset. */
  .pf .pf-card{flex-direction:column;align-items:stretch}
  .pf .pf-v{flex:0 0 auto;width:100%;padding-top:177.78%;max-width:200px}
  /* The 2-up row stays 2-up on a phone (two 9:16 posters at ~145px each is
     compact); it just must not inherit the quote card's 200px cap, which would
     leave a gap beside each poster. */
  .pf .pf-v--sm{max-width:none}
  .pf .pf-more{gap:10px}
  .pf .pf-body{flex:0 0 auto;width:100%}
}

/* ── Jump rail ───────────────────────────────────────────────────────────
   Nine gated levels, so this is a STEPPER, not a docs table of contents:
   every item is passed / current / locked, and the numbered disc plus the
   connector spine carry that state alongside the title.

   Four things here are deliberate, each one a production pattern that an
   earlier attempt got wrong:

   1. TOP-ANCHORED, never vertically centred. `top:50%` is a floating-widget
      pattern (share buttons), not a nav one — nothing in Stripe's, Next.js's
      or Josh Comeau's nav centres itself, because a centred rail aligns with
      nothing and reads as debris in the left margin. Anchoring to the same
      56px the column starts at lines the rail's heading up with the page
      title.

   2. ANCHORED TO THE COLUMN, not the viewport edge. `right: calc(50% + …)`
      keeps a CONSTANT gap to the reading column at every width; a `left:24px`
      rail drifts further from the text the wider the window gets.

      MEASURE THE COLUMN, DO NOT ASSUME IT. `.nt` is `max-width:63ch` at a
      19px root, which RENDERS 752px wide — so HALF of it is 376px, and the
      offset from the viewport centre line is 376px + the gutter. (A first
      pass here read the old comment as "the column is 376px" and halved it
      again to 188px; the rail then overlapped the text by 132px at every
      width. Render it and read `getBoundingClientRect()` before trusting any
      number in this block.)

   3. NUMBER + NAME AT EVERY WIDTH. The old compact tier (≤1279px) dropped to
      bare 10px dots with the title behind a hover tooltip. A dot with no
      number and no name is decoration: it says "there are nine somethings"
      and nothing else, it is unreadable at a glance, and hover does not exist
      on a phone. The numeral now lives INSIDE the disc that already carries
      passed / current / locked — one element, both jobs, spine still threaded
      through it.

   4. IT DEGRADES TO A MENU, IT DOES NOT VANISH. Below 1100px a 752px column
      plus a rail with readable titles genuinely does not fit, so the same
      markup renders in flow inside the header as a collapsible
      "Levels · 3 of 9" disclosure. Phones used to get nothing at all, which
      is the one tier where losing your place costs the most.

   Contrast: every state clears WCAG 1.4.3 (4.5:1) against #111315 — locked
   included, and the numeral inside every disc variant. Locked is dimmed with
   a COLOUR token, never `opacity`, which composites the text against the
   background before contrast is measured and silently caps it (see
   quality-checks.md). */
.jump{
  position:fixed;top:56px;right:calc(50% + 424px);
  width:248px;max-height:calc(100vh - 112px);overflow-y:auto;
  z-index:5;
}
.jump-h{
  margin:0 0 12px 12px;color:#8e9095;font-size:12px;font-weight:700;
  letter-spacing:.11em;text-transform:uppercase;
}
.jump-list{position:relative;display:flex;flex-direction:column}

/* The mobile disclosure control. Hidden on the gutter rail, where the list is
   always open and `.jump-h` is the heading instead. */
.jump-tog{display:none}

.jump-i{
  position:relative;display:flex;align-items:flex-start;gap:14px;
  width:100%;border:0;background:none;border-radius:9px;
  padding:9px 12px;margin:0;
  font:inherit;font-size:15px;line-height:1.4;text-align:left;
  color:#b7b9bd;cursor:pointer;
}
/* The connector spine, drawn per item so wrapped titles cannot break it.
   left 24px = 12px padding + 13px half-disc − 1px half-line.
   22px      = 9px padding + 13px half-disc, i.e. the disc's centre line. */
.jump-i::before,
.jump-i::after{
  content:'';position:absolute;left:24px;width:2px;background:#4e555f;
}
.jump-i::before{top:0;height:22px}
.jump-i::after{top:22px;bottom:0}
.jump-i:first-child::before,
.jump-i:last-child::after{display:none}

/* The numbered disc. 26px keeps the numeral legible at 12.5px and makes the
   row 44px tall, which is the touch-target floor the mobile menu needs. */
.jump-dot{
  flex:0 0 26px;width:26px;height:26px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  border:2px solid #3a4147;background:#111315;color:#8e9095;
  font-size:12.5px;font-weight:700;line-height:1;
  font-variant-numeric:tabular-nums;
  position:relative;z-index:1;
}
/* 3px lines the title's first line up with the disc's centre rather than its
   top edge, without `align-items:center` — which would re-centre the whole
   disc against a two-line title and break the spine. */
.jump-t{flex:1 1 auto;min-width:0;padding-top:3px;overflow-wrap:anywhere}

/* Passed. Filled disc, lit spine above it: the path you have walked.
   #111315 on #4f9b6e = 5.6:1. */
.jump-i:not([disabled]):not([aria-current="step"]) .jump-dot{
  border-color:#4f9b6e;background:#4f9b6e;color:#111315;
}
.jump-i:not([disabled])::before{background:#3f8f60}
.jump-i:not([disabled]):hover{background:#181b1e;color:#e6e7e9}

/* Current. A ring rather than a fill, plus a tinted pill — colour alone is
   what fails contrast on Next.js's own nav, so the state is carried by
   THREE cues (ring, background, weight), never just hue. The font SIZE is
   deliberately unchanged: resizing the current row shifts every row below it
   on each Next, which reads as the rail twitching. */
.jump-i[aria-current="step"]{
  color:#fff;font-weight:600;background:rgba(122,214,155,.11);
}
.jump-i[aria-current="step"] .jump-dot{
  border-color:#7ad69b;background:#111315;color:#7ad69b;
  box-shadow:0 0 0 3px rgba(122,214,155,.16);
}
.jump-i[aria-current="step"]::after{background:#4e555f}

/* Locked. Hollow disc, muted spine, and a label that is still legible —
   5.6:1 for both the numeral and the title, above the 4.5:1 floor. */
.jump-i[disabled]{color:#8e9095;cursor:default}
.jump-i[disabled]:hover{background:none;color:#8e9095}

.jump-i:focus-visible{outline:2px solid #7ad69b;outline-offset:2px}
.jump-i:focus:not(:focus-visible){outline:none}

/* 1100-1399px: the centred gutter is no longer wide enough for a rail with
   readable titles (752px of column leaves only 224px each side at 1200px), so
   RESERVE A LANE instead — pad the page left and re-anchor the rail into it.
   The column stays exactly as wide and as readable; it just sits off-centre,
   which is what every docs site with a left rail does. The rail's own offset
   has to absorb the padding: with `padding-left:P` the column's left edge is
   at (100vw + P)/2 − 376, so a 32px gutter puts the rail's right edge at
   50% + (376 + 32 − P/2) = 50% + 296px for P = 224px. */
@media (max-width:1399px) and (min-width:1100px){
  :root{--jump-lane:224px}
  body{padding-left:var(--jump-lane)}
  .jump{right:calc(50% + 296px);width:216px}
}

/* ── The menu tier ───────────────────────────────────────────────────────
   Below 1040px a fixed gutter rail would collide with the text, so the same
   markup renders in flow under the progress bar as a disclosure. Collapsed by
   default: nine titles stacked ahead of the level you came to read is a wall
   to scroll past, and the toggle carries "3 of 9" so the closed state still
   answers "where am I". */
@media (max-width:1099px){
  /* PINNED to the top of the viewport, not left in flow. A reader is nine
     levels deep in a scrolling argument; a menu that has scrolled off the top
     is a menu they have to scroll back up to find, which is most of what a
     rail is for. `position:sticky` cannot do this — the nav's parent is the
     header, so it would unstick the moment the header scrolled past — so the
     bar is fixed and .nt reserves its height below.

     env() is the phone's own top inset; it resolves to 0 everywhere else, so
     the same rule is correct on a desktop-narrow window. */
  .jump{
    position:fixed;top:0;left:0;right:0;z-index:40;
    width:auto;max-height:none;overflow:visible;margin-top:0;
    padding:calc(8px + env(safe-area-inset-top, 0px)) 16px 8px;
    background:#111315;border-bottom:1px solid #26292c;
  }
  /* Room for the pinned bar. 61px is its collapsed height (13px + 44px
     control + 8px); the h1 sits under it, not behind it. */
  .nt{padding-top:calc(61px + env(safe-area-inset-top, 0px) + 20px)}
  .jump-h{display:none}

  .jump-tog{
    display:flex;align-items:center;gap:10px;width:100%;
    padding:13px 15px;border:1px solid #2b2e31;border-radius:10px;
    background:#16181a;color:#e6e7e9;font:inherit;font-size:15px;
    cursor:pointer;text-align:left;
  }
  .jump-tog:hover{border-color:#3a4147;background:#191c1e}
  .jump-tog:focus-visible{outline:2px solid #7ad69b;outline-offset:2px}
  .jump-tog__t{font-weight:600;letter-spacing:.06em;text-transform:uppercase;font-size:13px}
  .jump-tog__n{margin-left:auto;color:#8e9095;font-size:14px}
  /* Chevron from two borders rather than an icon file — no request, and it
     inherits the button's colour in both states. */
  .jump-tog__c{
    flex:0 0 auto;width:8px;height:8px;
    border-right:2px solid #8e9095;border-bottom:2px solid #8e9095;
    transform:translateY(-2px) rotate(45deg);transition:transform .15s ease;
  }
  .jump--open .jump-tog__c{transform:translateY(2px) rotate(225deg)}

  /* The open list hangs off the pinned bar, so it scrolls itself rather than
     the page — overscroll-behavior stops a flick at its end from carrying on
     into the argument behind it. */
  .jump-list{
    display:none;margin-top:8px;padding:8px 4px;
    border:1px solid #2b2e31;border-radius:10px;background:#141618;
    max-height:min(52vh,460px);overflow-y:auto;overscroll-behavior:contain;
  }
  .jump--open .jump-list{display:flex}

  /* 48px rows: above the 44px touch floor with room for a wrapped title. */
  .jump-i{padding:11px 12px;font-size:15.5px}
  .jump-i::before{height:24px}
  .jump-i::after{top:24px}
  .jump-i:not([disabled]):hover{background:#1c1f22}
  .jump-i[aria-current="step"]{background:rgba(122,214,155,.13)}
}

@media (prefers-reduced-motion:reduce){
  .jump-tog__c{transition:none}
}

/* ── Level video ────────────────────────────────────────────────────────────
   A poster with a play button; the iframe replaces both on click (start.js).

   The box is sized by ASPECT-RATIO on a block-level element, which is safe.
   Do NOT make this a flex item and keep aspect-ratio: Safari 18.x does not
   resolve aspect-ratio height for a flex child whose width comes from
   align-items:stretch, and the box collapses to 0. If this ever needs to sit
   in a flex row, switch to a padding-top ratio (see coach-classroom.css). */
.lv-vid {
  position: relative;
  width: 100%;
  max-width: 760px;
  aspect-ratio: 16 / 9;
  margin: 0 0 30px;
  border-radius: 14px;
  overflow: hidden;
  background: #05060a;
  box-shadow: 0 10px 38px rgba(0, 0, 0, .34);
}
.lv-vid img,
.lv-vid iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  border: 0;
  object-fit: cover;
}
.lv-vid__play {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  padding: 0;
  cursor: pointer;
  background: rgba(5, 6, 10, .3);
  transition: background .18s ease;
}
.lv-vid__play::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 0;
  height: 0;
  /* a triangle, offset so its VISUAL centre sits on the button's centre -
     a centred bounding box reads as left-heavy for a play glyph */
  transform: translate(-42%, -50%);
  border-left: 26px solid #fff;
  border-top: 17px solid transparent;
  border-bottom: 17px solid transparent;
  filter: drop-shadow(0 2px 10px rgba(0, 0, 0, .55));
}
.lv-vid__play:hover { background: rgba(5, 6, 10, .14); }
.lv-vid__play:focus-visible { outline: 3px solid var(--accent, #2563eb); outline-offset: -3px; }
@media (prefers-reduced-motion: reduce) { .lv-vid__play { transition: none; } }
@media (max-width: 700px) { .lv-vid { margin-bottom: 22px; border-radius: 10px; } }
