/* ============================================================
   THE ANNOTATED NOTEBOOK — Multiple-Choice study surface.

   Page-scoped: it legitimately styles the FROZEN mcq.js /
   tab-indicator.js DOM classes (question-card, mcq-*,
   .questions-mode-tab*, .qmt-indicator, .esa-dots …) — restyle,
   never rename. nb pages load ONLY the nb layers (no mcq.css /
   tab-indicator.css / lazy-loading.css / noteviewer.css), so
   every rule those legacy sheets owned is reproduced here.

   The lazily-injected /page/ fragments carry the SAME
   question-card / mcq-* classes as the first window (they are
   rendered from the same _mcq_card.html), so styling these
   classes reaches offset>0 cards identically.

   THE LOOK (owner, 2026-10-05: "make the mcqs layout look 1:1 like
   this", the mock-ups in Desktop/mcq draft, without their Flag).
   · The title at the left, then ONE bar under it: the two tabs as
     words with the page you are on underlined in blue, the answered
     count over its line, and Retry questions. A hairline under it.
   · Questions sit on the desk, not in cards: Q02 in blue in the
     margin, the question beside it, the options under the
     question, a hairline between questions.
   · An option is a row on the sheet's tone with its letter in a
     filled circle. Answered: the pick goes red with "Your answer",
     the answer green with "Correct"; the other rows stay as they are.
   · The response is a card: a big tick or cross, "Correct" or "Not
     quite", your answer and the correct answer by letter, a rule,
     then each explanation under an icon and a bold heading. From
     1280px it stands beside the question; under that, below the
     options. On a phone the options take the full width and each
     row carries a ring at its end that fills with the tick or cross.

   Discipline (test-enforced by pages/tests_notebook.py):
   · zero raw colours — every colour enters as var(--nb-*)/color-mix.
   · font sizes only through var(--nb-text-*) (the typography ratchet,
     pages/tests_font_foundation.py, counts every font / family /
     weight declaration and pins their SHA).
   · the verdict colours are the callout pair: --nb-adm-tip (green)
     = correct, --nb-adm-warn (red) = incorrect, nothing else.

   Contents
     1 · Column and title
     2 · The bar: switcher, count, Retry
     3 · The list and one question
     4 · Question head (number, count, question)
     5 · Options
     6 · Answered states and the marks
     7 · The response
     8 · Loading dots + empty state + prev/next
     9 · Phone
    10 · Reduced motion
    11 · The answered sheet grows (1280px and up)
    12 · Maths in a question
    13 · The Retry dialog
    14 · The tutor's quiz
   ============================================================ */

/* ---------- 1 · Column and title ------------------------------ */
/* The sheet takes the track beside the rail (the mock-up's column runs from
   the rail to the window's edge), capped so a 1920 screen does not turn a
   question into a poster.

   ⚑ width:100% IS LOAD-BEARING. .nb-notes-column sets margin-inline:auto
   (notebook-page.css), and a grid item with an auto margin is sized to
   fit-content instead of stretching: a chapter page with no question on it
   would otherwise be as wide as whatever it happens to hold. */
.nb-mcq-column {
  --nb-mcq-sheet-width: 760px;
  width: 100%;
  /* centred in the track (notebook-page.css's auto margins) at the question's
     own measure; from 1280 it widens to 1240px once a question is answered
     (section 11; owner, 2026-10-05: "centered and then it expands") */
  max-width: var(--nb-mcq-sheet-width);
}
/* The subject practice page shares the Topic Questions measure; the
   tutor quiz keeps its own reading column. */
.nb-mcq-column:not(.nb-quiz) {
  --nb-mcq-sheet-width: 982px;
}

/* The title reads at the left, over the bar (the mock-up). */
.nb-mcq-head {
  --nb-practice-title-size: 2rem;
  margin-bottom: var(--nb-s7);
  padding-inline-start: var(--nb-s9);
  text-align: left;
}
.nb-mcq-head .nb-notes-title {
  line-height: 1.25;
  font-size: var(--nb-practice-title-size);
  font-weight: 600;
  letter-spacing: -0.01em;
  text-align: left;
}

.nb-mcq-agg {
  display: inline-block;
  margin-left: var(--nb-s2);
  padding: var(--nb-s1) var(--nb-s3);
  vertical-align: middle;
  background: var(--nb-paper-sunken);
  border: 1px solid var(--nb-border);
  border-radius: var(--nb-r-pill);
  font: var(--nb-type-label);
  letter-spacing: 0.02em;
  color: var(--nb-ink-2);
}

/* mcq.js sets `hidden` on the Retry button when the confirmation opens, and on
   the confirmation when Cancel closes it. `hidden` is a USER-AGENT rule at the
   lowest specificity, so any author `display` beats it — .nb-btn carries
   display:inline-flex (notebook-components.css). Scoped to the two retry
   hooks, not a site-wide [hidden] rule. */
[data-mcq-retry][hidden],
[data-mcq-retry-confirm][hidden] {
  display: none !important;
}
.nb-mcq-back {
  padding-left: var(--nb-s2);
  padding-right: var(--nb-s2);
  /* wraps instead of pushing the page sideways, as .nb-qg-back does */
  white-space: normal;
  text-wrap: balance;
  text-align: center;
}
.nb-mcq-whole {
  margin-left: 0;
}

.nb-mcq-body {
  margin-top: 0;
}

/* Paywall placement — the mirror of notebook-grader.css. .nb-paywall is a
   460px max-width BLOCK, so without a centring wrapper it takes the
   wrapper's left edge. */
.nb-paywall-wrap {
  display: flex;
  justify-content: center;
  margin-top: var(--nb-s8);
}

/* ---------- 2 · The bar: switcher, count, Retry --------------- */
/* Two rows as the phone mock-up draws it: the tabs
   on their hairline (the blue underline of the page you are on is drawn
   over it), then the count over its line with Retry at the right, a hairline
   under them too. nb pages do not load noteviewer.css or tab-indicator.css,
   so the switcher's whole skin is here. */
.nb-mcq-bar {
  padding-inline-start: var(--nb-s9);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
}

.questions-mode-tabs {
  position: relative;
  display: flex;
  flex: 1 1 100%;
  gap: var(--nb-s6);
  margin: 0;
  padding: 0;
  border-bottom: 1px solid var(--nb-border);
}
.questions-mode-tab {
  position: relative;
  z-index: 1;
  padding: var(--nb-s4) var(--nb-s2) var(--nb-s5);
  font: var(--nb-type-control);
  font-size: var(--nb-text-md);
  font-weight: 400;
  text-decoration: none;
  white-space: nowrap;
  color: var(--nb-ink);
  transition: color var(--nb-dur-1) var(--nb-ease);
}
/* Hover is interaction blue: the resting tab is already the full ink. */
.questions-mode-tab:hover {
  color: var(--nb-blue);
}
/* The page you are on: the selection's soft ink (the link blue by night, the
   stronger blue by day), and the underline before tab-indicator.js runs (and
   without it): a mark that is not colour alone. */
.questions-mode-tab.is-active {
  font-weight: 500;
  color: var(--nb-selection-soft-ink);
  box-shadow: inset 0 -3px 0 var(--nb-selection-soft-ink);
}
.questions-mode-tab:focus-visible {
  outline: 2px solid var(--nb-blue);
  outline-offset: -2px;
  border-radius: var(--nb-r-sm);
}
/* The sliding underline (tab-indicator.js injects it and writes left/width;
   it slides in from the tab you came from). It sits on the bar's hairline. */
.qmt-indicator {
  position: absolute;
  top: auto;
  bottom: -1px;
  left: 0;
  width: 0;
  height: 3px;
  border-radius: var(--nb-r-sm) var(--nb-r-sm) 0 0;
  background: var(--nb-selection-soft-ink);
  pointer-events: none;
  z-index: 2;
  will-change: left, width; /* hint for the one-shot entrance glide */
}
/* Where large text stacks the two tabs, tab-indicator.js writes the active
   tab's top and height inline (for the pill it was written for). The line
   stays a line on the bar's foot, which is the active tab's foot: Multiple
   Choice is the last tab. */
.nb-mcq-bar .qmt-indicator {
  top: auto !important;
  bottom: -1px !important;
  height: 3px !important;
}
/* When the indicator is wired, the active tab shows through it. */
.questions-mode-tabs.has-indicator .questions-mode-tab.is-active {
  box-shadow: none;
}

/* The count over its line, then Retry questions, at the bar's right. */
.nb-mcq-progress {
  display: flex;
  flex: 1 1 100%;
  align-items: center;
  gap: var(--nb-s5);
  padding-block: var(--nb-s4);
  border-bottom: 1px solid var(--nb-border);
}
.nb-mcq-progress-count {
  display: grid;
  flex: 1 1 auto;
  gap: var(--nb-s2);
  max-inline-size: 26rem;
}
.nb-mcq-progress .nb-mcq-retry-btn {
  margin-left: auto;
}
.nb-mcq-progress-meta {
  margin: 0;
  font: var(--nb-type-ui);
  color: var(--nb-ink);
  font-variant-numeric: tabular-nums;
}
/* A plain rounded line that fills with blue (the mock-up), not the signature
   ink line with its nib: the count above it already says the number. */
.nb-progress.nb-mcq-progress-bar {
  height: 8px;
  background: color-mix(in srgb, var(--nb-ink) 12%, transparent);
  overflow: hidden;
}
/* The fill is unmasked rather than scaled, so its rounded end keeps its
   shape at every length (a scaleX squashes the radius). */
.nb-mcq-progress-bar .nb-progress-fill {
  transform: none;
  clip-path: inset(0 calc((1 - var(--nb-progress, 0)) * 100%) 0 0 round var(--nb-r-pill));
  transition: clip-path var(--nb-dur-3) var(--nb-ease);
}
.nb-mcq-retry-btn {
  gap: var(--nb-s3);
  padding: var(--nb-s3) var(--nb-s5);
  /* a hairline with a touch of its blue, soft in both themes (the strong
     edge read as a black outline by day) */
  border-color: color-mix(in srgb, var(--nb-blue) 30%, var(--nb-border));
  border-radius: var(--nb-r-md);
  background: transparent;
  font-size: var(--nb-text-base);
  white-space: nowrap;
}
.nb-mcq-retry-btn svg {
  flex: none;
  transition: transform var(--nb-dur-2) var(--nb-ease);
}
@media (hover: hover) {
  .nb-mcq-retry-btn:hover:not(:disabled) svg {
    transform: rotate(-70deg);
  }
}
/* nothing answered yet: an outline at rest, not a sunken hole */
.nb-mcq-retry-btn:disabled {
  background: transparent;
}

/* ---------- 3 · The list and one question --------------------- */
/* The list stacks its questions; the loader + sentinel are pinned last
   (mcq.js inserts new cards before them). A hairline between questions. */
.mcq-list {
  display: flex;
  flex-direction: column;
}

/* A question on the desk: the number in a margin column, the question and
   its options in the second, the response under them (or, from 1280, in a
   third column beside them, section 11). The frozen .question-card wrapper
   is the state root mcq.js flips. */
.question-card {
  --mcq-num-w: 60px;
  --mcq-col-gap: var(--nb-s7);
  position: relative;
  display: grid;
  grid-template-columns: var(--mcq-num-w) minmax(0, 1fr);
  column-gap: var(--mcq-col-gap);
  padding: var(--nb-s7) 0 var(--nb-s8);
}
.question-card + .question-card {
  border-top: 1px solid var(--nb-border);
}

/* ---------- 4 · Question head --------------------------------- */
/* The head's two parts take the card's first two columns. */
.mcq-q-head {
  display: contents;
}
/* It spans the options' row too, so a tier's two lines never push a
   one-line question's options down (on a phone, section 9, it keeps to its
   row). */
.mcq-q-no {
  grid-column: 1;
  grid-row: 1 / span 2;
  align-self: start;
  display: flex;
  flex-direction: column;
  gap: var(--nb-s1);
  font: var(--nb-type-label);
  font-size: var(--nb-text-lg);
  line-height: 1.2;
  letter-spacing: 0;
  color: var(--nb-blue);
  /* a tier's rocket takes its own line over Q02 rather than running into
     the question beside it */
  white-space: normal;
  font-variant-numeric: tabular-nums;
}
/* The question and its options keep one reading measure (owner, 2026-10-05:
   "the mcq options are toooo long"), so a short answer is not a 900px bar. */
.question-card {
  --mcq-measure: 46rem;
}
.mcq-q-main {
  grid-column: 2;
  grid-row: 1;
  min-width: 0;
  max-width: var(--mcq-measure);
}
/* .mcq-question is a div (escapes .noteviewer-body h2). It MUST match
   .tq-question in notebook-grader.css exactly (same size/weight/line-height/
   tracking): the switcher toggles Topic Questions <-> Multiple Choice on the
   same chapter, so the question text reads identically across both. */
.mcq-question {
  font-family: var(--nb-sans);
  font-size: var(--nb-text-md);
  font-weight: 600;
  line-height: 1.5;
  letter-spacing: -0.005em;
  color: var(--nb-ink);
  /* a word wider than the sheet breaks instead of pushing the page sideways */
  overflow-wrap: break-word;
}
/* A picture's caption is its label, not part of the question (owner
   2026-09-30): the small step of the scale, regular and italic. */
.mcq-question .note-figure-caption {
  margin-top: var(--nb-s2);
  font-size: var(--nb-text-sm);
  font-style: italic;
  font-weight: 400;
  line-height: 1.4;
  color: var(--nb-ink);
}
.mcq-question > :first-child { margin-top: 0; }
.mcq-question > :last-child  { margin-bottom: 0; }
.mcq-question p {
  margin: 0 0 var(--nb-s3);
}
.mcq-question p:last-child { margin-bottom: 0; }

/* The old rule under the question: the options' own edges carry it now. */
.mcq-rule {
  display: none;
}

/* ---------- 5 · Options --------------------------------------- */
/* Rows under the question. The A/B/C letter is a CSS counter (mcq.js derives
   its feedback letters from the SAME rendered order — never reorder in the
   template). */
.mcq-options {
  grid-column: 2;
  grid-row: 2;
  counter-reset: mcq-letter;
  display: flex;
  flex-direction: column;
  gap: var(--nb-s3);
  max-width: var(--mcq-measure);
  margin: var(--nb-s6) 0 0;
  padding: 0;
  list-style: none;
}
.mcq-option {
  margin: 0;
  padding: 0;
}
.mcq-option-btn {
  counter-increment: mcq-letter;
  display: flex;
  align-items: center;
  gap: var(--nb-s5);
  width: 100%;
  min-height: 62px;
  padding: var(--nb-s3) var(--nb-s6) var(--nb-s3) var(--nb-s5);
  background: var(--nb-paper-raised);
  /* the sheet's hairline in both themes: by day the 3:1 control edge drew a
     near-black outline round every row (owner, 2026-10-05: "on light ... this
     black outline that makes it look disgusting"); the row's own fill and
     its letter circle say it is a control */
  border: 1px solid var(--nb-border);
  border-radius: var(--nb-r-md);
  font: var(--nb-type-prose);
  line-height: 1.45;
  text-align: left;
  color: var(--nb-ink);
  cursor: pointer;
  transition:
    border-color var(--nb-dur-1) var(--nb-ease),
    background-color var(--nb-dur-1) var(--nb-ease),
    transform var(--nb-dur-1) var(--nb-ease);
}
@media (hover: hover) {
  .mcq-option-btn:hover:not(:disabled) {
    border-color: color-mix(in srgb, var(--nb-blue) 42%, var(--nb-border));
    background: var(--nb-blue-wash);
  }
}
.mcq-option-btn:focus-visible {
  outline: 2px solid var(--nb-blue);
  outline-offset: 2px;
}
@media (prefers-reduced-motion: no-preference) {
  .mcq-option-btn:active:not(:disabled) {
    transform: translateY(1px);
  }
}

/* The letter in a filled circle. ::before renders counter(mcq-letter). */
.mcq-opt-badge {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: var(--nb-r-pill);
  background: color-mix(in srgb, var(--nb-ink) 10%, var(--nb-paper-raised));
  font: var(--nb-type-label);
  font-size: var(--nb-text-base);
  line-height: 1;
  color: var(--nb-ink);
  transition:
    background-color var(--nb-dur-1) var(--nb-ease),
    color var(--nb-dur-1) var(--nb-ease);
}
.mcq-opt-badge::before {
  content: counter(mcq-letter, upper-alpha);
}
@media (hover: hover) {
  .mcq-option-btn:hover:not(:disabled) .mcq-opt-badge {
    background: color-mix(in srgb, var(--nb-blue) 20%, var(--nb-paper-raised));
    color: var(--nb-blue);
  }
}
.mcq-opt-text {
  flex: 1 1 auto;
  min-width: 0;
  overflow-wrap: break-word;
}

/* ---------- 6 · Answered states and the marks ----------------- */
/* mcq.js disables all buttons and tags each: is-correct / is-incorrect on the
   pick (and on the answer when the pick was wrong), is-dimmed on the rest.
   The rest stay exactly as they were (the mock-up): they are read again to
   compare with the answer. */
.mcq-option-btn:disabled {
  cursor: default;
}
.mcq-option-btn.is-correct,
.mcq-option-btn.is-incorrect {
  --mcq-state: var(--nb-adm-tip);
  border-color: color-mix(in srgb, var(--mcq-state) 75%, transparent);
  background: color-mix(in srgb, var(--mcq-state) 9%, var(--nb-paper-raised));
}
.mcq-option-btn.is-incorrect {
  --mcq-state: var(--nb-adm-warn);
}
.mcq-option-btn.is-correct .mcq-opt-badge,
.mcq-option-btn.is-incorrect .mcq-opt-badge {
  background: color-mix(in srgb, var(--mcq-state) 22%, var(--nb-paper-raised));
  color: var(--mcq-state);
}

/* The mark at the row's end: an icon and "Your answer" or "Correct", in the
   state's colour. The words are the template's (data-wrong / data-right). */
.mcq-opt-mark {
  display: none;
  flex: none;
  align-items: center;
  gap: var(--nb-s2);
  margin-left: auto;
  font-size: var(--nb-text-base);
  line-height: 1.2;
  color: var(--mcq-state);
  white-space: nowrap;
}
.mcq-opt-mark::before {
  content: "";
  flex: none;
  width: 18px;
  height: 18px;
  background: currentColor;
  -webkit-mask: var(--mcq-mark-icon) center / contain no-repeat;
  mask: var(--mcq-mark-icon) center / contain no-repeat;
}
.mcq-option-btn.is-correct .mcq-opt-mark,
.mcq-option-btn.is-incorrect .mcq-opt-mark {
  display: inline-flex;
}
.mcq-option-btn.is-correct .mcq-opt-mark::after { content: attr(data-right); }
.mcq-option-btn.is-incorrect .mcq-opt-mark::after { content: attr(data-wrong); }
/* Beside the answer card on a laptop (1280 to 1449, where the sheet is under
   1000px) the options are narrow: the tick or the cross alone, with the row's
   colour, so an option keeps its line. (Not a container query: containment
   on the list would scope its letter counter and every badge would read A.) */
@media (min-width: 1280px) and (max-width: 1449.98px) {
  .question-card.is-answered .mcq-opt-mark::after {
    content: none;
  }
}
.mcq-option-btn,
.mcq-pset-item {
  --mcq-tick: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");
  --mcq-cross: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M18 6 6 18M6 6l12 12'/%3E%3C/svg%3E");
  --mcq-dot: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Ccircle cx='12' cy='12' r='6' fill='%23000'/%3E%3C/svg%3E");
}
.mcq-option-btn.is-correct { --mcq-mark-icon: var(--mcq-tick); }
.mcq-option-btn.is-incorrect { --mcq-mark-icon: var(--mcq-cross); }

/* A tiny confirm pop on the correct choice (interaction feedback). */
@media (prefers-reduced-motion: no-preference) {
  .question-card.is-answered-correct .mcq-option-btn.is-correct {
    animation: nb-mcq-pop var(--nb-dur-2) var(--nb-ease);
  }
}
@keyframes nb-mcq-pop {
  0%   { transform: scale(1); }
  45%  { transform: scale(1.01); }
  100% { transform: scale(1); }
}

/* ---------- 7 · The response ---------------------------------- */
/* mcq.js builds this into .mcq-reasoning after answering, then adds
   .is-visible. Every inner class below is JS-created — style them, never
   emit them. Under 1280 it opens under the options (a max-height reveal);
   section 11 stands it beside the question. */
.mcq-reasoning {
  grid-column: 2;
  grid-row: 3;
  min-width: 0;
  /* under the options it keeps their measure, so the two share a right edge */
  max-width: var(--mcq-measure);
  overflow: hidden;
  max-height: 0;
  margin-top: 0;
  opacity: 0;
  transition:
    max-height var(--nb-dur-3) var(--nb-ease),
    opacity var(--nb-dur-2) var(--nb-ease),
    margin-top var(--nb-dur-2) var(--nb-ease);
}
/* margin-top is --nb-s5: mcq.js reads that token to know where the response
   is heading while it opens (settledBox). */
.mcq-reasoning.is-visible {
  max-height: 2400px;
  margin-top: var(--nb-s5);
  padding: var(--nb-s6);
  background: var(--nb-paper-raised);
  border: 1px solid var(--nb-border);
  border-radius: var(--nb-r-md);
  opacity: 1;
}
/* An empty zone draws nothing, so a box is only ever round a response. */
.mcq-reasoning:empty {
  padding: 0;
  border: 0;
}

/* The verdict: a big filled tick or cross, "Correct" or "Not quite" in its
   colour, and under it your answer and the correct one by letter. A rule
   under the whole head. */
.mcq-verdict {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  column-gap: var(--nb-s4);
  padding-bottom: var(--nb-s5);
  border-bottom: 1px solid var(--nb-border);
}
.mcq-verdict.is-correct {
  --mcq-verdict: var(--nb-adm-tip);
}
.mcq-verdict.is-incorrect {
  --mcq-verdict: var(--nb-adm-warn);
}
.mcq-verdict-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: var(--nb-r-pill);
  background: var(--mcq-verdict);
  /* the glyph is white on the filled circle in both themes (the mock-up) */
  color: var(--nb-pset-card-bg);
}
.mcq-verdict-body {
  display: grid;
  gap: var(--nb-s1);
  min-width: 0;
}
.mcq-verdict-text {
  font-family: var(--nb-sans);
  font-size: var(--nb-text-xl);
  font-weight: 600;
  line-height: 1.15;
  letter-spacing: -0.01em;
  color: var(--mcq-verdict);
}

/* Your answer: C   Correct answer: D — the letters in their colours. */
.mcq-answer-ref,
.nb-mcq-empty .nb-empty-note {
  font: var(--nb-type-ui);
}
.mcq-answer-ref {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--nb-s1) var(--nb-s5);
  color: var(--nb-ink);
}
.mcq-answer-ref-item {
  white-space: nowrap;
}
.mcq-answer-ref-label {
  font: var(--nb-type-label);
  font-size: var(--nb-text-base);
  font-weight: 400;
  color: var(--nb-ink);
}
.mcq-answer-ref-value {
  margin-left: var(--nb-s2);
  font-weight: 600;
  color: var(--nb-adm-tip);
}
.mcq-answer-ref-value.is-wrong {
  color: var(--nb-adm-warn);
}

/* An explanation: an icon and a bold heading, the paragraph under them. */
.mcq-explanation {
  margin-top: var(--nb-s6);
}
.mcq-verdict + .mcq-explanation {
  margin-top: var(--nb-s5);
}
/* ⚑ THE LABEL INK IS A CUSTOM PROPERTY ON THE ZONE, never a theme-scoped
   selector: `html.theme-dark .mcq-explanation-label` is (0,2,1) and would
   outrank the correction's own (0,2,0) restatement below.
   pages/tests_typography_stage5_wave3.py forbids the selector form. */
.mcq-reasoning {
  --mcq-explanation-ink: var(--nb-ink);
}
.mcq-explanation-label {
  position: relative;
  display: block;
  margin-bottom: var(--nb-s2);
  padding-left: 34px;
  font: var(--nb-type-label);
  font-size: var(--nb-text-md);
  line-height: 1.35;
  letter-spacing: normal;
  text-transform: none;
  color: var(--mcq-explanation-ink);
}
/* The heading's icon (mcq.js puts it first in the label): a filled red cross
   for why the pick is wrong, a filled green tick for why the answer is right,
   a book for the correction. It hangs in the label's padding, so a heading
   that wraps keeps its own left edge and the paragraph runs full width. */
.mcq-expl-icon {
  position: absolute;
  left: 0;
  top: 0.05em;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: var(--nb-r-pill);
  background: var(--mcq-expl-icon-fill, transparent);
  color: var(--mcq-expl-icon-ink, var(--nb-ink));
}
.mcq-explanation--incorrect {
  --mcq-expl-icon-fill: var(--nb-adm-warn);
  --mcq-expl-icon-ink: var(--nb-pset-card-bg);
}
.mcq-explanation--correct {
  --mcq-expl-icon-fill: var(--nb-adm-tip);
  --mcq-expl-icon-ink: var(--nb-pset-card-bg);
}
.mcq-explanation-text {
  margin: 0;
  font: var(--nb-type-prose);
  line-height: 1.55;
  color: var(--nb-ink);
}

/* ---------- the correction, the response's last block -----------
   Built by mcq.js only when the clicked option carries
   data-misconception-html (absent means no element). It reads as the mock-up's
   "Remember": a book, the misconception's own authored heading in bold, the
   correction under it. It closes the column, so no bottom margin.

   ⚑ THE TYPE STILL COMES FROM THE SHARED CLASSES. mcq.js gives each part BOTH
   .mcq-explanation-label / -text and its own modifier, so the correction
   inherits family and weight and only restates size, leading and colour. */
.mcq-misconception {
  position: relative;
  display: block;
  margin: var(--nb-s6) 0 0;
  padding: 0;
}
.mcq-misconception-label {
  text-wrap: balance;
}
.mcq-misconception-text {
  /* No font shorthand: it inherits font: var(--nb-type-prose) from
     .mcq-explanation-text. Lining figures: a correction is mostly units and
     powers of ten. */
  font-variant-numeric: lining-nums;
  text-wrap: pretty;
}
.mcq-misconception-link {
  display: inline-flex;
  align-items: center;
  gap: var(--nb-s2);
  margin-top: var(--nb-s3);
  font: var(--nb-type-control);
  color: var(--nb-blue);
  text-decoration: none;
}
.mcq-misconception-link:hover { text-decoration: underline; }
.mcq-misconception-link::after {
  content: "";
  flex: 0 0 auto;
  width: 14px;
  height: 14px;
  background: currentColor;
  -webkit-mask: var(--nb-mcq-arrow) center / contain no-repeat;
  mask: var(--nb-mcq-arrow) center / contain no-repeat;
  transition: transform var(--nb-dur-1) var(--nb-ease);
}
.mcq-misconception-link:hover::after { transform: translateX(3px); }
.mcq-misconception {
  --nb-mcq-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14m-6-6 6 6-6 6'/%3E%3C/svg%3E");
}
/* ⚑ THE RESTATEMENT, AND IT IS LOAD-BEARING. The correction's parts carry
   BOTH the generic class and the modifier, and single classes tie, so the
   later rule would win. Two classes each, (0,2,0): they win on specificity,
   proof against someone reordering this file. */
.mcq-misconception .mcq-misconception-label {
  font-size: var(--nb-text-md);
  line-height: 1.35;
  letter-spacing: normal;
  text-transform: none;
  color: var(--nb-ink);
}
.mcq-misconception .mcq-misconception-text {
  font-size: var(--nb-text-md);
  line-height: 1.55;
  color: var(--nb-ink);
}

/* MOTION — staged off .is-visible, via transition-delay, in reading order:
   verdict 0 · explanations 120 and 180 · correction 260. The whole response
   settles inside half a second: the student is mid-task. */
.mcq-reasoning > * {
  opacity: 0;
  transform: translateY(4px);
  transition:
    opacity var(--nb-dur-2) var(--nb-ease),
    transform var(--nb-dur-2) var(--nb-ease);
}
.mcq-reasoning.is-visible > * { opacity: 1; transform: translateY(0); }
.mcq-reasoning.is-visible .mcq-verdict { transition-delay: 0ms; }
.mcq-reasoning.is-visible .mcq-explanation { transition-delay: 120ms; }
.mcq-reasoning.is-visible .mcq-explanation--correct { transition-delay: 180ms; }
.mcq-reasoning.is-visible .mcq-misconception { transition-delay: 260ms; }

/* ⚑ REQUIRED GUARD. --nb-dur-* zero themselves under reduced motion
   (notebook-tokens.css), but a transition-delay is a raw number and would
   still stagger the reveal into a slideshow with no movement. */
@media (prefers-reduced-motion: reduce) {
  .mcq-reasoning > * {
    opacity: 1;
    transform: none;
    transition: none;
    transition-delay: 0ms;
  }
  .mcq-misconception-link::after { transition: none; }
}

/* ---------- 8 · Loading dots + empty + prev/next ------------- */
/* mcq.js unhides .mcq-loading during a lazy fetch. nb doesn't load
   lazy-loading.css, so the loader is defined here in ink. */
.esa-loading {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 120px;
}
.esa-loading[hidden] {
  display: none;
}
.esa-dots {
  display: inline-flex;
  gap: var(--nb-s1);
  align-items: center;
  line-height: 0;
  color: var(--nb-ink-3);
}
.esa-dots > span {
  width: var(--nb-s2);
  height: var(--nb-s2);
  border-radius: var(--nb-r-pill);
  background: currentColor;
  opacity: 0.35;
  animation: nb-mcq-dots 1.1s infinite ease-in-out both;
}
.esa-dots > span:nth-child(2) { animation-delay: 0.16s; }
.esa-dots > span:nth-child(3) { animation-delay: 0.32s; }
@keyframes nb-mcq-dots {
  0%, 80%, 100% { opacity: 0.3; transform: translateY(0) scale(0.8); }
  40%           { opacity: 1;   transform: translateY(-4px) scale(1); }
}

/* The invisible IntersectionObserver target — MUST stay last child. */
.mcq-sentinel {
  height: 1px;
}

.nb-mcq-empty {
  margin-top: var(--nb-s6);
}

/* Prev/next topic nav. */
.nb-mcq-pagination {
  display: flex;
  justify-content: space-between;
  /* Tops aligned: a title that wraps makes its link taller than its partner. */
  align-items: flex-start;
  gap: var(--nb-s4);
  margin-top: var(--nb-s6);
  padding-top: var(--nb-s5);
  border-top: 1px solid var(--nb-border);
}
.nb-pagenav {
  display: flex;
  flex-direction: column;
  gap: var(--nb-s1);
  min-width: 0;
  max-width: 46%;
  text-align: left;
}
.nb-pagenav--next {
  text-align: right;
  align-items: flex-end;
}
.nb-pagenav-dir {
  font: var(--nb-type-label);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--nb-ink-2);
}
/* The title wraps, it is never cut (mobile audit 2026-09-25, S-015). The link
   carries .nb-btn, which is nowrap, hence the explicit white-space. */
.nb-pagenav-title {
  font: var(--nb-type-label);
  color: var(--nb-ink);
  white-space: normal;
  overflow-wrap: anywhere;
  text-wrap: balance;
  max-width: 100%;
}

/* Both practice modes use the Topic Questions sheet position. The MCQ
   body alone keeps the theme button's lane on narrow desktop windows. */
@media (min-width: 1024px) and (max-width: 1279px) {
  html:not(.note-focus-mode) .nb-page-layout:has(.nb-notes-column.nb-mcq-column:not(.nb-quiz)) {
    padding-right: 0;
  }
  .nb-mcq-column:not(.nb-quiz) .nb-mcq-body {
    padding-right: calc(var(--ft-theme-lane) - clamp(20px, 2.5vw, 48px));
  }
}
@media (max-width: 860px) {
  .nb-mcq-head,
  .nb-mcq-bar {
    padding-inline-start: 0;
  }
  .nb-mcq-head {
    margin-bottom: var(--nb-s5);
  }
  .nb-mcq-head .nb-notes-title {
    font-size: var(--nb-text-2xl);
  }
  .nb-mcq-column .nb-mcq-modetabs {
    gap: var(--nb-s5);
  }
}

/* ---------- 9 · Phone ----------------------------------------- */
@media (max-width: 860px) {
  .nb-mcq-whole {
    margin-left: 0;
  }
  /* Half the row each on a phone, so a wrapped title keeps its lines few. */
  .nb-mcq-pagination .nb-pagenav {
    max-width: 50%;
  }
}

@media (max-width: 720px) {
  /* Whole chapter wraps inside the column instead of pushing the page
     sideways (mobile audit round 2, S-R1-2). */
  .nb-mcq-whole {
    white-space: normal;
    text-wrap: balance;
    text-align: center;
    max-inline-size: 100%;
  }
}
/* A phone: Retry is a plain blue word with its icon (the phone mock-up).
   The tabs keep their own widths on one row; with large text or page zoom a
   label wraps inside its tab, and where even that cannot fit the two tabs
   stack (S-G7) and the underline stays on the bar's foot (section 2). */
@media (max-width: 720px) {
  .questions-mode-tabs {
    gap: var(--nb-s5);
    max-width: 100%;
    flex-wrap: wrap;
  }
  .questions-mode-tab {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 1 auto;
    white-space: normal;
    text-align: center;
  }
  .nb-mcq-progress-count {
    max-inline-size: 80%;
  }
  .nb-mcq-retry-btn {
    margin-left: auto;
    padding: var(--nb-s2) 0 var(--nb-s2) var(--nb-s2);
    border: 0;
    font-size: var(--nb-text-md);
  }
}
@media (max-width: 720px) and (hover: hover) {
  .nb-mcq-retry-btn:hover:not(:disabled) {
    background: transparent;
    transform: none;
  }
}
/* "Retry" on a phone, so the count keeps its line. */
@media (max-width: 560px) {
  .nb-mcq-retry-more {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}

/* A phone: the title steps down, the tabs keep one row as long as their
   words fit (they wrap inside their own tab when they cannot), the options
   and the response take the column's full width under the question, and each
   option carries a ring at its end that fills with the tick or cross. */
@media (max-width: 640px) {
  .nb-mcq-head .nb-notes-title {
    font-size: var(--nb-text-xl);
  }
  .questions-mode-tabs {
    gap: var(--nb-s4);
  }
  .questions-mode-tab {
    padding: var(--nb-s3) var(--nb-s1) var(--nb-s4);
    font-size: var(--nb-text-base);
  }
  .question-card {
    --mcq-num-w: 44px;
    --mcq-col-gap: var(--nb-s4);
    padding: var(--nb-s6) 0 var(--nb-s7);
  }
  .mcq-q-no {
    grid-row: 1;
    font-size: var(--nb-text-md);
  }
  .mcq-options,
  .mcq-reasoning {
    grid-column: 1 / -1;
  }
  .mcq-options {
    margin-top: var(--nb-s5);
  }
  .mcq-option-btn {
    gap: var(--nb-s4);
    min-height: 56px;
    padding: var(--nb-s2) var(--nb-s4) var(--nb-s2) var(--nb-s3);
  }
  .mcq-opt-badge {
    width: 32px;
    height: 32px;
  }
  /* the mark is a ring: empty at rest, a filled tick or cross once answered */
  .mcq-opt-mark {
    display: inline-flex;
    justify-content: center;
    width: 26px;
    height: 26px;
    border: 1.5px solid color-mix(in srgb, var(--nb-ink) 40%, transparent);
    border-radius: var(--nb-r-pill);
  }
  .mcq-opt-mark::before {
    display: none;
  }
  .mcq-option-btn.is-correct .mcq-opt-mark,
  .mcq-option-btn.is-incorrect .mcq-opt-mark {
    border-color: var(--mcq-state);
    background: var(--mcq-state);
    color: var(--nb-pset-card-bg);
  }
  .mcq-option-btn.is-correct .mcq-opt-mark::before,
  .mcq-option-btn.is-incorrect .mcq-opt-mark::before {
    display: block;
    width: 15px;
    height: 15px;
  }
  .mcq-option-btn.is-correct .mcq-opt-mark::after,
  .mcq-option-btn.is-incorrect .mcq-opt-mark::after {
    content: none;
  }
  .mcq-reasoning.is-visible {
    padding: var(--nb-s5);
  }
  .mcq-verdict-icon {
    width: 40px;
    height: 40px;
  }
  /* "Your answer: C | Correct answer: D": one line, a short rule between */
  .mcq-answer-ref {
    column-gap: var(--nb-s3);
    font-size: var(--nb-text-sm);
  }
  .mcq-answer-ref-label {
    font-size: var(--nb-text-sm);
  }
  .mcq-answer-ref-value {
    margin-left: var(--nb-s1);
  }
  .mcq-answer-ref-item + .mcq-answer-ref-item {
    padding-left: var(--nb-s3);
    border-left: 1px solid var(--nb-border-strong);
  }
}
/* Below 360px the tabs and the number column give a little back. */
@media (max-width: 359px) {
  .questions-mode-tabs {
    gap: var(--nb-s3);
  }
  .questions-mode-tab {
    font-size: var(--nb-text-sm);
  }
  .question-card {
    --mcq-num-w: 40px;
    --mcq-col-gap: var(--nb-s3);
  }
}

/* Route-local touch target: the tabs keep a 44px floor, the label in its
   middle (S-R1-4). */
@media (pointer: coarse) {
  .questions-mode-tab {
    min-block-size: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
  }
}

/* ---------- 10 · Reduced motion ------------------------------ */
@media (prefers-reduced-motion: reduce) {
  .mcq-reasoning {
    transition: none;
  }
  .esa-dots > span { animation: none; opacity: 0.55; }
  .nb-mcq-retry-btn svg,
  .nb-mcq-progress-bar .nb-progress-fill {
    transition: none;
  }
  .question-card.is-answered {
    animation: none;
  }
}

/* ---------- 11 · The answered sheet grows (1280px and up)
   A textbook answers you beside the question, not under it. The sheet works
   as it did before the mock-up (owner, 2026-10-05: "make it functional like
   it was centered and then it expands like earlier"): a question sits
   centred at 982px; when it is answered the column widens (to 1240px, as
   far as the track allows) and THAT card grows to the column's width, the
   response card standing in a third column on its right. The options keep
   about the width they had (~670px beside a 440px card), so the question
   does not squeeze; the card unmasks from its centre as it grows.

   ⚑ CENTRED, NEVER ANCHORED TO AN EDGE. The column grows symmetrically
   (margin-inline:auto from notebook-page.css) and every card is centred in
   it, so the column's centre is the cards' centre: answering one question
   moves no other card, and the title and the bar stay pinned at 982px in the
   middle. An edge anchor once dragged every sibling 52px when one card was
   answered.

   ⚑ THE THIRD ROW IS 1fr, AND THAT IS THE WHOLE TRICK. The response spans
   the three rows and is usually taller than the question and its options.
   With every row at auto, grid would spread the excess over all three and
   push the options away from their question; a spanning item crossing a
   flexible track is settled in flex sizing instead (CSS Grid 12.5, 12.7.1),
   so the 1fr row takes all of it and the question and options stay together
   at the top. */
@media (min-width: 1280px) {
  .nb-mcq-column:has(.question-card.is-answered) {
    max-width: 1240px;
    margin-inline: auto;
  }
  .nb-mcq-column:has(.question-card.is-answered) > :not(.nb-mcq-body) {
    max-width: var(--nb-mcq-sheet-width);
    margin-inline: auto;
  }
  /* The Topic Questions measure, fixed so the reveal has a stable start. */
  .nb-mcq-column .question-card {
    box-sizing: border-box;
    width: var(--nb-mcq-sheet-width);
    max-width: 100%;
    margin-inline: auto;
  }
  .nb-mcq-column .question-card.is-answered {
    width: 100%;
    /* the response takes a good share of the sheet, so its explanations
       read in long lines (owner, 2026-10-05: "make the correct or wrong
       wider so more content can be filled in it") */
    grid-template-columns: var(--mcq-num-w) minmax(0, 1fr) clamp(340px, 36%, 440px);
    grid-template-rows: auto auto 1fr;
    animation: mcq-sheet-reveal var(--nb-dur-3) var(--nb-ease) backwards;
  }
  .question-card.is-answered > .mcq-reasoning {
    grid-column: 3;
    grid-row: 1 / -1;
    align-self: start;
    /* its top a little over the question's first line (the mock-up) */
    margin-top: calc(-1 * var(--nb-s4));
    /* it is laid out at its full height at once: the reveal is the sheet's
       unmasking plus the fade and slide of section 7 */
    max-width: none;
    max-height: none;
    overflow: visible;
  }
}
/* ⚑ UNMASKS FROM THE CENTRE, both edges at once, because the card grows both
   ways. inset() percentages resolve against the card's own border box, so
   calc((100% - var(--nb-mcq-sheet-width)) / 2) is exactly half the growth on each side. */
@keyframes mcq-sheet-reveal {
  from {
    clip-path: inset(0 calc((100% - var(--nb-mcq-sheet-width)) / 2) 0 calc((100% - var(--nb-mcq-sheet-width)) / 2));
  }
  to { clip-path: inset(0 0 0 0); }
}

/* ---------- 12 · Maths in a question ---------------------------
   ⚑ DISPLAY MATHS NEVER SCROLLS IN THE ANSWER CARD, at the desk either
   (owner, 2026-10-05, of a scroll bar under "N = 0.1001 × 6.022 × 10²³ ..."
   in the card: "there is scrollbar fix it"). The card is ~440px and a worked
   line with substituted values is wider, so the row wraps between KaTeX's own
   boxes (each relation and operand stays whole) and lines break where the
   maths allows, as the phone's fallback below does. */
.mcq-reasoning .katex-display {
  overflow: visible;
  padding-bottom: 0;
}
.mcq-reasoning .katex-display > .katex {
  white-space: normal;
  text-wrap: balance;
}
/* ⚑ ON A PHONE NOTHING IN A QUESTION SCROLLS SIDEWAYS (The No-Sideways
   Rule, DESIGN.md; owner, 2026-09-27). Below 861px note-math-fit.js sets an
   equation that does not fit on lines, each relation opening its line under
   the first one, and shrinks it only for a piece that cannot break, so the
   box has nothing to scroll. Without the script the row still wraps between
   KaTeX's own boxes. A word, a URL or a code run longer than its line breaks
   inside itself; KaTeX never does. */
@media (max-width: 860px) {
  :is(.mcq-question, .mcq-opt-text, .mcq-reasoning) .katex-display .nb-math-line {
    display: block;
    white-space: nowrap;
  }
  :is(.mcq-question, .mcq-opt-text, .mcq-reasoning) .katex-display .nb-math-line + .nb-math-line {
    margin-top: var(--nb-s2);
  }
  :is(.mcq-question, .mcq-opt-text, .mcq-reasoning) .katex-display[data-math-align] > .katex > .katex-html {
    display: inline-block;
    text-align: left;
  }
  .mcq-reasoning .katex-display {
    overflow: visible;
    padding-bottom: 0;
  }
  .mcq-reasoning .katex-display > .katex {
    white-space: normal;
    text-wrap: balance;
  }
  .mcq-opt-text {
    min-width: 0;
  }
  :is(.mcq-question, .mcq-opt-text, .mcq-reasoning) {
    overflow-wrap: break-word;
  }
  :is(.mcq-question, .mcq-opt-text, .mcq-reasoning) .katex {
    overflow-wrap: normal;
  }
  :is(.mcq-question, .mcq-opt-text, .mcq-reasoning) pre {
    white-space: pre-wrap;
    overflow-wrap: anywhere;
  }
  :is(.mcq-question, .mcq-opt-text, .mcq-reasoning) code {
    overflow-wrap: anywhere;
  }
}

/* ---------- 13 · The Retry dialog ------------------------------
   The one dialog (pages/css/nb-dialog.css; owner, 2026-10-23: "standardize
   this new design for all popups"): its veil, sheet, headline, tick and
   buttons are every pop-up's. Only its own two states stay here. */
.nb-mcq-retry-error {
  margin: var(--nb-s4) 0 0;
  font: var(--nb-type-ui);
  font-size: var(--nb-text-sm);
  font-weight: 500;
  color: var(--nb-error);
}
/* saving: the primary keeps its colour and its width (mcq.js holds the
   width) and says what it is doing */
.nb-mcq-retry-acts [data-mcq-retry-go][data-ui-busy="true"] {
  cursor: progress;
}

/* ---------- 14 · The tutor's quiz ------------------------------
   The quiz draws the same questions without a rail. The way back (owner, 2026-10-05): the breadcrumb over the
   title names the page it came from; this button, centred under the last
   question, takes the student there when they have finished. */
.nb-quiz .mcq-list {
  border-top: 1px solid var(--nb-border);
}
.nb-quiz-back-row { display: flex; justify-content: center; margin: var(--nb-s8) 0 0; }
.nb-quiz-back { gap: var(--nb-s2); }

@media (min-width: 601px) and (max-width: 640px) {
  .nb-mcq-head .nb-notes-title {
    font-size: var(--nb-text-2xl);
  }
  .nb-mcq-modetabs .questions-mode-tab {
    padding: var(--nb-s4) var(--nb-s2) var(--nb-s5);
    font-size: var(--nb-text-md);
  }
}

@media (max-width: 600px) {
  .nb-mcq-modetabs .questions-mode-tab {
    min-height: 44px;
    padding: var(--nb-s3) var(--nb-s1) var(--nb-s4);
    font-size: var(--nb-text-base);
    line-height: 1.2;
  }
}
