/* ════════════════════════════════════════════════════════════════════════
   PsychologyGeet design system - ONE stylesheet for every shell.
   Extracted verbatim from the four reviewed artefacts in docs/design/, so the
   production CSS and the reviewed design cannot drift. The only change is that
   the three subset fonts are now cacheable files under /fonts/ instead of
   base64 (they were inlined only because the Artifact CSP blocks external CSS).
   Brand system LOCKED - see the psychologygeet-brand skill before editing.
   ════════════════════════════════════════════════════════════════════════ */

/* ========================================================================
   shell-notes - the public SEO leaf. ~818 instances.
   Brand system LOCKED (brand-book 03-color, 04-typography, 06-layout).
   Fonts subset from assets/fonts/ and inlined (Artifact CSP blocks CDNs).
   In production these become preloaded external woff2.
   Zero JavaScript by design: INP is free, and it survives a bad 4G hop.
   ======================================================================== */

@font-face{
  font-family:"DM Sans PG";
  src:url("/fonts/dmsans.woff2") format("woff2");
  font-weight:400 700; font-style:normal; font-display:swap;
}
@font-face{
  font-family:"DM Sans PG";
  src:url("/fonts/dmsans-italic.woff2") format("woff2");
  font-weight:400 700; font-style:italic; font-display:swap;
}
@font-face{
  font-family:"DM Serif PG";
  src:url("/fonts/dmserif.woff2") format("woff2");
  font-weight:400; font-style:normal; font-display:swap;
}

/* -- tokens -------------------------------------------------------------
   Every value below is either straight from the brand book or solved for
   AA. Contrast ratios recorded inline so a reviewer can audit them.        */
:root{
  --ground:#EDE4D3;        /* Warm Sand - 55-65% of layout               */
  --surface:#E4D9C4;       /* bounded blocks; Teal on it 6.39:1           */
  --text:#28504F;          /* Teal-Slate on Sand 7.08:1                   */
  --text-strong:#26232F;   /* Ink on Sand 12.20:1                         */
  --muted:#506362;         /* solved for AA-body 5.04:1                   */
  --accent:#B65A3C;        /* Rust 3.68:1 -> rules, fills, large text ONLY */
  --accent-text:#8F4529;   /* Rust darkened where it must carry body text  */
  --track:#C39A3B;         /* University Mustard                          */
  --track-ink:#26232F;     /* Ink on Mustard 5.87:1 - NEVER white 2.62:1   */
  --hair:#D6C9B2;          /* decorative only; structure is semantic       */
  --hair-firm:#BCAB8E;
  --focus:#B65A3C;
  --gauge-off:#C9BCA3;

  --measure:40rem;         /* ~66 CPL at 17px - brand long-form spec       */
  --gutter:3rem;           /* hanging numerals hang into the edge          */
  --edge:1.5rem;           /* ONE page edge shared by masthead, breadcrumb,
                              body and footer, so all left edges align    */

  /* 8px scale (brand 06-layout-spacing) */
  --s1:.5rem; --s2:1rem; --s3:1.5rem; --s4:2rem; --s5:3rem; --s6:4rem;
}

/* Night reading. Derived from the locked palette, not inverted: the ground
   is a deep Teal-Slate-Ink, the text is a warm off-Sand, and Rust is
   lifted to stay text-capable. The Mustard chip is self-contained so it
   carries Ink text unchanged in both themes. */
@media (prefers-color-scheme:dark){
  :root{
    --ground:#1B2524; --surface:#232F2E;
    --text:#E9E0CF;          /* 11.99:1 */
    --text-strong:#F5EFE2;
    --muted:#9DABA9;         /* 6.61:1  */
    --accent:#D9805C;        /* 5.38:1 - text-capable in dark */
    --accent-text:#D9805C;
    --hair:#33423F; --hair-firm:#455654;
    --focus:#D9805C; --gauge-off:#3D4C4A;
  }
}
:root[data-theme="dark"]{
  --ground:#1B2524; --surface:#232F2E; --text:#E9E0CF; --text-strong:#F5EFE2;
  --muted:#9DABA9; --accent:#D9805C; --accent-text:#D9805C;
  --hair:#33423F; --hair-firm:#455654; --focus:#D9805C; --gauge-off:#3D4C4A;
}
:root[data-theme="light"]{
  --ground:#EDE4D3; --surface:#E4D9C4; --text:#28504F; --text-strong:#26232F;
  --muted:#506362; --accent:#B65A3C; --accent-text:#8F4529;
  --hair:#D6C9B2; --hair-firm:#BCAB8E; --focus:#B65A3C; --gauge-off:#C9BCA3;
}

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

body{
  margin:0; background:var(--ground); color:var(--text);
  font-family:"DM Sans PG",system-ui,-apple-system,"Segoe UI",sans-serif;
  font-size:17px; line-height:1.6;            /* brand long-form spec */
  -webkit-text-size-adjust:100%;
  text-align:left;                             /* ragged-right, always */
}

a{color:var(--text); text-decoration-color:var(--accent);
  text-decoration-thickness:1px; text-underline-offset:3px}
a:hover{color:var(--accent-text)}
:focus-visible{outline:2px solid var(--focus); outline-offset:2px; border-radius:2px}

.skip{position:absolute; left:-9999px}
.skip:focus{left:var(--s2); top:var(--s2); z-index:9; background:var(--surface);
  padding:var(--s1) var(--s2); border:1px solid var(--hair-firm)}

/* -- masthead --------------------------------------------------------- */
.masthead{
  display:flex; flex-wrap:wrap; gap:var(--s2) var(--s3);
  align-items:center; justify-content:space-between;
  padding:var(--s3) var(--edge) var(--s2);
  max-width:74rem; margin:0 auto;
}
.lockup{display:flex; align-items:center; gap:.625rem; text-decoration:none}
/* The "G" monogram: DM Serif G in a Teal-Slate rounded square with the
   Rust speech-mark dot at upper-right (brand 02-logo-system). */
.monogram{
  position:relative; flex:none; width:34px; height:34px; border-radius:8px;
  background:#28504F; color:#EDE4D3;
  font-family:"DM Serif PG",Georgia,serif; font-size:22px; line-height:34px;
  text-align:center;
}
.monogram::after{
  content:""; position:absolute; top:4px; right:4px;
  width:6px; height:6px; border-radius:50%; background:#B65A3C;
}
.wordmark{font-family:"DM Serif PG",Georgia,serif; font-size:1.25rem;
  color:var(--text-strong); letter-spacing:.01em}
.mast-actions{display:flex; align-items:center; gap:var(--s2); font-size:.9375rem}
.btn-quiet{color:var(--text); text-decoration:none; padding:.375rem 0}
.btn-quiet:hover{text-decoration:underline; text-decoration-color:var(--accent)}
.btn{
  display:inline-block; background:var(--accent); color:#FFF7EF;
  font-weight:600; font-size:.9375rem; text-decoration:none;
  padding:.5rem .9375rem; border-radius:4px; min-height:24px;
}
.btn:hover{background:var(--accent-text); color:#FFF7EF}
@media (prefers-color-scheme:dark){ .btn{color:#1B2524} .btn:hover{color:#1B2524} }
:root[data-theme="dark"] .btn{color:#1B2524}

/* -- breadcrumb ------------------------------------------------------- */
.crumbs{max-width:74rem; margin:0 auto; padding:0 var(--edge) var(--s3);
  font-size:.8125rem; color:var(--muted)}
.crumbs ol{list-style:none; margin:0; padding:0;
  display:flex; flex-wrap:wrap; gap:.25rem .5rem}
.crumbs li{display:flex; align-items:center}
.crumbs li::after{content:"\203A"; margin-left:.5rem; color:var(--hair-firm)}
.crumbs li:last-child::after{content:""}
/* WCAG 2.2 SC 2.5.8: breadcrumbs are navigation in a list, not links inside a
   sentence, so the inline exception does not cover them - pad to 24px. */
.crumbs a{color:var(--muted); display:inline-block; padding:.21875rem 0; min-height:24px}
.crumbs [aria-current]{color:var(--text)}

/* -- page grid -------------------------------------------------------- */
.page{
  max-width:74rem; margin:0 auto; padding:0 var(--edge) var(--s6);
  display:grid; gap:var(--s6) var(--s5); align-items:start;
  grid-template-columns:minmax(0,1fr);
}
/* Single column: no gutter, so every block aligns to the reading measure. */
.notes{max-width:var(--measure); min-width:0}
@media (min-width:1080px){
  :root{--edge:4.5rem}   /* room for the numerals to hang, text stays put */
  .page{grid-template-columns:minmax(0,1fr) 16rem}
  .rail{position:sticky; top:var(--s2); max-height:calc(100vh - var(--s4));
    grid-template-rows:auto minmax(0,1fr)}
}

/* -- eyebrow + title ------------------------------------------------- */
.eyebrow{display:flex; flex-wrap:wrap; align-items:center; gap:var(--s1) .75rem;
  margin-bottom:var(--s2)}
/* Track colour is ALWAYS a bounded chip carrying a printed text label -
   never colour alone (brand 07-track-system). */
.chip{
  display:inline-flex; align-items:center; gap:.375rem;
  background:var(--track); color:var(--track-ink);
  font-size:.6875rem; font-weight:700; letter-spacing:.09em;
  text-transform:uppercase; padding:.25rem .5rem; border-radius:3px;
}
.chip svg{flex:none}
.eyebrow .paper{font-size:.875rem; color:var(--muted)}

h1{
  font-family:"DM Serif PG",Georgia,serif; font-weight:400;
  font-size:clamp(1.875rem,5.5vw,2.625rem); line-height:1.14;
  color:var(--text-strong); margin:0 0 var(--s2); text-wrap:balance;
}
.byline{font-size:.9375rem; color:var(--muted); margin:0 0 var(--s4);
  text-wrap:pretty}
.byline strong{color:var(--text); font-weight:600}

/* Teaching hours are absent from every rendered surface by rule: contact
   hours are an institution timetable artefact, unlike UGC-standard credits.
   They stay in curriculum.yaml for internal coverage reports only.
   -- THE DOCKET - signature element -------------------------------------
   The at-a-glance block, mandated BEFORE the intro (schema sec. 9). Built as a
   syllabus coordinate stamp rather than a summary card: this is not an
   article, it is chapter 1 of 12 inside a 60-hour four-unit paper, and the
   reader's first question is where they are.                              */
.docket{
  background:var(--surface); border:1px solid var(--hair-firm);
  border-radius:4px; padding:var(--s3);
  display:grid; gap:1.25rem; margin:0 0 var(--s4);
}

/* 12 ticks, grouped into the 4 units. Position, not progress - nothing has
   been "completed". Colour is never the sole carrier: the text line states
   it, and the current tick is also taller. */
.gauge{display:grid; gap:.5rem}
.gauge-track{display:flex; gap:.75rem; align-items:flex-end}
.gauge-unit{display:flex; gap:.1875rem; align-items:flex-end}
.tick{width:100%; min-width:.5rem; flex:1; height:.5rem; border-radius:1px;
  background:var(--gauge-off)}
.tick.is-here{height:1rem; background:var(--accent)}
.gauge-label{font-size:.75rem; color:var(--muted); letter-spacing:.02em;
  font-variant-numeric:tabular-nums}
.gauge-label b{color:var(--text); font-weight:600}

.docket-rule{border:0; border-top:1px solid var(--hair-firm); margin:0}

.coords{display:grid; gap:.375rem; font-variant-numeric:tabular-nums}
.coords dt{font-size:.6875rem; letter-spacing:.09em; text-transform:uppercase;
  color:var(--muted)}
.coords dd{margin:0; font-size:1.0625rem; color:var(--text-strong)}
.coords .row{display:flex; flex-wrap:wrap; gap:var(--s1) var(--s4)}
.coords .cell{display:grid; gap:.125rem}

.covers{display:grid; gap:.5rem}
.covers h2{font-family:"DM Sans PG",sans-serif; font-size:.6875rem;
  font-weight:700; letter-spacing:.09em; text-transform:uppercase;
  color:var(--muted); margin:0}
.covers ul{list-style:none; margin:0; padding:0; display:grid; gap:.375rem}
.covers li{display:grid; grid-template-columns:.875rem 1fr; gap:.5rem;
  font-size:.9375rem}
.covers li::before{content:"\2014"; color:var(--accent)}

/* -- prose -------------------------------------------------------------
   Flow spacing on a single owl selector so nothing collides. Headings and
   blocks override their own top margin only.                             */
.prose{max-width:var(--measure)}
/* Flow spacing lives on ONE owl selector, and every override of it is
   deliberately higher-specificity. A bare `.prose p{margin:0}` here is
   (0,1,1) and silently beats the owl at (0,1,0), collapsing every
   paragraph gap in the chapter. Reset via `.prose > *` instead, which
   ties on specificity and loses to the owl on source order. */
.prose > *{margin:0}
.prose > * + *{margin-top:1.5em}
.prose > h2{
  font-family:"DM Serif PG",Georgia,serif; font-weight:400;
  font-size:clamp(1.375rem,3.4vw,1.75rem); line-height:1.22;
  color:var(--text-strong); margin:2.75em 0 0; text-wrap:balance;
}
.prose > h3{
  font-family:"DM Serif PG",Georgia,serif; font-weight:400;
  font-size:1.25rem; line-height:1.3; color:var(--text);
  margin:2.25em 0 0; text-wrap:balance;
}
.prose > h2 + *, .prose > h3 + *{margin-top:.75em}

/* Hanging numerals. The author numbered these sections; the numeral is real
   information, so it stays in the accessible name and only moves visually. */
.h-num{display:block}
@media (min-width:1080px){
  /* Specificity must beat `.prose > h2`, whose `margin` shorthand would
     otherwise reset margin-left back to 0 and un-hang the numeral. */
  .prose > h2.h-num{display:grid; grid-template-columns:var(--gutter) 1fr;
    align-items:baseline; margin-left:calc(var(--gutter) * -1)}
}
.h-num .n{color:var(--accent); font-size:.8em}
@media (max-width:1079.98px){ .h-num .n{margin-right:.4em} }

/* Asst. Prof. Geetika Rai's own pattern: "**Choosing.** This happens..." - a bold
   lead-in opening a paragraph. Styled because the content does it, not
   because a template offered it. */
.prose p > strong:first-child{color:var(--text-strong); font-weight:700}
.prose strong{font-weight:600; color:var(--text-strong)}
/* A real italic cut, not a synthesized oblique - DMSans-Italic[opsz,wght]
   subset alongside the roman. The chapter leans on italic emphasis heavily
   ("why you bought *that* one"), so a faked slant was visible. */
.prose em{font-style:italic}

.prose ol,.prose ul{padding-left:1.375rem; display:grid; gap:.5em}
.prose li{padding-left:.125rem}
.prose ol{list-style:decimal}
.prose ol::marker,.prose li::marker{color:var(--muted)}

/* the chapter's one formal definition */
.keydef{background:var(--surface); border-left:3px solid var(--track);
  padding:var(--s2) var(--s3); border-radius:0 4px 4px 0;
  font-size:1.0625rem; line-height:1.55}
.keydef strong{color:var(--text-strong)}

/* Pull-quote, brand spec exactly: DM Serif Display 28px, 4px Rust left
   rule, 1.5em indent, NO quotation marks. Authored as a Markdown
   blockquote - see the note in docs/design/README. Used once. */
.prose blockquote{
  /* rem, not em: 2em would resolve against the quote's own 28px and
     silently double the gap the rest of the flow uses. */
  margin:2rem 0 0; padding-left:1.5em; border-left:4px solid var(--accent);
  font-family:"DM Serif PG",Georgia,serif; font-weight:400;
  font-size:1.75rem; line-height:1.3; color:var(--text);
}
.prose blockquote p{margin:0}

/* key terms -> a real definition list */
.terms{margin:0; display:grid; gap:var(--s2)}
.terms > div{display:grid; gap:.25rem}
.terms dt{font-weight:700; color:var(--text-strong)}
.terms dd{margin:0; color:var(--text)}
/* first mentions link to the glossary anchor - no tooltip JS, works on touch */
.term-link{text-decoration:underline; text-decoration-style:dotted;
  text-decoration-color:var(--hair-firm); text-underline-offset:3px}
.term-link:hover{text-decoration-color:var(--accent)}
:target{scroll-margin-top:var(--s3)}
.terms > div:target dt{color:var(--accent-text)}

/* -- check yourself ---------------------------------------------------
   The author's own exit test. Answers live in the answer key, which is
   gated - so this block is where the account earns itself honestly. */
.selftest{
  margin-top:var(--s5); background:var(--surface);
  border:1px solid var(--hair-firm); border-radius:4px; padding:var(--s3);
}
.selftest h2{font-family:"DM Serif PG",Georgia,serif; font-weight:400;
  font-size:1.5rem; line-height:1.25; color:var(--text-strong); margin:0 0 .5rem}
.selftest > p{margin:0 0 var(--s2); font-size:.9375rem; color:var(--muted)}
.selftest ol{margin:0; padding-left:1.375rem; display:grid; gap:.625rem}
.selftest .after{margin:var(--s3) 0 0; padding-top:var(--s2);
  border-top:1px solid var(--hair-firm); font-size:.9375rem; color:var(--muted)}

/* -- the one CTA, naming exactly what an account opens ----------------- */
.unlock{
  margin-top:var(--s5); border:1px solid var(--hair-firm); border-radius:4px;
  padding:var(--s3); display:grid; gap:var(--s2); background:var(--surface);
}
.unlock h2{font-family:"DM Serif PG",Georgia,serif; font-weight:400;
  font-size:1.5rem; line-height:1.25; color:var(--text-strong); margin:0}
.unlock p{margin:0; font-size:.9375rem}
.unlock ul{list-style:none; margin:0; padding:0; display:grid; gap:.375rem;
  font-size:.9375rem}
.unlock li{display:grid; grid-template-columns:1rem 1fr; gap:.5rem}
.unlock li::before{content:"+"; color:var(--accent); font-weight:700}
.unlock .actions{display:flex; flex-wrap:wrap; gap:var(--s2); align-items:center;
  margin-top:var(--s1)}
.unlock .note{font-size:.8125rem; color:var(--muted); margin:0}

/* -- provenance + sources (E-E-A-T, and the schema's visible provenance) - */
.sources{margin-top:var(--s5)}
.sources h2{font-family:"DM Serif PG",Georgia,serif; font-weight:400;
  font-size:1.375rem; color:var(--text-strong); margin:0 0 var(--s2)}
.sources ul{list-style:none; margin:0; padding:0; display:grid; gap:.625rem;
  font-size:.9375rem; color:var(--text)}
.sources cite{font-style:italic}
.sources .flag{font-size:.6875rem; font-weight:700; letter-spacing:.06em;
  text-transform:uppercase; color:var(--accent-text)}

.provenance{
  margin-top:var(--s4); padding-top:var(--s3);
  border-top:1px solid var(--hair-firm);
  font-size:.8125rem; color:var(--muted); display:grid; gap:.5rem;
}
.provenance dl{margin:0; display:grid; gap:.25rem}
.provenance .pair{display:flex; flex-wrap:wrap; gap:.375rem}
.provenance dt{font-weight:600; color:var(--text)}
.provenance dd{margin:0}

/* -- rail: the syllabus spine + the sibling assets -------------------- */
.rail{display:grid; gap:var(--s4); font-size:.875rem; min-width:0}
/* The spine can be long; the slot nav must not be pushed out of sight, so
   only the spine scrolls inside the sticky rail. */
.rail .spine-wrap{min-height:0; overflow-y:auto}
.rail section{display:grid; gap:.75rem}
.rail h2{font-family:"DM Sans PG",sans-serif; font-size:.6875rem;
  font-weight:700; letter-spacing:.09em; text-transform:uppercase;
  color:var(--muted); margin:0}
.spine{list-style:none; margin:0; padding:0; display:grid; gap:.25rem}
.spine .unit{
  margin-top:.75rem; padding-top:.5rem; border-top:1px solid var(--hair);
  font-size:.6875rem; letter-spacing:.06em; text-transform:uppercase;
  color:var(--muted); font-weight:700;
}
.spine .unit:first-child{margin-top:0; padding-top:0; border-top:0}
.spine a{display:grid; grid-template-columns:1.75rem 1fr; gap:.375rem;
  padding:.3125rem .375rem; border-radius:3px; text-decoration:none;
  color:var(--text); min-height:24px; align-items:baseline}
.spine a:hover{background:var(--surface)}
.spine .cn{color:var(--muted); font-size:.75rem; font-variant-numeric:tabular-nums}
.spine [aria-current="page"]{background:var(--surface); font-weight:600;
  color:var(--text-strong); box-shadow:inset 3px 0 0 var(--accent)}
.spine [aria-current="page"] .cn{color:var(--accent-text)}

/* Sibling assets. Only the five a student tier may ever see are rendered.
   The three teacher slots are ABSENT from the DOM - HIDE, not DENY
   (schema sec. 14). A locked-but-visible teacher slot would be a leak. */
.slots{list-style:none; margin:0; padding:0; display:grid; gap:.25rem}
.slots a,.slots .now{display:grid; grid-template-columns:1fr auto; gap:.5rem;
  align-items:baseline; padding:.4375rem .5rem; border-radius:3px;
  text-decoration:none; color:var(--text); min-height:24px}
.slots a:hover{background:var(--surface)}
.slots .now{background:var(--surface); font-weight:600; color:var(--text-strong);
  box-shadow:inset 3px 0 0 var(--accent)}
.slots .state{font-size:.6875rem; color:var(--muted); letter-spacing:.03em;
  white-space:nowrap}
.slots .now .state{color:var(--accent-text); font-weight:700}
.rail .rail-note{margin:0; font-size:.75rem; color:var(--muted)}

/* -- footer: the sitewide notices (schema sec. 18) ------------------------ */
.footnotes{
  border-top:1px solid var(--hair-firm); margin-top:var(--s4);
  padding:var(--s4) var(--edge) var(--s6);
}
.footnotes .inner{max-width:74rem; margin:0 auto; display:grid; gap:var(--s2);
  font-size:.8125rem; color:var(--muted)}
.footnotes strong{color:var(--text); font-weight:600}
.footnotes p{margin:0; max-width:52rem}

/* -- print: suppressed while signed out ----------------------------------
   Friction, not security. The real control is that PDF and Word
   derivatives are entitlement-gated server-side and watermarked per user.
   Text selection is deliberately NOT blocked - that breaks assistive tech
   and buys nothing.                                                       */
@media print{
  .masthead,.crumbs,.rail,.footnotes,.sitefoot,.utility,.sitenav,
  .unlock,.selftest,.docket,.prose,
  .sources,.provenance,.byline,.eyebrow,h1{display:none !important}
  .print-notice{display:block !important; font-family:Georgia,serif;
    font-size:12pt; line-height:1.5; color:#000; max-width:34em}
}
.print-notice{display:none}

@media (prefers-reduced-motion:reduce){
  *{animation:none !important; transition:none !important; scroll-behavior:auto !important}
}

/* ======== shared by shell-chapter and shell-asset ======== */

/* A state is always a printed word. Colour only reinforces it, never carries
   it - a colour-blind or photocopied read must lose nothing. */
.state-tag{font-size:.6875rem; font-weight:700; letter-spacing:.07em;
  text-transform:uppercase; white-space:nowrap}
.state-free{color:var(--text)}          /* Teal-Slate  7.08 / 6.39 */
.state-account{color:var(--accent-text)}/* #8F4529     5.45 / 4.92 */
.state-soon{color:var(--muted)}         /* #506362     5.04 / 4.55 */

.section-label{font-family:"DM Sans PG",sans-serif; font-size:.6875rem;
  font-weight:700; letter-spacing:.09em; text-transform:uppercase;
  color:var(--muted); margin:0}

.block{margin-top:var(--s5)}
.block > h2{font-family:"DM Serif PG",Georgia,serif; font-weight:400;
  font-size:clamp(1.375rem,3.4vw,1.625rem); line-height:1.22;
  color:var(--text-strong); margin:0 0 var(--s2); text-wrap:balance}
.block > p{margin:0 0 var(--s2)}
.block > p:last-child{margin-bottom:0}

.empty{border:1px dashed var(--hair-firm); border-radius:4px;
  padding:var(--s2) var(--s3); color:var(--muted); font-size:.9375rem}

.pairs{margin:0; display:grid; gap:.75rem}
.pairs > div{display:grid; grid-template-columns:9.5rem 1fr; gap:.75rem;
  align-items:baseline}
@media (max-width:539.98px){ .pairs > div{grid-template-columns:1fr; gap:.125rem} }
.pairs dt{font-size:.6875rem; font-weight:700; letter-spacing:.07em;
  text-transform:uppercase; color:var(--muted)}
.pairs dd{margin:0}

.faq{display:grid; gap:var(--s3)}
.faq > div{display:grid; gap:.375rem}
.faq h3{font-family:"DM Serif PG",Georgia,serif; font-weight:400;
  font-size:1.1875rem; line-height:1.3; color:var(--text-strong); margin:0}
.faq p{margin:0}

.chips-row{display:flex; flex-wrap:wrap; gap:.5rem; margin:0; padding:0;
  list-style:none}
.chips-row a{display:inline-block; padding:.3125rem .625rem; min-height:24px;
  border:1px solid var(--hair-firm); border-radius:3px; font-size:.875rem;
  text-decoration:none; color:var(--text)}
.chips-row a:hover{background:var(--surface); color:var(--accent-text)}

.stepper{display:grid; gap:var(--s2); margin-top:var(--s5);
  border-top:1px solid var(--hair-firm); padding-top:var(--s3)}
@media (min-width:560px){ .stepper{grid-template-columns:1fr 1fr; gap:var(--s3)} }
.stepper a,.stepper .none{display:grid; gap:.1875rem; padding:.625rem .75rem;
  border:1px solid var(--hair-firm); border-radius:4px; text-decoration:none;
  color:var(--text)}
.stepper a:hover{background:var(--surface)}
.stepper .none{border-style:dashed; color:var(--muted)}
.stepper .dir{font-size:.6875rem; font-weight:700; letter-spacing:.07em;
  text-transform:uppercase; color:var(--muted)}
.stepper .ttl{font-weight:600}

/* ======== shell-chapter ========
   THE BUNDLE MANIFEST - signature element.
   The chapter hub's whole job is answering "what is here for me, and can I
   have it right now". That is a comparison across items on two axes, so it is
   built as a ruled manifest, not a grid of cards - cards would decorate a
   question that a ledger answers.

   Only the five student-tier slots are rendered. deck_outline, teaching_notes
   and teaching_guide are ABSENT from the DOM, and coverage_report has no URL
   at any tier. Rendering a teacher slot as "locked" would leak its existence,
   which is the HIDE-vs-DENY error (schema sec. 14).                          */
.bundle{margin-top:var(--s5)}
.bundle-head{display:flex; flex-wrap:wrap; align-items:baseline;
  justify-content:space-between; gap:var(--s1) var(--s2); margin-bottom:var(--s2)}
.bundle-head h2{font-family:"DM Serif PG",Georgia,serif; font-weight:400;
  font-size:clamp(1.375rem,3.4vw,1.625rem); line-height:1.2;
  color:var(--text-strong); margin:0}
.bundle-count{font-size:.8125rem; color:var(--muted);
  font-variant-numeric:tabular-nums}
.bundle-count b{color:var(--text); font-weight:600}

.manifest{list-style:none; margin:0; padding:0;
  border-top:1px solid var(--hair-firm)}
.manifest > li{border-bottom:1px solid var(--hair)}
.manifest .row{display:grid; gap:.25rem; padding:var(--s2) .5rem var(--s2) .75rem;
  text-decoration:none; color:var(--text); box-shadow:inset 3px 0 0 transparent}
a.row:hover{background:var(--surface)}
a.row:hover .name{color:var(--accent-text)}
.manifest .is-open{box-shadow:inset 3px 0 0 var(--accent)}
.manifest .top{display:flex; flex-wrap:wrap; align-items:baseline;
  justify-content:space-between; gap:.25rem var(--s2)}
.name{font-family:"DM Serif PG",Georgia,serif; font-size:1.1875rem;
  line-height:1.25; color:var(--text-strong)}
.manifest .what{font-size:.9375rem; color:var(--text); max-width:44ch}
.manifest .meta{font-size:.8125rem; color:var(--muted);
  font-variant-numeric:tabular-nums}
.bundle-note{margin:var(--s2) 0 0; font-size:.8125rem; color:var(--muted)}

.objectives{margin:0; padding-left:1.375rem; display:grid; gap:.5em}
.objectives li{padding-left:.125rem}
.objectives::marker,.objectives li::marker{color:var(--muted)}

.topics{list-style:none; margin:0; padding:0; display:grid; gap:.375rem}
.topics li{display:grid; grid-template-columns:.875rem 1fr; gap:.5rem}
.topics li::before{content:"\2014"; color:var(--accent)}

/* ======== shell-chapter, sparse state ========
   An unwritten slot is inert text, never a link that goes nowhere and never a
   button that looks pressable. It is also NOT styled as an error - an empty
   slot is a normal state of a seeded tree, not a fault.                      */
.manifest .row{cursor:default}
.manifest > li:has(.state-soon) .name{color:var(--muted)}
.slots .slot-off{display:grid; grid-template-columns:1fr auto; gap:.5rem;
  align-items:baseline; padding:.4375rem .5rem; color:var(--muted)}
.slots .slot-off .state{font-size:.6875rem; letter-spacing:.03em}

/* The honest route out. A 0-of-5 chapter must not be a dead end, so it points
   at the chapter that IS ready rather than leaving the reader stranded. */
.detour{margin-top:var(--s4); border-left:3px solid var(--accent);
  padding:.25rem 0 .25rem var(--s2); display:grid; gap:.5rem}
.detour p{margin:0}

/* ======== shell-asset ========
   THE SPECIMEN - signature element.
   ~4,900 of these pages exist. A gated page that only says "sign in" is thin
   content (risk R-04) and earns a noindex forever. So this page carries the
   asset's real specification and a genuine excerpt, and stops at a printed
   boundary. No blur-fade: a fade is a dark pattern that also ships the text
   to the client anyway. An honest hard stop respects the reader and is
   cheaper.                                                                  */
.specimen{margin-top:var(--s5); border:1px solid var(--hair-firm);
  border-radius:4px; background:var(--surface); overflow:hidden}
.specimen-head{display:flex; flex-wrap:wrap; align-items:baseline;
  justify-content:space-between; gap:.25rem var(--s2);
  padding:.625rem var(--s3); border-bottom:1px solid var(--hair-firm)}
.specimen-body{padding:var(--s3)}
.specimen-body h3{font-family:"DM Serif PG",Georgia,serif; font-weight:400;
  font-size:1.25rem; line-height:1.3; color:var(--text-strong);
  margin:0 0 .5rem}
.specimen-body p{margin:0}
.specimen-stop{display:flex; align-items:center; gap:.75rem;
  padding:.625rem var(--s3); border-top:1px solid var(--hair-firm);
  font-size:.75rem; font-weight:700; letter-spacing:.07em;
  text-transform:uppercase; color:var(--muted)}
.specimen-stop::before,.specimen-stop::after{content:""; flex:1;
  border-top:1px solid var(--hair-firm)}

.inside{list-style:none; margin:0; padding:0;
  border-top:1px solid var(--hair-firm)}
.inside li{display:grid; grid-template-columns:1.75rem 1fr; gap:.75rem;
  padding:.625rem .25rem; border-bottom:1px solid var(--hair);
  align-items:baseline}
.inside .n{font-size:.8125rem; color:var(--muted);
  font-variant-numeric:tabular-nums}
.inside b{color:var(--text-strong); font-weight:600}
.inside .plain{grid-column:1 / -1}

.free-route{margin-top:var(--s4); border-left:3px solid var(--accent);
  padding:.25rem 0 .25rem var(--s2)}
.free-route p{margin:0}


/* ════════ site navigation (sec. 6) ════════
   A track that is not published yet is TEXT, never a link. A nav full of dead
   links teaches a visitor the site is broken before they read a word. */
.sitenav{border-top:1px solid var(--hair); border-bottom:1px solid var(--hair);
  background:var(--surface)}
.sitenav ul{max-width:74rem; margin:0 auto; padding:0 var(--edge);
  display:flex; flex-wrap:wrap; gap:0 var(--s4); list-style:none}
.sitenav a,.sitenav .soon{display:inline-block; padding:.6875rem 0;
  font-size:.9375rem; text-decoration:none; color:var(--text); min-height:24px}
.sitenav a:hover{color:var(--accent-text); text-decoration:underline;
  text-decoration-color:var(--accent); text-underline-offset:4px}
.sitenav [aria-current]{font-weight:600; box-shadow:inset 0 -3px 0 var(--accent)}
.sitenav .soon{color:var(--muted); cursor:default}

/* ════════ front-door pages ════════ */
.hero{max-width:74rem; margin:0 auto; padding:var(--s6) var(--edge) var(--s5)}
.hero h1{font-family:"DM Serif PG",Georgia,serif; font-weight:400;
  font-size:clamp(2rem,6vw,3rem); line-height:1.1; color:var(--text-strong);
  margin:0 0 var(--s2); max-width:20ch; text-wrap:balance}
.hero .lede{font-size:1.125rem; line-height:1.55; max-width:52ch; margin:0 0 var(--s3)}
.hero .by{font-size:.9375rem; color:var(--muted); margin:0}

.counts{display:flex; flex-wrap:wrap; gap:var(--s4); margin:var(--s4) 0 0;
  padding:0; list-style:none; font-variant-numeric:tabular-nums}
.counts b{display:block; font-family:"DM Serif PG",Georgia,serif;
  font-size:1.75rem; line-height:1.1; color:var(--text-strong)}
.counts span{font-size:.8125rem; color:var(--muted)}

.band{max-width:74rem; margin:0 auto; padding:0 var(--edge) var(--s6)}
.band > h2{font-family:"DM Serif PG",Georgia,serif; font-weight:400;
  font-size:clamp(1.375rem,3.4vw,1.75rem); color:var(--text-strong);
  margin:0 0 var(--s2)}
.band > p{max-width:60ch; margin:0 0 var(--s3)}

.cards{list-style:none; margin:0; padding:0; display:grid; gap:var(--s2)}
@media (min-width:700px){ .cards{grid-template-columns:repeat(2,minmax(0,1fr))} }
@media (min-width:1080px){ .cards{grid-template-columns:repeat(3,minmax(0,1fr))} }
.cards a{display:grid; gap:.3125rem; padding:var(--s2);
  border:1px solid var(--hair-firm); border-radius:4px; text-decoration:none;
  color:var(--text); background:var(--surface)}
.cards a:hover{border-color:var(--accent)}
.cards .code{font-size:.75rem; letter-spacing:.06em; color:var(--muted);
  font-variant-numeric:tabular-nums}
.cards .name{font-family:"DM Serif PG",Georgia,serif; font-size:1.125rem;
  line-height:1.25; color:var(--text-strong)}
.cards .meta{font-size:.8125rem; color:var(--muted)}

.plain-list{list-style:none; margin:0; padding:0;
  border-top:1px solid var(--hair-firm)}
.plain-list li{border-bottom:1px solid var(--hair)}
.plain-list a{display:grid; grid-template-columns:5rem 1fr auto; gap:var(--s2);
  align-items:baseline; padding:.75rem .25rem; text-decoration:none; color:var(--text)}
.plain-list a:hover{background:var(--surface)}
@media (max-width:599.98px){ .plain-list a{grid-template-columns:4rem 1fr} .plain-list .st{grid-column:2} }
.plain-list .cd{font-size:.8125rem; color:var(--muted); font-variant-numeric:tabular-nums}
.plain-list .nm{color:var(--text-strong)}
.plain-list .st{font-size:.75rem; letter-spacing:.05em; text-transform:uppercase;
  color:var(--muted); white-space:nowrap}

/* =========================================================================
   Accounts, dashboards, mega-menu, real footer, static pages.
   Everything below reuses the locked tokens above — no new colour is
   introduced, so dark mode is inherited rather than re-solved.
   ========================================================================= */

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

/* -- utility bar (sec. 6.1) ---------------------------------------------- */
.utility{border-bottom:1px solid var(--hair); font-size:.8125rem}
.utility{display:flex; flex-wrap:wrap; gap:var(--s1) var(--s3);
  align-items:center; justify-content:space-between;
  max-width:74rem; margin:0 auto; padding:.375rem var(--edge)}
.utility ul{list-style:none; margin:0; padding:0; display:flex;
  flex-wrap:wrap; gap:var(--s1) var(--s3)}
.utility a{color:var(--muted); text-decoration:none; padding:.25rem 0;
  display:inline-block; min-height:24px}
.utility a:hover{color:var(--accent-text); text-decoration:underline}
.utility-account a strong{color:var(--text); font-weight:600}
.linkish{background:none; border:0; padding:.25rem 0; font:inherit;
  color:var(--muted); cursor:pointer; text-decoration:none}
.linkish:hover{color:var(--accent-text); text-decoration:underline}

/* -- mega-menu: native <details>, no JavaScript --------------------------- */
.sitenav .mega{position:relative}
.sitenav summary{display:inline-block; padding:.6875rem 0; cursor:pointer;
  list-style:none; color:var(--text); text-decoration:none}
.sitenav summary::-webkit-details-marker{display:none}
.sitenav summary::after{content:"\25BE"; font-size:.625rem; margin-left:.375rem;
  color:var(--muted)}
.sitenav summary:hover{color:var(--accent-text); text-decoration:underline;
  text-decoration-color:var(--accent)}
.sitenav [aria-current]{font-weight:600; box-shadow:inset 0 -3px 0 var(--accent)}
.sitenav details[open] > summary{color:var(--accent-text); font-weight:600}

/* Translucent, with a blur behind it. A flat opaque panel in --surface sat
   almost the same colour as the page and read as part of it; frosting lifts it
   off the page and makes it obvious which menu is open. The blur is what keeps
   the text legible over whatever it covers — WITHOUT it, transparency here
   would be actively worse than the opaque version. */
.mega-panel{
  position:absolute; z-index:20; left:0; top:100%; min-width:min(34rem,92vw);
  background:var(--surface); border:1px solid var(--hair-firm);
  border-radius:6px; padding:var(--s3);
  box-shadow:0 16px 40px rgba(38,35,47,.22), 0 2px 6px rgba(38,35,47,.10);
}
@supports (backdrop-filter:blur(14px)) or (-webkit-backdrop-filter:blur(14px)){
  .mega-panel{
    background:color-mix(in srgb, var(--surface) 82%, transparent);
    -webkit-backdrop-filter:blur(14px) saturate(1.3);
    backdrop-filter:blur(14px) saturate(1.3);
  }
}
/* The open tab is tied to its panel by a shared edge. */
.sitenav details[open] > summary{
  box-shadow:inset 0 -3px 0 var(--accent);
}
.mega-lede{margin:0 0 var(--s2); font-size:.875rem; color:var(--muted);
  max-width:44ch}
.mega-cols{display:grid; gap:var(--s3)}
@media (min-width:600px){ .mega-cols{grid-template-columns:repeat(auto-fit,minmax(11rem,1fr))} }
.mega-cols h3{font-family:"DM Sans PG",sans-serif; font-size:.6875rem;
  letter-spacing:.09em; text-transform:uppercase; color:var(--muted);
  margin:0 0 .5rem; font-weight:600}
.mega-cols ul{list-style:none; margin:0; padding:0; display:grid; gap:.375rem}
.mega-cols a{color:var(--text); text-decoration:none; font-size:.9375rem;
  display:inline-block; padding:.1875rem 0; min-height:24px}
.mega-cols a:hover{color:var(--accent-text); text-decoration:underline}
/* The section overview, promoted from the foot of the panel to its head.
   It was there before and read as absent, which is what a link below a
   column of links amounts to. Now it is the first and most prominent thing
   a reader meets when the menu opens. */
.mega-index{margin:0 0 var(--s2); padding-bottom:var(--s2);
  border-bottom:1px solid var(--hair)}
.mega-index a{display:inline-block; color:var(--accent-text); font-weight:700;
  font-size:.9375rem; text-decoration:none; padding:.25rem 0; min-height:24px}
.mega-index a:hover{text-decoration:underline}

/* On a narrow screen the panel is a normal block, not an overlay. */
@media (max-width:599px){
  .sitenav ul{flex-direction:column; align-items:stretch}
  .mega-panel{position:static; min-width:0; box-shadow:none;
    margin:0 0 var(--s2)}
}

/* -- the real footer ------------------------------------------------------ */
.sitefoot{border-top:1px solid var(--hair-firm); margin-top:var(--s6);
  background:var(--surface)}
.foot-cols{max-width:74rem; margin:0 auto; padding:var(--s5) var(--edge) var(--s4);
  display:grid; gap:var(--s4)}
@media (min-width:640px){ .foot-cols{grid-template-columns:repeat(2,minmax(0,1fr))} }
@media (min-width:900px){
  .foot-cols{grid-template-columns:1.4fr repeat(5,minmax(0,1fr))}
}
.foot-brand .monogram{display:inline-block; margin-bottom:.5rem}
/* The masthead monogram is a flex item, so its box applies there. Standing
   alone in the footer it is an inline span, which ignores width/height and
   clipped the G to a sliver. */
.foot-word{font-family:"DM Serif PG",Georgia,serif; font-size:1.125rem;
  color:var(--text-strong); margin:0 0 .375rem}
.foot-line{margin:0; font-size:.8125rem; color:var(--muted); max-width:32ch}
.foot-cols h2{font-family:"DM Sans PG",sans-serif; font-size:.6875rem;
  letter-spacing:.09em; text-transform:uppercase; color:var(--muted);
  margin:0 0 .625rem; font-weight:600}
.foot-cols ul{list-style:none; margin:0; padding:0; display:grid; gap:.4375rem}
.foot-cols a{color:var(--text); text-decoration:none; font-size:.875rem;
  display:inline-block; padding:.1875rem 0; min-height:24px}
.foot-cols a:hover{color:var(--accent-text); text-decoration:underline}

.foot-strip{border-top:1px solid var(--hair-firm)}
.foot-strip{max-width:74rem; margin:0 auto; padding:var(--s3) var(--edge) var(--s4);
  display:grid; gap:var(--s2); font-size:.8125rem; color:var(--muted)}
.foot-strip p{margin:0; max-width:60rem}
.foot-strip strong{color:var(--text); font-weight:600}
.foot-strip a{color:var(--muted)}
.foot-care{padding-left:.75rem; border-left:3px solid var(--accent)}

/* -- forms ---------------------------------------------------------------- */
/* Constrain the FORM, not the band. Overriding .band's max-width re-centred
   the whole block inside the 74rem page, so the form floated to the middle
   while the hero above it stayed on the left edge. The band keeps its width
   and its left edge; only the fields are narrow. */
.form-band > *{max-width:34rem}
.stack{display:grid; gap:var(--s3)}
.stack label{display:grid; gap:.375rem; font-size:.9375rem; color:var(--text)}
.stack label small{color:var(--muted); font-size:.8125rem}
.stack input[type=text],.stack input[type=email],.stack input[type=tel],
.stack input[type=password]{
  font:inherit; font-size:1rem; padding:.625rem .75rem; color:var(--text-strong);
  background:var(--ground); border:1px solid var(--hair-firm); border-radius:2px;
  min-height:44px; width:100%;
}
.stack input:focus-visible,.linkish:focus-visible,.stack button:focus-visible{
  outline:3px solid var(--focus); outline-offset:2px}

.stages{border:1px solid var(--hair-firm); border-radius:2px;
  padding:var(--s2); margin:0; display:grid; gap:.5rem}
.stages legend{font-size:.9375rem; padding:0 .375rem; color:var(--text)}
.stages > small{color:var(--muted); font-size:.8125rem; margin-bottom:.25rem}
.choice{display:grid; grid-template-columns:auto 1fr; gap:.125rem .625rem;
  align-items:start; padding:.375rem; border-radius:2px; cursor:pointer}
.choice:hover{background:var(--surface)}
.choice input{grid-row:span 2; margin-top:.25rem; min-width:20px; min-height:20px}
.choice-label{color:var(--text-strong); font-size:.9375rem}
.choice-hint{color:var(--muted); font-size:.8125rem}

.consent{display:grid; grid-template-columns:auto 1fr; gap:.625rem;
  align-items:start; font-size:.875rem}
.consent input{margin-top:.1875rem; min-width:20px; min-height:20px}
.btn-lg{font-size:1rem; padding:.75rem 1.5rem; min-height:48px; border:0;
  cursor:pointer; justify-self:start}
.fineprint{font-size:.8125rem; color:var(--muted); margin:0; max-width:52ch}
.alt{font-size:.9375rem; color:var(--muted); margin-top:var(--s3)}
.cta-row{display:flex; flex-wrap:wrap; gap:var(--s2); align-items:center}

/* -- notices -------------------------------------------------------------- */
.notice{border-left:3px solid var(--hair-firm); background:var(--surface);
  padding:var(--s2); margin:0 0 var(--s3); display:grid; gap:.5rem}
.notice p{margin:0; font-size:.9375rem; max-width:60ch}
.notice-bad{border-left-color:var(--accent)}
.notice-good{border-left-color:var(--track)}
.notice ul{margin:0; padding-left:1.25rem; font-size:.9375rem}

/* -- dashboards ----------------------------------------------------------- */
.dash{max-width:74rem; margin:0 auto; padding:0 var(--edge);
  display:grid; gap:var(--s4)}
@media (min-width:900px){ .dash{grid-template-columns:minmax(0,1fr) 17rem} }
.dash-main{min-width:0; display:grid; gap:0; align-content:start}
.dash-main .band{padding-left:0; padding-right:0; max-width:none}
.dash-side{display:grid; gap:var(--s2); align-content:start}
.side-card{border:1px solid var(--hair); border-radius:2px; padding:var(--s2)}
.side-card h2{font-family:"DM Sans PG",sans-serif; font-size:.6875rem;
  letter-spacing:.09em; text-transform:uppercase; color:var(--muted);
  margin:0 0 .5rem; font-weight:600}
.side-card ul{list-style:none; margin:0; padding:0; display:grid; gap:.375rem}
.side-card a{color:var(--text); font-size:.875rem; text-decoration:none;
  display:inline-block; padding:.1875rem 0; min-height:24px}
.side-card a:hover{color:var(--accent-text); text-decoration:underline}
.side-card .empty{font-size:.8125rem}
.band .sub{color:var(--muted); font-size:.9375rem; margin:-.5rem 0 var(--s2)}
.factlist{display:grid; grid-template-columns:auto 1fr; gap:.5rem var(--s3);
  margin:0 0 var(--s3); font-size:.9375rem}
.factlist dt{color:var(--muted); font-size:.8125rem}
.factlist dd{margin:0; color:var(--text-strong)}

/* -- static pages --------------------------------------------------------- */
.hero .meta{font-size:.8125rem; color:var(--muted); margin:0}
.policy-list{list-style:none; margin:0; padding:0; display:grid; gap:var(--s2)}
@media (min-width:700px){ .policy-list{grid-template-columns:repeat(2,minmax(0,1fr))} }
.policy-list li{display:grid; gap:.25rem; padding:var(--s2);
  border:1px solid var(--hair); border-radius:2px}
.policy-list a{color:var(--text-strong); text-decoration:none}
.policy-list a:hover{color:var(--accent-text); text-decoration:underline}
.policy-list span{font-size:.875rem; color:var(--muted)}
.prose table{border-collapse:collapse; width:100%; font-size:.9375rem;
  margin:0 0 var(--s3); display:block; overflow-x:auto}
.prose th,.prose td{border:1px solid var(--hair-firm); padding:.5rem .625rem;
  text-align:left; vertical-align:top}
.prose th{background:var(--surface); font-weight:600; color:var(--text-strong)}

/* -- admin: the approval queue (§12.7) ------------------------------------ */
.queue-stats dd.bad{color:var(--accent-text); font-weight:600}
.queue{width:100%; border-collapse:collapse; font-size:.9375rem;
  margin:0 0 var(--s3); display:block; overflow-x:auto}
@media (min-width:900px){ .queue{display:table} }
.queue th,.queue td{border-bottom:1px solid var(--hair); padding:.625rem .75rem;
  text-align:left; vertical-align:top}
.queue thead th{font-family:"DM Sans PG",sans-serif; font-size:.6875rem;
  letter-spacing:.09em; text-transform:uppercase; color:var(--muted);
  border-bottom:1px solid var(--hair-firm); font-weight:600; white-space:nowrap}
.queue tbody tr:hover{background:var(--surface)}
/* A flagged row is marked with a rule, not with colour alone. */
.queue tr.flagged{box-shadow:inset 3px 0 0 var(--accent)}
.queue tr.overdue td:nth-child(4){color:var(--accent-text); font-weight:600}
.queue .muted{color:var(--muted); font-size:.8125rem}
.queue .bad{color:var(--accent-text); font-weight:600; font-size:.8125rem}
.queue input[type=checkbox]{min-width:20px; min-height:20px}
.flag{display:inline-block; background:var(--ground); color:var(--accent-text);
  border:1px solid var(--accent); border-radius:2px; padding:.125rem .375rem;
  font-size:.75rem; margin:0 .25rem .25rem 0}
.btn-sm{font-size:.8125rem; padding:.375rem .75rem; border:0; cursor:pointer}
.decide{white-space:nowrap}
.decide details{margin-top:.375rem}
.decide summary{cursor:pointer; color:var(--muted); font-size:.8125rem}
.decide summary:hover{color:var(--accent-text)}
.reject{display:grid; gap:.375rem; margin-top:.5rem; max-width:22rem}
.reject label{font-size:.75rem; color:var(--muted)}
.reject textarea{font:inherit; font-size:.875rem; padding:.5rem;
  border:1px solid var(--hair-firm); border-radius:2px; background:var(--ground);
  color:var(--text-strong); width:100%}
.reject button{cursor:pointer; background:none; border:1px solid var(--accent);
  color:var(--accent-text); border-radius:2px; padding:.375rem .625rem;
  justify-self:start}
.bulk{margin-top:var(--s3); padding-top:var(--s3);
  border-top:1px solid var(--hair-firm)}
.bulk .muted{color:var(--muted); font-size:.875rem}

/* -- staff surfacing ------------------------------------------------------ */
.utility .staff-link{color:var(--accent-text); font-weight:600}
.staff-band{border-left:3px solid var(--track); padding-left:var(--s2)}
.staff-cards{margin-bottom:var(--s2)}
.staff-cards .code{color:var(--accent-text); font-weight:600}

/* -- two-factor ----------------------------------------------------------- */
.steps{list-style:none; counter-reset:step; margin:0; padding:0; display:grid;
  gap:var(--s4)}
.steps > li{counter-increment:step; display:grid; gap:.5rem;
  grid-template-columns:2rem 1fr; align-items:start}
.steps > li::before{content:counter(step); grid-row:span 3;
  font-family:"DM Serif PG",Georgia,serif; font-size:1.5rem; color:var(--accent);
  line-height:1}
.steps h2{grid-column:2; font-family:"DM Serif PG",Georgia,serif;
  font-weight:400; font-size:1.25rem; margin:0}
.steps p,.steps form,.steps details,.steps .qr{grid-column:2}
.secret code{display:inline-block; font-size:1.125rem; letter-spacing:.12em;
  background:var(--surface); border:1px solid var(--hair-firm); border-radius:2px;
  padding:.5rem .75rem; word-break:break-all}
.wrap{word-break:break-all; font-size:.75rem}
.codes{list-style:none; margin:.5rem 0; padding:0; display:grid; gap:.375rem;
  grid-template-columns:repeat(auto-fit,minmax(9rem,1fr))}
.codes code{background:var(--ground); border:1px solid var(--hair-firm);
  border-radius:2px; padding:.25rem .5rem; display:block; text-align:center;
  letter-spacing:.05em}

/* -- two-factor QR --------------------------------------------------------- */
.qr{display:inline-block; justify-self:start; background:#FFF; padding:.75rem; border-radius:6px;
  border:1px solid var(--hair-firm); line-height:0; margin:.25rem 0 var(--s2)}
/* The code must stay dark-on-white in BOTH themes — a QR inverted by a dark
   theme is unreadable to most phone cameras. */
.qr svg{display:block; width:220px; height:220px}

/* -- admin home ------------------------------------------------------------ */
.surfaces{list-style:none; margin:0 0 var(--s3); padding:0; display:grid;
  gap:var(--s2)}
@media (min-width:760px){ .surfaces{grid-template-columns:repeat(2,minmax(0,1fr))} }
.surfaces li > a,.surfaces li > div{display:grid; gap:.25rem; padding:var(--s2);
  border:1px solid var(--hair); border-radius:4px; text-decoration:none;
  height:100%}
.surfaces li > a{background:var(--surface)}
.surfaces li > a:hover{border-color:var(--accent)}
/* Unbuilt surfaces are visibly inert: dashed, muted, not a link. */
.surfaces li.unbuilt > div{border-style:dashed; opacity:.72}
.s-name{font-family:"DM Serif PG",Georgia,serif; font-size:1.0625rem;
  color:var(--text-strong)}
.s-badge{font-size:.6875rem; letter-spacing:.08em; text-transform:uppercase;
  color:var(--accent-text); font-weight:600}
.s-soon{color:var(--muted)}
.s-blurb{font-size:.875rem; color:var(--muted)}

/* -- completeness matrix --------------------------------------------------- */
.fill{display:inline-block; width:6rem; height:.5rem; background:var(--gauge-off);
  border-radius:2px; overflow:hidden; vertical-align:middle; margin-right:.5rem}
.fill > span{display:block; height:100%; background:var(--accent)}
.fill-n{font-size:.8125rem; font-variant-numeric:tabular-nums}
.matrix td.cell{text-align:center; font-variant-numeric:tabular-nums;
  color:var(--muted); min-width:2.5rem}
.matrix td.cell.has{color:var(--text-strong); font-weight:600;
  background:color-mix(in srgb, var(--track) 22%, transparent)}
.matrix tr.empty-paper td:first-child{opacity:.65}
.matrix th.rot{vertical-align:bottom; height:8rem; white-space:nowrap;
  padding:0 .25rem}
.matrix th.rot > span{display:inline-block; transform:rotate(180deg);
  writing-mode:vertical-rl; font-size:.6875rem; letter-spacing:.06em}
.surface-group{font-family:"DM Sans PG",sans-serif; font-size:.6875rem;
  letter-spacing:.09em; text-transform:uppercase; color:var(--muted);
  font-weight:600; margin:var(--s4) 0 .75rem; padding-bottom:.375rem;
  border-bottom:1px solid var(--hair)}
.surface-group:first-of-type{margin-top:var(--s2)}
.ledger td.ref{font-variant-numeric:tabular-nums; color:var(--muted);
  white-space:nowrap; width:4rem}
.pill{display:inline-block; font-size:.6875rem; letter-spacing:.06em;
  text-transform:uppercase; font-weight:600; padding:.125rem .5rem;
  border-radius:10px; white-space:nowrap; border:1px solid}
.pill-done{color:#1F5E3A; border-color:#1F5E3A; background:rgba(31,94,58,.10)}
.pill-partial{color:var(--track-ink); border-color:var(--track);
  background:color-mix(in srgb, var(--track) 26%, transparent)}
.pill-not_started{color:var(--accent-text); border-color:var(--accent);
  background:rgba(182,90,60,.08)}
.pill-dormant{color:var(--muted); border-color:var(--hair-firm)}
@media (prefers-color-scheme:dark){ .pill-done{color:#7FD1A0; border-color:#7FD1A0} }
.ledger tr.st-done td{opacity:.72}

/* -- messaging settings (§19.7) -------------------------------------------- */
.settings-grid{display:grid; gap:var(--s3)}
@media (min-width:760px){ .settings-grid{grid-template-columns:repeat(2,minmax(0,1fr))} }
.settings-grid label{display:grid; gap:.375rem; align-content:start;
  font-size:.9375rem; color:var(--text)}
.settings-grid input[type=text],.settings-grid input[type=password]{
  font:inherit; font-size:.9375rem; padding:.5rem .625rem; width:100%;
  color:var(--text-strong); background:var(--ground);
  border:1px solid var(--hair-firm); border-radius:2px; min-height:40px}
.settings-grid small{color:var(--muted); font-size:.8125rem}
.settings-grid input:disabled{opacity:.6; cursor:not-allowed}
.inline-clear{display:inline-flex; align-items:center; gap:.375rem;
  flex-wrap:nowrap; white-space:nowrap;
  margin-left:.5rem; font-size:.8125rem; color:var(--accent-text)}
.inline-clear input{flex:none; min-width:16px; min-height:16px; margin:0}

.template{border:1px solid var(--hair); border-radius:4px; padding:var(--s2);
  margin-bottom:var(--s2)}
.template > summary{cursor:pointer; font-weight:600; color:var(--text-strong)}
.template form{margin-top:var(--s2); max-width:44rem}
.template textarea{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;
  font-size:.8125rem; line-height:1.5; padding:.625rem; width:100%;
  background:var(--ground); color:var(--text-strong);
  border:1px solid var(--hair-firm); border-radius:2px}
.template input[type=text]{font:inherit; padding:.5rem .625rem; width:100%;
  background:var(--ground); color:var(--text-strong);
  border:1px solid var(--hair-firm); border-radius:2px}

/* -- downloads (§14.3.2) --------------------------------------------------- */
.downloads{max-width:var(--measure); margin:var(--s5) 0 0; padding-top:var(--s3);
  border-top:1px solid var(--hair-firm)}
.downloads h2{font-family:"DM Serif PG",Georgia,serif; font-weight:400;
  font-size:1.25rem; margin:0 0 var(--s2)}
.downloads .actions{display:flex; flex-wrap:wrap; gap:var(--s2);
  align-items:center; margin:0 0 var(--s2)}
.downloads .note{font-size:.8125rem; color:var(--muted); margin:0; max-width:56ch}

/* -- search (§15) ---------------------------------------------------------- */
.searchbar{display:flex; flex-wrap:wrap; gap:.5rem; align-items:stretch;
  max-width:46rem; margin-bottom:var(--s2)}
.searchbar input[type=search]{
  /* Grows to fill, but never shrinks below a readable query. The old
     `flex:1 1 16rem` let it collapse next to the select on a narrow window,
     so the box holding the actual question became the smallest control. */
  flex:1 1 20rem; min-width:12rem;
  font:inherit; font-size:1.0625rem; padding:.6875rem .875rem; min-height:46px;
  color:var(--text-strong); background:var(--ground);
  border:1px solid var(--hair-firm); border-radius:3px}
.searchbar input[type=search]:focus-visible{border-color:var(--accent);
  outline:3px solid var(--focus); outline-offset:1px}
.searchbar select{flex:0 1 11rem; font:inherit; font-size:.9375rem;
  padding:.5rem .625rem; background:var(--ground); color:var(--text);
  border:1px solid var(--hair-firm); border-radius:3px; min-height:46px}
.searchbar button{flex:none; min-height:46px; padding-inline:1.25rem}
/* The hint sat tight against the input and read as part of it. */
.form-band > #search-help{margin-top:0; margin-bottom:var(--s3)}
@media (max-width:520px){
  .searchbar input[type=search]{flex:1 1 100%}
  .searchbar select,.searchbar button{flex:1 1 auto}
}
.result-group{font-family:"DM Sans PG",sans-serif; font-size:.6875rem;
  letter-spacing:.09em; text-transform:uppercase; color:var(--muted);
  font-weight:600; margin:var(--s4) 0 .75rem; padding-bottom:.375rem;
  border-bottom:1px solid var(--hair)}
.results{list-style:none; margin:0 0 var(--s3); padding:0; display:grid; gap:.25rem}
.results a{display:grid; gap:.125rem; padding:.625rem .75rem; text-decoration:none;
  border:1px solid transparent; border-radius:3px}
.results a:hover{background:var(--surface); border-color:var(--hair)}
.r-type{font-size:.625rem; letter-spacing:.09em; text-transform:uppercase;
  color:var(--muted); font-weight:600}
.r-title{font-size:1.0625rem; color:var(--text-strong)}
.r-sub{font-size:.8125rem; color:var(--muted)}
.result-paper .r-title{font-family:"DM Serif PG",Georgia,serif}
.sub a.picked{font-weight:600; color:var(--accent-text)}

/* -- error reports (§18.1) ------------------------------------------------- */
.report-card{border:1px solid var(--hair); border-radius:4px; padding:var(--s2);
  margin-bottom:var(--s2)}
.report-card .r-meta{font-size:.8125rem; color:var(--muted); margin:0 0 .5rem}
.report-card .r-body{margin:0 0 var(--s2); white-space:pre-wrap; max-width:60ch}
.r-actions{display:flex; flex-wrap:wrap; gap:.5rem; align-items:center}
.r-actions input{flex:1 1 18rem; font:inherit; font-size:.875rem;
  padding:.4375rem .625rem; background:var(--ground); color:var(--text-strong);
  border:1px solid var(--hair-firm); border-radius:2px}

/* -- faceted filters (§15.3, §15.4) --------------------------------------- */
.filters{padding-top:var(--s2); padding-bottom:var(--s2)}
.filter-panel > summary{cursor:pointer; font-weight:600; font-size:.9375rem;
  padding:.5rem 0; list-style:revert}
.chip-count{display:inline-block; min-width:1.25rem; padding:0 .3rem; margin-left:.35rem;
  border-radius:999px; background:var(--ink,#1a1a1a); color:var(--ground,#fff);
  font-size:.75rem; text-align:center}
.facet-grid{display:grid; gap:var(--s2); margin:var(--s2) 0;
  grid-template-columns:repeat(auto-fit,minmax(11rem,1fr))}
.facet{border:0; padding:0; margin:0; min-width:0}
.facet legend{font-size:.75rem; text-transform:uppercase; letter-spacing:.05em;
  color:var(--muted); padding:0 0 .4rem}
.opt{display:flex; align-items:center; gap:.5rem; padding:.25rem 0;
  font-size:.875rem; cursor:pointer}
.opt-label{flex:1 1 auto; min-width:0}
.opt-count{color:var(--muted); font-size:.8125rem; font-variant-numeric:tabular-nums}
/* Zero-result options stay VISIBLE and disabled — §15.4 rule 1. */
.opt-off{opacity:.45; cursor:not-allowed}
.facet-actions{display:flex; flex-wrap:wrap; gap:.75rem; align-items:center;
  padding-top:var(--s2); border-top:1px solid var(--hair)}
.facet-actions select{font:inherit; font-size:.875rem; padding:.375rem .5rem;
  background:var(--ground); color:var(--text-strong);
  border:1px solid var(--hair-firm); border-radius:2px}
.facet-note{font-size:.8125rem; color:var(--muted); margin:var(--s2) 0 0; max-width:60ch}
.chips{display:flex; flex-wrap:wrap; gap:.5rem; list-style:none; padding:0;
  margin:var(--s2) 0 0}
.chips a{display:inline-flex; align-items:center; gap:.4rem; padding:.25rem .625rem;
  border:1px solid var(--hair-firm); border-radius:999px; font-size:.8125rem;
  text-decoration:none}
.chips a:hover{background:var(--hair)}
.chip-clear{border-style:dashed}
.empty-filtered{border:1px solid var(--hair); border-radius:4px; padding:var(--s2);
  max-width:60ch}
.empty-filtered p{margin:0 0 .5rem}
@media (min-width:48rem){
  /* On a wide screen the panel is always open; the disclosure is a phone
     affordance (§15.4 rule 4), not a desktop one. */
  .filter-panel > summary{display:none}
  .filter-panel{display:block}
}

/* -- downloads index (§7.12) ---------------------------------------------- */
.dl-list{list-style:none; padding:0; margin:0}
.dl-row{display:flex; flex-wrap:wrap; gap:.75rem; align-items:baseline;
  justify-content:space-between; padding:.75rem 0; border-bottom:1px solid var(--hair)}
.dl-row > a{flex:1 1 20rem; text-decoration:none; display:flex; flex-wrap:wrap;
  gap:.5rem; align-items:baseline; min-width:0}
.dl-row > a:hover .dl-title{text-decoration:underline}
.dl-slot{font-size:.75rem; text-transform:uppercase; letter-spacing:.04em;
  color:var(--muted); flex:0 0 auto}
.dl-title{font-weight:500; color:var(--text-strong)}
.dl-meta{font-size:.8125rem; color:var(--muted)}
.dl-state{flex:0 0 auto; font-size:.75rem; padding:.125rem .5rem; border-radius:2px}
.dl-open{background:var(--hair); color:var(--text-strong)}
.dl-locked{border:1px solid var(--hair-firm); color:var(--muted)}
.facet-note ul{margin:.5rem 0 0; padding-left:1.1rem}
.facet-note li{margin-bottom:.35rem}

/* -- programme views (§7.2) ------------------------------------------------ */
.alt-link{font-size:.8125rem; font-weight:400; margin-left:.5rem}

/* -- exams (§7.7) ---------------------------------------------------------- */
.exam-sections{list-style:none; padding:0; margin:0}
.exam-section{display:flex; flex-wrap:wrap; gap:.75rem; align-items:baseline;
  justify-content:space-between; padding:.875rem 0; border-bottom:1px solid var(--hair)}
.exam-section > a{flex:1 1 22rem; text-decoration:none; min-width:0}
.exam-section > a:hover .es-title{text-decoration:underline}
.es-title{display:block; font-weight:500; color:var(--text-strong)}
.es-purpose{display:block; font-size:.8125rem; color:var(--muted); margin-top:.15rem}
.es-state{flex:0 0 auto; font-size:.75rem; padding:.125rem .5rem; border-radius:2px}
.es-checked{background:var(--hair); color:var(--text-strong)}
.es-pending{border:1px dashed var(--hair-firm); color:var(--muted)}
.exam-section-empty .es-title{color:var(--muted); font-weight:400}
.provenance{border-left:3px solid var(--hair-firm); padding:.75rem 1rem;
  background:var(--hair); border-radius:0 3px 3px 0; max-width:60ch}
.provenance p{margin:0 0 .35rem}
.provenance-stale{border-left-color:#b45309}
.sources{margin:.35rem 0 0; padding-left:1.1rem; font-size:.8125rem; word-break:break-all}

/* -- upload wizard (§13.8) ------------------------------------------------- */
.upload-form{max-width:46rem}
.upl-step{border:1px solid var(--hair); border-radius:4px; padding:var(--s2);
  margin:0 0 var(--s2)}
.upl-step legend{font-weight:600; padding:0 .4rem}
.step-n{display:inline-block; width:1.4rem; height:1.4rem; line-height:1.4rem;
  text-align:center; border-radius:50%; background:var(--ink,#1a1a1a);
  color:var(--ground,#fff); font-size:.8125rem; margin-right:.4rem}
.upl-drop{display:block; border:2px dashed var(--hair-firm); border-radius:4px;
  padding:var(--s2); margin:var(--s2) 0; cursor:pointer; text-align:center}
.upl-drop:hover{border-color:var(--text-strong)}
.upl-hint{display:block; font-size:.875rem; color:var(--muted); margin-top:.5rem}
.tally{display:flex; flex-wrap:wrap; gap:var(--s2); list-style:none; padding:0; margin:0}
.tally li{font-size:.9375rem}
.tally strong{font-size:1.5rem; display:block; font-variant-numeric:tabular-nums}
.rejections{max-width:70ch; font-size:.875rem; padding-left:1.1rem}
.rejections li{margin-bottom:.35rem; color:var(--muted)}

/* -- review reading (§9.10) ------------------------------------------------ */
.read-list{list-style:none; padding:0; margin:var(--s2) 0; font-size:.875rem}
.read-list li{padding:.3rem 0; display:flex; gap:.5rem; align-items:baseline}
.rl-mark{flex:0 0 1rem; color:var(--muted); font-variant-numeric:tabular-nums}
.read-done .rl-mark{color:#2f6f4f}
.read-current{font-weight:600}
.blocked-note{font-size:.8125rem; color:var(--muted); font-style:italic}
.read-draft{border-left:3px solid var(--hair-firm); padding-left:var(--s2)}

/* -- verification (§12.5) --------------------------------------------------- */
.verify-form{margin-top:var(--s2); padding-top:var(--s2); border-top:1px solid var(--hair)}
.verify-form input[type=text]{font-size:1.5rem; letter-spacing:.4em; max-width:9ch;
  text-align:center; font-variant-numeric:tabular-nums; padding:.5rem;
  border:1px solid var(--hair-firm); border-radius:3px; background:var(--ground)}
.stack{display:flex; flex-direction:column; gap:.5rem; align-items:flex-start}

/* ── §7.7 the two aspects of an exam, side by side ─────────────────────────
   Every exam answers two questions — what it IS and what to STUDY for it — and
   they were built as separate pages that never linked to each other. Showing
   them as ONE choice is the point, so the grid collapses to a single column on
   a phone rather than hiding either half. */
.two-aspects { display: grid; gap: 1.5rem; grid-template-columns: 1fr; margin-top: .5rem; }
@media (min-width: 46rem) { .two-aspects { grid-template-columns: 1fr 1fr; gap: 2rem; } }
.two-aspects .aspect { border: 1px solid var(--rule, #e3e0da); border-radius: .5rem;
  padding: 1.25rem 1.35rem; }
.two-aspects .aspect h3 { margin: 0 0 .5rem; font-size: 1.15rem; }
.two-aspects .aspect p { margin: 0 0 .75rem; }
.two-aspects .aspect > :last-child { margin-bottom: 0; }
.two-aspects .aspect-count { font-size: .95rem; opacity: .8; }
.two-aspects .plain-list { margin: 0; }

/* ── /exams/ — a card per family ───────────────────────────────────────────
   The flat list this replaced made every exam look identical: a reader could
   not see that SET holds thirteen state exams, or that anything had study
   material behind it. The card carries exactly those two facts, because they
   are what decides where someone clicks. */
.exam-grid { list-style: none; margin: 0; padding: 0; display: grid; gap: 1rem;
  grid-template-columns: 1fr; }
@media (min-width: 46rem) { .exam-grid { grid-template-columns: 1fr 1fr; gap: 1.25rem; } }
.exam-card > a { display: block; padding: 1.25rem 1.35rem; border: 1px solid var(--rule, #e3e0da);
  border-radius: .5rem; text-decoration: none; color: inherit; height: 100%; }
.exam-card > a:hover, .exam-card > a:focus-visible { border-color: currentColor; }
.ec-head { display: block; margin-bottom: .5rem; }
.ec-name { display: block; font-weight: 600; font-size: 1.15rem; }
.ec-code { display: block; font-size: .85rem; opacity: .7; margin-top: .15rem; }
.ec-lede { display: block; margin-bottom: .85rem; }
.ec-facts { display: flex; flex-wrap: wrap; gap: .4rem .9rem; font-size: .9rem; }
.ec-fact { opacity: .8; }
.ec-fact b { opacity: 1; }
.ec-study { font-weight: 600; opacity: 1; }

/* ── Blog topic selector ──────────────────────────────────────────────
   The tabular chooser at the top of /blog/ and /blog/{topic}/. A table
   because it IS tabular — subject, what it covers, who for, how many —
   and a table lets a reader compare rows, which is the whole job.
   §15.4: it must scroll inside its own box rather than push the page
   sideways on a phone. */
.table-scroll{overflow-x:auto; -webkit-overflow-scrolling:touch}
.topic-table{width:100%; min-width:34rem}
.topic-table th[scope="row"]{text-align:left; font-weight:600; white-space:nowrap}
.topic-table td{vertical-align:top}
