/* ═══════════════════════════════════════════════════════════════════════════
   Refraime MI Portal — Styles
   Base palette carried from vehicle6. Layout adapted for sidebar + report views.
═══════════════════════════════════════════════════════════════════════════ */

/* ── CSS Variables ─────────────────────────────────────────────────────────── */
:root {
  /* Core palette — identical to vehicle6 */
  --bg:            #0d1117;
  --bg-panel:      #161b22;
  --bg-panel-alt:  #1c2230;
  --bg-input:      #21262d;
  --border:        #30363d;
  --border-focus:  #e63946;
  --text:          #e6edf3;
  --text-muted:    #8b949e;
  --text-dim:      #484f58;
  --accent:        #e63946;
  --accent-hover:  #c1121f;
  --accent-soft:   rgba(230, 57, 70, 0.15);
  --success:       #3fb950;
  --warning:       #d29922;
  --font:          -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --font-mono:     "Cascadia Code", "Consolas", "Fira Code", monospace;
  --radius:        6px;
  --radius-lg:     10px;
  --shadow:        0 4px 16px rgba(0,0,0,0.5);

  /* Portal layout dimensions */
  --header-h:      72px;
  --tabbar-h:      58px;
  --sidebar-w:     224px;
  --filter-h:      52px;
}

/* ── Reset ─────────────────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { height: 100%; }
body {
  font-family:    var(--font);
  font-size:      13px;
  background:     var(--bg);
  color:          var(--text);
  height:         100%;
  display:        flex;
  flex-direction: column;
  overflow:       hidden;
}

/* ── Scrollbars ────────────────────────────────────────────────────────────── */
::-webkit-scrollbar              { width: 6px; height: 6px; }
::-webkit-scrollbar-track        { background: transparent; }
::-webkit-scrollbar-thumb        { background: var(--text-dim); border-radius: 3px; }
::-webkit-scrollbar-thumb:hover  { background: var(--text-muted); }

/* ── App Header ────────────────────────────────────────────────────────────── */
.app-header {
  height:          var(--header-h);
  min-height:      var(--header-h);
  background:      var(--bg-panel);
  border-bottom:   1px solid var(--border);
  display:         flex;
  align-items:     center;
  padding:         0 20px;
  gap:             14px;
  flex-shrink:     0;
  box-shadow:      var(--shadow);
  z-index:         100;
}

.header-logo {
  display:         flex;
  align-items:     center;
  gap:             10px;
  flex-shrink:     0;
}

.logo-img {
  height:          40px;
  width:           auto;
  filter:          drop-shadow(0 0 8px rgba(230,57,70,0.35));
}

.header-divider {
  width:           1px;
  height:          24px;
  background:      var(--border);
  flex-shrink:     0;
}

.header-title {
  font-size:       30px;
  font-weight:     600;
  color:           var(--text);
  letter-spacing:  0.2px;
  flex:            1;
  margin-left:     12px;
}

.header-subtitle {
  font-size:       15px;
  color:           var(--text-muted);
  font-weight:     400;
}

/* "Account" label sits beside a column (.header-account-control) holding the
   select's own row plus a "Data as of D Mon HH:MM" freshness line
   underneath it (2026-07-10) — the latest event timestamp for whichever
   account is selected (data_service.get_data_freshness()), refreshed on
   every account switch. The freshness line needs to be its own column
   nested inside .header-account-control, separate from the label
   (Bruce's correction, second round): the label and the column are
   siblings, so the freshness line's left edge lines up with the SELECT
   (the column's own left edge), not the label to its left. */
.header-account {
  display:         flex;
  /* flex-start, not center (2026-07-15, Bruce's screenshot): center vertically
     centered the "Account" label against the FULL 2-row control column
     (select + freshness line), landing it visually between the two rows
     rather than level with the select. flex-start aligns the label's top
     with the select row's top instead; the label's own font-size (13px) is
     shorter than the select's rendered height, so a small margin-top on the
     label (below) nudges it down to the select row's own vertical center.
     Mirrored on .header-user for the same reason and so "Account"/"User"
     land at the same height (both control columns are now the same total
     height, TODO-244). */
  align-items:     flex-start;
  gap:             10px;
  flex-shrink:     0;
}

.header-account-control {
  display:        flex;
  flex-direction: column;
  align-items:    flex-start;
  gap:            3px;
}

.header-account-row {
  display:     flex;
  align-items: center;
  gap:         8px;
}

.header-account .filter-select option:disabled {
  color:           var(--text-muted);
}

/* Header labels/select/freshness/username/logout text sized up further
   (2026-07-15, Bruce's request) — scoped to the header groups only, so the
   dozens of other .filter-label/.filter-select uses across the report/
   dashboard/geo/compare/operator filter bars are untouched. */
.header-account .filter-label,
.header-user .filter-label {
  font-size:   13px;
  /* Nudges the label down from the flex-start top edge to sit level with
     the select/logout-button row's own vertical centre (2026-07-15) — see
     .header-account's comment above. */
  margin-top:  6px;
}

.header-account .filter-select {
  font-size: 14px;
  padding:   5px 28px 5px 9px;
}

.header-account-freshness {
  font-size:      12px;
  color:          var(--text-muted);
  letter-spacing: 0.02em;
  min-height:     14px; /* reserves the row's height even while empty (pre-fetch) — avoids a layout jump in the fixed-height header */
  /* Left-align with the SELECT's own text, not its outer edge (2026-07-15,
     Bruce's screenshot) — flex-start on the parent column only aligns box
     edges; the select has a 1px border + 9px left padding before its text
     starts, which this plain div has none of. */
  padding-left:   10px;
}

/* "Back to [Parent]" breadcrumb (Sub-Account Rollup Reporting, 2026-07-27) —
   only shown while the active account is itself a sub-account (a
   main_account_id is set). Same left-align convention as
   .header-account-freshness above. */
.header-parent-account-link {
  font-size:      12px;
  letter-spacing: 0.02em;
  padding-left:   10px;
  color:          var(--accent);
  cursor:         pointer;
  user-select:    none;
}
.header-parent-account-link:hover {
  text-decoration: underline;
}

/* Vertical rule separating the Account and User groups. Widened margin
   (2026-07-15, Bruce's request, was "0 6px") — since .header-title is the
   only flex-growing header child, widening the gap here shrinks the title's
   available width by the same amount, which shifts the Account group's
   start position further left as a side effect (not just adding visual
   space between the two groups). */
.header-divider-right {
  height:  32px;
  margin:  0 24px;
}

/* ── Section Tab Bar ───────────────────────────────────────────────────────── */
.section-tabs {
  height:          var(--tabbar-h);
  min-height:      var(--tabbar-h);
  background:      var(--bg);
  border-bottom:   1px solid var(--border);
  display:         flex;
  align-items:     stretch;
  padding:         0 20px;
  gap:             0;
  flex-shrink:     0;
}

.section-tab {
  display:         flex;
  align-items:     center;
  padding:         0 18px;
  font-family:     var(--font);
  font-size:       17px;
  font-weight:     600;
  letter-spacing:  0.09em;
  text-transform:  uppercase;
  color:           var(--text-muted);
  background:      transparent;
  border:          none;
  border-bottom:   2px solid transparent;
  cursor:          pointer;
  transition:      color 0.15s, border-color 0.15s;
  white-space:     nowrap;
  margin-bottom:   -1px;
}

.section-tab:hover:not(:disabled) {
  color:           var(--text);
}

.section-tab.active {
  color:           var(--text);
  border-bottom-color: var(--accent);
  font-weight:     600;
}

.section-tab:disabled {
  color:           var(--text-dim);
  cursor:          not-allowed;
}

/* ── Portal Body ───────────────────────────────────────────────────────────── */
.portal-body {
  flex:            1;
  display:         flex;
  overflow:        hidden;
}

/* ── Sidebar ───────────────────────────────────────────────────────────────── */
.sidebar {
  width:           var(--sidebar-w);
  min-width:       var(--sidebar-w);
  background:      var(--bg-panel);
  border-right:    1px solid var(--border);
  display:         flex;
  flex-direction:  column;
  overflow-y:      auto;
  flex-shrink:     0;
}

.sidebar-header {
  height:          var(--filter-h);
  min-height:      var(--filter-h);
  display:         flex;
  align-items:     center;
  padding:         0 14px;
  background:      var(--bg-panel-alt);
  border-bottom:   1px solid var(--border);
  flex-shrink:     0;
  position:        sticky;
  top:             0;
  z-index:         1;
  font-size:       10px;
  font-weight:     700;
  letter-spacing:  1.2px;
  text-transform:  uppercase;
  color:           var(--accent);
}

.sidebar-section-label {
  font-size:       10px;
  font-weight:     700;
  letter-spacing:  0.8px;
  text-transform:  uppercase;
  color:           var(--text-dim);
  padding:         16px 14px 6px;
}

.nav-group-label {
  font-size:       13px;
  font-weight:     700;
  letter-spacing:  0.9px;
  text-transform:  uppercase;
  color:           var(--text-muted);
  padding:         12px 14px 4px;
  border-top:      1px solid var(--border);
  margin-top:      4px;
}

.nav-group-label:first-child,
.sidebar-header + .nav-group-label {
  border-top:      none;
  margin-top:      0;
  padding-top:     10px;
}

.nav-item {
  display:         flex;
  align-items:     center;
  gap:             8px;
  padding:         8px 14px;
  cursor:          pointer;
  border-left:     2px solid transparent;
  transition:      background 0.1s, border-color 0.1s, color 0.1s;
  color:           var(--text-muted);
  font-size:       12.5px;
  user-select:     none;
}

.nav-item:hover {
  background:      var(--bg-panel-alt);
  color:           var(--text);
}

.nav-item.active {
  background:      var(--accent-soft);
  border-left-color: var(--accent);
  color:           var(--text);
}

.nav-item-id {
  font-family:     var(--font-mono);
  font-size:       10px;
  color:           var(--text-dim);
  min-width:       28px;
  flex-shrink:     0;
}

.nav-item.active .nav-item-id {
  color:           var(--accent);
}

.nav-item-name {
  flex:            1;
  line-height:     1.3;
}

/* R08/R09 — no live implementation yet; italic marks them as a MOCK-only pair
   in both the Analytics and Comparisons sidebars (always), .nav-item-disabled
   additionally greys them out and blocks interaction while a non-MOCK account
   is selected (toggled by _refreshMockOnlyNavAvailability() in app.js). */
.nav-item-mock-only {
  font-style:      italic;
}

.nav-item-disabled {
  opacity:         0.4;
  cursor:          default;
}

.nav-item-disabled:hover {
  background:      none;
  color:           var(--text-muted);
}

/* ── Main Content ──────────────────────────────────────────────────────────── */
.main-content {
  flex:            1;
  display:         flex;
  flex-direction:  column;
  overflow:        hidden;
  min-width:       0;
}

/* ── Filter Bar ────────────────────────────────────────────────────────────── */
.filter-bar {
  height:          var(--filter-h);
  min-height:      var(--filter-h);
  background:      var(--bg-panel-alt);
  border-bottom:   1px solid var(--border);
  display:         flex;
  align-items:     center;
  padding:         0 20px;
  gap:             16px;
  flex-shrink:     0;
}

.filter-group {
  display:         flex;
  align-items:     center;
  gap:             6px;
}

.filter-label {
  font-size:       10px;
  font-weight:     700;
  letter-spacing:  0.9px;
  text-transform:  uppercase;
  color:           var(--accent);
  white-space:     nowrap;
}

.filter-select {
  background:      var(--bg-input);
  border:          1px solid var(--border);
  border-radius:   var(--radius);
  color:           var(--text);
  font-family:     var(--font);
  font-size:       12px;
  padding:         4px 26px 4px 8px;
  appearance:      none;
  cursor:          pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%238b949e'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 8px center;
  transition:      border-color 0.15s;
}

.filter-select:focus {
  outline:         none;
  border-color:    var(--border-focus);
}

.filter-select:disabled {
  color:           var(--text-dim);
  cursor:          not-allowed;
  opacity:         0.6;
}

.filter-input {
  background:      var(--bg-input);
  border:          1px solid var(--border);
  border-radius:   var(--radius);
  color:           var(--text);
  font-family:     var(--font);
  font-size:       12px;
  padding:         4px 8px;
  transition:      border-color 0.15s;
}

.filter-input:focus {
  outline:         none;
  border-color:    var(--border-focus);
}

.filter-divider {
  width:           1px;
  height:          20px;
  background:      var(--border);
  flex-shrink:     0;
}

.filter-hint {
  font-size:       10px;
  font-weight:     700;
  letter-spacing:  0.6px;
  text-transform:  uppercase;
  color:           var(--text-dim);
  white-space:     nowrap;
}

/* ── Report Heading Strip ──────────────────────────────────────────────────── */
.report-heading {
  padding:         14px 20px 10px;
  border-bottom:   1px solid var(--border);
  flex-shrink:     0;
  background:      var(--bg);
  display:         flex;
  align-items:     flex-start;
  justify-content: space-between;
  gap:             12px;
}

.report-heading-text {
  flex:            1;
  min-width:       0;
}

.report-heading-title {
  font-size:       20px;
  font-weight:     600;
  color:           var(--text);
  letter-spacing:  -0.01em;
}

.report-heading-desc {
  font-size:       11.5px;
  color:           var(--text-muted);
  margin-top:      2px;
}

/* ── KPI Summary Strip ─────────────────────────────────────────────────────── */
.kpi-summary {
  padding:         14px 20px;
  border-bottom:   1px solid var(--border);
  background:      var(--bg);
  flex-shrink:     0;
}

/* ── Camera Focus Chip ──────────────────────────────────────────────────────── */
.camera-focus-chip {
  display:         flex;
  align-items:     center;
  gap:             8px;
  padding:         6px 20px;
  background:      var(--bg-panel-alt);
  border-bottom:   1px solid var(--border);
  flex-shrink:     0;
}
.camera-chip-label {
  font-size:       10px;
  text-transform:  uppercase;
  letter-spacing:  0.06em;
  color:           var(--text-dim);
}
.camera-chip-name {
  font-size:       13px;
  font-weight:     600;
  color:           var(--text);
}
.camera-chip-clear {
  margin-left:     4px;
  background:      none;
  border:          none;
  color:           var(--text-dim);
  font-size:       13px;
  cursor:          pointer;
  line-height:     1;
  padding:         0 2px;
}
.camera-chip-clear:hover { color: var(--accent); }

/* ── Views Scroll Container ────────────────────────────────────────────────── */
.views-container {
  flex:            1;
  overflow-y:      auto;
  padding:         16px 20px 32px;
  display:         flex;
  flex-direction:  column;
  gap:             16px;
}

/* ── View Panel ────────────────────────────────────────────────────────────── */
.view-panel {
  background:      var(--bg-panel);
  border:          1px solid var(--border);
  border-radius:   var(--radius-lg);
  min-height:      420px;
}

.view-panel-header {
  display:         flex;
  align-items:     center;
  gap:             10px;
  padding:         10px 16px;
  border-bottom:   1px solid var(--border);
  background:      var(--bg-panel-alt);
  border-radius:   var(--radius-lg) var(--radius-lg) 0 0;
}

.view-panel-tag {
  font-size:       9px;
  font-weight:     700;
  letter-spacing:  0.8px;
  text-transform:  uppercase;
  padding:         2px 7px;
  border-radius:   3px;
  background:      var(--accent-soft);
  color:           var(--accent);
  border:          1px solid rgba(230,57,70,0.3);
  flex-shrink:     0;
}

.view-panel-title {
  font-size:       12px;
  font-weight:     600;
  color:           var(--text);
}

.view-panel-controls {
  margin-left:     auto;
  display:         flex;
  align-items:     center;
  gap:             8px;
}

.view-panel-body {
  padding:         16px;
}

/* ── KPI Cards ─────────────────────────────────────────────────────────────── */
.kpi-grid {
  display:         flex;
  flex-wrap:       wrap;
  gap:             12px;
}

.kpi-card {
  background:      var(--bg-panel-alt);
  border:          1px solid var(--border);
  border-radius:   var(--radius);
  padding:         14px 16px;
  display:         flex;
  flex-direction:  column;
  gap:             4px;
  flex:            1 1 160px;
  min-width:       0;
}

/* Fixed-width, non-growing spacer between two specific KPI cards — e.g.
   R06's split between headline totals (Generated/Actioned/Active
   Operators) and the per-operator distribution stats that follow. A
   margin on the card itself would make that one card narrower than its
   siblings (tried first, visibly wrong); a dedicated non-growing flex
   item keeps every real card equal-width via flex-grow. Rendered by
   renderKpis() when a KPI item carries "gap_before". */
.kpi-gap-spacer {
  flex: 0 0 32px;
}

.kpi-label {
  font-size:       10px;
  font-weight:     600;
  letter-spacing:  0.5px;
  text-transform:  uppercase;
  color:           var(--text-muted);
}

.kpi-value {
  font-size:       26px;
  font-weight:     700;
  color:           var(--text);
  line-height:     1.1;
  font-variant-numeric: tabular-nums;
}

.kpi-value.accent { color: var(--accent); }
.kpi-value.success { color: var(--success); }
.kpi-value.warning { color: var(--warning); }

.kpi-freq-unit {
  font-size:   0.45em;
  font-weight: 400;
  opacity:     0.65;
}

/* ── R08 Grouped KPI panels ────────────────────────────────────────────────── */

/* Wrapper fills the kpi-summary strip's full width (kpi-grid is a flex
   row now, not grid — flex-basis:100% is the equivalent of the old
   grid-column:1/-1 span) so the 4-panel row isn't crushed to 160px */
.kpi-group-wrapper {
  flex:           1 1 100%;
  display:        flex;
  flex-direction: column;
  gap:            8px;
}

.kpi-group-date {
  font-size: 10px;
  color:     var(--text-muted);
}

.kpi-group-panels {
  display: flex;
  gap:     10px;
}

.kpi-group-panel {
  flex:           1;
  min-width:      0;
  background:     var(--bg-panel-alt);
  border:         1px solid var(--border);
  border-radius:  var(--radius);
  padding:        10px 14px;
  display:        flex;
  flex-direction: column;
}

.kpi-group-header {
  font-size:      10px;
  font-weight:    700;
  letter-spacing: 0.8px;
  text-transform: uppercase;
  color:          var(--accent);
  padding-bottom: 6px;
  border-bottom:  1px solid var(--border);
  margin-bottom:  6px;
}

.kpi-group-card {
  display:     flex;
  align-items: center;
  gap:         6px;
  padding:     4px 0;
}

.kpi-state-dot {
  width:        8px;
  height:       8px;
  border-radius: 50%;
  flex-shrink:  0;
}

.kpi-group-card .kpi-label {
  flex:           1;
  font-size:      10px;
  text-transform: uppercase;
  letter-spacing: 0.4px;
}

.kpi-group-card .kpi-value {
  font-size:   18px;
  font-weight: 700;
}

/* Compact A/B/Δ compare display inside grouped KPI cards (Comparisons tab,
   R08) — single row like Analytics' own .kpi-group-card (dot + label left,
   values right), with the A and B figures rendered as two fixed-width right-
   aligned columns ahead of the delta badge, rather than Analytics' one. */
.kpi-group-card-compare {
  gap: 10px;
}

.kpi-gcmp-val {
  min-width:   30px;
  text-align:  right;
  font-size:   14px;
  font-weight: 700;
  color:       var(--text-primary);
}

/* Smaller delta badge when inside a group card */
.kpi-group-card .kpi-compare-delta {
  font-size: 10px;
  padding:   2px 5px;
}

.kpi-sub {
  font-size:       10.5px;
  color:           var(--text-dim);
}

/* ── Chart Container ───────────────────────────────────────────────────────── */
.chart-wrap {
  width:           100%;
  height:          320px;
  overflow-x:      auto;
  overflow-y:      hidden;
}

.chart-wrap.heatmap {
  height:          auto;
  min-height:      200px;
  overflow-x:      auto;
  overflow-y:      visible;
}

/* Split bar (R08 Camera Analysis — two stacked panels) */
.chart-wrap.split-mode {
  height:          auto;
  min-height:      0;
  overflow-y:      visible;
}
.split-bar-panel {
  margin-bottom:   20px;
}
.split-bar-panel:last-child {
  margin-bottom:   0;
}
.split-bar-title {
  font-size:       11px;
  font-weight:     600;
  color:           var(--text-muted);
  text-transform:  uppercase;
  letter-spacing:  0.06em;
  margin-bottom:   8px;
}
.split-bar-chart {
  height:          280px;
  overflow-x:      auto;
  overflow-y:      hidden;
}

/* Center placeholder text when chart data is not yet available */
.chart-wrap .empty-state {
  height:          100%;
  display:         flex;
  align-items:     center;
  justify-content: center;
}

/* ApexCharts dark theme overrides */
.apexcharts-tooltip {
  background:      var(--bg-panel-alt) !important;
  border:          1px solid var(--border) !important;
  color:           var(--text) !important;
}

.apexcharts-tooltip-title {
  background:      var(--bg) !important;
  border-bottom:   1px solid var(--border) !important;
  color:           var(--text) !important;
}

/* Shared bar tooltip (R01 stacked bar — all series + Generated on hover) */
.bar-shared-tooltip {
  padding:    8px 11px;
  min-width:  150px;
  font-size:  12px;
}
.bar-shared-tooltip .bst-title {
  font-weight:    600;
  color:          var(--text);
  border-bottom:  1px solid var(--border);
  padding-bottom: 5px;
  margin-bottom:  5px;
}
.bar-shared-tooltip .bst-row {
  display:     flex;
  align-items: center;
  gap:         7px;
  padding:     2px 0;
  color:       var(--text-dim);
}
.bar-shared-tooltip .bst-row i {
  width:         8px;
  height:        8px;
  border-radius: 50%;
  flex:          none;
}
.bar-shared-tooltip .bst-row b {
  margin-left: auto;
  color:       var(--text);
  font-weight: 600;
}
.bar-shared-tooltip .bst-extra span { color: var(--text); }
.bar-shared-tooltip .bst-label-bold { font-weight: 600; color: var(--text); }

/* ── Buttons ───────────────────────────────────────────────────────────────── */
.btn {
  display:         inline-flex;
  align-items:     center;
  gap:             5px;
  padding:         5px 12px;
  font-family:     var(--font);
  font-size:       12px;
  font-weight:     500;
  border-radius:   var(--radius);
  border:          1px solid transparent;
  cursor:          pointer;
  transition:      background 0.15s, border-color 0.15s, color 0.15s;
  white-space:     nowrap;
  text-decoration: none;
}

.btn:focus-visible {
  outline:         2px solid var(--accent);
  outline-offset:  2px;
}

.btn-primary {
  background:      var(--accent);
  color:           #fff;
  border-color:    var(--accent);
}

.btn-primary:hover {
  background:      var(--accent-hover);
  border-color:    var(--accent-hover);
}

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

.btn-ghost:hover {
  background:      var(--bg-panel-alt);
  color:           var(--text);
  border-color:    var(--text-dim);
}

.btn-sm {
  padding:         3px 8px;
  font-size:       11px;
}

/* ── Badges ────────────────────────────────────────────────────────────────── */
.badge {
  display:         inline-block;
  font-size:       10px;
  font-weight:     600;
  padding:         1px 6px;
  border-radius:   3px;
  line-height:     1.6;
  vertical-align:  middle;
}

.badge-flagged   { background: rgba(230,57,70,.15);  color: #e63946; }
.badge-cleared   { background: rgba(63,185,80,.12);  color: #3fb950; }
.badge-incorrect { background: rgba(210,153,34,.12); color: #d29922; }
.badge-assigned  { background: rgba(56,139,253,.12); color: #58a6ff; }

/* ── Loading / Empty States ────────────────────────────────────────────────── */
.loading-wrap {
  display:         flex;
  align-items:     center;
  justify-content: center;
  min-height:      120px;
  color:           var(--text-dim);
  gap:             8px;
  font-size:       12px;
}

@keyframes spin { to { transform: rotate(360deg); } }

.spinner {
  display:         inline-block;
  width:           16px;
  height:          16px;
  border:          2px solid var(--border);
  border-top-color: var(--accent);
  border-radius:   50%;
  animation:       spin 0.7s linear infinite;
  flex-shrink:     0;
}

/* Dashboard's large, unmissable loading indicator — lives in the section tab
   bar itself (fixed-height row shared by every section) rather than
   overlaying or pushing the KPI bands below. Its box is always present
   (visibility toggled, not display) so the tab bar's width/layout — and the
   Refresh Mocked Data button's position — never shifts when a fetch starts
   or finishes. */
.dash-loading-banner {
  display:          flex;
  align-items:      center;
  justify-content:  center;
  width:            36px;
  visibility:       hidden;
}

.spinner-lg {
  width:            28px;
  height:           28px;
  border-width:     4px;
}

.empty-state {
  padding:         32px 16px;
  text-align:      center;
  color:           var(--text-dim);
  font-size:       12px;
  font-style:      italic;
}

/* ── Metric Selector (View 3) ──────────────────────────────────────────────── */
.metric-selector-wrap {
  display:         flex;
  align-items:     center;
  gap:             6px;
}

.metric-selector-label {
  font-size:       11px;
  font-weight:     600;
  color:           var(--text-muted);
  white-space:     nowrap;
}

/* ── Responsive ────────────────────────────────────────────────────────────── */
@media (max-width: 860px) {
  :root { --sidebar-w: 48px; }
  .nav-item-name,
  .nav-item-id,
  .sidebar-section-label { display: none; }
  .nav-item { justify-content: center; padding: 10px 0; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   Help Drawer
═══════════════════════════════════════════════════════════════════════════ */

/* ── Help Button (?) ───────────────────────────────────────────────────────── */
.help-btn {
  flex-shrink:     0;
  width:           32px;
  height:          32px;
  border-radius:   50%;
  border:          1px solid rgba(230, 57, 70, 0.45);
  background:      rgba(230, 57, 70, 0.08);
  color:           var(--accent);
  font-size:       15px;
  font-weight:     700;
  font-family:     var(--font);
  cursor:          pointer;
  display:         flex;
  align-items:     center;
  justify-content: center;
  transition:      background 0.15s, border-color 0.15s, color 0.15s;
  margin-top:      1px;
}

.help-btn:hover {
  background:      var(--accent-soft);
  border-color:    var(--accent);
  color:           var(--accent);
}

/* ── R10 Export button/dropdown (2026-07-21) ────────────────────────────────── */
.export-menu {
  position:        relative;
  flex-shrink:     0;
  margin-top:      1px;
}

.export-btn {
  height:          32px;
  padding:         0 14px;
  border-radius:   var(--radius);
  border:          1px solid var(--border);
  background:      var(--bg-panel);
  color:           var(--text);
  font-size:       13px;
  font-family:     var(--font);
  cursor:          pointer;
  transition:      background 0.15s, border-color 0.15s;
}

.export-btn:hover {
  background:      var(--accent-soft);
  border-color:    var(--accent);
}

.export-dropdown {
  position:        absolute;
  top:             calc(100% + 4px);
  right:           0;
  z-index:         20;
  background:      var(--bg-panel);
  border:          1px solid var(--border);
  border-radius:   var(--radius);
  box-shadow:      0 4px 16px rgba(0, 0, 0, 0.4);
  overflow:        hidden;
  min-width:       130px;
}

.export-dropdown button {
  display:         block;
  width:           100%;
  padding:         8px 14px;
  border:          none;
  background:      transparent;
  color:           var(--text);
  font-size:       13px;
  font-family:     var(--font);
  text-align:      left;
  cursor:          pointer;
}

.export-dropdown button:hover {
  background:      var(--accent-soft);
  color:           var(--accent);
}

/* ── Backdrop ──────────────────────────────────────────────────────────────── */
.help-backdrop {
  position:        fixed;
  inset:           0;
  z-index:         900;
  background:      rgba(0, 0, 0, 0.45);
  opacity:         0;
  pointer-events:  none;
  transition:      opacity 0.3s ease;
}

.help-backdrop.open {
  opacity:         1;
  pointer-events:  all;
}

/* ── Drawer Shell ──────────────────────────────────────────────────────────── */
.help-drawer {
  position:        fixed;
  top:             0;
  right:           0;
  width:           clamp(480px, 33vw, 700px);
  height:          100vh;
  z-index:         901;
  transform:       translateX(100%);
  transition:      transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  background:      rgba(22, 27, 34, 0.85);
  border-left:     1px solid rgba(255, 255, 255, 0.08);
  box-shadow:      -8px 0 40px rgba(0, 0, 0, 0.7);
  display:         flex;
  flex-direction:  column;
  overflow:        hidden;
}

.help-drawer.open {
  transform:       translateX(0);
}

/* ── Drawer Header ─────────────────────────────────────────────────────────── */
.help-drawer-header {
  display:         flex;
  align-items:     flex-start;
  justify-content: space-between;
  padding:         20px 20px 16px;
  border-bottom:   1px solid rgba(255, 255, 255, 0.07);
  flex-shrink:     0;
  gap:             12px;
}

.help-drawer-tag {
  font-size:       9px;
  font-weight:     700;
  letter-spacing:  1px;
  text-transform:  uppercase;
  color:           var(--accent);
  margin-bottom:   4px;
}

.help-drawer-title {
  font-size:       15px;
  font-weight:     600;
  color:           var(--text);
  line-height:     1.25;
}

.help-close-btn {
  width:           28px;
  height:          28px;
  flex-shrink:     0;
  border-radius:   var(--radius);
  border:          1px solid rgba(255, 255, 255, 0.1);
  background:      rgba(255, 255, 255, 0.04);
  color:           var(--text-muted);
  font-size:       13px;
  cursor:          pointer;
  display:         flex;
  align-items:     center;
  justify-content: center;
  transition:      background 0.15s, color 0.15s, border-color 0.15s;
  margin-top:      2px;
}

.help-close-btn:hover {
  background:      rgba(230, 57, 70, 0.12);
  color:           var(--accent);
  border-color:    rgba(230, 57, 70, 0.3);
}

/* ── Filters Applied Strip ─────────────────────────────────────────────────── */
.help-filters-applied {
  padding:         12px 20px;
  border-bottom:   1px solid rgba(255, 255, 255, 0.06);
  background:      rgba(255, 255, 255, 0.02);
  flex-shrink:     0;
}

.help-filters-title {
  font-size:       10px;
  font-weight:     700;
  letter-spacing:  0.12em;
  text-transform:  uppercase;
  color:           var(--text-muted);
  margin:          -12px -20px 10px;
  padding:         10px 20px;
  background:      rgba(255, 255, 255, 0.05);
  border-bottom:   1px solid rgba(255, 255, 255, 0.09);
}

.help-filter-row {
  display:         flex;
  gap:             6px;
  font-size:       11.5px;
  line-height:     1.6;
}

.help-filter-key {
  color:           var(--text-dim);
  min-width:       88px;
  flex-shrink:     0;
}

.help-filter-val {
  color:           var(--text);
  font-weight:     500;
}

/* ── Drawer Scrollable Body ────────────────────────────────────────────────── */
.help-drawer-body {
  flex:            1;
  overflow-y:      auto;
  padding-bottom:  32px;
}

/* ── Help Sections ─────────────────────────────────────────────────────────── */
.help-section {
  padding:         16px 20px;
  border-bottom:   1px solid rgba(255, 255, 255, 0.08);
}

.help-section:last-child {
  border-bottom:   none;
}

.help-section-title {
  font-size:       10px;
  font-weight:     700;
  letter-spacing:  0.12em;
  text-transform:  uppercase;
  color:           var(--text-muted);
  margin:          -16px -20px 14px;
  padding:         10px 20px;
  background:      rgba(255, 255, 255, 0.05);
  border-bottom:   1px solid rgba(255, 255, 255, 0.09);
}

/* Purpose */
.help-purpose {
  font-size:       12.5px;
  color:           var(--text-muted);
  line-height:     1.6;
  font-style:      italic;
}

/* View definitions */
.help-view-item {
  margin-bottom:   14px;
}

.help-view-item:last-child {
  margin-bottom:   0;
}

.help-view-name {
  font-size:       12px;
  font-weight:     600;
  color:           var(--text);
  margin-bottom:   4px;
}

.help-view-what {
  font-size:       12px;
  color:           var(--text-muted);
  line-height:     1.55;
  margin-bottom:   6px;
}

.help-view-how {
  padding-left:    10px;
  border-left:     2px solid var(--border);
  display:         flex;
  flex-direction:  column;
  gap:             4px;
}

.help-view-how-item {
  font-size:       11.5px;
  color:           var(--text-muted);
  line-height:     1.5;
}

/* Metric rows */
.help-metric-row {
  display:         flex;
  gap:             10px;
  margin-bottom:   8px;
  font-size:       12px;
  line-height:     1.5;
}

.help-metric-row:last-child {
  margin-bottom:   0;
}

.help-metric-name {
  font-weight:     600;
  color:           var(--text);
  flex-shrink:     0;
  min-width:       68px;
}

.help-metric-def {
  color:           var(--text-muted);
}

/* Key questions */
.help-questions-list {
  list-style:      none;
  padding:         0;
  margin:          0;
  display:         flex;
  flex-direction:  column;
  gap:             6px;
}

.help-questions-list li {
  font-size:       12px;
  color:           var(--text-muted);
  line-height:     1.55;
  padding-left:    14px;
  position:        relative;
}

.help-questions-list li::before {
  content:         "›";
  position:        absolute;
  left:            0;
  color:           var(--accent);
  font-weight:     700;
  line-height:     1.55;
}

/* Watch points */
.help-watchpoint {
  display:         flex;
  gap:             9px;
  padding:         9px 11px;
  background:      rgba(230, 57, 70, 0.06);
  border:          1px solid rgba(230, 57, 70, 0.14);
  border-radius:   var(--radius);
  margin-bottom:   6px;
  font-size:       12px;
  line-height:     1.55;
  color:           var(--text-muted);
}

.help-watchpoint:last-child {
  margin-bottom:   0;
}

.help-watchpoint-icon {
  color:           var(--warning);
  flex-shrink:     0;
  font-size:       11px;
  margin-top:      2px;
}

/* Data coverage */
.help-coverage {
  font-size:       12px;
  color:           var(--text-muted);
  line-height:     1.6;
}

/* Related reports */
.help-related-list {
  display:         flex;
  flex-direction:  column;
  gap:             5px;
}

.help-related-link {
  display:         flex;
  align-items:     center;
  gap:             8px;
  padding:         7px 11px;
  border-radius:   var(--radius);
  border:          1px solid var(--border);
  background:      rgba(255, 255, 255, 0.02);
  color:           var(--text-muted);
  font-size:       12px;
  font-family:     var(--font);
  cursor:          pointer;
  transition:      background 0.15s, color 0.15s, border-color 0.15s;
  text-align:      left;
  width:           100%;
}

.help-related-link:hover {
  background:      var(--accent-soft);
  border-color:    rgba(230, 57, 70, 0.3);
  color:           var(--text);
}

.help-related-arrow {
  color:           var(--accent);
  font-size:       13px;
  flex-shrink:     0;
}

/* Coming soon */
.help-placeholder {
  font-size:       12px;
  color:           var(--text-dim);
  font-style:      italic;
}

/* Responsive: full-width drawer on narrow screens */
@media (max-width: 860px) {
  .help-drawer { width: 100vw; }
}

/* ── View Expand / Collapse ────────────────────────────────────────────────── */
.view-expand-btn {
  display:         flex;
  align-items:     center;
  justify-content: center;
  width:           22px;
  height:          22px;
  flex-shrink:     0;
  border-radius:   var(--radius);
  border:          1px solid var(--border);
  background:      var(--bg-panel);
  color:           var(--text-dim);
  font-size:       13px;
  line-height:     1;
  cursor:          pointer;
  transition:      background 0.15s, border-color 0.15s, color 0.15s;
}

.view-expand-btn:hover {
  background:      var(--bg-panel-alt);
  border-color:    var(--text-muted);
  color:           var(--text);
}

/* When a view is expanded, lock the scroll container and hide the others */
.views-container.has-expanded {
  overflow-y:      hidden;
}

.views-container.has-expanded .view-panel:not(.expanded) {
  display:         none;
}

/* Expanded panel — fill the full views-container height */
.view-panel.expanded {
  flex:            1;
  min-height:      0;
  display:         flex;
  flex-direction:  column;
}

.view-panel.expanded .view-panel-body {
  flex:            1;
  min-height:      0;
  display:         flex;
  flex-direction:  column;
}

.view-panel.expanded .chart-wrap {
  flex:            1;
  min-height:      0;
}

/* ── Catch Up button (tab bar, far right) ──────────────────────────────────── */
.catchup-btn {
  margin-left:     auto;
  align-self:      center;
  display:         flex;
  align-items:     center;
  gap:             6px;
  padding:         5px 13px;
  font-family:     var(--font);
  font-size:       12px;
  font-weight:     500;
  color:           #58a6ff;
  background:      transparent;
  border:          1px solid rgba(88, 166, 255, 0.4);
  border-radius:   var(--radius);
  cursor:          pointer;
  transition:      color 0.15s, border-color 0.15s, background 0.15s;
  white-space:     nowrap;
}

.catchup-btn:hover:not(:disabled) {
  color:           #58a6ff;
  border-color:    #58a6ff;
  background:      rgba(88, 166, 255, 0.1);
}

.catchup-btn:disabled {
  color:           var(--text-dim);
  border-color:    var(--text-dim);
  cursor:          not-allowed;
  opacity:         0.6;
}

.catchup-icon {
  font-size:       14px;
  line-height:     1;
}

/* ── Geo Maps Section ──────────────────────────────────────────────────────── */

.geo-section {
  flex:            1;
  display:         flex;
  flex-direction:  column;
  overflow:        hidden;
  min-height:      0;
}

.geo-filter-bar {
  height:          var(--filter-h);
  min-height:      var(--filter-h);
  background:      var(--bg-panel-alt);
  border-bottom:   1px solid var(--border);
  display:         flex;
  align-items:     center;
  padding:         0 20px;
  gap:             16px;
  flex-shrink:     0;
}

.geo-map-wrap {
  flex:            1;
  position:        relative;
  min-height:      0;
}

#geo-map {
  position:        absolute;
  inset:           0;
  width:           100%;
  height:          100%;
}

.geo-loading {
  position:        absolute;
  inset:           0;
  display:         flex;
  align-items:     center;
  justify-content: center;
  gap:             10px;
  background:      rgba(13,17,23,0.7);
  color:           var(--text-muted);
  font-size:       13px;
  z-index:         1000;
}

/* ── Leaflet dark theme overrides ──────────────────────────────────────────── */

.leaflet-container {
  background:      var(--bg);
  font-family:     var(--font);
}

.leaflet-control-zoom a {
  background:      var(--bg-panel) !important;
  color:           var(--text) !important;
  border-color:    var(--border) !important;
}

.leaflet-control-zoom a:hover {
  background:      var(--bg-panel-alt) !important;
  color:           var(--accent) !important;
}

.leaflet-control-attribution {
  background:      rgba(22,27,34,0.75) !important;
  color:           var(--text-dim) !important;
  font-size:       10px !important;
}

.leaflet-control-attribution a {
  color:           var(--text-muted) !important;
}

/* ── Geo tooltip ───────────────────────────────────────────────────────────── */

.geo-tooltip {
  background:      rgba(22,27,34,0.92) !important;
  border:          1px solid var(--border) !important;
  border-radius:   var(--radius) !important;
  color:           var(--text) !important;
  box-shadow:      var(--shadow) !important;
  padding:         10px 13px !important;
  backdrop-filter: blur(8px);
  min-width:       160px;
  pointer-events:  none;
}

.geo-tooltip::before { display: none !important; }

.geo-tip-name {
  font-size:       13px;
  font-weight:     600;
  color:           var(--text);
  margin-bottom:   2px;
}

.geo-tip-group {
  font-size:       11px;
  color:           var(--text-muted);
  margin-bottom:   6px;
}

.geo-tip-divider {
  height:          1px;
  background:      var(--border);
  margin-bottom:   6px;
}

.geo-tip-row {
  display:         flex;
  justify-content: space-between;
  gap:             16px;
  font-size:       12px;
  color:           var(--text-muted);
  line-height:     1.6;
}

.geo-tip-val {
  color:           var(--text);
  font-weight:     500;
  font-variant-numeric: tabular-nums;
}

/* Incidents row reads in the same amber as the map's hazard-triangle marker
   when a site has 1+ (2026-07-09; amber, not accent red — the marker itself
   moved to amber the same session so the tooltip number matches it). */
.geo-tip-val.geo-tip-incident {
  color:       #f59e0b;
  font-weight: 700;
}

/* Indented sub-item rows in the Dashboard KPI-selector tooltips (2026-07-10)
   — e.g. Armed/Disarmed/No Schedule/No Zones under Enabled on the Cameras
   KPI. */
.geo-tip-row.geo-tip-indent {
  padding-left: 12px;
}

/* ── Geo legend ────────────────────────────────────────────────────────────── */

.geo-legend-panel {
  background:      rgba(22,27,34,0.92);
  border:          1px solid var(--border);
  border-radius:   var(--radius);
  padding:         10px 12px;
  backdrop-filter: blur(8px);
  min-width:       150px;
  box-shadow:      var(--shadow);
}

.geo-legend-title {
  font-size:       12px;
  font-weight:     600;
  color:           var(--text);
  margin-bottom:   2px;
}

.geo-legend-meta {
  font-size:       10px;
  color:           var(--text-muted);
  margin-bottom:   8px;
}

.geo-legend-scale {
  display:         flex;
  gap:             4px;
  margin-bottom:   4px;
  align-items:     center;
}

.geo-legend-dot {
  display:         inline-block;
  width:           18px;
  height:          10px;
  border-radius:   3px;
  flex-shrink:     0;
}

.geo-legend-range {
  display:         flex;
  justify-content: space-between;
  font-size:       10px;
  color:           var(--text-muted);
  font-variant-numeric: tabular-nums;
}

/* Incident-marker key (2026-07-09) — always shown, same as the colour scale
   above it, so the glyph's meaning is explained even on a view with no
   current incidents. */
.geo-legend-incident {
  display:       flex;
  align-items:   center;
  gap:           6px;
  margin-top:    8px;
  padding-top:   6px;
  border-top:    1px solid var(--border);
  font-size:     10px;
  color:         var(--text-muted);
}

/* Icon content is now an inline SVG (2026-07-09), not a text glyph — colour
   comes from the SVG's own fill, this just handles layout so it doesn't
   stretch or misalign against the label text next to it. */
.geo-legend-incident-icon {
  display:     inline-flex;
  flex-shrink: 0;
}

.geo-legend-incident-icon svg {
  display: block;
}

/* ── Geo pulse animation (highest-severity marker) ─────────────────────────── */

@keyframes geo-pulse {
  0%   { transform: scale(1);   opacity: 0.9; }
  50%  { transform: scale(1.7); opacity: 0; }
  100% { transform: scale(1);   opacity: 0.9; }
}

.geo-pulse {
  animation:        geo-pulse 2s ease-out infinite;
  transform-origin: center;
  transform-box:    fill-box;
}

/* Incident marker (a divIcon rendered above a site's circle when it has 1+
   confirmed incidents/Flagged alerts) — deliberately a distinct SHAPE, not
   just another colour, since the circle already uses colour for the
   (unrelated) volume-percentile scale. Non-interactive (see geo.js) —
   pointer-events:none here is defensive/explicit, ensuring hover always
   reaches the circle beneath. Icon content is an inline SVG hazard triangle
   (2026-07-09, replacing a flat "▲" text glyph Bruce found "isn't obvious")
   — drop-shadow (not text-shadow, since there's no text here anymore) gives
   it definition against whatever tile/circle colour is directly behind it. */
.geo-incident-marker {
  display:         flex;
  align-items:     center;
  justify-content: center;
  filter:          drop-shadow(0 1px 2px rgba(0,0,0,0.7));
  pointer-events:  none;
}

/* ═══════════════════════════════════════════════════════════════════════════
   Comparisons Section
═══════════════════════════════════════════════════════════════════════════ */

/* ── Compare section shell ─────────────────────────────────────────────────── */

#compare-section {
  display:        flex;
  flex-direction: row;
  flex:           1;
  min-height:     0;
  overflow:       hidden;
}

/* ── Compare filter bar ────────────────────────────────────────────────────── */

.compare-filter-bar {
  display:          flex;
  align-items:      center;
  gap:              16px;
  padding:          0 20px;
  height:           var(--filter-h);
  min-height:       var(--filter-h);
  background:       var(--bg-panel-alt);
  border-bottom:    1px solid var(--border);
  flex-shrink:      0;
  flex-wrap:        nowrap;
  overflow-x:       auto;
}

/* ── Compare body: sidebar + main ──────────────────────────────────────────── */

.compare-body {
  display:    flex;
  flex:       1;
  min-height: 0;
  overflow:   hidden;
}

/* Reuse #sidebar styles — compare-sidebar gets same base, just different id */
#compare-sidebar {
  width:            220px;
  min-width:        220px;
  background:       var(--bg-panel);
  border-right:     1px solid var(--border);
  overflow-y:       auto;
  flex-shrink:      0;
  padding:          12px 0;
}

/* ── Compare KPI delta cards ───────────────────────────────────────────────── */

/* .compare-kpi-grid was display:grid (repeat(auto-fill, minmax(200px,1fr)))
   until 2026-07-15 — the element also carries .kpi-grid, so with the grid
   override removed it inherits Analytics' flex model (Rule 29: flex-wrap +
   .kpi-card's flex:1 1 160px / min-width:0). Aligned so per-report KPI
   layout features work identically on both tabs — the immediate driver was
   R06's .kpi-gap-spacer (a flex-basis spacer, meaningless inside a grid;
   Bruce's request), and it also obsoleted the grid-column:1/-1 span rule
   R08's .kpi-group-wrapper needed under grid (Rule 38) — the wrapper's own
   flex-basis:100% now handles that, same as Analytics. */

.compare-kpi-card {
  background:    var(--bg-panel-alt);
  border:        1px solid var(--border);
  border-radius: var(--radius);
  padding:       12px 14px;
}

.compare-kpi-card .kpi-label {
  font-size:   11px;
  font-weight: 600;
  color:       var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-bottom: 8px;
}

.kpi-compare-grid {
  display:        flex;
  flex-direction: column;
  align-items:    stretch;
  gap:            5px;
}

.kpi-compare-col {
  display:         flex;
  flex-direction:  row;
  justify-content: space-between;
  align-items:     baseline;
  gap:             8px;
}

.kpi-compare-grid .kpi-compare-delta {
  align-self: flex-end;
}

.kpi-compare-period-label {
  font-size:  10px;
  color:      var(--text-muted);
  white-space: nowrap;
}

.kpi-compare-value {
  font-size:   20px;
  font-weight: 700;
  color:       var(--text);
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}

.kpi-compare-delta {
  font-size:     12px;
  font-weight:   700;
  padding:       3px 8px;
  border-radius: 4px;
  white-space:   nowrap;
  margin-left:   auto;
  align-self:    flex-end;
}

.kpi-compare-delta.positive {
  color:      #3fb950;
  background: rgba(63, 185, 80, 0.12);
}

.kpi-compare-delta.negative {
  color:      var(--accent);
  background: var(--accent-soft);
}

.kpi-compare-delta.neutral {
  color:      var(--text-muted);
  background: rgba(139, 148, 158, 0.1);
}


/* ═══════════════════════════════════════════════════════════════════════════
   Dashboard Section
═══════════════════════════════════════════════════════════════════════════ */

#dash-section {
  display: flex;
  flex-direction: column;
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
}

/* ── Dashboard Filter Bar ── */

.dash-filter-bar {
  display:       flex;
  align-items:   center;
  gap:           0 16px;
  padding:       10px 20px;
  background:    var(--bg-panel-alt);
  border-bottom: 1px solid var(--border);
  flex-shrink:   0;
}

.dash-refresh-ctrl {
  margin-left:   auto;
  display:       flex;
  align-items:   center;
  gap:           8px;
  padding:       5px 12px;
  border:        1px solid var(--border);
  border-radius: var(--radius);
  background:    var(--bg-input);
}

.dash-refresh-label {
  font-size:      10px;
  font-weight:    700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color:          var(--text-dim);
  white-space:    nowrap;
  padding-right:  4px;
  border-right:   1px solid var(--border);
  margin-right:   2px;
}

.dash-refresh-btn {
  background:    transparent;
  border:        1px solid rgba(88, 166, 255, 0.4);
  color:         #58a6ff;
  padding:       4px 14px;
  border-radius: var(--radius);
  cursor:        pointer;
  font-size:     12px;
  font-family:   var(--font-mono);
  transition:    border-color 0.15s, color 0.15s, background 0.15s;
}

.dash-refresh-btn:hover {
  border-color: #58a6ff;
  color:        #58a6ff;
  background:   rgba(88, 166, 255, 0.1);
}

.dash-refresh-countdown {
  font-family: var(--font-mono);
  font-size:   13px;
  font-weight: 600;
  color:       var(--text);
  min-width:   32px;
  text-align:  right;
  font-variant-numeric: tabular-nums;
}

/* ── KPI Bands ── */

.dash-kpi-area {
  display:     flex;
  flex-wrap:   wrap;
  align-items: stretch;
  gap:         16px 24px;
  padding:     16px 20px 12px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}

.dash-band {
  display:        flex;
  flex-direction: column;
}

.dash-band-header {
  font-size:      11px;
  font-weight:    700;
  letter-spacing: 0.10em;
  color:          var(--text);
  text-transform: uppercase;
  margin-bottom:  10px;
  padding-left:   10px;
  border-left:    3px solid var(--accent);
  line-height:    1.2;
}

.dash-band-header-note {
  text-transform: none;
  font-weight:    400;
  letter-spacing: normal;
  color:          var(--text-muted);
  margin-left:    6px;
}

.dash-band-cards {
  display:     flex;
  gap:         10px;
  /* flex-start (was stretch) — the two card tiers below have deliberately
     DIFFERENT fixed heights (focus vs non-focus, 2026-07-09); stretch would
     pull every non-focus card in a row up to the focus card's height,
     erasing the size distinction Bruce asked for. */
  align-items: flex-start;
}

/* Vertical alignment across a band's cards (Alert Queue/Activity/Performance/
   Operator Load — Bruce: titles wrap to 1 or 2 lines depending on length,
   which pushed the value and delta badge below to different heights per
   card). Reserving a fixed 2-line title box makes the value row — and so the
   delta/sublabel row after it — start at the same Y position on every card
   in the row, regardless of that card's own title length. Scoped to
   .dash-band-cards specifically (not the shared .kpi-label/.kpi-value used
   by Reports/Operators/Comparisons, which weren't part of this request). */
.dash-band-cards .kpi-label {
  line-height: 1.3;
  min-height:  26px; /* 2 lines at 10px/1.3 */
}

.dash-band-cards .kpi-value {
  white-space:   nowrap;
  overflow:      hidden;
  text-overflow: ellipsis;
}

/* Reserves the sublabel row's height even when a card's .kpi-sublabel div is
   empty (2026-07-09) — every Dashboard KPI card now always renders that div
   (see renderDashboardKpis() in app.js), blank when there's nothing to show,
   so cards within the same size tier (focus vs non-focus) stay pixel-equal
   regardless of which ones have real sublabel text. Same reasoning as the
   .kpi-label min-height fix above (Session 51), one row lower. */
.dash-band-cards .kpi-sublabel,
.dash-camera-row .kpi-sublabel {
  min-height: 12px;
}

/* % Armed's card (#dash-cam-focus) lives inside .dash-camera-row, not
   .dash-band-cards, so it never got the .kpi-label height reservation above
   — its shorter one-line label let its value start higher than every other
   hero card's, so % Armed's "33.6%" and Workload Gap's "+2.2" didn't line
   up (Bruce's screenshot, 2026-07-10). Same 26px/1.3 reservation, applied
   here so every hero card's value row starts at an identical Y offset
   regardless of which container it lives in. */
.dash-camera-row .kpi-label {
  line-height: 1.3;
  min-height:  26px;
}

/* Two fixed card tiers (2026-07-09, Bruce's screenshot feedback on the first
   pass): the base .kpi-card's flex:1 1 160px GROWS to fill its band's row,
   so a card's real width depended on how many siblings it shared a band
   with — focus cards came out different widths per band. Dashboard cards
   now use fixed flex-basis with no grow: every focus card is exactly one
   size (matched to how the Oldest Alert card rendered), every non-focus
   card exactly one smaller size. min-heights keep the two tiers'
   HEIGHTS uniform too (a card whose delta badge is absent would otherwise
   render shorter than its siblings). Scoped to the Dashboard's own
   containers — Reports/Operators/Comparisons keep the flexible base rule. */
.dash-band-cards .kpi-card {
  flex:       0 0 160px;
  min-height: 136px;
}

/* Focus card — one per Dashboard band/section, the section's headline KPI,
   always the band's first card (2026-07-09, Bruce's request). Bigger value
   font + left accent border + the larger of the two fixed sizes. */
.kpi-card.dash-hero {
  border-left: 3px solid var(--accent);
  flex:        0 0 200px;
  min-height:  150px;
}

.kpi-card.dash-hero .kpi-value {
  font-size: 38px;
}

/* Queue Depth's "queue is growing" warning — kept on Queue Depth itself
   (the metric that's actually growing) rather than moving to the Oldest
   Alert focus card, so it no longer needs .dash-hero; applies to a plain
   .kpi-card the same way it did to the hero card before (2026-07-09). */
.kpi-card.queue-growing {
  border-color: var(--accent);
  background:   rgba(230, 57, 70, 0.06);
}

.kpi-sublabel {
  font-size:      10px;
  color:          var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin-top:     3px;
}

/* Delta badge */
.kpi-delta-badge {
  display:       inline-block;
  font-size:     13px;
  font-family:   var(--font-mono);
  padding:       3px 8px;
  border-radius: 3px;
  margin-top:    6px;
  font-weight:   700;
}

.kpi-delta-badge.delta-good {
  color:      #22c55e;
  background: rgba(34, 197, 94, 0.12);
}

.kpi-delta-badge.delta-bad {
  color:      var(--accent);
  background: var(--accent-soft);
}

.kpi-delta-badge.delta-neutral {
  color:      var(--text-muted);
  background: rgba(139, 148, 158, 0.10);
}

/* Delta inside the metric's typical 7-day band for this clock window —
   deliberately as quiet as neutral, whatever its direction, so a coloured
   badge always means "outside normal variation" (Dashboard baseline model). */
.kpi-delta-badge.delta-within {
  color:      var(--text-muted);
  background: rgba(139, 148, 158, 0.10);
}

/* Baseline micro-label inside the delta badge ("vs 7-day norm" / "vs yesterday") */
.delta-baseline-lbl {
  margin-left:    6px;
  font-size:      9px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  opacity:        0.65;
}

/* KPI unit suffix */
.kpi-unit {
  font-size:   11px;
  color:       var(--text-muted);
  font-weight: 400;
}

/* ── Camera Health Compact Panel ── */

/* Wraps the % Armed focus card and the 3 compact camera-state cards side by
   side (2026-07-09) — % Armed is its own focus-sized kpi-card; the other 5
   states are split across 3 compact cards (Enabled|Disabled, Armed|Disarmed,
   Snoozed — Bruce's grouping). flex-start (was stretch): the compact cards
   keep the standard non-focus height rather than rising to the focus card's
   — same focus/non-focus size distinction as every other band (Bruce's
   screenshot feedback, second round). */
.dash-camera-row {
  display:     flex;
  gap:         10px;
  align-items: flex-start;
}

/* #dash-cam-focus is a plain wrapper div (not itself a .kpi-card), so it
   needs its own flex-basis matching the focus-card width; display:flex lets
   the card inside fill the wrapper's full width and stretched height. */
#dash-cam-focus {
  flex:    0 0 200px;
  display: flex;
}

#dash-cam-focus .kpi-card {
  flex: 1;
}

/* Row of the 3 compact camera-state cards */
.dash-camera-cards {
  display:     flex;
  gap:         10px;
  align-items: stretch;
}

/* Column layout (2026-07-10): a small category title ("Enabled"/"Disabled"/
   "Snoozed") above the item row — needed now that the Enabled card's 4
   sub-items (Armed/Disarmed/No Schedule/No Zones, none of them literally
   labelled "Enabled") would otherwise have nothing on the card explaining
   what population they're drawn from. */
.dash-camera-health {
  display:        flex;
  flex-direction: column;
  gap:            8px;
  background:     var(--bg-panel);
  border:         1px solid var(--border);
  border-radius:  var(--radius);
  padding:        10px 12px;
  /* Matches the standard non-focus card tier (136px) so these read as
     non-focus siblings of the % Armed focus card, not equals. */
  min-height:     136px;
}

.cam-health-card-title {
  font-size:      10px;
  font-weight:    700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color:          var(--accent);
  padding-bottom: 6px;
  border-bottom:  1px solid var(--border);
}

.cam-health-items {
  display:     flex;
  align-items: center;
  flex:        1;
}

.cam-health-item {
  display:        flex;
  flex-direction: column;
  align-items:    center;
  padding:        0 14px;
  gap:            4px;
}

.cam-health-val {
  font-size:   22px;
  font-weight: 700;
  font-family: var(--font-mono);
  color:       var(--text);
}

.cam-health-lbl {
  font-size:      10px;
  color:          var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  white-space:    nowrap;
}

.cam-health-sep {
  width:      1px;
  height:     38px;
  background: var(--border);
  flex-shrink: 0;
}

/* Disabled/Snoozed — single-value cards; the card title already says what
   the number is, so no repeated per-item label underneath it. */
.dash-camera-health-single {
  min-width: 140px;
}

.cam-health-val-solo {
  flex:            1;
  display:         flex;
  align-items:     center;
  justify-content: center;
  font-size:       28px;
  font-weight:     700;
  font-family:     var(--font-mono);
  color:           var(--text);
}

/* ── Dashboard Panels ── */

.dash-panel {
  margin:        12px 20px;
  background:    var(--bg-panel);
  border:        1px solid var(--border);
  border-radius: var(--radius);
  padding:       14px 16px;
  flex-shrink:   0;
}

.dash-panel-title {
  font-size:      11px;
  font-weight:    600;
  color:          var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.10em;
  margin-bottom:  10px;
}

.dash-chart-container {
  height:   320px;
  overflow: hidden;
}

/* Per-section failure state (TODO-228) — rendered into only the failed
   section's own containers; the other Dashboard sections keep working. */
.dash-section-error {
  display:         flex;
  flex-direction:  column;
  align-items:     center;
  justify-content: center;
  gap:             6px;
  padding:         24px 16px;
  color:           var(--text-muted);
  font-size:       13px;
  text-align:      center;
  border:          1px dashed var(--border);
  border-radius:   var(--radius);
  width:           100%;
}

.dash-section-error-detail {
  font-size:  11px;
  color:      var(--text-dim);
  max-width:  480px;
  word-break: break-word;
}

.dash-geo-panel {
  margin-bottom: 20px;
}

.dash-geo-container {
  height:        480px;
  border-radius: 4px;
  overflow:      hidden;
}

/* ── Dashboard panel header (title + expand button) ── */

.dash-panel-header {
  display:         flex;
  align-items:     center;
  justify-content: space-between;
  margin-bottom:   10px;
}

.dash-panel-header .dash-panel-title {
  margin-bottom: 0;
}

/* Right-hand control group in a dash panel header (KPI selector + expand
   button on the geo panel, 2026-07-10) — keeps the selector snug against
   the button instead of floating mid-header under space-between. */
.dash-panel-controls {
  display:     flex;
  align-items: center;
  gap:         10px;
}

/* ── Dashboard panel expand / collapse ── */

#dash-section.has-dash-expanded .dash-panel:not(.dash-panel-expanded) {
  display: none;
}

#dash-section.has-dash-expanded .dash-panel.dash-panel-expanded {
  flex:           1;
  min-height:     0;
  margin-bottom:  0;
  display:        flex;
  flex-direction: column;
}

#dash-section.has-dash-expanded .dash-panel.dash-panel-expanded .dash-chart-container,
#dash-section.has-dash-expanded .dash-panel.dash-panel-expanded .dash-geo-container {
  flex:   1;
  height: auto;
}

/* ── KPI Hover Tooltip ── */

[data-kpi-help] {
  cursor: help;
}

#kpi-tooltip {
  display:          none;
  position:         fixed;
  z-index:          9999;
  width:            270px;
  background:       rgba(16, 20, 28, 0.96);
  backdrop-filter:  blur(10px);
  border:           1px solid var(--border);
  border-radius:    var(--radius);
  padding:          12px 14px;
  pointer-events:   none;
  box-shadow:       0 6px 24px rgba(0, 0, 0, 0.5);
}

#kpi-tooltip.visible {
  display: block;
}

.kpi-tooltip-title {
  font-size:      10px;
  font-weight:    700;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color:          var(--accent);
  margin-bottom:  7px;
}

.kpi-tooltip-body {
  font-size:   12px;
  color:       var(--text);
  line-height: 1.55;
}

/* ── Sidebar report tooltip ────────────────────────────────────────────────── */
#nav-tooltip {
  display:        none;
  position:       fixed;
  z-index:        9999;
  width:          210px;
  background:     rgba(22, 28, 36, 0.96);
  border:         1px solid var(--border);
  border-radius:  var(--radius);
  padding:        10px 13px 12px;
  pointer-events: none;
  box-shadow:     0 6px 24px rgba(0, 0, 0, 0.5);
}

#nav-tooltip.visible {
  display: block;
}

.nav-tip-id {
  font-size:      10px;
  font-weight:    700;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color:          var(--accent);
  margin-bottom:  7px;
}

.nav-tip-list {
  margin:      0;
  padding:     0 0 0 12px;
  font-size:   11.5px;
  color:       var(--text);
  line-height: 1.75;
}

/* ── Operators Section ─────────────────────────────────────────────────────── */
.operators-section {
  flex:       1;
  display:    flex;
  overflow:   hidden;
}

/* ── Authentication: login page + header user chip (TODO-212/213) ──────────── */

.login-body {
  display:         flex;
  align-items:     center;
  justify-content: center;
  min-height:      100vh;
}

.login-card {
  background:      var(--bg-panel);
  border:          1px solid var(--border);
  border-radius:   8px;
  padding:         36px 40px;
  width:           360px;
  display:         flex;
  flex-direction:  column;
  gap:             12px;
}

.login-logo {
  height:          42px;
  align-self:      center;
  margin-bottom:   4px;
}

.login-title {
  color:           var(--text);
  font-size:       14px;
  text-align:      center;
  margin-bottom:   10px;
}

.login-error {
  background:      var(--accent-soft);
  border:          1px solid var(--accent);
  border-radius:   4px;
  color:           var(--text);
  font-size:       12px;
  padding:         8px 10px;
}

.login-form {
  display:         flex;
  flex-direction:  column;
  gap:             10px;
}

.login-label {
  color:           var(--text-muted);
  font-size:       11px;
  text-transform:  uppercase;
  letter-spacing:  0.5px;
}

.login-input {
  background:      var(--bg-input);
  border:          1px solid var(--border);
  border-radius:   4px;
  color:           var(--text);
  font-family:     inherit;
  font-size:       13px;
  padding:         9px 10px;
  outline:         none;
}

.login-input:focus {
  border-color:    var(--border-focus);
}

.login-btn {
  margin-top:      8px;
  background:      var(--accent);
  border:          none;
  border-radius:   4px;
  color:           #fff;
  font-family:     inherit;
  font-size:       13px;
  font-weight:     600;
  padding:         10px 0;
  cursor:          pointer;
}

.login-btn:hover {
  background:      var(--accent-hover);
}

/* Mirrors .header-account's shape — a label-side column beside a 2-row
   stack — so the two right-hand header groups read as one tidy, aligned
   pair. Restructured 2026-07-15 (Bruce's request): the "User" label and its
   icon are now stacked (label-col), and the control column's rows swapped
   to Logout button (row 1) / username (row 2, small text falling under the
   button) — mirroring Account's select-then-freshness pattern exactly, so
   the account SELECT and the logout BUTTON — the two "field/button"
   controls — land in the same row, both vertically centered by the same
   amount within the header's fixed height (their columns are now the same
   overall height as Account's select+freshness column). */
.header-user {
  display:         flex;
  /* flex-start, not center — same fix and reasoning as .header-account
     above (2026-07-15): centers the label-col against just the top row of
     .header-user-control (the Logout button), matching "Account" instead of
     centering against the full 2-row height. */
  align-items:     flex-start;
  gap:             10px;
  flex-shrink:     0;
}

.header-user-label-col {
  display:        flex;
  flex-direction: column;
  align-items:    center;
  gap:            4px;
}

.header-user-control {
  display:        flex;
  flex-direction: column;
  align-items:    flex-start;
  gap:            3px;
}

.header-user-icon {
  color:       var(--text-muted);
  flex-shrink: 0;
}

.header-user-name {
  color:           var(--text-muted);
  font-size:       13px;
  /* Left-align with the Logout BUTTON's own label text, not its outer edge
     (2026-07-15, Bruce's screenshot) — same reasoning as
     .header-account-freshness above: the button has a 1px border + 12px
     left padding before "Log out" starts. */
  padding-left:    13px;
}

.logout-btn {
  background:      var(--bg-input);
  border:          1px solid var(--border);
  border-radius:   4px;
  color:           var(--text-muted);
  font-family:     inherit;
  font-size:       13px;
  padding:         5px 12px;
  cursor:          pointer;
}

.logout-btn:hover {
  border-color:    var(--accent);
  color:           var(--text);
}
