/* Jost is the logo's own typeface — the wordmark is set in it, so it is
   loaded for the brand mark only rather than for body copy. */
@import url('https://fonts.googleapis.com/css2?family=Sora:wght@400;500;600;700;800&family=IBM+Plex+Mono:wght@400;500;600&family=Jost:wght@300;400&display=swap');

/* Theme: editorial. Dark-only, turquoise accent, no green anywhere — the
   old green semantics (confirmed, match, verdict) all fold into the same
   accent, so --green/--green-soft are deliberately aliased to the
   turquoise rather than removed, and anything still referencing them
   picks up the accent for free.

   Structure comes from hairline rules and space, not from filled boxes.
   The one recurring device is the *tick*: a short turquoise segment at
   the left end of a rule, echoing the four cardinal marks on the logo
   ring. It marks the start of anything that is its own unit of meaning —
   a section, a step, a field. Everything else stays quiet. */
:root {
  color-scheme: dark;
  --bg: #0A0F10;
  --bg-gradient: radial-gradient(ellipse 1200px 600px at 50% -10%, rgba(34,200,190,0.10), transparent),
                 radial-gradient(ellipse 900px 500px at 90% 10%, rgba(34,200,190,0.12), transparent);
  --panel: #111819;
  --panel-2: #18211F;
  --panel-3: #1C2626;
  --border: #1C2626;
  --border-soft: #141B1C;
  --ink: #E9F1F0;
  --ink-dim: #B6C4C3;
  --muted: #86969A;
  --muted-2: #5F6F70;
  --blue: #22C8BE;            /* accent is now turquoise */
  --blue-hover: #38E0D2;
  --blue-soft: rgba(34,200,190,0.15);
  --blue-border: rgba(34,200,190,0.35);
  /* Filled button surfaces. Held apart from --blue so light mode can
     darken the readable accent without dulling the buttons.
     NOTE: in dark mode nothing actually paints with these — the primary
     button is a translucent gradient on the dark surface (see the
     :root[data-theme="dark"] button rules below), so background-color
     stays transparent. They're kept as the un-themed default and are
     what light mode overrides. */
  --accent-fill: #22C8BE;
  --accent-fill-hover: #38E0D2;
  --row-hover: rgba(34,200,190,0.04);
  --white: #FFFFFF;
  /* Sits on top of the turquoise accent — it's a light colour, so filled
     accent surfaces need dark ink rather than white. */
  --on-accent: #04211F;
  --error: #F87171;
  --error-bg: rgba(248,113,113,0.10);
  --error-border: rgba(248,113,113,0.28);
  --green: #22C8BE;                    /* green folded into turquoise accent */
  --green-soft: rgba(34,200,190,0.15);
  --green-border: rgba(34,200,190,0.35);
  --mono: 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, monospace;

  /* Layout constants. One page width, one prose measure — everything
     lines up to these two so the columns never drift screen to screen. */
  --page: 1080px;
  --measure: 60ch;
  --rail: 124px;
  --gutter: 40px;
  --tick: 26px;
  --radius: 2px;
}

* { box-sizing: border-box; }

html {
  background: var(--bg);
}

body {
  margin: 0;
  font-family: 'Sora', system-ui, -apple-system, sans-serif;
  font-weight: 400;
  /* Longhands, not the shorthand: --bg-gradient is more than one layer,
     and the background shorthand only accepts a colour in its FINAL
     layer, so `background: var(--bg) var(--bg-gradient)` parses as
     invalid and drops the wash entirely. */
  background-color: var(--bg);
  background-image: var(--bg-gradient);
  background-attachment: fixed;
  color: var(--ink);
  -webkit-font-smoothing: antialiased;
  min-height: 100vh;
}

h1, h2, h3, h4 {
  font-weight: 700;
  letter-spacing: -0.025em;
  line-height: 1.15;
  margin: 0;
}

p { margin: 0; }

input[type="text"]:-webkit-autofill,
input[type="email"]:-webkit-autofill,
input[type="password"]:-webkit-autofill,
textarea:-webkit-autofill {
  -webkit-text-fill-color: var(--ink);
  -webkit-box-shadow: 0 0 0 1000px var(--panel-2) inset;
  transition: background-color 9999s ease-in-out 0s;
}

:focus-visible {
  outline: 2px solid var(--blue);
  outline-offset: 3px;
}

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; }
}

/* ---------------------------------------------------------------- *
 * Shared devices: the eyebrow, the rule, the tick
 * ---------------------------------------------------------------- */

/* Metadata voice — anything that labels rather than speaks. */
.eyebrow,
#phase-indicator,
.step-num,
.tagline,
.crumb-trail,
.match-badge,
.crit-pct,
.crit-label,
.stat-row,
.chat-shell-label,
.confirmed-pill,
.onboarding-dots,
.mode-tag {
  font-family: var(--mono);
  font-weight: 400;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-size: 14px;
}

.eyebrow {
  color: var(--blue);
  margin: 0 0 18px;
}

.eyebrow-quiet { color: var(--muted-2); }

/* The tick. Applied to anything that owns a top rule. */
.ticked {
  border-top: 1px solid var(--border);
  position: relative;
}
.ticked::before {
  content: "";
  position: absolute;
  top: -1px;
  left: 0;
  width: var(--tick);
  height: 1px;
  background: var(--blue);
}

/* ---------------------------------------------------------------- *
 * Brand mark
 *
 * The wordmark is set in Jost — the logo's own face — and stays
 * lowercase, so the compass reads as part of the word rather than as a
 * badge stuck beside it. Everything is sized in em off the element's
 * font-size, so the topbar lockup and the hero mark are the same markup
 * at two sizes with no separate geometry to keep in sync.
 * ---------------------------------------------------------------- */

.logo-mark {
  font-family: 'Jost', 'Sora', system-ui, sans-serif;
  font-weight: 300;
  letter-spacing: 0.02em;
  text-transform: lowercase;
  /* Load-bearing. The compass is pinned with `bottom`, which measures
     from the j-wrap's box — and that box is as tall as the line-height.
     Leaving it inherited meant the topbar (body line-height) and the hero
     (line-height 1) anchored the same em offset at two different heights,
     which is why the mark sat off the dot in one of them. Pinning it here
     makes the offset mean the same thing at every size. */
  line-height: 1;
}

.logo-mark .j-wrap {
  position: relative;
  display: inline-block;
}

/* Pinned so the pivot lands on the j's own dot. The pivot is drawn a
   little larger than the dot it replaces and painted over it, which
   avoids masking the dot with a background-coloured patch — that patch
   would be visible in dark mode, where the page carries a gradient the
   flat --bg can't match. */
/* Dimensions come straight from the source file, at 100 SVG units = 1em:
   dial 1.5em wide by 0.75em tall, needle 0.62em at 35 degrees, pivot
   0.15em across. The viewBox is 150 x 82.5 so the artwork fits it
   exactly — 75 units of dial plus the 7.5 the pivot hangs below it. */
.logo-mark .compass {
  position: absolute;
  left: 50%;
  /* Puts the pivot on Jost's j-dot. Derived rather than eyeballed: the
     dot's centre measures 0.670em above the baseline, and with
     line-height 1 the baseline sits 0.153em above this box's bottom, so
     the pivot belongs at 0.823em — less the 0.075em the pivot already
     sits above the svg's own bottom edge. */
  bottom: 0.748em;
  width: 1.5em;
  height: 0.825em;
  transform: translateX(-50%);
  overflow: visible;
  pointer-events: none;
}

/* Hairlines, matching the source's 0.022em border and 0.03em needle.
   Butt caps because the original is a bordered box and a rotated
   rectangle — both have flat ends, and round caps visibly fatten a
   stroke this fine. */
.logo-mark .dial,
.logo-mark .needle {
  fill: none;
  stroke: var(--blue);
  stroke-linecap: butt;
}
.logo-mark .dial { stroke-width: 2.2; }
.logo-mark .needle { stroke-width: 3; }
/* Radius is set on the element rather than here — `r` as a CSS property
   is an SVG-geometry feature with uneven support, and the mark should
   not depend on it. */
.logo-mark .pivot {
  fill: var(--blue);
  stroke: none;
}

/* The hero lockup. Large enough to be the first thing on the page, with
   the dial given room above it so it never crowds the eyebrow.
   Qualified with .brand deliberately: .brand also lands on this element
   and sits later in the file, so at equal specificity it would win the
   font-size and flatten the hero back to topbar scale. */
.brand.logo-hero {
  font-size: clamp(56px, 11vw, 104px);
  font-weight: 300;
  line-height: 1;
  color: var(--ink);
  margin-bottom: 40px;
  padding-top: 0.34em;
}

/* ---------------------------------------------------------------- *
 * Shell
 * ---------------------------------------------------------------- */

#app {
  max-width: var(--page);
  margin: 0 auto;
  padding: 0 32px 120px;
}

.topbar {
  display: flex;
  align-items: center;
  gap: 18px;
  height: 72px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 0;
  position: sticky;
  top: 0;
  z-index: 40;
  /* Repeats the body's own background rather than using a flat colour.
     Dark mode paints a fixed turquoise wash on the body, so a solid fill
     here would sit as a visible rectangle against it as content scrolls
     under. Same layers plus the same `fixed` attachment means the bar is
     painted from the viewport exactly like the body is, and the two line
     up seamlessly.
     Longhands, not the shorthand — --bg-gradient is multi-layer, and the
     shorthand only accepts a colour in its final layer. */
  background-color: var(--bg);
  background-image: var(--bg-gradient);
  background-attachment: fixed;
}

/* .brand only ever appears on the logo, alongside .logo-mark. It carried
   the old Sora-bold treatment (700 weight, tight tracking) and, being
   later in the file at equal specificity, was overriding the Jost
   wordmark above — so it now sets only what isn't the mark's own. */
.brand {
  font-size: 21px;
  color: var(--ink);
}

.tagline {
  color: var(--muted-2);
  letter-spacing: 0.16em;
  padding-left: 18px;
  border-left: 1px solid var(--border);
}

.screen { display: block; }
.hidden { display: none !important; }

/* ---------------------------------------------------------------- *
 * Buttons
 * ---------------------------------------------------------------- */

button {
  font-family: inherit;
  font-size: 17px;
  font-weight: 600;
  letter-spacing: -0.005em;
  color: var(--on-accent);
  background: var(--accent-fill);
  border: 1px solid var(--accent-fill);
  border-radius: var(--radius);
  padding: 12px 22px;
  cursor: pointer;
  transition: background 0.14s ease, border-color 0.14s ease, color 0.14s ease;
}
button:hover { background: var(--accent-fill-hover); border-color: var(--accent-fill-hover); }
button:active { background: var(--accent-fill); }
button:disabled { opacity: 0.4; cursor: default; }
button:disabled:hover { background: var(--accent-fill); border-color: var(--accent-fill); }

/* Dark mode only: the primary button is not a solid turquoise chip. It
   is the dark surface itself, tinted with the accent and edged in it —
   a shaded panel that catches light at the top and falls away toward
   the bottom, carrying light text rather than dark. That puts it in
   the same family as the quiet secondary button beside it: same shape,
   same dark ground, and only the accent on the border and the tint
   telling you which one is the primary action.
   Scoped to the primary fill specifically; every other button class
   here (nav links, tabs, the demote/generate/theme-toggle/show-password
   actions) already overrides `background` to go quiet, and this rule would
   otherwise win on specificity and repaint them regardless of source
   order — the same leak the dark-mode glow work ran into earlier. */
:root[data-theme="dark"] button:not(.secondary-btn):not(.link-btn):not(.text-action):not(.choice-btn):not(.tab-btn):not(.demote-btn):not(.generate-btn):not(.theme-toggle-btn):not(.password-toggle):not(.path-card-footer button):not(.crumb-trail button) {
  background: linear-gradient(180deg, rgba(34,200,190,0.26) 0%, rgba(34,200,190,0.07) 100%);
  border-color: rgba(34,200,190,0.60);
  color: #EAF7F6;
}
:root[data-theme="dark"] button:not(.secondary-btn):not(.link-btn):not(.text-action):not(.choice-btn):not(.tab-btn):not(.demote-btn):not(.generate-btn):not(.theme-toggle-btn):not(.password-toggle):not(.path-card-footer button):not(.crumb-trail button):hover {
  background: linear-gradient(180deg, rgba(34,200,190,0.36) 0%, rgba(34,200,190,0.12) 100%);
  border-color: rgba(34,200,190,0.85);
  color: #FFFFFF;
}
/* Pressed settles the gradient flat — the shading reads as a surface
   catching light, and a press is the moment that surface goes flat. */
:root[data-theme="dark"] button:not(.secondary-btn):not(.link-btn):not(.text-action):not(.choice-btn):not(.tab-btn):not(.demote-btn):not(.generate-btn):not(.theme-toggle-btn):not(.password-toggle):not(.path-card-footer button):not(.crumb-trail button):active {
  background: rgba(34,200,190,0.20);
  border-color: rgba(34,200,190,0.70);
}

.secondary-btn {
  background: transparent;
  color: var(--ink-dim);
  border: 1px solid var(--border);
}
.secondary-btn:hover {
  background: transparent;
  color: var(--blue);
  border-color: var(--blue-border);
}

/* Chrome links — back, sign out, log in, history toggle. Metadata voice,
   so they read as navigation rather than as actions in the page. */
.link-btn {
  background: none;
  border: none;
  padding: 0;
  font-family: var(--mono);
  font-size: 14px;
  font-weight: 400;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  cursor: pointer;
}
.link-btn:hover { background: none; color: var(--blue); }
.link-btn.small { font-size: 13px; }

.small-btn { padding: 7px 14px; font-size: 15px; }

/* An action written as prose, with a rule under it — the editorial
   alternative to a second filled button. */
.text-action {
  background: none;
  border: none;
  border-bottom: 1px solid var(--muted-2);
  border-radius: 0;
  padding: 0 0 3px;
  color: var(--ink);
  font-size: 17px;
  font-weight: 500;
}
.text-action:hover {
  background: none;
  color: var(--blue);
  border-bottom-color: var(--blue);
}

.muted { color: var(--muted); }
.small { font-size: 15.5px; line-height: 1.6; }
p.muted, .muted p { line-height: 1.65; }

/* ---------------------------------------------------------------- *
 * Marketing hero
 * ---------------------------------------------------------------- */

.hero {
  padding: 72px 0 64px;
}

.hero h1 {
  font-size: clamp(38px, 5vw, 62px);
  line-height: 1.02;
  letter-spacing: -0.042em;
  font-weight: 700;
  margin: 0;
  max-width: 17ch;
}

/* The second half of the thesis, set back — the page says what everyone
   else does, then what this does, in one breath. */
.hero h1 .dim { color: var(--muted); display: block; }

.hero-sub {
  margin-top: 30px;
  max-width: 56ch;
  font-size: 20px;
  line-height: 1.62;
  color: var(--ink-dim);
}

.hero-footer { margin-top: 40px; }

/* ---------------------------------------------------------------- *
 * Rail rows — the recurring editorial unit. Mono label in a narrow left
 * column, content in a wide right one, hairline and tick above.
 * ---------------------------------------------------------------- */

.steps {
  margin-top: 24px;
}

.step {
  display: grid;
  grid-template-columns: var(--rail) minmax(0, 1fr);
  gap: 0 var(--gutter);
  padding: 30px 0 34px;
  border-top: 1px solid var(--border);
  position: relative;
}
.step::before {
  content: "";
  position: absolute;
  top: -1px;
  left: 0;
  width: var(--tick);
  height: 1px;
  background: var(--blue);
}

.step-num {
  color: var(--blue);
  padding-top: 6px;
}

.step h3 {
  font-size: 24px;
  font-weight: 600;
  letter-spacing: -0.025em;
  margin-bottom: 12px;
}

.step p {
  font-size: 18.5px;
  line-height: 1.68;
  color: var(--ink-dim);
  max-width: var(--measure);
}

/* ---------------------------------------------------------------- *
 * Calls to action
 * ---------------------------------------------------------------- */

.cta-section {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 0 var(--gutter);
  margin-top: 56px;
}

.cta-option {
  padding: 28px 0 0;
  border-top: 1px solid var(--border);
  position: relative;
}
.cta-option::before {
  content: "";
  position: absolute;
  top: -1px;
  left: 0;
  width: var(--tick);
  height: 1px;
  background: var(--blue);
}

.cta-option p {
  margin-top: 16px;
  max-width: 42ch;
  color: var(--muted);
  font-size: 16px;
  line-height: 1.65;
}

.hero-cta,
.cta-btn {
  padding: 14px 26px;
  font-size: 18px;
}

/* "Try the demo" used to be an outline button so only one filled CTA
   appeared per view. Both are filled now, so the two entry points read as
   equal choices rather than one being the fallback — it takes the base
   button styling with no override of its own. */

.ready-row {
  margin: 32px 0 8px;
  padding-top: 26px;
  border-top: 1px solid var(--border);
  position: relative;
}
.ready-row::before {
  content: "";
  position: absolute;
  top: -1px;
  left: 0;
  width: var(--tick);
  height: 1px;
  background: var(--blue);
}
.ready-row p {
  margin-top: 14px;
  color: var(--muted);
}

.signup-mode-note { margin-bottom: 8px; }
.signup-mode-note:empty { display: none; }

/* ---------------------------------------------------------------- *
 * Section headings
 * ---------------------------------------------------------------- */

.section-heading {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 20px;
  margin: 72px 0 0;
  padding-top: 22px;
  border-top: 1px solid var(--border);
  position: relative;
}
.section-heading::before {
  content: "";
  position: absolute;
  top: -1px;
  left: 0;
  width: var(--tick);
  height: 1px;
  background: var(--blue);
}

.section-heading h2 {
  font-size: 25px;
  font-weight: 600;
  letter-spacing: -0.028em;
}

.section-heading p {
  font-family: var(--mono);
  font-size: 14px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted-2);
  white-space: nowrap;
}

/* ---------------------------------------------------------------- *
 * Panels — the few places a bounded surface still earns its keep
 * (forms and the transcript shell). Squared off, hairline, no fill
 * beyond the faintest lift off the page.
 * ---------------------------------------------------------------- */

.card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 32px;
}

/* Not boxed. Nothing else on the site is, and a lone panel floating in
   the middle of a page of rules is exactly the look this replaced. */
/* Sample exchange on the welcome page. Borrows the transcript's own
   language — named turns, assistant on a tint — so what a visitor sees
   here is literally what the product looks like, not an illustration of
   it. Fixed min-height because the lines type in one at a time and the
   steps below it must not jump on every loop. */
.sample-convo {
  margin: 0 0 48px;
  padding-top: 22px;
  border-top: 1px solid var(--border);
  position: relative;
}
.sample-convo::before {
  content: "";
  position: absolute;
  top: -1px;
  left: 0;
  width: var(--tick);
  height: 1px;
  background: var(--blue);
}

.sample-convo-label {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted-2);
  margin-bottom: 16px;
}

.sample-convo-body {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-height: 232px;
}

.sample-line {
  padding: 12px 16px 14px 18px;
  position: relative;
}
.sample-line::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 2px;
}
.sample-line.assistant {
  background: var(--panel);
  color: var(--ink-dim);
}
.sample-line.assistant::before { background: var(--blue-border); }
.sample-line.user { color: var(--muted); }
.sample-line.user::before { background: var(--border); }

.sample-who {
  display: block;
  margin-bottom: 4px;
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted-2);
}
.sample-line.assistant .sample-who { color: var(--blue); }

.sample-text {
  margin: 0;
  font-size: 15.5px;
  line-height: 1.6;
  max-width: var(--measure);
  min-height: 1.6em;
}

@media (max-width: 760px) {
  .sample-convo-body { min-height: 300px; }
}

/* Above the panel's top rule, so it reads as leaving this screen rather
   than as an action inside the form. */
.auth-back {
  display: inline-block;
  margin-bottom: 26px;
}

.auth-panel {
  padding-top: 22px;
  border-top: 1px solid var(--border);
  position: relative;
}
.auth-panel::before {
  content: "";
  position: absolute;
  top: -1px;
  left: 0;
  width: var(--tick);
  height: 1px;
  background: var(--blue);
}

.card h1, .card h2 {
  font-size: 25px;
  font-weight: 600;
  letter-spacing: -0.028em;
}

/* ---------------------------------------------------------------- *
 * Home: a signed-in student's own progress
 * ---------------------------------------------------------------- */

#home-greeting {
  font-size: clamp(32px, 4.4vw, 48px);
  letter-spacing: -0.038em;
  font-weight: 700;
  padding: 72px 0 0;
}

.home-block {
  margin-top: 56px;
  padding-top: 24px;
  border-top: 1px solid var(--border);
  position: relative;
}
.home-block::before {
  content: "";
  position: absolute;
  top: -1px;
  left: 0;
  width: var(--tick);
  height: 1px;
  background: var(--blue);
}

.admin-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 20px;
}

.admin-header h1, .admin-header h2 {
  font-size: 25px;
  font-weight: 600;
  letter-spacing: -0.028em;
}

.home-status-text {
  margin-top: 10px;
  font-family: var(--mono);
  font-size: 14px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted-2);
}

/* The full-assessment block has no heading any more, so its status line
   is what titles it — carried at full ink strength, the same colour the
   "Full assessment" heading used to be. The demo block still has its own
   heading, so its status stays muted and is untouched by this. */
#home-full-status {
  color: var(--ink);
}

/* What the student is doing now, under what they've finished. Set in the
   accent rather than the muted grey the line above uses: "assessment
   complete" is a closed state, this is the live one, and it should be the
   part that draws the eye. */
.home-status-sub {
  margin-top: 4px;
  font-family: var(--mono);
  font-size: 14px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--blue);
}

/* Profile / analysis blocks read as an article, not as a stack of
   panels — the heading is a mono label and the prose carries itself. */
.profile-card {
  margin-top: 34px;
}

.profile-card h3 {
  font-family: var(--mono);
  font-size: 14px;
  font-weight: 400;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted-2);
  margin-bottom: 14px;
}

.analysis-headline {
  font-size: clamp(24px, 2.6vw, 30px);
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1.28;
  color: var(--ink);
  max-width: 34ch;
  margin-bottom: 16px;
}

.profile-summary {
  font-size: 18.5px;
  line-height: 1.72;
  color: var(--ink-dim);
  max-width: var(--measure);
}

.profile-direction {
  font-size: 22px;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--blue);
  margin-bottom: 10px;
}

.analysis-sections {
  margin-top: 30px;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 0 var(--gutter);
}

.analysis-section {
  padding: 20px 0 4px;
  border-top: 1px solid var(--border);
}

.analysis-section h4 {
  font-size: 18px;
  font-weight: 600;
  letter-spacing: -0.015em;
  color: var(--ink);
  margin-bottom: 8px;
}

.analysis-section p {
  font-size: 17px;
  line-height: 1.68;
  color: var(--ink-dim);
}

.profile-card ul, .profile-card ol {
  margin: 0;
  padding-left: 18px;
  color: var(--ink-dim);
  font-size: 18px;
  line-height: 1.7;
  max-width: var(--measure);
}
.profile-card li { margin-bottom: 8px; }
.profile-card li::marker { color: var(--blue); }

/* Progressive disclosure. Everything on this page that is a paragraph
   rather than a fact lives behind one of these — the home page should be
   readable in about five seconds, and the prose is one click away for
   anyone who actually wants it. */
.disclosure {
  border-top: 1px solid var(--border);
  margin-top: 22px;
  position: relative;
}
.disclosure::before {
  content: "";
  position: absolute;
  top: -1px;
  left: 0;
  width: var(--tick);
  height: 1px;
  background: var(--muted-2);
  transition: background 0.14s ease;
}
.disclosure:hover::before,
.disclosure[open]::before { background: var(--blue); }

.disclosure > summary {
  display: flex;
  align-items: baseline;
  gap: 12px;
  padding: 15px 0;
  cursor: pointer;
  list-style: none;
  font-family: var(--mono);
  font-size: 14px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  transition: color 0.14s ease;
}
.disclosure > summary::-webkit-details-marker { display: none; }
.disclosure > summary:hover { color: var(--blue); }

/* The +/− sits at the far right of the rule, so a column of closed
   disclosures reads as one list of things you can open. */
.disclosure > summary::after {
  content: "+";
  margin-left: auto;
  font-size: 17px;
  line-height: 1;
}
.disclosure[open] > summary { color: var(--ink); }
.disclosure[open] > summary::after { content: "\2212"; }

.disclosure-body { padding: 6px 0 30px; }
.disclosure-body .rec-group:first-child { padding-top: 0; }
.disclosure-body .rec-group:last-child { padding-bottom: 0; }
.disclosure-body .analysis-sections { margin-top: 26px; }
.disclosure-body .profile-card ul,
.disclosure-body ul,
.disclosure-body ol { margin: 0; }

.disclosure-section { margin-top: 40px; }

/* ---------------------------------------------------------------- *
 * The analysis, full page
 *
 * The written analysis as a magazine piece: display headline, a lede
 * with a drop cap, hairline-ruled sections with their own stroke
 * icons, and the model's pull quotes printed large between them.
 * Reached from the prepare screen (the gate into the field stage) and
 * from the home page's "Read the whole thing".
 * ---------------------------------------------------------------- */

.analysis-page {
  max-width: 780px;
  padding: 56px 0 0;
}

.analysis-display {
  font-size: clamp(34px, 5.2vw, 54px);
  font-weight: 700;
  letter-spacing: -0.04em;
  line-height: 1.08;
  color: var(--ink);
  max-width: 22ch;
  margin-bottom: 30px;
}

.analysis-lede {
  font-size: 20px;
  line-height: 1.75;
  color: var(--ink-dim);
  max-width: var(--measure);
}

/* The drop cap — the one unmistakably editorial device on the page,
   set in Jost like the wordmark so it reads as the brand's own hand. */
.analysis-lede::first-letter {
  float: left;
  font-family: 'Jost', 'Sora', system-ui, sans-serif;
  font-weight: 300;
  font-size: 3.6em;
  line-height: 0.82;
  padding: 4px 12px 0 0;
  color: var(--blue);
}

.analysis-mag-sections { margin-top: 26px; }

/* The same layout on the home page, one notch quieter: the analysis
   there sits among the other cards rather than being the whole screen,
   and the card's own "YOUR ANALYSIS" label plus the headline above it
   already announce it. */
#home-full-card-analysis .analysis-lede { margin-top: 18px; }
#home-full-card-analysis .mag-section { margin-top: 30px; }
#home-full-card-analysis .mag-pull { margin: 38px 0 6px; }

.mag-section {
  margin-top: 40px;
  padding: 26px 0 6px;
}

.mag-section-head {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 14px;
}

.mag-icon {
  width: 24px;
  height: 24px;
  flex: none;
  color: var(--blue);
}
.mag-icon svg { display: block; width: 100%; height: 100%; }

.mag-section-head h2 {
  font-size: 22px;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--ink);
}

.mag-num {
  margin-left: auto;
  font-family: var(--mono);
  font-size: 13px;
  letter-spacing: 0.14em;
  color: var(--muted-2);
}

.mag-body {
  font-size: 18px;
  line-height: 1.75;
  color: var(--ink-dim);
  max-width: var(--measure);
}

/* Pull quote: the model's own one-line distillation of the section it
   follows, printed at display size against the accent rule. */
.mag-pull {
  margin: 46px 0 6px;
  padding: 4px 0 4px 26px;
  border-left: 2px solid var(--blue);
  font-size: clamp(22px, 2.7vw, 28px);
  font-weight: 600;
  letter-spacing: -0.025em;
  line-height: 1.34;
  color: var(--ink);
  max-width: 28ch;
}

.analysis-page-footer {
  margin-top: 72px;
  padding-top: 26px;
  border-top: 1px solid var(--border);
  position: relative;
}
.analysis-page-footer::before {
  content: "";
  position: absolute;
  top: -1px;
  left: 0;
  width: var(--tick);
  height: 1px;
  background: var(--blue);
}
.analysis-footer-note { margin-bottom: 20px; }

/* ---------------------------------------------------------------- *
 * The round checkpoint
 *
 * One paragraph — "what we've put together about you so far" — and a
 * Continue button, shown between rounds 1→2 and 2→3. Same card family
 * as the onboarding and prepare screens.
 * ---------------------------------------------------------------- */

/* ---------------------------------------------------------------- *
 * Voice
 *
 * The Voice on/off toggle (chat header + fields topbar) and the
 * floating status pill that says what the mic is doing. Same metadata
 * voice as every other label on the site.
 * ---------------------------------------------------------------- */

.voice-toggle {
  background: none;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 5px 12px;
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 400;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  position: relative;
  padding-left: 26px;
}
.voice-toggle:hover { background: none; border-color: var(--muted-2); color: var(--ink); }
/* The state dot: filled turquoise when on, hollow when off. */
.voice-toggle::before {
  content: "";
  position: absolute;
  left: 11px;
  top: 50%;
  transform: translateY(-50%);
  width: 7px;
  height: 7px;
  border-radius: 50%;
  border: 1px solid var(--muted-2);
}
.voice-toggle.is-on { color: var(--blue); border-color: var(--blue-border); }
.voice-toggle.is-on::before { background: var(--blue); border-color: var(--blue); }

.voice-pill {
  position: fixed;
  bottom: 26px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 60;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 9px 18px 9px 34px;
  font-family: var(--mono);
  font-size: 13px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-dim);
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.25);
}
.voice-pill.hidden { display: none; }
.voice-pill::before {
  content: "";
  position: absolute;
  left: 15px;
  top: 50%;
  transform: translateY(-50%);
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--muted-2);
}
.voice-pill.listening { color: var(--blue); border-color: var(--blue-border); }
.voice-pill.listening::before {
  background: var(--blue);
  animation: voice-pulse 1.4s ease-in-out infinite;
}
.voice-pill.transcribing::before { background: var(--blue); }
.voice-pill.error { color: var(--error); border-color: var(--error-border); }
.voice-pill.error::before { background: var(--error); }

@keyframes voice-pulse {
  0%, 100% { opacity: 0.35; transform: translateY(-50%) scale(0.8); }
  50% { opacity: 1; transform: translateY(-50%) scale(1.25); }
}

@media (prefers-reduced-motion: reduce) {
  .voice-pill.listening::before { animation: none; }
}

.onboarding-voice-row {
  margin-top: 24px;
  display: flex;
  align-items: center;
  gap: 22px;
}

/* ---------------------------------------------------------------- *
 * The full transcript (admin only)
 * ---------------------------------------------------------------- */

.admin-transcript-row {
  margin-top: 64px;
  padding-top: 22px;
  border-top: 1px solid var(--border);
}
.admin-transcript-row .eyebrow { margin-bottom: 14px; }

.transcript-page {
  max-width: 780px;
  padding: 56px 0 0;
}

.transcript-back {
  display: block;
  margin-bottom: 34px;
}

.transcript-title {
  font-size: clamp(28px, 3.6vw, 38px);
  font-weight: 700;
  letter-spacing: -0.035em;
  margin-bottom: 8px;
}

/* Same device as the round bars' labels: a mono rule-caption marking
   where each round begins in the stream. */
.transcript-divider {
  margin: 44px 0 10px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
  position: relative;
  font-family: var(--mono);
  font-size: 13px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}
.transcript-divider::before {
  content: "";
  position: absolute;
  top: -1px;
  left: 0;
  width: var(--tick);
  height: 1px;
  background: var(--blue);
}

.round-summary-card { padding-top: 96px; }

.round-summary-text {
  font-size: 20px;
  line-height: 1.78;
  color: var(--ink-dim);
  max-width: var(--measure);
  margin-bottom: 28px;
}

/* What the next round asks of them — quieter than the summary above,
   sitting right against the Continue button it frames. */
.round-summary-next {
  font-size: 17px;
  line-height: 1.7;
  color: var(--muted);
  max-width: var(--measure);
  margin-bottom: 40px;
}

/* Fields the student is exploring. Same rhythm as the colleges/next-steps
   groups it sits next to inside its own disclosure — small type, a
   one-line rationale in gray underneath — rather than the large bold
   list style this used before those three were made to match. */
.field-summary-list { margin-top: 0; }

.field-summary-row {
  display: block;
  position: relative;
  padding: 18px 26px 18px 0;
  border-bottom: 1px solid var(--border-soft);
  cursor: pointer;
  transition: border-color 0.14s ease;
}
.field-summary-row:last-child { border-bottom: none; }
.field-summary-row:hover { border-bottom-color: var(--blue-border); }
.field-summary-row:hover .field-summary-title { color: var(--blue-hover); }

.field-summary-title {
  display: block;
  font-size: 17px;
  font-weight: 500;
  letter-spacing: -0.01em;
  color: var(--blue);
  transition: color 0.14s ease;
}

.field-summary-desc {
  display: block;
  margin-top: 6px;
  font-size: 16.5px;
  line-height: 1.62;
  color: var(--muted);
  max-width: var(--measure);
}

/* Written by app.js on every row; carried in the markup so the row stays
   clickable and accessible, shown only as a hover affordance. */
.field-summary-row::after {
  content: "\2192";
  position: absolute;
  top: 18px;
  right: 0;
  color: var(--muted-2);
  opacity: 0;
  transition: opacity 0.14s ease, color 0.14s ease;
}
.field-summary-row:hover::after { opacity: 1; color: var(--blue); }

.continue-row {
  margin-top: 46px;
  padding-top: 26px;
  border-top: 1px solid var(--border);
}

/* Recommendations, grouped by the field that produced them. */
.rec-panel { margin-top: 8px; }

.rec-group { padding: 24px 0; }
.rec-group:last-child { padding-bottom: 0; }

.rec-group h4 {
  font-family: var(--mono);
  font-size: 14px;
  font-weight: 400;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--blue);
  margin-bottom: 12px;
}

.rec-group ul, .rec-group ol {
  margin: 0;
  padding-left: 20px;
  font-size: 18px;
  line-height: 1.72;
  color: var(--ink-dim);
  max-width: var(--measure);
}
.rec-group li { margin-bottom: 8px; }
.rec-group li::marker { color: var(--muted-2); }

.rec-divider {
  height: 1px;
  background: var(--border);
}

.mode-hint {
  margin-top: 14px;
  color: var(--muted-2);
}

/* ---------------------------------------------------------------- *
 * Auth
 * ---------------------------------------------------------------- */

#auth-forms {
  max-width: 440px;
  margin: 96px 0 0;
}

.auth-tabs {
  display: flex;
  gap: 28px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 32px;
}

.tab-btn {
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  border-radius: 0;
  padding: 0 0 14px;
  font-family: var(--mono);
  font-size: 14px;
  font-weight: 400;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted-2);
  margin-bottom: -1px;
}
.tab-btn:hover { background: none; color: var(--ink-dim); }
.tab-btn.active { color: var(--blue); border-bottom-color: var(--blue); }

.auth-form { display: flex; flex-direction: column; }

.auth-form .forgot-link {
  margin-top: 16px;
  align-self: flex-start;
}

.auth-form label {
  font-family: var(--mono);
  font-size: 13px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted-2);
  margin-bottom: 8px;
}

input[type="text"], input[type="email"], input[type="password"], textarea {
  font-family: inherit;
  font-size: 18px;
  color: var(--ink);
  background: transparent;
  border: none;
  border-bottom: 1px solid var(--border);
  border-radius: 0;
  padding: 10px 0 12px;
  margin-bottom: 26px;
  transition: border-color 0.14s ease;
}
input[type="text"]:focus, input[type="email"]:focus, input[type="password"]:focus {
  outline: none;
  border-bottom-color: var(--blue);
}
input::placeholder, textarea::placeholder { color: var(--muted-2); }

.auth-form button[type="submit"] {
  align-self: flex-start;
  margin-top: 4px;
  padding: 13px 28px;
}

/* Show/hide password. The wrapper carries the spacing the input used to
   own, so the toggle can sit on the baseline of the underline without the
   26px gap pushing it away from the field it belongs to. */
.password-field {
  position: relative;
  display: block;
  margin-bottom: 26px;
}
.password-field input {
  width: 100%;
  margin-bottom: 0;
  /* Room for the word, so a long password never runs under it. */
  padding-right: 62px;
}

/* A word rather than an eye icon: the two eye states (open/closed) are
   read in opposite directions by different people, and "Show"/"Hide" says
   what pressing it does. Styled as a quiet control, not a second button
   competing with Start. */
.password-toggle {
  position: absolute;
  right: 0;
  bottom: 10px;
  padding: 4px 2px;
  background: none;
  border: none;
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted-2);
  cursor: pointer;
}
.password-toggle:hover {
  background: none;
  color: var(--blue);
}
.password-toggle:focus-visible {
  outline: 2px solid var(--blue);
  outline-offset: 2px;
}

/* ---------------------------------------------------------------- *
 * Admin: the student list
 * ---------------------------------------------------------------- */

#admin-view { padding-top: 72px; }

.admin-list-hint {
  margin: 14px 0 8px;
  color: var(--muted);
  max-width: var(--measure);
}

.student-list { margin-top: 20px; }

.student-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  padding: 22px 0;
  border-top: 1px solid var(--border);
  cursor: pointer;
  transition: background 0.14s ease;
}
.student-row:hover { background: var(--row-hover); }
.student-row:hover .name { color: var(--blue); }

.student-row .name {
  font-size: 19px;
  font-weight: 600;
  letter-spacing: -0.02em;
  transition: color 0.14s ease;
}

.student-row .meta {
  font-family: var(--mono);
  font-size: 13px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted-2);
  margin-top: 6px;
}

.slot-row {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-top: 10px;
}
.slot-row .muted {
  font-family: var(--mono);
  font-size: 14px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted-2);
}

.mode-tag { color: var(--blue); }

/* ---------------------------------------------------------------- *
 * Onboarding
 * ---------------------------------------------------------------- */

.onboarding-card {
  max-width: 720px;
  padding: 80px 0 0;
}

.onboarding-dots {
  display: flex;
  gap: 8px;
  margin-bottom: 40px;
}

/* Ticks rather than dots — same device as every other rule on the site,
   and they read as progress along a line instead of as decoration. */
.onboarding-dots .dot {
  width: 34px;
  height: 2px;
  background: var(--border);
  transition: background 0.2s ease;
}
.onboarding-dots .dot.active { background: var(--blue); }

.onboarding-title {
  font-size: clamp(30px, 4vw, 42px);
  font-weight: 700;
  letter-spacing: -0.038em;
  line-height: 1.08;
  margin-bottom: 24px;
}

.onboarding-intro {
  font-size: 19px;
  color: var(--muted);
  margin-bottom: 8px;
}

.onboarding-slide p {
  font-size: 19px;
  line-height: 1.72;
  color: var(--ink-dim);
  max-width: var(--measure);
  margin-bottom: 20px;
}

.onboarding-slide .step { padding: 26px 0 28px; }
.onboarding-slide .step p { margin-bottom: 0; }

.onboarding-next-btn { margin-top: 24px; }

/* ---------------------------------------------------------------- *
 * Preparing phase 2
 * ---------------------------------------------------------------- */

#screen-prepare .onboarding-card { padding-top: 120px; }

/* Same card as the phase screen, smaller in every dimension that
   signals importance: less drop from the top, a smaller title, a
   narrower bar. The phase screen keeps the eyebrow, the sub-paragraph,
   the step list and the button — this one has none of them, which is
   what makes it read as a pause rather than a milestone. */
#screen-round .onboarding-card { padding-top: 96px; }
#round-title {
  font-size: 30px;
  margin-bottom: 26px;
}
#screen-round .prepare-progress { max-width: 360px; }
#screen-round .prepare-narration { margin-bottom: 0; }

#prepare-sub {
  font-size: 19px;
  line-height: 1.7;
  max-width: var(--measure);
  margin-bottom: 44px;
}

/* The wait is a couple of minutes of model time. A bar that actually
   advances is the difference between "working" and "frozen" — but it
   stays a hairline in the same language as the ticks and rules rather
   than becoming a chunky loader bolted onto an editorial layout. */
.prepare-progress {
  position: relative;
  height: 3px;
  margin: 4px 0 18px;
  background: var(--border);
  overflow: hidden;
}

.prepare-progress-fill {
  height: 100%;
  width: 0;
  background: var(--blue);
  /* Matches the 200ms driver tick, so the bar glides between samples
     instead of stepping. */
  transition: width 0.24s linear;
}

.prepare-narration {
  margin: 0 0 30px;
  min-height: 1.6em;
  font-family: var(--mono);
  font-size: 13px;
  letter-spacing: 0.04em;
  color: var(--muted);
  opacity: 0;
  transform: translateY(3px);
}
.prepare-narration.is-in {
  opacity: 1;
  transform: none;
  transition: opacity 0.45s ease, transform 0.45s ease;
}

@media (prefers-reduced-motion: reduce) {
  .prepare-progress-fill { transition: none; }
  .prepare-narration, .prepare-narration.is-in {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

.prepare-steps {
  list-style: none;
  margin: 0 0 36px;
  padding: 0;
}

.prepare-steps li {
  position: relative;
  padding: 20px 0 20px 42px;
  border-top: 1px solid var(--border);
  font-size: 19px;
  color: var(--muted-2);
  transition: color 0.2s ease;
}

.prepare-steps li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 27px;
  width: 22px;
  height: 1px;
  background: var(--border);
  transition: background 0.2s ease, width 0.2s ease;
}

.prepare-steps li.active { color: var(--ink); }
.prepare-steps li.active::before {
  background: var(--blue);
  animation: tick-scan 1.7s ease-in-out infinite;
}

/* The only animation on the site. This is the one screen where the
   student waits on the machine for two minutes with nothing to do, so
   the active tick has to prove something is still happening. */
@keyframes tick-scan {
  0%, 100% { width: 9px; opacity: 0.5; }
  50% { width: 30px; opacity: 1; }
}

.prepare-steps li.done { color: var(--ink-dim); }
.prepare-steps li.done::before { background: var(--muted-2); }

#prepare-continue-btn, #prepare-retry-btn { margin-top: 8px; }

/* ---------------------------------------------------------------- *
 * Chat / the phase 1 question flow
 * ---------------------------------------------------------------- */

.chat-layout { padding-top: 0; }

.chat-main { max-width: 780px; }

.chat-header {
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 26px 0;
  border-bottom: 1px solid var(--border);
  margin-bottom: 22px;
}

.chat-student-name {
  font-size: 17px;
  font-weight: 600;
  letter-spacing: -0.015em;
}

#phase-indicator {
  color: var(--muted-2);
  text-align: center;
  margin: 0 0 10px;
}

#signout-btn { margin-left: auto; }

.quiz-body { padding-bottom: 40px; }

/* The question is the page. No box — a turquoise tick down the left
   edge instead, the same mark the rules use, rotated to vertical. */
.question-card {
  border-left: 2px solid var(--blue);
  padding: 4px 0 4px 26px;
  margin-bottom: 40px;
}

.question-text {
  font-size: clamp(23px, 2.6vw, 30px);
  font-weight: 500;
  letter-spacing: -0.028em;
  line-height: 1.36;
  color: var(--ink);
  max-width: 34ch;
  white-space: pre-wrap;
  /* The text is revealed a character at a time, and the last line's
     length changes on every frame. Without a floor the whole card
     collapses to one line and grows as it types, shoving the answer
     controls below it down the page while the student is reading. */
  min-height: 1.36em;
}

/* A caret while the text is being written, so the reveal reads as
   composition rather than as a rendering glitch. It is part of the
   animation, so it goes away with the animation under reduced motion. */
.question-text.is-typing::after {
  content: "";
  display: inline-block;
  width: 0.06em;
  height: 0.92em;
  margin-left: 0.06em;
  vertical-align: -0.1em;
  background: var(--blue);
  animation: type-caret 1s steps(2, start) infinite;
}

@keyframes type-caret {
  0%, 50% { opacity: 1; }
  50.01%, 100% { opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .question-text.is-typing::after { display: none; }
}

.answer-widget { margin-bottom: 32px; }

.widget-hint {
  color: var(--muted-2);
  margin-bottom: 14px;
  font-family: var(--mono);
  font-size: 13px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.widget-choices, .widget-scale {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.choice-btn {
  background: transparent;
  color: var(--ink-dim);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 11px 18px;
  font-size: 17px;
  font-weight: 400;
}
.choice-btn:hover {
  background: transparent;
  color: var(--blue);
  border-color: var(--blue-border);
}
.choice-btn.selected {
  background: var(--blue-soft);
  color: var(--blue);
  border-color: var(--blue);
}

.scale-btn {
  min-width: 46px;
  font-family: var(--mono);
  text-align: center;
  padding: 11px 0;
}

.widget-submit-btn { margin-top: 14px; }

.message-form {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 16px;
  padding-top: 26px;
  border-top: 1px solid var(--border);
}

.message-form textarea {
  width: 100%;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--panel);
  padding: 16px 18px;
  margin-bottom: 0;
  font-size: 18px;
  line-height: 1.6;
  resize: vertical;
  min-height: 96px;
}
.message-form textarea:focus {
  outline: none;
  border-color: var(--blue-border);
}

/* #thinking-indicator used to be styled here. The assessment chat now
   swaps the send button for the rocking compass (.sending-compass, below)
   for the whole round trip, same as the field chat. */

#history-toggle { margin-top: 40px; }

.messages {
  margin-top: 26px;
  padding-top: 26px;
  border-top: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  /* Each line now carries its own padding and ground, so they butt up
     against each other and read as one continuous transcript. The old
     22px gap was sized for bare unpadded lines and now reads as a stack
     of disconnected cards. */
  gap: 3px;
}

/* Transcript lines are attributed by a name and a ground tint, not by
   opposing bubbles. Opposing bubbles are the grammar of a messaging app;
   this is a record of work, so it reads as one. The line runs full-bleed
   while the TEXT inside it keeps the prose measure — the ground marks who
   is speaking, the measure keeps it readable. */
.bubble {
  position: relative;
  padding: 16px 20px 18px 22px;
  font-size: 17.5px;
  line-height: 1.7;
  white-space: pre-wrap;
}
.bubble::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 2px;
}

.bubble-who {
  display: block;
  margin-bottom: 6px;
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted-2);
}

.bubble-text {
  margin: 0;
  max-width: var(--measure);
}

/* The assistant's turns sit on a tint because they are the output being
   read; the student's own turns stay on the page ground. */
.bubble.assistant {
  background: var(--panel);
  color: var(--ink-dim);
}
.bubble.assistant::before { background: var(--blue-border); }
.bubble.assistant .bubble-who { color: var(--blue); }

.bubble.user {
  background: transparent;
  color: var(--muted);
}
.bubble.user::before { background: var(--border); }

.error-banner {
  margin-top: 24px;
  padding: 14px 18px;
  border-left: 2px solid var(--error);
  background: var(--error-bg);
  color: var(--error);
  font-size: 17px;
  line-height: 1.6;
}

/* ---------------------------------------------------------------- *
 * Phase 2: fields
 * ---------------------------------------------------------------- */

.fields-topbar {
  display: flex;
  align-items: center;
  gap: 20px;
  padding: 26px 0;
  border-bottom: 1px solid var(--border);
  margin-bottom: 56px;
}

.fields-topbar .crumb-trail { margin-left: 4px; }
#fields-signout-btn { margin-left: auto; }

.crumb-trail {
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--muted-2);
}

.crumb-trail button {
  background: none;
  border: none;
  padding: 0;
  font-family: var(--mono);
  font-size: 14px;
  font-weight: 400;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
}
.crumb-trail button:hover { background: none; color: var(--blue); }
.crumb-trail button.current { color: var(--ink); }
.crumb-trail button.current:hover { color: var(--ink); cursor: default; }

.crumb-sep { color: var(--muted-2); }

.card-grid-view.hidden { display: none !important; }

.path-intro { max-width: 720px; }

.path-intro h3 {
  font-size: clamp(30px, 4vw, 44px);
  font-weight: 700;
  letter-spacing: -0.04em;
  line-height: 1.04;
  margin-bottom: 20px;
}

.path-intro p {
  font-size: 19px;
  line-height: 1.68;
  color: var(--ink-dim);
  max-width: var(--measure);
}

/* Counts as a readout, spaced along a rule. */
.path-status-line {
  display: flex;
  gap: 34px;
  margin: 44px 0 0;
  padding: 16px 0;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  font-family: var(--mono);
  font-size: 14px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted-2);
}
.path-status-line b { color: var(--blue); font-weight: 500; }

/* The grid is an index of fields. Each entry owns a rule and a tick;
   nothing is boxed. */
.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  /* Wider than the shared --gutter used elsewhere. Each card now carries
     a tinted ground that bleeds 20px past the text column on both sides,
     so the default 40px gutter left the two columns' grounds touching in
     the middle with no visible channel between them. */
  gap: 26px 72px;
  margin-top: 0;
}

.path-card {
  display: flex;
  flex-direction: column;
  padding: 26px 0 44px;
  border-top: 1px solid var(--border);
  position: relative;
  transition: border-color 0.16s ease;
}
.path-card::before {
  content: "";
  position: absolute;
  top: -1px;
  left: 0;
  width: var(--tick);
  height: 1px;
  background: var(--muted-2);
  transition: background 0.16s ease, width 0.16s ease;
}
.path-card:hover::before { background: var(--blue); width: 100%; }

.path-card.demoted { opacity: 0.42; }
.path-card.demoted::before { background: var(--border); }
.path-card.demoted:hover { opacity: 0.7; }

.path-card.confirmed::before,
.card-grid .path-card:first-child:not(.demoted)::before {
  background: var(--blue);
}

/* "Outside the box" — the deliberately niche, surprising cards, named
   by the turquoise tag under the title. */
.outside-box-tag {
  display: inline-block;
  font-family: var(--mono);
  font-weight: 400;
  font-size: 12px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--blue);
  border: 1px solid var(--blue-border);
  border-radius: var(--radius);
  padding: 3px 9px;
}

/* On a card, the tag rides the footer line, bottom right — level with
   "Explore this field" — so it costs the card no vertical space. The
   footer becomes the flex row only when a tag is actually in it, via
   :has(), so plain cards keep the exact layout they had. */
.path-card-footer:has(.outside-box-tag) {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.path-card .outside-box-tag {
  font-size: 12px;
  line-height: 1;
  padding: 4px 8px;
}

/* On the field's own page the tag sits alone above the title. */
.field-page > .outside-box-tag { margin-bottom: 14px; }

/* On the home page's field list it rides inline after the title. */
.field-summary-row .outside-box-tag {
  font-size: 11px;
  padding: 2px 7px;
  margin-left: 8px;
  vertical-align: 2px;
}

.path-card-top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
}

.path-title {
  font-size: 22px;
  font-weight: 600;
  letter-spacing: -0.028em;
  line-height: 1.22;
  /* Two lines' worth, always — field names run long and short, and the
     stat rows underneath have to line up across a row of the grid. */
  min-height: 2.44em;
}

/* The match number is the one place a figure gets to be typography — only
   the digits are turquoise, "match" stays metadata-gray. app.js wraps the
   number in .match-num; the surrounding text is a plain text node. */
.match-badge {
  color: var(--muted);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.08em;
}

.match-badge .match-num { color: var(--blue); font-size: 16px; }

/* Always one line — three figures side by side is the point, wrapping to
   two lines would make the card's rhythm uneven row to row. The figures
   stay at their full size; it's the label text and the gaps around them
   that give way first when a card is narrow. */
.stat-row {
  display: flex;
  flex-wrap: nowrap;
  align-items: baseline;
  gap: 0 6px;
  margin-top: 12px;
  color: var(--muted-2);
  font-size: 10px;
  letter-spacing: 0.1em;
  overflow-x: auto;
  scrollbar-width: none;
}
.stat-row::-webkit-scrollbar { display: none; }
.stat-row .stat {
  display: flex;
  align-items: baseline;
  gap: 3px;
  white-space: nowrap;
  flex-shrink: 0;
}
.stat-row .stat b {
  font-size: 13px;
  color: var(--ink-dim);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
}
.stat-row .stat-sep { color: var(--border); flex-shrink: 0; }

@media (max-width: 380px) {
  .stat-row { font-size: 9px; gap: 0 5px; }
  .stat-row .stat { gap: 2px; }
}

.path-rationale {
  margin-top: 16px;
  font-size: 17.5px;
  line-height: 1.68;
  color: var(--ink-dim);
  flex: 1;
}

.path-card-footer { margin-top: 22px; }

.path-card-footer button {
  background: none;
  border: none;
  border-bottom: 1px solid var(--muted-2);
  border-radius: 0;
  padding: 0 0 3px;
  color: var(--ink);
  font-size: 17px;
  font-weight: 500;
}
.path-card-footer button:hover {
  background: none;
  color: var(--blue);
  border-bottom-color: var(--blue);
}

.confirmed-pill {
  color: var(--blue);
  letter-spacing: 0.12em;
}

.generate-row {
  margin-top: 48px;
  padding-top: 26px;
  border-top: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: 20px;
  flex-wrap: wrap;
}

.generate-btn {
  background: transparent;
  color: var(--ink-dim);
  border: 1px solid var(--border);
  font-family: var(--mono);
  font-size: 14px;
  font-weight: 400;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 12px 20px;
}
.generate-btn:hover {
  background: transparent;
  color: var(--blue);
  border-color: var(--blue-border);
}

/* ---------------------------------------------------------------- *
 * A single field's page
 * ---------------------------------------------------------------- */

.chat-view.hidden { display: none !important; }

.field-page { max-width: 780px; }

.field-head {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 12px 20px;
}

.field-head h1 {
  font-size: clamp(32px, 4.4vw, 48px);
  font-weight: 700;
  letter-spacing: -0.04em;
  line-height: 1.04;
  flex: 1 1 auto;
}

.field-head .match-badge {
  font-size: 16px;
  letter-spacing: 0.1em;
}

.field-head .match-badge .match-num { font-size: 18px; }

/* Pushed to the far edge — it's the one destructive action on the page
   and shouldn't sit close enough to the match figure to be misread as
   part of it. */
.field-head .demote-btn { margin-left: auto; }

.demote-btn {
  background: none;
  border: none;
  padding: 0;
  font-family: var(--mono);
  font-size: 13px;
  font-weight: 400;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted-2);
}

/* Pinned to the question's top-right corner. The card reserves room for
   it on the right so a long question wraps before it reaches the button
   rather than running underneath it.
   `position: relative` is load-bearing: .question-card has no position of
   its own, so without it the absolutely-positioned button escapes to the
   viewport and lands in the page's top-right corner instead of the
   card's. */
.question-card-actionable {
  position: relative;
  padding-right: 130px;
}
.question-demote-btn {
  position: absolute;
  top: 2px;
  right: 0;
  font-size: 12px;
}
.question-demote-btn:hover { color: var(--error); }

@media (max-width: 620px) {
  /* No room for a corner at phone width — it goes back to sitting above
     the question rather than overlapping it. */
  .question-card-actionable { padding-right: 0; padding-top: 26px; }
  .question-demote-btn { top: 0; }
}
.demote-btn:hover { background: none; color: var(--error); }
.demote-btn.hidden { display: none !important; }

.field-description {
  margin-top: 22px;
  font-size: 19.5px;
  line-height: 1.68;
  color: var(--ink-dim);
  max-width: var(--measure);
}

.criteria-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 0 var(--gutter);
  margin-top: 44px;
}

.criterion {
  padding: 20px 0 6px;
  border-top: 1px solid var(--border);
}

.criterion .crit-head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin-bottom: 12px;
}

/* The three axis figures, set large in mono — the numbers are the
   argument the card is making, so they get to look like it. */
.criterion .crit-pct {
  font-size: 29px;
  letter-spacing: -0.02em;
  color: var(--blue);
  font-variant-numeric: tabular-nums;
}

.criterion .crit-label {
  font-size: 13px;
  color: var(--muted-2);
}

.criterion p {
  font-size: 16.5px;
  line-height: 1.65;
  color: var(--muted);
}

.section-divider {
  height: 1px;
  background: var(--border);
  margin: 56px 0 0;
}

.get-next-steps-row { margin-top: 40px; }

.outcome-section { margin-top: 52px; }

.outcome-section h3 {
  font-family: var(--mono);
  font-size: 14px;
  font-weight: 400;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--blue);
  margin-bottom: 20px;
}

.verdict-card {
  padding-top: 22px;
  border-top: 1px solid var(--border);
}

.verdict-card h5 {
  font-size: 18px;
  font-weight: 600;
  letter-spacing: -0.02em;
  margin: 0 0 12px;
}
.verdict-card h5:not(:first-of-type) { margin-top: 30px; }

.verdict-card ol, .verdict-card ul {
  margin: 0;
  padding-left: 20px;
  font-size: 18px;
  line-height: 1.72;
  color: var(--ink-dim);
  max-width: var(--measure);
}
.verdict-card li { margin-bottom: 8px; }
.verdict-card ol li::marker { color: var(--blue); }
.verdict-card ul li::marker { color: var(--muted-2); }

/* The send button becomes this while an answer is in flight — the product's
   own compass, swinging the way a needle does before it settles. It sits
   in the button's place rather than beside it so the confirmation lands
   exactly where the student was looking when they pressed.

   Sized and weighted to match the button it replaces, so the row doesn't
   reflow when they swap. */
.sending-compass {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 46px;
  padding: 0 22px;
}

/* Square, unlike the logo's half-dial — this one is a whole instrument
   rather than a mark sitting on a letterform. */
.sending-compass .compass {
  width: 26px;
  height: 26px;
  overflow: visible;
}

.sending-compass .dial,
.sending-compass .needle {
  fill: none;
  stroke: var(--blue);
  stroke-linecap: butt;
}
.sending-compass .dial { stroke-width: 2.2; }
.sending-compass .needle { stroke-width: 3; }
.sending-compass .pivot { fill: var(--blue); stroke: none; }

/* Only the needle moves. Rocking the whole dial would read as a wobbling
   object; a needle swinging past the bearing and back is what a compass
   actually does while it's looking for north, which is the exact thing
   being communicated. Rotated about the pivot (75,75), not the box —
   and since the needle is drawn pointing at north, the swing is
   symmetrical about north rather than starting from it. */
.sending-compass .needle {
  transform-origin: 75px 75px;
  animation: compass-swing 1.5s ease-in-out infinite;
}

@keyframes compass-swing {
  0%, 100% { transform: rotate(-30deg); }
  50%      { transform: rotate(30deg); }
}

/* Motion is the whole point here, so with reduced motion the needle holds
   still and the dial pulses instead — quieter, but still clearly live. */
@media (prefers-reduced-motion: reduce) {
  .sending-compass .needle { animation: none; }
  .sending-compass .compass { animation: compass-hold 1.6s ease-in-out infinite; }
}

@keyframes compass-hold {
  0%, 100% { opacity: 0.45; }
  50%      { opacity: 1; }
}

/* "Finding colleges" — stands in for the named-college list while those
   names are still being checked against the live web (see
   startCollegeCheck). Everything else in the outcome is ready
   immediately; this is the only part that has to wait, so it says so
   rather than showing names that might not survive the check.

   The mark is the same scanning tick the prepare screen uses, not a
   spinner. Ticks and hairline rules are the structural vocabulary
   throughout this theme, and a rotating circle would be the only one of
   its kind on the site. Set at the list's own font size so the line sits
   on the same baseline the names will occupy when they arrive. */
.colleges-pending {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 0;
  font-size: 18px;
  line-height: 1.72;
  color: var(--muted);
}

.colleges-spinner {
  flex-shrink: 0;
  height: 2px;
  width: 26px;
  background: var(--blue);
  animation: tick-scan 1.7s ease-in-out infinite;
}

@media (prefers-reduced-motion: reduce) {
  .colleges-spinner { animation: none; opacity: 0.75; }
}

/* Carries the "still checking" wording to a screen reader without
   repeating it visually next to the spinner. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* The field's own conversation, shown in full inline. */
.chat-shell { margin-top: 44px; }

.chat-shell-label {
  color: var(--muted-2);
  margin-bottom: 26px;
}

.chat-body { display: flex; flex-direction: column; }

.chat-body .question-card { margin-bottom: 32px; }
.chat-body .message-form { margin-top: 8px; }
/* The history toggle and the thinking line are appended by app.js rather
   than written into the markup, so they get their spacing from here. */
.chat-body .link-btn { margin-top: 32px; }
#fields-thinking-indicator {
  margin-top: 18px;
  font-family: var(--mono);
  font-size: 14px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--blue);
}

.prior-msgs { margin-top: 26px; }
.prior-msgs:empty { display: none; }

.choice-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 8px;
}
.choice-row .choice-btn.negative:hover {
  color: var(--error);
  border-color: var(--error-border);
}

/* ---------------------------------------------------------------- *
 * Narrow screens
 * ---------------------------------------------------------------- */

@media (max-width: 760px) {
  #app { padding: 0 20px 80px; }
  .tagline { display: none; }
  .hero { padding: 60px 0 48px; }
  .step {
    grid-template-columns: minmax(0, 1fr);
    gap: 12px;
    padding: 24px 0 28px;
  }
  .step-num { padding-top: 0; }
  .cta-section { gap: 0; }
  .cta-option { margin-bottom: 34px; }
  .card-grid, .criteria-grid, .analysis-sections { grid-template-columns: minmax(0, 1fr); }
  .chat-header { flex-wrap: wrap; gap: 10px; margin-bottom: 18px; }
  #signout-btn { margin-left: auto; }
  .path-status-line { gap: 6px 18px; flex-wrap: wrap; }
  /* Three items of chrome don't fit on one phone-width line — the
     breadcrumb drops below the back/sign-out row rather than squeezing. */
  .fields-topbar { flex-wrap: wrap; gap: 12px; margin-bottom: 40px; }
  .fields-topbar .crumb-trail { order: 3; flex-basis: 100%; margin-left: 0; }
  #fields-signout-btn { margin-left: auto; }
  .field-head .demote-btn { margin-left: 0; }
  .question-card { padding-left: 18px; }
  .card { padding: 24px 20px; }
  #home-greeting { padding-top: 48px; }
}

/* ---------------------------------------------------------------- *
 * Light mode
 *
 * Not an inversion. The dark background is #0A0F10 — a near-black with
 * a teal cast rather than a neutral one — so the paper it becomes keeps
 * that cast instead of going white, and the two modes read as one brand
 * with the lights on. The tint lives in the base colour itself rather
 * than in a gradient laid over it, so it reads the same in every corner
 * of the page.
 *
 * The accent splits here. #22C8BE glows on near-black but washes out as
 * a 1px rule on paper, so anything that has to be *read* — ticks, rules,
 * links, the match figures — darkens to #077872. Filled buttons keep the
 * bright turquoise, which stays punchy on light because it has always
 * carried near-black text rather than white.
 * ---------------------------------------------------------------- */

:root[data-theme="light"] {
  color-scheme: light;
  /* Cream paper, tinted the whole way across rather than a near-white
     page with tinted cards sitting on it. The tint is in --bg itself, so
     every screen carries it and nothing has to opt in. */
  --bg: #F0EADE;
  --bg-gradient: none;
  --panel: #E7DFCF;
  --panel-2: #E1D8C6;
  --panel-3: #D8CDB8;
  --border: #C9BCA3;
  --border-soft: #DFD6C4;
  /* The text ramp is deliberately near-black the whole way down. Each
     step carries a WARM cast to sit on cream — a cool grey on warm paper
     reads faintly green, which is what made the previous ramp look washed
     out no matter how far it was darkened. Even the lightest step is a
     dark brown-grey rather than a mid grey, so secondary text still reads
     as text; the four steps stay separated enough to keep the hierarchy. */
  --ink: #100E09;
  --ink-dim: #2A251C;
  --muted: #443D31;
  --muted-2: #5C5445;
  /* Deepened a step from #077872, which only reached 4.45:1 on cream —
     the new paper is lighter than the cool ground this was originally
     tuned against, so the accent had to follow it down. */
  --blue: #06706A;
  --blue-hover: #045854;
  --blue-soft: rgba(6,112,106,0.14);
  --blue-border: rgba(6,112,106,0.32);
  /* A greyed turquoise — hue 179 at 16% saturation, against the dark
     theme's 176 at 79%. Saturation is what was doing the shouting: the
     accent was tuned to glow on near-black, and on warm paper any
     high-chroma fill becomes the loudest thing on the page. This is the
     only place in either theme that paints a large solid block of the
     accent, so it is the one that has to be quietest.
     Previously hue 194 at 22%, which read as a blue-leaning cyan rather
     than as turquoise; the hue is pulled back to the accent family and
     the chroma dropped further. Still 5.06:1 on --on-accent, and hover
     lightens rather than saturating so the state reads without the
     button getting louder.
     Light mode only — in dark mode the primary button is a translucent
     gradient and never paints this. */
  --accent-fill: #6B9493;
  --accent-fill-hover: #81A7A7;
  /* Ink on the button: a green-cast near-black, so it belongs to the
     turquoise it sits on rather than fighting it. */
  --on-accent: #04211F;
  --row-hover: rgba(6,112,106,0.06);
  --error: #B3352C;
  --error-bg: rgba(179,53,44,0.08);
  --error-border: rgba(179,53,44,0.26);
  /* Aliased to the accent, as in the dark theme — kept in step with it. */
  --green: #06706A;
  --green-soft: rgba(6,112,106,0.14);
  --green-border: rgba(6,112,106,0.32);
}

/* ---------------------------------------------------------------- *
 * Light mode — field cards
 *
 * Every card gets the same treatment: the same accent in --field (the
 * FIGURE — match number, confirmed pill, stat emphasis) and the same
 * warm --field-wash behind it. Cards are already sorted strongest match
 * first and each prints its own percentage, so ordering is legible
 * twice over without also spending colour on it.
 *
 * This replaced a rank ramp that ran turquoise -> cyan -> navy down the
 * grid. It read as intended on paper and badly in practice: only the
 * first card kept the accent, and every card below it drifted colder and
 * greyer until the fifth looked disabled rather than ranked.
 *
 * The tick (--field-line) is a structural device, the same one used
 * everywhere else in the theme, and is a single subdued navy on every
 * card — it never carried the ramp and doesn't carry the accent either.
 * ---------------------------------------------------------------- */

/* --field-line is deliberately NOT part of the per-rank set below — it
   is the same subdued navy on every card, first through last. The rank
   ramp still lives in the FIGURE (--field) and the card's own faint
   wash (--field-wash); the tick is a structural device, like the
   hairline rules and ticks everywhere else in the theme, and reads as
   one consistent mark rather than five different-coloured ones. */
:root[data-theme="light"] .card-grid .path-card { --field-line: #2A3C58; }

/* One treatment on every card, first through last. The ramp that used to
   live here gave each rank its own hue, which meant the figure and the
   card wash cooled from teal through blue into navy as you read down the
   grid — so only the top card carried the accent and the rest looked
   progressively greyer and colder against warm paper, as though they had
   been dimmed rather than ranked. Rank is already stated twice on the
   card (the ordering itself, and the match number), so it does not need a
   third encoding that costs every card below the first its colour.

   The wash is a WARM tint, not a tint of --field. Same-hue-behind-figure
   was eroding contrast, and a cool wash on cream reads faintly grey; a
   warm one deepens the paper instead, which is what makes the card read
   as a card rather than as a slightly discoloured patch of page. */
:root[data-theme="light"] .card-grid .path-card {
  --field: #017065;
  --field-wash: rgba(198,156,82,0.10);
}

/* Every card carries its rank colour immediately, not only when hovered
   or confirmed, so the ramp reads as one gradient down the grid rather
   than mostly-grey with two lit exceptions. The tick also thickens from
   the dark theme's hairline to 3px — enough to read as a colour bar at
   a glance rather than a rule that happens to be tinted. */
:root[data-theme="light"] .card-grid .path-card::before {
  height: 3px;
  width: 40px;
}
/* Scoped through .card-grid and :not(.demoted) purely to outrank the
   base theme, which singles the first card out at (0,4,1) and would
   otherwise paint its tick a flat accent — that is what made the first
   card look like a different treatment instead of matching the rest.
   Every card, first included, shows the same line colour at rest. */
:root[data-theme="light"] .card-grid .path-card:not(.demoted)::before {
  background: var(--field-line);
}
/* A demoted card is out of the running, so it drops the line entirely. */
:root[data-theme="light"] .card-grid .path-card.demoted::before {
  background: var(--border);
}
/* Hover is the ONLY thing that stretches a tick. Confirmed deliberately
   does not: a permanently stretched bar reads as a hover that is stuck
   on, and the confirmed state already says so in words on the card
   itself. Every card therefore sits at rest identically and only
   responds to the pointer. The stretch keeps the same line colour, so
   it simply grows — the short line and the long line are the same
   line, not two different marks. */
:root[data-theme="light"] .card-grid .path-card:not(.demoted):hover::before {
  background: var(--field-line);
  width: 100%;
}

/* A faint wash of the step's own colour behind the card, so the rank
   reads as a tinted block rather than a bar and a number alone. The
   negative margins let it bleed past the text column without moving
   the text itself. */
:root[data-theme="light"] .path-card {
  background: var(--field-wash);
  padding-left: 20px;
  padding-right: 20px;
  margin-left: -20px;
  margin-right: -20px;
}

:root[data-theme="light"] .path-card .match-num,
:root[data-theme="light"] .path-card .confirmed-pill {
  color: var(--field);
  font-weight: 600;
}
:root[data-theme="light"] .path-card .stat-row .stat b { color: var(--field); }
:root[data-theme="light"] .path-card-footer button:hover {
  color: var(--field);
  border-bottom-color: var(--field);
}

/* Wrapping the right-hand chrome keeps the theme switch hard against the
   corner whether or not Log in happens to be showing. */
.topbar-right {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 20px;
}

/* Names the mode you'd switch to, never the one you're already in — so
   it's an action, and it reads exactly like the Sign out and Back links
   it sits beside rather than introducing a control of its own. Which
   face shows is driven off data-theme in CSS, so it can't flash the
   wrong one before the script runs. */
.theme-toggle-btn {
  background: none;
  border: none;
  border-radius: 0;
  padding: 0;
  display: flex;
  align-items: center;
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 400;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  cursor: pointer;
  transition: color 0.14s ease;
}
.theme-toggle-btn:hover { background: none; color: var(--blue); }

.theme-face { display: flex; align-items: center; gap: 7px; }
:root[data-theme="light"] .theme-face-light { display: none; }
:root:not([data-theme="light"]) .theme-face-dark { display: none; }

.theme-icon { font-size: 13px; line-height: 1; }

/* Phone widths: the glyph carries it alone, the word drops. */
@media (max-width: 620px) {
  .theme-label { display: none; }
  .theme-face { gap: 0; }
}

/* ---- The three round bars at the top of the assessment ---- */
.round-bars {
  display: flex;
  gap: 10px;
  max-width: 340px;
  margin: 0 auto 48px;
}
/* The centered phase line + bars replace the header's old bottom gap —
   but when the bars are hidden (demo, check-ins), the phase line
   carries the spacing itself. */
#phase-indicator:has(+ .round-bars.hidden) { margin-bottom: 48px; }
.round-seg { flex: 1; }
.round-label {
  display: block;
  font-family: var(--mono, monospace);
  font-size: 9px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-dim);
  margin-bottom: 3px;
  text-align: center;
  white-space: nowrap;
}
.round-seg.current .round-label,
.round-seg.done .round-label { color: var(--ink); }
.round-track {
  display: block;
  height: 3px;
  border-radius: 2px;
  background: color-mix(in srgb, var(--ink-dim) 25%, transparent);
  overflow: hidden;
}
.round-fill {
  display: block;
  height: 100%;
  width: 0;
  border-radius: 2px;
  background: var(--accent-fill);
  transition: width 0.5s ease;
}
.round-seg.done .round-fill,
.round-seg.current .round-fill { width: 100%; }
