/* =========================================================================
   Application styles
   =========================================================================

   The design system, applied to the surfaces this product actually has.

     design/tokens.css      colour, type, space, shape, depth, material, motion
     design/system.css      primitives — glass, buttons, fields, layout, motion
     design/components.css  signature components — nav, voice field, score dial

   Everything below styles the class names the existing pages already use, so
   that adopting the system required no markup churn: one stylesheet changed
   and every candidate-facing page moved with it. Where a legacy name and a
   system primitive overlap, the system primitive wins on specificity and the
   legacy rule is the fallback — which is how these pages will be migrated one
   at a time without a flag day.

   See /design/ for the living reference.
   ========================================================================= */

@import url("/design/tokens.css");
@import url("/design/system.css");
@import url("/design/components.css");

/* -------------------------------------------------------------------------
   Legacy token aliases.
   Inline styles across the HTML and proctoring.css still reference these two
   names. Aliasing costs nothing and means the rename never becomes a
   coordinated edit across six files.
   ------------------------------------------------------------------------- */
:root {
  --muted: var(--ink-muted);
  --panel: var(--surface);
}

/* =========================================================================
   Shell
   ========================================================================= */

body::before {
  /* The atmosphere layer, without asking every page to add an element. */
  content: "";
  position: fixed; inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image: var(--aura-petrol), var(--aura-sand);
  background-repeat: no-repeat;
}

.shell {
  position: relative;
  z-index: 1;
  max-width: var(--container);
  margin: 0 auto;
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  padding-inline: var(--gutter);
}

main { flex: 1; padding-block: var(--s-10) var(--s-20); }

/* -------------------------------------------------------------------------
   Top bar, as a floating glass rail.
   The markup comes from auth.js `mountTopbar` and is unchanged: this is the
   same five spans, treated as a material instead of a border-bottom.
   ------------------------------------------------------------------------- */
.topbar {
  position: sticky; top: var(--s-3);
  z-index: var(--z-nav);
  display: flex; align-items: center; gap: var(--s-4);
  min-height: 3.25rem;
  margin-top: var(--s-3);
  padding: var(--s-2) var(--s-3) var(--s-2) var(--s-5);
  border-radius: var(--r-pill);
  border: 1px solid transparent;
  font-size: var(--t-small-size);
  color: var(--ink-muted);
  transition: background-color var(--t-surface), border-color var(--t-surface),
              box-shadow var(--t-surface);
}
[data-scrolled] .topbar {
  border-color: var(--glass-border);
  background-image: var(--glass-fill-floating);
  box-shadow: var(--glass-inner), var(--shadow-2);
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  [data-scrolled] .topbar {
    -webkit-backdrop-filter: blur(var(--glass-blur-lg)) saturate(var(--glass-sat));
    backdrop-filter: blur(var(--glass-blur-lg)) saturate(var(--glass-sat));
  }
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  [data-scrolled] .topbar { background-color: var(--surface); }
}

.brand {
  font-weight: var(--w-semibold);
  color: var(--ink-display);
  letter-spacing: -0.015em;
  white-space: nowrap;
}
.topbar .spacer { flex: 1 1 auto; min-width: var(--s-2); }
.topbar #crumb, .topbar #envinfo { white-space: nowrap; }

.who { display: flex; align-items: center; gap: var(--s-2); font-size: var(--t-small-size); }
.who b { color: var(--ink); font-weight: var(--w-medium); }

/* Resets min-height, radius and shadow as well as the paint: without them the
   bare `button` rule above leaves a pill-shaped shadow behind a text link. */
.linkbtn {
  display: inline; min-height: 0; border-radius: 0; box-shadow: none;
  background: none; border: 0; padding: 0;
  color: var(--accent); font: inherit; font-size: var(--t-small-size);
  font-weight: var(--w-medium); cursor: pointer;
  text-decoration: underline; text-underline-offset: 2px;
  text-decoration-color: var(--accent-line);
  transition: color var(--t-control);
}
.linkbtn:hover { color: var(--accent-hover); text-decoration-color: currentColor; }

@media (max-width: 44rem) {
  .topbar { flex-wrap: wrap; border-radius: var(--r-xl); padding-inline: var(--s-4); }
  .brand { font-size: var(--t-small-size); }
  .topbar #envinfo { display: none; }
  .who { font-size: var(--t-micro-size); }
}

/* =========================================================================
   Type
   ========================================================================= */

h1, h2, h3 {
  font-family: var(--font-display);
  color: var(--ink-display);
  margin: 0 0 var(--s-2);
  text-wrap: balance;
}
h1 {
  font-size: var(--t-h1-size); line-height: var(--t-h1-lh);
  letter-spacing: var(--t-h1-track); font-weight: var(--w-regular);
}
h2 {
  font-size: var(--t-h2-size); line-height: var(--t-h2-lh);
  letter-spacing: var(--t-h2-track); font-weight: var(--w-medium);
}
h3 {
  font-size: var(--t-h3-size); line-height: var(--t-h3-lh);
  letter-spacing: var(--t-h3-track); font-weight: var(--w-semibold);
}

.sub {
  color: var(--ink-secondary);
  font-size: var(--t-lead-size);
  line-height: var(--t-lead-lh);
  letter-spacing: var(--t-lead-track);
  margin: 0 0 var(--s-8);
  max-width: var(--measure);
  text-wrap: pretty;
}
.hint {
  font-size: var(--t-small-size);
  line-height: 1.55;
  color: var(--ink-muted);
  max-width: var(--measure);
}
.crumb {
  font-size: var(--t-micro-size);
  letter-spacing: var(--t-micro-track);
  text-transform: uppercase;
  font-weight: var(--w-semibold);
  color: var(--accent);
  margin-bottom: var(--s-6);
}

/* =========================================================================
   Surfaces
   ========================================================================= */

.card {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-xl);
  padding: clamp(var(--s-6), 3vw, var(--s-10));
  box-shadow: var(--shadow-1);
}
.card > p, .card > .hint { max-width: var(--measure); }
/* Form controls respect the same reading measure as the copy beside them, so
   a wide card does not produce a column of text next to a full-bleed field. */
.card input, .card select { max-width: var(--measure); }

/* The pre-flight screens are a focused single column, not a full-width sheet. */
#setup, #scoring, #section { max-width: 54rem; }

.narrow { max-width: 27.5rem; margin: 10vh auto; }

/* `.stack` predates the system's `.stack-N` gap scale; keep its default. */
.stack { display: flex; flex-direction: column; }
.stack:not([class*="stack-"]) { gap: var(--s-5); }

.row { display: flex; gap: var(--s-3); align-items: center; flex-wrap: wrap; }

/* Block, not flex: the markup is bare inline content, and a flex container
   turns every text node and <strong> into its own column. */
/*
 * The rules box before a sitting, and anywhere else a candidate is told what
 * will end their assessment. Red, for the same reason the monitoring banner
 * is: amber reads as advisory, and none of this is advisory.
 */
.warnbox {
  display: block;
  background: var(--danger-soft);
  border: 1px solid transparent;
  border-left: 3px solid var(--danger);
  color: var(--danger);
  padding: var(--s-4) var(--s-5);
  border-radius: var(--r-md);
  font-size: var(--t-small-size);
  line-height: 1.55;
  margin: var(--s-5) 0;
  max-width: var(--measure);
}
.warnbox strong { color: var(--danger); font-weight: var(--w-semibold); }

.caveat {
  border-left: 2px solid var(--line-strong);
  padding: var(--s-1) 0 var(--s-1) var(--s-5);
  color: var(--ink-muted);
  font-size: var(--t-small-size);
  line-height: 1.6;
  margin: var(--s-6) 0;
  max-width: var(--measure);
  background: none; border-radius: 0;
}
.caveat strong { color: var(--ink-secondary); font-weight: var(--w-semibold); }

/* =========================================================================
   Controls
   =========================================================================
   Bare `button` and `input` are styled directly so existing markup upgrades
   without adding classes. Anything carrying a system class (`.btn`, `.field`)
   beats these on specificity and keeps its own treatment.
   ========================================================================= */

/*
 * The legacy bare-element button, for the pages that predate the design
 * system.
 *
 * `:where()` gives the whole thing ZERO specificity, which is the honest
 * description of what it is: a default that any class may override. Written
 * plainly, `button:hover` is more specific than `.btn--danger`, so a red Stop
 * button turned accent-coloured the moment the pointer was over it - which is
 * the whole time somebody is about to press it. Scoping it to `:not(.btn)`
 * instead only moved the problem: it raised the rule to a class's specificity
 * and flattened `.link-btn` and every other single-class override into a solid
 * accent pill.
 */
:where(button) {
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--s-2);
  min-height: 2.75rem;
  padding: 0 var(--s-6);
  border-radius: var(--r-pill);
  border: 1px solid transparent;
  background: var(--accent);
  color: var(--ink-on-accent);
  box-shadow: var(--shadow-accent);
  font: inherit;
  font-size: var(--t-body-size);
  font-weight: var(--w-medium);
  letter-spacing: -0.005em;
  cursor: pointer;
  white-space: nowrap;
  transition: background-color var(--t-control), border-color var(--t-control),
              color var(--t-control), box-shadow var(--t-control),
              transform var(--d-instant) var(--ease-spring);
}
:where(button:hover:not(:disabled)) { background: var(--accent-hover); }
:where(button:active:not(:disabled)) { background: var(--accent-press); transform: scale(0.975); }
:where(button:disabled) { opacity: .45; cursor: not-allowed; box-shadow: none; }

button.ghost {
  background: var(--surface);
  color: var(--ink);
  border-color: var(--line-strong);
  box-shadow: var(--shadow-1);
}
button.ghost:hover:not(:disabled) { background: var(--surface); border-color: var(--ink-faint); }
button.ghost:active:not(:disabled) { background: var(--bg-deep); }

a:has(> button) { text-decoration: none; }

label {
  display: block;
  font-size: var(--t-small-size);
  font-weight: var(--w-medium);
  color: var(--ink-secondary);
  margin: var(--s-5) 0 var(--s-2);
}

/*
 * Text-like inputs only.
 *
 * This used to be bare `input`, which meant every checkbox and radio on the
 * platform inherited `width: 100%`, a 2.75rem minimum height, padding and a
 * border - so a tick box rendered as a large empty rectangle that was awkward
 * to hit and did not look like a control at all. A checkbox is not a field
 * with a smaller value in it; it is a different thing.
 */
input:not([type="checkbox"]):not([type="radio"]), select {
  width: 100%;
  min-height: 2.75rem;
  padding: var(--s-3) var(--s-4);
  background: var(--surface);
  color: var(--ink);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
  font: inherit;
  font-size: var(--t-body-size);
  transition: border-color var(--t-control), box-shadow var(--t-control);
}
input::placeholder { color: var(--ink-faint); }
input:not([type="checkbox"]):not([type="radio"]):hover, select:hover {
  border-color: var(--ink-faint); }
input:focus-visible, select:focus-visible {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

/* =========================================================================
   Assessment surface
   =========================================================================
   The screen a candidate looks at for twenty minutes. It is deliberately the
   quietest surface in the product: an open composition rather than a card, so
   nothing frames the question but whitespace.
   ========================================================================= */

#item.card, #instructions.card {
  background: none;
  border: 0;
  box-shadow: none;
  padding-inline: 0;
}

/* While the runner is on screen its glass bar is the only chrome. */
body[data-screen="item"] .topbar { display: none; }

/* -------------------------------------------------------------------------
   The assessment runner.
   A glass bar, the field, the camera, and a footer stating the conditions.
   Nothing else: for twenty minutes this is the whole product.
   ------------------------------------------------------------------------- */
.runner {
  display: grid;
  grid-template-rows: auto 1fr auto;
  gap: var(--s-6);
  min-height: min(38rem, 78vh);
}

.runner__bar {
  display: flex; align-items: center; gap: var(--s-4);
  padding: var(--s-3) var(--s-3) var(--s-3) var(--s-5);
  border-radius: var(--r-pill);
}
.runner__brand { font-weight: var(--w-semibold); letter-spacing: -.015em;
  color: var(--ink-display); }
.runner__part { font-size: var(--t-small-size); color: var(--ink-muted); white-space: nowrap; }
.runner__spacer { flex: 1 1 auto; }
@media (max-width: 34rem) { .runner__brand { display: none; } }

.runner__body {
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--s-8); align-items: center;
}
.runner__main {
  display: grid; gap: var(--s-6); justify-items: center;
  align-content: center; text-align: center;
}
.runner__progress { display: grid; gap: var(--s-2); justify-items: center; }

/* The question, set large and light. It is the only sentence on screen. */
.runner__prompt {
  margin: 0; max-width: 26rem;
  font-size: clamp(1.3125rem, 1.1rem + 1vw, 1.625rem);
  line-height: 1.3; letter-spacing: -.016em;
  font-weight: var(--w-medium); color: var(--ink-display);
  text-wrap: balance;
}
.runner__task {
  margin: calc(var(--s-4) * -1) 0 0; max-width: 30rem;
  font-size: var(--t-small-size); color: var(--ink-muted); text-wrap: pretty;
}

/* The camera tile. Portrait, because a person is portrait. */
.runner__cam {
  position: relative; width: 11rem; aspect-ratio: 4 / 5;
  border-radius: var(--r-lg); overflow: hidden;
  background: var(--c-graphite);
}
.runner__cam video { width: 100%; height: 100%; object-fit: cover;
  /* Mirrored, and that is right HERE: this corner view is a mirror for the
     candidate's own benefit - "am I still in frame" - and nothing is captured
     from it for anyone to compare against. The identity photo is the opposite
     case and is left true; see proctoring.css. */
  transform: scaleX(-1); }
/* ---- two fields: the question, and the answer ---------------------------- */

.runner__fields {
  display: flex; flex-direction: column; align-items: center; gap: var(--s-6);
  margin: var(--s-6) 0;
}
.runner__stage { display: grid; justify-items: center; gap: var(--s-3); }
.runner__stagelabel {
  margin: 0; font-size: var(--t-small-size); color: var(--ink-muted); text-align: center;
}
.runner__control { display: grid; justify-items: center; gap: var(--s-2); }
.runner__control .btn { min-width: 12rem; }

/* The question field is the platform talking. Quieter than the answer field,
   which is the candidate - the one that matters is the one they control. */
.voice-field--prompt { opacity: .92; }

@media (min-width: 60rem) {
  .runner__fields { flex-direction: row; align-items: flex-start; justify-content: center;
                    gap: var(--s-10); }
}

.runner__cam-chips { position: absolute; left: var(--s-2); right: var(--s-2);
  bottom: var(--s-2); display: flex; gap: var(--s-2); flex-wrap: wrap; }

.glass-chip {
  display: inline-flex; align-items: center; gap: var(--s-2);
  padding: var(--s-1) var(--s-3); border-radius: var(--r-pill);
  border: 1px solid var(--glass-border-dark);
  background-image: var(--glass-fill-dark);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .10);
  color: #fff; font-size: var(--t-micro-size); font-weight: var(--w-medium);
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .glass-chip {
    -webkit-backdrop-filter: blur(var(--glass-blur-md)) saturate(var(--glass-sat));
    backdrop-filter: blur(var(--glass-blur-md)) saturate(var(--glass-sat));
  }
}

.runner__foot {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-3) var(--s-5); flex-wrap: wrap;
  padding-top: var(--s-4); border-top: 1px solid var(--line);
  font-size: var(--t-small-size); color: var(--ink-muted);
}
.runner__foot span { display: inline-flex; align-items: center; gap: var(--s-2); }

@media (max-width: 52rem) {
  .runner__body { grid-template-columns: 1fr; justify-items: center; }
  /* The tile moves above the question rather than disappearing: a candidate
     who cannot see their own camera cannot tell they are still in frame. */
  .runner__cam { order: -1; width: 7.5rem; }
  .runner__foot { justify-content: center; }
}

.qcount {
  font-size: var(--t-small-size);
  color: var(--ink-muted);
  margin: var(--s-6) 0 var(--s-3);
  font-variant-numeric: tabular-nums;
}

/* The listen / answer pair. Two quiet fields, separated by space rather than
   by a box: the candidate should feel the shift from listening to speaking as
   a change in emphasis, not as a panel swap. */
.panes {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s-4);
  background: none;
  border-radius: var(--r-xl);
  overflow: visible;
  min-height: 12rem;
}
.pane {
  padding: var(--s-8) var(--s-6);
  border-radius: var(--r-lg);
  background: var(--surface);
  border: 1px solid var(--line);
  transition: background-color var(--t-surface), border-color var(--t-surface),
              opacity var(--t-surface);
}
.pane h3 {
  margin: 0 0 var(--s-6);
  font-size: var(--t-h3-size);
  font-weight: var(--w-medium);
  color: var(--ink);
  display: flex; align-items: center; flex-wrap: wrap; gap: var(--s-2);
}
/* The inactive half recedes rather than disappearing — the candidate still
   needs to see what is coming next. */
.pane.idle { background: none; border-color: transparent; opacity: .5; }
.pane.idle h3 { color: var(--ink-muted); font-weight: var(--w-regular); }

@media (max-width: 44rem) { .panes { grid-template-columns: 1fr; } }

/* Level meter. Used for the microphone check and as the fallback level display
   wherever the voice field is not mounted. */
.wave {
  display: flex; align-items: center; justify-content: center;
  gap: 3px; height: 4rem;
}
.wave i {
  display: block; width: 3px; border-radius: var(--r-pill);
  background: var(--line-strong); height: 6px;
  transition: height 90ms linear, background-color var(--t-control);
}
.wave.on i  { background: var(--accent); animation: wave-pulse .9s var(--ease-in-out) infinite; }
.wave.rec i { background: var(--danger); animation: wave-pulse .55s var(--ease-in-out) infinite; }
.wave i:nth-child(2n) { animation-delay: .1s; }
.wave i:nth-child(3n) { animation-delay: .22s; }
.wave i:nth-child(5n) { animation-delay: .34s; }
@keyframes wave-pulse { 0%, 100% { height: 8px; } 50% { height: 34px; } }
@media (prefers-reduced-motion: reduce) {
  .wave.on i, .wave.rec i { animation: none; height: 20px; }
}

.timer {
  display: inline-flex; align-items: center; gap: var(--s-2);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  padding: var(--s-1) var(--s-3);
  font-size: var(--t-small-size);
  font-weight: var(--w-medium);
  font-variant-numeric: tabular-nums;
  color: var(--ink-secondary);
  margin-left: var(--s-2);
  transition: color var(--t-control), border-color var(--t-control),
              background-color var(--t-control);
}
.timer.low { color: var(--danger); border-color: var(--danger); background: var(--danger-soft); }

.statusrow {
  display: flex; align-items: center; justify-content: center;
  gap: var(--s-3);
  margin-top: var(--s-8);
  color: var(--ink-muted);
  font-size: var(--t-small-size);
}

/* Progress within a part. Segments, not a creeping bar. */
.dots { display: flex; gap: var(--s-1); align-items: center; }
.dots b {
  display: block; width: 1.5rem; height: 3px;
  border-radius: var(--r-pill);
  background: var(--line-strong);
  transition: background-color var(--t-surface), transform var(--t-surface);
}
.dots b.done { background: var(--accent); }
.dots b.now  { background: var(--accent); transform: scaleY(2); }
@media (max-width: 32rem) { .dots b { width: .75rem; } }

/* =========================================================================
   Terms, and end-of-sitting feedback
   =========================================================================

   Both are screens somebody meets once, under mild pressure - about to start,
   or just finished. They are deliberately plain: short lines, one decision
   each, nothing that rewards a second read.
   ========================================================================= */

.terms {
  margin: var(--s-6) 0 0;
  padding: var(--s-5) var(--s-6);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface-sunken);
}
.terms__head {
  margin: 0 0 var(--s-3); font-size: var(--t-small-size);
  text-transform: uppercase; letter-spacing: var(--t-micro-track);
  color: var(--ink-muted); font-weight: var(--w-semibold);
}
.terms__list {
  margin: 0; padding-left: var(--s-5); display: grid; gap: var(--s-3);
  font-size: var(--t-small-size); line-height: 1.55; color: var(--ink);
  max-width: var(--measure);
}
.terms__accept {
  display: flex; gap: var(--s-3); align-items: flex-start;
  margin-top: var(--s-5); padding-top: var(--s-4);
  border-top: 1px solid var(--line);
  font-size: var(--t-small-size); cursor: pointer;
}
.terms__accept input {
  margin-top: .15em; width: 1.1rem; height: 1.1rem; flex: none; accent-color: var(--accent);
}

.fb { display: grid; gap: var(--s-5); margin: var(--s-6) 0; }
.fb__q { border: 0; padding: 0; margin: 0; }
.fb__prompt {
  padding: 0; margin-bottom: var(--s-3);
  font-size: var(--t-body-size); color: var(--ink-display);
}
.fb__scale { display: flex; align-items: center; gap: var(--s-3); flex-wrap: wrap; }
.fb__end { font-size: var(--t-micro-size); color: var(--ink-muted); min-width: 6rem; }
.fb__end:last-child { text-align: right; }
.fb__opt { position: relative; }
.fb__opt input {
  position: absolute; inset: 0; opacity: 0; cursor: pointer; margin: 0;
}
.fb__opt span {
  display: grid; place-items: center; width: 2.5rem; height: 2.5rem;
  border: 1px solid var(--line); border-radius: var(--r-md);
  background: var(--surface); font-variant-numeric: tabular-nums;
  transition: border-color var(--t-control), background-color var(--t-control);
}
.fb__opt input:hover + span { border-color: var(--accent); }
.fb__opt input:checked + span {
  background: var(--accent); border-color: var(--accent); color: #fff;
  font-weight: var(--w-semibold);
}
.fb__opt input:focus-visible + span { outline: 2px solid var(--accent); outline-offset: 2px; }

@media (max-width: 40rem) {
  .fb__end { min-width: 0; flex-basis: 100%; }
  .fb__end:last-child { text-align: left; }
  .fb__opt span { width: 2.75rem; height: 2.75rem; }
}

/* =========================================================================
   Dashboard
   =========================================================================

   The standing comes before the list. A returning candidate arrives asking
   "how am I doing?", not "what can I sit?", and the page is ordered to answer
   the question they actually have.
   ========================================================================= */

.dash__head { margin-bottom: var(--s-7); }
.dash__head h1 { margin: var(--s-2) 0 var(--s-2); }
.dash__head .up   { color: var(--ok); font-weight: var(--w-medium); }
.dash__head .down { color: var(--warn); font-weight: var(--w-medium); }

.dash { display: grid; gap: var(--s-6); margin-bottom: var(--s-9); }

.dash__grid {
  display: grid; grid-template-columns: auto minmax(0, 1fr);
  align-items: center; gap: var(--s-8);
  padding: var(--s-7);
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-xl);
}
.dash__dial { display: grid; place-items: center; }
.dash__stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
               gap: var(--s-6); }
.dash__stats .stat__value { font-size: 2.25rem; }
.stat__note { font-size: var(--t-micro-size); color: var(--ink-muted); }

.dash__panel {
  padding: var(--s-6);
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-xl);
}
.dash__panelhead {
  margin: 0 0 var(--s-4); font-size: var(--t-small-size); font-weight: var(--w-semibold);
  text-transform: uppercase; letter-spacing: var(--t-micro-track); color: var(--ink-muted);
}

.dash__section { margin: var(--s-10) 0 var(--s-2); }

.histtable { display: grid; }
.histrow {
  display: grid; grid-template-columns: 8rem auto minmax(0, 1fr) auto;
  align-items: center; gap: var(--s-4);
  padding: var(--s-3) 0; border-top: 1px solid var(--line);
  font-size: var(--t-small-size);
}
.histrow:first-child { border-top: 0; }
.hist__when { color: var(--ink-muted); }
.hist__score strong { font-size: var(--t-body-size); color: var(--ink-display); }

.profileform { margin-top: var(--s-4); }

@media (max-width: 48rem) {
  .dash__grid { grid-template-columns: 1fr; justify-items: center; }
  .dash__stats { width: 100%; }
  .histrow { grid-template-columns: 1fr auto; }
  .hist__when { grid-column: 1 / -1; }
}

.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(21rem, 1fr)); gap: var(--s-6); }

.acard {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-xl);
  padding: var(--s-8);
  display: flex; flex-direction: column;
  box-shadow: var(--shadow-1);
  transition: box-shadow var(--t-surface), transform var(--t-surface),
              border-color var(--t-surface);
}
.acard:hover {
  box-shadow: var(--shadow-2);
  border-color: var(--line-strong);
  transform: translateY(-2px);
}
@media (prefers-reduced-motion: reduce) { .acard:hover { transform: none; } }

.acard h3 { margin: 0 0 var(--s-1); font-size: var(--t-h2-size); font-weight: var(--w-medium); }
.acard .formtag {
  display: inline-flex; align-self: flex-start;
  font-size: var(--t-micro-size); font-weight: var(--w-semibold);
  letter-spacing: var(--t-micro-track); text-transform: uppercase;
  color: var(--accent); background: var(--accent-soft);
  padding: var(--s-1) var(--s-3); border-radius: var(--r-pill);
  margin-bottom: var(--s-3);
}
.acard .spec { font-size: var(--t-small-size); color: var(--ink-muted); margin: 0 0 var(--s-5); }
.acard .grow { flex: 1; }

.partlist { list-style: none; padding: 0; margin: 0 0 var(--s-6); font-size: var(--t-small-size); }
.partlist li {
  display: flex; justify-content: space-between; gap: var(--s-4);
  padding: var(--s-2) 0;
  border-bottom: 1px solid var(--line);
  color: var(--ink-muted);
}
.partlist li:last-child { border-bottom: 0; }
.partlist li b { color: var(--ink); font-weight: var(--w-medium); font-variant-numeric: tabular-nums; }

/* Mode choice. Practice reveals answers, so it is never the default and the
   difference is stated on the control itself rather than in a tooltip. */
.modes { display: flex; flex-direction: column; gap: var(--s-2); margin-bottom: var(--s-6); }
.mode {
  display: flex; gap: var(--s-3); align-items: flex-start;
  padding: var(--s-4);
  border: 1px solid var(--line); border-radius: var(--r-md);
  cursor: pointer; font-size: var(--t-small-size);
  transition: border-color var(--t-control), background-color var(--t-control);
}
.mode:hover { border-color: var(--accent-line); background: var(--bg-deep); }
.mode input { width: auto; min-height: 0; margin: 2px 0 0; accent-color: var(--accent); }
.mode .mt { font-weight: var(--w-semibold); color: var(--ink); display: block; margin-bottom: 2px; }
.mode .md { color: var(--ink-muted); display: block; line-height: 1.5; }
.mode.sel { border-color: var(--accent); background: var(--accent-soft); }

.hist { margin-top: var(--s-5); border-top: 1px solid var(--line); padding-top: var(--s-4); }
.hist h4 {
  margin: 0 0 var(--s-3); font-size: var(--t-micro-size);
  text-transform: uppercase; letter-spacing: var(--t-micro-track);
  color: var(--ink-faint); font-weight: var(--w-semibold);
}
.hrow { display: flex; align-items: center; gap: var(--s-3); font-size: var(--t-small-size); padding: var(--s-2) 0; }
.hrow .sp { flex: 1; color: var(--ink-muted); }

.pill {
  display: inline-flex; align-items: center;
  font-size: var(--t-micro-size); font-weight: var(--w-semibold);
  padding: var(--s-1) var(--s-3); border-radius: var(--r-pill);
  text-transform: uppercase; letter-spacing: var(--t-micro-track);
  background: var(--surface-sunken); color: var(--ink-muted);
}
.pill.scored   { background: var(--ok-soft);     color: var(--ok); }
.pill.progress { background: var(--warn-soft);   color: var(--warn); }
.pill.practice { background: var(--accent-soft); color: var(--accent-press); }
.pill.exam     { background: var(--surface-sunken); color: var(--ink-muted); }

/* =========================================================================
   Results
   ========================================================================= */

.score {
  font-family: var(--font-display);
  font-size: clamp(3rem, 2rem + 4vw, 4.5rem);
  font-weight: var(--w-light);
  letter-spacing: -0.04em;
  line-height: 1;
  color: var(--ink-display);
  font-variant-numeric: tabular-nums;
}
.cefr { font-size: var(--t-small-size); color: var(--ink-muted); margin-top: var(--s-2); }

.meter {
  display: grid;
  grid-template-columns: minmax(7rem, 11rem) 1fr auto;
  align-items: center; gap: var(--s-4);
  margin: var(--s-3) 0;
}
.meter .nm { font-size: var(--t-body-size); color: var(--ink-secondary); }
.meter .track {
  height: .375rem; background: var(--surface-sunken);
  border-radius: var(--r-pill); overflow: hidden;
}
.meter .fill {
  display: block; height: 100%;
  background: var(--viz-1); border-radius: inherit;
  transition: width var(--d-scene) var(--ease-out);
}
.meter .val {
  text-align: right; font-size: var(--t-small-size);
  font-variant-numeric: tabular-nums; color: var(--ink-muted); white-space: nowrap;
}
@media (max-width: 40rem) {
  .meter { grid-template-columns: 1fr auto; }
  .meter .track { grid-column: 1 / -1; order: 3; }
}

/* -------------------------------------------------------------------------
   The score report's headline.
   A glass card on a coloured, ruled ground - the one place in the product that
   is allowed a moment, because it is the one place a candidate has been
   waiting twenty minutes to reach.
   ------------------------------------------------------------------------- */
.report-stage {
  position: relative; overflow: hidden;
  border-radius: var(--r-2xl);
  padding: clamp(var(--s-5), 3vw, var(--s-10));
  margin: var(--s-6) 0 var(--s-8);
  background-color: var(--bg-deep);
  background-image:
    radial-gradient(40% 60% at 20% 30%, rgba(18,121,138,.26), transparent 70%),
    radial-gradient(45% 55% at 78% 60%, rgba(184,121,44,.22), transparent 70%);
}
.report-stage__rule { position: absolute; inset: 0; pointer-events: none;
  background-image:
    repeating-linear-gradient(90deg, rgba(23,28,34,.10) 0 1px, transparent 1px 2.25rem),
    repeating-linear-gradient(0deg,  rgba(23,28,34,.06) 0 1px, transparent 1px 2.25rem); }
.report-stage__grid {
  position: relative;
  /* Centred as a pair rather than stretched across the panel: the rollup is
     three short figures, and giving it 1fr leaves a wide band of empty
     gradient beside the card. */
  display: grid; grid-template-columns: auto auto;
  justify-content: center;
  gap: clamp(var(--s-6), 5vw, var(--s-16)); align-items: center;
}
.report-dial { padding: clamp(var(--s-5), 3vw, var(--s-8)); display: grid; place-items: center; }
.report-rollup { display: grid; gap: var(--s-6); }
@media (max-width: 46rem) {
  .report-stage__grid { grid-template-columns: 1fr; justify-items: center; }
  .report-rollup { grid-auto-flow: column; gap: var(--s-8); }
}
@media (max-width: 30rem) {
  .report-rollup { grid-auto-flow: row; justify-items: center; text-align: center; }
}

.secthead { display: flex; align-items: center; gap: var(--s-5); flex-wrap: wrap; margin-bottom: var(--s-2); }
.bigpct {
  font-family: var(--font-display);
  font-size: 2.75rem; font-weight: var(--w-light);
  line-height: 1; letter-spacing: -0.035em;
  font-variant-numeric: tabular-nums;
  color: var(--ink-display);
}

table { width: 100%; border-collapse: collapse; margin-top: var(--s-4); font-size: var(--t-body-size); }
th, td { text-align: left; padding: var(--s-3) var(--s-4); border-bottom: 1px solid var(--line); }
th {
  font-size: var(--t-micro-size); text-transform: uppercase;
  letter-spacing: var(--t-micro-track); color: var(--ink-faint);
  font-weight: var(--w-semibold);
}
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; }

details { margin-top: var(--s-6); }
summary {
  cursor: pointer; font-weight: var(--w-medium);
  font-size: var(--t-small-size); color: var(--ink-secondary);
  padding: var(--s-2) 0;
}
summary:hover { color: var(--ink); }

pre {
  background: var(--c-ink-deep); color: #d6e2ec;
  padding: var(--s-5); border-radius: var(--r-md);
  overflow: auto; font-family: var(--font-mono);
  font-size: var(--t-small-size); line-height: 1.6;
}

.flag {
  display: block;
  padding: var(--s-3) var(--s-4);
  border-radius: var(--r-md);
  font-size: var(--t-small-size);
  line-height: 1.55;
  margin: var(--s-2) 0;
  border-left: 3px solid transparent;
  max-width: var(--measure);
}
.flag.warn     { background: var(--warn-soft);   color: var(--warn);   border-left-color: var(--warn); }
.flag.critical { background: var(--danger-soft); color: var(--danger); border-left-color: var(--danger); }
.flag.info     { background: var(--surface-sunken); color: var(--ink-muted); border-left-color: var(--ink-faint); }

/* =========================================================================
   Per-item review
   ========================================================================= */

.vitem {
  border: 1px solid var(--line);
  border-left: 3px solid var(--line-strong);
  border-radius: var(--r-lg);
  padding: var(--s-5) var(--s-6);
  margin-bottom: var(--s-3);
  background: var(--surface);
}
.vitem.correct     { border-left-color: var(--ok); }
.vitem.partial     { border-left-color: var(--warn); }
.vitem.incorrect   { border-left-color: var(--danger); }
.vitem.no_response { border-left-color: var(--line-strong); }

.vhead { display: flex; align-items: baseline; gap: var(--s-3); margin-bottom: var(--s-3); flex-wrap: wrap; }
.vhead .vid { font-size: var(--t-micro-size); color: var(--ink-faint); font-variant-numeric: tabular-nums; }
.vhead .vv {
  font-size: var(--t-micro-size); font-weight: var(--w-semibold);
  text-transform: uppercase; letter-spacing: var(--t-micro-track);
}
.vv.correct { color: var(--ok); } .vv.partial { color: var(--warn); }
.vv.incorrect { color: var(--danger); } .vv.no_response { color: var(--ink-muted); }
.vhead .vpct {
  margin-left: auto; font-variant-numeric: tabular-nums;
  font-size: var(--t-small-size); color: var(--ink-muted);
}
.vq { font-weight: var(--w-medium); margin: 0 0 var(--s-4); color: var(--ink); }

.ab { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-3); margin-bottom: var(--s-4); }
.ab .box { padding: var(--s-3) var(--s-4); border-radius: var(--r-md); font-size: var(--t-body-size); }
.ab .box .bl {
  font-size: var(--t-micro-size); text-transform: uppercase;
  letter-spacing: var(--t-micro-track); font-weight: var(--w-semibold);
  color: var(--ink-faint); display: block; margin-bottom: var(--s-2);
}
.ab .yours  { background: var(--surface-sunken); border: 1px solid var(--line); }
.ab .theirs { background: var(--accent-soft); border: 1px solid var(--accent-line); }
.ab .empty  { color: var(--ink-faint); font-style: italic; }
@media (max-width: 40rem) { .ab { grid-template-columns: 1fr; } }

.analysis { list-style: none; padding: 0; margin: 0 0 var(--s-3); font-size: var(--t-small-size); }
.analysis li { padding: var(--s-1) 0 var(--s-1) var(--s-5); position: relative; color: var(--ink-secondary); }
.analysis li::before {
  content: ""; position: absolute; left: 0; top: .65em;
  width: 10px; height: 1px; background: var(--accent-line);
}

.coach {
  background: var(--warn-soft);
  border: 1px solid transparent; border-left: 3px solid var(--warn);
  border-radius: var(--r-md);
  padding: var(--s-3) var(--s-4);
  font-size: var(--t-small-size); line-height: 1.55;
  color: var(--warn);
}
.coach b { color: var(--warn); font-weight: var(--w-semibold); }

/* Word-by-word diff for repeat items. Colour never carries the meaning alone:
   omitted words are struck through and inserted words are bracketed, so the
   diff is readable without colour vision. */
.diff { display: flex; flex-wrap: wrap; gap: var(--s-1); margin: 0 0 var(--s-4); font-size: var(--t-body-size); }
.diff span { padding: 2px var(--s-2); border-radius: var(--r-xs); }
.diff .match  { background: var(--ok-soft);     color: var(--ok); }
.diff .near   { background: var(--warn-soft);   color: var(--warn); }
.diff .wrong  { background: var(--danger-soft); color: var(--danger); }
.diff .missed { background: var(--danger-soft); color: var(--danger); text-decoration: line-through; opacity: .8; }
.diff .added  { background: var(--surface-sunken); color: var(--ink-muted); }

.recplayer { margin: 0 0 var(--s-4); }
.recplayer audio { width: 100%; height: 2.25rem; }

/* =========================================================================
   Print
   =========================================================================
   A score report gets printed and filed. Strip the environment, keep the
   evidence.
   ========================================================================= */

@media print {
  body::before, .topbar, .proctor-status, .proctor-debug { display: none !important; }
  .shell { max-width: none; padding: 0; }
  .card, .acard, .vitem { box-shadow: none; border-color: #ccc; break-inside: avoid; }
  a { text-decoration: none; color: inherit; }
}
