/* =============================================================
   Structech EV Charging Platform — Super Admin Console
   Custom Enterprise Design System
   ============================================================= */

/* ---------- Design Tokens ---------- */
:root {
  /* Brand */
  --brand-700: #0B6E4F;   /* Primary */
  --brand-600: #138A5E;
  --brand-500: #16A34A;   /* Secondary */
  --brand-400: #22C55E;   /* Accent */
  --brand-300: #4ADE80;
  --brand-100: #DCFCE7;
  --brand-050: #F0FDF4;

  /* Neutral gray scale */
  --gray-25:  #FCFCFD;
  --gray-50:  #F9FAFB;
  --gray-100: #F2F4F7;
  --gray-200: #E4E7EC;
  --gray-300: #D0D5DD;
  --gray-400: #98A2B3;
  --gray-500: #667085;
  --gray-600: #475467;
  --gray-700: #344054;
  --gray-800: #1D2939;
  --gray-900: #101828;
  --gray-950: #0A0F1A;

  /* Semantic */
  --success: #16A34A;
  --success-bg: #ECFDF3;
  --warning: #D97706;
  --warning-bg: #FFFAEB;
  --danger:  #D92D20;
  --danger-bg: #FEF3F2;
  --info:    #2563EB;
  --info-bg: #EFF6FF;
  --purple:  #7C3AED;
  --purple-bg: #F5F3FF;

  /* Surfaces (light) */
  --bg-app: #F5F7FA;
  --bg-surface: #FFFFFF;
  --bg-surface-2: #F9FAFB;
  --bg-elevated: #FFFFFF;
  --bg-sidebar: #0B1F19;
  --bg-sidebar-active: rgba(34, 197, 94, 0.14);
  --bg-hover: #F2F4F7;

  --text-strong: #101828;
  --text-default: #344054;
  --text-muted: #667085;
  --text-faint: #98A2B3;
  --text-onbrand: #FFFFFF;
  --text-sidebar: #C5D0CB;
  --text-sidebar-muted: #7A8C84;

  --border: #E4E7EC;
  --border-strong: #D0D5DD;
  --border-light: #F2F4F7;

  /* Effects */
  --radius-xs: 6px;
  --radius-sm: 8px;
  --radius-md: 10px;
  --radius-lg: 14px;
  --radius-xl: 20px;
  --radius-full: 999px;

  --shadow-xs: 0 1px 2px rgba(16,24,40,.05);
  --shadow-sm: 0 1px 3px rgba(16,24,40,.08), 0 1px 2px rgba(16,24,40,.04);
  --shadow-md: 0 4px 8px -2px rgba(16,24,40,.08), 0 2px 4px -2px rgba(16,24,40,.04);
  --shadow-lg: 0 12px 24px -6px rgba(16,24,40,.10), 0 4px 8px -4px rgba(16,24,40,.06);
  --shadow-xl: 0 24px 48px -12px rgba(16,24,40,.18);

  --ring: 0 0 0 4px rgba(22,163,74,.14);

  --sidebar-w: 264px;
  --sidebar-w-collapsed: 80px;
  --header-h: 68px;

  --font: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --transition: 180ms cubic-bezier(.4,0,.2,1);

  /* Scrollbar (light surfaces — body, cards, modals, dropdowns, tables) */
  --scrollbar-thumb: var(--gray-300);
  --scrollbar-thumb-hover: var(--gray-400);
}

/* ---------- Dark theme ---------- */
[data-theme="dark"] {
  --bg-app: #0A0F1A;
  --bg-surface: #111827;
  --bg-surface-2: #0E1623;
  --bg-elevated: #161F2E;
  --bg-sidebar: #070D0B;
  --bg-sidebar-active: rgba(34, 197, 94, 0.16);
  --bg-hover: #1A2333;

  --text-strong: #F9FAFB;
  --text-default: #E4E7EC;
  --text-muted: #98A2B3;
  --text-faint: #667085;
  --text-sidebar: #C5D0CB;
  --text-sidebar-muted: #6B7D75;

  --border: #1F2937;
  --border-strong: #2D3A4D;
  --border-light: #1A2333;

  --gray-50:  #0E1623;
  --gray-100: #161F2E;
  --gray-200: #1F2937;

  --success-bg: rgba(22,163,74,.14);
  --warning-bg: rgba(217,119,6,.16);
  --danger-bg: rgba(217,45,32,.16);
  --info-bg: rgba(37,99,235,.16);
  --purple-bg: rgba(124,58,237,.18);

  --shadow-xs: 0 1px 2px rgba(0,0,0,.4);
  --shadow-sm: 0 1px 3px rgba(0,0,0,.5);
  --shadow-md: 0 4px 12px rgba(0,0,0,.45);
  --shadow-lg: 0 16px 32px rgba(0,0,0,.55);
  --shadow-xl: 0 28px 56px rgba(0,0,0,.6);

  /* Scrollbar — reuse the same faint/muted grays dark theme already uses
     for --text-faint/--text-muted, proven legible on these dark surfaces. */
  --scrollbar-thumb: var(--gray-500);
  --scrollbar-thumb-hover: var(--gray-400);
}

/* ---------- Reset ---------- */
/* scrollbar-width doesn't inherit like scrollbar-color does — every
   individual overflow container needs its own copy, so it rides the same
   universal selector as box-sizing rather than living only on html/body
   (see the Scrollbar block below for the rest of the thin-scrollbar setup). */
*, *::before, *::after { box-sizing: border-box; scrollbar-width: thin; }
html, body { margin: 0; padding: 0; }
body {
  font-family: var(--font);
  background: var(--bg-app);
  color: var(--text-default);
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
a { color: inherit; text-decoration: none; }
button { font-family: inherit; cursor: pointer; border: none; background: none; }
input, select, textarea { font-family: inherit; font-size: 14px; }
svg { display: block; }
::selection { background: var(--brand-100); color: var(--brand-700); }

/* Scrollbar — thin, theme-aware, applied globally (body, sidebar, modal
   content, dropdowns/Select2, tables, and any other overflow container).
   `scrollbar-width: thin` is set on the universal `*` selector above since,
   unlike scrollbar-color, it does NOT inherit — every individual overflow
   box needs its own copy. `scrollbar-color` genuinely does inherit, so one
   copy on `html` reaches every descendant; per-surface overrides (e.g.
   .sidebar-nav, always dark regardless of app theme) just override the
   thumb color, never the width — one thin size everywhere. */
html { scrollbar-color: var(--scrollbar-thumb) transparent; }
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-corner { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--scrollbar-thumb); border-radius: 999px; border: 1px solid transparent; background-clip: content-box; }
::-webkit-scrollbar-thumb:hover { background: var(--scrollbar-thumb-hover); background-clip: content-box; }

/* =============================================================
   Layout
   ============================================================= */
.app-shell { display: flex; min-height: 100vh; }

/* ---------- Sidebar ---------- */
.sidebar {
  width: var(--sidebar-w);
  flex-shrink: 0;
  background: var(--bg-sidebar);
  color: var(--text-sidebar);
  position: fixed;
  inset: 0 auto 0 0;
  display: flex;
  flex-direction: column;
  z-index: 60;
  transition: width var(--transition), transform var(--transition);
  border-right: 1px solid rgba(255,255,255,.04);
}
.sidebar-brand {
  height: var(--header-h);
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 0 20px;
  flex-shrink: 0;
}
.brand-logo {
  width: 38px; height: 38px;
  border-radius: 11px;
  background: linear-gradient(135deg, var(--brand-400), var(--brand-700));
  display: grid; place-items: center;
  box-shadow: 0 4px 14px rgba(34,197,94,.35);
  flex-shrink: 0;
}
.brand-logo svg { width: 22px; height: 22px; }
.brand-text { display: flex; flex-direction: column; line-height: 1.15; overflow: hidden; }
.brand-text .name { color: #fff; font-weight: 700; font-size: 15px; letter-spacing: -.01em; white-space: nowrap; }
.brand-text .sub { color: var(--text-sidebar-muted); font-size: 11px; font-weight: 500; white-space: nowrap; }

/* Scrollbar hidden — still scrolls via wheel/trackpad/touch/keyboard,
   overflow-y:auto below is untouched, just nothing is painted for it. */
.sidebar-nav { flex: 1; overflow-y: auto; padding: 8px 12px 20px; scrollbar-width: none; }
.sidebar-nav::-webkit-scrollbar { display: none; width: 0; height: 0; }

.nav-group { margin-top: 18px; }
.nav-group:first-child { margin-top: 6px; }
.nav-group-label {
  color: var(--text-sidebar-muted);
  font-size: 10.5px; font-weight: 700;
  letter-spacing: .08em; text-transform: uppercase;
  padding: 0 12px 8px;
  white-space: nowrap;
}
.nav-item {
  display: flex; align-items: center; gap: 12px;
  padding: 9px 12px; margin-bottom: 2px;
  border-radius: var(--radius-sm);
  color: var(--text-sidebar);
  font-weight: 500; font-size: 13.5px;
  transition: background var(--transition), color var(--transition);
  position: relative; white-space: nowrap;
}
.nav-item:hover { background: rgba(255,255,255,.05); color: #fff; }
.nav-item.active { background: var(--bg-sidebar-active); color: #fff; }
.nav-item.active::before {
  content: ''; position: absolute; left: -12px; top: 50%; transform: translateY(-50%);
  width: 3px; height: 22px; border-radius: 0 3px 3px 0; background: var(--brand-400);
}
.nav-item svg { width: 19px; height: 19px; flex-shrink: 0; opacity: .9; }
.nav-item.active svg { color: var(--brand-300); opacity: 1; }
.nav-item .nav-text { flex: 1; overflow: hidden; }
.nav-badge {
  background: var(--brand-500); color: #fff;
  font-size: 11px; font-weight: 700;
  padding: 1px 7px; border-radius: var(--radius-full); min-width: 20px; text-align: center;
}
.nav-badge.amber { background: var(--warning); }

.sidebar-foot { padding: 14px 16px; border-top: 1px solid rgba(255,255,255,.06); flex-shrink: 0; }
.sidebar-upsell {
  background: linear-gradient(135deg, rgba(34,197,94,.16), rgba(11,110,79,.10));
  border: 1px solid rgba(34,197,94,.22);
  border-radius: var(--radius-md); padding: 14px;
}
.sidebar-upsell .t { color: #fff; font-weight: 600; font-size: 13px; margin-bottom: 3px; }
.sidebar-upsell .d { color: var(--text-sidebar-muted); font-size: 11.5px; margin-bottom: 10px; }
.sidebar-upsell .bar { height: 6px; background: rgba(255,255,255,.1); border-radius: 999px; overflow: hidden; }
.sidebar-upsell .bar > span { display: block; height: 100%; background: linear-gradient(90deg, var(--brand-400), var(--brand-300)); border-radius: 999px; }

/* Collapsed sidebar */
.app-shell.collapsed .sidebar { width: var(--sidebar-w-collapsed); }
.app-shell.collapsed .brand-text,
.app-shell.collapsed .nav-text,
.app-shell.collapsed .nav-group-label,
.app-shell.collapsed .nav-badge,
.app-shell.collapsed .sidebar-foot { display: none; }
.app-shell.collapsed .nav-item { justify-content: center; padding: 11px; }
.app-shell.collapsed .sidebar-brand { justify-content: center; padding: 0; }
.app-shell.collapsed .main { margin-left: var(--sidebar-w-collapsed); }

/* ---------- Main ---------- */
.main {
  flex: 1; margin-left: var(--sidebar-w);
  display: flex; flex-direction: column; min-width: 0;
  transition: margin var(--transition);
}

/* ---------- Header ---------- */
.header {
  height: var(--header-h); flex-shrink: 0;
  background: color-mix(in srgb, var(--bg-surface) 85%, transparent);
  backdrop-filter: saturate(180%) blur(12px);
  border-bottom: 1px solid var(--border);
  display: flex; align-items: center; gap: 16px;
  padding: 0 28px; position: sticky; top: 0; z-index: 50;
}
.icon-btn {
  width: 40px; height: 40px; border-radius: var(--radius-sm);
  display: grid; place-items: center; color: var(--text-muted);
  transition: background var(--transition), color var(--transition);
  position: relative; flex-shrink: 0;
}
.icon-btn:hover { background: var(--bg-hover); color: var(--text-strong); }
.icon-btn svg { width: 20px; height: 20px; }
.icon-btn .dot {
  position: absolute; top: 8px; right: 9px; width: 8px; height: 8px;
  background: var(--danger); border-radius: 50%; border: 2px solid var(--bg-surface);
}

.global-search {
  flex: 1; max-width: 460px; position: relative;
}
.global-search svg { position: absolute; left: 14px; top: 50%; transform: translateY(-50%); width: 18px; height: 18px; color: var(--text-faint); }
.global-search input {
  width: 100%; height: 42px; padding: 0 14px 0 42px;
  background: var(--bg-surface-2); border: 1px solid var(--border);
  border-radius: var(--radius-md); color: var(--text-default);
  transition: border var(--transition), box-shadow var(--transition), background var(--transition);
}
.global-search input::placeholder { color: var(--text-faint); }
.global-search input:focus { outline: none; border-color: var(--brand-400); background: var(--bg-surface); box-shadow: var(--ring); }
.global-search .kbd {
  position: absolute; right: 12px; top: 50%; transform: translateY(-50%);
  display: flex; gap: 3px;
}
.kbd kbd {
  font-family: var(--font); font-size: 11px; font-weight: 600; color: var(--text-faint);
  background: var(--bg-surface); border: 1px solid var(--border); border-radius: 5px;
  padding: 1px 6px; box-shadow: var(--shadow-xs);
}
.header-spacer { flex: 1; }
.header-actions { display: flex; align-items: center; gap: 6px; }
.header-divider { width: 1px; height: 28px; background: var(--border); margin: 0 6px; }

.profile-chip {
  display: flex; align-items: center; gap: 10px; padding: 5px 10px 5px 6px;
  border-radius: var(--radius-full); transition: background var(--transition);
}
.profile-chip:hover { background: var(--bg-hover); }
.profile-chip > svg { width: 18px; height: 18px; color: var(--text-faint); flex-shrink: 0; }
.avatar {
  width: 36px; height: 36px; border-radius: 50%; flex-shrink: 0;
  display: grid; place-items: center; font-weight: 700; font-size: 13px; color: #fff;
  background: linear-gradient(135deg, var(--brand-500), var(--brand-700));
}
.avatar.sm { width: 30px; height: 30px; font-size: 11px; }
.avatar.lg { width: 56px; height: 56px; font-size: 18px; }
.profile-chip .meta { line-height: 1.2; }
.profile-chip .meta .n { font-weight: 600; color: var(--text-strong); font-size: 13px; }
.profile-chip .meta .r { color: var(--text-muted); font-size: 11.5px; }

/* ---------- Content ----------
   No max-width — .content always fills 100% of whatever space .main
   (flex:1, offset by the sidebar's own margin-left) actually has, at every
   viewport width, same as .header (this same .main's other flex child,
   which has never had a width cap of its own and always spans .main's
   full width flush against the sidebar). A max-width here used to leave a
   large empty gutter on the right on wide/ultra-wide monitors — cards/
   tables/DataTables/forms stretch to fill the real available width
   instead. No margin:0 auto either — with no cap there's nothing left to
   center, and this keeps .content's left edge permanently identical to
   .header's regardless of viewport width. */
.content { padding: 26px 28px 60px; flex: 1; width: 100%; }
.page-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 20px; margin-bottom: 24px; flex-wrap: wrap; }
.breadcrumb { display: flex; align-items: center; gap: 7px; color: var(--text-muted); font-size: 12.5px; margin-bottom: 8px; flex-wrap: wrap; }
.breadcrumb a:hover { color: var(--brand-600); }
.breadcrumb .sep { color: var(--text-faint); }
.breadcrumb .current { color: var(--text-default); font-weight: 500; }
.page-title { font-size: 24px; font-weight: 700; color: var(--text-strong); letter-spacing: -.02em; margin: 0; }
.page-sub { color: var(--text-muted); font-size: 13.5px; margin-top: 4px; max-width: 640px; }
.page-actions { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }

/* =============================================================
   Components
   ============================================================= */

/* Buttons */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  height: 40px; padding: 0 16px; border-radius: var(--radius-sm);
  font-weight: 600; font-size: 13.5px; white-space: nowrap;
  transition: all var(--transition); border: 1px solid transparent;
}
.btn svg { width: 17px; height: 17px; }
.btn-primary { background: var(--brand-700); color: #fff; box-shadow: var(--shadow-xs); }
.btn-primary:hover { background: var(--brand-600); box-shadow: var(--shadow-sm); }
.btn-secondary { background: var(--bg-surface); color: var(--text-default); border-color: var(--border-strong); box-shadow: var(--shadow-xs); }
.btn-secondary:hover { background: var(--bg-hover); border-color: var(--gray-400); }
.btn-ghost { color: var(--text-muted); }
.btn-ghost:hover { background: var(--bg-hover); color: var(--text-strong); }
.btn-danger { background: var(--danger); color: #fff; }
.btn-danger:hover { filter: brightness(.94); }
.btn-success { background: var(--brand-500); color: #fff; }
.btn-success:hover { background: var(--brand-600); }
.btn-sm { height: 34px; padding: 0 12px; font-size: 13px; }
.btn-sm svg { width: 15px; height: 15px; }
.btn-icon-only { padding: 0; width: 40px; }
.btn-icon-only.btn-sm { width: 34px; }
.btn:disabled { opacity: .5; pointer-events: none; }

/* Cards */
.card {
  background: var(--bg-surface); border: 1px solid var(--border);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-sm);
}
.card-head { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 18px 20px; border-bottom: 1px solid var(--border-light); }
.card-head .ttl { font-size: 15px; font-weight: 650; color: var(--text-strong); }
.card-head .ttl small { display: block; font-size: 12px; font-weight: 400; color: var(--text-muted); margin-top: 2px; }
.card-body { padding: 20px; }
.card-body.tight { padding: 0; }
/* Optional icon badge preceding a card-head title — same tone tokens as
   .kpi-icon (see .kpi-icon.sm below), just wrapped inline with the title
   text instead of floated top-right like a KPI card's own icon. */
.card-head .ttl-row { display: flex; align-items: center; gap: 9px; }

/* Grid helpers */
.grid { display: grid; gap: 20px; }
.kpi-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 18px; }
.grid-2 { grid-template-columns: repeat(2, 1fr); }
.grid-3 { grid-template-columns: repeat(3, 1fr); }
.span-2 { grid-column: span 2; }
.span-3 { grid-column: span 3; }
.dash-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }

/* KPI cards */
.kpi {
  background: var(--bg-surface); border: 1px solid var(--border);
  border-radius: var(--radius-lg); padding: 20px; box-shadow: var(--shadow-sm);
  position: relative; overflow: hidden; transition: box-shadow var(--transition), transform var(--transition);
}
.kpi:hover { box-shadow: var(--shadow-md); transform: translateY(-2px); }
.kpi-top { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; }
.kpi-icon { width: 42px; height: 42px; border-radius: var(--radius-md); display: grid; place-items: center; }
.kpi-icon svg { width: 21px; height: 21px; }
.kpi-icon.green { background: var(--brand-050); color: var(--brand-600); }
.kpi-icon.blue { background: var(--info-bg); color: var(--info); }
.kpi-icon.amber { background: var(--warning-bg); color: var(--warning); }
.kpi-icon.purple { background: var(--purple-bg); color: var(--purple); }
.kpi-icon.red { background: var(--danger-bg); color: var(--danger); }
[data-theme="dark"] .kpi-icon.green { background: rgba(22,163,74,.16); color: var(--brand-300); }
.kpi-label { color: var(--text-muted); font-size: 13px; font-weight: 500; }
.kpi-value { font-size: 28px; font-weight: 750; color: var(--text-strong); letter-spacing: -.02em; margin: 6px 0 2px; line-height: 1; }
.kpi-foot { display: flex; align-items: center; gap: 8px; margin-top: 12px; }
.delta { display: inline-flex; align-items: center; gap: 3px; font-weight: 650; font-size: 12.5px; padding: 2px 7px; border-radius: var(--radius-full); }
.delta svg { width: 13px; height: 13px; }
.delta.up { color: var(--success); background: var(--success-bg); }
.delta.down { color: var(--danger); background: var(--danger-bg); }
.delta.flat { color: var(--text-muted); background: var(--bg-hover); }
.kpi-foot .ctx { color: var(--text-faint); font-size: 12px; }
.kpi-spark { position: absolute; right: 0; bottom: 0; width: 110px; height: 48px; opacity: .85; }

/* Badges */
.badge {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 2px 9px; border-radius: var(--radius-full);
  font-size: 12px; font-weight: 600; line-height: 1.6; white-space: nowrap;
}
.badge .bdot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.badge.green  { color: var(--success); background: var(--success-bg); }
.badge.amber  { color: var(--warning); background: var(--warning-bg); }
.badge.red    { color: var(--danger);  background: var(--danger-bg); }
.badge.blue   { color: var(--info);    background: var(--info-bg); }
.badge.purple { color: var(--purple);  background: var(--purple-bg); }
.badge.gray   { color: var(--text-muted); background: var(--bg-hover); }

/* Tables */
.table-wrap { width: 100%; overflow-x: auto; }
.table { width: 100%; border-collapse: collapse; font-size: 13.5px; }
.table thead th {
  text-align: left; padding: 11px 18px; background: var(--bg-surface-2);
  color: var(--text-muted); font-weight: 600; font-size: 12px;
  letter-spacing: .02em; text-transform: uppercase; white-space: nowrap;
  border-bottom: 1px solid var(--border); position: sticky; top: 0;
}
.table thead th.sortable { cursor: pointer; user-select: none; }
.table thead th.sortable:hover { color: var(--text-default); }
.table thead th.sortable .th-in svg { transition: transform .15s ease; }
.table thead th.sorted { color: var(--brand-700); }
.table thead th.sorted .th-in svg { opacity: 1; color: var(--brand-600); }
.table thead th.sorted[aria-sort="descending"] .th-in svg { transform: rotate(180deg); }
.table thead th .th-in { display: inline-flex; align-items: center; gap: 5px; }
.table thead th svg { width: 13px; height: 13px; opacity: .6; }
.table tbody td { padding: 14px 18px; border-bottom: 1px solid var(--border-light); color: var(--text-default); vertical-align: middle; }
.table tbody tr { transition: background var(--transition); }
.table tbody tr:hover { background: var(--bg-surface-2); }
.table tbody tr:last-child td { border-bottom: none; }
.table .cell-strong { color: var(--text-strong); font-weight: 600; }
.table .cell-muted { color: var(--text-muted); font-size: 12.5px; }
.cell-id { font-family: ui-monospace, 'SF Mono', Menlo, monospace; font-size: 12.5px; color: var(--text-muted); }
.cell-user { display: flex; align-items: center; gap: 11px; }
.cell-user .meta .n { font-weight: 600; color: var(--text-strong); }
.cell-user .meta .e { color: var(--text-muted); font-size: 12px; }
.checkbox {
  width: 18px; height: 18px; border-radius: 5px; border: 1.5px solid var(--border-strong);
  background: var(--bg-surface); appearance: none; cursor: pointer; position: relative; transition: all var(--transition);
}
.checkbox:checked { background: var(--brand-600); border-color: var(--brand-600); }
.checkbox:checked::after { content: ''; position: absolute; left: 5px; top: 1.5px; width: 5px; height: 9px; border: solid #fff; border-width: 0 2px 2px 0; transform: rotate(45deg); }

/* Table toolbar */
.table-toolbar { display: flex; align-items: center; gap: 12px; padding: 16px 20px; border-bottom: 1px solid var(--border-light); flex-wrap: wrap; }
.table-toolbar .search-mini { position: relative; flex: 1; min-width: 200px; max-width: 320px; }
.table-toolbar .search-mini svg { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); width: 16px; height: 16px; color: var(--text-faint); }
.table-toolbar .search-mini input {
  width: 100%; height: 38px; padding: 0 12px 0 36px; background: var(--bg-surface-2);
  border: 1px solid var(--border); border-radius: var(--radius-sm); color: var(--text-default);
}
.table-toolbar .search-mini input:focus { outline: none; border-color: var(--brand-400); box-shadow: var(--ring); }
.toolbar-spacer { flex: 1; }

/* Select / inputs */
.field { display: flex; flex-direction: column; gap: 6px; }
.field label { font-size: 12.5px; font-weight: 600; color: var(--text-default); }
.field .hint { font-size: 12px; color: var(--text-muted); }
.input, .select, textarea.input {
  height: 40px; padding: 0 12px; background: var(--bg-surface);
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm); color: var(--text-default);
  transition: border var(--transition), box-shadow var(--transition); width: 100%;
}
textarea.input { height: auto; padding: 10px 12px; resize: vertical; min-height: 90px; }
.input:focus, .select:focus, textarea.input:focus { outline: none; border-color: var(--brand-400); box-shadow: var(--ring); }
.select {
  appearance: none; cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23667085' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 10px center; padding-right: 34px;
}
.filter-select {
  height: 38px; padding: 0 30px 0 12px; background: var(--bg-surface);
  border: 1px solid var(--border); border-radius: var(--radius-sm); color: var(--text-default);
  font-weight: 500; font-size: 13px; cursor: pointer; appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23667085' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 9px center;
}
.filter-select:focus { outline: none; border-color: var(--brand-400); box-shadow: var(--ring); }
.toggle { position: relative; display: inline-block; width: 42px; height: 24px; flex-shrink: 0; }
.toggle input { opacity: 0; width: 0; height: 0; }
.toggle .slider { position: absolute; inset: 0; background: var(--gray-300); border-radius: 999px; transition: var(--transition); }
.toggle .slider::before { content: ''; position: absolute; width: 18px; height: 18px; left: 3px; top: 3px; background: #fff; border-radius: 50%; transition: var(--transition); box-shadow: var(--shadow-sm); }
.toggle input:checked + .slider { background: var(--brand-500); }
.toggle input:checked + .slider::before { transform: translateX(18px); }
.segmented { display: inline-flex; background: var(--bg-surface-2); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 3px; gap: 2px; }
.segmented button { padding: 5px 12px; border-radius: 6px; font-size: 12.5px; font-weight: 600; color: var(--text-muted); transition: all var(--transition); }
.segmented button.active { background: var(--bg-surface); color: var(--brand-700); box-shadow: var(--shadow-xs); }
[data-theme="dark"] .segmented button.active { color: var(--brand-300); background: var(--bg-elevated); }

/* Station Owner Management — clickable KYC status badge (opens the quick
   KYC-status modal) and its tone-aware segmented status picker inside that
   modal. .badge-btn is an invisible button wrapper so the badge looks
   identical to a plain <span> at rest, with just a subtle hover/focus
   affordance signalling it's interactive. */
.badge-btn { background: none; border: none; padding: 0; cursor: pointer; border-radius: 999px; }
.badge-btn:hover .badge { filter: brightness(.94); }
.badge-btn:focus-visible { outline: 2px solid var(--brand-400); outline-offset: 2px; border-radius: 999px; }

.kyc-segmented { width: 100%; justify-content: space-between; }
.kyc-segmented .kyc-seg-btn { flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: 5px; }
.kyc-seg-btn.active.tone-green { color: var(--success); background: var(--success-bg); }
.kyc-seg-btn.active.tone-amber { color: var(--warning); background: var(--warning-bg); }
.kyc-seg-btn.active.tone-red   { color: var(--danger);  background: var(--danger-bg); }

/* Pagination */
.pagination { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 14px 20px; border-top: 1px solid var(--border-light); flex-wrap: wrap; }
.pagination .info { color: var(--text-muted); font-size: 13px; }
.pagination .pages { display: flex; gap: 4px; align-items: center; }
.page-btn {
  min-width: 36px; height: 36px; padding: 0 6px; border-radius: var(--radius-sm);
  display: grid; place-items: center; color: var(--text-muted); font-weight: 600; font-size: 13px;
  border: 1px solid transparent; transition: all var(--transition);
}
.page-btn:hover { background: var(--bg-hover); color: var(--text-strong); }
.page-btn.active { background: var(--brand-700); color: #fff; }
.page-btn:disabled { opacity: .4; pointer-events: none; }
.page-btn svg { width: 16px; height: 16px; }

/* Action menu (row dropdown) */
.menu-wrap { position: relative; display: inline-block; }
.menu {
  position: absolute; right: 0; top: calc(100% + 6px); min-width: 188px; z-index: 30;
  background: var(--bg-elevated); border: 1px solid var(--border); border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg); padding: 6px; display: none;
}
.menu.open { display: block; animation: pop .14s ease; }
.menu-item { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: var(--radius-xs); color: var(--text-default); font-size: 13px; font-weight: 500; width: 100%; transition: background var(--transition); }
.menu-item:hover { background: var(--bg-hover); }
.menu-item svg { width: 16px; height: 16px; color: var(--text-muted); }
.menu-item.danger { color: var(--danger); }
.menu-item.danger svg { color: var(--danger); }
.menu-sep { height: 1px; background: var(--border-light); margin: 6px 4px; }
@keyframes pop { from { opacity: 0; transform: translateY(-4px) scale(.98); } to { opacity: 1; transform: none; } }

/* Notification / profile dropdown — #profileDd is rendered as a sibling of
   .app-shell (see layouts/app.blade.php), not nested inside the sticky
   .header, so it has no positioned ancestor to anchor to. `position: fixed`
   (not `absolute`) is required: the header is `position: sticky; top: 0`
   and stays pinned to the viewport at any scroll depth, but an absolutely
   positioned element with no positioned ancestor anchors to the top of the
   whole document instead — it would drift away from the header (or off
   the visible viewport entirely) as soon as the page is scrolled. Fixed
   positioning anchors to the viewport itself, exactly matching where the
   sticky header visually sits regardless of scroll position. */
.dropdown {
  position: fixed; right: 28px; top: calc(var(--header-h) - 6px); width: 380px; z-index: 70;
  background: var(--bg-elevated); border: 1px solid var(--border); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xl); display: none; overflow: hidden;
  max-height: calc(100vh - var(--header-h) - 20px); overflow-y: auto;
}
.dropdown.open { display: block; animation: pop .16s ease; }
.dropdown.profile-dd { width: 260px; }
.dd-head { padding: 16px 18px; border-bottom: 1px solid var(--border-light); display: flex; align-items: center; justify-content: space-between; }
.dd-head .t { font-weight: 650; color: var(--text-strong); font-size: 14px; }
.dd-head a { color: var(--brand-600); font-size: 12.5px; font-weight: 600; }
.dd-list { max-height: 380px; overflow-y: auto; }
.notif {
  display: flex; gap: 12px; padding: 13px 18px; border-bottom: 1px solid var(--border-light); transition: background var(--transition); cursor: pointer;
}
.notif:hover { background: var(--bg-surface-2); }
.notif.unread { background: color-mix(in srgb, var(--brand-050) 60%, transparent); }
[data-theme="dark"] .notif.unread { background: rgba(34,197,94,.06); }
.notif-ic { width: 36px; height: 36px; border-radius: var(--radius-sm); display: grid; place-items: center; flex-shrink: 0; }
.notif-ic svg { width: 18px; height: 18px; }
.notif .body .t { font-size: 13px; color: var(--text-strong); font-weight: 600; }
.notif .body .d { font-size: 12.5px; color: var(--text-muted); margin: 2px 0; }
.notif .body .time { font-size: 11.5px; color: var(--text-faint); }
.dd-foot { padding: 12px; text-align: center; }
.dd-menu-item { display: flex; align-items: center; gap: 11px; padding: 10px 16px; color: var(--text-default); font-size: 13.5px; font-weight: 500; transition: background var(--transition); }
.dd-menu-item:hover { background: var(--bg-hover); }
.dd-menu-item svg { width: 18px; height: 18px; color: var(--text-muted); }

/* Modal */
.overlay {
  position: fixed; inset: 0; background: rgba(16,24,40,.55); backdrop-filter: blur(3px);
  z-index: 90; display: none; align-items: flex-start; justify-content: center; padding: 60px 20px; overflow-y: auto;
}
.overlay.open { display: flex; animation: fade .2s ease; }
.modal {
  background: var(--bg-surface); border-radius: var(--radius-xl); box-shadow: var(--shadow-xl);
  width: 100%; max-width: 560px; animation: rise .25s cubic-bezier(.2,.8,.2,1); border: 1px solid var(--border);
}
.modal.lg { max-width: 760px; }
.modal.xl { max-width: 980px; }
.modal-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; padding: 22px 24px 18px; border-bottom: 1px solid var(--border-light); }
.modal-head .t { font-size: 17px; font-weight: 700; color: var(--text-strong); letter-spacing: -.01em; }
.modal-head .s { font-size: 13px; color: var(--text-muted); margin-top: 3px; }
.modal-body { padding: 22px 24px; max-height: 64vh; overflow-y: auto; }
.modal-foot { display: flex; align-items: center; justify-content: flex-end; gap: 10px; padding: 16px 24px; border-top: 1px solid var(--border-light); background: var(--bg-surface-2); border-radius: 0 0 var(--radius-xl) var(--radius-xl); }
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes rise { from { opacity: 0; transform: translateY(16px) scale(.98); } to { opacity: 1; transform: none; } }

/* Form grid */
.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px 18px; }
.form-grid .full { grid-column: 1 / -1; }

/* Tabs */
.tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--border); margin-bottom: 22px; overflow-x: auto; }
.tab { padding: 12px 16px; font-weight: 600; font-size: 13.5px; color: var(--text-muted); border-bottom: 2px solid transparent; transition: all var(--transition); white-space: nowrap; }
.tab:hover { color: var(--text-default); }
.tab.active { color: var(--brand-700); border-bottom-color: var(--brand-600); }
[data-theme="dark"] .tab.active { color: var(--brand-300); }

/* Misc */
.muted { color: var(--text-muted); }
.text-strong { color: var(--text-strong); font-weight: 600; }
.flex { display: flex; }
.items-center { align-items: center; }
.justify-between { justify-content: space-between; }
.gap-8 { gap: 8px; } .gap-12 { gap: 12px; } .gap-16 { gap: 16px; } .gap-20 { gap: 20px; }
.mt-8 { margin-top: 8px; } .mt-16 { margin-top: 16px; } .mt-20 { margin-top: 20px; } .mt-24 { margin-top: 24px; }
.mb-0 { margin-bottom: 0; }
.wrap { flex-wrap: wrap; }
.divider { height: 1px; background: var(--border-light); margin: 18px 0; }
.tag { display: inline-flex; align-items: center; gap: 5px; padding: 3px 9px; background: var(--bg-hover); border-radius: var(--radius-sm); font-size: 12px; font-weight: 600; color: var(--text-default); }
.progress { height: 8px; background: var(--bg-hover); border-radius: 999px; overflow: hidden; }
.progress > span { display: block; height: 100%; border-radius: 999px; background: linear-gradient(90deg, var(--brand-500), var(--brand-400)); }

/* Legend */
.legend { display: flex; gap: 18px; flex-wrap: wrap; }
.legend .li { display: flex; align-items: center; gap: 7px; font-size: 12.5px; color: var(--text-muted); font-weight: 500; }
.legend .sw { width: 11px; height: 11px; border-radius: 3px; }

/* Empty / list rows */
.list-row { display: flex; align-items: center; gap: 14px; padding: 14px 0; border-bottom: 1px solid var(--border-light); }
.list-row:last-child { border-bottom: none; }
.rank { width: 26px; height: 26px; border-radius: 8px; display: grid; place-items: center; font-weight: 700; font-size: 12px; background: var(--bg-hover); color: var(--text-muted); flex-shrink: 0; }
.rank.top { background: var(--brand-700); color: #fff; }

/* Toast */
.toast-host { position: fixed; bottom: 26px; right: 26px; z-index: 100; display: flex; flex-direction: column; gap: 10px; }
.toast {
  display: flex; align-items: center; gap: 12px; background: var(--bg-elevated); border: 1px solid var(--border);
  border-radius: var(--radius-md); box-shadow: var(--shadow-lg); padding: 13px 16px; min-width: 300px; max-width: 400px;
  animation: slidein .25s cubic-bezier(.2,.8,.2,1);
}
.toast .ic { width: 32px; height: 32px; border-radius: 8px; display: grid; place-items: center; flex-shrink: 0; }
.toast .ic svg { width: 18px; height: 18px; }
.toast.success .ic { background: var(--success-bg); color: var(--success); }
.toast.info .ic { background: var(--info-bg); color: var(--info); }
.toast .msg { font-size: 13.5px; color: var(--text-strong); font-weight: 500; }
@keyframes slidein { from { opacity: 0; transform: translateX(40px); } to { opacity: 1; transform: none; } }

/* Mobile backdrop */
.scrim { position: fixed; inset: 0; background: rgba(16,24,40,.5); z-index: 55; display: none; }
.scrim.open { display: block; }
.mobile-only { display: none; }

/* Stat strip */
.stat-strip { display: flex; gap: 28px; flex-wrap: wrap; }
.stat-strip .s .l { font-size: 12px; color: var(--text-muted); font-weight: 500; }
.stat-strip .s .v { font-size: 20px; font-weight: 700; color: var(--text-strong); margin-top: 2px; }

/* Chart helpers */
.chart-svg { width: 100%; height: auto; display: block; overflow: visible; }
.donut-wrap { display: flex; align-items: center; gap: 24px; flex-wrap: wrap; }
.donut-center { text-align: center; }
/* Donut ring polish — soft depth on the whole ring, plus a hover-dim/
   highlight pair on individual segments (donutChart()'s .donut-seg
   circles) so pointing at one slice visually recedes the rest. */
.donut-ring { filter: drop-shadow(0 3px 8px rgba(16,24,40,.08)); }
[data-theme="dark"] .donut-ring { filter: drop-shadow(0 3px 10px rgba(0,0,0,.35)); }
.donut-seg { cursor: pointer; transition: opacity .15s ease, filter .15s ease; }
.donut-wrap:hover .donut-seg:not(:hover) { opacity: .35; }
.donut-seg:hover { filter: brightness(1.08); }
.donut-center-value { font-weight: 750; color: var(--text-strong); letter-spacing: -.01em; line-height: 1; }
.donut-center-label { color: var(--text-muted); margin-top: 4px; }

/* geoMap()'s per-city dots (Dashboard's Geographic Density + Station
   Management's Network Coverage cards) — same hover affordance as the
   donut segments above, opted into the shared styled chart tooltip via
   wireChartTooltips() per consumer (see stations/manage.blade.php). */
.geo-dot { cursor: pointer; transition: opacity .15s ease; }
.geo-dot:hover { opacity: .82; }

/* lineAreaChart()'s optional per-point hit-targets (opt-in via a series'
   own `name`, see ui.js) — invisible, larger than the visible dot
   underneath, purely to make hovering a specific point on a thin line
   chart actually easy to land on; the shared chart tooltip does the rest. */
.line-chart-hit { cursor: pointer; }

/* funnelChart()'s per-stage bar track — only the stages carrying a real
   drop-off tooltip (every stage but the first) get the pointer cursor. */
.funnel-bar-track[data-tip-label] { cursor: pointer; }

/* Top Stations list — the utilisation .progress bar doubles as the
   hover-popup trigger for that row's real underlying booking count. */
.progress[data-tip-label] { cursor: pointer; }

/* Recent Activity timeline — each event dot doubles as the hover-popup
   trigger showing what actually changed (see summarizeAuditDiff() in
   dashboard.blade.php). */
.tl-dot[data-tip-label] { cursor: pointer; }

/* Shared chart tooltip (see wireChartTooltips() in ui.js) — a small
   floating pill that follows the cursor, styled like the rest of the
   theme (bg-elevated, border, shadow-md) instead of the unstyled native
   SVG <title> tooltip. */
.chart-tooltip {
  position: fixed; z-index: 9999; pointer-events: none;
  display: flex; align-items: center; gap: 7px;
  background: var(--bg-elevated); border: 1px solid var(--border);
  border-radius: var(--radius-sm); padding: 7px 11px;
  font-size: 12.5px; font-weight: 600; color: var(--text-strong);
  box-shadow: var(--shadow-md); white-space: nowrap;
  opacity: 0; transform: translateY(4px);
  transition: opacity .12s ease, transform .12s ease;
}
.chart-tooltip.show { opacity: 1; transform: translateY(0); }
.chart-tooltip-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
.chart-tooltip-val { color: var(--text-muted); font-weight: 500; }

/* Heatmap */
.heatmap { display: grid; gap: 3px; }
.heatcell { aspect-ratio: 1; border-radius: 3px; min-width: 14px; }

/* Avatars stack */
.avatar-stack { display: flex; }
.avatar-stack .avatar { border: 2px solid var(--bg-surface); margin-left: -10px; }
.avatar-stack .avatar:first-child { margin-left: 0; }
.avatar-stack .more { width: 30px; height: 30px; border-radius: 50%; background: var(--bg-hover); color: var(--text-muted); display: grid; place-items: center; font-size: 11px; font-weight: 700; border: 2px solid var(--bg-surface); margin-left: -10px; }

/* Detail rows */
.detail-list { display: grid; gap: 0; }
.detail-list .row { display: flex; justify-content: space-between; gap: 16px; padding: 11px 0; border-bottom: 1px solid var(--border-light); font-size: 13.5px; }
.detail-list .row:last-child { border-bottom: none; }
.detail-list .row .k { color: var(--text-muted); }
.detail-list .row .v { color: var(--text-strong); font-weight: 600; text-align: right; }

/* Timeline */
.timeline { position: relative; padding-left: 26px; }
.timeline::before { content: ''; position: absolute; left: 8px; top: 4px; bottom: 4px; width: 2px; background: var(--border); }
.tl-item { position: relative; padding-bottom: 20px; }
.tl-item:last-child { padding-bottom: 0; }
.tl-dot { position: absolute; left: -26px; top: 2px; width: 18px; height: 18px; border-radius: 50%; background: var(--bg-surface); border: 3px solid var(--brand-500); }
.tl-dot.gray { border-color: var(--gray-300); }
.tl-item .t { font-weight: 600; color: var(--text-strong); font-size: 13.5px; }
.tl-item .d { color: var(--text-muted); font-size: 12.5px; margin-top: 2px; }
.tl-item .time { color: var(--text-faint); font-size: 11.5px; margin-top: 3px; }

/* =============================================================
   Live Operations Map
   ============================================================= */
.ops-grid { grid-template-columns: 1fr 360px; }
@media (max-width: 1024px) { .ops-grid { grid-template-columns: 1fr; } }
.map-stage { position: relative; background:
  radial-gradient(1000px 500px at 70% -10%, rgba(22,163,74,.06), transparent 60%),
  var(--bg-surface-2); border-radius: var(--radius-md); overflow: hidden; min-height: 540px; display: grid; place-items: center; padding: 12px; }
.map-stage svg { width: 100%; height: 100%; max-height: 560px; }
.map-pin { cursor: pointer; transition: r .15s ease; }
.map-pin:hover { r: 8; }
.map-pin.sel { stroke: var(--text-strong); stroke-width: 2.5; }
.map-pulse { transform-box: fill-box; transform-origin: center; animation: mapPulse 2.2s ease-out infinite; }
@keyframes mapPulse { 0% { transform: scale(.5); opacity: .55; } 100% { transform: scale(2.6); opacity: 0; } }
.map-legend { position: absolute; left: 16px; bottom: 16px; background: var(--bg-surface); border: 1px solid var(--border); border-radius: var(--radius-md); padding: 12px 14px; box-shadow: var(--shadow-md); display: flex; flex-direction: column; gap: 8px; }
.map-legend .li { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--text-default); font-weight: 500; }
.map-legend .li .sw { width: 10px; height: 10px; border-radius: 50%; }
.map-zoom { position: absolute; right: 16px; bottom: 16px; display: flex; flex-direction: column; gap: 6px; }
.ops-panel-empty { display: grid; place-items: center; text-align: center; height: 100%; min-height: 340px; color: var(--text-faint); padding: 24px; }
.ops-panel-empty .ic { width: 56px; height: 56px; border-radius: 14px; background: var(--bg-hover); display: grid; place-items: center; margin: 0 auto 14px; color: var(--text-muted); }
.ops-panel-empty .ic svg { width: 26px; height: 26px; }
.ops-feed-row { display: flex; align-items: center; gap: 11px; padding: 11px 0; border-bottom: 1px solid var(--border-light); }
.ops-feed-row:last-child { border-bottom: none; }
.ops-feed-row .pdot { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; }

/* =============================================================
   Authentication (Login / MFA) — two-panel: brand aside + form.
   Shared by every identity type (Super Admin, Station Owner,
   future roles), so the aside carries neutral platform framing,
   not admin-specific copy or fabricated trust stats.
   ============================================================= */
.auth-wrap { min-height: 100vh; display: grid; grid-template-columns: 1.05fr 0.95fr; }

/* Left brand panel */
.auth-aside {
  position: relative; overflow: hidden; color: #fff;
  background:
    radial-gradient(1100px 520px at -8% -12%, rgba(34,197,94,.30), transparent 55%),
    radial-gradient(900px 600px at 110% 120%, rgba(22,163,74,.28), transparent 55%),
    linear-gradient(150deg, #0B6E4F 0%, #08493340 0%, #073D2C 55%, #052017 100%);
  padding: 52px 56px; display: flex; flex-direction: column; justify-content: center; gap: 40px;
}
.auth-aside .grid-bg { position: absolute; inset: 0; opacity: .5;
  background-image: linear-gradient(rgba(255,255,255,.04) 1px, transparent 1px), linear-gradient(90deg, rgba(255,255,255,.04) 1px, transparent 1px);
  background-size: 44px 44px; mask-image: radial-gradient(circle at 30% 40%, #000, transparent 75%); }
.auth-aside .glow { position: absolute; width: 380px; height: 380px; border-radius: 50%; filter: blur(70px); background: rgba(34,197,94,.35); top: -120px; right: -80px; }
.auth-brand { display: flex; align-items: center; gap: 13px; position: relative; z-index: 2; }
.auth-brand .brand-logo { width: 44px; height: 44px; box-shadow: 0 10px 28px rgba(0,0,0,.35); }
.auth-brand .brand-logo .bi { font-size: 24px; }
.auth-brand .t { font-weight: 700; font-size: 17px; letter-spacing: -.01em; }
.auth-brand .s { font-size: 12px; color: rgba(255,255,255,.6); }
.auth-hero { position: relative; z-index: 2; max-width: 480px; }
.auth-hero h1 { font-size: 34px; font-weight: 750; line-height: 1.18; letter-spacing: -.025em; margin: 0 0 16px; }
.auth-hero p { font-size: 15px; color: rgba(255,255,255,.78); line-height: 1.6; margin: 0 0 30px; }
.auth-feat { display: flex; flex-direction: column; gap: 16px; }
.auth-feat .f { display: flex; gap: 13px; align-items: flex-start; }
.auth-feat .f .ic { width: 38px; height: 38px; border-radius: 11px; background: rgba(255,255,255,.10); border: 1px solid rgba(255,255,255,.08); display: grid; place-items: center; flex-shrink: 0; }
.auth-feat .f .ic .bi { font-size: 19px; color: var(--brand-300); }
.auth-feat .f .tx .t { font-weight: 600; font-size: 14px; }
.auth-feat .f .tx .d { font-size: 12.5px; color: rgba(255,255,255,.62); margin-top: 1px; }

/* Right form panel */
.auth-main { position: relative; display: grid; place-items: center; padding: 40px 24px; background: var(--bg-app); }
.auth-theme { position: absolute; top: 22px; right: 22px; z-index: 3; }
.auth-card {
  width: 100%; max-width: 410px; animation: rise .4s cubic-bezier(.2,.8,.2,1);
  background: var(--bg-surface); border: 1px solid var(--border); border-radius: var(--radius-xl);
  box-shadow: var(--shadow-lg); padding: 40px 38px;
}
@media (max-width: 480px) { .auth-card { padding: 28px 22px; } }
.auth-card .head { margin-bottom: 26px; }
.auth-card .head h2 { font-size: 24px; font-weight: 700; color: var(--text-strong); margin: 0 0 7px; letter-spacing: -.015em; }
.auth-card .head p { color: var(--text-muted); font-size: 14px; margin: 0; line-height: 1.5; }
.auth-form { display: flex; flex-direction: column; gap: 17px; }
.input-icon { position: relative; }
.input-icon > svg:first-child { position: absolute; left: 14px; top: 50%; transform: translateY(-50%); width: 18px; height: 18px; color: var(--text-faint); pointer-events: none; }
.input-icon .input { padding-left: 42px; height: 46px; }
.input-icon .eye-btn { position: absolute; right: 6px; top: 50%; transform: translateY(-50%); width: 34px; height: 34px; border-radius: 7px; display: grid; place-items: center; color: var(--text-faint); }
.input-icon .eye-btn:hover { background: var(--bg-hover); color: var(--text-muted); }
.input-icon .eye-btn svg { width: 18px; height: 18px; }
.auth-row { display: flex; align-items: center; justify-content: space-between; margin: -2px 0; }
.checkline { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--text-default); cursor: pointer; }
.auth-link { color: var(--brand-600); font-weight: 600; font-size: 13px; }
.auth-link:hover { color: var(--brand-700); text-decoration: underline; }
.auth-card .btn-block { height: 47px; font-size: 14.5px; width: 100%; margin-top: 2px; }
.auth-secure { display: flex; align-items: center; justify-content: center; gap: 7px; margin-top: 22px; font-size: 12px; color: var(--text-faint); }
.auth-secure svg { width: 14px; height: 14px; }
.auth-foot { text-align: center; margin-top: 26px; font-size: 12.5px; color: var(--text-faint); }

/* MFA step */
.mfa-id { display: flex; align-items: center; gap: 12px; padding: 13px 14px; border: 1px solid var(--border); border-radius: var(--radius-md); background: var(--bg-surface-2); margin-bottom: 22px; }
.mfa-id .meta { flex: 1; min-width: 0; }
.mfa-id .meta .n { font-weight: 600; color: var(--text-strong); font-size: 13.5px; }
.mfa-id .meta .e { color: var(--text-muted); font-size: 12.5px; }
.mfa-id > svg { width: 22px; height: 22px; color: var(--brand-500); flex-shrink: 0; }
.otp-group { display: flex; gap: 9px; justify-content: space-between; margin: 4px 0; }
.otp-input { width: 100%; height: 58px; text-align: center; font-size: 23px; font-weight: 700; color: var(--text-strong); background: var(--bg-surface); border: 1.5px solid var(--border-strong); border-radius: var(--radius-md); transition: border var(--transition), box-shadow var(--transition); }
.otp-input:focus { outline: none; border-color: var(--brand-400); box-shadow: var(--ring); }
.otp-input.filled { border-color: var(--brand-500); background: var(--brand-050); }
[data-theme="dark"] .otp-input.filled { background: rgba(34,197,94,.10); }
.otp-resend { text-align: center; font-size: 13px; color: var(--text-muted); margin-top: 4px; }
.back-link { display: inline-flex; align-items: center; gap: 6px; color: var(--text-muted); font-size: 13px; font-weight: 500; margin-bottom: 18px; }
.back-link:hover { color: var(--text-strong); }
.back-link svg { width: 16px; height: 16px; }

/* Brand-panel live "product peek" glass card */
.auth-glass {
  position: relative; z-index: 2; margin: 6px 0;
  background: rgba(255,255,255,.07);
  border: 1px solid rgba(255,255,255,.14);
  border-radius: 18px; padding: 20px 20px 18px;
  -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
  box-shadow: 0 30px 70px -28px rgba(0,0,0,.6);
  animation: floaty 7s ease-in-out infinite;
}
@keyframes floaty { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-7px); } }
.ag-head { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; color: #fff; }
.ag-head .ag-time { margin-left: auto; font-size: 11px; color: rgba(255,255,255,.6); font-weight: 500; }
.live-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--accent); animation: pulseDot 2.2s infinite; }
@keyframes pulseDot { 0% { box-shadow: 0 0 0 0 rgba(34,197,94,.55); } 70% { box-shadow: 0 0 0 9px rgba(34,197,94,0); } 100% { box-shadow: 0 0 0 0 rgba(34,197,94,0); } }
.ag-kpis { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin: 16px 0 15px; }
.ag-kpi .l { font-size: 11.5px; color: rgba(255,255,255,.6); }
.ag-kpi .v { font-size: 25px; font-weight: 750; letter-spacing: -.02em; margin-top: 3px; color: #fff; }
.ag-kpi .v small { font-size: 12px; color: rgba(255,255,255,.5); font-weight: 600; }
.ag-kpi .t { font-size: 11.5px; font-weight: 600; margin-top: 2px; color: rgba(255,255,255,.55); }
.ag-kpi .t.up { color: var(--brand-300); }
.ag-bars { display: flex; align-items: flex-end; gap: 5px; height: 44px; margin-bottom: 15px; }
.ag-bars span { flex: 1; background: linear-gradient(180deg, var(--accent), rgba(34,197,94,.22)); border-radius: 3px 3px 0 0; opacity: .9; }
.ag-foot { display: flex; align-items: center; gap: 8px; font-size: 12px; color: rgba(255,255,255,.72); border-top: 1px solid rgba(255,255,255,.1); padding-top: 13px; }
.ag-foot svg { width: 15px; height: 15px; color: var(--brand-300); flex-shrink: 0; }
.ag-foot b { color: #fff; font-weight: 700; }

/* Enterprise SSO + divider */
.sso-group { display: flex; flex-direction: column; gap: 10px; }
.sso-btn { display: flex; align-items: center; justify-content: center; gap: 10px; height: 46px; border: 1px solid var(--border-strong); border-radius: var(--radius-md); background: var(--bg-surface); color: var(--text-strong); font-weight: 600; font-size: 14px; transition: background var(--transition), border-color var(--transition); }
.sso-btn:hover { background: var(--bg-hover); }
.sso-btn svg { width: 18px; height: 18px; }
.divider-or { display: flex; align-items: center; gap: 12px; color: var(--text-faint); font-size: 12px; font-weight: 500; margin: 18px 0; }
.divider-or::before, .divider-or::after { content: ""; flex: 1; height: 1px; background: var(--border); }

/* Compact brand lockup shown on the form when the aside is hidden
   (narrow viewports) — neutral for any user type. */
.auth-brand-lockup { display: none; align-items: center; gap: 11px; margin-bottom: 26px; }
.auth-brand-lockup .brand-logo { width: 40px; height: 40px; }
.auth-brand-lockup .brand-logo .bi { font-size: 22px; }
.auth-brand-lockup .t { font-weight: 700; font-size: 15px; color: var(--text-strong); }
.auth-brand-lockup .s { font-size: 12px; color: var(--text-muted); }

/* Footer legal row */
.auth-legal { position: absolute; bottom: 22px; left: 0; right: 0; text-align: center; font-size: 12px; color: var(--text-faint); }
.auth-legal a { color: var(--text-muted); }
.auth-legal a:hover { color: var(--text-default); }
.auth-legal .dot { margin: 0 8px; opacity: .5; }

@media (max-width: 920px) {
  .auth-wrap { grid-template-columns: 1fr; }
  .auth-aside { display: none; }
  .auth-brand-lockup { display: flex; }
  .auth-legal { position: static; margin-top: 28px; }
}

/* =============================================================
   Command Palette (⌘K)
   ============================================================= */
.cmdk-overlay { position: fixed; inset: 0; background: rgba(16,24,40,.45); -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px); z-index: 200; display: none; align-items: flex-start; justify-content: center; padding: 12vh 20px 20px; }
.cmdk-overlay.open { display: flex; }
.cmdk { width: 100%; max-width: 600px; background: var(--bg-elevated); border: 1px solid var(--border); border-radius: var(--radius-lg); box-shadow: var(--shadow-xl); overflow: hidden; animation: rise .18s cubic-bezier(.2,.8,.2,1); }
.cmdk-search { display: flex; align-items: center; gap: 10px; padding: 15px 16px; border-bottom: 1px solid var(--border); }
.cmdk-search svg { width: 18px; height: 18px; color: var(--text-faint); flex-shrink: 0; }
.cmdk-search input { flex: 1; border: none; background: transparent; font-size: 15px; color: var(--text-strong); outline: none; font-family: inherit; }
.cmdk-search .esc { font-size: 10.5px; font-weight: 600; color: var(--text-faint); border: 1px solid var(--border-strong); border-radius: 5px; padding: 2px 6px; }
.cmdk-list { max-height: 384px; overflow-y: auto; padding: 8px; }
.cmdk-group-label { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--text-faint); padding: 10px 10px 6px; }
.cmdk-item { display: flex; align-items: center; gap: 11px; padding: 9px 10px; border-radius: var(--radius-sm); cursor: pointer; color: var(--text-default); font-size: 13.5px; }
.cmdk-item .ic { width: 30px; height: 30px; border-radius: 7px; background: var(--bg-hover); display: grid; place-items: center; color: var(--text-muted); flex-shrink: 0; }
.cmdk-item .ic svg { width: 16px; height: 16px; }
.cmdk-item .label { flex: 1; }
.cmdk-item .hint { font-size: 11px; color: var(--text-faint); }
.cmdk-item.sel { background: var(--brand-050); color: var(--brand-700); }
.cmdk-item.sel .ic { background: var(--brand-100); color: var(--brand-700); }
[data-theme="dark"] .cmdk-item.sel { background: var(--bg-hover); color: var(--text-strong); }
[data-theme="dark"] .cmdk-item.sel .ic { background: var(--bg-sidebar-active); color: var(--brand-300); }
.cmdk-empty { text-align: center; padding: 44px 20px; color: var(--text-faint); }
.cmdk-empty svg { width: 26px; height: 26px; opacity: .6; }
.cmdk-foot { display: flex; gap: 16px; padding: 10px 16px; border-top: 1px solid var(--border); font-size: 11.5px; color: var(--text-faint); }
.cmdk-foot kbd { font-family: inherit; font-size: 11px; background: var(--bg-hover); border: 1px solid var(--border); border-radius: 4px; padding: 1px 5px; margin-right: 2px; }

/* =============================================================
   Empty / loading states
   ============================================================= */
.empty-state { text-align: center; padding: 56px 24px; }
.empty-state .ic { width: 64px; height: 64px; border-radius: 16px; background: var(--bg-hover); display: grid; place-items: center; margin: 0 auto 16px; color: var(--text-muted); }
.empty-state .ic svg { width: 30px; height: 30px; }
.empty-state h3 { font-size: 16px; font-weight: 650; color: var(--text-strong); margin: 0 0 6px; }
.empty-state p { font-size: 13.5px; color: var(--text-muted); margin: 0 auto 18px; max-width: 360px; line-height: 1.55; }
/* Compact variant — same anatomy/tokens as .empty-state above, sized to sit
   inside a dashboard widget's card-body rather than a full page/table. */
.empty-state.compact { padding: 30px 20px; }
.empty-state.compact .ic { width: 44px; height: 44px; border-radius: 12px; margin-bottom: 10px; }
.empty-state.compact .ic .bi { font-size: 19px; }
.empty-state.compact h3 { font-size: 13.5px; margin-bottom: 3px; }
.empty-state.compact p { font-size: 12.5px; margin-bottom: 0; }
.skeleton { background: linear-gradient(90deg, var(--bg-hover) 25%, var(--border-light) 37%, var(--bg-hover) 63%); background-size: 400% 100%; animation: shimmer 1.4s ease infinite; border-radius: 6px; }
@keyframes shimmer { 0% { background-position: 100% 0; } 100% { background-position: -100% 0; } }
.skel-line { height: 12px; margin: 8px 0; }

/* =============================================================
   Accessibility
   ============================================================= */
:focus-visible { outline: 2px solid var(--brand-500); outline-offset: 2px; border-radius: 4px; }
.skip-link { position: absolute; left: -9999px; top: 0; z-index: 300; background: var(--brand-700); color: #fff; padding: 10px 18px; border-radius: 0 0 8px 0; font-weight: 600; font-size: 13px; }
.skip-link:focus { left: 0; }
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .001ms !important; animation-iteration-count: 1 !important; transition-duration: .001ms !important; scroll-behavior: auto !important; }
}

/* =============================================================
   404 / error page
   ============================================================= */
.err-wrap { min-height: 100vh; display: grid; place-items: center; padding: 40px 24px; text-align: center; background:
  radial-gradient(900px 480px at 50% -10%, rgba(22,163,74,.08), transparent 60%), var(--bg-app); }
.err-code { font-size: 120px; font-weight: 800; letter-spacing: -.04em; line-height: 1; background: linear-gradient(135deg, var(--brand-500), var(--brand-700)); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; }
.err-wrap h1 { font-size: 26px; font-weight: 700; color: var(--text-strong); margin: 18px 0 8px; }
.err-wrap p { font-size: 15px; color: var(--text-muted); max-width: 440px; margin: 0 auto 28px; line-height: 1.6; }
.err-logo { display: inline-flex; align-items: center; gap: 11px; margin-bottom: 8px; }
.err-logo .brand-logo { width: 40px; height: 40px; }
.err-logo .t { font-weight: 700; font-size: 16px; color: var(--text-strong); }

/* =============================================================
   Print
   ============================================================= */
@media print {
  .sidebar, .header, .scrim, .toast-host, .page-actions, .table-toolbar, .pagination,
  .map-zoom, .cmdk-overlay, .segmented, .skip-link { display: none !important; }
  .app-shell { display: block !important; }
  .main { margin-left: 0 !important; }
  .content { padding: 0 !important; }
  body, .app-shell, .main { background: #fff !important; }
  .card { box-shadow: none !important; border: 1px solid #ddd !important; break-inside: avoid; }
  .page-title { font-size: 20px; }
}

/* =============================================================
   Responsive
   ============================================================= */
@media (max-width: 1280px) {
  .kpi-grid { grid-template-columns: repeat(2, 1fr); }
  .dash-grid { grid-template-columns: repeat(2, 1fr); }
  .dash-grid .span-3 { grid-column: span 2; }
}
@media (max-width: 1024px) {
  .sidebar { transform: translateX(-100%); width: var(--sidebar-w); }
  .app-shell.nav-open .sidebar { transform: translateX(0); box-shadow: var(--shadow-xl); }
  .main { margin-left: 0 !important; }
  .global-search { max-width: none; }
  .mobile-only { display: grid; }
  /* The desktop "Collapse sidebar" toggle (toggleSidebar(), which only ever
     flips .app-shell's own .collapsed width variant) is a no-op the moment
     the sidebar itself goes off-canvas above — .main's margin-left and the
     sidebar's own transform are both already forced regardless of
     .collapsed at this width, so there's nothing left for that button to
     toggle. .mobile-only's hamburger (toggleMobileNav()) is the only sidebar
     control that still does anything here, so hide the desktop one instead
     of leaving a second, redundant, functionally-dead button next to it.
     Scoped to its own class rather than widening .hide-sm's shared 820px
     breakpoint, which the header-divider/chevron-down still rely on. */
  .sidebar-collapse-btn { display: none !important; }
}
@media (max-width: 820px) {
  .kpi-grid { grid-template-columns: repeat(2, 1fr); gap: 14px; }
  .dash-grid { grid-template-columns: 1fr; }
  .dash-grid .span-2, .dash-grid .span-3 { grid-column: span 1; }
  .grid-2, .grid-3 { grid-template-columns: 1fr; }
  .content { padding: 20px 16px 50px; }
  .header { padding: 0 16px; gap: 10px; }
  .global-search .kbd { display: none; }
  .hide-sm { display: none !important; }
  .form-grid { grid-template-columns: 1fr; }
  .dropdown { right: 12px; width: calc(100vw - 24px); max-width: 380px; }
  .page-title { font-size: 20px; }
}
@media (max-width: 560px) {
  .kpi-grid { grid-template-columns: 1fr; }
  .profile-chip .meta { display: none; }
}

/* Laravel integration — toast() supports type 'success'/'info' out of the box;
   this app also surfaces server-side validation/auth failures via toast('…','danger').
   Completing that variant with the theme's own --danger tokens (same pattern as
   .badge.red / .kpi-icon.red above), not introducing a new palette. */
.toast.danger .ic { background: var(--danger-bg); color: var(--danger); }

/* jQuery Validation Plugin (ev-validation.init.js) toggles .is-invalid on
   .input/.select on failed fields — same --danger token as the toast/badge
   variants above, no new colour introduced. */
.input.is-invalid, .select.is-invalid { border-color: var(--danger); }
.input.is-invalid:focus, .select.is-invalid:focus { box-shadow: 0 0 0 4px rgba(217,45,32,.14); }

/* Compact KPI variant — same tokens/anatomy as .kpi above (bg-surface, border,
   radius-lg, shadow-sm, kpi-icon colour classes), just tighter spacing/type
   scale for list-page header stats where the full-size dashboard KPI is
   more real estate than the number needs. */
.kpi.compact { padding: 14px 16px; }
.kpi.compact .kpi-top { margin-bottom: 8px; }
.kpi.compact .kpi-icon { width: 32px; height: 32px; }
.kpi.compact .kpi-icon svg { width: 16px; height: 16px; }
.kpi.compact .kpi-value { font-size: 20px; margin: 2px 0 0; }
.kpi.compact .kpi-label { font-size: 12px; }

/* Small KPI-icon variant — same tone/dark-mode tokens as .kpi-icon above,
   sized for inline use next to a card-head title (see .ttl-row) rather
   than a KPI card's own top-right icon slot. */
.kpi-icon.sm { width: 30px; height: 30px; border-radius: var(--radius-sm); }
.kpi-icon.sm .bi { font-size: 15px; }

/* Dashboard widget cards — subtle lift on hover, matching the KPI cards'
   own hover treatment (.kpi:hover above), scoped to the dashboard grid only
   so it doesn't change card behaviour anywhere else in the app. */
.dash-grid > .card { transition: box-shadow var(--transition); }
.dash-grid > .card:hover { box-shadow: var(--shadow-md); }

/* Payment Methods legend rows — turns the plain flex list into hoverable,
   padded rows consistent with .list-row's own rhythm elsewhere in the app. */
.payment-legend-item { display: flex; align-items: center; justify-content: space-between; padding: 8px 10px; border-radius: var(--radius-md); transition: background var(--transition); }
.payment-legend-item:hover { background: var(--bg-hover); }

/* Table-toolbar filters, sized to content instead of Select2's default 100%
   (see ev-select2.init.js) — keeps search + each filter sitting inline in
   one row, same as the theme's own tableToolbar() layout. */
.table-toolbar .select2-container { min-width: 150px; }
.table-toolbar .select2-container--default .select2-selection--single { height: 38px; }
.table-toolbar .select2-container--default .select2-selection--single .select2-selection__rendered { line-height: 36px; }
.table-toolbar .select2-container--default .select2-selection--single .select2-selection__arrow { height: 36px; }

/* Compact table-toolbar — tighter padding/gap/control-height for list pages
   with several filters, so the toolbar reads as one dense row instead of a
   tall block. Same tokens as .table-toolbar above, just smaller scale. */
.table-toolbar.compact { padding: 10px 14px; gap: 8px; }
.table-toolbar.compact .search-mini { min-width: 180px; max-width: 260px; }
.table-toolbar.compact .search-mini input { height: 32px; font-size: 12.5px; }
.table-toolbar.compact .search-mini svg { width: 14px; height: 14px; }
.table-toolbar.compact .select2-container { min-width: 120px; }
.table-toolbar.compact .select2-container--default .select2-selection--single { height: 32px; }
.table-toolbar.compact .select2-container--default .select2-selection--single .select2-selection__rendered { line-height: 30px; font-size: 12.5px; padding-left: 10px; }
.table-toolbar.compact .select2-container--default .select2-selection--single .select2-selection__arrow { height: 30px; }

/* Page-length native select — dynamically injected by enhanceTables() after the
   .toolbar-spacer, so it sits on the right side of every paginated table toolbar.
   Not Select2: plain <select> so it stays lightweight and always renders correctly. */
.page-length-select {
  height: 38px; padding: 0 10px; background: var(--bg-surface);
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  color: var(--text-default); font-size: 13px; cursor: pointer;
  outline: none;
}
.page-length-select:focus { border-color: var(--brand-400); box-shadow: var(--ring); }
/* The select now lives in the bottom pagination bar (first child of the
   "Showing X–Y of Z" .info block, injected by the table engines) rather than
   the top toolbar — compact + vertically centered against the info text. */
.pagination .info .page-length-select { height: 32px; font-size: 12.5px; padding: 0 8px; margin-right: 10px; vertical-align: middle; }

/* Amenity toggle chips (Station detail → Photos & Amenities). A genuinely
   new interaction — a multi-select toggle tile — so this is an additive
   component rather than stretching .tag (display-only) or .checkbox (bare
   checkbox) to do a job neither was built for. Selected state reuses the
   theme's own --success/--success-bg tokens (already dark-mode aware, same
   pair .badge.green uses) instead of introducing a new colour. */
.amenity-chip {
  display: flex; align-items: center; gap: 10px; padding: 11px 14px;
  border: 1.5px solid var(--border); border-radius: var(--radius-md);
  background: var(--bg-surface); cursor: pointer; user-select: none;
  transition: border-color var(--transition), background var(--transition);
}
.amenity-chip:hover { background: var(--bg-hover); }
.amenity-chip input { position: absolute; opacity: 0; width: 0; height: 0; }
.amenity-chip .ic {
  width: 32px; height: 32px; border-radius: 8px; flex-shrink: 0;
  display: grid; place-items: center; background: var(--bg-hover); color: var(--text-muted);
}
.amenity-chip .ic svg { width: 16px; height: 16px; }
.amenity-chip .lbl { flex: 1; font-size: 13.5px; font-weight: 600; color: var(--text-default); }
.amenity-chip .check { display: none; flex-shrink: 0; color: var(--success); }
.amenity-chip .check svg { width: 18px; height: 18px; }
.amenity-chip.selected { border-color: var(--success); background: var(--success-bg); }
.amenity-chip.selected .ic { background: var(--bg-surface); color: var(--success); }
.amenity-chip.selected .lbl { color: var(--success); }
.amenity-chip.selected .check { display: block; }
.table-toolbar.compact .page-length-select { height: 32px; font-size: 12.5px; padding: 0 8px; }

/* Generic inline-loading spin utility (e.g. a save-button icon, or the small
   spinner AJAX'd into a KYC document row while its own upload/verify/reject/
   delete request is in flight). */
@keyframes ev-spin { to { transform: rotate(360deg); } }
.spin { display: inline-block; animation: ev-spin .8s linear infinite; }

/* Station Owner detail → KYC & Documents tab: a document row dims (and its
   own action buttons disable) while its own AJAX action is in flight, so the
   loading state stays scoped to just that row instead of the whole card. */
.doc-row.is-loading { opacity: .55; }
.doc-row.is-loading .btn { cursor: not-allowed; }
.doc-row-spinner { color: var(--text-muted); font-size: 13px; }

/* Slot Availability grid cells (Admin → Operations → Slot Availability).
   Read-only status grid — distinct from .badge since these need a fixed
   grid cell layout, a hover lift, and a "current" ring for today's
   in-progress slot, none of which .badge (a display-only inline pill)
   was built for. 8 distinguishable states, every colour reusing this
   theme's own existing tokens (--success/--warning/--info/--purple/
   --danger/--gray — the exact same palette .badge's own tone variants
   already use, dark-mode safe) — no new hex values introduced. Available/
   Reserved/Booked/Charging/Blocked each get their own solid hue; Completed
   and Cancelled are both neutral-toned (a slot that no longer needs
   action) but stay distinguishable from each other via icon + a
   strikethrough on Cancelled's time label, and from Past via a slightly
   deeper neutral. */
.slot-cell {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 2px; padding: 8px 6px; border-radius: var(--radius-sm); min-height: 40px;
  font-size: 11.5px; font-weight: 650; text-align: center; line-height: 1.25;
  border: 1.5px solid transparent; cursor: default; position: relative;
  transition: transform var(--transition), box-shadow var(--transition);
}
.slot-cell .bi { font-size: 12px; line-height: 1; }
.slot-cell:hover { transform: translateY(-1px); box-shadow: var(--shadow-xs); }
.slot-cell.slot-available { background: var(--success-bg); color: var(--success); }
.slot-cell.slot-reserved  { background: var(--warning-bg); color: var(--warning); }
.slot-cell.slot-booked    { background: var(--info-bg);    color: var(--info); }
.slot-cell.slot-charging  { background: var(--purple-bg);  color: var(--purple); }
.slot-cell.slot-blocked   { background: var(--danger-bg);  color: var(--danger); }
.slot-cell.slot-completed { background: var(--gray-100);   color: var(--gray-600); }
.slot-cell.slot-cancelled { background: var(--gray-100);   color: var(--danger); }
.slot-cell.slot-cancelled .slot-time { text-decoration: line-through; text-decoration-thickness: 1.5px; opacity: .85; }
.slot-cell.slot-past      { background: var(--bg-hover);   color: var(--text-faint); }
.slot-cell.slot-current   { border-color: var(--brand-500); box-shadow: 0 0 0 3px var(--ring); }
/* Clickable states (have a booking/block to show in the details popup) —
   only these get an interactive affordance; Available/Past stay
   cursor:default since there's nothing more to reveal. */
.slot-cell.slot-clickable { cursor: pointer; }
.slot-cell.slot-clickable:hover { filter: brightness(.96); }
[data-theme="dark"] .slot-cell.slot-clickable:hover { filter: brightness(1.18); }
/* A soft pulse on the currently-charging cell only — the one state that's
   genuinely "live" right now, worth a subtle extra affordance. */
.slot-cell.slot-charging.slot-current { animation: slot-pulse 1.8s ease-in-out infinite; }
@keyframes slot-pulse {
  0%, 100% { box-shadow: 0 0 0 3px var(--ring); }
  50% { box-shadow: 0 0 0 5px rgba(124,58,237,.22); }
}
.slot-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(92px, 1fr)); gap: 8px; }

/* Compact skeleton placeholders for the slot grid while a filter change
   is loading — same .skeleton shimmer every other async section in this
   app uses, just shaped to match .slot-cell's own footprint. */
.slot-skeleton { height: 40px; border-radius: var(--radius-sm); }

/* Status legend + filter chips — the same small dot+label row, but the
   filter variant is a real toggle button (aria-pressed, active state)
   that dims/hides non-matching cells client-side, no re-fetch needed
   since the whole day's data is already on the page. */
.slot-legend { display: flex; flex-wrap: wrap; gap: 10px 16px; align-items: center; }
.slot-legend-item { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text-muted); }
.slot-legend-dot { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; }

.slot-filter-chip {
  display: inline-flex; align-items: center; gap: 6px; padding: 5px 11px 5px 8px;
  border-radius: var(--radius-pill, 999px); border: 1.5px solid var(--border);
  background: var(--bg-surface); font-size: 12px; font-weight: 600; color: var(--text-muted);
  transition: all var(--transition); cursor: pointer;
}
.slot-filter-chip .slot-legend-dot { transition: opacity var(--transition); }
.slot-filter-chip:not(.active) .slot-legend-dot { opacity: .35; }
.slot-filter-chip.active { border-color: var(--border-strong); color: var(--text-strong); background: var(--bg-hover); }
.slot-filter-chip .cnt { font-weight: 700; color: var(--text-faint); }
.slot-filter-chip.active .cnt { color: inherit; }

/* A filtered-out cell fades rather than disappears, so the grid's overall
   shape/rhythm stays legible while browsing a subset of states. */
.slot-cell.slot-filtered-out { opacity: .16; filter: grayscale(.4); }

/* Bootstrap Icons (.bi) sizing — additive companions to every "X svg { width/
   height... }" rule above. Icons are moving from inline SVG (app/Helpers/
   ev_icon.php, sized via width/height) to Bootstrap Icons font glyphs (sized
   via font-size) across Blade views; the existing svg rules stay untouched
   since assets/js/icons.js's icon() still renders inline SVG for JS-built
   markup (toasts, quick-view modals, etc.) and needs them as-is. Each rule
   below mirrors its svg counterpart's pixel size as a font-size, plus any
   color/position/opacity/transform declarations that apply identically to
   an inline glyph. */
.bi { display: inline-block; line-height: 1; vertical-align: -0.125em; }
.brand-logo .bi { font-size: 22px; }
.nav-item .bi { font-size: 19px; flex-shrink: 0; opacity: .9; }
.nav-item.active .bi { color: var(--brand-300); opacity: 1; }
.icon-btn .bi { font-size: 20px; }
.global-search .bi { position: absolute; left: 14px; top: 50%; transform: translateY(-50%); font-size: 18px; color: var(--text-faint); }
.profile-chip > .bi { font-size: 18px; color: var(--text-faint); flex-shrink: 0; }
.btn .bi { font-size: 17px; }
.btn-sm .bi { font-size: 15px; }
.kpi-icon .bi { font-size: 21px; }
.delta .bi { font-size: 13px; }
.table thead th.sortable .th-in .bi { transition: transform .15s ease; }
.table thead th.sorted .th-in .bi { opacity: 1; color: var(--brand-600); }
.table thead th.sorted[aria-sort="descending"] .th-in .bi { transform: rotate(180deg); }
.table thead th .bi { font-size: 13px; opacity: .6; }
.table-toolbar .search-mini .bi { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); font-size: 16px; color: var(--text-faint); }
.page-btn .bi { font-size: 16px; }
.menu-item .bi { font-size: 16px; color: var(--text-muted); }
.menu-item.danger .bi { color: var(--danger); }
.notif-ic .bi { font-size: 18px; }
.dd-menu-item .bi { font-size: 18px; color: var(--text-muted); }
.toast .ic .bi { font-size: 18px; }
.ops-panel-empty .ic .bi { font-size: 26px; }
.input-icon > .bi:first-child { position: absolute; left: 14px; top: 50%; transform: translateY(-50%); font-size: 18px; color: var(--text-faint); pointer-events: none; }
.input-icon .eye-btn .bi { font-size: 18px; }
.auth-secure .bi { font-size: 14px; }
.mfa-id > .bi { font-size: 22px; color: var(--brand-500); flex-shrink: 0; }
.back-link .bi { font-size: 16px; }
.ag-foot .bi { font-size: 15px; color: var(--brand-300); flex-shrink: 0; }
.sso-btn .bi { font-size: 18px; }
.cmdk-search .bi { font-size: 18px; color: var(--text-faint); flex-shrink: 0; }
.cmdk-item .ic .bi { font-size: 16px; }
.cmdk-empty .bi { font-size: 26px; opacity: .6; }
.empty-state .ic .bi { font-size: 30px; }
.kpi.compact .kpi-icon .bi { font-size: 16px; }
.table-toolbar.compact .search-mini .bi { font-size: 14px; }
.amenity-chip .ic .bi { font-size: 16px; }
.amenity-chip .check .bi { font-size: 18px; }

/* Vehicle Variant "Manage Connectors" picker (Vehicle Management Phase 7) —
   same selectable-tile idea as .amenity-chip, but each tile also carries an
   optional per-pair "max power override" text input, which the base
   .amenity-chip's flat cursor:pointer <label> row can't safely host (a
   text input nested directly inside a native <label> risks the browser's
   own label-click-forwards-to-control behaviour reading as inconsistent
   depending on exactly where inside the label a click lands). Solved by
   making the .amenity-chip element itself a plain (non-labelable) <div>
   stacked in a column, with a real <label> wrapping ONLY the
   checkbox/icon/name row (safe — verified against stations/detail.blade.php's
   own .amenity-chip <label> usage, which this mirrors) and the optional
   power input in its own sibling row below, never inside that <label>. */
.amenity-chip.connector-chip { flex-direction: column; align-items: stretch; cursor: default; }
.amenity-chip.connector-chip > label { display: flex; align-items: center; gap: 10px; cursor: pointer; }
.connector-power-field { padding-left: 42px; margin-top: 8px; }
.connector-power-field .input { height: 32px; font-size: 12.5px; }
.connector-power-field .field-hint { font-size: 11px; color: var(--text-muted); margin-bottom: 4px; display: block; }

/* Vehicle Models list — cover-photo thumbnail cell (Vehicle Management
   Phase 8). Same rounded-square sizing as .avatar.sm but square, not
   circular — these are vehicle photos, not person initials — and always
   existence-gated: a missing/corrupted file falls back to a plain icon
   tile rather than a broken <img>, same §4l rule every other upload
   display path in this app already follows. */
.model-thumb {
  width: 36px; height: 36px; border-radius: var(--radius-sm); flex-shrink: 0;
  display: grid; place-items: center; overflow: hidden; background: var(--bg-hover);
}
.model-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.model-thumb-empty { color: var(--text-faint); font-size: 15px; }

/* Vehicle Model detail page — Images tab gallery grid + per-photo overlay
   controls (Vehicle Management Phase 8). Same anatomy as the Station
   detail page's own inline photo-gallery markup (stations/detail.blade.php)
   — kept inline there since it's the only consumer; broken out to real
   classes here since this page also needs the Move up/down + reorder
   button row the Station gallery doesn't have. */
.vimg-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 12px; }
.vimg-tile { position: relative; border-radius: var(--radius-md); overflow: hidden; border: 1px solid var(--border); aspect-ratio: 4/3; background: var(--bg-hover); }
.vimg-tile img { width: 100%; height: 100%; object-fit: cover; display: block; }
.vimg-tile .vimg-missing { width: 100%; height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px; color: var(--danger); font-size: 12px; text-align: center; padding: 8px; }
.vimg-tile .vimg-cover-badge { position: absolute; top: 6px; left: 6px; }
.vimg-tile .vimg-actions { position: absolute; bottom: 0; left: 0; right: 0; background: rgba(0,0,0,.55); display: flex; gap: 4px; padding: 6px; justify-content: flex-end; }
.vimg-tile .vimg-actions .btn { background: rgba(255,255,255,.9); }
.vimg-tile .vimg-order { position: absolute; top: 6px; right: 6px; display: flex; flex-direction: column; gap: 2px; }
.vimg-tile .vimg-order .btn { background: rgba(255,255,255,.9); width: 22px; height: 22px; padding: 0; }
.vimg-tile .vimg-order .btn:disabled { opacity: .35; cursor: not-allowed; }

/* =============================================================
   Assign Permissions screens (Roles & Users) — permission chip grid
   + sticky save bar. Same "checkbox wrapped in a selectable label"
   idea as .amenity-chip above, just a plain text row instead of an
   icon tile, and toggled via a JS-added .is-checked class rather than
   a CSS :has() selector, matching that same existing convention.
   ============================================================= */
/* Own responsive breakpoints (not the shared .kpi-grid ones — those get
   overridden by this element's plain .kpi-grid class alone at narrower
   widths, but a fixed 3-column count needs its own explicit steps down
   to 1 column so it never fights the base rule at a class-specificity tie). */
.perm-stats-grid { grid-template-columns: repeat(3, 1fr); gap: 10px; }
@media (max-width: 720px) { .perm-stats-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 480px) { .perm-stats-grid { grid-template-columns: 1fr; } }

/* Compact module cards — tighter card-head/card-body padding than the
   app-wide .card-head/.card-body defaults (18px 20px / 20px), scoped to
   .perm-module-card only so every other module's cards are unaffected.
   With 20+ module cards on one page, this padding reduction is most of
   the page's overall density win. */
.perm-module-card .card-head { padding: 10px 14px; }
.perm-module-card .card-body { padding: 10px 14px; }
.perm-module-card .ttl-row { gap: 7px; }
.perm-module-card .kpi-icon.sm { width: 24px; height: 24px; }
.perm-module-card .kpi-icon.sm .bi { font-size: 12px; }

.perm-chip-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 5px; }
.perm-chip {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 9px; border: 1px solid var(--border-light); border-radius: var(--radius-sm);
  font-size: 12.5px; color: var(--text-default); cursor: pointer;
  transition: background var(--transition), border-color var(--transition);
}
.perm-chip:hover { background: var(--bg-hover); }
.perm-chip .checkbox { flex-shrink: 0; }
.perm-chip.is-checked { border-color: var(--brand-400); background: var(--brand-050); }
[data-theme="dark"] .perm-chip.is-checked { background: rgba(34,197,94,.08); }
.perm-chip.is-checked span { color: var(--brand-700); font-weight: 600; }
[data-theme="dark"] .perm-chip.is-checked span { color: var(--brand-300); }

/* Module-wise Select all / Clear — previously plain .btn-ghost text (no
   background, no border — see .btn-ghost above), which read as faint,
   easy-to-miss labels rather than clickable buttons, especially at the
   compact card-head padding. A visible border + subtle fill fixes that
   while staying small enough for a control repeated on every one of 20+
   module cards. */
.perm-module-action-btn {
  display: inline-flex; align-items: center; gap: 5px;
  height: 26px; padding: 0 9px; border-radius: var(--radius-sm);
  font-size: 11.5px; font-weight: 600; white-space: nowrap;
  color: var(--text-muted); background: var(--bg-surface-2);
  border: 1px solid var(--border); cursor: pointer;
  transition: background var(--transition), color var(--transition), border-color var(--transition);
}
.perm-module-action-btn .bi { font-size: 12px; }
.perm-module-action-btn.select-all:hover { color: var(--brand-700); border-color: var(--brand-400); background: var(--brand-050); }
[data-theme="dark"] .perm-module-action-btn.select-all:hover { color: var(--brand-300); background: rgba(34,197,94,.10); }
.perm-module-action-btn.clear:hover { color: var(--danger); border-color: var(--danger); background: var(--danger-bg); }

.perm-sticky-bar {
  position: sticky; bottom: 12px; z-index: 20; width: 100%; box-sizing: border-box;
  display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap;
  background: var(--bg-elevated); border: 1px solid var(--border); border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg); padding: 10px 16px; margin-top: 12px;
}
.perm-sticky-count { font-size: 13px; font-weight: 600; color: var(--text-strong); flex: 1 1 auto; min-width: 0; }
.perm-sticky-count span { color: var(--brand-600); font-weight: 750; }
@media (max-width: 560px) { .perm-sticky-bar { flex-direction: column; align-items: stretch; } }

/* Module card-head (title+badge on the left, Select all/Clear on the
   right) doesn't wrap by default (.card-head is a plain non-wrapping flex
   row everywhere else in the app) — at narrow widths a long module name
   plus its count badge leaves no room for the two buttons, pushing them
   off-screen instead of overflowing visibly. Scoped to .perm-module-card
   only, so every other page's .card-head is unaffected. */
@media (max-width: 640px) {
  .perm-module-card .card-head { flex-wrap: wrap; row-gap: 10px; }
  .perm-module-card .card-head > div:last-child { width: 100%; justify-content: flex-end; }
}

/* =============================================================
   Bulk Actions (Vehicle Management Phase 13) — shared, additive
   infrastructure: the checkbox column itself is rendered by
   ev-server-table.js only when a table opts in via data-bulk="1"; this is
   purely the visual styling for that checkbox column plus the selection
   bar every opted-in page renders in its own toolbar. A table without
   data-bulk="1" never sees any of this. Deliberately a JS-added .bulk-col
   class on the th/td themselves rather than a :has() selector — same
   "explicit class, not :has()" convention the Assign Permissions screens
   already established elsewhere in this app. */
.table .bulk-col { width: 36px; text-align: center; padding-left: 14px; padding-right: 0; }
.bulk-row-check, .bulk-select-all { width: 16px; height: 16px; cursor: pointer; accent-color: var(--brand-600); }

.bulk-action-bar {
  display: none; align-items: center; gap: 10px; padding: 10px 14px;
  background: var(--bg-surface-2); border-bottom: 1px solid var(--border-light);
  flex-wrap: wrap;
}
.bulk-action-bar .bulk-count { font-size: 13px; font-weight: 650; color: var(--text-strong); }
.bulk-action-bar .bulk-count span { color: var(--brand-600); font-weight: 750; }
.bulk-action-bar .bulk-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.bulk-action-bar .toolbar-spacer { flex: 1; }
@media (max-width: 560px) { .bulk-action-bar { flex-direction: column; align-items: stretch; } }

/* Chargers list — single "Connector Details" summary column (see
   ChargerController::chargerDatatable()) replacing the previous 3
   separate Connector/Power/Pricing columns. A compact clickable button —
   icon, connector count, a short type preview, the lowest base rate on
   the charger, and a chevron — opens the same per-connector card detail
   already used elsewhere (viewCharger()). Same pattern/markup shape as
   the Station Owner Panel's own Chargers list
   (owner-datatables.init.css's .chg-summary-*), just re-tokened onto the
   admin theme's own CSS variables instead of the owner panel's --vg-*
   ones. */
.chg-summary-btn {
  display: inline-flex; align-items: center; gap: 10px; width: 100%; max-width: 260px;
  padding: 8px 10px; border: 1px solid var(--border); border-radius: var(--radius-md);
  background: var(--bg-surface); text-align: left; cursor: pointer;
  transition: border-color .15s, background .15s;
}
.chg-summary-btn:hover { border-color: var(--brand-600); background: var(--bg-hover); }
.chg-summary-ic {
  width: 32px; height: 32px; border-radius: 9px; flex-shrink: 0; font-size: 15px;
  display: grid; place-items: center; background: var(--bg-hover); color: var(--brand-600);
}
.chg-summary-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.chg-summary-count { font-size: 13px; font-weight: 700; color: var(--text-strong); line-height: 1.3; }
.chg-summary-meta { display: flex; align-items: center; gap: 8px; font-size: 11.5px; color: var(--text-muted); overflow: hidden; }
.chg-summary-types { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.chg-summary-rate { flex-shrink: 0; font-weight: 700; color: var(--brand-600); }
.chg-summary-chevron { color: var(--text-faint); font-size: 12px; flex-shrink: 0; }

/* Station Management — "Connector Details" quick-view modal (opened from
   the .chg-summary-btn above, StationController::connectorSummary()).
   A small 3-tile summary strip (types/connectors/chargers) followed by
   one card per distinct connector type — an icon badge, two tone-colored
   stat pills, and a relative-share bar (reusing the existing .progress
   component) instead of the plain stacked key:value .detail-list rows
   the column's very first pass used. Additive only — new classes, no
   existing modal/detail-list rule touched. */
.conn-summary-strip {
  display: flex; align-items: stretch; gap: 0; margin-bottom: 16px;
  border: 1px solid var(--border); border-radius: var(--radius-md); overflow: hidden;
}
.conn-summary-item {
  flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 2px; padding: 10px 8px; background: var(--bg-hover);
}
.conn-summary-item + .conn-summary-item { border-left: 1px solid var(--border); }
.conn-summary-item .v { font-size: 18px; font-weight: 700; color: var(--text-strong); line-height: 1.2; }
.conn-summary-item .l { font-size: 11px; color: var(--text-muted); text-transform: uppercase; letter-spacing: .03em; }

.conn-type-card {
  display: flex; align-items: flex-start; gap: 12px;
  border: 1px solid var(--border); border-radius: var(--radius-md);
  padding: 12px 14px; margin-bottom: 8px; background: var(--bg-surface);
}
.conn-type-card:last-child { margin-bottom: 0; }
.conn-type-ic {
  width: 34px; height: 34px; border-radius: 9px; flex-shrink: 0; font-size: 16px;
  display: grid; place-items: center; background: var(--bg-hover); color: var(--brand-600);
}
.conn-type-body { flex: 1; min-width: 0; }
.conn-type-head { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
.conn-type-name { font-size: 13.5px; font-weight: 700; color: var(--text-strong); margin-right: auto; }
.conn-stat-pill {
  display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px; font-weight: 600;
  padding: 3px 9px; border-radius: 999px; white-space: nowrap;
}
.conn-stat-pill.blue { background: var(--info-bg); color: var(--info); }
.conn-stat-pill.green { background: var(--success-bg); color: var(--success); }
.conn-stat-pill.purple { background: var(--purple-bg); color: var(--purple); }
.conn-stat-pill .bi { font-size: 11px; }
.conn-pill-row { display: flex; flex-wrap: wrap; gap: 6px; }

/* Charger Management quick-view modal (viewCharger()) reuses the same
   .conn-type-card/.conn-stat-pill component this file's own Connector
   Details cards already established (Station Management's own connector-
   summary modal) — here each card is one real connector (with its own
   editable .charger-status-select, unchanged), not an aggregated type
   row, so .conn-type-head also carries the status control on its right
   (pushed there by .conn-type-name's own margin-right:auto) instead of a
   pill. .conn-summary-strip/.conn-summary-item (the header info row) are
   reused as-is for text/badge content instead of their usual numeric
   tally — both classes are generic enough already, no override needed. */

/* Quick-view modal — per-connector "Change status" control (EDIT_CHARGER
   only, see window.ADMIN_CAN_EDIT_CHARGER in manage.blade.php's page-js).
   A real <select>, not a display-only badge, but still reads AS a badge —
   same pill shape/colour tokens as .badge's own tone variants, just with a
   dropdown arrow to signal it's interactive. Same pattern as the Station
   Owner Panel's own .chg-status-select (owner-datatables.init.css). */
.charger-status-select {
  appearance: none; -webkit-appearance: none; cursor: pointer;
  border: none; border-radius: var(--radius-full); padding: 3px 24px 3px 10px; font-size: 12px; font-weight: 600;
  background-repeat: no-repeat; background-position: right 8px center;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 16 16'%3E%3Cpath fill='currentColor' d='M4.646 6.646a.5.5 0 0 1 .708 0L8 9.293l2.646-2.647a.5.5 0 0 1 .708.708l-3 3a.5.5 0 0 1-.708 0l-3-3a.5.5 0 0 1 0-.708z'/%3E%3C/svg%3E");
}
.charger-status-select:disabled { opacity: .6; cursor: not-allowed; }
.charger-status-select.green { color: var(--success); background-color: var(--success-bg); }
.charger-status-select.blue  { color: var(--info);    background-color: var(--info-bg); }
.charger-status-select.amber { color: var(--warning); background-color: var(--warning-bg); }
.charger-status-select.red   { color: var(--danger);  background-color: var(--danger-bg); }
.charger-status-select.gray  { color: var(--text-muted); background-color: var(--bg-hover); }

/* #ccCard's own .card-head carries more content than the shared .card-head
   rule was ever sized for — icon+title+subtitle AND a count badge AND a
   text "Expand all"/"Collapse all" button AND an icon refresh button, all
   on the app-wide default nowrap row. Confirmed live at 375px: the shared
   rule's flex-wrap:nowrap squeezed the title/subtitle column down to ~93px,
   which just made the subtitle wrap onto 6+ lines instead of the row
   itself wrapping — technically no page-level horizontal overflow, but a
   badly cramped, oddly tall header. Scoped to #ccCard only (never the
   shared .card-head rule itself, which every other card in the app also
   uses) so the actions row can drop to its own line under ~560px instead. */
#ccCard .card-head { flex-wrap: wrap; row-gap: 10px; }
@media (max-width: 560px) {
  #ccCard .card-head .flex.items-center.gap-8 { width: 100%; justify-content: space-between; }
}

/* Charging Session Oversight — "Currently Charging Sessions" card. A
   compact, information-dense session-row list (redesigned from an earlier
   taller card layout per explicit request — see the design mockup this
   was built from), purely additive, reusing existing tokens/keyframes only
   (the brand, info, border and text color tokens plus gray-100, and the
   existing @keyframes pulseDot above) — never the Station Owner Panel's
   Bootstrap-flavored vg- and cs- prefixed classes, per this theme's own
   no-Bootstrap-in-the-Super-Admin-panel rule. Dark-mode-safe automatically,
   since every token used here is already redefined under [data-theme="dark"].
   Deliberately no left accent bar, icon ring or chip dividers — an earlier
   pass added those and it read as cluttered; color is reserved for just the
   live pulse dot and the status pill, everything else stays neutral. If
   revisiting the visual design again, verify the actual render (screenshot)
   before adding anything back, not just computed-style assertions.
   IMPORTANT: never let the two-character sequence asterisk-then-slash
   appear anywhere in this comment (even mid-word) — it silently closes a
   CSS comment early and swallows the very next rule; this exact bug once
   dropped the .live-session-grid rule below entirely. */
/* Explicit column-count breakpoints (not auto-fill) so the grid never
   exceeds 4 columns no matter how wide the screen is — auto-fill with a
   small minmax would otherwise keep adding columns on a large monitor. */
.live-session-grid { display: grid; grid-template-columns: 1fr; gap: 8px; max-height: 460px; overflow-y: auto; padding-right: 2px; }
@media (min-width: 620px)  { .live-session-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 920px)  { .live-session-grid { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1200px) { .live-session-grid { grid-template-columns: repeat(4, 1fr); } }
/* Compact card body — 3 short rows, not 5: identity+status, then a
   charger/connector line sharing its row with the actions (no separate
   action row), then a single wrapping strip of icon+value metric chips
   (no stacked uppercase-label-then-value — the icon + this element's own
   title="" tooltip carry the label instead) rather than a tall 2-column
   grid. This is a deliberate compaction pass — an earlier version of this
   card used a 2-col label/value grid plus its own action row and measured
   visibly taller than needed for what's genuinely a short list of facts. */
.live-session-card {
  display: flex; flex-direction: column; gap: 6px; padding: 9px 11px;
  border: 1px solid var(--border-light); border-radius: var(--radius-sm); background: var(--bg-surface-2);
  transition: background .1s ease, border-color .1s ease;
}
.live-session-card:hover { background: var(--bg-surface); border-color: var(--border); box-shadow: var(--shadow-xs); }

.ls-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--brand-500); box-shadow: 0 0 0 3px var(--brand-050); flex: none; animation: pulseDot 1.8s infinite; }
[data-theme="dark"] .ls-dot { box-shadow: 0 0 0 3px rgba(34,197,94,.16); }
@media (prefers-reduced-motion: reduce) { .ls-dot { animation: none; } }

.ls-top { display: flex; align-items: flex-start; gap: 7px; }
.ls-name { min-width: 0; flex: 1 1 auto; padding-top: 1px; }
.ls-name .n { font-size: 12.5px; font-weight: 600; color: var(--text-strong); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ls-name .s { display: flex; align-items: center; gap: 4px; font-size: 11px; color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-top: 1px; }
.ls-name .s i { font-size: 9.5px; color: var(--text-faint); flex: none; }

.ls-status {
  display: inline-flex; align-items: center; gap: 4px; flex: none; font-size: 9.5px; font-weight: 600; letter-spacing: .02em;
  text-transform: uppercase; color: var(--info); background: var(--info-bg); border-radius: var(--radius-full); padding: 2px 7px 2px 5px; white-space: nowrap;
}
.ls-status .bdot { width: 5px; height: 5px; background: currentColor; }

.ls-charger-row { display: flex; align-items: center; gap: 6px; }
.ls-charger { display: flex; align-items: center; gap: 5px; font-size: 11.5px; color: var(--text-default); min-width: 0; flex: 1 1 auto; }
.ls-charger i { font-size: 11.5px; color: var(--text-faint); flex: none; }
.ls-charger b { font-weight: 600; color: var(--text-strong); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ls-tag { flex: none; font-size: 10px; font-weight: 600; color: var(--text-muted); background: var(--gray-100); border-radius: 5px; padding: 1px 6px; }

.ls-actions { display: flex; align-items: center; gap: 1px; flex: none; margin-left: auto; }
.ls-actions .btn-icon-only.btn-sm { width: 23px; height: 23px; }
.ls-actions .btn-icon-only.btn-sm i { font-size: 12px; }

.ls-metrics { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 11px; padding-top: 6px; border-top: 1px dashed var(--border-light); }
.ls-metric { display: inline-flex; align-items: center; gap: 4px; font-size: 11.5px; color: var(--text-default); font-variant-numeric: tabular-nums; white-space: nowrap; }
.ls-metric i { font-size: 10.5px; color: var(--text-faint); flex: none; }
.ls-metric b { font-weight: 600; color: var(--text-strong); }
.ls-metric.cost b { color: var(--brand-700); }
[data-theme="dark"] .ls-metric.cost b { color: var(--brand-400); }

/* Station-wise grouping + expand/collapse for the same card (added per
   explicit request — this interaction doesn't exist anywhere else in the
   app yet, built fresh here rather than ported from the Owner Panel, which
   has no grouped/collapsible live-sessions view to copy). Each header is a
   compact 2-line block (name + LIVE badge, then owner/location meta) so a
   station's identity, live state, location and active-session count are
   all readable at a glance without expanding it — the header itself never
   scrolls away while its sessions are open, since it sits outside
   .live-session-grid's own scroll area (see that rule below), which is
   what "keep the header clear while viewing sessions" comes down to here;
   there's no independent per-group scroll container to make it literally
   position:sticky against. */
#ccBody { background: var(--bg-surface-2); padding: 12px; display: flex; flex-direction: column; gap: 10px; }
.cc-station-group {
  background: var(--bg-surface); border: 1px solid var(--border); border-radius: var(--radius-md);
  box-shadow: var(--shadow-xs); overflow: hidden;
}
.cc-station-head {
  width: 100%; display: flex; align-items: center; gap: 10px; padding: 11px 14px;
  background: var(--bg-surface); border: none; border-bottom: 1px solid var(--border-light); cursor: pointer; text-align: left;
}
.cc-station-group.collapsed .cc-station-head { border-bottom-color: transparent; }
.cc-station-head:hover { background: var(--bg-surface-2); }
.cc-station-chevron { color: var(--text-faint); font-size: 13px; flex: none; transition: transform .15s; }
.cc-station-titles { min-width: 0; flex: 1 1 auto; display: flex; flex-direction: column; gap: 1px; }
.cc-station-title-row { display: flex; align-items: center; gap: 8px; min-width: 0; }
.cc-station-name { font-size: 13px; font-weight: 600; color: var(--text-strong); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cc-live-badge {
  display: inline-flex; align-items: center; gap: 5px; flex: none; font-size: 10px; font-weight: 700; letter-spacing: .05em;
  color: var(--brand-700); background: var(--brand-050); border-radius: var(--radius-full); padding: 2px 8px 2px 6px;
}
[data-theme="dark"] .cc-live-badge { color: #6EE7A8; background: rgba(22,163,74,.16); }
.cc-live-badge .ls-dot { box-shadow: 0 0 0 2px var(--brand-050); }
[data-theme="dark"] .cc-live-badge .ls-dot { box-shadow: 0 0 0 2px rgba(22,163,74,.16); }
.cc-station-owner { display: flex; align-items: center; gap: 5px; font-size: 11.3px; color: var(--text-faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cc-station-owner i.bi { font-size: 10.5px; flex: none; }
.cc-station-count { flex: none; margin-left: 8px; }
.cc-station-body { padding: 10px 14px 14px; }
.cc-station-loading { display: flex; align-items: center; gap: 8px; padding: 16px 4px; font-size: 12.5px; color: var(--text-muted); }
.cc-station-loading i { font-size: 13px; color: var(--text-faint); }
.cc-load-more-row { display: flex; justify-content: center; padding-top: 10px; }
.cc-load-more-btn { min-width: 160px; }
.cc-load-more-btn:disabled { opacity: .65; cursor: default; }
/* Mobile: the fixed-width count badge sitting on the same row as the
   station name was starving the name of room (confirmed live — a real
   station name needing ~200px was getting squeezed to ~124px available
   and hard-truncating well before its natural length). Below 480px the
   badge wraps to its own line instead — .cc-station-titles stops
   shrinking (flex-shrink:0) so it keeps its full natural width, which is
   what pushes the count badge (the last item) onto a new line once the
   three no longer fit together; the name and LIVE badge then have the
   whole row to themselves, no truncation. */
@media (max-width: 480px) {
  .cc-station-head { flex-wrap: wrap; row-gap: 4px; }
  .cc-station-titles { flex-shrink: 0; }
  .cc-station-count { margin-left: 23px; }
}
.dash-cc-select {
  height: 32px; padding: 0 28px 0 10px; background: var(--bg-surface);
  border: 1px solid var(--border); border-radius: var(--radius-sm); color: var(--text-default);
  font-weight: 500; font-size: 12.5px; cursor: pointer; appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23667085' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 8px center; min-width: 180px;
}
.dash-cc-select:focus { outline: none; border-color: var(--brand-400); box-shadow: var(--ring); }

/* Per-station filter row inside each Currently Charging group (reuses
   .table-toolbar.compact's own search-mini/select sizing as-is — zero
   horizontal padding here since .cc-station-body already insets 14px on
   both sides, and it never carries a page-length select). */
.cc-station-filters.table-toolbar.compact { padding: 2px 0 10px; }
.cc-station-filters .search-mini { max-width: 240px; }
