/* =============================================================================
   Validation Portal — Game Day design system (Midnight theme as default)
   ----------------------------------------------------------------------------
   Three coordinated themes are scoped by [data-theme]:
     - midnight (dark, default)
     - arena    (light)
     - zen      (warm light)
   Components reference SEMANTIC tokens (var(--ice)) — never raw hex.
   Adapted from the Game Day design system spec, May 2026.
   ========================================================================= */

/* -----------------------------------------------------------------------
   Theme tokens — Midnight (default)
   --------------------------------------------------------------------- */
:root,
[data-theme="midnight"] {
  /* Accents — warm refinement (v8 UI pass).
     Kept the cyan/teal identity but warmed and brightened the palette so it
     feels fun and lively rather than cold. Amber (puck) and coral are pushed
     forward as warm co-leads alongside the signature sky/cyan. */
  --ice:     #43c6f5;
  --goal:    #3ddc97;
  --penalty: #fb7185;
  --puck:    #fda63a;
  --zen:     #5ef0d6;
  --fire:    #fb8b3d;

  /* Ice ramp */
  --ice-a3:    rgba(56,189,248,0.03);
  --ice-a5:    rgba(56,189,248,0.05);
  --ice-a7:    rgba(56,189,248,0.07);
  --ice-a8:    rgba(56,189,248,0.08);
  --ice-a10:   rgba(56,189,248,0.10);
  --ice-a12:   rgba(56,189,248,0.12);
  --ice-a15:   rgba(56,189,248,0.15);
  --ice-a20:   rgba(56,189,248,0.20);
  --ice-a25:   rgba(56,189,248,0.25);
  --ice-a30:   rgba(56,189,248,0.30);
  --ice-a40:   rgba(56,189,248,0.40);
  --ice-a55:   rgba(56,189,248,0.55);
  --ice-glow:  rgba(67,198,245,0.18);
  --ice-dim:   rgba(67,198,245,0.06);
  --ice-border:rgba(67,198,245,0.18);

  /* Goal ramp */
  --goal-a3:    rgba(52,211,153,0.03);
  --goal-a5:    rgba(52,211,153,0.05);
  --goal-a7:    rgba(52,211,153,0.07);
  --goal-a8:    rgba(52,211,153,0.08);
  --goal-a10:   rgba(52,211,153,0.10);
  --goal-a12:   rgba(52,211,153,0.12);
  --goal-a15:   rgba(52,211,153,0.15);
  --goal-a20:   rgba(52,211,153,0.20);
  --goal-a25:   rgba(52,211,153,0.25);
  --goal-a30:   rgba(52,211,153,0.30);
  --goal-a40:   rgba(52,211,153,0.40);
  --goal-a55:   rgba(52,211,153,0.55);
  --goal-glow:  rgba(52,211,153,0.18);
  --goal-dim:   rgba(52,211,153,0.06);
  --goal-border:rgba(52,211,153,0.16);

  /* Penalty ramp */
  --penalty-a3:    rgba(248,113,113,0.03);
  --penalty-a5:    rgba(248,113,113,0.05);
  --penalty-a8:    rgba(248,113,113,0.08);
  --penalty-a10:   rgba(248,113,113,0.10);
  --penalty-a12:   rgba(248,113,113,0.12);
  --penalty-a15:   rgba(248,113,113,0.15);
  --penalty-a20:   rgba(248,113,113,0.20);
  --penalty-a25:   rgba(248,113,113,0.25);
  --penalty-a30:   rgba(248,113,113,0.30);
  --penalty-a40:   rgba(248,113,113,0.40);
  --penalty-a55:   rgba(248,113,113,0.55);
  --penalty-glow:  rgba(248,113,113,0.18);
  --penalty-dim:   rgba(248,113,113,0.06);
  --penalty-border:rgba(248,113,113,0.16);

  /* Puck ramp */
  --puck-a5:    rgba(251,146,60,0.05);
  --puck-a8:    rgba(251,146,60,0.08);
  --puck-a10:   rgba(251,146,60,0.10);
  --puck-a15:   rgba(251,146,60,0.15);
  --puck-a20:   rgba(251,146,60,0.20);
  --puck-a25:   rgba(251,146,60,0.25);
  --puck-a40:   rgba(251,146,60,0.40);
  --puck-glow:  rgba(251,146,60,0.18);
  --puck-border:rgba(251,146,60,0.16);

  /* Zen ramp */
  --zen-a8:     rgba(94,234,212,0.08);
  --zen-a15:    rgba(94,234,212,0.15);
  --zen-a25:    rgba(94,234,212,0.25);
  --zen-a40:    rgba(94,234,212,0.40);
  --zen-glow:   rgba(94,234,212,0.18);
  --zen-border: rgba(94,234,212,0.16);

  /* Fire ramp */
  --fire-a8:    rgba(249,115,22,0.08);
  --fire-a15:   rgba(249,115,22,0.15);
  --fire-a25:   rgba(249,115,22,0.25);
  --fire-glow:  rgba(249,115,22,0.18);

  /* Neutral ramp — theme-agnostic tints */
  --n-a3:  rgba(255,255,255,0.03);
  --n-a5:  rgba(255,255,255,0.05);
  --n-a8:  rgba(255,255,255,0.08);
  --n-a12: rgba(255,255,255,0.12);
  --n-a20: rgba(255,255,255,0.20);

  /* Surfaces — warm refinement (v8 UI pass).
     Shifted from cool blue-navy toward a warm indigo-plum base: same depth and
     navy identity, but with red/warm undertones mixed in so it reads rich and
     inviting rather than cold-clinical. Surfaces lifted slightly so nothing
     looks dingy. */
  --bg:        #14111f;
  --bg-2:      #181425;
  --surface:   #201a30;
  --surface-2: #29223c;
  --surface-3: #342b4a;

  /* Borders — warmed neutral (was cool blue-grey). */
  --border:        rgba(196,170,150,0.10);
  --border-hover:  rgba(251,146,60,0.30);

  /* Text — warm off-white instead of cool slate; muted text gets a warm tint
     so secondary copy feels soft, not grey-cold. */
  --text:    #f3ece4;
  --text-2:  #b3a596;
  --text-mute: rgba(179,165,150,0.55);

  /* Shadows — warm-tinted ambient depth + a warm amber glow as the default
     accent halo (was cyan). Adds a touch more lift for a modern feel. */
  --shadow-sm:   0 2px 8px rgba(20,10,5,0.30);
  --shadow-card: 0 4px 18px rgba(20,10,5,0.34), 0 0 0 1px rgba(196,170,150,0.05);
  --shadow-lg:   0 8px 32px rgba(20,10,5,0.46), 0 2px 6px rgba(20,10,5,0.28);
  --shadow-glow: 0 0 34px rgba(251,146,60,0.12);

  /* Chrome — warm gradient sidebar + topbar, matching the new base. */
  --sidebar-bg:    linear-gradient(180deg, rgba(32,26,48,0.98) 0%, rgba(20,17,31,0.99) 100%);
  --sidebar-border: rgba(196,170,150,0.07);
  --topbar-bg:     rgba(20,17,31,0.88);
  --topbar-border: rgba(196,170,150,0.07);

  /* Fonts */
  --font-display: "Sora", system-ui, sans-serif;
  --font-body:    "Manrope", system-ui, sans-serif;
  --font-mono:    "JetBrains Mono", ui-monospace, "SF Mono", monospace;

  /* Easing */
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
}

/* -----------------------------------------------------------------------
   Theme tokens — Arena (light)
   --------------------------------------------------------------------- */
[data-theme="arena"] {
  --ice:     #0284c7;
  --goal:    #059669;
  --penalty: #dc2626;
  --puck:    #ea580c;
  --zen:     #0d9488;
  --fire:    #c2410c;

  --ice-a8:    rgba(2,132,199,0.08);
  --ice-a10:   rgba(2,132,199,0.10);
  --ice-a15:   rgba(2,132,199,0.15);
  --ice-a20:   rgba(2,132,199,0.20);
  --ice-a25:   rgba(2,132,199,0.25);
  --ice-glow:  rgba(2,132,199,0.20);
  --ice-border:rgba(2,132,199,0.18);

  --goal-a8:   rgba(5,150,105,0.08);
  --goal-a15:  rgba(5,150,105,0.15);
  --goal-a25:  rgba(5,150,105,0.25);
  --goal-glow: rgba(5,150,105,0.20);
  --goal-border:rgba(5,150,105,0.18);

  --penalty-a8:   rgba(220,38,38,0.08);
  --penalty-a15:  rgba(220,38,38,0.15);
  --penalty-a25:  rgba(220,38,38,0.25);
  --penalty-glow: rgba(220,38,38,0.20);
  --penalty-border:rgba(220,38,38,0.18);

  --puck-a8:   rgba(234,88,12,0.08);
  --puck-a15:  rgba(234,88,12,0.15);
  --puck-glow: rgba(234,88,12,0.20);
  --puck-border:rgba(234,88,12,0.18);

  --bg:        #f8fafc;
  --bg-2:      #f1f5f9;
  --surface:   #ffffff;
  --surface-2: #f8fafc;
  --surface-3: #eef2f7;

  --border:        rgba(15,23,42,0.10);
  --border-hover:  rgba(2,132,199,0.30);

  --text:    #0f172a;
  --text-2:  #475569;
  --text-mute: rgba(71,85,105,0.6);

  --shadow-sm:   0 1px 2px rgba(15,23,42,0.05);
  --shadow-card: 0 1px 3px rgba(15,23,42,0.06), 0 1px 2px rgba(15,23,42,0.04);
  --shadow-lg:   0 10px 24px rgba(15,23,42,0.10), 0 1px 3px rgba(15,23,42,0.06);
  --shadow-glow: 0 0 24px rgba(2,132,199,0.10);

  --sidebar-bg:    #ffffff;
  --sidebar-border: rgba(15,23,42,0.08);
  --topbar-bg:     rgba(255,255,255,0.95);
  --topbar-border: rgba(15,23,42,0.08);

  --n-a3:  rgba(15,23,42,0.03);
  --n-a5:  rgba(15,23,42,0.05);
  --n-a8:  rgba(15,23,42,0.08);
  --n-a12: rgba(15,23,42,0.12);
  --n-a20: rgba(15,23,42,0.20);
}

/* -----------------------------------------------------------------------
   Reset + base
   --------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html, body {
  margin: 0; padding: 0;
  /* Warm ambient depth (v8 UI pass): two very soft warm glows over the base
     give the dark theme atmosphere instead of a flat fill. Fixed attachment so
     they stay put while content scrolls. Subtle enough to never fight content. */
  background-color: var(--bg);
  background-image:
    radial-gradient(900px circle at 12% -5%, rgba(253,166,58,0.07), transparent 45%),
    radial-gradient(1100px circle at 105% 12%, rgba(251,113,133,0.055), transparent 50%);
  background-attachment: fixed;
  background-repeat: no-repeat;
  color: var(--text);
  font-family: var(--font-body);
  font-size: 15px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

a {
  color: var(--ice);
  text-decoration: none;
  transition: color 0.18s var(--ease-out);
}
a:hover { color: var(--ice); filter: brightness(1.15); }

h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-display);
  font-weight: 600;
  letter-spacing: -0.01em;
  margin: 0 0 0.5em;
  color: var(--text);
}
h1 { font-size: 1.75rem; }
h2 { font-size: 1.35rem; }
h3 { font-size: 1.1rem; }
h4 { font-size: 1rem; }

p { margin: 0 0 1em; }

code, pre {
  font-family: var(--font-mono);
  font-size: 0.875em;
}
pre {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 16px 18px;
  overflow-x: auto;
  margin: 0 0 1em;
  color: var(--text);
}
code {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 0.1em 0.4em;
  color: var(--text);
}
pre code { background: transparent; border: 0; padding: 0; }

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

::selection { background: var(--ice-a25); color: var(--text); }

/* -----------------------------------------------------------------------
   Layout — sidebar + main
   --------------------------------------------------------------------- */
.layout {
  display: grid;
  grid-template-columns: 260px 1fr;
  min-height: 100vh;
}

.sidebar {
  background: var(--sidebar-bg);
  border-right: 1px solid var(--sidebar-border);
  padding: 24px 16px;
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
}

.sidebar-brand {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.05rem;
  letter-spacing: 0.02em;
  padding: 8px 12px 24px;
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--text);
}
.sidebar-brand-mark {
  width: 28px; height: 28px;
  border-radius: 8px;
  background: linear-gradient(135deg, var(--ice) 0%, var(--zen) 100%);
  box-shadow: 0 0 18px var(--ice-glow);
  display: grid; place-items: center;
  color: #001;
  font-weight: 800;
  font-size: 0.75rem;
}
.sidebar-section {
  font-family: var(--font-display);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-2);
  padding: 16px 12px 8px;
}
.sidebar-footer {
  margin-top: auto;
  padding: 16px 12px;
  border-top: 1px solid var(--border);
  font-size: 0.78rem;
  color: var(--text-2);
}

.nav-link {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  color: var(--text-2);
  border-radius: 8px;
  font-weight: 500;
  font-size: 0.92rem;
  position: relative;
  transition: background 0.18s var(--ease-out), color 0.18s var(--ease-out),
              transform 0.18s var(--ease-out);
}
/* Warm, lively hover (v8 UI pass): a faint amber wash + a small slide-right
   nudge so navigation feels responsive and friendly. */
.nav-link:hover {
  background: var(--puck-a8);
  color: var(--text);
  transform: translateX(2px);
}
.nav-link.active {
  background: var(--ice-a8);
  color: var(--ice);
  box-shadow: var(--shadow-glow);
}
.nav-link.active:hover { transform: none; }
.nav-link.active::before {
  content: "";
  position: absolute;
  left: 0; top: 8px; bottom: 8px;
  width: 3px;
  background: var(--ice);
  border-radius: 0 4px 4px 0;
  box-shadow: 0 0 12px var(--ice-glow);
}
.nav-link-icon {
  width: 18px; height: 18px; flex: 0 0 18px;
  opacity: 0.85;
}

.main {
  padding: 32px 40px 80px;
  max-width: 1180px;
  width: 100%;
}

.page-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 28px;
}
.page-title {
  font-family: var(--font-display);
  font-size: 1.65rem;
  font-weight: 700;
  margin: 0 0 6px;
  letter-spacing: -0.02em;
}
.page-subtitle {
  color: var(--text-2);
  font-size: 0.95rem;
  margin: 0;
}

/* -----------------------------------------------------------------------
   Cards
   --------------------------------------------------------------------- */
.card {
  /* Subtle top-lit gradient (v8 UI pass) gives the surface dimension instead
     of a flat fill — lighter at the top edge, settling to the base. */
  background: linear-gradient(180deg, var(--surface-2) 0%, var(--surface) 60%);
  border: 1px solid var(--border);
  border-radius: 16px;
  padding: 22px 24px;
  box-shadow: var(--shadow-card);
  transition:
    border-color 0.25s var(--ease-out),
    box-shadow 0.25s var(--ease-out),
    transform 0.25s var(--ease-out);
}

/* Gentle lift on hover — only for interactive cards (links/summaries/forms
   inside). Static info cards still get the warmer border on hover, which reads
   as "alive" without floating away. */
.card:hover {
  border-color: var(--border-hover);
  box-shadow: var(--shadow-lg);
}
.card:hover { border-color: var(--border-hover); }
.card-flat { box-shadow: none; }
.card-zen {
  background: linear-gradient(180deg, var(--ice-a3) 0%, transparent 70%), var(--surface);
  border-color: var(--ice-border);
}
.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 16px;
  gap: 12px;
}
.card-title {
  font-family: var(--font-display);
  font-size: 1rem;
  font-weight: 600;
  margin: 0;
  letter-spacing: -0.005em;
}

/* Stat-card grid */
.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 16px;
  margin-bottom: 28px;
}
.stat-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 18px 20px;
  position: relative;
  overflow: hidden;
}
.stat-card::after {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 2px;
  background: var(--accent, var(--ice));
  opacity: 0.5;
}
.stat-card.stat-goal    { --accent: var(--goal); }
.stat-card.stat-penalty { --accent: var(--penalty); }
.stat-card.stat-puck    { --accent: var(--puck); }
.stat-label {
  font-family: var(--font-display);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-2);
  margin-bottom: 8px;
}
.stat-value {
  font-family: var(--font-display);
  font-size: 1.8rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--text);
}
.stat-delta {
  font-size: 0.78rem;
  color: var(--text-2);
  margin-top: 4px;
}

/* -----------------------------------------------------------------------
   Buttons
   --------------------------------------------------------------------- */
.btn,
button.btn,
a.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 10px 18px;
  border-radius: 10px;
  border: 1px solid transparent;
  font-family: var(--font-display);
  font-size: 0.85rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  cursor: pointer;
  text-decoration: none;
  transition: transform 0.15s var(--ease-out),
              background 0.18s var(--ease-out),
              border-color 0.18s var(--ease-out),
              box-shadow 0.18s var(--ease-out);
  user-select: none;
  white-space: nowrap;
}
.btn:active { transform: translateY(1px); }
/* Tactile lift on hover (v8 UI pass) — pairs with the per-variant glow below
   for a responsive, modern feel. :active already presses back down. */
.btn:hover { transform: translateY(-1px); }
.btn:disabled, .btn[aria-disabled="true"] {
  opacity: 0.55; cursor: not-allowed;
  transform: none;
}
.btn:disabled:hover, .btn[aria-disabled="true"]:hover { transform: none; }

.btn-ice {
  background: var(--ice);
  color: #001423;
  border-color: var(--ice);
}
.btn-ice:hover { box-shadow: 0 0 22px var(--ice-glow); filter: brightness(1.05); }

.btn-goal {
  background: var(--goal); color: #001a10; border-color: var(--goal);
}
.btn-goal:hover { box-shadow: 0 0 22px var(--goal-glow); filter: brightness(1.05); }

.btn-puck {
  background: var(--puck); color: #1a0700; border-color: var(--puck);
}
.btn-puck:hover { box-shadow: 0 0 22px var(--puck-glow); filter: brightness(1.05); }

.btn-fire {
  background: var(--fire); color: #1a0700; border-color: var(--fire);
}
.btn-fire:hover { box-shadow: 0 0 22px var(--fire-glow); filter: brightness(1.05); }

.btn-danger {
  background: var(--penalty-a15);
  color: var(--penalty);
  border-color: var(--penalty-border);
}
.btn-danger:hover {
  background: var(--penalty);
  color: #1a0000;
  border-color: var(--penalty);
  box-shadow: 0 0 22px var(--penalty-glow);
}

.btn-ghost {
  background: transparent;
  color: var(--text);
  border-color: var(--border);
}
.btn-ghost:hover { background: var(--n-a5); border-color: var(--border-hover); }

.btn-sm { padding: 6px 12px; font-size: 0.78rem; }
.btn-lg { padding: 14px 24px; font-size: 0.95rem; }
.btn-block { display: flex; width: 100%; }

/* -----------------------------------------------------------------------
   Inputs
   --------------------------------------------------------------------- */
.input-field, textarea, select {
  width: 100%;
  background: var(--surface-2);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 10px;
  padding: 11px 14px;
  font-family: var(--font-body);
  font-size: 0.92rem;
  transition: border-color 0.18s var(--ease-out), box-shadow 0.18s var(--ease-out), background 0.18s var(--ease-out);
}
.input-field:focus,
textarea:focus,
select:focus {
  outline: none;
  border-color: var(--ice-a55);
  box-shadow: 0 0 0 3px var(--ice-a15);
  background: var(--surface);
}
.input-field::placeholder, textarea::placeholder {
  color: var(--text-mute);
}
textarea { min-height: 90px; resize: vertical; }
.input-error {
  border-color: var(--penalty-a55) !important;
  box-shadow: 0 0 0 3px var(--penalty-a15) !important;
}

label.field-label,
.field-label {
  display: block;
  font-family: var(--font-display);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-2);
  margin-bottom: 6px;
}
.field { margin-bottom: 18px; }
.field-help {
  display: block;
  margin-top: 6px;
  font-size: 0.78rem;
  color: var(--text-2);
}

/* -----------------------------------------------------------------------
   Badges + status pills
   --------------------------------------------------------------------- */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 10px;
  border-radius: 999px;
  font-family: var(--font-display);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  border: 1px solid transparent;
}
.badge-ice     { background: var(--ice-a15); color: var(--ice); border-color: var(--ice-border); }
.badge-goal    { background: var(--goal-a15); color: var(--goal); border-color: var(--goal-border); }
.badge-penalty { background: var(--penalty-a15); color: var(--penalty); border-color: var(--penalty-border); }
.badge-puck    { background: var(--puck-a15); color: var(--puck); border-color: var(--puck-border); }
.badge-zen     { background: var(--zen-a15); color: var(--zen); border-color: var(--zen-border); }
.badge-mute    { background: var(--n-a5); color: var(--text-2); border-color: var(--border); }

.status-active    { background: var(--goal-a15); color: var(--goal); border-color: var(--goal-border); }
.status-suspended { background: var(--puck-a15); color: var(--puck); border-color: var(--puck-border); }
.status-cancelled { background: var(--penalty-a15); color: var(--penalty); border-color: var(--penalty-border); }
.status-revoked   { background: var(--n-a5); color: var(--text-2); border-color: var(--border); }

/* Severity pills (security events) */
.severity-info     { background: var(--ice-a15); color: var(--ice); border-color: var(--ice-border); }
.severity-warning  { background: var(--puck-a15); color: var(--puck); border-color: var(--puck-border); }
.severity-critical { background: var(--penalty-a15); color: var(--penalty); border-color: var(--penalty-border); }

/* -----------------------------------------------------------------------
   Tables
   --------------------------------------------------------------------- */
.table-wrap {
  border: 1px solid var(--border);
  border-radius: 12px;
  overflow: hidden;
  background: var(--surface);
}
table.data-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.88rem;
}
.data-table thead th {
  background: var(--surface-2);
  text-align: left;
  font-family: var(--font-display);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-2);
  padding: 12px 14px;
  border-bottom: 1px solid var(--border);
}
.data-table tbody td {
  padding: 12px 14px;
  border-bottom: 1px solid var(--border);
  color: var(--text);
  vertical-align: top;
}
.data-table tbody tr:last-child td { border-bottom: 0; }
.data-table tbody tr:hover { background: var(--puck-a5); }
/* Clickable rows (row-link) get a slightly stronger warm wash + pointer so
   they clearly read as interactive (v8 UI pass). */
.data-table tbody tr.row-link:hover { background: var(--puck-a8); }
.data-table .num { text-align: right; font-variant-numeric: tabular-nums; }
.data-table .mono { font-family: var(--font-mono); font-size: 0.82rem; }
.data-table .muted { color: var(--text-2); }

/* -----------------------------------------------------------------------
   Auth pages
   --------------------------------------------------------------------- */
.auth-shell {
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 32px;
  background: radial-gradient(1100px 600px at 30% -10%, var(--ice-a8) 0%, transparent 60%),
              radial-gradient(800px 500px at 110% 110%, var(--zen-a8) 0%, transparent 60%),
              var(--bg);
}
.auth-card {
  width: 100%;
  max-width: 420px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 16px;
  padding: 32px;
  box-shadow: var(--shadow-lg);
}
.auth-brand {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.05rem;
  letter-spacing: 0.04em;
  margin-bottom: 8px;
  color: var(--text);
  display: flex;
  align-items: center;
  gap: 12px;
}
.auth-title {
  font-family: var(--font-display);
  font-size: 1.4rem;
  font-weight: 700;
  margin: 12px 0 6px;
  letter-spacing: -0.02em;
}
.auth-subtitle {
  color: var(--text-2);
  margin: 0 0 24px;
  font-size: 0.92rem;
}
.auth-card.is-admin .auth-brand { color: var(--puck); }
.auth-card.is-admin .auth-brand .sidebar-brand-mark {
  background: linear-gradient(135deg, var(--puck) 0%, var(--fire) 100%);
  box-shadow: 0 0 18px var(--puck-glow);
}

/* -----------------------------------------------------------------------
   Alerts
   --------------------------------------------------------------------- */
.alert {
  border-radius: 10px;
  padding: 12px 14px;
  margin-bottom: 16px;
  font-size: 0.9rem;
  border: 1px solid transparent;
}
.alert-error    { background: var(--penalty-a15); border-color: var(--penalty-border); color: var(--penalty); }
.alert-warning  { background: var(--puck-a15); border-color: var(--puck-border); color: var(--puck); }
.alert-success  { background: var(--goal-a15); border-color: var(--goal-border); color: var(--goal); }
.alert-info     { background: var(--ice-a15); border-color: var(--ice-border); color: var(--ice); }

/* -----------------------------------------------------------------------
   "Reveal once" boxes — for new API keys + temp passwords
   --------------------------------------------------------------------- */
.reveal-box {
  background: linear-gradient(180deg, var(--goal-a8) 0%, transparent 70%), var(--surface);
  border: 1px solid var(--goal-border);
  border-radius: 14px;
  padding: 22px 24px;
  margin-bottom: 24px;
}
.reveal-box .reveal-label {
  font-family: var(--font-display);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--goal);
  margin-bottom: 10px;
}
.reveal-box .reveal-value {
  font-family: var(--font-mono);
  font-size: 0.92rem;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 12px 14px;
  word-break: break-all;
  margin-bottom: 12px;
  color: var(--text);
}
.reveal-box .reveal-warning {
  font-size: 0.82rem;
  color: var(--puck);
  display: flex;
  align-items: flex-start;
  gap: 8px;
}

/* -----------------------------------------------------------------------
   Code-sample tabs (examples page)
   --------------------------------------------------------------------- */
.code-tabs {
  display: flex;
  gap: 4px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 0;
  padding: 0 4px;
}
.code-tab {
  background: transparent;
  border: 0;
  border-bottom: 2px solid transparent;
  padding: 10px 14px;
  font-family: var(--font-display);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  color: var(--text-2);
  cursor: pointer;
  transition: all 0.18s var(--ease-out);
}
.code-tab:hover { color: var(--text); }
.code-tab.active {
  color: var(--ice);
  border-bottom-color: var(--ice);
}
.code-panel { display: none; }
.code-panel.active { display: block; }

.code-block-wrap {
  position: relative;
  margin-bottom: 24px;
}
.code-block-wrap pre {
  margin: 0;
  border-top-left-radius: 0;
  border-top-right-radius: 0;
}
.code-tabs + .code-panel pre,
.code-block-wrap > pre:first-child {
  border-top-left-radius: 0;
  border-top-right-radius: 0;
}
.copy-btn {
  position: absolute;
  top: 10px;
  right: 10px;
  background: var(--surface-3);
  border: 1px solid var(--border);
  color: var(--text-2);
  padding: 5px 10px;
  border-radius: 6px;
  font-family: var(--font-display);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  cursor: pointer;
  transition: all 0.18s var(--ease-out);
}
.copy-btn:hover { color: var(--ice); border-color: var(--ice-border); }
.copy-btn.copied { color: var(--goal); border-color: var(--goal-border); }

/* -----------------------------------------------------------------------
   Forms layout helpers
   --------------------------------------------------------------------- */
.form-grid-2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}
@media (max-width: 720px) {
  .form-grid-2 { grid-template-columns: 1fr; }
}
.form-actions {
  display: flex;
  gap: 10px;
  align-items: center;
  margin-top: 8px;
}
.muted-text { color: var(--text-2); font-size: 0.86rem; }
.small-text { font-size: 0.82rem; }

/* -----------------------------------------------------------------------
   Filter bars
   --------------------------------------------------------------------- */
.filter-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
  margin-bottom: 18px;
  padding: 14px 16px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
}
.filter-bar > label {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 0.82rem;
  color: var(--text-2);
}
.filter-bar input,
.filter-bar select {
  padding: 6px 10px;
  font-size: 0.82rem;
}

/* -----------------------------------------------------------------------
   Misc utilities
   --------------------------------------------------------------------- */
.flex { display: flex; }
.flex-between { display: flex; justify-content: space-between; align-items: center; }
.flex-col { display: flex; flex-direction: column; }
.gap-8  { gap: 8px; }
.gap-12 { gap: 12px; }
.gap-16 { gap: 16px; }
.gap-24 { gap: 24px; }
.mb-8   { margin-bottom: 8px; }
.mb-16  { margin-bottom: 16px; }
.mb-24  { margin-bottom: 24px; }
.mb-32  { margin-bottom: 32px; }
.mt-16  { margin-top: 16px; }
.mt-24  { margin-top: 24px; }
.text-center { text-align: center; }
.font-mono { font-family: var(--font-mono); }
.font-display { font-family: var(--font-display); }
.muted { color: var(--text-2); }
.text-goal    { color: var(--goal); }
.text-penalty { color: var(--penalty); }
.text-puck    { color: var(--puck); }
.text-ice     { color: var(--ice); }

.divider {
  height: 1px;
  background: var(--border);
  margin: 24px 0;
}

/* Empty state */
.empty {
  text-align: center;
  padding: 48px 24px;
  color: var(--text-2);
}
.empty-icon {
  width: 56px; height: 56px;
  margin: 0 auto 14px;
  border-radius: 14px;
  background: var(--n-a5);
  display: grid; place-items: center;
  color: var(--text-mute);
}

/* -----------------------------------------------------------------------
   Animations
   --------------------------------------------------------------------- */
@keyframes fadeIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@keyframes slideUp {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes pop {
  0%   { transform: scale(0.95); opacity: 0; }
  60%  { transform: scale(1.02); }
  100% { transform: scale(1); opacity: 1; }
}
@keyframes spin {
  from { transform: rotate(0); } to { transform: rotate(360deg); }
}

.animate-fade-in  { animation: fadeIn 0.4s var(--ease-out) both; }
.animate-slide-up { animation: slideUp 0.4s var(--ease-out) both; }
.animate-pop      { animation: pop 0.35s var(--ease-out) both; }

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

/* -----------------------------------------------------------------------
   Mobile
   --------------------------------------------------------------------- */
@media (max-width: 900px) {
  .layout { grid-template-columns: 1fr; }
  .sidebar {
    position: relative;
    height: auto;
    border-right: 0;
    border-bottom: 1px solid var(--sidebar-border);
  }
  .main { padding: 24px 20px 60px; }
}

/* -----------------------------------------------------------------------
   Theme switcher (top of sidebar footer)
   --------------------------------------------------------------------- */
.theme-switcher {
  display: inline-flex;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 3px;
  gap: 2px;
}
.theme-switcher button {
  background: transparent;
  border: 0;
  padding: 4px 10px;
  border-radius: 999px;
  font-family: var(--font-display);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-2);
  cursor: pointer;
  transition: all 0.18s var(--ease-out);
}
.theme-switcher button[aria-pressed="true"] {
  background: var(--ice-a15);
  color: var(--ice);
}

/* ==========================================================================
   Template-specific composites
   Used by admin templates (logs/security/ip_bans/audit) and customer flows.
   These extend the base components with structural classes.
   ========================================================================== */

/* Reveal-box internals (one-shot secret display) ---------------------------- */
.reveal-header {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
  margin-bottom: var(--space-4);
}

.reveal-row {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-3) 0;
  border-top: 1px solid var(--border);
}
.reveal-row:first-of-type { border-top: none; }

.reveal-row .reveal-label {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 0.8125rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-2);
}

.reveal-value-wrap {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
}

.reveal-value-wrap .reveal-value {
  flex: 1;
  min-width: 0;
  word-break: break-all;
  padding: var(--space-3);
  background: var(--surface-3);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  font-family: var(--font-mono);
  font-size: 0.9375rem;
  color: var(--text);
}

[data-reveal-blur] {
  filter: blur(6px);
  cursor: pointer;
  transition: filter 200ms var(--ease-out);
  user-select: none;
}
[data-reveal-blur].is-revealed,
[data-reveal-blur]:focus {
  filter: none;
  user-select: text;
}

/* Action row (button cluster under cards / page headers) ------------------- */
.action-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  align-items: center;
}

/* Two-column grid for paired cards ----------------------------------------- */
.grid-2 {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--space-5);
}
@media (max-width: 900px) {
  .grid-2 { grid-template-columns: 1fr; }
}

/* Stacked form field grouping ---------------------------------------------- */
.stacked-form {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.form-field {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

/* Filter bar checkbox variant ---------------------------------------------- */
.filter-checkbox .field-label {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  cursor: pointer;
  text-transform: none;
  letter-spacing: normal;
  font-size: 0.875rem;
}

/* Inline toggle inside card headers ---------------------------------------- */
.inline-toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin-left: auto;
}
.inline-toggle .field-label {
  text-transform: none;
  letter-spacing: normal;
  font-size: 0.875rem;
  cursor: pointer;
}

/* Muted link (subtle inline action) ---------------------------------------- */
.muted-link {
  color: var(--text-2);
  text-decoration: underline;
  text-decoration-color: var(--border);
  text-underline-offset: 3px;
  font-size: 0.875rem;
  transition: color 150ms var(--ease-out);
}
.muted-link:hover { color: var(--ice); text-decoration-color: var(--ice-a40); }

/* Security event feed ------------------------------------------------------ */
.event-feed {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.event-card {
  padding: var(--space-4) var(--space-5);
}

.event-head {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
  margin-bottom: var(--space-3);
}

.event-type {
  font-size: 0.875rem;
  color: var(--text);
}

.event-time {
  margin-left: auto;
  font-size: 0.8125rem;
  color: var(--text-2);
}

.event-body {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.event-message {
  margin: 0;
  color: var(--text);
  line-height: 1.5;
}

.event-meta {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-1) var(--space-4);
  margin: 0;
  font-size: 0.875rem;
}
.event-meta dt {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-2);
  align-self: center;
}
.event-meta dd { margin: 0; color: var(--text); }

.event-extra {
  border-top: 1px solid var(--border);
  padding-top: var(--space-3);
}
.event-extra summary {
  cursor: pointer;
  font-size: 0.8125rem;
  color: var(--text-2);
  user-select: none;
}
.event-extra summary:hover { color: var(--ice); }
.event-extra pre {
  margin: var(--space-3) 0 0;
  padding: var(--space-3);
  background: var(--surface-3);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  overflow-x: auto;
  font-size: 0.8125rem;
  color: var(--text);
}

/* Severity badges (already mapped via badge-* mods, but explicit aliases) -- */
.severity-info     { background: var(--ice-a8); color: var(--ice); border-color: var(--ice-a40); }
.severity-warning  { background: var(--puck-a8); color: var(--puck); border-color: var(--puck-a40); }
.severity-critical { background: var(--penalty-a8); color: var(--penalty); border-color: var(--penalty-a40); }


/* ==========================================================================
   Final missing utilities (filter bar layout, button + badge variants)
   ========================================================================== */

.filter-field {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  min-width: 160px;
}

.filter-actions {
  display: flex;
  gap: var(--space-2);
  align-items: flex-end;
  margin-left: auto;
}

.btn-penalty {
  background: var(--penalty);
  color: #fff;
  border-color: var(--penalty);
}
.btn-penalty:hover {
  background: var(--penalty-a55);
  border-color: var(--penalty-a55);
}

.badge-fire {
  background: var(--fire-a8);
  color: var(--fire);
  border-color: var(--fire-a40);
}

/* =======================================================================
   Onboarding wizard
   =======================================================================
   These styles live with the rest of the design system rather than in a
   feature-scoped file because the same tokens (ice/goal/penalty/zen) need
   to stay coordinated with the rest of the Game Day palette.
   ======================================================================= */

/* Wider auth card for the wizard's multi-field forms.
   Same chrome as .auth-card, just more horizontal room. */
.auth-card.is-wizard {
  max-width: 640px;
}

/* Step indicator row — the four dots at the top of every wizard page.
   Uses CSS counter trick: the connecting line is a single ::before on the
   <ol> sized to span between dot centers. */
.wizard-steps {
  list-style: none;
  margin: 0 0 28px;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(var(--wizard-step-count, 4), 1fr);
  position: relative;
  counter-reset: wstep;
}
/* Connecting baseline behind the dots */
.wizard-steps::before {
  content: "";
  position: absolute;
  left: calc(100% / var(--wizard-step-count, 4) / 2);
  right: calc(100% / var(--wizard-step-count, 4) / 2);
  top: 18px;
  height: 2px;
  background: var(--border);
  z-index: 0;
}
.wizard-step {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  font-size: 0.78rem;
  color: var(--text-2);
  font-family: var(--font-display);
  letter-spacing: 0.02em;
}
.wizard-step-dot {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: var(--surface);
  border: 2px solid var(--border);
  color: var(--text-2);
  display: grid;
  place-items: center;
  font-weight: 600;
  font-family: var(--font-display);
  font-size: 0.95rem;
  transition: all 0.25s var(--ease-out);
}
.wizard-step.is-current .wizard-step-dot {
  background: var(--ice);
  border-color: var(--ice);
  color: #001423;
  box-shadow: 0 0 0 4px var(--ice-a15), 0 0 18px var(--ice-glow);
  transform: scale(1.06);
}
.wizard-step.is-current .wizard-step-label {
  color: var(--text);
}
.wizard-step.is-done .wizard-step-dot {
  background: var(--goal);
  border-color: var(--goal);
  color: #001a10;
}
.wizard-step.is-done .wizard-step-dot::before {
  /* checkmark replaces the number on completed steps */
  content: "✓";
}
.wizard-step.is-done .wizard-step-num {
  display: none;
}

/* Review-page key/value list — matches the form-grid-2 muted-label idiom
   used elsewhere in the admin so the wizard "feels" like the rest. */
.wizard-review {
  margin: 0 0 8px;
  display: grid;
  grid-template-columns: 1fr;
  gap: 16px;
}
.wizard-review-item {
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 14px 16px;
  background: var(--surface-2, var(--surface));
}
.wizard-review-item-label {
  font-size: 0.74rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-2);
  font-family: var(--font-display);
  margin-bottom: 6px;
}
.wizard-review-item-value {
  font-size: 0.95rem;
  line-height: 1.5;
}
.wizard-review-item-value .wizard-review-line { display: block; }
.wizard-review-item-value .muted-text { font-size: 0.84rem; }

/* The "agree to terms" check — gives the checkbox a comfortable click
   target and makes it obvious this is the gate. */
.wizard-terms {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  padding: 14px 16px;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--ice-a5, var(--surface));
  margin: 8px 0 4px;
  cursor: pointer;
  transition: border-color 0.15s var(--ease-out);
}
.wizard-terms:hover { border-color: var(--ice-border); }
.wizard-terms input[type="checkbox"] { margin-top: 3px; }

/* End-state hero block for done.html / closed.html.
   Big colored ring around an icon/glyph to give these pages a sense
   of arrival rather than reading like an error page. */
.wizard-result {
  text-align: center;
  padding: 12px 0 4px;
}
.wizard-result-mark {
  width: 84px;
  height: 84px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  margin: 0 auto 18px;
  font-size: 2.4rem;
  font-weight: 600;
  font-family: var(--font-display);
  border: 2px solid;
}
.wizard-result-mark.is-success {
  color: var(--goal);
  background: var(--goal-a15);
  border-color: var(--goal-border);
  box-shadow: 0 0 32px var(--goal-glow, rgba(52, 211, 153, 0.35));
}
.wizard-result-mark.is-pending {
  color: var(--ice);
  background: var(--ice-a15);
  border-color: var(--ice-border);
  box-shadow: 0 0 32px var(--ice-glow);
}
.wizard-result-mark.is-warning {
  color: var(--puck);
  background: var(--puck-a15);
  border-color: var(--puck-border);
}
.wizard-result-mark.is-neutral {
  color: var(--text-2);
  background: var(--n-a5);
  border-color: var(--border);
}
.wizard-result-mark.is-error {
  color: var(--penalty);
  background: var(--penalty-a15);
  border-color: var(--penalty-border);
}

/* =======================================================================
   Onboarding status badges
   =======================================================================
   The OnboardingStatus enum has 7 values; map each to an existing palette
   accent so they read consistently with .status-active/.suspended/etc.
   ======================================================================= */
.status-pending     { background: var(--ice-a15);     color: var(--ice);     border-color: var(--ice-border);     }
.status-in_progress { background: var(--puck-a15);    color: var(--puck);    border-color: var(--puck-border);    }
.status-submitted   { background: var(--zen-a15);     color: var(--zen);     border-color: var(--zen-border);     }
.status-approved    { background: var(--goal-a15);    color: var(--goal);    border-color: var(--goal-border);    }
.status-rejected    { background: var(--penalty-a15); color: var(--penalty); border-color: var(--penalty-border); }
.status-expired     { background: var(--n-a5);        color: var(--text-2);  border-color: var(--border);         }
/* status-revoked already exists; reuse it */

/* =======================================================================
   Filter chip row — used by the onboarding index for the status filter.
   Generic enough that other pages can reuse it.
   ======================================================================= */
.chip-row {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  align-items: center;
  margin-bottom: 18px;
}
.chip-row .btn-sm {
  padding: 5px 12px;
}

/* =======================================================================
   One-shot reveal panel
   =======================================================================
   The boxed block that shows freshly-minted invitation URLs and temp
   passwords on the admin detail page. Was a pile of inline styles; now
   a real component that matches the rest of the app.
   ======================================================================= */
.reveal-panel {
  margin-top: 14px;
  padding: 14px 16px;
  background: var(--n-a5);
  border: 1px solid var(--border);
  border-radius: 10px;
}
.reveal-panel-caption {
  font-size: 0.78rem;
  color: var(--text-2);
  margin-bottom: 6px;
  display: flex;
  gap: 6px;
  align-items: center;
}
.reveal-panel-value {
  font-family: var(--font-mono);
  word-break: break-all;
  color: var(--text);
  margin: 4px 0 12px;
  font-size: 0.92rem;
  line-height: 1.5;
}
.reveal-panel-value .reveal-row {
  display: block;
}
.reveal-panel-value strong {
  font-family: var(--font-display);
  color: var(--text-2);
  font-weight: 500;
  margin-right: 6px;
}

/* =======================================================================
   Filter grid — used by /admin/logs and /admin/security
   =======================================================================
   A responsive 4-column grid that wraps gracefully on narrow viewports.
   The .field children inside use the standard input-field styling, so
   nothing here re-implements field chrome — only layout.
   ======================================================================= */
.filter-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 16px 16px;
  align-items: end;
}
.filter-grid .field { margin-bottom: 0; }

@media (max-width: 1100px) {
  .filter-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 600px) {
  .filter-grid { grid-template-columns: 1fr; }
}

/* Small numeric column right-alignment in data tables */
.data-table th.num,
.data-table td.num {
  text-align: right;
  white-space: nowrap;
}

/* =======================================================================
   Provider chip — radio button styled as a tab/chip on /admin/alerts
   ======================================================================= */
.chip {
  display: inline-flex;
  align-items: center;
  padding: 8px 12px;
  border: 1px solid var(--border, #2a2a2a);
  border-radius: 8px;
  background: var(--surface, #111);
  font-size: 0.875rem;
  cursor: pointer;
  user-select: none;
}
.chip:hover { border-color: var(--ice, #4ad); }
.chip:has(input:checked) {
  border-color: var(--ice, #4ad);
  background: var(--ice-a10, rgba(74, 170, 221, 0.08));
}

/* =======================================================================
   v8 cosmetic pass — loading feedback, richer empty states, stat icons,
   personality. All ADDITIVE (new classes only) so existing styles are
   untouched. Reuses the existing @keyframes spin.
   ======================================================================= */

/* ---- Spinner + button loading state -------------------------------- */
.spinner {
  display: inline-block;
  width: 16px; height: 16px;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: spin 0.6s linear infinite;
  vertical-align: -3px;
}
.spinner-lg { width: 28px; height: 28px; border-width: 3px; }

/* A button in the loading state: dims, shows a spinner, blocks clicks.
   Add .is-loading and (optionally) a <span class="spinner"> — or rely on the
   ::before below which injects one automatically before the label. */
.btn.is-loading {
  position: relative;
  color: transparent !important;
  pointer-events: none;
  cursor: progress;
}
.btn.is-loading::after {
  content: "";
  position: absolute;
  width: 16px; height: 16px;
  top: 50%; left: 50%;
  margin: -8px 0 0 -8px;
  border: 2px solid rgba(255,255,255,0.65);
  border-right-color: transparent;
  border-radius: 50%;
  animation: spin 0.6s linear infinite;
}
/* Ghost/light buttons need a dark spinner for contrast. */
.btn-ghost.is-loading::after,
.btn-light.is-loading::after { border-color: rgba(0,0,0,0.45); border-right-color: transparent; }

/* Inline "working…" row for async panels (sandbox/EDT result areas). */
.loading-row {
  display: flex; align-items: center; gap: 10px;
  padding: 18px 4px;
  color: var(--text-2);
  font-size: 0.9rem;
}
.loading-row .spinner { color: var(--ice); }

/* A thin top progress shimmer for whole-page async (optional hook). */
.async-veil { position: relative; }
.async-veil[aria-busy="true"]::before {
  content: "";
  position: absolute; inset: 0 0 auto 0; height: 2px;
  background: linear-gradient(90deg, transparent, var(--ice), transparent);
  background-size: 50% 100%;
  animation: shimmer 1.1s ease-in-out infinite;
  border-radius: 2px 2px 0 0;
}
@keyframes shimmer {
  0%   { background-position: -100% 0; }
  100% { background-position: 200% 0; }
}

/* ---- Unified, richer empty state ----------------------------------- */
/* One component to replace the three ad-hoc patterns (.empty, .empty-state,
   prose). Friendlier: larger tinted icon, title, hint line, optional CTA. */
.emptystate {
  text-align: center;
  padding: 44px 24px;
  display: flex; flex-direction: column; align-items: center;
  gap: 6px;
}
.emptystate-art {
  width: 64px; height: 64px;
  margin-bottom: 10px;
  border-radius: 18px;
  display: grid; place-items: center;
  color: var(--ice);
  background:
    radial-gradient(120% 120% at 30% 20%, var(--ice-a8), transparent 60%),
    var(--surface-2);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-sm);
}
.emptystate-art svg { width: 30px; height: 30px; }
.emptystate-art.tone-puck   { color: var(--puck);   background: radial-gradient(120% 120% at 30% 20%, var(--puck-a8), transparent 60%), var(--surface-2); }
.emptystate-art.tone-goal   { color: var(--goal);   background: radial-gradient(120% 120% at 30% 20%, var(--goal-a8, rgba(61,220,151,0.10)), transparent 60%), var(--surface-2); }
.emptystate-art.tone-mute   { color: var(--text-mute); background: var(--surface-2); }
.emptystate-title {
  font-family: var(--font-display);
  font-size: 1.05rem; font-weight: 600;
  color: var(--text);
  margin: 0;
}
.emptystate-hint {
  color: var(--text-2);
  font-size: 0.9rem;
  max-width: 44ch;
  margin: 0;
  line-height: 1.55;
}
.emptystate-actions { margin-top: 14px; display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; }

/* ---- Stat-card icon support (dashboard personality) ---------------- */
/* Lets a stat card carry a soft accent-tinted icon in the top-right without
   changing the existing markup for cards that don't use one. */
.stat-card.has-icon { padding-right: 64px; }
.stat-icon {
  position: absolute;
  top: 16px; right: 16px;
  width: 34px; height: 34px;
  border-radius: 10px;
  display: grid; place-items: center;
  color: var(--accent, var(--ice));
  background: color-mix(in srgb, var(--accent, var(--ice)) 14%, transparent);
}
.stat-icon svg { width: 18px; height: 18px; }
/* subtle entrance for the stat row */
.stat-card { transition: transform 0.2s var(--ease-out), border-color 0.2s var(--ease-out); }
.stat-card:hover { transform: translateY(-2px); border-color: var(--border-hover); }

/* ---- Section heading with eyebrow (welcoming dashboard) ------------ */
.eyebrow {
  font-family: var(--font-display);
  font-size: 0.68rem; font-weight: 700;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--ice);
  margin-bottom: 6px;
}

/* ---- Quick-action tiles (dashboard) -------------------------------- */
.quick-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 14px;
}
.quick-tile {
  display: flex; align-items: center; gap: 12px;
  padding: 16px 18px;
  border-radius: 14px;
  background: linear-gradient(180deg, var(--surface-2) 0%, var(--surface) 70%);
  border: 1px solid var(--border);
  color: var(--text);
  text-decoration: none;
  transition: transform 0.18s var(--ease-out), border-color 0.18s var(--ease-out), box-shadow 0.18s var(--ease-out);
}
.quick-tile:hover {
  transform: translateY(-2px);
  border-color: var(--border-hover);
  box-shadow: var(--shadow-lg);
}
.quick-tile-icon {
  flex: 0 0 38px; width: 38px; height: 38px;
  border-radius: 10px;
  display: grid; place-items: center;
  color: var(--accent, var(--ice));
  background: color-mix(in srgb, var(--accent, var(--ice)) 14%, transparent);
}
.quick-tile-icon svg { width: 20px; height: 20px; }
.quick-tile-body { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.quick-tile-title { font-weight: 600; font-size: 0.95rem; }
.quick-tile-sub { color: var(--text-2); font-size: 0.8rem; }
.quick-tile.tone-puck { --accent: var(--puck); }
.quick-tile.tone-goal { --accent: var(--goal); }
.quick-tile.tone-zen  { --accent: var(--zen); }

/* =======================================================================
   v8 cosmetic pass 2 — staggered entrance, table polish, richer auth.
   Additive only. Respects prefers-reduced-motion.
   ======================================================================= */

/* ---- Staggered content reveal -------------------------------------- */
/* Opt-in: add .reveal to a container; its DIRECT children cascade in.
   The <main> already fades in as a whole; this adds per-section rhythm.
   Pure CSS, no JS — uses nth-child delays. Caps at 10 to bound the stagger. */
.reveal > * {
  animation: revealUp 0.45s var(--ease-out) both;
}
.reveal > *:nth-child(1) { animation-delay: 0.02s; }
.reveal > *:nth-child(2) { animation-delay: 0.07s; }
.reveal > *:nth-child(3) { animation-delay: 0.12s; }
.reveal > *:nth-child(4) { animation-delay: 0.17s; }
.reveal > *:nth-child(5) { animation-delay: 0.22s; }
.reveal > *:nth-child(6) { animation-delay: 0.27s; }
.reveal > *:nth-child(7) { animation-delay: 0.32s; }
.reveal > *:nth-child(8) { animation-delay: 0.37s; }
.reveal > *:nth-child(9) { animation-delay: 0.42s; }
.reveal > *:nth-child(n+10) { animation-delay: 0.46s; }
@keyframes revealUp {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Honour reduced-motion: disable ALL entrance motion for users who ask. */
@media (prefers-reduced-motion: reduce) {
  .reveal > *,
  .animate-fade-in, .animate-slide-up, .animate-pop {
    animation: none !important;
  }
}

/* ---- Table polish -------------------------------------------------- */
/* Zebra striping for scan-ability on dense tables (logs/customers/audit).
   Subtle — a 3% warm wash on odd rows. Hover still wins over the stripe. */
.data-table tbody tr:nth-child(odd) { background: rgba(255,255,255,0.018); }
.data-table tbody tr { transition: background 0.12s var(--ease-out); }
.data-table tbody tr:hover,
.data-table tbody tr:nth-child(odd):hover { background: var(--puck-a5); }
.data-table tbody tr.row-link:hover,
.data-table tbody tr.row-link:nth-child(odd):hover { background: var(--puck-a8); }

/* Sticky header so column labels stay visible when a long table scrolls
   inside a scroll container. Harmless on short tables. */
.data-table thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  backdrop-filter: blur(2px);
}
/* A touch more breathing room + a crisper header underline. */
.data-table thead th { border-bottom: 1.5px solid var(--border-hover); }
.data-table tbody td { font-variant-numeric: tabular-nums; }

/* Wrap tables in this to get rounded corners + a contained scroll area. */
.table-wrap {
  border: 1px solid var(--border);
  border-radius: 14px;
  overflow: hidden;       /* clips the header/row corners */
  overflow-x: auto;       /* horizontal scroll on small screens */
}
.table-wrap .data-table { font-size: 0.86rem; }
.table-wrap .data-table thead th:first-child { border-top-left-radius: 14px; }
.table-wrap .data-table thead th:last-child  { border-top-right-radius: 14px; }

/* ---- Richer auth (login / TOTP first impression) ------------------- */
/* Animated aurora behind the auth card — slow, subtle, premium. The existing
   .auth-shell radial gradients stay; this adds gentle motion on top. */
.auth-shell { position: relative; overflow: hidden; }
.auth-shell::before {
  content: "";
  position: absolute;
  inset: -40%;
  background:
    radial-gradient(closest-side at 30% 30%, var(--ice-a8), transparent),
    radial-gradient(closest-side at 70% 60%, var(--zen-a8), transparent),
    radial-gradient(closest-side at 50% 80%, var(--puck-a8), transparent);
  filter: blur(40px);
  opacity: 0.7;
  animation: authDrift 18s ease-in-out infinite alternate;
  z-index: 0;
  pointer-events: none;
}
@keyframes authDrift {
  0%   { transform: translate(-3%, -2%) rotate(0deg) scale(1); }
  100% { transform: translate(3%, 2%) rotate(8deg) scale(1.08); }
}
.auth-card { position: relative; z-index: 1; }
/* Brand mark gets a soft glow so it reads as the focal point. */
.auth-card .auth-brand .sidebar-brand-mark {
  box-shadow: 0 0 0 1px var(--border), 0 6px 18px var(--ice-a8);
}
.auth-card.is-admin .auth-brand .sidebar-brand-mark {
  box-shadow: 0 0 0 1px var(--border), 0 6px 18px var(--puck-a8);
}
/* Slightly larger, more confident title on auth. */
.auth-title { font-size: 1.6rem; }
@media (prefers-reduced-motion: reduce) {
  .auth-shell::before { animation: none; }
}

/* ---- Validation-log status cell -------------------------------------
   The badge carries a native title= tooltip with the full plain-English
   explanation (native rather than a styled popup because .table-wrap is
   overflow:hidden / overflow-x:auto and would clip an absolutely
   positioned one). cursor:help advertises that hovering does something.
   The short label beside it means the common cases are readable without
   hovering at all; it hides on narrow screens where width is precious. */
.status-cell {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  cursor: help;
}
.status-cell .status-hint {
  font-size: 0.75rem;
  line-height: 1.2;
  max-width: 190px;
}
@media (max-width: 1200px) {
  .status-cell .status-hint { display: none; }
}
