/* =====================================================================
   Code Blue Training — brand design system
   ---------------------------------------------------------------------
   Built from the official brand package: red #C10000 / blue #4478CC
   duality joined by the EKG pulse, navy #212738 chrome, #D8DBE2 cool
   neutrals, #426A5A green for success. Inter (variable, self-hosted)
   stands in for the brand's New Science until webfont files exist —
   swap the @font-face sources and the stack picks it up unchanged.
   ===================================================================== */

/* ---- Typeface ------------------------------------------------------- */
@font-face {
  font-family: 'InterVariable';
  src: url("../fonts/InterVariable.2bf3d951bf9d.woff2") format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'InterVariable';
  src: url("../fonts/InterVariable-Italic.8d1dc86da258.woff2") format('woff2');
  font-weight: 100 900;
  font-style: italic;
  font-display: swap;
}

/* ---- Tokens: light (default) --------------------------------------- */
:root {
  color-scheme: light;

  /* Brand blue #4478CC — the interactive accent */
  --blue-50:  #eef3fb;
  --blue-100: #dbe6f6;
  --blue-200: #b8cfee;
  --blue-300: #8fb2e3;
  --blue-400: #6595d8;
  --blue-500: #4478cc;
  --blue-600: #3562ab;
  --blue-700: #294d89;

  /* Brand red #C10000 — the signal color: the pulse, danger, urgency */
  --red-500: #c10000;
  --red-600: #9e0000;

  /* Brand navy #212738 — chrome (sidebar, dark surfaces) */
  --navy: #212738;

  --ink: #1a2030;

  /* Neutrals built around brand gray #D8DBE2 (= n200) and navy (= n800) */
  --n0:  #ffffff;
  --n25: #fbfcfd;
  --n50: #f4f6f9;
  --n100:#eaedf2;
  --n150:#e1e4eb;
  --n200:#d8dbe2;
  --n300:#b8becb;
  --n400:#929aab;
  --n500:#6a7383;
  --n600:#4b5364;
  --n700:#343b4c;
  --n800:#212738;

  /* Semantics — success is brand green #426A5A; danger is brand red */
  --ok:#426a5a;     --ok-bg:#e9f1ed;   --ok-border:#c3d7ce;
  --warn:#b5540a;   --warn-bg:#fbefe2; --warn-border:#f0d4b0;
  --crit:#c10000;   --crit-bg:#fbeaea; --crit-border:#f0c4c4;

  /* Semantic role tokens */
  --bg: var(--n50);
  --surface: var(--n0);
  --surface-2: var(--n25);
  --surface-sunken: var(--n100);
  --line: var(--n150);
  --line-strong: var(--n200);
  --text: var(--ink);
  --text-2: var(--n600);
  --text-muted: var(--n500);
  --accent: var(--blue-500);
  --accent-hover: var(--blue-600);
  --accent-ink: #ffffff;
  --accent-weak: var(--blue-50);
  --ring: rgba(68, 120, 204, 0.30);

  /* Sidebar chrome — brand navy in light theme; the dark theme swaps in
     deeper variants of the same hue (see the dark token blocks) so the
     rail still reads as chrome against dark content. */
  --side-bg: var(--navy);
  --side-surface: #2a3145;
  --side-line: rgba(255,255,255,.08);
  --side-text: #b9c0d0;
  --side-text-strong: #ffffff;
  --side-hover: rgba(255,255,255,.06);
  --side-active: rgba(68,120,204,.22);
  --side-w: 264px;

  /* Rotating container-border palette (cards, stats, course cards pick a
     hue by position; --edge defaults to the accent). */
  --edge: var(--accent);
  --edge-teal: #2f8f74;
  --edge-violet: #6a5ce0;
  --edge-rose: #c14a6b;

  --shadow-sm: 0 1px 2px rgba(26,32,48,.05), 0 1px 1px rgba(26,32,48,.04);
  --shadow-md: 0 6px 16px -8px rgba(26,32,48,.18), 0 2px 6px -4px rgba(26,32,48,.10);
  --shadow-lg: 0 24px 60px -28px rgba(26,32,48,.30);
  --shadow-xl: 0 40px 80px -32px rgba(26,35,60,.30);

  --radius-sm: 6px;
  --radius: 10px;
  --radius-lg: 16px;

  --font-ui: 'InterVariable', system-ui, -apple-system, 'Segoe UI', Roboto,
             'Helvetica Neue', Arial, sans-serif;
  --font-mono: ui-monospace, 'SF Mono', 'JetBrains Mono', 'Cascadia Code',
               'Roboto Mono', Menlo, Consolas, monospace;
}

/* ---- Tokens: dark (navy-based) ------------------------------------- */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --bg:#12151d;
    --surface:#1a1f2b;
    --surface-2:#161b25;
    --surface-sunken:#10141c;
    --line:#262d3c;
    --line-strong:#313a4d;
    --text:#e8ebf2;
    --text-2:#aab2c2;
    --text-muted:#7d8698;
    --accent:#6e9ce0;
    --accent-hover:#86ade8;
    --accent-ink:#101623;
    --accent-weak:#1d2839;
    --ring: rgba(110,156,224,.40);
    --side-bg:#171c26;
    --side-surface:#212838;
    --edge-teal:#45b391;
    --edge-violet:#8f84ec;
    --edge-rose:#df6d8c;
    --ok:#6fa98f;     --ok-bg:#15251f;   --ok-border:#28443a;
    --warn:#e39a4b;   --warn-bg:#2c2013; --warn-border:#4a381f;
    --crit:#f37f76;   --crit-bg:#2d1716; --crit-border:#4c2624;
    --shadow-sm: 0 1px 2px rgba(0,0,0,.40);
    --shadow-md: 0 8px 24px -10px rgba(0,0,0,.60);
    --shadow-lg: 0 30px 70px -30px rgba(0,0,0,.70);
    --shadow-xl: 0 44px 90px -34px rgba(0,0,0,.75);
  }
}
:root[data-theme="dark"] {
  color-scheme: dark;
  --bg:#12151d;
  --surface:#1a1f2b;
  --surface-2:#161b25;
  --surface-sunken:#10141c;
  --line:#262d3c;
  --line-strong:#313a4d;
  --text:#e8ebf2;
  --text-2:#aab2c2;
  --text-muted:#7d8698;
  --accent:#6e9ce0;
  --accent-hover:#86ade8;
  --accent-ink:#101623;
  --accent-weak:#1d2839;
  --ring: rgba(110,156,224,.40);
  --side-bg:#171c26;
  --side-surface:#212838;
  --edge-teal:#45b391;
  --edge-violet:#8f84ec;
  --edge-rose:#df6d8c;
  --ok:#6fa98f;     --ok-bg:#15251f;   --ok-border:#28443a;
  --warn:#e39a4b;   --warn-bg:#2c2013; --warn-border:#4a381f;
  --crit:#f37f76;   --crit-bg:#2d1716; --crit-border:#4c2624;
  --shadow-sm: 0 1px 2px rgba(0,0,0,.40);
  --shadow-md: 0 8px 24px -10px rgba(0,0,0,.60);
  --shadow-lg: 0 30px 70px -30px rgba(0,0,0,.70);
  --shadow-xl: 0 44px 90px -34px rgba(0,0,0,.75);
}

/* ---- Reset & base -------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
[hidden] { display: none !important; }
/* No rubber-band overscroll: the fixed sidebar can't bounce, so the
   sticky topbar bouncing with the page read as a glitch. */
/* overflow-x: clip — the page can never pan sideways, no matter what
   overflows (measured guarantee; clip has no scroll mechanism at all). */
html { -webkit-text-size-adjust: 100%; overscroll-behavior-y: none; overflow-x: clip; }

body {
  margin: 0;
  font-family: var(--font-ui);
  font-size: 16px;
  line-height: 1.55;
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2, h3, h4 { margin: 0; font-weight: 650; line-height: 1.15; letter-spacing: -0.014em; }
h1, h2 { text-wrap: balance; }
p { margin: 0; }
a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

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

.eyebrow {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-muted);
}

/* =====================================================================
   Auth layout — light split, connected by a single continuous line
   ===================================================================== */
.auth {
  position: relative;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background:
    radial-gradient(120% 80% at 85% 15%, var(--accent-weak) 0%, transparent 45%),
    var(--bg);
}

/* The through-line: one continuous stroke that spans the whole viewport,
   physically connecting the sign-in form to the certificate. It draws on
   load (see @keyframes draw) — the signature moment. */
.auth__line {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}
.auth__line svg {
  position: absolute;
  left: 0;
  top: 50%;
  width: 100%;
  height: 360px;
  transform: translateY(-50%);
}
/* Dash values are in the path's user units (total length ~1524), so the
   draw and pulse behave identically at every viewport width. */
.auth__line .flow {
  fill: none;
  stroke-width: 2.25;
  stroke-linecap: round;
  stroke-dasharray: 1560;
  stroke-dashoffset: 1560;
  filter: drop-shadow(0 2px 10px rgba(68,120,204,.30));
  animation: draw 1.8s cubic-bezier(.16,.8,.3,1) 0.3s forwards;
}
/* A bright signal pulse that travels the full line once it has drawn. */
.auth__line .flow-pulse {
  fill: none;
  stroke: #6595d8;
  stroke-width: 4;
  stroke-linecap: round;
  stroke-dasharray: 90 1500;
  stroke-dashoffset: 1560;
  opacity: 0;
  filter: drop-shadow(0 0 5px rgba(101,149,216,.95))
          drop-shadow(0 0 2px #ffffff);
  animation: travel 3s linear 2.1s infinite, pulsein .5s ease 2.1s forwards;
}

.auth__top {
  position: relative;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: clamp(1.4rem, 3vw, 2.1rem) clamp(1.4rem, 4vw, 3rem);
}

.auth__main {
  position: relative;
  z-index: 1;
  flex: 1;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(1.5rem, 5vw, 4.5rem);
  align-items: center;
  width: 100%;
  max-width: 1160px;
  margin: 0 auto;
  padding: 1rem clamp(1.4rem, 4vw, 3rem) 2rem;
}

.auth__form {
  width: 100%;
  max-width: 25rem;
  justify-self: center;
}

.auth__aside {
  justify-self: center;
  width: 100%;
  max-width: 27rem;
}

.auth__foot {
  position: relative;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1rem clamp(1.4rem, 4vw, 3rem);
  font-size: 0.82rem;
  color: var(--text-muted);
}
.auth__foot-links { display: flex; gap: 1.1rem; flex-wrap: wrap; }
.auth__foot-links a { color: var(--text-2); }

/* =====================================================================
   Brand mark & wordmark
   ===================================================================== */
.brand-lockup {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  text-decoration: none;
  color: inherit;
}
.brand-lockup:hover { text-decoration: none; }
/* Image lockups (the real logo files) sit on the same anchor. No display
   here: the theme-only helpers control which variant shows. */
.brand-lockup > img { height: 34px; width: auto; }
.brand-mark {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 9px;
  background: var(--navy);
  box-shadow: 0 6px 16px -6px rgba(33,39,56,.55);
  flex: none;
}
.brand-mark svg { width: 22px; height: 22px; display: block; }
.brand-word { display: flex; flex-direction: column; line-height: 1.05; }
.brand-word b {
  font-weight: 660;
  font-size: 0.98rem;
  letter-spacing: -0.01em;
  color: var(--text);
}
.brand-word span {
  font-family: var(--font-mono);
  font-size: 0.58rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin-top: 2px;
}

/* =====================================================================
   Forms
   ===================================================================== */
.form-head { margin-bottom: 1.6rem; }
.form-head h2 { margin-top: 0.55rem; font-size: 1.6rem; }
.form-head p { margin-top: 0.55rem; color: var(--text-2); }

form { margin: 0; }

.field { margin-bottom: 1.05rem; }
.field > label,
.label-row > label {
  display: block;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--text);
  margin-bottom: 0.4rem;
}
.label-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
}
.label-row a { font-size: 0.82rem; font-weight: 500; }

.field input:not([type="checkbox"]):not([type="radio"]),
.field select,
.field textarea {
  width: 100%;
  font: inherit;
  font-size: 0.95rem;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  padding: 0.64rem 0.78rem;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.field input::placeholder { color: var(--text-muted); }
.field input:not([type="checkbox"]):focus,
.field select:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--ring);
}
.field.has-error input:not([type="checkbox"]) { border-color: var(--crit); }

/* Google Places autocomplete (<gmp-place-autocomplete>) dressed as a normal
   field input. address_autocomplete.js swaps the widget in for an opted-in
   input at runtime; element-level props forward to its shadow input, with
   ::part() for what they can't reach. */
.field gmp-place-autocomplete {
  display: block;
  width: 100%;
  font: inherit;
  font-size: 0.95rem;
  color: var(--text);
  background-color: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  color-scheme: inherit;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.field gmp-place-autocomplete::part(input) { padding: 0.64rem 0.78rem; }
/* Our ring replaces the widget's built-in focus ring. */
.field gmp-place-autocomplete::part(focus-ring) { outline: none; box-shadow: none; }
.field gmp-place-autocomplete:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--ring);
}
.field.has-error gmp-place-autocomplete { border-color: var(--crit); }
.field--icon .field-control gmp-place-autocomplete::part(input) { padding-left: 2.4rem; }

.input-affix { position: relative; display: flex; }
.input-affix input { padding-right: 4.2rem !important; }
.input-affix .affix-btn {
  position: absolute;
  right: 0.35rem;
  top: 50%;
  transform: translateY(-50%);
  border: 0;
  background: transparent;
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 0.3rem 0.5rem;
  border-radius: var(--radius-sm);
  cursor: pointer;
}
.input-affix .affix-btn:hover { color: var(--accent); background: var(--surface-sunken); }

.field-hint { margin-top: 0.4rem; font-size: 0.82rem; color: var(--text-muted); }
.field-error { margin-top: 0.4rem; font-size: 0.82rem; color: var(--crit); }
.field-error ul, .field-error p { margin: 0; padding-left: 1rem; }

/* Multi-checkbox groups (Django CheckboxSelectMultiple): one option
   per row, plain-weight option labels under the bold field label. */
.field--choices > div { display: grid; gap: 0.35rem; }
.field--choices > div label {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  font-size: 0.9rem;
  font-weight: 400;
  color: var(--text-2);
}

.checkbox { display: flex; align-items: flex-start; gap: 0.6rem; }
.checkbox input[type="checkbox"] {
  width: 1.1rem; height: 1.1rem; margin-top: 0.15rem;
  accent-color: var(--accent); flex: none;
}
.checkbox label { font-size: 0.9rem; color: var(--text-2); font-weight: 500; }
.checkbox label a { font-weight: 600; }

/* Two-up field row (e.g. first / last name), stacks on narrow screens */
.field-row { display: flex; gap: 0.9rem; }
.field-row > .field { flex: 1; min-width: 0; }

/* Live inline validity check (HTMX-swapped partials/check_result.html) */
.check { display: inline-block; font-size: 0.82rem; margin-top: 0.4rem; }
.check-ok    { color: var(--ok); }
.check-error { color: var(--crit); }
.check-warn  { color: var(--warn); }
.check-hint  { display: block; color: var(--text-muted); font-size: 0.8rem; margin-top: 0.2rem; }
.check-suggest {
  margin-left: 0.4rem; font-size: 0.82rem; color: var(--accent);
  background: none; border: 0; padding: 0; cursor: pointer; text-decoration: underline;
}

/* Inline text button (show/hide password, "use suggestion") */
.link-button {
  background: none; border: 0; padding: 0; cursor: pointer;
  color: var(--accent); font: inherit; font-size: 0.82rem;
  font-family: var(--font-mono); letter-spacing: 0.04em; text-transform: uppercase;
}
.link-button:hover { color: var(--accent-hover); }

/* Password strength meter (HTMX-swapped partials/password_meter.html) */
.meter {
  height: 6px; border-radius: 999px; background: var(--surface-sunken);
  overflow: hidden; margin-top: 0.55rem;
}
.meter span { display: block; height: 100%; transition: width .25s ease, background-color .25s ease; }
.meter-red span    { width: 33%;  background: var(--crit); }
.meter-yellow span { width: 66%;  background: var(--warn); }
.meter-green span  { width: 100%; background: var(--ok); }
.meter-label { display: inline-block; margin-top: 0.35rem; font-size: 0.8rem; color: var(--text-muted); }

/* Honeypot: parked off-screen, never display:none so bots still fill it */
.hp-wrapper, .hp-field {
  position: absolute; left: -9999px; top: -9999px;
  width: 1px; height: 1px; overflow: hidden;
}

/* Visually hidden but available to screen readers */
.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* Invite rows (registration step 4) */
.invite-head {
  display: grid;
  grid-template-columns: 1fr 11rem 2.5rem;
  gap: 0.6rem;
  margin-bottom: 0.45rem;
}
.invite-head span { font-size: 0.8rem; font-weight: 600; color: var(--text-2); }
.invite-rows { display: flex; flex-direction: column; gap: 0.7rem; }
.invite-row {
  display: grid;
  grid-template-columns: 1fr 11rem 2.5rem;
  gap: 0.6rem;
  align-items: start;
}
.invite-row .field { margin-bottom: 0; }
.invite-add { margin-top: 0.9rem; }
.btn--sm { padding: 0.5rem 0.85rem; font-size: 0.85rem; }

@media (max-width: 560px) {
  .invite-head, .invite-row { grid-template-columns: 1fr 8rem 2.5rem; }
}

/* =====================================================================
   Buttons
   ===================================================================== */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  font: inherit;
  font-size: 0.95rem;
  font-weight: 600;
  line-height: 1;
  padding: 0.74rem 1.1rem;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  cursor: pointer;
  text-decoration: none;
  transition: background-color .15s ease, border-color .15s ease,
              transform .06s ease, box-shadow .15s ease;
}
.btn:hover { text-decoration: none; }
.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: 0.6; cursor: not-allowed; }
.btn--block { width: 100%; }

.btn--primary {
  background: var(--accent);
  color: var(--accent-ink);
  box-shadow: 0 8px 20px -8px rgba(68,120,204,.55);
}
.btn--primary:hover { background: var(--accent-hover); box-shadow: 0 10px 24px -8px rgba(68,120,204,.65); }

.btn--ghost {
  background: var(--surface);
  color: var(--text);
  border-color: var(--line-strong);
}
.btn--ghost:hover { background: var(--surface-sunken); border-color: var(--n300); }

/* Destructive confirm action. A committed danger red in both themes (white
   text on it clears AA), rather than the theme-swapped --crit token whose
   dark value is too light to carry white text. */
.btn--danger {
  background: var(--red-500, #c10000);
  color: #fff;
  border-color: transparent;
  box-shadow: 0 8px 20px -8px rgba(193, 0, 0, .5);
}
.btn--danger:hover { background: var(--red-600, #9e0000); box-shadow: 0 10px 24px -8px rgba(193, 0, 0, .65); }

.stack { display: flex; flex-direction: column; gap: 0.7rem; }

.divider {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  margin: 1.35rem 0;
  color: var(--text-muted);
  font-size: 0.74rem;
  font-family: var(--font-mono);
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.divider::before, .divider::after {
  content: ""; flex: 1; height: 1px; background: var(--line);
}

.auth__aside-note {
  margin-top: 1.5rem;
  text-align: center;
  font-size: 0.9rem;
  color: var(--text-2);
}

/* =====================================================================
   Alerts / flash messages
   ===================================================================== */
.alert {
  display: flex; gap: 0.6rem; align-items: center;
  padding: 0.75rem 0.9rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line-strong);
  background: var(--surface-sunken);
  font-size: 0.88rem; color: var(--text);
  margin-bottom: 1rem;
}
.alert svg { flex: none; width: 19px; height: 19px; }
.alert ul { margin: 0; padding: 0; list-style: none; }
.alert li { list-style: none; }
.alert--error {
  background: var(--crit-bg); border-color: var(--crit); color: var(--crit);
  box-shadow: 0 0 0 3px rgba(193,0,0,.10), 0 10px 28px -8px rgba(193,0,0,.30);
}
.alert--success { background: var(--ok-bg);   border-color: var(--ok-border);   color: var(--ok); }
.alert--warning { background: var(--warn-bg); border-color: var(--warn-border); color: var(--warn); }
.alert--info    { background: var(--accent-weak); border-color: var(--blue-200); color: var(--accent-hover); }
.messages { display: flex; flex-direction: column; gap: 0.5rem; margin-bottom: 1.25rem; }

/* Address confirmation modal (Google Address Validation review step) */
.addr-modal {
  border: 0;
  padding: 0;
  max-width: 27rem;
  width: calc(100% - 2rem);
  background: transparent;
  color: var(--text);
  overflow: visible;
}
.addr-modal::backdrop {
  background: rgba(10, 14, 26, 0.5);
  backdrop-filter: blur(2px);
}
.addr-modal__panel {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xl);
  padding: 1.6rem;
  overflow: hidden;
}
.addr-modal__panel::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 3px;
}
.addr-modal__panel--corrected::before { background: var(--accent); }
.addr-modal__panel--unconfirmed::before { background: var(--warn); }
.addr-modal__close {
  position: absolute;
  top: 0.75rem;
  right: 0.75rem;
  display: grid;
  place-items: center;
  width: 2rem;
  height: 2rem;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
}
.addr-modal__close:hover { background: var(--surface-sunken); color: var(--text); }
.addr-modal__close svg { width: 18px; height: 18px; }
.addr-modal__eyebrow {
  font-family: var(--font-mono);
  font-size: 0.7rem; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--text-muted);
}
.addr-modal__panel--corrected .addr-modal__eyebrow { color: var(--accent-hover); }
.addr-modal__panel--unconfirmed .addr-modal__eyebrow { color: var(--warn); }
.addr-modal__title { margin-top: 0.45rem; font-size: 1.2rem; padding-right: 1.5rem; }
.addr-modal__lead { margin-top: 0.5rem; font-size: 0.9rem; color: var(--text-2); }
.addr-modal__addr {
  margin-top: 0.9rem;
  font-family: var(--font-mono);
  font-size: 0.9rem; line-height: 1.5;
  color: var(--text);
  padding: 0.75rem 0.85rem;
  background: var(--accent-weak);
  border: 1px solid var(--blue-200);
  border-radius: var(--radius-sm);
}
.addr-modal__actions { display: flex; flex-direction: column; gap: 0.6rem; margin-top: 1.35rem; }
.addr-modal[open] { animation: modalpop 0.18s cubic-bezier(.2,.7,.3,1); }
@keyframes modalpop { from { opacity: 0; transform: translateY(8px) scale(.98); } to { opacity: 1; transform: none; } }

/* Generic confirmation modal — the in-app replacement for window.confirm(),
   driven by any form[data-confirm] (see app.js). */
.confirm-modal {
  border: 0;
  padding: 0;
  max-width: 26rem;
  width: calc(100% - 2rem);
  background: transparent;
  color: var(--text);
  overflow: visible;
}
.confirm-modal::backdrop {
  background: rgba(10, 14, 26, 0.5);
  backdrop-filter: blur(2px);
}
.confirm-modal__panel {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xl);
  padding: 1.6rem;
}
.confirm-modal__eyebrow {
  font-family: var(--font-mono);
  font-size: 0.7rem; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--text-muted);
}
.confirm-modal__msg {
  margin-top: 0.55rem;
  font-size: 0.98rem; line-height: 1.5;
  color: var(--text);
}
.confirm-modal__actions {
  display: flex; justify-content: flex-end; flex-wrap: wrap; gap: 0.6rem;
  margin-top: 1.5rem;
}
.confirm-modal[open] { animation: modalpop 0.18s cubic-bezier(.2,.7,.3,1); }
/* Reject dialog: the confirm modal chrome carrying a small form. */
.reject-modal { max-width: 30rem; }
.reject-modal .field { margin-top: 0.95rem; }
.reject-modal textarea { resize: vertical; }

/* Google Places Autocomplete dropdown, restyled to the design system */
.pac-container {
  margin-top: 4px;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
  font-family: var(--font-ui);
}
.pac-container::after { display: none; }  /* hide the "powered by Google" spacer row image */
.pac-item {
  padding: 0.45rem 0.7rem;
  border-top: 1px solid var(--line);
  color: var(--text-2);
  font-size: 0.85rem;
  cursor: pointer;
}
.pac-item:first-child { border-top: 0; }
.pac-item:hover, .pac-item-selected { background: var(--surface-sunken); }
.pac-item-query { color: var(--text); font-size: 0.9rem; }
.pac-matched { color: var(--accent); }

/* =====================================================================
   Certificate — the product artifact shown as proof
   ===================================================================== */
.cert-stack { position: relative; }
/* A faint second card behind, hinting "many credentials" */
.cert-stack::before {
  content: "";
  position: absolute;
  inset: 18px -14px -18px 14px;
  border-radius: var(--radius-lg);
  background: var(--surface);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-md);
  opacity: 0.55;
  z-index: 0;
}

.cert-card {
  position: relative;
  z-index: 1;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xl);
  padding: 1.4rem 1.5rem 1.3rem;
  overflow: hidden;
  animation: floaty 7s ease-in-out 1.8s infinite;
}
/* Brand pulse cap (red-to-blue) where the through-line docks into the
   certificate */
.cert-card::before {
  content: "";
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 4px;
  background: linear-gradient(var(--red-500), var(--blue-500));
}
.cert-card__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 1.15rem;
}
.cert-brand { display: inline-flex; align-items: center; gap: 0.45rem; }
.cert-brand .brand-mark { width: 26px; height: 26px; border-radius: 7px; }
.cert-brand .brand-mark svg { width: 17px; height: 17px; }
.cert-brand b { font-size: 0.82rem; font-weight: 640; letter-spacing: -0.01em; }

.pill {
  display: inline-flex; align-items: center; gap: 0.4rem;
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  white-space: nowrap;
  padding: 0.26rem 0.55rem;
  border-radius: 999px;
  border: 1px solid var(--line-strong);
  color: var(--text-2);
}
.pill--ok { color: var(--ok); background: var(--ok-bg); border-color: var(--ok-border); }
.pill__dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: currentColor;
  box-shadow: 0 0 0 0 currentColor;
  animation: dotpulse 2.4s ease-out infinite;
}

.cert-card__eyebrow {
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.cert-card__title {
  margin-top: 0.35rem;
  font-size: 1.32rem;
  font-weight: 650;
  letter-spacing: -0.02em;
}
.cert-card__holder { margin-top: 0.5rem; font-size: 0.92rem; color: var(--text-2); }
.cert-card__holder b { color: var(--text); font-weight: 620; }

.cert-card__meta {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.75rem;
  margin: 1.2rem 0 0;
  padding-top: 1.15rem;
  border-top: 1px solid var(--line);
}
.cert-card__meta div { display: flex; flex-direction: column; gap: 0.25rem; }
.cert-card__meta dt {
  font-family: var(--font-mono);
  font-size: 0.6rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.cert-card__meta dd {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 0.85rem;
  font-variant-numeric: tabular-nums;
  color: var(--text);
}

.cert-card__foot {
  display: flex; align-items: center; gap: 0.45rem;
  margin-top: 1.15rem;
  font-size: 0.78rem;
  color: var(--ok);
}
.cert-card__foot svg { width: 15px; height: 15px; }

.cert-caption {
  margin-top: 1.5rem;
  text-align: center;
  font-size: 0.9rem;
  line-height: 1.5;
  color: var(--text-2);
  max-width: 24rem;
  margin-left: auto;
  margin-right: auto;
}

/* =====================================================================
   Step tracker — the aside for multi-step wizards
   ===================================================================== */
.steps { display: flex; flex-direction: column; }
.step {
  position: relative;
  display: flex;
  gap: 0.9rem;
  padding-bottom: 1.7rem;
}
.step:last-child { padding-bottom: 0; }
/* connector between markers */
.step:not(:last-child)::before {
  content: "";
  position: absolute;
  left: 16px;
  top: 34px;
  bottom: 2px;
  width: 2px;
  background: var(--line-strong);
}
.step--done:not(:last-child)::before { background: var(--accent); }
.step__marker {
  flex: none;
  width: 34px; height: 34px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-family: var(--font-mono);
  font-size: 0.85rem;
  font-weight: 600;
  border: 2px solid var(--line-strong);
  background: var(--surface);
  color: var(--text-muted);
  z-index: 1;
}
.step__marker svg { width: 16px; height: 16px; }
.step--active .step__marker {
  border-color: var(--accent);
  color: var(--accent);
  box-shadow: 0 0 0 4px var(--accent-weak);
}
.step--done .step__marker {
  border-color: var(--accent);
  background: var(--accent);
  color: var(--accent-ink);
}
.step__body { padding-top: 0.35rem; }
.step__body b { display: block; font-size: 0.95rem; font-weight: 620; color: var(--text); }
.step--todo .step__body b { color: var(--text-2); }
.step__body span { font-size: 0.85rem; color: var(--text-muted); }

/* =====================================================================
   Theme toggle
   ===================================================================== */
.theme-toggle {
  display: inline-flex; align-items: center; gap: 0.4rem;
  border: 1px solid var(--line-strong);
  background: var(--surface);
  color: var(--text-2);
  border-radius: 999px;
  padding: 0.32rem 0.7rem;
  font: inherit; font-size: 0.78rem;
  cursor: pointer;
}
.theme-toggle:hover { color: var(--text); border-color: var(--n300); }
.theme-toggle svg { width: 15px; height: 15px; }
.theme-toggle .theme-toggle__moon { display: none; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .theme-toggle .theme-toggle__sun { display: none; }
  :root:not([data-theme="light"]) .theme-toggle .theme-toggle__moon { display: inline; }
}
:root[data-theme="dark"] .theme-toggle .theme-toggle__sun { display: none; }
:root[data-theme="dark"] .theme-toggle .theme-toggle__moon { display: inline; }
:root[data-theme="light"] .theme-toggle .theme-toggle__sun { display: inline; }
:root[data-theme="light"] .theme-toggle .theme-toggle__moon { display: none; }

/* =====================================================================
   Motion — page-load sequence & ambient
   ===================================================================== */
.reveal {
  opacity: 0;
  animation: rise .6s cubic-bezier(.22,.61,.36,1) forwards;
  animation-delay: calc(var(--i, 0) * 80ms + 200ms);
}
@keyframes rise { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
@keyframes draw { to { stroke-dashoffset: 0; } }
@keyframes travel { from { stroke-dashoffset: 1560; } to { stroke-dashoffset: -90; } }
@keyframes pulsein { to { opacity: 1; } }
@keyframes floaty { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-7px); } }
@keyframes dotpulse {
  0%   { box-shadow: 0 0 0 0 rgba(18,128,92,.5); }
  70%  { box-shadow: 0 0 0 6px rgba(18,128,92,0); }
  100% { box-shadow: 0 0 0 0 rgba(18,128,92,0); }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  .reveal { opacity: 1; }
  .auth__line .flow { stroke-dashoffset: 0; }
  .auth__line .flow-pulse { opacity: 0 !important; }
}

/* =====================================================================
   Responsive
   ===================================================================== */
@media (max-width: 900px) {
  .auth__main {
    grid-template-columns: 1fr;
    gap: 2.5rem;
    padding-top: 0.5rem;
    padding-bottom: 3rem;
    align-items: start;
  }
  .auth__form { justify-self: stretch; max-width: 26rem; margin: 0 auto; order: 1; }
  .auth__aside { order: 2; max-width: 26rem; }
  /* Stacked layout: the horizontal line can no longer connect the two
     sections, so it would just cut across the form — hide it. */
  .auth__line { display: none; }
  .cert-card { animation: none; }
}

@media (max-width: 560px) {
  .auth__aside { display: none; }
  .auth__foot { flex-direction: column; align-items: flex-start; gap: 0.75rem; }
  .cert-card__meta { grid-template-columns: 1fr 1fr; }
}

/* =====================================================================
   Authenticated app shell + dashboards
   ---------------------------------------------------------------------
   The signed-in surface. Reuses the token system and the generic
   components above; the sign-in layout (.auth__*, .cert-*, .flow) is not
   used here. A cobalt hairline that draws under the header on load echoes
   the sign-in through-line, carrying the brand signature across the door.
   ===================================================================== */
.app {
  min-height: 100dvh;
  background: var(--bg);
}

/* Shell grid: fixed navy sidebar + fluid body column. The sidebar keeps
   the brand navy in BOTH themes — it's chrome, not content. */
.shell { display: flex; min-height: 100dvh; }
.shell__body {
  flex: 1;
  min-width: 0;
  margin-left: var(--side-w);
  display: flex;
  flex-direction: column;
  min-height: 100dvh;
  transition: margin-left .18s ease;
}
:root[data-sidenav="collapsed"] { --side-w: 76px; }

/* Keyboard skip link: off-screen until focused, then pinned top-left */
.skip-link {
  position: absolute;
  left: 0.75rem;
  top: -3.5rem;
  z-index: 60;
  padding: 0.55rem 0.9rem;
  background: var(--surface);
  color: var(--accent);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
  font-size: 0.85rem;
  font-weight: 600;
  transition: top 0.16s ease;
}
.skip-link:focus { top: 0.75rem; text-decoration: none; }

/* ---- Sidebar (navy, both themes) ----------------------------------- */
.sidenav {
  position: fixed;
  top: 0;
  bottom: 0;
  left: 0;
  z-index: 40;
  width: var(--side-w);
  display: flex;
  flex-direction: column;
  background: var(--side-bg);
  transition: width .18s ease, transform .22s ease;
}
.sidenav__brand {
  display: flex;
  align-items: center;
  justify-content: center;
  /* 59px matches the topbar's rendered height, so this row's
     border-bottom and the topbar's bottom hairline read as one
     continuous line across the whole viewport. */
  min-height: 59px;
  padding: 0 1.15rem;
  border-bottom: 1px solid var(--side-line);
}
.sidenav__brand a { display: inline-flex; align-items: center; }
.sidenav__wordmark { display: block; width: 168px; height: auto; }
.sidenav__mark { display: none; width: 38px; height: auto; }

.sidenav__nav {
  flex: 1 1 auto;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 1rem 0.7rem 1rem;
  scrollbar-width: thin;
  scrollbar-color: var(--side-surface) transparent;
}
.sidenav__group + .sidenav__group { margin-top: 1.25rem; }
.sidenav__label {
  padding: 0 0.6rem 0.45rem;
  font-family: var(--font-mono);
  font-size: 0.6rem;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: rgba(255,255,255,.38);
  white-space: nowrap;
}
.sidenav__item {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.62rem;
  padding: 0.5rem 0.6rem;
  margin: 0.1rem 0;
  border-radius: 8px;
  color: var(--side-text);
  font-size: 0.88rem;
  font-weight: 530;
  white-space: nowrap;
}
.sidenav__item svg { width: 18px; height: 18px; flex: none; opacity: 0.85; }
.sidenav__item:hover {
  color: var(--side-text-strong);
  background: var(--side-hover);
  text-decoration: none;
}
.sidenav__item--active {
  color: var(--side-text-strong);
  background: var(--side-active);
  font-weight: 620;
}
/* The brand pulse as the active marker: a red-to-blue bar on the rail edge */
.sidenav__item--active::before {
  content: "";
  position: absolute;
  left: -0.7rem;
  top: 5px;
  bottom: 5px;
  width: 3px;
  border-radius: 0 3px 3px 0;
  background: linear-gradient(180deg, var(--red-500), var(--blue-400));
}
.sidenav__foot {
  border-top: 1px solid var(--side-line);
  padding: 0.55rem 0.7rem;
}
.sidenav__collapse {
  display: flex;
  align-items: center;
  gap: 0.62rem;
  width: 100%;
  padding: 0.5rem 0.6rem;
  border: 0;
  border-radius: 8px;
  background: none;
  color: var(--side-text);
  font: inherit;
  font-size: 0.82rem;
  cursor: pointer;
  white-space: nowrap;
}
.sidenav__collapse svg { width: 17px; height: 17px; flex: none; transition: transform .18s ease; }
.sidenav__collapse:hover { color: var(--side-text-strong); background: var(--side-hover); }

/* Collapsed rail: icons only */
:root[data-sidenav="collapsed"] .sidenav__wordmark { display: none; }
:root[data-sidenav="collapsed"] .sidenav__mark { display: block; }
:root[data-sidenav="collapsed"] .sidenav__brand { padding: 0; }
:root[data-sidenav="collapsed"] .sidenav__label { display: none; }
:root[data-sidenav="collapsed"] .sidenav__text { display: none; }
:root[data-sidenav="collapsed"] .sidenav__item { justify-content: center; padding: 0.55rem 0; }
:root[data-sidenav="collapsed"] .sidenav__collapse { justify-content: center; padding: 0.55rem 0; }
:root[data-sidenav="collapsed"] .sidenav__collapse svg { transform: rotate(180deg); }

/* Mobile scrim behind the off-canvas sidebar */
.scrim {
  position: fixed;
  inset: 0;
  z-index: 35;
  background: rgba(16,20,30,.45);
  opacity: 0;
  pointer-events: none;
  transition: opacity .2s ease;
}

/* ---- Top utility bar ------------------------------------------------ */
.topbar {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.58rem clamp(1rem, 2.5vw, 1.6rem);
  background: var(--surface);
  background: color-mix(in srgb, var(--surface) 92%, transparent);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  box-shadow: 0 1px 0 var(--line);
}
.topbar__spacer { flex: 1; }
/* .icon-btn (defined later) would win a single-class display rule */
.topbar .topbar__hamburger { display: none; }
/* In the topbar the toggle is a compact 2rem control like the other
   icon buttons (its text label only shows on the public/auth shells). */
.topbar .theme-toggle {
  width: 2rem;
  height: 2rem;
  padding: 0;
  gap: 0;
  justify-content: center;
}
.topbar .theme-toggle svg { width: 17px; height: 17px; }
.topbar .theme-toggle > span:last-child { display: none; }
.topbar__brand { display: none; align-items: center; }
/* No display here: the theme-only helpers control visibility */
.topbar__brand img { width: 30px; height: auto; }

/* Command-palette trigger, styled as a search field */
.search-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  /* Fills the free topbar space up to 30rem and gives it back when the
     viewport tightens — a rigid min-width here pushed the topbar past
     the viewport at in-between widths and made the whole page pan. */
  flex: 999 1 auto;
  min-width: 0;
  max-width: 30rem;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  background: var(--surface);
  color: var(--text-muted);
  font: inherit;
  font-size: 0.84rem;
  padding: 0.34rem 0.55rem 0.34rem 0.8rem;
  cursor: pointer;
  transition: border-color .15s ease, background-color .15s ease;
}
.search-btn:hover { border-color: var(--n300); background: var(--surface-sunken); }
.search-btn svg { width: 15px; height: 15px; flex: none; }
.search-btn > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.search-btn .kbd-group { margin-left: auto; display: inline-flex; gap: 0.25rem; }

kbd {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  line-height: 1;
  padding: 0.18rem 0.4rem;
  border: 1px solid var(--line-strong);
  border-bottom-width: 2px;
  border-radius: 5px;
  background: var(--surface-sunken);
  color: var(--text-2);
}

/* ---- Public top bar (anonymous shells: catalog, legal) --------------
   Signed-out pages keep a horizontal bar — no sidebar for visitors.
   The brand pulse draws under it, red into blue. */
.appbar {
  position: sticky;
  top: 0;
  z-index: 20;
  background: var(--surface);
  box-shadow: 0 1px 0 var(--line);
}
.appbar__inner {
  position: relative;
  display: flex;
  align-items: center;
  gap: clamp(0.5rem, 2vw, 1.3rem);
  width: 100%;
  margin: 0 auto;
  padding: 0.6rem clamp(1rem, 3vw, 2rem);
}
.appbar .brand-lockup { flex: none; }
.appbar__rule {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 2px;
  background: linear-gradient(90deg,
    var(--red-500) 0%, #7a4a90 45%, var(--blue-500) 100%);
  transform: scaleX(0);
  transform-origin: left center;
  animation: raildraw 1.2s cubic-bezier(.16,.8,.3,1) 0.15s forwards;
}
@keyframes raildraw { to { transform: scaleX(1); } }
.appnav { display: flex; align-items: center; gap: 0.15rem; }
.appnav__link {
  position: relative;
  display: inline-flex;
  align-items: center;
  padding: 0.4rem 0.72rem;
  border-radius: var(--radius-sm);
  font-size: 0.9rem;
  font-weight: 550;
  color: var(--text-2);
}
.appnav__link:hover {
  color: var(--text);
  background: var(--surface-sunken);
  text-decoration: none;
}
.appnav__link--active { color: var(--accent); }
.appnav__link--active::after {
  content: "";
  position: absolute;
  left: 0.72rem;
  right: 0.72rem;
  bottom: -0.62rem;
  height: 2px;
  border-radius: 2px;
  background: var(--accent);
  z-index: 1;
}
.appbar__right {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.appbar .theme-toggle { padding: 0.34rem 0.4rem; }
.appbar .theme-toggle > span:last-child { display: none; }

/* live session countdown pill (text + .warn class set by app.js) */
.session-countdown {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.02em;
  font-variant-numeric: tabular-nums;
  color: var(--text-2);
  background: var(--surface-sunken);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 0.34rem 0.62rem;
  white-space: nowrap;
}
.session-countdown.warn {
  color: var(--warn);
  background: var(--warn-bg);
  border-color: var(--warn-border);
}

/* ---- Disclosure menus (org switcher + user menu) ------------------- */
.menu { position: relative; }
.menu > summary {
  list-style: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  border: 1px solid var(--line-strong);
  background: var(--surface);
  border-radius: 999px;
  padding: 0.3rem 0.5rem;
  color: var(--text);
  font-size: 0.85rem;
}
.menu > summary::-webkit-details-marker { display: none; }
.menu > summary:hover { border-color: var(--n300); background: var(--surface-sunken); }
.menu[open] > summary { border-color: var(--accent); box-shadow: 0 0 0 3px var(--ring); }
.menu__caret { width: 14px; height: 14px; color: var(--text-muted); transition: transform .15s ease; flex: none; }
.menu[open] .menu__caret { transform: rotate(180deg); }
.org-switch__icon { width: 18px; height: 18px; color: var(--text-muted); flex: none; }
.org-switch__name {
  font-weight: 600;
  max-width: 11rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.avatar {
  position: relative;
  overflow: hidden;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  flex: none;
  background: linear-gradient(150deg, var(--red-500), var(--blue-500));
  color: #fff;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.01em;
}
/* Uploaded photo overlays the initials; it's removed on load error so the
   initials (not a blank blue circle) show when the image can't load. */
.avatar__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* Hide the initials while a photo is present so only the photo shows; when the
   photo fails to load app.js removes the img and the initials return. */
.avatar:has(.avatar__img) { color: transparent; }

.menu__panel {
  position: absolute;
  right: 0;
  top: calc(100% + 0.5rem);
  z-index: 30;
  min-width: 15.5rem;
  padding: 0.4rem;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  animation: menupop .14s ease;
}
@keyframes menupop { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
.menu__label {
  padding: 0.5rem 0.6rem 0.35rem;
  font-family: var(--font-mono);
  font-size: 0.6rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.menu__id { padding: 0.35rem 0.6rem 0.55rem; }
.menu__id b { display: block; font-size: 0.9rem; font-weight: 640; }
.menu__id span { font-size: 0.8rem; color: var(--text-muted); word-break: break-all; }
.menu__form { display: block; margin: 0; }
.menu__item {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  text-align: left;
  padding: 0.52rem 0.6rem;
  border-radius: var(--radius-sm);
  font: inherit;
  font-size: 0.88rem;
  color: var(--text);
  background: none;
  border: 0;
  cursor: pointer;
}
.menu__item:hover { background: var(--surface-sunken); color: var(--text); text-decoration: none; }
.menu__item-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.menu__item .role-badge { margin-left: auto; flex: none; }
.menu__item--danger:hover { color: var(--crit); background: var(--crit-bg); }
.menu__sep { height: 1px; background: var(--line); margin: 0.35rem 0.3rem; }

/* ---- Full-width notification banners (verify email, session warn) --- */
.appbanner { background: var(--surface-2); box-shadow: 0 1px 0 var(--line); }
.appbanner__inner {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  flex-wrap: wrap;
  margin: 0 auto;
  padding: 0.7rem clamp(1rem, 3vw, 2rem);
  font-size: 0.88rem;
  color: var(--text-2);
}
.appbanner__inner > svg { width: 18px; height: 18px; flex: none; }
.appbanner__inner form { display: inline; margin: 0; }
.appbanner--warn { background: var(--warn-bg); box-shadow: 0 1px 0 var(--warn-border); color: var(--warn); }
.appbanner--warn a, .appbanner--warn .link-button { color: var(--warn); }
.appbanner__grow { margin-left: auto; }

/* ---- Main + footer ------------------------------------------------- */
.app-main {
  flex: 1;
  width: 100%;
  max-width: 1360px;
  margin: 0 auto;
  padding: clamp(1.5rem, 3vw, 2.4rem) clamp(1rem, 3vw, 2rem) 3.5rem;
}
/* One vertical rhythm for every stacked content block — cards, grids,
   headers, notes — at both the page and narrow-column level. This replaces
   the fragile per-block margins (which only spaced adjacent cards and left
   gaps wherever a grid or note sat between them). The page header keeps its
   larger margin-bottom, which collapses with this to give it extra room. */
.app-main > * + *,
.content-narrow > * + * {
  margin-top: 1.4rem;
}

.app-foot { box-shadow: 0 -1px 0 var(--line); background: var(--surface); }
.app-foot__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin: 0 auto;
  padding: 1rem clamp(1rem, 3vw, 2rem);
  font-size: 0.82rem;
  color: var(--text-muted);
}
.app-foot__links { display: flex; gap: 1.1rem; flex-wrap: wrap; }
.app-foot__links a { color: var(--text-2); }

/* ---- Page header --------------------------------------------------- */
.page-head { margin-bottom: 1.7rem; }
.page-head__row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}
/* A long lead's max-content width would otherwise force the actions onto
   their own row before the text ever shrinks (flex wraps at hypothetical
   size). Basis 0 keeps the text flexible and the actions top-right. */
.page-head__row > :first-child { flex: 1 1 0; min-width: 0; }
.page-head h1 { font-size: clamp(1.5rem, 3vw, 1.85rem); margin-top: 0.5rem; }
.page-head .lead { margin-top: 0.55rem; color: var(--text-2); font-size: 0.98rem; }
.page-head__meta { margin-top: 0.75rem; display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; }
.page-head__meta p { margin: 0; }
.page-head__actions { display: flex; gap: 0.6rem; flex: none; }

/* ---- Stat grid ----------------------------------------------------- */
.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 1rem;
}
/* Every stat tile gets a COMPLETE border in its color — accent cobalt by
   default, semantic color when statused — so tiles read uniformly instead
   of mixing a left accent bar with full status borders. */
.stat {
  position: relative;
  overflow: hidden;
  background: var(--surface);
  border: 2px solid var(--edge);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  padding: 1.15rem 1.25rem;
}
.stat--ok { border-color: var(--ok); }
.stat--warn { border-color: var(--warn); }
.stat--crit { border-color: var(--crit); }
/* Account pages: the 44rem column fits three auto-fit tiles per row, which
   strands the fourth on a stretched row of its own — pair them up instead. */
.content-narrow .stat-grid { grid-template-columns: repeat(2, 1fr); }
.stat__label {
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.stat__value {
  margin-top: 0.45rem;
  font-family: var(--font-mono);
  font-size: 2rem;
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.stat__hint { margin-top: 0.45rem; font-size: 0.8rem; color: var(--text-muted); }

/* ---- Generic card -------------------------------------------------- */
/* A COMPLETE colored border on all four sides. The hue comes from --edge:
   cobalt by default, rotated through the edge palette by position (see the
   rotation rules below the row components), and inherited by the rows,
   tables, and empty states inside the card so each card's contents
   harmonize with its border. Status variants recolor the whole border. */
.card {
  background: var(--surface);
  border: 2px solid var(--edge);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  padding: 1.3rem 1.4rem;
}
.card__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 1.05rem;
}
.card__title { font-size: 1.05rem; font-weight: 640; }
.card__action {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  white-space: nowrap;
  flex: none;
}
.card__foot {
  margin-top: 1.15rem;
  padding-top: 0.95rem;
  border-top: 1px solid var(--line);
  font-size: 0.85rem;
  color: var(--text-muted);
}
.card__foot a { font-weight: 500; }
.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(258px, 1fr));
  gap: 1.15rem;
}
/* Asymmetric admin layout: a compact form beside a wider table/list */
.admin-split {
  display: grid;
  grid-template-columns: minmax(0, 21rem) minmax(0, 1fr);
  gap: 1.15rem;
  align-items: start;
}
@media (max-width: 800px) { .admin-split { grid-template-columns: 1fr; } }

/* ---- Clinical data table ------------------------------------------- */
/* Tables get the same complete colored border as cards — all four sides,
   in the surrounding card's hue (accent when standalone). */
.table-wrap {
  overflow-x: auto;
  border: 2px solid var(--edge);
  border-radius: var(--radius-lg);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
}
/* Inside a card the wrap drops its own chrome — the card already draws
   the colored border, and a border-within-a-border reads as clutter.
   Standalone wraps keep the full treatment. */
/* overflow-x: clip, not auto — with fixed table layout nothing real can
   overflow, and clip means the wrap has no sideways scroll mechanism at
   all, so phantom overflow (tooltips, sub-pixel rounding) can't move it. */
.card .table-wrap { box-shadow: none; border: 0; border-radius: 0; overflow-x: clip; }
/* Dense by design: admin tables trade air for fit, so wide layouts
   stay on one screen without a horizontal scrollbar. table-layout:
   fixed is the guarantee — the table is exactly as wide as its card,
   so sideways movement is impossible by construction. Columns take
   width hints from th classes (below); everything else shares the
   remaining space and cell text wraps to fit. */
.data-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.84rem;
  table-layout: fixed;
}
.data-table td { overflow-wrap: anywhere; }
/* Cells that must stay on one line (audit dates, id strings): clip with
   an ellipsis instead of wrapping — pair with a title for the full value. */
.data-table td.cell-nowrap {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Column width hints for fixed layout — set on the header cell. On
   phones the hints would sum past the card, so they relax and every
   column shares the width equally (content wraps to fit). */
.data-table th.w-4 { width: 4rem; }
.data-table th.w-5 { width: 5rem; }
.data-table th.w-7 { width: 7rem; }
.data-table th.w-9 { width: 9rem; }
.data-table th.w-12 { width: 12rem; }
.data-table th.w-14 { width: 14rem; }
.data-table th.w-16 { width: 16rem; }
.data-table th.w-18 { width: 18rem; }
/* w-16 marks a table's lead (name) column: capped on wide screens so it
   cannot hoard the leftover width — fixed layout then shares the slack
   across every column — but flexible again on narrow laptops, where the
   full hint set would overflow the card. */
@media (max-width: 1279px) {
  .data-table th.w-16 { width: auto; }
}
/* w-14 marks a five-button action cluster: on narrow laptops its hint
   would starve the flexible data columns into letter-wrapping, so it
   relaxes and the icons wrap into a compact grid instead. */
@media (max-width: 1150px) {
  .data-table th.w-14 { width: auto; }
}
@media (max-width: 900px) {
  .data-table th.w-4,
  .data-table th.w-5,
  .data-table th.w-7,
  .data-table th.w-9,
  .data-table th.w-12,
  .data-table th.w-14,
  .data-table th.w-16,
  .data-table th.w-18 { width: auto; }
}
.data-table thead th {
  text-align: left;
  font-family: var(--font-mono);
  font-size: 0.62rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--text-muted);
  background: var(--surface-2);
  padding: 0.5rem 0.7rem;
  border-bottom: 1px solid var(--line-strong);
}
.data-table tbody td {
  padding: 0.5rem 0.7rem;
  border-bottom: 1px solid var(--line);
  color: var(--text-2);
  vertical-align: middle;
}
.data-table tbody tr:last-child td { border-bottom: 0; }
/* Status-tinted rows get the same semantic wash as .detail-list items.
   Declared before :hover so pointer feedback still wins on tinted rows. */
.data-table tbody tr.is-ok td { background: var(--ok-bg); }
.data-table tbody tr.is-warn td { background: var(--warn-bg); }
.data-table tbody tr.is-crit td { background: var(--crit-bg); }
.data-table tbody tr:hover td { background: var(--surface-sunken); }
.data-table th.num, .data-table td.num {
  text-align: right;
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}
.data-table .name-cell, .data-table .name-cell a { font-weight: 600; color: var(--text); }
/* Secondary line inside a table cell (instructor under the class name,
   timezone under the start time). overflow-wrap: a long unbroken token
   (an email address) must never set the column's minimum width — that
   is what forces tables into a horizontal scrollbar. */
.data-table .cell-sub {
  font-size: 0.76rem;
  font-weight: 400;
  color: var(--text-muted);
  margin-top: 0.1rem;
  overflow-wrap: anywhere;
}
.data-table .name-cell { overflow-wrap: anywhere; }

.pagination {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1.1rem;
  margin-top: 1.2rem;
  font-size: 0.88rem;
  color: var(--text-muted);
}
.pagination a { font-weight: 550; }
.pagination span { font-family: var(--font-mono); font-size: 0.8rem; }

/* ---- Labelled rows (role counts, locked accounts, org lists) ------- */
.membership-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
}
.membership-list > li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.7rem 0.9rem;
  /* Edge-tinted complete border so each row reads as its own item in
     both themes, in its card's hue (status classes recolor it outright). */
  border: 1px solid color-mix(in srgb, var(--edge) 35%, var(--line-strong));
  border-radius: var(--radius);
  background: var(--surface-2);
}
.membership-list > li > span:first-child {
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
  font-weight: 550;
}
.membership-list .count {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--text);
}
.inline-form { display: inline; margin: 0; }

/* small muted status tag */
.tag-muted {
  font-family: var(--font-mono);
  font-size: 0.62rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-muted);
  background: var(--surface-sunken);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 0.22rem 0.5rem;
  white-space: nowrap;
}
.tag-muted--warn { color: var(--warn); background: var(--warn-bg); border-color: var(--warn-border); }
.tag-muted--crit { color: var(--crit); background: var(--crit-bg); border-color: var(--crit-border); }

/* role badge (header + role-badge partial + org lists) */
.role-badge {
  display: inline-flex;
  align-items: center;
  font-family: var(--font-mono);
  font-size: 0.63rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent-hover);
  background: var(--accent-weak);
  border-radius: 999px;
  padding: 0.24rem 0.55rem;
  white-space: nowrap;
}

/* status pill variants (base .pill/.pill--ok/.pill__dot defined above) */
.pill--warn   { color: var(--warn); background: var(--warn-bg); border-color: var(--warn-border); }
.pill--crit   { color: var(--crit); background: var(--crit-bg); border-color: var(--crit-border); }
.pill--muted  { color: var(--text-muted); background: var(--surface-sunken); border-color: var(--line); }
.pill--accent {
  color: var(--accent-hover);
  background: var(--accent-weak);
  border-color: color-mix(in srgb, var(--accent) 35%, transparent);
}

/* ---- Empty / "coming soon" states ---------------------------------- */
.empty {
  display: flex;
  align-items: flex-start;
  gap: 0.9rem;
  padding: 1.1rem 1.15rem;
  border: 1px dashed color-mix(in srgb, var(--edge) 45%, var(--line-strong));
  border-radius: var(--radius);
  background: var(--surface-2);
}
.empty__icon {
  flex: none;
  width: 40px;
  height: 40px;
  border-radius: 10px;
  display: grid;
  place-items: center;
  background: var(--accent-weak);
  color: var(--accent);
}
.empty__icon svg { width: 20px; height: 20px; }
.empty__body b { display: block; font-size: 0.94rem; font-weight: 600; color: var(--text); margin-bottom: 0.15rem; }
.empty__body p { font-size: 0.87rem; color: var(--text-muted); }

.help { font-size: 0.86rem; color: var(--text-muted); }
.help a { font-weight: 500; }

/* ---- Content width helper for single-column settings / forms ------- */
.content-narrow { max-width: 44rem; margin-inline: auto; }

/* ---- Detail rows (devices, sessions, members: title + metadata) ---- */
.detail-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.6rem; }
.detail-list > li {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.9rem;
  padding: 0.85rem 0.95rem;
  /* Same edge-tinted complete border as .membership-list rows. */
  border: 1px solid color-mix(in srgb, var(--edge) 35%, var(--line-strong));
  border-radius: var(--radius);
  background: var(--surface-2);
}
.detail-list__body { min-width: 0; }
/* Course material previews (#64): generated JPEG when ready, kind icon
   fallback while pending or for types without a renderer. The sibling
   selector scopes the body growth to thumbed rows only — other
   detail-lists (e.g. My Certificates) keep their space-between layout. */
.material-thumb + .detail-list__body { flex: 1; }
.material-thumb {
  width: 56px;
  height: 56px;
  flex: 0 0 auto;
  border-radius: var(--radius);
  overflow: hidden;
  border: 1px solid var(--line);
  background: var(--surface-2);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--text-muted);
}
.material-thumb img { width: 100%; height: 100%; object-fit: cover; }
.material-thumb svg { width: 22px; height: 22px; }
.detail-list__title { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; font-weight: 600; }
.detail-list__meta {
  margin-top: 0.35rem;
  font-size: 0.8rem;
  color: var(--text-muted);
  font-family: var(--font-mono);
  line-height: 1.55;
  overflow-wrap: break-word;
}
.detail-list__empty { color: var(--text-muted); font-size: 0.9rem; padding: 0.6rem 0.1rem; }
/* Status-coded rows (certifications): a full border in the status color plus
   a faint tint around the whole row. */
.detail-list > li.is-ok {
  background: var(--ok-bg);
  border-color: var(--ok);
}
.detail-list > li.is-warn {
  background: var(--warn-bg);
  border-color: var(--warn);
}
.detail-list > li.is-crit {
  background: var(--crit-bg);
  border-color: var(--crit);
}
/* Accent-coded rows: pickable/featured items (e.g. class templates). */
.detail-list > li.is-accent {
  background: var(--accent-weak);
  border-color: var(--accent);
}

/* Status-coded section cards (certification groups): border in the status
   color so each section reads as Valid / Expiring Soon / Expired at a glance.
   `.card.card--x` outranks the base `.card` border. */
.card.card--ok { border-color: var(--ok); }
.card.card--warn { border-color: var(--warn); }
.card.card--crit { border-color: var(--crit); }

/* Per-organization verification badges under a certification row. */
.cert-verify {
  margin-top: 0.5rem;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.4rem;
}
.cert-verify__note {
  font-size: 0.8rem;
  color: var(--text-muted);
  font-style: italic;
}
/* ---- Inline code + QR (2FA enrollment) ----------------------------- */
code {
  font-family: var(--font-mono);
  font-size: 0.85em;
  background: var(--surface-sunken);
  border: 1px solid var(--line);
  padding: 0.08rem 0.36rem;
  border-radius: 5px;
}
.qr-code {
  display: inline-block;
  padding: 0.9rem;
  background: #fff;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
}
.qr-code svg, .qr-code img { display: block; width: 190px; height: 190px; }

/* One-time 2FA backup-code sheet: an easy-to-transcribe grid. */
.backup-codes {
  list-style: none;
  margin: 0.9rem 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(9.5rem, 1fr));
  gap: 0.5rem 0.75rem;
}
.backup-codes li {
  font-family: var(--font-mono);
  font-size: 1rem;
  letter-spacing: 0.06em;
  text-align: center;
  background: var(--surface-sunken);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 0.45rem 0.5rem;
}

/* ---- Public document shell (legal / long-form, no app chrome) ------ */
.doc { min-height: 100dvh; display: flex; flex-direction: column; background: var(--bg); }
.doc__top { box-shadow: 0 1px 0 var(--line); background: var(--surface); }
.doc__top-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  max-width: 1160px;
  margin: 0 auto;
  padding: 0.8rem clamp(1rem, 3vw, 2rem);
}
.doc__main {
  flex: 1;
  width: 100%;
  padding: clamp(1.7rem, 3vw, 2.8rem) clamp(1rem, 3vw, 2rem) 3.5rem;
}

/* ---- Prose (legal / long-form content) ----------------------------- */
.prose { max-width: 46rem; margin-inline: auto; color: var(--text-2); }
.prose > h1 { font-size: clamp(1.5rem, 3vw, 1.85rem); }
.prose h2 { font-size: 1.15rem; margin-top: 2rem; color: var(--text); }
.prose h3 { font-size: 1rem; margin-top: 1.4rem; color: var(--text); }
.prose p { margin-top: 0.9rem; line-height: 1.7; }
.prose ul, .prose ol { margin: 0.9rem 0; padding-left: 1.35rem; }
.prose li { margin-top: 0.4rem; line-height: 1.7; }
.prose a { font-weight: 500; }
/* Version + status pills under a document title, above the body. */
.prose .doc-meta {
  display: flex; flex-wrap: wrap; gap: 0.5rem;
  margin: 0.75rem 0 1.25rem;
}

/* Store quantity input: compact enough to sit inside a table cell. */
.data-table .qty-input { width: 5.5rem; }

/* ---- Platform log viewer ------------------------------------------- */
/* Inline traceback expansion in the System Logs table. Long frame
   paths wrap (pre-wrap + anywhere) instead of scrolling, so the box
   can never widen the page at any viewport. */
.log-trace { margin-top: 0.35rem; }
.log-trace summary {
  cursor: pointer;
  font-size: 0.76rem; font-weight: 550;
  color: var(--accent);
}
.log-trace pre {
  margin: 0.45rem 0 0.2rem;
  padding: 0.6rem 0.75rem;
  background: var(--surface-sunken);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  font-size: 0.74rem; line-height: 1.55;
  color: var(--text-2);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* ---- App shell responsive ------------------------------------------ */
/* Under 900px the sidebar goes off-canvas (hamburger + scrim); the
   desktop collapse control is meaningless there and any collapsed state
   is ignored so the drawer always opens full. */
@media (max-width: 900px) {
  .shell__body { margin-left: 0; }
  /* visibility (delayed until the slide-out ends) removes the closed
     drawer from the tab order and accessibility tree — a transform
     alone leaves ~15 invisible links keyboard-reachable. */
  .sidenav {
    width: 280px;
    transform: translateX(-100%);
    visibility: hidden;
    box-shadow: var(--shadow-xl);
    transition: transform .22s ease, visibility 0s linear .22s;
  }
  body.sidenav-open .sidenav {
    transform: none;
    visibility: visible;
    transition: transform .22s ease, visibility 0s;
  }
  body.sidenav-open .scrim { opacity: 1; pointer-events: auto; }
  .topbar .topbar__hamburger { display: inline-grid; }
  .topbar__brand { display: inline-flex; }
  .sidenav__foot { display: none; }
  :root[data-sidenav="collapsed"] .sidenav__wordmark { display: block; }
  :root[data-sidenav="collapsed"] .sidenav__mark { display: none; }
  :root[data-sidenav="collapsed"] .sidenav__brand { padding: 0 1.15rem; }
  :root[data-sidenav="collapsed"] .sidenav__label { display: block; }
  :root[data-sidenav="collapsed"] .sidenav__text { display: inline; }
  :root[data-sidenav="collapsed"] .sidenav__item { justify-content: flex-start; padding: 0.5rem 0.6rem; }
}
@media (max-width: 720px) {
  .session-countdown { display: none; }
  .org-switch__name { max-width: 7rem; }
  .search-btn > span { display: none; }
}
@media (max-width: 640px) {
  .page-head__row { flex-direction: column; }
  .page-head__row > :first-child { flex: 0 0 auto; }
  .page-head__actions { width: 100%; }
}
@media (max-width: 480px) {
  .brand-word span { display: none; }
  .org-switch__name { display: none; }
  .search-btn .kbd-group { display: none; }
}

/* Profile: grouped checkbox/input fields, specialty groups, chips */
.field--group {
  border: 0;
  padding: 0;
  margin: 0 0 1rem;
  min-inline-size: auto;
}
.field--group > legend {
  display: block;
  padding: 0;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--text);
  margin-bottom: 0.4rem;
}
.specialty-group {
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 0.7rem 0.9rem 0.9rem;
  margin: 0 0 0.7rem;
}
.specialty-group legend {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-2);
  padding: 0 0.4rem;
}
.specialty-group__items {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 0.35rem 0.9rem;
}
.chip-list {
  list-style: none;
  margin: 0.6rem 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}
.chip {
  display: inline-flex;
  align-items: center;
  gap: 0.15rem;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 0.25rem 0.4rem 0.25rem 0.75rem;
  font-size: 0.85rem;
  color: var(--text);
}
.chip__remove {
  border: 0;
  background: transparent;
  color: var(--text-2);
  cursor: pointer;
  font-size: 1.05rem;
  line-height: 1;
  padding: 0 0.35rem;
  border-radius: 999px;
}
.chip__remove:hover { color: var(--crit); }

/* Form-field leading icons */
.field-control { position: relative; }
.field--icon .field-control__icon {
  position: absolute;
  left: 0.75rem;
  top: 50%;
  transform: translateY(-50%);
  width: 1.05rem;
  height: 1.05rem;
  color: var(--text-muted);
  pointer-events: none;
}
.field--icon .field-control__icon svg { width: 100%; height: 100%; display: block; }
/* Specificity must beat the base `.field input:not(...):not(...)` padding rule
   so the icon isn't overlapped by the text. */
.field--icon .field-control input:not([type="checkbox"]):not([type="radio"]),
.field--icon .field-control select { padding-left: 2.4rem; }

/* Profile photo row in the Account section */
.profile-photo {
  display: flex;
  align-items: center;
  gap: 1.1rem;
  margin-bottom: 1rem;
  flex-wrap: wrap;
}
.profile-photo__preview {
  width: 84px;
  height: 84px;
  border-radius: 50%;
  overflow: hidden;
  flex: 0 0 auto;
  border: 1px solid var(--line);
  background: var(--surface-2);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.profile-photo__preview img[hidden] { display: none; }
.profile-photo__preview img { width: 100%; height: 100%; object-fit: cover; }
.profile-photo__placeholder { width: 42px; height: 42px; color: var(--text-muted); }
.profile-photo__placeholder[hidden] { display: none; }
.profile-photo__controls { flex: 1; min-width: 12rem; display: flex; flex-direction: column; gap: 0.5rem; }
.profile-photo__controls > label {
  display: block;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--text);
}
.profile-photo__actions { display: flex; gap: 0.6rem; flex-wrap: wrap; align-items: center; }
.profile-photo__actions .field-hint { margin: 0; }
/* Keyboard focus on the hidden file input shows on its "Choose photo" label. */
.profile-photo__choose:focus-within {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
/* Visually-hidden file input, still openable via its "Choose photo" label. */
.profile-photo__input {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  border: 0;
}

/* Colored borders per certification body's specialty group (uniform width) */
.specialty-group[data-provider="aha"] { border-color: #d64545; }
.specialty-group[data-provider="red_cross"] { border-color: #c8102e; }
.specialty-group[data-provider="ansi"] { border-color: #0b7285; }
.specialty-group[data-provider="naemt"] { border-color: #2f9e44; }
.specialty-group[data-provider="nremt"] { border-color: #7048e8; }

/* ------------------------------------------------------------------
   Instructor calendar (month grid)
   ------------------------------------------------------------------ */
.calendar-grid { width: 100%; border-collapse: collapse; table-layout: fixed; }
.calendar-grid thead th {
  padding: 0.5rem 0.4rem; font-size: 0.72rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--text-muted); border-bottom: 1px solid var(--line);
  text-align: center;
}
.calendar-grid tbody td {
  height: 5.2rem; padding: 0.35rem 0.4rem; vertical-align: top;
  border: 1px solid var(--line-strong); font-size: 0.85rem;
}
.calendar-grid .cal-day__num { font-weight: 600; }
.calendar-grid .is-outside { background: var(--surface-sunken); }
.calendar-grid .is-outside .cal-day__num { color: var(--text-muted); font-weight: 400; }
.calendar-grid .is-today .cal-day__num {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 1.6rem; height: 1.6rem; padding: 0 0.3rem; border-radius: 999px;
  background: var(--accent); color: var(--accent-ink);
}
.calendar-grid .is-blocked { background: var(--crit-bg); }
.cal-day__tag {
  display: block; margin-top: 0.3rem; font-size: 0.72rem;
  color: var(--crit); overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap;
}

/* Class chips on the instructor calendar, colored per organization: a
   COMPLETE border in the org color (thicker on the left edge), not just
   a left bar on a borderless tint. */
.cal-day__class {
  display: block; margin-top: 0.3rem; padding: 0.1rem 0.35rem;
  font-size: 0.72rem; border-radius: 0.35rem;
  border: 1px solid; border-left-width: 3px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  text-decoration: none; color: inherit;
}
.cal-org-0 { background: rgba(59, 130, 246, 0.14); border-color: #3b82f6; }
.cal-org-1 { background: rgba(16, 185, 129, 0.14); border-color: #10b981; }
.cal-org-2 { background: rgba(245, 158, 11, 0.16); border-color: #f59e0b; }
.cal-org-3 { background: rgba(139, 92, 246, 0.14); border-color: #8b5cf6; }
.cal-org-4 { background: rgba(236, 72, 153, 0.14); border-color: #ec4899; }
.cal-org-5 { background: rgba(20, 184, 166, 0.14); border-color: #14b8a6; }
span.pill.cal-org-0, span.pill.cal-org-1, span.pill.cal-org-2,
span.pill.cal-org-3, span.pill.cal-org-4, span.pill.cal-org-5 {
  border-left: 3px solid; color: var(--text);
}

/* Intro text inside a card (the page-head .lead rule doesn't reach here). */
.card > .lead {
  margin: 0 0 1rem; color: var(--text-muted); font-size: 0.9rem;
  line-height: 1.5;
}

/* ---- Public course catalog (FS 1.4) -------------------------------- */
.catalog-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(16.5rem, 1fr));
  gap: 1rem;
  margin-bottom: 1.25rem;
}
.course-card {
  display: flex; flex-direction: column; gap: 0.5rem;
  padding: 1.1rem;
  background: var(--surface);
  border: 1px solid color-mix(in srgb, var(--edge) 35%, var(--line-strong));
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  text-decoration: none; color: inherit;
  transition: border-color .15s ease, box-shadow .15s ease, transform .15s ease;
}
.course-card:hover {
  border-color: var(--edge);
  box-shadow: var(--shadow-md);
  transform: translateY(-2px);
}
.course-card > .pill { align-self: flex-start; }
.course-card__title { font-weight: 700; font-size: 1.02rem; color: var(--text); }
.course-card__meta { font-size: 0.85rem; color: var(--text-muted); }
.course-card__foot {
  margin-top: auto; padding-top: 0.5rem;
  display: flex; justify-content: space-between; align-items: baseline;
  border-top: 1px solid var(--line);
}
.course-card__price { font-weight: 700; color: var(--text); }

.catalog-filter-actions {
  display: flex; gap: 0.6rem; align-items: flex-end;
}

.public-course-layout {
  display: grid; grid-template-columns: 2fr 1fr; gap: 1.25rem;
  align-items: start;
}
@media (max-width: 760px) {
  .public-course-layout { grid-template-columns: 1fr; }
}
.card-text {
  margin: 0 0 1rem; color: var(--text-2); font-size: 0.95rem;
  line-height: 1.6;
}

.team-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 1rem; }
.team-member { display: flex; gap: 0.9rem; align-items: flex-start; }
.team-member__photo {
  width: 56px; height: 56px; border-radius: 50%; object-fit: cover;
  flex-shrink: 0; border: 1px solid var(--line);
}
.team-member__photo--empty {
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--accent-weak); color: var(--accent-hover);
  font-weight: 700; font-size: 1.2rem;
}
.team-member__body b { display: block; margin-bottom: 0.2rem; }
.team-member__body p {
  margin: 0; font-size: 0.88rem; color: var(--text-muted); line-height: 1.5;
}

.enroll-box { display: grid; gap: 0.7rem; justify-items: start; }
.enroll-box__price { font-size: 1.7rem; font-weight: 800; color: var(--text); }
.enroll-box__note { margin: 0; font-size: 0.9rem; color: var(--text-2); }
.enroll-box .btn { width: 100%; }
.enroll-box .help { margin: 0; }

/* =====================================================================
   Design pass (issue #74) — shared primitives that retire inline styles
   ===================================================================== */

/* ---- Tooltip --------------------------------------------------------
   Pure CSS, driven by data-tip; inverted surface reads in both themes.
   Pair with aria-label on icon-only controls (the tooltip text is
   ::after content, invisible to screen readers). */
[data-tip] { position: relative; }
[data-tip]::after {
  content: attr(data-tip);
  position: absolute;
  left: 50%;
  bottom: calc(100% + 8px);
  transform: translate(-50%, 2px);
  z-index: 40;
  width: max-content;
  max-width: 16rem;
  padding: 0.38rem 0.6rem;
  font: 500 0.75rem/1.4 var(--font-ui);
  letter-spacing: normal;
  text-transform: none;
  white-space: normal;
  text-align: center;
  color: var(--bg);
  background: var(--text);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
  opacity: 0;
  pointer-events: none;
  transition: opacity .12s ease .05s, transform .12s ease .05s;
}
[data-tip]::before {
  content: "";
  position: absolute;
  left: 50%;
  bottom: calc(100% + 3px);
  transform: translateX(-50%);
  border: 5px solid transparent;
  border-top-color: var(--text);
  opacity: 0;
  pointer-events: none;
  transition: opacity .12s ease .05s;
}
[data-tip]:hover::after, [data-tip]:focus-visible::after,
[data-tip]:hover::before, [data-tip]:focus-visible::before { opacity: 1; }
[data-tip]:hover::after, [data-tip]:focus-visible::after { transform: translate(-50%, 0); }
/* Controls near a container's left edge: left-align the bubble instead. */
.tip-start[data-tip]::after { left: 0; transform: translate(0, 2px); }
.tip-start[data-tip]:hover::after, .tip-start[data-tip]:focus-visible::after { transform: translate(0, 0); }
/* Controls at a container's right edge (table action cells): anchor the
   bubble to the button's right edge. Tooltips are laid out even while
   invisible, and a centered bubble on the last button extended the
   table wrap's scrollable area — the phantom horizontal scrollbar. */
.tip-end[data-tip]::after,
.data-table .table-actions [data-tip]::after,
.detail-list .table-actions [data-tip]::after {
  left: auto;
  right: 0;
  transform: translate(0, 2px);
}
.tip-end[data-tip]:hover::after,
.tip-end[data-tip]:focus-visible::after,
.data-table .table-actions [data-tip]:hover::after,
.data-table .table-actions [data-tip]:focus-visible::after,
.detail-list .table-actions [data-tip]:hover::after,
.detail-list .table-actions [data-tip]:focus-visible::after {
  transform: translate(0, 0);
}

/* ---- Icon button ----------------------------------------------------
   Compact quick action for table rows and row lists; sized for the
   17px stroke icons in partials/_icon.html. Works on <button> and <a>.
   Always pair with aria-label + data-tip. */
.icon-btn {
  display: inline-grid;
  place-items: center;
  width: 2rem;
  height: 2rem;
  flex: none;
  padding: 0;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text-muted);
  cursor: pointer;
  transition: color .15s ease, border-color .15s ease, background-color .15s ease;
}
.icon-btn svg { width: 17px; height: 17px; display: block; }
.icon-btn:hover {
  color: var(--accent);
  border-color: var(--accent);
  background: var(--accent-weak);
  text-decoration: none;
}
.icon-btn:active { transform: translateY(1px); }
.icon-btn:disabled { opacity: 0.5; cursor: not-allowed; }
.icon-btn--danger:hover {
  color: var(--crit);
  border-color: var(--crit);
  background: var(--crit-bg);
}
/* Leading icon inside a labelled .btn (e.g. "Approve" with a check). */
.btn svg { width: 16px; height: 16px; flex: none; }

/* ---- Table action cluster -------------------------------------------
   One layout for the per-row actions in .data-table cells AND in
   .detail-list / .membership-list rows (replaces .row-actions,
   .detail-list__actions, .membership-actions as templates migrate). */
.table-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.4rem;
  flex: none;
}
/* Rows align their content to the top (multi-line meta), but the action
   cluster reads better vertically centered against the whole row. */
.detail-list > li > .table-actions { align-self: center; }
/* CSRF form wrappers participate in the flex gap instead of breaking it. */
.table-actions .inline-form { display: contents; }
.table-actions .link-button { align-self: center; }
/* Inside a data table the cell must stay a real table cell — the flex
   display above would rip it out of the row's formatting context and
   misalign the buttons. Spacing targets the buttons themselves because
   inline-form wrappers are display: contents (margins on them vanish).
   No nowrap: under fixed layout a squeezed action cluster wraps onto a
   second line instead of painting over its neighbors. */
.data-table td.table-actions {
  display: table-cell;
  text-align: right;
  vertical-align: middle;
  padding-top: 0.45rem;
  padding-bottom: 0.45rem;
}
.data-table td.table-actions .icon-btn { margin-bottom: 0.15rem; }
.data-table td.table-actions .icon-btn,
.data-table td.table-actions .link-button { vertical-align: middle; }
/* Labelled buttons wrap between cluster items, never inside their own
   label. */
.data-table td.table-actions .btn { white-space: nowrap; }
.data-table td.table-actions :is(.icon-btn, .link-button) ~ :is(.icon-btn, .link-button),
.data-table td.table-actions :is(.icon-btn, .link-button) ~ .inline-form :is(.icon-btn, .link-button),
.data-table td.table-actions .inline-form ~ :is(.icon-btn, .link-button),
.data-table td.table-actions .inline-form ~ .inline-form :is(.icon-btn, .link-button) {
  margin-left: 0.4rem;
}
/* Fixed action-type hues: the same action reads the same color on every
   page — view/roster cobalt, PDF rose, CSV teal, public page violet.
   Buttons without a class fall back to their card's edge hue. */
.act-cobalt { --act: var(--accent); }
.act-teal { --act: var(--edge-teal); }
.act-violet { --act: var(--edge-violet); }
.act-rose { --act: var(--edge-rose); }
.act-amber { --act: var(--warn); }
.act-ok { --act: var(--ok); }

/* Action buttons tint from their action hue (fallback: card edge).
   Scoped to action clusters so the shell's neutral icon buttons — topbar,
   sidebar — keep their quiet chrome. The danger variant still wins. */
:is(.table-actions, .map-form) .icon-btn:not(.icon-btn--danger) {
  border-color: color-mix(in srgb, var(--act, var(--edge)) 55%, var(--line-strong));
  color: color-mix(in srgb, var(--act, var(--edge)) 60%, var(--text-muted));
}
:is(.table-actions, .map-form) .icon-btn:hover:not(.icon-btn--danger) {
  color: var(--act, var(--edge));
  border-color: var(--act, var(--edge));
  background: color-mix(in srgb, var(--act, var(--edge)) 12%, var(--surface));
}

/* ---- In-table editors and the month switcher --------------------------
   .map-form: a control + save button living inside a fixed-layout table
   cell (Billing Items' Books-item select, Payouts' fee input): the pair
   flexes to its column and never past it (min-width: 0 lets the control
   shrink; long option names ellipsize). .month-nav is the same cluster
   in a card head (prev / month input / view / next). Both match the
   .field control chrome at table density. */
.map-form, .month-nav { display: flex; align-items: center; gap: 0.4rem; }
.map-form :is(select, input),
.month-nav input {
  flex: 1 1 auto;
  min-width: 0;
  font: inherit;
  font-size: 0.82rem;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  padding: 0.34rem 0.5rem;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.month-nav input { flex: 0 1 auto; }
.month-nav .btn { flex: none; white-space: nowrap; }
.map-form :is(select, input):focus,
.month-nav input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--ring);
}

/* Columns that are nice to have but first to go when width tightens —
   keeps admin tables fitting without a horizontal scrollbar. The
   breakpoint is viewport-based, so it accounts for the 264px sidebar
   eating into the content column. */
@media (max-width: 1500px) {
  .data-table .col-roomy { display: none; }
}

/* ---- Reveal stagger ranks -------------------------------------------
   Replace style="--i:N" (.reveal consumes --i via animation-delay).
   Usage: class="card reveal r2". */
.r0 { --i: 0; }
.r1 { --i: 1; }
.r2 { --i: 2; }
.r3 { --i: 3; }
.r4 { --i: 4; }
.r5 { --i: 5; }
.r6 { --i: 6; }
.r7 { --i: 7; }
.r8 { --i: 8; }
/* Loop-rendered siblings: the container assigns ranks; items past the
   fifth arrive together rather than queueing indefinitely. */
.reveal-seq > .reveal:nth-child(1) { --i: 1; }
.reveal-seq > .reveal:nth-child(2) { --i: 2; }
.reveal-seq > .reveal:nth-child(3) { --i: 3; }
.reveal-seq > .reveal:nth-child(4) { --i: 4; }
.reveal-seq > .reveal:nth-child(n+5) { --i: 5; }

/* ---- Content flow ---------------------------------------------------
   Vertical rhythm inside a card body / conditional block; one class on
   the container replaces per-element inline margin-tops. */
.flow > * + * { margin-top: var(--flow, 0.9rem); }
.flow--tight { --flow: 0.45rem; }

/* ---- Form & row layout modifiers ------------------------------------ */
/* A form displayed as its own block under preceding text (was
   .inline-form + inline display:block overrides). */
.form-block { display: block; margin: 0.9rem 0 0; }
/* Submit/cancel action row at the end of a form. */
.form-actions {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  flex-wrap: wrap;
  margin-top: 1.1rem;
}
/* Space-between split row (card feet, list rows). */
.row-split {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}
/* Card foot variants. */
.card__foot--flush { border-top: 0; padding-top: 0; margin-top: 0.75rem; }
.card__foot--links { display: flex; gap: 1.1rem; flex-wrap: wrap; }
.card__action--muted { color: var(--text-muted); }
/* The row owns its bottom spacing; fields inside stop double-spacing. */
.field-row { margin-bottom: 1.05rem; }
.field-row > .field { margin-bottom: 0; }
.field-row--end { align-items: flex-end; }
/* Field width/rhythm modifiers. */
.field--tight { margin-bottom: 0.75rem; }
.field--w9 { flex: 0 0 9rem; }
.field--w11 { flex: 0 0 11rem; }
/* Empty-state CTA button clears the copy above it. */
.empty__body .btn { margin-top: 0.6rem; }
/* Wide content that scrolls sideways without .table-wrap's chrome. */
.scroll-x { overflow-x: auto; }
/* Margin-top scale for true one-offs (prefer the component fixes above). */
.mt-xs { margin-top: 0.35rem; }
.mt-sm { margin-top: 0.6rem; }
.mt-md { margin-top: 0.9rem; }
.mt-lg { margin-top: 1.25rem; }

/* ---- Section sub-nav (org settings tabs) ---------------------------- */
.subnav {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.15rem;
  border-bottom: 1px solid var(--line-strong);
}
.subnav__link {
  padding: 0.5rem 0.8rem 0.6rem;
  font-size: 0.88rem;
  font-weight: 550;
  color: var(--text-2);
  white-space: nowrap;
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
}
.subnav__link:hover {
  color: var(--text);
  background: var(--surface-sunken);
  text-decoration: none;
}
.subnav__link--active {
  color: var(--accent);
  box-shadow: inset 0 -2px 0 var(--accent);
}

/* ---- Rotating edge palette ------------------------------------------
   Containers pick their border hue from their position among siblings,
   so pages read colorful but deterministic: cobalt, teal, violet, rose,
   repeat. Zero-specificity :where() keeps every status variant
   (.card--ok, .stat--warn, row .is-crit...) winning unchanged, and the
   --edge variable inherits into the container's rows/tables/empty
   states so each card's contents match its border. */
:where(.card, .stat, .course-card):nth-child(4n+2) { --edge: var(--edge-teal); }
:where(.card, .stat, .course-card):nth-child(4n+3) { --edge: var(--edge-violet); }
:where(.card, .stat, .course-card):nth-child(4n) { --edge: var(--edge-rose); }

/* Explicit edge picks for cards that sit alone (or first) in their
   wrapper — sibling-position rotation can't reach those, so without an
   override every one of them falls back to cobalt. Single-class
   specificity beats the :where() rotation but stays under the status
   variants, which set border-color directly. */
.edge-cobalt { --edge: var(--accent); }
.edge-teal { --edge: var(--edge-teal); }
.edge-violet { --edge: var(--edge-violet); }
.edge-rose { --edge: var(--edge-rose); }

/* ---- Card-internal rhythm -------------------------------------------
   A row list that follows other card content (an add form, intro text,
   a table) gets breathing room; adjacent margins collapse, so lists at
   natural positions don't double-space. */
.card > * + .detail-list,
.card > * + .membership-list,
.card > * + .empty { margin-top: 1.15rem; }

/* =====================================================================
   Command palette (Cmd+K) — instant navigation over the sidebar links
   ===================================================================== */
.cmdk {
  border: 0;
  padding: 0;
  width: min(560px, 92vw);
  background: transparent;
  color: var(--text);
  overflow: visible;
}
.cmdk::backdrop {
  background: rgba(16, 20, 30, 0.5);
  backdrop-filter: blur(3px);
}
.cmdk__panel {
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: 14px;
  box-shadow: var(--shadow-xl);
  overflow: hidden;
}
.cmdk__input {
  width: 100%;
  border: 0;
  border-bottom: 1px solid var(--line);
  border-radius: 0;
  background: transparent;
  color: var(--text);
  font: 500 1rem/1.4 var(--font-ui);
  padding: 0.95rem 1.1rem;
  outline: none;
}
.cmdk__input::placeholder { color: var(--text-muted); }
.cmdk__list {
  max-height: 330px;
  overflow-y: auto;
  margin: 0;
  padding: 0.45rem;
  list-style: none;
}
.cmdk__group-label {
  padding: 0.5rem 0.65rem 0.25rem;
  font-family: var(--font-mono);
  font-size: 0.6rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.cmdk__item {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.55rem 0.65rem;
  border-radius: 8px;
  color: var(--text);
  font-size: 0.9rem;
  cursor: pointer;
}
.cmdk__item svg { width: 17px; height: 17px; flex: none; color: var(--text-muted); }
.cmdk__item.is-active { background: var(--accent-weak); color: var(--accent-hover); }
.cmdk__item.is-active svg { color: var(--accent-hover); }
.cmdk__empty { padding: 1.1rem; color: var(--text-muted); font-size: 0.9rem; text-align: center; }
.cmdk__hint {
  display: flex;
  gap: 0.9rem;
  padding: 0.55rem 1.05rem;
  border-top: 1px solid var(--line);
  color: var(--text-muted);
  font-size: 0.72rem;
}
.cmdk__hint span { display: inline-flex; align-items: center; gap: 0.35rem; }
.cmdk[open] { animation: modalpop 0.16s cubic-bezier(.2,.7,.3,1); }

/* =====================================================================
   Theme-scoped display helpers (brand images ship light + dark variants)
   ===================================================================== */
.theme-dark-only { display: none; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .theme-light-only { display: none; }
  :root:not([data-theme="light"]) .theme-dark-only { display: block; }
}
:root[data-theme="dark"] .theme-light-only { display: none; }
:root[data-theme="dark"] .theme-dark-only { display: block; }

/* =====================================================================
   KPI additions — icon slot and trend delta for stat tiles
   ===================================================================== */
.stat__row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.6rem;
}
.stat__icon {
  width: 34px;
  height: 34px;
  border-radius: 9px;
  display: grid;
  place-items: center;
  background: var(--accent-weak);
  color: var(--accent);
  flex: none;
}
.stat__icon svg { width: 18px; height: 18px; }
.stat__delta {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-variant-numeric: tabular-nums;
  border-radius: 999px;
  padding: 0.18rem 0.5rem;
  white-space: nowrap;
}
.stat__delta svg { width: 12px; height: 12px; }
.stat__delta--up { color: var(--ok); background: var(--ok-bg); }
.stat__delta--down { color: var(--crit); background: var(--crit-bg); }
.stat__delta--flat { color: var(--text-muted); background: var(--surface-sunken); }

/* Chart container: fixed height so canvas-based charts can't collapse
   or grow unbounded. */
.chart-card__canvas { position: relative; height: 260px; }

/* =====================================================================
   Platform hub — KPI foot row, hub columns, activity feed, system list
   ===================================================================== */
.stat__foot {
  margin-top: 0.55rem;
  display: flex;
  align-items: center;
  gap: 0.55rem;
  flex-wrap: wrap;
}
.stat__foot .stat__hint { margin-top: 0; }

.hub-cols {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem;
  align-items: start;
}
.hub-cols--wide-left { grid-template-columns: 1.6fr 1fr; }
@media (max-width: 1020px) {
  .hub-cols,
  .hub-cols--wide-left { grid-template-columns: 1fr; }
}

/* Activity feed — icon-led event rows inside a card. */
.feed { list-style: none; margin: 0; padding: 0; }
.feed__item {
  display: flex;
  align-items: flex-start;
  gap: 0.7rem;
  padding: 0.6rem 0;
  border-top: 1px solid var(--line);
}
.feed__item:first-child { border-top: 0; padding-top: 0.15rem; }
.feed__icon {
  width: 28px;
  height: 28px;
  border-radius: 8px;
  display: grid;
  place-items: center;
  background: var(--accent-weak);
  color: var(--accent);
  flex: none;
  margin-top: 0.1rem;
}
.feed__icon svg { width: 14px; height: 14px; }
.feed__title { margin: 0; font-size: 0.9rem; font-weight: 560; color: var(--text); }
.feed__title a { color: inherit; text-decoration: none; }
.feed__title a:hover,
.feed__title a:focus-visible { color: var(--accent); text-decoration: underline; }
.feed__meta { margin: 0.1rem 0 0; font-size: 0.76rem; color: var(--text-muted); }

/* System list — label/value counters. */
.syslist { list-style: none; margin: 0; padding: 0; }
.syslist__item {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.55rem 0;
  border-top: 1px solid var(--line);
}
.syslist__item:first-child { border-top: 0; padding-top: 0.15rem; }
.syslist__icon {
  width: 26px;
  height: 26px;
  border-radius: 7px;
  display: grid;
  place-items: center;
  background: var(--surface-sunken);
  color: var(--text-muted);
  flex: none;
}
.syslist__icon svg { width: 14px; height: 14px; }
.syslist__label { font-size: 0.86rem; color: var(--text-2); }
.syslist__value {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: 0.92rem;
  font-weight: 640;
  font-variant-numeric: tabular-nums;
  color: var(--text);
}

/* Equal-height row: the clamped card contributes no intrinsic height, so
   the row sizes to its sibling (the System list) and the feed scrolls
   inside the leftover space. Wide screens only — stacked cards keep
   their natural height. */
@media (min-width: 1021px) {
  .hub-cols--wide-left { align-items: stretch; }
  .card--clamp {
    display: flex;
    flex-direction: column;
    height: 0;
    min-height: 100%;
    overflow: hidden;
  }
  .card--clamp .feed {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    scrollbar-width: thin;
  }
}
