/* =====================================================================
   Question rendering
   ---------------------------------------------------------------------
   How a question, its options, its solution and a progress palette look —
   wherever they appear. That is not only the exam: practice, the mistake
   book, previous-year papers, bookmarks, the solutions review and the
   admin question analytics all render the same components.

   These rules lived in test.css, which only the exam layout loads. Every
   one of those other screens therefore drew its options with no styling
   at all — an inline run of text with no box, no letter badge and, worst
   of all, no visible selected state, so a student could not see which
   option they had picked.

   test.css now holds only the exam's own chrome (the bar, the timer, the
   two-column shell, the sidebar) and this file holds everything shared.
   ===================================================================== */

/* ---------------------------------------------------------------------
   Passage and directions
   ------------------------------------------------------------------ */

.exam-passage {
  padding: var(--sp-4) var(--sp-5);
  margin-bottom: var(--sp-5);
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 3px solid var(--brand-400);
  border-radius: var(--r-md);
  font-family: var(--font-serif);
  font-size: var(--fs-md);
  line-height: var(--lh-loose);
  max-height: 40vh;
  overflow-y: auto;
}

.exam-direction {
  padding: var(--sp-3) var(--sp-4);
  margin-bottom: var(--sp-4);
  background: var(--info-bg);
  border: 1px solid var(--info-br);
  border-radius: var(--r-md);
  color: var(--info-fg);
  font-size: var(--fs-sm);
}

/* ---------------------------------------------------------------------
   Options
   ---------------------------------------------------------------------
   The row IS the <label>, and the key and text are spans inside it.

   These rules used to assume `<li class="exam-option"><input>` followed
   by a sibling `<label class="exam-option__label">`. No view has ever
   rendered that: the input is nested inside the label. So the box, border
   and padding landed on the text span alone, the letter badge sat outside
   it as a bare circle on the line above, and every `input:checked + …`
   rule — the entire selected state — matched nothing at all.
   ------------------------------------------------------------------ */

.exam-options { display: grid; gap: var(--sp-2); list-style: none; padding: 0; margin: 0; }

.exam-option {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
  margin: 0;
  padding: var(--sp-3) var(--sp-4);
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: var(--r-md);
  cursor: pointer;
  font-size: var(--fs-md);
  line-height: var(--lh-base);
  transition: border-color var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
.exam-option input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.exam-option:hover { border-color: var(--brand-300); background: var(--surface-2); }
.exam-option__label { flex: 1 1 auto; min-width: 0; }

.exam-option__key {
  flex: 0 0 auto;
  width: 27px; height: 27px;
  display: grid; place-items: center;
  border: 1.5px solid var(--border-strong);
  border-radius: 50%;
  font-size: var(--fs-sm);
  font-weight: 700;
  color: var(--text-muted);
  transition: all var(--t-fast) var(--ease);
}

/* Selected. `.is-selected` is set server-side on resume and toggled by
   exam.js; `:has()` covers every other screen, where the checked radio is
   the only record of the choice and no script maintains a class. */
.exam-option.is-selected,
.exam-option:has(input:checked) {
  border-color: var(--brand-500);
  background: var(--brand-50);
}
:root[data-theme="dark"] .exam-option.is-selected,
:root[data-theme="dark"] .exam-option:has(input:checked) { background: var(--surface-3); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .exam-option.is-selected,
  :root:not([data-theme="light"]) .exam-option:has(input:checked) { background: var(--surface-3); }
}
.exam-option.is-selected .exam-option__key,
.exam-option:has(input:checked) .exam-option__key {
  background: var(--brand-600);
  border-color: var(--brand-600);
  color: #fff;
}
.exam-option:has(input:focus-visible) { outline: 2px solid var(--border-focus); outline-offset: 2px; }

/* A chosen option carries a check at the end of the row as well as the
   filled badge, so the choice is not communicated by colour alone. The
   pseudo-element is a flex item of the row itself, which puts it at the
   trailing edge without any positioning arithmetic. */
.exam-option.is-selected::after,
.exam-option:has(input:checked)::after {
  content: "\2713";
  flex: 0 0 auto;
  align-self: center;
  font-size: var(--fs-md);
  font-weight: 800;
  color: var(--brand-600);
}
/* Once right and wrong are on show, the tag says which is which; a second
   tick beside it would only be noise. */
.exam-option--correct::after,
.exam-option--chosen-wrong::after { content: none; }

/* Answered / reviewed: right and wrong revealed. */
.exam-option--correct { border-color: var(--success); background: var(--success-bg); }
.exam-option--correct .exam-option__key { background: var(--success); border-color: var(--success); color: #fff; }
.exam-option--chosen-wrong { border-color: var(--danger); background: var(--danger-bg); }
.exam-option--chosen-wrong .exam-option__key { background: var(--danger); border-color: var(--danger); color: #fff; }

/* Once the verdict is in, hover must not suggest the choice can change. */
.exam-option--correct:hover,
.exam-option--chosen-wrong:hover,
.exam-option:has(input:disabled):hover { border-color: inherit; background: inherit; }
.exam-option:has(input:disabled) { cursor: default; }

/* An inline chip trailing the option text. It carried margin-left:auto,
   which needs a flex parent — the label is a plain block, so it never
   moved and simply ran on after the text with no separation. */
.exam-option__tag {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-left: var(--sp-2);
  white-space: nowrap;
  font-size: var(--fs-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

/* ---------------------------------------------------------------------
   Progress palette
   ------------------------------------------------------------------ */

.palette {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(40px, 1fr));
  gap: var(--sp-2);
  list-style: none;
  padding: 0;
  margin: 0;
}
.palette__btn {
  aspect-ratio: 1;
  width: 100%;
  display: grid;
  place-items: center;
  border: 1.5px solid var(--border-strong);
  border-radius: var(--r-sm);
  background: var(--surface);
  color: var(--text-muted);
  font: inherit;
  font-size: var(--fs-sm);
  font-weight: 650;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
  position: relative;
  transition: transform var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease);
}
.palette__btn:hover { transform: scale(1.06); }
.palette__btn.is-current { box-shadow: 0 0 0 2px var(--brand-500); z-index: 1; }

/* State is carried by fill AND by a corner glyph, so the palette is
   readable without colour perception. */
.palette__btn[data-state="answered"]        { background: var(--state-answered); border-color: var(--state-answered); color: #fff; }
.palette__btn[data-state="unanswered"]      { background: var(--state-unanswered); border-color: var(--state-unanswered); color: #fff; }
.palette__btn[data-state="marked"]          { background: var(--state-marked); border-color: var(--state-marked); color: #fff; }
.palette__btn[data-state="answered_marked"] { background: var(--state-both); border-color: var(--state-both); color: #fff; }
.palette__btn[data-state="not_visited"]     { background: var(--surface); border-color: var(--state-unvisited); color: var(--text-subtle); }

.palette__btn::after {
  position: absolute;
  top: 1px; right: 3px;
  font-size: 9px;
  font-weight: 800;
  line-height: 1;
}
.palette__btn[data-state="answered"]::after        { content: "\2713"; }  /* check */
.palette__btn[data-state="unanswered"]::after      { content: "\00D7"; }  /* cross */
.palette__btn[data-state="marked"]::after          { content: "\25CF"; }  /* dot   */
.palette__btn[data-state="answered_marked"]::after { content: "\2713\00B7"; }

/* Practice states. A test palette cannot say whether an answer was right —
   nobody knows until submission — so practice needs its own vocabulary
   rather than borrowing "answered" and meaning something else by it. */
.palette__btn[data-state="correct"]  { background: var(--state-answered);   border-color: var(--state-answered);   color: #fff; }
.palette__btn[data-state="wrong"]    { background: var(--state-unanswered); border-color: var(--state-unanswered); color: #fff; }
.palette__btn[data-state="revealed"] { background: var(--state-marked);     border-color: var(--state-marked);     color: #fff; }

.palette__btn[data-state="correct"]::after  { content: "\2713"; }  /* check   */
.palette__btn[data-state="wrong"]::after    { content: "\00D7"; }  /* cross   */
.palette__btn[data-state="revealed"]::after { content: "\003F"; }  /* question */

.palette-legend { display: grid; gap: 7px; font-size: var(--fs-xs); }
.palette-legend__row { display: flex; align-items: center; gap: var(--sp-2); color: var(--text-muted); }
.palette-legend__swatch {
  width: 17px; height: 17px;
  border-radius: var(--r-xs);
  border: 1.5px solid var(--border-strong);
  display: grid; place-items: center;
  font-size: 9px; font-weight: 800; color: #fff;
  flex: 0 0 auto;
}
/* The legend takes the same data-state as the buttons it explains, so the
   two can never drift apart. */
.palette-legend__swatch[data-state="answered"],
.palette-legend__swatch[data-state="correct"]     { background: var(--state-answered);   border-color: var(--state-answered); }
.palette-legend__swatch[data-state="unanswered"],
.palette-legend__swatch[data-state="wrong"]       { background: var(--state-unanswered); border-color: var(--state-unanswered); }
.palette-legend__swatch[data-state="marked"],
.palette-legend__swatch[data-state="revealed"]    { background: var(--state-marked);     border-color: var(--state-marked); }
.palette-legend__swatch[data-state="answered_marked"] { background: var(--state-both);   border-color: var(--state-both); }
.palette-legend__swatch[data-state="not_visited"] { background: var(--surface);          border-color: var(--state-unvisited); }

/* ---------------------------------------------------------------------
   Solution and review
   ------------------------------------------------------------------ */

.solution {
  margin-top: var(--sp-4);
  padding: var(--sp-4);
  background: var(--surface-inset);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
}
.solution__head { display: flex; align-items: center; gap: var(--sp-2); margin-bottom: var(--sp-3); font-weight: 650; font-size: var(--fs-sm); text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-muted); }
.solution__body { line-height: var(--lh-loose); }
.solution__meta { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-top: var(--sp-3); padding-top: var(--sp-3); border-top: 1px solid var(--border); }

.qreview { border: 1px solid var(--border); border-radius: var(--r-lg); background: var(--surface); margin-bottom: var(--sp-4); overflow: hidden; }
.qreview__head { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); flex-wrap: wrap; padding: var(--sp-3) var(--sp-4); background: var(--surface-2); border-bottom: 1px solid var(--border); }
.qreview__body { padding: var(--sp-4); }
.qreview--correct { border-left: 3px solid var(--success); }
.qreview--wrong   { border-left: 3px solid var(--danger); }
.qreview--skipped { border-left: 3px solid var(--state-unvisited); }

@media (prefers-reduced-motion: reduce) {
  .palette__btn:hover { transform: none; }
  .exam-option { transition: none; }
}
