/* Lynx Cortex — portal stylesheet.
   Themes (dark/light) are declared via CSS custom properties on :root in
   base.html. This file is layout + components only.
   Mobile-first; all layout collapses gracefully on narrow viewports. */

:root {
  --radius: 8px;
  --radius-lg: 14px;
  --radius-pill: 999px;
  --space-xs: 4px;
  --space-sm: 8px;
  --space: 14px;
  --space-md: 20px;
  --space-lg: 28px;
  --space-xl: 44px;
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.18);
  --shadow-md: 0 4px 14px rgba(0, 0, 0, 0.22), 0 1px 2px rgba(0, 0, 0, 0.18);
  --shadow-lg: 0 14px 36px rgba(0, 0, 0, 0.28), 0 2px 4px rgba(0, 0, 0, 0.22);
  --ring: 0 0 0 3px color-mix(in srgb, var(--accent) 30%, transparent);
  --font-body: "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI",
    Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-display: "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI",
    sans-serif;
  --font-mono: ui-monospace, "JetBrains Mono", SFMono-Regular, Menlo,
    Consolas, monospace;
  --transition: 160ms cubic-bezier(0.2, 0.8, 0.2, 1);
  /* Height of a ONE-ROW sticky top nav. Kept for reference/anchoring offsets;
     note the desktop nav is now a fixed TWO rows (brandline + menu row), so
     nothing may assume this is the nav's real rendered height (the old sticky
     table headers did, and slid under the nav — they are static now). */
  --nav-h: 49px;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  min-height: 100%;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-body);
  font-size: 15.5px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

body {
  background:
    radial-gradient(1100px 600px at 12% -10%,
      color-mix(in srgb, var(--accent) 14%, transparent), transparent 60%),
    radial-gradient(900px 500px at 100% 0%,
      color-mix(in srgb, var(--accent-strong) 10%, transparent), transparent 55%),
    var(--bg);
  background-attachment: fixed;
}

code, pre, kbd, samp { font-family: var(--font-mono); }
pre {
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: var(--space);
  overflow-x: auto;
  font-size: 0.9em;
}
code:not(pre code) {
  background: color-mix(in srgb, var(--bg-elev) 80%, transparent);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 1px 6px;
  font-size: 0.88em;
}
/* Invite / set-password links: long signed tokens must wrap cleanly inside
   their box and never overflow, clip, or push past the card. A full-width
   block that breaks the unbroken token anywhere reads as an intentional frame. */
code.invite-link {
  display: block;
  max-width: 100%;
  margin: 4px 0;
  padding: 10px 12px;
  line-height: 1.6;
  white-space: normal;
  overflow-wrap: anywhere;
  word-break: break-all;
}
a[data-invite-url] {
  display: block;
  max-width: 100%;
  text-decoration: none;
}

h1, h2, h3, h4 {
  font-family: var(--font-display);
  line-height: 1.25;
  letter-spacing: -0.01em;
  margin: 0 0 var(--space-sm);
}
h1 { font-size: 1.85rem; font-weight: 700; }
h2 { font-size: 1.35rem; font-weight: 650; }
h3 { font-size: 1.1rem;  font-weight: 600; }

.container {
  max-width: 1080px;
  margin: 0 auto;
  padding: 0 var(--space);
}

main.container {
  padding-top: var(--space-lg);
  padding-bottom: var(--space-xl);
}

footer.container {
  border-top: 1px solid var(--border);
  margin-top: var(--space-xl);
  padding-top: var(--space-md);
  padding-bottom: var(--space-md);
  color: var(--muted);
  font-size: 0.85em;
}

a {
  color: var(--accent);
  text-decoration: none;
  transition: color var(--transition);
}
a:hover { color: var(--accent-strong); text-decoration: underline; }
a:focus-visible { outline: none; box-shadow: var(--ring); border-radius: 3px; }

.muted { color: var(--muted); }
.small { font-size: 0.85em; }
.danger { color: var(--danger); }
.ok { color: var(--ok); }
.mono { font-family: var(--font-mono); }

/* ── Top nav ────────────────────────────────────────────────────────── */

.topnav {
  position: sticky;
  top: 0;
  z-index: 50;
  background: color-mix(in srgb, var(--bg-elev) 88%, transparent);
  backdrop-filter: saturate(140%) blur(10px);
  -webkit-backdrop-filter: saturate(140%) blur(10px);
  border-bottom: 1px solid var(--border);
}
/* The header gets a wider canvas than page prose: with the menu sharing the
   brand row (centered) the full admin link set needs the real viewport width
   to sit on ONE line (the content container stays 1080px). */
.topnav .container { max-width: 1600px; }

/* ONE header row, three zones on a single flex line:
   [ brand · natural width ] [ menu · flex:1, centered ] [ controls · natural ].
   Wraps only as a last-resort safety valve on very narrow screens (the menu
   is display:none on mobile, so the row is just brand + controls there). */
.topnav-brandline {
  display: flex;
  align-items: center;
  gap: var(--space);
  padding: 7px 0;
  flex-wrap: wrap;
}
.topnav .brand { flex: none; }
.topnav .nav-controls { flex: none; }

/* Center zone — the menu. flex:1 + justify-content:center keeps the links
   optically centered between brand and controls; min-width:0 lets the zone
   shrink (rather than wrap the row) so brand/controls always hold their line;
   the .nav-primary inside pans within THIS zone when the link set is wider
   than the space (the page body never h-scrolls). */
.nav-links {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-sm);
}
.nav-primary,
.nav-controls {
  display: flex;
  align-items: center;
  gap: 2px;
}
/* Single-row guarantee for the admin link set: never wrap. If a viewport is
   narrower than the full set (1024–1150px, before the hamburger takes over),
   the bar pans INSIDE itself — the page never scrolls horizontally and no
   link ever drops to an orphan second line. */
.nav-primary {
  flex-wrap: nowrap;
  max-width: 100%;
  overflow-x: auto;
  scrollbar-width: none;
}
.nav-primary::-webkit-scrollbar { display: none; }

/* Nav dropdown groups (Study/Programs/Community/Account/Admin ▾): the flat
   link list collapses into a few role-aware dropdowns so the top-level row
   stays short — nothing ever scrolls out of the overflow zone. The admin
   elements carry both the shared .nav-dd* classes and their legacy
   .nav-admin-* names; the shared classes style them all. */
.nav-dd {
  position: relative;
  display: inline-flex;
  align-items: center;
  flex: none;
}
.nav-dd-toggle {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  cursor: pointer;
  border: none;
  background: none;
  font: inherit;
}
.nav-caret {
  transition: transform var(--transition);
  opacity: 0.8;
}
.nav-dd.open .nav-caret { transform: rotate(180deg); }
/* The menu: an absolutely-positioned card that opens under the toggle. Hidden
   until .open (toggled by portal.js); native fallback re-shows it on mobile. */
.nav-dd-menu {
  display: none;
  /* fixed (not absolute) so it escapes the .nav-primary overflow-x clip;
     portal.js positions it under the toggle on open. */
  position: fixed;
  top: 0;
  right: 0;
  min-width: 200px;
  flex-direction: column;
  gap: 1px;
  padding: 6px;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 12px 32px -8px rgba(0, 0, 0, 0.45);
  z-index: 60;
}
.nav-dd.open .nav-dd-menu { display: flex; }
.nav-dd-menu a {
  display: block;
  width: 100%;
  padding: 8px 10px;
  font-size: 0.86em;
}
.nav-dd-menu a::after { display: none; }
.nav-controls { gap: var(--space-sm); }

/* "Not applicable" card for non-student staff surfaces (marks/progress/etc.). */
.na-card { text-align: center; }
.na-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  margin: 0 auto var(--space-sm);
  border-radius: 50%;
  border: 2px solid var(--border);
  color: var(--muted);
  font-size: 1.6rem;
  line-height: 1;
}

/* Profile: contact fieldset, verified badges, programs list. */
.profile-contact {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: var(--space);
  margin: var(--space-sm) 0;
}
.profile-contact legend {
  padding: 0 6px;
  font-weight: 600;
  color: var(--muted);
}
.verify-badge {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 8px;
  border-radius: 20px;
  font-size: 0.72em;
  font-weight: 600;
  vertical-align: middle;
}
.verify-badge.is-verified {
  color: var(--ok);
  background: color-mix(in srgb, var(--ok) 15%, transparent);
}
.verify-badge.is-unverified {
  color: var(--danger);
  background: color-mix(in srgb, var(--danger) 14%, transparent);
}
.verify-link { margin-left: 6px; font-size: 0.78em; }
.program-list { list-style: none; padding: 0; margin: 0; }
.program-list li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm);
  padding: 8px 0;
  border-bottom: 1px solid var(--border);
}
.program-list li:last-child { border-bottom: none; }
.program-badge {
  padding: 2px 10px;
  border-radius: 20px;
  font-size: 0.74em;
  font-weight: 600;
  white-space: nowrap;
}
.program-badge.is-enrolled {
  color: var(--ok);
  background: color-mix(in srgb, var(--ok) 15%, transparent);
}
.program-badge.is-pending {
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 15%, transparent);
}

/* Professor console roster — a clean, well-aligned learner table (item C). */
.prof-roster {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9rem;
}
.prof-roster th,
.prof-roster td {
  padding: 0.6rem 0.75rem;
  border-bottom: 1px solid var(--border);
  text-align: left;
  vertical-align: middle;
}
.prof-roster thead th {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
  border-bottom: 2px solid var(--border);
  white-space: nowrap;
}
.prof-roster tbody tr:hover { background: color-mix(in srgb, var(--fg) 4%, transparent); }
.prof-roster .col-num { text-align: right; white-space: nowrap; }
.prof-roster .col-actions { text-align: right; white-space: nowrap; }
.prof-roster-name { font-weight: 600; }
.prof-roster tbody tr:last-child td { border-bottom: none; }

/* Owner & Admins account table — roomier columns + clean alignment (item E). */
.accounts-table { width: 100%; border-collapse: collapse; }
.accounts-table th,
.accounts-table td {
  padding: 0.6rem 1.1rem;
  border-bottom: 1px solid var(--border);
  text-align: left;
  vertical-align: middle;
}
.accounts-table thead th {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
  border-bottom: 2px solid var(--border);
  white-space: nowrap;
}
.accounts-table tbody tr:hover { background: color-mix(in srgb, var(--fg) 4%, transparent); }
.accounts-table .inline-form { display: inline-block; margin-left: 0.4rem; }
.admin-subhead { margin-top: var(--space); }

.topnav .brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: var(--fg);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.05rem;
  letter-spacing: -0.01em;
}
.topnav .brand:hover { text-decoration: none; color: var(--fg); }
.brand-mark {
  width: 22px;
  height: 22px;
  color: var(--accent);
  filter: drop-shadow(0 0 6px color-mix(in srgb, var(--accent) 45%, transparent));
}
.brand-text-accent {
  color: var(--accent);
  margin-left: 2px;
}

/* Heraldic brand crest (nav only — the 24-grid marks elsewhere keep the base
   .brand-mark sizing): navy shield, gold-metal "L" + rim, gold glow. The
   sheen rect sweeps across the shield every few seconds — a slow, quiet
   shimmer, not a spin; the reduced-motion media rule below renders it static. */
.brand-crest {
  width: 27px;
  height: 27px;
  filter: drop-shadow(0 0 6px color-mix(in srgb, #d8b24a 50%, transparent));
}
.brand-crest .bm-sheen {
  opacity: 0;
  transform: translateX(0) skewX(-18deg);
  animation: brand-sheen 7s cubic-bezier(0.4, 0, 0.2, 1) 2s infinite;
}
@keyframes brand-sheen {
  0%   { transform: translateX(0) skewX(-18deg); opacity: 0; }
  6%   { opacity: 0.35; }
  16%  { transform: translateX(158px) skewX(-18deg); opacity: 0; }
  100% { transform: translateX(158px) skewX(-18deg); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  /* Belt-and-braces on top of the global animation kill: the sheen must stay
     invisible (opacity 0 base state) so the crest reads as a static mark. */
  .brand-crest .bm-sheen { animation: none; opacity: 0; }
}

/* Primary destination links: quiet by default, with an animated underline that
   grows on hover and locks in on the active section. Compact metrics so the
   FULL admin set (18 links) holds one row at common desktop widths. */
.nav-link {
  position: relative;
  color: var(--muted);
  padding: 6px 8px;
  border-radius: var(--radius);
  font-size: 0.8em;
  font-weight: 500;
  white-space: nowrap;
  flex: none;
  transition: color var(--transition), background var(--transition);
}
.nav-link::after {
  content: "";
  position: absolute;
  left: 8px;
  right: 8px;
  bottom: 3px;
  height: 2px;
  border-radius: 2px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: center;
  opacity: 0;
  transition: transform var(--transition), opacity var(--transition);
}
.nav-link:hover {
  color: var(--fg);
  background: color-mix(in srgb, var(--fg) 6%, transparent);
  text-decoration: none;
}
.nav-link:hover::after { transform: scaleX(0.65); opacity: 0.5; }
.nav-link.is-active { color: var(--fg); }
.nav-link.is-active::after { transform: scaleX(1); opacity: 1; }

/* Identity chip — reads as a label, not a link. */
.nav-identity {
  color: var(--muted);
  font-size: 0.86em;
  padding: 4px 10px;
  border-radius: var(--radius-pill);
  background: color-mix(in srgb, var(--fg) 5%, transparent);
  max-width: 14ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Theme button + locale link share one compact control pill. */
.nav-control {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: transparent;
  border: 1px solid var(--border);
  color: var(--muted);
  padding: 5px 10px;
  border-radius: var(--radius-pill);
  cursor: pointer;
  font-family: var(--font-mono);
  font-size: 0.76em;
  letter-spacing: 0.03em;
  line-height: 1;
  transition: color var(--transition), border-color var(--transition),
    background var(--transition);
}
.nav-control:hover {
  color: var(--fg);
  border-color: color-mix(in srgb, var(--fg) 30%, var(--border));
  background: color-mix(in srgb, var(--fg) 6%, transparent);
  text-decoration: none;
}
.nav-control-icon { flex: none; }
a.nav-control { color: var(--muted); }
a.nav-control:hover { color: var(--fg); }

/* Notification bell: a compact icon link with an unread count badge. */
.nav-bell {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: var(--radius-pill);
  color: var(--muted);
  transition: color var(--transition), background var(--transition);
}
.nav-bell:hover,
.nav-bell.is-active { color: var(--fg); background: color-mix(in srgb, var(--fg) 6%, transparent); text-decoration: none; }
.nav-bell-icon { flex: none; }
.notif-badge {
  position: absolute;
  top: -2px;
  right: -2px;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: 8px;
  background: var(--danger);
  color: #fff;
  font-family: var(--font-mono);
  font-size: 0.62rem;
  line-height: 16px;
  text-align: center;
  font-weight: 600;
}

/* Accessible-only text (visually hidden, read by assistive tech). */
.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;
}

/* Notification feed (/me/notifications). */
.notif-feed { display: flex; flex-direction: column; gap: 10px; margin-top: 8px; }
.notif-item {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-elev);
}
.notif-item.is-unread { border-color: color-mix(in srgb, var(--accent) 45%, var(--border)); }
.notif-item.is-unread::before {
  content: "";
  flex: none;
  width: 8px;
  height: 8px;
  margin-top: 6px;
  border-radius: 50%;
  background: var(--accent);
}
.notif-item.is-read::before {
  content: "";
  flex: none;
  width: 8px;
  height: 8px;
  margin-top: 6px;
  border-radius: 50%;
  background: transparent;
}
.notif-body { flex: 1 1 auto; min-width: 0; }
.notif-title { margin: 0; font-size: 0.95rem; font-weight: 600; }
.notif-text { margin: 2px 0 0; color: var(--muted); font-size: 0.85rem; }
.notif-type {
  display: inline-block;
  margin-top: 4px;
  padding: 1px 8px;
  border-radius: var(--radius-pill);
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  color: var(--accent);
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.03em;
}
.notif-item form { flex: none; }

/* Logout lives inside a POST form so the request is CSRF-protected; style
   the form as a layout no-op and the button to read like the other nav
   links rather than a hard-bordered button. */
.nav-logout {
  display: inline-flex;
  margin: 0;
  padding: 0;
}
.nav-logout button.link {
  background: transparent;
  border: 0;
  color: var(--muted);
  padding: 6px 10px;
  font: inherit;
  font-size: 0.93em;
  cursor: pointer;
  border-radius: var(--radius);
}
.nav-logout button.link:hover {
  color: var(--fg);
  background: color-mix(in srgb, var(--fg) 6%, transparent);
}

/* ── Cards ──────────────────────────────────────────────────────────── */

.card {
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--space-lg);
  margin-bottom: var(--space-md);
  box-shadow: var(--shadow-sm);
}
.card.narrow {
  max-width: 440px;
  margin-left: auto;
  margin-right: auto;
}
.card.elevated { box-shadow: var(--shadow-md); }
.card h1 { margin-top: 0; }
.card h1 + p.muted { margin-top: -4px; margin-bottom: var(--space); }

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: var(--space);
}

/* ── Login hero ─────────────────────────────────────────────────────── */

.hero {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-md);
  padding: var(--space-xl) var(--space) var(--space-md);
}
.hero .brand-mark {
  width: 52px;
  height: 52px;
  filter: drop-shadow(0 0 18px color-mix(in srgb, var(--accent) 55%, transparent));
}
.hero h1 {
  font-size: 2.2rem;
  margin: 0;
  text-align: center;
  background: linear-gradient(135deg, var(--fg), color-mix(in srgb, var(--accent) 80%, var(--fg)));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.hero .tagline {
  color: var(--muted);
  margin: 0;
  font-size: 1rem;
  text-align: center;
  max-width: 36ch;
}

/* ── Forms ──────────────────────────────────────────────────────────── */

.stack {
  display: flex;
  flex-direction: column;
  gap: var(--space);
}
.row {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: var(--space);
  flex-wrap: wrap;
}

label > span {
  display: block;
  color: var(--muted);
  font-size: 0.82em;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin-bottom: 6px;
}

input[type="text"],
input[type="password"],
input[type="email"],
input[type="number"],
input[type="date"],
input[type="month"],
input[type="time"],
input[type="url"],
input[type="search"],
select,
textarea {
  width: 100%;
  background: var(--bg);
  border: 1px solid var(--border);
  color: var(--fg);
  border-radius: var(--radius);
  padding: 10px 12px;
  font: inherit;
  transition: border-color var(--transition), box-shadow var(--transition),
    background var(--transition);
}
input:hover, select:hover, textarea:hover {
  border-color: color-mix(in srgb, var(--fg) 25%, var(--border));
}
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: var(--ring);
}
textarea { font-family: var(--font-mono); min-height: 5em; resize: vertical; }

/* Native file pickers: theme the field + its "Browse" chip (the raw control
   rendered as a white UA widget inside dark cards). color-scheme in base.html
   keeps the OS dialog on-theme; this styles the in-page part. */
input[type="file"] {
  width: 100%;
  background: var(--bg);
  border: 1px solid var(--border);
  color: var(--muted);
  border-radius: var(--radius);
  padding: 7px 12px;
  font: inherit;
  cursor: pointer;
}
input[type="file"]::file-selector-button {
  background: color-mix(in srgb, var(--fg) 6%, transparent);
  border: 1px solid var(--border);
  color: var(--fg);
  border-radius: var(--radius);
  padding: 4px 12px;
  margin-right: 10px;
  font: inherit;
  font-size: 0.9em;
  cursor: pointer;
}

button {
  background: var(--bg);
  border: 1px solid var(--border);
  color: var(--fg);
  border-radius: var(--radius);
  padding: 9px 16px;
  cursor: pointer;
  font: inherit;
  font-weight: 500;
  transition: background var(--transition), border-color var(--transition),
    transform var(--transition), box-shadow var(--transition);
}
button:hover {
  background: color-mix(in srgb, var(--fg) 6%, transparent);
  border-color: color-mix(in srgb, var(--fg) 30%, var(--border));
}
button:active { transform: translateY(1px); }
button:focus-visible { outline: none; box-shadow: var(--ring); }

button.primary {
  background: linear-gradient(135deg, var(--accent), var(--accent-strong));
  border-color: var(--accent-strong);
  color: #fff;
  font-weight: 600;
  box-shadow: 0 2px 8px color-mix(in srgb, var(--accent) 30%, transparent);
}
button.primary:hover {
  filter: brightness(1.08);
  box-shadow: 0 4px 14px color-mix(in srgb, var(--accent) 45%, transparent);
}

button.danger {
  border-color: var(--danger);
  color: var(--danger);
}
button.danger:hover {
  background: color-mix(in srgb, var(--danger) 12%, transparent);
}

/* Quiet inline action: a submit button that reads as a link, not a chunky
   button (e.g. partner "Set tier" / "Record"). The bordered nav-logout variant
   keeps its own muted styling via the more-specific `.nav-logout button.link`. */
button.link {
  background: transparent;
  border: 0;
  color: var(--accent);
  padding: 6px 8px;
  font-weight: 500;
  box-shadow: none;
}
button.link:hover {
  background: transparent;
  border: 0;
  color: var(--accent-strong);
  text-decoration: underline;
}

/* Inline tier/outcome selects sit beside their submit button in a single-line
   form row; keep them content-width so the button never wraps to a new line
   (overrides the global full-width select rule). */
.tier-select,
.outcome-select {
  width: auto;
  min-width: 7rem;
}

/* ── Flash ──────────────────────────────────────────────────────────── */

.flash {
  border: 1px solid var(--border);
  border-left-width: 3px;
  border-radius: var(--radius);
  padding: 10px 14px;
  margin-bottom: var(--space);
  background: var(--bg-elev);
  font-size: 0.95em;
}
.flash-info    { border-left-color: var(--accent); }
.flash-success { border-left-color: var(--ok);     color: var(--ok); }
.flash-error   { border-left-color: var(--danger); color: var(--danger); }

/* ── Tables ─────────────────────────────────────────────────────────── */

/* Wide data tables are wrapped in `.table-scroll` so they scroll horizontally
   inside their card on narrow viewports instead of overflowing the page. */
.table-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.phase-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
}
.phase-table th,
.phase-table td {
  border-bottom: 1px solid var(--border);
  padding: 12px 8px;
  text-align: left;
  vertical-align: top;
}
.phase-table th {
  color: var(--muted);
  font-weight: 600;
  font-size: 0.78em;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  border-bottom-width: 1px;
  background: transparent;
  /* NOT sticky. Two independent failure modes killed stickiness here:
     1. inside a `.table-scroll` wrapper (every wide table) the wrapper is
        itself a scroll container, so `position: sticky; top: var(--nav-h)`
        pinned the header against the WRAPPER's scrollport — displaced
        --nav-h px down at rest, printing over the first data row;
     2. outside a wrapper, `top: var(--nav-h)` assumed a one-row (49px) nav,
        but the logged-in nav wraps to 2–3 rows on most desktop widths, so a
        scrolled header slid UNDER the translucent nav and ghosted through
        its blur. Static headers are correct in both cases. */
  position: static;
}
/* Belt-and-braces: inside a `.table-scroll` wrapper the header must never be
   sticky (see failure mode 1 above). Kept as an explicit override so a future
   re-introduction of sticky headers cannot regress the wrapped tables. */
.table-scroll .phase-table th {
  position: static;
}
.phase-table tbody tr {
  transition: background var(--transition);
}
.phase-table tbody tr:hover {
  background: color-mix(in srgb, var(--fg) 4%, transparent);
}
.phase-table tbody tr:hover a { color: var(--accent-strong); }
.phase-table td:first-child {
  font-family: var(--font-mono);
  font-size: 0.85em;
  width: 3em;
}

/* ── Badges ─────────────────────────────────────────────────────────── */

.badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 10px;
  border-radius: var(--radius-pill);
  font-size: 0.75em;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  border: 1px solid var(--border);
  color: var(--muted);
  background: color-mix(in srgb, var(--bg) 60%, transparent);
}
.badge-in_progress {
  color: var(--accent);
  border-color: color-mix(in srgb, var(--accent) 55%, var(--border));
  background: color-mix(in srgb, var(--accent) 12%, transparent);
}
.badge-done,
.badge-active,
.badge-live {
  color: var(--ok);
  border-color: color-mix(in srgb, var(--ok) 55%, var(--border));
  background: color-mix(in srgb, var(--ok) 12%, transparent);
}
.badge-pending {
  color: var(--accent);
  border-color: color-mix(in srgb, var(--accent) 55%, var(--border));
  background: color-mix(in srgb, var(--accent) 12%, transparent);
}
.badge-archived {
  color: var(--muted);
  border-color: var(--border);
  background: color-mix(in srgb, var(--muted) 10%, transparent);
}

/* Partner tier hierarchy: gold / silver / bronze. Used by the leaderboard and
   newsletter to rank companies at a glance. */
.badge-t1 {
  color: #5a4708;
  border-color: color-mix(in srgb, #d8b24a 60%, var(--border));
  background: color-mix(in srgb, #d8b24a 26%, transparent);
}
.badge-t2 {
  color: var(--fg);
  border-color: color-mix(in srgb, #b8bcc4 55%, var(--border));
  background: color-mix(in srgb, #b8bcc4 22%, transparent);
}
.badge-t3 {
  color: #6e4a23;
  border-color: color-mix(in srgb, #c08a4a 55%, var(--border));
  background: color-mix(in srgb, #c08a4a 20%, transparent);
}
:root[data-theme="dark"] .badge-t1 { color: #f0d68a; }
:root[data-theme="dark"] .badge-t3 { color: #e0b07a; }

/* ── Notes (review) ─────────────────────────────────────────────────── */

.note-list { list-style: none; padding: 0; }
.note {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: var(--space);
  margin-bottom: var(--space);
  background: var(--bg);
  transition: border-color var(--transition);
}
.note:hover { border-color: color-mix(in srgb, var(--fg) 25%, var(--border)); }
.note-body code, .note-body pre {
  background: var(--bg-elev);
  padding: 2px 6px;
  border-radius: 4px;
}

/* ── Quiz / review ──────────────────────────────────────────────────── */

.quiz-item, .review-card {
  border-top: 1px solid var(--border);
  padding: var(--space) 0;
}
.quiz-item:first-child, .review-card:first-child { border-top: 0; padding-top: 0; }

/* ── Utilities ──────────────────────────────────────────────────────── */

.text-center { text-align: center; }
.divider {
  height: 1px;
  background: var(--border);
  margin: var(--space) 0;
}
.kbd-hint {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 0.75em;
  padding: 1px 5px;
  border: 1px solid var(--border);
  border-bottom-width: 2px;
  border-radius: 4px;
  color: var(--muted);
}

/* ── Page header ────────────────────────────────────────────────────── */

.page-header {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space);
  flex-wrap: wrap;
  margin: var(--space-sm) 0 var(--space-md);
}
.page-header h1 { margin: 0 0 4px; }
.page-header p { margin: 0; }
/* Course-dashboard title herald: ONE small institutional mark on a serious
   surface (catalogue register) — full-size heraldry lives on profile pages. */
.dash-title-herald { display: block; align-self: center; }
.page-header-actions {
  display: flex;
  gap: var(--space-sm);
  flex-wrap: wrap;
}
.btn-link {
  display: inline-block;
  padding: 6px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--fg);
  font-size: 0.9em;
  transition: background var(--transition), border-color var(--transition);
}
.btn-link:hover {
  background: color-mix(in srgb, var(--fg) 6%, transparent);
  border-color: color-mix(in srgb, var(--fg) 30%, var(--border));
  text-decoration: none;
}
.btn-link.muted { color: var(--muted); }

.phase-link {
  font-weight: 600;
  color: var(--fg);
}
.phase-link:hover { color: var(--accent); text-decoration: none; }

.bare-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.bare-list li {
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--bg) 70%, transparent);
}

/* ── Toasts ─────────────────────────────────────────────────────────── */

.toasts {
  position: fixed;
  top: 70px;
  right: 18px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  z-index: 200;
  pointer-events: none;
  max-width: min(360px, calc(100vw - 36px));
}
.toast {
  pointer-events: auto;
  padding: 12px 16px;
  border: 1px solid var(--border);
  border-left-width: 3px;
  border-radius: var(--radius);
  background: var(--bg-elev);
  color: var(--fg);
  font-size: 0.92em;
  box-shadow: var(--shadow-md);
  opacity: 0;
  transform: translateX(20px);
  transition: opacity var(--transition), transform var(--transition);
  cursor: pointer;
}
.toast-in  { opacity: 1; transform: translateX(0); }
.toast-out { opacity: 0; transform: translateX(20px); }
.toast-info    { border-left-color: var(--accent); }
.toast-success { border-left-color: var(--ok);     color: var(--ok); }
.toast-error   { border-left-color: var(--danger); color: var(--danger); }

/* ── Empty state ────────────────────────────────────────────────────── */

.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: var(--space-xl) var(--space);
  gap: var(--space-sm);
}
.empty-state .brand-mark {
  width: 44px;
  height: 44px;
  opacity: 0.55;
}
.empty-state h2 { margin: 0; }
.empty-state p  { margin: 0; max-width: 40ch; }

/* ── Skeleton (htmx loading) ────────────────────────────────────────── */

.skeleton {
  display: block;
  height: 14px;
  border-radius: 4px;
  background: linear-gradient(90deg,
    color-mix(in srgb, var(--bg-elev) 60%, transparent) 0%,
    color-mix(in srgb, var(--fg)       10%, var(--bg-elev)) 50%,
    color-mix(in srgb, var(--bg-elev) 60%, transparent) 100%);
  background-size: 200% 100%;
  animation: skel-pulse 1.4s ease-in-out infinite;
  margin-bottom: 8px;
}
.skeleton.skeleton-lg { height: 28px; }
.skeleton.skeleton-sm { height: 10px; width: 60%; }
@keyframes skel-pulse {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}
.htmx-indicator { display: none; }
.htmx-request .htmx-indicator { display: block; }

/* ── Mobile nav ─────────────────────────────────────────────────────── */

.nav-toggle {
  display: none;
  background: transparent !important;
  border: 1px solid var(--border) !important;
  border-radius: var(--radius);
  padding: 6px !important;
  color: var(--fg) !important;
  cursor: pointer;
}
/* Collapse the MENU row into the hamburger below 1024px. The brandline stays
   put (brand left, session cluster right, then the burger); the links live in
   a stacked dropdown anchored under the brandline. The session cluster is NOT
   inside the dropdown — theme/locale/logout remain one tap away. */
@media (max-width: 1024px) {
  .nav-toggle { display: inline-flex; align-items: center; }
  .topnav .container { position: relative; }
  /* The centered menu leaves the flow; brand stays left, so push the session
     cluster (and the burger after it) to the right edge — the flex:1 menu that
     did this on desktop is now display:none. */
  .topnav .nav-controls { margin-left: auto; }
  .nav-links {
    display: none;
    flex: none;
    flex-direction: column;
    align-items: stretch;
    gap: var(--space-sm);
    position: absolute;
    top: calc(100% + 4px);
    right: var(--space);
    left: var(--space);
    background: var(--bg-elev);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    padding: var(--space);
    box-shadow: var(--shadow-lg);
  }
  .nav-links.open { display: flex; }
  .nav-primary {
    flex-direction: column;
    align-items: stretch;
    gap: 2px;
    flex-wrap: nowrap;
    overflow: visible;
  }
  /* Every nav dropdown group restacks as a full-width section set off by a
     top hairline — the toggle is hidden and every grouped link shows inline
     (native fallback, no JS needed to reveal them in the hamburger). */
  .nav-dd {
    flex-direction: column;
    align-items: stretch;
    width: 100%;
    padding-top: var(--space-sm);
    border-top: 1px solid var(--border);
  }
  /* The first group needs no separator above it. */
  .nav-primary > .nav-dd:first-child {
    padding-top: 0;
    border-top: none;
  }
  .nav-dd-toggle { display: none; }
  .nav-dd-menu {
    display: flex;
    position: static;
    min-width: 0;
    padding: 0;
    gap: 2px;
    background: none;
    border: none;
    border-radius: 0;
    box-shadow: none;
  }
  .nav-dd-menu a { font-size: 0.92em; padding: 9px 11px; }
  .nav-link { padding: 9px 11px; font-size: 0.92em; }
  .nav-link::after { display: none; }
  .nav-link.is-active {
    background: color-mix(in srgb, var(--accent) 12%, transparent);
  }
}

@media (max-width: 640px) {
  .hero h1 { font-size: 1.7rem; }
  .page-header { flex-direction: column; align-items: flex-start; }
  .phase-table th, .phase-table td { padding: 10px 6px; font-size: 0.92em; }
  /* Brandline stays one line as long as possible: drop the theme word and
     tighten the identity chip; below that the cluster wraps gracefully. */
  .nav-control-text { display: none; }
  .nav-identity { max-width: 9ch; }
}

/* ── Reduce-motion ──────────────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    transition: none !important;
    animation: none !important;
  }
}

/* ── Reference mode (prereq badges, teaches tags, mode toggle) ──────── */

.meta-strip { padding: 12px 16px; }
.meta-strip p { margin: 4px 0; }

.prereq-badge {
  text-decoration: none;
  text-transform: none;
  cursor: pointer;
}
.prereq-badge:hover {
  border-color: var(--accent);
  color: var(--accent);
}

.teaches-tag {
  font-size: 0.78em;
  padding: 1px 6px;
  border-radius: 4px;
  border: 1px solid var(--border);
  background: color-mix(in srgb, var(--bg) 60%, transparent);
}

.mode-toggle .mode-active {
  color: var(--accent);
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 4px;
}

.next-up { border-left: 3px solid var(--accent); }

/* ── Academic: marks, bands, profile (Cortex University) ──────────────── */

.row.gap { display: flex; gap: 0.6rem; align-items: flex-end; }
.row.gap.wrap { flex-wrap: wrap; }
.grow { flex: 1 1 auto; }

/* Profile form fields (country · enrollment year · date of birth). The generic
   `.row.gap` bottom-aligns items so a [label][input] pair lines its input up
   with its neighbours — but the enrollment-year field carries an extra help
   line under its input, which shoved that field up and left the three inputs
   at three different heights (reading as an overlap/misalignment). Top-align
   here and give each field an equal, shrinkable column so labels + inputs line
   up cleanly and wrap to full width on narrow screens. */
.row.gap.profile-fields { flex-wrap: wrap; align-items: flex-start; }
.row.gap.profile-fields > label { flex: 1 1 9rem; min-width: 0; margin: 0; }
.primary-link { font-weight: 700; }

/* Classification band palette (fail→excellence). */
.band-fail { --band: #c0392b; }
.band-pass { --band: #b8860b; }
.band-merit { --band: #2e86c1; }
.band-distinction { --band: #6c5ce7; }
.band-excellence { --band: #1e8e5a; }
.band-none { --band: var(--muted, #888); }

.band-pill {
  display: inline-block; padding: 0.1rem 0.55rem; border-radius: 0.7rem;
  font-size: 0.72rem; font-weight: 700; color: #fff; background: var(--band);
}
.band-text-fail { color: #c0392b; }
.band-text-pass { color: #b8860b; }
.band-text-merit { color: #2e86c1; }
.band-text-distinction { color: #6c5ce7; }
.band-text-excellence { color: #1e8e5a; }
.band-warn { color: #b8860b; }

.marks-overview { display: flex; align-items: center; gap: 1.2rem; flex-wrap: wrap; }
.marks-score { display: flex; align-items: baseline; gap: 0.2rem;
  padding: 0.4rem 1rem; border-radius: 0.6rem; border-left: 4px solid var(--band); }
.marks-score-num { font-size: 2.6rem; font-weight: 800; line-height: 1; color: var(--band); }
.marks-score-den { font-size: 1rem; opacity: 0.6; }
.marks-overview-meta { display: flex; flex-direction: column; gap: 0.3rem; }
.marks-strengths { margin: 0.8rem 0; }

.marks-table { width: 100%; border-collapse: collapse; font-size: 0.84rem; }
.marks-table th, .marks-table td { text-align: left; padding: 0.35rem 0.5rem; border-bottom: 1px solid var(--border, rgba(128,128,128,0.2)); }
.marks-table tr.is-unassessed { opacity: 0.55; }
.mono { font-family: var(--mono, monospace); }

.mark-bar-wrap { position: relative; display: inline-flex; align-items: center; gap: 0.4rem;
  width: 7rem; height: 0.95rem; background: rgba(128,128,128,0.18); border-radius: 0.3rem; overflow: hidden; }
.mark-bar-wrap.wide { width: 100%; max-width: 24rem; display: block; margin: 0.3rem 0; }
.mark-bar { position: absolute; left: 0; top: 0; bottom: 0; background: var(--band); border-radius: 0.3rem; }
.mark-bar-num { position: relative; margin-left: auto; padding-right: 0.4rem; font-size: 0.7rem; font-weight: 700; }

.phase-result-row { display: flex; align-items: baseline; gap: 0.5rem; flex-wrap: wrap; }
.phase-result .marks-score-num { font-size: 1.8rem; }

.profile-photo-preview { display: flex; align-items: center; gap: 0.6rem; }
.profile-photo-preview img { width: 84px; height: 84px; object-fit: cover; border-radius: 0.5rem; border: 1px solid var(--border, rgba(128,128,128,0.3)); }

/* ── Terms & code of conduct page ────────────────────────────────────── */
.terms-body { max-height: 30rem; overflow-y: auto; }
.terms-body h1 { font-size: 1.3rem; }
.terms-body h2 { font-size: 1.05rem; margin-top: 1.2rem; }
.accepted-banner { border-left: 3px solid #1e8e5a; color: #1e8e5a; font-weight: 600; }
label.check { display: flex; align-items: flex-start; gap: 0.5rem; font-size: 0.86rem; cursor: pointer; }
label.check input { margin-top: 0.2rem; }

/* ── Credential verification page ────────────────────────────────────── */
.verify-input { font-family: var(--mono, monospace); font-size: 0.8rem; width: 100%; resize: vertical; }
.verify-result { border: 2px solid var(--muted, #888); border-left-width: 5px; }
.verify-result.is-valid { border-color: #1e8e5a; background: rgba(30, 142, 90, 0.07); }
.verify-result.is-invalid { border-color: #c0392b; background: rgba(192, 57, 43, 0.07); }
.verify-result.is-required { border-color: var(--muted, #888); background: rgba(140, 140, 140, 0.06); }
.verify-result.is-valid h2 { color: #1e8e5a; }
.verify-result.is-invalid h2 { color: #c0392b; }
.verify-result.is-required h2 { color: var(--muted, #888); }
.profile-status { border: 2px solid; border-radius: 8px; padding: 10px 14px; margin: 0 0 1.1rem; font-size: 0.92rem; display: flex; align-items: baseline; gap: 0.5rem; flex-wrap: wrap; }
.profile-status .ps-icon { font-weight: 700; }
.profile-status .ps-missing { color: var(--fg); font-weight: 600; }
.profile-status-complete { border-color: #1e8e5a; background: rgba(30, 142, 90, 0.09); color: #1e8e5a; }
.profile-status-partial { border-color: #c89a2b; background: rgba(200, 154, 43, 0.12); color: #a9791a; }
.profile-status-empty { border-color: #c0392b; background: rgba(192, 57, 43, 0.09); color: #c0392b; }

/* Dark-theme contrast lift: the amber/gold status + warn text (#a9791a / #b8860b)
   are too dark to read on the dark surface (#161b22). Lighten them to a gold that
   meets contrast, and deepen the valid/invalid verify tints so they stay visible. */
:root[data-theme="dark"] .band-warn,
:root[data-theme="dark"] .profile-status-partial { color: #e0b341; }
:root[data-theme="dark"] .verify-result.is-valid { background: rgba(30, 142, 90, 0.14); }
:root[data-theme="dark"] .verify-result.is-invalid { background: rgba(192, 57, 43, 0.14); }
/* The same lift for the classification-band text colors (Wave-0 audit S3):
   the light-theme band inks are too dark on the dark surface — every band
   gets a lightened dark-theme ink (pass gets the audit-endorsed #e0b341). */
:root[data-theme="dark"] .band-text-pass { color: #e0b341; }
:root[data-theme="dark"] .band-text-fail { color: #f2705f; }
:root[data-theme="dark"] .band-text-merit { color: #58a6ff; }
:root[data-theme="dark"] .band-text-distinction { color: #a99df1; }
:root[data-theme="dark"] .band-text-excellence { color: #34c584; }

/* Shared status-hue palette — single source of truth for the status pills,
   the status-distribution SVG segments (university-status dashboard + admin
   analytics), and the build-control badges. The Wave-0 audit found this
   palette hand-copied in three places; templates now reference these vars. */
:root {
  --status-ok: #1a7f37;
  --status-wip: #bc4c00;
  --status-designed: #8250df;
  --status-info: #0969da;
  --status-gated: #57606a;
  --status-warn: #9a6700;
}
:root[data-theme="dark"] {
  --status-ok: #3fb950;
  --status-wip: #e8905c;
  --status-designed: #bc8cff;
  --status-info: #79b8ff;
  --status-gated: #b1bac4;
  --status-warn: #e3b341;
}

/* Page transition: a smooth, classy fade-rise on each navigation. A whisper of
   blur + scale that settles, rather than a hard slide — reads as a considered
   reveal, not a jump. CSS-only; reduced-motion disables it (global rule). */
@keyframes lynx-page-in {
  0%   { opacity: 0; transform: translateY(10px) scale(0.994); filter: blur(2px); }
  60%  { filter: blur(0); }
  100% { opacity: 1; transform: none; filter: blur(0); }
}
main.container {
  animation: lynx-page-in 360ms cubic-bezier(0.22, 0.61, 0.36, 1) both;
}
@media (prefers-reduced-motion: reduce) {
  main.container { animation: none; }
}

/* Dashboard: phases grouped under area headers (Fundamentals, Systems, …). */
.phase-group-head {
  font-size: 0.74rem;
  text-transform: uppercase;
  letter-spacing: 1.6px;
  color: var(--accent);
  font-weight: 700;
  margin: 0 0 0.7rem;
  padding-bottom: 0.4rem;
  border-bottom: 1px solid var(--border);
}
.verify-fields { display: grid; grid-template-columns: auto 1fr; gap: 0.3rem 1rem; margin: 0.6rem 0 0; font-size: 0.86rem; }
.verify-fields dt { font-weight: 700; opacity: 0.7; }
.verify-fields dd { margin: 0; }

/* ── University logo emblems on portal pages ─────────────────────────── */
.page-header-titled { display: flex; align-items: center; gap: 1rem; }
.cx-page-logo {
  height: 76px; width: auto; border-radius: 0.55rem;
  box-shadow: 0 2px 10px rgba(0,0,0,0.25);
}
@media (max-width: 40rem) { .cx-page-logo { height: 56px; } }

/* ── Grade stars & gems (honor system — static/emblems/grades/, brief B5) ──
   Bronze★=MSc · Silver★=PhD · Gold★=PostDoc · Ruby◆=Special · Diamond◆=Top;
   1/2/3 marks = Merit / Distinction / Highest Distinction. The shapes are
   inlined by grade_gems() (_partials/grade_gems.html) and take their tier
   color from currentColor; both themes tune the inks via the --gem-* vars. */
:root {
  --gem-bronze: #a5642a;
  --gem-silver: #7e8590;
  --gem-gold: #b8860b;
  --gem-ruby: #b3122e;
  --gem-diamond: #6d94b8;
}
:root[data-theme="dark"] {
  --gem-bronze: #d08a4e;
  --gem-silver: #c3cad2;
  --gem-gold: #e0b341;
  --gem-ruby: #ef3a5d;
  --gem-diamond: #b7d9f2;
}
.grade-gems {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 3px;
  vertical-align: middle;
  line-height: 0;
}
.grade-gems svg { width: 14px; height: 14px; display: block; }
.grade-gems.gg-sm svg { width: 11px; height: 11px; }
.grade-gems.gg-lg svg { width: 20px; height: 20px; }
.gg-bronze  { color: var(--gem-bronze); }
.gg-silver  { color: var(--gem-silver); }
.gg-gold    { color: var(--gem-gold); }
.gg-ruby    { color: var(--gem-ruby); }
.gg-diamond { color: var(--gem-diamond); }

/* ── Branded site footer ─────────────────────────────────────────────── */
.site-footer {
  margin-top: 2.5rem;
  border-top: 1px solid var(--border);
  background: var(--bg-elev);
}
.site-footer-inner {
  display: flex; flex-wrap: wrap; gap: 0.6rem 1.5rem;
  align-items: center; justify-content: space-between;
  padding-top: 1rem; padding-bottom: 1rem;
}
.site-footer-brand { font-size: 0.84rem; }
.site-footer-motto {
  display: block; font-size: 0.7rem; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--muted); margin-top: 0.15rem;
}
.site-footer-links { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 1rem; font-size: 0.8rem; }
.site-footer-links a, .site-footer-links span { white-space: nowrap; }
.site-footer-links a { color: var(--muted); text-decoration: none; }
.site-footer-links a:hover { color: var(--accent); }

/* ── Prev/next phase navigation (smooth walk through the curriculum) ──── */
.phase-nav {
  display: grid; grid-template-columns: 1fr 1fr; gap: 0.8rem; margin: 1.4rem 0 0.5rem;
}
.phase-nav-link {
  display: flex; flex-direction: column; gap: 0.2rem;
  padding: 0.7rem 0.9rem; border: 1px solid var(--border); border-radius: 0.6rem;
  background: var(--bg-elev); text-decoration: none; color: inherit;
  transition: transform 120ms ease, border-color 120ms ease;
}
.phase-nav-link:hover { transform: translateY(-2px); border-color: var(--accent); }
.phase-nav-next { text-align: right; align-items: flex-end; }
.phase-nav-dir { font-size: 0.72rem; font-weight: 700; letter-spacing: 0.04em; color: var(--accent); }
.phase-nav-title { font-size: 0.82rem; color: var(--muted); }
@media (max-width: 40rem) { .phase-nav { grid-template-columns: 1fr; } }

/* ── Boot splash ─────────────────────────────────────────────────────────
   An elegant once-per-session reveal: the Cortex crest draws itself in gold
   over a navy gradient, the wordmark + motto rise in, then the whole overlay
   fades to reveal the app. Hidden by default — portal.js opts in on the first
   view only, so it never flashes on navigation and never blocks usability if
   JS is absent. prefers-reduced-motion collapses it to an instant dismiss. */
.boot-splash {
  --boot-navy: #0a0e1a;
  --boot-navy-2: #11182d;
  --boot-gold: #d8b24a;
  --boot-gold-soft: #f0d68a;
  display: none;
  position: fixed;
  inset: 0;
  z-index: 9999;
  place-items: center;
  background:
    radial-gradient(900px 600px at 50% 38%,
      color-mix(in srgb, var(--boot-gold) 16%, transparent), transparent 62%),
    linear-gradient(160deg, var(--boot-navy) 0%, var(--boot-navy-2) 100%);
  color: var(--boot-gold-soft);
  cursor: pointer;
}
.boot-splash.boot-splash-play { display: grid; }
.boot-splash.boot-splash-done {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity 520ms ease, visibility 0s linear 520ms;
}
.boot-splash-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  padding: 24px;
  text-align: center;
}
.boot-crest {
  width: 132px;
  height: 132px;
  filter: drop-shadow(0 0 20px color-mix(in srgb, var(--boot-gold) 45%, transparent));
}
.boot-crest circle,
.boot-crest path {
  fill: none;
  stroke: var(--boot-gold);
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 1;
  stroke-dashoffset: 0;
}
.boot-crest-ring { stroke-width: 1.6; opacity: 0.85; }
.boot-crest-glyph { stroke: var(--boot-gold-soft); }
.boot-splash-play .boot-crest-ring   { animation: boot-draw 900ms ease both; }
.boot-splash-play .boot-crest-shield { animation: boot-draw 1000ms ease 220ms both; }
.boot-splash-play .boot-crest-glyph  { animation: boot-draw 800ms ease 620ms both; }
.boot-wordmark {
  font-family: var(--font-display);
  font-size: 1.7rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: #f6efdc;
}
.boot-wordmark-accent { color: var(--boot-gold); margin-left: 0.4ch; }
.boot-motto {
  font-size: 0.74rem;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--boot-gold-soft) 75%, transparent);
}
.boot-splash-play .boot-wordmark { animation: boot-rise 700ms ease 980ms both; }
.boot-splash-play .boot-motto    { animation: boot-rise 700ms ease 1180ms both; }
/* Ceremonial gold rule between wordmark and motto: draws outward from the
   centre once the crest has finished tracing. */
.boot-rule {
  width: 150px;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--boot-gold), transparent);
}
.boot-splash-play .boot-rule { animation: boot-rule-grow 600ms ease 1080ms both; }

@keyframes boot-draw {
  from { stroke-dashoffset: 1; }
  to   { stroke-dashoffset: 0; }
}
@keyframes boot-rise {
  from { opacity: 0; transform: translateY(10px); letter-spacing: 0.4em; }
  to   { opacity: 1; transform: none; }
}
@keyframes boot-rule-grow {
  from { transform: scaleX(0); opacity: 0; }
  to   { transform: none; opacity: 1; }
}

/* Reduced motion: portal.js never shows the splash at all (instant reveal);
   these rules are belt-and-braces so a stray `-play` class can't animate. */
@media (prefers-reduced-motion: reduce) {
  .boot-splash { display: none !important; }
  .boot-splash-play .boot-crest-ring,
  .boot-splash-play .boot-crest-shield,
  .boot-splash-play .boot-crest-glyph,
  .boot-splash-play .boot-rule,
  .boot-splash-play .boot-wordmark,
  .boot-splash-play .boot-motto { animation: none; }
}

/* ── Inter-menu transition (fast page-enter on top-nav navigation) ────────
   Much shorter than the boot splash: the OLD document fades slightly on a
   nav-link click (html.nav-leave), and the NEW one plays a ~240ms enter —
   <main> rises in and the brand mark gives one subtle gold-tinged pulse.
   portal.js only applies these classes for plain left-clicks on nav links
   and skips them entirely under prefers-reduced-motion. */
html.nav-leave main,
html.nav-leave .site-footer {
  opacity: 0.25;
  transition: opacity 140ms ease;
}
html.nav-enter main { animation: page-enter 240ms cubic-bezier(0.2, 0.7, 0.3, 1) both; }
html.nav-enter .brand-mark { animation: mark-pulse 320ms ease both; }
@keyframes page-enter {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}
@keyframes mark-pulse {
  0%   { transform: none; }
  45%  { transform: scale(1.18); color: #d8b24a; }
  100% { transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  html.nav-leave main,
  html.nav-leave .site-footer { opacity: 1; transition: none; }
  html.nav-enter main,
  html.nav-enter .brand-mark { animation: none; }
}

/* ── About: institutional identity page ──────────────────────────────────
   Centered crest + name + motto + blurb, with gold accents and a staggered
   reveal. The crest draws in on load (reduced-motion shows it instantly). */
.about {
  max-width: 760px;
  margin: 0 auto;
  padding: var(--space-lg) var(--space) var(--space-xl);
  text-align: center;
}
.about-crest-wrap { display: flex; justify-content: center; margin-bottom: var(--space-md); }
.about-crest {
  width: 150px;
  height: 150px;
  filter: drop-shadow(0 0 16px color-mix(in srgb, var(--band-pass, #b8860b) 35%, transparent));
}
.about-crest circle,
.about-crest path {
  fill: none;
  stroke: #c9a23a;
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 1;
  stroke-dashoffset: 0;
}
.about-crest-ring { stroke-width: 1.6; opacity: 0.8; }
.about-crest-glyph { stroke: color-mix(in srgb, #c9a23a 80%, var(--fg)); }
.about-crest-ring   { animation: boot-draw 1000ms ease both; }
.about-crest-shield { animation: boot-draw 1100ms ease 200ms both; }
.about-crest-glyph  { animation: boot-draw 900ms ease 640ms both; }
.about-name {
  font-size: 2.3rem;
  margin: 0 0 0.2rem;
  letter-spacing: -0.01em;
  background: linear-gradient(135deg, var(--fg), #c9a23a);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.about-motto {
  margin: 0 0 var(--space);
  font-size: 0.82rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: #b8860b;
  font-weight: 600;
}
.about-divider {
  width: 64px;
  height: 2px;
  margin: var(--space) auto var(--space-md);
  border-radius: 2px;
  background: linear-gradient(90deg, transparent, #c9a23a, transparent);
}
.about-lede {
  font-size: 1.12rem;
  line-height: 1.6;
  color: var(--fg);
  max-width: 56ch;
  margin: 0 auto var(--space);
}
.about-body {
  color: var(--muted);
  max-width: 60ch;
  margin: 0 auto var(--space-lg);
}
.about-pillars {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: var(--space);
  margin: 0;
  text-align: left;
}
.about-pillar {
  border: 1px solid var(--border);
  border-top: 2px solid #c9a23a;
  border-radius: var(--radius-lg);
  padding: var(--space) var(--space-md);
  background: var(--bg-elev);
  box-shadow: var(--shadow-sm);
}
.about-pillar dt {
  font-family: var(--font-display);
  font-weight: 700;
  color: #c9a23a;
  letter-spacing: 0.02em;
  margin-bottom: 0.3rem;
}
.about-pillar dd { margin: 0; font-size: 0.9rem; color: var(--muted); }

/* Staggered reveal for the textual blocks. Initial hidden state lives only in
   the keyframe's `from` (with fill `both`), so when reduced-motion cancels the
   animation the elements fall back to their fully-visible default. */
.reveal { animation: about-reveal 620ms cubic-bezier(0.22, 0.61, 0.36, 1) both; }
.reveal-1 { animation-delay: 120ms; }
.reveal-2 { animation-delay: 240ms; }
.reveal-3 { animation-delay: 360ms; }
@keyframes about-reveal {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: none; }
}
@media (max-width: 40rem) {
  .about-name { font-size: 1.8rem; }
  .about-lede { font-size: 1rem; }
}
/* Dark-theme lift for the About gold inks (same contrast rule as .band-warn). */
:root[data-theme="dark"] .about-motto,
:root[data-theme="dark"] .about-section-title { color: #e0b341; }

/* About — heraldry, honor marks, and license (Wave 1). New sections keep the
   centered gold-accent language; the crest artwork is photographic-on-dark,
   so it always sits on a fixed dark plate that holds in both themes. */
.about-section { margin-top: var(--space-xl); }
.about-section-title {
  font-size: 0.8rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: #b8860b;
  font-weight: 700;
  margin: 0 0 var(--space-sm);
}
.about-section-lede {
  color: var(--muted);
  font-size: 0.92rem;
  max-width: 60ch;
  margin: 0 auto var(--space-md);
}
.about-mark-card {
  margin: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background:
    radial-gradient(120% 90% at 50% 0%, #1d2027 0%, #101318 70%);
  padding: var(--space-md) var(--space) var(--space);
  box-shadow: var(--shadow-sm);
}
.about-mark-card img {
  display: block;
  margin: 0 auto;
  height: 150px;
  width: auto;
  max-width: 100%;
  object-fit: contain;
}
.about-mark-card figcaption {
  margin-top: 0.7rem;
  font-size: 0.8rem;
  letter-spacing: 0.04em;
  color: #cdd3da; /* fixed ink — the plate is dark in both themes */
}
/* Coat of arms — the single traditional plate, centered (P19 dropped the
   modern digital emblem that used to sit beside it). */
.about-arms {
  display: flex;
  justify-content: center;
  margin-bottom: var(--space-md);
}
.about-arm { max-width: 280px; width: 100%; }
.about-arm img { height: 200px; }
/* Institutional brand marks — the src-8 icon family (also the favicon). */
.about-brand-marks {
  list-style: none;
  margin: 0 0 var(--space-lg);
  padding: var(--space) 0 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space) var(--space-lg);
  justify-content: center;
}
.about-brand-marks li {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.75rem;
  letter-spacing: 0.04em;
  color: var(--muted);
}
.about-brand-marks img { width: 48px; height: 48px; object-fit: contain; }

.about-gem-note { margin: var(--space) 0 0; font-size: 0.82rem; color: var(--muted); }
.about-license {
  margin-top: var(--space-xl);
  text-align: left;
  border: 1px solid var(--border);
  border-top: 2px solid #c9a23a;
  border-radius: var(--radius-lg);
  background: var(--bg-elev);
  padding: var(--space-md);
  box-shadow: var(--shadow-sm);
}
.about-license h2 { margin: 0 0 0.45rem; font-size: 1.05rem; }
.spdx-chip {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: #b8860b;
  border: 1px solid #c9a23a;
  border-radius: var(--radius-pill);
  padding: 0.05rem 0.6rem;
  margin-left: 0.5rem;
  vertical-align: 0.12em;
}
:root[data-theme="dark"] .spdx-chip { color: #e0b341; }
.about-license p { margin: 0.45rem 0; font-size: 0.9rem; color: var(--muted); }
.about-license details { margin-top: var(--space-sm); }
.about-license summary {
  cursor: pointer;
  font-size: 0.86rem;
  color: var(--accent);
  font-weight: 600;
}
.about-license pre {
  margin: var(--space-sm) 0 0;
  font-size: 0.72rem;
  line-height: 1.55;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* ── Cortex Press (scoped .press-*) ─────────────────────────────────── */
/* The press pages shipped with semantic class hooks but no styles: the
   Library facets rendered as huge full-width stacked fields, long
   verification hashes overflowed phones, and the author/editor action
   cells were unspaced. Everything here is scoped under .press-* — no
   global element rules, no leaks into other pages. */

/* Library filter facets: one compact filter bar, wrapping on narrow. */
.press-facets {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--space);
  margin: var(--space) 0 var(--space-lg);
}
.press-facets > label {
  display: flex;
  flex-direction: column;
  gap: 6px;
  flex: 1 1 11rem;
  min-width: 0;
  color: var(--muted);
  font-size: 0.82em;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.press-facets select,
.press-facets input {
  font-size: 1rem;
  font-weight: 400;
  text-transform: none;
  letter-spacing: normal;
}
.press-facets button { flex: 0 0 auto; }
.press-facets > a { padding: 9px 0; white-space: nowrap; }

/* Search bar: input + button + back-link on one wrapping line. */
.press-search-form {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-sm);
  margin: var(--space) 0 var(--space-lg);
}
.press-search-form input[type="text"] { flex: 1 1 16rem; width: auto; min-width: 0; }
.press-search-form a { white-space: nowrap; }

/* Publication lists (Library “Latest” / “Distinguished” / search results). */
.press-list { margin: var(--space-sm) 0 var(--space-lg); padding-left: 1.2em; }
.press-list li { margin: 8px 0; }

/* Long verification ids / content hashes must wrap instead of widening the
   page on phones (the only unbreakable strings on these pages). */
.press-publication code,
.press-verify code,
.press-honesty code {
  overflow-wrap: anywhere;
  word-break: break-word;
}

/* Tag chips on a publication page. */
.press-tags { display: flex; flex-wrap: wrap; gap: 6px; }

/* Verification record: label/value grid instead of UA-indented dl. */
.press-verify dl {
  display: grid;
  grid-template-columns: max-content minmax(0, 1fr);
  gap: 8px var(--space-lg);
  margin: var(--space) 0;
}
.press-verify dt {
  color: var(--muted);
  font-size: 0.82em;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  padding-top: 3px;
}
.press-verify dd { margin: 0; min-width: 0; }
@media (max-width: 480px) {
  .press-verify dl { grid-template-columns: 1fr; gap: 2px; }
  .press-verify dd { margin-bottom: 8px; }
}

/* ── Status & admin dataviz (STATUS_UX_SPEC) ─────────────────────────────
   Shared component CSS for /admin/university-status + /admin: the promoted
   ust-st-* status pills, tier-metal pills, donut/gauge/bars, ONGOING pulse,
   stat tiles, zebra/sortable tables. All selectors are single-class .ust-*
   (never fights .card/.phase-table); theme switching is token-only except
   the four pill families, which keep their shipped per-theme blocks. */

:root {
  /* Heraldic metals (heraldry.py _METAL_STOPS — hi/mid/lo, verbatim) */
  --metal-gold-hi: #f0d68a;  --metal-gold: #d8b24a;  --metal-gold-lo: #a07818;
  --metal-silver-hi: #e8ecf2; --metal-silver: #b8bcc4; --metal-silver-lo: #7e858f;
  --metal-slate-hi: #a9b4c4;  --metal-slate: #64748b; --metal-slate-lo: #3b4554;
  /* Chart chrome */
  --viz-track: color-mix(in srgb, var(--accent) 16%, transparent);
  --viz-grid:  color-mix(in srgb, var(--fg) 8%, transparent);
}

/* Smooth anchor scrolling (reduced-motion kills it); anchored headings never
   land under the (possibly 2–3-row) logged-in nav. */
html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }
.ust-anchor { scroll-margin-top: 140px; }

/* Screen-reader-only text (tier letters/status words stay visible; this is
   for control labels like the expand chevron). Deliberately NOT the classic
   `position: absolute` recipe: main.container is transformed (page-in
   animation), so an absolute sr-span inside a `.table-scroll` would resolve
   its containing block OUTSIDE the scroll container and leak the table's
   width into the page's horizontal scroll (Chromium probe, 390px). The
   in-flow 1px inline-block variant stays contained. */
.ust-sr {
  display: inline-block;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Status pill anatomy + the ledger status scale (promoted from the
   university_status template so /admin can reuse it — spec §5.4). */
.ust-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.35em;
  padding: 0.08em 0.55em;
  border-radius: 999px;
  border: 1px solid transparent;
  font-size: 0.85em;
  line-height: 1.5;
  white-space: nowrap;
  margin-right: 0.35em;
}
.ust-badge .ust-emoji { font-size: 0.95em; }
:root[data-theme="dark"] .ust-st-done { background: rgba(63,185,80,.16); color: #3fb950; border-color: rgba(63,185,80,.45); }
:root[data-theme="light"] .ust-st-done { background: #dafbe1; color: #1a7f37; border-color: #aceebb; }
:root[data-theme="dark"] .ust-st-wip { background: rgba(219,109,40,.16); color: #e8905c; border-color: rgba(219,109,40,.45); }
:root[data-theme="light"] .ust-st-wip { background: #fff1e5; color: #bc4c00; border-color: #ffd8b5; }
:root[data-theme="dark"] .ust-st-designed { background: rgba(163,113,247,.16); color: #bc8cff; border-color: rgba(163,113,247,.45); }
:root[data-theme="light"] .ust-st-designed { background: #fbefff; color: #8250df; border-color: #ecd8ff; }
:root[data-theme="dark"] .ust-st-planned { background: rgba(88,166,255,.16); color: #79b8ff; border-color: rgba(88,166,255,.45); }
:root[data-theme="light"] .ust-st-planned { background: #ddf4ff; color: #0969da; border-color: #b6e3ff; }
:root[data-theme="dark"] .ust-st-gated { background: rgba(139,148,158,.16); color: #b1bac4; border-color: rgba(139,148,158,.45); }
:root[data-theme="light"] .ust-st-gated { background: #eff1f3; color: #57606a; border-color: #d0d7de; }
:root[data-theme="dark"] .ust-st-not-started { background: transparent; color: var(--muted); border-color: var(--border); }
:root[data-theme="light"] .ust-st-not-started { background: transparent; color: var(--muted); border-color: var(--border); }
:root[data-theme="dark"] .ust-st-open { background: rgba(210,153,34,.16); color: #e3b341; border-color: rgba(210,153,34,.45); }
:root[data-theme="light"] .ust-st-open { background: #fff8c5; color: #9a6700; border-color: #eed888; }

/* Tier-metal pills (program tiers — NOT the partner .badge-t* set; partner t3
   is bronze, program T3 is slate). The tier letter is always rendered text. */
.ust-tier-1 {
  background: color-mix(in srgb, var(--metal-gold) 26%, transparent);
  border-color: color-mix(in srgb, var(--metal-gold) 60%, var(--border));
  color: #5a4708;
  font-weight: 600;
}
.ust-tier-2 {
  background: color-mix(in srgb, var(--metal-silver) 22%, transparent);
  border-color: color-mix(in srgb, var(--metal-silver) 55%, var(--border));
  color: var(--fg);
  font-weight: 600;
}
.ust-tier-3 {
  background: color-mix(in srgb, var(--metal-slate) 18%, transparent);
  border-color: color-mix(in srgb, var(--metal-slate) 50%, var(--border));
  color: var(--metal-slate-lo);
  font-weight: 600;
}
.ust-tier-low {
  background: transparent;
  border-color: var(--border);
  color: var(--muted);
  font-weight: 600;
}
:root[data-theme="dark"] .ust-tier-1 {
  background: color-mix(in srgb, var(--metal-gold) 16%, transparent);
  color: var(--metal-gold-hi);
}
:root[data-theme="dark"] .ust-tier-2 {
  background: color-mix(in srgb, var(--metal-silver) 16%, transparent);
  color: var(--metal-silver-hi);
}
:root[data-theme="dark"] .ust-tier-3 {
  background: color-mix(in srgb, var(--metal-slate) 16%, transparent);
  color: var(--metal-slate-hi);
}
/* The "· Gold" word part shows ≥720px only; the letter is always present. */
@media (max-width: 719.98px) { .ust-tier-word { display: none; } }

/* Hero donut (spec §2.1.1) */
.ust-donut-track { stroke: var(--viz-track); }
.ust-donut-value { stroke: var(--accent); }
.ust-donut-wrap  { position: relative; width: 148px; margin: 0 auto; }
/* The SVG always fills its wrap: a wrap resized by page CSS (e.g. the status
   dashboard's 124px density override) must scale the ring with it, or the
   center overlay's numbers drift off the ring's true center. */
.ust-donut-wrap svg { width: 100%; height: auto; display: block; }
.ust-donut-center{ position: absolute; inset: 0; display: grid; place-content: center; text-align: center; }
.ust-donut-pct   { font-size: 2rem; font-weight: 650; line-height: 1; }
.ust-donut-sub   { font-size: 0.78rem; color: var(--muted); }

/* Remaining-effort gauge (spec §2.1.3) */
.ust-gauge-track { stroke: var(--viz-track); }
.ust-gauge-value { stroke: var(--accent); }
.ust-gauge-tick  { stroke: var(--viz-grid); }
.ust-gauge-sub { font-size: 0.78rem; color: var(--muted); text-align: center; max-width: 22ch; }

/* Status-count chips (legend + filter in one element — spec §2.1.2) */
.ust-chips { display: flex; flex-wrap: wrap; gap: 6px; }
button.ust-chip { cursor: pointer; font: inherit; font-size: 0.85em; }
button.ust-chip:focus-visible { outline: none; box-shadow: var(--ring); }
button.ust-chip[aria-pressed="true"] { box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 55%, transparent); }
.ust-chip-zero { opacity: 0.55; }
.ust-chip-count { font-weight: 650; font-variant-numeric: tabular-nums; }

/* Per-level progress bars (spec §2.2): one hue, 10px track, staggered reveal.
   Final state never depends on the animation (reduced-motion kill is global). */
.ust-bar-row {
  display: grid;
  grid-template-columns: 9rem 1fr 6.5rem;
  gap: var(--space-sm);
  align-items: center;
  margin: 8px 0;
}
@media (max-width: 560px) { .ust-bar-row { grid-template-columns: 6rem 1fr 6.5rem; } }
.ust-bar-label { font-size: 0.9em; }
.ust-bar-track { height: 10px; border-radius: 5px; background: var(--viz-track); overflow: hidden; }
.ust-bar-fill {
  height: 100%;
  background: var(--accent);
  border-radius: 0 5px 5px 0;
  transform-origin: left;
  animation: ust-fill-in 700ms cubic-bezier(0.22, 0.61, 0.36, 1) both;
  animation-delay: calc(var(--i, 0) * 60ms);
}
@keyframes ust-fill-in { from { transform: scaleX(0); } }
.ust-bar-value { font-size: 0.85em; color: var(--muted); font-variant-numeric: tabular-nums; text-align: right; }

/* ONGOING pulse pill (spec §2.4): danger hue, sonar dot. Reduced motion →
   solid dot + the word (the global kill cancels the keyframes). */
.ust-ongoing {
  color: var(--danger);
  border-color: color-mix(in srgb, var(--danger) 55%, var(--border));
  background: color-mix(in srgb, var(--danger) 10%, transparent);
}
.ust-ongoing-dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--danger);
  box-shadow: 0 0 0 2px var(--bg-elev);
  animation: ust-pulse 1.6s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
@keyframes ust-pulse {
  0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--danger) 45%, transparent); }
  70%  { box-shadow: 0 0 0 7px transparent; }
  100% { box-shadow: 0 0 0 0 transparent; }
}
/* One-shot row highlight when the poller changes a badge (spec §2.4). */
@keyframes ust-row-flash {
  from { background: color-mix(in srgb, var(--accent) 14%, transparent); }
  to   { background: transparent; }
}
.ust-row-flash { animation: ust-row-flash 1.2s ease-out both; }

/* Refresh spinner (↻ glyph spins while a soft refresh is in flight). */
.ust-refresh-btn { display: inline-flex; align-items: center; gap: 6px; }
.ust-spin-glyph { display: inline-block; }
.ust-refreshing .ust-spin-glyph { animation: ust-spin 900ms linear infinite; }
@keyframes ust-spin { to { transform: rotate(360deg); } }
/* Refetch keeps the frame: charts hold at reduced opacity, no skeleton swap. */
.ust-hold { opacity: 0.55; }

/* Collapsible section cards (native <details> — spec §2.6). */
details.ust-section > summary {
  cursor: pointer;
  list-style: none;
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}
details.ust-section > summary::-webkit-details-marker { display: none; }
details.ust-section > summary h2 { margin: 0; }
details.ust-section > summary .ust-sum-meta {
  display: inline-flex; align-items: center; gap: 8px; margin-left: auto;
}
details.ust-section > summary:focus-visible { outline: none; box-shadow: var(--ring); border-radius: 6px; }
details.ust-section .chev,
.ust-expand .chev {
  display: inline-block;
  font-weight: 700;
  color: var(--muted);
  transition: transform var(--transition);
}
details[open].ust-section > summary .chev { transform: rotate(90deg); }
details.ust-section[open] > summary { margin-bottom: var(--space-sm); }

/* "Submit a problem" capture box (backlog P28 — _partials/problem_button.html).
   A plain <details class="card">; the summary is styled to read as a button
   so the collapsed state matches the other .btn-link CTAs on the page. */
.problem-report-box > summary {
  cursor: pointer;
  list-style: none;
  display: inline-block;
  padding: 6px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  font-size: 0.9em;
  font-weight: 600;
}
.problem-report-box > summary::-webkit-details-marker { display: none; }
.problem-report-box > summary:hover {
  background: color-mix(in srgb, var(--fg) 6%, transparent);
  border-color: color-mix(in srgb, var(--fg) 30%, var(--border));
}
.problem-report-box[open] > summary { margin-bottom: var(--space-sm); }
.problem-report-box form.stack { margin-top: var(--space-sm); }

/* Expandable rows (details-on-demand — spec §2.8). */
.ust-expand-cell { width: 2.5em; }
.ust-expand-form { margin: 0; }
button.ust-expand {
  background: transparent;
  border: 1px solid transparent;
  padding: 2px 8px;
  border-radius: var(--radius);
  cursor: pointer;
}
button.ust-expand:hover { border-color: var(--border); background: color-mix(in srgb, var(--fg) 6%, transparent); }
button.ust-expand[aria-expanded="true"] .chev { transform: rotate(90deg); }
tbody tr.ust-detail > td {
  background: color-mix(in srgb, var(--fg) 3%, transparent);
}

/* Zebra + hover + sortable tables (spec §3.4). `.ust-zebra` stripes plain
   tables; `.ust-zebra-x` stripes tables whose data rows interleave with
   hidden detail rows (2 DOM rows per item → 4n+1 keeps honest striping). */
.ust-zebra tbody tr:nth-child(odd) { background: color-mix(in srgb, var(--fg) 3%, transparent); }
.ust-zebra-x tbody tr:nth-child(4n+1) { background: color-mix(in srgb, var(--fg) 3%, transparent); }
.ust-zebra tbody tr:hover,
.ust-zebra-x tbody tr:not(.ust-detail):hover { background: color-mix(in srgb, var(--fg) 6%, transparent); }
th[data-sort] button.ust-sort {
  background: transparent;
  border: 0;
  padding: 0;
  font: inherit;
  color: inherit;
  text-transform: inherit;
  letter-spacing: inherit;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
th[data-sort] button.ust-sort:focus-visible { outline: none; box-shadow: var(--ring); border-radius: 3px; }
.ust-sort-glyph { font-size: 0.9em; }

/* Admin stat tiles (spec §3.1). Plain HTML/CSS — numbers, not charts. */
.ust-tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: var(--space);
  margin: var(--space-sm) 0 var(--space-md);
}
.ust-tile {
  display: block;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--space) var(--space-md);
  box-shadow: var(--shadow-sm);
  color: inherit;
  text-decoration: none;
  transition: border-color var(--transition);
  min-width: 0;
}
a.ust-tile:hover { border-color: var(--accent); text-decoration: none; color: inherit; }
.ust-tile-label {
  display: block;
  color: var(--muted);
  font-size: 0.78em;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.ust-tile-value { display: block; font-size: 1.6rem; font-weight: 650; line-height: 1.25; }
.ust-tile-sub { display: block; color: var(--muted); font-size: 0.8em; overflow-wrap: anywhere; }
.ust-tile-delta-up { color: var(--ok); }
.ust-tile-delta-down { color: var(--danger); }

/* Roles mini-meter (spec §3.2): one-hue ordinal stacked bar, 2px surface gaps. */
.ust-meter { display: flex; column-gap: 2px; height: 8px; margin-top: 6px; border-radius: 4px; overflow: hidden; }
.ust-meter-seg { min-width: 3px; }

/* ── Partners admin table (compact layout, logo column leads) ─────────────
   7 columns: LOGO (own fixed-width column, ~2× the old inline slot), COMPANY
   (one-line name + sector·country), STUDENTS (accepted/rejected/ongoing/total
   stat cluster), RATIO (+ rejection streak subline), LINKS (icon pair), TIER
   and RECORD (inline forms that wrap, full option text visible). Wide rows
   pan inside .table-scroll — never the page. Below 860px the rows degrade to
   stacked cards (each cell labelled via data-label). */
.partners-table { table-layout: auto; }
/* The registry gained a dedicated 2× logo column: widen the page canvas so
   all 7 columns sit without an inner pan on desktop (same :has() idiom as the
   status dashboard's wide canvas; no-:has browsers keep 1080 + inner scroll). */
main.container:has(.partners-table) { max-width: 1400px; }
.partners-table th,
.partners-table td { padding: 10px 8px; }
.partners-table td { vertical-align: middle; }
/* The generic first-column treatment (mono, 3em — meant for phase numbers)
   would crush the LOGO column; restore normal text metrics. */
.partners-table td:first-child {
  font-family: inherit;
  font-size: inherit;
  width: auto;
}

/* Logo column: fixed-width so Company can flex; art is 2× the old 20px slot
   (40px tall, aspect preserved via object-fit) and never grows past 192px. */
.partners-table th.partner-logo-col { width: 200px; }
.partner-logo-cell { white-space: nowrap; }

/* Company identity cell: the name holds ONE line (never wraps), with the
   sector·country meta beneath it. */
.partner-co {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 3px;
  min-width: 0;
}
.partner-co-name { font-weight: 600; line-height: 1.2; white-space: nowrap; }
.partner-co-meta { color: var(--muted); font-size: 0.78em; line-height: 1.2; white-space: nowrap; }
.partner-logo {
  display: flex;
  align-items: center;
  height: 40px;
}
.partner-logo img {
  height: 40px;
  max-width: 192px;
  width: auto;
  object-fit: contain;
  object-position: left center;
  display: block;
}
/* Monogram fallback when no /static/partner_logos/<slug>.(svg|png) asset
   exists: company initials in a tier-tinted rounded box. Same 40px slot. */
.partner-monogram {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 40px;
  min-width: 52px;
  padding: 0 10px;
  border-radius: 8px;
  font-size: 1.05rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  border: 1px solid color-mix(in srgb, var(--accent) 40%, var(--border));
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
}
.partner-monogram-t1 {
  border-color: color-mix(in srgb, #d8b24a 60%, var(--border));
  color: #8a6d1c;
  background: color-mix(in srgb, #d8b24a 22%, transparent);
}
:root[data-theme="dark"] .partner-monogram-t1 { color: #f0d68a; }
.partner-monogram-t2 {
  border-color: color-mix(in srgb, #b8bcc4 55%, var(--border));
  color: var(--fg);
  background: color-mix(in srgb, #b8bcc4 18%, transparent);
}
.partner-monogram-t3 {
  border-color: color-mix(in srgb, #c08a4a 55%, var(--border));
  color: #8a5c2a;
  background: color-mix(in srgb, #c08a4a 18%, transparent);
}
:root[data-theme="dark"] .partner-monogram-t3 { color: #e0b07a; }
.partner-monogram-special {
  border-color: color-mix(in srgb, var(--accent) 55%, var(--border));
}
.partner-monogram-low,
.partner-monogram-excluded {
  border-color: var(--border);
  color: var(--muted);
  background: color-mix(in srgb, var(--muted) 10%, transparent);
}

/* Accepted/rejected/ongoing/total cluster: four labelled mini-stats in one
   cell. Colour reinforces, never carries — each figure keeps a text label. */
.pstats { display: flex; gap: 10px; white-space: nowrap; }
.pstat { display: inline-flex; flex-direction: column; align-items: center; min-width: 1.6em; }
.pstat-n { font-weight: 650; font-variant-numeric: tabular-nums; line-height: 1.2; }
.pstat-l {
  color: var(--muted);
  font-size: 0.62rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.pstat-accepted .pstat-n { color: var(--ok); }
.pstat-rejected .pstat-n { color: var(--danger); }
.pstat-ongoing .pstat-n { color: var(--accent); }

/* Ratio cell: percentage + optional rejection-streak subline. */
.pratio { display: flex; flex-direction: column; gap: 2px; white-space: nowrap; }
.pratio-streak { color: var(--danger); font-size: 0.72em; }

/* Link icons (website / careers): compact 26px hit targets, labelled for AT. */
.plinks { display: flex; gap: 4px; }
.plink {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: 6px;
  color: var(--muted);
  border: 1px solid transparent;
}
.plink:hover,
.plink:focus-visible {
  color: var(--accent);
  border-color: var(--border);
  background: color-mix(in srgb, var(--accent) 8%, transparent);
}

/* Tier / record forms: wrap instead of clipping; selects size to content. */
.partners-cell-action { min-width: 0; }
.partners-cell-action form.row { flex-wrap: wrap; gap: 6px; align-items: center; }
.partners-cell-action .tier-select,
.partners-cell-action .outcome-select {
  width: auto;
  min-width: 0;
  max-width: 100%;
}

/* Narrow viewports: stacked cards instead of a sideways pan. Each cell shows
   its column label (data-label) as an eyebrow; the company cell leads. */
@media (max-width: 860px) {
  .partners-table thead { display: none; }
  .partners-table,
  .partners-table tbody { display: block; }
  .partners-table tbody tr {
    display: block;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--bg-elev);
    padding: 6px 12px;
    margin-bottom: var(--space);
  }
  .partners-table tbody td {
    display: block;
    border-bottom: 0;
    padding: 6px 0;
  }
  .partners-table tbody td[data-label]::before {
    content: attr(data-label);
    display: block;
    color: var(--muted);
    font-size: 0.68rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    margin-bottom: 2px;
  }
  .partners-table .partner-co { min-width: 0; }
}

/* Heraldic section eyebrow on /admin cards (spec §3.5): the one gold echo. */
.ust-eyebrow {
  display: block;
  font-size: 0.74rem;
  text-transform: uppercase;
  letter-spacing: 1.6px;
  font-weight: 700;
  color: var(--metal-gold-lo);
  margin: 0 0 2px;
}
:root[data-theme="dark"] .ust-eyebrow { color: color-mix(in srgb, var(--metal-gold-hi) 80%, transparent); }

/* Standing verdict (verify page): metal is never colour-alone — the word
   itself is rendered; colour only reinforces it. */
.press-standing-published,
.press-standing-archived { color: var(--ok); }
.press-standing-revoked { color: var(--danger); }

/* Author/editor action cells: stack each action with breathing room. */
td.press-actions > a { display: inline-block; margin: 2px 0 6px; }
td.press-actions form { margin: 0 0 6px; }
td.press-actions form:last-child { margin-bottom: 0; }
.press-publish-form { display: grid; gap: 6px; justify-items: start; }
.press-publish-form label {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 0.9em;
}
.press-publish-form select { width: auto; }

/* ── Cortex Newsletter (/newsletter) ─────────────────────────────────────
   Announcement surfaces: masthead + signature, type-coded badges, the
   permanent v0 test ribbon, filter tabs, cards and partner chips. Colors
   ride the theme variables so light + dark both read cleanly. */
.nl-masthead {
  display: flex;
  align-items: center;
  gap: 14px;
  padding-bottom: 12px;
  margin-bottom: 14px;
  border-bottom: 1px solid var(--border);
}
.nl-crest { width: 52px; height: 52px; color: var(--accent); flex: none; }
.nl-masthead-text { display: grid; gap: 2px; }
.nl-wordmark { font-size: 1.3em; font-weight: 700; letter-spacing: 0.02em; }
.nl-wordmark-accent { color: var(--accent); }
.nl-signature { color: var(--muted); font-size: 0.85em; }
.nl-filters { display: flex; flex-wrap: wrap; gap: 8px; margin: 14px 0; }
.nl-filter {
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 4px 12px;
  font-size: 0.9em;
  text-decoration: none;
}
.nl-filter.is-active {
  border-color: var(--accent-strong);
  color: var(--accent);
  font-weight: 600;
}
.nl-cards { list-style: none; margin: 0; padding: 0; display: grid; gap: 14px; }
.nl-card {
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 14px 16px;
  background: var(--bg-elev);
}
.nl-card-meta { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.nl-card-title { margin: 6px 0 4px; font-size: 1.15em; }
.nl-datetime { font-variant-numeric: tabular-nums; }
.nl-signed { color: var(--muted); font-style: italic; margin-bottom: 0; }
.nl-title { margin-top: 10px; }
/* Type badges: launch / deadlines / partners / notice, color-coded. */
.nl-badge-program_launch { background: color-mix(in srgb, var(--ok) 18%, transparent); color: var(--ok); }
.nl-badge-deadlines { background: color-mix(in srgb, var(--accent) 18%, transparent); color: var(--accent); }
.nl-badge-partner_update { background: color-mix(in srgb, #b58900 22%, transparent); color: #b58900; }
:root[data-theme="dark"] .nl-badge-partner_update { color: #e0c060; }
.nl-badge-custom { background: color-mix(in srgb, var(--muted) 20%, transparent); color: var(--fg); }
/* The permanent v0 development/test ribbon (spec §4.3). */
.nl-ribbon {
  display: inline-block;
  border: 1px dashed #b58900;
  color: #b58900;
  border-radius: 4px;
  padding: 1px 8px;
  font-size: 0.75em;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
:root[data-theme="dark"] .nl-ribbon { color: #e0c060; border-color: #e0c060; }
.nl-ribbon-block { display: block; padding: 6px 10px; margin: 10px 0; }
.nl-highlight {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  border: 1px solid var(--border);
  border-left: 3px solid var(--ok);
  border-radius: 8px;
  padding: 10px 12px;
  margin: 12px 0;
  background: var(--bg-elev);
}
.nl-chips { display: flex; flex-wrap: wrap; gap: 8px; margin: 12px 0; }
.nl-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 3px 10px 3px 4px;
  font-size: 0.9em;
  background: var(--bg-elev);
}
.nl-chip-distinguished { border-color: #b58900; }
:root[data-theme="dark"] .nl-chip-distinguished { border-color: #e0c060; }
.nl-body table { border-collapse: collapse; margin: 10px 0; }
.nl-body th, .nl-body td { border: 1px solid var(--border); padding: 5px 10px; }
.nl-inline-form { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 8px 0; }
.nl-inline-form select, .nl-inline-form input[type="text"] { width: auto; }
.nl-generators { display: grid; gap: 10px; }

/* ── P1 · Modern chrome re-skin (register: reg-modern) ─────────────────────
   Restyles the app shell to the MODERN register (GAMIFICATION_USAGE_PLAN §1.3;
   src-10 UI kit + id-authenticator UI language). Purely visual, no markup or
   logic change. Everything is scoped to `body.reg-modern` so classic/print
   surfaces (id_card, certificate, transcript, letters) are untouched. Colours
   flow from the modern tokens (tokens-modern.css); the neon-cyan --accent is
   already inherited, so links, focus rings, active nav and badges pick it up. */

/* Header bar: a cyan hairline glow under the sticky nav. */
body.reg-modern .topnav {
  border-bottom-color: color-mix(in srgb, var(--m-cyan) 32%, var(--border));
  box-shadow: 0 1px 0 color-mix(in srgb, var(--m-cyan) 20%, transparent);
}

/* Footer: matching cyan hairline on top. */
body.reg-modern .site-footer {
  border-top-color: color-mix(in srgb, var(--m-cyan) 24%, var(--border));
}

/* Primary buttons: cyan→violet gradient. The raw cyan is too light to carry
   white text at AA, so the gradient starts at the deep cyan and resolves into
   the brand violet — high contrast and on-register (both modern accents). */
body.reg-modern button.primary,
body.reg-modern .btn-primary {
  background: linear-gradient(135deg, var(--m-cyan-deep), var(--m-violet));
  border-color: var(--m-violet);
  color: #fff;
}
body.reg-modern button.primary:hover,
body.reg-modern .btn-primary:hover {
  filter: brightness(1.1);
  box-shadow: 0 4px 16px color-mix(in srgb, var(--m-violet) 45%, transparent);
}

/* Flash / notification boxes: HUD-style tinted panels (src-10 alert kit) —
   a 4px semantic left rail over a faint same-hue wash. */
body.reg-modern .flash {
  border-left-width: 4px;
  background: color-mix(in srgb, var(--m-panel) 45%, var(--bg-elev));
}
body.reg-modern .flash-info {
  border-left-color: var(--m-cyan);
  background: color-mix(in srgb, var(--m-cyan) 8%, var(--bg-elev));
}
body.reg-modern .flash-success {
  background: color-mix(in srgb, var(--ok) 9%, var(--bg-elev));
}
body.reg-modern .flash-error {
  background: color-mix(in srgb, var(--danger) 9%, var(--bg-elev));
}

/* ── P21 · Classic chrome re-skin (register: reg-classic) ──────────────────
   The counterpart to the modern chrome block above, for the CLASSIC register
   (old-fashion / field-heraldic: gold–navy–parchment, engraved serif display).
   Colours flow from the classic tokens (tokens-classic.css) which also repoint
   --accent to heraldic gold, so links / focus rings / active nav pick it up.
   Purely visual, scoped to `body.reg-classic`; modern surfaces are untouched.
   Theme-aware — every colour is a token or a color-mix over the shared theme
   tokens, so light + dark both render correctly. */

/* Header bar: a gold hairline + faint gold glow under the sticky nav (the
   engraved-plate look), replacing the modern cyan glow. */
body.reg-classic .topnav {
  border-bottom-color: color-mix(in srgb, var(--c-gold) 42%, var(--border));
  box-shadow: 0 1px 0 color-mix(in srgb, var(--c-gold) 26%, transparent);
}
/* Footer: matching gold hairline on top. */
body.reg-classic .site-footer {
  border-top-color: color-mix(in srgb, var(--c-gold) 34%, var(--border));
}
/* Brand wordmark accent: gold on the classic register (was the modern cyan). */
body.reg-classic .brand-text-accent {
  color: var(--c-gold);
}

/* Primary buttons: a wax-seal red→gold heraldic gradient with a gold rim. */
body.reg-classic button.primary,
body.reg-classic .btn-primary {
  background: linear-gradient(135deg, var(--c-red), var(--c-gold-deep));
  border-color: var(--c-gold);
  color: #fff;
}
body.reg-classic button.primary:hover,
body.reg-classic .btn-primary:hover {
  filter: brightness(1.08);
  box-shadow: 0 4px 16px color-mix(in srgb, var(--c-gold-deep) 45%, transparent);
}

/* Flash / notification boxes: a parchment-tinted panel with a gold left rail —
   the "official notice" look, mirroring the modern HUD panels structurally. */
body.reg-classic .flash {
  border-left-width: 4px;
  border-left-color: var(--c-gold-deep);
  background: color-mix(in srgb, var(--c-parchment) 10%, var(--bg-elev));
}
body.reg-classic .flash-info {
  border-left-color: var(--c-gold-deep);
  background: color-mix(in srgb, var(--c-gold) 8%, var(--bg-elev));
}
body.reg-classic .flash-success {
  border-left-color: var(--c-green);
  background: color-mix(in srgb, var(--ok) 9%, var(--bg-elev));
}
body.reg-classic .flash-error {
  border-left-color: var(--c-red);
  background: color-mix(in srgb, var(--danger) 9%, var(--bg-elev));
}

/* Cards get a subtle double-rule gold inner border — the framed-certificate
   motif — without changing layout (inset box-shadow only). */
body.reg-classic .cat-card,
body.reg-classic .ov-card,
body.reg-classic .lib-card {
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--c-gold) 18%, transparent);
}

/* =========================================================================
   Catalogue · Guide · Overview · Path infographics (GAMIFICATION_USAGE_PLAN
   P8 + P9). Theme-aware (uses the shared --bg/--fg/--border tokens + the
   modern --m-* accents); animation is gated behind prefers-reduced-motion.
   CSP-safe: styling only, all behaviour lives in portal.js.
   ========================================================================= */

/* Shared button skins (base layout — .btn-primary colour is set above). */
.btn-primary,
.btn-secondary,
.btn-tertiary {
  display: inline-block;
  padding: 0.5rem 1rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  text-decoration: none;
  color: var(--fg);
  background: var(--bg-elev);
  transition: filter 0.15s ease, background 0.15s ease, border-color 0.15s ease;
}
.btn-secondary:hover,
.btn-tertiary:hover { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 8%, var(--bg-elev)); }
.btn-tertiary { background: transparent; }
.btn-primary { color: #fff; }
.btn-primary:disabled,
.btn-secondary:disabled { opacity: 0.55; cursor: not-allowed; filter: grayscale(0.3); }

/* ---- Catalogue ---------------------------------------------------------- */
.cat-page, .guide-page, .ov-page, .admin-cat { margin: 1.5rem auto 3rem; }
.cat-head, .guide-head, .ov-head, .admin-cat-head { margin-bottom: 1.5rem; }
.cat-title, .guide-title, .ov-title { margin: 0 0 0.4rem; font-size: 1.9rem; }
.cat-intro, .guide-intro, .ov-intro { color: var(--muted); max-width: 62ch; }
.cat-actions { margin-top: 0.8rem; }

.cat-grid, .ov-grid {
  list-style: none; padding: 0; margin: 0;
  display: grid; gap: 1.1rem;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
}
.cat-card, .ov-card {
  border: 1px solid var(--border); border-radius: 14px;
  background: var(--bg-elev); padding: 1.1rem 1.2rem 1.2rem;
  display: flex; flex-direction: column; gap: 0.7rem;
}
.cat-card.is-doctoral, .ov-card.is-doctoral {
  border-color: color-mix(in srgb, var(--m-violet, #7b2fff) 40%, var(--border));
}
/* Cards are clean/text-only (catalogue rework 2026-07-13): no herald/emblem
   art on a card — the status chip right-aligns alone on the top row. */
.cat-card-top, .ov-card-top { display: flex; align-items: center; justify-content: flex-end; gap: 0.6rem; }
.cat-card-title, .ov-card-title { margin: 0; font-size: 1.15rem; }
/* Whole-card click target (catalogue only): the title link stretches over the
   card; links/CTAs below sit above it so they stay clickable themselves. */
.cat-card { position: relative; }
.cat-card-link { color: inherit; text-decoration: none; }
.cat-card .cat-card-link::after { content: ""; position: absolute; inset: 0; border-radius: 14px; }
.cat-card:hover { border-color: color-mix(in srgb, var(--accent) 45%, var(--border)); }
.cat-card-links, .cat-card-foot { position: relative; z-index: 1; }
.cat-card-desc { margin: 0; font-size: 0.88rem; line-height: 1.45; }
.cat-card-links { margin: 0; font-size: 0.82rem; color: var(--muted); }
.cat-ladder { margin-top: 2.2rem; padding-top: 1.4rem; border-top: 1px solid var(--border); }
.cat-card-sector, .ov-card-sector { margin: 0; color: var(--muted); font-size: 0.85rem; }

/* Level sections L0–L10 (LEVELS_CATALOGUE_GUIDE_REWORK §A/§C, addendum (b)) */
.cat-level { margin: 1.8rem 0 0; padding-top: 1.1rem; border-top: 1px solid var(--border); }
.cat-level-head { margin: 0 0 0.7rem; font-size: 1.25rem; display: flex; align-items: center; gap: 0.55rem; }
/* Classic tier emblem beside the heading — uniform height, auto width (the
   medallions are not square, so never force a square that would distort). */
.cat-level-emblem { height: 40px; width: auto; max-width: 64px; object-fit: contain; flex: 0 0 auto; }
.cat-level-note {
  margin: 0 0 0.4rem; max-width: 68ch; color: var(--muted); font-size: 0.9rem;
  padding: 0.6rem 0.9rem; border-left: 3px solid var(--accent);
  background: color-mix(in srgb, var(--accent) 6%, transparent); border-radius: 4px;
}
.cat-level-howto { margin: 0 0 0.6rem; max-width: 72ch; color: var(--fg); font-size: 0.92rem; line-height: 1.55; }
.cat-level-cta { margin: 0 0 0.4rem; display: flex; flex-wrap: wrap; gap: 0.5rem; }
.cat-card-level {
  margin: 0; font-size: 0.72rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted);
}

.cat-status {
  font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em;
  padding: 0.15rem 0.5rem; border-radius: 999px; white-space: nowrap;
}
.cat-status-live { background: color-mix(in srgb, var(--ok) 18%, transparent); color: var(--ok); }
.cat-status-coming_soon { background: color-mix(in srgb, var(--muted) 20%, transparent); color: var(--muted); }

.cat-section { margin-top: 0.2rem; }
.cat-label, .ov-path-heading {
  margin: 0 0 0.35rem; font-size: 0.72rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted);
}
.cat-label-inline { color: var(--muted); font-size: 0.8rem; }
.cat-tiers, .cat-grades { list-style: none; padding: 0; margin: 0; display: flex; flex-wrap: wrap; gap: 0.4rem; }
.cat-tier, .cat-grade {
  display: inline-flex; align-items: center; gap: 0.3rem;
  padding: 0.2rem 0.5rem; border: 1px solid var(--border); border-radius: 999px; font-size: 0.8rem;
}
.cat-prereq-body { margin: 0; font-size: 0.85rem; }
.cat-prereq-note { display: block; color: var(--muted); font-size: 0.76rem; margin-top: 0.2rem; }
.cat-card-foot, .ov-card-foot {
  margin-top: auto; padding-top: 0.7rem; border-top: 1px solid var(--border);
  display: flex; align-items: center; justify-content: space-between; gap: 0.6rem; flex-wrap: wrap;
}
.cat-professor, .ov-professor { margin: 0; font-size: 0.85rem; }

/* ---- Catalogue detail (one program × tier) ------------------------------ */
.catd-page { max-width: 720px; }
.catd-back { margin: 0 0 1rem; }
.catd-head {
  display: flex; align-items: center; gap: 0.9rem;
  padding: 1.1rem 1.2rem; border: 1px solid var(--border); border-radius: 14px;
  background: var(--bg-elev);
}
.catd-head.is-doctoral {
  border-color: color-mix(in srgb, var(--m-violet, #7b2fff) 40%, var(--border));
}
/* The discipline herald — the ONE catalogue surface it renders on (catalogue
   rework 2026-07-13): a proper, larger emblem in a framed panel beside the
   programme facts. Theme-aware via the shared tokens; scales down politely. */
.catd-herald {
  margin: 0; flex: 0 0 auto;
  display: flex; flex-direction: column; align-items: center; gap: 0.45rem;
  padding: 0.8rem 0.9rem; border: 1px solid var(--border); border-radius: 12px;
  background: color-mix(in srgb, var(--accent) 5%, var(--bg));
}
.catd-herald img {
  width: 128px; height: 128px; max-width: 128px; max-height: 128px;
  object-fit: contain; border-radius: 10px;
}
.catd-herald-caption {
  font-size: 0.68rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.05em; color: var(--muted); text-align: center;
}
@media (max-width: 560px) {
  .catd-head { flex-direction: column; align-items: flex-start; }
  .catd-herald { align-self: center; }
  .catd-herald img { width: 104px; height: 104px; }
}
.catd-title { margin: 0 0 0.25rem; font-size: 1.45rem; }
.catd-facts { margin: 1.2rem 0 0; display: grid; gap: 1rem; }
.catd-fact {
  border: 1px solid var(--border); border-radius: 12px;
  background: var(--bg-elev); padding: 0.8rem 1rem;
}
.catd-fact-body { margin: 0.15rem 0 0; font-size: 0.95rem; }
.catd-syllabus summary { cursor: pointer; }
.catd-syllabus-list { margin: 0.6rem 0 0; padding-left: 2.2rem; font-size: 0.88rem; }
.catd-syllabus-list li { margin: 0.15rem 0; }
.catd-prereqs { list-style: none; padding: 0; margin: 0; display: grid; gap: 0.3rem; }
.catd-foot { margin-top: 1.2rem; border-top: 0; }

/* ---- Guide -------------------------------------------------------------- */
.guide-section { margin: 2rem 0; padding-top: 1.2rem; border-top: 1px solid var(--border); }
.guide-h2 { font-size: 1.35rem; margin: 0 0 0.6rem; }
.guide-body { color: var(--muted); max-width: 68ch; }
.guide-clause {
  margin-top: 0.8rem; padding: 0.8rem 1rem; border-left: 4px solid var(--accent);
  background: color-mix(in srgb, var(--accent) 7%, var(--bg-elev)); border-radius: 6px; font-size: 0.9rem;
}
.guide-matrix-wrap { overflow-x: auto; }
.guide-matrix, .guide-acronyms, .guide-journey, .admin-cat-table {
  width: 100%; border-collapse: collapse; margin-top: 0.6rem; min-width: 380px;
}
.guide-matrix th, .guide-matrix td,
.guide-acronyms th, .guide-acronyms td,
.guide-journey th, .guide-journey td,
.admin-cat-table th, .admin-cat-table td {
  border: 1px solid var(--border); padding: 0.5rem 0.7rem; text-align: left; vertical-align: middle;
}
.guide-matrix thead th, .guide-acronyms thead th, .guide-journey thead th, .admin-cat-table thead th {
  background: var(--bg-elev); font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.04em;
}
.guide-journey td { font-size: 0.88rem; }
.guide-acronym-sym { font-family: var(--m-font-body, monospace); font-weight: 700; white-space: nowrap; }
.guide-band-word { font-size: 0.78rem; font-weight: 700; letter-spacing: 0.04em; color: var(--muted); }
.guide-h3 { font-size: 1.05rem; margin: 1.2rem 0 0.4rem; }
.guide-delta-note { margin-top: 0.8rem; font-size: 0.88rem; }
/* One-by-one explainers (rework §F): attribute / herald / badge rows. */
.guide-attr-list, .guide-emblem-list { list-style: none; padding: 0; margin: 0.6rem 0 0;
  display: grid; gap: 0.7rem; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); }
.guide-attr-item, .guide-emblem-item {
  display: flex; align-items: flex-start; gap: 0.7rem;
  border: 1px solid var(--border); border-radius: 12px;
  background: var(--bg-elev); padding: 0.7rem 0.8rem;
}
.guide-attr-item img, .guide-emblem-item img {
  border-radius: 8px; flex: 0 0 auto; object-fit: contain;
}
.guide-item-name { margin: 0 0 0.15rem; font-size: 0.92rem; }
.guide-item-desc { margin: 0; font-size: 0.8rem; line-height: 1.4; color: var(--muted); }
/* Supreme-honorary crest showcase (L8 → L9 → L10, own coat of arms each,
   grander as they climb) — P17 UX pass (2026-07-17): same card language as
   the herald/badge "one by one" rows above (bordered rectangle, bg-elev,
   text inside the box) instead of floating art, so the section reads as one
   consistent system. Crests now carry transparent-background art (audit
   docs/audits/EMBLEM_AUDIT.md), so no radial-gradient backdrop is needed.
   Each card fixes the SAME image-slot height; the Special Honorific Seat
   (L10) art is natively landscape, so it simply fills that slot wider —
   no special-casing needed, and no crest is oversized. */
.guide-crest-showcase { list-style: none; padding: 0; margin: 0.9rem 0 1.2rem;
  display: grid; gap: 0.7rem; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); }
.guide-crest-item { display: flex; flex-direction: column; align-items: center;
  text-align: center; gap: 0.3rem;
  border: 1px solid var(--border); border-radius: 12px;
  background: var(--bg-elev); padding: 0.7rem 0.8rem; }
.guide-crest-img-wrap { display: flex; align-items: center; justify-content: center;
  width: 100%; height: 96px; }
/* L10 Special Honorific Seat = the show-off apex: a taller image slot makes its
   1.5-aspect art render widest (L8 ~1:1 → ~102px < L9 1.5 → ~144px < L10 → ~192px),
   so its card is intentionally the grandest of the three. */
.guide-crest-item--l10 .guide-crest-img-wrap { height: 128px; }
.guide-crest-img { max-width: 100%; max-height: 100%; width: auto; height: auto;
  object-fit: contain; }
.guide-crest-level { margin: 0.15rem 0 0; font-size: 0.72rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.09em; color: var(--metal-gold-lo); }
:root[data-theme="dark"] .guide-crest-level { color: var(--metal-gold-hi); }
.guide-crest-item .guide-item-name { margin: 0; font-size: 0.92rem; }

/* ---- Overview ----------------------------------------------------------- */
.ov-meter { display: flex; align-items: center; gap: 0.6rem; margin-top: 0.8rem; }
.ov-meter-bar { display: inline-flex; gap: 0.25rem; }
.ov-slot { width: 34px; height: 8px; border-radius: 999px; background: var(--border); }
.ov-slot.is-used { background: linear-gradient(90deg, var(--m-cyan-deep, #0099cc), var(--m-violet, #7b2fff)); }
.ov-meter-text { color: var(--muted); font-size: 0.82rem; }
.ov-flash { padding: 0.7rem 1rem; border-radius: 8px; margin: 0.8rem 0; }
.ov-flash.ok { background: color-mix(in srgb, var(--ok) 12%, var(--bg-elev)); border: 1px solid var(--ok); }
.ov-flash.err { background: color-mix(in srgb, var(--danger) 12%, var(--bg-elev)); border: 1px solid var(--danger); }
.ov-advisory { margin: 0; font-size: 0.8rem; color: var(--muted);
  padding: 0.4rem 0.6rem; border-left: 3px solid var(--accent);
  background: color-mix(in srgb, var(--accent) 6%, transparent); border-radius: 4px; }
.ov-request-form { margin: 0; }
.ov-guide-link { margin-top: 0.8rem; }
/* Overview programme table (rework §J): one simple row per program. */
.ov-table-wrap { overflow-x: auto; }
.ov-table { width: 100%; border-collapse: collapse; margin-top: 0.6rem; min-width: 560px; }
.ov-table th, .ov-table td {
  border: 1px solid var(--border); padding: 0.55rem 0.7rem; text-align: left; vertical-align: middle;
}
.ov-table thead th {
  background: var(--bg-elev); font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.04em;
}
.ov-row-title a { font-weight: 600; color: inherit; }
.ov-row-title .ov-advisory { display: block; margin-top: 0.35rem; }
.ov-row-levels { font-size: 0.85rem; white-space: nowrap; }
.ov-row-professor { font-size: 0.88rem; }
.ov-row-action .btn-primary, .ov-row-action .btn-secondary { white-space: nowrap; }

/* ---- Path infographic --------------------------------------------------- */
.path-track { margin: 0.6rem 0 0; }
.path-track-title { margin: 0 0 0.6rem; font-size: 0.82rem; color: var(--muted); font-weight: 600; }
/* Wrapping ladder: the L0→L10 path flows onto 2-3 centred lines instead of a
   horizontal scrollbar (Borja 2026-07-13) — the rows wrap responsively and
   stay centred at every width. */
.path-nodes { list-style: none; margin: 0; padding: 0.2rem 0; display: flex; align-items: stretch;
  flex-wrap: wrap; justify-content: center; gap: 0.55rem 0.1rem; overflow: visible; }
.path-node-wrap { display: inline-flex; align-items: center; gap: 0.1rem; flex: 0 0 auto; }
.path-link { flex: 0 0 auto; width: 22px; }
.path-link-line { stroke: var(--border); stroke-width: 2; stroke-dasharray: 1;
  stroke-dashoffset: 1; animation: pathDraw 0.6s ease forwards; }
.path-node {
  display: inline-flex; flex-direction: column; align-items: center; gap: 0.2rem;
  min-width: 62px; padding: 0.45rem 0.4rem; border: 1px solid var(--border); border-radius: 12px;
  background: var(--bg-elev); cursor: pointer; font: inherit; color: var(--fg);
  transition: transform 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
}
.path-node:hover, .path-node:focus-visible {
  border-color: var(--m-cyan, var(--accent)); transform: translateY(-2px);
  box-shadow: 0 4px 14px color-mix(in srgb, var(--m-cyan, #00e5ff) 22%, transparent); outline: none;
}
.path-node.is-locked { opacity: 0.55; filter: grayscale(0.6); }
.path-node-badge { display: inline-flex; }
/* Level emblem medallions are not square — render at a uniform height with
   auto width so none is distorted (overrides the macro's 46x46 attrs). */
.path-node-badge img { height: 44px; width: auto; max-width: 72px; object-fit: contain; }
.path-node-label { font-weight: 700; font-size: 0.82rem; }
.path-node-sub { font-size: 0.68rem; color: var(--muted); }

.path-dialog {
  border: 1px solid var(--border); border-radius: 14px; background: var(--bg-elev); color: var(--fg);
  max-width: 460px; width: calc(100% - 2rem); padding: 0;
}
.path-dialog::backdrop { background: rgba(4, 8, 16, 0.62); }
.path-dialog-form { padding: 1.2rem 1.3rem; margin: 0; }
.path-dialog-title { margin: 0 0 0.5rem; font-size: 1.15rem; }
.path-dialog-detail { margin: 0 0 1rem; color: var(--muted); }
.path-dialog-menu { margin: 0; padding: 0; display: flex; justify-content: flex-end; }

@keyframes pathDraw { to { stroke-dashoffset: 0; } }
@media (prefers-reduced-motion: reduce) {
  .path-link-line { animation: none; stroke-dashoffset: 0; }
  .path-node { transition: none; }
  .path-node:hover, .path-node:focus-visible { transform: none; }
}

/* ---- Admin catalogue (professor picker P27 + lifecycle P23/P26) --------- */
.admin-cat-prog code { display: inline-block; margin-top: 0.2rem; }
.admin-cat-actions { margin: 0.6rem 0 0; }
.admin-cat-form { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; margin: 0; }
.admin-cat-form input[type="text"],
.admin-cat-form select { flex: 1 1 220px; min-width: 180px; padding: 0.4rem 0.6rem;
  border: 1px solid var(--border); border-radius: 8px; background: var(--bg); color: var(--fg); font: inherit; }
.admin-cat-eff { color: var(--muted); font-size: 0.8rem; }
.admin-cat-lifecycle-actions { display: flex; gap: 0.5rem; flex-wrap: wrap; }
.admin-cat-inline-form { display: inline-flex; margin: 0; }
.admin-cat-sync .badge { white-space: nowrap; }
.admin-cat-onboardable { margin-top: 1.6rem; }
.admin-cat-onboardable-list { list-style: none; margin: 0.6rem 0 0; padding: 0;
  display: flex; flex-direction: column; gap: 0.5rem; }
.admin-cat-onboardable-list li { display: flex; align-items: center; justify-content: space-between;
  gap: 0.8rem; border: 1px solid var(--border); border-radius: 8px; padding: 0.5rem 0.8rem;
  background: var(--bg-elev); }

/* ── Email signature generator (P7) ─────────────────────────────────────── */
.emailsig-preview {
  margin: 0.8rem 0 1rem;
  padding: 1rem;
  border: 1px solid var(--border);
  border-radius: 0.6rem;
  background: #fff;
  overflow-x: auto;
}
.emailsig-source {
  width: 100%;
  font-family: 'Courier New', monospace;
  font-size: 0.78rem;
  resize: vertical;
  padding: 0.6rem;
  border: 1px solid var(--border);
  border-radius: 0.5rem;
  background: var(--bg-elev);
  color: var(--fg);
}

/* ── State-page illustrations (P9: 404 / suspended / request-pending) ────
   A single, generously-sized illustration above the existing card copy —
   theme-neutral (the source art already reads on light or dark chrome), with
   a soft rounded frame so it doesn't collide with the hard page edges. */
.state-hero {
  display: block;
  width: 100%;
  max-width: 480px;
  height: auto;
  margin: 0 auto 1.2rem;
  border-radius: 0.9rem;
  box-shadow: 0 10px 30px rgba(0,0,0,0.35);
}

/* ── Splash / hero banners (P9: login bootsplash page, loading, About) ──── */
.splash-hero {
  display: block;
  width: 100%;
  max-height: 260px;
  object-fit: cover;
  border-radius: 0.9rem;
  margin: 0 0 1.4rem;
  box-shadow: 0 10px 30px rgba(0,0,0,0.35);
}

/* Full-bleed banner (login): break the hero out of the 1080px main.container so
   the Cortex University banner spans the entire page width. Scoped to
   .hero-fullbleed so other .hero/.splash-hero uses are untouched. The 100vw
   container + 100%-width image (not a second 100vw) avoids scrollbar overflow. */
.hero-fullbleed {
  width: 100vw;
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
  padding-top: 0;
  padding-left: 0;
  padding-right: 0;
}
.hero-fullbleed .splash-hero {
  width: 100%;
  max-width: none;
  max-height: 340px;
  border-radius: 0;
  margin: 0 0 var(--space-lg);
  box-shadow: 0 14px 36px rgba(0,0,0,0.42);
}

/* ── Welcome splash backdrop (P9): the once-per-session boot-splash gains a
   full-bleed Welcome_* / Welcome_public_boot backdrop behind the existing
   crest-draw animation, selected server-side by role/program (or the public
   boot art when signed out). Low-opacity + dark scrim keeps the gold crest
   and wordmark legible over any source photo. */
.boot-splash-art {
  position: absolute;
  inset: 0;
  z-index: 0;
  background-size: cover;
  background-position: center;
  opacity: 0.34;
  filter: saturate(0.85);
}
.boot-splash-scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(160deg, var(--boot-navy) 0%, color-mix(in srgb, var(--boot-navy-2) 78%, transparent) 100%);
}
.boot-splash-inner { position: relative; z-index: 2; }

/* One background-image class per welcome_splash_key() value — kept as CSS
   classes (never an inline style) so the boot-splash element stays free of
   inline style attributes. */
.boot-splash-art.wa-student          { background-image: url('/static/emblems/welcome/student.webp'); }
.boot-splash-art.wa-professor        { background-image: url('/static/emblems/welcome/professor.webp'); }
.boot-splash-art.wa-admin            { background-image: url('/static/emblems/welcome/admin.webp'); }
.boot-splash-art.wa-ceo              { background-image: url('/static/emblems/welcome/ceo.webp'); }
.boot-splash-art.wa-hacker           { background-image: url('/static/emblems/welcome/hacker.webp'); }
.boot-splash-art.wa-cryptographer    { background-image: url('/static/emblems/welcome/cryptographer.webp'); }
.boot-splash-art.wa-security-defense { background-image: url('/static/emblems/welcome/security-defense.webp'); }
.boot-splash-art.wa-other-programs   { background-image: url('/static/emblems/welcome/other-programs.webp'); }
.boot-splash-art.wa-public-boot      { background-image: url('/static/emblems/welcome/public-boot.webp'); }

@media (prefers-reduced-motion: reduce) {
  .state-hero, .splash-hero { box-shadow: none; }
}

/* ── Country flag chips (profile residence/citizenship pickers, §2.7) ── */
.flag-field { display: flex; align-items: center; gap: 8px; }
.flag-field select { flex: 1 1 auto; min-width: 0; }
.flag-chip {
  width: 28px;
  height: 21px;
  border-radius: 3px;
  box-shadow: 0 0 0 1px var(--border, rgba(127, 127, 127, 0.35));
  flex: 0 0 auto;
}

/* ── Founder page (/founder) — flagship public biography ─────────────────────
   Scholarly, non-gamified register: left-aligned prose, gold institutional
   inks, year-columned timelines, and archival photos. Every in-flow photo
   sits in an IDENTICAL 4:3 mat frame (object-fit: contain — never cropped,
   never stretched; portraits letterbox on the mat, which reads intentional);
   the hero portrait keeps the same mat language in a 3:4 portrait frame.
   Theme-aware via the shared tokens; gold accents match the About page
   (#c9a23a / #b8860b, dark lift #e0b341). */
.founder {
  max-width: 880px;
  margin: 0 auto;
  padding: var(--space-lg) var(--space) var(--space-xl);
}

/* Hero — portrait beside the identity block; stacks and centers when narrow. */
.founder-hero {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--space-lg);
  margin-bottom: var(--space-lg);
}
.founder-hero-id { flex: 1 1 340px; min-width: 260px; }
.founder-eyebrow {
  margin: 0 0 0.4rem;
  font-size: 0.78rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: #b8860b;
  font-weight: 700;
}
.founder-name {
  margin: 0 0 0.3rem;
  font-family: var(--font-display);
  font-size: 2.6rem;
  line-height: 1.1;
  letter-spacing: -0.01em;
  background: linear-gradient(135deg, var(--fg), #c9a23a);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.founder-role { margin: 0; font-size: 0.95rem; color: var(--muted); }
.founder-divider {
  width: 64px;
  height: 2px;
  margin: var(--space) 0;
  border-radius: 2px;
  background: linear-gradient(90deg, #c9a23a, transparent);
}
.founder-tagline {
  margin: 0;
  font-size: 1.12rem;
  line-height: 1.6;
  max-width: 46ch;
  color: var(--fg);
}

/* Sections — small-caps gold title with a fading hairline. */
.founder-section { margin-top: var(--space-xl); }
.founder-section-title {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  margin: 0 0 var(--space-md);
  font-size: 0.8rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: #b8860b;
  font-weight: 700;
}
.founder-section-title::after {
  content: "";
  flex: 1;
  height: 1px;
  background: linear-gradient(90deg, color-mix(in srgb, #c9a23a 45%, transparent), transparent);
}
:root[data-theme="dark"] .founder-eyebrow,
:root[data-theme="dark"] .founder-section-title,
:root[data-theme="dark"] .founder-year { color: #e0b341; }

/* Prose */
.founder-prose p {
  margin: 0 0 var(--space);
  max-width: 68ch;
  line-height: 1.7;
  color: var(--fg);
}
.founder-prose p:last-child { margin-bottom: 0; }
.founder-note {
  border-left: 2px solid #c9a23a;
  padding-left: var(--space);
  color: var(--muted);
  font-size: 0.95rem;
}

/* Timelines — tabular-nums year column + dotted-spine entries. */
.founder-timeline { list-style: none; margin: 0; padding: 0; }
.founder-timeline > li {
  display: grid;
  grid-template-columns: 6.8rem 1fr;
  gap: var(--space);
}
.founder-year {
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  font-size: 0.9rem;
  color: #b8860b;
  text-align: right;
  white-space: nowrap;
  padding-top: 0.15rem;
}
.founder-entry {
  position: relative;
  padding: 0 0 var(--space-md) var(--space-md);
  border-left: 1px solid var(--border);
}
.founder-timeline > li:last-child .founder-entry { padding-bottom: 0; }
.founder-entry::before {
  content: "";
  position: absolute;
  left: -5px;
  top: 0.35rem;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: #c9a23a;
  box-shadow: 0 0 0 3px color-mix(in srgb, #c9a23a 25%, transparent);
}
.founder-entry h4 { margin: 0 0 0.3rem; font-size: 1.02rem; line-height: 1.35; }
.founder-entry p {
  margin: 0 0 0.5rem;
  max-width: 62ch;
  font-size: 0.95rem;
  line-height: 1.65;
  color: var(--muted);
}
.founder-entry ul {
  margin: 0.3rem 0 0.5rem;
  padding-left: 1.1rem;
  max-width: 62ch;
  font-size: 0.92rem;
  line-height: 1.65;
  color: var(--muted);
}
.founder-entry ul li { margin-bottom: 0.35rem; }

/* Photo mats — the uniform frame. Fixed 4:3 aspect at a shared max width, so
   every framed photo on the page is the same size; object-fit: contain keeps
   the full image visible (no crop, no stretch) centered on a subtle mat. */
.founder-photos {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space);
  margin: var(--space-sm) 0 0;
}
.founder-photo {
  margin: 0;
  flex: 0 1 340px;
  width: 100%;
  max-width: 340px;
  min-width: 0;
}
.founder-photo-frame {
  display: block;
  aspect-ratio: 4 / 3;
  padding: 6px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background:
    linear-gradient(180deg,
      color-mix(in srgb, var(--fg) 6%, var(--bg-elev)),
      color-mix(in srgb, var(--fg) 3%, var(--bg-elev)));
  box-shadow: var(--shadow-sm);
}
.founder-photo-frame img {
  display: block;
  width: 100%;
  height: 100%;
  max-width: 100%;
  object-fit: contain;
  border-radius: calc(var(--radius-lg) - 4px);
}
.founder-photo figcaption {
  margin-top: 0.5rem;
  font-size: 0.8rem;
  line-height: 1.45;
  color: var(--muted);
}
/* Hero portrait — same mat language, portrait orientation. */
.founder-hero-photo { flex: 0 1 300px; max-width: 300px; }
.founder-hero-photo .founder-photo-frame { aspect-ratio: 3 / 4; }
.founder-hero-photo figcaption { text-align: center; }

/* Education / research-and-craft cards — the About pillar language. */
.founder-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: var(--space);
}
.founder-card {
  border: 1px solid var(--border);
  border-top: 2px solid #c9a23a;
  border-radius: var(--radius-lg);
  background: var(--bg-elev);
  padding: var(--space) var(--space-md);
  box-shadow: var(--shadow-sm);
}
.founder-card h4 { margin: 0 0 0.3rem; font-size: 1rem; }
.founder-card-where {
  margin: 0 0 0.5rem;
  font-size: 0.85rem;
  font-weight: 600;
  color: #b8860b;
}
:root[data-theme="dark"] .founder-card-where { color: #e0b341; }
.founder-card p { margin: 0 0 0.4rem; font-size: 0.92rem; line-height: 1.6; color: var(--muted); }
.founder-card ul {
  margin: 0.3rem 0 0;
  padding-left: 1.1rem;
  font-size: 0.92rem;
  line-height: 1.6;
  color: var(--muted);
}
.founder-card ul li { margin-bottom: 0.4rem; }
.founder-backlink { margin: var(--space-lg) 0 0; font-size: 0.9rem; }

/* Narrow viewports — the year column folds above its entry; the hero centers.
   Flex-wrapped mats already shrink to 100%; the body never h-scrolls. */
@media (max-width: 40rem) {
  .founder-name { font-size: 2rem; }
  .founder-hero { text-align: center; }
  .founder-hero-id { min-width: 100%; }
  .founder-divider { margin-left: auto; margin-right: auto; }
  .founder-tagline { margin: 0 auto; }
  .founder-timeline > li { grid-template-columns: 1fr; gap: 0.2rem; }
  .founder-year { text-align: left; padding-top: 0; }
  .founder-photo { flex-basis: 100%; max-width: 340px; }
}

/* About → Founder cross-link (centered page register). */
.about-founder-link { margin: var(--space-md) 0 0; font-size: 0.92rem; }

/* ════════════════════════════════════════════════════════════════════════
   HUD LOGIN (confidential design) — a sealed, "hermetic" dark-navy HUD login
   that reveals after the boot splash. Self-contained fixed dark scheme,
   deliberately independent of the light/dark data-theme toggle: a locked
   confidential screen must look identical regardless of viewer preference.
   Only the page BODY is themed here; base.html nav + footer are untouched.
   All colours are local (auth-scoped custom props) so no global token leaks.
   ════════════════════════════════════════════════════════════════════════ */
.auth-screen {
  /* Full-bleed navy that escapes the 1080px main.container. The 100vw box +
     100%-width children avoid the horizontal-scrollbar overflow trap. */
  --auth-navy: #01040b;
  --auth-navy-2: #061224;
  --auth-blue: #2f6fb0;
  --auth-blue-bright: #59b7ff;
  --auth-blue-glow: rgba(80, 180, 255, 0.55);
  --auth-silver: #cdd6e2;
  --auth-fg: #dbe6f2;
  --auth-muted: #7f93ad;

  width: 100vw;
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
  margin-top: calc(-1 * var(--space-lg, 1.5rem));
  padding: clamp(1rem, 4vw, 3rem) 1rem clamp(2rem, 6vw, 4rem);
  min-height: calc(100vh - 220px);
  display: flex;
  justify-content: center;
  align-items: flex-start;
  background:
    radial-gradient(120% 90% at 50% 22%, var(--auth-navy-2) 0%, var(--auth-navy) 62%, #000208 100%);
  color: var(--auth-fg);
  font-family: var(--font-sans, system-ui, sans-serif);
}

.auth-hud {
  width: 100%;
  max-width: 560px;
  display: flex;
  flex-direction: column;
  align-items: center;
}

/* ══ THE VAULT ══ a layered, robotic bank-vault / spaceship-airlock mechanism
   (inline SVG + CSS transforms only — no libs). The silver Cortex "C" emblem is
   the FIXED ANCHOR: it never moves or fades in any state; the machinery unlocks
   AROUND it. Every transition is a GPU-friendly transform/opacity change keyed
   off .auth-screen[data-auth-state]; portal.js enforces ≥3s per state so the
   choreography is always seen regardless of server latency. Precise, mechanical
   easing (no soft/organic curves). Depth is faked with stacked transform planes
   + pointer parallax (--px/--py, set by portal.js). */
.auth-vault {
  position: relative;
  width: clamp(240px, 62vw, 400px);
  aspect-ratio: 1 / 1;
  margin: 0 auto clamp(1rem, 3vw, 2rem);
  line-height: 0;
  isolation: isolate;
  --px: 0; --py: 0;                 /* pointer parallax offset (−1..1) */
  perspective: 900px;
}
.vault-svg { position: relative; z-index: 2; display: block; width: 100%; height: 100%; overflow: visible; }

/* Explicit transform box for every animated SVG part (SVG needs it). */
.vault-plane, .vault-wheel, .vault-bolts, .vault-rivets, .vault-ticks,
.vault-rim, .vault-rim-glow, .vault-scan, .vault-hex, .vault-progress,
.vault-deadbolts, .vault-core, .blade, .bolt, .deadbolt, .hex {
  transform-origin: 220px 220px;
  transform-box: view-box;
}
.blade { transition: transform 0.55s cubic-bezier(.3,0,.15,1), opacity 0.5s ease; }
.bolt  { transition: transform 0.35s cubic-bezier(.16,.8,.3,1); }

/* Parallax planes — each drifts a different amount for a layered-depth read. */
.vault-depth  { transform: translate(calc(var(--px) * 5px),  calc(var(--py) * 5px)); }
.vault-aperture { transform: translate(calc(var(--px) * 9px), calc(var(--py) * 9px)); }
.vault-frame  { transform: translate(calc(var(--px) * 3px),  calc(var(--py) * 3px)); }
.vault-wheel  { transform: translate(calc(var(--px) * 13px), calc(var(--py) * 13px)); }

/* Emblem "C" — the fixed anchor. Circular-masked, always on top of the aperture. */
.vault-emblem {
  position: absolute;
  z-index: 4;
  top: 50%; left: 50%;
  width: 35%; height: 35%;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  object-fit: cover;
  -webkit-mask-image: radial-gradient(circle at 50% 50%, #000 60%, transparent 76%);
          mask-image: radial-gradient(circle at 50% 50%, #000 60%, transparent 76%);
  filter: drop-shadow(0 0 7px rgba(80, 180, 255, 0.4));
  animation: vault-breathe 5s ease-in-out infinite;
}

/* Full-vault colour flash overlay (core pulse / klaxon / lockdown). */
.vault-flash {
  position: absolute; inset: 0; z-index: 3;
  border-radius: 50%;
  opacity: 0; pointer-events: none;
  mix-blend-mode: screen;
}

/* Terminal deadbolt seal stamp — slams over centre on LOCKED. */
.vault-seal {
  position: absolute; z-index: 5;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%) scale(2.4);
  color: #05070c; opacity: 0;
  filter: drop-shadow(0 0 3px rgba(0,0,0,0.9));
  pointer-events: none;
}

/* Blade/steel default fill (paths carry no inline fill). */
.blade { fill: url(#vaultFace); stroke: #223244; stroke-width: 1; }
.bolt  { }
.vault-core { opacity: 0; }
.vault-scan, .vault-hex { opacity: 0; }
.vault-progress { opacity: 0; stroke-dasharray: 100; stroke-dashoffset: 100; }
.deadbolt { transform: translateY(-64px); opacity: 0; }

/* ── IDLE: sealed, calm — slow structural drift + breathing glow/emblem. ── */
.vault-rivets { animation: vault-spin-slow 80s linear infinite; }
.vault-ticks  { animation: vault-spin-slow 120s linear infinite reverse; }
.vault-rim-glow {
  stroke: #2f6fb0;
  filter: drop-shadow(0 0 4px rgba(47,111,176,0.6));
  animation: vault-breathe 5s ease-in-out infinite;
}
@keyframes vault-spin-slow { to { transform: rotate(360deg); } }
@keyframes vault-breathe { 0%,100% { opacity: 0.62; } 50% { opacity: 1; } }

/* ── VERIFYING: security theatre — wheel spins, ticks race, blades illuminate
   in sequence, scan beam sweeps, hex/data streams cascade, gauge fills. ── */
.auth-screen[data-auth-state="verifying"] .vault-wheel { animation: vault-spin-fast 1.05s linear infinite; }
.auth-screen[data-auth-state="verifying"] .vault-ticks { animation: vault-spin-fast 2.2s linear infinite reverse; }
.auth-screen[data-auth-state="verifying"] .vault-rivets { animation: vault-spin-fast 6s steps(24) infinite; }
.auth-screen[data-auth-state="verifying"] .vault-rim-glow { stroke: #e0c43a; filter: drop-shadow(0 0 8px rgba(224,196,58,0.75)); }
.auth-screen[data-auth-state="verifying"] .vault-scan { opacity: 1; }
.auth-screen[data-auth-state="verifying"] .vault-scan rect { animation: vault-scan 1.5s cubic-bezier(.5,0,.5,1) infinite; }
.auth-screen[data-auth-state="verifying"] .vault-hex { opacity: 1; }
.auth-screen[data-auth-state="verifying"] .vault-hex .hex { animation: vault-hex-fall 1.4s linear infinite; }
.auth-screen[data-auth-state="verifying"] .vault-progress { opacity: 1; animation: vault-gauge-fill 2.8s cubic-bezier(.4,0,.2,1) forwards; }
.auth-screen[data-auth-state="verifying"] .blade { animation: vault-seg-scan 1.6s linear infinite; }
/* stagger blade illumination in sequence around the ring */
.auth-screen[data-auth-state="verifying"] .blade-0 { animation-delay: 0ms; }
.auth-screen[data-auth-state="verifying"] .blade-1 { animation-delay: 200ms; }
.auth-screen[data-auth-state="verifying"] .blade-2 { animation-delay: 400ms; }
.auth-screen[data-auth-state="verifying"] .blade-3 { animation-delay: 600ms; }
.auth-screen[data-auth-state="verifying"] .blade-4 { animation-delay: 800ms; }
.auth-screen[data-auth-state="verifying"] .blade-5 { animation-delay: 1000ms; }
.auth-screen[data-auth-state="verifying"] .blade-6 { animation-delay: 1200ms; }
.auth-screen[data-auth-state="verifying"] .blade-7 { animation-delay: 1400ms; }
.vault-hex .hex-0{--hd:0ms}.vault-hex .hex-1{--hd:120ms}.vault-hex .hex-2{--hd:240ms}
.vault-hex .hex-3{--hd:360ms}.vault-hex .hex-4{--hd:80ms}.vault-hex .hex-5{--hd:300ms}
.vault-hex .hex-6{--hd:180ms}.vault-hex .hex-7{--hd:420ms}.vault-hex .hex-8{--hd:60ms}
.vault-hex .hex-9{--hd:340ms}.vault-hex .hex-10{--hd:220ms}.vault-hex .hex-11{--hd:400ms}
.auth-screen[data-auth-state="verifying"] .vault-hex .hex { animation-delay: var(--hd); }
@keyframes vault-spin-fast { to { transform: rotate(360deg); } }
@keyframes vault-scan {
  0% { opacity: 0; transform: translateY(-160px); }
  15%,85% { opacity: 0.8; }
  100% { opacity: 0; transform: translateY(160px); }
}
@keyframes vault-hex-fall {
  0% { opacity: 0; transform: translateY(0); }
  20% { opacity: 0.9; }
  100% { opacity: 0; transform: translateY(300px); }
}
@keyframes vault-gauge-fill { to { stroke-dashoffset: 0; } }
@keyframes vault-seg-scan {
  0%, 100% { stroke: #223244; filter: none; }
  8% { stroke: #59b7ff; filter: drop-shadow(0 0 6px rgba(89,183,255,0.9)); }
}

/* ── GRANTED: robotic airlock unlock AROUND the fixed C. Servo bolts retract →
   rings snap to lock → blades iris open → core pulse → wipe. The C stays put. ── */
.auth-screen[data-auth-state="granted"] .vault-rim-glow { stroke: #3fb950; filter: drop-shadow(0 0 12px rgba(63,185,80,0.95)); }
.auth-screen[data-auth-state="granted"] .vault-progress { opacity: 1; stroke: #3fb950; stroke-dashoffset: 0; }
/* 1. bolts retract inward, hard staggered servo (transitions on .bolt). */
.auth-screen[data-auth-state="granted"] .bolt-0 { transform: translateY(40px); transition-delay: 0ms; }
.auth-screen[data-auth-state="granted"] .bolt-1 { transform: translateY(40px); transition-delay: 60ms; }
.auth-screen[data-auth-state="granted"] .bolt-2 { transform: translateY(40px); transition-delay: 120ms; }
.auth-screen[data-auth-state="granted"] .bolt-3 { transform: translateY(40px); transition-delay: 180ms; }
.auth-screen[data-auth-state="granted"] .bolt-4 { transform: translateY(40px); transition-delay: 240ms; }
.auth-screen[data-auth-state="granted"] .bolt-5 { transform: translateY(40px); transition-delay: 300ms; }
.auth-screen[data-auth-state="granted"] .bolt-6 { transform: translateY(40px); transition-delay: 360ms; }
.auth-screen[data-auth-state="granted"] .bolt-7 { transform: translateY(40px); transition-delay: 420ms; }
/* 2. rings counter-rotate and CLICK into aligned lock positions (stepped). */
.auth-screen[data-auth-state="granted"] .vault-ticks  { animation: vault-lock-cw  0.7s steps(6) 0.35s forwards; }
.auth-screen[data-auth-state="granted"] .vault-rivets { animation: vault-lock-ccw 0.7s steps(4) 0.35s forwards; }
.auth-screen[data-auth-state="granted"] .vault-wheel  { animation: vault-wheel-snap 0.6s cubic-bezier(.2,.9,.1,1) 0.35s forwards; }
/* 3. blades iris open — retract radially outward, staggered (transforms below). */
.auth-screen[data-auth-state="granted"] .blade { transition: transform 0.6s cubic-bezier(.5,0,.1,1), opacity 0.5s ease; }
.auth-screen[data-auth-state="granted"] .blade-0{transform:translate(72.1px,29.8px);transition-delay:900ms;opacity:0;}
.auth-screen[data-auth-state="granted"] .blade-1{transform:translate(29.8px,72.1px);transition-delay:955ms;opacity:0;}
.auth-screen[data-auth-state="granted"] .blade-2{transform:translate(-29.8px,72.1px);transition-delay:1010ms;opacity:0;}
.auth-screen[data-auth-state="granted"] .blade-3{transform:translate(-72.1px,29.8px);transition-delay:1065ms;opacity:0;}
.auth-screen[data-auth-state="granted"] .blade-4{transform:translate(-72.1px,-29.8px);transition-delay:1120ms;opacity:0;}
.auth-screen[data-auth-state="granted"] .blade-5{transform:translate(-29.8px,-72.1px);transition-delay:1175ms;opacity:0;}
.auth-screen[data-auth-state="granted"] .blade-6{transform:translate(29.8px,-72.1px);transition-delay:1230ms;opacity:0;}
.auth-screen[data-auth-state="granted"] .blade-7{transform:translate(72.1px,-29.8px);transition-delay:1285ms;opacity:0;}
/* 4. depth well + core light revealed through the open aperture, then wipe. */
.auth-screen[data-auth-state="granted"] .vault-core { animation: vault-core-pulse 1.9s ease-in 1.2s forwards; }
.auth-screen[data-auth-state="granted"] .vault-flash {
  background: radial-gradient(circle, #eaf6ff 0%, #3fb950 45%, rgba(20,60,110,0) 72%);
  animation: vault-wipe 1.5s ease-in 1.9s forwards;
}
@keyframes vault-wheel-snap {
  0% { transform: rotate(0); } 60% { transform: rotate(46deg); } 100% { transform: rotate(45deg); }
}
@keyframes vault-lock-cw  { to { transform: rotate(30deg); } }
@keyframes vault-lock-ccw { to { transform: rotate(-30deg); } }
@keyframes vault-core-pulse {
  0% { opacity: 0; transform: scale(0.55); }
  40% { opacity: 0.85; }
  100% { opacity: 0.95; transform: scale(1.15); }
}
@keyframes vault-wipe {
  0% { opacity: 0; transform: scale(0.4); }
  30% { opacity: 1; }
  100% { opacity: 1; transform: scale(6); }
}

/* ── DENIED: red lockdown klaxon flash, mechanism recoils + SLAMS, glitch burst.
   The C holds. Then portal.js runs the 5s SECURITY HOLD countdown. ── */
.auth-screen[data-auth-state="denied"] .vault-svg { animation: vault-shudder 0.4s cubic-bezier(.36,.07,.19,.97) 3; }
.auth-screen[data-auth-state="denied"] .vault-wheel { animation: vault-recoil 0.55s cubic-bezier(.2,.9,.1,1); }
.auth-screen[data-auth-state="denied"] .bolt { transform: translateY(-6px); transition: transform 0.12s steps(2); }
.auth-screen[data-auth-state="denied"] .vault-rim-glow { stroke: #f85149; filter: drop-shadow(0 0 16px rgba(248,81,73,0.95)); animation: vault-red-flash 0.45s steps(2) 4; }
.auth-screen[data-auth-state="denied"] .vault-flash {
  background: radial-gradient(circle, rgba(255,60,50,0.85) 0%, rgba(180,10,10,0.2) 60%, transparent 75%);
  animation: vault-klaxon 0.5s steps(2) 4;
}
.auth-screen[data-auth-state="denied"] .blade { animation: vault-glitch 0.24s steps(2) 5; }
@keyframes vault-shudder {
  0%,100% { transform: translate(0,0); }
  20% { transform: translate(-9px,2px) rotate(-1.2deg); }
  60% { transform: translate(9px,-2px) rotate(1.2deg); }
  80% { transform: translate(-4px,1px); }
}
@keyframes vault-recoil { 0% { transform: rotate(0); } 35% { transform: rotate(-26deg); } 100% { transform: rotate(-4deg); } }
@keyframes vault-red-flash { 0%,100% { opacity: 0.45; } 50% { opacity: 1; } }
@keyframes vault-klaxon { 0%,100% { opacity: 0; } 50% { opacity: 1; } }
@keyframes vault-glitch {
  0% { transform: translate(0,0); } 50% { transform: translate(3px,-2px); } 100% { transform: translate(-2px,1px); }
}

/* ── LOCKED (most severe): heavy deadbolts DROP into the frame, mechanism seals,
   cold desaturated lockdown + red→black vignette. Terminal. The C holds. ── */
.auth-screen[data-auth-state="locked"] .vault-svg { filter: grayscale(0.9) brightness(0.5) contrast(1.05); transition: filter 0.6s ease; }
.auth-screen[data-auth-state="locked"] .vault-emblem { filter: grayscale(0.92) brightness(0.55); }
.auth-screen[data-auth-state="locked"] .deadbolt { transform: translateY(0); opacity: 1; transition: transform 0.32s cubic-bezier(.7,0,.85,.6), opacity 0.15s ease; }
.auth-screen[data-auth-state="locked"] .deadbolt-0 { transition-delay: 0ms; }
.auth-screen[data-auth-state="locked"] .deadbolt-1 { transition-delay: 130ms; }
.auth-screen[data-auth-state="locked"] .deadbolt-2 { transition-delay: 260ms; }
.auth-screen[data-auth-state="locked"] .deadbolt-3 { transition-delay: 390ms; }
.auth-screen[data-auth-state="locked"] .vault-seal { animation: vault-seal-slam 0.5s cubic-bezier(.2,.8,.2,1.2) 0.5s forwards; }
.auth-screen[data-auth-state="locked"]::after {
  content: "";
  position: absolute; inset: 0; z-index: 6; pointer-events: none;
  background: radial-gradient(120% 90% at 50% 40%, transparent 38%, rgba(120,10,10,0.28) 70%, rgba(0,0,0,0.9) 100%);
  animation: vault-fade-in 0.8s ease forwards;
}
@keyframes vault-seal-slam {
  0% { opacity: 0; transform: translate(-50%,-50%) scale(2.8) rotate(-8deg); }
  70% { opacity: 1; transform: translate(-50%,-50%) scale(0.88) rotate(2deg); }
  100% { opacity: 1; transform: translate(-50%,-50%) scale(1) rotate(0); }
}
@keyframes vault-fade-in { from { opacity: 0; } to { opacity: 1; } }

/* Always-on faint CRT scanline shimmer over the whole confidential screen. */
.auth-screen::before {
  content: "";
  position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background: repeating-linear-gradient(0deg, rgba(89,183,255,0.035) 0 1px, transparent 1px 3px);
  mix-blend-mode: screen;
  animation: vault-crt 8s linear infinite;
  opacity: 0.5;
}
@keyframes vault-crt { to { background-position: 0 120px; } }

/* ── Readout: neon state text, one colour per state. ── */
.auth-readout {
  min-height: 1.4em;
  margin: 0 0 clamp(0.6rem, 2vw, 1.2rem);
  text-align: center;
  font-size: clamp(0.95rem, 2.6vw, 1.25rem);
  font-weight: 700;
  letter-spacing: 0.34em;
  text-transform: uppercase;
  opacity: 0;
  transition: opacity 0.35s ease, color 0.35s ease;
}
.auth-screen[data-auth-state] .auth-readout { opacity: 0; }
.auth-screen[data-auth-state="verifying"] .auth-readout {
  opacity: 1; color: #e0c43a;
  text-shadow: 0 0 8px rgba(224,196,58,0.8), 0 0 20px rgba(224,196,58,0.5);
  animation: auth-readout-pulse 1.2s ease-in-out infinite;
}
.auth-screen[data-auth-state="granted"] .auth-readout {
  opacity: 1; color: #4be07a;
  text-shadow: 0 0 8px rgba(63,185,80,0.9), 0 0 22px rgba(63,185,80,0.6);
}
.auth-screen[data-auth-state="denied"] .auth-readout {
  opacity: 1; color: #ff5a52;
  text-shadow: 0 0 8px rgba(248,81,73,0.9), 0 0 22px rgba(248,81,73,0.6);
}
.auth-screen[data-auth-state="hold"] .auth-readout {
  opacity: 1; color: #ff5a52;
  text-shadow: 0 0 6px rgba(248,81,73,0.7);
}
.auth-screen[data-auth-state="error"] .auth-readout {
  opacity: 1; color: #e0a63a;
  text-shadow: 0 0 8px rgba(224,166,58,0.7);
}
.auth-screen[data-auth-state="locked"] .auth-readout {
  opacity: 1;
  color: #05070c;
  font-weight: 900;
  letter-spacing: 0.42em;
  /* "Imperial" heavy black lettering — a hard, embossed stamp, no neon glow. */
  text-shadow: 0 1px 0 #3a3f47, 0 -1px 0 #000, 1px 0 0 #2a2e35, 0 0 2px rgba(0,0,0,0.9);
  position: relative;
  z-index: 6;
}
@keyframes auth-readout-pulse { 0%,100% { opacity: 0.75; } 50% { opacity: 1; } }

/* ── Form ── */
.auth-form {
  width: 100%;
  max-width: 460px;
  display: flex;
  flex-direction: column;
  gap: clamp(0.8rem, 2.4vw, 1.15rem);
}
.auth-form-wide { max-width: 500px; }

.auth-field { display: flex; flex-direction: column; gap: 0.4rem; }

.auth-label {
  font-size: 0.82rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--auth-muted);
  font-weight: 600;
  padding: 0;
}

.auth-input-shell {
  position: relative;
  display: flex;
  align-items: center;
  border: 1px solid rgba(89, 155, 210, 0.45);
  border-radius: 4px;
  background: rgba(6, 18, 36, 0.55);
  box-shadow: inset 0 0 18px rgba(20, 60, 110, 0.25);
  transition: border-color 0.18s ease, box-shadow 0.18s ease;
}
.auth-input-shell:focus-within {
  border-color: var(--auth-blue-bright);
  box-shadow: inset 0 0 18px rgba(20, 60, 110, 0.35),
              0 0 0 1px var(--auth-blue-bright),
              0 0 16px var(--auth-blue-glow);
}

.auth-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--auth-silver);
  flex: 0 0 auto;
}
.auth-icon-left  { padding: 0 0.55rem 0 0.7rem; }
.auth-icon-right { padding: 0 0.7rem 0 0.55rem; color: var(--auth-blue); }
.auth-hex { opacity: 0.85; }

.auth-input {
  flex: 1 1 auto;
  min-width: 0;
  width: 100%;
  border: 0;
  outline: 0;
  background: transparent;
  color: var(--auth-fg);
  font-size: 1rem;
  letter-spacing: 0.04em;
  padding: 0.78rem 0.4rem;
  font-family: inherit;
}
.auth-input::placeholder { color: rgba(127, 147, 173, 0.7); }
/* selects share the shell; give the arrow room */
select.auth-input { padding-right: 0.7rem; cursor: pointer; appearance: none; }
select.auth-input option { background: var(--auth-navy-2); color: var(--auth-fg); }
/* When a field has no left icon (selects/email), keep text off the border. */
.auth-input-shell > .auth-input:first-child { padding-left: 0.85rem; }

/* Autofill: keep the navy shell, override the browser's white box. */
.auth-input:-webkit-autofill,
.auth-input:-webkit-autofill:hover,
.auth-input:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--auth-fg);
  -webkit-box-shadow: 0 0 0 1000px rgba(6, 18, 36, 0.98) inset;
  caret-color: var(--auth-fg);
}

/* ── Wave-B mode radios ── */
.auth-fieldset { border: 0; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 0.5rem; }
.auth-modes { display: flex; flex-wrap: wrap; gap: 0.4rem 1rem; }
.auth-mode {
  display: inline-flex; align-items: center; gap: 0.4rem;
  font-size: 0.9rem; color: var(--auth-fg); cursor: pointer;
}
.auth-mode input { accent-color: var(--auth-blue-bright); }

/* ── Octagonal submit ── */
.auth-submit-row { display: flex; justify-content: center; margin-top: 0.4rem; }
.auth-submit {
  --oct: 12px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 118px;
  height: 54px;
  color: var(--auth-blue-bright);
  background: rgba(6, 18, 36, 0.5);
  border: 1px solid rgba(89, 155, 210, 0.6);
  /* octagon */
  clip-path: polygon(var(--oct) 0, calc(100% - var(--oct)) 0, 100% var(--oct),
                     100% calc(100% - var(--oct)), calc(100% - var(--oct)) 100%,
                     var(--oct) 100%, 0 calc(100% - var(--oct)), 0 var(--oct));
  cursor: pointer;
  transition: color 0.18s ease, box-shadow 0.18s ease, background 0.18s ease;
}
.auth-submit:hover,
.auth-submit:focus-visible {
  color: #fff;
  background: rgba(31, 90, 150, 0.35);
  box-shadow: 0 0 22px var(--auth-blue-glow);
}
.auth-submit svg { transition: transform 0.18s ease; }
.auth-submit:hover svg { transform: translateX(3px); }

/* ── Links + tagline ── */
.auth-links {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.4rem 1.4rem;
  margin-top: clamp(1.2rem, 3vw, 1.8rem);
}
.auth-links a {
  color: var(--auth-muted);
  text-decoration: none;
  font-size: 0.86rem;
  letter-spacing: 0.06em;
  border-bottom: 1px solid transparent;
  transition: color 0.15s ease, border-color 0.15s ease;
}
.auth-links a:hover,
.auth-links a:focus-visible {
  color: var(--auth-blue-bright);
  border-bottom-color: var(--auth-blue-bright);
}

.auth-tagline {
  margin-top: clamp(1.5rem, 5vw, 3rem);
  text-align: center;
  font-size: 0.78rem;
  letter-spacing: 0.34em;
  text-transform: uppercase;
  color: var(--auth-blue);
  opacity: 0.75;
}

/* Focus-visible on all interactive auth controls (a11y). */
.auth-screen a:focus-visible,
.auth-screen button:focus-visible,
.auth-screen input:focus-visible,
.auth-screen select:focus-visible {
  outline: 2px solid var(--auth-blue-bright);
  outline-offset: 2px;
}

/* Visually-hidden but screen-reader-available heading. */
.auth-visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0);
  white-space: nowrap; border: 0;
}

/* Disable the whole form while any animation runs (no double-submit). */
.auth-screen.auth-busy .auth-form { pointer-events: none; opacity: 0.55; }
.auth-screen.auth-busy .auth-submit { cursor: progress; }

/* Mobile: vault scales down, fields stack, no horizontal scroll. */
@media (max-width: 40rem) {
  .auth-screen { min-height: calc(100vh - 160px); padding-top: 1.5rem; }
  .auth-label { font-size: 0.76rem; letter-spacing: 0.16em; }
  .auth-tagline { letter-spacing: 0.22em; font-size: 0.7rem; }
  .auth-readout { letter-spacing: 0.2em; }
  .auth-modes { gap: 0.35rem 0.75rem; }
  .auth-vault { width: clamp(200px, 72vw, 320px); }
}

/* Reduced motion: keep every colour + text state + HUD readout, but replace all
   spin / iris / recoil / slam / parallax motion with fast static crossfades. No
   looping ambient motion, no rotation/scale/translate. The C anchor is fixed
   regardless. */
@media (prefers-reduced-motion: reduce) {
  /* Kill all ambient + per-state animations and parallax drift. */
  .vault-rivets, .vault-ticks, .vault-rim-glow, .vault-emblem, .vault-plane,
  .blade, .bolt, .deadbolt, .hex, .vault-core, .vault-flash, .vault-progress,
  .vault-scan rect, .vault-seal, .auth-readout,
  .auth-screen::before, .auth-screen::after,
  .auth-screen[data-auth-state] .vault-wheel,
  .auth-screen[data-auth-state] .vault-svg {
    animation: none !important;
    transition: opacity 0.35s ease !important;
    transform: none !important;
  }
  /* GRANTED: no iris — just reveal the core light + fade the aperture out. */
  .auth-screen[data-auth-state="granted"] .blade { opacity: 0; }
  .auth-screen[data-auth-state="granted"] .vault-core,
  .auth-screen[data-auth-state="granted"] .vault-flash { opacity: 0.9; }
  .auth-screen[data-auth-state="granted"] .vault-progress { opacity: 1; }
  /* VERIFYING: hold the beam + gauge visible (no sweep/fill motion). */
  .auth-screen[data-auth-state="verifying"] .vault-scan,
  .auth-screen[data-auth-state="verifying"] .vault-progress { opacity: 1; }
  .auth-screen[data-auth-state="verifying"] .vault-progress { stroke-dashoffset: 0; }
  /* LOCKED: deadbolts + seal shown in place, no drop/slam. */
  .auth-screen[data-auth-state="locked"] .deadbolt { opacity: 1; }
  .auth-screen[data-auth-state="locked"] .vault-seal { opacity: 1; transform: translate(-50%,-50%) scale(1) !important; }
  .auth-submit svg, .auth-submit:hover svg { transition: none; transform: none; }
}
