/* Toothpillow Myofunctional Exercises: standalone training course page.
   Built on tokens.css. MRC-style course layout, Toothpillow brand.
   2026-07-16 audit remediation pass: gradients purged (P1.3), tokens
   enforced (P2.1/P2.2/P3.2), type on the token scale (P1.9/P1.10/P2.3/P2.6),
   motion tokens + reduced-motion guard (P2.13), breakpoints 900/640 (P2.16). */

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  font-family: var(--font-sans);
  background: var(--tp-canvas);
  color: var(--fg-primary);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
img { display: block; max-width: 100%; }

/* iOS zooms focused form controls under 16px (audit P2.7); this surface has
   no input rules of its own, so pin the floor here. */
input, select, textarea { font-family: var(--font-sans); font-size: var(--fs-16); }

.wrap { max-width: 1180px; margin: 0 auto; padding: 0 28px; }

/* ============================ Top bar ================================= */
.nav {
  position: sticky; top: 0; z-index: 50;
  background: var(--tp-nav-glass);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  backdrop-filter: saturate(180%) blur(14px);
  border-bottom: 1px solid var(--tp-line);
}
.nav-inner {
  max-width: 1180px; margin: 0 auto; padding: 14px 28px;
  display: flex; align-items: center; gap: 18px;
}
/* flex-shrink:0 is load-bearing, not tidiness. The bar is a flex row and the
   wordmark was the only item able to shrink, so on a phone it was compressed
   from its natural 116px (at 22px tall) down to 23px. With object-fit:fill
   that is a 5x horizontal SQUASH, not a scale, so the logo was rendering
   distorted rather than merely small (measured 2026-08-31). */
.nav-logo, .nav-logo img { flex-shrink: 0; }
.nav-logo img { height: 22px; display: block; width: auto; }
.nav-tag {
  font-size: var(--fs-12); font-weight: 700; letter-spacing: var(--tracking-strapline);
  text-transform: uppercase; color: var(--fg-muted);
  padding-left: 16px; margin-left: 4px; border-left: 1px solid var(--tp-line);
}
.nav-spacer { flex: 1; }
.nav-prog {
  display: flex; align-items: center; gap: 10px;
  font-size: var(--fs-12); font-weight: 500; color: var(--fg-secondary);
}
.nav-prog .track {
  width: 90px; height: 7px; border-radius: var(--radius-pill);
  background: var(--tp-cream-300); overflow: hidden;
}
.nav-prog .fill { height: 100%; background: var(--tp-mint-green); transition: width var(--dur-slow) var(--ease-out); }

/* ============================ Buttons ================================= */
/* buttons.css is the CANONICAL .btn layer (audit P1.2, P2.6, P2.11). This
   block MIRRORS it for the bundled course surface, which may load without
   buttons.css at runtime. Keep the two in sync; edit buttons.css first. */
.btn {
  /* text-align matters only when the label WRAPS. justify-content centres the
     text node as one block, but the lines inside it inherit text-align:start,
     so "Book Appointment" broke as a left-ragged "Book" over "Appointment".
     Measured at 404px: line widths 30px and 79px, both flush left. */
  text-align: center;
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
  min-height: 44px; /* HIG / WCAG 2.5.8 touch target */
  border: 2px solid var(--tp-ink); background: var(--tp-sky-blue);
  color: var(--tp-ink); border-radius: var(--radius-pill);
  padding: var(--space-3) var(--space-6); font-family: var(--font-sans);
  font-weight: 500; font-size: var(--fs-14);
  /* Was --lh-tight, which computes to 1.05. On a single-line button that is
     fine, but when a label wraps the line boxes end up SHORTER than the
     glyphs: measured at 404px the two lines of "Book Appointment"
     overlapped by 5px. 1.25 separates them; min-height:44px means
     single-line buttons do not change height. */
  line-height: 1.25;
  letter-spacing: 0.01em;
  cursor: pointer; text-decoration: none;
  transition: transform var(--dur-fast) var(--ease-out), background var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out);
}
.btn:hover { transform: translateY(-1px); box-shadow: var(--shadow-sm); }
.btn:active { transform: translateY(0); box-shadow: var(--shadow-xs); }
.btn.secondary { background: transparent; }
.btn.secondary:hover { background: var(--ink-ghost); } /* mirror of buttons.css review fix */
.btn.cream { background: var(--tp-cream); }
.btn.cream:hover { background: var(--tp-cream-200); }
.btn.sm { padding: var(--space-2) var(--space-4); font-size: var(--fs-12); }
.btn .arr { width: 14px; height: 14px; flex-shrink: 0; }
/* unified disabled recipe (audit P2.11), mirrors buttons.css */
.btn:disabled,
.btn.btn-disabled {
  background: var(--tp-cream-200); border-color: var(--tp-line); color: var(--fg-muted);
  opacity: 0.6; pointer-events: none; cursor: not-allowed;
  transform: none; box-shadow: none;
}

.tlink {
  background: none; border: none; padding: 4px 0; cursor: pointer;
  font-family: var(--font-sans); font-weight: 500; font-size: var(--fs-14);
  color: var(--fg-primary); display: inline-flex; align-items: center; gap: 7px;
  border-bottom: 2px solid transparent;
}
.tlink:hover { border-bottom-color: currentColor; }

/* ============================ Hero =================================== */
.hero { padding: 46px 0 8px; }
.hero-grid {
  display: grid; grid-template-columns: 1fr; gap: 52px; align-items: center;
}
.hero-col { max-width: 680px; }
.eyebrow {
  font-size: var(--fs-12); font-weight: 700; letter-spacing: var(--tracking-strapline);
  text-transform: uppercase; color: var(--fg-secondary); margin: 0 0 16px;
}
.hero h1 {
  font-family: var(--font-display); font-weight: 400;
  font-size: clamp(40px, 5vw, 68px); line-height: var(--lh-tight);
  margin: 0 0 18px; letter-spacing: 0; /* Bigola ships at 0% tracking (P3.1) */
}
.hero-tag {
  font-size: var(--fs-18); line-height: var(--lh-relaxed); color: var(--fg-secondary);
  margin: 0 0 22px; max-width: 520px; text-wrap: pretty;
}
/* 26px below was right when this block ended with an avatar and stood alone.
   With the avatar gone (2026-08-31) the name, bio and credential line are one
   unit, so the name no longer needs a section-sized gap under it. 4px here
   plus the bio's own 12px top margin gives 16px. */
.presenter {
  display: flex; align-items: center; gap: 12px; margin: 0 0 4px;
}
.presenter .ava {
  width: 44px; height: 44px; border-radius: var(--radius-pill); flex-shrink: 0;
  background: var(--tp-bubblegum-100); /* flat tint, gradient purged (P1.3) */
  color: var(--tp-ink); font-weight: 700; font-size: var(--fs-16);
  display: flex; align-items: center; justify-content: center;
  border: 2px solid #fff; box-shadow: var(--shadow-xs);
}
.presenter .who b { font-size: var(--fs-14); display: block; }
.presenter .who span { font-size: var(--fs-12); color: var(--fg-muted); }

.meta-row {
  display: flex; flex-wrap: wrap; gap: 0; margin: 0 0 26px;
  border: 1px solid var(--tp-line); border-radius: var(--radius-inner); overflow: hidden;
  background: #fff; width: fit-content; max-width: 100%;
}
.meta-row .m {
  padding: 12px 20px; display: flex; flex-direction: column; gap: 2px;
  border-right: 1px solid var(--tp-line);
}
.meta-row .m:last-child { border-right: none; }
/* Bigola below 19px reads smeared; stat numerals are Cerco bold (P1.9) */
.meta-row .m b { font-size: var(--fs-16); font-weight: 700; font-family: var(--font-sans); }
.meta-row .m span { font-size: var(--fs-12); letter-spacing: var(--tracking-wide); text-transform: uppercase; color: var(--fg-muted); }

.hero-cta { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; }
.hero-prog {
  margin: 26px 0 0; display: flex; align-items: center; gap: 14px;
  font-size: var(--fs-14); color: var(--fg-secondary); font-weight: 500;
}
.hero-prog .track { flex: 1; max-width: 340px; height: 8px; border-radius: var(--radius-pill); background: var(--tp-cream-300); overflow: hidden; }
.hero-prog .fill { height: 100%; background: var(--tp-mint-green); transition: width var(--dur-slow) var(--ease-out); }

/* video player */
.player {
  position: relative; border-radius: var(--radius-card); overflow: hidden;
  aspect-ratio: 16 / 9; cursor: pointer;
  background: var(--tp-sky-blue-700); /* flat poster fill, gradient purged (P1.3) */
  box-shadow: var(--shadow-lg);
}
.player .poster {
  position: absolute; inset: 0;
  /* pinstripe + radial texture removed (P1.3): flat fill comes from .player */
  display: flex; align-items: center; justify-content: center; flex-direction: column; gap: 16px;
}
.player .play {
  width: 78px; height: 78px; transition: transform var(--dur-base) var(--ease-out);
  filter: drop-shadow(0 8px 18px rgba(29, 42, 58, 0.18)); /* ink-tinted (P2.9) */
}
.player:hover .play { transform: scale(1.06); }
.player .pill {
  position: absolute; top: 16px; left: 16px;
  display: flex; align-items: center; gap: 8px;
  background: rgba(255,255,255,.16); color: #fff;
  padding: 6px 13px; border-radius: var(--radius-pill);
  font-size: var(--fs-12); font-weight: 700; letter-spacing: var(--tracking-wide); text-transform: uppercase;
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
}
.player .pill .dot { width: 6px; height: 6px; border-radius: var(--radius-pill); background: var(--tp-mint-green); }
.player .titlebar {
  position: absolute; left: 16px; bottom: 16px; right: 16px;
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
}
.player .titlebar .t {
  background: var(--tp-cream); color: var(--tp-ink);
  padding: 8px 15px; border-radius: var(--radius-pill); font-size: var(--fs-14); font-weight: 700;
}
.player .titlebar .d {
  background: var(--scrim-pill); color: #fff; padding: 6px 11px;
  border-radius: var(--radius-pill); font-size: var(--fs-12); font-weight: 500; font-variant-numeric: tabular-nums;
}
/* dev-note restyled as a Cerco caption (P3.5); on-color because it sits on
   the dark sky-700 poster where --fg-muted would fail contrast */
.player .ph-note {
  font-family: var(--font-sans); font-size: var(--fs-14);
  color: var(--fg-on-color);
}
.player.playing { cursor: default; }
.player .embed, .mini-player .embed {
  position: absolute; inset: 0; width: 100%; height: 100%;
  border: 0; display: block; background: #000;
}

/* ============================ Section frame ========================== */
.sec { padding: 56px 0; }
.sec.alt { background: var(--tp-cream-50); border-top: 1px solid var(--tp-line); border-bottom: 1px solid var(--tp-line); }
.sec-head { margin: 0 0 30px; }
.sec-head .strap {
  font-size: var(--fs-12); font-weight: 700; letter-spacing: var(--tracking-strapline); text-transform: uppercase;
  color: var(--fg-muted); margin: 0 0 10px;
}
.sec-head h2 {
  font-family: var(--font-display); font-weight: 400;
  font-size: clamp(30px, 3.4vw, 44px); line-height: var(--lh-tight); margin: 0; letter-spacing: 0;
}
.sec-head p { margin: 12px 0 0; font-size: var(--fs-16); line-height: var(--lh-relaxed); color: var(--fg-secondary); max-width: var(--measure-wide); }

/* ---- Meet your guide + contact (Myo team merge 2026-07-16) ---- */
#guide { padding-bottom: 0; }
.guide-card {
  background: var(--tp-cream-200); border: 1px solid var(--tp-line);
  border-radius: var(--radius-card); padding: 28px;
}
.guide-card .strap {
  font-size: var(--fs-12); font-weight: 700; letter-spacing: var(--tracking-strapline); text-transform: uppercase;
  color: var(--fg-muted); margin: 0 0 14px;
}
.guide-head { display: flex; align-items: center; gap: 14px; margin: 0 0 12px; }
.guide-ava {
  width: 56px; height: 56px; border-radius: var(--radius-pill); flex-shrink: 0;
  background: var(--tp-bubblegum-100); color: var(--tp-ink);
  font-weight: 700; font-size: var(--fs-18);
  display: flex; align-items: center; justify-content: center;
  border: 2px solid #fff; box-shadow: var(--shadow-xs);
}
.guide-who h3 { font-family: var(--font-display); font-weight: 400; font-size: var(--fs-24); margin: 0; }
.guide-who span { font-size: var(--fs-12); color: var(--fg-muted); }
.guide-bio {
  margin: 0 0 18px; font-size: var(--fs-16); line-height: var(--lh-relaxed);
  color: var(--fg-secondary); max-width: var(--measure-wide);
}
.cred-row { display: flex; gap: 12px; flex-wrap: wrap; }
.cred-card {
  background: var(--tp-card); border: 1px solid var(--tp-line); border-radius: var(--radius-inner);
  padding: 12px 16px; flex: 1; min-width: 180px;
}
.cred-card b { display: block; font-size: var(--fs-14); }
.cred-card span { display: block; font-size: var(--fs-12); color: var(--fg-muted); margin-top: 2px; }
#contactSec { padding-top: 0; }
.contact-card {
  background: var(--tp-card); border: 1px solid var(--tp-line); border-radius: var(--radius-card);
  padding: 26px 28px; display: flex; gap: 10px; align-items: flex-start;
  flex-direction: column;
}
.contact-card h3 { font-family: var(--font-display); font-weight: 400; font-size: var(--fs-24); margin: 0; }
.contact-card p { margin: 0; font-size: var(--fs-16); color: var(--fg-secondary); max-width: 58ch; }
.contact-card a { color: inherit; font-weight: 600; text-decoration: underline; text-underline-offset: 2px; }
@media (max-width: 640px) {
  /* The top bar carries the progress readout, the logo and the CTA, and on a
     phone there is not room for all three at honest proportions. The nav
     progress is the one to drop: it is the THIRD copy on screen (the hero and
     the menu drawer both show it, and both say "1 of 10 modules" rather than
     this one's bare "10%"), so nothing is lost, and it frees the 120px the
     wordmark needs to render at full size undistorted. */
  .nav-prog { display: none; }
  .nav-logo img { height: 26px; }
}

/* Narrow phones (iPhone SE and similar at 320px). flex-shrink:0 protects the
   wordmark's proportions, but that means it can no longer absorb a squeeze, so
   below this width the bar has to be given room explicitly or it would overflow
   instead. Arithmetic at 320: 24 padding + 44 burger + 95 logo + 115 button +
   2x8 gap = 294, inside 320 with headroom. */
@media (max-width: 380px) {
  .nav-inner { gap: 8px; padding-left: 12px; padding-right: 12px; }
  .nav-logo img { height: 18px; }

  .guide-card { padding: 20px; border-radius: var(--radius-card-mobile); }
  .contact-card { border-radius: var(--radius-card-mobile); }
}

/* overview */
.overview-grid { display: grid; grid-template-columns: 1.3fr 1fr; gap: 48px; align-items: start; }
.overview-grid .body p { font-size: var(--fs-16); line-height: var(--lh-relaxed); color: var(--fg-secondary); margin: 0 0 18px; }
.learn-card {
  background: var(--tp-sky-blue); border-radius: var(--radius-card);
  padding: 28px 30px;
}
.learn-card h3 { font-family: var(--font-sans); font-weight: 700; font-size: var(--fs-16); margin: 0 0 18px; }
.learn-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 14px; }
.learn-list li { display: flex; gap: 12px; align-items: flex-start; font-size: var(--fs-14); line-height: var(--lh-normal); color: var(--fg-primary); }
.learn-list .tick {
  width: 22px; height: 22px; border-radius: var(--radius-pill); flex-shrink: 0; margin-top: 1px;
  background: var(--tp-cream); display: flex; align-items: center; justify-content: center;
}

/* phase summary cards */
.phase-cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; margin-top: 38px; }
.pcard {
  border-radius: var(--radius-card); padding: 26px; color: var(--fg-primary);
  display: flex; flex-direction: column; gap: 12px; min-height: 220px;
}
.pcard.peach { background: var(--tp-peach); }
.pcard.mint  { background: var(--tp-mint-green); }
.pcard.sky   { background: var(--tp-sky-blue); }
/* solid ink-2 instead of the .65 opacity trick that fell under AA (P2.14) */
.pcard .pno { font-size: var(--fs-12); font-weight: 700; letter-spacing: var(--tracking-strapline); text-transform: uppercase; color: var(--tp-ink-2); }
.pcard h4 { font-family: var(--font-display); font-weight: 400; font-size: var(--fs-32); line-height: var(--lh-tight); margin: 0; }
.pcard .psub { font-size: var(--fs-14); font-weight: 700; margin: -4px 0 0; }
.pcard p { font-size: var(--fs-14); line-height: var(--lh-relaxed); color: var(--tp-ink-2); margin: 4px 0 0; }
.pcard .pfoot { margin-top: auto; padding-top: 14px; display: flex; gap: 16px; font-size: var(--fs-12); font-weight: 500; }
.pcard .pfoot .x { opacity: .55; }

/* ============================ Curriculum ============================ */
.phase-block { margin-bottom: 40px; }
.phase-block:last-child { margin-bottom: 0; }
.phase-bar {
  display: flex; align-items: center; gap: 16px; padding: 0 4px 16px;
}
.phase-bar .dot {
  width: 14px; height: 14px; border-radius: var(--radius-pill); flex-shrink: 0;
}
.phase-bar .dot.peach { background: var(--tp-peach); }
.phase-bar .dot.mint  { background: var(--tp-mint-green); }
.phase-bar .dot.sky   { background: var(--tp-sky-blue); }
.phase-bar .ptitle { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.phase-bar .ptitle .no { font-size: var(--fs-12); font-weight: 700; letter-spacing: var(--tracking-strapline); text-transform: uppercase; color: var(--fg-muted); }
.phase-bar .ptitle h3 { font-family: var(--font-display); font-weight: 400; font-size: var(--fs-24); line-height: var(--lh-tight); margin: 0; }
.phase-bar .ptitle .sub { font-size: var(--fs-14); color: var(--fg-secondary); }
.phase-bar .pmeta { margin-left: auto; font-size: var(--fs-12); color: var(--fg-muted); display: flex; gap: 16px; }
.phase-bar .pmeta .pphase-prog { font-weight: 700; color: var(--fg-secondary); }

.lessons { display: grid; gap: 10px; }
.lesson {
  background: var(--tp-card); border: 1px solid var(--tp-line); border-radius: 18px;
  overflow: hidden; transition: box-shadow var(--dur-base) var(--ease-out), border-color var(--dur-base) var(--ease-out);
}
.lesson:hover { box-shadow: var(--shadow-sm); }
.lesson.open { box-shadow: var(--shadow-md); border-color: transparent; }
.lesson-head {
  display: grid; grid-template-columns: 42px 1fr auto auto auto; gap: 18px;
  align-items: center; padding: 15px 20px; cursor: pointer;
}
/* number chip: Cerco bold, not sub-19px Bigola (P1.9) */
.lesson .num {
  width: 38px; height: 38px; border-radius: var(--radius-pill); display: flex; align-items: center; justify-content: center;
  background: var(--tp-cream-200); font-weight: 700; font-size: var(--fs-14); color: var(--fg-secondary);
  font-family: var(--font-sans);
}
.lesson.done .num { background: var(--tp-mint-green); color: var(--tp-ink); }
.lesson .lh-body h4 { margin: 0 0 3px; font-size: var(--fs-16); font-weight: 700; line-height: var(--lh-snug); }
.lesson .lh-body p { margin: 0; font-size: var(--fs-12); color: var(--fg-secondary); line-height: var(--lh-normal); }

/* The module title is a real <button> so the accordion is keyboard operable.
   Before this, .lesson-head was a plain div with a click listener, so no
   keyboard or screen reader user could open any of the ten modules.
   The button carries no visual weight of its own: it inherits the h4. */
.lesson .lh-body h4 .lesson-toggle {
  appearance: none; -webkit-appearance: none;
  background: none; border: 0; margin: 0; padding: 0;
  font: inherit; color: inherit; text-align: left; letter-spacing: inherit;
  cursor: pointer; width: 100%; display: block;
}
/* "Module 3: " for screen readers only. The .num chip is aria-hidden, so
   without this the button announces a bare title with no position. */
.lt-no {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}
/* Duration lives in the .dur grid column on desktop. Below 640px that column
   is dropped to stop the chevron wrapping (P2.17), which also removed the one
   fact a parent needs to decide whether to start tonight. This puts it back
   inline, inside the title, without touching the grid. */
.lt-dur { display: none; }
.lesson .dur { font-size: var(--fs-12); color: var(--fg-muted); font-variant-numeric: tabular-nums; }
.lesson .state {
  width: 22px; height: 22px; border-radius: var(--radius-pill); border: 2px solid var(--tp-line);
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
}
.lesson.done .state { background: var(--tp-mint-green); border-color: var(--tp-mint-green); }
.lesson.done .state .chk { display: block; }
.lesson .state .chk { display: none; }
.lesson .chev { width: 18px; height: 18px; color: var(--fg-muted); transition: transform var(--dur-base) var(--ease-out); }
.lesson.open .chev { transform: rotate(180deg); }

/* expanded body */
.lesson-body { display: none; padding: 0 20px 22px; }
.lesson.open .lesson-body { display: block; }
.lesson-body-inner {
  border-top: 1px solid var(--tp-line); padding-top: 20px;
  /* Was a fixed 300px video column. With no breakpoint between 640 and 900,
     a 660px tablet gave the video 300px and the prose 292px, so an iPad
     rendered a SMALLER video and NARROWER text than a 390px iPhone. A
     proportional column keeps the video subordinate to the prose at every
     width in that band. */
  display: grid; grid-template-columns: minmax(220px, 40%) 1fr; gap: 26px; align-items: start;
}
.mini-player {
  position: relative; border-radius: var(--radius-inner); overflow: hidden; aspect-ratio: 16/9;
  background: var(--tp-sky-blue-700); cursor: pointer; /* flat poster (P1.3) */
}
.mini-player .mp-poster {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  /* pinstripe texture removed (P1.3) */
}
.mini-player .play { width: 52px; height: 52px; transition: transform var(--dur-base) var(--ease-out); }
.mini-player:hover .play { transform: scale(1.07); }
.mini-player .mp-dur {
  position: absolute; right: 10px; bottom: 10px; background: var(--scrim-pill); color: #fff;
  padding: 4px 9px; border-radius: var(--radius-pill); font-size: var(--fs-12); font-weight: 500;
}
.mp-col { display: flex; flex-direction: column; gap: 9px; }
/* dev-note restyled as Cerco caption (P3.5) */
.mp-note { font-family: var(--font-sans); font-size: var(--fs-14); line-height: var(--lh-normal); color: var(--fg-muted); }
.mini-player.kids { box-shadow: 0 0 0 3px var(--tp-yellow), var(--shadow-sm); }
.mini-player .real-video {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; background: #000; display: block;
}
.mini-player.playing { cursor: default; }
.kid-pill {
  position: absolute; top: 10px; left: 10px; z-index: 2;
  background: var(--tp-yellow); color: var(--tp-ink);
  padding: 5px 11px; border-radius: var(--radius-pill);
  font-size: var(--fs-12); font-weight: 700; letter-spacing: .01em;
  box-shadow: var(--shadow-sm);
}
.vchip {
  display: inline-flex; align-items: center; gap: 4px; vertical-align: middle;
  margin-left: 7px; background: var(--tp-mint-green); color: var(--tp-ink);
  font-size: var(--fs-12); font-weight: 700; letter-spacing: .04em;
  padding: 2px 8px 2px 7px; border-radius: var(--radius-pill);
}
.vchip.doc { background: var(--tp-yellow); }
/* printable workbook panel (non-video module) */
.pdf-panel {
  position: relative; border-radius: var(--radius-inner); overflow: hidden; aspect-ratio: 16/9;
  background: var(--tp-cream-200); /* flat panel, gradient purged (P1.3) */
  border: 1px solid var(--tp-line); box-shadow: var(--shadow-sm); /* was var(--border), undefined (P2.1) */
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 12px; padding: 18px; text-align: center;
}
.pdf-panel .doc-ico {
  width: 46px; height: 46px; display: flex; align-items: center; justify-content: center;
  border-radius: 13px; background: var(--tp-yellow); color: var(--tp-ink);
  box-shadow: var(--shadow-sm);
}
/* dev-note restyled as Cerco caption (P3.5) */
.pdf-panel .pp-meta { font-family: var(--font-sans); font-size: var(--fs-14); color: var(--fg-muted); }
.pdf-panel .pp-open {
  display: inline-flex; align-items: center; gap: 7px;
  background: var(--tp-ink); color: #fff; text-decoration: none;
  font-size: var(--fs-14); font-weight: 700; padding: 9px 16px; border-radius: var(--radius-pill);
  transition: transform var(--dur-base) var(--ease-out);
}
.pdf-panel .pp-open:hover { transform: translateY(-1px); }
.celebrate {
  position: absolute; inset: 0; z-index: 3; pointer-events: none;
  display: flex; align-items: center; justify-content: center; overflow: hidden;
}
.celebrate .star-toast {
  background: var(--tp-cream); color: var(--tp-ink);
  padding: 10px 18px; border-radius: var(--radius-pill); font-weight: 700; font-size: var(--fs-14);
  box-shadow: var(--shadow-lg); animation: starpop var(--dur-slow) var(--ease-bounce);
}
@keyframes starpop { from { opacity: 0; transform: scale(.8) translateY(6px); } to { opacity: 1; transform: scale(1) translateY(0); } }
.celebrate .cf-star {
  position: absolute; bottom: 22%; color: var(--tp-yellow);
  animation: cf-float 2.2s var(--ease-out) forwards; opacity: 0;
  text-shadow: 0 2px 5px rgba(29, 42, 58, 0.15); /* ink-tinted (P2.9) */
}
@keyframes cf-float {
  0% { opacity: 0; transform: translateY(20px) rotate(0deg); }
  20% { opacity: 1; }
  100% { opacity: 0; transform: translateY(-130px) rotate(200deg); }
}

.lb-points h5 {
  font-size: var(--fs-12); letter-spacing: var(--tracking-strapline); text-transform: uppercase; color: var(--fg-muted);
  margin: 0 0 14px; font-weight: 700;
}
.takeaways { display: grid; gap: 12px; margin: 0 0 18px; }
.takeaway { display: flex; gap: 13px; align-items: flex-start; }
/* numeral chip: Cerco bold, not sub-19px Bigola (P1.9) */
.takeaway .tn {
  width: 26px; height: 26px; border-radius: var(--radius-pill); flex-shrink: 0; margin-top: 1px;
  background: var(--tp-peach); display: flex; align-items: center; justify-content: center;
  font-family: var(--font-sans); font-size: var(--fs-12); font-weight: 700; color: var(--tp-ink);
}
.takeaway p { margin: 2px 0 0; font-size: var(--fs-14); line-height: var(--lh-relaxed); }
.callout {
  background: var(--tp-cream-200); border-radius: 14px; padding: 14px 16px;
  font-size: var(--fs-14); line-height: var(--lh-relaxed); color: var(--fg-secondary); margin: 0 0 18px;
  display: flex; gap: 11px; align-items: flex-start;
}
.callout .ci { flex-shrink: 0; font-size: var(--fs-16); }
.glossary { display: flex; gap: 8px; flex-wrap: wrap; margin: 0 0 10px; }
.glossary .term {
  background: var(--tp-cream-200); padding: 6px 12px; border-radius: var(--radius-pill);
  font-size: var(--fs-12); font-weight: 500; border: 1px solid var(--tp-line); color: var(--fg-secondary);
  font-family: var(--font-sans); cursor: pointer;
  transition: background var(--dur-base) var(--ease-out), border-color var(--dur-base) var(--ease-out);
}
.glossary .term:hover { background: var(--tp-cream-300); }
.glossary .term.on { background: var(--tp-sky-blue-100, #eaf3ff); border-color: var(--tp-sky-blue-600); color: var(--tp-ink); }
.gloss-def {
  margin: 0 0 20px; padding: 12px 16px; background: var(--tp-inset);
  border: 1px solid var(--tp-line); border-radius: var(--radius-inner);
  font-size: var(--fs-14); line-height: var(--lh-relaxed); color: var(--fg-secondary);
  max-width: var(--measure-wide);
}
.gloss-def b { color: var(--fg-primary); font-weight: 700; }
.gloss-tip {
  position: absolute; z-index: 60; width: min(340px, 92%);
  background: var(--tp-float); border: 1px solid var(--tp-line); border-radius: var(--radius-inner);
  box-shadow: var(--shadow-md, 0 8px 24px rgba(29, 42, 58, .12));
  padding: 10px 14px; font-family: var(--font-sans); font-size: var(--fs-12);
  line-height: var(--lh-relaxed); color: var(--fg-secondary); pointer-events: none;
}
.lb-actions { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-top: 20px; }
.mark-btn {
  display: inline-flex; align-items: center; gap: 9px; cursor: pointer;
  border: 2px solid var(--tp-ink); background: transparent; color: var(--fg-primary);
  border-radius: var(--radius-pill); padding: .6rem 1.3rem; font-family: var(--font-sans);
  font-weight: 500; font-size: var(--fs-14); transition: background var(--dur-base) var(--ease-out);
}
.mark-btn:hover { background: var(--ink-ghost); }
.lesson.done .mark-btn { background: var(--tp-mint-green); border-color: var(--tp-mint-green); }
.mark-btn .mb-box {
  width: 18px; height: 18px; border-radius: 6px; border: 2px solid currentColor;
  display: flex; align-items: center; justify-content: center;
}
.mark-btn .mb-box .chk { display: none; }
.lesson.done .mark-btn .mb-box { background: var(--tp-ink); border-color: var(--fg-primary); }
.lesson.done .mark-btn .mb-box .chk { display: block; }

/* ---- What to spot banner ---- */
.spot {
  display: flex; gap: 12px; align-items: flex-start;
  background: var(--tp-sky-blue-50); border: 1px solid var(--tp-line-2);
  border-radius: 14px; padding: 13px 15px; margin: 0 0 18px;
}
.spot-ico {
  width: 30px; height: 30px; border-radius: 9px; flex-shrink: 0;
  background: var(--tp-sky-blue); display: flex; align-items: center; justify-content: center;
}
/* sky-600 on the sky-50 tint: accent-strong measured 3.72:1 there (P2.14) */
.spot-strap {
  display: block; margin-bottom: 3px;
  font-size: var(--fs-12); font-weight: 700; letter-spacing: var(--tracking-strapline); text-transform: uppercase;
  color: var(--tp-sky-blue-600);
}
.spot p { margin: 0; font-size: var(--fs-14); line-height: var(--lh-relaxed); color: var(--fg-primary); }

/* ---- Try this at home ---- */
.activity {
  margin-top: 20px; background: var(--tp-cream-50);
  border: 1px solid var(--tp-line); border-radius: 18px; padding: 20px 22px;
}
.act-head { display: flex; align-items: center; gap: 13px; margin-bottom: 16px; }
.act-ico {
  width: 38px; height: 38px; border-radius: 11px; flex-shrink: 0;
  background: var(--tp-yellow); display: flex; align-items: center; justify-content: center;
}
.act-strap {
  display: block;
  font-size: var(--fs-12); font-weight: 700; letter-spacing: var(--tracking-strapline); text-transform: uppercase;
  color: var(--fg-muted);
}
.act-head h5 { margin: 2px 0 0; font-family: var(--font-display); font-weight: 400; font-size: var(--fs-20); line-height: var(--lh-tight); }
.act-steps { margin: 0; padding: 0; list-style: none; counter-reset: step; display: grid; gap: 11px; }
.act-steps li {
  position: relative; padding-left: 34px; counter-increment: step;
  font-size: var(--fs-14); line-height: var(--lh-relaxed); color: var(--fg-primary);
}
/* step numeral: Cerco bold, not sub-19px Bigola (P1.9) */
.act-steps li::before {
  content: counter(step); position: absolute; left: 0; top: -1px;
  width: 23px; height: 23px; border-radius: var(--radius-pill);
  background: var(--tp-yellow); color: var(--tp-ink);
  font-family: var(--font-sans); font-size: var(--fs-12); font-weight: 700;
  display: flex; align-items: center; justify-content: center;
}
.act-need {
  display: flex; flex-wrap: wrap; gap: 8px; align-items: center;
  margin-top: 16px; padding-top: 15px; border-top: 1px dashed var(--tp-line);
}
.need-label {
  font-size: var(--fs-12); font-weight: 700; letter-spacing: var(--tracking-strapline); text-transform: uppercase;
  color: var(--fg-muted); margin-right: 2px;
}
.need-chip {
  background: #fff; border: 1px solid var(--tp-line); border-radius: var(--radius-pill);
  padding: 5px 12px; font-size: var(--fs-12); font-weight: 500; color: var(--fg-secondary);
}

/* ---- Right way vs. what to watch for ---- */
.compare { margin-top: 20px; }
.cmp-head { margin-bottom: 14px; }
.cmp-strap {
  display: block; margin-bottom: 5px;
  font-size: var(--fs-12); font-weight: 700; letter-spacing: var(--tracking-strapline); text-transform: uppercase;
  color: var(--fg-muted);
}
.cmp-head h5 { margin: 0; font-family: var(--font-display); font-weight: 400; font-size: var(--fs-20); line-height: var(--lh-tight); }
.cmp-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.cmp-card { border-radius: 18px; padding: 16px; border: 2px solid; }
/* tint + flag tokens replace hand-rolled hexes (P2.2) */
.cmp-card.right { background: var(--tp-mint-50); border-color: var(--tp-mint-green); }
.cmp-card.wrong { background: var(--tp-peach-50); border-color: var(--tp-peach); }
.cmp-tag {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: var(--fs-12); font-weight: 700; padding: 5px 13px 5px 10px;
  border-radius: var(--radius-pill); margin-bottom: 13px;
}
.cmp-card.right .cmp-tag { background: var(--tp-mint-green); color: var(--tp-ink); }
.cmp-card.wrong .cmp-tag { background: var(--tp-peach); color: var(--tp-flag-ink); }
.cmp-card image-slot { margin-bottom: 4px; }
.cmp-noimg {
  border: 1.5px dashed var(--tp-line); border-radius: var(--radius-inner);
  padding: 22px 16px; text-align: center; font-size: var(--fs-12); color: var(--fg-muted);
  background: rgba(255, 255, 255, .55);
}
.mini-player, .ex-video { position: relative; }
.vid-expand {
  position: absolute; top: 10px; right: 10px; z-index: 5;
  display: inline-flex; align-items: center; gap: 6px;
  border: 0; border-radius: var(--radius-pill); padding: 7px 13px;
  background: rgba(255, 255, 255, .92); color: var(--fg-primary);
  font-family: var(--font-sans); font-size: var(--fs-12); font-weight: 600; cursor: pointer;
  box-shadow: var(--shadow-xs);
}
.vid-expand:hover { background: var(--tp-float); }
.vid-modal {
  position: fixed; inset: 0; z-index: 1000; background: var(--scrim-pill, rgba(29, 42, 58, .78));
  display: flex; align-items: center; justify-content: center; padding: 20px;
}
.vidm-panel {
  width: min(1100px, 96vw); background: #101418; border-radius: var(--radius-card);
  overflow: hidden; display: flex; flex-direction: column;
  box-shadow: var(--shadow-lg, 0 18px 50px rgba(0, 0, 0, .5));
}
.vidm-head {
  display: flex; align-items: center; gap: 14px; padding: 10px 16px; background: #101418; color: #fff8ed;
}
.vidm-title { font-weight: 700; font-size: var(--fs-14); margin-right: auto; }
.vidm-hint { font-size: var(--fs-12); opacity: .65; }
.vidm-close {
  width: 34px; height: 34px; border-radius: var(--radius-pill); border: 0;
  background: rgba(255, 255, 255, .14); color: #fff8ed; font-size: 20px; line-height: 1; cursor: pointer;
}
.vidm-frame-wrap { aspect-ratio: 16/9; width: 100%; }
.vidm-frame { width: 100%; height: 100%; border: 0; display: block; }
.ws-modal {
  position: fixed; inset: 0; z-index: 1000; background: var(--scrim-pill, rgba(29, 42, 58, .72));
  display: flex; align-items: center; justify-content: center; padding: 20px;
}
.wsm-panel {
  width: min(680px, 96vw); max-height: 92vh; overflow: auto; background: var(--tp-cream-50);
  border-radius: var(--radius-card); box-shadow: var(--shadow-lg, 0 18px 50px rgba(29,42,58,.35));
}
.wsm-head {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 14px;
  padding: 22px 26px 14px; border-bottom: 1px solid var(--tp-line);
}
.wsm-strap {
  font-size: var(--fs-12); font-weight: 700; letter-spacing: var(--tracking-strapline);
  text-transform: uppercase; color: var(--fg-muted);
}
.wsm-head h3 { font-family: var(--font-display); font-weight: 400; font-size: var(--fs-24); margin: 4px 0 0; }
.wsm-close {
  width: 34px; height: 34px; border-radius: var(--radius-pill); border: 1px solid var(--tp-line);
  background: var(--tp-float); color: var(--fg-primary); font-size: 20px; line-height: 1; cursor: pointer; flex-shrink: 0;
}
.wsm-body { padding: 18px 26px 24px; }
.ws-date { display: block; font-size: var(--fs-14); font-weight: 600; margin: 0 0 16px; }
.ws-date input {
  margin-left: 8px; font-family: var(--font-sans); font-size: var(--fs-14);
  border: 1px solid var(--tp-line); border-radius: var(--radius-xs); padding: 6px 10px; background: #fff;
}
.ws-q { display: block; margin: 0 0 16px; }
.ws-q span { display: block; font-size: var(--fs-14); font-weight: 600; margin: 0 0 6px; }
.ws-q textarea {
  width: 100%; box-sizing: border-box; font-family: var(--font-sans); font-size: var(--fs-14);
  line-height: var(--lh-relaxed); border: 1px solid var(--tp-line); border-radius: var(--radius-inner);
  padding: 10px 14px; background: #fff; resize: vertical;
}
.ws-q textarea:focus-visible { outline: 2px solid var(--tp-sky-blue-600); outline-offset: 1px; }
.wsm-foot { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; margin: 4px 0 14px; }
.wsm-saved { font-size: var(--fs-12); color: var(--fg-muted); margin-right: auto; }
.wsm-print {
  border: 2px solid var(--tp-ink); background: transparent; color: var(--fg-primary);
  border-radius: var(--radius-pill); padding: .45rem 1.1rem; font-family: var(--font-sans);
  font-weight: 500; font-size: var(--fs-12); cursor: pointer;
}
.wsm-print:hover { background: var(--ink-ghost); }
.wsm-pdf { font-size: var(--fs-12); color: var(--fg-secondary); font-weight: 600; text-decoration: underline; text-underline-offset: 2px; }
.ws-intro { margin: 0 0 16px; font-size: var(--fs-14); line-height: var(--lh-relaxed); color: var(--fg-secondary); }
.ws-footnote {
  margin: 4px 0 16px; padding: 10px 14px; background: var(--tp-cream-200);
  border-radius: var(--radius-inner); font-size: var(--fs-12); line-height: var(--lh-relaxed); color: var(--fg-secondary);
}
.ws-sec { margin: 0 0 6px; }
.ws-sec-h {
  font-family: var(--font-sans); font-size: var(--fs-12); font-weight: 700;
  letter-spacing: var(--tracking-strapline); text-transform: uppercase;
  color: var(--fg-muted); margin: 18px 0 10px;
}
.ws-check {
  display: flex; align-items: flex-start; gap: 10px; margin: 0 0 8px;
  background: #fff; border: 1px solid var(--tp-line); border-radius: var(--radius-inner);
  padding: 10px 14px; font-size: var(--fs-14); line-height: var(--lh-normal); cursor: pointer;
}
.ws-check input { width: 17px; height: 17px; margin: 2px 0 0; accent-color: var(--tp-sky-blue-600); flex-shrink: 0; cursor: pointer; }
.ws-check:has(input:checked) { background: var(--tp-mint-50, #eef8f6); border-color: var(--tp-mint-green); }
.ws-radio-label { display: block; font-size: var(--fs-14); font-weight: 600; margin: 0 0 8px; }
.ws-radio { display: flex; gap: 8px; flex-wrap: wrap; }
.ws-opt { position: relative; cursor: pointer; }
.ws-opt input { position: absolute; opacity: 0; pointer-events: none; }
.ws-opt span {
  display: inline-block; border: 1px solid var(--tp-line); background: #fff;
  border-radius: var(--radius-pill); padding: 7px 15px; font-size: var(--fs-12); font-weight: 600;
  color: var(--fg-secondary); transition: background var(--dur-base) var(--ease-out);
}
.ws-opt input:checked + span { background: var(--tp-sky-blue-100, #eaf3ff); border-color: var(--tp-sky-blue-600); color: var(--tp-ink); }
.ws-opt input:focus-visible + span { outline: 2px solid var(--tp-sky-blue-600); outline-offset: 1px; }
.ws-tablewrap { overflow-x: auto; margin: 0 0 14px; border: 1px solid var(--tp-line); border-radius: var(--radius-inner); background: #fff; }
.ws-table { border-collapse: collapse; width: 100%; font-size: var(--fs-12); }
.ws-table th, .ws-table td { padding: 9px 10px; border-bottom: 1px solid var(--tp-line); text-align: center; }
.ws-table thead th { background: var(--tp-cream-100); font-weight: 700; }
.ws-table tbody th { text-align: left; font-weight: 600; color: var(--fg-secondary); min-width: 150px; }
.ws-table tbody tr:last-child th, .ws-table tbody tr:last-child td { border-bottom: 0; }
.ws-table input { width: 17px; height: 17px; accent-color: var(--tp-sky-blue-600); cursor: pointer; }
.wsm-past-label { display: block; font-size: var(--fs-12); font-weight: 700; color: var(--fg-muted); margin: 0 0 8px; }
.wsm-chip {
  border: 1px solid var(--tp-line); background: var(--tp-float); color: var(--fg-secondary);
  border-radius: var(--radius-pill); padding: 5px 12px; margin: 0 6px 6px 0;
  font-family: var(--font-sans); font-size: var(--fs-12); cursor: pointer;
}
.wsm-chip:hover { background: var(--tp-cream-200); }
.pdf-modal {
  position: fixed; inset: 0; z-index: 1000; background: var(--scrim-pill, rgba(29, 42, 58, .72));
  display: flex; align-items: center; justify-content: center; padding: 24px;
}
.pdfm-panel {
  width: min(920px, 96vw); height: min(86vh, 1100px); background: var(--tp-float);
  border-radius: var(--radius-card); overflow: hidden; display: flex; flex-direction: column;
  box-shadow: var(--shadow-lg, 0 18px 50px rgba(29,42,58,.35));
}
.pdfm-head {
  display: flex; align-items: center; gap: 14px; padding: 12px 16px;
  border-bottom: 1px solid var(--tp-line); background: var(--tp-cream-50);
}
.pdfm-title { font-weight: 700; font-size: var(--fs-14); margin-right: auto; }
.pdfm-newtab { font-size: var(--fs-12); font-weight: 600; color: var(--fg-secondary); text-decoration: underline; text-underline-offset: 2px; }
.pdfm-close {
  width: 34px; height: 34px; border-radius: var(--radius-pill); border: 1px solid var(--tp-line);
  background: var(--tp-float); color: var(--fg-primary); font-size: 20px; line-height: 1; cursor: pointer;
}
.pdfm-frame { flex: 1; width: 100%; border: 0; }
.img-lightbox {
  position: fixed; inset: 0; z-index: 1000; background: var(--scrim-pill, rgba(29, 42, 58, .72));
  display: flex; align-items: center; justify-content: center; padding: 24px; cursor: zoom-out;
}
.img-lightbox img {
  max-width: 92vw; max-height: 92vh; object-fit: contain;
  border-radius: var(--radius-inner); background: var(--tp-float); box-shadow: var(--shadow-lg, 0 18px 50px rgba(29,42,58,.35));
}
.img-lightbox .lb-close {
  position: absolute; top: 16px; right: 16px; width: 44px; height: 44px;
  border-radius: var(--radius-pill); border: 0; background: var(--tp-float); color: var(--fg-primary);
  font-size: 26px; line-height: 1; cursor: pointer;
}
.cmp-cap { margin: 12px 0 11px; font-size: var(--fs-14); font-weight: 700; line-height: var(--lh-normal); }
.cmp-points { margin: 0; padding: 0; list-style: none; display: grid; gap: 7px; }
.cmp-points li {
  position: relative; padding-left: 18px;
  font-size: var(--fs-12); line-height: var(--lh-normal); color: var(--fg-secondary);
}
.cmp-points li::before {
  content: ""; position: absolute; left: 2px; top: 6px;
  width: 6px; height: 6px; border-radius: var(--radius-pill);
}
.cmp-card.right .cmp-points li::before { background: var(--tp-mint-green); }
.cmp-card.wrong .cmp-points li::before { background: var(--tp-flag-border); }

/* checkpoint */
.checkpoint {
  margin-top: 12px; background: var(--tp-cream); border: 2px dashed var(--tp-mint-green);
  border-radius: 18px; padding: 18px 22px;
  display: flex; align-items: center; gap: 18px;
}
.checkpoint .ck-ico {
  width: 40px; height: 40px; border-radius: 12px; background: var(--tp-mint-green);
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
}
.checkpoint .ck-body h5 { margin: 0 0 3px; font-size: var(--fs-14); font-weight: 700; }
.checkpoint .ck-body p { margin: 0; font-size: var(--fs-12); color: var(--fg-secondary); line-height: var(--lh-normal); }
.checkpoint .ck-link { margin-left: auto; }

/* ============================ Resources ============================= */
.res-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
.res {
  background: var(--tp-card); border: 1px solid var(--tp-line); border-radius: 18px; padding: 20px;
  display: flex; flex-direction: column; gap: 8px; text-decoration: none; color: inherit;
  transition: transform var(--dur-fast) var(--ease-out), box-shadow var(--dur-base) var(--ease-out);
}
.res:hover { transform: translateY(-2px); box-shadow: var(--shadow-sm); }
.res .rtop { display: flex; align-items: center; justify-content: space-between; }
.res .ricon {
  width: 38px; height: 38px; border-radius: 11px; background: var(--tp-peach);
  display: flex; align-items: center; justify-content: center; color: var(--tp-ink);
}
/* Rotating tints, previously written inline by the renderer. */
.res .ricon[data-tint="peach"] { background: var(--tp-peach); }
.res .ricon[data-tint="mint"]  { background: var(--tp-mint-green); }
.res .ricon[data-tint="sky"]   { background: var(--tp-sky-blue); }
.res .rphase { font-size: var(--fs-12); font-weight: 700; letter-spacing: var(--tracking-wide); text-transform: uppercase; color: var(--fg-muted); }
.res h4 { margin: 6px 0 0; font-size: var(--fs-16); font-weight: 700; line-height: var(--lh-snug); }
.res p { margin: 0; font-size: var(--fs-12); color: var(--fg-secondary); line-height: var(--lh-relaxed); }
.res .rdl { margin-top: 6px; display: inline-flex; align-items: center; gap: 7px; font-size: var(--fs-12); font-weight: 500; color: var(--accent-press); }  /* accent-strong (sky-500) measured 3.29:1 on the Paper card */

/* ============================ Footer CTA ============================ */
/* Accent discipline (P1.4, P2.8): cream-200 foundation surface with the
   bubblegum accent confined to the avatar chip; big-shape radius. */
.cta-band {
  background: var(--tp-cream-200); border: 1px solid var(--tp-line);
  border-radius: var(--radius-bg);
  padding: 40px 44px; display: grid; grid-template-columns: 1fr auto; gap: 28px; align-items: center;
}
.cta-band .cb-left { display: flex; gap: 20px; align-items: center; }
.cta-band .cb-ava {
  width: 64px; height: 64px; border-radius: var(--radius-pill); flex-shrink: 0;
  background: var(--tp-bubblegum); border: 2px solid #fff; /* flat accent chip (P1.3, P1.4) */
  display: flex; align-items: center; justify-content: center;
}
.cta-band h3 { font-family: var(--font-display); font-weight: 400; font-size: var(--fs-32); line-height: var(--lh-tight); margin: 0 0 8px; }
.cta-band p { margin: 0; font-size: var(--fs-16); line-height: var(--lh-relaxed); color: var(--tp-ink-2); max-width: var(--measure); }

.footer { padding: 40px 0 56px; text-align: center; }
.footer img { height: 20px; margin: 0 auto 14px; opacity: .8; }
.footer p { font-size: var(--fs-12); color: var(--fg-muted); margin: 0; line-height: var(--lh-relaxed); }
.footer .disc { max-width: 46ch; margin: 0 auto; }  /* was 640px = 85 chars at 12px */
.foot-social { display: flex; justify-content: center; gap: 10px; margin: 0 0 18px; }
.foot-soc {
  width: 38px; height: 38px; border-radius: var(--radius-pill); display: flex; align-items: center; justify-content: center;
  color: var(--fg-primary); background: #fff; border: 1px solid var(--tp-line);
  transition: transform var(--dur-fast) var(--ease-out), background var(--dur-base) var(--ease-out);
}
.foot-soc:hover { transform: translateY(-2px); background: var(--tp-cream-200); }
.foot-contact { margin: 0 0 14px !important; font-size: var(--fs-14) !important; color: var(--fg-secondary) !important; }
.foot-contact a { color: var(--fg-secondary); font-weight: 500; text-decoration: underline; text-underline-offset: 2px; }
.foot-copy { margin: 16px 0 0 !important; opacity: .8; }

/* The privacy link sits in the copyright line. Underlined rather than relying on
   colour alone, because the footer's muted ink against the footer ground does not
   carry a 3:1 non-text contrast difference on its own, so colour would be the
   only signal it is a link. */
.foot-copy a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
.foot-copy a:hover { color: var(--fg-primary); }

/* ===================== Exercise library (Module 10) ===================== */
/* ---- un-nested Module 10 blocks, now peers of the module list -----------
   The exercise plan and the progress check used to render inside Module 10's
   accordion body. As siblings they need their own top margin and an anchor
   offset that clears the 73px sticky nav. */
.cur-sub {
  margin-top: 10px; scroll-margin-top: 88px;
  background: var(--tp-card); border: 1px solid var(--tp-line); border-radius: 18px; overflow: hidden;
}
/* The plan is the most important thing in the curriculum, so it reads as a
   peer of the module list rather than another identical row. */
.cur-sub:first-of-type { margin-top: 22px; }
.cur-sub .sub-head h3 { margin: 0; }
.cur-sub .sub-toggle {
  appearance: none; -webkit-appearance: none; background: none; border: 0;
  width: 100%; display: flex; align-items: center; gap: 12px;
  padding: 17px 20px; cursor: pointer; text-align: left; font-family: var(--font-sans);
}
.cur-sub .sub-title { font-size: var(--fs-16); font-weight: 700; color: var(--fg-primary); }
.cur-sub .sub-meta {
  font-size: var(--fs-12); color: var(--fg-muted); font-variant-numeric: tabular-nums;
  margin-left: auto; white-space: nowrap;
}
.cur-sub .chev {
  width: 18px; height: 18px; color: var(--fg-muted); flex-shrink: 0;
  transition: transform var(--dur-base) var(--ease-out);
}
.cur-sub.open .chev { transform: rotate(180deg); }
.cur-sub .sub-body { display: none; padding: 0 20px 22px; }
.cur-sub.open .sub-body { display: block; }
.cur-sub .sub-body > .exlib,
.cur-sub .sub-body > .progress-check { margin-top: 0; }
@media (max-width: 640px) {
  .cur-sub .sub-toggle { padding: 15px; gap: 10px; }
  .cur-sub .sub-body { padding: 0 15px 18px; }
}

/* Pointer left behind in Module 10 so the plan is not silently missing. */
.sub-jump {
  margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--tp-line);
}
.sub-jump p { margin: 0 0 8px; font-size: var(--fs-14); color: var(--fg-secondary); }

.exlib { margin: 4px 0 22px; }
.exlib-head h5 { margin: 0 0 6px; font-size: var(--fs-16); font-weight: 700; }
.exlib-tip {
  margin: 0 0 20px; font-size: var(--fs-14); line-height: var(--lh-relaxed); color: var(--fg-secondary);
  background: var(--tp-cream-200); border-radius: 12px; padding: 12px 15px; max-width: var(--measure-wide);
}
.exlib-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
.exgrp-head {
  display: flex; align-items: baseline; flex-wrap: wrap; gap: 8px 12px;
  margin: 22px 0 12px; padding-bottom: 9px; border-bottom: 2px solid var(--tp-line);
}
.exgrp-head:first-of-type { margin-top: 2px; }
.exgrp-label { font-family: var(--font-display); font-weight: 400; font-size: var(--fs-20); line-height: var(--lh-tight); color: var(--fg-primary); }
.exgrp-tag {
  font-size: var(--fs-12); font-weight: 700; letter-spacing: var(--tracking-wide); text-transform: uppercase;
  color: var(--tp-ink); background: var(--tp-mint-green); padding: 3px 10px; border-radius: var(--radius-pill);
}
.exgrp-note { flex-basis: 100%; font-size: var(--fs-12); color: var(--fg-secondary); line-height: var(--lh-normal); }
.ex-video.no-video { cursor: default; background: var(--tp-cream-200); /* flat panel (P1.3) */ }
.ex-video.no-video .ex-vtitle { color: var(--fg-primary); text-shadow: none; }
/* dev-note restyled as Cerco caption (P3.5) */
.ex-soon {
  font-family: var(--font-sans); font-size: var(--fs-14);
  color: var(--fg-muted); margin-top: 6px;
}
.excard {
  background: var(--tp-card); border: 1px solid var(--tp-line); border-radius: var(--radius-inner); overflow: hidden;
  display: flex; flex-direction: column;
}
.ex-video {
  position: relative; aspect-ratio: 16/9; cursor: pointer;
  background: var(--tp-sky-blue-700); /* flat poster (P1.3) */
}
.ex-poster {
  position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px;
  /* pinstripe texture removed (P1.3) */
  text-align: center; padding: 14px;
}
.ex-video .play { width: 46px; height: 46px; transition: transform var(--dur-base) var(--ease-out); }
.ex-video:hover .play { transform: scale(1.08); }
.ex-vtitle { color: #fff; font-weight: 700; font-size: var(--fs-14); letter-spacing: .01em; text-shadow: 0 1px 4px rgba(29, 42, 58, 0.18); /* ink-tinted (P2.9) */ }
.ex-video .embed { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; display: block; background: #000; }
.ex-body { padding: 16px 17px 18px; }
.ex-body h6 { margin: 0 0 9px; font-size: var(--fs-16); font-weight: 700; line-height: var(--lh-snug); }
.ex-why { margin: 0 0 12px; font-size: var(--fs-14); line-height: var(--lh-relaxed); color: var(--fg-secondary); }

/* Clinically approved safety note. Deliberately louder than .ex-why: it uses the
   amber accent rather than the muted body colour, because it must survive being
   skimmed. Not red: the vast majority of these are ordinary precautions, not
   alarms, and a page of red boxes teaches parents to ignore them. */
.ex-safety {
  /* Symmetric 12px top and bottom, matching the gap .ex-why already leaves
     above it. Was 0 at the bottom, so "How to do it" collided with the
     box edge and the note read as part of the steps rather than as its own
     block. */
  margin: 12px 0; padding: 12px 14px;
  background: var(--tp-cream-200); border-left: 3px solid var(--tp-yellow);
  border-radius: 0 10px 10px 0;
  font-size: var(--fs-14); line-height: var(--lh-relaxed); color: var(--fg-primary);
}
.ex-safety > span {
  display: block; font-size: var(--fs-12); font-weight: 700;
  letter-spacing: .06em; text-transform: uppercase;
  color: var(--tp-ink-2); margin: 0 0 4px;
}
.ex-why span, .ex-how span {
  display: inline-block; font-size: var(--fs-12); font-weight: 700; letter-spacing: var(--tracking-wide); text-transform: uppercase;
  color: var(--fg-muted); margin-right: 4px;
}
.ex-how span { display: block; margin: 0 0 6px; }
.ex-how ol { margin: 0; padding-left: 18px; display: grid; gap: 5px; }
.ex-how li { font-size: var(--fs-14); line-height: var(--lh-relaxed); color: var(--fg-primary); }
.ex-pending { margin: 0; font-size: var(--fs-14); line-height: var(--lh-relaxed); color: var(--fg-muted); }
/* dev-note restyled as Cerco caption (P3.5) */
.ex-pending span {
  display: block; font-family: var(--font-sans); font-size: var(--fs-14);
  font-weight: 500; color: var(--fg-muted); margin: 0 0 5px;
}

/* ===================== Progress check (Module 10) ===================== */
.progress-check {
  background: var(--tp-sky-blue-50); border: 1px solid var(--tp-line-2);
  border-radius: 18px; padding: 22px 22px 24px; margin: 4px 0 22px;
}
.pc-head { margin: 0 0 18px; }
.pc-strap {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: var(--fs-12); font-weight: 700; letter-spacing: var(--tracking-wide); text-transform: uppercase;
  color: var(--tp-ink); background: var(--tp-mint-green);
  padding: 4px 11px 4px 9px; border-radius: var(--radius-pill); margin: 0 0 10px;
}
.pc-head h5 { margin: 0 0 6px; font-family: var(--font-display); font-weight: 400; font-size: var(--fs-24); line-height: var(--lh-tight); }
.pc-head p { margin: 0; font-size: var(--fs-14); line-height: var(--lh-relaxed); color: var(--fg-secondary); max-width: var(--measure-wide); }
.pc-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.pc-card { background: var(--tp-card); border: 1px solid var(--tp-line); border-radius: 14px; padding: 15px 16px; }
.pc-sec {
  font-size: var(--fs-12); font-weight: 700; letter-spacing: var(--tracking-wide); text-transform: uppercase;
  color: var(--fg-muted); margin: 0 0 12px; padding-bottom: 9px; border-bottom: 1px solid var(--tp-line);
}
.pc-q { display: flex; align-items: center; gap: 12px; padding: 9px 0; }
.pc-q + .pc-q { border-top: 1px solid var(--tp-cream-200); }
.pc-q p { margin: 0; flex: 1; font-size: var(--fs-14); line-height: var(--lh-normal); color: var(--fg-primary); }
.pc-toggle { display: flex; gap: 6px; flex-shrink: 0; }
.pc-toggle button {
  border: 1px solid var(--tp-line); background: #fff; color: var(--fg-secondary);
  border-radius: var(--radius-pill); padding: 5px 13px; font-family: var(--font-sans);
  font-size: var(--fs-12); font-weight: 700; cursor: pointer;
  transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
}
.pc-toggle button:hover { border-color: var(--fg-primary); }
.pc-toggle .pc-yes.on { background: var(--tp-mint-green); border-color: var(--tp-mint-green); color: var(--tp-ink); }
.pc-toggle .pc-no.on { background: var(--tp-peach); border-color: var(--tp-peach); color: var(--tp-ink); }
.pc-next {
  display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
  margin-top: 16px; padding: 16px 18px; background: var(--tp-yellow); border-radius: 14px;
}
.pc-next-body { flex: 1; min-width: 240px; }
.pc-next-strap { display: block; font-size: var(--fs-12); font-weight: 700; letter-spacing: var(--tracking-wide); text-transform: uppercase; color: var(--tp-ink-2); margin: 0 0 4px; } /* P2.14: solid token, no opacity trick */
.pc-next-body p { margin: 0; font-size: var(--fs-14); line-height: var(--lh-relaxed); color: var(--fg-primary); }
.pc-next-body p a { color: var(--fg-primary); font-weight: 700; text-decoration: underline; text-underline-offset: 2px; }
.pc-next-body p a:hover { opacity: .75; }

/* ---- per-module concern / gut-check CTA ---- */
.concern-cta {
  display: flex; align-items: center; gap: 18px; flex-wrap: wrap;
  margin: 26px 0 6px; padding: 17px 20px;
  background: var(--tp-peach); border-radius: var(--radius-inner);
}
.concern-body { flex: 1; min-width: 240px; }
.concern-strap {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: var(--fs-12); font-weight: 700; letter-spacing: var(--tracking-wide); text-transform: uppercase;
  color: var(--tp-ink-2); margin: 0 0 6px; /* P2.14: solid token */
}
.concern-body p { margin: 0; font-size: var(--fs-14); line-height: var(--lh-relaxed); color: var(--fg-primary); font-weight: 500; }
.concern-cta .btn { flex-shrink: 0; }

/* ===================== FAQ accordion ===================== */
.faq-list { display: grid; gap: 10px; max-width: 860px; }
.faq-item { background: var(--tp-card); border: 1px solid var(--tp-line); border-radius: 14px; overflow: hidden; }
.faq-q {
  width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 16px;
  background: none; border: 0; cursor: pointer; text-align: left;
  padding: 17px 20px; font-family: var(--font-sans); font-size: var(--fs-16); font-weight: 700; color: var(--fg-primary);
}
.faq-chev { width: 18px; height: 18px; flex-shrink: 0; color: var(--fg-muted); transition: transform var(--dur-base) var(--ease-out); }
.faq-item.open .faq-chev { transform: rotate(180deg); }
.faq-a { display: grid; grid-template-rows: 0fr; align-items: start; transition: grid-template-rows var(--dur-base) var(--ease-out); }
.faq-item.open .faq-a { grid-template-rows: 1fr; }
.faq-a-inner { overflow: hidden; }
.faq-item.open .faq-a-inner { padding: 0 20px 18px; }
.faq-a-inner p { margin: 0 0 11px; font-size: var(--fs-14); line-height: var(--lh-relaxed); color: var(--fg-secondary); }
.faq-a-inner p:last-child { margin-bottom: 0; }
.faq-a-inner ul, .faq-a-inner ol { margin: 0 0 11px; padding-left: 20px; display: grid; gap: 6px; }
.faq-a-inner li { font-size: var(--fs-14); line-height: var(--lh-relaxed); color: var(--fg-secondary); }
.faq-a-inner b { color: var(--fg-primary); }
.faq-a-inner a { color: var(--fg-primary); font-weight: 500; text-decoration: underline; text-underline-offset: 2px; }
.faq-cta-wrap { margin: 14px 0 0 !important; }
.faq-cta {
  display: inline-flex; align-items: center; gap: 8px;
  background: var(--tp-ink); color: #fff !important; text-decoration: none !important;
  font-size: var(--fs-14); font-weight: 700; padding: 10px 18px; border-radius: var(--radius-pill);
  transition: transform var(--dur-fast) var(--ease-out);
}
.faq-cta:hover { transform: translateY(-1px); }

/* Anchor targets sit under a 73px sticky nav, so every jump landed with its
   heading hidden behind the chrome. */
:target, .sec[id], .cur-sub { scroll-margin-top: 88px; }

/* ===================== Touch target floor (WCAG 2.5.5 / Apple 44pt) =======
   Audited at 390px: the module title button measured 39px, the brand logo
   22px, the footer social icons 38px and inline text links 31px. None of
   these change position or size visually; they only grow the hit area, so
   both layouts get them safely. */
.lesson .lh-body h4 .lesson-toggle {
  min-height: 44px; display: flex; align-items: center; flex-wrap: wrap;
}
.nav-logo { min-height: 44px; display: inline-flex; align-items: center; }
.foot-soc { min-width: 44px; min-height: 44px; display: inline-flex; align-items: center; justify-content: center; }
/* inline-flex lets an inline link take a real height without changing where
   it sits, which is more reliable than guessing padding per instance. */
.tlink { display: inline-flex; align-items: center; min-height: 44px; }
/* Glossary chips measured 32px. The sibling stylesheet already shipped this
   exact painted-pill fix (styles.css:770-772); it was never ported here. */
.glossary .term { min-height: 44px; display: inline-flex; align-items: center; }

/* ================== Tablet band: 641px to 820px ==========================
   The system previously had NO breakpoint between 640 and 900, so a tablet
   inherited the desktop two-column lesson body. At 660px that gave the video
   a fixed 300px against 292px of prose, meaning an iPad rendered a smaller
   video AND narrower text than a 390px iPhone.
   Widening the ratio alone was not enough: at 768px it still produced a 262px
   video (versus 320px on a phone) and 44 characters per line, under the 45
   character comfort floor. Two columns is simply the wrong layout at this
   width, so the band stacks like the phone does and caps the media instead. */
@media (min-width: 641px) and (max-width: 820px) {
  .lesson-body-inner { grid-template-columns: 1fr; gap: 22px; }
  .mini-player { max-width: 440px; }
  /* Stacking frees the full 655px, which swings prose to 82 characters per
     line. Cap the prose column only. The cap is a px value tuned to the 14px
     body text (about 7.5px per character, so 520px lands near 69 characters);
     a ch unit resolves against the CONTAINER's font size, not the paragraph's,
     and computed to 665px here, which was wider than the column and therefore
     did nothing. The activity and compare blocks keep the full width, since
     they are step lists and image pairs rather than running prose. */
  .lesson-body-inner .lb-points { max-width: 520px; }
}

/* ====================== Focus visibility (P2.10, P2.15) ================== */
a:focus-visible, button:focus-visible, [tabindex]:focus-visible,
input:focus-visible, select:focus-visible, textarea:focus-visible {
  outline: 3px solid var(--tp-sky-blue-600);
  outline-offset: 2px;
}

/* ============================ Responsive ============================ */
/* Breakpoint policy (P2.16): exactly two, 900px collapse + 640px phone. */
@media (max-width: 900px) {
  .hero-grid { grid-template-columns: 1fr; gap: 30px; }
  .hero-grid .player-col { order: -1; }
  .overview-grid { grid-template-columns: 1fr; gap: 28px; }
  .phase-cards { grid-template-columns: 1fr; }
  .res-grid { grid-template-columns: 1fr 1fr; }
}
/* Lives in bundled/app markup: keep the lesson meta row wrapping instead of
   overflowing under four items plus the child picker (P2.17). */
.lesson-header .meta { flex-wrap: wrap; }

@media (max-width: 640px) {
  .wrap, .nav-inner { padding-left: 18px; padding-right: 18px; }
  .nav-tag { display: none; }
  .nav-prog .track { width: 64px; }
  .hero { padding: 30px 0 4px; }
  .sec { padding: 40px 0; }
  .btn { padding: var(--space-3) var(--space-5); } /* mirrors buttons.css */
  .res-grid { grid-template-columns: 1fr; }
  /* 4 columns for the 4 remaining children (.dur is hidden), so the chevron
     no longer wraps onto a second row (P2.17) */
  .lesson-head { grid-template-columns: 38px 1fr auto auto; gap: 12px; padding: 13px 15px; }
  .lesson .dur { display: none; }
  /* Duration returns inline inside the title, so the 4-column phone grid and
     the P2.17 chevron-wrap fix both stay exactly as they are. */
  .lt-dur {
    display: inline; margin-left: 8px; font-size: var(--fs-12); font-weight: 400;
    color: var(--fg-muted); font-variant-numeric: tabular-nums; white-space: nowrap;
  }
  .lesson-body { padding: 0 15px 18px; }
  .lesson-body-inner { grid-template-columns: 1fr; gap: 18px; }
  .cmp-grid { grid-template-columns: 1fr; }
  .concern-cta .btn { width: 100%; }
  .activity { padding: 16px 17px; }
  /* Was max-width:320px, which left the player flush left with 48px of dead
     space at 404px wide, and visibly narrower than the cards above and below
     it. Filling the column centres it by definition and lines it up with the
     surrounding content. margin-inline:auto keeps it centred if any other
     rule ever caps the width again. */
  /* NO margin-inline:auto here. .mp-col is a COLUMN flex container, so items
     stretch to its width by default; an auto inline margin cancels that
     stretch, and the poster inside is absolutely positioned so the intrinsic
     width is 0. Adding it collapsed the player to 0x0. Stretching to the
     column is what centres it. */
  .mini-player { max-width: 100%; }
  .exlib-grid { grid-template-columns: 1fr; }
  .pc-grid { grid-template-columns: 1fr; }
  .phase-bar { flex-wrap: wrap; }
  .phase-bar .pmeta { margin-left: 0; width: 100%; }
  .cta-band { grid-template-columns: 1fr; padding: 28px 24px; text-align: center; }
  .cta-band .cb-left { flex-direction: column; text-align: center; }
  .checkpoint { flex-wrap: wrap; }
  .checkpoint .ck-link { margin-left: 0; }
  .meta-row { width: 100%; }
  .meta-row .m { flex: 1; min-width: 33%; }
  .hero h1 { font-size: clamp(34px, 9vw, 44px); }
}

/* ====================== Reduced motion guard (P2.13) ===================== */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* Responsive 16:9 wrapper for the video embedded in the merged FAQ answer.
   loading="lazy" plus the collapsed FAQ means the Vimeo iframe is not fetched
   until the answer is opened, so it costs nothing on page load. */
.faq-a-inner .faq-video {
  position: relative; width: 100%; max-width: 560px;
  aspect-ratio: 16 / 9; margin: 0 0 14px;
  border-radius: var(--radius-inner); overflow: hidden; background: var(--tp-sky-blue-700);
}
.faq-a-inner .faq-video iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

/* A failed worksheet save must read as a warning, not as a status line. */
.wsm-saved.ws-save-fail { color: var(--tp-flag-ink); font-weight: 700; }

/* Export / import card, shown under the worksheet grid. */
.port-card {
  margin-top: 18px; padding: 20px; border-radius: 18px;
  background: var(--tp-card); border: 1px solid var(--tp-line);
}
.port-card h4 { margin: 0 0 6px; font-size: var(--fs-16); font-weight: 700; }
.port-card p { margin: 0 0 12px; font-size: var(--fs-14); color: var(--fg-secondary); line-height: 1.55; }
.port-actions { display: flex; gap: 10px; flex-wrap: wrap; }
.port-note:empty { display: none; }
.port-card .port-note { margin: 12px 0 0; font-weight: 700; color: var(--tp-sky-blue-700); }
@media (max-width: 640px) { .port-actions .btn { width: 100%; justify-content: center; } }

/* ================= Light-filled containers, all schemes ==================
   These carry a LIGHT fill in every scheme (sky blue, white), so their text
   must pin dark ink rather than inherit the body colour. Without this they
   vanish the moment a scheme flips body text light: measured at 1.21:1 on
   the "What you'll learn" card in dark mode.

   Deliberately NOT scoped to the dark scheme. A dark-only patch would rot the
   next time a scheme is added; this states the actual invariant, which is
   "light fill implies dark ink", and is a no-op on the light schemes.

   The earlier ink/fg-primary split only guarded rules where the fill and the
   colour were declared TOGETHER. Every case below has the fill on a parent
   and the text on a child, which is why the first pass missed them. */
.learn-card,
.learn-card *,
.learn-card .learn-list li,   /* beats the .learn-list li rule from the ink split */
.need-chip,
.foot-soc,
.meta-row, .meta-row *,       /* hero stat strip: white card in every scheme */
.pc-toggle button { color: var(--tp-ink); }

/* Secondary buttons are the mirror image: a TRANSPARENT fill sitting directly
   on the canvas, so their ink has to follow the scheme, not stay dark. */
html[data-canvas="dark"] .btn.secondary {
  color: var(--fg-primary);
  border-color: var(--tp-hairline-strong);
}
html[data-canvas="dark"] .btn.secondary:hover { background: var(--ink-ghost-strong); }

/* The selected glossary chip pairs a LIGHT fill with dark ink, which is the
   correct pairing on the light schemes. In dark, --tp-sky-blue-100 resolves to
   #24303f, a dark tint, so the fill is no longer light while the ink stayed
   #333: measured 1.16:1, i.e. the word vanished into its own chip
   (KP 2026-09-01). Fill and ink have to move together, so both are restated
   here. Third instance of this same trap; see the light-fill invariant above. */
html[data-canvas="dark"] .glossary .term.on {
  background: var(--tp-sky-blue-100);
  color: var(--fg-primary);
  border-color: var(--tp-sky-blue-600);
}

/* Deep-blue accents used as TEXT are unreadable on a dark ground. */
html[data-canvas="dark"] .port-card .port-note,
html[data-canvas="dark"] .tlink { color: var(--tp-sky-blue-300); }

/* The practice tip is an intro paragraph sitting between the section label
   and the first group header. It was rendering with 11px above and 22px
   below, which read as cramped and made it float between two labels rather
   than belong to the section. */
/* Top margin was 4px, which left the tip callout almost touching the week
   selector above it while the exercise cards further down the same page sit
   18px apart. Matching that 18px is what makes the top of the page read as
   the same rhythm as the rest of it (KP 2026-08-31). */
.exlib-tip { margin: 18px 0 22px; padding: 14px 16px; line-height: 1.6; }
.exlib-head { margin-bottom: 8px; }
.exlib .exgrp-head:first-of-type { margin-top: 26px; }

/* Video posters. The thumbnail is a background image so the play glyph, the
   duration pill and the title overlay keep working unchanged on top of it.
   A scrim keeps white overlay text readable against a bright frame. */
.mp-poster.has-thumb,
.ex-poster.has-thumb {
  background-size: cover; background-position: center; background-repeat: no-repeat;
}
/* NO position override on either poster. Both are already
   "position:absolute; inset:0" from their base rules, and resetting to
   relative collapsed them to content height, leaving a solid band under the
   thumbnail. An absolutely positioned parent is already a containing block
   for the ::before scrim, so nothing further is needed. */
.mp-poster.has-thumb::before,
.ex-poster.has-thumb::before {
  content: ""; position: absolute; inset: 0; z-index: 0;
  background: linear-gradient(180deg, rgba(20,26,34,.10) 0%, rgba(20,26,34,.52) 100%);
}
.mp-poster.has-thumb > *,
.ex-poster.has-thumb > * { position: relative; z-index: 1; }
.ex-poster.has-thumb .ex-vtitle { text-shadow: 0 1px 3px rgba(20,26,34,.6); }

/* Progress-check answers measured 30px tall. They are the primary interaction
   on that screen, so they take the 44px floor even though it makes the step
   taller. Inline links inside FAQ prose are deliberately NOT padded: WCAG
   2.5.8 exempts targets within a sentence or block of text, and bloating them
   would wreck the line rhythm. The FAQ call-to-action is not inline prose. */
.pc-toggle button { min-height: 44px; }
.faq-cta { min-height: 44px; display: inline-flex; align-items: center; }

/* ===================== Reading measure for running prose =================
   Measured across views at 768 and 1440: paragraphs ran 85 to 144 characters
   per line (the export card was the worst at 144, the FAQ answers 114). The
   comfortable range is roughly 45 to 75, and the rail layout made it worse by
   giving the content area the full width with no column constraint.

   Capped on the TEXT elements, not their containers, so grids, card rows,
   compare pairs and the exercise library still use the full width. The ch
   unit is safe here for the same reason: it resolves against the element that
   actually renders the text. */
.faq-a-inner p,
.faq-a-inner li,
.guide-bio,
.guide-card p,
.ck-body p,
.port-card p,
.pc-head p,
.contact-card p,
.sec-head p,
.disc,
.rail-note { max-width: 50ch; }
/* 50ch, not 62: the ch unit is the width of "0", which is wider than the
   average character, so 62ch measured out at 85 characters per line. 50ch
   lands near 68, inside the comfortable range. Verified, not assumed. */

/* The footer disclaimer is centred, so its cap has to centre too. */
.disc { margin-left: auto; margin-right: auto; }

/* Lesson body prose. An earlier cap existed only inside the 641 to 820 tablet
   band, so the module detail view ran to 143 characters per line on desktop.
   Capped at every width; the compare pairs, exercise grid and media keep the
   full column. */
.lesson-body-inner .takeaway p,
.lesson-body-inner .spot p,
.lesson-body-inner .callout p,
.lesson-body-inner .lb-points p,
.sub-jump p { max-width: 50ch; }
/* .activity (and its .act-steps) is a SIBLING of .lesson-body-inner, not a
   descendant, so a .lesson-body-inner prefix silently missed it and the steps
   ran to 143 characters. Same for the About copy, whose paragraphs are
   unclassed inside .body. */
.act-steps li { max-width: 50ch; }
.sec .body > p { max-width: 54ch; }

/* ===================== Workbook first-page previews ======================
   Rendered from the PDFs with pdf.js and self-hosted, same reasoning as the
   video posters: no third-party image request from a patient-facing page.
   The preview is the card header; the coloured icon tile is redundant once a
   real page is showing, so it is dropped on cards that have one. */
.res.has-preview { padding-top: 18px; overflow: hidden; }
/* The sheets are portrait letter pages, so cropping them to fill a landscape
   tile slices a table mid-row and reads as a broken image. Show the whole page
   on a mat instead: nothing is cut and the page shape says "printable" on its
   own. The mat is a scheme token so it follows the colour options and dark. */
.res .rthumb {
  display: block; margin: 0 20px 16px;
  aspect-ratio: 4 / 3; background-size: contain; background-position: center;
  background-repeat: no-repeat;
  background-color: var(--tp-inset);
  border: 1px solid var(--tp-line); border-radius: 12px;
}
/* Portrait letter pages shown whole left 68px of mat down each side, 42% of
   the tile, which read as a gap rather than a preview. They fill the tile from
   the top instead: the masthead, title and intro are what identify the sheet,
   and the card title underneath says the rest. The two 16:9 sheets keep
   "contain" above, since cropping those loses a whole column. */
.res .rthumb.portrait { background-size: cover; background-position: top center; }
.res.has-preview .ricon { display: none; }
.res.has-preview .rtop,
.res.has-preview h4,
.res.has-preview p,
.res.has-preview .rdl { margin-left: 20px; margin-right: 20px; }
.res.has-preview .rdl { margin-bottom: 20px; }
/* The sheets are mostly white, so they need an edge against a white card. */
html[data-canvas="paper"] .res .rthumb,
html[data-canvas="stone"] .res .rthumb { border-color: var(--tp-hairline-strong); }

/* Module 10 workbook panel. The panel is already a 16:9 centred tile, so the
   first page becomes its background and a scrim keeps the label and button
   readable over it. The icon tile is redundant once a real page shows. */
.pdf-panel.has-preview {
  background-size: cover; background-position: top center; background-repeat: no-repeat;
  justify-content: flex-end;
}
.pdf-panel.has-preview::before {
  content: ""; position: absolute; inset: 0; z-index: 0;
  background: linear-gradient(180deg, rgba(20,26,34,.16) 0%, rgba(20,26,34,.74) 72%);
}
.pdf-panel.has-preview > * { position: relative; z-index: 1; }
.pdf-panel.has-preview .doc-ico { display: none; }
.pdf-panel.has-preview .pp-meta { color: #fff; font-weight: 700; text-shadow: 0 1px 3px rgba(20,26,34,.6); }

/* Workbook open link measured 39px. */
.pp-open { min-height: 44px; display: inline-flex; align-items: center; justify-content: center; }

/* The practice tip spanned the full column (KP 2026-08-14), which was right
   while it was one short line. It has since grown to 342 characters, and at
   full width that ran 114 characters per line against a comfortable 45 to 75,
   so KP asked on 2026-08-22 for it to sit at reading measure like the module
   prose. The tint keeps spanning the column: the <p> is the panel, so the cap
   goes on an inner span rather than on the panel itself.
   MEASURED, not guessed: at this 14px size one ch is 9.11px (the "0" glyph)
   while an average character in this copy is 6.4px, so ch overshoots by 42%.
   52ch = 473px = about 74 characters. Do not "correct" this upward; 64ch was
   tried and rendered 85 characters per line. */
.exlib-tip { max-width: none; }
.exlib-tip-t { display: block; }

/* ======================= Partial borders removed ========================
   Half-borders (a rule on one edge only) read as unfinished. Replaced with
   either nothing or a full container edge. */
.exgrp-head { border-bottom: 0; padding-bottom: 4px; }

/* --------------- dark scheme: remaining contrast corrections -------------
   Found by a corrected audit. The previous sweep only tested LEAF elements,
   so it skipped every button containing an <svg>, which is exactly where the
   reported fades were. It now tests any element with its own text nodes. */

/* .btn.cream is a light-neutral button by design, but --tp-cream is a dark
   surface in this scheme, so it rendered dark ink on a dark fill (1.42:1).
   It becomes a proper dark secondary here. */
html[data-canvas="dark"] .btn.cream {
  background: var(--tp-inset); color: var(--fg-primary); border: 1px solid var(--tp-hairline-strong);
}
html[data-canvas="dark"] .btn.cream:hover { background: var(--tp-line); }

/* Deep blues used as TEXT on dark surfaces. */
html[data-canvas="dark"] .spot-strap,
html[data-canvas="dark"] .rdl,
html[data-canvas="dark"] .pc-next-strap,
html[data-canvas="dark"] .act-strap,
html[data-canvas="dark"] .cmp-strap { color: var(--tp-sky-blue-300); }

/* .meta-row .m span (0,2,1) out-specifies the light-fill rule above, so the
   stat labels kept --fg-muted and went light on a permanently white card.
   Fixed dark value because this surface is white in EVERY scheme; a token
   that follows the scheme is exactly what breaks here. */
.meta-row .m span { color: #5f6a7a; }

/* ================= Aspect-aware video presentation ======================
   All 12 exercise clips are shot vertical (9:16); all 10 module videos are
   landscape (16:9). Confirmed against Vimeo oEmbed for all 22.

   POSTERS. A 9:16 frame in a 16:9 box shows only 32% of its height, which is
   the mouth-only close-up. A 4:5 box shows about 70% while keeping the card a
   sensible height in a two-column grid, and the crop favours the upper body
   so faces are not sliced. Full 9:16 tiles were rejected: at 450px wide they
   would be 800px tall and the plan view is already the longest screen. */
.ex-video.portrait { aspect-ratio: 4 / 5; }
.ex-video.portrait .ex-poster.has-thumb { background-position: center 22%; }

/* THEATER. The panel was fixed at 16:9, so vertical playback sat between two
   large empty bars on desktop. Vertical video gets a tall, narrow panel
   instead, capped by viewport height so it never overflows. */
/* Derive the WIDTH from the available height rather than fixing the width and
   capping the height: fixing the width left the clip letterboxed inside its
   own panel (measured 26% dead space either side). Setting the height and
   letting aspect-ratio produce the width means the panel hugs the video. */
.vid-modal.portrait .vidm-panel { width: auto; max-width: 94vw; }
.vid-modal.portrait .vidm-frame-wrap {
  aspect-ratio: 9 / 16;
  /* Compute the width from BOTH constraints and let aspect-ratio derive the
     height. Setting the height explicitly meant that on a phone, where the
     modal's own 20px padding binds the width first, the clip letterboxed
     vertically instead (measured 0.509 against a 0.5625 source). */
  width: min(94vw, calc((88vh - 56px) * 0.5625));
  height: auto;
}
.vid-modal.portrait .vidm-frame { height: 100%; }
/* The player letterboxes inside its own frame, so the panel behind it should
   read as part of the player rather than as a white gap. */
.vidm-frame-wrap { background: #000; }

/* The panel is width:auto, so its width is set by the WIDEST child. The header
   (title + hint + close) was wider than the video, so the panel stayed 471px
   against a 414px video and kept 12% dead space. Let the header shrink: the
   hint is secondary and the title truncates. */
.vid-modal.portrait .vidm-hint { display: none; }
.vid-modal.portrait .vidm-head { min-width: 0; }
.vid-modal.portrait .vidm-title {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ---- Guide bio, merged into the Start hero 2026-08-28 -------------------
   "Your guide" was its own rail destination and its own section. KP asked to
   fold it into Start and cut the text down, because a full bio plus three
   credential cards is a lot of scrolling on a phone for something a parent
   reads once. The presenter block above already names her, so this is the
   short "what she does for you" line plus a compact credential strip. */
/* Deliberately identical to .hero-tag (size, leading, colour, measure). They
   sit in the same column as one another and read as one block of prose, so a
   15px bio under an 18px intro looked like a mistake rather than a hierarchy.
   Keep these two rules in step if either changes. */
.hero-bio {
  margin: 12px 0 0; max-width: 520px;
  font-size: var(--fs-18); line-height: var(--lh-relaxed);
  color: var(--fg-secondary); text-wrap: pretty;
}
/* The credential strip had no bottom margin and .meta-row has no top margin,
   so the certifications sat flush against the module squares: measured 0px.
   22px matches the gap .hero-tag already leaves below itself. */
/* This wraps to three lines on a phone now that both myology credentials are
   named in full, and at --lh-tight those lines ran together (KP 2026-09-01:
   "too jumbled"). Bold small caps need MORE leading when they wrap, not less,
   so line-height and the space above it both open up. */
.hero-creds {
  margin: 12px 0 26px;
  font-size: var(--fs-12); font-weight: 700;
  letter-spacing: var(--tracking-wide);
  line-height: 1.7;
  color: var(--fg-muted);
}

/* ---- Storage honesty + install prompt ---------------------------------- */
/* Progress is six localStorage keys on the parent's own device. Safari deletes
   script-writable storage after seven days without a visit UNLESS the site has
   been added to the home screen (webkit.org/blog/10218), which is why the
   install card below exists and why it leads with the progress reason. */
.prog-note {
  margin: 6px 0 0; font-size: var(--fs-12); color: var(--fg-muted);
  line-height: var(--lh-normal);
}
.install-card {
  display: none;                      /* shown by install-prompt.js only when useful */
  margin: 18px 0 0; padding: 14px 16px;
  background: var(--tp-card); border: 1px solid var(--tp-line);
  border-radius: var(--radius-inner);
}
.install-card.on { display: block; }
.install-card p { margin: 0; font-size: var(--fs-14); line-height: var(--lh-relaxed); color: var(--fg-secondary); }
.install-card b { color: var(--fg-primary); }
.install-row { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin-top: 12px; }
.install-row .btn { flex: 0 0 auto; }
.install-dismiss {
  background: none; border: 0; cursor: pointer; padding: 0 6px;
  min-height: 44px; display: inline-flex; align-items: center;
  font-family: var(--font-sans); font-size: var(--fs-12); color: var(--fg-muted);
  text-decoration: underline; text-underline-offset: 2px;
}
.install-dismiss:hover { color: var(--fg-primary); }

/* Numbered install steps (iOS path only). Deliberately styled as a real
   ordered list rather than prose: a parent does this once, on a phone, and
   needs to be able to glance back at step 2 without re-reading a paragraph. */
.install-steps {
  margin: 12px 0 0; padding: 0 0 0 20px;
  font-size: var(--fs-14); line-height: var(--lh-relaxed); color: var(--fg-secondary);
}
.install-steps li { margin: 0 0 6px; }
.install-steps li:last-child { margin-bottom: 0; }
.install-steps b { color: var(--fg-primary); }
/* The Share glyph sits mid-sentence, so it needs optical alignment with the
   text baseline rather than sitting on it. */
.install-steps .ios-share {
  display: inline-block; vertical-align: -3px; margin: 0 1px;
  color: var(--tp-sky-blue-700);
}


/* ---- Animated compare image: say that it is tappable -------------------
   Module 6's "right way" image is a GIF that plays only in the lightbox, so
   the tile is a still. Without a cue nothing tells a parent that tapping does
   anything (KP 2026-09-01). The badge sits on the wrapper rather than inside
   image-slot, which owns its own shadow DOM. */
.cmp-media { position: relative; display: block; }
.cmp-media::after {
  content: "▶  Tap to play";
  position: absolute; left: 50%; bottom: 12px; transform: translateX(-50%);
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 14px; border-radius: var(--radius-pill);
  background: rgba(20, 26, 34, 0.82); color: #fff;
  font-family: var(--font-sans); font-size: var(--fs-12); font-weight: 700;
  letter-spacing: var(--tracking-wide);
  pointer-events: none;   /* the slot underneath keeps the click */
  white-space: nowrap;
}
