/* =========================================================================
   LEARNERS — signature components
   =========================================================================

   The handful of surfaces that carry the product's identity: the floating
   navigation, the voice field, the score dial, the progress rail and the
   audio transport. Everything here composes tokens.css and system.css.

   These are the pieces worth spending design on, because they are the pieces a
   candidate actually looks at: the thing that proves it can hear them, the
   thing that tells them where they are, and the thing that tells them how they
   did. Everything else in the product should get out of their way.
   ========================================================================= */

/* ==========================================================================
   Floating navigation
   ==========================================================================
   Almost absent at the top of a page, and materialising into glass as content
   passes beneath it — driven by [data-scrolled] on <html> from motion.js. A
   full-width bar with a border would announce itself on every page; this
   belongs to the environment until there is something behind it to separate
   from.
   ========================================================================== */

.nav-rail {
  position: sticky; top: var(--s-3);
  z-index: var(--z-nav);
  margin: var(--s-3) auto 0;
  width: min(100% - var(--gutter) * 2, var(--container));
  display: flex; align-items: center; gap: var(--s-4);
  padding: var(--s-2) var(--s-2) var(--s-2) var(--s-5);
  min-height: 3.25rem;
  border-radius: var(--r-pill);
  border: 1px solid transparent;
  background-image: none;
  box-shadow: none;
  transition:
    background-color var(--t-surface),
    border-color var(--t-surface),
    box-shadow var(--t-surface),
    backdrop-filter var(--t-surface);
}

[data-scrolled] .nav-rail {
  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] .nav-rail {
    -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] .nav-rail { background-image: none; background-color: var(--surface); }
}

.nav-rail__brand {
  font-weight: var(--w-semibold);
  letter-spacing: -0.015em;
  color: var(--ink-display);
  text-decoration: none;
  white-space: nowrap;
}
.nav-rail__spacer { flex: 1 1 auto; min-width: var(--s-2); }
.nav-rail__meta {
  color: var(--ink-muted);
  font-size: var(--t-small-size);
  white-space: nowrap;
}
@media (max-width: 40rem) {
  .nav-rail { padding-left: var(--s-4); gap: var(--s-2); }
  .nav-rail__meta { display: none; }
}

/* ==========================================================================
   Voice field
   ==========================================================================
   The canvas does the drawing (design/voice-field.js); this owns the frame,
   the resting breath, and the label underneath. The idle breath is a CSS
   transform on the wrapper rather than a JavaScript loop — it is free on the
   compositor, and it means the rAF loop can stay stopped while nothing is
   happening.
   ========================================================================== */

.voice-field {
  position: relative;
  display: grid; place-items: center;
  width: var(--field-size, 15rem);
  aspect-ratio: 1;
  margin-inline: auto;
}

.voice-field__canvas {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  animation: field-breath 6s var(--ease-in-out) infinite;
}
.voice-field__canvas[data-state="recording"],
.voice-field__canvas[data-state="processing"] { animation: none; }

@keyframes field-breath {
  0%, 100% { transform: scale(0.985); }
  50%      { transform: scale(1.005); }
}
@media (prefers-reduced-motion: reduce) {
  .voice-field__canvas { animation: none; }
}

/* The glyph or countdown that sits at the centre of the field. */
.voice-field__core {
  position: relative;
  display: grid; place-items: center; gap: var(--s-1);
  text-align: center;
  pointer-events: none;
}
.voice-field__state {
  font-size: var(--t-micro-size);
  letter-spacing: var(--t-micro-track);
  text-transform: uppercase;
  font-weight: var(--w-semibold);
  color: var(--ink-muted);
}
.voice-field__count {
  font-family: var(--font-display);
  font-size: 2.5rem; font-weight: var(--w-light);
  letter-spacing: -0.03em; line-height: 1;
  font-variant-numeric: tabular-nums;
  color: var(--ink-display);
}

/* Recording is never signalled by colour or motion alone: there is a live pip
   drawn in the canvas, this text label, and the word "Recording". */
.voice-field__badge {
  display: inline-flex; align-items: center; gap: var(--s-2);
  padding: var(--s-1) var(--s-3);
  border-radius: var(--r-pill);
  background: var(--danger-soft); color: var(--danger);
  font-size: var(--t-small-size); font-weight: var(--w-medium);
}
.voice-field__badge .dot { animation: live-pulse 1.6s var(--ease-in-out) infinite; }
@keyframes live-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }
@media (prefers-reduced-motion: reduce) {
  .voice-field__badge .dot { animation: none; }
}

/* ==========================================================================
   Score dial
   ========================================================================== */

.score-dial {
  position: relative;
  width: var(--dial-size, 16rem);
  aspect-ratio: 1;
  display: grid; place-items: center;
  margin-inline: auto;
}
.score-dial__face { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }

.score-dial__track,
.score-dial__value {
  fill: none;
  stroke-width: 2.5;
  stroke-linecap: round;
  transform-box: fill-box;
}
.score-dial__track { stroke: var(--line); }
.score-dial__value {
  stroke: var(--viz-1);
  /* The arc is drawn from its start; the reveal simply lets it out. */
  transition: stroke-dashoffset 1.25s var(--ease-out);
}

.score-dial__tick { stroke: var(--line-strong); stroke-width: 0.8; }
.score-dial__tick.is-end { stroke: var(--ink-faint); }
.score-dial__tick-label {
  fill: var(--ink-faint);
  font-family: var(--font-sans);
  font-size: 3.6px;
  font-weight: var(--w-semibold);
  letter-spacing: 0.06em;
}
.score-dial__tick-label.is-end { font-weight: var(--w-regular); }

.score-dial__readout { display: grid; place-items: center; gap: var(--s-1); text-align: center; }
.score-dial__value-text {
  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);
}
.score-dial__level {
  font-size: var(--t-h3-size);
  font-weight: var(--w-medium);
  color: var(--accent);
  letter-spacing: -0.01em;
}
.score-dial__caption { color: var(--ink-faint); }

@media (prefers-reduced-motion: reduce) {
  .score-dial__value { transition: none; }
}

/* ==========================================================================
   Progress rail
   ==========================================================================
   Where the candidate is, inside the current part. Segments rather than a
   continuous bar, because the unit that matters is "questions left", not a
   percentage — and a bar that creeps encourages clock-watching.
   ========================================================================== */

.step-rail {
  display: flex; align-items: center; gap: var(--s-1);
  padding: 0; margin: 0; list-style: none;
}
.step-rail__step {
  height: 3px; flex: 1 1 auto; min-width: .5rem; max-width: 2.5rem;
  border-radius: var(--r-pill);
  background: var(--line-strong);
  transition: background-color var(--t-surface), transform var(--t-surface);
}
.step-rail__step.is-done { background: var(--accent); }
.step-rail__step.is-now  { background: var(--accent); transform: scaleY(2); }

/* ==========================================================================
   Timer
   ==========================================================================
   Tabular figures so the digits do not shuffle as they count. The low state
   changes colour AND adds a label, never colour alone.
   ========================================================================== */

.timer-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(--line);
  background: var(--surface);
  font-size: var(--t-small-size);
  font-weight: var(--w-medium);
  font-variant-numeric: tabular-nums;
  color: var(--ink-secondary);
  transition: color var(--t-control), border-color var(--t-control), background-color var(--t-control);
}
.timer-chip.is-low {
  color: var(--danger);
  border-color: var(--danger);
  background: var(--danger-soft);
}

/* ==========================================================================
   Audio transport
   ==========================================================================
   A custom surface for prompt playback. The browser's default player is a
   different shape, colour and size in every engine, which for a test that must
   be identical for every candidate is a fairness problem before it is a design
   one.
   ========================================================================== */

.transport {
  /* Relative + clipped so a specular sweep laid inside it stays inside it.
     Without these the highlight escapes the pill and travels across the page,
     which looks exactly like a rendering fault. */
  position: relative;
  overflow: hidden;
  display: flex; align-items: center; gap: var(--s-4);
  padding: var(--s-3) var(--s-4) var(--s-3) var(--s-3);
  border-radius: var(--r-pill);
}
.transport__button {
  flex: none;
  width: 2.75rem; height: 2.75rem;
  display: grid; place-items: center;
  border-radius: var(--r-pill);
  border: 0;
  background: var(--accent);
  color: var(--ink-on-accent);
  cursor: pointer;
  transition: background-color var(--t-control), transform var(--d-instant) var(--ease-spring);
}
.transport__button:hover { background: var(--accent-hover); }
.transport__button:active { transform: scale(0.94); }
.transport__button:disabled { opacity: .4; cursor: not-allowed; }

/* A still waveform: the shape of the clip, with a played portion. Static bars,
   because a prompt is played once and a dancing waveform during the question
   is a distraction from listening to it. */
.transport__wave {
  flex: 1 1 auto;
  display: flex; align-items: center; gap: 2px;
  height: 1.75rem;
  --played: 0%;
}
.transport__wave i {
  display: block; flex: 1 1 auto;
  min-width: 2px; border-radius: var(--r-pill);
  background: var(--line-strong);
  height: var(--h, 30%);
  transition: background-color var(--d-fast) linear;
}
.transport__wave i.is-played { background: var(--accent); }

.transport__time {
  flex: none;
  font-size: var(--t-small-size);
  font-variant-numeric: tabular-nums;
  color: var(--ink-muted);
}

/* ==========================================================================
   Editorial helpers
   ==========================================================================
   For the few surfaces that are prose rather than product: the caveat on a
   score report, an explanatory aside. Quiet, and never a card.
   ========================================================================== */

.aside-note {
  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;
  max-width: var(--measure);
}
.aside-note strong { color: var(--ink-secondary); font-weight: var(--w-semibold); }

/* A single figure with its label. Used for at-a-glance numbers that do not
   deserve a card each. */
.stat { display: grid; gap: var(--s-1); }
.stat__value {
  font-family: var(--font-display);
  font-size: var(--t-h1-size);
  font-weight: var(--w-light);
  letter-spacing: -0.03em;
  line-height: 1;
  color: var(--ink-display);
  font-variant-numeric: tabular-nums;
}
.stat__label { font-size: var(--t-small-size); color: var(--ink-muted); }
