/* ============================================================================
   VALID THRU — ADMIN PORTAL SHARED STYLESHEET · A1 "ORBIT" RESKIN
   admin/assets/admin.css

   Visual system from ../../Design kit.html (authoritative tokens) in the
   a1-orbit direction: Blueprint dark is the DEFAULT theme, Signal light is
   the toggle alternative. Archivo everywhere, mono micro-labels, orbital
   ring language. One palette, flipped — light's ink is dark's canvas.

   Layer 1 — TOKENS: kit primitives (--vt-*) + the semantic names the 22
             pages and the component layers already use, remapped onto the
             kit palette. Ratios verified in comments (scripted check).
   Layer 2 — PRIMITIVES: vt-* kit (buttons, fields, checks, toggles, tabs,
             cards, modal, toast, empty state, skeleton, ring).
   Layer 3 — ADMIN SHELL: adm-* top bar, grouped sidebar (240px → icon rail
             <1024px → bottom sheet <768px), main region, audit footer.
   Layer 4 — ADMIN COMPONENTS: stat cards, ops-density data table, badges,
             sparkline/donut, drawer, step-up modal, feed, SLA chip,
             danger zone, "What staff cannot see" panel, code block,
             orbit strip (index.html only).

   Every text-bearing pairing below clears WCAG 2.2 AA in both themes
   (checked ratios noted). Status is never conveyed by color alone — every
   status class expects icon + text in the markup.
   ========================================================================== */

/* Archivo — self-hosted variable font (wght 100-900), latin + latin-ext subsets.
   Downloaded from Google Fonts v25 on 1 September 2026; SIL-adjacent OFL license.
   No third-party font hosts — font-src stays 'self'. */
@font-face{
  font-family:'Archivo'; font-style:normal; font-weight:100 900; font-display:swap;
  src:url('fonts/archivo-latin.woff2') format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face{
  font-family:'Archivo'; font-style:normal; font-weight:100 900; font-display:swap;
  src:url('fonts/archivo-latin-ext.woff2') format('woff2');
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1EFF,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}


/* ############################################################################
   LAYER 1 — TOKENS (kit system, Blueprint dark default)
   ######################################################################### */

/* ==========================================================================
   1. PRIMITIVES — shared by both themes
   ========================================================================== */

:root {

  /* --- Type: Archivo per the kit; mono for micro-labels and figures ------ */
  --font-sans: "Archivo", ui-sans-serif, system-ui, -apple-system,
               "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;

  --figures-tabular: "tnum" 1, "lnum" 1;

  --size-100:  11px;   --lh-100:  16px;
  --size-200:  12px;   --lh-200:  18px;
  --size-300:  13px;   --lh-300:  20px;
  --size-400:  15px;   --lh-400:  22px;   /* UI default */
  --size-500:  16px;   --lh-500:  26px;   /* reading default */
  --size-600:  18px;   --lh-600:  28px;
  --size-700:  21px;   --lh-700:  30px;
  --size-800:  26px;   --lh-800:  34px;
  --size-900:  33px;   --lh-900:  40px;
  --size-1000: 41px;   --lh-1000: 47px;
  --size-1100: 52px;   --lh-1100: 58px;
  --size-1200: 64px;   --lh-1200: 68px;

  --weight-regular:  500;   /* Archivo starts at 500 — the kit's body weight */
  --weight-medium:   600;
  --weight-semibold: 700;
  --weight-bold:     800;

  --track-display: -0.02em;
  --track-heading: -0.012em;
  --track-body:     0;
  --track-label:    0.08em;   /* mono micro-labels, a1 style */
  --track-mrz:      0.14em;

  /* --- Space: 4px base -------------------------------------------------- */
  --space-0:    0;
  --space-25:   2px;
  --space-50:   4px;
  --space-75:   6px;
  --space-100:  8px;
  --space-150:  12px;
  --space-200:  16px;
  --space-250:  20px;
  --space-300:  24px;
  --space-400:  32px;
  --space-500:  40px;
  --space-600:  48px;
  --space-800:  64px;
  --space-1000: 80px;
  --space-1200: 96px;
  --space-1600: 128px;

  /* --- Radii: kit scale 8/11/14 ------------------------------------------ */
  --radius-xs:   4px;
  --radius-sm:   6px;
  --radius-md:   8px;
  --radius-lg:  11px;
  --radius-xl:  14px;
  --radius-full: 9999px;

  /* --- Borders ---------------------------------------------------------- */
  --border-hairline: 1px;
  --border-thick:    1.5px;
  --border-heavy:    2px;
  --focus-width:     2px;
  --focus-offset:    2px;

  /* --- Motion ------------------------------------------------------------ */
  --duration-instant: 80ms;
  --duration-fast:    120ms;
  --duration-base:    180ms;
  --duration-slow:    260ms;
  --duration-slower:  400ms;

  --ease-standard: cubic-bezier(0.2, 0, 0, 1);
  --ease-entrance: cubic-bezier(0, 0, 0, 1);
  --ease-exit:     cubic-bezier(0.3, 0, 1, 1);

  /* --- Layers ------------------------------------------------------------ */
  --z-base:     0;
  --z-raised:   10;
  --z-sticky:   100;
  --z-overlay:  1000;
  --z-modal:    1100;
  --z-toast:    1200;
  --z-tooltip:  1300;
}


/* ==========================================================================
   2. SEMANTIC — DARK · BLUEPRINT (the DEFAULT theme)
   Kit palette: bg #232A33 · surface #2C3540 · ink #F2F5F8 · soft #A5AEB9 ·
   line #3A444F · valid #27C287/#3BD49A · soon #EAAE41/#F2BC55 ·
   expired #E66E5E/#F79A8C. Ratios below are scripted-check results.
   ========================================================================== */

:root,
[data-theme="dark"] {

  color-scheme: dark;

  /* kit status hues, graphic weight + text weight */
  --vt-valid:        #27C287;   --vt-valid-text:   #3BD49A;
  --vt-soon:         #EAAE41;   --vt-soon-text:    #F2BC55;
  --vt-expired:      #E66E5E;   --vt-expired-text: #F79A8C;
  --vt-ink:          #F2F5F8;

  --surface-page:      #232A33;
  --surface-sunken:    #1C232B;
  --surface-raised:    #2C3540;
  --surface-overlay:   #313B47;
  --surface-inverse:   #F2F5F8;
  --surface-hover:     #333D49;
  --surface-active:    #3A444F;
  --surface-selected:  color-mix(in srgb, var(--vt-valid) 14%, transparent);

  /* Text — verified against page / raised */
  --text-strong:    #F2F5F8;   /* 13.23 / 11.35  AAA */
  --text-body:      #D9E0E7;   /* 10.87 /  9.33  AAA */
  --text-muted:     #A5AEB9;   /*  6.45 /  5.53  AA  */
  --text-disabled:  #6C7885;   /* decorative only, never sole carrier of meaning */
  --text-inverse:   #232A33;
  --text-brand:     #3BD49A;   /*  7.63 /  6.55  AAA */
  --text-link:      #3BD49A;

  --border-subtle:      #303945;
  --border-default:     #3A444F;
  --border-interactive: #75828F;   /* 3.16:1 on raised — clears 3:1 */
  --border-strong:      #5C6B77;
  --border-inverse:     #DFE6EC;

  /* Primary is the kit's ink-flip: light ink on the dark sky. */
  --brand-solid:        #F2F5F8;   /* text-inverse on this: 13.23  AAA */
  --brand-solid-hover:  #DFE6EC;
  --brand-solid-text:   #232A33;
  --brand-subtle:       color-mix(in srgb, var(--vt-valid) 16%, var(--surface-page)); /* opaque, see status note */
  --brand-subtle-text:  #3BD49A;   /* 5.72 on subtle  AA */
  --brand-line:         color-mix(in srgb, var(--vt-valid) 40%, transparent);

  --focus-ring:         var(--vt-ink);   /* kit focus: 2px ink */
  --focus-ring-offset:  var(--surface-page);

  /* ---- STATUS: never color alone; icon + label always. -----------------
     Subtle fills are OPAQUE (mixed onto --surface-page, not transparent) so
     the text ratio cannot degrade when a badge sits on a lighter surface —
     hovered table rows (#333D49) and drawer/modal overlays (#313B47) pushed
     translucent fills under 4.5. Ratios below are the fixed composite. */

  --status-current-text:    var(--vt-valid-text);   /* 5.72 on subtle  AA */
  --status-current-subtle:  color-mix(in srgb, var(--vt-valid) 16%, var(--surface-page));
  --status-current-line:    color-mix(in srgb, var(--vt-valid) 45%, transparent);
  --status-current-solid:   var(--vt-valid);

  --status-soon-text:       var(--vt-soon-text);    /* 5.29 on subtle  AA */
  --status-soon-subtle:     color-mix(in srgb, var(--vt-soon) 22%, var(--surface-page));
  --status-soon-line:       color-mix(in srgb, var(--vt-soon) 50%, transparent);
  --status-soon-solid:      var(--vt-soon);

  --status-expired-text:    var(--vt-expired-text); /* 5.53 on subtle  AA */
  --status-expired-subtle:  color-mix(in srgb, var(--vt-expired) 16%, var(--surface-page));
  --status-expired-line:    color-mix(in srgb, var(--vt-expired) 45%, transparent);
  --status-expired-solid:   var(--vt-expired);

  --status-unknown-text:    #C6CFD8;                /* 7.26 on subtle  AA */
  --status-unknown-subtle:  color-mix(in srgb, var(--vt-ink) 8%, var(--surface-page));
  --status-unknown-line:    #4A5560;
  --status-unknown-solid:   #A5AEB9;

  /* Elevation is carried by surface lightness and border on dark. */
  --shadow-none: none;
  --shadow-sm:  0 1px 2px rgba(9, 12, 15, 0.40);
  --shadow-md:  0 2px 6px rgba(9, 12, 15, 0.45);
  --shadow-lg:  0 8px 24px rgba(9, 12, 15, 0.55);
  --shadow-xl:  0 16px 48px rgba(9, 12, 15, 0.65);

  /* Component-scoped themed values */
  --toggle-track-off: #4A5560;
  /* Self-hosted files, not data: URIs — the admin CSP is img-src 'self'. */
  --check-glyph: url("glyph-check-dark.svg");
  --select-glyph: url("glyph-select-dark.svg");
  --scrim-color: rgba(9, 12, 15, 0.66);
  --skeleton-sweep: rgba(242, 245, 248, 0.08);
}


/* ==========================================================================
   3. SEMANTIC — LIGHT · SIGNAL (the toggle alternative)
   Kit palette: bg #F5F6F8 · surface #FFFFFF · ink #232A33 · soft #646D78 ·
   line #E2E5E9 · valid #0FA46F/#09724D · soon #E3A424/#7D5A0C ·
   expired #C64438/#A93A2B.
   ========================================================================== */

[data-theme="light"] {

  color-scheme: light;

  --vt-valid:        #0FA46F;   --vt-valid-text:   #09724D;
  --vt-soon:         #E3A424;   --vt-soon-text:    #7D5A0C;
  --vt-expired:      #C64438;   --vt-expired-text: #A93A2B;
  --vt-ink:          #232A33;

  --surface-page:      #F5F6F8;
  --surface-sunken:    #EDEFF2;
  --surface-raised:    #FFFFFF;
  --surface-overlay:   #FFFFFF;
  --surface-inverse:   #232A33;
  --surface-hover:     #F0F2F4;
  --surface-active:    #E6E9ED;
  --surface-selected:  color-mix(in srgb, var(--vt-valid) 12%, transparent);

  --text-strong:    #232A33;   /* 13.39 / 14.48  AAA */
  --text-body:      #39424E;   /*  9.41  AAA */
  --text-muted:     #5C6570;   /*  5.47 / 5.13 on sunken  AA */
  --text-disabled:  #99A2AC;   /* decorative only */
  --text-inverse:   #F5F6F8;
  --text-brand:     #09724D;   /*  5.51 / 5.96  AA */
  --text-link:      #09724D;

  --border-subtle:      #E9EBEE;
  --border-default:     #E2E5E9;
  --border-interactive: #84919D;   /* 3.22:1 on white */
  --border-strong:      #8F9BA6;
  --border-inverse:     #39424E;

  --brand-solid:        #232A33;   /* white on this: 14.48  AAA */
  --brand-solid-hover:  #39424E;
  --brand-solid-text:   #FFFFFF;
  --brand-subtle:       color-mix(in srgb, var(--vt-valid) 14%, var(--surface-raised)); /* opaque, see status note */
  --brand-subtle-text:  #09724D;   /* 5.11 on subtle  AA */
  --brand-line:         color-mix(in srgb, var(--vt-valid) 40%, transparent);

  --focus-ring:         var(--vt-ink);
  --focus-ring-offset:  var(--surface-page);

  /* Opaque subtle fills (mixed onto white), same reasoning as the dark set:
     translucent fills fell under 4.5 on sunken (#EDEFF2) and hover surfaces. */
  --status-current-text:    var(--vt-valid-text);   /* 4.89 on subtle  AA */
  --status-current-subtle:  color-mix(in srgb, var(--vt-valid) 18%, var(--surface-raised));
  --status-current-line:    color-mix(in srgb, var(--vt-valid) 45%, transparent);
  --status-current-solid:   var(--vt-valid);

  --status-soon-text:       var(--vt-soon-text);    /* 5.17 on subtle  AA */
  --status-soon-subtle:     color-mix(in srgb, var(--vt-soon) 26%, var(--surface-raised));
  --status-soon-line:       color-mix(in srgb, var(--vt-soon) 55%, transparent);
  --status-soon-solid:      var(--vt-soon);

  --status-expired-text:    var(--vt-expired-text); /* 5.04 on subtle  AA */
  --status-expired-subtle:  color-mix(in srgb, var(--vt-expired) 16%, var(--surface-raised));
  --status-expired-line:    color-mix(in srgb, var(--vt-expired) 45%, transparent);
  --status-expired-solid:   var(--vt-expired);

  --status-unknown-text:    #39424E;                /* 8.93 on subtle  AAA */
  --status-unknown-subtle:  color-mix(in srgb, var(--vt-ink) 7%, var(--surface-raised));
  --status-unknown-line:    #D5DBE1;
  --status-unknown-solid:   #646D78;

  --shadow-sm:   0 1px 2px rgba(28, 35, 43, 0.06),
                 0 1px 1px rgba(28, 35, 43, 0.04);
  --shadow-md:   0 2px 4px rgba(28, 35, 43, 0.07),
                 0 4px 10px rgba(28, 35, 43, 0.05);
  --shadow-lg:   0 4px 8px rgba(28, 35, 43, 0.08),
                 0 12px 28px rgba(28, 35, 43, 0.10);
  --shadow-xl:   0 8px 16px rgba(28, 35, 43, 0.10),
                 0 24px 56px rgba(28, 35, 43, 0.14);

  --toggle-track-off: #B7C0C9;
  --check-glyph: url("glyph-check-light.svg");
  --select-glyph: url("glyph-select-light.svg");
  --scrim-color: rgba(28, 35, 43, 0.45);
  --skeleton-sweep: rgba(100, 109, 120, 0.12);
}


/* ==========================================================================
   4. BASE
   ========================================================================== */

*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--surface-page);
  color: var(--text-body);
  font-family: var(--font-sans);
  font-size: var(--size-400);      /* admin default is UI density, not reading */
  line-height: var(--lh-400);
  letter-spacing: var(--track-body);
  font-weight: var(--weight-regular);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* One focus treatment everywhere: 2px ink, per the kit. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: var(--focus-width) solid var(--focus-ring);
  outline-offset: var(--focus-offset);
  border-radius: var(--radius-xs);
}

/* Any element carrying a date or count opts in to tabular figures. */
.vt-figures,
.vt-date,
.vt-count,
.vt-identifier {
  font-variant-numeric: tabular-nums lining-nums;
  font-feature-settings: var(--figures-tabular);
}

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


/* ############################################################################
   LAYER 2 — PRIMITIVES (vt-*)
   ######################################################################### */

/* ==========================================================================
   5. TYPOGRAPHY AND UTILITIES
   ========================================================================== */

/* THE CONSOLE TYPE SCALE — six rungs, no others. Every page uses these and
   nothing between them, so a heading is never mistaken for body text.
     page title    h1                       26/34  w800   once per page
     section title h2 (outside a card)      18/28  w700   .adm-sectionhead
     card title    h3 · .vt-card__title ·
                   h2 inside a card         16/26  w700
     sub-title     h4                       15/22  w700   strong, not muted
     body                                   15/22  w500   .vt-*, page copy
     small                                  13/20  w500   meta, hints, tables
     mono label    11px mono, 0.08em, upper        w500   .adm-stat__label,
                                                          table th, .adm-collabel
   Mono is for numbers, dates, ids, counts and micro-labels — never prose. */
h1, h2, h3, h4 {
  color: var(--text-strong);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--track-heading);
}
h1 { font-size: var(--size-800); line-height: var(--lh-800); font-weight: var(--weight-bold); letter-spacing: var(--track-display); margin: 0 0 var(--space-200); }
h2 { font-size: var(--size-600); line-height: var(--lh-600); margin: var(--space-400) 0 var(--space-200); }
h3 { font-size: var(--size-500); line-height: var(--lh-500); margin: var(--space-300) 0 var(--space-150); }
/* h4 was body size at body-ish weight and read as a paragraph; the weight and
   the strong colour are what separate it now. */
h4 { font-size: var(--size-400); line-height: var(--lh-400); margin: var(--space-250) 0 var(--space-100); }

/* A card, panel or danger box supplies its own top padding: the first thing
   inside it never adds a heading margin on top of that. */
.vt-card > :first-child,
.adm-cannotsee > :first-child,
.adm-danger > :first-child,
.adm-drawer__body > * > :first-child { margin-top: 0; }

/* The mono micro-label rung, for column and field labels that are not table
   headers or stat labels (both of which already carry it). */
.adm-collabel { font-family: var(--font-mono); font-size: var(--size-100); line-height: var(--lh-100);
  letter-spacing: var(--track-label); text-transform: uppercase;
  font-weight: var(--weight-regular); color: var(--text-muted); }

p { margin: 0 0 var(--space-200); }
a { color: var(--text-link); }

.vt-mono, .vt-identifier {
  font-family: var(--font-mono);
  letter-spacing: 0.02em;
}
.vt-eyebrow {
  font-family: var(--font-mono);
  font-size: var(--size-100);
  letter-spacing: var(--track-mrz);
  text-transform: uppercase;
  color: var(--text-brand);
  font-weight: var(--weight-regular);
  margin: 0 0 var(--space-200);
}
.vt-lede {
  font-size: var(--size-500);
  line-height: var(--lh-500);
  color: var(--text-muted);
  max-width: 62ch;
}
.vt-muted { color: var(--text-muted); }

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* Skip link — first focusable element on every page. */
.skip-link {
  position: fixed;
  top: -100px;
  left: var(--space-200);
  z-index: var(--z-tooltip);
  background: var(--surface-inverse);
  color: var(--text-inverse);
  padding: var(--space-100) var(--space-200);
  border-radius: var(--radius-md);
  font-size: var(--size-300);
  font-weight: var(--weight-medium);
  text-decoration: none;
  box-shadow: var(--shadow-lg);
}
.skip-link:focus,
.skip-link:focus-visible { top: var(--space-200); }


/* ==========================================================================
   6. BUTTONS — primary, secondary, ghost, danger. One primary per screen.
   Primary is the kit's ink-flip: light ink on the dark sky, and vice versa.
   ========================================================================== */

.vt-btn {
  font-family: var(--font-sans); font-size: var(--size-400); line-height: 1;
  font-weight: var(--weight-medium); letter-spacing: 0;
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-100);
  padding: 0 var(--space-250); height: 38px;
  border-radius: var(--radius-lg); border: var(--border-thick) solid transparent;
  cursor: pointer; white-space: nowrap; text-decoration: none;
  transition: background var(--duration-fast) var(--ease-standard),
              border-color var(--duration-fast) var(--ease-standard),
              color var(--duration-fast) var(--ease-standard);
}
.vt-btn svg { width: 16px; height: 16px; flex: none; }
.vt-btn--sm { height: 30px; font-size: var(--size-300); padding: 0 var(--space-150); border-radius: var(--radius-md); }
.vt-btn--lg { height: 46px; font-size: var(--size-500); padding: 0 var(--space-300); }
.vt-btn--full { width: 100%; }

.vt-btn--primary { background: var(--brand-solid); color: var(--brand-solid-text); }
.vt-btn--primary:hover { background: var(--brand-solid-hover); }
.vt-btn--primary:active { background: var(--brand-solid-hover); transform: translateY(0.5px); }

.vt-btn--secondary { background: var(--surface-raised); color: var(--text-body); border-color: var(--border-interactive); }
.vt-btn--secondary:hover { background: var(--surface-hover); border-color: var(--border-strong);
  color: var(--text-strong); }
.vt-btn--secondary:active { background: var(--surface-active); }

.vt-btn--ghost { background: transparent; color: var(--text-body); }
.vt-btn--ghost:hover { background: color-mix(in srgb, var(--vt-ink) 6%, transparent); color: var(--text-strong); }
.vt-btn--ghost:active { background: var(--surface-active); }

/* Danger text uses --surface-page so it flips with the theme:
   dark = #232A33 on #E66E5E (4.66), light = #F5F6F8 on #C64438 (4.53). */
.vt-btn--danger { background: var(--status-expired-solid); color: var(--surface-page); }
.vt-btn--danger:hover { filter: brightness(0.92); }

.vt-btn:disabled, .vt-btn[aria-disabled="true"] {
  cursor: not-allowed; background: var(--surface-sunken); color: var(--text-disabled);
  border-color: var(--border-subtle); filter: none; transform: none;
}
.vt-btn[data-loading="true"] { cursor: progress; }
.vt-btn .spin { animation: vt-spin 700ms linear infinite; transform-origin: center; }
@keyframes vt-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .vt-btn .spin { animation: none; } }

@media (pointer: coarse) {
  .vt-btn--primary, .vt-btn--danger { min-height: 44px; }
}


/* ==========================================================================
   7. FIELDS
   ========================================================================== */

.vt-field { display: flex; flex-direction: column; gap: var(--space-75); max-width: 360px; }
.vt-field--wide { max-width: none; }
.vt-label { font-size: var(--size-300); font-weight: var(--weight-medium); color: var(--text-strong); }
.vt-label .vt-optional { color: var(--text-muted); font-weight: var(--weight-regular); }
.vt-hint { font-size: var(--size-200); line-height: var(--lh-200); color: var(--text-muted); }
.vt-error { font-size: var(--size-200); line-height: var(--lh-200); color: var(--status-expired-text); display: flex; align-items: center; gap: var(--space-75); }
.vt-error svg { width: 13px; height: 13px; flex: none; }

.vt-input, .vt-select, .vt-textarea {
  font-family: var(--font-sans); font-size: var(--size-400); line-height: 1.4;
  font-weight: var(--weight-regular);
  color: var(--text-strong); background: var(--surface-raised);
  border: var(--border-thick) solid var(--border-interactive);
  border-radius: var(--radius-lg); padding: var(--space-100) var(--space-150); height: 38px; width: 100%;
  transition: border-color var(--duration-fast) var(--ease-standard);
}
.vt-textarea { height: auto; min-height: 88px; resize: vertical; padding: var(--space-150); }
.vt-input::placeholder, .vt-textarea::placeholder { color: var(--text-muted); }
.vt-input:hover, .vt-select:hover, .vt-textarea:hover { border-color: var(--border-strong); }
.vt-input:focus-visible, .vt-select:focus-visible, .vt-textarea:focus-visible {
  border-color: var(--focus-ring); outline-offset: 1px; }
.vt-input:disabled, .vt-textarea:disabled, .vt-select:disabled {
  background: var(--surface-sunken); color: var(--text-disabled); cursor: not-allowed; border-color: var(--border-subtle);
}
.vt-input[aria-invalid="true"], .vt-textarea[aria-invalid="true"], .vt-select[aria-invalid="true"] {
  border-color: var(--status-expired-solid); border-width: var(--border-thick);
}

.vt-input[data-mono="true"],
.vt-input.vt-date,
.vt-input[type="date"] {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
}

.vt-select {
  appearance: none; padding-right: var(--space-500);
  background-image: var(--select-glyph);
  background-repeat: no-repeat; background-position: right var(--space-150) center; background-size: 16px;
}

/* Compact variants for table filter bars and dense panels. */
.vt-input--sm, .vt-select--sm { height: 32px; font-size: var(--size-300); padding: var(--space-50) var(--space-100); border-radius: var(--radius-md); }
.vt-select--sm { padding-right: var(--space-400); background-position: right var(--space-100) center; }


/* ==========================================================================
   8. CHECKBOX · RADIO · TOGGLE
   ========================================================================== */

.vt-check { display: flex; align-items: flex-start; gap: var(--space-150); cursor: pointer; font-size: var(--size-400); line-height: var(--lh-400); color: var(--text-body); }
.vt-check input { appearance: none; width: 18px; height: 18px; margin: 0; flex: none; margin-top: 2px;
  border: var(--border-thick) solid var(--border-interactive); background: var(--surface-raised); cursor: pointer;
  transition: background var(--duration-fast) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard); }
.vt-check input[type="checkbox"] { border-radius: var(--radius-xs); }
.vt-check input[type="radio"] { border-radius: var(--radius-full); }
.vt-check input:hover { border-color: var(--border-strong); }
.vt-check input:checked { background: var(--brand-solid); border-color: var(--brand-solid); }
.vt-check input[type="checkbox"]:checked {
  background-image: var(--check-glyph);
  background-size: 14px; background-position: center; background-repeat: no-repeat;
}
.vt-check input[type="radio"]:checked { box-shadow: inset 0 0 0 3px var(--surface-raised); }
.vt-check input:disabled { background: var(--surface-sunken); border-color: var(--border-subtle); cursor: not-allowed; }
.vt-check:has(input:disabled) { color: var(--text-disabled); cursor: not-allowed; }

.vt-toggle { display: inline-flex; align-items: center; gap: var(--space-150); cursor: pointer; font-size: var(--size-400); color: var(--text-body); }
.vt-toggle input { appearance: none; width: 40px; height: 23px; margin: 0; flex: none; border-radius: var(--radius-full);
  background: var(--toggle-track-off); position: relative; cursor: pointer;
  transition: background var(--duration-base) var(--ease-standard); }
.vt-toggle input::after { content: ""; position: absolute; top: 3px; left: 3px; width: 17px; height: 17px; border-radius: var(--radius-full);
  background: var(--surface-raised); box-shadow: var(--shadow-sm);
  transition: transform var(--duration-base) var(--ease-standard); }
[data-theme="light"] .vt-toggle input::after { background: #FFFFFF; }
.vt-toggle input:checked { background: var(--brand-solid); }
.vt-toggle input:checked::after { background: var(--brand-solid-text); }
.vt-toggle input:checked::after { transform: translateX(17px); }
.vt-toggle input:disabled { opacity: .45; cursor: not-allowed; }


/* ==========================================================================
   9. ITEM-STATUS BADGES (vt-badge) — the product's four expiry states.
   Admin/ops statuses use .adm-badge in Layer 4. Icon + text, always.
   ========================================================================== */

.vt-badge {
  display: inline-flex; align-items: center; gap: var(--space-75);
  font-size: var(--size-200); font-weight: var(--weight-medium); line-height: 1;
  letter-spacing: 0.02em;
  padding: var(--space-75) var(--space-150); border-radius: var(--radius-full);
  border: var(--border-hairline) solid;
}
.vt-badge svg { width: 12px; height: 12px; flex: none; }
.vt-badge--current { color: var(--status-current-text); background: var(--status-current-subtle); border-color: var(--status-current-line); }
.vt-badge--soon    { color: var(--status-soon-text);    background: var(--status-soon-subtle);    border-color: var(--status-soon-line); }
.vt-badge--expired { color: var(--status-expired-text); background: var(--status-expired-subtle); border-color: var(--status-expired-line); }
.vt-badge--unknown { color: var(--status-unknown-text); background: var(--status-unknown-subtle); border-color: var(--status-unknown-line); }


/* ==========================================================================
   10. CARDS · LIST ROWS
   ========================================================================== */

.vt-card { border: var(--border-hairline) solid var(--border-default); border-radius: var(--radius-xl);
  background: var(--surface-raised); padding: var(--space-300); box-shadow: var(--shadow-sm); }
.vt-card__head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-200); }
.vt-card__title { font-size: var(--size-500); line-height: var(--lh-500); font-weight: var(--weight-semibold); color: var(--text-strong); margin: 0; letter-spacing: var(--track-heading); }
.vt-card__meta { font-size: var(--size-300); line-height: var(--lh-300); color: var(--text-muted); margin: var(--space-75) 0 0; }
/* An h2 that titles a card is a CARD title, not a section title: two cards
   side by side must not disagree about how big their headings are. Section
   titles live outside the card, in .adm-sectionhead. (.vt-empty overrides
   this below — its headline is the whole point of the card.) */
.vt-card h2, .adm-cannotsee h2, .adm-danger h2 { font-size: var(--size-500); line-height: var(--lh-500); }
.vt-card > h2, .adm-cannotsee > h2, .adm-danger > h2 { margin-bottom: var(--space-150); }

a.vt-card { display: block; text-decoration: none; color: inherit; transition: border-color var(--duration-fast) var(--ease-standard); }
a.vt-card:hover { border-color: var(--border-strong); }

.vt-list { border: var(--border-hairline) solid var(--border-default); border-radius: var(--radius-xl);
  background: var(--surface-raised); overflow: hidden; }

.vt-row { display: flex; align-items: center; gap: var(--space-250); padding: var(--space-200) var(--space-250);
  border-bottom: var(--border-hairline) solid var(--border-subtle); transition: background var(--duration-fast) var(--ease-standard); }
.vt-row:hover { background: var(--surface-hover); }
.vt-row:last-child { border-bottom: 0; }
a.vt-row { text-decoration: none; color: inherit; }
.vt-row__body { flex: 1; min-width: 0; }
.vt-row__title { font-size: var(--size-400); font-weight: var(--weight-medium); color: var(--text-strong); margin: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (max-width: 639px) {
  .vt-row__title { white-space: normal; }
}
.vt-row__sub { font-size: var(--size-300); line-height: var(--lh-300); color: var(--text-muted); margin: 2px 0 0; }
.vt-row__date { font-family: var(--font-mono); font-size: var(--size-300); line-height: var(--lh-300); color: var(--text-body);
  font-variant-numeric: tabular-nums; text-align: right; flex: none; }
.vt-row__date .is-soon    { color: var(--status-soon-text); }
.vt-row__date .is-expired { color: var(--status-expired-text); }
.vt-row__date .is-muted   { color: var(--text-muted); }


/* ==========================================================================
   11. IN-PAGE TABS
   ========================================================================== */

.vt-tabs { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-50);
  border-bottom: var(--border-hairline) solid var(--border-subtle); }
.vt-tab { appearance: none; background: none; border: none; cursor: pointer;
  font-family: var(--font-sans); font-size: var(--size-400); font-weight: var(--weight-medium);
  color: var(--text-muted); text-decoration: none; white-space: nowrap;
  padding: var(--space-150) var(--space-200);
  border-bottom: var(--border-heavy) solid transparent; margin-bottom: -1px; min-height: 44px; }
.vt-tab:hover { color: var(--text-body); }
.vt-tab[aria-selected="true"], .vt-tab[aria-current="page"] { color: var(--text-strong); border-bottom-color: var(--status-current-solid); }
.vt-tabpanel { padding-top: var(--space-300); }
.vt-tabpanel[hidden] { display: none; }


/* ==========================================================================
   12. MODAL + SCRIM · TOAST · EMPTY STATE · SKELETON
   ========================================================================== */

.vt-scrim { position: fixed; inset: 0; z-index: var(--z-modal);
  background: var(--scrim-color);
  display: flex; align-items: center; justify-content: center; padding: var(--space-300); }
.vt-scrim[hidden] { display: none; }

.vt-modal { border: var(--border-hairline) solid var(--border-default); border-radius: var(--radius-xl);
  background: var(--surface-overlay); box-shadow: var(--shadow-xl); width: 100%; max-width: 440px; padding: var(--space-400); }
.vt-modal h4, .vt-modal h2 { font-size: var(--size-700); line-height: var(--lh-700); font-weight: var(--weight-semibold); letter-spacing: var(--track-heading);
  color: var(--text-strong); margin: 0 0 var(--space-150); }
.vt-modal p { font-size: var(--size-400); line-height: var(--lh-400); color: var(--text-muted); margin: 0 0 var(--space-300); }
.vt-modal__actions { display: flex; gap: var(--space-150); justify-content: flex-end; flex-wrap: wrap; }

.vt-toast-region { position: fixed; right: var(--space-300); bottom: var(--space-300); z-index: var(--z-toast);
  display: flex; flex-direction: column; gap: var(--space-150); max-width: calc(100vw - var(--space-600)); }
.vt-toast { display: flex; align-items: flex-start; gap: var(--space-150); max-width: 420px;
  border: var(--border-hairline) solid var(--border-default); border-left: 3px solid var(--status-current-solid);
  border-radius: var(--radius-lg); background: var(--surface-overlay); box-shadow: var(--shadow-lg);
  padding: var(--space-200) var(--space-250); }
.vt-toast svg { width: 18px; height: 18px; flex: none; margin-top: 1px; color: var(--text-brand); }
.vt-toast--warn { border-left-color: var(--status-soon-solid); }
.vt-toast--warn svg { color: var(--status-soon-text); }
.vt-toast--error { border-left-color: var(--status-expired-solid); }
.vt-toast--error svg { color: var(--status-expired-text); }
.vt-toast p { margin: 0; font-size: var(--size-400); line-height: var(--lh-400); color: var(--text-body); }
.vt-toast p b { display: block; color: var(--text-strong); font-weight: var(--weight-medium); }

.vt-empty { text-align: center; padding: var(--space-800) var(--space-400);
  border: var(--border-thick) dashed var(--border-default); border-radius: var(--radius-xl); background: var(--surface-sunken); }
.vt-empty svg { width: 36px; height: 36px; color: var(--text-disabled); margin-bottom: var(--space-200); }
.vt-empty h4, .vt-empty h2 { font-size: var(--size-600); line-height: var(--lh-600); font-weight: var(--weight-semibold); color: var(--text-strong); margin: 0 0 var(--space-75); }
/* Centred text needs a measure: full-bleed empty states were running to 90+
   characters a line on a 1200px column. */
.vt-empty p { font-size: var(--size-400); line-height: var(--lh-400); color: var(--text-muted);
  margin: 0 auto var(--space-300); max-width: 62ch; }
.vt-empty__actions { display: flex; gap: var(--space-200); justify-content: center; flex-wrap: wrap; }

.vt-skel { background: var(--surface-active); border-radius: var(--radius-sm); position: relative; overflow: hidden; }
[data-theme="light"] .vt-skel { background: var(--surface-sunken); }
.vt-skel::after { content: ""; position: absolute; inset: 0; transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, var(--skeleton-sweep), transparent);
  animation: vt-sweep 1.4s ease-in-out infinite; }
@keyframes vt-sweep { to { transform: translateX(100%); } }
@media (prefers-reduced-motion: reduce) { .vt-skel::after { animation: none; } }


/* ############################################################################
   LAYER 3 — ADMIN SHELL (adm-*)
   Desktop ≥1024px: 240px grouped sidebar + content column.
   768–1023px: 64px icon rail (labels hidden, groups flattened).
   <768px: sidebar hidden; fixed bottom bar opens a bottom-sheet nav.
   Every page: slim top bar + <main> + fixed audit footer line.
   ######################################################################### */

.adm-shell { display: grid; grid-template-columns: 1fr; min-height: 100vh; }

/* --- Sidebar ------------------------------------------------------------ */

.adm-sidebar { display: none; flex-direction: column;
  position: sticky; top: 0; height: 100vh; overflow-y: auto; overflow-x: hidden;
  padding: var(--space-150) var(--space-100);
  background: var(--surface-sunken);
  border-right: var(--border-hairline) solid var(--border-subtle); }

/* --- Logo: kit ring mark + the "ValidThru / Admin" lockup ----------------
   One lockup, one typeface: both words carry the wordmark's family, size and
   weight; the separator is thin and "Admin" is muted, so the hierarchy reads
   without a second family. The ring mark itself is untouched. */

.adm-logo { display: flex; align-items: center; gap: var(--space-75);
  text-decoration: none; color: var(--text-strong);
  margin: 0 var(--space-50) var(--space-150); min-height: 32px; }
.adm-logo svg { width: 26px; height: 26px; flex: none; }
.adm-logo__ring { transform: rotate(-90deg); }         /* arc starts at midnight */
.adm-logo__ring circle { fill: none; stroke-width: 4.5; }
.adm-logo__ring-track { stroke: var(--border-default); }
.adm-logo__ring-arc { stroke: var(--status-current-solid);
  stroke-linecap: round; stroke-dasharray: 75 100; }
.adm-logo__ring-check { fill: none; stroke: var(--text-strong); stroke-width: 3.9;
  stroke-linecap: round; stroke-linejoin: round; }
.adm-logo__word { display: inline-flex; align-items: baseline; gap: var(--space-50);
  font-size: var(--size-400); font-weight: var(--weight-bold);
  letter-spacing: -0.02em; white-space: nowrap; }
.adm-logo__word i { font-style: normal; font-weight: var(--weight-regular); color: var(--text-muted); }
.adm-logo__sep { font-weight: var(--weight-regular); color: var(--text-disabled); }
.adm-logo__admin { color: var(--text-muted); }

/* Grouped nav. Groups collapse via [data-collapsed] set by the page script.
   Row heights are the density budget: 15 entries, 7 group labels, the logo and
   the foot all have to clear a 640px viewport, so every rung is measured.
   Entries never go below 32px; group labels are secondary controls and sit at
   26px, above the 24px pointer-target floor. */
.adm-navgroup { margin-bottom: var(--space-50); }
.adm-navgroup__toggle { appearance: none; background: none; border: none; cursor: pointer;
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-100);
  width: 100%; min-height: 26px; padding: var(--space-25) var(--space-100);
  font-family: var(--font-mono); font-size: var(--size-100); line-height: var(--lh-100);
  letter-spacing: var(--track-label); text-transform: uppercase;
  font-weight: var(--weight-regular); color: var(--text-muted); text-align: left; }
.adm-navgroup__toggle:hover { color: var(--text-body); }
.adm-navgroup__toggle svg { width: 13px; height: 13px; flex: none;
  transition: transform var(--duration-fast) var(--ease-standard); }
.adm-navgroup[data-collapsed="true"] .adm-navgroup__toggle svg { transform: rotate(-90deg); }
.adm-navgroup[data-collapsed="true"] .adm-nav { display: none; }

.adm-nav { display: flex; flex-direction: column; gap: 0; }
.adm-nav a { display: flex; align-items: center; gap: var(--space-100);
  padding: var(--space-50) var(--space-100); min-height: 32px;
  border-radius: var(--radius-md);
  font-size: var(--size-300); line-height: var(--lh-200); font-weight: var(--weight-medium);
  color: var(--text-body); text-decoration: none; white-space: nowrap;
  transition: background var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard); }
.adm-nav a svg { width: 17px; height: 17px; flex: none; color: var(--text-muted); }
.adm-nav a:hover { background: var(--surface-hover); color: var(--text-strong); }
/* Current page: a solid rail on the leading edge plus the heavier weight, so
   the state survives a grayscale print or a colour-blind reading. */
.adm-nav a[aria-current="page"] { background: var(--surface-selected); color: var(--brand-subtle-text);
  font-weight: var(--weight-semibold);
  box-shadow: inset 2px 0 0 0 var(--status-current-solid); }
.adm-nav a[aria-current="page"] svg { color: inherit; }

.adm-sidebar__foot { margin-top: auto; padding: var(--space-150) var(--space-100) 0;
  border-top: var(--border-hairline) solid var(--border-subtle);
  font-size: var(--size-100); line-height: 1.3; color: var(--text-muted); }
.adm-sidebar__foot .vt-btn { height: 28px; margin-bottom: var(--space-25); }

/* --- Content column ----------------------------------------------------- */

.adm-body { min-width: 0; display: flex; flex-direction: column; }

/* Slim top bar: breadcrumb · PRODUCTION badge · search · theme · identity */
.adm-topbar { position: sticky; top: 0; z-index: var(--z-sticky);
  display: flex; align-items: center; gap: var(--space-150);
  min-height: 52px; padding: var(--space-75) var(--space-200);
  background: var(--surface-page);
  border-bottom: var(--border-hairline) solid var(--border-subtle); }

/* Breadcrumb. <nav class="adm-crumbs"><ol><li><a>…, current li has
   aria-current="page". Separator is drawn, not typed, and hidden from AT. */
.adm-crumbs { min-width: 0; }
.adm-crumbs ol { display: flex; align-items: center; gap: var(--space-75);
  list-style: none; margin: 0; padding: 0; min-width: 0; }
.adm-crumbs li { display: flex; align-items: center; gap: var(--space-75);
  font-size: var(--size-300); white-space: nowrap; min-width: 0; }
.adm-crumbs li + li::before { content: "/"; color: var(--text-disabled); }
.adm-crumbs a { color: var(--text-muted); text-decoration: none; }
.adm-crumbs a:hover { color: var(--text-body); text-decoration: underline; }
.adm-crumbs [aria-current="page"] { color: var(--text-strong); font-weight: var(--weight-medium);
  overflow: hidden; text-overflow: ellipsis; }

/* Environment badge. Amber = live data, tread carefully. Pairing is the
   verified soon-status pair in both themes. Not color alone: the word IS
   the message. */
.adm-env { flex: none; display: inline-flex; align-items: center;
  font-family: var(--font-mono); font-size: var(--size-100); line-height: 1;
  letter-spacing: var(--track-label); text-transform: uppercase; font-weight: var(--weight-medium);
  color: var(--status-soon-text); background: var(--status-soon-subtle);
  border: var(--border-hairline) solid var(--status-soon-line);
  border-radius: var(--radius-sm); padding: var(--space-50) var(--space-100); }

/* Top-bar search — an <a> to the search affordance styled as a field. */
.adm-search { flex: 1; max-width: 360px; min-width: 0; margin-left: auto;
  display: flex; align-items: center; gap: var(--space-100);
  height: 34px; padding: 0 var(--space-150);
  border: var(--border-hairline) solid var(--border-interactive);
  border-radius: var(--radius-lg); background: var(--surface-raised);
  color: var(--text-muted); font-size: var(--size-300);
  text-decoration: none; white-space: nowrap;
  transition: border-color var(--duration-fast) var(--ease-standard); }
.adm-search:hover { border-color: var(--border-strong); }
.adm-search svg { width: 15px; height: 15px; flex: none; }
.adm-search span { overflow: hidden; text-overflow: ellipsis; }
.adm-search kbd { margin-left: auto; font-family: var(--font-mono); font-size: var(--size-100);
  color: var(--text-muted); border: var(--border-hairline) solid var(--border-default);
  border-radius: var(--radius-xs); padding: 1px 5px; }

/* Icon button (theme toggle and friends). 40px target. */
.adm-iconbtn { position: relative; width: 40px; height: 40px; flex: none;
  display: grid; place-items: center;
  border: none; background: transparent; border-radius: var(--radius-md);
  color: var(--text-body); cursor: pointer; text-decoration: none;
  transition: background var(--duration-fast) var(--ease-standard); }
.adm-iconbtn:hover { background: var(--surface-hover); }
.adm-iconbtn svg { width: 19px; height: 19px; }

/* Theme toggle shows one icon at a time. Dark is the default, so the moon
   shows unless the light theme is explicitly on. */
.adm-themetoggle .adm-themetoggle__light { display: none; }
.adm-themetoggle .adm-themetoggle__dark { display: block; }
[data-theme="light"] .adm-themetoggle .adm-themetoggle__light { display: block; }
[data-theme="light"] .adm-themetoggle .adm-themetoggle__dark { display: none; }

/* Admin identity chip. */
.adm-id { display: flex; align-items: center; gap: var(--space-100); flex: none;
  min-height: 40px; padding: var(--space-50); padding-right: var(--space-150);
  border-radius: var(--radius-full); text-decoration: none;
  color: var(--text-body); font-size: var(--size-300); font-weight: var(--weight-medium);
  transition: background var(--duration-fast) var(--ease-standard); }
.adm-id:hover { background: var(--surface-hover); }
.adm-id__avatar { width: 28px; height: 28px; flex: none; border-radius: var(--radius-full);
  display: grid; place-items: center;
  background: var(--brand-subtle); color: var(--brand-subtle-text);
  font-size: var(--size-200); font-weight: var(--weight-semibold); line-height: 1; }
.adm-id__role { display: block; font-size: var(--size-100); line-height: var(--lh-100);
  font-weight: var(--weight-regular); color: var(--text-muted); }

/* --- Main region --------------------------------------------------------- */

/* Bottom padding clears the fixed audit footer (and mobile bar below 768). */
.adm-main { flex: 1;
  padding: var(--space-300) var(--space-200) calc(var(--space-600) + 44px); }
.adm-content { max-width: 1200px; margin: 0 auto; }

/* Page header row: h1 + actions on one line where room allows. */
.adm-pagehead { display: flex; align-items: flex-end; justify-content: space-between;
  flex-wrap: wrap; gap: var(--space-150) var(--space-300); margin-bottom: var(--space-300); }
.adm-pagehead h1 { margin: 0; }
.adm-pagehead__sub { font-size: var(--size-300); line-height: var(--lh-300);
  color: var(--text-muted); margin: var(--space-50) 0 0; max-width: 70ch; }
.adm-pagehead__actions { display: flex; align-items: center; gap: var(--space-150); flex-wrap: wrap; }

/* --- Audit footer line ---------------------------------------------------
   Persistent on every page. Fixed so it is present regardless of scroll —
   the point is that the operator can never not know they are logged. */
.adm-audit { position: fixed; left: 0; right: 0; bottom: 0; z-index: var(--z-sticky);
  display: flex; align-items: center; gap: var(--space-100);
  min-height: 34px; padding: var(--space-50) var(--space-200);
  background: var(--surface-sunken);
  border-top: var(--border-hairline) solid var(--border-subtle);
  font-family: var(--font-mono); font-size: var(--size-100); line-height: var(--lh-100);
  letter-spacing: 0.02em; color: var(--text-muted);
  font-variant-numeric: tabular-nums; }
.adm-audit svg { width: 13px; height: 13px; flex: none; color: var(--text-brand); }
.adm-audit b { font-weight: var(--weight-medium); color: var(--text-body); }
.adm-audit span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* --- Mobile bottom bar + bottom sheet (<768px) --------------------------- */

.adm-mobilebar { position: fixed; left: 0; right: 0; bottom: 0; z-index: var(--z-overlay);
  display: flex; align-items: stretch; gap: var(--space-100);
  background: var(--surface-raised);
  border-top: var(--border-hairline) solid var(--border-default);
  padding: var(--space-75) var(--space-150);
  padding-bottom: calc(var(--space-75) + env(safe-area-inset-bottom, 0px)); }
.adm-mobilebar__menu { flex: 1; display: flex; align-items: center; justify-content: center;
  gap: var(--space-100); min-height: 44px;
  border: var(--border-hairline) solid var(--border-interactive);
  border-radius: var(--radius-lg); background: var(--surface-raised);
  font-family: var(--font-sans); font-size: var(--size-400); font-weight: var(--weight-medium);
  color: var(--text-body); cursor: pointer; }
.adm-mobilebar__menu:hover { background: var(--surface-hover); }
.adm-mobilebar__menu svg { width: 18px; height: 18px; }

/* Scrim shared by the sheet and the drawer. */
.adm-scrim { position: fixed; inset: 0; z-index: var(--z-overlay);
  background: var(--scrim-color); }
.adm-scrim[hidden] { display: none; }

.adm-sheet { position: fixed; left: 0; right: 0; bottom: 0; z-index: calc(var(--z-overlay) + 1);
  max-height: 82dvh; overflow-y: auto;
  background: var(--surface-overlay);
  border-top: var(--border-hairline) solid var(--border-default);
  border-radius: var(--radius-xl) var(--radius-xl) 0 0;
  box-shadow: var(--shadow-xl);
  padding: var(--space-150) var(--space-200) calc(var(--space-400) + env(safe-area-inset-bottom, 0px));
  transform: translateY(100%); visibility: hidden;
  transition: transform var(--duration-slow) var(--ease-entrance),
              visibility 0s linear var(--duration-slow); }
.adm-sheet[data-open="true"] { transform: translateY(0); visibility: visible; transition-delay: 0s; }
.adm-sheet__grip { width: 36px; height: 4px; border-radius: var(--radius-full);
  background: var(--border-strong); margin: 0 auto var(--space-200); }
/* The sheet is a touch surface: it keeps the roomier rows the sidebar gave up. */
.adm-sheet .adm-navgroup { margin-bottom: var(--space-100); }
.adm-sheet .adm-navgroup__toggle { min-height: 40px; padding-inline: var(--space-150); }
.adm-sheet .adm-nav { gap: var(--space-25); }
.adm-sheet .adm-nav a { min-height: 44px; gap: var(--space-150);
  padding: var(--space-75) var(--space-150); font-size: var(--size-400); }

/* --- Responsive shell ---------------------------------------------------- */

/* Icon rail: 768–1023px. Labels and group headers hidden; collapse state
   ignored so every destination stays one click away. */
@media (min-width: 768px) {
  .adm-shell { grid-template-columns: 64px minmax(0, 1fr); }
  .adm-sidebar { display: flex; align-items: stretch; padding-inline: var(--space-100); }
  .adm-mobilebar, .adm-sheet { display: none; }

  .adm-logo { justify-content: center; margin-inline: 0; margin-bottom: var(--space-100); }
  .adm-logo__word { position: absolute; width: 1px; height: 1px;
    padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

  .adm-sidebar .adm-navgroup__toggle { display: none; }
  .adm-sidebar .adm-navgroup[data-collapsed="true"] .adm-nav { display: flex; }
  .adm-sidebar .adm-navgroup { margin-bottom: 0; }
  .adm-sidebar .adm-navgroup + .adm-navgroup { margin-top: var(--space-50);
    padding-top: var(--space-50); border-top: var(--border-hairline) solid var(--border-default); }
  .adm-sidebar .adm-nav a { justify-content: center; padding: var(--space-50); min-height: 34px; }
  .adm-sidebar .adm-nav a .adm-nav__label { position: absolute; width: 1px; height: 1px;
    padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
  .adm-sidebar__foot { display: none; }

  .adm-audit { left: 64px; }
  .adm-topbar { padding-inline: var(--space-300); }
  .adm-main { padding: var(--space-400) var(--space-300) calc(var(--space-600) + 44px); }
}

/* Full 240px sidebar: ≥1024px. */
@media (min-width: 1024px) {
  .adm-shell { grid-template-columns: 240px minmax(0, 1fr); }
  .adm-sidebar { padding-inline: var(--space-100); }

  .adm-logo { justify-content: flex-start; margin: 0 var(--space-50) var(--space-150); }
  .adm-logo__word { position: static; width: auto; height: auto;
    margin: 0; padding: 0; overflow: visible; clip: auto; }

  .adm-sidebar .adm-navgroup__toggle { display: flex; }
  .adm-sidebar .adm-navgroup[data-collapsed="true"] .adm-nav { display: none; }
  .adm-sidebar .adm-navgroup { margin-bottom: var(--space-50); }
  .adm-sidebar .adm-navgroup + .adm-navgroup { margin-top: 0; padding-top: 0; border-top: 0; }
  .adm-sidebar .adm-nav a { justify-content: flex-start; padding: var(--space-50) var(--space-100); min-height: 32px; }
  .adm-sidebar .adm-nav a .adm-nav__label { position: static; width: auto; height: auto;
    margin: 0; padding: 0; overflow: visible; clip: auto; }
  .adm-sidebar__foot { display: block; }

  .adm-audit { left: 240px; }
  .adm-main { padding: var(--space-400) var(--space-400) calc(var(--space-800) + 44px); }
}

/* Short viewports — a 13-inch laptop is about 640px of viewport once browser
   chrome is subtracted, and 15 entries at 32px already spend 480 of it. The
   seven group label rows are the only chrome big enough to buy the fit, so
   they give way to hairline separators: the grouping still reads, every
   entry stays visible, and no row shrinks below 32px. Each group keeps its
   name for assistive technology via aria-label on .adm-navgroup, and collapse
   is suspended here so a group closed on a taller screen cannot hide itself
   with its toggle gone. */
@media (min-width: 768px) and (max-height: 880px) {
  .adm-sidebar { padding-block: var(--space-75); }
  .adm-logo { margin-bottom: var(--space-50); }
  .adm-sidebar .adm-navgroup__toggle { display: none; }
  .adm-sidebar .adm-navgroup[data-collapsed="true"] .adm-nav { display: flex; }
  .adm-sidebar .adm-navgroup { margin-bottom: 0; }
  .adm-sidebar .adm-navgroup + .adm-navgroup { margin-top: var(--space-25);
    padding-top: var(--space-50); border-top: var(--border-hairline) solid var(--border-default); }
  .adm-sidebar__foot { padding-top: var(--space-75); }
}

/* Narrow phones: nothing overflows at 375px. */
@media (max-width: 767px) {
  .adm-main { padding-bottom: calc(var(--space-600) + 44px + 60px); }
  .adm-audit { bottom: calc(58px + env(safe-area-inset-bottom, 0px)); }
}
@media (max-width: 639px) {
  .adm-topbar { gap: var(--space-100); padding: var(--space-75) var(--space-150); }
  .adm-search { display: none; }
  .adm-id__name { display: none; }
  .adm-id { padding-right: var(--space-50); }
  .adm-crumbs { margin-right: auto; }
}


/* ############################################################################
   LAYER 4 — ADMIN COMPONENTS (adm-*)
   ######################################################################### */

/* ==========================================================================
   20. STAT CARD — value, delta arrow + label, footnote, optional sparkline
   Big figures in Archivo 800 like the a1 orbit instrument; labels in mono.
   ========================================================================== */

/* The strip packs itself, which is right for three, four or five cards. Six
   packed into a five-column content column leaves one card orphaned on a row
   of its own, and two cards leave three empty tracks — so those two counts
   declare their shape with a modifier and the row always divides evenly. */
.adm-statgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: var(--space-200); margin-bottom: var(--space-300); }
@media (min-width: 900px) {
  .adm-statgrid--2 { grid-template-columns: repeat(2, minmax(180px, 300px)); }
  .adm-statgrid--6 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

.adm-stat { border: var(--border-hairline) solid var(--border-default); border-radius: var(--radius-xl);
  background: var(--surface-raised); padding: var(--space-250); box-shadow: var(--shadow-sm);
  display: flex; flex-direction: column; gap: var(--space-75); min-width: 0; }
a.adm-stat { text-decoration: none; color: inherit;
  transition: border-color var(--duration-fast) var(--ease-standard); }
a.adm-stat:hover { border-color: var(--border-strong); }

.adm-stat__label { font-family: var(--font-mono); font-size: var(--size-100); line-height: var(--lh-100);
  letter-spacing: var(--track-label); text-transform: uppercase;
  font-weight: var(--weight-regular); color: var(--text-muted); }
.adm-stat__value { font-family: var(--font-sans); font-size: var(--size-800); line-height: var(--lh-800);
  font-weight: var(--weight-bold); color: var(--text-strong);
  font-variant-numeric: tabular-nums; letter-spacing: var(--track-display); }
.adm-stat__value small { font-size: var(--size-400); font-weight: var(--weight-regular); color: var(--text-muted); letter-spacing: 0; }

/* Delta: arrow SVG + written change + period label. The arrow and the text
   carry direction; color reinforces. --down uses red only when down is bad —
   pass --down --is-good to render a good decline (e.g. churn) in green. */
.adm-stat__delta { display: inline-flex; align-items: center; gap: var(--space-50);
  font-family: var(--font-mono); font-size: var(--size-200); line-height: var(--lh-200);
  font-variant-numeric: tabular-nums; color: var(--text-muted); }
.adm-stat__delta svg { width: 12px; height: 12px; flex: none; }
.adm-stat__delta--up   { color: var(--status-current-text); }
.adm-stat__delta--down { color: var(--status-expired-text); }
.adm-stat__delta--up.is-bad    { color: var(--status-expired-text); }
.adm-stat__delta--down.is-good { color: var(--status-current-text); }
.adm-stat__delta--flat { color: var(--text-muted); }
.adm-stat__delta .adm-stat__period { color: var(--text-muted); font-family: var(--font-sans); }

.adm-stat__foot { font-size: var(--size-200); line-height: var(--lh-200); color: var(--text-muted); }
.adm-stat .adm-spark { margin-top: var(--space-50); }


/* ==========================================================================
   21. SPARKLINE + DONUT — inline SVG patterns
   The aria-label states the trend in words; the graphic is reinforcement,
   never the sole carrier.
   ========================================================================== */

.adm-spark { display: block; width: 100%; height: 36px; color: var(--status-current-solid); overflow: visible; }
.adm-spark--muted { color: var(--border-strong); }
.adm-spark--warn  { color: var(--status-soon-solid); }
.adm-spark__line { fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.adm-spark__area { fill: currentColor; opacity: 0.12; stroke: none; }
.adm-spark__dot  { fill: currentColor; stroke: var(--surface-raised); stroke-width: 1.5; }

/* Donut: circles r="15.9155" (circumference 100 → dasharray "PCT 100-PCT"),
   stroke-width 6, fill none, rotated -90° so segments start at midnight —
   the same math as the brand ring. Always pair with .adm-legend. */
.adm-donut { display: flex; align-items: center; gap: var(--space-300); flex-wrap: wrap; }
.adm-donut__svg { width: 132px; height: 132px; flex: none; transform: rotate(-90deg); }
.adm-donut__track { stroke: var(--border-default); fill: none; }
.adm-donut__seg { fill: none; stroke-linecap: butt;
  transition: stroke-dasharray var(--duration-slow) var(--ease-standard); }
.adm-donut__seg--brand  { stroke: var(--status-current-solid); }
.adm-donut__seg--soft   { stroke: color-mix(in srgb, var(--vt-valid) 45%, var(--surface-raised)); } /* decorative; legend text carries the value */
.adm-donut__seg--muted  { stroke: var(--border-strong); }
.adm-donut__seg--amber  { stroke: var(--status-soon-solid); }
.adm-donut__center { position: relative; }
.adm-donut__label { position: absolute; inset: 0; display: grid; place-content: center; text-align: center; }
.adm-donut__label b { font-family: var(--font-sans); font-size: var(--size-700); line-height: var(--lh-700);
  font-weight: var(--weight-bold); color: var(--text-strong);
  font-variant-numeric: tabular-nums; letter-spacing: var(--track-display); }
.adm-donut__label span { font-family: var(--font-mono); font-size: var(--size-100); line-height: var(--lh-100);
  letter-spacing: var(--track-label); text-transform: uppercase; color: var(--text-muted); }

.adm-legend { display: flex; flex-direction: column; gap: var(--space-100);
  font-size: var(--size-300); line-height: var(--lh-300); color: var(--text-body); min-width: 0; }
.adm-legend__item { display: flex; align-items: baseline; gap: var(--space-100); }
.adm-legend__swatch { width: 10px; height: 10px; flex: none; border-radius: var(--radius-full);
  align-self: center; background: var(--status-current-solid); }
.adm-legend__swatch--soft  { background: color-mix(in srgb, var(--vt-valid) 45%, var(--surface-raised)); }
.adm-legend__swatch--muted { background: var(--border-strong); }
.adm-legend__swatch--amber { background: var(--status-soon-solid); }
.adm-legend__value { margin-left: auto; font-family: var(--font-mono);
  font-variant-numeric: tabular-nums; color: var(--text-strong); }


/* ==========================================================================
   22. DATA TABLE — ops density, sticky header, sortable, filter bar,
   pagination. Wrap in .adm-table-wrap; add .adm-table-wrap--scroll for a
   capped-height scrolling body (sticky header earns its keep there).
   ========================================================================== */

.adm-tablebar { display: flex; align-items: center; flex-wrap: wrap;
  gap: var(--space-100) var(--space-150); margin-bottom: var(--space-150); }
.adm-tablebar .vt-input, .adm-tablebar .vt-select { width: auto; }
.adm-tablebar__search { position: relative; }
.adm-tablebar__search svg { position: absolute; left: var(--space-100); top: 50%;
  transform: translateY(-50%); width: 14px; height: 14px; color: var(--text-muted); pointer-events: none; }
.adm-tablebar__search .vt-input { padding-left: var(--space-400); min-width: 200px; }
.adm-tablebar__count { margin-left: auto; font-family: var(--font-mono); font-size: var(--size-200);
  color: var(--text-muted); font-variant-numeric: tabular-nums; white-space: nowrap; }

.adm-table-wrap { overflow-x: auto; border: var(--border-hairline) solid var(--border-default);
  border-radius: var(--radius-xl); background: var(--surface-raised); }
.adm-table-wrap--scroll { max-height: min(64vh, 640px); overflow-y: auto; }

.adm-table { width: 100%; border-collapse: collapse;
  font-size: var(--size-300); line-height: var(--lh-300); }
.adm-table th {
  position: sticky; top: 0; z-index: var(--z-raised);
  text-align: left; font-family: var(--font-mono); font-size: var(--size-100);
  font-weight: var(--weight-regular);
  letter-spacing: var(--track-label); text-transform: uppercase; color: var(--text-muted);
  background: var(--surface-sunken); padding: var(--space-100) var(--space-200);
  white-space: nowrap;
  /* inset shadow instead of border-bottom: borders scroll away under sticky */
  box-shadow: inset 0 -1px 0 var(--border-default);
}
.adm-table td { padding: var(--space-100) var(--space-200);
  border-bottom: var(--border-hairline) solid var(--border-subtle);
  color: var(--text-body); vertical-align: middle; }
.adm-table tr:last-child td { border-bottom: 0; }
.adm-table tbody tr:hover td { background: var(--surface-hover); }
.adm-table td.vt-date, .adm-table td.vt-num, .adm-table td.vt-mono {
  font-family: var(--font-mono); font-size: var(--size-200); font-variant-numeric: tabular-nums; }
.adm-table td.vt-num { text-align: right; }
.adm-table th.vt-num { text-align: right; }
.adm-table td .adm-table__primary { font-weight: var(--weight-medium); color: var(--text-strong); }
.adm-table td .adm-table__sub { display: block; font-size: var(--size-200); color: var(--text-muted); }

/* Phone widths: nothing may overflow at 375px (SPEC). Fixed layout pins the
   table to its wrapper's width and wrap-anywhere lets dense cells break, so
   even the widest tables fit the viewport instead of forcing a wide box. */
@media (max-width: 639px) {
  .adm-table { table-layout: fixed; }
  .adm-table th, .adm-table td {
    white-space: normal; overflow-wrap: anywhere;
    padding-left: var(--space-100); padding-right: var(--space-100); }
  .adm-table .adm-badge, .adm-table .vt-btn { white-space: normal; }
}

/* Whole-row link rows: <tr data-href> get pointer + strong hover via JS,
   or wrap the primary cell text in an <a class="adm-table__rowlink">. */
.adm-table a.adm-table__rowlink { color: var(--text-strong); font-weight: var(--weight-medium); text-decoration: none; }
.adm-table a.adm-table__rowlink:hover { text-decoration: underline; color: var(--text-link); }
.adm-table tr[data-href] { cursor: pointer; }

/* Sortable header affordance. Put a <button class="adm-sort"> inside the th;
   set aria-sort="ascending|descending" on the th. Chevron flips for
   descending; both direction and the pressed state are conveyed by aria-sort,
   not color. */
.adm-sort { appearance: none; background: none; border: none; cursor: pointer;
  display: inline-flex; align-items: center; gap: var(--space-50);
  font: inherit; letter-spacing: inherit; text-transform: inherit; color: inherit;
  padding: 0; min-height: 24px; }
.adm-sort:hover { color: var(--text-body); }
.adm-sort svg { width: 12px; height: 12px; flex: none; opacity: 0.45;
  transition: transform var(--duration-fast) var(--ease-standard); }
th[aria-sort] .adm-sort { color: var(--text-strong); }
th[aria-sort] .adm-sort svg { opacity: 1; }
th[aria-sort="ascending"] .adm-sort svg { transform: rotate(180deg); }

/* Pagination bar. */
.adm-pagebar { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-150);
  padding: var(--space-150) var(--space-50) 0; }
.adm-pagebar__info { font-family: var(--font-mono); font-size: var(--size-200);
  color: var(--text-muted); font-variant-numeric: tabular-nums; }
.adm-pagebar__pages { display: flex; align-items: center; gap: var(--space-50); margin-left: auto; }
.adm-pagebar__pages a, .adm-pagebar__pages button, .adm-pagebar__pages span {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 32px; height: 32px; padding: 0 var(--space-100);
  border-radius: var(--radius-sm); border: var(--border-hairline) solid transparent;
  font-family: var(--font-mono); font-size: var(--size-300); font-variant-numeric: tabular-nums;
  color: var(--text-body); text-decoration: none; background: none; cursor: pointer; }
.adm-pagebar__pages a:hover, .adm-pagebar__pages button:hover { background: var(--surface-hover); }
.adm-pagebar__pages [aria-current="page"] { background: var(--surface-selected);
  color: var(--brand-subtle-text); font-weight: var(--weight-semibold); }
.adm-pagebar__pages [aria-disabled="true"] { color: var(--text-disabled); cursor: not-allowed; }
.adm-pagebar__pages .adm-pagebar__gap { color: var(--text-muted); cursor: default; min-width: 20px; }


/* ==========================================================================
   23. ADMIN STATUS + TIER BADGES — icon + text, never color alone
   ok → check · warn → clock · error → triangle-alert · info → info-circle.
   Tier badges are metadata, not status: neutral/brand family only.
   ========================================================================== */

.adm-badge {
  display: inline-flex; align-items: center; gap: var(--space-50);
  font-size: var(--size-200); font-weight: var(--weight-medium); line-height: 1;
  letter-spacing: 0.02em;
  padding: var(--space-50) var(--space-100); border-radius: var(--radius-full);
  border: var(--border-hairline) solid; white-space: nowrap;
}
.adm-badge svg { width: 12px; height: 12px; flex: none; }
.adm-badge--ok    { color: var(--status-current-text); background: var(--status-current-subtle); border-color: var(--status-current-line); }
.adm-badge--warn  { color: var(--status-soon-text);    background: var(--status-soon-subtle);    border-color: var(--status-soon-line); }
.adm-badge--error { color: var(--status-expired-text); background: var(--status-expired-subtle); border-color: var(--status-expired-line); }
.adm-badge--info  { color: var(--status-unknown-text); background: var(--status-unknown-subtle); border-color: var(--status-unknown-line); }

/* Tiers. free: quiet neutral. monthly: brand outline. annual: brand subtle.
   All pairings verified: unknown pair, text-brand on page (7.63/5.51),
   brand-subtle-text on brand-subtle (5.7/4.9). */
.adm-badge--free    { color: var(--status-unknown-text); background: var(--status-unknown-subtle); border-color: var(--status-unknown-line); }
.adm-badge--monthly { color: var(--text-brand); background: transparent; border-color: var(--brand-line); }
.adm-badge--annual  { color: var(--brand-subtle-text); background: var(--brand-subtle); border-color: var(--brand-line); }
.adm-badge--free svg, .adm-badge--monthly svg, .adm-badge--annual svg { display: none; } /* tier ≠ status; text is enough */

/* Mono badge for ids/codes sitting inside tables. */
.adm-badge--mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; letter-spacing: 0.02em; }


/* ==========================================================================
   24. SLA CHIP — response-time budget on tickets. Icon + written time.
   ok = within budget · warn = over half spent · breach = blown.
   ========================================================================== */

.adm-sla { display: inline-flex; align-items: center; gap: var(--space-50);
  font-family: var(--font-mono); font-size: var(--size-200); line-height: 1;
  font-variant-numeric: tabular-nums; letter-spacing: 0.02em; font-weight: var(--weight-regular);
  padding: var(--space-50) var(--space-100); border-radius: var(--radius-sm);
  border: var(--border-hairline) solid; white-space: nowrap; }
.adm-sla svg { width: 12px; height: 12px; flex: none; }
.adm-sla--ok     { color: var(--status-unknown-text); background: var(--status-unknown-subtle); border-color: var(--status-unknown-line); }
.adm-sla--warn   { color: var(--status-soon-text);    background: var(--status-soon-subtle);    border-color: var(--status-soon-line); }
.adm-sla--breach { color: var(--status-expired-text); background: var(--status-expired-subtle); border-color: var(--status-expired-line); }


/* ==========================================================================
   25. DRAWER PANEL — right-side edit/detail surface. Toggle by adding
   data-open="true"; pair with .adm-scrim. Below 640px it fills the width.
   ========================================================================== */

.adm-drawer { position: fixed; top: 0; right: 0; bottom: 0; z-index: calc(var(--z-overlay) + 1);
  width: min(420px, 100vw); display: none; flex-direction: column;
  background: var(--surface-overlay);
  border-left: var(--border-hairline) solid var(--border-default);
  box-shadow: var(--shadow-xl);
  transform: translateX(100%);
  transition: transform var(--duration-slow) var(--ease-entrance),
              display var(--duration-slow) allow-discrete; }
/* display:none while closed (not just translated offscreen) so the hidden
   panel contributes no layout box at 375px; @starting-style keeps the
   slide-in, allow-discrete keeps the slide-out. */
.adm-drawer[data-open="true"] { display: flex; transform: translateX(0); }
@starting-style {
  .adm-drawer[data-open="true"] { transform: translateX(100%); }
}

.adm-drawer__head { display: flex; align-items: flex-start; justify-content: space-between;
  gap: var(--space-200); padding: var(--space-300) var(--space-300) var(--space-200);
  border-bottom: var(--border-hairline) solid var(--border-subtle); }
.adm-drawer__title { font-size: var(--size-600); line-height: var(--lh-600);
  font-weight: var(--weight-semibold); color: var(--text-strong); margin: 0;
  letter-spacing: var(--track-heading); }
.adm-drawer__body { flex: 1; overflow-y: auto; padding: var(--space-300);
  display: flex; flex-direction: column; gap: var(--space-300); }
.adm-drawer__foot { display: flex; gap: var(--space-150); justify-content: flex-end; flex-wrap: wrap;
  padding: var(--space-200) var(--space-300);
  border-top: var(--border-hairline) solid var(--border-subtle);
  background: var(--surface-sunken); }


/* ==========================================================================
   26. STEP-UP MODAL — re-authentication before a sensitive action.
   A .vt-modal variant: passkey-first, TOTP fallback, no SMS — ever.
   Calm brand accent, not alarm red; the action being confirmed carries its
   own danger styling on its own button.
   ========================================================================== */

.vt-modal--stepup { max-width: 400px; }
.adm-stepup__icon { width: 44px; height: 44px; border-radius: var(--radius-lg);
  display: grid; place-items: center; margin-bottom: var(--space-200);
  background: var(--brand-subtle); color: var(--brand-subtle-text); }
.adm-stepup__icon svg { width: 22px; height: 22px; }
.adm-stepup__action { display: flex; align-items: center; gap: var(--space-100);
  font-family: var(--font-mono); font-size: var(--size-200); line-height: var(--lh-200);
  color: var(--text-body); background: var(--surface-sunken);
  border: var(--border-hairline) solid var(--border-subtle);
  border-radius: var(--radius-md); padding: var(--space-100) var(--space-150);
  margin-bottom: var(--space-300); }
.adm-stepup__fallback { font-size: var(--size-300); text-align: center;
  margin-top: var(--space-200); }
.adm-stepup__fallback a { color: var(--text-link); }
.adm-stepup__note { font-size: var(--size-200); line-height: var(--lh-200);
  color: var(--text-muted); text-align: center; margin: var(--space-200) 0 0; }


/* ==========================================================================
   27. TIMELINE / FEED — audit trails, ticket threads, security events.
   Dot color pairs with an icon inside the dot; the label text names the
   event type, so the feed reads in grayscale.
   ========================================================================== */

.adm-feed { list-style: none; margin: 0; padding: 0; }
.adm-feed__item { position: relative; display: flex; gap: var(--space-200);
  padding: 0 0 var(--space-300) 0; }
.adm-feed__item::before { content: ""; position: absolute; left: 13px; top: 28px; bottom: 0;
  width: var(--border-hairline); background: var(--border-default); }
.adm-feed__item:last-child { padding-bottom: 0; }
.adm-feed__item:last-child::before { display: none; }

.adm-feed__dot { width: 28px; height: 28px; flex: none; border-radius: var(--radius-full);
  display: grid; place-items: center; z-index: var(--z-raised);
  background: var(--status-unknown-subtle); color: var(--status-unknown-text);
  border: var(--border-hairline) solid var(--status-unknown-line); }
.adm-feed__dot svg { width: 14px; height: 14px; }
.adm-feed__dot--ok    { background: var(--status-current-subtle); color: var(--status-current-text); border-color: var(--status-current-line); }
.adm-feed__dot--warn  { background: var(--status-soon-subtle);    color: var(--status-soon-text);    border-color: var(--status-soon-line); }
.adm-feed__dot--error { background: var(--status-expired-subtle); color: var(--status-expired-text); border-color: var(--status-expired-line); }
.adm-feed__dot--brand { background: var(--brand-subtle); color: var(--brand-subtle-text); border-color: var(--brand-line); }

.adm-feed__body { flex: 1; min-width: 0; padding-top: var(--space-25); }
.adm-feed__title { font-size: var(--size-400); line-height: var(--lh-400);
  font-weight: var(--weight-medium); color: var(--text-strong); margin: 0; }
.adm-feed__meta { overflow-wrap: anywhere;
  font-family: var(--font-mono); font-size: var(--size-200); line-height: var(--lh-200);
  color: var(--text-muted); font-variant-numeric: tabular-nums; margin: var(--space-25) 0 0; }
.adm-feed__text { font-size: var(--size-300); line-height: var(--lh-300);
  color: var(--text-body); margin: var(--space-75) 0 0; max-width: 70ch; }


/* ==========================================================================
   28. CODE / MONO BLOCK — ids, payload excerpts, runbook commands
   ========================================================================== */

.adm-code { display: block; margin: 0; padding: var(--space-150) var(--space-200);
  background: var(--surface-sunken);
  border: var(--border-hairline) solid var(--border-subtle);
  border-radius: var(--radius-md);
  font-family: var(--font-mono); font-size: var(--size-200); line-height: var(--lh-300);
  color: var(--text-body); letter-spacing: 0.02em;
  font-variant-numeric: tabular-nums;
  overflow-x: auto; white-space: pre; }
code.adm-code, .adm-code--inline { display: inline; padding: 1px var(--space-75);
  white-space: normal; overflow-wrap: anywhere; }


/* ==========================================================================
   29. DANGER-ZONE CARD — destructive settings, always step-up gated.
   Calm: red is on the boundary and the heading, not washed over the card.
   ========================================================================== */

.adm-danger { border: var(--border-hairline) solid var(--status-expired-line);
  border-radius: var(--radius-xl); background: var(--surface-raised);
  padding: var(--space-300); }
.adm-danger__title { display: flex; align-items: center; gap: var(--space-100);
  font-size: var(--size-500); line-height: var(--lh-500); font-weight: var(--weight-semibold);
  color: var(--status-expired-text); margin: 0 0 var(--space-100); }
.adm-danger__title svg { width: 18px; height: 18px; flex: none; }
.adm-danger p { font-size: var(--size-300); line-height: var(--lh-300);
  color: var(--text-body); max-width: 70ch; }
.adm-danger__row { display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-200); flex-wrap: wrap; padding: var(--space-200) 0;
  border-top: var(--border-hairline) solid var(--border-subtle); }
.adm-danger__row:first-of-type { border-top: 0; }
.adm-danger__row b { font-size: var(--size-400); font-weight: var(--weight-medium); color: var(--text-strong); display: block; }
.adm-danger__row span { font-size: var(--size-200); line-height: var(--lh-200); color: var(--text-muted); }


/* ==========================================================================
   30. "WHAT STAFF CANNOT SEE" PANEL — distinct, calm, not alarmist.
   The posture is the product: state the limits plainly, in the valid green,
   on a quiet sunken surface. Never red, never a warning icon.
   ========================================================================== */

.adm-cannotsee { background: var(--surface-sunken);
  border: var(--border-hairline) solid var(--border-default);
  border-left: 3px solid var(--status-current-solid);
  border-radius: var(--radius-xl); padding: var(--space-250) var(--space-300); }
/* Card title rung: this panel sits beside ordinary cards on audit-log,
   support and user-detail, and its heading has to match theirs. */
.adm-cannotsee__title { display: flex; align-items: center; gap: var(--space-100);
  font-size: var(--size-500); line-height: var(--lh-500); font-weight: var(--weight-semibold);
  color: var(--text-brand); margin: 0 0 var(--space-100); letter-spacing: var(--track-heading); }
.adm-cannotsee__title svg { width: 18px; height: 18px; flex: none; }
.adm-cannotsee p { font-size: var(--size-300); line-height: var(--lh-300);
  color: var(--text-body); margin: 0 0 var(--space-150); max-width: 70ch; }
/* Hanging dash, not a flex row: a flex li turns an inline link or a trailing
   sentence into a second flex item, which is why "( health )" used to float
   off to the right of its own bullet. */
.adm-cannotsee ul, ul.adm-cannotsee { list-style: none; margin: 0; padding: 0; }
.adm-cannotsee li { font-size: var(--size-300); line-height: var(--lh-300);
  color: var(--text-body); max-width: 70ch;
  padding-left: var(--space-200); text-indent: calc(-1 * var(--space-200)); }
.adm-cannotsee li + li { margin-top: var(--space-75); }
.adm-cannotsee li::before { content: "—"; color: var(--text-brand);
  margin-right: var(--space-75); }
.adm-cannotsee__foot { font-size: var(--size-200); line-height: var(--lh-200);
  color: var(--text-muted); margin: var(--space-150) 0 0; }
.adm-cannotsee__foot a { color: var(--text-link); }


/* ==========================================================================
   31. LAYOUT HELPERS — two-column detail pages, section stacks
   ========================================================================== */

/* minmax(0, 1fr): a bare 1fr floors at the column's min-content width, so one
   wide card (code block, long mono id) forces the whole page past 375px. */
.adm-grid { display: grid; gap: var(--space-300); grid-template-columns: minmax(0, 1fr); }
@media (min-width: 900px) {
  .adm-grid--2      { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .adm-grid--main   { grid-template-columns: minmax(0, 2fr) minmax(260px, 1fr); }
}
.adm-stack { display: flex; flex-direction: column; gap: var(--space-300); min-width: 0; }

/* Section head inside a card region. */
.adm-sectionhead { display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--space-200); flex-wrap: wrap; margin-bottom: var(--space-150); }
.adm-sectionhead h2, .adm-sectionhead h3 { margin: 0; }
.adm-sectionhead a { font-size: var(--size-300); }

/* Key-value definition rows for detail panels. */
.adm-kv { display: grid; grid-template-columns: minmax(120px, max-content) 1fr;
  gap: var(--space-75) var(--space-300); margin: 0;
  font-size: var(--size-300); line-height: var(--lh-300); }
.adm-kv dt { color: var(--text-muted); }
.adm-kv dd { margin: 0; color: var(--text-body); min-width: 0; overflow-wrap: anywhere; }
.adm-kv dd.vt-mono, .adm-kv dd.vt-date { font-variant-numeric: tabular-nums; }


/* ==========================================================================
   32. ORBIT STRIP — index.html only. The next scheduled events as bodies
   approaching a midnight marker, in the a1 orbit language: thin track,
   small dots, one bright tick, mono labels. The written labels carry the
   information; position and color only reinforce.
   ========================================================================== */

.adm-orbitstrip { border: var(--border-hairline) solid var(--border-default);
  border-radius: var(--radius-xl); background: var(--surface-raised);
  box-shadow: var(--shadow-sm);
  padding: var(--space-250) var(--space-300); margin-bottom: var(--space-300);
  overflow: hidden; }
.adm-orbitstrip__head { display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--space-100) var(--space-300); flex-wrap: wrap; margin-bottom: var(--space-100); }
.adm-orbitstrip__title { font-size: var(--size-500); line-height: var(--lh-500);
  font-weight: var(--weight-semibold); color: var(--text-strong); margin: 0;
  letter-spacing: var(--track-heading); }
.adm-orbitstrip__key { font-family: var(--font-mono); font-size: var(--size-100);
  line-height: var(--lh-100); letter-spacing: 0.04em; color: var(--text-muted); }

.adm-orbitstrip__lane { position: relative; height: 128px; min-width: 0; }
/* the track — the flattened orbit */
.adm-orbitstrip__lane::before { content: ""; position: absolute; left: 0; right: 0;
  top: 50%; height: 2px; margin-top: -1px;
  background: var(--border-default); border-radius: var(--radius-full); }
/* faint guide, a1's inner ring */
.adm-orbitstrip__lane::after { content: ""; position: absolute; left: 4%; right: 4%;
  top: calc(50% + 7px); height: 1px; background: var(--border-subtle); }

/* midnight marker: bright tick + mono label */
.adm-orbitstrip__mid { position: absolute; left: 94%; top: 0; bottom: 0; width: 0; }
.adm-orbitstrip__mid i { position: absolute; left: -1px; top: 50%;
  transform: translateY(-50%); width: 2.5px; height: 40px;
  background: var(--text-strong); border-radius: var(--radius-full); }
.adm-orbitstrip__mid span { position: absolute; top: 0; right: -4px;
  font-family: var(--font-mono); font-size: 10px; line-height: var(--lh-100);
  letter-spacing: var(--track-label); text-transform: uppercase;
  color: var(--text-muted); white-space: nowrap; }

/* one event = dot on the track + stacked mono label */
.adm-orbitstrip__ev { position: absolute; top: 0; bottom: 0;
  left: var(--x, 50%); width: 0; }
.adm-orbitstrip__dot { position: absolute; left: 0; top: 50%;
  transform: translate(-50%, -50%); width: 11px; height: 11px;
  border-radius: var(--radius-full);
  background: var(--text-muted);
  box-shadow: 0 0 0 3px var(--surface-raised); }
.adm-orbitstrip__ev--done .adm-orbitstrip__dot { background: var(--status-current-solid); }
.adm-orbitstrip__ev--next .adm-orbitstrip__dot { background: var(--status-soon-solid); }
.adm-orbitstrip__label { position: absolute; left: 0; transform: translateX(-50%);
  width: max-content; max-width: 92px; text-align: center;
  font-family: var(--font-mono); font-size: 10px; line-height: 14px;
  letter-spacing: 0.03em; color: var(--text-muted);
  font-variant-numeric: tabular-nums; }
.adm-orbitstrip__label b { display: block; font-weight: var(--weight-medium);
  color: var(--text-body); letter-spacing: 0.05em; text-transform: uppercase; }
/* labels alternate: below the track by default, above with --up */
.adm-orbitstrip__label { top: calc(50% + 16px); }
.adm-orbitstrip__ev--up .adm-orbitstrip__label { top: auto; bottom: calc(50% + 16px); }
/* connector from dot to label */
.adm-orbitstrip__ev::before { content: ""; position: absolute; left: -0.5px; width: 1px;
  top: calc(50% + 7px); height: 7px; background: var(--border-strong); }
.adm-orbitstrip__ev--up::before { top: auto; bottom: calc(50% + 7px); }

/* keep the edge labels inside the card */
.adm-orbitstrip__ev--last .adm-orbitstrip__label { transform: translateX(-82%); }
/* On narrow lanes the marker word would collide with event labels; the tick
   stays, and the head's reading key still names the marker. */
@media (max-width: 767px) {
  .adm-orbitstrip__mid span { display: none; }
}
@media (max-width: 479px) {
  .adm-orbitstrip { padding-inline: var(--space-200); }
  .adm-orbitstrip__label { max-width: 76px; }
  .adm-orbitstrip__ev--first .adm-orbitstrip__label { transform: translateX(-30%); }
}


/* ==========================================================================
   33. PRINT — audit exports and runbooks come out clean
   ========================================================================== */

@media print {
  .adm-sidebar, .adm-mobilebar, .adm-sheet, .adm-scrim,
  .adm-search, .adm-themetoggle, .adm-iconbtn,
  .vt-scrim, .adm-drawer, .vt-toast-region, .skip-link,
  .adm-pagehead__actions, .vt-btn { display: none !important; }

  .adm-shell { display: block; }
  .adm-topbar { position: static; border-bottom: 1pt solid #000; }
  .adm-main { padding: 0; }
  .adm-audit { position: static; border-top: 1pt solid #000; margin-top: 16pt; }

  body { background: #fff; color: #000; font-size: 10.5pt; }
  .adm-table th { position: static; }
  .adm-table-wrap, .adm-table-wrap--scroll { max-height: none; overflow: visible; border-color: #000; }
  .vt-card, .adm-stat, .adm-danger, .adm-cannotsee { box-shadow: none; break-inside: avoid; }
  a { color: #000; text-decoration: underline; }
}


/* ==========================================================================
   33. BILLING MODE CHIP · NATIVE DIALOG · CHECKLIST · STATUS LINE
   The Stripe mode chip sits beside the environment badge on every page
   (built by assets/admin-shell.js). test = flask icon on the quiet unknown
   pair; live = card icon on the valid pair; unknown = info icon, outline.
   The word is always present — never colour alone.
   ========================================================================== */

.adm-modechip { flex: none; display: inline-flex; align-items: center; gap: var(--space-50);
  font-family: var(--font-mono); font-size: var(--size-100); line-height: 1;
  letter-spacing: var(--track-label); text-transform: uppercase; font-weight: var(--weight-medium);
  border: var(--border-hairline) solid var(--border-default); border-radius: var(--radius-sm);
  padding: var(--space-50) var(--space-100); text-decoration: none; color: var(--text-muted);
  background: transparent; }
.adm-modechip svg { width: 12px; height: 12px; flex: none; }
.adm-modechip:hover { text-decoration: underline; }
.adm-modechip--test { color: var(--status-unknown-text); background: var(--status-unknown-subtle); border-color: var(--status-unknown-line); }
.adm-modechip--live { color: var(--status-current-text); background: var(--status-current-subtle); border-color: var(--status-current-line); }
@media (max-width: 639px) { .adm-modechip__prefix { display: none; } }

/* Native <dialog> carrying the .vt-modal look: focus is trapped and Escape
   closes it for free. Forms inside build their fields from DOM calls. */
dialog.vt-modal { margin: auto; color: var(--text-body); max-height: calc(100vh - var(--space-600)); overflow-y: auto; }
dialog.vt-modal::backdrop { background: var(--scrim-color); }
dialog.vt-modal form { margin: 0; }
dialog.vt-modal .vt-field { max-width: none; margin-bottom: var(--space-200); }
dialog.vt-modal .vt-error { margin: 0 0 var(--space-200); }
dialog.vt-modal .vt-error[hidden] { display: none; }
dialog.vt-modal .adm-checklist { margin-bottom: var(--space-300); }

/* Precondition / readiness list: icon + text per row. */
.adm-checklist { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-75); }
.adm-checklist li { display: flex; align-items: flex-start; gap: var(--space-100);
  font-size: var(--size-300); line-height: var(--lh-300); color: var(--text-body); }
.adm-checklist li svg { width: 16px; height: 16px; flex: none; margin-top: 2px; }
.adm-checklist li[data-state="ok"] svg { color: var(--status-current-text); }
.adm-checklist li[data-state="warn"] svg { color: var(--status-soon-text); }
.adm-checklist li[data-state="fail"] svg { color: var(--status-expired-text); }
.adm-checklist li[data-state="none"] svg { color: var(--text-muted); }

/* Outcome line under a panel: icon + sentence, aria-live on the element. */
.adm-statusline { display: flex; align-items: flex-start; gap: var(--space-100);
  font-size: var(--size-300); line-height: var(--lh-300); color: var(--text-body);
  margin: var(--space-150) 0 0; min-height: var(--lh-300); }
.adm-statusline svg { width: 16px; height: 16px; flex: none; margin-top: 2px; }
.adm-statusline--ok { color: var(--status-current-text); }
.adm-statusline--warn { color: var(--status-soon-text); }
.adm-statusline--error { color: var(--status-expired-text); }
.adm-statusline:empty { display: none; }

/* Page-level notice (API unavailable, request failed): calm sunken strip. */
.bl-notice { font-size: var(--size-300); line-height: var(--lh-300); color: var(--text-body);
  background: var(--surface-sunken); border: var(--border-hairline) solid var(--border-subtle);
  border-radius: var(--radius-md); padding: var(--space-150) var(--space-200); margin: 0 0 var(--space-300); }
.bl-notice--error { color: var(--status-expired-text); border-color: var(--status-expired-line); }
.bl-notice[hidden] { display: none; }
