/* =============================================================================
   PrimeTanki Control — "Modern Blue Ops" design system
   -----------------------------------------------------------------------------
   Single hand-written stylesheet. No framework, no build step, no CDN.
   Every colour, size, radius and shadow used by a component comes from a token.

   Reading order:
     01  Fonts
     02  Primitive tokens (raw palette + scales — never used directly by components)
     03  Semantic tokens (dark = default, light mapping ready for later)
     04  Reset & base elements
     05  Utilities
     06  App shell (rail, topbar, env banner, main, footer)
     07  Page header / section
     08  Panels, cards, stat tiles, key-value lists
     09  Dense data table  <- the density anchor; other components sized around it
     10  Forms & inputs
     11  Buttons
     12  Badges, tier chips, status dots, meters, tabs, toolbar, pagination
     13  States: empty / loading / error / forbidden / degraded / banners
     14  Toasts, modal, drawer, tooltip, kbd hints
     15  Command palette
     16  Styleguide-only helpers
     17  Responsive + motion + print

   Design rules baked in (owner direction, 2026-07-26):
     - COMPACT. 13px base, 32px table rows, 4px spacing unit. Density is a
       requirement. If something feels roomy, it is wrong.
     - MODERN. Linear / Vercel / Grafana feel: hairline borders, 6px radii,
       layered surfaces instead of heavy shadows, quiet micro-interactions.
     - BLUE. Blue-slate surfaces by elevation, vivid blue primary, sky secondary.
     - Amber + red are RESERVED for mutation actions (reversible / irreversible).
       They never appear as decoration on read-only observation screens.
       The single exception is --env-live-*, because "you are on the live game"
       is a genuine danger semantic, not decoration.
     - No military/stencil styling, no hazard stripes, no bevels, no gradients
       as chrome, nothing echoing the Flash-era game UI.
   ========================================================================== */


/* == 01  Fonts ============================================================= */
/* Self-hosted. Zero external requests (CSP-safe, works offline on the VPS).   */
@font-face {
  font-family: 'InterVar';
  font-style: normal;
  font-weight: 400 900;
  font-display: swap;
  src: url('../fonts/inter-var-latin.woff2') format('woff2');
}


/* == 02  Primitive tokens ================================================== */
/* Raw values. Components must NOT reference these directly — only section 03. */
:root {
  /* --- blue-slate neutral ramp (the surfaces + the text) ------------------ */
  --c-slate-1000: #05080d;
  --c-slate-950:  #080c13;
  --c-slate-900:  #0b111a;
  --c-slate-850:  #0f1621;
  --c-slate-800:  #131c29;
  --c-slate-750:  #182233;
  --c-slate-700:  #1e2a3d;
  --c-slate-650:  #24344a;
  --c-slate-600:  #2d4059;
  --c-slate-500:  #3d5573;
  --c-slate-400:  #587294;
  --c-slate-350:  #6d87a8;
  --c-slate-300:  #8ba3c0;
  --c-slate-250:  #a3b8d0;
  --c-slate-200:  #c0cfe0;
  --c-slate-150:  #d6e0ec;
  --c-slate-100:  #e7edf5;
  --c-slate-50:   #f3f7fb;
  --c-white:      #ffffff;

  /* --- blue: the primary accent, carries identity ------------------------ */
  --c-blue-200: #bfd8ff;
  --c-blue-300: #93bcff;
  --c-blue-400: #63a0fb;
  --c-blue-500: #3b82f6;
  --c-blue-600: #2563eb;
  --c-blue-700: #1d4ed8;
  --c-blue-800: #1a3a94;
  --c-blue-900: #14275c;
  --c-blue-950: #0e1c40;

  /* --- sky/cyan: secondary highlight, links, focus ----------------------- */
  --c-sky-300: #7dd3fc;
  --c-sky-400: #38bdf8;
  --c-sky-500: #0ea5e9;
  --c-sky-700: #0b5f86;
  --c-sky-900: #082f45;

  /* --- indigo / violet / teal: tier identity only ------------------------ */
  --c-violet-300: #c4b5fd;
  --c-violet-400: #a78bfa;
  --c-violet-900: #2c2258;
  --c-indigo-300: #a5b4fc;
  --c-indigo-400: #818cf8;
  --c-indigo-900: #26295e;
  --c-teal-300:   #5eead4;
  --c-teal-400:   #2dd4bf;
  --c-teal-900:   #0c3b39;

  /* --- action colours: RESERVED (see header note) ------------------------ */
  --c-amber-300: #fcd34d;
  --c-amber-400: #fbbf24;
  --c-amber-500: #f59e0b;
  --c-amber-700: #b45309;
  --c-amber-900: #402b06;
  --c-red-300:   #fca5a5;
  --c-red-400:   #f87171;
  --c-red-500:   #ef4444;
  --c-red-600:   #dc2626;
  --c-red-700:   #b91c1c;
  --c-red-900:   #3d1113;
  --c-green-300: #86efac;
  --c-green-400: #4ade80;
  --c-green-500: #22c55e;
  --c-green-700: #15803d;
  --c-green-900: #0b3520;

  /* --- typography -------------------------------------------------------- */
  --font-sans: 'InterVar', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
               'Helvetica Neue', Arial, sans-serif;
  --font-mono: ui-monospace, 'SFMono-Regular', 'Cascadia Mono', 'Segoe UI Mono',
               'JetBrains Mono', Consolas, 'Liberation Mono', monospace;

  --fs-3xs: 0.625rem;   /* 10px — micro caps labels */
  --fs-2xs: 0.6875rem;  /* 11px — table micro meta, chips */
  --fs-xs:  0.75rem;    /* 12px — table cells, hints */
  --fs-sm:  0.8125rem;  /* 13px — BASE UI SIZE */
  --fs-md:  0.875rem;   /* 14px — emphasised body */
  --fs-lg:  1rem;       /* 16px — panel titles */
  --fs-xl:  1.1875rem;  /* 19px — page titles */
  --fs-2xl: 1.4375rem;  /* 23px — stat figures */
  --fs-3xl: 1.75rem;    /* 28px — hero figures only */

  --lh-tight:  1.2;
  --lh-snug:   1.35;
  --lh-normal: 1.5;

  --fw-regular:  400;
  --fw-medium:   500;
  --fw-semibold: 600;
  --fw-bold:     700;

  --ls-caps:  0.06em;
  --ls-tight: -0.011em;

  /* --- spacing: 4px unit ------------------------------------------------- */
  --sp-0:   0;
  --sp-05:  2px;
  --sp-1:   4px;
  --sp-15:  6px;
  --sp-2:   8px;
  --sp-3:   12px;
  --sp-4:   16px;
  --sp-5:   20px;
  --sp-6:   24px;
  --sp-8:   32px;
  --sp-10:  40px;
  --sp-12:  48px;
  --sp-16:  64px;

  /* --- radii ------------------------------------------------------------- */
  --radius-xs:   3px;
  --radius-sm:   4px;
  --radius-md:   6px;   /* default */
  --radius-lg:   8px;
  --radius-xl:   12px;
  --radius-full: 999px;

  /* --- fixed layout metrics (density anchors) ---------------------------- */
  --rail-w:          216px;
  --rail-w-collapsed: 52px;
  --topbar-h:        44px;
  --envstrip-h:      2px;
  --row-h:           32px;   /* dense table row — the anchor for everything */
  --row-h-compact:   28px;
  --row-h-roomy:     36px;
  --control-h:       28px;   /* inputs & buttons */
  --control-h-sm:    24px;
  --control-h-lg:    32px;
  --content-max:     1680px;

  /* --- z layers ---------------------------------------------------------- */
  --z-base:     0;
  --z-sticky:   100;
  --z-rail:     200;
  --z-topbar:   300;
  --z-dropdown: 400;
  --z-drawer:   500;
  --z-modal:    600;
  --z-toast:    700;
  --z-palette:  800;
  --z-tooltip:  900;

  /* --- motion ------------------------------------------------------------ */
  --dur-fast: 90ms;
  --dur-med:  150ms;
  --dur-slow: 240ms;
  --ease:     cubic-bezier(0.2, 0, 0.15, 1);
}


/* == 03  Semantic tokens =================================================== */
/* Components use ONLY these. Re-map this block to add a theme; do not touch
   component rules. Dark is the default (:root); light is a full mapping.      */
:root,
:root[data-theme='dark'] {
  color-scheme: dark;

  /* surfaces, by elevation */
  --bg-canvas:      var(--c-slate-1000);  /* the page behind everything */
  --surface-1:      var(--c-slate-900);   /* app chrome: rail, topbar */
  --surface-2:      var(--c-slate-850);   /* panels, cards, table head */
  --surface-3:      var(--c-slate-800);   /* raised: dropdown, modal, drawer */
  --surface-4:      var(--c-slate-750);   /* highest: palette, tooltip */
  --surface-sunken: var(--c-slate-950);   /* inputs, code, wells */
  --surface-hover:  rgba(99, 160, 251, 0.07);
  --surface-active: rgba(99, 160, 251, 0.13);
  --surface-selected: rgba(59, 130, 246, 0.14);

  /* text — four levels, ALL of them WCAG AA on every surface token above.
     Measured against --surface-3 (the lightest surface) which is the worst
     case: primary 14.9:1, secondary 11.1:1, muted 8.6:1, faint 4.7:1.
     --c-slate-400 and below are decorative only — never text. */
  --text-primary:   var(--c-slate-100);
  --text-secondary: var(--c-slate-200);
  --text-muted:     var(--c-slate-250);
  --text-faint:     var(--c-slate-350);
  --text-inverse:   var(--c-slate-1000);
  --text-on-accent: var(--c-white);
  --text-link:      var(--c-sky-400);
  --text-link-hover: var(--c-sky-300);

  /* borders */
  --border-subtle:  rgba(148, 178, 216, 0.10);
  --border-default: rgba(148, 178, 216, 0.16);
  --border-strong:  rgba(148, 178, 216, 0.28);
  --border-accent:  var(--c-blue-600);

  /* accent (primary blue) */
  --accent:          var(--c-blue-500);
  --accent-strong:   var(--c-blue-600);
  --accent-stronger: var(--c-blue-700);
  --accent-text:     var(--c-blue-300);
  --accent-soft-bg:  rgba(59, 130, 246, 0.14);
  --accent-soft-bd:  rgba(59, 130, 246, 0.34);

  /* secondary (sky) — highlights, links, focus */
  --highlight:         var(--c-sky-400);
  --highlight-text:    var(--c-sky-300);
  --highlight-soft-bg: rgba(56, 189, 248, 0.13);
  --highlight-soft-bd: rgba(56, 189, 248, 0.32);

  /* observation surface — the calm default for read-only screens */
  --observe-bg: rgba(120, 155, 200, 0.055);
  --observe-bd: rgba(148, 178, 216, 0.16);
  --observe-tx: var(--c-slate-250);

  /* mutation: reversible (amber) — RESERVED for action surfaces */
  --warn:         var(--c-amber-500);
  --warn-text:    var(--c-amber-300);
  --warn-bg:      rgba(245, 158, 11, 0.12);
  --warn-bd:      rgba(245, 158, 11, 0.38);
  --warn-solid:   var(--c-amber-500);
  --warn-on-solid: #241704;

  /* mutation: irreversible (red) — RESERVED for destructive actions */
  --danger:         var(--c-red-500);
  --danger-text:    var(--c-red-300);
  --danger-bg:      rgba(239, 68, 68, 0.12);
  --danger-bd:      rgba(239, 68, 68, 0.40);
  --danger-solid:   var(--c-red-600);
  --danger-solid-hover: var(--c-red-700);
  --danger-on-solid: var(--c-white);

  /* confirmed (green) */
  --success:      var(--c-green-500);
  --success-text: var(--c-green-300);
  --success-bg:   rgba(34, 197, 94, 0.12);
  --success-bd:   rgba(34, 197, 94, 0.36);

  /* informational (blue) */
  --info-text: var(--c-blue-300);
  --info-bg:   rgba(59, 130, 246, 0.12);
  --info-bd:   rgba(59, 130, 246, 0.34);

  /* neutral chip */
  --neutral-text: var(--c-slate-250);
  --neutral-bg:   rgba(148, 178, 216, 0.10);
  --neutral-bd:   rgba(148, 178, 216, 0.20);

  /* environment banner (the one sanctioned non-action use of red) */
  --env-test-text: var(--c-sky-300);
  --env-test-bg:   rgba(56, 189, 248, 0.14);
  --env-test-bd:   rgba(56, 189, 248, 0.42);
  --env-test-line: var(--c-sky-500);
  --env-live-text: var(--c-red-300);
  --env-live-bg:   rgba(239, 68, 68, 0.16);
  --env-live-bd:   rgba(239, 68, 68, 0.48);
  --env-live-line: var(--c-red-500);

  /* staff authority tiers — cool hues only (amber/red stay reserved).
     Higher tier = more saturated + more violet. Lower tier = muted steel. */
  --tier-100-text: var(--c-violet-300); --tier-100-bg: rgba(167,139,250,0.16); --tier-100-bd: rgba(167,139,250,0.40);
  --tier-90-text:  var(--c-indigo-300); --tier-90-bg:  rgba(129,140,248,0.15); --tier-90-bd:  rgba(129,140,248,0.38);
  --tier-85-text:  var(--c-blue-300);   --tier-85-bg:  rgba(99,160,251,0.15);  --tier-85-bd:  rgba(99,160,251,0.38);
  --tier-70-text:  var(--c-sky-300);    --tier-70-bg:  rgba(56,189,248,0.14);  --tier-70-bd:  rgba(56,189,248,0.36);
  --tier-60-text:  var(--c-teal-300);   --tier-60-bg:  rgba(45,212,191,0.13);  --tier-60-bd:  rgba(45,212,191,0.34);
  --tier-50-text:  var(--c-teal-300);   --tier-50-bg:  rgba(45,212,191,0.10);  --tier-50-bd:  rgba(45,212,191,0.26);
  --tier-40-text:  var(--c-slate-200);  --tier-40-bg:  rgba(148,178,216,0.12); --tier-40-bd:  rgba(148,178,216,0.26);
  --tier-30-text:  var(--c-slate-250);  --tier-30-bg:  rgba(148,178,216,0.09);  --tier-30-bd:  rgba(148,178,216,0.20);
  --tier-20-text:  var(--c-slate-300);  --tier-20-bg:  rgba(148,178,216,0.07);  --tier-20-bd:  rgba(148,178,216,0.18);
  --tier-10-text:  var(--c-slate-350);  --tier-10-bg:  rgba(148,178,216,0.06);  --tier-10-bd:  rgba(148,178,216,0.16);

  /* elevation — subtle, layered, never a "card float" */
  --shadow-xs: 0 1px 1px rgba(0, 0, 0, 0.30);
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.36), 0 0 0 1px rgba(0, 0, 0, 0.18);
  --shadow-md: 0 6px 18px -6px rgba(0, 0, 0, 0.55), 0 0 0 1px rgba(0, 0, 0, 0.22);
  --shadow-lg: 0 24px 56px -16px rgba(0, 0, 0, 0.68), 0 0 0 1px rgba(0, 0, 0, 0.28);
  --shadow-inset: inset 0 1px 0 rgba(255, 255, 255, 0.03);

  /* focus */
  --focus-color: var(--c-sky-400);
  --focus-ring:  0 0 0 2px var(--bg-canvas), 0 0 0 4px var(--focus-color);
  --focus-width: 2px;

  /* skeleton shimmer */
  --skeleton-base:  rgba(148, 178, 216, 0.07);
  --skeleton-shine: rgba(148, 178, 216, 0.14);

  /* scrollbars */
  --scroll-thumb: rgba(148, 178, 216, 0.20);
  --scroll-track: transparent;
}

/* Light theme — the same semantic names, remapped. Components need no change.
   Not shipped as a user-facing toggle in phase 1; it exists to prove the token
   layer is theme-clean. */
:root[data-theme='light'] {
  color-scheme: light;

  --bg-canvas:      #eef2f8;
  --surface-1:      #ffffff;
  --surface-2:      #ffffff;
  --surface-3:      #ffffff;
  --surface-4:      #ffffff;
  --surface-sunken: #f4f7fb;
  --surface-hover:  rgba(37, 99, 235, 0.06);
  --surface-active: rgba(37, 99, 235, 0.10);
  --surface-selected: rgba(37, 99, 235, 0.09);

  --text-primary:   #0b1622;
  --text-secondary: #37485e;
  --text-muted:     #55697f;
  --text-faint:     #71849a;
  --text-inverse:   #ffffff;
  --text-on-accent: #ffffff;
  --text-link:      #1258c8;
  --text-link-hover: #0e47a1;

  --border-subtle:  rgba(15, 32, 55, 0.09);
  --border-default: rgba(15, 32, 55, 0.15);
  --border-strong:  rgba(15, 32, 55, 0.28);
  --border-accent:  var(--c-blue-600);

  --accent:          var(--c-blue-600);
  --accent-strong:   var(--c-blue-600);
  --accent-stronger: var(--c-blue-700);
  --accent-text:     #1550c0;
  --accent-soft-bg:  rgba(37, 99, 235, 0.09);
  --accent-soft-bd:  rgba(37, 99, 235, 0.28);

  --highlight:         var(--c-sky-500);
  --highlight-text:    #0b6a94;
  --highlight-soft-bg: rgba(14, 165, 233, 0.10);
  --highlight-soft-bd: rgba(14, 165, 233, 0.30);

  --observe-bg: rgba(15, 32, 55, 0.025);
  --observe-bd: rgba(15, 32, 55, 0.12);
  --observe-tx: #37485e;

  --warn-text:    #8a5307;
  --warn-bg:      rgba(245, 158, 11, 0.14);
  --warn-bd:      rgba(180, 83, 9, 0.42);
  --warn-on-solid: #241704;

  --danger-text:  #a51616;
  --danger-bg:    rgba(220, 38, 38, 0.10);
  --danger-bd:    rgba(185, 28, 28, 0.38);

  --success-text: #15703a;
  --success-bg:   rgba(34, 197, 94, 0.13);
  --success-bd:   rgba(21, 128, 61, 0.36);

  --info-text: #1550c0;
  --info-bg:   rgba(37, 99, 235, 0.09);
  --info-bd:   rgba(37, 99, 235, 0.28);

  --neutral-text: #37485e;
  --neutral-bg:   rgba(15, 32, 55, 0.055);
  --neutral-bd:   rgba(15, 32, 55, 0.14);

  --env-test-text: #0b6a94;
  --env-test-bg:   rgba(14, 165, 233, 0.13);
  --env-test-bd:   rgba(14, 165, 233, 0.40);
  --env-live-text: #a51616;
  --env-live-bg:   rgba(220, 38, 38, 0.12);
  --env-live-bd:   rgba(185, 28, 28, 0.42);

  --tier-100-text: #5b32c4; --tier-100-bg: rgba(124,58,237,0.11); --tier-100-bd: rgba(124,58,237,0.30);
  --tier-90-text:  #3a41b8; --tier-90-bg:  rgba(79,70,229,0.10);  --tier-90-bd:  rgba(79,70,229,0.28);
  --tier-85-text:  #1550c0; --tier-85-bg:  rgba(37,99,235,0.09);  --tier-85-bd:  rgba(37,99,235,0.26);
  --tier-70-text:  #0b6a94; --tier-70-bg:  rgba(14,165,233,0.10); --tier-70-bd:  rgba(14,165,233,0.28);
  --tier-60-text:  #0a6b62; --tier-60-bg:  rgba(13,148,136,0.10); --tier-60-bd:  rgba(13,148,136,0.26);
  --tier-50-text:  #0a6b62; --tier-50-bg:  rgba(13,148,136,0.07); --tier-50-bd:  rgba(13,148,136,0.20);
  --tier-40-text:  #37485e; --tier-40-bg:  rgba(15,32,55,0.06);   --tier-40-bd:  rgba(15,32,55,0.16);
  --tier-30-text:  #45596f; --tier-30-bg:  rgba(15,32,55,0.05);   --tier-30-bd:  rgba(15,32,55,0.14);
  --tier-20-text:  #55697f; --tier-20-bg:  rgba(15,32,55,0.04);   --tier-20-bd:  rgba(15,32,55,0.12);
  --tier-10-text:  #55697f; --tier-10-bg:  rgba(15,32,55,0.03);   --tier-10-bd:  rgba(15,32,55,0.11);

  --shadow-xs: 0 1px 1px rgba(15, 32, 55, 0.06);
  --shadow-sm: 0 1px 2px rgba(15, 32, 55, 0.08), 0 0 0 1px rgba(15, 32, 55, 0.04);
  --shadow-md: 0 8px 20px -8px rgba(15, 32, 55, 0.20), 0 0 0 1px rgba(15, 32, 55, 0.06);
  --shadow-lg: 0 24px 56px -16px rgba(15, 32, 55, 0.28), 0 0 0 1px rgba(15, 32, 55, 0.08);
  --shadow-inset: none;

  --focus-color: var(--c-blue-600);

  --skeleton-base:  rgba(15, 32, 55, 0.06);
  --skeleton-shine: rgba(15, 32, 55, 0.11);

  --scroll-thumb: rgba(15, 32, 55, 0.22);
}


/* == 04  Reset & base ====================================================== */
*, *::before, *::after { box-sizing: border-box; }

html {
  font-size: 16px;              /* keep rem honest for user zoom/a11y */
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  min-height: 100vh;
  background: var(--bg-canvas);
  color: var(--text-primary);
  font-family: var(--font-sans);
  font-size: var(--fs-sm);
  line-height: var(--lh-normal);
  letter-spacing: var(--ls-tight);
  font-feature-settings: 'cv05' 1, 'ss03' 1;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

h1, h2, h3, h4, h5, h6, p, figure, ul, ol, dl, dd { margin: 0; }
ul, ol { padding: 0; list-style: none; }

h1 { font-size: var(--fs-xl); line-height: var(--lh-tight); font-weight: var(--fw-semibold); }
h2 { font-size: var(--fs-lg); line-height: var(--lh-snug); font-weight: var(--fw-semibold); }
h3 { font-size: var(--fs-md); line-height: var(--lh-snug); font-weight: var(--fw-semibold); }
h4 { font-size: var(--fs-sm); line-height: var(--lh-snug); font-weight: var(--fw-semibold); }

a {
  color: var(--text-link);
  text-decoration: none;
  border-radius: var(--radius-xs);
}
a:hover { color: var(--text-link-hover); text-decoration: underline; text-underline-offset: 2px; }

code, kbd, samp, pre, .mono {
  font-family: var(--font-mono);
  font-size: 0.92em;
  font-variant-ligatures: none;
}

hr {
  border: 0;
  border-top: 1px solid var(--border-subtle);
  margin: var(--sp-4) 0;
}

img, svg { display: block; max-width: 100%; }
button, input, select, textarea { font: inherit; letter-spacing: inherit; color: inherit; }

/* One focus treatment everywhere. Always visible for keyboard users. */
:focus-visible {
  outline: var(--focus-width) solid var(--focus-color);
  outline-offset: 2px;
}
:focus:not(:focus-visible) { outline: none; }

::selection { background: var(--accent-soft-bg); color: var(--text-primary); }

/* Scrollbars: thin, quiet, blue-neutral. */
* { scrollbar-width: thin; scrollbar-color: var(--scroll-thumb) var(--scroll-track); }
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-track { background: var(--scroll-track); }
*::-webkit-scrollbar-thumb {
  background: var(--scroll-thumb);
  border-radius: var(--radius-full);
  border: 3px solid transparent;
  background-clip: content-box;
}
*::-webkit-scrollbar-thumb:hover { background: var(--border-strong); background-clip: content-box; }


/* == 05  Utilities ========================================================= */
.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;
}

.skip-link {
  position: fixed; top: var(--sp-2); left: var(--sp-2);
  transform: translateY(-200%);
  z-index: var(--z-tooltip);
  background: var(--accent-strong);
  color: var(--text-on-accent);
  padding: var(--sp-2) var(--sp-3);
  border-radius: var(--radius-md);
  font-weight: var(--fw-semibold);
  box-shadow: var(--shadow-md);
  transition: transform var(--dur-fast) var(--ease);
}
.skip-link:focus { transform: translateY(0); text-decoration: none; }

.stack   { display: flex; flex-direction: column; gap: var(--sp-3); }
.stack-2 { display: flex; flex-direction: column; gap: var(--sp-2); }
.stack-4 { display: flex; flex-direction: column; gap: var(--sp-4); }
.row     { display: flex; align-items: center; gap: var(--sp-2); }
.row-3   { display: flex; align-items: center; gap: var(--sp-3); }
.row-wrap { flex-wrap: wrap; }
.spacer  { flex: 1 1 auto; }

.grid-2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-3); }
.grid-3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--sp-3); }
.grid-4 { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--sp-3); }

.text-primary   { color: var(--text-primary); }
.text-secondary { color: var(--text-secondary); }
.text-muted     { color: var(--text-muted); }
.text-faint     { color: var(--text-faint); }
.text-accent    { color: var(--accent-text); }
.text-warn      { color: var(--warn-text); }
.text-danger    { color: var(--danger-text); }
.text-success   { color: var(--success-text); }

.t-xs { font-size: var(--fs-xs); }
.t-sm { font-size: var(--fs-sm); }
.t-md { font-size: var(--fs-md); }
.t-semibold { font-weight: var(--fw-semibold); }
.t-right { text-align: right; }
.t-center { text-align: center; }

.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.nowrap   { white-space: nowrap; }

/* Numbers, ids, hashes: monospace + tabular so columns line up. */
.num, .mono, .id {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-xs);
  letter-spacing: 0;
}
.id { color: var(--text-muted); }

/* Micro section label ("OVERVIEW", "MODERATION"). Uppercase, never stencil. */
.eyebrow {
  font-size: var(--fs-3xs);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: var(--text-faint);
}

.divider { height: 1px; background: var(--border-subtle); margin: var(--sp-3) 0; }
.divider-v { width: 1px; align-self: stretch; background: var(--border-subtle); margin: 0 var(--sp-1); }

.icon { flex: none; display: block; }
.icon--inline { display: inline-block; vertical-align: -0.18em; }


/* == 06  App shell ========================================================= */
.app {
  display: grid;
  grid-template-columns: var(--rail-w) minmax(0, 1fr);
  grid-template-rows: 100vh;
  min-height: 100vh;
}
.app[data-rail='collapsed'] { grid-template-columns: var(--rail-w-collapsed) minmax(0, 1fr); }

/* --- environment strip: a 2px line across the very top of the app --------- */
.env-strip {
  position: fixed; inset: 0 0 auto 0;
  height: var(--envstrip-h);
  background: var(--env-test-line);
  z-index: var(--z-tooltip);
}
[data-env='live'] .env-strip { background: var(--env-live-line); }

/* --- left rail ------------------------------------------------------------ */
.rail {
  grid-row: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  background: var(--surface-1);
  border-right: 1px solid var(--border-subtle);
  z-index: var(--z-rail);
}

.rail__brand {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  height: var(--topbar-h);
  padding: 0 var(--sp-3);
  border-bottom: 1px solid var(--border-subtle);
  flex: none;
}
.rail__mark {
  width: 22px; height: 22px; flex: none;
  display: grid; place-items: center;
  border-radius: var(--radius-sm);
  background: var(--accent-strong);
  color: var(--text-on-accent);
}
.rail__wordmark {
  display: flex; flex-direction: column; line-height: 1.05; min-width: 0;
}
.rail__wordmark b {
  font-size: var(--fs-sm); font-weight: var(--fw-semibold); color: var(--text-primary);
  letter-spacing: 0.01em;
}
.rail__wordmark span {
  font-size: var(--fs-3xs); letter-spacing: var(--ls-caps);
  text-transform: uppercase; color: var(--text-faint);
}

.rail__nav {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  padding: var(--sp-2) var(--sp-15) var(--sp-4);
}

.nav-group { margin-bottom: var(--sp-1); }
.nav-group__label {
  padding: var(--sp-3) var(--sp-2) var(--sp-1);
  font-size: var(--fs-3xs);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: var(--text-faint);
}

.nav-item {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  height: 28px;
  padding: 0 var(--sp-2);
  border-radius: var(--radius-sm);
  color: var(--text-secondary);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  white-space: nowrap;
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.nav-item:hover { background: var(--surface-hover); color: var(--text-primary); text-decoration: none; }
.nav-item .icon { color: var(--text-faint); transition: color var(--dur-fast) var(--ease); }
.nav-item:hover .icon { color: var(--text-secondary); }

.nav-item.is-active {
  background: var(--accent-soft-bg);
  color: var(--text-primary);
  font-weight: var(--fw-semibold);
  box-shadow: inset 2px 0 0 var(--accent);
}
.nav-item.is-active .icon { color: var(--accent-text); }

/* "coming soon" sections: visibly quieter than live items, but still readable
   (no opacity dimming — that would drop them below AA). */
.nav-item.is-disabled {
  color: var(--text-faint);
  cursor: default;
  pointer-events: none;
}
.nav-item.is-disabled .icon { color: var(--text-faint); opacity: 0.7; }
.nav-item__count {
  margin-left: auto;
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-2xs);
  color: var(--text-muted);
  background: var(--neutral-bg);
  border-radius: var(--radius-full);
  padding: 0 var(--sp-15);
  line-height: 16px;
}
.nav-item__soon {
  margin-left: auto;
  font-size: var(--fs-3xs);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: var(--text-faint);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-xs);
  padding: 0 var(--sp-1);
  line-height: 14px;
}

.rail__foot {
  flex: none;
  border-top: 1px solid var(--border-subtle);
  padding: var(--sp-2) var(--sp-15);
}

/* collapsed rail: icons only */
.app[data-rail='collapsed'] .rail__wordmark,
.app[data-rail='collapsed'] .nav-group__label,
.app[data-rail='collapsed'] .nav-item span,
.app[data-rail='collapsed'] .nav-item__soon,
.app[data-rail='collapsed'] .rail__foot .staff-card__meta { display: none; }
.app[data-rail='collapsed'] .nav-item { justify-content: center; padding: 0; }

/* --- main column ---------------------------------------------------------- */
.main {
  grid-row: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
}

.topbar {
  flex: none;
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  height: var(--topbar-h);
  padding: 0 var(--sp-4) 0 var(--sp-3);
  background: var(--surface-1);
  border-bottom: 1px solid var(--border-subtle);
  position: sticky; top: 0;
  z-index: var(--z-topbar);
}

.env-pill {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-15);
  height: 22px;
  padding: 0 var(--sp-2);
  border-radius: var(--radius-sm);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: var(--env-test-text);
  background: var(--env-test-bg);
  border: 1px solid var(--env-test-bd);
  white-space: nowrap;
}
.env-pill__dot {
  width: 6px; height: 6px; border-radius: var(--radius-full);
  background: currentColor;
}
[data-env='live'] .env-pill {
  color: var(--env-live-text);
  background: var(--env-live-bg);
  border-color: var(--env-live-bd);
}
[data-env='live'] .env-pill__dot { animation: pulse-dot 2.4s var(--ease) infinite; }
@keyframes pulse-dot { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }

/* the palette trigger doubles as the global search box */
.topbar__search {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  height: var(--control-h);
  width: min(360px, 34vw);
  padding: 0 var(--sp-2);
  background: var(--surface-sunken);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  color: var(--text-muted);
  font-size: var(--fs-sm);
  cursor: pointer;
  text-align: left;
  transition: border-color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease);
}
.topbar__search:hover { border-color: var(--border-strong); background: var(--surface-2); }
.topbar__search .icon { color: var(--text-faint); }
.topbar__search .kbd-hint { margin-left: auto; }

.topbar__actions { display: flex; align-items: center; gap: var(--sp-1); margin-left: auto; }

/* icon button used in the topbar and panel headers */
.icon-btn {
  display: inline-grid; place-items: center;
  position: relative;
  width: var(--control-h); height: var(--control-h);
  border-radius: var(--radius-md);
  background: transparent;
  border: 1px solid transparent;
  color: var(--text-muted);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.icon-btn:hover { background: var(--surface-hover); color: var(--text-primary); }
.icon-btn[aria-expanded='true'] { background: var(--surface-active); color: var(--text-primary); }
.icon-btn__badge {
  position: absolute; top: 2px; right: 2px;
  min-width: 14px; height: 14px; padding: 0 3px;
  border-radius: var(--radius-full);
  background: var(--accent-strong);
  color: var(--text-on-accent);
  font-family: var(--font-mono);
  font-size: 9px; line-height: 14px; font-weight: var(--fw-bold);
  text-align: center;
  border: 2px solid var(--surface-1);
  box-sizing: content-box;
}

/* signed-in staff chip (topbar + rail footer) */
.staff-card {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-15) var(--sp-2);
  border-radius: var(--radius-md);
  background: transparent;
  border: 1px solid transparent;
  cursor: pointer;
  width: 100%;
  text-align: left;
  transition: background var(--dur-fast) var(--ease);
}
/* It is an <a href="/account">, so the global a:hover underline has to be undone. */
.staff-card:hover { background: var(--surface-hover); text-decoration: none; }
.avatar {
  width: 24px; height: 24px; flex: none;
  display: grid; place-items: center;
  border-radius: var(--radius-md);
  background: var(--accent-soft-bg);
  border: 1px solid var(--accent-soft-bd);
  color: var(--accent-text);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-bold);
  letter-spacing: 0;
}
.avatar--lg { width: 32px; height: 32px; font-size: var(--fs-xs); }
.staff-card__meta { min-width: 0; display: flex; flex-direction: column; line-height: 1.2; }
.staff-card__name { font-size: var(--fs-xs); font-weight: var(--fw-semibold); color: var(--text-primary); }
.staff-card__role { font-size: var(--fs-2xs); color: var(--text-muted); }

/* --- content + footer ----------------------------------------------------- */
.content {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  padding: var(--sp-4) var(--sp-5) var(--sp-8);
}
.content__inner { max-width: var(--content-max); margin: 0 auto; }

/* --- fill-height list screens --------------------------------------------
   A page whose main content is ONE long table opts in: <main class="content
   content--fill"> plus .panel--fill on the panel that owns the table. The panel
   is then the only element in the column allowed to SHRINK, so the table scrolls
   inside its own wrap, the sticky header stays pinned, and .content never gains
   a second scrollbar of its own.

   Why not viewport arithmetic: `max-height: calc(100vh - N)` has to guess how
   much chrome sits above the table, and that is not a constant. On /audit the
   filter disclosure alone moves it by ~250px between closed and open, so no
   single N is right in both states - which is how the first attempt at this
   ended up allowing 660px inside a 550px column and producing the exact nested
   scrollbars it was meant to remove. Flex measures instead of guessing. */
.content--fill { display: flex; flex-direction: column; }
.content--fill > .content__inner {
  /* width:100% because auto cross-margins suppress flex stretch - without it the
     column would collapse to fit-content and every page would go narrow. */
  width: 100%;
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
}
/* Pass the shrink through any wrapper between the column and the panel
   (templates/audit/list.html wraps its page in .stack). */
.content--fill > .content__inner > .stack { flex: 1 1 auto; min-height: 0; }
/* .flash-region centres itself with auto margins, which in a flex column means
   it stops stretching and shrink-wraps its text. It is already inside the
   centred column here, so it just takes the full width. */
.content--fill > .content__inner > .flash-region { width: 100%; margin-left: 0; margin-right: 0; }
/* 0 1 auto, not 1 1 auto: a short table keeps its natural height instead of
   stretching a half-empty panel to the bottom of the screen. It only shrinks,
   and only when there is not enough room. */
.panel--fill { flex: 0 1 auto; min-height: 0; display: flex; flex-direction: column; }
.panel--fill > .panel__body { flex: 0 1 auto; min-height: 0; display: flex; flex-direction: column; }
.panel--fill .table-wrap { flex: 0 1 auto; min-height: 0; max-height: none; }

.flash-region {
  display: flex; flex-direction: column; gap: var(--sp-2);
  max-width: var(--content-max); margin: 0 auto var(--sp-3);
}

.appfoot {
  flex: none;
  display: flex; align-items: center; gap: var(--sp-3);
  height: 28px;
  padding: 0 var(--sp-5);
  border-top: 1px solid var(--border-subtle);
  background: var(--surface-1);
  color: var(--text-faint);
  font-size: var(--fs-2xs);
}
.appfoot__sep { color: var(--border-strong); }


/* == 07  Page header ======================================================= */
.page-head {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-4);
  padding-bottom: var(--sp-3);
  margin-bottom: var(--sp-4);
  border-bottom: 1px solid var(--border-subtle);
}
.page-head__main { min-width: 0; flex: 1 1 auto; }
.page-head__crumbs {
  display: flex; align-items: center; gap: var(--sp-1);
  font-size: var(--fs-2xs); color: var(--text-faint); margin-bottom: var(--sp-1);
}
.page-head__crumbs a { color: var(--text-muted); }
.page-head__title { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }
.page-head__title h1 { letter-spacing: -0.015em; }
.page-head__sub { margin-top: var(--sp-1); font-size: var(--fs-xs); color: var(--text-muted); max-width: 78ch; }
.page-head__meta {
  display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap;
  margin-top: var(--sp-2); font-size: var(--fs-2xs); color: var(--text-faint);
}
.page-head__meta b { color: var(--text-secondary); font-weight: var(--fw-medium); }
.page-head__actions { display: flex; align-items: center; gap: var(--sp-2); flex: none; }

.section-head {
  display: flex; align-items: center; gap: var(--sp-2);
  margin: var(--sp-5) 0 var(--sp-2);
}
.section-head h2 { font-size: var(--fs-md); }


/* == 08  Panels, stats, key-values ========================================= */
.panel {
  background: var(--surface-2);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xs);
  overflow: hidden;
}
.panel + .panel { margin-top: var(--sp-3); }

.panel__head {
  display: flex; align-items: center; gap: var(--sp-2);
  min-height: 34px;
  padding: var(--sp-15) var(--sp-3);
  border-bottom: 1px solid var(--border-subtle);
  background: linear-gradient(0deg, transparent, transparent); /* flat by intent */
}
.panel__title {
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  color: var(--text-primary);
  display: flex; align-items: center; gap: var(--sp-15);
}
.panel__title .icon { color: var(--text-faint); }
.panel__hint { font-size: var(--fs-2xs); color: var(--text-faint); }
.panel__actions { margin-left: auto; display: flex; align-items: center; gap: var(--sp-1); }
.panel__body { padding: var(--sp-3); }
.panel__body--flush { padding: 0; }
.panel__foot {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  border-top: 1px solid var(--border-subtle);
  background: var(--surface-sunken);
  font-size: var(--fs-xs);
  color: var(--text-muted);
}

/* Collapsible panel section. The <summary> IS the panel head, so a filter bar
   costs one 34px row until somebody opens it. Native <details> on purpose: no
   JavaScript, keyboard and screen-reader behaviour for free. */
.disclosure > summary {
  list-style: none;
  cursor: pointer;
}
.disclosure > summary::-webkit-details-marker { display: none; }
.disclosure > summary:hover .panel__title { color: var(--text-primary); }
.disclosure:not([open]) > summary { border-bottom: 0; }
.disclosure__chev {
  display: inline-flex;
  color: var(--text-faint);
  transition: transform var(--dur-fast) var(--ease);
}
.disclosure[open] .disclosure__chev { transform: rotate(180deg); }

/* Intent variants. Observation is the phase-1 default; the two mutation
   variants exist now so later phases stay consistent, and are visually
   SEPARATED from read surfaces exactly as the design doc requires. */
.panel--observation { background: var(--surface-2); }
.panel--mutation {
  background: var(--warn-bg);
  border-color: var(--warn-bd);
}
.panel--mutation .panel__head { border-bottom-color: var(--warn-bd); }
.panel--mutation .panel__title { color: var(--warn-text); }
.panel--destructive {
  background: var(--danger-bg);
  border-color: var(--danger-bd);
}
.panel--destructive .panel__head { border-bottom-color: var(--danger-bd); }
.panel--destructive .panel__title { color: var(--danger-text); }

/* stat tiles */
.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: var(--sp-2);
}
.stat {
  background: var(--surface-2);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  padding: var(--sp-2) var(--sp-3) var(--sp-15);
  min-width: 0;
}
.stat__label {
  display: flex; align-items: center; gap: var(--sp-1);
  font-size: var(--fs-3xs);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  font-weight: var(--fw-semibold);
  color: var(--text-faint);
}
.stat__value {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-2xl);
  font-weight: var(--fw-semibold);
  line-height: 1.15;
  color: var(--text-primary);
  margin-top: var(--sp-05);
}
.stat__value small { font-size: var(--fs-xs); color: var(--text-muted); font-weight: var(--fw-regular); }
.stat__delta { font-size: var(--fs-2xs); color: var(--text-muted); margin-top: var(--sp-05); }
.stat--accent .stat__value { color: var(--accent-text); }

/* key/value description rows — used all over player profiles */
.kv { display: grid; grid-template-columns: minmax(96px, 152px) minmax(0, 1fr); }
.kv > dt {
  padding: var(--sp-1) var(--sp-2) var(--sp-1) 0;
  font-size: var(--fs-xs);
  color: var(--text-faint);
  border-bottom: 1px solid var(--border-subtle);
}
.kv > dd {
  padding: var(--sp-1) 0;
  font-size: var(--fs-xs);
  color: var(--text-primary);
  border-bottom: 1px solid var(--border-subtle);
  min-width: 0;
}
.kv > dt:last-of-type, .kv > dd:last-of-type { border-bottom: 0; }


/* == 09  Dense data table ================================================== */
/* The density anchor. 32px rows, 12px text, sticky header, hairline rules.
   A staff member must see 20+ rows without scrolling on a laptop.            */
/* The wrap is the scroll container, which is what makes the sticky header work:
   `position: sticky` anchors to the nearest scrolling ancestor, so the table
   MUST own its own scroll box. The default cap keeps a 5,000-row list inside
   the panel instead of stretching the page; override per table with
   style="--table-max-h: 40vh", or switch it off with .table-wrap--fill. */
.table-wrap {
  position: relative;
  overflow: auto;
  max-height: var(--table-max-h, calc(100vh - 300px));
}
/* --fill means "size to the rows", NOT "stop scrolling": a wrap with
   `max-height: none` is still the sticky containment box, so its header would
   anchor to a box that never scrolls and scroll off the screen with the page -
   which is exactly what every shipped screen did, since they all pass
   max_height='none'. It cannot become `overflow: visible` instead: .panel is
   `overflow: hidden`, so sticky would just anchor there, and a wide table would
   lose its horizontal scroll.

   The four SINGLE-table screens (players, audit, staff, roles) do not use this
   cap at all - they opt into .content--fill / .panel--fill above, which measures
   the space left in the column instead of guessing at it. What is left here are
   the SUB-tables of a record page (the moderation tab stacks four, the garage
   tab one per category, staff detail one). Those pages are legitimately taller
   than the viewport and scroll as a page; the cap only stops one 5,000-row
   section from burying the sections under it, so a generous value is the right
   one. It is deliberately larger than the fill screens' old 240px offset was. */
.table-wrap--fill { --table-max-h: calc(100vh - 180px); }
.table-wrap--bordered {
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
}

table.data {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: var(--fs-xs);
  line-height: 1.35;
}

table.data thead th {
  position: sticky;
  top: 0;
  z-index: var(--z-sticky);
  height: 28px;
  padding: 0 10px;
  background: var(--surface-2);
  border-bottom: 1px solid var(--border-default);
  color: var(--text-muted);
  font-size: var(--fs-3xs);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  text-align: left;
  white-space: nowrap;
  user-select: none;
}
/* keep the sticky header opaque over scrolled rows */
table.data thead th::after {
  content: '';
  position: absolute; inset: auto 0 -1px 0; height: 1px;
  background: var(--border-default);
}

table.data th.is-sortable { cursor: pointer; }
table.data th.is-sortable:hover { color: var(--text-primary); }
table.data th .sort-ind { display: inline-block; margin-left: var(--sp-1); opacity: 0; vertical-align: -0.15em; }
table.data th[aria-sort='ascending'] .sort-ind,
table.data th[aria-sort='descending'] .sort-ind { opacity: 1; color: var(--accent-text); }
table.data th[aria-sort='descending'] .sort-ind { transform: rotate(180deg); }

table.data tbody td {
  height: var(--row-h);
  padding: 0 10px;
  border-bottom: 1px solid var(--border-subtle);
  color: var(--text-secondary);
  vertical-align: middle;
  white-space: nowrap;
}
table.data tbody tr:last-child td { border-bottom: 0; }
table.data tbody tr { transition: background var(--dur-fast) var(--ease); }
table.data tbody tr:hover td { background: var(--surface-hover); }

/* keyboard cursor row (j/k or arrow keys) + selected row */
table.data tbody tr.is-cursor td {
  background: var(--surface-active);
  box-shadow: inset 2px 0 0 var(--accent);
}
table.data tbody tr[aria-selected='true'] td { background: var(--surface-selected); }
table.data tbody tr[data-href] { cursor: pointer; }

/* density modifiers */
table.data--compact tbody td { height: var(--row-h-compact); }
table.data--roomy tbody td   { height: var(--row-h-roomy); }
table.data--zebra tbody tr:nth-child(even) td { background: rgba(148, 178, 216, 0.028); }
table.data--zebra tbody tr:nth-child(even):hover td { background: var(--surface-hover); }

/* cell helpers */
table.data .cell-primary { color: var(--text-primary); font-weight: var(--fw-medium); }
table.data .cell-num {
  text-align: right;
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}
table.data .cell-mono { font-family: var(--font-mono); font-size: var(--fs-2xs); color: var(--text-muted); }
table.data .cell-actions { text-align: right; width: 1%; }
table.data .cell-tight { width: 1%; }
table.data .cell-wrap { white-space: normal; min-width: 200px; }
table.data .cell-trunc { max-width: 260px; overflow: hidden; text-overflow: ellipsis; }
table.data col.col-narrow { width: 68px; }

/* selection checkbox column */
table.data .cell-select { width: 28px; padding-left: var(--sp-2); padding-right: 0; }

/* table toolbar sits directly above a flush table inside a panel */
.toolbar {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  border-bottom: 1px solid var(--border-subtle);
  background: var(--surface-2);
  flex-wrap: wrap;
}
.toolbar__count {
  font-size: var(--fs-2xs); color: var(--text-faint);
  font-variant-numeric: tabular-nums;
}

/* pagination strip */
.pager {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  border-top: 1px solid var(--border-subtle);
  font-size: var(--fs-2xs);
  color: var(--text-muted);
}
.pager__pages { display: flex; align-items: center; gap: var(--sp-05); margin-left: auto; }
.pager__page {
  min-width: 22px; height: 22px; padding: 0 var(--sp-15);
  display: grid; place-items: center;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  background: transparent;
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-2xs);
  cursor: pointer;
}
.pager__page:hover { background: var(--surface-hover); color: var(--text-primary); }
/* Ends of the range: present, obviously inert, not a dead link. */
.pager__page.is-disabled,
.pager__page[disabled] {
  color: var(--text-faint);
  cursor: default;
  pointer-events: none;
}
.pager__page[aria-current='page'] {
  background: var(--accent-soft-bg);
  border-color: var(--accent-soft-bd);
  color: var(--accent-text);
  font-weight: var(--fw-semibold);
}


/* == 10  Forms & inputs ==================================================== */
.field { display: flex; flex-direction: column; gap: var(--sp-1); min-width: 0; }
.field--row { flex-direction: row; align-items: center; gap: var(--sp-2); }

.label {
  font-size: var(--fs-xs);
  font-weight: var(--fw-medium);
  color: var(--text-secondary);
  display: flex; align-items: center; gap: var(--sp-1);
}
.label .req { color: var(--warn-text); font-weight: var(--fw-bold); }
.label .optional { color: var(--text-faint); font-weight: var(--fw-regular); font-size: var(--fs-2xs); }

.hint { font-size: var(--fs-2xs); color: var(--text-faint); }
.err  { font-size: var(--fs-2xs); color: var(--danger-text); display: flex; align-items: center; gap: var(--sp-1); }

.input, .select, .textarea {
  width: 100%;
  min-width: 0;
  height: var(--control-h);
  padding: 0 var(--sp-2);
  background: var(--surface-sunken);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  color: var(--text-primary);
  font-size: var(--fs-sm);
  transition: border-color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease),
              box-shadow var(--dur-fast) var(--ease);
}
.textarea { height: auto; min-height: 64px; padding: var(--sp-15) var(--sp-2); resize: vertical; line-height: var(--lh-snug); }
.input::placeholder, .textarea::placeholder { color: var(--text-faint); }
.input:hover, .select:hover, .textarea:hover { border-color: var(--border-strong); }
.input:focus, .select:focus, .textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft-bg);
  background: var(--surface-2);
}
.input:disabled, .select:disabled, .textarea:disabled {
  opacity: 0.5; cursor: not-allowed; background: var(--surface-2);
}
.input--mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; letter-spacing: 0.02em; }
.input--lg { height: var(--control-h-lg); font-size: var(--fs-md); }

/* The chevron is a data-URI, so its stroke cannot be a var(). It is the ONLY
   hard-coded colour outside the token blocks; keep it equal to --c-slate-350. */
.select {
  appearance: none;
  padding-right: var(--sp-6);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236d87a8' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--sp-15) center;
}

.field.is-invalid .input,
.field.is-invalid .select,
.field.is-invalid .textarea { border-color: var(--danger-bd); }
.field.is-invalid .input:focus { box-shadow: 0 0 0 3px var(--danger-bg); }

/* input with a leading icon (search boxes, filters) */
.input-icon { position: relative; display: flex; align-items: center; min-width: 0; }
.input-icon > .icon {
  position: absolute; left: var(--sp-2); color: var(--text-faint); pointer-events: none;
}
.input-icon > .input { padding-left: 28px; }

/* segmented control / filter chips row */
.segmented {
  display: inline-flex;
  padding: 2px;
  background: var(--surface-sunken);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  gap: 2px;
}
.segmented button {
  height: 22px;
  padding: 0 var(--sp-2);
  border: 0;
  background: transparent;
  border-radius: var(--radius-sm);
  color: var(--text-muted);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-medium);
  cursor: pointer;
  white-space: nowrap;
}
.segmented button:hover { color: var(--text-primary); }
.segmented button[aria-pressed='true'] {
  background: var(--surface-3);
  color: var(--text-primary);
  box-shadow: var(--shadow-xs);
}

/* checkbox / radio */
.check { display: inline-flex; align-items: flex-start; gap: var(--sp-2); cursor: pointer; }
.check input[type='checkbox'], .check input[type='radio'] {
  appearance: none;
  width: 14px; height: 14px; margin: 2px 0 0; flex: none;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-xs);
  background: var(--surface-sunken);
  cursor: pointer;
  display: grid; place-items: center;
  transition: background var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.check input[type='radio'] { border-radius: var(--radius-full); }
.check input:checked {
  background: var(--accent-strong);
  border-color: var(--accent-strong);
}
.check input[type='checkbox']:checked::after {
  content: '';
  width: 8px; height: 8px;
  background: var(--text-on-accent);
  clip-path: polygon(14% 45%, 0 60%, 38% 100%, 100% 22%, 85% 8%, 36% 66%);
}
.check input[type='radio']:checked::after {
  content: ''; width: 5px; height: 5px; border-radius: 50%; background: var(--text-on-accent);
}
.check__text { font-size: var(--fs-xs); color: var(--text-secondary); line-height: 1.35; }
.check__text b { display: block; color: var(--text-primary); font-weight: var(--fw-medium); }

/* switch */
.switch { display: inline-flex; align-items: center; gap: var(--sp-2); cursor: pointer; }
.switch input { appearance: none; margin: 0; width: 28px; height: 16px; flex: none;
  background: var(--border-strong); border-radius: var(--radius-full);
  position: relative; cursor: pointer; transition: background var(--dur-fast) var(--ease); }
.switch input::after {
  content: ''; position: absolute; top: 2px; left: 2px;
  width: 12px; height: 12px; border-radius: 50%;
  background: var(--c-white);
  transition: transform var(--dur-fast) var(--ease);
}
.switch input:checked { background: var(--accent-strong); }
.switch input:checked::after { transform: translateX(12px); }

/* form layout helpers */
.form-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: var(--sp-3); }
.form-actions {
  display: flex; align-items: center; gap: var(--sp-2);
  padding-top: var(--sp-3); margin-top: var(--sp-3);
  border-top: 1px solid var(--border-subtle);
}

/* typed-confirm field for destructive actions (later phases) */
.confirm-type {
  background: var(--surface-sunken);
  border: 1px dashed var(--danger-bd);
  border-radius: var(--radius-md);
  padding: var(--sp-2) var(--sp-3);
}
.confirm-type__prompt { font-size: var(--fs-xs); color: var(--danger-text); margin-bottom: var(--sp-15); }


/* == 11  Buttons =========================================================== */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-15);
  height: var(--control-h);
  padding: 0 var(--sp-3);
  border-radius: var(--radius-md);
  border: 1px solid var(--border-default);
  background: var(--surface-3);
  color: var(--text-primary);
  font-size: var(--fs-xs);
  font-weight: var(--fw-medium);
  white-space: nowrap;
  cursor: pointer;
  text-decoration: none;
  transition: background var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease),
              color var(--dur-fast) var(--ease);
}
.btn:hover { background: var(--surface-4); border-color: var(--border-strong); text-decoration: none; }
.btn:active { transform: translateY(0.5px); }
/* Quieter through TOKENS, never through opacity. `opacity: 0.45` blended the
   label toward the surface behind it (~3.9:1 on --surface-3) and the nested
   .text-faint phase suffix down to ~2:1 - and on the player profile those chips
   are not decoration, they are the only place the portal says WHEN a control
   arrives. Same reasoning as .nav-item.is-disabled and .pager__page.is-disabled,
   which already refuse opacity for exactly this. --text-muted on --neutral-bg
   measures ~7.5:1 on --surface-2 and --surface-3. */
.btn:disabled, .btn.is-disabled {
  background: var(--neutral-bg);
  border-color: var(--border-subtle);
  color: var(--text-muted);
  cursor: not-allowed;
  pointer-events: none;
}
.btn:disabled .icon, .btn.is-disabled .icon { color: var(--text-faint); }
/* The phase suffix carries the payload ("· phase 5"), so it is muted, not faint,
   wherever it sits inside a disabled chip. */
.btn:disabled .text-faint, .btn.is-disabled .text-faint { color: var(--text-muted); }
.btn .icon { margin-left: -2px; }

.btn--primary {
  background: var(--accent-strong);
  border-color: var(--accent-strong);
  color: var(--text-on-accent);
  font-weight: var(--fw-semibold);
}
.btn--primary:hover { background: var(--accent-stronger); border-color: var(--accent-stronger); }

.btn--secondary { /* the default look, named for clarity in templates */ }

.btn--ghost {
  background: transparent;
  border-color: transparent;
  color: var(--text-muted);
}
.btn--ghost:hover { background: var(--surface-hover); color: var(--text-primary); border-color: transparent; }

.btn--warn {
  background: var(--warn-bg);
  border-color: var(--warn-bd);
  color: var(--warn-text);
}
.btn--warn:hover { background: rgba(245, 158, 11, 0.2); border-color: var(--warn); }

.btn--danger {
  background: var(--danger-solid);
  border-color: var(--danger-solid);
  color: var(--danger-on-solid);
  font-weight: var(--fw-semibold);
}
.btn--danger:hover { background: var(--danger-solid-hover); border-color: var(--danger-solid-hover); }

.btn--danger-quiet {
  background: transparent;
  border-color: var(--danger-bd);
  color: var(--danger-text);
}
.btn--danger-quiet:hover { background: var(--danger-bg); }

.btn--sm { height: var(--control-h-sm); padding: 0 var(--sp-2); font-size: var(--fs-2xs); }
.btn--lg { height: var(--control-h-lg); padding: 0 var(--sp-4); font-size: var(--fs-sm); }
.btn--block { width: 100%; }
.btn--icon { width: var(--control-h); padding: 0; }
.btn--icon.btn--sm { width: var(--control-h-sm); }

.btn-group { display: inline-flex; }
.btn-group .btn { border-radius: 0; margin-left: -1px; }
.btn-group .btn:first-child { border-radius: var(--radius-md) 0 0 var(--radius-md); margin-left: 0; }
.btn-group .btn:last-child { border-radius: 0 var(--radius-md) var(--radius-md) 0; }

/* loading button */
.btn.is-loading { color: transparent !important; position: relative; pointer-events: none; }
.btn.is-loading::after {
  content: '';
  position: absolute; width: 12px; height: 12px;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  color: var(--text-on-accent);
  animation: spin 0.6s linear infinite;
}
.btn--secondary.is-loading::after, .btn--ghost.is-loading::after { color: var(--text-muted); }
@keyframes spin { to { transform: rotate(360deg); } }


/* == 12  Badges, tiers, dots, meters, tabs ================================= */
.badge {
  display: inline-flex; align-items: center; gap: var(--sp-1);
  height: 18px;
  padding: 0 var(--sp-15);
  border-radius: var(--radius-sm);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-medium);
  white-space: nowrap;
  border: 1px solid var(--neutral-bd);
  background: var(--neutral-bg);
  color: var(--neutral-text);
}
.badge--info    { background: var(--info-bg);      border-color: var(--info-bd);      color: var(--info-text); }
.badge--accent  { background: var(--accent-soft-bg); border-color: var(--accent-soft-bd); color: var(--accent-text); }
.badge--highlight { background: var(--highlight-soft-bg); border-color: var(--highlight-soft-bd); color: var(--highlight-text); }
.badge--success { background: var(--success-bg);   border-color: var(--success-bd);   color: var(--success-text); }
.badge--warn    { background: var(--warn-bg);      border-color: var(--warn-bd);      color: var(--warn-text); }
.badge--danger  { background: var(--danger-bg);    border-color: var(--danger-bd);    color: var(--danger-text); }
.badge--outline { background: transparent; }
.badge--caps { text-transform: uppercase; letter-spacing: var(--ls-caps); font-size: var(--fs-3xs); font-weight: var(--fw-semibold); }

/* staff authority tier chip — "T60 Senior Mod". Cool hues only, never insignia. */
.tier {
  display: inline-flex; align-items: center; gap: var(--sp-1);
  height: 18px; padding: 0 var(--sp-15) 0 var(--sp-1);
  border-radius: var(--radius-sm);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-medium);
  white-space: nowrap;
  border: 1px solid var(--neutral-bd);
  background: var(--neutral-bg);
  color: var(--neutral-text);
}
.tier__n {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-3xs);
  font-weight: var(--fw-bold);
  padding: 0 var(--sp-1);
  border-radius: var(--radius-xs);
  background: rgba(0, 0, 0, 0.22);
  letter-spacing: 0;
}
.tier[data-tier='100'] { color: var(--tier-100-text); background: var(--tier-100-bg); border-color: var(--tier-100-bd); }
.tier[data-tier='90']  { color: var(--tier-90-text);  background: var(--tier-90-bg);  border-color: var(--tier-90-bd); }
.tier[data-tier='85']  { color: var(--tier-85-text);  background: var(--tier-85-bg);  border-color: var(--tier-85-bd); }
.tier[data-tier='70']  { color: var(--tier-70-text);  background: var(--tier-70-bg);  border-color: var(--tier-70-bd); }
.tier[data-tier='60']  { color: var(--tier-60-text);  background: var(--tier-60-bg);  border-color: var(--tier-60-bd); }
.tier[data-tier='50']  { color: var(--tier-50-text);  background: var(--tier-50-bg);  border-color: var(--tier-50-bd); }
.tier[data-tier='40']  { color: var(--tier-40-text);  background: var(--tier-40-bg);  border-color: var(--tier-40-bd); }
.tier[data-tier='30']  { color: var(--tier-30-text);  background: var(--tier-30-bg);  border-color: var(--tier-30-bd); }
.tier[data-tier='20']  { color: var(--tier-20-text);  background: var(--tier-20-bg);  border-color: var(--tier-20-bd); }
.tier[data-tier='10']  { color: var(--tier-10-text);  background: var(--tier-10-bg);  border-color: var(--tier-10-bd); }

/* status dot for online/offline/degraded lists */
.dot {
  display: inline-block; width: 7px; height: 7px; flex: none;
  border-radius: var(--radius-full);
  background: var(--text-faint);
  box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.25);
}
.dot--online  { background: var(--success); }
.dot--warn    { background: var(--warn); }
.dot--danger  { background: var(--danger); }
.dot--info    { background: var(--highlight); }
.dot--offline { background: var(--c-slate-500); }

/* quota / budget meter (My Work, Economy ceiling) */
.meter { display: flex; flex-direction: column; gap: var(--sp-05); min-width: 0; }
.meter__top {
  display: flex; align-items: baseline; gap: var(--sp-2);
  font-size: var(--fs-2xs); color: var(--text-muted);
}
.meter__top b {
  margin-left: auto;
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  color: var(--text-secondary);
  font-weight: var(--fw-medium);
}
.meter__track {
  height: 5px;
  border-radius: var(--radius-full);
  background: var(--surface-sunken);
  border: 1px solid var(--border-subtle);
  overflow: hidden;
}
.meter__fill {
  height: 100%;
  background: var(--accent);
  border-radius: var(--radius-full);
  transition: width var(--dur-slow) var(--ease);
}
.meter--warn .meter__fill   { background: var(--warn); }
.meter--danger .meter__fill { background: var(--danger); }

/* tabs (player profile: Overview / Garage / Economy / ...) */
.tabs {
  display: flex; align-items: center; gap: var(--sp-1);
  border-bottom: 1px solid var(--border-subtle);
  margin-bottom: var(--sp-3);
  overflow-x: auto;
}
.tab {
  height: 30px;
  padding: 0 var(--sp-2);
  display: inline-flex; align-items: center; gap: var(--sp-1);
  border: 0; background: transparent;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  color: var(--text-muted);
  font-size: var(--fs-xs);
  font-weight: var(--fw-medium);
  white-space: nowrap;
  cursor: pointer;
}
.tab:hover { color: var(--text-primary); }
.tab[aria-selected='true'] { color: var(--text-primary); border-bottom-color: var(--accent); font-weight: var(--fw-semibold); }
.tab__count { font-family: var(--font-mono); font-size: var(--fs-3xs); color: var(--text-faint); }


/* == 13  States ============================================================ */
/* Shared shell for empty / error / forbidden / loading panels. */
.state {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--sp-2);
  padding: var(--sp-8) var(--sp-4);
  color: var(--text-muted);
}
.state__icon {
  width: 34px; height: 34px;
  display: grid; place-items: center;
  border-radius: var(--radius-md);
  background: var(--neutral-bg);
  border: 1px solid var(--neutral-bd);
  color: var(--text-faint);
}
.state__title { font-size: var(--fs-md); font-weight: var(--fw-semibold); color: var(--text-primary); }
.state__body { font-size: var(--fs-xs); color: var(--text-muted); max-width: 56ch; }
.state__actions { display: flex; gap: var(--sp-2); margin-top: var(--sp-1); }
.state--compact { padding: var(--sp-5) var(--sp-4); }

.state--error .state__icon    { background: var(--danger-bg); border-color: var(--danger-bd); color: var(--danger-text); }
.state--forbidden .state__icon { background: var(--warn-bg); border-color: var(--warn-bd); color: var(--warn-text); }
.state--empty .state__icon    { background: var(--observe-bg); border-color: var(--observe-bd); }

/* forbidden must always name the missing capability and who can grant it */
.state__cap {
  font-family: var(--font-mono);
  font-size: var(--fs-2xs);
  color: var(--text-secondary);
  background: var(--surface-sunken);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  padding: var(--sp-05) var(--sp-15);
}

/* banners: page-level notices (degraded dependency, read-only mode, flash) */
.banner {
  display: flex; align-items: flex-start; gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  border-radius: var(--radius-md);
  border: 1px solid var(--info-bd);
  background: var(--info-bg);
  color: var(--text-secondary);
  font-size: var(--fs-xs);
}
.banner .icon { color: var(--info-text); margin-top: 1px; }
.banner__title { font-weight: var(--fw-semibold); color: var(--text-primary); }
.banner__body { min-width: 0; }
.banner__actions { margin-left: auto; display: flex; gap: var(--sp-2); align-items: center; }
.banner--success { border-color: var(--success-bd); background: var(--success-bg); }
.banner--success .icon { color: var(--success-text); }
.banner--warn { border-color: var(--warn-bd); background: var(--warn-bg); }
.banner--warn .icon { color: var(--warn-text); }
.banner--danger { border-color: var(--danger-bd); background: var(--danger-bg); }
.banner--danger .icon { color: var(--danger-text); }
.banner--degraded { border-color: var(--warn-bd); background: var(--warn-bg); border-left-width: 3px; }

/* skeletons — layout-preserving, never a spinner over a blank page */
.skeleton {
  position: relative;
  overflow: hidden;
  background: var(--skeleton-base);
  border-radius: var(--radius-sm);
  height: 12px;
}
.skeleton::after {
  content: '';
  position: absolute; inset: 0;
  transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, var(--skeleton-shine), transparent);
  animation: shimmer 1.4s var(--ease) infinite;
}
@keyframes shimmer { to { transform: translateX(100%); } }
.skeleton--text  { height: 10px; }
.skeleton--title { height: 16px; width: 40%; }
.skeleton--pill  { height: 18px; width: 56px; border-radius: var(--radius-sm); }
.skeleton-rows { display: flex; flex-direction: column; }
.skeleton-rows > div {
  display: grid;
  grid-template-columns: 1.6fr 1fr 0.8fr 0.8fr 0.6fr;
  gap: var(--sp-3);
  align-items: center;
  height: var(--row-h);
  padding: 0 10px;
  border-bottom: 1px solid var(--border-subtle);
}

/* inline spinner */
.spinner {
  width: 14px; height: 14px; flex: none;
  border: 2px solid var(--border-strong);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
}


/* == 14  Toast, modal, drawer, tooltip, kbd ================================ */
.toast-region {
  position: fixed;
  right: var(--sp-4); bottom: var(--sp-4);
  z-index: var(--z-toast);
  display: flex; flex-direction: column; gap: var(--sp-2);
  width: min(360px, calc(100vw - var(--sp-8)));
  pointer-events: none;
}
.toast {
  pointer-events: auto;
  display: flex; align-items: flex-start; gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  background: var(--surface-3);
  border: 1px solid var(--border-default);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  font-size: var(--fs-xs);
  color: var(--text-secondary);
  animation: toast-in var(--dur-med) var(--ease);
}
@keyframes toast-in { from { opacity: 0; transform: translateY(6px); } }
.toast.is-leaving { opacity: 0; transform: translateY(6px); transition: all var(--dur-med) var(--ease); }
.toast__title { font-weight: var(--fw-semibold); color: var(--text-primary); }
.toast__body { min-width: 0; flex: 1 1 auto; }
.toast--success { border-left-color: var(--success); }
.toast--success .icon { color: var(--success-text); }
.toast--warn    { border-left-color: var(--warn); }
.toast--warn .icon { color: var(--warn-text); }
.toast--danger  { border-left-color: var(--danger); }
.toast--danger .icon { color: var(--danger-text); }
.toast .icon { color: var(--accent-text); margin-top: 1px; }

/* modal + drawer share the backdrop */
.overlay {
  position: fixed; inset: 0;
  background: rgba(3, 6, 12, 0.62);
  backdrop-filter: blur(2px);
  z-index: var(--z-modal);
  display: grid;
  place-items: center;
  padding: var(--sp-6);
  animation: fade-in var(--dur-med) var(--ease);
}
@keyframes fade-in { from { opacity: 0; } }
.overlay[hidden] { display: none; }

.modal {
  width: min(520px, 100%);
  max-height: 84vh;
  display: flex; flex-direction: column;
  background: var(--surface-3);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
  animation: modal-in var(--dur-med) var(--ease);
}
@keyframes modal-in { from { opacity: 0; transform: translateY(8px) scale(0.99); } }
.modal--wide { width: min(760px, 100%); }
.modal__head {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-3);
  border-bottom: 1px solid var(--border-subtle);
}
.modal__title { font-size: var(--fs-md); font-weight: var(--fw-semibold); }
.modal__body { padding: var(--sp-3); overflow-y: auto; font-size: var(--fs-xs); color: var(--text-secondary); }
.modal__foot {
  display: flex; align-items: center; justify-content: flex-end; gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  border-top: 1px solid var(--border-subtle);
  background: var(--surface-sunken);
}
.modal--destructive { border-color: var(--danger-bd); }
.modal--destructive .modal__head { border-bottom-color: var(--danger-bd); background: var(--danger-bg); }
.modal--destructive .modal__title { color: var(--danger-text); }

/* right drawer — every mutation in later phases opens in one of these */
.drawer-overlay { place-items: stretch; justify-items: end; padding: 0; z-index: var(--z-drawer); }
.drawer {
  width: min(480px, 100%);
  height: 100%;
  display: flex; flex-direction: column;
  background: var(--surface-3);
  border-left: 1px solid var(--border-default);
  box-shadow: var(--shadow-lg);
  animation: drawer-in var(--dur-med) var(--ease);
}
@keyframes drawer-in { from { transform: translateX(16px); opacity: 0; } }
.drawer--wide { width: min(680px, 100%); }
.drawer__head {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-3);
  border-bottom: 1px solid var(--border-subtle);
  flex: none;
}
.drawer__title { font-size: var(--fs-md); font-weight: var(--fw-semibold); }
.drawer__sub { font-size: var(--fs-2xs); color: var(--text-muted); }
.drawer__body { padding: var(--sp-3); overflow-y: auto; flex: 1 1 auto; }
.drawer__foot {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  border-top: 1px solid var(--border-subtle);
  background: var(--surface-sunken);
  flex: none;
}

/* before/after preview block — fixed position inside every mutation drawer */
.diff {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  gap: var(--sp-2);
  align-items: center;
  padding: var(--sp-2);
  background: var(--surface-sunken);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
}
.diff__side { min-width: 0; }
.diff__label { font-size: var(--fs-3xs); text-transform: uppercase; letter-spacing: var(--ls-caps); color: var(--text-faint); }
.diff__val {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-sm);
  color: var(--text-primary);
}
.diff__val--after { color: var(--warn-text); }
.diff__arrow { color: var(--text-faint); }

/* tooltip */
.tooltip {
  position: absolute;
  z-index: var(--z-tooltip);
  max-width: 260px;
  padding: var(--sp-1) var(--sp-2);
  background: var(--surface-4);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
  font-size: var(--fs-2xs);
  color: var(--text-secondary);
}

/* keyboard hints */
kbd, .kbd {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 18px; height: 18px;
  padding: 0 var(--sp-1);
  border: 1px solid var(--border-default);
  border-bottom-width: 2px;
  border-radius: var(--radius-xs);
  background: var(--surface-sunken);
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: var(--fs-3xs);
  font-weight: var(--fw-medium);
  line-height: 1;
}
.kbd-hint { display: inline-flex; align-items: center; gap: 3px; color: var(--text-faint); font-size: var(--fs-2xs); }
.kbd-legend {
  display: flex; flex-wrap: wrap; gap: var(--sp-3);
  font-size: var(--fs-2xs); color: var(--text-faint);
}
.kbd-legend > span { display: inline-flex; align-items: center; gap: var(--sp-1); }


/* == 15  Command palette (Ctrl+K) ========================================== */
.palette-overlay {
  position: fixed; inset: 0;
  z-index: var(--z-palette);
  background: rgba(3, 6, 12, 0.55);
  backdrop-filter: blur(2px);
  display: flex;
  justify-content: center;
  padding-top: 12vh;
  animation: fade-in var(--dur-fast) var(--ease);
}
.palette-overlay[hidden] { display: none; }

.palette {
  width: min(600px, calc(100vw - var(--sp-8)));
  max-height: 64vh;
  display: flex; flex-direction: column;
  background: var(--surface-4);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
  animation: modal-in var(--dur-med) var(--ease);
}
.palette__search {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  border-bottom: 1px solid var(--border-subtle);
  flex: none;
}
.palette__search .icon { color: var(--text-faint); }
.palette__input {
  flex: 1 1 auto; min-width: 0;
  border: 0; background: transparent;
  font-size: var(--fs-md);
  color: var(--text-primary);
  outline: none;
}
.palette__input::placeholder { color: var(--text-faint); }
.palette__list { overflow-y: auto; padding: var(--sp-1); flex: 1 1 auto; }
.palette__group {
  padding: var(--sp-2) var(--sp-2) var(--sp-1);
  font-size: var(--fs-3xs);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: var(--text-faint);
  font-weight: var(--fw-semibold);
}
.palette__item {
  display: flex; align-items: center; gap: var(--sp-2);
  height: 30px;
  padding: 0 var(--sp-2);
  border-radius: var(--radius-sm);
  color: var(--text-secondary);
  font-size: var(--fs-sm);
  cursor: pointer;
}
.palette__item .icon { color: var(--text-faint); }
.palette__item small { margin-left: auto; color: var(--text-faint); font-size: var(--fs-2xs); }
.palette__item.is-active {
  background: var(--accent-soft-bg);
  color: var(--text-primary);
}
.palette__item.is-active .icon { color: var(--accent-text); }
.palette__foot {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-15) var(--sp-3);
  border-top: 1px solid var(--border-subtle);
  background: var(--surface-sunken);
  flex: none;
}
.palette__empty { padding: var(--sp-5); text-align: center; color: var(--text-faint); font-size: var(--fs-xs); }


/* == 16  Styleguide-only helpers =========================================== */
.sg-nav {
  position: sticky; top: 0; z-index: var(--z-sticky);
  display: flex; flex-wrap: wrap; gap: var(--sp-1);
  padding: var(--sp-2) 0;
  margin-bottom: var(--sp-3);
  background: var(--bg-canvas);
  border-bottom: 1px solid var(--border-subtle);
}
.sg-nav a {
  font-size: var(--fs-2xs); color: var(--text-muted);
  padding: var(--sp-05) var(--sp-15);
  border-radius: var(--radius-sm);
  border: 1px solid var(--border-subtle);
}
.sg-nav a:hover { background: var(--surface-hover); color: var(--text-primary); text-decoration: none; }

.sg-section { margin-bottom: var(--sp-8); scroll-margin-top: 56px; }
.sg-section > h2 {
  display: flex; align-items: baseline; gap: var(--sp-2);
  padding-bottom: var(--sp-1);
  margin-bottom: var(--sp-1);
  border-bottom: 1px solid var(--border-default);
}
.sg-section > h2 small { font-size: var(--fs-2xs); font-weight: var(--fw-regular); color: var(--text-faint); }
.sg-note { font-size: var(--fs-xs); color: var(--text-muted); margin-bottom: var(--sp-3); max-width: 84ch; }

.sg-demo {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2);
  padding: var(--sp-3);
  background: var(--surface-2);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
}
.sg-demo--col { flex-direction: column; align-items: stretch; }
.sg-demo + .sg-demo { margin-top: var(--sp-2); }
.sg-label {
  width: 100%;
  font-size: var(--fs-3xs);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: var(--text-faint);
  font-weight: var(--fw-semibold);
}

.sg-swatches { display: grid; grid-template-columns: repeat(auto-fill, minmax(148px, 1fr)); gap: var(--sp-2); }
.sg-swatch {
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--surface-2);
}
.sg-swatch__chip { height: 40px; border-bottom: 1px solid var(--border-subtle); }
.sg-swatch__meta { padding: var(--sp-1) var(--sp-2) var(--sp-15); }
.sg-swatch__name { font-size: var(--fs-2xs); color: var(--text-primary); font-weight: var(--fw-medium); }
.sg-swatch__var { font-family: var(--font-mono); font-size: 9.5px; color: var(--text-faint); }

.sg-typerow {
  display: flex; align-items: baseline; gap: var(--sp-3);
  padding: var(--sp-15) 0;
  border-bottom: 1px solid var(--border-subtle);
}
.sg-typerow__meta {
  width: 150px; flex: none;
  font-family: var(--font-mono); font-size: var(--fs-2xs); color: var(--text-faint);
}

.sg-scale { display: flex; align-items: flex-end; gap: var(--sp-2); flex-wrap: wrap; }
.sg-scale__item { text-align: center; }
.sg-scale__bar { background: var(--accent-soft-bg); border: 1px solid var(--accent-soft-bd); border-radius: var(--radius-xs); }
.sg-scale__lbl { font-family: var(--font-mono); font-size: 9.5px; color: var(--text-faint); margin-top: var(--sp-05); }

.sg-icons { display: grid; grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); gap: var(--sp-1); }
.sg-icon {
  display: flex; flex-direction: column; align-items: center; gap: var(--sp-1);
  padding: var(--sp-2) var(--sp-1);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  background: var(--surface-2);
  color: var(--text-secondary);
}
.sg-icon span { font-family: var(--font-mono); font-size: 9.5px; color: var(--text-faint); }

/* fake shell used to preview rail/topbar inside the styleguide page */
.sg-shell {
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--surface-1);
}


/* == 17  Responsive, motion, print ========================================= */
@media (max-width: 1180px) {
  .app { grid-template-columns: var(--rail-w-collapsed) minmax(0, 1fr); }
  .app .rail__wordmark,
  .app .nav-group__label,
  .app .nav-item span,
  .app .nav-item__soon,
  .app .rail__foot .staff-card__meta { display: none; }
  .app .nav-item { justify-content: center; padding: 0; }
  .topbar__search { width: 200px; }
}

@media (max-width: 860px) {
  .app { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto; }
  .rail {
    position: fixed; inset: 0 auto 0 0;
    width: var(--rail-w);
    transform: translateX(-100%);
    transition: transform var(--dur-med) var(--ease);
    box-shadow: var(--shadow-lg);
  }
  .app[data-rail='open'] .rail { transform: translateX(0); }
  .app[data-rail='open'] .rail__wordmark,
  .app[data-rail='open'] .nav-group__label,
  .app[data-rail='open'] .nav-item span,
  .app[data-rail='open'] .nav-item__soon { display: initial; }
  .app[data-rail='open'] .nav-item { justify-content: flex-start; padding: 0 var(--sp-2); }
  .content { padding: var(--sp-3) var(--sp-3) var(--sp-8); }
  .page-head { flex-direction: column; gap: var(--sp-2); }
  .topbar__search { width: auto; flex: 1 1 auto; }
  .grid-2, .grid-3, .grid-4 { grid-template-columns: minmax(0, 1fr); }
}

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

@media print {
  .rail, .topbar, .toast-region, .palette-overlay, .appfoot { display: none !important; }
  body { background: #fff; color: #000; }
  .panel { break-inside: avoid; }
}
