/* ============================================================================
   Sections below the hero. Token-driven like everything else — no colour is
   named here.

   HIDING A SECTION
   ----------------
   A section the seller does not want is **hidden, never deleted** — they ask
   for it back more often than not, and rebuilding it loses the copy that was
   argued over. Set the attribute:

       <section class="section section-video" data-state="hidden">

   It stops rendering, stays in the file, and comes back by removing one word.
   Anything the section loads is also skipped while hidden: the scripts check
   the attribute before initialising, so a hidden video costs nothing.
   ============================================================================ */
[data-state="hidden"]{display:none !important}

.section{position:relative;z-index:3;padding:88px 32px 96px}
.section + .section{border-top:1px solid var(--line)}
/* alternate the ground so each section reads as a new chapter */
.section-alt{background:var(--surface)}

.section-inner{max-width:960px;margin:0 auto;text-align:center}

.section h2{
  font-family:var(--font);font-weight:var(--h-weight);
  font-size:clamp(28px,3.4vw,40px);letter-spacing:var(--h-track);
  line-height:1.12;margin:0 0 14px;color:var(--ink);
}
.section .lede{
  font-size:16.5px;line-height:1.6;color:var(--mute);
  max-width:560px;margin:0 auto 34px;
}

/* ---------------- video ---------------- */
.player{
  position:relative;width:100%;aspect-ratio:16/9;margin:0 auto 32px;
  max-width:880px;border-radius:14px;overflow:hidden;
  border:1px solid var(--edge);background:var(--raised);
  box-shadow:var(--shadow-lg);
}
.player iframe,.player mux-player,.player video{
  position:absolute;inset:0;width:100%;height:100%;border:0;display:block;
}
.player mux-player{--controls:none;border-radius:14px}

/* The facade. A YouTube iframe on page load pulls ~1MB and third-party cookies
   before anyone has asked to watch anything, so the poster stands in until a
   click, and only then is the real player injected. */
.facade{position:absolute;inset:0;width:100%;height:100%;padding:0;border:0;
  cursor:pointer;background-size:cover;background-position:center;display:block}
.facade::after{content:"";position:absolute;inset:0;
  background:linear-gradient(180deg,rgb(0 0 0 / .10),rgb(0 0 0 / .38))}
.facade .play{
  position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);z-index:2;
  width:74px;height:74px;border-radius:50%;background:var(--accent);
  display:grid;place-items:center;transition:transform .18s;
  box-shadow:0 10px 30px rgb(0 0 0 / .32);
}
.facade:hover .play{transform:translate(-50%,-50%) scale(1.07)}
.facade .play svg{width:26px;height:26px;margin-left:3px;fill:var(--accent-ink)}
.facade .cap{
  position:absolute;left:0;right:0;bottom:0;z-index:2;padding:14px 16px;
  font-size:12px;letter-spacing:.04em;text-transform:uppercase;
  color:#fff;opacity:.82;text-align:left;
}

.section-cta{display:inline-flex;align-items:center;justify-content:center;min-height:56px;
  font-family:var(--font);font-size:16.5px;font-weight:600;letter-spacing:-.012em;
  text-decoration:none;color:var(--accent-ink);background:var(--accent);
  padding:0 34px;border-radius:9px;transition:transform .16s,background-color .35s}
.section-cta{box-shadow:var(--shadow)}
.section-cta:hover{transform:translateY(-2px);box-shadow:var(--shadow-lg)}
.section-note{font-size:13px;color:var(--mute);margin:15px 0 0;opacity:.9}

@media (max-width:760px){
  .section{padding:56px 20px 62px}
  .section-inner{text-align:left}
  .section h2{font-size:26px}
  .section .lede{max-width:none;margin-bottom:26px}
  .player{border-radius:11px;margin-bottom:24px}
  .facade .play{width:58px;height:58px}
  .facade .play svg{width:21px;height:21px}
  .facade .cap{display:none}
  .section-cta{display:flex;width:100%;padding:0 20px}
}
@media (prefers-reduced-motion:reduce){ .facade:hover .play{transform:translate(-50%,-50%)} }

/* ---------------- inverted section ----------------
   A section that reads as its own chapter: on a light page it goes dark, on a
   dark page it goes light. It remaps its local tokens to the opposite mode's
   set, so every child — headings, lede, chips, button, player chrome — follows
   without a single hard-coded colour.

       <section class="section section-invert section-video"> */
.section-invert,
.unit-invert{
  --bg:var(--inv-bg);            --bg-rgb:var(--inv-bg-rgb);
  --surface:var(--inv-surface);  --surface-rgb:var(--inv-surface-rgb);
  --raised:var(--inv-raised);    --raised-rgb:var(--inv-raised-rgb);
  --line:var(--inv-line);        --line-rgb:var(--inv-line-rgb);
  --ink:var(--inv-ink);          --ink-rgb:var(--inv-ink-rgb);
  --mute:var(--inv-mute);        --mute-rgb:var(--inv-mute-rgb);
  --accent:var(--inv-accent);    --accent-rgb:var(--inv-accent-rgb);
  --accent-fill:var(--inv-accent-fill);
  --accent-on-fill:var(--inv-accent-on-fill);
  --tint-1:var(--inv-tint-1); --tint-2:var(--inv-tint-2); --tint-3:var(--inv-tint-3);
  --tint-4:var(--inv-tint-4); --tint-5:var(--inv-tint-5); --tint-6:var(--inv-tint-6);
  --accent-ink:var(--inv-accent-ink);
  background:var(--bg);
  color:var(--ink);
}
/* the inverted block owns its edges, so the shared hairline would double up */
.section-invert,.section-invert + .section{border-top:0}

/* ---------------- profile ----------------
   Identity on the left, the argument on the right.

   The organising idea is that credibility here is *checkable*, not asserted:
   a link the reader can follow, marks they recognise, and numbers attached to
   a situation. A round number in a box persuades nobody. */
.section-profile .section-inner{max-width:1080px;text-align:left}
.profile-grid{display:grid;grid-template-columns:302px 1fr;gap:54px;align-items:start}

/* The rail is a card with an accent tint, so it reads as its own object. The
   tint is alpha over the accent, not a ramp stop — a stop that works on white
   is wrong on black, and this has to hold in both modes. */
.rail{
  position:sticky;top:96px;             /* clears the sticky nav */
  padding:22px 22px 20px;
  border-radius:20px;
  background:var(--tint-5);
  border:1px solid var(--edge);box-shadow:var(--shadow);
}

/* Photo as a composed object: a hard accent block behind, offset and counter-
   rotated. The block gives the photo a direction and an anchor — a circle with
   a ring was decoration, this is composition. Rotation stays under 2deg; more
   than that fights the grid in the background. */
.photo{position:relative;width:100%;max-width:210px;margin:0 0 20px}
.photo .block{
  position:absolute;inset:0;border-radius:18px;background:var(--accent-fill);
  transform:rotate(2deg) translate(11px,11px);
}
.photo img{
  /* height:auto is load-bearing — a width/height attribute on the <img> sets
     `height` as a presentational hint, which beats aspect-ratio and makes the
     photo render at its attribute height instead of the 4:5 crop. */
  position:relative;display:block;width:100%;height:auto;aspect-ratio:4/5;object-fit:cover;
  border-radius:18px;transform:rotate(-1.2deg);
  border:1px solid rgb(var(--ink-rgb) / .10);
}

/* After the face, the name is the second thing to take in — it was the seventh */
.section-profile .who{
  margin:0 0 4px;font-size:37px;font-weight:var(--h-weight);
  letter-spacing:-.045em;line-height:1.02;color:var(--ink);
}
.section-profile .role{margin:0 0 17px;font-size:14.5px;line-height:1.45;color:var(--mute)}

/* the one clickable proof on the page, and for a LinkedIn workshop the
   teacher's own profile is the product working */
.li-btn{
  display:inline-flex;align-items:center;gap:10px;
  padding:8px 18px 8px 8px;border-radius:999px;
  background:var(--bg);border:1px solid rgb(var(--ink-rgb) / .14);
  font-size:14.5px;font-weight:600;letter-spacing:-.015em;
  color:var(--ink);text-decoration:none;transition:transform .16s,border-color .2s;
}
.li-btn:hover{transform:translateY(-1px);border-color:rgb(var(--ink-rgb) / .3)}
.li-btn svg{width:28px;height:28px;flex:none}   /* brand mark keeps its own colour */

.rail hr{border:0;border-top:1px solid rgb(var(--ink-rgb) / .13);margin:18px 0 14px}

.eyebrow{
  margin:0 0 12px;font-size:11.5px;font-weight:600;letter-spacing:.15em;
  text-transform:uppercase;color:var(--mute);
}
/* Marks only — four wordmarks will not fit a 302px rail, and a logo row reads
   as logos. Each carries an accessible name instead of visible text. Greyscale
   by convention: a row of full-colour logos competes with the CTA. */
.prev{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;gap:9px}
.prev li{display:inline-flex}
.prev .mk{
  width:38px;height:38px;border-radius:10px;flex:none;display:grid;place-items:center;
  background:rgb(var(--ink-rgb) / .05);
  border:1px solid rgb(var(--ink-rgb) / .10);
  transition:background .2s;
}
.prev .mk:hover{background:rgb(var(--ink-rgb) / .09)}
.prev .mk svg{width:19px;height:19px;fill:var(--mute);opacity:.9}

/* ---- what they have done: claim in bold, situation in muted ----
   The bold half carries the fact; the muted half names who and where, which is
   what makes a number believable rather than marketing. */
.done{list-style:none;margin:0;padding:0}
.done li{display:flex;gap:13px;margin:0 0 15px}
.done li:last-child{margin-bottom:0}
.done .tick{
  width:23px;height:23px;border-radius:50%;flex:none;margin-top:3px;
  background:var(--accent-fill);display:grid;place-items:center;
}
.done .tick svg{width:13px;height:13px;stroke:var(--accent-on-fill);stroke-width:3;fill:none;
  stroke-linecap:round;stroke-linejoin:round}
.done p{margin:0;font-size:16.5px;line-height:1.6;color:var(--mute)}
.done strong{color:var(--ink);font-weight:600}

.section-profile h2{margin:0 0 18px}
.story{max-width:none}
.story p{margin:0 0 17px;font-size:16.5px;line-height:1.7;color:var(--mute)}
.story p:last-child{margin-bottom:0}
.story{margin-bottom:34px}
.story strong{color:var(--ink);font-weight:600}

/* the one line that is the whole argument, lifted out of the paragraph */
.pull{
  margin:26px 0;padding:0 0 0 20px;border-left:3px solid var(--accent-600);
  font-size:23px;font-weight:600;line-height:1.3;letter-spacing:-.03em;color:var(--ink);
}

.profile-cta{margin:48px 0 0;text-align:center}

@media (max-width:860px){
  .profile-grid{grid-template-columns:1fr;gap:34px}
  .rail{position:static}
  .photo{max-width:220px}
}
@media (max-width:760px){
  .rail{padding:22px 20px 20px;border-radius:16px}
  .photo{max-width:190px;margin-bottom:22px}
  .section-profile .who{font-size:34px}
  .pull{font-size:20px;margin:22px 0;padding-left:16px}
  .done p{font-size:16px}
  .profile-cta{margin-top:36px;text-align:left}
}
@media (prefers-reduced-motion:reduce){ .li-btn:hover{transform:none} }

/* ---------------- curriculum ----------------
   Four cards, one per hour. Each carries the same four things in the same
   order: which part of the arc it is, what you walk out of that hour with,
   and three things you actually do. Same shape four times is what makes it
   scannable — the reader learns the pattern once and then only reads the
   content.

   The last hour inverts, and so does the closing card. That is deliberate: the
   eye should land on where the whole thing is going, not on hour one. */
/* left-aligned: a centred heading over a left-aligned grid of cards leaves the
   eye with two different start points */
.section-curriculum .section-inner{max-width:1080px;text-align:left}
.section-curriculum h2{max-width:20ch;margin-bottom:14px}
.section-curriculum .lede{margin:0 0 34px;max-width:62ch}

.curriculum-grid{display:grid;grid-template-columns:1fr 1fr;gap:22px;margin:0 0 22px}

.unit{
  position:relative;overflow:hidden;
  background:var(--tint-1);border:1px solid var(--edge);box-shadow:var(--shadow);
  border-radius:20px;padding:28px 30px 26px;
}
/* One hue per card, all at the same lightness and chroma. Varying hue is what
   lets four colours sit side by side; varying saturation is what makes them
   fight. The text on them stays --ink — never a tint of the card's own hue. */
.unit[data-tint="1"]{background:var(--tint-1)}
.unit[data-tint="2"]{background:var(--tint-2)}
.unit[data-tint="3"]{background:var(--tint-3)}
.unit[data-tint="4"]{background:var(--tint-4)}
.unit[data-tint="5"]{background:var(--tint-5)}
.unit[data-tint="6"]{background:var(--tint-6)}
/* the ghost number: big enough to give the card a corner, faint enough that it
   never competes with the title sitting next to it */
.unit .num{
  position:absolute;top:14px;right:22px;line-height:.86;
  font-size:76px;font-weight:var(--h-weight);letter-spacing:-.06em;
  color:rgb(var(--accent-rgb) / .20);pointer-events:none;
}
.unit .phase{
  position:relative;display:inline-flex;align-items:center;
  margin:0 0 14px;font-size:12px;font-weight:600;letter-spacing:.13em;
  text-transform:uppercase;color:var(--mute);
}
/* first letter in a chip, rest of the word plain — the four chips read down the
   grid as the acronym, which is the whole reason for the device */
.unit .phase .key{
  display:inline-grid;place-items:center;width:19px;height:19px;border-radius:5px;
  margin-right:1px;background:var(--accent-fill);color:var(--accent-on-fill);
  font-size:11.5px;font-weight:700;letter-spacing:0;
}
.unit h3{
  position:relative;margin:0 0 18px;font-size:22px;font-weight:var(--h-weight);
  letter-spacing:-.035em;line-height:1.18;color:var(--ink);max-width:88%;
}
.unit ul{list-style:none;margin:0;padding:0}
.unit li{
  position:relative;padding-left:21px;margin:0 0 12px;
  font-size:15.5px;line-height:1.55;color:var(--mute);
}
.unit li:last-child{margin-bottom:0}
.unit li::before{
  content:"";position:absolute;left:0;top:.62em;width:11px;height:2.5px;
  border-radius:2px;background:var(--accent-600);
}
.unit strong{color:var(--ink);font-weight:600}

/* the closing card — full width, inverted, and it answers "so what" */
.summary{
  border-radius:20px;padding:34px 36px 36px;
  background:var(--tint-6);color:var(--ink);
  border:1px solid var(--edge);box-shadow:var(--shadow);
}
.summary .eyebrow{color:var(--mute);margin-bottom:14px}
.summary h3{
  margin:0 0 14px;font-size:clamp(24px,2.7vw,32px);font-weight:var(--h-weight);
  letter-spacing:-.04em;line-height:1.16;color:var(--ink);max-width:22ch;
}
.summary p{margin:0;font-size:16.5px;line-height:1.65;color:var(--mute);max-width:62ch}
.summary strong{color:var(--ink);font-weight:600}

@media (max-width:860px){
  .curriculum-grid{grid-template-columns:1fr;gap:16px;margin-bottom:16px}
  .section-curriculum h2{max-width:none}
}
@media (max-width:760px){
  .unit{padding:22px 22px 20px;border-radius:16px}
  .unit .num{font-size:58px;top:12px;right:16px}
  .unit h3{font-size:19.5px;margin-bottom:15px;max-width:78%}
  .unit li{font-size:15px;padding-left:19px}
  .summary{padding:26px 22px 28px;border-radius:16px}
  .summary p{font-size:16px}
}

/* ---------------- bonuses ----------------
   A ticket stub, because that is what a bonus is: something you are handed on
   the way in. The notches are the device — they say "voucher" before a word is
   read, and they cost two pseudo-elements.

   The section inverts. It is the page's second and last dark block, and the
   one place the value stack gets to feel like an event. */
.section-bonuses .section-inner{max-width:1120px;text-align:left}
.section-bonuses h2{max-width:18ch;margin-bottom:34px}

.bonus-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:28px;margin:0 0 36px}

.bonus{
  position:relative;background:var(--base-tint-6);color:var(--base-ink);
  box-shadow:var(--shadow-lg);
  border-radius:18px;padding:26px 26px 28px;
  display:flex;flex-direction:column;
}
/* the stub notches — painted in the section's own ground so they read as cut
   out of the card. Half outside the card on each side, at the waist. */
.bonus::before,.bonus::after{
  content:"";position:absolute;top:50%;width:26px;height:26px;border-radius:50%;
  background:var(--bg);transform:translateY(-50%);
}
.bonus::before{left:-13px}
.bonus::after{right:-13px}

.bonus .n{
  margin:0 0 11px;font-size:11.5px;font-weight:600;letter-spacing:.15em;
  text-transform:uppercase;color:var(--base-mute);
}
.bonus h3{
  margin:0 0 12px;font-size:20px;font-weight:var(--h-weight);
  letter-spacing:-.035em;line-height:1.22;color:var(--base-ink);
}
.bonus p{margin:0;font-size:15.5px;line-height:1.6;color:var(--base-mute)}
.bonus .rule{border:0;border-top:1px dashed rgb(var(--base-ink-rgb) / .28);margin:20px 0 16px}
.bonus .val{display:flex;align-items:center;gap:13px;margin:0 0 8px}
.bonus .amt{font-size:27px;font-weight:var(--h-weight);letter-spacing:-.04em;color:var(--base-ink)}

/* solid chip = you get it. dashed chip = you can win it. The distinction is
   solid-versus-outline, so neither has to borrow the accent from the button. */
.chip-get,.chip-win{
  display:inline-flex;align-items:center;padding:5px 13px;border-radius:999px;
  font-size:11.5px;font-weight:700;letter-spacing:.11em;text-transform:uppercase;
}
.chip-get{background:var(--base-accent-fill);color:var(--base-accent-on-fill)}
.chip-win{border:1.5px dashed rgb(var(--base-ink-rgb) / .38);color:var(--base-mute)}
.bonus .who{margin:0;font-size:14.5px;line-height:1.55;color:var(--base-mute)}
.bonus .who strong{color:var(--base-ink);font-weight:600}
.bonus .spacer{flex:1;min-height:6px}

.bonus-cta{text-align:center}

@media (max-width:900px){
  .bonus-grid{grid-template-columns:1fr;gap:34px}
  /* stacked, the notches belong at top and bottom, not at the sides */
  .bonus::before,.bonus::after{top:auto;left:50%;right:auto;transform:translateX(-50%)}
  .bonus::before{top:-13px}
  .bonus::after{bottom:-13px}
}
@media (max-width:760px){
  .section-bonuses h2{max-width:none;margin-bottom:26px}
  .bonus{padding:22px 20px 24px;border-radius:15px}
  .bonus h3{font-size:18.5px}
  .bonus .amt{font-size:24px}
  .bonus-cta{text-align:left}
}

/* ---------------- the outside case ----------------
   Two facts about the platform, before any claim about the teacher. The reader
   asks "is this worth my Sunday" long before "can she teach me", and nothing
   answers the first question unless you build it.

   Every figure carries a visible source. A statistic without one is an opinion
   with a number in it, and on a page selling credibility that is worse than no
   statistic at all. */
/* Two inverted sections that touch read as one long dark region. Rather than
   un-inverting either, this one stands one rung lighter — still dark, visibly
   its own block. */
.section-case{background:var(--surface)}
.section-case .section-inner{max-width:1120px;text-align:left}
.case-mark{width:40px;height:40px;display:block;margin:0 0 18px}
.section-case{padding-top:104px}
.section-case .eyebrow{margin-bottom:38px}

.case-grid{display:grid;grid-template-columns:1fr 1fr;gap:56px 72px;align-items:start}
/* the second stat drops, so the pair reads as two separate thoughts rather than
   a row of two things */
.case-grid .stat:nth-child(2){margin-top:88px}

.stat p.fact{
  margin:0 0 16px;font-size:clamp(25px,2.9vw,34px);font-weight:var(--h-weight);
  letter-spacing:-.035em;line-height:1.34;color:var(--ink);
}
/* the drawn marks. A ring and a stroke, deliberately a touch off-true — a
   perfect ellipse reads as a border, not as something a person drew. */
.mk-ring,.mk-line{position:relative;display:inline-block;white-space:nowrap}
.mk-ring svg,.mk-line svg{
  position:absolute;left:50%;transform:translateX(-50%);
  overflow:visible;pointer-events:none;
}
.mk-ring svg{top:50%;width:128%;height:128%;transform:translate(-50%,-50%)}
.mk-line svg{bottom:-.17em;width:106%;height:.4em}
.mk-ring path,.mk-line path{
  fill:none;stroke:var(--accent);stroke-linecap:round;
  stroke-dasharray:var(--len,600);stroke-dashoffset:var(--len,600);
  animation:draw-mark 1s .35s cubic-bezier(.22,.8,.3,1) forwards;
}
.mk-ring path{stroke-width:2.6}
.mk-line path{stroke-width:4.5}
@keyframes draw-mark{ to{ stroke-dashoffset:0 } }

.src{margin:0;font-size:15px;line-height:1.6;color:var(--mute)}
.src .ar{color:var(--accent);margin-right:5px;font-weight:600}
.src strong{color:var(--ink);font-weight:600}

@media (max-width:860px){
  .case-grid{grid-template-columns:1fr;gap:38px}
  .case-grid .stat:nth-child(2){margin-top:0}
}
@media (max-width:760px){
  .section-case .eyebrow{margin-bottom:26px}
  .case-mark{width:34px;height:34px;margin-bottom:14px}
  .src{font-size:14.5px}
}
@media (prefers-reduced-motion:reduce){
  /* without this the marks freeze at full offset and vanish entirely */
  .mk-ring path,.mk-line path{stroke-dashoffset:0}
}

/* ---------------- testimonials ----------------
   A different argument from the profile section: that one says trust this
   person, this one says it worked for people like you. Both earn their place
   only because they answer different questions.

   The outcome chip is the load-bearing part. "Really useful session" is worth
   nothing; "three interviews in two weeks" is the only sentence a reader
   actually checks themselves against. */
.section-said .section-inner{max-width:1120px;text-align:left}
.section-said h2{max-width:20ch;margin-bottom:34px}

/* ======================================================================
   STUDENT REVIEWS
   ----------------------------------------------------------------------
   White cards on the off-white ground, between two dark sections. The only
   colour is the mark token: a near-black in light mode, the accent in dark.
   The outcome tag used --accent-fill and came out blue, which is the one
   thing this section is not allowed to be.

   On a phone the three cards become one swipe row rather than a tall stack:
   the row bleeds past the section padding so the next card shows at the
   edge, which is what tells the reader to swipe.
   ====================================================================== */
.section-said .section-inner{max-width:1080px}
.section-said h2{margin:0 0 34px}

.said-grid{
  display:grid;grid-template-columns:repeat(3,1fr);gap:22px;
  margin:0;padding:0;align-items:stretch;
}

.said{
  display:flex;flex-direction:column;margin:0;
  background:var(--card-light);border:1px solid var(--card-line);
  box-shadow:var(--shadow);border-radius:18px;padding:24px 26px 24px;
}

.said .qm{
  margin:0 0 2px;font-size:46px;line-height:.8;font-weight:700;
  color:var(--mark-ink);opacity:.26;
}

/* outlined, not filled — a filled pill here reads as a second button */
.said .out{
  align-self:flex-start;margin:0 0 15px;padding:6px 13px;border-radius:999px;
  background:transparent;border:1px solid color-mix(in srgb, var(--mark-ink) 42%, transparent);
  color:var(--mark-ink);
  font-size:12px;font-weight:700;letter-spacing:.04em;
}

.said blockquote{margin:0;font-size:16.5px;line-height:1.62;color:var(--ink)}
.said .spacer{flex:1;min-height:18px}
.said-rule{border:0;border-top:1px solid var(--card-line);margin:0 0 15px}

.said figcaption{display:flex;align-items:center;gap:12px}
.said img{
  width:44px;height:44px;border-radius:50%;object-fit:cover;flex:none;
  /* the ring sits off the photo so a light portrait still has an edge */
  box-shadow:0 0 0 1px var(--card-light), 0 0 0 2.5px color-mix(in srgb, var(--mark-ink) 34%, transparent);
}
.said .nm{margin:0;font-size:14.5px;font-weight:600;letter-spacing:-.02em;color:var(--mark-ink)}
.said .rl{margin:1px 0 0;font-size:13px;line-height:1.4;color:var(--mute)}

/* cards arrive one after another, the same curve the timeline rows use */
.said{opacity:0;transform:translateY(14px);
      transition:opacity .5s ease,transform .5s ease}
.said.seen{opacity:1;transform:none}

@media (max-width:900px) and (min-width:761px){
  .said-grid{grid-template-columns:1fr 1fr}
}

@media (max-width:760px){
  .section-said h2{max-width:none;margin-bottom:26px}
  /* one card at a time, the next one showing at the edge */
  .said-grid{
    display:flex;grid-template-columns:none;gap:14px;
    overflow-x:auto;overscroll-behavior-x:contain;
    scroll-snap-type:x mandatory;-webkit-overflow-scrolling:touch;
    margin-inline:-20px;padding-inline:20px;padding-bottom:4px;
    scrollbar-width:none;
  }
  .said-grid::-webkit-scrollbar{display:none}
  .said{
    flex:0 0 84%;scroll-snap-align:center;
    padding:22px 20px 20px;border-radius:15px;
  }
  .said blockquote{font-size:16px}
  .said .qm{font-size:40px}
}

@media (prefers-reduced-motion:reduce){
  .said{opacity:1;transform:none;transition:none}
}

/* ---------------- value stack / price ----------------
   The honest part of this section is the subtraction. Two bonuses are marked
   "not counted below" and left out of the total, because only a handful of
   people win them — counting them as part of what everyone buys is a number
   the reader finds out was wrong on the day.

   A value stack that inflates is worse than no value stack: it is the one
   place on a page where the reader can do the arithmetic themselves. */
/* ======================================================================
   PRICING
   ----------------------------------------------------------------------
   Copy on the left, the price card on the right. The copy is the shorter
   column, so it is the one that sticks: it holds the claim in view while
   the card's rows scroll past, which is the order the reader needs them in.

   The whole section is written in literal values rather than tokens. It has
   to stay dark with a white card in BOTH modes, and .section-invert flips
   its token set in dark mode — anything token-driven here would inverse.
   ====================================================================== */
/* Muted text on the white card is a SOLID grey, not the dark at low alpha.
   Alpha over white composites to a mid grey: rgb(3 26 29 / .6) measured
   2.31:1, and the small notes were worse. These two are measured on #fff. */
:root{ --pr-mute:#5F6B6D; --pr-faint:#6A7678 }
/* This section is dark in BOTH modes, so it has to out-rank the dark-mode
   .section-invert rule above, which repaints that class light. Matching its
   specificity and coming later is what does it — the text here is literal
   light-on-dark and would otherwise land on a white ground at 1:1. */
.section-price,
:root[data-mode="dark"] .section-price.section-invert{ background:#031A1D }
.section-price .section-inner{max-width:1140px;text-align:left}

.pr-cols{display:grid;grid-template-columns:1fr 520px;gap:56px;align-items:start}

.pr-copy{position:sticky;top:110px}
.section-price .eyebrow{color:rgb(244 252 253 / .7)}
.section-price h2{max-width:16ch;margin:0 0 14px;color:#F4FCFD}
.section-price .lede{margin:0 0 26px;max-width:46ch;color:rgb(244 252 253 / .72)}
.pr-rule{border:0;border-top:1px solid rgb(255 255 255 / .12);margin:0 0 22px}
.section-price .stack-note{
  margin:0;font-size:14.5px;line-height:1.65;color:rgb(244 252 253 / .62);max-width:52ch;
}
.section-price .stack-note strong{color:#F4FCFD;font-weight:600}

/* ---- the card ------------------------------------------------------- */
.pr-card{
  background:#fff;border-radius:22px;padding:28px 30px 26px;
  box-shadow:0 30px 70px -20px rgb(0 0 0 / .55), 0 2px 8px rgb(0 0 0 / .18);
}
.pr-label{
  margin:0 0 18px;font-size:11.5px;font-weight:700;letter-spacing:.1em;
  text-transform:uppercase;color:var(--pr-mute);
}

.section-price .srow{
  display:grid;grid-template-columns:1fr auto;gap:18px;align-items:start;
  padding:15px 0;border-top:1px solid rgb(3 26 29 / .08);
}
.section-price .srow:first-of-type{border-top:0;padding-top:0}
.section-price .srow .lbl{
  margin:0 0 3px;font-size:11px;font-weight:700;letter-spacing:.09em;
  text-transform:uppercase;color:var(--pr-mute);
}
.section-price .srow h3{
  margin:0 0 4px;font-size:16px;font-weight:600;letter-spacing:-.02em;color:#031A1D;
  display:flex;align-items:center;gap:8px;flex-wrap:wrap;
}
.section-price .srow p{margin:0;font-size:13.5px;line-height:1.5;color:var(--pr-mute);max-width:38ch}
.section-price .srow .amt{text-align:right;white-space:nowrap}
.section-price .srow .amt b{
  display:block;font-size:20px;font-weight:600;letter-spacing:-.035em;color:#031A1D;
}
.section-price .srow .amt span{
  display:block;margin-top:2px;font-size:11.5px;line-height:1.35;
  color:var(--pr-faint);white-space:normal;max-width:17ch;margin-left:auto;
}
/* the two that are earned, not bought: greyed so the eye skips them when
   it adds the total up */
.section-price .srow.off .amt b{color:var(--pr-mute);font-weight:500}
.section-price .srow.off h3{color:#3A4446}

.section-price .chip-get,
.section-price .chip-win{
  font-size:10.5px;font-weight:700;letter-spacing:.07em;text-transform:uppercase;
  padding:3px 9px;border-radius:999px;line-height:1.5;
}
.section-price .chip-get{background:#031A1D;color:#F4FCFD;border:0}
.section-price .chip-win{
  background:transparent;border:1px solid rgb(3 26 29 / .38);color:var(--pr-mute);
}

.pr-dash{border:0;border-top:1px dashed rgb(3 26 29 / .26);margin:16px 0 14px}

.pr-total{display:flex;align-items:baseline;justify-content:space-between;gap:16px;margin:0 0 16px}
.pr-total h3{margin:0;font-size:16px;font-weight:600;letter-spacing:-.02em;color:#031A1D}
.pr-was{margin:0;font-size:24px;font-weight:600;letter-spacing:-.04em;color:var(--pr-mute)}
.pr-was s{text-decoration:line-through;text-decoration-thickness:2px}

.section-price .payrow{
  display:flex;align-items:center;justify-content:space-between;gap:18px;flex-wrap:wrap;
  background:#F7F4F0;border-radius:16px;padding:18px 20px;margin:0 0 12px;border:0;
}
.section-price .payrow .k{
  margin:0 0 2px;font-size:11px;font-weight:700;letter-spacing:.09em;
  text-transform:uppercase;color:var(--pr-mute);
}
.section-price .payrow .sub{margin:0;font-size:13.5px;line-height:1.45;color:var(--pr-mute);max-width:26ch}
.section-price .payrow .big{
  margin:0;font-size:64px;font-weight:600;letter-spacing:-.05em;line-height:1;
  color:#031A1D;font-variant-numeric:tabular-nums;
}

.pr-save{margin:0 0 18px;font-size:13.5px;line-height:1.5;color:var(--pr-mute)}

/* the generic dark-mode rule clears this border for .section-invert, and sits
   later in the file — this section stays dark there, so it needs the border
   back, at a specificity that rule cannot match */
.section-price .pr-cta,
:root[data-mode="dark"] .section-price.section-invert .pr-cta{
  display:flex;width:100%;background:#031A1D;color:#F4FCFD;
  border:1px solid rgb(255 255 255 / .18);
  margin:0 0 12px;
}
.section-price .pr-cta:hover{background:#0D2C30}
.pr-trust{margin:0;text-align:center;font-size:12.5px;line-height:1.5;color:var(--pr-faint)}

/* ---- motion --------------------------------------------------------- */
.pr-copy,.pr-card{opacity:0;transform:translateY(18px);
  transition:opacity .7s ease,transform .7s ease}
.pr-card{transition-delay:.1s}
.pr-copy.seen,.pr-card.seen{opacity:1;transform:none}

@media (max-width:960px){
  .pr-cols{grid-template-columns:1fr;gap:34px}
  .pr-copy{position:static}
  .section-price h2{max-width:none}
  .section-price .lede{max-width:none}
  .section-price .stack-note{max-width:none}
}
@media (max-width:760px){
  .pr-card{padding:22px 20px 22px;border-radius:18px}
  .section-price .srow{grid-template-columns:1fr;gap:8px;padding:14px 0}
  .section-price .srow .amt{text-align:left}
  .section-price .srow .amt span{margin-left:0;max-width:none}
  .section-price .payrow .big{font-size:54px}
  .section-price .payrow{padding:16px 16px 18px}
}

@media (prefers-reduced-motion:reduce){
  .pr-copy,.pr-card{opacity:1;transform:none;transition:none}
}

/* ---------------- why now ----------------
   The cost-of-waiting section, and it belongs after the price — the reader has
   the number it argues against. Its job is not "is LinkedIn worth it" but "why
   not leave it until later", which is a different question.

   Narrative on the left with the evidence under it, a vertical clip on the
   right. The evidence carries live source links, because a figure the reader
   can click is the only kind that survives scepticism. */
.section-now .section-inner{max-width:1120px;text-align:left}
.section-now h2{max-width:14ch;margin-bottom:28px}
.now-grid{display:grid;grid-template-columns:1.12fr .88fr;gap:60px;align-items:start}
.now-copy p{margin:0 0 18px;font-size:17px;line-height:1.68;color:var(--mute)}
.now-copy p:last-of-type{margin-bottom:24px}

/* A highlighter that survives wrapping. box-decoration-break:clone is the whole
   trick — without it the mark paints one box across both lines and bleeds into
   the margin. */
.hl{
  background:rgb(var(--accent-rgb) / .20);
  -webkit-box-decoration-break:clone;box-decoration-break:clone;
  padding:.1em .2em;border-radius:3px;
  color:var(--ink);font-weight:600;
}

.evid{
  background:var(--tint-1);border:1px solid var(--edge);box-shadow:var(--shadow);
  border-radius:14px;padding:18px 20px 16px;margin:0 0 13px;
}
.evid b{
  display:block;margin:0 0 5px;font-size:20px;font-weight:var(--h-weight);
  letter-spacing:-.035em;line-height:1.2;color:var(--ink);
}
.evid p{margin:0 0 9px;font-size:14.5px;line-height:1.55;color:var(--mute)}
.evid a{
  font-size:13px;color:var(--mute);text-decoration:underline;
  text-underline-offset:3px;text-decoration-thickness:1px;
}
.evid a:hover{color:var(--ink)}

/* portrait clip — a vertical video wants a 9:16 frame, not a letterboxed 16:9 */
.now-clip{max-width:340px}
.now-clip .player{aspect-ratio:9/16;max-width:none;margin-bottom:18px}
.now-clip figcaption{margin:0;font-size:16px;line-height:1.6;color:var(--mute)}
.now-clip figcaption strong{color:var(--ink);font-weight:600}
.now-cta{margin:44px 0 0;text-align:center}

@media (max-width:900px){
  .now-grid{grid-template-columns:1fr;gap:38px}
  .now-clip{max-width:300px}
}
@media (max-width:760px){
  .section-now h2{max-width:none;margin-bottom:22px}
  .now-copy p{font-size:16.5px}
  .now-clip{max-width:none}
  .now-cta{margin-top:32px;text-align:left}
}

/* ---------------- guarantee ----------------
   A guarantee tied to effort, in the teacher's own words, with the one thing
   that makes it real: it is not the prize five people win — everybody gets it.
   That sentence is the section. */
.section-promise{background:var(--tint-3)}
.section-promise .section-inner{max-width:720px;text-align:left}
.section-promise h2{margin-bottom:12px}
.section-promise .sub{margin:0 0 30px;font-size:19px;line-height:1.45;color:var(--ink);max-width:24ch}
.vow{
  margin:0 0 26px;font-size:clamp(23px,2.7vw,30px);font-weight:var(--h-weight);
  letter-spacing:-.035em;line-height:1.3;color:var(--ink);
}
.sig{display:flex;align-items:center;gap:14px;margin:0 0 22px}
.sig img{width:52px;height:52px;border-radius:50%;object-fit:cover;flex:none;
  border:1px solid rgb(var(--ink-rgb) / .12)}
/* the one place a seventh face is allowed: a signature is a mark, not type */
.sig .nm{margin:0;font-family:"Caveat",cursive;font-size:30px;font-weight:600;
  letter-spacing:0;color:var(--ink);line-height:1}
.fine{margin:0 0 30px;font-size:15.5px;line-height:1.65;color:var(--mute)}
.fine strong{color:var(--ink);font-weight:600}
.promise-cta{text-align:center}

/* ---------------- faq ----------------
   <details> so it works with JavaScript off and reads correctly to a screen
   reader. The first one is open because an all-closed list looks like a wall. */
/* ======================================================================
   FAQ
   ----------------------------------------------------------------------
   The question list is the long column, so the heading and the CTA sit in a
   sticky rail beside it: the reader can open a fifth answer and still have
   somewhere to go. Below 900px that rail has nowhere to be, so the CTA
   moves under the list instead of being lost above five collapsed cards.

   The <details> elements are gone. A native disclosure cannot animate its
   own height, and one-open-at-a-time needs scripting anyway — a button with
   aria-expanded over a role="region" gives the same semantics and leaves the
   height to CSS. Enter and Space come free with a real <button>.
   ====================================================================== */
.section-faq .section-inner{max-width:1140px;text-align:left}

.fq-cols{display:grid;grid-template-columns:380px 1fr;gap:56px;align-items:start}
.fq-side{position:sticky;top:110px}
/* the literal is the light theme's; in dark mode this sits on the dark
   ground and measured 1:1, so it hands back to the mode's own ink */
.section-faq .eyebrow{color:#031A1D}
:root[data-mode="dark"] .section-faq .eyebrow{color:var(--ink)}
.section-faq h2{max-width:14ch;margin:0 0 26px}

.section-faq .fq-cta{
  display:inline-flex;background:#031A1D;color:#F4FCFD;border:1px solid transparent;
}
.section-faq .fq-cta:hover{background:#0D2C30}
.fq-cta-m{display:none;margin:30px 0 0;text-align:center}

/* ---- the cards ------------------------------------------------------ */
.fq-list{display:flex;flex-direction:column;gap:12px}

.fq-item{
  background:#fff;border:1px solid rgb(3 26 29 / .10);border-radius:16px;
  box-shadow:0 1px 2px rgb(3 26 29 / .04), 0 6px 18px -10px rgb(3 26 29 / .18);
  transition:border-color .38s ease, box-shadow .38s ease;
}
.fq-item.is-open{
  border-color:rgb(3 26 29 / .24);
  box-shadow:0 2px 4px rgb(3 26 29 / .06), 0 16px 34px -14px rgb(3 26 29 / .3);
}

.fq-q{margin:0;font-size:inherit;font-weight:inherit;letter-spacing:normal}
.fq-btn{
  display:flex;align-items:center;justify-content:space-between;gap:16px;width:100%;
  margin:0;padding:18px 20px;background:none;border:0;border-radius:16px;
  font-family:inherit;font-size:17px;font-weight:600;letter-spacing:-.02em;
  line-height:1.45;color:#031A1D;text-align:left;cursor:pointer;
}
.fq-btn:focus-visible{outline:2px solid #031A1D;outline-offset:3px}
.fq-t{flex:1}

/* a circle with a CSS plus; open, it turns over and the plus loses its stem */
.fq-ic{
  position:relative;flex:none;width:30px;height:30px;border-radius:50%;
  border:1px solid rgb(3 26 29 / .22);
  transition:transform .38s ease, background-color .38s ease, border-color .38s ease;
}
.fq-ic::before,.fq-ic::after{
  content:"";position:absolute;left:50%;top:50%;background:#031A1D;border-radius:1px;
  transition:background-color .38s ease, opacity .38s ease;
}
.fq-ic::before{width:11px;height:1.5px;margin:-.75px 0 0 -5.5px}
.fq-ic::after{width:1.5px;height:11px;margin:-5.5px 0 0 -.75px}
.fq-item.is-open .fq-ic{transform:rotate(180deg);background:#031A1D;border-color:#031A1D}
.fq-item.is-open .fq-ic::before{background:#F4FCFD}
.fq-item.is-open .fq-ic::after{opacity:0}

/* height is driven in px by the script, so the panel can animate and then
   settle on auto — a panel left at a fixed height cannot reflow */
/* Collapsed only once the script is present. <details> degraded to "all
   answers readable" with JavaScript off; a div does not, and height:0 by
   default would have hidden four answers with no way to reach them. */
.fq-a{height:auto;overflow:hidden;transition:height .38s ease}
.fq-list.js .fq-a{height:0}
.fq-a-in{padding:0 20px 20px;max-width:68ch}
.fq-a p{margin:0 0 10px;font-size:15.5px;line-height:1.65;color:#4f5a5c}
.fq-a p:last-child{margin-bottom:0}
.fq-a strong{color:#031A1D;font-weight:600}

/* ---- motion --------------------------------------------------------- */
.fq-item,.fq-side{opacity:0;transform:translateY(18px);
  transition:opacity .7s ease, transform .7s ease,
             border-color .38s ease, box-shadow .38s ease}
.fq-item.seen,.fq-side.seen{opacity:1;transform:none}

@media (max-width:900px){
  .fq-cols{grid-template-columns:1fr;gap:26px}
  .fq-side{position:static}
  .section-faq h2{max-width:none;margin-bottom:0}
  .section-faq .fq-cta{display:none}
  .fq-cta-m{display:block}
}
@media (max-width:760px){
  .fq-btn{font-size:16px;padding:16px 17px;gap:12px}
  .fq-a-in{padding:0 17px 17px}
  .fq-cta-m{text-align:center}
}

@media (prefers-reduced-motion:reduce){
  .fq-item,.fq-side{opacity:1;transform:none;transition:none}
  .fq-a{transition:none}
  .fq-ic,.fq-ic::before,.fq-ic::after{transition:none}
}

/* ---------------- closing recap ----------------
   Everything the reader needs to act, in one screen, with nothing new in it.
   A recap that introduces a fresh argument is a section, not a recap. */
.section-recap .section-inner{max-width:760px;text-align:center}
.section-recap .hand{
  margin:0 0 14px;font-family:"Caveat",cursive;font-size:25px;color:var(--mute);
  letter-spacing:0;
}
.section-recap h2{max-width:none;margin:0 auto 30px}
.recap-list{list-style:none;margin:0 0 30px;padding:0;border-top:1px solid var(--line);text-align:left}
.recap-list li{
  display:flex;align-items:center;gap:14px;padding:16px 4px;
  border-bottom:1px solid var(--line);font-size:16px;line-height:1.5;color:var(--mute);
}
.recap-list svg{width:18px;height:18px;flex:none;opacity:.55;fill:none;
  stroke:currentColor;stroke-width:1.6;stroke-linecap:round}
.recap-list strong{color:var(--ink);font-weight:600}
.recap-list .live{width:9px;height:9px;margin:0 4px}

/* ---------------- footer ---------------- */
.site-footer{
  position:relative;z-index:3;padding:42px 32px;
  display:flex;align-items:flex-start;justify-content:space-between;gap:30px;flex-wrap:wrap;
}
.site-footer .who{margin:0 0 5px;font-size:17px;font-weight:600;letter-spacing:-.025em;color:var(--ink)}
.site-footer .blurb{margin:0;font-size:14.5px;line-height:1.5;color:var(--mute);max-width:40ch}
.site-footer nav{display:flex;gap:26px;flex-wrap:wrap}
.site-footer a{font-size:14.5px;color:var(--mute);text-decoration:none}
.site-footer a:hover{color:var(--ink);text-decoration:underline;text-underline-offset:3px}
.site-footer .legal{width:100%;margin:14px 0 0;font-size:13px;line-height:1.6;color:var(--mute);opacity:.8}

@media (max-width:760px){
  .section-promise .sub{max-width:none;font-size:18px}
  .promise-cta{text-align:left}
  .section-faq h2{max-width:none}
  .section-recap .section-inner{text-align:left}
  .site-footer{flex-direction:column;gap:22px;padding:34px 20px}
  .site-footer nav{gap:14px 22px}
}


/* ======================================================================
   TWO GROUNDS, AND NOTHING ELSE
   ----------------------------------------------------------------------
   Everything below the hero sits on one of two families: an off-white that
   alternates between two values so neighbouring light sections separate
   without a rule, or the dark CTA shade. Cards are white on the light
   family and one step up from the ground on the dark one.

   The six-step tint ladder is collapsed into those card colours rather than
   deleted, because the cards across the page all paint with --tint-N; this
   way every one of them follows without touching its own rule.

   The hard hexes are the light theme's. Dark mode re-points the same three
   tokens at the palette it already has, so an off-white ground never ends up
   under near-white text.
   ====================================================================== */
:root{
  --ground-a:#FDFBF8;
  --ground-b:#F7F4F0;
  --card-light:#FFFFFF;
  --card-line:rgb(0 0 0 / .09);
}
:root[data-mode="dark"]{
  --ground-a:var(--bg);
  --ground-b:var(--surface);
  --card-light:var(--raised);
  --card-line:var(--line);
}

/* Light family, alternating in document order. Named rather than nth-of-type
   because the dark sections sit between them: what has to alternate is the
   light sections as the reader meets them, not every section. */
.section{ background:var(--ground-a) }
.section-curriculum,
.section-now,
.section-faq{ background:var(--ground-b) }

/* Dark family — LIGHT MODE ONLY.
   .section-invert flips its text tokens to the opposite mode's set, so in dark
   mode it is the page's LIGHT block and carries near-black ink. Forcing the
   dark ground on it there put that ink on #031A1D and measured 1.03:1. In dark
   mode it keeps the inverted surface the token system already builds for it,
   and the dark-ground role passes to every other section. */
/* This block's .section rule above is later in the file than the original
   .section-invert rule, so it repainted it. Hand the inverted ground back. */
:root[data-mode="dark"] .section-invert{ background:var(--inv-bg) }

:root[data-mode="light"] .section-invert,
:root[data-mode="light"] .unit-invert{
  background:var(--ground-dark);
  --tint-1:var(--card-dark); --tint-2:var(--card-dark); --tint-3:var(--card-dark);
  --tint-4:var(--card-dark); --tint-5:var(--card-dark); --tint-6:var(--card-dark);
  --surface:var(--card-dark); --raised:var(--card-dark);
  --line:var(--card-dark-line);
}
:root[data-mode="light"] .section-invert .card,
:root[data-mode="light"] .section-invert .unit,
:root[data-mode="light"] .section-invert [class*="box"]{ border:1px solid var(--card-dark-line) }

/* light-family cards: white, with the border doing the separating */
.section:not(.section-invert){
  --tint-1:var(--card-light); --tint-2:var(--card-light); --tint-3:var(--card-light);
  --tint-4:var(--card-light); --tint-5:var(--card-light); --tint-6:var(--card-light);
  --surface:var(--card-light); --raised:var(--card-light);
}
.section:not(.section-invert) .unit{
  background:var(--card-light); border:1px solid var(--card-line);
}

/* the alternation is the separator; the hairline between sections is not */
.section + .section{ border-top:0 }

/* ----------------------------------------------------------------------
   NO FADE BETWEEN SECTIONS
   The first section below the hero used to ramp into its colour at the top
   and back out to off-white at the bottom. Both are gone: a section ends on
   its own colour and the next one starts on its own.

   The bottom ramp was the visible one, and it read as haze — dark to
   off-white passes through grey, so a 90px band of it between two solid
   blocks looked like fog rather than a transition.

   The top ramp was never visible at all. It was written as var(--bg) into
   var(--ground-dark), but .section-invert remaps --bg to the INVERTED
   background, so it was fading rgb(6,11,21) into rgb(3,25,28) — two darks a
   few units apart. That boundary has always been a hard edge; the rule and
   the padding that cleared it were doing nothing but adding 36px of space.
   -------------------------------------------------------------------- */

/* ----------------------------------------------------------------------
   CTA
   One colour everywhere. On a dark section the button and the ground are
   the same shade, so the 1px light border is the only thing holding its
   edge — it is load-bearing, not decoration.
   -------------------------------------------------------------------- */
.cta, .nav-cta, .section-cta{
  background:var(--cta); color:var(--cta-ink); border:1px solid transparent;
}
.cta:hover, .nav-cta:hover, .section-cta:hover{ background:var(--cta-hover) }

:root[data-mode="light"] .section-invert .cta,
:root[data-mode="light"] .section-invert .nav-cta,
:root[data-mode="light"] .section-invert .section-cta,
:root[data-mode="light"] .unit-invert .cta,
:root[data-mode="light"] .unit-invert .section-cta,
/* in dark mode every block but .section-invert is the dark one, the hero
   and the nav included — neither sits inside a .section */
:root[data-mode="dark"] .cta,
:root[data-mode="dark"] .nav-cta,
:root[data-mode="dark"] .section-cta{ border-color:rgb(255 255 255 / .18) }
:root[data-mode="dark"] .section-invert .cta,
:root[data-mode="dark"] .section-invert .nav-cta,
:root[data-mode="dark"] .section-invert .section-cta{ border-color:transparent }

/* ======================================================================
   CURRICULUM TIMELINE
   ----------------------------------------------------------------------
   Four hours down a line. The time sits in its own column on the left so
   the eye can read the schedule without going through the cards; on a
   phone that column has nowhere to go, so the time moves above its card
   and the line keeps the left edge.

   The dot column is a fixed width and the track is centred in it, which is
   what lets the JS line up the fill with the real dot positions instead of
   guessing at percentages.
   ====================================================================== */
.section-curriculum .section-inner{max-width:1080px;text-align:left}

/* Small marks — the timeline's line and dots, and the bonus graphics — are
   the CTA colour, which is a near-black: on the dark page that is a dark mark
   on a dark card. Dark mode hands the same roles to the accent, which the ramp
   has already lifted to read there. One token for all of them, so a line and
   the dots on it can never disagree. */
:root{ --mark-ink:var(--cta); --mark-on-ink:var(--cta-ink) }
:root[data-mode="dark"]{ --mark-ink:var(--accent); --mark-on-ink:var(--accent-ink) }

.tl-pills{display:flex;flex-wrap:wrap;gap:8px;list-style:none;margin:0 0 38px;padding:0}
.tl-pills li{
  font-size:13px;font-weight:500;letter-spacing:-.005em;color:var(--ink);
  background:var(--card-light);border:1px solid var(--card-line);
  padding:7px 13px;border-radius:999px;
}

.tl-wrap{margin:0 0 30px}
.tl{list-style:none;margin:0;padding:0;position:relative}

.tl-row{
  display:grid;grid-template-columns:132px 44px 1fr;align-items:start;
  padding-bottom:26px;
}
.tl-row:last-child{padding-bottom:0}

.tl-when{display:flex;flex-direction:column;gap:3px;padding-top:7px;text-align:right}
.tl-time{font-size:14.5px;font-weight:600;letter-spacing:-.015em;color:var(--mark-ink)}
.tl-hour{font-size:12.5px;color:var(--mute)}

/* the dot column, and the track running down the middle of it */
.tl-mark{position:relative;display:flex;justify-content:center}
.tl-dot{
  position:relative;z-index:2;width:34px;height:34px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  font-size:11.5px;font-weight:700;letter-spacing:.01em;font-variant-numeric:tabular-nums;
  background:var(--card-light);border:1px solid var(--card-line);color:var(--ink);
  transition:background-color .45s ease,color .45s ease,border-color .45s ease;
}
.tl-dot.on{background:var(--mark-ink);border-color:var(--mark-ink);color:var(--mark-on-ink)}
/* one ring, once, when the line arrives */
.tl-dot.ping::after{
  content:"";position:absolute;inset:-5px;border-radius:50%;
  border:2px solid var(--mark-ink);animation:tl-ping .75s ease-out forwards;
}
@keyframes tl-ping{ from{opacity:.55;transform:scale(.85)} to{opacity:0;transform:scale(1.5)} }

.tl-track{
  position:absolute;left:calc(132px + 22px);top:10px;bottom:10px;width:2px;
  transform:translateX(-1px);background:var(--card-line);border-radius:2px;
}
.tl-fill{
  position:absolute;left:0;top:0;width:100%;height:0;
  background:var(--mark-ink);border-radius:2px;
}
/* the moving tip, which is only there while the line is still travelling */
.tl-tip{
  position:absolute;left:50%;top:0;width:9px;height:9px;margin-left:-4.5px;margin-top:-4.5px;
  border-radius:50%;background:var(--mark-ink);opacity:0;
  box-shadow:0 0 0 0 color-mix(in srgb, var(--mark-ink) 38%, transparent);
  animation:tl-pulse 1.5s ease-out infinite;
}
.tl-tip.on{opacity:1}
@keyframes tl-pulse{
  0%{box-shadow:0 0 0 0 color-mix(in srgb, var(--mark-ink) 38%, transparent)}
  70%{box-shadow:0 0 0 11px color-mix(in srgb, var(--mark-ink) 0%, transparent)}
  100%{box-shadow:0 0 0 0 color-mix(in srgb, var(--mark-ink) 0%, transparent)}
}

.tl-card{
  background:var(--card-light);border:1px solid var(--card-line);
  border-radius:13px;padding:20px 22px 21px;margin-left:8px;
}
.tl-kicker{
  font-size:11.5px;font-weight:700;letter-spacing:.085em;text-transform:uppercase;
  color:var(--mark-ink);margin:0 0 8px;
}
.tl-card h3{font-size:19px;font-weight:600;letter-spacing:-.022em;margin:0 0 12px;line-height:1.3;color:var(--ink)}
.tl-card ul{list-style:none;margin:0;padding:0}
.tl-card li{
  position:relative;padding-left:17px;margin-bottom:8px;
  font-size:14.5px;line-height:1.58;color:var(--mute);
}
.tl-card li:last-child{margin-bottom:0}
.tl-card li::before{
  content:"";position:absolute;left:0;top:.72em;width:9px;height:1.5px;background:var(--mark-ink);opacity:.75;
}
.tl-card strong{color:var(--ink);font-weight:600}

/* enter: cards and times come up slightly as they arrive */
.tl-when,.tl-card{opacity:0;transform:translateY(14px);
  transition:opacity .5s ease,transform .5s ease}
.tl-row.seen .tl-when,.tl-row.seen .tl-card{opacity:1;transform:none}

@media (max-width:760px){
  .tl-row{grid-template-columns:44px 1fr;padding-bottom:22px}
  .tl-mark{grid-column:1;grid-row:1 / span 2}
  .tl-when{grid-column:2;grid-row:1;flex-direction:row;align-items:baseline;gap:9px;
           text-align:left;padding:7px 0 9px}
  .tl-card{grid-column:2;grid-row:2;margin-left:0}
  .tl-track{left:22px}
}

/* ----------------------------------------------------------------------
   Reduced motion: the line is simply already full and nothing pulses.
   -------------------------------------------------------------------- */
@media (prefers-reduced-motion:reduce){
  .tl-fill{height:100% !important}
  .tl-tip{display:none}
  .tl-dot{background:var(--mark-ink);border-color:var(--mark-ink);color:var(--mark-on-ink)}
  .tl-dot.ping::after{display:none}
  .tl-when,.tl-card{opacity:1;transform:none;transition:none}
}

/* ======================================================================
   BONUS CARD GRAPHICS
   ----------------------------------------------------------------------
   Three small graphics, one per stub. The geometry and the motion curves
   come from the HyperFrames registry rather than being drawn by eye:

     calendar  <- stagger-cascade   (opacity 0->1, power2.out, 60ms apart)
     audit     <- success-check     (svg back.out(1.8), then a 36->0 dash)
     voucher   <- confetti          (seeded arcs: cos(i*.83), sin(i*.61))

   The components are built for a 1920x1080 video timeline, so what is kept
   is their shape and their easing; the trigger is swapped from timeline
   time to an IntersectionObserver in bonus-graphics.js.

   The stubs are white, so every mark is the CTA colour.
   ====================================================================== */
/* The stubs are painted with --base-* text, which ignores .section-invert but
   still follows the MODE, so their ground has to do the same: a hard white put
   near-white dark-mode ink on it (measured 1.11:1). These two are literals
   because the token set has no neutral surface that .section-invert leaves
   alone — every candidate is either remapped or blue-tinted, and the rule says
   no tints. White is the card colour the rule asks for. */
:root{ --stub:#ffffff }
:root[data-mode="dark"]{ --stub:#1c1f24 }
.bonus{ background:var(--stub) }

.bfx{
  position:relative;height:126px;margin:0 0 18px;
  border-radius:10px;overflow:hidden;
  background:color-mix(in srgb, var(--mark-ink) 5%, transparent);
}

/* ---- 01 · the month fills in ---------------------------------------- */
/* seven columns, five weeks. The width is capped so a day stays roughly
   square: stretched to the full card it read as a barcode, not a month. */
.cal-grid{
  position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);
  width:min(100% - 34px, 158px);
  display:grid;grid-template-columns:repeat(7,1fr);gap:3.5px;
}
.cal-c{aspect-ratio:1}
.cal-c{
  border-radius:2.5px;background:color-mix(in srgb, var(--mark-ink) 15%, transparent);
  opacity:0;
}
.cal-c.on{background:var(--mark-ink)}
.bfx-cal.go .cal-c{animation:bg-in .42s cubic-bezier(.22,.61,.36,1) forwards}

/* ---- 02 · the profile gets marked up -------------------------------- */
.bfx-audit{padding:16px 18px;display:flex;flex-direction:column;gap:9px;justify-content:center}
.au-head{display:flex;align-items:center;gap:8px}
.au-av{width:17px;height:17px;border-radius:50%;background:var(--mark-ink);opacity:.22;flex:none}
.au-name{height:6px;width:84px;border-radius:3px;background:var(--mark-ink);opacity:.3}
.au-row{display:flex;align-items:center;gap:9px}
.au-line{height:5px;flex:1;border-radius:3px;background:var(--mark-ink);opacity:.16}
.au-row:nth-child(3) .au-line{max-width:78%}
.au-row:nth-child(4) .au-line{max-width:58%}
.au-tick{
  width:20px;height:20px;flex:none;fill:none;
  stroke:var(--mark-ink);stroke-width:7;stroke-linecap:round;stroke-linejoin:round;
  opacity:0;
}
/* the dash length the component uses, so the draw reads the same */
.au-tick path{stroke-dasharray:36;stroke-dashoffset:36}
.bfx-audit.go .au-tick{animation:bg-pop .34s cubic-bezier(.18,1.3,.4,1) forwards}
.bfx-audit.go .au-tick path{animation:bg-draw .42s cubic-bezier(.22,.61,.36,1) forwards}
.bfx-audit.go .au-row:nth-child(2) .au-tick,
.bfx-audit.go .au-row:nth-child(2) .au-tick path{animation-delay:.18s}
.bfx-audit.go .au-row:nth-child(3) .au-tick,
.bfx-audit.go .au-row:nth-child(3) .au-tick path{animation-delay:.42s}
.bfx-audit.go .au-row:nth-child(4) .au-tick,
.bfx-audit.go .au-row:nth-child(4) .au-tick path{animation-delay:.66s}
/* a marker pass down the block, once */
.au-sweep{
  position:absolute;left:0;right:0;top:0;height:34px;pointer-events:none;opacity:0;
  background:linear-gradient(180deg,transparent,color-mix(in srgb, var(--mark-ink) 9%, transparent),transparent);
}
.bfx-audit.go .au-sweep{animation:bg-sweep 1.1s ease-out forwards}

/* ---- 03 · the voucher arrives --------------------------------------- */
.bfx-voucher{display:flex;align-items:center;justify-content:center}
.vo-card{
  position:relative;width:118px;height:52px;border-radius:7px;background:var(--mark-ink);
  display:flex;flex-direction:column;justify-content:center;gap:6px;padding:0 13px;
  opacity:0;
}
.vo-strip{height:5px;width:52px;border-radius:3px;background:var(--stub);opacity:.9}
.vo-amt{height:9px;width:34px;border-radius:3px;background:var(--stub);opacity:.55}
.bfx-voucher.go .vo-card{animation:bg-pop .4s cubic-bezier(.18,1.3,.4,1) forwards}

.vo-burst{position:absolute;left:50%;top:58%;width:0;height:0}
.vo-p{
  position:absolute;width:5px;height:5px;margin:-2.5px 0 0 -2.5px;border-radius:1px;
  background:var(--mark-ink);opacity:0;
}
.vo-p:nth-child(even){border-radius:50%}
.bfx-voucher.go .vo-p{animation:bg-fly .8s cubic-bezier(.22,.61,.36,1) forwards}

@keyframes bg-in   { to{opacity:1} }
@keyframes bg-pop  { from{opacity:0;transform:scale(.72) rotate(-18deg);filter:blur(7px)}
                     to{opacity:1;transform:none;filter:none} }
@keyframes bg-draw { to{stroke-dashoffset:0} }
@keyframes bg-sweep{ 0%{opacity:0;transform:translateY(-10px)} 25%{opacity:1}
                     100%{opacity:0;transform:translateY(126px)} }
/* the arcs are the confetti component's, scaled to a 96px box */
@keyframes bg-fly  { 0%{opacity:0;transform:none}
                     18%{opacity:1}
                     100%{opacity:0;
                       transform:translate(var(--dx),var(--dy)) rotate(var(--dr))} }

@media (max-width:760px){ .bfx{height:118px} }

@media (prefers-reduced-motion:reduce){
  .bfx-cal .cal-c{opacity:1;animation:none}
  .bfx-audit .au-tick{opacity:1;animation:none}
  .bfx-audit .au-tick path{stroke-dashoffset:0;animation:none}
  .bfx-audit .au-sweep{display:none}
  .bfx-voucher .vo-card{opacity:1;animation:none}
  .bfx-voucher .vo-burst{display:none}
}

/* ======================================================================
   REVEAL
   ----------------------------------------------------------------------
   One entrance, used everywhere: up 18px over .6s, once, on arrival. The
   markup declares it with data-reveal, or data-reveal-group on a parent to
   stagger its children — so what moves is visible in the HTML rather than
   buried in a selector list in here.

   Only opacity and transform, so nothing reflows while it plays and the
   page never jumps under a reader who is already reading.
   ====================================================================== */
[data-reveal],
[data-reveal-group] > *{
  opacity:0;transform:translateY(18px);
  transition:opacity .6s ease, transform .6s ease;
}
[data-reveal].seen,
[data-reveal-group] > .seen{ opacity:1;transform:none }

/* The drawn marks used to run 0.35s after load, with their section a whole
   page below the fold — the draw was always over before anyone saw it. They
   hold at zero length now and draw when the stat arrives. */
.mk-ring path,.mk-line path{ animation:none }
.stat.seen .mk-ring path,
.stat.seen .mk-line path{
  animation:draw-mark 1s .25s cubic-bezier(.22,.8,.3,1) forwards;
}

@media (prefers-reduced-motion:reduce){
  [data-reveal],
  [data-reveal-group] > *{ opacity:1;transform:none;transition:none }
  .mk-ring path,.mk-line path,
  .stat.seen .mk-ring path,.stat.seen .mk-line path{
    animation:none;stroke-dashoffset:0;
  }
}

/* ---- curriculum: the brochure download -------------------------------------
   A secondary action, deliberately quieter than the CTA beside it. It is for the
   reader who is interested but not ready, and taking it away from them behind an
   email form turns a warm reader into a cold lead -- so it is a direct link and
   it says so. Generated from sections/brochure.html by _generators/brochure.py;
   the two must never be edited apart. */
.cur-dl{
  display:flex; align-items:center; gap:14px; flex-wrap:wrap;
  max-width:560px; margin:26px auto 0; padding:15px 18px;
  background:var(--card-light); border:1px solid var(--card-line); border-radius:14px;
}
.cur-dl svg{ flex:none; width:26px; height:26px; fill:none;
  stroke:var(--mark-ink); stroke-width:1.7; stroke-linecap:round; stroke-linejoin:round }
.cur-dl .t{ flex:1 1 180px; min-width:0 }
.cur-dl .t b{ display:block; font-size:15px; font-weight:600; color:var(--ink); letter-spacing:-.01em }
.cur-dl .t span{ display:block; font-size:13px; color:var(--mute); margin-top:2px }
.cur-dl a{
  flex:none; font-size:14px; font-weight:600; text-decoration:none;
  color:var(--mark-ink); background:transparent;
  border:1px solid var(--mark-ink); border-radius:9px; padding:9px 16px;
  transition:background .18s ease, color .18s ease;
}
.cur-dl a:hover{ background:var(--mark-ink); color:var(--mark-on-ink) }
.cur-dl a:focus-visible{ outline:2px solid var(--mark-ink); outline-offset:3px }

@media (max-width:620px){
  .cur-dl{ gap:11px; padding:14px 15px }
  .cur-dl a{ width:100%; text-align:center }
}
