/* ══ THE CORPUS — the admin half of the coach surface ═══════════════════════
   js/11-skill-coach.js (_ccLoad), markup in index.html (#coach-corpus).
   Numbered 24 so it lands after 20-coach-roster.css, which it is a sibling of.

   MARK IS BOTH PEOPLE. He teaches the students and he maintains the question
   bank, and his ruling of 2026-08-14 was that those are not two products. So
   this is written in the SAME register as the roster above it — broadsheet,
   ruled, agate figures, no cards — rather than as a second visual system for
   an "admin" that does not exist. If it looked like a different product it
   would be one.

   THE WEIGHT ORDER, and why it inverts the roster's:

     roster   triage is the news (display scale), the table is the reference.
     corpus   ONE display figure — the share of the live bank meeting the bar —
              and then a ledger. There is no triage here because there is no
              "today" in corpus work; there is a number that is going up, and
              the six rows that say where the remaining work is.

   A percentage hides the size of the work, so every ledger row prints its
   SHORTFALL as a count beside the bar. 53% and "24,507 short" are the same
   fact and only one of them is actionable.
   ═══════════════════════════════════════════════════════════════════════════ */

.bs .cc {
  --cc-measure: 800px;
  margin-bottom: 44px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--bs-rule);
}

/* ── the head ──
   NOT a .page-head. scripts/measure_chrome.py enforces exactly one visible
   `.page-title` per screen and "The roster" is it; this is a section heading a
   clear step below it, which is also the honest hierarchy — the screen is the
   roster, and the corpus is the other half of the same job. */
.bs .cc-head {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 4px 18px;
  border-top: 3px solid var(--bs-ink);
  padding-top: 12px;
  margin-top: 6px;
  /* CAPPED to the same measure as the ledger and the headline. Left uncapped
     it ran the full 1200px of .coach-body while everything under it stopped at
     800, so the measured-at line sat 400px right of the figures it dates and
     the section had two right edges. */
  max-width: var(--cc-measure);
}
.bs .cc-title {
  font-family: var(--bs-ed);
  font-variation-settings: 'WONK' 1;
  font-weight: 900;
  font-size: clamp(21px, 2.4vw, 27px);
  line-height: 1.05;
  letter-spacing: -.022em;
  color: var(--bs-ink);
  margin: 0;
}
/* Sits at the end of the band on a wide window and drops beneath it when the
   band wraps — same behaviour as .cr-triage-hand above. It carries the
   MEASURED-AT time, which is the one thing that stops a cached figure from
   quietly becoming a claim about now. */
.bs .cc-dateline {
  font-family: var(--bs-mono);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--bs-ink-3);
  font-variant-numeric: tabular-nums;
  margin-left: auto;
}

/* ══ THE HEADLINE ═══════════════════════════════════════════════════════════
   One figure, at display scale, because "is the work landing" is a
   five-second question and 79% is the whole answer to it. */
.bs .cc-headline {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 4px 20px;
  margin-top: 18px;
  max-width: var(--cc-measure);
}
.bs .cc-figure {
  font-family: var(--bs-ed);
  font-variation-settings: 'WONK' 1;
  font-weight: 900;
  font-size: clamp(38px, 5.6vw, 58px);
  line-height: .88;
  letter-spacing: -.04em;
  font-variant-numeric: tabular-nums;
  color: var(--bs-ink);
}
.bs .cc-figure-lbl {
  font-family: var(--bs-mono);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--bs-ink-3);
}
/* The shortfall, set as a sentence rather than as a second numeral. Two large
   figures side by side would be a pair to compare; this is a consequence. */
.bs .cc-shortfall {
  font-family: var(--bs-ui);
  font-size: 14.5px;
  line-height: 1.45;
  color: var(--bs-ink-2);
  max-width: 46ch;
  margin-left: auto;
  text-align: right;
}
.bs .cc-shortfall b {
  font-weight: 700;
  color: var(--bs-ink);
  font-variant-numeric: tabular-nums;
}

/* ══ THE LEDGER ═════════════════════════════════════════════════════════════
   One row per element of the bar. A three-column grid — name, meter, count —
   so the meters share one left edge and the counts share one right edge and
   the eye can run down either without reading the other. */
.bs .cc-ledger {
  list-style: none;
  margin: 26px 0 0;
  padding: 0;
  max-width: var(--cc-measure);
  border-top: 1px solid var(--bs-rule);
}
.bs .cc-row {
  display: grid;
  grid-template-columns: minmax(90px, 148px) minmax(0, 1fr) minmax(120px, auto);
  align-items: center;
  gap: 4px 18px;
  padding: 11px 2px 10px;
  border-bottom: 1px solid var(--bs-rule);
}
.bs .cc-row-name {
  font-family: var(--bs-mono);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--bs-ink);
}
/* Where the criterion does not apply to the whole bank, the denominator says
   so — MEASURED, from the payload's own `applicable`, never a hand-written
   "EBRW only" that could outlive the SQL clause it is describing. */
.bs .cc-row-scope {
  display: block;
  margin-top: 3px;
  font-family: var(--bs-mono);
  font-size: 8.5px;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: none;
  color: var(--bs-ink-3);
  font-variant-numeric: tabular-nums;
}

/* The meter. A rule that fills, not a rounded pill — this page is ruled paper
   and a candy bar would be from a different product. */
.bs .cc-meter {
  position: relative;
  height: 9px;
  background: var(--bs-stock-2);
  border: 1px solid var(--bs-rule);
  overflow: hidden;
}
.bs .cc-meter-fill {
  position: absolute;
  inset: 0 auto 0 0;
  background: var(--bs-ink);
}
/* COMPLETE is not the same news as NEARLY. A finished element goes green so a
   run down the ledger separates "done" from "99%, keep going" without reading
   a single figure — the same reason the triage band's calm branch is a word
   and not a zero. */
.bs .cc-row[data-state="complete"] .cc-meter-fill { background: var(--bs-ok); }
/* Under half. The red pen, and the only place on this panel it appears. */
.bs .cc-row[data-state="thin"] .cc-meter-fill { background: var(--bs-pen); }

.bs .cc-row-fig {
  text-align: right;
  font-family: var(--bs-mono);
  font-variant-numeric: tabular-nums;
}
.bs .cc-row-pct {
  font-size: 15px;
  font-weight: 600;
  line-height: 1;
  color: var(--bs-ink);
}
.bs .cc-row-short {
  display: block;
  margin-top: 4px;
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--bs-ink-3);
}
.bs .cc-row[data-state="complete"] .cc-row-short { color: var(--bs-ok); }

/* REPORTED, NOT REQUIRED. `solution` is measured and printed and is deliberately
   NOT part of the full-bar figure: a generated explanation satisfies the bar
   where no official worked solution exists. Set below the rule that closes the
   bar elements, at text weight rather than in the mono stack, so it reads as a
   footnote to the ledger instead of as a seventh row of it. Which rows land
   here is read off the payload's `bar_elements`, so the screen cannot disagree
   with the server about what the bar is. */
.bs .cc-row--note {
  grid-template-columns: minmax(0, 1fr) minmax(120px, auto);
  border-bottom: 0;
  padding-top: 13px;
}
.bs .cc-row--note .cc-row-name {
  font-family: var(--bs-ui);
  font-size: 13px;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  color: var(--bs-ink-2);
  max-width: 62ch;
}
.bs .cc-row--note .cc-row-pct {
  font-size: 12px;
  color: var(--bs-ink-3);
}

/* ── the way into the family table ── */
.bs .cc-more {
  display: inline-block;
  margin-top: 18px;
  font-family: var(--bs-mono);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--bs-ink);
  background: transparent;
  border: 1.5px solid var(--bs-ink);
  border-radius: 0;
  padding: 8px 14px 7px;
  cursor: pointer;
  transition: background .12s ease, color .12s ease;
}
.bs .cc-more:hover { background: var(--bs-ink); color: var(--bs-sheet); }
.bs .cc-more:focus-visible { outline: 2px solid var(--bs-blue); outline-offset: 2px; }

/* ══ DEMO DATA ══════════════════════════════════════════════════════════════
   docs/HANDOFF-2026-08-15.md §2. The seeder writes answers relative to when it
   runs and the gone-dark line is 7 days, so a week after a seed the ENTIRE demo
   cohort reads as gone dark and the triage band at the top of this screen shows
   three classes of markup carrying one class of information.

   That used to be a test that failed every seventh day, which is noise, and it
   was correctly narrowed — which leaves this line as the ONLY honest place for
   the question. It is quiet when the data is fresh and loud when it is not,
   because a warning that is always on is not a warning. */
.bs .cc-demo { margin-top: 34px; max-width: var(--cc-measure); }
.bs .cc-demo-line {
  font-family: var(--bs-ui);
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--bs-ink-2);
  max-width: 66ch;
  border-left: 2px solid var(--bs-rule);
  padding-left: 13px;
}
.bs .cc-demo-line b { font-weight: 700; color: var(--bs-ink); }
.bs .cc-demo-kicker {
  display: block;
  margin-bottom: 4px;
  font-family: var(--bs-mono);
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--bs-ink-3);
}
/* Stale. The red pen on the rule and on the kicker — the same device the
   roster's load-failure note uses, because it is the same kind of statement:
   what is on the screen above cannot be trusted. */
.bs .cc-demo--stale .cc-demo-line { border-left-color: var(--bs-pen); }
.bs .cc-demo--stale .cc-demo-kicker { color: var(--bs-pen); }
.bs .cc-demo-fix {
  display: block;
  margin-top: 7px;
  font-family: var(--bs-mono);
  font-size: 11px;
  color: var(--bs-ink-3);
  overflow-wrap: anywhere;
}

/* ── loading and failure ──
   Never a silent empty band. An empty corpus panel would read as "the bank is
   fine", which is the one thing it must not be able to say by accident. */
.bs .cc-wait,
.bs .cc-fail {
  font-family: var(--bs-ui);
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--bs-ink-2);
  max-width: 58ch;
  margin-top: 16px;
}
.bs .cc-fail { border-left: 2px solid var(--bs-pen); padding-left: 13px; }

/* ══ THE FAMILY TABLE, IN ITS MODAL ═════════════════════════════════════════
   27 families by 8 columns is a reference table, not a headline, so it lives
   behind "Every family" rather than on the page. It reuses the payload the
   ledger already fetched — no second request, so the two can never disagree.

   `.bs` is on .vgm-panel (js/11d-modals.js), which is what lets these rules
   match at all. */
.bs .ccf-scroll { overflow-x: auto; }
.bs .ccf-table {
  border-collapse: collapse;
  font-variant-numeric: tabular-nums;
  min-width: 620px;
  width: 100%;
}
.bs .ccf-table th,
.bs .ccf-table td {
  padding: 7px 9px 6px;
  border-bottom: 1px solid var(--bs-rule);
  text-align: right;
  white-space: nowrap;
}
.bs .ccf-table th {
  font-family: var(--bs-mono);
  font-size: 8.5px;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--bs-ink-3);
  border-bottom: 2px solid var(--bs-ink);
  position: sticky;
  top: 0;
  background: var(--bs-sheet);
  /* THE HEADS WRAP, THE FIGURES DO NOT. Under `table-layout: auto` a
     non-wrapping "WORKED SOLUTION" sets a ~130px column to hold a 40px "100%",
     and eight such columns pushed ELO off the panel into a scroll nobody would
     think to perform. Wrapping the labels lets each column size to its DATA,
     which is what a box score does. */
  white-space: normal;
  vertical-align: bottom;
  min-width: 52px;
}
.bs .ccf-table td { font-family: var(--bs-mono); font-size: 12px; color: var(--bs-ink-2); }
/* BOTH selectors carry `.ccf-table` on purpose. `.bs .ccf-fam` alone is
   (0,2,0) and loses to `.bs .ccf-table td` at (0,2,1) — MEASURED: every family
   name rendered right-aligned under a left-aligned "FAMILY" head. */
.bs .ccf-table th.ccf-fam,
.bs .ccf-table td.ccf-fam { text-align: left; }
.bs .ccf-table td.ccf-fam {
  font-family: var(--bs-ui);
  font-size: 13.5px;
  font-weight: 600;
  color: var(--bs-ink);
  /* NOT wrapped. `overflow-wrap: anywhere` broke `synthetic_amc` into
     "synthetic_ / amc" and `aops_forum` into "aops_foru / m" — a family name
     is an identifier and a reader has to be able to match it against the one
     in a script's output. The table is already inside .ccf-scroll, so the
     honest answer to a narrow window is to scroll, not to hyphenate an id. */
  white-space: nowrap;
}
/* n/a is not 0%. A criterion that does not apply to a family must never be
   legible as a failure — scoping traps to all multiple choice once made every
   AP family read 0% and dragged the headline from 79 to 57. */
/* `.ccf-table` is carried here for the same reason as `.ccf-fam` above, and it
   was missing: `.bs .ccf-na` is (0,2,0) and lost to `.bs .ccf-table td` at
   (0,2,1), so --bs-ink-3 never applied and every n/a cell rendered in ink-2.
   The `opacity: .65` was doing the muting on its own, and at .65 over --bs-sheet
   that painted 3.40:1 against a 4.5 floor — MEASURED on 41 cells, 2026-08-15.
   With the specificity fixed, ink-3 mutes it as intended at 6.24:1 and the
   opacity is not needed. Muting with a colour is legible; muting with opacity
   is a contrast failure the stylesheet cannot see. */
.bs .ccf-table td.ccf-na { color: var(--bs-ink-3); }
.bs .ccf-bar { font-weight: 600; color: var(--bs-ink); }
.bs .ccf-table tbody tr:hover td { background: var(--bs-stock-2); }
.bs .ccf-note {
  font-family: var(--bs-ui);
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--bs-ink-3);
  max-width: 64ch;
  margin: 14px 0 2px;
}

@media (max-width: 560px) {
  /* The name column loses its fixed track and the meter drops to its own row:
     at 320 a three-column grid put a 90px name against a 40px meter, and the
     meter is the whole point of the row. */
  .bs .cc-row { grid-template-columns: minmax(0, 1fr) auto; }
  .bs .cc-meter { grid-column: 1 / -1; order: 3; }
  .bs .cc-shortfall { margin-left: 0; text-align: left; }
}

/* ══ WHAT STUDENTS REPORTED ═══════════════════════════════════════════════════
   Third block of #coach-corpus, above "Review a question" because a report and
   the question it names are one motion.

   NO `opacity` ANYWHERE IN HERE, on purpose. E2's contrast audit found 44
   failures once the checker learned to read `opacity`, and the worst of them was
   a line faded by three independent `.88` declarations. Every colour below is a
   token that has been measured on the ground it sits on. */
.bs .cc-reports {
  margin-top: 38px;
  max-width: var(--cc-measure);
}

.bs .ccr-head-block {
  border-top: 2px solid var(--bs-ink);
  padding-top: 11px;
}

.bs .ccr-title {
  margin: 0;
  font-family: var(--bs-ed);
  font-variation-settings: 'WONK' 1;
  font-size: 21px;
  font-weight: 900;
  line-height: 1.1;
  letter-spacing: -.018em;
  color: var(--bs-ink);
}

.bs .ccr-dateline {
  margin-top: 5px;
  font-family: var(--bs-mono);
  font-size: 12px;
  letter-spacing: .01em;
  color: var(--bs-ink-3);
}

/* A full page of results must never read as a complete one. */
.bs .ccr-capped {
  margin-top: 7px;
  padding-left: 11px;
  border-left: 2px solid var(--bs-pen, #8a5b2a);
  font-size: 12.5px;
  color: var(--bs-ink-2);
}

.bs .ccr-hint {
  margin-top: 9px;
  font-size: 12px;
  font-style: italic;
  color: var(--bs-ink-3);
}

.bs .ccr-list {
  margin-top: 15px;
  display: flex;
  flex-direction: column;
}

/* The whole row is the button. Reset the UA button styling rather than fight it,
   and keep the text left-aligned — this is a document row, not a control. */
.bs .ccr-row {
  display: block;
  width: 100%;
  margin: 0;
  padding: 13px 14px 14px;
  border: 0;
  border-top: 1px solid var(--bs-rule);
  background: none;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
}
.bs .ccr-row:last-child { border-bottom: 1px solid var(--bs-rule); }
.bs .ccr-row:hover { background: var(--bs-sheet); }
.bs .ccr-row:focus-visible { outline: 2px solid var(--bs-blue); outline-offset: -2px; }
.bs .ccr-row:active { background: var(--bs-stock-2, var(--bs-sheet)); }

.bs .ccr-head {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 3px 12px;
}

.bs .ccr-chip {
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .11em;
  text-transform: uppercase;
  color: var(--bs-ink);
  border-bottom: 2px solid var(--bs-ink);
  padding-bottom: 1px;
}
/* 48 of 64 reports carry no reason, because the picker shipped before the free
   text did. That is the commonest kind of report, so it is stated rather than
   dashed — but it is not given the same weight as a reason a student chose. */
.bs .ccr-chip--none {
  font-weight: 400;
  text-transform: none;
  letter-spacing: .02em;
  font-style: italic;
  color: var(--bs-ink-3);
  border-bottom-style: dotted;
  border-bottom-color: var(--bs-rule);
}

.bs .ccr-who {
  font-size: 13px;
  font-weight: 700;
  color: var(--bs-ink);
}
.bs .ccr-when,
.bs .ccr-id {
  font-size: 12px;
  color: var(--bs-ink-3);
}
.bs .ccr-id {
  margin-left: auto;
  font-family: var(--bs-mono);
  font-variant-numeric: tabular-nums;
}

/* The student's own words. The only part of a report a detector could not have
   produced, so it is set as a quotation and it comes first. */
.bs .ccr-detail {
  margin: 9px 0 0;
  padding: 0 0 0 13px;
  border-left: 3px solid var(--bs-ink);
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--bs-ink);
}

.bs .ccr-stem {
  margin-top: 9px;
  font-size: 13px;
  line-height: 1.5;
  color: var(--bs-ink-2);
}
/* When there is a quotation above it, the stem is context rather than content. */
.bs .ccr-stem--secondary {
  margin-top: 7px;
  font-size: 12px;
  color: var(--bs-ink-3);
}

/* MEASURED at 320: hiding #cc-reports took documentElement.scrollWidth from 348
   to 320, and no element box in the panel reported a rect past 320 — so the 28px
   was INLINE content spilling out of boxes that were themselves the right width.
   A stem is corpus text, so it contains things no line-breaker will split: a
   bare `\frac{x^2 + 6x - 7}{x + 7} = ax + d`, a source_dataset slug, a URL a
   student pasted into their own description. `anywhere` rather than `break-word`
   because break-word still refuses to split inside a long token when the line
   already has content on it, which is the case that produced this. */
.bs .ccr-detail,
.bs .ccr-stem,
.bs .ccr-stem * {
  overflow-wrap: anywhere;
}
/* A flex item's default min-width is auto — its min-CONTENT width — so one long
   word in a row head pushes the row wider than its container no matter what the
   container says. */
.bs .ccr-head > * { min-width: 0; }

@media (max-width: 640px) {
  .bs .ccr-id { margin-left: 0; }
  .bs .ccr-row { padding-left: 0; padding-right: 0; }
}

/* The expander. Reuses .cc-more's shape — same job one section up, and a second
   button style for the same act would be a drift. */
.bs .ccr-more {
  margin-top: 15px;
  padding: 9px 15px;
  border: 1px solid var(--bs-ink);
  background: none;
  font-family: var(--bs-mono);
  font-size: 11.5px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--bs-ink);
  cursor: pointer;
}
.bs .ccr-more:hover { background: var(--bs-ink); color: var(--bs-sheet); }
.bs .ccr-more:focus-visible { outline: 2px solid var(--bs-blue); outline-offset: 2px; }
