/* The study room.
 *
 * The exam clone (exam.css, marrow.css) keeps the institutional blue chrome,
 * because imitating the NBE screen is the point of it. Everything else — the
 * lobby, the doors, the confirm screen, the scorecard, the ledger — is this
 * file, and it is deliberately a different place: quiet ground, near-black
 * text, one accent used only on things you can act on.
 *
 * The rule for the accent: if it is blue, you can click it. Nothing decorative
 * is ever the accent colour, so scanning for blue is the same as scanning for
 * what to do next.
 */

:root {
  --ink:        #1a1d21;   /* body text */
  --ink-soft:   #5b6670;   /* secondary text */
  --ink-faint:  #8b959e;   /* thirds: counts, timestamps */
  --ground:     #fbfaf8;   /* page */
  --surface:    #ffffff;   /* panels */
  --line:       #e5e2dc;   /* hairlines */
  --line-firm:  #cfcac2;   /* input borders */
  --accent:     #1b5e8e;   /* the one accent */
  --accent-ink: #ffffff;
  --accent-wash:#eef4f9;
  --good:       #2e7d54;
  --bad:        #b3402e;
  --warn-bg:    #fdf6e7;
  --warn-line:  #e6d3a8;
  --warn-ink:   #6e5518;
  --radius:     8px;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font: 15px/1.55 ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto,
        Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
}

/* ---- chrome ---------------------------------------------------------- */
.topbar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; padding: 14px 22px;
  background: var(--surface); border-bottom: 1px solid var(--line);
}
.brand { font-weight: 600; letter-spacing: -0.01em; }
.topbar nav { display: flex; gap: 18px; align-items: center; font-size: 14px; }
.topbar a { color: var(--ink-soft); text-decoration: none; }
.topbar a:hover { color: var(--accent); }
.linklike {
  background: none; border: none; padding: 0; cursor: pointer;
  color: var(--ink-soft); font: inherit; font-size: 14px;
}
.linklike:hover { color: var(--accent); }
.inline { display: inline; }

main { max-width: 720px; margin: 0 auto; padding: 40px 20px 80px; }
h1 { font-size: 26px; font-weight: 600; letter-spacing: -0.02em; margin: 0 0 6px; }
h2 { font-size: 17px; font-weight: 600; margin: 0 0 8px; }
.lede { color: var(--ink-soft); margin: 0 0 26px; max-width: 60ch; }
.muted { color: var(--ink-soft); }
.small { font-size: 13px; }
.error { color: var(--bad); }
.right { text-align: right; }
.count { font-weight: 400; font-size: 16px; color: var(--ink-faint); }
.eyebrow {
  font-size: 11px; font-weight: 600; letter-spacing: 0.09em; text-transform: uppercase;
  color: var(--ink-faint); margin: 0 0 10px;
}
.back {
  display: inline-block; margin-bottom: 18px; font-size: 13px;
  color: var(--ink-soft); text-decoration: none;
}
.back:hover { color: var(--accent); }

/* ---- buttons --------------------------------------------------------- */
.btn {
  display: inline-block; padding: 9px 16px; border-radius: 6px; cursor: pointer;
  border: 1px solid var(--line-firm); background: var(--surface); color: var(--ink);
  font: inherit; font-size: 14px; text-decoration: none; text-align: center;
}
.btn:hover { border-color: var(--accent); color: var(--accent); }
.btn.primary { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
.btn.primary:hover { filter: brightness(1.08); color: var(--accent-ink); }
.btn.big { padding: 12px 26px; font-size: 15px; width: 100%; }
.btn.small { padding: 5px 12px; font-size: 13px; }
.btn.ghost { color: var(--ink-soft); }
.btn:disabled { opacity: 0.45; cursor: not-allowed; filter: none; }
.btn.marrow { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }

/* ---- home: the doors -------------------------------------------------- */
.resume {
  background: var(--surface); border: 1px solid var(--line);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius); padding: 16px 18px; margin-bottom: 28px;
}
.resume-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; flex-wrap: wrap;
}
.resume-row + .resume-row { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--line); }
.resume-name { display: block; font-weight: 600; }
.resume-meta { display: block; font-size: 13px; color: var(--ink-soft); margin-top: 2px; }

.door {
  display: grid; grid-template-columns: 1fr auto; align-items: center;
  gap: 4px 16px; padding: 22px 24px; margin-bottom: 12px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); text-decoration: none; color: inherit;
}
.door:hover { border-color: var(--accent); background: var(--accent-wash); }
/* All three need a definite column. Grid places items with a definite row
   before the free-floating ones, so an unplaced .door-go claimed row 1 /
   column 1 and knocked the title into the arrow's column. */
.door-title { grid-row: 1; grid-column: 1; font-size: 18px; font-weight: 600; letter-spacing: -0.01em; }
.door-blurb { grid-row: 2; grid-column: 1; font-size: 14px; color: var(--ink-soft); }
.door-go { grid-row: 1 / span 2; grid-column: 2; font-size: 20px; color: var(--accent); }
.door-empty { opacity: 0.55; cursor: default; }
.door-empty:hover { border-color: var(--line); background: var(--surface); }

.quiet-links { display: flex; gap: 20px; flex-wrap: wrap; margin-top: 30px; font-size: 14px; }
.quiet-links a { color: var(--ink-soft); text-decoration: none; }
.quiet-links a:hover { color: var(--accent); }

/* ---- panels: door picker, confirm ------------------------------------ */
.panel {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); margin-bottom: 18px; overflow: hidden;
}
.panel-head, .pick-row {
  display: grid; grid-template-columns: 22px 1fr 5.5rem 5rem 4rem 5rem;
  gap: 10px; align-items: center; padding: 9px 16px;
}
.panel-head {
  grid-template-columns: 1fr 5.5rem 5rem 4rem 5rem;
  padding-left: 48px;
  font-size: 11px; letter-spacing: 0.05em; text-transform: uppercase;
  color: var(--ink-faint); background: var(--ground); border-bottom: 1px solid var(--line);
}
.pick-row { border-bottom: 1px solid var(--line); cursor: pointer; }
.pick-row:last-child { border-bottom: none; }
.pick-row:hover { background: var(--accent-wash); }
.pick-name { font-weight: 500; }
.alloc { color: var(--ink-faint); font-variant-numeric: tabular-nums; }
.alloc.has { color: var(--accent); font-weight: 600; }
.pick-row .right { font-variant-numeric: tabular-nums; }

.controls { padding: 18px 20px; }
.field { margin-bottom: 14px; }
.field-label {
  display: block; font-size: 13px; color: var(--ink-soft); margin-bottom: 7px;
}
.segmented { display: inline-flex; border: 1px solid var(--line-firm); border-radius: 6px; overflow: hidden; }
.seg {
  padding: 8px 18px; border: none; border-right: 1px solid var(--line-firm);
  background: var(--surface); color: var(--ink-soft); font: inherit; font-size: 14px;
  cursor: pointer;
}
.seg:last-child { border-right: none; }
.seg:hover { background: var(--accent-wash); }
.seg.on { background: var(--accent); color: var(--accent-ink); }
.summary { font-weight: 600; margin: 4px 0 10px; }
.warning {
  background: var(--warn-bg); border: 1px solid var(--warn-line); color: var(--warn-ink);
  border-radius: 6px; padding: 9px 12px; font-size: 13px; margin: 0 0 14px;
}

/* ---- confirm --------------------------------------------------------- */
.confirm { padding: 24px; }
.confirm-name { font-size: 19px; font-weight: 600; margin: 0; letter-spacing: -0.01em; }
.confirm-size { color: var(--ink-soft); margin: 2px 0 16px; }
.consequences { list-style: none; padding: 0; margin: 0 0 22px; }
.consequences li {
  display: grid; grid-template-columns: 26px 1fr; gap: 10px; align-items: start;
  padding: 11px 0; border-top: 1px solid var(--line); font-size: 14px;
}
.consequences .icon { font-size: 15px; line-height: 1.5; }

.switch { margin-top: 16px; }
.switch > summary { cursor: pointer; font-size: 13px; color: var(--ink-soft); }
.switch > summary:hover { color: var(--accent); }
.switch-body { margin-top: 10px; }
.switch-mode {
  display: block; padding: 11px 14px; margin-bottom: 8px; text-decoration: none;
  border: 1px solid var(--line); border-radius: 6px; color: inherit;
}
.switch-mode:hover { border-color: var(--accent); background: var(--accent-wash); }
.switch-mode.on { border-color: var(--accent); background: var(--accent-wash); }
.switch-mode b { display: block; font-size: 14px; }
.switch-mode span { font-size: 12.5px; color: var(--ink-soft); }

/* ---- archive --------------------------------------------------------- */
.shelf-head { display: flex; align-items: baseline; gap: 16px; flex-wrap: wrap; }
.shelf-head h1 { flex: 1; }
.filter {
  flex: 1; min-width: 190px; padding: 8px 12px; font: inherit; font-size: 14px;
  border: 1px solid var(--line-firm); border-radius: 6px; background: var(--surface);
}
.filter:focus { outline: 2px solid var(--accent-wash); border-color: var(--accent); }

.shelf-group { margin-bottom: 10px; }
.shelf-group > summary {
  cursor: pointer; padding: 10px 14px; font-weight: 600; font-size: 14px;
  background: var(--surface); border: 1px solid var(--line); border-radius: 6px;
}
.shelf-group > summary:hover { border-color: var(--accent); color: var(--accent); }
.shelf-group[open] > summary { border-radius: 6px 6px 0 0; border-bottom: none; }
.shelf {
  background: var(--surface); border: 1px solid var(--line);
  border-top: none; border-radius: 0 0 6px 6px;
}
.panel.shelf { border-top: 1px solid var(--line); border-radius: var(--radius); }

.prow {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 11px 16px; border-bottom: 1px solid var(--line);
}
.prow:last-child { border-bottom: none; }
.prow-main { flex: 1; min-width: 210px; }
.prow-name { font-weight: 500; }
.prow-meta { display: block; font-size: 12.5px; color: var(--ink-soft); margin-top: 2px; }
.prow-actions { display: flex; gap: 8px; align-items: center; }
.prow-more { width: 100%; }
.prow-more > summary { cursor: pointer; font-size: 12px; color: var(--ink-faint); list-style: none; }
.prow-more > summary::before { content: "▸ "; }
.prow-more[open] > summary::before { content: "▾ "; }
.prow-more > summary:hover { color: var(--accent); }
.prow-detail { padding: 8px 0 4px; }

.chip {
  font-size: 11px; padding: 1px 8px; border-radius: 999px; margin-left: 6px;
  border: 1px solid var(--line-firm); background: var(--ground); color: var(--ink-soft);
}
.chip.gt { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
.chip.mine { background: var(--accent-wash); border-color: var(--accent); color: var(--accent); }
.chip.done { background: #eaf4ee; border-color: #bcd9c7; color: var(--good); }
.mix .sub { display: inline-block; margin-right: 12px; font-size: 13px; color: var(--ink-soft); }
.mix .sub b { color: var(--ink); }

/* ---- tables ---------------------------------------------------------- */
table.board { border-collapse: collapse; width: 100%; margin-top: 6px; font-size: 13.5px; }
.board th, .board td { border-bottom: 1px solid var(--line); padding: 7px 10px; text-align: left; }
.board th { color: var(--ink-faint); font-weight: 500; font-size: 12px;
  text-transform: uppercase; letter-spacing: 0.04em; }
.board a { color: var(--accent); text-decoration: none; }
.board-label { margin: 14px 0 2px; font-size: 13px; font-weight: 600; }

/* ---- login ----------------------------------------------------------- */
.login-card {
  max-width: 340px; margin: 90px auto; background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--radius); padding: 28px;
}
.login-card label { display: block; margin: 14px 0; font-size: 14px; color: var(--ink-soft); }
.login-card input {
  width: 100%; padding: 9px 11px; margin-top: 5px; font: inherit;
  border: 1px solid var(--line-firm); border-radius: 6px; background: var(--ground);
}
.login-card input:focus { outline: 2px solid var(--accent-wash); border-color: var(--accent); }
.login-card .btn { width: 100%; margin-top: 10px; }

/* ---- admin: right now -------------------------------------------------
   Presence is the one place a colour means a state rather than an action, so
   the dot carries it and nothing else does: green at the screen, amber idle.
   The progress bar reuses the scorecard's four-outcome segments deliberately —
   a live paper and a finished one should read the same way. */
.live h2 { display: flex; align-items: center; gap: 8px; }
.pulse {
  width: 7px; height: 7px; border-radius: 50%; background: var(--good);
  animation: pulse 2.4s ease-in-out infinite;
}
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.25; } }
@media (prefers-reduced-motion: reduce) { .pulse { animation: none; } }

.who { display: flex; flex-wrap: wrap; gap: 8px; margin: 10px 0 4px; }
.chip {
  display: inline-flex; align-items: center; gap: 6px; font-size: 13px;
  padding: 3px 10px 3px 8px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--ground); white-space: nowrap;
}
.chip em { font-style: normal; color: var(--ink-faint); font-size: 12px; }
.chip .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--line-firm); }
.chip.online .dot { background: var(--good); }
.chip.idle .dot { background: #c99a3d; }
.chip.online { border-color: #cfe4d8; }

.live-board td { vertical-align: middle; }
.live-board .num { font-variant-numeric: tabular-nums; }
.live-board .num small { color: var(--ink-faint); margin-left: 4px; }
.live-board .num.low { color: var(--bad); font-weight: 600; }
.progress-cell { min-width: 160px; }
.progress-cell .outcome-bar { height: 8px; }
.progress-cell small { display: block; margin-top: 4px; color: var(--ink-faint); font-size: 12px; }
.flag { color: var(--warn-ink); background: var(--warn-bg);
  border: 1px solid var(--warn-line); border-radius: 4px; padding: 0 5px; font-size: 12px; }

/* ---- results --------------------------------------------------------- */
.card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 18px 20px; margin-bottom: 16px;
}
.headline { padding: 24px; }
.headline-score { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.score-big { font-size: 52px; font-weight: 600; letter-spacing: -0.035em; line-height: 1; }
.score-big.pass { color: var(--good); } .score-big.fail { color: var(--bad); }
.score-of { font-size: 22px; color: var(--ink-faint); }
.verdict {
  margin-left: 8px; font-size: 12px; font-weight: 600; letter-spacing: 0.09em;
  border-radius: 999px; padding: 4px 12px; align-self: center;
}
.verdict.pass { background: #eaf4ee; color: var(--good); }
.verdict.fail { background: #fbecea; color: var(--bad); }
.headline-line { margin: 10px 0 18px; color: var(--ink-soft); max-width: 58ch; }

/* One bar, four outcomes. Right and wrong alone hide the two failures that
   have different fixes, so all four get width in proportion. */
.outcome-bar { display: flex; height: 10px; border-radius: 999px; overflow: hidden; gap: 2px; }
.outcome-bar > span, .stack > span { display: block; }
.seg-correct   { background: var(--good); }
.seg-wrong     { background: var(--bad); }
.seg-skip      { background: #c99a3d; }
.seg-unreached { background: var(--line-firm); }

.legend { display: flex; gap: 16px; flex-wrap: wrap; list-style: none;
  padding: 0; margin: 10px 0 0; font-size: 13px; color: var(--ink-soft); }
.legend i { display: inline-block; width: 9px; height: 9px; border-radius: 3px; margin-right: 6px; }
.k-correct { background: var(--good); } .k-wrong { background: var(--bad); }
.k-skip { background: #c99a3d; } .k-unreached { background: var(--line-firm); }

.note { font-size: 13.5px; margin: 14px 0 0; }
.note.warning { background: var(--warn-bg); border: 1px solid var(--warn-line);
  color: var(--warn-ink); border-radius: 6px; padding: 10px 12px; }

.projection { padding: 20px 22px; }
.projection-line { font-size: 17px; margin: 0 0 12px; }
.projection-line b { font-size: 22px; letter-spacing: -0.02em; }
.proj-bar { display: flex; height: 12px; background: var(--line);
  border-radius: 999px; overflow: hidden; }
.proj-fill { background: var(--accent); }
.proj-rest { flex: 1; }

.subjects td { vertical-align: middle; }
.subjects .subj { font-weight: 500; }
.subjects .chip { font-size: 10px; }
.stack { display: flex; height: 9px; border-radius: 999px; overflow: hidden;
  gap: 2px; width: 100%; vertical-align: middle; }
th.w-bar, td.w-bar { width: 42%; }

.up { color: var(--good); } .down { color: var(--bad); }

.review-q { scroll-margin-top: 20px; }
.review-q img { max-width: 100%; height: auto; }
.review-head { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; margin-bottom: 10px; }
.tag { font-size: 11px; padding: 2px 9px; border-radius: 999px; color: #fff; }
.tag.right { background: var(--good); } .tag.wrong { background: var(--bad); }
.tag.skip { background: var(--ink-faint); }
.tag.repeat { background: #7a4fa3; }
.review-choices { list-style: upper-alpha; padding-left: 22px; }
.review-choices li { margin: 5px 0; padding: 7px 10px; border-radius: 6px; }
.review-choices .is-correct { background: #eaf4ee; }
.review-choices .is-chosen:not(.is-correct) { background: #fbecea; }
.review-choices .mark { font-size: 12px; color: var(--ink-soft); white-space: nowrap; }
.solution { margin-top: 10px; }
.solution summary { cursor: pointer; color: var(--accent); font-weight: 500; font-size: 14px; }
.solution div { margin-top: 8px; line-height: 1.6; }
.solution img { max-width: 100%; height: auto; }

/* ---- the scorecard's four pictures ------------------------------------
 *
 * All four are drawn with the colours already defined above: green is banked,
 * red is lost, amber is left blank, grey is never reached. Nothing here invents
 * a palette, because the same four outcomes are being shown as the bar at the
 * top of the page and a reader should not have to learn them twice.
 *
 * There is no chart library. Three of the four are boxes with a percentage
 * width, which CSS does natively and correctly at every screen size; only the
 * pace curve needs real geometry, and that is one inline <svg>.
 */

/* The paper in one picture: one square per question, in the order you sat it.
   Squares are small on purpose — 300 of them have to fit on one screen for the
   shape to be visible, and the shape is the whole point. */
.qmap { display: flex; flex-wrap: wrap; gap: 3px; }
.qcell {
  width: 15px; height: 15px; border-radius: 3px; display: block;
  background: var(--line-firm); position: relative;
}
.qcell.is-correct { background: var(--good); }
.qcell.is-wrong { background: var(--bad); }
.qcell.is-skip { background: #c99a3d; }
.qcell.is-unreached { background: var(--line-firm); }
/* Missed here and missed before. It is a fact about the question, not a fifth
   outcome, so it is a mark on top of the colour rather than another colour. */
.qcell.is-repeat::after {
  content: ""; position: absolute; inset: auto 2px 2px auto;
  width: 4px; height: 4px; border-radius: 50%; background: #7a4fa3;
  box-shadow: 0 0 0 1px #fff;
}
.qcell:hover { outline: 2px solid var(--accent); outline-offset: 1px; }
.k-repeat { background: #7a4fa3; }
.vh {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}

/* Marks at risk in October, subject by subject. The bar's WIDTH is what the
   blueprint gives the subject, so a long bar is a heavy subject; the split
   inside it is what you would bank against what you would lose. Two encodings
   in one row, and neither can be read as the other. */
.stakes { display: flex; flex-direction: column; gap: 7px; }
.stake-row {
  display: grid; gap: 2px 12px; align-items: center;
  grid-template-columns:
    minmax(140px, 1.5fr) minmax(110px, 3fr) minmax(86px, auto) minmax(74px, auto);
}
.stake-name { font-weight: 500; }
/* Two right answers out of thirty-three marks draws the greenest bar on the
   page, and it is the least trustworthy row on it. Thin rows are faded so the
   eye does not read the strongest signal off the weakest evidence. */
.stake-row.is-thin { opacity: 0.55; }
.stake-track { min-width: 0; }
.stake-bar { display: flex; height: 12px; border-radius: 3px; overflow: hidden; min-width: 2px; }
.stake-banked { background: var(--good); }
.stake-risk { background: var(--bad); opacity: 0.55; }
.stake-none { flex: 1; background: repeating-linear-gradient(
  45deg, var(--line) 0 4px, var(--surface) 4px 8px); }
.stake-num { font-size: 13px; text-align: right; white-space: nowrap; }
.stake-num b { font-variant-numeric: tabular-nums; }
.stake-here { font-size: 12px; color: var(--ink-faint); text-align: right; white-space: nowrap; }
@media (max-width: 620px) {
  /* Four columns do not fit a phone, and the bar is the one that must not
     shrink: the name wraps above it and the two numbers share the line below. */
  .stake-row { grid-template-columns: 1fr auto auto; }
  .stake-name { grid-column: 1 / -1; }
  .stake-track { grid-column: 1 / -1; }
}

/* Then against now, per subject, on one 0-100% track. A slope, not two bars:
   the question is which way it moved, and a pair of bars makes you subtract. */
.shifts { display: flex; flex-direction: column; gap: 10px; }
.shift-row {
  display: grid; gap: 12px; align-items: center;
  grid-template-columns: minmax(110px, 1.2fr) minmax(140px, 3fr) minmax(120px, auto);
}
.shift-row.is-thin { opacity: 0.62; }
.shift-name { font-weight: 500; }
.shift-track {
  position: relative; height: 14px; border-radius: 999px;
  background: linear-gradient(to right, var(--line), var(--line));
  background-size: 100% 2px; background-position: 0 center;
  background-repeat: no-repeat;
}
.shift-link { position: absolute; top: 6px; height: 2px; background: var(--ink-faint); }
.shift-link.up { background: var(--good); }
.shift-link.down { background: var(--bad); }
.shift-dot {
  position: absolute; top: 3px; width: 8px; height: 8px; margin-left: -4px;
  border-radius: 50%; box-sizing: content-box;
}
.shift-dot.before { background: var(--surface); border: 2px solid var(--ink-faint); top: 1px; }
.shift-dot.now { background: var(--ink); border: 2px solid var(--surface); top: 1px; }
.shift-num { font-size: 13px; text-align: right; white-space: nowrap; }
.shift-num b { margin-right: 6px; font-variant-numeric: tabular-nums; }

/* Score across your attempts, with the pass line drawn where it actually is.
   A column per attempt: there are rarely more than a handful, and columns make
   the gap between two of them readable in a way a sparkline does not. */
.trend {
  position: relative; display: flex; align-items: flex-end; gap: 6px;
  height: 130px; padding: 0 2px; border-bottom: 1px solid var(--line-firm);
}
.trend-col {
  flex: 1; height: 100%; max-width: 64px;
  display: flex; flex-direction: column; justify-content: flex-end;
}
.trend-value { font-size: 12px; color: var(--ink-soft); text-align: center; margin-bottom: 3px; }
.trend-bar { width: 100%; border-radius: 3px 3px 0 0; background: var(--line-firm); min-height: 2px; }
.trend-bar.pass { background: var(--good); }
.trend-bar.fail { background: var(--bad); opacity: 0.55; }
.trend-bar.is-current { outline: 2px solid var(--accent); outline-offset: 1px; opacity: 1; }
.trend-line {
  position: absolute; left: 0; right: 0; height: 0;
  border-top: 1px dashed var(--ink-faint);
}
.trend-line::after {
  content: attr(data-label); position: absolute; right: 0; top: -16px;
  font-size: 11px; color: var(--ink-faint);
}

/* The only chart here with real geometry. preserveAspectRatio="none" stretches
   the plot to the panel, which distorts shapes -- so nothing inside is a shape:
   two strokes, both kept true width by vector-effect, and every label in HTML
   underneath. */
.curve { display: block; width: 100%; height: 170px; }
.curve-line { fill: none; stroke: var(--accent); stroke-width: 2;
  stroke-linejoin: round; stroke-linecap: round; }
.curve-even { stroke: var(--ink-faint); stroke-width: 1; stroke-dasharray: 4 4; }
.curve-axis {
  display: flex; justify-content: space-between; font-size: 12px;
  color: var(--ink-faint); margin-top: 6px;
}
.curve-y { font-size: 12px; color: var(--ink-faint); margin: 0 0 2px; }

/* The projected mark and what it is out of, in one tile without two font
   sizes fighting each other. */
.tile b .of { font-size: 15px; font-weight: 500; color: var(--ink-faint); }

.next-list { margin: 0; padding-left: 20px; }
.next-list li { margin: 8px 0; }
.head-aside { margin: 0; font-size: 14px; }

/* ---- the review screen ------------------------------------------------ */
/* The scorecard's map on one line. It does not wrap: 300 squares in a grid at
   the top of a review screen would push the question itself below the fold,
   which is the problem this screen exists to fix. */
.qstrip-wrap {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 8px; margin: 14px 0;
  overflow-x: auto; overscroll-behavior-x: contain;
}
.qmap.qstrip { flex-wrap: nowrap; gap: 3px; width: max-content; }
.qstrip .qcell { width: 13px; height: 13px; }
/* Outside the current filter: still reachable, visibly not part of the walk. */
.qstrip .qcell.is-out { opacity: 0.34; }
.qstrip .qcell.is-here {
  outline: 2px solid var(--accent); outline-offset: 1px; opacity: 1;
}
.review-nav { display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin-top: 16px; }
.review-count { font-size: 13px; color: var(--ink-soft); }
.btn.is-off { opacity: 0.4; pointer-events: none; }
.segmented a.seg { text-decoration: none; }

/* ---- weak areas ------------------------------------------------------ */
.tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
  gap: 10px; margin: 16px 0; }
.tile {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 14px; text-align: center;
}
.tile b { display: block; font-size: 26px; font-weight: 600; letter-spacing: -0.02em; line-height: 1.15; }
.tile span { font-size: 12px; color: var(--ink-soft); }
.tile.accent b { color: var(--accent); }
.subjects td { vertical-align: middle; }
.subjects .subj { font-weight: 500; }
th.w-bar, td.w-bar { width: 46%; }
.bar {
  display: inline-block; width: calc(100% - 46px); height: 8px;
  background: var(--line); border-radius: 999px; overflow: hidden; vertical-align: middle;
}
.bar .fill { display: block; height: 100%; border-radius: 999px; }
.fill.low { background: var(--bad); } .fill.mid { background: #c99a3d; }
.fill.high { background: var(--good); }
.pct { display: inline-block; width: 40px; text-align: right; font-variant-numeric: tabular-nums; }
.thin { margin-top: 14px; }

/* ---- admin ----------------------------------------------------------- */
.row-actions form { margin-right: 6px; }
.add-user { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.add-user input {
  padding: 7px 10px; font: inherit; border: 1px solid var(--line-firm); border-radius: 6px;
}

/* ---- touch + small screens -------------------------------------------
 *
 * Two separate concerns, deliberately keyed off two different things:
 *
 *   `pointer: coarse` — the input is a finger. Nothing to do with width: an
 *   iPad in landscape is 1024px wide and still wants 44px hit targets and
 *   16px inputs (Safari zooms the whole page when you focus anything
 *   smaller, and never zooms back out).
 *
 *   `max-width` — the sheet is narrow. This is where columns reflow.
 *
 * A desktop at 500px gets the reflow and not the fat targets; an iPad at
 * 1024px gets the targets and not the reflow. Keying both off width would
 * get both cases wrong.
 */

@media (pointer: coarse) {
  /* 16px is the threshold below which iOS Safari zooms on focus. Every
     control that sets its own size has to be named: `.login-card input`
     and `.add-user input` say `font: inherit` at a higher specificity than
     a bare `input`, so the generic rule alone leaves both at 15px and both
     still zoom. */
  input, select, textarea,
  .filter, .login-card input, .add-user input { font-size: 16px; }

  .btn, .seg, .linklike, .btn-nbe { min-height: 44px; }
  .btn.small { min-height: 38px; }
  .topbar nav { gap: 20px; }
  .topbar a, .quiet-links a { padding: 4px 0; }
  .pick-row, .prow, .switch-mode { min-height: 48px; }
}

/* Hover is a lie on a touchscreen: the state sticks to the last thing
   tapped until you tap elsewhere. Leave the colour cues to :active. */
@media (hover: none) {
  .door:hover { border-color: var(--line); background: var(--surface); }
  .pick-row:hover, .switch-mode:hover { background: transparent; }
  .switch-mode:hover { border-color: var(--line); }
  .door:active { border-color: var(--accent); background: var(--accent-wash); }
  .pick-row:active { background: var(--accent-wash); }
}

/* Tables carry more columns than a phone has room for. Let them keep their
   real widths and scroll inside their own box, rather than squashing the
   numbers into unreadable slivers or pushing the whole page sideways. */
.board-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.board-wrap > .board { min-width: 460px; }
.board-wrap > .subjects { min-width: 520px; }
.board-wrap > .live-board { min-width: 760px; }

@media (max-width: 620px) {
  main { padding: 24px 14px 60px; }
  .topbar { flex-wrap: wrap; gap: 8px 16px; padding: 12px 14px; }
  .topbar nav { flex-wrap: wrap; gap: 14px; }
  h1 { font-size: 22px; }
  .score-big { font-size: 42px; }

  .door { padding: 18px 16px; }
  .door-title { font-size: 17px; }

  /* The picker's six columns become two lines: the decision (tick, subject,
     how many this paper gets) on top, the evidence for it underneath. The
     header row goes away, so each number carries its own label. */
  .panel-head { display: none; }
  .pick-row {
    grid-template-columns: 22px auto auto auto 1fr auto;
    gap: 3px 12px;
    padding: 12px 14px;
  }
  .pick-row .pick  { grid-row: 1 / span 2; grid-column: 1; align-self: center; }
  .pick-name       { grid-row: 1; grid-column: 2 / 6; }
  .pick-row .alloc { grid-row: 1; grid-column: 6; }
  .pick-marks { grid-row: 2; grid-column: 2; }
  .pick-avail { grid-row: 2; grid-column: 3; }
  .pick-seen  { grid-row: 2; grid-column: 4; }
  .pick-marks, .pick-avail, .pick-seen {
    text-align: left; font-size: 12px; color: var(--ink-faint);
  }
  .pick-marks::before, .pick-avail::before, .pick-seen::before {
    content: attr(data-label) " ";
  }

  .controls { padding: 14px; }
  .segmented { display: flex; width: 100%; }
  .seg { flex: 1; padding: 10px 6px; }

  .confirm { padding: 18px 16px; }
  .headline, .projection { padding: 18px 16px; }
  .card { padding: 14px 16px; }
  .login-card { margin: 40px auto; padding: 22px; }
  .tiles { grid-template-columns: repeat(auto-fit, minmax(88px, 1fr)); }
  .review-choices { padding-left: 20px; }
}
