/* SOAi Sales Coach — front end (picker, live call, grading, debrief).
   Brand tokens copied from /brand/tokens.css at the repo root. Keep in sync. */

:root {
  --navy: #1B2A4A;
  --navy-l: #253660;
  --navy-d: #0F1B30;
  --cream: #E8E0C8;
  --cream-d: #D4C9A8;
  --gold: #C9A961;
  --gold-l: #DDBF7E;
  /* AA-safe gold for small text on --bg (~6.4:1). --gold itself stays untouched
     for graphics (bars, dots, glows) — only this darker variant is for text. */
  --gold-text: #6F5B33;
  /* Same idea for the "what worked" accent: --success is a graphic green and is
     too light for text (3.1:1); this is its readable sibling at 5.9:1. */
  --success-text: #46653A;

  /* Surfaces are a three-plane system, not one flat page: --bg is the page,
     --surface is a raised card (true white, so it separates from the ivory page
     instead of dissolving into it), --bg-warm is a recessed panel. Before this,
     cards were --bg on a --bg page and only a hairline border said otherwise. */
  --bg: #FDFCFA;
  --surface: #FFFFFF;
  --bg-warm: #F3EFE6;
  --text: #1B2A4A;
  /* Contrast pass 2026-08-01, on Jorge's note that the screen reads washed out.
     The muted greys were neutral AND light; these are navy-tinted (the brand's
     temperature) and materially darker. Measured on --bg:
     --text-muted 4.6:1 -> 7.3:1, --text-faint 2.6:1 -> 4.8:1 (was below the
     4.5:1 floor at any size), --gold-text 4.8:1 -> 6.4:1. */
  --text-muted: #46557A;
  --text-faint: #63718F;
  --border: #D8D2C4;
  --border-n: rgba(27, 42, 74, 0.20);

  --navy-xl: rgba(27, 42, 74, 0.07);
  --navy-xxl: rgba(27, 42, 74, 0.04);
  --cream-l: rgba(232, 224, 200, 0.18);
  --cream-ll: rgba(232, 224, 200, 0.08);

  --error: #B8483D;
  --error-d: #7A2E27;
  --success: #6B8E5A;

  --r-full: 9999px;
  --r-xl: 28px;
  --r-lg: 20px;
  --r: 12px;
  --r-sm: 8px;

  /* Layered and navy-tinted, never a flat grey blur. Opacities went up with the
     2026-08-01 contrast pass: at the old values a white card on an ivory page
     had almost no edge, which is half of why the screen read washed out. */
  --shadow-sm: 0 2px 8px rgba(27, 42, 74, 0.09), 0 1px 2px rgba(27, 42, 74, 0.06);
  --shadow-md: 0 10px 28px rgba(27, 42, 74, 0.13), 0 2px 6px rgba(27, 42, 74, 0.07);
  --shadow-lg: 0 22px 52px rgba(27, 42, 74, 0.17), 0 6px 16px rgba(27, 42, 74, 0.09);
  --shadow-gold: 0 16px 40px rgba(201, 169, 97, 0.22), 0 4px 12px rgba(27, 42, 74, 0.08);

  --font-display: 'Playfair Display', Georgia, serif;
  --font-body: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;

  /* --- Type scale ---------------------------------------------------------
     One ramp, used everywhere. Before this, forty-odd font sizes were decided
     per rule (11, 11.5, 12, 12.5, 13, 13.5, 14, 14.5, 15, 15.5 ...) which is
     not a scale, it is a list. Every step here is ~20-25% larger than the
     value it replaces — Jorge read a real debrief on a large monitor on
     2026-08-01 and could not comfortably read the outcome of his own call.
     Changing the ramp changes every screen at once, which is the point. */
  --fs-micro: 13.5px;        /* was 11    — bubble speaker labels */
  --fs-caption: 14.5px;      /* was 12    — uppercase section labels */
  --fs-small: 16px;          /* was 13    — hints, secondary lines */
  --fs-body: 17px;           /* was 14    — the default reading size */
  --fs-lead: 18px;           /* was 15    — transcript, emphasis body */
  --fs-cta: 19px;            /* was 16    — secondary button */
  --fs-cta-xl: 26.5px;       /* --fs-title x 1.3 — the hero CTA, one button only */
  --fs-title: 20.5px;        /* was 17    — card titles, primary button */
  --fs-title-lg: 22px;       /* was 18    — card titles one step up */
  /* The wordmark left the shared ramp on 2026-08-02: at --fs-title-lg it read as
     one more label in the nav row instead of as the brand. Twice the old size,
     fluid so a phone gets a wordmark that still fits its own line. */
  --fs-brand: clamp(28px, 3.4vw, 44px);
  --brand-mark: clamp(46px, 5vw, 68px);
  --fs-h3: 24px;             /* was 19-20 — reveal headings */
  --fs-h2: 34px;             /* was 28    — "Not graded" */
  --fs-h2-fluid: clamp(32px, 4vw, 40px);
  --fs-h1: clamp(42px, 5.6vw, 68px);
  --fs-score: clamp(84px, 7vw, 104px);
  --fs-score-denom: 30px;

  /* --- Layout -------------------------------------------------------------
     The app was capped at 640px on every screen, so a 27" monitor showed a
     narrow ribbon down the middle. These are generous but finite: text lines
     wider than ~75 characters cost more in tracking-back than they gain in
     space, so width is spent on COLUMNS (see the debrief grid), never on
     longer lines. The gutter is a fixed 44px (22px a side), not a percentage:
     a percentage gutter is invisible on a phone and enormous on a monitor. */
  --w-page: min(1280px, calc(100vw - 44px));
  --w-start: min(1120px, calc(100vw - 44px));
  --w-call: min(980px, calc(100vw - 40px));
  --w-narrow: min(720px, calc(100vw - 44px));
  --measure: 66ch;           /* max line length for running body copy */

  /* --- Stack rhythm -------------------------------------------------------
     Vertical air between blocks of running text, decided once instead of per
     rule. Jorge read the screens on 2026-08-02 and the paragraphs ran into
     each other: the type ramp had grown 20-25% (see above) while the gaps
     around it never did, so every block sat at the spacing that suited the
     smaller text. Four steps, each used for one job:
       tight  items inside one list, label above its own text
       sm     parts of a single thought (eyebrow, headline, paragraph)
       md     between blocks that are separate thoughts
       lg     between sections of a screen */
  --stack-tight: 12px;
  --stack-sm: 22px;
  --stack: 32px;
  --stack-lg: 44px;

  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-smooth: cubic-bezier(0.16, 1, 0.3, 1);
}

/* --- Reset --- */
*, *::before, *::after { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0;
  font-family: var(--font-body);
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
h1, h2, p { margin: 0; }
button { font: inherit; color: inherit; }
img { display: block; max-width: 100%; }

/* --- Ambient background --- */
.bg-field {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(720px 520px at 12% -8%, rgba(201, 169, 97, 0.14), transparent 60%),
    radial-gradient(640px 480px at 108% 12%, rgba(27, 42, 74, 0.08), transparent 55%),
    radial-gradient(900px 700px at 50% 118%, rgba(232, 224, 200, 0.35), transparent 60%),
    var(--bg);
}
.bg-field::after {
  content: '';
  position: absolute;
  inset: 0;
  opacity: 0.5;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='140' height='140'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/><feColorMatrix type='matrix' values='0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 0.02 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
}

/* --- App shell --- */
.app {
  position: relative;
  z-index: 1;
  min-height: 100vh;
  display: flex;
  align-items: stretch;
  justify-content: center;
}

.screen {
  display: none;
  width: 100%;
}
.screen.is-active { display: flex; }

/* ===========================================================================
   Screen 1 — Start
   =========================================================================== */

.screen--start {
  flex-direction: column;
  min-height: 100vh;
  width: var(--w-start);
  margin: 0 auto;
  padding: 32px 0 48px;
}

.brand-row {
  display: flex;
  align-items: center;
  gap: 14px;
  flex: none;
}

.start-body {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--stack-lg);
  /* Padding, not a gap on the parent: the body is centred in what is left of
     the viewport, and once the content is taller than the screen a gap
     collapses to nothing and the eyebrow ends up under the nav. */
  padding: var(--stack-lg) 0;
}
.brand-mark {
  width: var(--brand-mark);
  height: var(--brand-mark);
  object-fit: contain;
}
.brand-name {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-brand);
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--navy);
}
/* --gold is the graphic gold; on an ivory page it dissolves at text weight.
   --gold-text is the same hue taken down to 6.4:1 against --bg. */
.brand-name__accent { color: var(--gold-text); font-style: italic; }

.start-hero {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--stack-sm);
}

.eyebrow {
  font-family: var(--font-body);
  font-size: var(--fs-small);
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--gold-text);
}

.start-hero__title {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--fs-h1);
  line-height: 1.06;
  letter-spacing: -0.03em;
  color: var(--navy);
}

.start-hero__body {
  max-width: var(--measure);
  font-size: var(--fs-title);
  line-height: 1.7;
  color: var(--text-muted);
}

/* --- Scenario picker (radio cards) --- */

/* auto-fit, not a fixed column count: the three calls sit side by side the
   moment there is room for a 260px card and stack when there is not. No
   breakpoint has to be maintained for the in-between sizes. */
.scenario-picker {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(268px, 1fr));
  gap: 16px;
  width: 100%;
  margin: 0;
  padding: 0;
  border: none;
}
.scenario-picker__legend {
  /* A <legend> is not a grid item — the browser lays it out as the fieldset's
     own label box — so grid properties do nothing to it and it needs its own
     full-width box to center inside. */
  width: 100%;
  text-align: center;
}

.scenario-picker__legend {
  /* Its own air above the first card. At 2px the label touched the card and
     read as part of it rather than as the heading of the group. */
  padding: 0 0 var(--stack-tight);
  font-family: var(--font-body);
  font-size: var(--fs-small);
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--gold-text);
}

.scenario-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 22px 24px;
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm);
  cursor: pointer;
  transform: translateY(0);
  transition: transform 180ms var(--ease), box-shadow 180ms var(--ease), border-color 180ms var(--ease);
}
.scenario-card:hover {
  transform: translateY(-1px);
  box-shadow: var(--shadow-md);
}
.scenario-card:active {
  transform: translateY(0) scale(0.995);
}
/* The selected card is the one piece of state on this screen, so it is stated
   three ways at once — navy border at 2px, a warm fill, and a gold rail down
   the left edge. At the old single hairline it was easy to miss which of the
   three calls you were about to start. */
.scenario-card:has(.scenario-card__input:checked) {
  border-color: var(--navy);
  border-width: 2px;
  background: linear-gradient(180deg, #FFFDF6 0%, var(--bg-warm) 100%);
  box-shadow: var(--shadow-md);
}
.scenario-card:has(.scenario-card__input:checked)::before {
  content: '';
  position: absolute;
  left: -2px;
  top: 18px;
  bottom: 18px;
  width: 4px;
  border-radius: var(--r-full);
  background: linear-gradient(180deg, var(--gold-l), var(--gold));
}
.scenario-card:has(.scenario-card__input:focus-visible) {
  outline: none;
  box-shadow: var(--shadow-md), 0 0 0 3px var(--bg), 0 0 0 6px var(--gold);
}

.scenario-card__input {
  position: absolute;
  top: 18px;
  right: 18px;
  width: 18px;
  height: 18px;
  margin: 0;
  accent-color: var(--navy);
  cursor: pointer;
}
.scenario-card__input:focus-visible {
  /* The card-level box-shadow ring (above, via :has()) is the ONE focus
     indicator. Without this, the browser also paints its own native
     outline directly on the input, on top of that ring — two indicators
     for one focus state. */
  outline: none;
}

.scenario-card__title {
  padding-right: 32px;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-title);
  letter-spacing: -0.01em;
  color: var(--navy);
}

.scenario-card__goal {
  padding-right: 32px;
  font-size: var(--fs-body);
  line-height: 1.65;
  color: var(--text-muted);
}

.rando-note {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  max-width: var(--measure);
  padding: 18px 22px;
  background: var(--bg-warm);
  border: 1px solid var(--border-n);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm);
}
.rando-note__dot {
  flex: none;
  width: 8px;
  height: 8px;
  margin-top: 7px;
  border-radius: 50%;
  background: var(--gold);
  box-shadow: 0 0 0 4px rgba(201, 169, 97, 0.18);
}
.rando-note p {
  font-size: var(--fs-body);
  line-height: 1.7;
  color: var(--navy-l);
}

.btn-start {
  position: relative;
  margin-top: 8px;
  padding: 18px 40px;
  border: none;
  border-radius: var(--r-full);
  background: linear-gradient(155deg, var(--navy) 0%, var(--navy-d) 100%);
  color: var(--cream);
  font-family: var(--font-body);
  font-weight: 700;
  font-size: var(--fs-title);
  letter-spacing: -0.005em;
  cursor: pointer;
  box-shadow: var(--shadow-lg);
  transform: translateY(0) scale(1);
  transition: transform 220ms var(--ease), opacity 220ms var(--ease);
}
.btn-start::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow: var(--shadow-gold);
  opacity: 0;
  pointer-events: none;
  transition: opacity 220ms var(--ease);
}
.btn-start:hover {
  transform: translateY(-2px) scale(1.015);
}
.btn-start:hover::after {
  opacity: 1;
}
.btn-start:active {
  transform: translateY(0) scale(0.98);
}
.btn-start:focus-visible {
  outline: none;
  box-shadow: var(--shadow-lg), 0 0 0 3px var(--bg), 0 0 0 6px var(--gold);
}
.btn-start:disabled {
  cursor: progress;
  opacity: 0.85;
}

/* The one primary CTA on the app: 30% larger than the shared button (padding
   and label together, so the pill keeps its proportions), with a light that
   runs its circumference. A halo pulsing underneath was tried first and read
   as a lamp switching on and off; this reads as light travelling along an
   edge, which is what a physical object does.

   How it works: ONE conic gradient whose start angle is animated, masked down
   to a band just outside the pill. The angle has to be a REGISTERED custom
   property (@property below) — a plain --var cannot be interpolated, so the
   animation would jump from 0 to 360 and look like nothing at all. Rotating
   the element instead is the obvious alternative and is wrong: this pill is a
   rectangle, and rotating it swings the whole shape.

   The button keeps overflow visible, since the light lives outside its box.
   Anything else layered on it must therefore be a background, never a
   translated layer — a translated layer draws OUTSIDE the pill (caught in the
   lab: a pale smudge floating to the right of the button). */
@property --cta-angle {
  syntax: '<angle>';
  initial-value: 0deg;
  inherits: false;
}

.btn-start--hero {
  padding: 23px 52px;
  font-size: var(--fs-cta-xl);
  /* Its own stacking context, so the z-index: -1 below stays behind the label
     and in front of the button's own background instead of vanishing under it. */
  isolation: isolate;
}
.btn-start--hero::before {
  content: '';
  position: absolute;
  inset: -4px;
  border-radius: inherit;
  padding: 4px;                       /* the thickness of the light */
  background: conic-gradient(from var(--cta-angle),
    rgba(201, 169, 97, 0) 0deg,
    rgba(201, 169, 97, 0) 190deg,
    rgba(201, 169, 97, 0.30) 262deg,
    rgba(221, 191, 126, 0.90) 296deg,
    #FFF6DF 316deg,
    rgba(221, 191, 126, 0.90) 334deg,
    rgba(201, 169, 97, 0) 360deg);
  /* Keep only the outer band: the whole fill minus the content box. */
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask-composite: exclude;
  filter:
    drop-shadow(0 0 10px rgba(201, 169, 97, 0.90))
    drop-shadow(0 0 22px rgba(201, 169, 97, 0.45));
  animation: cta-orbit 2.6s linear infinite;
  pointer-events: none;
  z-index: -1;
}
@keyframes cta-orbit { to { --cta-angle: 360deg; } }

/* Nothing runs while the call is being set up — at that moment the button is
   reporting progress, not inviting a click. */
.btn-start--hero.is-loading::before,
.btn-start--hero:disabled::before {
  animation: none;
  opacity: 0;
}
@media (prefers-reduced-motion: reduce) {
  .btn-start--hero::before { animation: none; }
}
.btn-start__spinner {
  display: none;
}
.btn-start.is-loading .btn-start__label { opacity: 0.55; }
.btn-start.is-loading .btn-start__spinner {
  display: inline-block;
  width: 16px;
  height: 16px;
  margin-left: 10px;
  vertical-align: -3px;
  border-radius: 50%;
  border: 2px solid rgba(232, 224, 200, 0.35);
  border-top-color: var(--gold);
  animation: spin 800ms linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

.start-hint {
  font-size: var(--fs-small);
  color: var(--text-muted);
  letter-spacing: 0.01em;
  /* Centred explicitly: it is centred on a wide screen only because it fits on
     one line there. On a phone it wraps, and a ragged left-aligned pair of
     lines under a centred column reads as a mistake. */
  text-align: center;
}

/* ===========================================================================
   Screen 2 — Live call
   =========================================================================== */

.screen--call {
  flex-direction: column;
  width: var(--w-call);
  margin: 0 auto;
  height: 100vh;
  padding: 24px 0 28px;
}

.call-topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.call-topbar__status {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 8px 14px;
  background: var(--bg-warm);
  border: 1px solid var(--border);
  border-radius: var(--r-full);
  box-shadow: var(--shadow-sm);
}
.live-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--error);
  box-shadow: 0 0 0 3px rgba(184, 72, 61, 0.16);
  animation: pulse-dot 1.6s var(--ease) infinite;
}
@keyframes pulse-dot {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: 0.55; transform: scale(0.82); }
}
.call-timer {
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  font-size: var(--fs-body);
  letter-spacing: 0.01em;
  color: var(--navy);
}

.build-chip {
  font-family: 'SFMono-Regular', ui-monospace, Menlo, monospace;
  font-size: var(--fs-caption);
  letter-spacing: 0.02em;
  color: var(--navy-l);
  background: var(--cream-l);
  border: 1px solid var(--border-n);
  border-radius: var(--r-full);
  padding: 7px 13px;
  white-space: nowrap;
}

.call-stage {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
  padding: 36px 0 28px;
}

.orb-wrap {
  position: relative;
  width: 168px;
  height: 168px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.orb__glow {
  position: absolute;
  inset: -34px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(201, 169, 97, 0.55) 0%, rgba(201, 169, 97, 0.16) 45%, transparent 72%);
  opacity: 0.35;
  transform: scale(1);
  will-change: transform, opacity;
}

.orb {
  position: relative;
  width: 132px;
  height: 132px;
  border-radius: 50%;
  transform: scale(1);
  will-change: transform;
}

.orb__ring {
  position: absolute;
  inset: -10px;
  border-radius: 50%;
  border: 1.5px solid var(--border-n);
}

.orb__core {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: radial-gradient(circle at 32% 28%, var(--navy-l) 0%, var(--navy) 55%, var(--navy-d) 100%);
  box-shadow: var(--shadow-lg), inset 0 0 24px rgba(201, 169, 97, 0.14);
}
.orb__core::after {
  content: '';
  position: absolute;
  inset: 18%;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(232, 224, 200, 0.5), transparent 70%);
  opacity: 0.6;
}

.equalizer {
  display: flex;
  align-items: flex-end;
  gap: 6px;
  height: 34px;
}
.equalizer span {
  width: 5px;
  height: 34px;
  border-radius: var(--r-full);
  background: linear-gradient(180deg, var(--gold) 0%, var(--gold-l) 100%);
  transform: scaleY(0.12);
  transform-origin: bottom center;
  will-change: transform;
}

.call-status {
  font-size: var(--fs-body);
  font-weight: 500;
  color: var(--text-muted);
  letter-spacing: 0.01em;
}

.transcript {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 4px 4px 12px;
  scrollbar-width: thin;
}
.transcript:empty {
  align-items: center;
  justify-content: center;
}
.transcript:empty::before {
  content: 'The transcript will show up here once the call gets going.';
  max-width: 360px;
  text-align: center;
  font-size: var(--fs-body);
  line-height: 1.6;
  color: var(--text-muted);
}

.bubble {
  /* A ch cap as well as a percentage: at 980px wide, 82% alone would put a
     transcript line past 110 characters, which is past the point where the eye
     reliably finds the start of the next line. */
  max-width: min(82%, 62ch);
  display: flex;
  flex-direction: column;
  gap: 4px;
  animation: bubble-in 260ms var(--ease-smooth);
}
@keyframes bubble-in {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: translateY(0); }
}

.bubble__label {
  font-size: var(--fs-micro);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.bubble__text {
  padding: 14px 18px;
  border-radius: var(--r-lg);
  font-size: var(--fs-lead);
  line-height: 1.7;
}

.bubble--agent {
  align-self: flex-start;
}
.bubble--agent .bubble__text {
  background: var(--bg-warm);
  border: 1px solid var(--border);
  border-bottom-left-radius: var(--r-sm);
  color: var(--navy);
  box-shadow: var(--shadow-sm);
}

.bubble--user {
  align-self: flex-end;
}
.bubble--user .bubble__label { text-align: right; }
.bubble--user .bubble__text {
  background: linear-gradient(155deg, var(--navy) 0%, var(--navy-d) 100%);
  border-bottom-right-radius: var(--r-sm);
  color: var(--cream);
  box-shadow: var(--shadow-md);
}

.btn-hangup {
  position: relative;
  align-self: center;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-top: 14px;
  padding: 15px 30px;
  border: none;
  border-radius: var(--r-full);
  background: linear-gradient(155deg, var(--error) 0%, var(--error-d) 100%);
  color: var(--bg);
  font-weight: 700;
  font-size: var(--fs-lead);
  cursor: pointer;
  box-shadow: 0 14px 30px rgba(184, 72, 61, 0.28), 0 2px 8px rgba(27, 42, 74, 0.08);
  transform: translateY(0) scale(1);
  transition: transform 200ms var(--ease), opacity 200ms var(--ease);
}
.btn-hangup::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow: 0 18px 36px rgba(184, 72, 61, 0.34), 0 3px 10px rgba(27, 42, 74, 0.09);
  opacity: 0;
  pointer-events: none;
  transition: opacity 200ms var(--ease);
}
.btn-hangup:hover {
  transform: translateY(-2px) scale(1.015);
}
.btn-hangup:hover::after {
  opacity: 1;
}
.btn-hangup:active {
  transform: translateY(0) scale(0.97);
}
.btn-hangup:focus-visible {
  outline: none;
  box-shadow: 0 14px 30px rgba(184, 72, 61, 0.28), 0 0 0 3px var(--bg), 0 0 0 6px var(--error);
}
.btn-hangup__icon { width: 18px; height: 18px; }

/* ===========================================================================
   Screen 3 — Grading
   =========================================================================== */

.screen--grading {
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  width: var(--w-narrow);
  margin: 0 auto;
  padding: 28px 0 40px;
}

.grading {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 16px;
  max-width: 52ch;
}

.grading__pulse {
  position: relative;
  width: 64px;
  height: 64px;
  margin-bottom: 10px;
  border-radius: 50%;
  background: radial-gradient(circle at 32% 28%, var(--navy-l) 0%, var(--navy) 55%, var(--navy-d) 100%);
  box-shadow: var(--shadow-lg), inset 0 0 16px rgba(201, 169, 97, 0.18);
  animation: grading-pulse 1.6s var(--ease-smooth) infinite;
}
@keyframes grading-pulse {
  0%, 100% { transform: scale(1); opacity: 1; }
  50% { transform: scale(1.12); opacity: 0.78; }
}

.grading__title {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--fs-h2-fluid);
  letter-spacing: -0.02em;
  color: var(--navy);
}

.grading__step {
  font-size: var(--fs-lead);
  font-weight: 500;
  color: var(--navy-l);
  min-height: 1.4em;
}

.grading__hint {
  font-size: var(--fs-small);
  color: var(--text-muted);
}

/* Recovery state: grading did not finish, but this call can still be graded.
   The pulse and the "don't close the tab" hint are instructions for waiting, so
   they go away the moment there is nothing left to wait for. */
.grading.is-recovering .grading__pulse,
.grading.is-recovering .grading__step,
.grading.is-recovering .grading__hint { display: none; }

.grading__recovery {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
  width: 100%;
  margin-top: 4px;
  padding: 22px 24px 24px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm);
}

.grading__recovery-text {
  font-size: var(--fs-body);
  line-height: 1.7;
  color: var(--text-muted);
  max-width: 44ch;
}

.grading__recovery-actions {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
}

/* Side by side, both labels wrapped to two lines, on a phone. Stack instead —
   and give the primary action the full width, the same way the debrief's
   actions already do at this breakpoint. */
@media (max-width: 560px) {
  .grading__recovery { padding: 20px 18px 22px; }
  .grading__recovery-actions {
    flex-direction: column;
    align-items: stretch;
    width: 100%;
    gap: 4px;
  }
}

/* ===========================================================================
   Screen 4 — Debrief
   =========================================================================== */

.screen--debrief {
  flex-direction: column;
  width: var(--w-page);
  margin: 0 auto;
  min-height: 100vh;
  padding: 32px 0 56px;
}

/* The debrief is the screen this product is judged on, and it was a single
   560px column: on a large monitor the verdict sat alone in the middle with
   two thirds of the screen empty, and everything below the fold. Wide, it
   becomes a fixed left rail (the outcome — score and verdict, which stay put
   while the detail scrolls) and a right stack (the coaching itself). The
   reveal spans the full width underneath, because "who you were talking to"
   is the payoff and deserves the whole line. */
.debrief {
  display: flex;
  flex-direction: column;
  gap: var(--stack);
  width: 100%;
  padding-top: 20px;
}

@media (min-width: 1000px) {
  .debrief {
    display: grid;
    grid-template-columns: minmax(320px, 400px) minmax(0, 1fr);
    align-items: start;
    column-gap: 36px;
    row-gap: var(--stack);
  }
  .debrief__rail {
    position: sticky;
    top: 32px;
  }
  .debrief__reveal,
  .debrief__actions,
  .debrief__notice { grid-column: 1 / -1; }
}

/* "You have this debrief, but we could not store it." Amber rather than the
   error red: nothing failed for the trainee in this call, and the one thing they
   must not do is assume it will be in their history tomorrow. */
.debrief__notice {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 16px 20px;
  background: var(--bg-warm);
  border: 1px solid var(--border);
  border-left: 3px solid var(--gold);
  border-radius: var(--r);
  font-size: var(--fs-small);
  line-height: 1.7;
  color: var(--text-muted);
}

.debrief__notice-mark {
  flex: none;
  font-weight: 700;
  color: var(--gold-text);
}

.debrief__rail {
  display: flex;
  flex-direction: column;
  gap: var(--stack-sm);
  padding: 32px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-md);
}
.debrief__main {
  display: flex;
  flex-direction: column;
  gap: var(--stack);
  min-width: 0;
}

.debrief__score {
  display: flex;
  align-items: baseline;
  gap: 6px;
}
.debrief__score-num {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--fs-score);
  line-height: 1;
  letter-spacing: -0.03em;
  color: var(--navy);
}
.debrief__score-denom {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-score-denom);
  color: var(--text-muted);
}
.debrief__score--ungraded .debrief__score-text {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-h2);
  letter-spacing: -0.01em;
  color: var(--text-muted);
}

.debrief__verdict {
  max-width: var(--measure);
  font-size: var(--fs-title);
  line-height: 1.7;
  color: var(--navy-l);
}

/* auto-fit again: two coaching columns on a wide screen, one on a phone, and
   no breakpoint in between to keep in sync. */
.debrief__cols {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: var(--stack-sm);
  width: 100%;
}
.debrief__col {
  padding: 24px 26px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 4px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm);
}
/* The two columns say opposite things and looked identical. The rail colour is
   the fastest possible read of which is which, before a single word is read. */
.debrief__col--good { border-left-color: var(--success); }
.debrief__col--work { border-left-color: var(--gold); }
.debrief__col--good .debrief__col-title { color: var(--success-text); }
.debrief__col-title {
  margin: 0 0 var(--stack-tight);
  font-family: var(--font-body);
  font-size: var(--fs-caption);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--gold-text);
}
.debrief__col-list {
  margin: 0;
  padding: 0 0 0 18px;
  display: flex;
  flex-direction: column;
  gap: var(--stack-tight);
  font-size: var(--fs-body);
  line-height: 1.7;
  color: var(--text);
}
.debrief__col-empty {
  list-style: none;
  margin-left: -18px;
  /* --text-faint measures ~2.27:1 on --bg-warm (this card's background) — well
     under the 3:1 large-text floor, let alone 4.5:1. --navy-l is the token
     this stylesheet already uses for de-emphasized-but-readable body copy
     (see .rando-note p) and clears 10.5:1 here. */
  color: var(--navy-l);
  font-style: italic;
}

.debrief__objection {
  width: 100%;
  padding: 22px 26px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 4px solid var(--navy);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm);
}
.debrief__objection-label {
  display: block;
  margin-bottom: 10px;
  font-size: var(--fs-caption);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--gold-text);
}
.debrief__objection-text {
  font-size: var(--fs-body);
  line-height: 1.7;
  color: var(--text);
}

.debrief__fair-housing {
  width: 100%;
  padding: 22px 26px;
  background: var(--surface);
  border: 1px solid var(--border);
  /* Gold by default, red only for an actual violation. Fair housing coming up
     and being handled correctly is a GOOD outcome; painting that note in alarm
     red taught the trainee that mentioning schools was a mistake. */
  border-left: 4px solid var(--gold);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm);
}
.debrief__fair-housing-label {
  display: block;
  margin-bottom: 10px;
  font-size: var(--fs-caption);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--gold-text);
}
.debrief__fair-housing-text {
  font-size: var(--fs-body);
  line-height: 1.7;
  color: var(--text);
}
.debrief__fair-housing.is-violation {
  background: rgba(184, 72, 61, 0.06);
  border-left-color: var(--error);
}
.debrief__fair-housing.is-violation .debrief__fair-housing-label {
  color: var(--error-d);
}

/* The one deliberately warm surface on the screen — navy-on-cream, so the
   reveal reads as a different kind of information from the coaching above it. */
.debrief__reveal {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--stack-tight);
  width: 100%;
  padding: 34px 28px;
  text-align: center;
  background: linear-gradient(180deg, #FBF7EA 0%, var(--bg-warm) 100%);
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-sm);
}
.debrief__reveal-eyebrow {
  font-size: var(--fs-caption);
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--gold-text);
  margin-bottom: 6px;
}
.debrief__reveal-scenario {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-h3);
  letter-spacing: -0.01em;
  color: var(--navy);
}

.debrief__reveal-level {
  font-size: var(--fs-body);
  font-weight: 600;
  color: var(--navy-l);
}
.debrief__reveal-archetype {
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 700;
  font-size: var(--fs-h3);
  letter-spacing: -0.01em;
  color: var(--navy);
}
.debrief__reveal-prospect {
  font-size: var(--fs-body);
  color: var(--text-muted);
}

.debrief__actions {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 20px;
  margin-top: 4px;
}

.btn-start--debrief {
  padding: 16px 34px;
  font-size: var(--fs-cta);
}

.btn-quiet {
  padding: 12px 8px;
  border: none;
  background: none;
  color: var(--text-muted);
  font-weight: 600;
  font-size: var(--fs-body);
  cursor: pointer;
  border-radius: var(--r-sm);
  transform: translateY(0);
  transition: transform 180ms var(--ease), opacity 180ms var(--ease), color 180ms var(--ease);
}
.btn-quiet:hover {
  color: var(--navy);
  transform: translateY(-1px);
}
.btn-quiet:active {
  transform: translateY(0) scale(0.97);
}
.btn-quiet:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--bg), 0 0 0 6px var(--gold);
}

/* ===========================================================================
   Toast (error banner) — shared by both screens
   =========================================================================== */

.toast {
  position: fixed;
  top: 92px;
  left: 50%;
  z-index: 20;
  max-width: min(480px, calc(100vw - 40px));
  padding: 14px 20px;
  border-radius: var(--r-lg);
  background: linear-gradient(155deg, var(--error) 0%, var(--error-d) 100%);
  color: var(--bg);
  font-size: var(--fs-body);
  font-weight: 500;
  line-height: 1.5;
  box-shadow: 0 18px 40px rgba(122, 46, 39, 0.3), 0 4px 12px rgba(27, 42, 74, 0.1);
  opacity: 0;
  transform: translate(-50%, -16px);
  pointer-events: none;
  transition: transform 260ms var(--ease-smooth), opacity 260ms var(--ease-smooth);
}
.toast.is-visible {
  opacity: 1;
  transform: translate(-50%, 0);
}

/* ===========================================================================
   Responsive
   =========================================================================== */

@media (max-width: 560px) {
  .screen--start { padding: 22px 0 36px; }
  /* The section gap used to be pinned to 24px here, from when the desktop gap
     was 28px. After the rhythm pass that left a phone reading the SAME size
     type at half the desktop air, which is backwards: a stacked column has no
     side-by-side grouping to help the eye, so it needs at least as much. It
     now simply inherits --stack-lg. */
  .start-hero__body { font-size: var(--fs-lead); }
  .scenario-picker { gap: var(--stack-sm); }
  .orb-wrap { width: 140px; height: 140px; }
  .orb { width: 110px; height: 110px; }
  .scenario-card { padding: 18px 20px; }
  .scenario-card__input { top: 16px; right: 16px; }
  .debrief__rail { padding: 24px 22px; }
  .debrief__col { padding: 20px 22px; }
  .debrief__score-num { font-size: clamp(64px, 16vw, 84px); }
  .debrief__actions { flex-direction: column; gap: 12px; width: 100%; }
  .btn-start--debrief { width: 100%; }
  .screen--debrief { padding: 24px 0 40px; }
}

@media (prefers-reduced-motion: reduce) {
  .btn-start, .btn-hangup, .btn-start::after, .btn-hangup::after, .toast, .bubble,
  .scenario-card, .btn-quiet {
    transition: none;
    animation: none;
  }
  .live-dot, .grading__pulse { animation: none; }
}

/* ===========================================================================
   Screen 0 — Login
   =========================================================================== */

.screen--login {
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  width: var(--w-narrow);
  margin: 0 auto;
  padding: 32px 0 48px;
}

.login-card {
  display: flex;
  flex-direction: column;
  gap: var(--stack-sm);
  width: 100%;
  max-width: 440px;
  padding: 40px 38px 34px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-lg);
}
/* Stacked on the login card: at the doubled size the wordmark wraps to two
   lines inside a 460px card, and a two-line block beside the mark reads as a
   misalignment. Mark over wordmark is a lockup instead. */
.brand-row--center {
  flex-direction: column;
  justify-content: center;
  gap: 12px;
  text-align: center;
}

.login-title {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--fs-h2-fluid);
  letter-spacing: -0.02em;
  color: var(--navy);
  text-align: center;
}
.login-sub {
  margin-top: -10px;
  text-align: center;
  font-size: var(--fs-body);
  color: var(--text-muted);
}

.login-form { display: flex; flex-direction: column; gap: 16px; }

.field { display: flex; flex-direction: column; gap: 7px; }
.field__label {
  font-size: var(--fs-caption);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--gold-text);
}
.field__input {
  width: 100%;
  padding: 15px 17px;
  font-family: var(--font-body);
  font-size: var(--fs-body);
  color: var(--text);
  background: var(--bg);
  border: 1.5px solid var(--border);
  border-radius: var(--r);
  transition: border-color 160ms var(--ease), box-shadow 160ms var(--ease);
}
.field__input::placeholder { color: var(--text-faint); }
.field__input:hover { border-color: var(--border-n); }
.field__input:focus-visible {
  outline: none;
  border-color: var(--navy);
  box-shadow: 0 0 0 3px var(--bg), 0 0 0 6px var(--gold);
}

.login-error {
  padding: 12px 14px;
  font-size: var(--fs-body);
  line-height: 1.5;
  color: var(--error-d);
  background: rgba(184, 72, 61, 0.08);
  border-left: 4px solid var(--error);
  border-radius: var(--r-sm);
}

.btn-start--full { width: 100%; margin-top: 4px; }
.btn-start--small { padding: 12px 24px; font-size: var(--fs-body); }

.login-foot {
  text-align: center;
  font-size: var(--fs-small);
  color: var(--text-muted);
}

/* --- Top navigation, on every signed-in screen --- */

.topnav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex: none;
  flex-wrap: wrap;
}
.topnav__links { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }

.navlink {
  padding: 9px 14px;
  border: none;
  border-radius: var(--r-full);
  background: none;
  font-size: var(--fs-body);
  font-weight: 600;
  color: var(--text-muted);
  cursor: pointer;
  transform: translateY(0);
  transition: color 160ms var(--ease), background-color 160ms var(--ease), transform 160ms var(--ease);
}
.navlink:hover { color: var(--navy); background: var(--bg-warm); transform: translateY(-1px); }
.navlink:active { transform: translateY(0) scale(0.97); }
.navlink:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--bg), 0 0 0 6px var(--gold);
}
.navlink.is-current { color: var(--navy); background: var(--cream-l); }
.navlink--quiet { color: var(--text-faint); }
.navlink:disabled { opacity: 0.4; cursor: not-allowed; }
.navlink:disabled:hover { background: none; color: var(--text-muted); transform: none; }

/* Who is signed in — the disc, the name, and the account menu under it.
   The disc alone carried the initials and the name lived in a tooltip; it is a
   pill now, so the screen says who you are without being hovered. It reads as
   one object and not a fourth tab: the tabs are pills of text on the page, this
   one is a raised surface with its own edge and shadow. */
.navuser-wrap { position: relative; margin-left: 10px; }

.navuser {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 5px 14px 5px 5px;
  border: 1px solid var(--border);
  border-radius: var(--r-full);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  font-weight: 600;
  color: var(--navy);
  cursor: pointer;
  transform: translateY(0);
  transition: border-color 160ms var(--ease), box-shadow 160ms var(--ease),
              transform 160ms var(--ease);
}
.navuser:hover { border-color: var(--border-n); box-shadow: var(--shadow-md); transform: translateY(-1px); }
.navuser:active { transform: translateY(0) scale(0.985); }
.navuser:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--bg), 0 0 0 6px var(--gold);
}

.navuser__disc {
  display: grid;
  place-items: center;
  flex: none;
  width: 36px;
  height: 36px;
  border-radius: var(--r-full);
  background: var(--navy);
  font-size: var(--fs-small);
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--cream);
  user-select: none;
}

.navuser__name {
  max-width: 18ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.navuser__caret {
  flex: none;
  width: 11px;
  height: 8px;
  color: var(--text-faint);
  transform: rotate(0deg);
  transition: transform 200ms var(--ease);
}
.navuser[aria-expanded="true"] .navuser__caret { transform: rotate(180deg); }

/* The floating plane: above the elevated cards, anchored to the pill. */
.usermenu {
  position: absolute;
  top: calc(100% + 10px);
  right: 0;
  z-index: 20;
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 236px;
  padding: 8px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg);
  animation: menu-in 180ms var(--ease) both;
}
.usermenu[hidden] { display: none; }

@keyframes menu-in {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Role above address, reversed in flow so the DOM still reads email-then-role:
   the role is the one-word answer to "what account is this", the address is the
   detail under it. Stacked the other way they read as one run-on line. */
.usermenu__head {
  display: flex;
  flex-direction: column-reverse;
  gap: 4px;
  padding: 8px 12px 10px;
  margin-bottom: 4px;
  border-bottom: 1px solid var(--border);
}
.usermenu__email {
  font-size: var(--fs-small);
  color: var(--text-muted);
  overflow: hidden;
  text-overflow: ellipsis;
}
.usermenu__role {
  font-size: var(--fs-caption);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--gold-text);
}

.usermenu__item {
  padding: 11px 12px;
  border: none;
  border-radius: var(--r);
  background: none;
  text-align: left;
  font-family: var(--font-body);
  font-size: var(--fs-body);
  font-weight: 600;
  color: var(--navy);
  cursor: pointer;
  transition: color 140ms var(--ease), background-color 140ms var(--ease);
}
.usermenu__item:hover { background: var(--bg-warm); }
.usermenu__item:active { background: var(--cream-l); }
.usermenu__item:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--surface), 0 0 0 4px var(--gold);
}
.usermenu__item--quiet { color: var(--text-muted); }
.usermenu__item[hidden] { display: none; }

/* Name, email and role in the account modal. A definition list because that is
   what it is — three labelled facts, not a form nobody can edit. */
.whois {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: baseline;
  gap: 8px 20px;
  padding: 16px 18px;
  background: var(--bg-warm);
  border-radius: var(--r);
}
.whois__label {
  font-size: var(--fs-caption);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-faint);
}
.whois__value {
  font-size: var(--fs-body);
  font-weight: 600;
  color: var(--navy);
  overflow-wrap: anywhere;
}

/* ===========================================================================
   Screens 5-6 — History and replay
   =========================================================================== */

.screen--history,
.screen--replay,
.screen--admin {
  flex-direction: column;
  gap: var(--stack);
  width: var(--w-page);
  margin: 0 auto;
  min-height: 100vh;
  padding: 32px 0 56px;
}

.page-title {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--fs-h2-fluid);
  letter-spacing: -0.02em;
  color: var(--navy);
}

.btn-back { align-self: flex-start; padding-left: 0; }

.history-list { display: flex; flex-direction: column; gap: var(--stack-tight); }

.histrow {
  display: grid;
  grid-template-columns: 64px minmax(0, 1fr) auto;
  align-items: center;
  gap: 20px;
  width: 100%;
  padding: 20px 24px;
  text-align: left;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm);
  cursor: pointer;
  transform: translateY(0);
  transition: transform 180ms var(--ease), box-shadow 180ms var(--ease);
}
.histrow:hover { transform: translateY(-1px); box-shadow: var(--shadow-md); }
.histrow:active { transform: translateY(0) scale(0.997); }
.histrow:focus-visible {
  outline: none;
  box-shadow: var(--shadow-md), 0 0 0 3px var(--bg), 0 0 0 6px var(--gold);
}

.histrow__score {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--fs-h3);
  color: var(--navy);
  text-align: center;
}
.histrow__main { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.histrow__title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-title);
  color: var(--navy);
}
.histrow__sub {
  font-size: var(--fs-body);
  line-height: 1.5;
  color: var(--text-muted);
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
}
.histrow__meta { font-size: var(--fs-small); color: var(--text-faint); white-space: nowrap; }

/* Discarded practices are SHOWN, greyed and labelled. Hiding them would make
   the minimum-practice guard look like data loss (spec §6.2). */
.histrow--discarded { background: var(--bg-warm); box-shadow: none; }
.histrow--discarded .histrow__score,
.histrow--discarded .histrow__title { color: var(--text-muted); }

.empty-note {
  padding: 28px 0;
  text-align: center;
  font-size: var(--fs-body);
  color: var(--text-muted);
}

.replay { display: flex; flex-direction: column; gap: var(--stack); }
.replay__head { font-size: var(--fs-body); color: var(--text-muted); }
.replay__section {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-h3);
  color: var(--navy);
}
/* The live transcript is a scrolling pane inside a fixed-height call screen; a
   replay is a document and simply runs down the page. */
.transcript--replay {
  flex: none;
  max-height: none;
  overflow: visible;
  gap: var(--stack-sm);
}

/* ===========================================================================
   Screen 7 — Admin
   =========================================================================== */

.kpis {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 18px;
}
.kpi {
  padding: 24px 26px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm);
}
.kpi__value {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--fs-h2);
  letter-spacing: -0.02em;
  color: var(--navy);
}
.kpi__label {
  margin-top: 4px;
  font-size: var(--fs-caption);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--gold-text);
}
.kpi__hint { margin-top: 6px; font-size: var(--fs-small); color: var(--text-muted); }

.panel {
  padding: 30px 32px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-sm);
}
.panel__head { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-bottom: var(--stack-sm); }
.panel__title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-h3);
  color: var(--navy);
  margin-bottom: var(--stack-sm);
}
.panel__head .panel__title { margin-bottom: 0; }

.trend { display: flex; align-items: flex-end; gap: 14px; height: 210px; padding-top: 8px; }
.trend__col {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  flex: 1;
  height: 100%;
  justify-content: flex-end;
}
.trend__bar {
  width: 100%;
  max-width: 56px;
  min-height: 4px;
  border-radius: var(--r-sm) var(--r-sm) 0 0;
  background: linear-gradient(180deg, var(--gold-l) 0%, var(--gold) 100%);
}
.trend__label { font-size: var(--fs-small); color: var(--text-muted); white-space: nowrap; }
.trend__value { font-size: var(--fs-body); font-weight: 700; color: var(--navy); }

.ranking { display: flex; flex-direction: column; gap: 8px; }
.rankrow {
  display: grid;
  grid-template-columns: 36px minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 16px;
  width: 100%;
  padding: 14px 16px;
  text-align: left;
  background: none;
  border: 1px solid transparent;
  border-radius: var(--r);
  cursor: pointer;
  transition: background-color 160ms var(--ease), border-color 160ms var(--ease);
}
.rankrow:hover { background: var(--bg-warm); border-color: var(--border); }
.rankrow:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--bg), 0 0 0 6px var(--gold); }
.rankrow__pos {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-title);
  color: var(--text-faint);
}
.rankrow__name { font-size: var(--fs-title); font-weight: 600; color: var(--navy); }
.rankrow__count { font-size: var(--fs-small); color: var(--text-muted); white-space: nowrap; }
.rankrow__score {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--fs-h3);
  color: var(--navy);
  min-width: 3ch;
  text-align: right;
}

.usertable { display: flex; flex-direction: column; gap: 6px; }
.userrow {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 1.6fr) auto auto auto;
  align-items: center;
  gap: 16px;
  padding: 14px 16px;
  border-radius: var(--r);
  border: 1px solid transparent;
}
.userrow:hover { background: var(--bg-warm); border-color: var(--border); }
.userrow--off { opacity: 0.55; }
.userrow__name { font-size: var(--fs-body); font-weight: 600; color: var(--navy); }
.userrow__email {
  font-size: var(--fs-body);
  color: var(--text-muted);
  overflow: hidden;
  text-overflow: ellipsis;
}
.userrow__count { font-size: var(--fs-small); color: var(--text-muted); white-space: nowrap; }
.userrow__actions { display: flex; gap: 4px; }

.chip {
  justify-self: start;
  padding: 4px 12px;
  font-size: var(--fs-caption);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--gold-text);
  background: var(--cream-l);
  border: 1px solid var(--border-n);
  border-radius: var(--r-full);
}

.modal {
  position: fixed;
  inset: 0;
  z-index: 30;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: rgba(15, 27, 48, 0.42);
}
.modal[hidden] { display: none; }
.modal__card {
  display: flex;
  flex-direction: column;
  gap: 16px;
  width: 100%;
  max-width: 460px;
  padding: 32px 30px;
  background: var(--surface);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-lg);
}
.modal__title {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--fs-h3);
  color: var(--navy);
}
.modal__actions { display: flex; align-items: center; justify-content: flex-end; gap: 12px; }

@media (max-width: 760px) {
  /* These live HERE and not in the 560px block above, which sits earlier in
     the file than the .topnav rules it would be trying to override — same
     specificity, so source order decides and the override silently loses.
     The nav wraps onto its own line at this width; give it room to. */
  .topnav { gap: var(--stack-sm); }
  .topnav__links { gap: 8px; row-gap: 10px; }
  /* Both of these rows were auto-placed, and auto-placement after an item that
     spans to the last line pushes the NEXT item to a fresh row: the score
     landed under "14 practices" in column 1, and the accounts row unfolded
     into five stacked lines. Every cell is now placed explicitly. */
  .rankrow {
    grid-template-columns: 28px minmax(0, 1fr) auto;
    column-gap: 12px;
    row-gap: 2px;
  }
  .rankrow__pos { grid-column: 1; grid-row: 1 / span 2; align-self: center; }
  .rankrow__name { grid-column: 2; grid-row: 1; }
  .rankrow__score { grid-column: 3; grid-row: 1; }
  .rankrow__count { grid-column: 2; grid-row: 2; }

  .userrow {
    grid-template-columns: minmax(0, 1fr) auto;
    column-gap: 10px;
    row-gap: 4px;
  }
  .userrow__name { grid-column: 1; grid-row: 1; }
  .userrow .chip { grid-column: 2; grid-row: 1; justify-self: end; }
  /* The count rides on the email's line, not the buttons' — the two actions
     are ~230px of a 313px card, which leaves the count too little to sit
     beside them, and the count does not wrap. */
  .userrow__email { grid-column: 1; grid-row: 2; }
  .userrow__count { grid-column: 2; grid-row: 2; justify-self: end; }
  .userrow__actions { grid-column: 1 / -1; grid-row: 3; justify-self: end; }
  /* "Reset password" wrapped to two lines at the nav size. It is a row action
     here, not a nav item, so it gets the secondary size and tighter padding. */
  .userrow__actions .navlink { padding: 7px 9px; font-size: var(--fs-small); white-space: nowrap; }

  .histrow { grid-template-columns: 48px minmax(0, 1fr); }
  .histrow__meta { grid-column: 2; }
  .topnav__links { width: 100%; justify-content: flex-start; }
  /* The row wraps and left-aligns here, so the pill is usually near the left
     edge — a menu anchored to its right would hang off the screen. */
  .navuser-wrap { margin-left: 0; }
  .usermenu { right: auto; left: 0; }
}

/* Also below .trend rather than in the 560px block near the top of the file,
   for the source-order reason spelled out above. */
@media (max-width: 560px) {
  /* The trend ran off the card AND off the screen on a phone. The cause is not
     the bars: .trend__col is `flex: 1` with the browser default min-width:auto,
     so no column can shrink below its own nowrap date label. Six "Jun 22"s at
     16px need ~358px; the card offers 285px. So let the columns shrink, let the
     date break onto its own second line, and stop spending 64px of a 349px
     screen on card padding. All six weeks stay visible — a six-point trend that
     needs a swipe is not a trend you can read. */
  .panel { padding: 22px 18px 24px; }
  .trend { gap: 6px; height: 178px; }
  .trend__col { min-width: 0; gap: 6px; }
  .trend__bar { max-width: none; }
  .trend__value { font-size: var(--fs-small); }
  .trend__label {
    text-align: center;
    font-size: var(--fs-caption);
    line-height: 1.2;
  }
  .trend__month, .trend__day { display: block; }
}
