/* ════════════════════════════════════════════════════════════
   PathFinder — "The Atlas" design system
   Cartographic editorial: warm paper, ink typography, one
   vermilion route accent. Fraunces / Instrument Sans / Plex Mono.
   ════════════════════════════════════════════════════════════ */

:root {
  /* Surfaces */
  --paper:    #F4F1EA;
  --paper-2:  #ECE7DC;
  --night:    #181610;
  --night-2:  #211E16;

  /* Ink */
  --ink:       #1C1A15;
  --ink-soft:  rgba(28,26,21,.66);
  --ink-faint: rgba(28,26,21,.42);
  --line:      rgba(28,26,21,.14);
  --line-soft: rgba(28,26,21,.08);

  /* Cartographic accents */
  --route:  #C2401C;   /* vermilion — the drawn route, primary accent  */
  --pine:   #2D5A41;   /* survey green — confirmation, growth          */
  --sea:    #2F5D74;   /* bathymetric blue — data, depth               */
  --ochre:  #8A6A2F;   /* annotation gold — notes, hints               */

  /* Legacy aliases (app views reference these) */
  --teal:        var(--pine);
  --violet:      var(--sea);
  --gold:        var(--ochre);
  --rose:        var(--route);
  --teal-soft:   rgba(45,90,65,.10);
  --violet-soft: rgba(47,93,116,.10);
  --gold-soft:   rgba(138,106,47,.12);
  --ink-2:       var(--paper-2);
  --surface:     #FDFCF8;
  --surface-2:   #FFFFFF;
  --line-2:      rgba(28,26,21,.22);
  --text:        var(--ink);
  --text-dim:    var(--ink-soft);
  --text-faint:  var(--ink-faint);
  --grad-brand:  var(--route);

  --font-display: 'Fraunces', Georgia, serif;
  --font-body:    'Instrument Sans', -apple-system, sans-serif;
  --font-mono:    'IBM Plex Mono', ui-monospace, monospace;

  /* 4px spacing scale */
  --s1: 4px;  --s2: 8px;  --s3: 16px; --s4: 24px;
  --s5: 40px; --s6: 64px; --s7: 104px; --s8: 168px;

  --shadow-1: 0 1px 2px rgba(28,26,21,.06), 0 8px 28px rgba(28,26,21,.07);
  --shadow-2: 0 2px 6px rgba(28,26,21,.08), 0 24px 64px rgba(28,26,21,.14);
}

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; }
body {
  min-height: 100vh;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.6;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
  font-feature-settings: 'ss01';
}
::selection { background: rgba(194,64,28,.18); }

h1,h2,h3,h4 { font-weight: 500; letter-spacing: -.015em; }
.display {
  font-family: var(--font-display);
  font-weight: 480;
  font-variation-settings: 'SOFT' 40, 'WONK' 0;
  letter-spacing: -.022em;
  line-height: 1.04;
}
.display em { font-style: italic; font-variation-settings: 'SOFT' 80, 'WONK' 1; color: var(--route); }

a { color: inherit; text-decoration: none; }
button { font-family: inherit; cursor: pointer; color: inherit; }
img, svg { display: block; max-width: 100%; }

.wrap { max-width: 1240px; margin: 0 auto; padding: 0 clamp(20px, 4vw, 48px); }

/* ── Mono labels — coordinates, indices, captions ── */
.mono {
  font-family: var(--font-mono);
  font-size: 11.5px;
  font-weight: 500;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.mono .tick { color: var(--route); }

/* Chapter label: "01 — The Method" with hairline */
.chapter {
  display: flex; align-items: baseline; gap: 14px;
  padding-top: 18px; border-top: 1px solid var(--ink);
  margin-bottom: var(--s5);
}
.chapter .no { font-family: var(--font-mono); font-size: 12px; font-weight: 600; letter-spacing: .1em; color: var(--route); }
.chapter .ttl { font-family: var(--font-mono); font-size: 12px; font-weight: 500; letter-spacing: .18em; text-transform: uppercase; color: var(--ink-soft); }
.chapter .end { margin-left: auto; font-family: var(--font-mono); font-size: 11px; letter-spacing: .1em; color: var(--ink-faint); }

/* ── Buttons ── */
.btn {
  display: inline-flex; align-items: center; gap: 10px;
  padding: 14px 24px; border-radius: 2px; border: 1px solid var(--ink);
  font-size: 14px; font-weight: 500; letter-spacing: .01em; white-space: nowrap;
  background: transparent; color: var(--ink);
  transition: background .22s, color .22s, border-color .22s, transform .22s;
}
/* Icon-font fallback for the LANDING AND LEGAL pages. app.html gets the
   same guard from brand.css, which those pages never load — and now that
   Google Fonts is fetched asynchronously everywhere, they need it too:
   between first paint and the font arriving (or forever, if it is blocked)
   Material Symbols renders its ligature text literally, printing the word
   "space_dashboard" where an icon belongs. A fixed box makes that an empty
   space instead, and stops the layout jumping when the font lands.

   Ligatures are deliberately NOT disabled here — the icons ARE ligatures,
   so turning them off would break every glyph in the product. */
.material-symbols-outlined {
  display: inline-block;
  width: 1em; height: 1em;
  overflow: hidden;
  vertical-align: -0.15em;
}

.btn .material-symbols-outlined, .btn svg { transition: transform .25s cubic-bezier(.22,1,.36,1); }
.btn:hover .material-symbols-outlined, .btn:hover svg { transform: translateX(3px); }
.btn-primary { background: var(--ink); color: var(--paper); }
.btn-primary:hover { background: var(--route); border-color: var(--route); }
.btn-ghost:hover { border-color: var(--route); color: var(--route); }
.btn-sm { padding: 9px 16px; font-size: 13px; }
.btn:disabled { opacity: .45; cursor: not-allowed; }
.btn:focus-visible, a:focus-visible { outline: 2px solid var(--route); outline-offset: 2px; }

/* Text link with sliding underline */
.tlink {
  position: relative; display: inline-flex; align-items: center; gap: 6px;
  font-size: 14px; font-weight: 500; color: var(--ink);
  padding-bottom: 2px;
}
.tlink::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 1px;
  background: var(--route); transform: scaleX(0); transform-origin: left;
  transition: transform .3s cubic-bezier(.22,1,.36,1);
}
.tlink:hover::after { transform: scaleX(1); }
.tlink:hover { color: var(--route); }

/* ── Stamps (replaces chips) — bordered mono tags ── */
.chip, .stamp {
  display: inline-block; padding: 3px 9px; border-radius: 2px;
  font-family: var(--font-mono); font-size: 10.5px; font-weight: 500;
  letter-spacing: .08em; text-transform: uppercase;
  border: 1px solid currentColor; background: transparent;
}
.chip-teal   { color: var(--pine); }
.chip-violet { color: var(--sea); }
.chip-gold   { color: var(--ochre); }
.chip-rose   { color: var(--route); }
.chip-dim    { color: var(--ink-faint); }

/* ── Cards → "plates": flat, hairline, square ── */
.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 3px;
  padding: 28px;
  transition: border-color .25s, box-shadow .25s, transform .25s;
}
.card:hover { border-color: var(--line-2); box-shadow: var(--shadow-1); }

/* ── Forms ── */
.field {
  width: 100%; padding: 13px 14px; border-radius: 2px;
  background: var(--surface); border: 1px solid var(--line-2);
  color: var(--ink); font-size: 14px; font-family: inherit; outline: none;
  transition: border-color .2s, box-shadow .2s;
}
.field::placeholder { color: var(--ink-faint); }
.field:focus { border-color: var(--ink); box-shadow: 2px 2px 0 var(--route); }
select.field { appearance: none; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' fill='none'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%231C1A15' stroke-width='1.5' stroke-linecap='round'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 14px center; }

/* ── Nav ── */
.nav { position: fixed; top: 0; left: 0; right: 0; z-index: 100; padding: 0; background: transparent; transition: background .3s, border-color .3s; border-bottom: 1px solid transparent; }
.nav.scrolled { background: rgba(244,241,234,.92); backdrop-filter: blur(12px); border-bottom-color: var(--line); }
.nav-inner { display: flex; align-items: center; justify-content: space-between; gap: 16px; height: 64px; }
.logo { display: flex; align-items: baseline; gap: 10px; }
.logo .word { font-family: var(--font-display); font-size: 21px; font-weight: 560; letter-spacing: -.02em; }
.logo .word i { font-style: italic; color: var(--route); }
.logo-mark { display: none; }
.nav-links { display: flex; gap: 28px; font-family: var(--font-mono); font-size: 11.5px; font-weight: 500; letter-spacing: .12em; text-transform: uppercase; color: var(--ink-soft); }
.nav-links a { transition: color .2s; padding-bottom: 2px; border-bottom: 1.5px solid transparent; }
.nav-links a:hover { color: var(--route); }
.nav-links a[aria-current="page"] { color: var(--route); border-bottom-color: var(--route); }
@media (max-width: 880px) { .nav-links { display: none; } }

/* ── Reveal ── */
[data-reveal] { opacity: 0; transform: translateY(14px); transition: opacity .7s cubic-bezier(.22,1,.36,1), transform .7s cubic-bezier(.22,1,.36,1); }
[data-reveal].visible { opacity: 1; transform: none; }

/* ── Sections ── */
.sec { padding: var(--s7) 0; }
.sec-head h2 { font-size: clamp(1.9rem, 3.8vw, 3rem); line-height: 1.08; }
.sec-head p { color: var(--ink-soft); max-width: 520px; }

/* ── Tables (funding ledger etc.) ── */
.ledger { width: 100%; border-collapse: collapse; }
.ledger th {
  font-family: var(--font-mono); font-size: 10.5px; font-weight: 600;
  letter-spacing: .14em; text-transform: uppercase; color: var(--ink-faint);
  text-align: left; padding: 0 16px 12px 0; border-bottom: 1px solid var(--ink);
}
.ledger td { padding: 18px 16px 18px 0; border-bottom: 1px solid var(--line); vertical-align: top; font-size: 14px; }
.ledger tr { transition: background .2s; }
.ledger tbody tr:hover { background: rgba(194,64,28,.035); }

/* ── Progress bar ── */
.bar { height: 3px; background: var(--line-soft); overflow: hidden; }
.bar > span { display: block; height: 100%; background: var(--route); transition: width .6s cubic-bezier(.22,1,.36,1); }

/* ── Toast ── */
#toast {
  position: fixed; bottom: 28px; left: 50%; transform: translate(-50%, 16px);
  background: var(--ink); color: var(--paper);
  padding: 11px 20px; border-radius: 2px;
  font-family: var(--font-mono); font-size: 12px; letter-spacing: .04em;
  box-shadow: var(--shadow-2); opacity: 0; pointer-events: none;
  transition: opacity .3s, transform .3s; z-index: 500;
}
#toast.show { opacity: 1; transform: translate(-50%, 0); }

/* ── Utility ── */
.muted { color: var(--ink-soft); }
.faint { color: var(--ink-faint); }
.tag { display: inline-flex; align-items: center; gap: 8px; font-family: var(--font-mono); font-size: 11px; font-weight: 500; letter-spacing: .16em; text-transform: uppercase; color: var(--ink-soft); }
.tag .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--route); }
.grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px; }
/* Grid and flex items default to min-width:auto, so a child that refuses to
   wrap — a <pre>, a long unbroken string — sizes its track to the content
   instead of the container and pushes the whole page wider than the
   viewport. Same failure the .hero-row comment below describes. */
.grid-2 > *, .grid-3 > *, .grid-4 > * { min-width: 0; }
/* The Starter Kit's template previews are <pre>: without this they hold
   their longest line at full width and blow out the grid on a phone. */
.tpl-preview { white-space: pre-wrap; overflow-wrap: anywhere; }
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
.grid-4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: 20px; }
@media (max-width: 980px) { .grid-3, .grid-4 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 640px) { .grid-2, .grid-3, .grid-4 { grid-template-columns: 1fr; } }
.hidden { display: none !important; }
/* `hidden` is a UA rule with almost no specificity, so any component that
   sets its own display (.btn is inline-flex, .navpop-link is flex) wins and
   the element shows anyway. Contact links ship hidden and are revealed once
   PFContact confirms a number is configured, so this has to actually hide. */
[hidden] { display: none !important; }

/* ── Pricing tiers (#pricing) — side-by-side plan comparison ──
   Breakpoint note: this page shares .main with a 232px fixed sidebar down
   to a 880px viewport (see .shell in app.html), so a plain "does 3 columns
   fit" check can't use the same width number the sidebar-collapse query
   uses — the content column is ~230px narrower than the viewport above
   880px. 1180px covers the with-sidebar case; below the sidebar's own
   880px collapse the column is already full-width, so one query serves
   both regimes without a cramped middle zone. */
.price-tiers { display: flex; align-items: stretch; gap: 20px; }
.price-tier {
  flex: 1 1 0; min-width: 0; display: flex; flex-direction: column;
  background: var(--surface); border: 1px solid var(--line); border-radius: 3px;
  padding: 28px 24px; transition: border-color .25s, box-shadow .25s;
}
.price-tier:hover { border-color: var(--line-2); box-shadow: var(--shadow-1); }
/* box-shadow ring instead of a thicker border — highlights the plan without
   changing the box model, so no compensating padding is needed to keep
   inner content aligned with the other two cards. */
.price-tier-best { border-color: var(--route); box-shadow: 0 0 0 1px var(--route); }
.price-tier-best:hover { box-shadow: 0 0 0 1px var(--route), var(--shadow-1); }
.price-tier-icon {
  width: 48px; height: 48px; border-radius: 3px; margin-top: 14px;
  display: flex; align-items: center; justify-content: center;
}
.price-tier-icon .material-symbols-outlined { font-size: 24px; }
.price-tier-teal .price-tier-icon { background: var(--teal-soft); color: var(--pine); }
.price-tier-gold .price-tier-icon { background: var(--gold-soft); color: var(--ochre); }
.price-tier-rose .price-tier-icon { background: rgba(194,64,28,.10); color: var(--route); }
.price-tier-name { font-size: 13px; margin: 16px 0 6px; color: var(--ink); font-weight: 600; }
.price-tier-sub { font-size: 13px; min-height: 38px; margin: 0 0 4px; }
.price-tier-amount { font-family: var(--font-display); font-size: 2rem; font-weight: 500; margin: 4px 0 14px; display: flex; align-items: baseline; gap: 8px; }
.price-tier-amount span { font-family: var(--font-body); font-size: 12px; font-weight: 500; color: var(--ink-faint); text-transform: uppercase; letter-spacing: .08em; }
.price-list { list-style: none; display: flex; flex-direction: column; gap: 10px; margin: 4px 0 0; }
.price-list li { display: flex; align-items: flex-start; gap: 9px; font-size: 13px; line-height: 1.4; }
.price-list li .material-symbols-outlined { font-size: 17px; flex-shrink: 0; margin-top: 1px; }
.price-list li.yes { color: var(--ink); }
.price-list li.yes .material-symbols-outlined { color: var(--pine); }
/* Deliberately darker than --ink-faint (.42 alpha, ~2.9:1): these rows
   still carry real information ("you don't get this"), not just muted
   decoration, so they're set to clear WCAG AA contrast (~4.5:1+) against
   --surface instead. */
.price-list li.no { color: rgba(28,26,21,.58); }
.price-list li.no .material-symbols-outlined { color: rgba(28,26,21,.58); }
@media (max-width: 1180px) {
  .price-tiers { flex-direction: column; }
}
@media (max-width: 360px) {
  /* The "one-time" unit tag no longer fits beside a 2rem price on the
     narrowest phones without wrapping mid-word — stack it underneath. */
  .price-tier-amount { flex-direction: column; align-items: flex-start; gap: 2px; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
  html { scroll-behavior: auto; }
}

/* ── Research Studio (#research) ── */
.rs-field { margin-bottom: 16px; }
.rs-label { display: block; font-size: 12.5px; font-weight: 500; color: var(--ink-soft); margin-bottom: 6px; }
.rs-label .faint { font-weight: 400; }
.rs-h2 { font-size: 1.05rem; letter-spacing: .01em; margin: 0 0 16px; }

.rs-cand { display: flex; flex-direction: column; }
.rs-cand .btn { align-self: flex-start; margin-top: auto; }

.rs-notice {
  display: flex; align-items: flex-start; gap: 10px;
  background: var(--gold-soft); border: 1px solid var(--ochre);
  border-radius: 3px; padding: 12px 16px; margin-bottom: 24px;
  font-size: 13px; color: var(--ink-soft); max-width: 720px;
}
.rs-notice .material-symbols-outlined { color: var(--ochre); flex-shrink: 0; margin-top: 1px; }

.rs-chips { display: flex; flex-wrap: wrap; gap: 7px; margin: 12px 0; }
.rs-authors { list-style: none; margin: 12px 0 0; padding: 0; font-size: 13px; }
.rs-authors li { padding: 5px 0; border-bottom: 1px solid var(--line); }
.rs-authors li:last-child { border-bottom: none; }

.rs-hist { display: flex; align-items: flex-end; gap: 5px; height: 70px; margin-top: 16px; }
.rs-hist-bar { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; height: 100%; }
.rs-hist-bar > span { display: block; width: 100%; min-height: 2px; background: var(--route); border-radius: 1px; transition: height .5s cubic-bezier(.22,1,.36,1); }
.rs-hist-bar > em { font-family: var(--font-mono); font-size: 9.5px; color: var(--ink-faint); font-style: normal; margin-top: 4px; }

.rs-paper a:hover { color: var(--route); }

.rs-spinner {
  width: 34px; height: 34px; margin: 0 auto; border-radius: 50%;
  border: 3px solid var(--line-2); border-top-color: var(--route);
  animation: rs-spin .8s linear infinite;
}
@keyframes rs-spin { to { transform: rotate(360deg); } }

.rs-proposal .rs-stamps { display: flex; flex-wrap: wrap; gap: 7px; }
.rs-title { font-family: var(--font-display); font-size: clamp(1.4rem, 2.6vw, 1.9rem); line-height: 1.18; margin: 14px 0 4px; }
.rs-sec { margin-top: 26px; padding-top: 22px; border-top: 1px solid var(--line); }
.rs-sec h3 { font-size: 12px; font-family: var(--font-mono); letter-spacing: .12em; text-transform: uppercase; color: var(--route); margin-bottom: 12px; }
.rs-sec p { font-size: 14.5px; line-height: 1.7; color: var(--ink); }
.rs-ol, .rs-refs { margin: 0; padding-left: 20px; font-size: 14px; line-height: 1.7; }
.rs-refs { font-size: 13px; color: var(--ink-soft); }
.rs-refs li { margin-bottom: 8px; }
.rs-tl { margin-bottom: 14px; }
.rs-tl strong { display: block; font-family: var(--font-mono); font-size: 12px; letter-spacing: .06em; color: var(--sea); margin-bottom: 4px; }
.rs-tl ul, .rs-sup { margin: 0; padding-left: 20px; font-size: 14px; line-height: 1.6; }
.rs-sup { list-style: none; padding-left: 0; }
.rs-sup li { padding: 10px 0; border-bottom: 1px solid var(--line); }
.rs-sup li:last-child { border-bottom: none; }
.rs-disclaimer { margin-top: 26px; padding-top: 18px; border-top: 1px solid var(--line); font-size: 12px; color: var(--ink-faint); font-style: italic; }

/* "Research happening in New Zealand" opportunity panel */
.rs-nz { margin: 8px 0 36px; border: 1px solid var(--pine); background: linear-gradient(180deg, color-mix(in srgb, var(--pine) 6%, transparent), transparent); }
.rs-nz-h { font-size: 1.15rem; margin: 12px 0 6px; }
.rs-nz-sub { font-size: 14px; line-height: 1.6; color: var(--ink-soft); margin: 0 0 16px; max-width: 64ch; }
.rs-nz-people { list-style: none; margin: 0 0 18px; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 10px; }
.rs-nz-person { display: flex; align-items: center; gap: 10px; }
.rs-nz-dot { flex-shrink: 0; width: 34px; height: 34px; border-radius: 50%; display: grid; place-items: center; font-family: var(--font-display); font-size: 15px; color: #fff; background: var(--pine); }
.rs-nz-person strong { display: block; font-size: 13.5px; }
.rs-nz-place { display: block; font-size: 12px; color: var(--ink-faint); }
.rs-nz-why { font-size: 13px; font-weight: 600; color: var(--ink-soft); margin: 0 0 8px; }
.rs-nz-perks { margin: 0 0 18px; padding-left: 20px; font-size: 13px; line-height: 1.7; color: var(--ink-soft); }
.rs-nz-cta { display: flex; gap: 10px; flex-wrap: wrap; }

/* ════════════════════════════════════════════════════════════
   PathFinder — "Ink & Brass" component classes (app.html only)

   Every rule below is scoped under .shell, the app-shell wrapper
   in app.html. index.html and the legal pages never contain a
   .shell element, so they keep the "Atlas" shapes above completely
   unchanged even though several class names (.btn, .field, .bar,
   .chip) are shared with this file's earlier rules. Where a name
   below is entirely new (.topnav, .hero, .listcard, .row, .stat,
   .sidecard, .nudge, .tab, .icontile, .avatar) scoping isn't load-
   bearing, but every rule stays under .shell anyway for one
   consistent, greppable boundary between "old, shared" and
   "new, app-only" styles in this file.
   ════════════════════════════════════════════════════════════ */

.shell { -webkit-font-smoothing: antialiased; }
.shell, .shell input, .shell select, .shell textarea, .shell button { font-family: var(--font-body); }

.shell :focus-visible { outline: 2px solid var(--accent-ink); outline-offset: 2px; }

/* ── Buttons ── */
.shell .btn {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 13px 22px; border-radius: var(--r-btn); border: none;
  font-family: var(--font-body); font-size: 13.5px; font-weight: 600; line-height: 1;
  background: var(--accent); color: var(--on-accent); white-space: nowrap;
  transition: background-color var(--t-fast), border-color var(--t-fast), color var(--t-fast), filter var(--t-fast), opacity var(--t-fast);
}
.shell .btn:hover { filter: brightness(1.06); }
.shell .btn:active { filter: brightness(.96); }
.shell .btn:disabled { opacity: .45; cursor: not-allowed; filter: none; }
.shell .btn .material-symbols-outlined { font-size: 16px; }

.shell .btn-ghost {
  background: transparent; border: 1px solid var(--chrome-line); color: var(--on-chrome);
  padding: 13px 20px; font-weight: 500;
}
.shell .btn-ghost:hover { border-color: var(--on-chrome-dim); filter: none; }

.shell .btn-quiet {
  background: transparent; border: 1px solid var(--line-strong); color: var(--ink);
  padding: 11px 18px; font-size: 12.5px; font-weight: 600;
}
.shell .btn-quiet:hover { border-color: var(--ink); filter: none; }
.shell .btn-block { width: 100%; justify-content: center; }

.shell .btn-sm { padding: 9px 14px; font-size: 12.5px; }

/* ── Top navigation ── */
.shell .topnav {
  position: relative; display: flex; align-items: center; gap: 34px;
  background: var(--chrome); color: var(--on-chrome);
  padding: 20px 44px;
}
.shell .tn-logo { display: inline-flex; align-items: baseline; font-family: var(--font-display); font-size: 17px; }
.shell .tn-logo-path { font-weight: 600; color: var(--on-chrome); }
/* "finder" is italic in the wordmark everywhere else (.logo .word i on the
   marketing/legal pages) — the app's top-nav mark dropped that, so the
   same name read as two different logos (W-31). Color stays --accent (not
   the marketing site's --route) deliberately: it's tuned for contrast
   against --chrome, see brand.css. */
.shell .tn-logo-finder { font-weight: 400; font-style: italic; color: var(--accent); }

.shell .topnav-links { display: flex; align-items: center; gap: 26px; list-style: none; margin: 0; padding: 0; }
.shell .topnav-links a {
  display: inline-block; padding-bottom: 3px; border-bottom: 1.5px solid transparent;
  font-family: var(--font-mono); font-size: 10.5px; font-weight: 500; letter-spacing: .14em; text-transform: uppercase;
  color: var(--on-chrome-dim);
  transition: color var(--t-fast), border-color var(--t-fast);
}
.shell .topnav-links a:hover:not([aria-current="page"]) { color: var(--on-chrome); }
.shell .topnav-links a[aria-current="page"] { color: var(--on-chrome); border-bottom-color: var(--accent); }

.shell .topnav-right { display: flex; align-items: center; gap: 16px; margin-left: auto; }
.shell .topnav-context {
  font-family: var(--font-mono); font-size: 10px; font-weight: 500; letter-spacing: .12em; text-transform: uppercase;
  color: var(--on-chrome-dim); white-space: nowrap;
}
.shell .navmore {
  display: inline-flex; align-items: center; justify-content: center;
  width: 36px; height: 36px; border-radius: var(--r-btn); border: none; background: transparent;
  color: var(--on-chrome-dim); cursor: pointer; transition: color var(--t-fast), background-color var(--t-fast);
}
.shell .navmore:hover { color: var(--on-chrome); background: var(--chrome-track); }
.shell .navmore .ic-menu { display: none; }

/* overflow popover — a .listcard-styled panel anchored under the avatar */
.shell .navpop {
  position: absolute; top: calc(100% + 8px); right: 44px; z-index: 300;
  min-width: 240px; background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-card); box-shadow: var(--shadow-card); padding: 8px;
}
.shell .navpop[hidden] { display: none; }
.shell .navpop-link {
  display: flex; align-items: center; gap: 10px; padding: 10px 12px; border-radius: var(--r-btn);
  font-size: 13.5px; font-weight: 500; color: var(--ink); white-space: nowrap;
  transition: background-color var(--t-fast);
}
.shell .navpop-link:hover { background: rgba(25,27,30,.05); }
.shell .navpop-link .material-symbols-outlined { font-size: 18px; color: var(--ink-dim); }
.shell .navpop-sep { height: 1px; background: var(--line-soft); margin: 8px 4px; }
.shell .navpop-sync {
  margin: 10px 12px 0; padding: 0;
  font-family: var(--font-mono); font-size: 10px; letter-spacing: .04em;
  color: var(--ink-faint);
}
.shell .navpop-foot {
  display: flex; flex-wrap: wrap; gap: 4px 10px; padding: 6px 12px 4px;
  font-family: var(--font-mono); font-size: 9.5px; letter-spacing: .08em; text-transform: uppercase;
}
.shell .navpop-foot a { color: var(--ink-dim); }
.shell .navpop-foot a:hover { color: var(--ink); }
.shell .navpop .track-switch { margin: 0 0 6px; }

/* bottom tab bar — <900px only, see media query below */
.shell .tabbar {
  display: none;
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 200;
  background: var(--card); border-top: 1px solid var(--line);
  min-height: 56px;
}
.shell .tabbar a {
  flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
  min-height: 56px; padding: 6px 4px; border-top: 1.5px solid transparent;
  font-family: var(--font-mono); font-size: 9px; font-weight: 500; letter-spacing: .08em; text-transform: uppercase;
  color: var(--ink-dim);
}
.shell .tabbar a .material-symbols-outlined { font-size: 20px; color: inherit; }
.shell .tabbar a[aria-current="page"] { color: var(--accent-ink); border-top-color: var(--accent); }

/* ── Hero panel ── */
.shell .hero {
  background: var(--chrome); color: var(--on-chrome);
  border-radius: var(--r-hero); padding: var(--pad-hero);
  box-shadow: var(--shadow-hero); margin-bottom: 24px;
}
.shell .hero-row { display: flex; justify-content: space-between; align-items: flex-start; gap: 24px; flex-wrap: wrap; }
.shell .hero-left { max-width: 520px; min-width: 0; }
.shell .hero-kicker {
  font-family: var(--font-mono); font-size: 10px; font-weight: 500; letter-spacing: .20em; text-transform: uppercase;
  color: var(--accent);
}
.shell .hero-title {
  font-family: var(--font-display); font-size: 2.5rem; font-weight: 600; letter-spacing: -.02em; line-height: 1.08;
  color: var(--on-chrome); margin: 14px 0 10px;
}
.shell .hero-body { color: var(--on-chrome-dim); margin: 0 0 22px; max-width: 520px; }
.shell .hero-actions { display: flex; gap: 10px; flex-wrap: wrap; }
.shell .hero-right { text-align: right; flex-shrink: 0; }
.shell .hero-figure {
  font-family: var(--font-display); font-size: 3.4rem; font-weight: 600; letter-spacing: -.03em; line-height: 1;
  color: var(--accent);
}
.shell .hero-figure .suf { font-size: .32em; font-weight: 600; color: var(--on-chrome-dim); }
.shell .hero-caption {
  margin-top: 6px; font-family: var(--font-mono); font-size: 9.5px; font-weight: 500; letter-spacing: .14em; text-transform: uppercase;
  color: var(--on-chrome-dim);
}
.shell .hero-figure-mobile { display: none; }

/* ── Journey segments — each one a real link to that phase's own next
   step, with a numbered/checked badge and a done/total count, so the
   strip reads as a compact five-phase map rather than one bare bar per
   phase. The fuller "what's next" sentence rides in the title attribute
   (hover/long-press) instead of being printed, to stay five short labels
   wide. */
.shell .segs { display: flex; gap: 10px; margin-top: 28px; }
.shell .seg {
  flex: 1; min-width: 0; display: block; color: inherit; text-decoration: none;
  padding: 6px; border-radius: 10px;
  transition: background-color var(--t-fast);
}
.shell .seg:hover { background: var(--chrome-track); }
.shell .seg-top { display: flex; align-items: center; gap: 7px; }
.shell .seg-num {
  display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0;
  width: 18px; height: 18px; border-radius: 50%;
  font-family: var(--font-mono); font-size: 9.5px; font-weight: 600;
  background: var(--chrome-track); color: var(--on-chrome-dim);
}
.shell .seg-num .material-symbols-outlined { font-size: 12px; }
.shell .seg.is-current .seg-num { background: var(--accent); color: var(--on-accent); }
.shell .seg.is-complete .seg-num { background: var(--ok); color: #fff; }
.shell .seg-track { flex: 1; min-width: 0; height: 4px; border-radius: 3px; background: var(--chrome-track); overflow: hidden; }
.shell .seg-track > span { display: block; height: 100%; background: var(--accent); width: 0; transition: width var(--t-bar); }
.shell .seg.is-empty .seg-track > span { background: var(--chrome-line); }
.shell .seg-meta { display: flex; justify-content: space-between; align-items: baseline; gap: 6px; margin-top: 8px; }
.shell .seg-label {
  font-family: var(--font-mono); font-size: 9px; font-weight: 500; letter-spacing: .10em; text-transform: uppercase;
  color: var(--on-chrome-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.shell .seg.is-current .seg-label { color: var(--on-chrome); }
.shell .seg-frac { font-family: var(--font-mono); font-size: 9px; font-weight: 500; color: var(--on-chrome-dim); flex-shrink: 0; }

/* ── Stat tile ── */
.shell .stat-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; }
.shell .stat {
  display: block; min-width: 0; background: var(--card); border: 1px solid var(--line); border-radius: var(--r-sm);
  padding: 18px; box-shadow: var(--shadow-card); transition: border-color var(--t-fast);
}
.shell .stat:hover { border-color: var(--line-strong); }
.shell .stat-icon { font-size: 18px; color: var(--accent-ink); }
.shell .stat-figure { font-family: var(--font-display); font-size: 1.5rem; font-weight: 600; letter-spacing: -.01em; margin-top: 10px; }
.shell .stat-label { font-size: 11.5px; color: var(--ink-dim); margin-top: 4px; }

/* ── List card ── */
.shell .listcard {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r-card);
  padding: 24px 26px; box-shadow: var(--shadow-card); transition: border-color var(--t-fast);
}
.shell .listcard:hover { border-color: var(--line-strong); }
.shell .listcard-head { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; margin-bottom: 6px; flex-wrap: wrap; }
.shell .listcard-title { font-family: var(--font-display); font-size: 1.05rem; font-weight: 600; letter-spacing: -.01em; line-height: 1.25; margin: 0; }
.shell .listcard-summary {
  font-family: var(--font-mono); font-size: 9.5px; font-weight: 500; letter-spacing: .12em; text-transform: uppercase; color: var(--ink-dim);
}
.shell .row {
  display: flex; align-items: center; gap: 14px; padding: 14px 0; border-bottom: 1px solid var(--line-soft);
  transition: background-color var(--t-fast);
}
.shell a.row { color: inherit; }
.shell .row:hover { background: rgba(25,27,30,.02); margin: 0 -10px; padding: 14px 10px; }
.shell .row-main { flex: 1; min-width: 0; }
.shell .row-title { font-size: 13.5px; font-weight: 500; letter-spacing: -.005em; line-height: 1.3; }
.shell .row-sub { font-size: 12px; color: var(--ink-dim); margin-top: 2px; line-height: 1.4; }
.shell .listcard > p { font-size: 14px; color: var(--ink-dim); line-height: 1.6; margin: 4px 0 0; max-width: 560px; }

/* ── Status chip — tinted fill, no border ── */
.shell .chip {
  display: inline-block; padding: 4px 11px; border-radius: var(--r-pill); border: none;
  font-family: var(--font-mono); font-size: 9.5px; font-weight: 500; letter-spacing: .10em; text-transform: uppercase;
}
.shell .chip-ok { color: var(--ok); background: var(--ok-bg); }
.shell .chip-warn { color: var(--warn); background: var(--warn-bg); }
.shell .chip-alert { color: var(--alert); background: var(--alert-bg); }
.shell .chip-info { color: var(--info); background: var(--info-bg); }
.shell .chip-neutral { color: var(--ink-dim); background: var(--line-soft); }

/* ── Side card ── */
.shell .sidecard {
  display: block; color: inherit;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r-card);
  padding: 22px; box-shadow: var(--shadow-card); transition: border-color var(--t-fast);
}
.shell .sidecard:hover { border-color: var(--line-strong); }
.shell .sidecard-kicker {
  display: block; font-family: var(--font-mono); font-size: 9.5px; font-weight: 500; letter-spacing: .14em; text-transform: uppercase;
  color: var(--ink-dim); margin-bottom: 10px;
}
.shell .sidecard p { font-size: 13px; color: var(--ink-dim); line-height: 1.5; margin: 4px 0 0; }
.shell .sidecard-figure { font-family: var(--font-display); font-size: 1.9rem; font-weight: 600; letter-spacing: -.02em; color: var(--ink); }
.shell .sidecard-head { display: flex; align-items: center; gap: 14px; margin-bottom: 12px; }
.shell .sidecard-name { font-size: 13.5px; font-weight: 600; }
.shell .sidecard-sub { font-size: 12px; color: var(--ink-dim); margin-top: 1px; }
.shell .sidecard .bar { margin-top: 14px; }
.shell .sidecard .bar-caption { margin-top: 8px; }
.shell .sidecard > .btn, .shell .sidecard > .btn-quiet { margin-top: 14px; }
.shell .sidecard > .chip { margin-top: 10px; }
.shell .icon-btn .material-symbols-outlined { font-size: 16px; }
.shell .save-btn .material-symbols-outlined { font-size: 16px; }

/* form fields laid out two-up inside a listcard, collapsing to one column
   on narrow screens (used by the dashboard's "track an application" form) */
.shell .form-row { display: grid; grid-template-columns: 1.4fr 1fr 1fr auto; gap: 10px; align-items: end; }
@media (max-width: 640px) { .shell .form-row { grid-template-columns: 1fr; } }
.shell .row-actions { display: flex; align-items: center; gap: 8px; margin-left: auto; flex-shrink: 0; }
.shell .row-actions .field { width: auto; padding: 8px 30px 8px 10px; font-size: 12.5px; }
.shell .icon-btn {
  display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px;
  border-radius: var(--r-btn); border: 1px solid var(--line-strong); background: transparent; color: var(--ink-dim);
  transition: color var(--t-fast), border-color var(--t-fast);
}
.shell .icon-btn:hover { color: var(--alert); border-color: var(--alert); }

/* ── Advisory panel ── */
.shell .nudge { display: block; background: var(--nudge-bg); border: 1px solid var(--nudge-line); border-radius: var(--r-card); padding: 20px; color: inherit; }
.shell .nudge-icon { font-size: 19px; color: var(--accent-ink); }
.shell .nudge-body { font-size: 12.5px; color: var(--ink-dim); margin-top: 10px; line-height: 1.5; }
.shell .nudge-toggle {
  display: block; background: none; border: none; padding: 0; margin-top: 10px; text-align: left; cursor: pointer;
  font-family: var(--font-body); font-size: 12.5px; color: var(--ink-dim); line-height: 1.5;
}
.shell .nudge form { margin-top: 10px; display: flex; flex-direction: column; gap: 8px; }
.shell .listcard .nudge { margin-top: 16px; }

/* ── The immigration boundary ──
   Where a mentor hook would sit on an immigration step, adviserReferral()
   renders this instead: no form, no fields, just the way out to INZ and to
   the licensed register. Warm-toned rather than alarming — it is a handover,
   not an error — but visually distinct from the mentor nudge so a student
   can tell at a glance that this step works differently. */
.shell .adviser-referral { border-color: var(--warn-line, var(--nudge-line)); background: var(--warn-bg, var(--nudge-bg)); }
.shell .adviser-referral .nudge-icon { color: var(--warn); }
.shell .adviser-referral-title { display: block; font-size: 13.5px; margin-top: 8px; }
.shell .adviser-referral-body { font-size: 12.5px; color: var(--ink-dim); margin-top: 6px; line-height: 1.55; }
.shell .adviser-referral-links {
  display: flex; flex-wrap: wrap; gap: 8px 18px; margin-top: 12px;
}
.shell .adviser-referral-links .tlink { font-size: 12.5px; }
.shell .visa-boundary { border-color: var(--warn-line, var(--line)); }
.shell .visa-boundary .adviser-referral-links { margin-top: 16px; }

/* ── Agent performance table (INZ published data) ── */
.shell .agent-sort { display: flex; gap: 8px; flex-wrap: wrap; margin: 18px 0 12px; }
.shell .agent-scroll { overflow-x: auto; margin-bottom: 6px; }
.shell .agent-table { width: 100%; min-width: 440px; }
.shell .agent-table thead th {
  font-family: var(--font-mono); font-size: 10.5px; text-transform: uppercase;
  letter-spacing: .07em; color: var(--ink-dim); text-align: left;
  padding-bottom: 8px; border-bottom: 1px solid var(--line); white-space: nowrap;
}
.shell .agent-table td { padding: 9px 12px 9px 0; vertical-align: middle; }
.shell .agent-table td:last-child { padding-right: 0; }
.shell .agent-name { font-size: 13.5px; line-height: 1.35; }
.shell .agent-band { width: 1%; white-space: nowrap; }
.shell .agent-vol {
  width: 1%; white-space: nowrap; font-family: var(--font-mono);
  font-size: 11.5px; color: var(--ink-dim); font-variant-numeric: tabular-nums;
}
.shell .agent-notes { margin: 12px 0; }
.shell .agent-notes summary {
  cursor: pointer; font-size: 12.5px; color: var(--ink-dim);
  padding: 4px 0; list-style-position: outside;
}
.shell .agent-notes summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.shell .agent-notes ul { margin-top: 8px; }
.shell .agent-notes li { font-size: 12.5px; }

/* ── Roadmap: numbered phase circle + collapsible completed phases ── */
.shell .phase-num {
  display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0;
  width: 27px; height: 27px; border-radius: 50%; background: var(--accent); color: var(--on-accent);
  font-family: var(--font-mono); font-size: 11.5px; font-weight: 600;
}
.shell .phase-num.is-done { background: var(--ok); color: #fff; }
.shell .phase-num .material-symbols-outlined { font-size: 15px; }
.shell .phase-collapse-toggle {
  background: none; border: none; padding: 0; cursor: pointer; color: var(--ink-dim);
  display: inline-flex; align-items: center; gap: 4px; font-size: 12.5px; font-family: var(--font-body);
}
.shell .phase-collapse-toggle .material-symbols-outlined { font-size: 16px; }
.shell .phase-link { margin-top: 16px; }
.shell .phase-head-left { display: flex; align-items: center; gap: 12px; }
.shell .roadmap-phase { margin-bottom: 16px; }
.shell .vh-head { min-height: 44px; }
.shell .vh-stage.done .listcard-title { color: var(--ink-dim); }
.shell .ck-box .material-symbols-outlined { font-size: 12px; }
.shell .listcard .ck-list { margin-top: 4px; }

/* ── Progress bar on canvas ── */
.shell .bar { height: 4px; border-radius: 3px; background: var(--track); overflow: hidden; }
.shell .bar > span { display: block; height: 100%; background: var(--accent-ink); width: 0; transition: width var(--t-bar); }
.shell .bar-caption {
  margin-top: 8px; font-family: var(--font-mono); font-size: 9.5px; font-weight: 500; letter-spacing: .14em; text-transform: uppercase;
  color: var(--ink-dim);
}

/* ── Form field ── */
.shell .field-label {
  display: block; font-family: var(--font-mono); font-size: 9.5px; font-weight: 500; letter-spacing: .14em; text-transform: uppercase;
  color: var(--ink-dim); margin-bottom: 6px;
}
.shell .field {
  width: 100%; background: var(--card); border: 1px solid var(--line-strong); border-radius: var(--r-btn);
  padding: 13px 14px; font-family: var(--font-body); font-size: 14px; color: var(--ink); outline: none;
  transition: border-color var(--t-fast), box-shadow var(--t-fast);
}
.shell .field::placeholder { color: var(--ink-dim); }
.shell .field:focus { border-color: var(--accent-ink); box-shadow: 0 0 0 3px rgba(176,138,74,.16); }
.shell .field.error { border-color: var(--alert); }
.shell .field-error { font-size: 12px; color: var(--alert); margin-top: 6px; }
.shell select.field {
  appearance: none; padding-right: 36px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='18' height='18' viewBox='0 0 24 24'%3E%3Cpath fill='%23191B1E' fill-opacity='.56' d='M7 10l5 5 5-5z'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 10px center; cursor: pointer;
}

/* ── Filter chip / tab ── */
.shell .tab {
  display: inline-flex; align-items: center; padding: 8px 14px; border-radius: var(--r-btn);
  font-family: var(--font-mono); font-size: 10.5px; font-weight: 500; letter-spacing: .14em; text-transform: uppercase;
  background: transparent; border: 1px solid var(--line); color: var(--ink-dim);
  transition: background-color var(--t-fast), border-color var(--t-fast), color var(--t-fast);
}
.shell .tab:hover { border-color: var(--line-strong); }
.shell .tab[aria-selected="true"] { background: var(--chrome); color: var(--on-chrome); border-color: var(--chrome); }
.shell .tab-n { opacity: .6; margin-left: 4px; }

/* ── Assessment: field-styled radio rows, 44px min touch target ── */
.shell .asm-opts { display: flex; flex-direction: column; gap: 10px; max-width: 560px; }
.shell .asm-opt {
  display: block; width: 100%; min-height: 44px; text-align: left; cursor: pointer;
  font-family: var(--font-body); font-size: 14px; color: var(--ink);
}
.shell .asm-opt:hover { border-color: var(--ink); }
.shell .result-stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; margin-top: 16px; }
@media (max-width: 480px) { .shell .result-stats { grid-template-columns: 1fr; } }

/* ── Spacing utilities — the README's own 8px scale, for the handful of
   dynamic top-margins a template string can't express as a static rule ── */
.shell .mt-3 { margin-top: 12px; }
.shell .mt-4 { margin-top: 16px; }
.shell .mt-5 { margin-top: 20px; }
.shell .mt-6 { margin-top: 24px; }
.shell .mt-7 { margin-top: 32px; }
.shell .chip-row { display: flex; flex-wrap: wrap; gap: 6px; }
.shell .fc-currency { display: flex; border: 1px solid var(--line-strong); border-radius: var(--r-btn); overflow: hidden; }
.shell .fc-amount-row { display: flex; gap: 10px; align-items: stretch; flex-wrap: wrap; max-width: 560px; }
.shell .fc-amount-row .field { flex: 1; min-width: 160px; font-size: 16px; }

/* ── Two-up choice cards (track picker, plan cards) ── */
.shell .choice-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px; margin-top: 24px; }
@media (max-width: 640px) { .shell .choice-grid { grid-template-columns: 1fr; } }

/* ── Course Catalogue / result grids: 3-up cards, expanded one spans full width ── */
.shell .card-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; align-items: start; }
.shell .card-grid > .listcard { min-width: 0; }
.shell .card-grid > .listcard.is-open { grid-column: 1 / -1; }
@media (max-width: 1199px) { .shell .card-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 899px) { .shell .card-grid { grid-template-columns: 1fr; } }
.shell .tab-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 16px; }
.shell .tab-row-end { margin-left: auto; display: flex; align-items: center; gap: 8px; }
.shell .tab .material-symbols-outlined { font-size: 14px; vertical-align: -2px; }

/* ── Icon tile ── */
.shell .icontile {
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
  width: 34px; height: 34px; border-radius: var(--r-icon); background: var(--accent-wash);
}
.shell .icontile .material-symbols-outlined { font-size: 19px; color: var(--accent-ink); }

/* ── Avatar ── */
.shell .avatar {
  display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; border-radius: 50%;
  font-family: var(--font-mono); font-weight: 600;
}
.shell .avatar-nav { width: 30px; height: 30px; font-size: 11px; background: var(--accent); color: var(--on-accent); }
/* A signed-in staff session must read as staff at a glance — not look
   identical to any other signed-in visitor (U-30). */
.shell .avatar-nav[data-role="admin"] { background: var(--alert); color: #fff; }
.shell .avatar-nav[data-role="mentor"] { background: var(--ok); color: #fff; }
.shell .avatar-nav[data-role="mentor_pending"] { background: var(--warn); color: #fff; }
.shell .avatar-card { width: 36px; height: 36px; font-size: 11.5px; background: var(--accent-wash); color: var(--accent-ink); }

/* ── Skeleton loading rows ── */
.shell .skel-row { height: 44px; border-radius: 8px; background: var(--line-soft); margin-bottom: 8px; }
.shell .skel-row:last-child { margin-bottom: 0; }

/* ── Main layout grid ── */
.shell .viewgrid { display: grid; grid-template-columns: 1fr var(--aside-w); gap: var(--gap-main); align-items: start; }
/* grid items default to min-width:auto, which lets long unbroken content
   (a long course/application title, a wide row) grow a column past its
   track instead of wrapping — the same failure mode as the mobile hero
   bug above. min-width:0 on every direct grid/flex child in this file
   keeps that content inside its column. */
.shell .viewgrid > * { min-width: 0; }
.shell .aside { display: flex; flex-direction: column; gap: 16px; }

@media (max-width: 1199px) {
  .shell .viewgrid { grid-template-columns: 1fr; }
  .shell .aside { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
  .shell .stat-grid { grid-template-columns: repeat(4, 1fr); }
}

@media (max-width: 899px) {
  .shell .main { padding: 28px 20px 96px; }
  .shell .topnav { padding: 16px 20px; }
  .shell .topnav-links, .shell .topnav-context { display: none; }
  .shell .navmore .ic-more { display: none; }
  .shell .navmore .ic-menu { display: inline; }
  .shell .navpop { right: 20px; }
  .shell .tabbar { display: flex; }
  .shell .aside { grid-template-columns: 1fr; }
  .shell .hero { padding: 24px 22px; }
  .shell .hero-title { font-size: 1.75rem; }
  /* align-items:flex-start (set for the desktop side-by-side row) makes a
     column-direction flex child size toward its own max-width instead of
     the actual (narrower) container — .hero-left would sit at ~520px
     regardless of viewport, and since flex/grid items default to
     min-width:auto, that oversized child then blows out .hero, .main and
     .shell instead of wrapping, giving the whole page a horizontal
     scrollbar. stretch forces it back to the real container width. */
  .shell .hero-row { flex-direction: column; align-items: stretch; }
  .shell .hero-right { display: none; }
  .shell .hero-figure-mobile { display: block; margin-bottom: 22px; }
  .shell .hero-figure-mobile .hero-figure { font-size: 2.6rem; }
  .shell .hero-actions { flex-direction: column; }
  .shell .hero-actions .btn, .shell .hero-actions .btn-ghost { width: 100%; justify-content: center; }
  .shell .stat-grid { grid-template-columns: repeat(2, 1fr); }
  /* ── Rows on a phone ──────────────────────────────────────────────
     `.row` is a desktop three-part strip: [optional icon][.row-main][
     .row-actions]. `.row-actions` had no rule of its own, so it sized to
     its max-content — two side-by-side buttons — while `.row-main` (flex:1,
     min-width:0) obligingly shrank to whatever was left. On a 390px screen
     that left the text column at SIXTY-NINE PIXELS: a scholarship
     description wrapping at two words a line down the left third of the
     card, with the buttons floating in the empty right half, vertically
     centred against a column of text ten times their height.

     `flex-wrap: wrap` alone never fixed it, because a flex item with
     min-width:0 shrinks rather than wraps. Giving the ACTIONS a full-width
     basis is what forces them onto their own line and hands `.row-main`
     the rest of line one. `.row-main` deliberately keeps a flexible basis
     rather than 100% — at 100% it pushes a leading icon onto a line of its
     own, which is how the Visa Hub's "where to go" rows look wrong. */
  .shell .row { flex-wrap: wrap; align-items: flex-start; gap: 10px 12px; }
  .shell .row-main { flex: 1 1 auto; min-width: 0; }
  .shell .row-actions {
    flex: 0 0 100%; display: flex; flex-wrap: wrap; gap: 8px;
  }
  .shell .row-actions .btn { flex: 1 1 auto; justify-content: center; }
  /* Leading icons keep their own column and never stretch. */
  .shell .row > .material-symbols-outlined,
  .shell .row > .stat-icon { flex: 0 0 auto; margin-top: 2px; }

  /* Body copy in a row was 12px with a 1.4 line-height — the size you use
     for a caption, carrying the actual content of this screen. */
  .shell .row-title { font-size: 15px; line-height: 1.35; }
  .shell .row-sub { font-size: 13.5px; line-height: 1.55; margin-top: 4px; }
  /* 9.5px uppercase mono is unreadable at arm's length on a phone. */
  .shell .chip { font-size: 10.5px; padding: 4px 10px; letter-spacing: .07em; }
  /* Chip groups need room to breathe once they wrap. */
  .shell .row-main .mt-3 { display: flex; flex-wrap: wrap; gap: 6px; }
  .shell .segs { overflow-x: auto; scroll-snap-type: x proximity; margin: 30px -4px 0; padding: 0 4px 4px; scrollbar-width: none; }
  .shell .segs::-webkit-scrollbar { display: none; }
  .shell .seg { flex: 0 0 30%; scroll-snap-align: start; }
}

@media (max-width: 480px) {
  .shell .stat-grid { grid-template-columns: repeat(2, 1fr); }
}

/* ═══════════════════════════════════════════════════════════════════
   Cost & payback (#cost)

   Written mobile-first, because this screen is read on a phone by a
   student and printed on paper for a parent, and almost never opened on
   a desktop. The previous version reused .row / .row-actions, which is a
   flex pair built for a short label and a chip — given a money column,
   a currency conversion and a sentence it refused to wrap and pushed the
   document to 770px inside a 375px viewport.

   Every rule below therefore starts from the narrow case and only widens
   at a breakpoint, and every text container is min-width:0 so a long
   unbreakable string shrinks its column instead of the page.
   ═══════════════════════════════════════════════════════════════════ */

.shell .roi-plan { padding: 0; overflow: hidden; }
/* The summary is a ROW — a text column that wraps freely and a control
   on the end that stays put. The chevron used to be absolutely
   positioned at a fixed offset from the top, which is correct for
   exactly one summary height: at 360px the plan line wraps to three
   lines and the chevron floated up beside the kicker, and on the sources
   card it sat beside a one-line heading. As a flex item it is centred
   against whatever the text does. */
.shell .roi-plan-summary {
  display: flex; align-items: center; gap: 14px;
  padding: 16px 18px; cursor: pointer; list-style: none;
}
.shell .roi-plan-summary::-webkit-details-marker { display: none; }
.shell .roi-plan-text {
  display: flex; flex-direction: column; gap: 3px;
  flex: 1 1 auto; min-width: 0;
}
/* An "edit" affordance rather than a bare chevron: a heading with a
   caret beside it reads as a heading, and students were not finding the
   fields underneath it. The chevron is drawn in CSS rather than set as a
   Material Symbols ligature — the icon font is a network request, and
   when it fails the ligature name renders as the literal word
   "expand_more". A border triangle always draws. */
.shell .roi-plan-edit {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: 7px;
  padding: 7px 12px; border: 1px solid var(--line-strong); border-radius: var(--r-btn);
  font-family: var(--font-mono); font-size: 10px; font-weight: 500;
  letter-spacing: .12em; text-transform: uppercase; color: var(--ink-soft);
  white-space: nowrap;
}
.shell .roi-plan-edit::after {
  content: ''; width: 7px; height: 7px; margin-top: -3px;
  border-right: 2px solid currentColor; border-bottom: 2px solid currentColor;
  transform: rotate(45deg); transition: transform var(--t-bar, .2s) ease;
}
.shell details[open] > .roi-plan-summary .roi-plan-edit::after { transform: rotate(-135deg); margin-top: 2px; }
.shell .roi-plan-summary:hover .roi-plan-edit { border-color: var(--accent-ink); color: var(--ink); }
.shell .roi-plan-summary strong { font-size: 15px; line-height: 1.35; overflow-wrap: anywhere; }
.shell .roi-plan-summary .faint { font-size: 12.5px; line-height: 1.45; }

.shell .roi-fields {
  display: grid; grid-template-columns: 1fr; gap: 16px;
  padding: 4px 18px 18px; border-top: 1px solid var(--line);
}
.shell .roi-fields label { display: block; min-width: 0; }
.shell .roi-fields .field { width: 100%; }
.shell .roi-fields .field-label { margin-bottom: 3px; }
/* One plain sentence under each label. The audience for this screen has
   never seen a New Zealand fee schedule and does not know that student
   work is legal, let alone capped at 25 hours — a bare label like
   "Scholarship on tuition (%)" is a question they cannot answer. */
.shell .field-help {
  display: block; font-size: 12px; line-height: 1.45;
  color: var(--ink-faint); margin: 0 0 8px;
}
.shell .roi-plan-foot {
  display: flex; flex-wrap: wrap; gap: 10px 16px; align-items: center; justify-content: space-between;
  padding: 14px 18px; border-top: 1px solid var(--line); background: var(--surface, transparent);
}
.shell .roi-plan-foot p { font-size: 12px; line-height: 1.5; margin: 0; flex: 1 1 220px; }

/* ── "How to read this page" ────────────────────────────────────────
   Three numbered steps, in the order the page is read. */
.shell .roi-intro { border-color: var(--accent-ink, var(--ochre)); }
.shell .roi-steps { list-style: none; counter-reset: roi-step; padding: 0; margin: 14px 0 0; }
.shell .roi-steps li {
  counter-increment: roi-step; position: relative;
  padding: 0 0 14px 38px; margin-bottom: 14px; border-bottom: 1px solid var(--line);
}
.shell .roi-steps li:last-child { border-bottom: 0; margin-bottom: 0; padding-bottom: 0; }
.shell .roi-steps li::before {
  content: counter(roi-step); position: absolute; left: 0; top: -1px;
  width: 24px; height: 24px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--gold-soft, var(--surface)); color: var(--accent-ink, var(--ochre));
  font-family: var(--font-mono); font-size: 11px; font-weight: 600;
}
/* Direct children only — the body text quotes the card's own heading in
   bold, and a nested <strong> that goes display:block breaks the
   sentence in half. */
.shell .roi-steps li > strong { display: block; font-size: 14.5px; line-height: 1.35; }
.shell .roi-steps li > span { display: block; font-size: 13px; color: var(--ink-soft); line-height: 1.55; margin-top: 4px; }
.shell .roi-intro-foot { font-size: 12px; color: var(--ink-faint); line-height: 1.55; margin: 16px 0 0; padding-top: 14px; border-top: 1px solid var(--line); }

/* ── The student's own shortlist, costable in one tap ──────────────── */
.shell .roi-courses { padding: 14px 0; border-bottom: 1px solid var(--line); }
.shell .roi-courses:last-child { border-bottom: 0; }
.shell .roi-courses-head { margin-bottom: 4px; }
.shell .roi-course {
  display: flex; flex-direction: column; gap: 10px;
  padding: 12px 0; border-bottom: 1px solid var(--line);
}
.shell .roi-course:last-child { border-bottom: 0; padding-bottom: 0; }
.shell .roi-course-main { min-width: 0; flex: 1 1 auto; }
.shell .roi-course-title { font-size: 14px; line-height: 1.35; overflow-wrap: anywhere; }
.shell .roi-course-sub { font-size: 12px; color: var(--ink-faint); line-height: 1.45; margin-top: 3px; }
.shell .roi-course-fee { font-size: 12px; color: var(--ink-soft); line-height: 1.5; margin-top: 7px; }
.shell .roi-course-act { flex: 0 0 auto; }
.shell .roi-course-act .btn { width: 100%; justify-content: center; }
.shell .roi-course.is-current .roi-course-title { font-weight: 600; }

.shell .roi-headline { border-color: var(--ochre); }
.shell .roi-big {
  font-family: var(--font-mono, inherit); font-weight: 700;
  font-size: clamp(1.55rem, 8.5vw, 2.4rem); line-height: 1.1;
  margin-top: 6px; overflow-wrap: anywhere;
}
.shell .roi-big-sub { font-size: 12.5px; color: var(--ink-soft); margin-top: 6px; }
.shell .roi-facts {
  display: grid; grid-template-columns: 1fr; gap: 10px;
  margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--line);
}
.shell .roi-facts > div { display: flex; justify-content: space-between; gap: 12px; align-items: baseline; }
.shell .roi-facts .faint { font-size: 12.5px; }
.shell .roi-facts strong { font-size: 14px; white-space: nowrap; }
/* The one sentence that stops a five-figure number being read as a
   yearly fee, which is how most readers have seen every other figure
   quoted to them. */
.shell .roi-headline-note {
  font-size: 12.5px; color: var(--ink-soft); line-height: 1.55;
  margin: 14px 0 0; padding-top: 12px; border-top: 1px solid var(--line);
}

/* One cost/earnings line. Label block is min-width:0 so it wraps; the
   money block never wraps and never shrinks. */
.shell .roi-line {
  display: flex; gap: 14px; align-items: flex-start; justify-content: space-between;
  padding: 13px 0; border-bottom: 1px solid var(--line);
}
.shell .roi-line:last-of-type { border-bottom: 0; }
.shell .roi-line-main { min-width: 0; flex: 1 1 auto; }
.shell .roi-line-label { font-size: 14px; line-height: 1.35; }
.shell .roi-line-detail { font-size: 12px; color: var(--ink-faint); line-height: 1.45; margin-top: 3px; }
.shell .roi-line-money {
  flex: 0 0 auto; text-align: right; display: flex; flex-direction: column; gap: 2px;
}
.shell .roi-line-money strong { font-size: 14px; white-space: nowrap; }
.shell .roi-line-money .faint { font-size: 11.5px; white-space: nowrap; }

.shell .roi-basis { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--line); }
.shell .roi-basis p { font-size: 12.5px; color: var(--ink-soft); margin: 8px 0 0; }
.shell .roi-basis .btn { width: 100%; justify-content: center; }

/* A cheaper-route card. Stacks on a phone — the saving is the headline,
   so it sits under the provider name at full width rather than being
   squeezed into a right-hand column. */
.shell .roi-route {
  padding: 16px 0; border-bottom: 1px solid var(--line);
}
.shell .roi-route:last-of-type { border-bottom: 0; }
.shell .roi-route-head {
  display: flex; flex-direction: column; gap: 8px; margin-bottom: 8px;
}
.shell .roi-route-kicker {
  font-size: 10.5px; text-transform: uppercase; letter-spacing: .08em; color: var(--ink-faint);
}
.shell .roi-route-title { font-size: 15px; font-weight: 600; line-height: 1.3; }
.shell .roi-route-save { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.shell .roi-route-save strong { font-size: 15px; color: var(--ok, var(--route)); white-space: nowrap; }
.shell .roi-route-save .faint { font-size: 12px; white-space: nowrap; }
.shell .roi-route-tradeoff { font-size: 12px; color: var(--ink-soft); margin: 8px 0 0; line-height: 1.5; }
.shell .roi-route-foot {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; margin-top: 12px;
}
.shell .roi-route-foot .faint { font-size: 11.5px; }

/* .roi-src and .roi-warn sit inside a plain (non-.roi-plan) .listcard, which
   already provides the card's 24px/26px inset — the 20px this pair used to
   add on top of that pushed the source list and the closing note visibly
   further right than the "Where these numbers come from" heading above
   them, in the same card. That is the "narrow margins" bug: not narrow
   overall, just narrower than every sibling block on the same screen. */
.shell .roi-src { list-style: none; padding: 0 0 4px; margin: 0; }
.shell .roi-src li {
  font-size: 12px; color: var(--ink-soft); line-height: 1.5;
  padding: 7px 0; border-bottom: 1px solid var(--line); overflow-wrap: anywhere;
}
.shell .roi-src li:last-child { border-bottom: 0; }
.shell .roi-warn { font-size: 11.5px; color: var(--ink-soft); line-height: 1.55; padding: 10px 0 0; margin: 0; }
/* .roi-plan-summary is shared with the Plan card's <details>, which zeroes
   the listcard padding itself (.roi-plan below) and relies on this rule's
   own 18px horizontal inset instead. The Sources card never resets that
   padding, so without this override its heading row would also gain a
   phantom extra inset the rest of the card does not have. */
.shell .listcard:not(.roi-plan) > .roi-plan-summary { padding: 16px 0; }

/* Wider screens: two money columns side by side, fields in a grid. */
@media (min-width: 620px) {
  .shell .roi-fields { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .shell .roi-facts { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .shell .roi-facts > div { flex-direction: column; gap: 3px; }
  .shell .roi-line-money { flex-direction: row; align-items: baseline; gap: 12px; }
  .shell .roi-line-money .faint { min-width: 118px; }
  .shell .roi-route-head { flex-direction: row; align-items: flex-start; justify-content: space-between; }
  .shell .roi-route-save { flex-direction: column; align-items: flex-end; gap: 2px; text-align: right; flex: 0 0 auto; }
  .shell .roi-basis .btn { width: auto; }
  /* A saved course and its button sit on one line once there is room for
     the title to still read as a title. */
  .shell .roi-course { flex-direction: row; align-items: flex-start; justify-content: space-between; gap: 16px; }
  .shell .roi-course-act .btn { width: auto; }
}
@media (min-width: 900px) {
  .shell .roi-fields { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
/* Small phones: the plan summary's "Change" pill and a three-line plan
   description fight for the same 320px. Drop the pill's word and keep
   the chevron, which is all it needs to be at that width. */
@media (max-width: 360px) {
  .shell .roi-plan-summary { gap: 10px; padding: 15px 14px; }
  .shell .roi-plan-edit { font-size: 0; padding: 8px 9px; gap: 0; }
  .shell .roi-plan-edit::after { width: 8px; height: 8px; }
  .shell .roi-fields { padding: 4px 14px 16px; }
  .shell .roi-plan-foot { padding: 12px 14px; }
}

/* ── Provider quality (#cost) ───────────────────────────────────────
   NZQA's published record, shown next to the price. Sized so the
   regulator's finding and the saving are legible in one glance — a
   comparison that shows only the cheaper number is an argument for the
   cheapest option, not a decision aid. */
.shell .roi-qa-concern { border-color: var(--alert, var(--ochre)); }
.shell .roi-qa-verdict { margin-top: 14px; }
.shell .roi-qa-verdict p { font-size: 13px; color: var(--ink-soft); line-height: 1.55; margin: 9px 0 0; }
.shell .roi-qa-note { font-size: 11.5px !important; color: var(--ink-faint) !important; }
.shell .roi-qa-list { list-style: none; padding: 0; margin: 14px 0 0; }
.shell .roi-qa-list li {
  font-size: 12.5px; color: var(--ink-soft); line-height: 1.5;
  padding: 7px 0; border-bottom: 1px solid var(--line);
}
.shell .roi-qa-list li:last-child { border-bottom: 0; }
.shell .roi-qa-code { font-size: 12.5px; color: var(--ink-soft); line-height: 1.55; margin: 14px 0 0; }
.shell .roi-qa-reports {
  display: flex; flex-wrap: wrap; gap: 8px 14px; align-items: baseline; margin-top: 14px;
}
.shell .roi-qa-reports .faint { font-size: 11.5px; }
.shell .roi-qa-reports a { font-size: 12.5px; }
.shell .roi-qa-limits { margin: 8px 0 0; padding-left: 18px; }
.shell .roi-qa-limits li { font-size: 12px; color: var(--ink-soft); line-height: 1.5; margin-bottom: 5px; }
.shell .roi-qa-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 16px; }
.shell .roi-qa-actions .btn { flex: 1 1 auto; justify-content: center; }

.shell .roi-route-qa {
  display: flex; flex-wrap: wrap; align-items: center; gap: 7px 10px; margin-top: 10px;
}
.shell .roi-route-qa a { font-size: 11.5px; }
.shell .roi-route-warn {
  font-size: 12px; line-height: 1.5; margin: 10px 0 0; padding: 10px 12px;
  border-radius: 3px; background: var(--warn-bg, var(--gold-soft));
  border: 1px dashed var(--line-2);
}
@media (min-width: 620px) {
  .shell .roi-qa-actions .btn { flex: 0 0 auto; }
}

/* ══ Government data panels (#visa, #cost, #settlement) ═══════════════
   Immigration NZ decision figures and MBIE rent medians. These carry an
   authority the rest of the app's numbers do not — they are the state's
   own record, not PathFinder's estimate — so they get one restrained
   visual signal (the pine rule) and otherwise sit inside the existing
   card, chip and ledger vocabulary rather than inventing a second one. */
.shell .govt-card { border-top: 2px solid var(--pine); }

.shell .govt-headline {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 14px 28px; margin-top: 16px;
}
.shell .govt-figure { display: flex; flex-direction: column; gap: 2px; }
.shell .govt-figure strong {
  font-family: var(--font-display); font-size: 40px; line-height: 1;
  letter-spacing: -.02em; color: var(--pine); font-variant-numeric: tabular-nums;
}
.shell .govt-figure span { font-size: 12.5px; color: var(--ink-soft); }

.shell .govt-split { display: flex; flex-wrap: wrap; gap: 12px 24px; }
.shell .govt-split > div { display: flex; flex-direction: column; gap: 1px; }
.shell .govt-n {
  font-family: var(--font-mono); font-size: 16px; font-variant-numeric: tabular-nums; color: var(--ink);
}
.shell .govt-l {
  font-size: 10.5px; text-transform: uppercase; letter-spacing: .07em; color: var(--ink-faint);
}

/* Ten years, ten bars. Deliberately not a chart: the figure that matters
   is printed above, and these only carry the shape of the decade. */
/* Tall enough for ten values to separate, and capped in width — stretched
   across a full-width card the columns turn into a wall of blocks and the
   trend stops being legible. */
.shell .govt-bars {
  display: flex; align-items: flex-end; gap: 4px; height: 76px;
  margin-top: 18px; max-width: 460px;
}
/* No track behind the column. A full-height tint on every bar makes the
   low years read as tall grey blocks, which is the opposite of what a
   trend is for — the shape has to come from the filled height alone. */
.shell .govt-bar {
  flex: 1 1 0; height: 100%; display: flex; align-items: flex-end;
  border-bottom: 1px solid var(--line);
}
.shell .govt-bar > span {
  display: block; width: 100%; background: var(--pine); opacity: .38; border-radius: 2px 2px 0 0;
}
.shell .govt-bar.is-now > span { opacity: 1; }
.shell .govt-bars-axis {
  display: flex; justify-content: space-between; margin-top: 6px; max-width: 460px;
  font-family: var(--font-mono); font-size: 10px; color: var(--ink-faint);
}

/* Attribution. A licence condition, not a footnote — CC BY on the MBIE
   data and NZGOAL on the INZ files both require the credit to travel
   with the figures, so it renders next to them and never collapses. */
.shell .govt-src {
  font-size: 11px; line-height: 1.5; color: var(--ink-faint); margin: 10px 0 0;
}
.shell .govt-src a { color: var(--ink-soft); }
.shell .govt-inline {
  font-size: 12.5px; line-height: 1.55; color: var(--ink-soft);
  margin: 12px 0 0; padding-top: 12px; border-top: 1px dashed var(--line);
}
.shell .govt-inline .govt-src { margin-top: 6px; }

.shell .govt-locked {
  margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--line);
}
.shell .govt-locked p { font-size: 13px; line-height: 1.55; color: var(--ink-soft); }

.shell .govt-detail { margin-top: 20px; padding-top: 18px; border-top: 1px solid var(--line); }
.shell .govt-h3 { font-size: 14px; margin: 0 0 4px; }
.shell .govt-detail .govt-h3:not(:first-child) { margin-top: 26px; }
.shell .govt-note { font-size: 11.5px; color: var(--ink-faint); margin: 0 0 6px; }

.shell .govt-table td { padding: 11px 12px 11px 0; font-size: 13px; vertical-align: middle; }
.shell .govt-table tr:last-child td { border-bottom: 0; }
.shell .govt-table tr.is-mine td { font-weight: 600; }
.shell .govt-td-n {
  font-family: var(--font-mono); font-size: 12.5px; text-align: right;
  white-space: nowrap; font-variant-numeric: tabular-nums; width: 1%;
}
.shell .govt-faint { color: var(--ink-faint); font-size: 11px; }
.shell .govt-td-bar { width: 40%; min-width: 90px; }
.shell .govt-rate {
  display: block; height: 6px; border-radius: 3px; background: var(--line-soft); overflow: hidden;
}
.shell .govt-rate-fill { display: block; height: 100%; background: var(--sea); opacity: .55; border-radius: 3px; }
.shell .govt-rate-fill.is-mine { background: var(--pine); opacity: 1; }

@media (max-width: 560px) {
  .shell .govt-figure strong { font-size: 34px; }
  .shell .govt-td-bar { display: none; }
}

/* Result-list pager (#courses). The catalogue can match 1,716 rows; the
   list renders a page at a time so the DOM stays under ~700 nodes instead
   of 18,000, which is the difference between a smooth scroll and a stalled
   one on the mid-range Android this audience actually browses on. */
.shell .crs-more {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px 16px;
  margin-top: 20px; padding-top: 18px; border-top: 1px solid var(--line);
}
.shell .crs-more .faint { font-size: 12.5px; }

/* ── Mentor profiles ══════════════════════════════════════════════════
   Browse profiles (#mentors → grid of mn-card) and the full profile
   page (mnp-*) it links into. Built from the same tokens as the rest of
   the shell (--card, --r-card, --shadow-card, the chip system) so a
   "modern" feel comes from proportion, whitespace and the avatar
   treatment — not a second visual language bolted onto this one. */

/* Avatar — no photo-upload pipeline in this build, so a colour-coded
   initials mark stands in (see mentorAvatarHtml in app.js). The ring is
   a soft halo in the same colour as the fill, not a hard border. */
.shell .mn-avatar {
  display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0;
  width: 52px; height: 52px; border-radius: var(--r-pill);
  font-family: var(--font-display); font-weight: 600; font-size: 1.05rem; letter-spacing: -.01em;
  box-shadow: 0 0 0 4px rgba(255,255,255,.6), 0 4px 14px rgba(25,27,30,.10);
}
.shell .mn-avatar-lg {
  width: 88px; height: 88px; font-size: 1.9rem;
  box-shadow: 0 0 0 6px rgba(255,255,255,.7), 0 10px 28px rgba(25,27,30,.14);
}

/* Locked teaser — shown in place of the grid/profile when signed out. */
.shell .mn-locked { text-align: center; padding: 48px 32px; max-width: 480px; margin: 0 auto; }
.shell .mn-locked-icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 52px; height: 52px; border-radius: var(--r-pill); background: var(--accent-wash); color: var(--accent-ink);
  font-size: 24px;
}
.shell .mn-locked p { max-width: 40ch; margin-left: auto; margin-right: auto; }

/* Search + grid */
.shell .mn-search { max-width: 420px; }
.shell .mn-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 16px;
}
.shell .mn-card {
  display: block; color: inherit;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r-card);
  padding: 22px; box-shadow: var(--shadow-card);
  transition: transform var(--t-fast), border-color var(--t-fast), box-shadow var(--t-fast);
}
.shell .mn-card:hover { transform: translateY(-2px); border-color: var(--line-strong); box-shadow: var(--shadow-hero); }
.shell .mn-card-top { display: flex; align-items: center; gap: 14px; }
.shell .mn-card-id { min-width: 0; }
.shell .mn-card-name { font-family: var(--font-display); font-weight: 600; font-size: 1.02rem; letter-spacing: -.01em; }
.shell .mn-card-quals { font-size: 12px; color: var(--ink-dim); margin-top: 2px; }
.shell .mn-card-bio { font-size: 13px; color: var(--ink-dim); line-height: 1.55; margin-top: 14px; }
.shell .mn-card-skills { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 14px; }
.shell .mn-card-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--line-soft);
  font-size: 12px; color: var(--ink-dim);
}
.shell .mn-card-city { display: inline-flex; align-items: center; gap: 4px; }
.shell .mn-card-city .material-symbols-outlined { font-size: 14px; }
.shell .mn-card-link { display: inline-flex; align-items: center; gap: 3px; color: var(--accent-ink); font-weight: 600; }
.shell .mn-card-link .material-symbols-outlined { font-size: 15px; transition: transform var(--t-fast); }
.shell .mn-card:hover .mn-card-link .material-symbols-outlined { transform: translateX(2px); }

/* A "topic I help with" tag — its own tint, distinct from the chip-*
   status colours (this isn't a state, it's a category). */
.shell .chip-topic { color: var(--accent-ink); background: var(--accent-wash); }

/* Full profile page */
.shell .mnp-back {
  display: inline-flex; align-items: center; gap: 6px; color: var(--ink-dim); font-size: 13px; font-weight: 500;
  margin-bottom: 18px;
}
.shell .mnp-back .material-symbols-outlined { font-size: 16px; }
.shell .mnp-back:hover { color: var(--ink); }
.shell .mnp-hero {
  display: flex; align-items: center; gap: 22px; flex-wrap: wrap;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r-hero);
  padding: 32px 34px; box-shadow: var(--shadow-card);
}
.shell .mnp-name { font-family: var(--font-display); font-size: 1.7rem; font-weight: 600; letter-spacing: -.015em; }
.shell .mnp-quals { font-size: 14.5px; color: var(--ink-dim); margin-top: 3px; }
.shell .mnp-hero-meta { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-top: 12px; font-size: 13px; color: var(--ink-dim); }
.shell .mnp-hero-meta > span { display: inline-flex; align-items: center; gap: 4px; }
.shell .mnp-hero-meta .material-symbols-outlined { font-size: 16px; }
.shell .mnp-skills { display: flex; flex-wrap: wrap; gap: 8px; }
.shell .mnp-packages { display: flex; flex-direction: column; gap: 2px; }
.shell .mnp-pkg {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 13px 0; border-bottom: 1px solid var(--line-soft); font-size: 13.5px;
}
.shell .mnp-pkg:last-child { border-bottom: 0; }
.shell .mnp-pkg-name { font-weight: 500; }
.shell .mnp-pkg-price { font-family: var(--font-mono); font-size: 12px; color: var(--ink-dim); white-space: nowrap; }
.shell .mnp-fact { display: flex; align-items: flex-start; gap: 10px; padding: 10px 0; }
.shell .mnp-fact + .mnp-fact { border-top: 1px solid var(--line-soft); }
.shell .mnp-fact .material-symbols-outlined { font-size: 17px; color: var(--accent-ink); margin-top: 1px; }
.shell .mnp-fact-label { display: block; font-family: var(--font-mono); font-size: 9.5px; font-weight: 500; letter-spacing: .1em; text-transform: uppercase; color: var(--ink-dim); }
.shell .mnp-fact-value { display: block; font-size: 13px; margin-top: 2px; }
#mnp-ask .consult-hook { border: 0; padding: 0; margin-top: 10px; }
#mnp-ask .consult-hook-toggle { padding: 0; }

@media (max-width: 720px) {
  .shell .mnp-hero { padding: 24px; }
  .shell .mn-avatar-lg { width: 68px; height: 68px; font-size: 1.5rem; }
}

/* ════════════════════════════════════════════════════════════
   Analytics consent banner (assets/js/analytics.js)

   Injected into <body> by PFAnalytics on every page, including the
   legal pages, which load no other JavaScript — hence styling it here
   in the one stylesheet all six HTML files already share rather than
   shipping colours inside the script.

   Bottom-anchored rather than a full-screen interstitial: this is a
   question about page counting, not a gate, and the site is required
   to work identically whichever button is pressed. The two buttons are
   deliberately the same size — an under-styled "Decline" beside a
   bright "Accept" is not a free choice, and this audience is being
   asked to trust the site with their visa and their money.
   ════════════════════════════════════════════════════════════ */
.pf-consent {
  /* Below .modal (200) and .toast (500) ON PURPOSE. At a z-index above them
     an unanswered banner floats over the payment modal and, on a short
     screen, sits directly on top of the "I've paid" button — a consent
     prompt that silently costs a student their purchase. Above the nav
     (100) is all the prominence this needs; the media query below already
     lifts it clear of the mobile tab bar. */
  position: fixed; z-index: 190;
  left: 16px; right: 16px; bottom: 16px;
  max-width: 640px; margin-inline: auto;
  background: var(--surface); color: var(--ink);
  border: 1px solid var(--line); border-radius: 12px;
  box-shadow: var(--shadow-2);
  /* Starts translated out and un-hit-testable; .is-in (added on the next
     frame) is what animates it in, so it never flashes at its final
     position before the transition begins. */
  opacity: 0; transform: translateY(14px); pointer-events: none;
  transition: opacity .26s ease, transform .26s cubic-bezier(.22,1,.36,1);
}
.pf-consent.is-in { opacity: 1; transform: none; pointer-events: auto; }
.pf-consent-inner { display: flex; align-items: center; gap: 18px; padding: 16px 18px; }
.pf-consent-copy strong { display: block; font-size: 13.5px; font-weight: 600; margin-bottom: 3px; }
.pf-consent-copy p { font-size: 12.5px; line-height: 1.55; color: var(--ink-soft); margin: 0; }
.pf-consent-copy a { color: var(--route); text-decoration: underline; text-underline-offset: 2px; }
.pf-consent-actions { display: flex; gap: 8px; flex-shrink: 0; }
.pf-consent-actions .btn { white-space: nowrap; }

/* On a phone the two buttons cannot sit beside 60 words of copy without
   one of them wrapping to two lines, so they move under it and split the
   width evenly — which also keeps them equally weighted at the size where
   a mis-tap is most likely. */
@media (max-width: 620px) {
  .pf-consent { left: 10px; right: 10px; bottom: 10px; }
  .pf-consent-inner { flex-direction: column; align-items: stretch; gap: 14px; padding: 16px; }
  .pf-consent-actions .btn { flex: 1; justify-content: center; }
}

/* The workspace's bottom tab bar owns the bottom of the screen on mobile;
   without this the banner sits on top of it and covers the navigation. */
@media (max-width: 900px) {
  .shell ~ .pf-consent, body:has(.shell) .pf-consent { bottom: calc(10px + 64px); }
}

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