/* ============================================
   KOTT Admin Dashboard — Design System
   True black + frosted glass + cyan accent
   ============================================ */

/* --- Design Tokens ---
   The canonical :root now lives in tokens.css (linked FIRST in App.razor);
   every shared token + the derived scales are inherited from there. This
   sheet keeps ONLY the admin surface's intentional per-surface overrides,
   scoped to .admin-shell so load order no longer decides them.

   These five tokens differ on purpose between admin (calmer Tailwind-ish)
   and public (brighter neon). Before reconciliation admin.css loaded last,
   so admin's values won everywhere — including on public pages (a bug).
   Pinning per-surface restores public's design while keeping admin pixel-
   identical to today. Values below are admin's existing palette, verbatim. */
.admin-shell {
    --success: #34d399;
    --danger: #f87171;
    --warning: #fbbf24;
    --text-tertiary: #6b7280;
    --border-hover: rgba(255, 255, 255, 0.12);
}

/* --- Reset & Base --- */
* { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: var(--font-body); background: var(--bg-primary); color: var(--text-primary); font-size: 14px; line-height: 1.5; }
a { color: var(--link); text-decoration: none; transition: color 0.12s ease; }
a:hover { color: var(--link-hover); }

/* --- Layout --- */
.admin-shell { display: flex; min-height: 100vh; }
.sidebar { width: 220px; background: rgba(4, 6, 10, 0.8); backdrop-filter: blur(16px) saturate(1.2); -webkit-backdrop-filter: blur(16px) saturate(1.2); padding: 16px 12px; display: flex; flex-direction: column; gap: 2px; position: fixed; top: 0; bottom: 0; overflow-y: auto; z-index: 100; border-right: 1px solid var(--border); }
/* Brand lockup (redesign 2026-06-21) — skewed cyan mark + KOTT / ADMIN CONSOLE. */
.sidebar-brand { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; padding: 4px 8px 14px; border-bottom: 1px solid var(--border); }
.sidebar-brand-mark { width: 26px; height: 26px; border-radius: 7px; background: linear-gradient(140deg, var(--accent), #0093a8); box-shadow: 0 0 14px var(--accent-glow), inset 0 0 0 1px rgba(255, 255, 255, 0.2); display: grid; place-items: center; font-family: var(--font-display); font-weight: 700; color: #001016; font-size: 15px; transform: skewX(-6deg); flex-shrink: 0; }
.sidebar-brand-text { font-family: var(--font-display); font-weight: 700; font-size: 18px; letter-spacing: 0.5px; color: var(--text-primary); line-height: 1; display: flex; flex-direction: column; }
.sidebar-brand-text small { font-size: 9px; font-weight: 600; letter-spacing: 2.2px; color: var(--text-tertiary); margin-top: 2px; }
/* Section/item legibility (2026-06-22): page links are the PRIMARY, clickable
   thing — readable Title-case, brighter, icon-led — so they read as rows, NOT
   as the tiny UPPERCASE eyebrow section headers above them. (Was uppercase +
   tertiary, which blurred links and section labels into one wall of text.) */
.sidebar-nav a, .sidebar-nav a:visited { position: relative; color: var(--text-secondary); text-decoration: none; padding: 8px 12px; border-radius: var(--radius-6); display: flex; align-items: center; justify-content: space-between; font-family: var(--font-display); font-size: 14px; font-weight: 600; transition: all 0.12s ease; text-transform: none; letter-spacing: 0.1px; }
.sidebar-nav a:hover { background: rgba(255, 255, 255, 0.03); color: var(--text-primary); }
.sidebar-nav a.active { background: linear-gradient(90deg, var(--accent-dim), transparent 70%); color: var(--accent); }
.sidebar-nav a.active::before { content: ""; position: absolute; left: -12px; top: 7px; bottom: 7px; width: 2px; background: var(--accent); border-radius: 2px; box-shadow: var(--glow-sm); }
.sidebar-spacer { flex: 1; }
/* Section header = a quiet "eyebrow" divider, deliberately UNLIKE the page links:
   tiny, wide-tracked UPPERCASE, dim, and clearly separated by whitespace + a
   hairline rule, so groups read as groups (not clickable rows). */
.sidebar-section { font-family: var(--font-display); font-weight: 700; font-size: 9.5px; text-transform: uppercase; letter-spacing: 2px; color: var(--text-tertiary); padding: 6px 12px 5px; margin-top: 16px; border-top: 1px solid var(--border); }
.sidebar-nav > .sidebar-section:first-child { margin-top: 0; border-top: none; padding-top: 2px; }
/* Orienting layer (2026-06-22) — one-line muted sub-header under each section
   title ("what is this group for"). Lowercase-friendly + dimmer than the title. */
.sidebar-section-desc { display: block; margin-top: 3px; font-size: 9.5px; font-weight: 500; letter-spacing: 0.3px; text-transform: none; color: var(--text-tertiary); opacity: 0.72; line-height: 1.3; }
/* Orienting layer — NavLink internal layout: [icon + label] on the left, badge
   on the right (the parent <a> is flex space-between). The icon SVG inherits
   currentColor so it follows the link / active-accent color automatically. */
.nav-link-label { display: inline-flex; align-items: center; gap: 9px; min-width: 0; }
.nav-link-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nav-icon { width: 17px; height: 17px; flex-shrink: 0; opacity: 0.9; }
.sidebar-nav a.active .nav-icon { opacity: 1; }
.sidebar-logout { margin-top: auto; color: var(--text-tertiary); border-top: 1px solid var(--border); padding-top: 12px; font-size: 12px; }
/* Density pass (2026-06-08): gutters driven by --admin-gutter-* (tokens.css);
   max-width raised 1100 -> 1400 so wide ops tables get room (Proposal A). */
.content { flex: 1; padding: var(--admin-gutter-y) var(--admin-gutter-x); margin-left: 220px; max-width: 1400px; }

/* --- Typography --- */
/* Density pass (2026-06-08): heading rhythm tightened (h1 20->12, h2 24/12->16/8, h3 12->8). */
h1 { font-family: var(--font-display); font-size: 26px; font-weight: 700; color: var(--text-primary); margin-bottom: 12px; letter-spacing: 0.3px; }
h2 { font-family: var(--font-display); font-size: 15px; font-weight: 600; color: var(--text-secondary); margin: 16px 0 8px; text-transform: uppercase; letter-spacing: 0.5px; }
h3 { font-family: var(--font-display); font-size: 15px; font-weight: 600; color: var(--text-primary); margin-bottom: 8px; }

/* --- Status Badges — thin border + tinted bg --- */
/* ── Pill line-height (2026-07-14) ──────────────────────────────────────────────────────────
   Every pill below pins its own line-height. body sets 1.5 (prose), so an 11px pill inherited a
   16.5px line box + padding + border = ~22.5px — TALLER than the 19.5px strut of the 13px text
   beside it in a table cell. The pill, not the data, was setting the row height on every dense
   admin table. This isn't a new convention: .chip and .tenant-vitals-chip already do it — the
   .badge family was the outlier. Values are chosen to land AT or under 19.5px, so the visual
   pill is unchanged; it just stops inflating the line box. */
.badge { display: inline-block; padding: 2px 10px; border-radius: 4px; font-family: var(--font-display); font-size: 11px; font-weight: 700; letter-spacing: 0.5px; text-transform: uppercase; border: 1px solid; line-height: 1.2; }
.badge-online { background: rgba(52, 211, 153, 0.08); color: var(--success); border-color: rgba(52, 211, 153, 0.2); }
.badge-offline { background: rgba(248, 113, 113, 0.08); color: var(--danger); border-color: rgba(248, 113, 113, 0.2); }
.badge-provisioning { background: rgba(251, 191, 36, 0.08); color: var(--warning); border-color: rgba(251, 191, 36, 0.2); }
.badge-failed { background: rgba(248, 113, 113, 0.1); color: var(--danger); border-color: rgba(248, 113, 113, 0.2); animation: pulse-badge 2s infinite; }
.badge-unknown { background: rgba(107, 114, 128, 0.08); color: var(--text-secondary); border-color: rgba(107, 114, 128, 0.15); }
.badge-ranked { background: var(--accent-dim); color: var(--accent); border-color: var(--border-accent); }
.badge-unranked { background: rgba(107, 114, 128, 0.08); color: var(--text-tertiary); border-color: rgba(107, 114, 128, 0.15); }
/* Per-role badges on template cards. */
.badge-role-timeattack { background: rgba(138, 111, 255, 0.08); color: #b49cff; border-color: rgba(138, 111, 255, 0.2); }
.badge-role-freeroam { background: rgba(255, 184, 107, 0.08); color: #ffb86b; border-color: rgba(255, 184, 107, 0.2); }
.badge-admin { background: rgba(248, 113, 113, 0.08); color: var(--danger); border-color: rgba(248, 113, 113, 0.2); }
.badge-read { background: rgba(107, 114, 128, 0.08); color: var(--text-secondary); border-color: rgba(107, 114, 128, 0.15); }
/* Wave 2.4 F23 — AuditLog operation pills grouped into 4 visual-scan categories. */
.badge-category-mutation   { background: rgba(0, 224, 255, 0.08);   color: var(--accent);          border-color: rgba(0, 224, 255, 0.2); }
.badge-category-read       { background: rgba(107, 114, 128, 0.08); color: var(--text-secondary);  border-color: rgba(107, 114, 128, 0.15); }
.badge-category-governance { background: rgba(251, 191, 36, 0.08);  color: var(--warning);         border-color: rgba(251, 191, 36, 0.2); }
.badge-category-system     { background: rgba(168, 85, 247, 0.08);  color: #c084fc;                border-color: rgba(168, 85, 247, 0.2); }
@keyframes pulse-badge { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } }

/* --- Spinner --- */
.spinner { display: inline-block; width: 14px; height: 14px; border: 2px solid var(--border); border-top-color: var(--accent); border-radius: 50%; animation: spin 0.6s linear infinite; vertical-align: middle; }
@keyframes spin { to { transform: rotate(360deg); } }

/* --- Empty State --- */
/* Density pass (2026-06-08): zero-state top/bottom 40 -> 24; .compact for inline widgets. */
.empty-state { background: var(--bg-panel); backdrop-filter: blur(12px) saturate(1.1); -webkit-backdrop-filter: blur(12px) saturate(1.1); border: 1px solid var(--border); border-radius: 5px; padding: 24px 28px; text-align: center; }
.empty-state.compact { padding: 16px 14px; }
.empty-state h3 { color: var(--text-secondary); font-family: var(--font-display); font-size: 15px; margin-bottom: 8px; }
.empty-state p { color: var(--text-muted); font-size: 13px; margin-bottom: 16px; }

/* --- Key Group Header --- */
.key-group-header { font-family: var(--font-display); font-size: 13px; font-weight: 600; color: var(--text-tertiary); text-transform: uppercase; letter-spacing: 0.5px; padding: 14px 0 6px; margin-top: 12px; border-bottom: 1px solid var(--border); display: flex; align-items: center; gap: 8px; }
.key-group-header .count { font-size: 11px; color: var(--text-muted); font-weight: 400; }

/* --- Relative Time Styles --- */
.time-muted { color: var(--text-muted); font-size: 12px; }
.time-active { color: var(--success); font-size: 12px; }
.time-never { color: var(--text-muted); font-size: 12px; font-style: italic; }

/* --- Phase 7 API Key rotation UI --- */
.key-countdown { font-variant-numeric: tabular-nums; font-size: 12px; color: var(--text-secondary); }
.key-countdown.key-countdown-urgent { color: var(--danger); font-weight: 600; }
.key-stale-badge { display: inline-block; padding: 2px 8px; border-radius: 4px; font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; background: rgba(255, 179, 71, 0.12); color: var(--warning); border: 1px solid rgba(255, 179, 71, 0.35); margin-right: 4px; }
.key-deprecated-badge { display: inline-block; padding: 2px 8px; border-radius: 4px; font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; background: rgba(255, 107, 107, 0.10); color: var(--danger); border: 1px solid rgba(255, 107, 107, 0.35); }
.key-orphan-badge { display: inline-block; padding: 2px 8px; border-radius: 4px; font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; line-height: 1.2; background: rgba(255, 107, 107, 0.10); color: var(--danger); border: 1px solid rgba(255, 107, 107, 0.35); margin-right: 4px; }
.key-superseded-badge { display: inline-block; padding: 2px 8px; border-radius: 4px; font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; line-height: 1.2; background: var(--accent-dim); color: var(--accent); border: 1px solid var(--border-accent); margin-right: 4px; }
/* Owner column: kind chip + label on one dense line (2026-09-15). */
.key-owner { display: inline-flex; align-items: baseline; gap: 6px; line-height: 1.3; font-size: 12px; color: var(--text-secondary); }
.key-owner-kind { font-family: var(--font-display); font-size: 10px; font-weight: 700; letter-spacing: 0.5px; text-transform: uppercase; color: var(--text-muted); }
.key-warn { color: var(--danger); font-weight: 600; }

/* --- Stats Bar --- */
.stats-bar { display: flex; gap: 12px; margin-bottom: 16px; flex-wrap: wrap; }
.stat { background: var(--bg-panel); backdrop-filter: blur(12px) saturate(1.1); -webkit-backdrop-filter: blur(12px) saturate(1.1); padding: 12px 14px; border-radius: 5px; font-size: 13px; border: 1px solid var(--border); }
.stat strong { color: var(--text-primary); }

/* --- Cards Grid --- */
.instance-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 12px; }
.instance-card { background: var(--bg-panel); backdrop-filter: blur(12px) saturate(1.1); -webkit-backdrop-filter: blur(12px) saturate(1.1); border-radius: 5px; padding: 16px; border: 1px solid var(--border); transition: border-color 0.15s ease, transform 0.1s ease; cursor: pointer; }
.instance-card:hover { border-color: var(--border-hover); transform: translateY(-1px); }
.card-header { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.card-header strong { font-family: var(--font-display); font-size: 14px; color: var(--text-primary); }
.card-body { font-size: 12px; color: var(--text-secondary); line-height: 1.7; }
.card-footer { display: flex; gap: 6px; margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--border); }

/* --- Tables — Hairline borders, panel-tone sticky header.
   Wave 2.4 F21 — was background: #000000 (true black) which clashed
   visually against the panel cards (rgba(8,12,18,0.65)). The panel-solid
   token matches the surrounding chrome so headers no longer pop as a
   foreign black bar. */
table { width: 100%; border-collapse: collapse; font-size: 13px; }
thead { position: sticky; top: 0; z-index: 10; }
/* Density pass (2026-06-08): all four table flavors share --cell-pad-y/x. */
th { text-align: left; padding: var(--cell-pad-y) var(--cell-pad-x); background: var(--bg-panel-solid); color: var(--text-tertiary); font-family: var(--font-display); font-weight: 600; font-size: 11px; text-transform: uppercase; letter-spacing: 0.5px; border-bottom: 1px solid var(--border-hover); }
td { padding: var(--cell-pad-y) var(--cell-pad-x); border-bottom: 1px solid var(--border); }
tr { transition: background 0.1s ease; }
tr:hover { background: var(--bg-hover); }
tr.revoked { opacity: 0.4; }

/* --- Buttons --- */
.btn { font-family: var(--font-display); font-weight: 600; font-size: 13px; background: transparent; color: var(--text-secondary); border: 1px solid var(--border); padding: 8px 18px; border-radius: var(--radius-6); cursor: pointer; transition: all 0.14s ease; display: inline-flex; align-items: center; gap: 6px; text-transform: uppercase; letter-spacing: var(--letter-spacing-tight); }
.btn:hover { border-color: var(--border-hover); color: var(--text-primary); }
.btn.primary { background: var(--accent); border-color: var(--accent); color: #00171c; box-shadow: 0 2px 14px rgba(0, 224, 255, 0.16); }
.btn.primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); box-shadow: 0 4px 22px rgba(0, 224, 255, 0.30); }
.btn.danger { color: var(--danger); border-color: rgba(248, 113, 113, 0.2); }
.btn.danger:hover { background: rgba(248, 113, 113, 0.08); border-color: var(--danger); }
.btn.success { color: var(--success); border-color: rgba(52, 211, 153, 0.2); }
.btn.success:hover { background: rgba(52, 211, 153, 0.08); border-color: var(--success); }
/* Wave 2.4 F26 — `.btn.warning` for impact-medium actions (Restart / Drain).
   Sits between `.btn.danger` (irreversible / Force-*) and the default neutral
   button so the Quick-controls group reads at a glance. */
.btn.warning { color: var(--warning); border-color: rgba(251, 191, 36, 0.25); }
.btn.warning:hover { background: rgba(251, 191, 36, 0.08); border-color: var(--warning); }
.btn.secondary { background: transparent; border-color: var(--border); }
.btn.secondary:hover { border-color: var(--border-hover); }
.btn.small { padding: 4px 10px; font-size: 12px; }
.btn:disabled { opacity: 0.4; cursor: not-allowed; pointer-events: none; }

/* --- Forms --- */
/* Density pass (2026-06-08): the biggest win — 94 panels across 64 files.
   padding/margin/gap driven by --panel-pad / --panel-gap / --panel-inner-gap. */
.form-panel { background: var(--bg-panel); backdrop-filter: blur(12px) saturate(1.1); -webkit-backdrop-filter: blur(12px) saturate(1.1); padding: var(--panel-pad); border-radius: 5px; margin: var(--panel-gap) 0; display: flex; flex-direction: column; gap: var(--panel-inner-gap); border: 1px solid var(--border); }
.form-panel.warning { background: rgba(251, 191, 36, 0.04); border-color: rgba(251, 191, 36, 0.15); }
.form-panel h3 { margin-bottom: 4px; }
.form-panel label { display: flex; flex-direction: column; gap: 4px; font-size: 13px; color: var(--text-secondary); }
/* Wave I (2026-05-12) F-306 — help-text bumped 11px → 12px so the muted
   copy clears WCAG AA readability on mobile. --text-muted (#7a8493) on
   #000 is 5.58:1 contrast, comfortably above 4.5:1 at 12px. */
.form-panel .help-text { font-size: 12px; color: var(--text-muted); margin-top: 2px; }
.form-panel input, .form-panel select, .form-panel textarea { background: var(--bg-input); border: 1px solid var(--border); color: var(--text-primary); padding: 8px 12px; border-radius: 4px; font-size: 13px; font-family: var(--font-body); transition: border-color 0.12s ease; }
.form-panel input:focus, .form-panel select:focus, .form-panel textarea:focus { outline: none; border-color: var(--border-accent-strong); box-shadow: 0 0 0 1px var(--border-accent); }
.form-panel input[readonly] { color: var(--text-tertiary); cursor: default; }
.form-actions { display: flex; gap: 8px; margin-top: 4px; }
.form-panel-actions { display: flex; gap: 8px; }

/* ============================================
   Wave I (2026-05-12) F-301 — layout utility classes.
   These retire the per-page inline style="display:flex; gap:..."
   overrides that 26 admin pages carried. Use a utility instead of a
   one-off inline style; the gaps map onto the canonical spacing scale
   (--space-* above) so admin pages share one rhythm source-of-truth.

   F-305 container-padding scale (documented here so the next overhaul
   keeps the four container densities aligned):
     form-panel  20px  (--space tight container — inline forms)
     modal       28px  (focus surface — needs breathing room)
     login-box   40px  (marketing-grade hero card)
     empty-state 40px 28px (centered zero-state — generous top/bottom)
   ============================================ */
.flex-center      { display: flex; align-items: center; }
.flex-between     { display: flex; align-items: center; justify-content: space-between; }
.flex-wrap        { flex-wrap: wrap; }
.flex-col         { display: flex; flex-direction: column; }
.flex-1           { flex: 1; }
.flex-gap-sm      { display: flex; gap: 8px; }
.flex-gap-md      { display: flex; gap: 12px; }
.flex-gap-lg      { display: flex; gap: 20px; }
.flex-center.flex-gap-sm,
.flex-center.flex-gap-md,
.flex-center.flex-gap-lg { align-items: center; }
.grid-2col        { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; }
.grid-3col        { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
/* Margin utilities — SINGLE canonical block. There were previously TWO
   conflicting definitions of .mt-sm/.mt-md/.mt-lg/.mb-sm/.mb-md/.mb-lg/.ml-sm
   (this block + a later one in the Utility Classes section). The later block
   won the cascade for the overlapping classes, so the values below are the
   ones that ACTUALLY rendered (later-block values for the overlapping
   classes) merged with this block's unique survivors (.mt-xs/.mb-xl/.mr-sm,
   which the later block did not redefine). Pixel-neutral consolidation —
   every class keeps the value it rendered before the dedup. */
.mt-xs  { margin-top: 4px; }
.mt-sm  { margin-top: 4px; }
.mt-md  { margin-top: 12px; }
.mt-lg  { margin-top: 16px; }
.mb-sm  { margin-bottom: 6px; }
.mb-md  { margin-bottom: 12px; }
.mb-lg  { margin-bottom: 16px; }
.mb-xl  { margin-bottom: 24px; }
.ml-sm  { margin-left: 4px; }
.ml-auto { margin-left: auto; }
.mr-sm  { margin-right: 8px; }
.w-full { width: 100%; }
.nowrap { white-space: nowrap; }
/* Reserve the grid slot but hide contents (no reflow) — used where a
   conditional field toggles visibility without collapsing its layout cell. */
.field-hidden { visibility: hidden; }
/* Wave I (2026-05-12) F-301 — FirstTimeSetup step panels + copyable command
   boxes. Replaces the repeated inline style="padding:16px; margin-bottom:12px"
   on the <details> steps and the readonly <textarea class="form-input"> command
   boxes (which were never real form inputs — just monospace copy targets). */
.step-panel { padding: 16px; margin-bottom: 12px; }
.step-summary { cursor: pointer; font-weight: 600; font-size: 15px; }
.cmd-textarea { font-family: var(--font-mono, monospace); font-size: 13px; flex: 1;
    background: var(--bg-input); border: 1px solid var(--border); color: var(--text-primary);
    padding: 8px 12px; border-radius: 4px; resize: vertical; }
.copied-ack { display: none; color: #00cc88; font-size: 13px; }
.setup-complete-callout { border-left: 4px solid #00cc88; background: rgba(0, 204, 136, 0.06); }
/* Wave I (2026-05-12) F-301 — small static helpers retiring one-off inline
   styles across the admin page tree. */
.spinner-sm { width: 12px; height: 12px; display: inline-block; vertical-align: middle; }
.row-flex { display: flex; gap: 20px; flex-wrap: wrap; }
.col-min-400 { flex: 1; min-width: 400px; }
.col-min-200 { flex: 1; min-width: 200px; }
.col-min-150 { flex: 1; min-width: 150px; }
.panel-subtle { background: rgba(255, 255, 255, 0.02); }
.danger-left { border-left: 4px solid #ff4d4d; background: rgba(255, 77, 77, 0.06); }
.label-check { display: flex; align-items: center; gap: 8px; cursor: pointer; }
/* Dynamic-value hooks: pass the runtime color via style="--accent-color:@c"
   and let the static rule consume it. Keeps data-driven color out of a
   hand-rolled inline rule (only the CSS custom property is inline). */
.swatch-bg { background: var(--accent-color, var(--text-muted)); }
.chip-accent { border-color: var(--accent-color, var(--border)); color: var(--accent-color, inherit); }
/* Conditional-dirty textarea border (replaces inline ternary style). */
.input-dirty { border-color: var(--accent) !important; }
.help-block { display: block; margin-top: 6px; }
.tpe-empty-hint { padding: 8px 4px; }
.badge-neutral { background: var(--bg-elevated); color: var(--text-muted); padding: 4px 8px; border: 1px solid var(--border); border-radius: var(--radius-sm); }
.m-0 { margin: 0; }
.th-checkbox { width: 40px; }
.incident-row-head { gap: 10px; }
.accent-left { border-left: 3px solid var(--accent); }
/* Wave I (2026-05-12) F-302 — BansTable cell sub-styles, retired from the
   per-<td> inline styles when the page moved onto AdminDataTable. */
.ban-scoped-id { color: var(--text-secondary); }
.ban-internal-note { font-size: 12px; color: var(--text-secondary); margin-top: 2px; }
.ban-banned-by { font-size: 12px; color: var(--text-secondary); }
.input-narrow { max-width: 240px; }
/* CSS-custom-property hook so a per-row accent color can be passed via
   style="--swatch:@color" while the static rule lives here (keeps the
   dynamic value out of a hand-rolled inline rule). */
.swatch-dot { display: inline-block; width: 14px; height: 14px; border-radius: 3px; background: var(--swatch, var(--text-muted)); }

/* ============================================
   Car Lists page (/car-lists) — picker grid + per-row chips.
   ============================================ */
.carlist-search { display: flex; align-items: center; gap: 12px; margin-bottom: 8px; }
.carlist-search input { flex: 1; max-width: 320px; }
.carlist-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); column-gap: 12px; row-gap: 1px; max-height: 520px; overflow-y: auto; padding: 4px 6px; background: var(--bg-input); border: 1px solid var(--border); border-radius: 4px; }
.carlist-car { display: flex !important; flex-direction: row !important; align-items: center; gap: 6px; padding: 2px 6px; margin: 0; background: transparent; border: 1px solid transparent; border-radius: 2px; cursor: pointer; font-size: 11.5px; line-height: 1.25; font-family: var(--font-mono); color: var(--text-secondary); transition: background 0.08s ease, color 0.08s ease; user-select: none; min-height: 22px; }
.carlist-car:hover { background: var(--bg-hover); color: var(--text-primary); }
.carlist-car.selected { background: var(--accent-dim); border-color: var(--border-accent-strong); color: var(--accent); }
.carlist-car input[type="checkbox"] { width: 12px; height: 12px; accent-color: var(--accent); margin: 0; flex-shrink: 0; }
.carlist-car-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.carlist-selected-summary { margin-top: 8px; padding: 8px 12px; background: rgba(0, 224, 255, 0.05); border: 1px solid rgba(0, 224, 255, 0.15); border-radius: 4px; font-size: 11px; color: var(--text-secondary); line-height: 1.5; word-wrap: break-word; }

/* Car/item picker grid */
.checkbox-label { display: flex !important; flex-direction: row !important; align-items: center; gap: 6px; padding: 6px 12px; background: var(--bg-input); border: 1px solid var(--border); border-radius: 4px; cursor: pointer; font-size: 12px; color: var(--text-secondary); transition: all 0.12s ease; user-select: none; }
.checkbox-label:hover { border-color: var(--border-accent-strong); color: var(--text-primary); }
.checkbox-label:has(input:checked) { background: var(--accent-dim); border-color: var(--accent); color: var(--accent); }
.checkbox-label input[type="checkbox"] { width: 14px; height: 14px; accent-color: var(--accent); margin: 0; }

/* --- Code / Copy --- */
/* line-height 1.2 — `code` is opened inline in ~199 places including table CellTemplates, and on
   the badge-free/button-free tables (TenantDetailAudit, LayoutLapsTab at PageSize=100) it was the
   element setting row height. See the pill note above. */
code { background: var(--bg-elevated); padding: 2px 8px; border-radius: 4px; font-size: 12px; font-family: var(--font-mono); color: var(--text-primary); line-height: 1.2; }
.copy-group { display: inline-flex; align-items: center; gap: 6px; }
.copy-value { padding: 4px 10px; }
.copy-btn { font-size: 11px !important; padding: 3px 8px !important; }

/* --- Code Editor --- */
.code-editor { background: var(--bg-input); color: var(--text-primary); font-family: var(--font-mono); font-size: 12px; line-height: 1.6; border: 1px solid var(--border); border-radius: 5px; padding: 14px; width: 100%; resize: vertical; tab-size: 2; transition: border-color 0.12s ease; }
.code-editor:focus { outline: none; border-color: var(--border-accent-strong); box-shadow: 0 0 0 1px var(--border-accent); }

/* --- Breadcrumb --- */
.breadcrumb { display: flex; align-items: center; gap: 8px; font-family: var(--font-mono); font-size: 11px; color: var(--text-tertiary); margin-bottom: 16px; }
.breadcrumb a { color: var(--text-tertiary); }
.breadcrumb a:hover { color: var(--accent); }
.breadcrumb-sep { color: var(--text-muted); }
.breadcrumb span:last-child { color: var(--text-primary); }

/* Template editor sub-nav as horizontal tabs (redesign 2026-06-21). These live
   in GLOBAL admin.css (not TemplateDetailLayout.razor.css) on purpose: the
   <ul class="tpl-sidebar"> is rendered by the CHILD _TemplateSidebar component,
   so the parent's Blazor-scoped CSS never reached it — which is exactly why the
   sub-nav used to render as bare default links. */
.tpl-tabs { margin-bottom: 20px; }
.tpl-sidebar { list-style: none; padding: 0; margin: 0; display: flex; gap: 2px; border-bottom: 1px solid var(--border); }
.tpl-sidebar-item a { position: relative; display: inline-flex; align-items: center; gap: 8px; padding: 10px 16px; color: var(--text-tertiary); text-decoration: none; font-family: var(--font-display); font-weight: 600; font-size: 13px; letter-spacing: 0.6px; transition: color 0.12s ease; }
.tpl-sidebar-item a:hover { color: var(--text-primary); }
.tpl-sidebar-item.active a { color: var(--accent); }
.tpl-sidebar-item.active a::after { content: ""; position: absolute; left: 8px; right: 8px; bottom: -1px; height: 2px; background: var(--accent); box-shadow: var(--glow-sm); border-radius: 2px; }
.tpl-dirty-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--accent); display: inline-block; box-shadow: 0 0 4px var(--accent-glow); }
@media (max-width: 720px) { .tpl-sidebar { overflow-x: auto; } }

/* R12 (2026-06-22) — shared Legal sub-nav reuses the .tpl-* horizontal-tab
   chrome; the erasures badge rides inside the NavLink. */
.legal-subnav .tpl-sidebar-item a { gap: 6px; }
/* Inline CurrentTosVersion flag/drift row beneath the Legal sub-nav. */
.legal-tos-flag-row { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin-bottom: 16px; }

/* Per-server structured config form (Tier 2) — Form/Raw toggle + a field grid
   grouped by INI section. Fields render through the shared FormField primitives. */
.config-view-toggle { display: flex; align-items: center; gap: 8px; margin-bottom: 14px; }
.config-form { display: flex; flex-direction: column; gap: 4px; }
.config-form-section { font-family: var(--font-display); font-weight: 600; font-size: 11px; letter-spacing: 1.2px; text-transform: uppercase; color: var(--accent); margin: 18px 0 10px; padding-bottom: 5px; border-bottom: 1px solid var(--border); }
.config-form-section:first-child { margin-top: 0; }
.config-form-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 14px 18px; align-items: start; }

/* --- Modal / Confirm Dialog — Glass treatment --- */
.modal-overlay { position: fixed; inset: 0; background: rgba(0, 0, 0, 0.7); z-index: 999; display: flex; align-items: center; justify-content: center; backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px); }
/* Density pass (2026-06-08): focus surface trimmed 28 -> 20/24. */
.modal { background: var(--bg-panel); backdrop-filter: blur(16px) saturate(1.2); -webkit-backdrop-filter: blur(16px) saturate(1.2); border: 1px solid var(--border); border-radius: var(--radius-lg); padding: 20px 24px; max-width: 420px; width: 90%; box-shadow: var(--shadow-modal); }
.modal h3 { margin-bottom: 8px; }
.modal-message { color: var(--text-secondary); font-size: 13px; margin: 0 0 12px; line-height: 1.6; }
.modal-actions { display: flex; gap: 8px; justify-content: flex-end; margin-top: 16px; }

/* --- Toast — Glass treatment with colored left border --- */
.toast-container { position: fixed; top: 20px; right: 20px; z-index: 1000; display: flex; flex-direction: column; gap: 8px; }
.toast { background: var(--bg-panel); backdrop-filter: blur(16px) saturate(1.2); -webkit-backdrop-filter: blur(16px) saturate(1.2); border: 1px solid var(--border); padding: 12px 18px; border-radius: 5px; font-size: 13px; min-width: 260px; box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5); animation: toast-in 0.2s ease; display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.toast-success { border-left: 3px solid var(--success); }
.toast-error { border-left: 3px solid var(--danger); }
.toast-info { border-left: 3px solid var(--accent); }
@keyframes toast-in { from { opacity: 0; transform: translateX(20px); } to { opacity: 1; transform: translateX(0); } }
.toast-dismiss { background: none; border: none; color: var(--text-muted); cursor: pointer; font-size: 18px; line-height: 1; padding: 0 2px; transition: color 0.12s ease; }
.toast-dismiss:hover { color: var(--text-primary); }

table input[type="checkbox"] { accent-color: var(--accent); cursor: pointer; width: 15px; height: 15px; }

/* --- Login --- */
.login-shell { display: flex; align-items: center; justify-content: center; min-height: 100vh; background: var(--bg-primary); }
.login-box { background: var(--bg-panel); backdrop-filter: blur(16px) saturate(1.2); -webkit-backdrop-filter: blur(16px) saturate(1.2); border: 1px solid var(--border); border-radius: 5px; padding: 40px 36px; width: 100%; max-width: 380px; }
.login-brand { font-family: var(--font-display); font-size: 20px; font-weight: 700; color: var(--accent); margin-bottom: 28px; text-align: center; letter-spacing: 1px; }
.login-field { margin-bottom: 16px; }
.login-input { width: 100%; background: var(--bg-input); border: 1px solid var(--border); color: var(--text-primary); padding: 10px 14px; border-radius: 4px; font-size: 14px; font-family: var(--font-body); transition: border-color 0.12s ease; }
.login-input:focus { outline: none; border-color: var(--border-accent-strong); box-shadow: 0 0 0 1px var(--border-accent); }
.login-input::placeholder { color: var(--text-muted); }
.login-btn { width: 100%; justify-content: center; padding: 10px 16px !important; font-size: 14px !important; }
.login-error { background: rgba(248, 113, 113, 0.08); border: 1px solid rgba(248, 113, 113, 0.2); color: var(--danger); padding: 8px 12px; border-radius: 4px; font-size: 13px; margin-bottom: 16px; text-align: center; }

/* --- Responsive --- */
@media (max-width: 768px) {
    .admin-shell { flex-direction: column; }
    .sidebar { width: 100%; position: static; flex-direction: row; overflow-x: auto; gap: 0; padding: 8px; border-right: none; border-bottom: 1px solid var(--border); backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px); }
    .sidebar-brand { display: none; }
    .sidebar-nav a { white-space: nowrap; padding: 6px 12px; font-size: 12px; }
    .content { margin-left: 0; padding: 16px; }
    .instance-grid { grid-template-columns: 1fr; }
    .stats-bar { flex-direction: column; }
    .modal { margin: 10vh 16px; }
}

/* Admins page */
.inline-form { display: flex; gap: 8px; align-items: center; margin-bottom: 12px; }
.inline-form input { flex: 1; }
/* Wave I (2026-05-12) F-302 — .bespoke-table aliases .data-table styling for
   the handful of admin tables that genuinely can't adopt AdminDataTable:
     • AnalyticsCharts — custom canvas-shaped bar/heatmap content.
     • DisputesTable — emits a secondary per-row notes <tr> (ColumnDef is
       strictly one <tr> per item) + per-cell row-click / stop-propagation.
     • EndSeasonModal — read-only reset-preview table inside an AdminConfirm.
   They keep their bespoke markup but move off the forbidden `data-table`
   class name so the admin forbidden-grep stays clean. */
.data-table, .bespoke-table { width: 100%; border-collapse: collapse; margin-top: 8px; }
.data-table th, .data-table td, .bespoke-table th, .bespoke-table td { padding: var(--cell-pad-y) var(--cell-pad-x); text-align: left; border-bottom: 1px solid var(--border); }
.data-table th, .bespoke-table th { color: var(--text-secondary); font-family: var(--font-display); font-weight: 600; font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.5px; }
.data-table code, .bespoke-table code { background: var(--bg-elevated); padding: 2px 6px; border-radius: 3px; font-size: 0.85rem; }
.btn-export-csv { padding: 4px 10px; font-size: 11px; margin-left: 12px; }
/* Wave I (2026-05-12) F-309/F-810 — operator Bundle page panels + install
   details (retired from inline border-left colors). */
.bundle-warn-panel { border-left: 4px solid #d9a946; }
.bundle-danger-panel { border-left: 4px solid #d94646; }
.bundle-install-details { margin-top: 14px; border-top: 1px solid var(--border); padding-top: 12px; }
.bundle-install-details > summary { cursor: pointer; font-family: var(--font-display); font-weight: 600; font-size: 14px; color: var(--text-secondary); }
.bundle-install-details > summary:hover { color: var(--text-primary); }
.bundle-install-body { margin-top: 10px; font-size: 13px; color: var(--text-secondary); line-height: 1.7; }
.bundle-install-body ul, .bundle-install-body ol { margin: 6px 0 12px 20px; }
.bundle-install-body li { margin-bottom: 4px; }
.community-admin-actions { display: flex; gap: 8px; flex-wrap: wrap; margin: 16px 0; }
/* Wave I (2026-05-12) F-309 — Community/Admin operator-page helpers retired
   from inline styles. */
.danger-left-thin { border-left: 4px solid #d94646; }
.success-left-thin { border-left: 4px solid #46d950; }
.col-min-220 { flex: 1; min-width: 220px; }
.help-text-tight { margin-top: -4px; margin-bottom: 12px; }
/* mig174 — help text that IS the whole section body (e.g. the self-hosted server card's
   "power controls live on your machine" note), where the default paragraph margins would
   leave the panel looking like it lost its controls rather than never having had any. */
.help-text-flush { margin: 0; }
.text-center { text-align: center; }
.cell-13 { font-size: 13px; }
.text-emerald { color: #10b981; }
.text-amber { color: #f59e0b; }
.ta-bar-track { background: var(--bg-elevated); border-radius: 4px; height: 14px; width: 160px; overflow: hidden; }
.form-inline { margin: 0; display: inline; }
.btn-compact { padding: 4px 10px; }
/* Wave I (2026-05-12) F-312 — sort glyph in the display font (was browser serif). */
.sort-icon { font-family: var(--font-display); }
.form-error { color: var(--danger); font-size: 0.85rem; margin-bottom: 8px; }
/* Wave I (2026-05-12) F-301 — success counterpart to .form-error so inline
   green success copy (style="color:#4ade80") retires to a token-driven class. */
.form-success { color: var(--success); font-size: 13px; }
.text-muted { color: var(--text-secondary); }


/* --- Utility Classes ---
   (Margin utilities .mt-*/.mb-*/.ml-* were consolidated into the single
   canonical block near the top of this file — see the dedup note there.) */
.text-xs { font-size: 11px; }
.text-sm { font-size: 12px; }
.text-tertiary { color: var(--text-tertiary); }
.text-danger { color: var(--danger); }
.text-success { color: var(--success); }
.text-warning { color: var(--warning); }
.text-mono { font-family: var(--font-mono, 'JetBrains Mono', 'Consolas', monospace); }
.color-warning { color: var(--warning); }
.color-success { color: var(--success); }
/* Wave 2.4 F15 — utility classes for the inline-style sweep so common
   '<div style="display:flex; gap:Npx; ...">' shapes go through CSS, not
   spread-by-copy across razor pages. */
.flex-row { display: flex; align-items: center; gap: 8px; }
.flex-row-md { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.flex-row-wrap { display: flex; gap: 16px; flex-wrap: wrap; }
.flex-col-1 { flex: 1; min-width: 220px; }
.inline-flex-row { display: inline-flex; align-items: center; gap: 6px; }

/* Wave 2.4 F1 — hero h1 modifier for landing pages that need a bigger
   typographic hook than the default 20px. */
.h1-hero {
    font-size: 44px;
    letter-spacing: -1px;
    line-height: 1.1;
}
@media (max-width: 640px) {
    .h1-hero { font-size: 32px; }
}

/* Wave 2.4 F36 — Tenants/Index local refinements (reuses .attention-row
   from AttentionStrip; just trims a couple of layout knobs). */
.tenants-distribution-banner { margin-bottom: 16px; align-items: flex-start; }
.tenants-distribution-banner .attention-text { font-size: 13px; line-height: 1.5; }
.tenants-action-row { margin-bottom: 16px; }
.tenants-row-count { margin-bottom: 12px; }

/* Wave 2.4 F15 — Maintenance.razor section heading spacing. */
.maintenance-section-h3 { margin-top: 1.5rem; }

/* Wave 2.4 F15 — Announcements page page-specific layout knobs. */
.announcements-create-panel { margin-bottom: 1.5rem; }
.announcements-pinned-row { gap: 8px; }

/* R14 (2026-06-22) — Create-Announcement form collapsed into a <details>
   drawer so the page leads with the announcements list. The <summary> carries
   the section heading; suppress the default disclosure triangle's collision
   with the inline <h3> and keep a click affordance. */
.announcements-create-summary { cursor: pointer; list-style: none; }
.announcements-create-summary::-webkit-details-marker { display: none; }
.announcements-create-summary > h3 { display: inline-block; margin: 0; }
.announcements-create-summary::before {
    content: "▸";
    display: inline-block;
    margin-right: 8px;
    color: var(--text-secondary);
    transition: transform 0.15s ease;
}
details[open] > .announcements-create-summary::before { transform: rotate(90deg); }

/* Wave 2.2 → Wave 2 cleanup — back-link banner shown when Announcements
   is opened from an alert via ?fromAlert=N. */
.announcements-from-alert {
    margin-bottom: 1rem;
    border-left: 3px solid var(--accent);
}

/* Wave 2.2 → Wave 2 cleanup — visually marks a row navigated to via
   /admins?highlight= or /bans?id= so the operator can see what they
   landed on. Subtle outline + faint cyan tint. */
.row-highlighted {
    outline: 2px solid var(--accent);
    outline-offset: -2px;
    background: rgba(0, 224, 255, 0.06);
}
.announcements-pinned-label { margin: 0; }

/* Wave 2.4 F15 — AuditLog correlation-chain banner + per-row chain button. */
.audit-correlation-banner { margin-bottom: 12px; border-left: 3px solid var(--accent); }
.audit-correlation-btn { background: none; border: none; padding: 0; cursor: pointer; color: var(--accent); }
.audit-correlation-btn:hover { color: var(--accent-hover); }

/* Wave 2.4 F15 — AlertDetailDrawer audit list + actions row. */
.alert-drawer-empty { font-size: 13px; }
.alert-drawer-audit-list { font-size: 13px; }
.alert-drawer-ack-input { width: 120px; }
.alert-drawer-actions { gap: 8px; }
.alert-drawer-status { color: var(--success); margin-top: 6px; font-size: 13px; }

/* Wave 2.4 F15 — TenantDetailKeyRotation staged-rotation card. */
.staged-rotation-panel { border-left: 4px solid var(--success); background: rgba(52, 211, 153, 0.06); padding: 12px 16px; }
.staged-rotation-list { margin: 0 0 12px 1em; }

/* Wave 2.4 F15 — TenantDetailBundle layout knobs. */
.bundle-handoff-chip-row { margin-top: 12px; }
.bundle-private-channel-banner { border-left: 4px solid var(--warning); background: rgba(251, 191, 36, 0.06); padding: 12px 16px; margin-bottom: 16px; }
.bundle-dm-textarea { font-family: var(--font-mono); font-size: 13px; }
.bundle-dm-actions { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.bundle-dm-copied-ack { display: none; color: var(--success); font-size: 13px; }
.bundle-dm-issued { margin-left: auto; }
.bundle-section-divider { margin: 20px 0; border: 0; border-top: 1px solid rgba(255,255,255,0.08); }

/* --- Form Input (standalone, outside .form-panel) --- */
.form-input { background: var(--bg-input); border: 1px solid var(--border); color: var(--text-primary); padding: 8px 12px; border-radius: 4px; font-size: 13px; font-family: var(--font-body); transition: border-color 0.12s ease; width: 100%; }
.form-input:focus { outline: none; border-color: var(--border-accent-strong); box-shadow: 0 0 0 1px var(--border-accent); }
.form-input:disabled { opacity: 0.5; cursor: not-allowed; }
/* Wave I (2026-05-12) F-302 — FeedbackDetailPanel keeps its inline-with-label
   select + bespoke notes textarea but styles them via dedicated classes so the
   forbidden `form-input` class isn't reused outside a primitive. */
.feedback-notes-textarea, .feedback-status-select { background: var(--bg-input); border: 1px solid var(--border); color: var(--text-primary); padding: 8px 12px; border-radius: 4px; font-size: 13px; font-family: var(--font-body); transition: border-color 0.12s ease; }
.feedback-notes-textarea { width: 100%; resize: vertical; }
.feedback-notes-textarea:focus, .feedback-status-select:focus { outline: none; border-color: var(--border-accent-strong); box-shadow: 0 0 0 1px var(--border-accent); }
.feedback-status-select { width: auto; display: inline-block; margin-left: 6px; }
/* Wave I (2026-05-12) F-302 — .input-bare is the canonical styling for the
   handful of raw <input>/<textarea>/<select> that legitimately can't adopt
   FormField (custom label/validation layouts: Disputes annotation, the
   ProvisionWizard batch-count beside its own label, the IncidentList inline
   public-note). Visually identical to .form-input; the distinct class keeps
   the forbidden `form-input` token off non-primitive markup. */
.input-bare { background: var(--bg-input); border: 1px solid var(--border); color: var(--text-primary); padding: 8px 12px; border-radius: 4px; font-size: 13px; font-family: var(--font-body); transition: border-color 0.12s ease; width: 100%; }
.input-bare:focus { outline: none; border-color: var(--border-accent-strong); box-shadow: 0 0 0 1px var(--border-accent); }

/* Per-server car roster editor (ServerTabCars, migration 138) — removable car
   chips + an inline input+button row for adding car ids. */
.form-inline-row { display: flex; gap: 8px; align-items: center; }
.form-inline-row .input-bare { flex: 1; }
.car-chip-list { display: flex; flex-wrap: wrap; gap: 6px; }
.car-chip { display: inline-flex; align-items: center; gap: 6px; padding: 3px 6px 3px 10px; background: var(--bg-input); border: 1px solid var(--border); border-radius: 4px; font-size: 12px; }
.car-chip code { color: var(--text-primary); font-size: 12px; }
.car-chip-x { background: none; border: none; color: var(--text-muted); cursor: pointer; font-size: 15px; line-height: 1; padding: 0 2px; border-radius: 3px; }
.car-chip-x:hover { color: var(--danger); background: rgba(248, 113, 113, 0.1); }
.car-chip-x:disabled { opacity: 0.4; cursor: not-allowed; }
/* Installed-cars picker (ServerTabCars, 2026-09-14 — moved in from the removed community
   operator card): click a car folder found on the host to add it to the roster. Pinned
   leading — a dense chip list must not inherit the body's prose line-height. */
.car-pick-list { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-top: 8px; max-height: 184px; overflow-y: auto; padding: 2px; line-height: 1.25; }
.car-pick { display: inline-flex; align-items: center; gap: 5px; cursor: pointer; background: var(--bg-input); border: 1px solid var(--border); border-radius: 4px; padding: 3px 8px; font-size: 12px; transition: border-color 0.12s ease; }
.car-pick:hover { border-color: var(--accent); }
.car-pick:disabled { opacity: 0.6; cursor: default; }
.car-pick code { color: var(--text-primary); font-size: 12px; }
.car-pick-plus { color: var(--accent); font-weight: 700; line-height: 1; }
.car-pick-more { width: 100%; }
.input-bare:disabled { opacity: 0.5; cursor: not-allowed; }
.form-group { display: flex; flex-direction: column; gap: 4px; }
.form-group label { font-size: 13px; color: var(--text-secondary); }
/* Wave I (2026-05-12) F-306 — help-text + form-hint bumped 11px → 12px
   to match .form-panel .help-text and clear mobile readability. */
.form-group .help-text { font-size: 12px; color: var(--text-muted); margin-top: 2px; }
.form-hint { font-size: 12px; color: var(--text-muted); font-weight: normal; }

/* --- Form Row --- */
/* Density pass (2026-06-08): inter-field gap 16 -> 12. */
.form-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: var(--space-12); }

/* --- Weather warning --- */
.weather-warning { background: var(--warning-dim, rgba(251, 191, 36, 0.08)); color: var(--warning); padding: 8px 12px; border-radius: 4px; font-size: 0.85rem; margin-top: 6px; }

/* --- Tab navigation --- */
/* Density pass (2026-06-08): tab bar tightened (mb 20->12, btn 10/20->8/16). */
.tab-bar { display: flex; gap: 0; border-bottom: 1px solid var(--border); margin-bottom: 12px; }
.tab-btn { padding: 8px 16px; background: none; border: none; color: var(--text-muted); cursor: pointer; font-family: var(--font-display); font-size: 0.95rem; border-bottom: 2px solid transparent; transition: color 0.2s, border-color 0.2s; }
.tab-btn:hover { color: var(--text-primary); }
.tab-btn.active { color: var(--accent); border-bottom-color: var(--accent); }

/* ============================================
   Phase 0 — Admin IA shared components
   (StateBadge, DependencyPanel, PreviewConfirmModal,
    DriftIndicator, ObjectAuditTab, ReadinessChecklist)
   The plural Breadcrumbs primitive was unified with the singular
   Breadcrumb (see line 205) in Phase 3.4 of the admin migration
   completion plan (2026-05-04).
   ============================================ */

/* --- StateBadge (Task 0.10) --- */
.state-badge { display: inline-block; padding: 2px 8px; border-radius: 6px;
    font-size: .72rem; font-weight: 600; letter-spacing: .04em; border: 1px solid transparent;
    line-height: 1.15; }   /* 1.15 not 1.2: at .72rem, 1.2 lands 0.3px over the cell strut */
.state-badge.state-draft      { background: #3a3a1a; color: #ffd166; border-color: #ffd16655; }
.state-badge.state-active     { background: #0d3a2a; color: #8aff8a; border-color: #8aff8a55; }
.state-badge.state-archived   { background: #2a2a2a; color: #9a9a9a; border-color: #9a9a9a55; }
.state-badge.state-deprecated { background: #3a1a1a; color: #ff9a9a; border-color: #ff9a9a55; }
.state-badge.state-scheduled  { background: #1a2a3a; color: #9ac8ff; border-color: #9ac8ff55; }
.state-badge.state-unknown    { background: #222; color: #666; border-color: #66666655; }

/* --- DependencyPanel (Task 0.11) --- */
.dep-panel { padding: 12px 16px; border-radius: 5px; margin: 12px 0; font-size: .9rem; }
.dep-panel.dep-warn  { background: #2a2010; color: #ffd166; border: 1px solid #ffd16655; }
.dep-panel.dep-block { background: #2a1010; color: #ff9a9a; border: 1px solid #ff9a9a88; }
.dep-title { font-weight: 600; margin-bottom: 6px; }
.dep-list { margin: 0; padding-left: 18px; }
.dep-list li { margin: 2px 0; }
.dep-kind { display: inline-block; min-width: 80px; color: #888; font-size: .75rem; text-transform: uppercase; }

/* --- SeasonPoolAwarenessBanner (Phase 5 Task 5.20) ---
   Subtle cyan callout on /car-lists/{id} when this list is the live
   source for an active season's Time Attack pool. Hidden when no
   active season references the list. */
.season-pool-banner {
    padding: 10px 14px;
    margin: 12px 0;
    border-radius: 5px;
    background: rgba(0, 224, 255, 0.08);
    color: #9deeff;
    border: 1px solid rgba(0, 224, 255, 0.35);
    font-size: .9rem;
    line-height: 1.5;
}

/* --- PreviewConfirmModal (Task 0.12) --- */
.modal.preview-confirm { min-width: 520px; max-width: 760px; max-height: 80vh; overflow: auto; }
.preview-pane { background: #111; border: 1px solid #333; border-radius: 4px; padding: 12px;
    margin: 12px 0; font-family: monospace; font-size: .85rem; max-height: 40vh; overflow: auto; }
.ack-row { display: flex; align-items: center; gap: 8px; margin: 12px 0; font-size: .9rem; }
.btn.danger:disabled { background: #444; color: #888; cursor: not-allowed; }

/* --- DriftIndicator (Task 0.13) --- */
.drift-chip { display: inline-flex; align-items: center; gap: 6px; padding: 2px 8px;
    border-radius: 6px; font-size: .72rem; font-weight: 600; line-height: 1.15; }
.drift-dot { width: 6px; height: 6px; border-radius: 50%; }
.drift-chip.drift-insync  { background: #0d3a2a; color: #8aff8a; }
.drift-chip.drift-insync .drift-dot  { background: #8aff8a; }
.drift-chip.drift-drifted { background: #3a2a10; color: #ffd166; }
.drift-chip.drift-drifted .drift-dot { background: #ffd166; }
/* Wave 7 F30 — drift "unknown" state had a near-invisible #888 on
   #222 (4.6:1, marginal). Bump to a clearer outline-only treatment
   with a brighter dot so the operator can spot it at-a-glance. */
.drift-chip.drift-unknown {
    background: transparent;
    color: #b0b8c4;
    border: 1px dashed rgba(255,255,255,0.18);
}
.drift-chip.drift-unknown .drift-dot { background: #b0b8c4; }

/* --- ObjectAuditTab (Task 0.14) --- */
.audit-table { width: 100%; border-collapse: collapse; font-size: .88rem; }
.audit-table th, .audit-table td { padding: 6px 10px; border-bottom: 1px solid #222; text-align: left; }
.audit-table th { color: #888; font-weight: 600; font-size: .78rem; text-transform: uppercase; letter-spacing: .04em; }
.audit-table .mono { font-family: monospace; }
.audit-table .dim { color: #666; }
.audit-detail { max-width: 360px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* --- Breadcrumbs (Task 0.15) ---
   Plural <Breadcrumbs> component was unified into the singular
   <Breadcrumb> (.breadcrumb rules above, line 205) in Phase 3.4 of
   the admin primitive migration completion plan (2026-05-04). The
   .breadcrumbs / .crumb-sep / .crumb-current rules that lived here
   went with it. */

/* --- ReadinessChecklist (Task 0.16) --- */
.readiness-list { list-style: none; padding: 0; margin: 12px 0; }
.readiness-row { display: flex; align-items: baseline; gap: 8px; padding: 6px 0; border-bottom: 1px solid #1a1a1a; }
.readiness-row.sat .readiness-mark   { color: #8aff8a; }
.readiness-row.unsat .readiness-mark { color: #ff6b6b; }
.readiness-row.unsat.opt .readiness-mark { color: #888; }
.readiness-mark { font-weight: 700; font-family: monospace; width: 16px; }
.readiness-opt-tag { font-size: .7rem; color: #888; padding: 1px 6px; border: 1px solid #444; border-radius: 5px; }
.readiness-hint { flex-basis: 100%; margin-left: 24px; color: #888; font-size: .82rem; }

/* --- Status badges (FirstTimeSetup / PluginArtifacts / ProtocolVersions / Tenants) --- */
/* Wave 2.4 F27 — codify the status-badge / check-ok / check-fail color tokens that
   FirstTimeSetup + ReadinessChecklist rely on. Previously these classes inherited
   no explicit color rules so the ✓/✗ glyphs read as plain text. */
.status-badge { display: inline-flex; align-items: center; gap: 4px; font-family: var(--font-display); font-size: 11px; font-weight: 700; padding: 2px 8px; border-radius: 4px; letter-spacing: 0.4px; border: 1px solid transparent; line-height: 1.2; }
.status-badge.status-success { background: rgba(138, 255, 138, 0.08); color: var(--success); border-color: rgba(138, 255, 138, 0.25); }
.status-badge.status-danger  { background: rgba(255, 107, 107, 0.08); color: var(--danger);  border-color: rgba(255, 107, 107, 0.28); }
.status-badge.status-warning { background: rgba(255, 179, 71, 0.08);  color: var(--warning); border-color: rgba(255, 179, 71, 0.28); }
.status-badge.status-muted   { background: rgba(255, 255, 255, 0.04); color: var(--text-muted); border-color: rgba(255, 255, 255, 0.08); }

/* Inline check glyph utilities — for "this control is OK / failed" badges in narrative pages.
   Use <span class="check-ok">✓</span> / <span class="check-fail">✗</span> instead of literal X. */
.check-ok   { color: var(--success); font-weight: 700; }
.check-fail { color: var(--danger);  font-weight: 700; }

/* --- Phase 6 Task 6.18-6.19 — Alerts drawer --- */
.drawer-backdrop {
    position: fixed; inset: 0; background: rgba(0, 0, 0, 0.45);
    z-index: 90;
}
.drawer {
    position: fixed; top: 0; right: 0; height: 100vh; width: min(460px, 92vw);
    background: #141414; border-left: 1px solid #2a2a2a;
    box-shadow: -4px 0 16px rgba(0, 0, 0, 0.4);
    padding: 20px; overflow-y: auto; z-index: 100;
    animation: drawer-slide 0.22s ease-out;
}
.drawer.slide-in { animation: drawer-slide 0.22s ease-out; }
@keyframes drawer-slide { from { transform: translateX(100%); } to { transform: translateX(0); } }
.drawer-header {
    display: flex; align-items: center; justify-content: space-between;
    border-bottom: 1px solid #2a2a2a; padding-bottom: 10px; margin-bottom: 14px;
}
.drawer-section { margin-bottom: 20px; }
.drawer-section h4 { margin: 0 0 8px; color: #00e0ff; font-size: .95rem; text-transform: uppercase; letter-spacing: .08em; }
.audit-list { list-style: none; padding: 0; margin: 0; }
.audit-list li { padding: 4px 0; border-bottom: 1px dashed #222; }
.audit-time { color: var(--text-muted); font-family: monospace; font-size: 12px; }

/* --- Phase 6 Task 6.21 — Bans form grid + table helpers --- */
/* 2026-06-08 — base auto-fill form grid (was UNDEFINED — 5 operator-admin
   panels referenced .form-grid with no rule, so their fields stacked
   unstyled). Auto-fills as many ~160px columns as fit. */
/* Density pass (2026-06-08): tighter cells (160->140) + token-driven gap. */
.form-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
    gap: var(--panel-inner-gap);
}
.form-grid-2col {
    display: grid; gap: 12px;
    grid-template-columns: repeat(2, minmax(0, 1fr));
}
@media (max-width: 640px) {
    .form-grid-2col { grid-template-columns: 1fr; }
}
.form-grid-2col .form-group.full-width { grid-column: 1 / -1; }
.kv-grid {
    display: grid; grid-template-columns: minmax(110px, auto) 1fr;
    gap: 4px 14px; margin: 8px 0 0;
}
.kv-grid dt { color: var(--text-muted); font-size: 12px; text-transform: uppercase; letter-spacing: .05em; }
.kv-grid dd { margin: 0; font-size: 13px; }

/* Phase 7 Task 7.10 — Admins page presence dot (green = seen in last 5m). */
.presence-dot {
    display: inline-block;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    vertical-align: middle;
}
.presence-online { background: #00e08a; box-shadow: 0 0 6px rgba(0, 224, 138, 0.55); }
.presence-offline { background: rgba(255, 255, 255, 0.18); }
.preview-row { display: flex; gap: 12px; padding: 4px 0; border-bottom: 1px solid rgba(255,255,255,0.04); font-size: 13px; }
.preview-row:last-child { border-bottom: none; }
.preview-label { color: var(--text-muted); min-width: 110px; text-transform: uppercase; font-size: 11px; letter-spacing: .05em; }

/* Phase 7 Task 7.15 — audit target chip (deep-links to related admin page). */
.target-chip {
    display: inline-block;
    font-size: 12px;
    /* AuditLog has no per-row button, so THIS chip was the tallest thing in the row and set the
       height for all 50 rows on the most scan-heavy page in the admin. See the pill note above. */
    line-height: 1.2;
    padding: 1px 8px;
    border-radius: 6px;
    background: rgba(0, 224, 255, 0.08);
    border: 1px solid rgba(0, 224, 255, 0.25);
    color: var(--text-primary);
    text-decoration: none;
    font-family: var(--font-mono, monospace);
}
a.target-chip:hover { background: rgba(0, 224, 255, 0.14); }

/* Phase 7 Task 7.27 — Legal page markdown preview pane.
   Not a real markdown renderer (no Markdig); keeps whitespace + wraps so
   admins can eyeball the draft against the active version without a round-trip. */
.md-preview {
    font-family: var(--font-body, 'Inter', sans-serif);
    font-size: 0.9rem;
    color: var(--text-primary);
    background: rgba(0, 0, 0, 0.3);
    border: 1px solid var(--border);
    border-radius: 4px;
    padding: 12px;
    max-height: 400px;
    overflow-y: auto;
    white-space: pre-wrap;
    word-break: break-word;
}

/* ============================================
   Phase 6-8 Admin IA — LiveOps + shared components
   ============================================ */

/* --- Page header (title row with optional actions) --- */
.page-header-row { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-bottom: 16px; flex-wrap: wrap; }
.page-header-row h1 { margin: 0; }
.page-intro { color: var(--text-secondary); font-size: 13px; margin-bottom: 16px; max-width: 760px; line-height: 1.6; }

/* --- PageHeader primitive (orienting layer, 2026-06-22) ---
   Canonical scannable page header: breadcrumb (small, top, rendered by the
   <Breadcrumb> component just above .page-header) → prominent title → one-line
   muted description → right-aligned actions. Calm hierarchy: the title is the
   one prominent element, the description sits clearly secondary beneath it. */
.page-header { margin-bottom: 18px; }
.page-header .ph-main {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
}
.page-header .ph-titles { min-width: 0; }
.ph-title {
    margin: 0;
    display: flex;
    align-items: center;
    gap: 10px;
    font-family: var(--font-display);
    font-size: 26px;
    font-weight: 700;
    line-height: 1.15;
    letter-spacing: 0.3px;
    color: var(--text-primary);
}
.ph-icon { display: inline-flex; align-items: center; color: var(--accent); font-size: 22px; }
.ph-badge {
    font-family: var(--font-mono);
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    color: var(--accent);
    background: var(--accent-dim);
    border: 1px solid var(--border-accent);
    border-radius: 9px;
    padding: 2px 8px;
    line-height: 1.4;
    align-self: center;
}
.ph-desc {
    margin: 5px 0 0;
    color: var(--text-secondary);
    font-size: 13px;
    line-height: 1.55;
    max-width: 760px;
}
/* .ph-actions piggybacks on .page-header-actions spacing; align it to the
   title baseline-ish so buttons sit level with the title row. */
.page-header .ph-actions { margin: 0; flex-shrink: 0; }
@media (max-width: 720px) {
    .page-header .ph-main { flex-direction: column; align-items: stretch; }
    .page-header .ph-actions { justify-content: flex-start; }
}

/* --- LiveOps page shell --- */
/* Density pass (2026-06-08): LiveOps inter-section gap 20 -> 14. */
.live-ops-shell { display: flex; flex-direction: column; gap: 14px; }
.live-ops-title { font-family: var(--font-display); font-size: 26px; font-weight: 700; color: var(--text-primary); margin-bottom: 4px; letter-spacing: 0.3px; }
.live-ops-bottom-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 14px;
    align-items: start;
}
@media (max-width: 1100px) { .live-ops-bottom-row { grid-template-columns: 1fr; } }

/* --- AttentionStrip (Phase 6 Task 6.11) ---
   Horizontal row of attention-needed callouts above LiveOps. "All clear"
   when nothing needs attention; otherwise stacks rows with severity
   coloring. Each row is a link with an action label on the right. */
.attention-strip {
    background: var(--bg-panel);
    border: 1px solid var(--border);
    border-radius: 5px;
    padding: 4px;
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.attention-clear {
    padding: 12px 16px;
    color: var(--success);
    font-size: 13px;
    text-align: center;
}
.attention-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 14px;
    border-radius: 4px;
    text-decoration: none;
    color: var(--text-primary);
    border: 1px solid transparent;
    background: rgba(255, 255, 255, 0.015);
    transition: background 0.12s ease, border-color 0.12s ease;
}
.attention-row:hover { background: var(--bg-hover); border-color: var(--border-hover); }
.attention-row.attention-critical { background: rgba(248, 113, 113, 0.08); border-color: rgba(248, 113, 113, 0.22); }
.attention-row.attention-critical:hover { background: rgba(248, 113, 113, 0.14); }
.attention-row.attention-warning { background: rgba(251, 191, 36, 0.06); border-color: rgba(251, 191, 36, 0.2); }
.attention-row.attention-warning:hover { background: rgba(251, 191, 36, 0.11); }
.attention-row.attention-info { background: rgba(0, 224, 255, 0.06); border-color: rgba(0, 224, 255, 0.2); }
.attention-row.attention-info:hover { background: rgba(0, 224, 255, 0.11); }
.attention-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px; height: 22px;
    border-radius: 50%;
    font-weight: 700;
    font-size: 12px;
    font-family: var(--font-display);
    flex-shrink: 0;
}
.attention-critical .attention-icon { background: rgba(248, 113, 113, 0.2); color: var(--danger); }
.attention-warning .attention-icon { background: rgba(251, 191, 36, 0.2); color: var(--warning); }
.attention-info .attention-icon { background: rgba(0, 224, 255, 0.2); color: var(--accent); }
.attention-text { flex: 1; font-size: 13px; color: var(--text-primary); }
.attention-action {
    font-family: var(--font-display);
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    color: inherit;
    padding: 4px 10px;
    border-radius: 4px;
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid rgba(255, 255, 255, 0.1);
    flex-shrink: 0;
}
.attention-row:hover .attention-action { background: rgba(255, 255, 255, 0.1); }

/* --- LiveMatchesGrid (Phase 6 Task 6.12) --- */
.live-grid {
    background: var(--bg-panel);
    border: 1px solid var(--border);
    border-radius: 5px;
    padding: 16px 18px;
}
.live-grid-header {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 12px;
    padding-bottom: 10px;
    border-bottom: 1px solid var(--border);
}
.live-grid-header h3 { margin: 0; font-family: var(--font-display); font-size: 14px; color: var(--text-primary); letter-spacing: 0.5px; }
.live-grid-count { font-size: 12px; color: var(--text-muted); font-family: var(--font-mono); }
.live-grid-cards {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
    gap: 12px;
}
.live-card {
    background: var(--bg-elevated);
    border: 1px solid var(--border);
    border-radius: 4px;
    padding: 12px 14px;
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.live-card-top { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.live-card-server { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.live-card-server strong { font-family: var(--font-display); font-size: 13px; color: var(--text-primary); }
.live-card-elapsed { font-family: var(--font-mono); font-size: 12px; color: var(--text-tertiary); }
.live-round-chip {
    font-family: var(--font-mono);
    font-size: 11px;
    padding: 2px 8px;
    border-radius: 6px;
    background: var(--accent-dim);
    color: var(--accent);
    border: 1px solid var(--border-accent);
}
.live-card-racers {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    gap: 8px;
    align-items: center;
}
.live-racer { display: flex; flex-direction: column; gap: 2px; }
.live-racer.right { text-align: right; align-items: flex-end; }
.live-racer-role {
    font-family: var(--font-display);
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.6px;
}
.live-racer-role.king { color: var(--warning); }
.live-racer-role.challenger { color: var(--accent); }
.live-racer-name { font-size: 13px; color: var(--text-primary); font-weight: 600; }
.live-vs { font-family: var(--font-display); font-size: 11px; color: var(--text-muted); letter-spacing: 1px; text-transform: uppercase; }
.live-card-gap {
    display: flex;
    align-items: center;
    gap: 10px;
    padding-top: 8px;
    border-top: 1px dashed var(--border);
}
.live-gap-label { font-size: 10px; text-transform: uppercase; letter-spacing: 0.6px; color: var(--text-muted); font-family: var(--font-display); }
.live-gap-value { font-family: var(--font-mono); font-size: 12px; color: var(--text-primary); font-weight: 600; min-width: 40px; }
.live-card-actions { display: flex; flex-wrap: wrap; gap: 6px; padding-top: 6px; border-top: 1px solid var(--border); }

/* Tiny button variant shared by Phase 6 action rows. */
.btn-xs, .btn.btn-xs {
    font-family: var(--font-display);
    font-weight: 600;
    font-size: 11px;
    background: transparent;
    color: var(--text-secondary);
    border: 1px solid var(--border);
    padding: 4px 8px;
    border-radius: 4px;
    cursor: pointer;
    transition: all 0.12s ease;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    text-decoration: none;
}
.btn-xs:hover, .btn.btn-xs:hover { border-color: var(--border-hover); color: var(--text-primary); }
.btn-xs.secondary { background: transparent; border-color: var(--border); }
.btn-xs.danger { color: var(--danger); border-color: rgba(248, 113, 113, 0.25); }
.btn-xs.danger:hover { background: rgba(248, 113, 113, 0.08); border-color: var(--danger); }
.btn-xs.warning { color: var(--warning); border-color: rgba(251, 191, 36, 0.3); }
.btn-xs.warning:hover { background: rgba(251, 191, 36, 0.08); border-color: var(--warning); }
.btn.small.warning { color: var(--warning); border-color: rgba(251, 191, 36, 0.3); }
.btn.small.warning:hover { background: rgba(251, 191, 36, 0.08); border-color: var(--warning); }

/* --- GapSparkline --- */
.gap-sparkline { display: inline-block; vertical-align: middle; }
.gap-spark-zero { stroke: var(--border); stroke-width: 1; stroke-dasharray: 2,2; }
.gap-spark-line { fill: none; stroke: var(--accent); stroke-width: 1.5; }
.gap-sparkline-empty { color: var(--text-muted); font-size: 12px; }

/* --- FleetStatsRow (Phase 6 Task 6.16) --- */
.fleet-stats-row {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
    gap: 10px;
    background: var(--bg-panel);
    border: 1px solid var(--border);
    border-radius: 5px;
    padding: 14px;
}
.fs-tile {
    background: var(--bg-elevated);
    border: 1px solid var(--border);
    border-radius: 4px;
    padding: 10px;
    display: flex;
    flex-direction: column;
    gap: 4px;
    align-items: center;
    justify-content: center;
    text-align: center;
    /* Density pass (2026-06-08): fleet-summary tile floor 82 -> 60. */
    min-height: 60px;
}
.fs-tile-value {
    font-family: var(--font-display);
    font-size: 22px;
    font-weight: 700;
    color: var(--text-primary);
    line-height: 1.1;
    font-variant-numeric: tabular-nums;
}
.fs-tile-label {
    font-family: var(--font-display);
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    color: var(--text-muted);
}
.fs-online .fs-tile-value { color: var(--success); }
.fs-draining .fs-tile-value { color: var(--warning); }
.fs-offline .fs-tile-value { color: var(--text-tertiary); }
.fs-failed .fs-tile-value { color: var(--danger); }
.fs-online { border-color: rgba(52, 211, 153, 0.18); }
.fs-failed { border-color: rgba(248, 113, 113, 0.18); }

/* --- ActiveAdminsWidget (Phase 6 Task 6.15) --- */
.active-admins-widget {
    background: var(--bg-panel);
    border: 1px solid var(--border);
    border-radius: 5px;
    padding: 14px 16px;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    min-height: 52px;
}
.active-admins-label {
    font-family: var(--font-display);
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    color: var(--text-muted);
    margin-right: 4px;
}
.active-admins-empty { color: var(--text-muted); font-size: 12px; font-style: italic; }

/* R13 (2026-06-22) — LiveOps System Health card (gap signals only:
   active incidents + active maintenance window). */
.system-health-card h3 { margin-bottom: 10px; }
.system-health-rows { display: flex; flex-direction: column; gap: 6px; }
.system-health-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 8px 10px;
    border-radius: 4px;
    background: rgba(255, 255, 255, 0.02);
    border: 1px solid var(--border);
    text-decoration: none;
    color: var(--text-secondary);
    font-size: 13px;
    transition: border-color 0.12s ease, background 0.12s ease;
}
.system-health-row:hover { border-color: var(--border-accent); background: rgba(255, 255, 255, 0.04); }
.system-health-label { color: var(--text-muted); }
.system-health-value { color: var(--text-primary); font-weight: 600; font-family: var(--font-mono); font-size: 12px; }
.system-health-row-alert { border-color: var(--danger); }
.system-health-row-alert .system-health-value { color: var(--danger); }
.system-health-row-warn { border-color: var(--warning, #f59e0b); }
.system-health-row-warn .system-health-value { color: var(--warning, #f59e0b); }
.active-admin-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 10px 4px 8px;
    background: var(--bg-elevated);
    border: 1px solid var(--border);
    border-radius: 7px;
    font-size: 12px;
    color: var(--text-primary);
}
.active-admin-chip .chip-dot {
    width: 7px; height: 7px; border-radius: 50%;
    background: var(--success); box-shadow: 0 0 4px rgba(52, 211, 153, 0.5);
    flex-shrink: 0;
}
.active-admin-chip .chip-muted { color: var(--text-muted); font-family: var(--font-mono); font-size: 11px; }

/* --- RecentReactiveOpsCard (Phase 6 Task 6.17) --- */
.recent-ops-card {
    background: var(--bg-panel);
    border: 1px solid var(--border);
    border-radius: 5px;
    padding: 14px 16px;
}
.recent-ops-header {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 10px;
    padding-bottom: 8px;
    border-bottom: 1px solid var(--border);
}
.recent-ops-header h4 { margin: 0; font-family: var(--font-display); font-size: 13px; color: var(--text-primary); text-transform: uppercase; letter-spacing: 0.5px; }
.recent-ops-list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 4px; }
.recent-ops-list li {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 0;
    border-bottom: 1px dashed var(--border);
    font-size: 12px;
}
.recent-ops-list li:last-child { border-bottom: none; }
.recent-ops-op { flex-shrink: 0; }
.recent-ops-by { color: var(--text-secondary); flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.recent-ops-time { color: var(--text-muted); font-family: var(--font-mono); font-size: 11px; flex-shrink: 0; }
.recent-ops-link { font-family: var(--font-mono); font-size: 11px; color: var(--accent); padding: 2px 6px; border: 1px solid var(--border-accent); border-radius: 4px; flex-shrink: 0; }
.recent-ops-link:hover { background: var(--accent-dim); }
.badge-default { background: rgba(107, 114, 128, 0.08); color: var(--text-secondary); border-color: rgba(107, 114, 128, 0.15); }
.badge-warning { background: rgba(251, 191, 36, 0.08); color: var(--warning); border-color: rgba(251, 191, 36, 0.2); }
.badge-info { background: var(--accent-dim); color: var(--accent); border-color: var(--border-accent); }
.badge-danger { background: rgba(248, 113, 113, 0.08); color: var(--danger); border-color: rgba(248, 113, 113, 0.2); }

/* ============================================
   Phase 2 — Servers list + filters
   ============================================ */
.servers-toolbar { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 14px; align-items: center; }
.region-pill {
    display: inline-block;
    margin-left: 6px;
    padding: 1px 6px;
    font-size: 10px;
    font-family: var(--font-display);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--text-tertiary);
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid var(--border);
    border-radius: 5px;
}
.template-version { display: inline-block; margin-left: 4px; font-family: var(--font-mono); font-size: 10.5px; color: var(--text-muted); }
.tenant-pill {
    display: inline-block;
    padding: 2px 8px;
    font-family: var(--font-mono);
    font-size: 11px;
    line-height: 1.2;
    color: var(--accent);
    background: rgba(0, 224, 255, 0.06);
    border: 1px solid rgba(0, 224, 255, 0.18);
    border-radius: 6px;
    text-decoration: none;
}
.tenant-pill:hover { background: rgba(0, 224, 255, 0.12); }
.info-banner {
    margin: 12px 0 18px;
    padding: 10px 14px;
    background: rgba(0, 224, 255, 0.04);
    border: 1px solid rgba(0, 224, 255, 0.16);
    border-left: 3px solid var(--accent);
    border-radius: 4px;
    color: var(--text-secondary);
    font-size: 13px;
    line-height: 1.5;
}
.info-banner code { font-family: var(--font-mono); font-size: 12px; color: var(--accent); background: rgba(0, 0, 0, 0.25); padding: 1px 5px; border-radius: 3px; }
.sidebar-tenant-switcher { display: flex; flex-direction: column; gap: 4px; padding: 8px 14px; border-top: 1px solid var(--border); }
.sidebar-tenant-switcher label { font-family: var(--font-display); font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.6px; color: var(--text-tertiary); }
.sidebar-tenant-switcher select {
    appearance: none;
    background: rgba(0, 0, 0, 0.4);
    color: var(--text-secondary);
    border: 1px solid var(--border);
    border-radius: 3px;
    padding: 4px 8px;
    font-family: var(--font-mono);
    font-size: 12px;
    cursor: pointer;
}
.sidebar-tenant-switcher select:hover { border-color: var(--accent); color: var(--accent); }
.hash-short { font-family: var(--font-mono); font-size: 11px; color: var(--text-tertiary); background: var(--bg-elevated); padding: 1px 6px; border-radius: 3px; }

/* Admin table — canonical structure for all admin list pages. */
.admin-table { width: 100%; border-collapse: collapse; font-size: 13px; background: transparent; }
.admin-table thead { position: sticky; top: 0; z-index: 2; }
.admin-table th { text-align: left; padding: var(--cell-pad-y) var(--cell-pad-x); background: var(--bg-panel-solid); color: var(--text-tertiary); font-family: var(--font-display); font-weight: 600; font-size: 11px; text-transform: uppercase; letter-spacing: 0.5px; border-bottom: 1px solid var(--border-hover); }
.admin-table td { padding: var(--cell-pad-y) var(--cell-pad-x); border-bottom: 1px solid var(--border); vertical-align: middle; }
.admin-table tr:hover { background: var(--bg-hover); }
.admin-table .col-actions { text-align: right; white-space: nowrap; }
.admin-table .col-actions .btn,
.admin-table .col-actions .btn-xs { margin-left: 4px; }
.admin-table .col-select { width: 36px; text-align: center; }
@media (max-width: 800px) {
    .admin-table .col-hide-sm { display: none; }
}

/* --- Loading skeleton + error state (shared list-page states) --- */
.loading-skeleton {
    color: var(--text-muted);
    padding: 24px 12px;
    text-align: center;
    font-size: 13px;
    background: var(--bg-panel);
    border: 1px dashed var(--border);
    border-radius: 4px;
    animation: loading-skeleton-pulse 1.4s ease-in-out infinite;
}
@keyframes loading-skeleton-pulse { 0%, 100% { opacity: 0.7; } 50% { opacity: 1; } }
.error-state {
    background: rgba(248, 113, 113, 0.08);
    border: 1px solid rgba(248, 113, 113, 0.25);
    color: var(--danger);
    padding: 12px 16px;
    border-radius: 4px;
    font-size: 13px;
    margin: 8px 0 16px;
}

/* ============================================
   Phase 6 — Alerts drawer filter-row shorthand
   (List.razor uses inline styles; we scope a fallback here.)
   ============================================ */
.filter-row { display: flex; flex-wrap: wrap; gap: 12px; align-items: flex-end; margin-bottom: 16px; }
.filter-row .form-group { margin-bottom: 0; }
.pub-loading { padding: 24px 12px; text-align: center; color: var(--text-muted); font-size: 13px; }
.pub-loading .spinner { margin: 0 auto 8px; }

/* ============================================
   Phase 6 — TabStrip (Templates sub-routes, Server detail tabs)
   Minor override for keyboard focus visibility.
   ============================================ */
.tab-btn:focus { outline: 2px solid var(--border-accent-strong); outline-offset: -2px; }

/* ============================================
   Phase 3 — Seasons panels
   ============================================ */
.active-panel-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 16px;
    align-items: start;
}
@media (max-width: 900px) { .active-panel-grid { grid-template-columns: 1fr; } }

/* Key-value definition list used across season panels + overview tabs. */
.kv-list {
    display: grid;
    grid-template-columns: minmax(120px, auto) 1fr;
    gap: 4px 14px;
    margin: 4px 0 12px;
}
.kv-list dt { color: var(--text-muted); font-size: 12px; text-transform: uppercase; letter-spacing: 0.4px; }
.kv-list dd { margin: 0; font-size: 13px; color: var(--text-primary); }

/* Generic note box (inside a form-panel). */
.note {
    padding: 10px 14px;
    border-radius: 4px;
    font-size: 12.5px;
    line-height: 1.5;
    border: 1px solid transparent;
    color: var(--text-secondary);
    background: rgba(255, 255, 255, 0.02);
    margin: 8px 0;
}
.note strong { color: var(--text-primary); display: block; margin-bottom: 4px; }
.note.info { background: var(--accent-dim); border-color: var(--border-accent); color: var(--text-primary); }
.note.info strong { color: var(--accent); }
.note.warning { background: rgba(251, 191, 36, 0.06); border-color: rgba(251, 191, 36, 0.22); }
.note.warning strong { color: var(--warning); }
.note ul { margin: 4px 0 0 18px; padding: 0; }
.note li { margin: 2px 0; }

/* Track-pool chip editor. */
.track-pool-chips { display: flex; flex-wrap: wrap; gap: 6px; margin: 8px 0; min-height: 32px; }
.item-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 4px 4px 10px;
    border-radius: 9px;
    background: var(--bg-elevated);
    border: 1px solid var(--border);
    font-size: 12px;
    color: var(--text-primary);
}
.item-chip code { background: transparent; padding: 0; color: inherit; font-size: 12px; }
.item-chip.chip-draining { opacity: 0.65; border-style: dashed; }

/* Wave 3.1 Item 13 — BanForm chip strip (recent reporters + live-match
   players). The button-shaped chips reuse the existing .item-chip rule above;
   the strip just stacks two horizontally-scrolling rows above the SteamId input. */
.ban-chip-strip { display: flex; flex-direction: column; gap: 6px; margin-bottom: 12px; }
.ban-chip-row { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px; }
.ban-chip-label { white-space: nowrap; }
.chip-sid-suffix { color: var(--text-muted); font-size: 11px; font-family: var(--font-mono); }
.item-chip.chip-live { border-color: rgba(0, 224, 255, 0.4); background: rgba(0, 224, 255, 0.06); }
.item-chip:hover { background: rgba(0, 224, 255, 0.1); cursor: pointer; }

/* Wave 3.1 Item 16 — ProvisionWizard batch-error rollup. Compact list under
   a .form-panel.error so the existing red border carries through. */
.provision-batch-error { margin-top: 12px; }
.provision-batch-error-list { margin: 6px 0; padding-left: 18px; }
.provision-batch-err-count { color: var(--text-muted); font-family: var(--font-mono); margin-right: 6px; }

/* Wave 3.1 Item 4 — LiveOps SSE state chip. Sits beside the page title and
   reflects the SSE bridge state (connected / silent / fallback). The
   warn variant uses the same amber the existing alert pills use so the
   admin's color expectation stays consistent. */
.live-ops-header-row { display: flex; align-items: baseline; gap: 0.75rem; flex-wrap: wrap; }
.live-ops-sse-chip { font-size: 12px; padding: 2px 10px; border-radius: 7px; font-family: var(--font-mono); }
.live-ops-sse-chip-ok { background: rgba(74, 222, 128, 0.12); color: #4ade80; border: 1px solid rgba(74, 222, 128, 0.4); }
.live-ops-sse-chip-warn { background: rgba(251, 191, 36, 0.12); color: #fbbf24; border: 1px solid rgba(251, 191, 36, 0.4); }

/* Wave 3.1 Item 5 — alert drawer ack row places FormField + button side by
   side instead of FormField's default vertical stack. */
.ack-row { display: flex; flex-wrap: wrap; align-items: end; gap: 8px; }

/* Wave 3.1 Item 9 — Disputes Reject preview kv-grid spacing. */
.dispute-reject-context { margin-bottom: 0.5rem; }

/* R16 (2026-06-22) — relocated from Disputes.razor's inline <style> block
   (house convention: admin styling lives centrally). Verbatim move; no rule
   changes. */
.dispute-reason { max-width: 300px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dispute-status { padding: 2px 8px; border-radius: 4px; font-size: 0.8rem; font-weight: 600; line-height: 1.15; }
.dispute-status-open { background: rgba(251,191,36,0.15); color: #fbbf24; }
.dispute-status-accepted { background: rgba(52,211,153,0.15); color: #34d399; }
.dispute-status-rejected { background: rgba(248,113,113,0.15); color: #f87171; }
.dispute-status-reviewed { background: rgba(0,224,255,0.15); color: #00e0ff; }
.dispute-resolved-info { font-size: 0.75rem; color: #888; }
.dispute-notes-row td { background: rgba(255,255,255,0.02); font-size: 0.85rem; color: #999; }
.btn-sm { padding: 2px 10px; font-size: 0.8rem; margin-right: 4px; }
.dispute-id-link { color: var(--text-primary, #fff); text-decoration: none; cursor: pointer; }
.dispute-preview { display: flex; flex-direction: column; gap: 10px; }
.dispute-preview-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.dispute-preview-table th, .dispute-preview-table td { text-align: left; padding: 6px 8px; border-bottom: 1px solid rgba(255,255,255,0.08); }
.dispute-preview-warn { color: #fbbf24; font-size: 0.85rem; margin: 0.25rem 0; }
.dispute-preset-chips { margin-top: 8px; }
.chip-row { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 4px; }
.chip { background: rgba(255,255,255,0.05); color: #ddd; border: 1px solid rgba(255,255,255,0.1); padding: 4px 10px; font-size: 12px; border-radius: 9px; cursor: pointer; }
.chip:hover { background: rgba(0,224,255,0.1); }
.chip-active { background: rgba(0,224,255,0.2); border-color: rgba(0,224,255,0.5); color: #00e0ff; }
.form-label-req { display: block; margin-top: 8px; }
.dispute-no-match { color: #888; font-style: italic; font-size: 0.85rem; }

/* Wave 3.1 Item 24 — IncidentEditor inline component description help-text. */
.incident-component-help { display: block; margin-top: 4px; color: var(--text-muted); font-size: 12px; }

/* Wave 3.1 Item 21 — SeasonFailedPanel inline audit log details. */
.season-failed-audit { margin-top: 12px; }
.season-failed-audit summary { cursor: pointer; color: var(--text-muted); font-size: 13px; }
.season-failed-audit-list { margin: 6px 0 0 0; padding-left: 18px; font-size: 12px; }
.season-failed-audit-list li { margin: 2px 0; font-family: var(--font-mono); color: var(--text-muted); }
.chip-badge {
    font-family: var(--font-display);
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    padding: 1px 6px;
    border-radius: 5px;
    background: rgba(251, 191, 36, 0.15);
    color: var(--warning);
}
.chip-x {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px; height: 18px;
    border-radius: 50%;
    background: transparent;
    border: none;
    color: var(--text-muted);
    cursor: pointer;
    font-size: 14px;
    line-height: 1;
    padding: 0;
    transition: background 0.12s ease, color 0.12s ease;
}
.chip-x:hover { background: rgba(248, 113, 113, 0.15); color: var(--danger); }
.chip-layout { color: var(--text-muted); font-size: 11px; }

/* Track-pool picker — search-filtered, track-grouped list (Phase 3 hot-fix). */
.track-picker-list {
    margin-top: 8px;
    border: 1px solid var(--border);
    border-radius: 4px;
    background: var(--bg-elevated);
    max-height: 360px;
    overflow-y: auto;
}
.track-picker-group {
    border-bottom: 1px solid var(--border);
}
.track-picker-group:last-child { border-bottom: none; }
.track-picker-track-row {
    display: flex;
    align-items: center;
    padding: 8px 12px;
    background: var(--bg-base);
    border-bottom: 1px solid var(--border);
    font-family: var(--font-mono);
    font-size: 12px;
    color: var(--text-primary);
}
.track-picker-track-row code {
    background: transparent;
    padding: 0;
    color: inherit;
}
.track-picker-layouts {
    list-style: none;
    margin: 0;
    padding: 0;
}
.track-picker-layout-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 6px 12px 6px 24px;
    font-size: 12px;
    color: var(--text-primary);
}
.track-picker-layout-row + .track-picker-layout-row {
    border-top: 1px solid var(--border-subtle, var(--border));
}

/* Activation checklist (SeasonActivatingPanel). */
.activation-checklist {
    list-style: none;
    margin: 8px 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.activation-checklist li {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 10px;
    border-radius: 4px;
    background: rgba(255, 255, 255, 0.02);
    font-size: 13px;
}
.activation-checklist li.ok { background: rgba(52, 211, 153, 0.05); }
.activation-checklist li.err { background: rgba(248, 113, 113, 0.06); }
.activation-checklist li.queued { opacity: 0.65; }
.activation-checklist .mark { width: 18px; text-align: center; font-weight: 700; flex-shrink: 0; }
.activation-checklist li.ok .mark { color: var(--success); }
.activation-checklist li.err .mark { color: var(--danger); }
.activation-checklist .err-text { color: var(--danger); font-size: 12px; }

/* ============================================
   Phase 4 — Tracks list + layout detail
   ============================================ */
.layout-sep { color: var(--text-muted); margin: 0 4px; font-weight: 400; }
.tab-body { padding-top: 12px; }
.edit-section {
    margin-bottom: 20px;
    padding-bottom: 18px;
    border-bottom: 1px solid var(--border);
}
.edit-section:last-child { border-bottom: none; padding-bottom: 0; }
.edit-section h3 { margin-bottom: 8px; }

/* R11 (2026-06-22) — DraftEditor advanced sections collapse into <details>
   so checkpoints + grid are the default view. The <summary> wraps an <h4>;
   strip the default disclosure-triangle list styling and render our own
   caret so the heading reads as a clickable section toggle. */
details.tc-advanced-section { margin: 12px 0; }
details.tc-advanced-section > summary {
    cursor: pointer;
    list-style: none;
    display: flex;
    align-items: center;
    gap: 6px;
    user-select: none;
}
details.tc-advanced-section > summary::-webkit-details-marker { display: none; }
details.tc-advanced-section > summary::before {
    content: "\25B8"; /* right-pointing caret */
    color: var(--text-muted);
    font-size: 11px;
    transition: transform 0.12s ease;
}
details.tc-advanced-section[open] > summary::before { transform: rotate(90deg); }
details.tc-advanced-section > summary h4 { margin: 0; display: inline; }
.tc-test-teleport-section { margin-top: 16px; }
.empty-state-inline {
    padding: 12px 14px;
    font-size: 13px;
    color: var(--text-muted);
    background: rgba(255, 255, 255, 0.02);
    border: 1px dashed var(--border);
    border-radius: 4px;
    font-style: italic;
}
.host-content-list { list-style: none; padding: 0; margin: 6px 0 0; display: flex; flex-direction: column; gap: 4px; }
.host-content-list li { display: flex; align-items: center; gap: 10px; padding: 6px 10px; background: rgba(255,255,255,0.02); border-radius: 4px; font-size: 13px; }
.host-content-name { color: var(--text-primary); font-weight: 500; }
.host-content-assumed { color: var(--text-muted); font-size: 11px; font-style: italic; }
.dim { color: var(--text-muted); }
.mono { font-family: var(--font-mono); font-size: 12px; }

/* PromotionAckPanel. */
.ack-list { list-style: none; margin: 6px 0 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
.ack-list li { display: grid; grid-template-columns: 24px 1fr auto; align-items: center; gap: 8px; padding: 5px 8px; border-bottom: 1px solid var(--border); font-size: 12.5px; }
.ack-list li:last-child { border-bottom: none; }
.ack-symbol { text-align: center; font-weight: 700; }
.ack-name { color: var(--text-primary); font-family: var(--font-mono); font-size: 12px; }
.ack-detail { color: var(--text-muted); font-size: 11.5px; }

/* DiffModal fallback (if the page uses raw modal-backdrop/modal-header/modal-close classes). */
.modal-backdrop { position: fixed; inset: 0; background: rgba(0,0,0,0.7); z-index: 999; display: flex; align-items: center; justify-content: center; backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px); }
.modal-backdrop > .modal { max-width: 720px; width: 92%; }
.modal-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; padding-bottom: 10px; border-bottom: 1px solid var(--border); gap: 8px; }
.modal-header h3 { margin: 0; }
.modal-body { max-height: 60vh; overflow-y: auto; }
.modal-footer { display: flex; justify-content: flex-end; gap: 8px; margin-top: 14px; padding-top: 10px; border-top: 1px solid var(--border); }
.modal-close { background: transparent; border: none; color: var(--text-muted); cursor: pointer; font-size: 22px; line-height: 1; padding: 0 4px; transition: color 0.12s ease; }
.modal-close:hover { color: var(--text-primary); }

/* Lap filter bar (Tracks > Laps tab). */
.lap-filter-bar { display: flex; flex-wrap: wrap; gap: 12px; align-items: flex-end; margin-bottom: 12px; }
.lap-filter-group { display: flex; flex-direction: column; gap: 2px; }
.lap-filter-group label { font-size: 11px; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.4px; }

/* Lap-detail sector table — the Total row + sum-mismatch flag (Wave S, 2026-06-16).
   Global (not scoped) so they reach LapPanelSectorBreakdown, a child component. */
.sector-total td { border-top: 1px solid rgba(255, 255, 255, 0.12); font-weight: 600; }
.sector-mismatch { color: var(--danger, #ff6b6b); margin-left: 6px; }

/* ============================================
   Phase 2 — Server detail tabs
   ============================================ */
.overview-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
    gap: 16px;
    align-items: start;
}
.config-diff {
    background: var(--bg-input);
    border: 1px solid var(--border);
    border-radius: 4px;
    padding: 10px;
    font-family: var(--font-mono);
    font-size: 12px;
    line-height: 1.5;
    max-height: 50vh;
    overflow: auto;
    white-space: pre;
    color: var(--text-primary);
}
.rollback-preview, .deploy-preview {
    list-style: none;
    padding: 8px 10px;
    margin: 6px 0;
    background: var(--bg-elevated);
    border: 1px solid var(--border);
    border-radius: 4px;
    font-size: 12.5px;
}
.rollback-preview li, .deploy-preview li { padding: 2px 0; color: var(--text-secondary); }

/* RegenerateConfigsDropdown. */
.regen-menu {
    list-style: none;
    padding: 6px 0;
    margin: 0;
    background: var(--bg-panel-solid);
    border: 1px solid var(--border);
    border-radius: 4px;
    box-shadow: 0 4px 16px rgba(0,0,0,0.4);
    min-width: 220px;
}
.regen-menu li { padding: 6px 14px; cursor: pointer; font-size: 12.5px; color: var(--text-secondary); transition: background 0.1s ease; }
.regen-menu li:hover { background: var(--bg-hover); color: var(--text-primary); }
.regen-menu-divider { font-family: var(--font-display); font-size: 10px; text-transform: uppercase; color: var(--text-muted); letter-spacing: 0.5px; padding: 8px 14px 2px !important; pointer-events: none !important; border-top: 1px solid var(--border); margin-top: 4px; }
.regen-menu-divider:first-child { margin-top: 0; border-top: none; padding-top: 2px !important; }
.regen-menu-divider:hover { background: transparent !important; color: var(--text-muted) !important; }

/* Wave 6 Task 6.8 — transparent click-outside backdrop. Sits BELOW the menu
   (z-index 99 vs 1000) so clicks on the menu itself aren't intercepted;
   clicks elsewhere on the page hit the backdrop and close the dropdown. */
.regen-dropdown-backdrop {
    position: fixed;
    inset: 0;
    z-index: 99;
    background: transparent;
    cursor: default;
}
.regen-menu { z-index: 1000; }

.change-track-flow { background: rgba(0, 224, 255, 0.03); border: 1px solid var(--border-accent); border-radius: 4px; padding: 10px 12px; font-size: 12.5px; color: var(--text-secondary); margin-top: 8px; }

/* ============================================
   Phase 8 — LiveOps (extra) — responsive sizing
   ============================================ */
@media (max-width: 640px) {
    .fleet-stats-row { grid-template-columns: repeat(2, 1fr); }
    .live-card-racers { grid-template-columns: 1fr; }
    .live-vs { text-align: center; }
    .live-racer.right { text-align: left; align-items: flex-start; }
}

/* ============================================
   Phase 2 — Server detail overview tab (extra)
   ============================================ */
.overview-card-connection,
.overview-card-template,
.overview-card-readiness,
.overview-card-controls { min-height: 100%; }
.host-line { color: var(--text-secondary); font-size: 12px; margin-top: 6px; }
.hash-line { color: var(--text-tertiary); font-size: 12px; margin-top: 4px; }
.region-tag { color: var(--text-muted); font-size: 11px; }
.live-counts { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.live-chip { display: inline-block; padding: 2px 8px; border-radius: 6px; font-size: 11px; background: var(--bg-elevated); border: 1px solid var(--border); color: var(--text-secondary); }
.modal-summary { font-size: 13px; color: var(--text-secondary); margin: 0; }

/* Responsive scroll wrapper for wide admin tables (AuditLog, Alerts, Bans). */
.table-responsive { overflow-x: auto; width: 100%; -webkit-overflow-scrolling: touch; }
.table-responsive > table { min-width: 640px; }

/* .warn class (ProvisionWizard + similar). */
p.warn, .warn { color: var(--warning); }

/* "View public site" escape-hatch under the sidebar brand. Subdued so the
   admin nav stays the visual anchor; an admin who needs to hop to the
   public site can find it without it shouting. */
.sidebar-view-site {
    display: block;
    padding: 0 12px 14px;
    font-family: var(--font-display);
    font-size: 11px;
    font-weight: 500;
    color: var(--text-tertiary);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    border-radius: 0;
    text-decoration: none;
    transition: color 0.12s ease;
}
.sidebar-view-site:hover {
    background: transparent;
    color: var(--accent);
}

/* "Signed in as <name>" identity row above Logout. Tertiary text — present
   for orientation, not nav. Sits in the sidebar-spacer flow. */
.sidebar-identity {
    color: var(--text-tertiary);
    font-family: var(--font-display);
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    padding: 8px 12px 0;
    border-top: 1px solid var(--border);
}
/* When identity is present, suppress the logout's own divider — the identity
   row already provides one and we don't want a stacked double-border. */
.sidebar-identity + .sidebar-logout {
    border-top: none;
    padding-top: 6px;
}

/* ============================================
   Phase A — Admin shared primitives (1.1–1.7)
   ============================================ */

/* AdminDataTable */
.admin-data-table table { width: 100%; border-collapse: collapse; }
/* Density pass (2026-06-08): canonical AdminDataTable cells on --cell-pad-y/x. */
.admin-data-table th { padding: var(--cell-pad-y) var(--cell-pad-x); font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; color: var(--text-tertiary); border-bottom: 1px solid var(--border); }
.admin-data-table td { padding: var(--cell-pad-y) var(--cell-pad-x); font-size: 13px; color: var(--text-secondary); border-bottom: 1px solid var(--border); }
/* Wave 7 F22 — opt-in cell ellipsis class. Apply to wide columns
   (descriptions, paths) on CarLists / Tracks / similar tables so a
   long string doesn't reflow the row. Sets max-width via the column's
   Width parameter; the rule itself just enables overflow + ellipsis. */
.admin-data-table td.cell-truncate {
    max-width: 0; /* lets the table layout shrink to allotted width */
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* Wave 7 Refactor 7.4 — split the row-hover affordance into two arms:
   the background hover applies to every table for visual feedback, but
   `cursor: pointer` only kicks in when AdminDataTable applied the
   .has-row-click marker (i.e. the page bound an OnRowClick handler).
   Catches the Disputes / static-list tables that were rendering a fake
   pointer cursor on rows that did nothing on click. */
.admin-data-table tbody tr:hover { background: var(--bg-hover); }
.admin-data-table.has-row-click tbody tr:hover { cursor: pointer; }
.admin-data-table tbody tr.selected { background: rgba(0, 224, 255, 0.05); }
.admin-data-table .sort-button { background: none; border: none; color: inherit; cursor: pointer; font-size: inherit; font-family: inherit; font-weight: inherit; text-transform: inherit; letter-spacing: inherit; padding: 0; }
.admin-data-table .sort-button:hover { color: var(--text-primary); }
.admin-data-table .pagination { display: flex; align-items: center; gap: 12px; padding: 12px 0; font-size: 13px; color: var(--text-secondary); }

/* AdminFilterBar */
/* Density pass (2026-06-08): filter bar padding/margin trimmed. */
.admin-filter-bar { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 12px; padding: 8px 0; margin-bottom: 12px; }
.admin-filter-bar .filter-field { display: flex; flex-direction: column; gap: 4px; }
.admin-filter-bar .filter-field label { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; color: var(--text-tertiary); }
.admin-filter-bar .filter-field input,
.admin-filter-bar .filter-field select { background: var(--bg-input); border: 1px solid var(--border); color: var(--text-primary); padding: 6px 10px; border-radius: 4px; font-size: 13px; }
.admin-filter-bar .clear-filters { background: transparent; border: 1px solid var(--border); color: var(--text-secondary); padding: 6px 12px; border-radius: 4px; cursor: pointer; font-size: 13px; align-self: flex-end; }
.admin-filter-bar .clear-filters:hover { color: var(--text-primary); border-color: var(--text-secondary); }

/* AdminDrawer */
.admin-drawer-backdrop { position: fixed; inset: 0; background: rgba(0,0,0,0.5); z-index: 200; }
.admin-drawer {
    position: fixed; top: 0; right: 0; bottom: 0;
    background: var(--bg-panel-solid); border-left: 1px solid var(--border);
    z-index: 201; display: flex; flex-direction: column;
    transform: translateX(100%); transition: transform 200ms ease-out;
    overflow-y: auto; box-shadow: -4px 0 16px rgba(0,0,0,0.3);
}
.admin-drawer.open { transform: translateX(0); }
.admin-drawer-header { display: flex; align-items: center; justify-content: space-between; padding: 16px 20px; border-bottom: 1px solid var(--border); }
.admin-drawer-header h2 { margin: 0; font-size: 16px; font-family: var(--font-display); }
.admin-drawer-header .close { background: transparent; border: none; color: var(--text-secondary); font-size: 24px; cursor: pointer; }
.admin-drawer-content { padding: 20px; flex: 1; }

/* AdminTabs */
/* Density pass (2026-06-08): tab bar mb 20 -> 12, button padding 8/14 -> 7/14. */
/* overflow-x (2026-07-09 mobile report): 8+ tab labels are wider than a phone — the strip must
   scroll INSIDE its own container (house rule), never widen the page sideways. */
.admin-tabs-bar { display: flex; gap: 4px; border-bottom: 1px solid var(--border); margin-bottom: 12px; overflow-x: auto; scrollbar-width: thin; }
.admin-tabs-bar button { white-space: nowrap; flex-shrink: 0; }
.admin-tabs-bar button {
    padding: 7px 14px; background: transparent; border: none;
    color: var(--text-secondary); cursor: pointer;
    border-bottom: 2px solid transparent;
    font-family: var(--font-display); font-size: 13px; text-transform: uppercase; letter-spacing: 0.5px;
}
.admin-tabs-bar button.active { color: var(--accent); border-bottom-color: var(--accent); }
.admin-tabs-bar button:hover { color: var(--text-primary); }
/* WCAG 2.4.7 — keyboard focus ring (AdminTabs had no visible focus state). */
.admin-tabs-bar button:focus-visible { outline: 2px solid var(--border-accent-strong); outline-offset: -2px; }
.admin-tabs-bar .dirty-dot { display: inline-block; width: 6px; height: 6px; border-radius: 50%; background: var(--warning); margin-left: 6px; vertical-align: middle; }

/* FormField */
/* Density pass (2026-06-08): margin-bottom 14 -> 0 — the parent .form-panel
   flex gap (--panel-inner-gap) owns the vertical rhythm now, so a field inside
   a panel no longer double-spaces. */
.form-field { display: flex; flex-direction: column; gap: 4px; margin-bottom: 0; }
.form-field label { font-family: var(--font-display); font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: var(--letter-spacing-normal); color: var(--text-secondary); }
.form-field .required-asterisk { color: var(--danger); margin-left: 2px; }
/* font-size 13px + width:100% — these controls previously had NO font-size set
   and rendered at the browser ~16px default, larger than every sibling input. */
.form-field input,
.form-field select,
.form-field textarea {
    background: var(--bg-input); border: 1px solid var(--border); color: var(--text-primary);
    padding: 8px 12px; border-radius: 4px; font-family: var(--font-body);
    font-size: 13px; width: 100%;
}
.form-field input:focus,
.form-field select:focus,
.form-field textarea:focus { outline: none; border-color: var(--border-accent-strong); box-shadow: 0 0 0 1px var(--border-accent); }
.form-field.has-error input,
.form-field.has-error select,
.form-field.has-error textarea { border-color: var(--danger); }
.form-field .help-text { font-size: 12px; color: var(--text-muted); }
.form-field .form-error { font-size: 12px; color: var(--danger); }
/* Toggle-switch checkbox field (redesign 2026-06-21). The FormField checkbox
   branch emits a [switch][meta] row — a sliding HUD-style switch beside a
   label with help stacked under it. Replaces the old bare native checkbox
   (which also had a layout bug: missing display:flex + .form-panel label's
   display:flex leaked in, dropping the label onto its own line). */
.form-field-checkbox { display: flex; flex-direction: row; align-items: flex-start; gap: 12px; margin-bottom: 0; }
.form-field-checkbox.disabled { opacity: 0.55; }
.form-field-checkbox-meta { display: flex; flex-direction: column; gap: 3px; }
.form-field-checkbox-meta label { text-transform: none; letter-spacing: normal; font-weight: 500; font-size: 14px; color: var(--text-secondary); cursor: pointer; font-family: var(--font-body); }
/* The switch is a SPAN (not a <label>) so .form-panel label{display:flex} can't
   hijack its geometry; the transparent input fills it and owns the click. */
.kott-switch { position: relative; display: inline-block; width: 42px; height: 23px; flex-shrink: 0; margin-top: 1px; }
.kott-switch input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; z-index: 2; }
.kott-switch-track { position: absolute; inset: 0; border-radius: var(--radius-pill); background: var(--bg-input); border: 1px solid var(--border-hover); transition: background var(--dur-slow) var(--ease-standard), border-color var(--dur-slow) var(--ease-standard); }
.kott-switch-knob { position: absolute; top: 3px; left: 3px; width: 15px; height: 15px; border-radius: 50%; background: var(--text-tertiary); transition: transform var(--dur-slow) var(--ease-standard), background var(--dur-slow) var(--ease-standard); }
.kott-switch input:checked ~ .kott-switch-track { background: var(--accent-dim); border-color: var(--accent); box-shadow: inset 0 0 10px var(--accent-glow); }
.kott-switch input:checked ~ .kott-switch-knob { transform: translateX(19px); background: var(--accent); box-shadow: var(--glow-sm); }
.kott-switch input:focus-visible ~ .kott-switch-track { box-shadow: 0 0 0 2px var(--accent-dim); }
.form-field-checkbox.disabled .kott-switch input { cursor: not-allowed; }

/* Number inputs as instrument readouts (redesign) — kill native steppers,
   render the value in mono so it reads like telemetry. */
.form-field input[type="number"] { -moz-appearance: textfield; font-family: var(--font-mono); font-weight: 500; }
.form-field input[type="number"]::-webkit-outer-spin-button,
.form-field input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
/* Optional trailing unit chip (FormField Unit="…"). */
.form-field-input-wrap { display: flex; align-items: stretch; background: var(--bg-input); border: 1px solid var(--border); border-radius: var(--radius-6); transition: border-color var(--dur-fast) var(--ease-standard); }
.form-field-input-wrap:focus-within { border-color: var(--border-accent-strong); box-shadow: var(--ring-accent); }
.form-field-input-wrap input { flex: 1; width: 100%; border: none !important; background: transparent !important; box-shadow: none !important; }
.form-field-input-wrap input:focus { outline: none; }
.form-field-unit { font-family: var(--font-mono); font-size: var(--text-sm); color: var(--text-muted); padding: 0 12px; border-left: 1px solid var(--border); display: flex; align-items: center; }
/* Width caps (FormField Size="sm|md|lg") so a short value isn't stranded in a
   full-width box — direct-child selectors so a unit-wrap's inner input keeps its
   flex:1 and only the wrap is capped. Textareas stay full-width. */
.form-field-sm > input, .form-field-sm > select, .form-field-sm > .form-field-input-wrap { max-width: 130px; }
.form-field-md > input, .form-field-md > select, .form-field-md > .form-field-input-wrap { max-width: 220px; }
.form-field-lg > input, .form-field-lg > select, .form-field-lg > .form-field-input-wrap { max-width: 380px; }
/* Locked (disabled) fields read as locked — e.g. weather fields when "Use
   overrides" is off. Dim the wrap for unit fields, the input for plain ones. */
.form-field > input:disabled, .form-field > select:disabled, .form-field > textarea:disabled { opacity: 0.5; cursor: not-allowed; }
.form-field-input-wrap:has(input:disabled) { opacity: 0.5; }

/* Custom select chevron (redesign) — replaces the dated native dropdown arrow. */
.form-field select {
    -webkit-appearance: none; -moz-appearance: none; appearance: none;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'><path d='M2.5 4.5L6 8l3.5-3.5' fill='none' stroke='%237a8493' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/></svg>");
    background-repeat: no-repeat; background-position: right 12px center; padding-right: 34px;
}
/* Horizontal label-beside-input variant (label left, control fills the rest). */
.form-field.horizontal { flex-direction: row; align-items: center; gap: 12px; }
.form-field.horizontal > label { flex: 0 0 auto; min-width: 140px; margin: 0; }
.form-field.horizontal input,
.form-field.horizontal select,
.form-field.horizontal textarea { flex: 1; width: auto; }

/* AdminConfirm extras */
.ack-checkbox { display: flex; align-items: center; gap: 8px; margin: 12px 0; font-size: 13px; }
.inline-confirm { background: var(--bg-elevated); border: 1px solid var(--border); padding: 14px; border-radius: 4px; margin: 12px 0; }
.inline-confirm.danger { border-left: 3px solid var(--danger); }
.inline-actions { display: flex; gap: 10px; margin-top: 10px; }

/* Type-to-confirm friction block (AdminConfirm.razor — modal + inline).
   Safety-critical: this is the last gate before a destructive op. Render it as
   a clearly danger-tinted callout so the operator registers the friction. */
.typed-confirm {
    background: var(--danger-dim);
    border: 1px solid var(--danger-border);
    border-radius: 4px;
    padding: 12px;
    margin: 12px 0 0;
}
.typed-confirm-prompt {
    margin: 0 0 8px;
    font-size: 13px;
    color: var(--text-secondary);
}
/* The phrase the operator must retype reads as mono so it's unambiguous. */
.typed-confirm-prompt code {
    font-family: var(--font-mono);
    color: var(--danger);
    background: rgba(248, 113, 113, 0.1);
}
.typed-confirm input {
    width: 100%;
    font-family: var(--font-mono);
}

/* Bulk-action blast-radius preview (BulkActionBar.razor — the PreviewContent
   fragment passed into AdminConfirm). Tells the operator exactly how many /
   which rows the destructive bulk op will touch. */
.bulk-blast-radius {
    background: var(--danger-dim);
    border: 1px solid var(--danger-border);
    border-left: 3px solid var(--danger);
    border-radius: 4px;
    padding: 10px 12px;
    margin: 8px 0;
    font-size: 13px;
    color: var(--text-secondary);
    line-height: 1.5;
}

/* EmptyState (primitive — supplements the existing .empty-state page-level style) */
.empty-state .empty-icon { font-size: 36px; opacity: 0.5; margin-bottom: 12px; }

/* LoadingState / skeleton */
.loading-state { padding: 8px 0; }
.skeleton-row {
    height: 32px;
    background: linear-gradient(90deg, rgba(255,255,255,0.04) 0%, rgba(255,255,255,0.08) 50%, rgba(255,255,255,0.04) 100%);
    background-size: 200% 100%;
    border-radius: 4px; margin-bottom: 6px;
    animation: skeleton-shimmer 1.4s infinite linear;
}
@keyframes skeleton-shimmer {
    0% { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}
.spinner-inline { color: var(--text-tertiary); font-size: 13px; padding: 12px 0; }

/* AsyncButton in-flight spinner. Uses currentColor + a transparent top so it
   reads on any .btn variant (neutral, primary's dark text, danger, …) without a
   per-variant override. Sits inline before the busy label via the .btn flex gap. */
.btn-spinner {
    display: inline-block;
    width: 12px; height: 12px;
    border: 2px solid currentColor;
    border-top-color: transparent;
    border-radius: 50%;
    animation: spin 0.6s linear infinite;
    opacity: 0.85;
    flex: 0 0 auto;
}

/* BulkActionBar */
.bulk-action-bar { display: flex; align-items: center; gap: 12px; background: var(--bg-elevated); border: 1px solid var(--border); padding: 10px 16px; border-radius: 4px; margin: 12px 0; }
.bulk-action-bar .selected-count { font-weight: 600; color: var(--accent); }
.btn-link { background: transparent; border: none; color: var(--text-secondary); cursor: pointer; text-decoration: underline; font-size: 13px; }

/* ============================================
   Wave 3 IA reorg (2026-05-05)
   - Sidebar notification badges
   - Mobile hamburger toggle (CSS-only :checked hack)
   - Cmd-K AdminSearchPalette overlay
   - /infra + /distribution discovery card grid
   ============================================ */

/* Sidebar badge — small cyan pill rendered next to the NavLink label
   when a count > 0 (Disputes / Alerts / Feedback / Erasures). */
.sidebar-badge {
    display: inline-block;
    margin-left: 8px;
    padding: 1px 6px;
    border-radius: 9px;
    background: var(--accent);
    color: #000;
    font-family: var(--font-mono);
    font-size: 10px;
    font-weight: 700;
    line-height: 1.4;
    vertical-align: middle;
}

/* Top bar — only visible on mobile. Contains the hamburger toggle and a
   search-palette trigger so the palette is reachable without a keyboard.
   Above 1024px the bar collapses (display:none) and the sidebar is the
   primary nav surface again. */
.kott-admin-topbar { display: none; }
.kott-sidebar-toggle-input { display: none; }
.kott-sidebar-backdrop { display: none; }
.kott-hamburger { display: none; }

@media (max-width: 1024px) {
    /* Reset the legacy 768px row layout — at the new breakpoint we go
       full off-canvas instead of collapsing into a horizontal scroll. */
    .admin-shell { flex-direction: column; }
    .kott-admin-topbar {
        display: flex;
        align-items: center;
        gap: 12px;
        position: sticky;
        top: 0;
        z-index: 90;
        background: rgba(4, 6, 10, 0.92);
        backdrop-filter: blur(12px);
        -webkit-backdrop-filter: blur(12px);
        padding: 10px 16px;
        border-bottom: 1px solid var(--border);
    }
    .kott-admin-topbar-brand {
        flex: 1;
        font-family: var(--font-display);
        font-weight: 700;
        font-size: 14px;
        color: var(--accent);
        letter-spacing: 0.6px;
    }
    .kott-hamburger {
        display: inline-flex;
        flex-direction: column;
        justify-content: space-between;
        width: 28px;
        height: 22px;
        cursor: pointer;
        padding: 4px 0;
    }
    .kott-hamburger span {
        display: block;
        height: 2px;
        background: var(--text-secondary);
        border-radius: 2px;
    }
    /* Sidebar slides in from the left when the toggle is checked. */
    .sidebar {
        position: fixed;
        top: 0; bottom: 0;
        left: -260px;
        width: 240px;
        transition: left 0.18s ease;
        z-index: 200;
        flex-direction: column;
        overflow-x: hidden;
        gap: 2px;
    }
    .kott-sidebar-toggle-input:checked ~ .sidebar { left: 0; }
    .kott-sidebar-toggle-input:checked ~ .kott-sidebar-backdrop {
        display: block;
        position: fixed;
        top: 0; left: 0; right: 0; bottom: 0;
        background: rgba(0, 0, 0, 0.55);
        z-index: 150;
    }
    .content { margin-left: 0; padding: 16px; }
    /* Hide the top-of-sidebar brand since the topbar already shows it. */
    .sidebar > .sidebar-brand { display: none; }
}

/* Search-palette trigger button on the mobile top bar. */
.kott-search-trigger {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: rgba(0, 224, 255, 0.06);
    border: 1px solid rgba(0, 224, 255, 0.22);
    color: var(--text-secondary);
    padding: 5px 9px;
    border-radius: 4px;
    cursor: pointer;
    font-family: var(--font-display);
    font-size: 12px;
}
.kott-search-trigger:hover { color: var(--accent); border-color: var(--accent); }
.kott-search-trigger kbd {
    font-family: var(--font-mono);
    font-size: 10.5px;
    padding: 1px 5px;
    background: rgba(0, 0, 0, 0.5);
    border-radius: 2px;
    color: var(--accent);
}
.kott-search-trigger-hint { display: none; }
@media (min-width: 480px) {
    .kott-search-trigger-hint { display: inline; }
}

/* AdminSearchPalette — centered modal overlay. Cyan accent matches the
   admin design tokens; backdrop dims the page underneath. */
.admin-search-palette { display: none; }
.admin-search-palette.open {
    display: block;
    position: fixed;
    top: 0; left: 0; right: 0; bottom: 0;
    z-index: 500;
}
.admin-search-backdrop {
    position: absolute;
    top: 0; left: 0; right: 0; bottom: 0;
    background: rgba(0, 0, 0, 0.6);
    backdrop-filter: blur(2px);
    -webkit-backdrop-filter: blur(2px);
}
.admin-search-card {
    position: relative;
    margin: 12vh auto 0;
    width: 92%;
    max-width: 560px;
    background: rgba(8, 12, 18, 0.96);
    border: 1px solid rgba(0, 224, 255, 0.28);
    border-radius: 5px;
    /* Wave 7 F38 — canonical modal shadow (matches admin-keybinding-help). */
    box-shadow: 0 24px 60px rgba(0, 0, 0, 0.6);
    overflow: hidden;
}
.admin-search-input-wrap {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 12px 14px;
    border-bottom: 1px solid var(--border);
}
.admin-search-icon { color: var(--accent); font-size: 18px; }
.admin-search-input {
    flex: 1;
    background: transparent;
    border: none;
    outline: none;
    color: var(--text-primary);
    font-family: var(--font-display);
    font-size: 15px;
    padding: 4px 0;
}
.admin-search-input::placeholder { color: var(--text-muted); }
.admin-search-hint {
    font-family: var(--font-mono);
    font-size: 11px;
    color: var(--text-tertiary);
}
.admin-search-results {
    list-style: none;
    margin: 0;
    padding: 4px 0;
    max-height: 50vh;
    overflow-y: auto;
}
.admin-search-result {
    display: flex;
    align-items: baseline;
    gap: 10px;
    padding: 8px 14px;
    cursor: pointer;
    font-size: 13px;
}
.admin-search-result.selected,
.admin-search-result:hover {
    background: rgba(0, 224, 255, 0.08);
}
.admin-search-group {
    font-family: var(--font-display);
    font-size: 10.5px;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--text-tertiary);
    min-width: 92px;
}
.admin-search-label { flex: 1; color: var(--text-primary); font-weight: 500; }
.admin-search-path {
    font-family: var(--font-mono);
    font-size: 11.5px;
    color: var(--accent);
    opacity: 0.85;
}
.admin-search-empty {
    padding: 16px;
    color: var(--text-tertiary);
    font-style: italic;
    font-size: 13px;
    text-align: center;
}
/* Wave 7 Refactor 7.5 — Recently-visited section. Renders a small
   uppercase divider above the route list when the query is empty +
   prior visits exist. Recent rows themselves get a subtle left
   accent strip so they're visually distinct from the main results. */
.admin-search-section-header {
    padding: 10px 14px 4px;
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 1px;
    color: var(--text-muted);
    background: rgba(255, 255, 255, 0.02);
}
.admin-search-result.admin-search-recent {
    border-left: 2px solid rgba(0, 224, 255, 0.4);
}
/* UX-audit 2026-05-06 Priority 4 (b) — synthesized "Go to <id>" jump rows.
   Purple left-rule mirrors the TimeAttack accent so they read as a distinct
   action (direct deep-link) versus the cyan recent/list navigation. */
.admin-search-result.admin-search-goto {
    border-left: 2px solid rgba(180, 156, 255, 0.55);
}

/* /infra + /distribution discovery card grid. Same shape on both pages
   so an admin who's seen one knows what to expect on the other. */
.infra-tabs-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 14px;
    margin-top: 18px;
}
.infra-tab-card {
    display: block;
    padding: 16px 18px;
    background: var(--bg-elevated);
    border: 1px solid var(--border);
    border-radius: 4px;
    color: var(--text-primary);
    text-decoration: none;
    transition: border-color 0.12s ease, transform 0.12s ease;
}
/* Wave 7 F37 — bump hover lift from 1px to 2px + add a subtle
   accent shadow so the card affordance is more noticeable on
   the Distribution / Infra umbrella pages. */
.infra-tab-card:hover {
    border-color: var(--accent);
    color: var(--text-primary);
    transform: translateY(-2px);
    box-shadow: 0 4px 16px rgba(0, 224, 255, 0.10);
}
.infra-tab-title {
    font-family: var(--font-display);
    font-size: 14px;
    font-weight: 600;
    color: var(--accent);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    margin-bottom: 6px;
}
.infra-tab-help {
    font-size: 12.5px;
    color: var(--text-secondary);
    line-height: 1.5;
}

/* Wave 6 Task 6.1 — /infra umbrella tab body. Tab summary lists +
   host-picker grid for the Host Content tab. */
.infra-summary {
    list-style: none;
    padding: 0;
    margin: 12px 0;
    display: flex;
    flex-wrap: wrap;
    gap: 18px;
}
.infra-summary li {
    background: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: 4px;
    padding: 10px 14px;
    font-size: 13px;
    color: var(--text-secondary);
}
.host-picker-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 12px;
    margin-top: 12px;
}
.host-picker-card {
    display: block;
    padding: 12px 14px;
    background: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: 4px;
    text-decoration: none;
    color: inherit;
    transition: border-color 0.12s ease;
}
.host-picker-card:hover { border-color: var(--accent); }
.host-picker-name { margin-bottom: 4px; font-size: 13px; }
.host-picker-ip { margin-bottom: 6px; font-size: 12px; color: var(--text-tertiary); }

/* Wave 5.A F17 — auto-refresh-tick + AutoPollControl + manual refresh
   button shape. The header itself is .page-header-row (canonical, defined
   above); .page-header-actions groups the right-side widgets so they stay
   together when flex-wrap kicks in on narrow viewports. Replaces the old
   .alerts-header-row / .alerts-header-actions / .disputes-header trio so
   every auto-poll page renders the chip in the same top-right slot. */
.page-header-actions {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
}
.auto-refresh-tick {
    font-size: 12px;
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* Wave 7 Refactor 7.1 — auto-poll pause toggle. Sits next to
   .auto-refresh-tick; the icon button is small + outline-only so it
   doesn't compete with primary actions. .paused state flips to amber
   so the operator notices the page is intentionally frozen. */
.auto-poll-toggle {
    background: transparent;
    border: 1px solid var(--border, rgba(255,255,255,0.1));
    color: var(--text-muted);
    font-size: 12px;
    line-height: 1;
    padding: 2px 6px;
    border-radius: var(--radius-sm, 4px);
    cursor: pointer;
    transition: border-color 0.15s ease, color 0.15s ease;
}
.auto-poll-toggle:hover {
    border-color: var(--accent, #00e0ff);
    color: var(--accent, #00e0ff);
}
.auto-poll-toggle.paused {
    border-color: #c98b30;
    color: #c98b30;
}
.auto-poll-paused-pill {
    font-size: 10px;
    font-weight: 600;
    color: #c98b30;
    background: rgba(201,139,48,0.12);
    border: 1px solid rgba(201,139,48,0.3);
    border-radius: var(--radius-sm, 4px);
    padding: 1px 6px;
    letter-spacing: 0.5px;
    white-space: nowrap;
}

/* --------------------------------------------------------------------------
   2026-05-05 VITALS pass — TenantDetail strip.
   --------------------------------------------------------------------------
   1-line summary of tenant vitals (status / instances / license / bundle)
   that renders above the 8 stacked panels so an admin can triage during
   an incident without scrolling. Kept as inline markup (not a primitive)
   per task spec; chip palette mirrors public.css .status-pill semantics
   so colour treatment stays consistent across admin + operator surfaces.
   -------------------------------------------------------------------------- */
.tenant-vitals-strip {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin: 8px 0 16px;
    padding: 6px 0;
    align-items: center;
}
.tenant-vitals-chip {
    display: inline-flex;
    align-items: baseline;
    gap: 6px;
    padding: 4px 10px;
    border-radius: 9px;
    font-family: var(--font-mono, ui-monospace, monospace);
    font-size: 12px;
    line-height: 1.2;
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid rgba(255, 255, 255, 0.10);
    color: var(--text-muted);
    white-space: nowrap;
}
.tenant-vitals-label {
    text-transform: uppercase;
    font-size: 10px;
    letter-spacing: 0.6px;
    color: var(--text-muted);
    opacity: 0.75;
}
.tenant-vitals-value {
    color: var(--text-primary);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}
.tenant-vitals-chip.tenant-vitals-ok {
    background: rgba(16, 185, 129, 0.10);
    border-color: rgba(16, 185, 129, 0.40);
}
.tenant-vitals-chip.tenant-vitals-ok .tenant-vitals-value { color: #10b981; }
.tenant-vitals-chip.tenant-vitals-warn {
    background: rgba(245, 158, 11, 0.10);
    border-color: rgba(245, 158, 11, 0.40);
}
.tenant-vitals-chip.tenant-vitals-warn .tenant-vitals-value { color: #f59e0b; }
.tenant-vitals-chip.tenant-vitals-bad {
    background: rgba(248, 113, 113, 0.12);
    border-color: rgba(248, 113, 113, 0.50);
}
.tenant-vitals-chip.tenant-vitals-bad .tenant-vitals-value { color: #fca5a5; }

/* --------------------------------------------------------------------------
   Wave 7 Refactor 7.2 — generic <Chip> primitive.
   --------------------------------------------------------------------------
   Mirrors the .tenant-vitals-chip palette but with a tone-prefix naming
   scheme (.chip-ok / .chip-warn / .chip-bad / .chip-info / .chip-neutral)
   that matches the <Chip Cls="..."> parameter contract. Existing surfaces
   (.tenant-vitals-chip, .status-pill, .ops-mode-badge) keep their rules;
   .chip is the canonical primitive going forward. NOTE: .chip already
   exists for ban-form chips (rounded buttons) in BanForm.razor's <style>
   scope, so the .chip rule here only applies when paired with a tone class
   (.chip.chip-ok etc.) to avoid stomping the older surface.
   -------------------------------------------------------------------------- */
.chip {
    display: inline-flex;
    align-items: baseline;
    gap: 6px;
    padding: 4px 10px;
    border-radius: 9px;
    font-family: var(--font-mono, ui-monospace, monospace);
    font-size: 12px;
    line-height: 1.2;
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid rgba(255, 255, 255, 0.10);
    color: var(--text-muted);
    white-space: nowrap;
}
.chip .chip-label {
    text-transform: uppercase;
    font-size: 10px;
    letter-spacing: 0.6px;
    color: var(--text-muted);
    opacity: 0.75;
}
.chip .chip-value {
    color: var(--text-primary);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}
.chip.chip-ok {
    background: rgba(16, 185, 129, 0.10);
    border-color: rgba(16, 185, 129, 0.40);
}
.chip.chip-ok .chip-value { color: #10b981; }
.chip.chip-warn {
    background: rgba(245, 158, 11, 0.10);
    border-color: rgba(245, 158, 11, 0.40);
}
.chip.chip-warn .chip-value { color: #f59e0b; }
.chip.chip-bad {
    background: rgba(248, 113, 113, 0.12);
    border-color: rgba(248, 113, 113, 0.50);
}
.chip.chip-bad .chip-value { color: #fca5a5; }
.chip.chip-info {
    background: rgba(0, 224, 255, 0.10);
    border-color: rgba(0, 224, 255, 0.35);
}
.chip.chip-info .chip-value { color: #00e0ff; }
.chip.chip-neutral {
    /* Default — no override needed. */
}
/* Wave 7 Refactor 7.2 — kill the inline-style margin-left on the
   ContentPacks rollup badges by reusing the same gap declared on the
   row container. */
.content-pack-rollup-badge { margin-left: 0.4rem; }

/* Content-packs management list (2026-06-26 redesign) — compact stats strip + table. */
.ta-right { text-align: right; }
.content-stats { display: flex; flex-wrap: wrap; gap: 10px; margin: 0 0 14px; }
.content-stat {
    display: flex; flex-direction: column; gap: 1px; padding: 8px 14px; min-width: 92px;
    background: rgba(255, 255, 255, 0.03); border: 1px solid var(--border); border-radius: 4px;
}
.content-stat-num { font-family: var(--font-mono); font-size: 18px; font-weight: 600; color: var(--text-primary); line-height: 1.1; }
.content-stat-label { font-size: 11px; text-transform: uppercase; letter-spacing: 0.5px; color: var(--text-muted); }
.content-stat-warn .content-stat-num { color: var(--warn, #f4b740); }
.content-packs-table td { vertical-align: top; }
.content-pack-name { font-weight: 600; }
.content-packs-actions { display: inline-flex; gap: 6px; justify-content: flex-end; flex-wrap: wrap; }
/* Installed-content view section headers (Cars / Tracks) on the host content page. */
.content-section-head { display: flex; justify-content: space-between; align-items: center; gap: 12px; margin: 20px 0 8px; }
.content-section-head h2 { margin: 0; }

/* Expanded suspicious-activity banner — per-key detail rows. */
.suspicious-detail-list {
    list-style: none;
    margin: 12px 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.suspicious-detail-row {
    padding: 8px 10px;
    background: rgba(255, 77, 77, 0.04);
    border: 1px solid rgba(255, 77, 77, 0.20);
    border-radius: 4px;
    font-size: 13px;
}
.suspicious-detail-row code {
    font-size: 12px;
    background: rgba(255, 255, 255, 0.05);
    padding: 1px 4px;
    border-radius: 3px;
}
.suspicious-detail-row .status-pill {
    margin-left: 8px;
}

/* Provision wizard step rail (2026-05-05). Renders the 4-step
   horizontal indicator above the wizard panels. Linear / done /
   active / pending states for the three step categories. */
.provision-steprail {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    list-style: none;
    margin: 12px 0 4px;
    padding: 0;
    counter-reset: provision-step;
}
.provision-stepitem {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px;
    border-radius: 4px;
    border: 1px solid var(--border, #2a2a2a);
    background: var(--surface, #1a1a1a);
    color: var(--text-muted);
    font-size: 13px;
}
.provision-stepitem.active {
    border-color: var(--accent, #00e0ff);
    color: var(--text-primary);
    box-shadow: 0 0 0 1px var(--accent, #00e0ff);
}
.provision-stepitem.done {
    border-color: var(--accent, #00e0ff);
    color: var(--accent, #00e0ff);
    opacity: 0.85;
}
.provision-stepnum {
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}
.provision-stepof {
    font-size: 12px;
    color: var(--text-muted);
    margin: 0 0 16px;
}

/* Preflight checklist rows on Step 3 of the provision wizard. */
.preflight-checklist {
    list-style: none;
    margin: 12px 0;
    padding: 0;
}
.preflight-row {
    display: grid;
    grid-template-columns: 24px 200px 1fr;
    align-items: baseline;
    gap: 12px;
    padding: 6px 0;
    border-bottom: 1px solid var(--border, #2a2a2a);
}
.preflight-row.ok { color: var(--text-primary); }
.preflight-row.warn { color: #f5a623; }
.preflight-row.err { color: #e74c3c; }
.preflight-mark { font-size: 16px; }
.preflight-label { font-weight: 600; }
.preflight-detail {
    font-size: 13px;
    color: var(--text-muted);
}

/* Step 4 — per-instance live tracker rows. Mirrors the existing
   .activation-checklist styling but scoped to the provision wizard. */
.provision-instance-list {
    list-style: none;
    margin: 12px 0;
    padding: 0;
}
.provision-instance-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 0;
    border-bottom: 1px solid var(--border, #2a2a2a);
}
.provision-instance-row.ok { color: var(--text-success, #2ecc71); }
.provision-instance-row.err { color: var(--text-danger, #e74c3c); }
.provision-instance-row.queued { color: var(--text-muted); }
.provision-instance-row .mark {
    width: 18px;
    text-align: center;
    font-weight: 600;
}
.provision-instance-row .err-text {
    color: var(--text-danger, #e74c3c);
    font-size: 13px;
}

/* Wave 3.2 Item 8 — RankTiers color picker row. The native color input is
   small + the hex text input handles paste flow. Keep them side-by-side with
   the live swatch. */
.rank-tier-color-row {
    display: flex;
    align-items: center;
    gap: 8px;
}
.rank-tier-color-row > .form-field { margin: 0; }
.rank-tier-color-row > .form-field:first-child { flex: 0 0 56px; }
.rank-tier-color-row > .form-field:nth-child(2) { flex: 1; }
.rank-tier-color-swatch {
    width: 24px;
    height: 24px;
    border-radius: 4px;
    border: 1px solid rgba(255, 255, 255, 0.2);
    flex-shrink: 0;
}

/* Wave 3.2 Item 11 — Feature flag toggle.
   Density pass (2026-06-08): the WCAG 2.5.5 44x44 tap floor only matters on
   touch — it wasted ~28px of vertical chrome per flag row on the desktop
   ops surface. Dropped here; restored inside the mobile media query below. */
.flag-toggle {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 4px 0;
    cursor: pointer;
}
.flag-toggle input[type="checkbox"] {
    width: 20px;
    height: 20px;
    margin: 0;
    cursor: pointer;
}
@media (max-width: 768px) {
    .flag-toggle { min-width: 44px; min-height: 44px; padding: 8px 12px; }
}

/* Wave 3.2 Item 9 — PluginDefaults Save-all + dirty-dot. Marks dirty knob
   rows with an amber dot before the key code so the operator scans for
   pending edits at a glance. */
.plugin-defaults-actions {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 16px;
    flex-wrap: wrap;
}
.dirty-dot {
    display: inline-block;
    width: 8px;
    height: 8px;
    background: #f59e0b;
    border-radius: 50%;
    margin-right: 6px;
    vertical-align: middle;
}

/* Wave 3.2 Item 16 — chart-header row keeps the section title left and the
   Export-CSV button right via flex (replaces the old float:right /
   negative-margin hack on AnalyticsCharts win-rate). */
.chart-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-top: 24px;
}
.chart-header > .chart-header-title {
    margin: 0;
}
.chart-header-csv {
    padding: 4px 10px;
    font-size: 11px;
}

/* Wave 3.2 Item 19+20 — ServiceHealth. Wrap the AdminDataTable in form-panel
   chrome for consistency with other admin list pages, then band even rows
   so a 30+ service list scans more easily. */
.service-health-table tbody tr:nth-child(even) {
    background: rgba(255, 255, 255, 0.02);
}

/* R16 (2026-06-22) — relocated from ServiceHealth.razor's inline <style>.
   The bespoke .status-badge override (and its .success/.warning/.danger
   modifiers) was DROPPED: the page now uses the canonical .status-badge +
   .status-success/.status-warning/.status-danger family already defined above.
   These rules are the ServiceHealth-only chrome that has no canonical home. */
.admin-drawer-content h4 { margin-top: 12px; margin-bottom: 8px; color: var(--text-secondary); font-size: 12px; text-transform: uppercase; letter-spacing: 0.5px; }
.service-health-legend { margin: 12px 0 16px; padding: 8px 14px; border: 1px solid var(--border); border-radius: 4px; background: var(--bg-panel); }
.service-health-legend > summary { cursor: pointer; font-weight: 600; color: var(--text-secondary); padding: 4px 0; }
.service-health-legend[open] > summary { margin-bottom: 8px; }
.service-health-legend h4 { margin: 16px 0 6px; font-size: 12px; color: var(--text-secondary); text-transform: uppercase; letter-spacing: 0.5px; }
.service-health-legend dl.kv-grid { display: grid; grid-template-columns: max-content 1fr; column-gap: 12px; row-gap: 6px; margin: 0; }
.service-health-legend dl.kv-grid dt { font-weight: 600; }
.service-health-legend dl.kv-grid dd { margin: 0; color: var(--text-muted); }
.service-health-legend ul { margin: 4px 0 0; padding-left: 20px; }
.service-health-legend ul li { color: var(--text-muted); margin-bottom: 3px; }

/* Wave 6 admin keyboard navigation (2026-05-06) — `?` help overlay. Mirrors
   the AdminDrawer's z-index pattern (backdrop just below the panel, panel
   centred via fixed-position transform). */
.admin-keybinding-help-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.55);
    z-index: 1100;
}
.admin-keybinding-help {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: min(560px, 92vw);
    max-height: 80vh;
    overflow: auto;
    background: var(--bg-card, #121418);
    color: var(--text-primary, #e6eaf2);
    border: 1px solid var(--border-color, #222);
    border-radius: 4px;
    /* Wave 7 F38 — canonical modal shadow (matches AdminSearchPalette card). */
    box-shadow: 0 24px 60px rgba(0, 0, 0, 0.6);
    z-index: 1101;
    padding: 0;
}
.admin-keybinding-help-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 14px 18px;
    border-bottom: 1px solid var(--border-color, #222);
}
.admin-keybinding-help-header h2 {
    margin: 0;
    font-size: 1.1rem;
}
.admin-keybinding-help-close {
    background: transparent;
    border: none;
    color: inherit;
    font-size: 1.6rem;
    line-height: 1;
    cursor: pointer;
    padding: 0 4px;
}
.admin-keybinding-help-body {
    padding: 16px 18px 20px;
}
.admin-keybinding-help-list {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: 10px 22px;
    margin: 0 0 12px;
}
.admin-keybinding-help-list dt {
    text-align: right;
}
.admin-keybinding-help-list dd {
    margin: 0;
}
.admin-keybinding-help-list kbd {
    display: inline-block;
    padding: 2px 6px;
    border: 1px solid var(--border-color, #222);
    border-bottom-width: 2px;
    border-radius: 3px;
    background: rgba(255, 255, 255, 0.04);
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 0.85em;
    line-height: 1;
}
.admin-keybinding-help-foot {
    margin: 0;
    color: var(--text-muted);
    font-size: 0.85rem;
}

/* ============================================
   Wave I (2026-05-12) F-301 — AnalyticsCharts static-style retirement.
   Each .ac-* class is a 1:1 lift of a former inline style= value on the
   chart scaffolding (containers, labels, stat tiles). Data-driven bar
   dimensions + colors stay inline (they carry a runtime @-value).
   ============================================ */
.ac-35042d { color: var(--text-secondary); }
.ac-e59b8f { display: flex; gap: 12px; margin-bottom: 8px; }
.ac-d93311 { color: var(--text-secondary); font-size: 13px; }
.ac-b25d56 { color: var(--text-primary); }
.ac-c30bfe { display: flex; flex-direction: column; gap: 2px; }
.ac-bd9db1 { display: flex; align-items: center; gap: 8px; }
.ac-7d71c9 { min-width: 70px; font-size: 12px; color: var(--text-tertiary); text-align: right; }
.ac-16961f { flex: 1; background: var(--bg-elevated); border-radius: 3px; overflow: hidden; }
.ac-a3a49a { min-width: 28px; font-size: 12px; color: var(--text-secondary); text-align: right; }
.ac-cffe66 { display: flex; gap: 16px; flex-wrap: wrap; }
.ac-20d425 { background: var(--bg-elevated); border-radius: 5px; padding: 16px 24px; min-width: 140px; text-align: center; }
.ac-bb69b1 { font-size: 24px; font-weight: 700; color: var(--accent); }
.ac-b3ce8c { font-size: 12px; color: var(--text-tertiary); margin-top: 4px; }
.ac-e899a0 { font-size: 24px; font-weight: 700; color: var(--text-primary); }
.ac-1ad741 { font-size: 24px; font-weight: 700; color: var(--text-secondary); }
.ac-5bcf4c { display: flex; flex-direction: column; gap: 4px; }
.ac-c3c68c { border-top: 2px solid var(--accent); padding-top: 24px; margin-top: 32px; }
.ac-e5e1d0 { margin: 0 0 4px 0; }
.ac-79393c { margin: 0 0 16px 0; }
.ac-d1a98c { padding: 4px 10px; font-size: 11px; margin-left: 12px; }
.ac-a81293 { margin-top: 16px; }
.ac-556881 { display: flex; align-items: center; gap: 8px; cursor: pointer; }
.ac-daf7c4 { float: right; margin-top: -32px; }
.ac-5c2918 { margin-top: 24px; }
.ac-1558ef { color: var(--text-tertiary); }
.ac-3dc569 { color: var(--link); }
.ac-db1172 { font-weight: 600; }
.ac-592de8 { border-top: 2px solid #a78bfa; padding-top: 24px; margin-top: 32px; }
.ac-383ad4 { display: inline-block; width: 60px; background: var(--bg-elevated); border-radius: 2px; }
.ac-6ec01b { margin-left: 6px; }
.ac-b15616 { color: var(--danger); font-weight: 600; }
.ac-0814fd { border-top: 2px solid #34d399; padding-top: 24px; margin-top: 32px; }
.ac-b56181 { overflow-x: auto; }
.ac-4f6ce8 { border-collapse: separate; border-spacing: 2px; }
.ac-a7c158 { font-size: 10px; color: var(--text-tertiary); padding: 2px 4px; }
.ac-4b1fe2 { font-size: 11px; color: var(--text-tertiary); font-weight: 600; padding-right: 6px; }
.ac-7b794e { color: var(--warning); font-weight: 600; }
.ac-39b233 { display: flex; gap: 8px; flex-wrap: wrap; }
.ac-ed785e { background: var(--bg-elevated); padding: 10px 14px; border-radius: 4px; border-left: 3px solid #34d399; }
.ac-252f12 { font-size: 20px; font-weight: 700; color: var(--accent); }
.ac-bc1bc5 { font-size: 11px; color: var(--text-tertiary); }
.ac-7851db { text-align: right; }
.ac-3bd722 { font-family: monospace; }

/* ── Soft-loading refresh state (2026-07-08) ─────────────────────────────
   Applied to the DATA REGION ONLY (tbody / rows / cards) while a re-query is
   in flight: prior rows stay rendered but dimmed so the layout doesn't jump,
   and the filter/tab/pagination controls around the region stay interactive.
   Mirrors the same-named utility in public.css. */
.is-refreshing { opacity: 0.45; pointer-events: none; user-select: none; transition: opacity 120ms ease; }

/* ── Viz Wave 1 helpers (F-301: no static inline styles on admin pages) ───────── */
/* ServiceHealth drawer: spacing under the full-window tick strip. */
.viz-strip-block { margin-bottom: 10px; }
/* Lap sector panel: bar column width + block-level inline SVG (kills baseline gap). */
.sector-bar-col { width: 45%; }
.viz-svg-block { display: block; }


/* === Sharp refinement (2026-07-12): cyan top-accent + tabular numerals ============ */
.form-panel, .system-health-card, .recent-ops-card, .queue-panel, .dep-panel,
.empty-state, .attention-strip, .fleet-stats-row, .live-grid > * {
  border-top: 2px solid var(--accent);
}
.admin-data-table, .kv-list, .kv-grid, [class*="time"], [class*="stat-"], .live-ops-sse-chip {
  font-variant-numeric: tabular-nums;
}

/* ============================================================================
   Fleet cards (2026-08-01) — the card view on /servers.

   DENSITY IS THE POINT HERE. `body` sets line-height 1.5 for prose; a card that
   is almost entirely labels and values inherits ~25% of height it does not need,
   which is exactly what makes an expanded card feel tall. Every text block below
   pins its own leading (1.2–1.35), per the density convention in CLAUDE.md.
   Interactive rows still clear the ~24px minimum target.
   ========================================================================= */
.fleet-card-list { display: flex; flex-direction: column; gap: 8px; }

.fleetcard { border: 1px solid var(--border); border-radius: 6px; background: var(--bg-card); overflow: hidden; }
.fleetcard.is-open { border-color: var(--border-accent, rgba(0, 224, 255, 0.42)); }

/* Header is a full-width button so the whole strip is one hit target. */
.fleetcard-hd {
    display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
    width: 100%; padding: 9px 12px; background: none; border: none;
    color: var(--text-primary); font: inherit; line-height: 1.25;
    text-align: left; cursor: pointer;
}
.fleetcard-hd:hover { background: var(--bg-hover); }
.fleetcard-hd:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.fc-chev { color: var(--accent); font-size: 10px; width: 10px; line-height: 1; }
.fc-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--text-tertiary); flex: 0 0 auto; }
.st-on   .fc-dot { background: var(--success); }
.st-drain .fc-dot { background: var(--warning); }
.st-fail .fc-dot { background: var(--danger); }
.fc-name { font-family: var(--font-display); font-size: 15px; font-weight: 600; letter-spacing: 0.3px; line-height: 1.2; }
.fc-players { font-size: 12px; line-height: 1; padding: 3px 7px; border-radius: 3px;
              background: rgba(255, 255, 255, 0.06); font-variant-numeric: tabular-nums; }

/* Pills cap their own height so they can't set the header row's height. */
.fc-pill { font-size: 10px; letter-spacing: 0.06em; text-transform: uppercase; line-height: 1;
           padding: 3px 7px; border-radius: 3px; white-space: nowrap; }
.fc-pill.ok     { background: rgba(52, 211, 153, 0.14); color: var(--success); }
.fc-pill.warn   { background: rgba(251, 191, 36, 0.14); color: var(--warning); }
.fc-pill.bad    { background: rgba(248, 113, 113, 0.14); color: var(--danger); }
.fc-pill.off    { background: rgba(255, 255, 255, 0.06); color: var(--text-secondary); }
.fc-pill.info   { background: rgba(0, 224, 255, 0.11); color: var(--accent); }
.fc-pill.purple { background: rgba(180, 156, 255, 0.14); color: #b49cff; }

.fc-meta { margin-left: auto; font-family: var(--font-mono, monospace); font-size: 11px;
           color: var(--text-tertiary); line-height: 1.2; }

.fleetcard-body { padding: 12px; border-top: 1px solid var(--border); line-height: 1.35; }
.fc-zone-l { font-size: 10px; letter-spacing: 0.14em; text-transform: uppercase;
             color: var(--accent); line-height: 1; margin-bottom: 9px; }
.fc-rule { height: 1px; background: var(--border); margin: 14px -12px; }

.fc-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(104px, 1fr)); gap: 10px;
            font-variant-numeric: tabular-nums; }
.fc-st { display: flex; flex-direction: column; gap: 1px; line-height: 1.2; min-width: 0; }
.fc-st-l { font-size: 10px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-tertiary); line-height: 1; }
.fc-st-v { font-size: 13px; color: var(--text-primary); overflow: hidden; text-overflow: ellipsis; }
.fc-mono { font-family: var(--font-mono, monospace); }

.fc-actions { display: flex; gap: 7px; flex-wrap: wrap; align-items: center; margin-top: 11px; }
.fc-consequence { font-size: 11.5px; color: var(--text-tertiary); line-height: 1.3; }

/* More: ONE row of group buttons, one pane open at a time. An earlier draft stacked
   five permanent rows here and cost ~190px of collapsed chrome for nothing. */
.fc-more { margin: 12px -12px -12px; border-top: 1px solid var(--border); background: rgba(255, 255, 255, 0.015); }
.fc-more-tabs { display: flex; gap: 6px; flex-wrap: wrap; padding: 8px 12px; }
.fc-more-btn { font-size: 11.5px; line-height: 1.2; padding: 5px 9px; border-radius: 3px;
               border: 1px solid var(--border); background: transparent; color: var(--text-secondary); cursor: pointer; }
.fc-more-btn:hover { border-color: var(--border-hover); color: var(--text-primary); }
.fc-more-btn.on { border-color: var(--accent); color: var(--accent); background: rgba(0, 224, 255, 0.07); }
.fc-more-pane { padding: 0 12px 11px; display: flex; flex-direction: column; gap: 8px; align-items: flex-start; }
.fc-more-desc { font-size: 12px; color: var(--text-tertiary); line-height: 1.45; max-width: 68ch; }

/* View toggle on the Servers page header. */
.fleet-view-toggle { display: inline-flex; gap: 0; border: 1px solid var(--border); border-radius: 4px; overflow: hidden; }
.fleet-view-toggle button { font-size: 12px; line-height: 1.2; padding: 5px 11px; border: none;
                            background: transparent; color: var(--text-secondary); cursor: pointer; }
.fleet-view-toggle button.on { background: rgba(0, 224, 255, 0.1); color: var(--accent); }

/* /webhooks — DB-managed Discord webhook slots (mig186, 2026-08-18). One row
   per slot: title+description line, masked-URL state on the right, then the
   input + Save/Test/Clear controls. Dense component — pins its own leading. */
.webhook-slot { padding: 0.6rem 0; border-bottom: 1px solid rgba(255, 255, 255, 0.06); line-height: 1.35; }
.webhook-slot-head { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; flex-wrap: wrap; }
.webhook-slot-state { line-height: 1.3; }
.webhook-slot-desc { margin-left: 0.5rem; }
.webhook-slot-controls { display: flex; gap: 0.5rem; margin-top: 0.4rem; flex-wrap: wrap; }
.webhook-url-input { flex: 1; min-width: 280px; }

/* ── Line submissions review queue (/spline-submissions, mig188) ─────────────── */
.ssub-layout { display: grid; grid-template-columns: minmax(260px, 340px) 1fr; gap: var(--panel-gap); align-items: start; }
.ssub-queue { display: flex; flex-direction: column; gap: 6px; }
.ssub-filter { display: flex; gap: 6px; margin-bottom: 4px; }
.ssub-item { display: block; padding: 8px 10px; border-radius: 5px; border: 1px solid var(--border); background: var(--bg-panel); color: inherit; text-decoration: none; line-height: 1.3; }
.ssub-item:hover { border-color: var(--border-accent); }
.ssub-item.sel { border-color: var(--accent); background: var(--accent-dim); }
.ssub-item-head { display: flex; justify-content: space-between; gap: 8px; align-items: center; }
.ssub-item-track { font-weight: 600; font-size: 13px; }
.ssub-item-sub { font-size: 11.5px; color: var(--text-tertiary); margin-top: 2px; font-variant-numeric: tabular-nums; }
.ssub-head { display: flex; justify-content: space-between; gap: 1rem; align-items: flex-start; flex-wrap: wrap; }
.ssub-title { margin: 0 0 4px; font-size: 18px; line-height: 1.2; }
.ssub-layout-id { color: var(--text-secondary); font-weight: 400; }
.ssub-badges { display: flex; gap: 6px; }
.ssub-facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 8px 16px; margin: 0; line-height: 1.25; }
.ssub-facts dt { font-size: 10.5px; text-transform: uppercase; letter-spacing: .05em; color: var(--text-tertiary); }
.ssub-facts dd { margin: 2px 0 0; font-size: 13px; font-variant-numeric: tabular-nums; }
.ssub-plot { margin: 0; background: rgba(0,0,0,.35); border: 1px solid var(--border); border-radius: 5px; padding: 6px; }
.ssub-plot svg { width: 100%; height: auto; display: block; }
.ssub-plot figcaption { display: flex; gap: 14px; font-size: 11px; color: var(--text-tertiary); padding: 6px 4px 0; line-height: 1.2; }
.ssub-key::before { content: ""; display: inline-block; width: 14px; height: 2px; vertical-align: middle; margin-right: 5px; background: var(--text-tertiary); }
.ssub-key-submitted::before { background: var(--accent); }
.ssub-key-current::before { background: #b49cff; }
.ssub-key-sibling::before { background: rgba(255,255,255,.25); }
.ssub-key:last-child::before { display: none; }
.ssub-line-submitted { fill: none; stroke: var(--accent); stroke-width: 2.2; stroke-linejoin: round; }
.ssub-line-current { fill: none; stroke: #b49cff; stroke-width: 1.6; stroke-dasharray: 6 4; }
.ssub-line-sibling { fill: none; stroke: rgba(255,255,255,.22); stroke-width: 1.2; }
.ssub-start { fill: var(--accent); }
.ssub-h3 { margin: 6px 0 0; font-size: 13px; text-transform: uppercase; letter-spacing: .05em; color: var(--text-secondary); }
.ssub-checks { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 3px; }
.ssub-check { display: grid; grid-template-columns: 140px 1fr; gap: 10px; font-size: 12.5px; line-height: 1.3; }
.ssub-check code { align-self: start; }
.ssub-check-flag code { color: var(--warning); }
.ssub-check-reject code { color: var(--danger); }
.ssub-drift { border-collapse: collapse; font-size: 12.5px; font-variant-numeric: tabular-nums; line-height: 1.25; }
.ssub-drift th, .ssub-drift td { text-align: left; padding: 3px 12px 3px 0; border-bottom: 1px solid var(--border); }
.ssub-drift-flag td { color: var(--warning); }
.ssub-drift-block td { color: var(--danger); }
.ssub-ack { display: flex; gap: 8px; align-items: flex-start; font-size: 12.5px; color: var(--warning); line-height: 1.3; }
.ssub-actions { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-top: 4px; }
.ssub-reason { flex: 1; min-width: 260px; }
@media (max-width: 900px) { .ssub-layout { grid-template-columns: 1fr; } }
.ssub-newid { display: flex; flex-direction: column; gap: 4px; font-size: 12px; color: var(--text-secondary); }
.ssub-newid input { max-width: 320px; }

/* ── Tracks workbench (/tracks, 2026-08-21 redesign) ─────────────────────────── */
.twb-strip { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; margin: 0 0 var(--panel-gap); }
.twb-kpi { text-align: left; background: var(--bg-panel); border: 1px solid var(--border); border-radius: 5px; padding: 10px 12px; display: flex; flex-direction: column; gap: 2px; line-height: 1.15; color: inherit; cursor: pointer; font: inherit; }
.twb-kpi:hover { border-color: var(--border-accent); }
.twb-kpi.on { border-color: var(--accent); background: var(--accent-dim); }
.twb-kpi b { font-family: var(--font-display); font-size: 26px; font-weight: 700; }
.twb-kpi span { font-size: 11.5px; color: var(--text-tertiary); }
.twb-kpi.bad b { color: var(--danger); } .twb-kpi.warn b { color: var(--warning); } .twb-kpi.k b { color: #b49cff; }
.twb { display: grid; grid-template-columns: minmax(260px, 320px) 1fr; gap: var(--panel-gap); align-items: start; }
.twb-side { display: flex; flex-direction: column; gap: 8px; position: sticky; top: 12px; }
.twb-side .admin-filter-bar { flex-direction: column; align-items: stretch; }
.twb-side-meta { font-size: 11.5px; color: var(--text-tertiary); line-height: 1.3; padding: 0 2px; }
.twb-side-meta .probing { color: var(--accent); }
.twb-list { display: flex; flex-direction: column; gap: 4px; max-height: calc(100vh - 330px); overflow-y: auto; padding-right: 2px; }
.twb-row { display: grid; grid-template-columns: 1fr auto; gap: 2px 8px; align-items: center; padding: 7px 10px; border-radius: 5px; border: 1px solid var(--border); background: var(--bg-panel); color: inherit; text-decoration: none; line-height: 1.25; }
.twb-row:hover { border-color: var(--border-accent); }
.twb-row.sel { border-color: var(--accent); background: var(--accent-dim); }
.twb-row-name { font-family: var(--font-display); font-size: 15px; font-weight: 600; }
.twb-row-count { font-family: var(--font-display); font-size: 11px; font-weight: 700; padding: 1px 7px; border-radius: 999px; background: rgba(255,255,255,.06); color: var(--text-tertiary); line-height: 1.3; }
.twb-row-count.att { background: rgba(251,191,36,.15); color: var(--warning); }
.twb-row-sub { grid-column: 1 / -1; font-size: 11px; color: var(--text-tertiary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.twb-row-sub code { font-size: 10.5px; }
.twb-empty { font-size: 12px; color: var(--text-tertiary); padding: 8px; }
.twb-side-sync { display: flex; flex-direction: column; gap: 6px; border-top: 1px solid var(--border); padding-top: 8px; }
.twb-main { display: flex; flex-direction: column; gap: var(--panel-gap); min-width: 0; }
.twb-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; flex-wrap: wrap; }
.twb-title { margin: 0 0 2px; font-size: 22px; line-height: 1.15; }
.twb-title-id { font-size: 12px; color: var(--text-secondary); margin-left: 8px; }
.twb-head-actions { display: flex; gap: 6px; flex-wrap: wrap; }
.twb-layout-link { color: inherit; text-decoration: none; }
.twb-layout-link.sel code { color: var(--accent); box-shadow: inset 0 -2px 0 var(--accent); }
.twb-unreg { margin-left: 6px; }
.twb-pending { margin-left: 6px; text-decoration: none; }
.twb-plot { margin: 0; }
.twb-line { fill: none; stroke: rgba(255,255,255,.3); stroke-width: 1.4; }
.twb-detail { border-top: 1px solid var(--border2, var(--border)); padding-top: var(--panel-gap); display: flex; flex-direction: column; gap: 10px; }
.twb-detail-title { margin: 0; font-size: 15px; font-family: var(--font-display); }
@media (max-width: 980px) { .twb { grid-template-columns: 1fr; } .twb-side { position: static; } .twb-list { max-height: 260px; } .twb-strip { grid-template-columns: 1fr 1fr; } }
.twb-lock-reason { min-width: 220px; }

/* Shared track → layout picker (Components/Shared/TrackLayoutPicker.razor, 2026-09-13) — the
   same rules as public.css's .layout-card block, on the admin theme's variables (with fallbacks). */
.layout-card-grid {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: 10px; margin: 8px 0 12px;
}
.layout-card {
    display: flex; flex-direction: column; gap: 6px; text-align: left; cursor: pointer;
    background: rgba(255, 255, 255, 0.03); border: 1px solid var(--border, rgba(255, 255, 255, 0.1));
    border-radius: 5px; padding: 8px; transition: border-color 0.12s ease, background 0.12s ease;
    color: inherit; font: inherit;
}
.layout-card:hover { border-color: var(--accent, #00e0ff); background: rgba(255, 255, 255, 0.05); }
.layout-card.selected { border-color: var(--accent, #00e0ff); background: rgba(0, 224, 255, 0.08); }
.layout-card:disabled { opacity: 0.6; cursor: default; }
.layout-card-map {
    height: 94px; border-radius: 4px; overflow: hidden;
    background: linear-gradient(160deg, rgba(255, 255, 255, 0.06), rgba(255, 255, 255, 0.015));
    border: 1px solid var(--border, rgba(255, 255, 255, 0.1));
    display: flex; align-items: center; justify-content: center;
    font-size: 10px; color: var(--text-tertiary, #6b7280);
}
.layout-card-map img { max-width: 100%; max-height: 100%; object-fit: contain; filter: invert(1) opacity(0.82); }
.layout-card-name { font-size: 13.5px; font-weight: 600; color: var(--text-primary, #e5e7eb); line-height: 1.15; }
.layout-card-id { font-family: var(--font-mono, ui-monospace, monospace); font-size: 10px; color: var(--text-tertiary, #6b7280); }
.layout-card-stats { display: flex; flex-wrap: wrap; gap: 4px; }
.lc-stat {
    font-size: 10.5px; font-weight: 600; color: var(--text-muted, #9ca3af);
    background: rgba(255, 255, 255, 0.06); border-radius: 3px; padding: 1px 5px; white-space: nowrap;
}
.layout-card-warn { font-size: 10.5px; font-weight: 600; color: var(--warning, #fbbf24); }
.input-bare { width: 100%; }

/* Server → Traffic tab (2026-09-13): readiness rows + missing-model chips */
.readiness-list { list-style: none; padding: 0; margin: 4px 0 0; display: flex; flex-direction: column; gap: 6px; }
.readiness-list li { padding: 8px 10px 8px 30px; border: 1px solid var(--border, rgba(255,255,255,0.1)); border-radius: 5px; position: relative; line-height: 1.35; font-size: 12.5px; }
.readiness-list li::before { content: "•"; position: absolute; left: 12px; top: 7px; font-size: 16px; line-height: 1; }
.readiness-list li.ok::before { content: "✓"; color: var(--success, #34d399); }
.readiness-list li.bad::before { content: "✕"; color: var(--danger, #f87171); }
.readiness-list li.unknown::before { content: "•"; color: var(--text-tertiary, #6b7280); }
.readiness-list li.bad { border-color: rgba(248, 113, 113, 0.35); }
.car-chip.missing { border-color: var(--danger, #f87171); }
.warn-text { color: var(--warning, #fbbf24); }
