/* Study Mode — quiz-specific layout only. Builds on css/styles.css's design
   tokens and shared components (.site-header, .mode-switcher, .status-banner,
   .board/.cell, .share-btn); doesn't redefine any :root variable. */

.round-setup {
  margin: var(--space-5) 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

/* The row itself is the button. */
.round-setup-summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  flex-wrap: wrap;
  width: 100%;
  font: inherit;
  text-align: left;
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface);
  cursor: pointer;
  transition: background-color 120ms ease, border-color 120ms ease;
}

.round-setup-summary:hover { background: var(--bg); border-color: var(--muted); }
.round-setup-summary:hover .round-setup-pill { background: var(--surface); }

.round-setup-summary:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.round-setup-text {
  margin: 0;
  font-size: var(--fs-base);
  color: var(--text);
}

/* Same pill geometry as .mode-btn / .weak-spots-btn — the selects in the
   panel are the only OS chrome left on the page. Decoration now: the row
   around it takes the clicks, so this is only the affordance saying so. */
.round-setup-pill {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  flex: none;
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--muted);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  padding: var(--space-2) var(--space-4);
  transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease;
}

.round-setup-chevron {
  width: 1em;
  height: 1em;
  transition: transform 120ms ease;
}

.round-setup-summary[aria-expanded="true"] .round-setup-pill {
  color: #fff;
  background: var(--accent);
  border-color: var(--accent);
}

.round-setup-summary[aria-expanded="true"] .round-setup-chevron {
  transform: rotate(180deg);
}

/* aria-disabled rather than the disabled attribute: the row now *contains*
   the blocked warning, and :disabled's opacity would drag that text under
   the contrast floor while also dropping it out of the tab order. Only the
   pill dims; the sentence stays fully legible and still focusable. */
.round-setup-summary[aria-disabled="true"] { cursor: default; }
.round-setup-summary[aria-disabled="true"]:hover { background: var(--surface); border-color: var(--loss); }
.round-setup-summary[aria-disabled="true"] .round-setup-pill { opacity: 0.5; }

.round-setup-panel {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: var(--space-6);
  padding: var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--bg);
}

.pool-filter {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  font-size: var(--fs-xs);
  color: var(--muted);
  align-self: flex-start;
}

/* Its own full-width row under the two filters: a standing preference rather
   than a per-round choice, and the hint needs the space. */
.pool-filter--wide {
  flex-basis: 100%;
  border-top: 1px solid var(--border);
  padding-top: var(--space-4);
}

/* The row is full-width for the chips and hint; the select itself shouldn't
   stretch to match, or it reads as the panel's primary control. */
.pool-filter--wide select {
  align-self: flex-start;
  min-width: 12rem;
  max-width: 20rem;
}

.set-aside-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: var(--space-3);
}

/* Neutral, not --loss: a set-aside maker is switched off, not wrong. */
.set-aside-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font: inherit;
  font-size: var(--fs-xs);
  color: var(--text);
  background: var(--no-match-bg);
  border: 1px solid transparent;
  border-radius: var(--radius-pill);
  padding: var(--space-2) var(--space-3);
  cursor: pointer;
  transition: border-color 120ms ease, background-color 120ms ease;
}

.set-aside-chip:hover { border-color: var(--border); background: var(--surface); }
.set-aside-chip:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.set-aside-chip-x { display: inline-flex; width: 0.85rem; height: 0.85rem; color: var(--muted); }
.set-aside-chip-x svg { width: 100%; height: 100%; }
.set-aside-chip:hover .set-aside-chip-x { color: var(--text); }

.set-aside-hint {
  margin: var(--space-3) 0 0;
  max-width: 46ch;
  font-size: var(--fs-xs);
  color: var(--muted);
  line-height: 1.5;
}

.round-length-pills {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: 0.15rem;
}

.round-length-pill {
  font: inherit;
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--muted);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  padding: var(--space-2) var(--space-4);
  cursor: pointer;
  transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease;
}

.round-length-pill:hover { background: var(--bg); }

.round-length-pill[aria-checked="true"] {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

.round-length-pill:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* No select styling exists elsewhere in the app (no <select> until this
   feature) — matches .icon-btn's border/radius treatment for consistency. */
.pool-filter select {
  font: inherit;
  font-size: var(--fs-base);
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: var(--space-2) var(--space-3);
  cursor: pointer;
}

.pool-filter select:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* A filter that matches nothing — or too few mics for the active mode —
   locks out every category/dimension at once, so the summary line turns
   into an unmissable warning — and the bar force-expands
   and refuses to collapse, since a blocking state must never be hidden
   behind a collapsed control. */
.round-setup--blocked .round-setup-summary {
  color: var(--loss);
  background: var(--loss-bg);
  border-color: var(--loss);
}

.round-setup--blocked .round-setup-text {
  font-weight: 600;
  color: var(--loss);
}

/* Replaces the whole category/dimension list (not just a per-item note)
   when the filter matches nothing, or matches too few mics to build a round
   — same reasoning as above. */
.pool-blocked-notice {
  padding: var(--space-5);
  border: 1px solid var(--loss);
  border-radius: var(--radius-lg);
  background: var(--loss-bg);
  color: var(--loss);
  font-weight: 600;
  text-align: center;
}

.quiz-picker {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
  margin-top: var(--space-5);
}

.category-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--space-3);
}

/* No justify-content: space-between — in a 200px-min grid cell it stranded
   the checkbox hard-left and its own label hard-right with a gap between
   them, which read as two unrelated things. Shared by the Quiz, Order and
   Match pickers, so all three get the fix. */
.category-pill {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  cursor: pointer;
  transition: border-color 120ms ease, background-color 120ms ease;
}

.category-pill:has(input:checked) {
  border-color: var(--accent);
  background: var(--hint-bg);
}

/* Custom-styled rather than left as a native checkbox — nothing else in the
   app uses OS-default form-control chrome, so a bare native checkbox was the
   one element that didn't look like it belonged. The checkmark glyph matches
   the app's own check icon (js/app.js's ICONS.check / the legend's match
   swatch in index.html), so a checked category reads as the same "match"
   affordance used everywhere else. */
.category-pill input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  flex: none;
  width: 1.25rem;
  height: 1.25rem;
  margin: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background-color: var(--surface);
  background-repeat: no-repeat;
  background-position: center;
  background-size: 70%;
  cursor: pointer;
  transition: background-color 120ms ease, border-color 120ms ease;
}

.category-pill input[type="checkbox"]:checked {
  background-color: var(--accent);
  border-color: var(--accent);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");
}

.category-pill input[type="checkbox"]:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Radio variant — same custom-styled treatment as the checkbox above (the
   Order/Match dimension pickers are single-select, so radio is the correct
   semantic input), but a filled dot rather than a checkmark so it still
   reads as visually distinct from a checkbox at a glance. */
.category-pill input[type="radio"] {
  appearance: none;
  -webkit-appearance: none;
  flex: none;
  width: 1.25rem;
  height: 1.25rem;
  margin: 0;
  border: 1px solid var(--border);
  border-radius: 50%;
  background-color: var(--surface);
  cursor: pointer;
  position: relative;
  transition: border-color 120ms ease;
}

.category-pill input[type="radio"]:checked {
  border-color: var(--accent);
}

.category-pill input[type="radio"]:checked::after {
  content: "";
  position: absolute;
  inset: 3px;
  border-radius: 50%;
  background: var(--accent);
}

.category-pill input[type="radio"]:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.category-pill-label {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  /* min-width:0 so a long category name wraps inside the pill instead of
     forcing the grid cell wider than its track. */
  min-width: 0;
  flex: 1;
}

.category-pill-name { font-weight: 600; font-size: var(--fs-base); }
.category-pill-accuracy { font-size: var(--fs-xs); color: var(--muted); }

/* Accuracy as a bar, so six categories can be compared at a glance rather
   than by reading six percentages. Quiz-only for now (Order/Match report
   "3 / 5 rounds correct", not a percentage), hence the separate element
   rather than restyling .category-pill-accuracy itself. */
.category-pill-bar {
  height: 3px;
  border-radius: 999px;
  background: var(--no-match-bg);
  overflow: hidden;
  margin: var(--space-2) 0 var(--space-1);
}

.category-pill-bar-fill {
  height: 100%;
  border-radius: 999px;
  background: var(--accent);
}

.quiz-picker-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--space-4);
}

.weak-spots-btn {
  font: inherit;
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  padding: var(--space-2) var(--space-4);
  cursor: pointer;
  transition: background-color 120ms ease, border-color 120ms ease;
}

.weak-spots-btn:hover { background: var(--bg); }

.weak-spots-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.weak-spots-btn:disabled:hover { background: var(--surface); }
.weak-spots-btn:disabled { opacity: 0.5; cursor: default; }

.weak-spots-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.quiz-active {
  margin-top: var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.quiz-status {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  flex-wrap: wrap;
}

.quiz-progress {
  font-size: var(--fs-sm);
  color: var(--muted);
  margin: 0;
}

.quiz-chips {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.quiz-chip {
  font-size: var(--fs-xs);
  font-weight: 600;
  border-radius: var(--radius-pill);
  padding: var(--space-1) var(--space-3);
  white-space: nowrap;
}

.quiz-chip--score { color: var(--match); background: var(--match-bg); }
.quiz-chip--streak { color: var(--partial); background: var(--partial-bg); }

.quiz-progress-track {
  height: 4px;
  border-radius: 999px;
  background: var(--no-match-bg);
  overflow: hidden;
}

/* Width is set by JS from session.length — a retry round is 1–9 questions
   and the count is user-selectable, so it can't be a fixed segment count. */
.quiz-progress-fill {
  height: 100%;
  width: 0;
  border-radius: 999px;
  background: var(--accent);
  transition: width 160ms ease;
}

.quiz-question {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.quiz-prompt {
  font-size: var(--fs-lg);
  font-weight: 600;
  margin: 0;
}

/* Full-width rows, not a grid. The longest real option — the AKG C414's six
   switchable polar patterns — is 86 characters and wraps to seven or eight
   lines in a two-column grid at phone width. min-height is set by JS on each
   render so the inline explanation can expand without moving the Next
   button below it. */
.quiz-options {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.quiz-option {
  display: flex;
  flex-direction: column;
  padding: 0;
  font-size: var(--fs-base);
  font-family: inherit;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface);
  color: var(--text);
  cursor: pointer;
  text-align: left;
  overflow: hidden;
  transition: border-color 120ms ease, background-color 120ms ease;
}

.quiz-option:hover:not(:disabled) { background: var(--bg); }
.quiz-option:disabled { cursor: default; }

.quiz-option-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-4);
}

.quiz-option-badge {
  flex: none;
  font-size: var(--fs-2xs);
  font-weight: 600;
  color: var(--muted);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0 var(--space-2);
  line-height: 1.4;
}

.quiz-option-label { flex: 1; min-width: 0; }

.quiz-option-icon {
  flex: none;
  display: inline-flex;
}

.quiz-option-icon svg { width: 1rem; height: 1rem; }

/* Label stays --text rather than the state colour: --match on --match-bg is
   only 3.5:1, under the 4.5:1 floor. The tint, border and glyph carry the
   state instead — and the glyph matters on its own, since colour alone is
   indistinguishable for red-green colour blindness. */
.quiz-option--correct {
  background: var(--match-bg);
  border-color: var(--match);
}

.quiz-option--correct .quiz-option-icon,
.quiz-option--correct .quiz-option-badge { color: var(--match); border-color: var(--match); }

.quiz-option--incorrect {
  background: var(--loss-bg);
  border-color: var(--loss);
}

.quiz-option--incorrect .quiz-option-icon,
.quiz-option--incorrect .quiz-option-badge { color: var(--loss); border-color: var(--loss); }

.quiz-option-explain {
  font-size: var(--fs-sm);
  line-height: 1.45;
  padding: var(--space-3) var(--space-4);
  border-top: 1px solid var(--loss);
  color: var(--text);
}

.quiz-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  flex-wrap: wrap;
}

.quiz-action-note {
  font-size: var(--fs-xs);
  color: var(--muted);
}

.quiz-actions .share-btn--page { margin: 0; }

.quiz-summary {
  margin-top: var(--space-5);
}

.quiz-summary h2 { margin: 0 0 var(--space-2); }

.quiz-summary-trend {
  font-size: var(--fs-sm);
  color: var(--muted);
  margin: 0;
}

.quiz-summary-breakdown {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  margin: var(--space-5) 0;
}

.quiz-summary-row {
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface);
  font-size: var(--fs-sm);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.quiz-summary-row-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
}

.quiz-summary-row-head strong { font-size: var(--fs-base); }
.quiz-summary-row-score { color: var(--muted); white-space: nowrap; }

.quiz-summary-bar {
  height: 6px;
  border-radius: 999px;
  background: var(--no-match-bg);
  overflow: hidden;
}

.quiz-summary-bar-fill {
  height: 100%;
  border-radius: 999px;
  background: var(--match);
}

/* The round's actual study payload: which mics you got wrong, and what the
   answer was. Built from the questions already held in memory. */
.quiz-missed {
  margin: 0 0 var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.quiz-missed-title {
  margin: 0;
  font-size: var(--fs-base);
}

.quiz-missed-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.quiz-missed-item {
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface);
  padding: var(--space-3) var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.quiz-missed-mic { font-weight: 600; font-size: var(--fs-base); }
.quiz-missed-q { font-size: var(--fs-xs); color: var(--muted); }

.quiz-missed-answers {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
  font-size: var(--fs-sm);
  margin-top: var(--space-1);
}

.quiz-missed-yours { color: var(--loss); }
.quiz-missed-right { color: var(--match); }
.quiz-missed-answers span strong { font-weight: 600; }

/* margin-top rather than padding so it collapses against a preceding block's
   own bottom margin — the quiz's "Mics you missed" already ends with one, so
   this only adds room where there wasn't any (Match's ledger, Order's list). */
.quiz-summary-actions {
  display: flex;
  gap: var(--space-3);
  flex-wrap: wrap;
  margin-top: var(--space-7);
}

/* Fill the row rather than shrink-wrapping the label, so the action row
   lines up with the ledger/list above it. Two buttons split it evenly; with
   flex-wrap they each go full width if the labels stop fitting. */
.quiz-summary-actions .share-btn--page {
  margin: 0;
  flex: 1 1 0;
  min-width: 8rem;
}

.quiz-summary-actions .share-btn--secondary {
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border);
}

.quiz-summary-actions .share-btn--secondary:hover { background: var(--bg); }

#reference-detail-empty {
  color: var(--muted);
  font-size: var(--fs-base);
}

/* ------------------------------------------------------------- World map */

.mic-map {
  margin: var(--space-5) 0;
}

/* The SVG sizes itself from its viewBox aspect ratio, with no JS measurement
   anywhere — which matters because [hidden] is display:none !important, so
   anything that measured itself before the Reference tab was first shown
   would silently read zero. */
.mic-map-figure {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--space-3);
}

.mic-map-svg {
  display: block;
  width: 100%;
  height: auto;
}

/* Countries with no mics are inert scenery: no pointer events, no hover, no
   click. Only the eight that have mics get data-country and the --has-mics
   class from buildWorldMapSvg(). */
.mic-map-country {
  fill: var(--no-match-bg);
  stroke: var(--bg);
  stroke-width: 1;
  pointer-events: none;
}

/* Selected vs merely-selectable is expressed with fill-opacity, not two
   different colour tokens: --hint (#8fb0f0) and --accent (#7fa0e0) are almost
   the same blue in dark mode, so a token swap left the active country
   invisible. Opacity differentiates reliably in both schemes. */
.mic-map-country--has-mics {
  fill: var(--accent);
  fill-opacity: 0.4;
  pointer-events: auto;
  cursor: pointer;
  transition: fill-opacity 120ms ease;
}

.mic-map-country--has-mics:hover { fill-opacity: 0.7; }

.mic-map-country--active {
  fill-opacity: 1;
  stroke: var(--text);
  stroke-width: 2;
}

/* The real control. Denmark is roughly 5x3 CSS px on a phone and Austria 8x3,
   so the map alone can't be the way you pick a country — these chips are
   keyboard-navigable, screen-reader-legible and comfortably tappable at every
   width, and they carry the per-country counts the map can't show. */
.country-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: var(--space-3);
}

.country-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 2.75rem;
  padding: var(--space-2) var(--space-4);
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  cursor: pointer;
  transition: background-color 120ms ease, border-color 120ms ease;
}

.country-chip:hover { background: var(--bg); }

.country-chip[aria-pressed="true"] {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

.country-chip-count {
  font-size: var(--fs-2xs);
  color: var(--muted);
}

.country-chip[aria-pressed="true"] .country-chip-count { color: #fff; }

/* --------------------------------------------------------- Sorting + table */

/* Pills are the only sort control that survives card mode: below 800px
   .board-row--header is display:none, so the clickable column headers
   genuinely don't exist there. Both controls drive the same state. */
.mic-sort {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
  margin-bottom: var(--space-3);
}

.mic-sort-label {
  font-size: var(--fs-2xs);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  font-weight: 600;
  color: var(--muted);
}

.mic-sort-pills {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.mic-sort-pill {
  min-height: 2.25rem;
  padding: var(--space-1) var(--space-3);
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--muted);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  cursor: pointer;
  transition: background-color 120ms ease, color 120ms ease;
}

.mic-sort-pill:hover { background: var(--bg); }

.mic-sort-pill--active {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

/* Column headers become buttons so they're keyboard-operable. Styled to still
   read as a table header rather than a control. */
.board--reference .mic-sort-header {
  font: inherit;
  color: inherit;
  text-transform: inherit;
  letter-spacing: inherit;
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
}

.board--reference .mic-sort-header:hover { color: var(--accent); }

/* A manufacturer band between groups. Deliberately not a .board-row variant:
   in card mode .board-row gains padding/border/background and
   .board-row--header is hidden outright, both wrong for a heading. */
.mic-group {
  margin-top: var(--space-3);
  padding: var(--space-2) var(--space-3);
  font-size: var(--fs-2xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
  background: var(--bg);
  border-radius: var(--radius-sm);
}

.mic-group:first-child { margin-top: 0; }

/* styles.css clamps .cell-text to 2 lines so the game board's tiles stay
   height-matched. That's wrong here: this is a reference table, and at
   desktop widths the clamp truncates "Condenser (Large-Diaphragm)" in 70 of
   118 rows and the longer polar-pattern lists on top of that. Rows growing
   unevenly is a much smaller cost than hiding the values the page exists to
   show. --tile-h stays a floor, so short rows keep their shape. */
.board--reference .cell-text {
  display: block;
  -webkit-line-clamp: none;
  line-clamp: none;
  overflow: visible;
}

/* --------------------------------------------------- Reference tile rows

   The daily board's look, compacted. Each value keeps its own bordered tile
   on --surface, in the same 7 aligned columns, so a mic reads here the way it
   reads when you're guessing it.

   The one thing that doesn't carry over is --tile-h. That 4.25rem floor
   exists so the game's guess rows stay height-matched to each other, which is
   what makes a board of them look like a board. Nothing here is matched
   against anything, so a one-line value gets one line: 74px per mic becomes
   ~35px, and a screen shows about 25 mics instead of 12.

   Tiles are left-aligned rather than centred, the other departure. Centring
   is right on the board, where every cell is a short scored result; here the
   Polar Pattern column carries things like the C414's six-pattern list, and
   centred ragged text is materially harder to scan down a column of 118. */
.board--reference {
  gap: 0.25rem;
}

/* Wider than the quiz screens: the extra 260px all goes to the columns, which
   is the difference between the long pattern lists sitting on one line and
   wrapping to two. :has() keys it to the tab actually being visible, so Quiz,
   Order and Match keep the shared 920px without any JS toggling a class. */
main:has(#reference-tab:not([hidden])) {
  max-width: 1180px;
}

/* Re-weighted from the game board's ratios. The name column is widest here
   because it carries the full "Audio-Technica ATM87R" rather than a guess,
   Origin and Manufacturer are single words, and Year and Price are narrow
   fixed-width numbers. Polar Pattern keeps the lion's share — the C414's
   six-pattern list is still the longest value in the pool. */
.board--reference > .board-row {
  grid-template-columns: 1.7fr 0.85fr 1.2fr 2.1fr 1.15fr 0.6fr 0.8fr;
  gap: var(--space-2);
  padding: 0;
}

/* Same tile as the game, minus the floor. min-height is one line of text plus
   its padding, so short values sit on one line and the pattern lists grow the
   row only when they actually need to. */
.board--reference > .board-row > .cell {
  min-height: 1.95rem;
  padding: 0.25rem var(--space-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  align-items: flex-start;
  justify-content: center;
  text-align: left;
  font-size: var(--fs-xs);
  line-height: 1.3;
}

/* The name is the row's subject; everything else is an attribute of it. */
.board--reference > .board-row > .cell--guess {
  font-weight: 600;
}

/* Numbers align on their right edge and share a digit width, so prices and
   years compare by length down the column — worth keeping even though the
   other tiles are left-aligned, since these two are the only columns you read
   as quantities rather than labels. */
.board--reference > .board-row > .cell[data-label="Year"],
.board--reference > .board-row > .cell[data-label="Price"] {
  text-align: right;
  align-items: flex-end;
  font-variant-numeric: tabular-nums;
}

/* The header is a set of column labels, not a row of tiles — it has to shed
   the chrome the rule above just gave every .cell. styles.css already resets
   .board-row--header > .cell, but that selector ties this one on specificity
   and loses on order, so it gets restated here rather than left to chance. */
.board--reference > .board-row--header > .cell {
  min-height: 0;
  padding: var(--space-2) var(--space-2) var(--space-1);
  border: none;
  background: transparent;
  align-items: flex-start;
}

.board--reference > .board-row--header {
  border-bottom: 1px solid var(--border);
  margin-bottom: 0.25rem;
}

/* buildHeaderCell puts the same data-label on the header cells, so the
   right-alignment rule above lands on the Year and Price headings too. The
   button has to opt in separately — it's a block inside the cell with its own
   text-align. */
.board--reference > .board-row--header .mic-sort-header {
  text-align: inherit;
  width: 100%;
}

/* -------------------------------------------------- Reference on a phone

   Seven columns don't survive a 390px viewport, and card mode (css/styles.css,
   @media max-width 800px) is the wrong fallback here: it gives every value a
   labelled chip with a 3.1rem floor, which ran the tab to 27,811px. Instead
   the row keeps its line-per-mic shape and simply wraps — the name on its own
   line, the six values flowing after it as one muted run separated by
   middots. The labels go with the columns, which is survivable because every
   value says what it is: a year, a price, a country, a pattern. */
@media (max-width: 800px) {
  .board--reference > .board-row {
    display: flex;
    flex-wrap: wrap;
    gap: 0 var(--space-2);
    padding: var(--space-2) var(--space-2) var(--space-3);
    border: none;
    border-bottom: 1px solid var(--border);
    border-radius: 0;
    background: transparent;
  }

  /* .board-row--header is already display:none in card mode, but the flex rule
     above ties it on specificity and wins on order, which switched the seven
     column names back on as a meaningless wrapped block above the list. The
     extra class pins it shut regardless of order. */
  .board--reference > .board-row.board-row--header {
    display: none;
  }

  /* Tiles are a desktop-column device: at 390px each one would be a bordered
     box on its own line and the tab would run past 25,000px. Here the values
     go back to flowing as text, so every cell sheds the border, the fill and
     the floor the tile rule gives it. */
  .board--reference > .board-row > .cell {
    min-height: 0;
    border: none;
    background: transparent;
    border-radius: 0;
  }

  .board--reference > .board-row > .cell--guess {
    flex: 0 0 100%;
    font-size: var(--fs-base);
    padding: 0 0 0.1rem;
  }

  .board--reference > .board-row > .cell:not(.cell--guess) {
    display: block;
    padding: 0;
    font-size: var(--fs-xs);
    color: var(--muted);
  }

  /* Card mode hangs the category name off each chip. Back out both that and
     the 3-line clamp it pairs with. */
  .board--reference > .board-row > .cell:not(.cell--guess)::before {
    content: none;
  }

  /* Inline, not block: the middot below is an ::after on the cell, and after a
     block-level .cell-text it would drop onto its own line inside the cell
     instead of following the value. */
  .board--reference > .board-row > .cell:not(.cell--guess) > .cell-text {
    display: inline;
    -webkit-line-clamp: none;
    line-clamp: none;
  }

  .board--reference > .board-row > .cell:not(.cell--guess):not(:last-child)::after {
    content: "·";
    margin-left: var(--space-2);
    opacity: 0.5;
  }

  /* Right-alignment is a column property; inline in a wrapped run it would
     just push the price away from the value before it. */
  .board--reference > .board-row > .cell[data-label="Year"],
  .board--reference > .board-row > .cell[data-label="Price"] {
    text-align: left;
    align-items: stretch;
  }
}

/* ------------------------------------------------------- Reference filters

   A row of disclosure buttons, each opening a checklist below the whole bar.
   Panels are plain blocks in normal flow rather than popovers anchored to
   their own button: nothing to position, nothing to collide, and no ancestor
   can clip them — the trap .board documents in css/styles.css, where an
   overflow on one axis silently makes the element a scrollport on both.

   Visual language is borrowed wholesale from the controls either side of it
   (.country-chip below the map, .mic-sort-pill under it) so the tab reads as
   one set of controls rather than three. */
.mic-filters {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
  margin-bottom: var(--space-3);
}

.mic-filters-label {
  font-size: var(--fs-2xs);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  font-weight: 600;
  color: var(--muted);
}

.mic-filter-menus {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.facet-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 2.25rem;
  padding: var(--space-1) var(--space-3);
  font: inherit;
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--muted);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  cursor: pointer;
  transition: background-color 120ms ease, color 120ms ease, border-color 120ms ease;
}

.facet-btn:hover { background: var(--bg); }

/* Open and active are different states and can occur apart: a panel can be
   open with nothing checked, and a facet stays filtered once closed. */
.facet-btn[aria-expanded="true"] {
  border-color: var(--accent);
  color: var(--text);
}

.facet-btn--active {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

.facet-btn-badge {
  font-size: var(--fs-2xs);
  font-weight: 600;
  padding: 0 var(--space-2);
  border-radius: var(--radius-pill);
  background: var(--bg);
  color: var(--muted);
}

.facet-btn--active .facet-btn-badge {
  background: rgba(255, 255, 255, 0.22);
  color: #fff;
}

.mic-filter-panels:empty { display: none; }

.facet-panel {
  margin-bottom: var(--space-3);
  padding: var(--space-4);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
}

/* Manufacturer carries 34 options. Two columns keeps it from running a
   third of a screen tall, and the cap turns the long tail into a scroll
   rather than pushing the table off the page. */
.facet-options {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: var(--space-1) var(--space-4);
  max-height: 45vh;
  overflow-y: auto;
}

.facet-option {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 2.25rem;
  padding: 0 var(--space-2);
  font-size: var(--fs-sm);
  border-radius: var(--radius-sm);
  cursor: pointer;
}

.facet-option:hover { background: var(--bg); }

/* Drawn from the site's tokens rather than left to the UA.
   accent-color alone only tints the CHECKED fill — an unchecked box keeps the
   platform's own light-mode square, which stayed white-on-dark here however
   the page declared its color-scheme. appearance:none plus a ::before glyph
   is the only way to get both states right in every engine. The element stays
   a real <input>, so the label association, keyboard behaviour and
   screen-reader semantics are all untouched; only the painting changes. */
.facet-option input[type="checkbox"],
.facet-option input[type="radio"] {
  appearance: none;
  -webkit-appearance: none;
  flex: none;
  width: 1rem;
  height: 1rem;
  margin: 0;
  display: grid;
  place-content: center;
  background: var(--bg);
  border: 1px solid var(--border);
  cursor: pointer;
  transition: background-color 120ms ease, border-color 120ms ease;
}

.facet-option input[type="checkbox"] { border-radius: var(--radius-sm); }
.facet-option input[type="radio"] { border-radius: 50%; }

.facet-option input[type="checkbox"]:hover,
.facet-option input[type="radio"]:hover { border-color: var(--accent); }

.facet-option input:checked {
  background: var(--accent);
  border-color: var(--accent);
}

/* The glyph is --surface, not #fff. White on the dark theme's lighter accent
   (#7fa0e0) is about 2:1 and barely legible; --surface tracks the theme and
   lands near 6.5:1 in both — white on the light accent, near-black on the
   dark one. */
.facet-option input[type="checkbox"]::before {
  content: "";
  width: 0.5rem;
  height: 0.28rem;
  border-left: 2px solid var(--surface);
  border-bottom: 2px solid var(--surface);
  transform: rotate(-45deg) translate(1px, -1px);
  opacity: 0;
}

.facet-option input[type="checkbox"]:checked::before { opacity: 1; }

.facet-option input[type="radio"]::before {
  content: "";
  width: 0.4rem;
  height: 0.4rem;
  border-radius: 50%;
  background: var(--surface);
  opacity: 0;
}

.facet-option input[type="radio"]:checked::before { opacity: 1; }

/* appearance:none takes the native focus ring with it. */
.facet-option input:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.facet-option-name {
  flex: 1;
  min-width: 0;
}

.facet-option-count {
  font-size: var(--fs-2xs);
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

/* Dimmed, not hidden. An option that drops to zero under the other facets
   still says something — and removing it would make the list jump under the
   pointer mid-decision, and could pull the element out from under focus. */
.facet-option--empty { opacity: 0.45; }

.facet-option input:disabled { cursor: not-allowed; }
.facet-option:has(input:disabled) { cursor: not-allowed; }

/* Two <input type=range> stacked in one box. The inputs themselves are
   pointer-transparent and only their thumbs take events, so the lower one
   can't swallow clicks meant for the upper — the usual dual-handle trap —
   and each stays a real range input, keyboard-operable with arrows, Home
   and End for free. */
.facet-range-value {
  display: block;
  margin-bottom: var(--space-3);
  font-size: var(--fs-sm);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--text);
}

.facet-slider {
  position: relative;
  height: 1.75rem;
  margin: 0 0.5rem;
}

.facet-slider-track,
.facet-slider-fill {
  position: absolute;
  top: 50%;
  height: 4px;
  border-radius: var(--radius-pill);
  transform: translateY(-50%);
  pointer-events: none;
}

.facet-slider-track {
  left: 0;
  right: 0;
  background: var(--border);
}

.facet-slider-fill { background: var(--accent); }

.facet-slider-input {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  background: none;
  appearance: none;
  -webkit-appearance: none;
  pointer-events: none;
}

.facet-slider-input::-webkit-slider-thumb {
  appearance: none;
  -webkit-appearance: none;
  width: 1.15rem;
  height: 1.15rem;
  border-radius: 50%;
  background: var(--surface);
  border: 2px solid var(--accent);
  cursor: grab;
  pointer-events: auto;
}

.facet-slider-input::-moz-range-thumb {
  width: 1.15rem;
  height: 1.15rem;
  border-radius: 50%;
  background: var(--surface);
  border: 2px solid var(--accent);
  cursor: grab;
  pointer-events: auto;
}

.facet-slider-input:focus-visible::-webkit-slider-thumb { box-shadow: 0 0 0 3px var(--hint-bg); }
.facet-slider-input:focus-visible::-moz-range-thumb { box-shadow: 0 0 0 3px var(--hint-bg); }

.facet-slider-input::-moz-range-track { background: none; }

.facet-range-reset {
  margin-top: var(--space-3);
  padding: var(--space-1) var(--space-3);
  font: inherit;
  font-size: var(--fs-sm);
  color: var(--muted);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  cursor: pointer;
}

.facet-range-reset:hover { color: var(--text); }

/* Reuses .set-aside-chip for each active filter — the same removable-chip
   idiom the round-setup bar uses, rather than a second one that looks
   almost but not quite like it. */
.mic-active-filters {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-3);
}

.mic-clear-all {
  margin-left: auto;
  padding: var(--space-1) var(--space-2);
  font: inherit;
  font-size: var(--fs-xs);
  color: var(--muted);
  background: none;
  border: none;
  text-decoration: underline;
  cursor: pointer;
}

.mic-clear-all:hover { color: var(--text); }

/* A country the current filters have emptied. It keeps its place so the row
   doesn't reflow as you filter, but stops being a live control. */
.country-chip--empty { opacity: 0.4; }
.country-chip:disabled { cursor: not-allowed; }

.mic-empty {
  margin: var(--space-7) 0;
  text-align: center;
  color: var(--muted);
}

@media (max-width: 800px) {
  .facet-options {
    grid-template-columns: minmax(0, 1fr);
    max-height: 55vh;
  }
}

@media (prefers-reduced-motion: reduce) {
  .mic-map-country--has-mics,
  .country-chip,
  .mic-sort-pill,
  .facet-btn,
  .facet-option input {
    transition: none;
  }
}

/* The map is decoration below the card-mode breakpoint: at 375px Denmark is
   about 5x3 CSS px and Austria 8x3, so it can't be a usable control there.
   It stays visible as orientation — which country lit up when you tapped a
   chip — but the chips do the work. */
@media (max-width: 520px) {
  .mic-map-figure {
    padding: var(--space-2);
  }

  .country-chip {
    flex: 1 1 calc(50% - var(--space-2));
    justify-content: center;
  }
}

.icon-btn--back {
  gap: var(--space-2);
  text-decoration: none;
}

/* ---------------------------------------------------------------- Order mode */

.order-active {
  margin-top: var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.order-instructions {
  font-size: var(--fs-sm);
  color: var(--muted);
  margin: 0;
}

.order-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.order-item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface);
  /* Without this, a touch-drag starts a page scroll instead of firing
     pointermove at the granularity the drag handler needs. */
  touch-action: none;
  /* The whole row is the drag target, so a grab that lands on the mic name
     must not select the text. Done here rather than with preventDefault() in
     pointerdown, which would also suppress the focus the row needs for its
     tabindex="0" keyboard path. */
  -webkit-user-select: none;
  user-select: none;
  cursor: grab;
}

.order-item:active { cursor: grabbing; }

.order-item:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.order-item--dragging {
  position: relative;
  z-index: 1;
  opacity: 0.7;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}

/* Purely the visual cue that the row is draggable — the row itself carries
   the cursor, touch-action and the pointerdown listener. */
.order-item-grip {
  color: var(--muted);
  font-size: var(--fs-lg);
  line-height: 1;
  flex: none;
}

/* The move buttons sit inside the draggable row, so they need their own
   cursor back. */
.order-move-btn { cursor: pointer; }

.order-item-name {
  flex: 1;
  font-weight: 500;
  min-width: 0;
}

.order-item-controls {
  display: flex;
  gap: var(--space-1);
  flex: none;
}

.order-move-btn {
  width: 1.75rem;
  height: 1.75rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text);
  cursor: pointer;
  font-size: var(--fs-sm);
  line-height: 1;
}

.order-move-btn:hover { background: var(--bg); }
.order-move-btn:disabled { opacity: 0.4; cursor: default; }

.order-move-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.order-summary { margin-top: var(--space-5); }
.order-summary h2 { margin: 0 0 var(--space-4); }

.order-summary-label {
  font-size: var(--fs-2xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
  margin: 0 0 var(--space-2);
}

.order-summary-list {
  list-style: none;
  margin: 0 0 var(--space-5);
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.order-summary-item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface);
  font-size: var(--fs-sm);
}

.order-summary-name { flex: 1; min-width: 0; }
.order-summary-value { color: var(--muted); white-space: nowrap; }

.order-summary-icon { flex: none; display: inline-flex; }
.order-summary-icon svg { width: 1rem; height: 1rem; }

/* Tells a misplaced row where it actually belonged, so the correction is
   attached to the row you got wrong. */
.order-summary-badge {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--fs-xs);
  font-weight: 600;
  color: var(--loss);
  background: var(--surface);
  border: 1px solid var(--loss);
  border-radius: var(--radius-pill);
  padding: 0 var(--space-3);
  white-space: nowrap;
}

.order-summary-badge svg { width: 0.85rem; height: 0.85rem; }

/* The answer itself. Ranks come from orderRanks() in js/training.js, so two
   mics of equal value share a number rather than reading as a sequence. */
.order-answer {
  margin: 0 0 var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.order-answer-title { margin: 0; font-size: var(--fs-base); }

.order-answer-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.order-answer-item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  background: var(--surface);
  border: 1px solid var(--border);
  font-size: var(--fs-sm);
}

.order-answer-item > span:nth-child(2) { flex: 1; min-width: 0; }

.order-answer-rank {
  flex: none;
  min-width: 1.25rem;
  font-weight: 600;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.order-answer-value { color: var(--muted); white-space: nowrap; }

.order-summary-item--correct { border-color: var(--match); color: var(--match); }
.order-summary-item--incorrect { border-color: var(--loss); color: var(--loss); }

/* ---------------------------------------------------------------- Match mode */

.match-active {
  margin-top: var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

/* One segment per mic in the round, filled in as you answer. Decoration over
   .match-run-count, which states the same progress in words. */
.match-run-bar {
  display: flex;
  gap: var(--space-2);
}

.match-run-seg {
  flex: 1;
  height: 4px;
  border-radius: 2px;
  background: var(--border);
  transition: background-color 160ms ease;
}

.match-run-seg--correct { background: var(--match); }
.match-run-seg--incorrect { background: var(--loss); }

.match-run-count {
  margin: 0;
  font-size: var(--fs-xs);
  color: var(--muted);
}

.match-target { color: var(--accent); font-weight: 600; }

.match-card-face {
  padding: var(--space-6) var(--space-5);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  text-align: center;
}

.match-mic-name {
  margin: 0 0 var(--space-2);
  font-size: 1.25rem;
  color: var(--text);
}

.match-mic-meta {
  margin: 0;
  font-size: var(--fs-sm);
  color: var(--muted);
}

.match-choices {
  display: flex;
  gap: var(--space-4);
}

/* Deliberately equal weight — "no" is the right answer three times out of
   four in a typical round, so styling it as the secondary option would push
   against the truth of the task. Yes leads, matching the question's phrasing. */
.match-choice {
  flex: 1;
  font: inherit;
  font-size: 1rem;
  font-weight: 600;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--space-4);
  cursor: pointer;
  transition: background-color 120ms ease, border-color 120ms ease;
}

.match-choice:hover:not(:disabled) { background: var(--bg); border-color: var(--accent); }
.match-choice:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Answered: both lock, and the one you pressed stays marked so the verdict
   below reads against your actual answer rather than in the abstract. */
.match-choice:disabled { cursor: default; color: var(--muted); }

.match-choice--chosen {
  border-color: var(--accent);
  background: var(--hint-bg);
  color: var(--text);
}

.match-verdict {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
}

/* Label stays --text and the tint/border/glyph carry the state — same reason
   as .quiz-option--correct: --match on --match-bg is only 3.5:1. */
.match-verdict--correct { border-color: var(--match); background: var(--match-bg); }
.match-verdict--incorrect { border-color: var(--loss); background: var(--loss-bg); }

.match-verdict-icon { flex: none; display: flex; width: 1.25rem; height: 1.25rem; }
.match-verdict-icon svg { width: 100%; height: 100%; }
.match-verdict--correct .match-verdict-icon { color: var(--match); }
.match-verdict--incorrect .match-verdict-icon { color: var(--loss); }

.match-verdict-text {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  font-size: var(--fs-base);
  color: var(--text);
}

.match-verdict-detail { font-size: var(--fs-sm); color: var(--muted); }

.match-summary-tally {
  margin: 0 0 var(--space-4);
  font-size: var(--fs-sm);
  color: var(--muted);
}

/* Rows, not cards: the ledger is read top-to-bottom with mistakes first, so a
   wrapping grid would scramble the one ordering that matters. */
.match-ledger {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-top: var(--space-4);
}

.match-ledger-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
}

.match-ledger-row--correct { border-color: var(--match); background: var(--match-bg); }
.match-ledger-row--incorrect { border-color: var(--loss); background: var(--loss-bg); }

.match-ledger-icon { flex: none; display: flex; width: 1.1rem; height: 1.1rem; }
.match-ledger-icon svg { width: 100%; height: 100%; }
.match-ledger-row--correct .match-ledger-icon { color: var(--match); }
.match-ledger-row--incorrect .match-ledger-icon { color: var(--loss); }

.match-ledger-body { display: flex; flex-direction: column; gap: 0.1rem; min-width: 0; flex: 1; }
.match-ledger-name { font-size: var(--fs-base); color: var(--text); }
.match-ledger-note { font-size: var(--fs-xs); color: var(--muted); }

/* Only on a clean sweep — every other round is a score, not a failure. */
.match-sweep {
  display: inline-flex;
  width: 0.9em;
  height: 0.9em;
  margin-left: var(--space-2);
  vertical-align: -0.05em;
  color: var(--match);
}

.match-sweep svg { width: 100%; height: 100%; }

.match-ledger-value {
  flex: none;
  max-width: 45%;
  text-align: right;
  font-size: var(--fs-xs);
  color: var(--muted);
}

@media (max-width: 480px) {
  /* .quiz-options no longer needs a breakpoint — it's a single column at
     every width now, for the long-option reason noted above its rule. */
  .quiz-actions { flex-direction: column; align-items: stretch; }
  .quiz-actions .share-btn--page { width: 100%; }
}
