/* ═══════════════════════════════════════════════════════
   VOLTIQ ADMIN — Tesla V12 Design System
   Light monochromatic
═══════════════════════════════════════════════════════ */

:root {
  --sw: 240px;           /* sidebar width */
  --th: 64px;            /* topbar height */

  /* Surfaces */
  --bg:    #f4f5f7;
  --s1:    #ffffff;
  --s2:    #f0f1f4;
  --s3:    #e5e7eb;
  --s4:    #d1d5db;

  /* Borders */
  --b1: rgba(0,0,0,0.08);
  --b2: rgba(0,0,0,0.14);
  --b3: rgba(0,0,0,0.20);

  /* Text */
  --t1: #111827;
  --t2: #6b7280;
  --t3: #9ca3af;
  --t4: #c4c9d4;

  /* Primary accent */
  --w:       #2563EB;
  --w-hover: #1D4ED8;
  --w-light: #EFF6FF;

  /* Radius */
  --r1: 6px;
  --r2: 10px;
  --r3: 14px;
  --r4: 18px;
  --rf: 9999px;

  /* Transition */
  --tf: 140ms ease;
  --tm: 200ms ease;
  --ts: 300ms ease;

  --font: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}

/* ── DARK THEME ─────────────────────────────────────
   Applied via <html data-theme="dark">. The whole system is
   variable-driven, so overriding the tokens flips the entire
   UI. A few hardcoded black-overlay fills get explicit dark
   variants below so they stay visible on dark surfaces. */
:root[data-theme="dark"] {
  /* Surfaces */
  --bg:    #0e0f12;
  --s1:    #17191d;
  --s2:    #1e2126;
  --s3:    #272b31;
  --s4:    #353a42;

  /* Borders */
  --b1: rgba(255,255,255,0.08);
  --b2: rgba(255,255,255,0.15);
  --b3: rgba(255,255,255,0.24);

  /* Text */
  --t1: #f4f5f7;
  --t2: #9aa3af;
  --t3: #6b7280;
  --t4: #4b5563;

  /* Accent tint (active nav link, etc.) */
  --w-light: rgba(37,99,235,0.18);
}
/* Black-overlay fills → light overlays so they read on dark */
:root[data-theme="dark"] .nav-live      { background: rgba(255,255,255,0.10); }
:root[data-theme="dark"] .nav-count--beta { background: rgba(255,255,255,0.08); }
:root[data-theme="dark"] .btn-d         { background: rgba(255,255,255,0.06); }
:root[data-theme="dark"] .btn-d:hover   { background: rgba(255,255,255,0.12); }
:root[data-theme="dark"] .modal-box,
:root[data-theme="dark"] .login-box     { box-shadow: 0 12px 48px rgba(0,0,0,.55); }
:root[data-theme="dark"] img.logo-mark  { filter: brightness(0) invert(1); }

/* Smooth the flip */
body, .sidebar, .topbar, .card, .stat-card, .btn { transition: background var(--tf), color var(--tf), border-color var(--tf); }

/* ── RESET ─────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; height: 100%; }
body {
  font-family: var(--font);
  background: var(--bg);
  color: var(--t1);
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow: hidden;
  height: 100vh;
}
a { text-decoration: none; color: inherit; cursor: pointer; }
button { cursor: pointer; border: none; background: none; font-family: var(--font); color: inherit; }
input, textarea, select { font-family: var(--font); }
img { display: block; max-width: 100%; }
svg { display: block; }

/* ── APP SHELL ─────────────────────────────────────── */
.app { display: flex; height: 100vh; overflow: hidden; }

/* ── SIDEBAR ───────────────────────────────────────── */
.sidebar {
  width: var(--sw);
  flex-shrink: 0;
  background: var(--s1);
  border-right: 1px solid var(--b1);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  transition: transform var(--ts);
  z-index: 100;
  position: relative;
}

.sidebar-logo {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 20px;
  height: var(--th);
  border-bottom: 1px solid var(--b1);
  flex-shrink: 0;
}
.logo-mark {
  width: auto; height: 32px;
  flex-shrink: 0;
  object-fit: contain;
}
.logo-name { font-size: 14px; font-weight: 700; letter-spacing: -0.3px; color: var(--w); display: block; }
.logo-sub  { font-size: 10px; color: var(--t3); display: block; margin-top: -1px; }

.sidebar-nav {
  flex: 1;
  overflow-y: auto;
  padding: 16px 10px;
  display: flex; flex-direction: column; gap: 24px;
  scrollbar-width: none;
}
.sidebar-nav::-webkit-scrollbar { display: none; }

.nav-group { display: flex; flex-direction: column; gap: 2px; }
.nav-group-label {
  font-size: 10px; font-weight: 600;
  letter-spacing: .08em; text-transform: uppercase;
  color: var(--t4);
  padding: 0 10px;
  margin-bottom: 4px;
}

.nav-link {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px;
  border-radius: var(--r2);
  color: var(--t2);
  font-size: 13px; font-weight: 450;
  transition: background var(--tf), color var(--tf);
  user-select: none;
  cursor: pointer;
}
.nav-link:hover   { background: var(--s2); color: var(--t1); }
.nav-link.active  { background: var(--w-light); color: var(--w); font-weight: 500; }

.nav-icon { width: 15px; height: 15px; flex-shrink: 0; stroke-width: 1.8; }
.nav-link > span:nth-of-type(1) { flex: 1; }

.nav-count {
  font-size: 11px; color: var(--t3);
  font-variant-numeric: tabular-nums;
}
/* TEMPORARY (beta): the Customers count is replaced by a "BETA" pill.
   See App.BETA_HIDE_CUSTOMER_COUNT — remove both when the count comes back. */
.nav-count--beta {
  font-size: 9px; font-weight: 700; letter-spacing: .06em;
  color: var(--t2);
  background: rgba(0,0,0,0.06);
  border: 1px solid var(--b1);
  padding: 1px 6px;
  border-radius: var(--rf);
}
/* Red "new / needs attention" pill — pending submissions, pool candidates, etc. */
.nav-new {
  font-size: 10px; font-weight: 700;
  background: #EF4444; color: #ffffff;
  min-width: 17px; height: 17px; padding: 0 5px;
  border-radius: 9px;
  display: inline-flex; align-items: center; justify-content: center;
  font-variant-numeric: tabular-nums;
  box-shadow: 0 0 0 2px var(--s1);
}
.nav-live {
  font-size: 10px; font-weight: 600;
  background: rgba(0,0,0,0.08);
  color: var(--w);
  padding: 2px 7px;
  border-radius: var(--rf);
  letter-spacing: .04em;
  animation: livePulse 3s ease infinite;
}
@keyframes livePulse { 0%,100%{opacity:1} 50%{opacity:.5} }

.sidebar-profile {
  display: flex; align-items: center; gap: 10px;
  padding: 14px 16px;
  border-top: 1px solid var(--b1);
  flex-shrink: 0;
}
.profile-avatar {
  width: 30px; height: 30px;
  background: var(--s3); border: 1px solid var(--b2);
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 12px; font-weight: 600; flex-shrink: 0;
}
.profile-info { flex: 1; min-width: 0; }
.profile-name  { font-size: 12px; font-weight: 500; display: block; }
.profile-email { font-size: 11px; color: var(--t3); display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.profile-logout {
  width: 28px; height: 28px; border-radius: var(--r1);
  display: flex; align-items: center; justify-content: center;
  color: var(--t3); transition: background var(--tf), color var(--tf);
}
.profile-logout:hover { background: var(--s3); color: var(--t1); }
.profile-logout svg { width: 14px; height: 14px; }

/* ── OVERLAY ────────────────────────────────────────── */
.overlay {
  display: none; position: fixed; inset: 0;
  background: rgba(0,0,0,.55); z-index: 90;
}
.overlay.open { display: block; }

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

/* ── TOPBAR ─────────────────────────────────────────── */
.topbar {
  height: var(--th); flex-shrink: 0;
  border-bottom: 1px solid var(--b1);
  display: flex; align-items: center; justify-content: space-between;
  padding: 0 24px; gap: 16px;
  background: var(--bg);
}
.topbar-left { display: flex; align-items: center; gap: 16px; }
.topbar-right { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }

.topbar-menu {
  width: 34px; height: 34px; border-radius: var(--r1);
  display: none; align-items: center; justify-content: center;
  color: var(--t2); transition: background var(--tf);
}
.topbar-menu:hover { background: var(--s2); color: var(--t1); }
.topbar-menu svg { width: 18px; height: 18px; }

.page-title-text { font-size: 15px; font-weight: 600; letter-spacing: -.3px; }

.topbar-search {
  display: flex; align-items: center; gap: 8px;
  background: var(--s1); border: 1px solid var(--b1);
  border-radius: var(--r2); padding: 0 12px;
  height: 36px; width: 300px; transition: border-color var(--tf);
}
.topbar-search:focus-within { border-color: var(--b2); }
.topbar-search svg { width: 14px; height: 14px; color: var(--t3); flex-shrink: 0; }
.topbar-search input {
  flex: 1; background: none; border: none; outline: none;
  color: var(--t1); font-size: 13px;
}
.topbar-search input::placeholder { color: var(--t3); }

.topbar-btn {
  width: 34px; height: 34px; border-radius: var(--r1);
  display: flex; align-items: center; justify-content: center;
  color: var(--t1); transition: background var(--tf), color var(--tf);
  position: relative;
}
.topbar-btn:hover { background: var(--s2); color: var(--w); }
.topbar-btn svg { width: 16px; height: 16px; }
.pos-rel { position: relative; }

.notif-badge {
  position: absolute; top: 1px; right: 1px;
  width: 13px; height: 13px;
  background: #EF4444; color: #ffffff;
  border-radius: 50%; font-size: 8px; font-weight: 700;
  display: flex; align-items: center; justify-content: center;
  border: 1.5px solid var(--s1);
}

.topbar-avatar {
  width: 30px; height: 30px;
  background: var(--s3); border: 1px solid var(--b2);
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 12px; font-weight: 600; cursor: pointer; margin-left: 2px;
}

/* ── CONTENT AREA ───────────────────────────────────── */
.content {
  flex: 1; overflow-y: auto; padding: 24px;
  scrollbar-width: thin; scrollbar-color: var(--b1) transparent;
}
.content::-webkit-scrollbar { width: 4px; }
.content::-webkit-scrollbar-thumb { background: var(--b1); border-radius: 2px; }

/* ── PAGE HEADER ────────────────────────────────────── */
.ph {
  display: flex; align-items: flex-start;
  justify-content: space-between; gap: 16px;
  margin-bottom: 24px; flex-wrap: wrap;
}
.ph-left {}
.ph-title { font-size: 20px; font-weight: 700; letter-spacing: -.5px; line-height: 1.2; }
.ph-sub   { font-size: 12px; color: var(--t2); margin-top: 4px; }
.ph-right { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }

/* ── STAT CARDS ─────────────────────────────────────── */
.stats-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 14px; margin-bottom: 20px;
}
.stat-card {
  background: var(--s1); border: 1px solid var(--b1); border-radius: var(--r3);
  padding: 18px 20px; transition: border-color var(--tf);
}
.stat-card:hover { border-color: var(--b2); }
.stat-top { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.stat-label { font-size: 11px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase; color: var(--t2); }
.stat-ico {
  width: 30px; height: 30px;
  background: var(--s2); border: 1px solid var(--b1);
  border-radius: var(--r1);
  display: flex; align-items: center; justify-content: center;
}
.stat-ico svg { width: 14px; height: 14px; color: var(--t2); }
.stat-val { font-size: 26px; font-weight: 700; letter-spacing: -1px; line-height: 1; font-variant-numeric: tabular-nums; }
.stat-change {
  font-size: 11px; color: var(--t2);
  margin-top: 6px; display: flex; align-items: center; gap: 4px;
}
.stat-change.up   { color: var(--t1); }
.stat-change.live { color: var(--w); }

/* ── GRIDS ─────────────────────────────────────────── */
.g2   { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.g3   { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 14px; }
.g21  { display: grid; grid-template-columns: 2fr 1fr; gap: 14px; }
.g31  { display: grid; grid-template-columns: 3fr 1fr; gap: 14px; }
.g-col { display: flex; flex-direction: column; gap: 14px; }
.mb14 { margin-bottom: 14px; }
.mb20 { margin-bottom: 20px; }

/* ── CARD ───────────────────────────────────────────── */
.card { background: var(--s1); border: 1px solid var(--b1); border-radius: var(--r3); overflow: hidden; }
.card-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 16px 20px 14px; border-bottom: 1px solid var(--b1);
}
.card-title { font-size: 13px; font-weight: 600; }
.card-sub   { font-size: 11px; color: var(--t2); margin-top: 2px; }
.card-acts  { display: flex; gap: 6px; align-items: center; }
.card-body  { padding: 20px; }
.chart-wrap { padding: 4px 16px 16px; }
.ch200 { height: 200px; }
.ch240 { height: 240px; }
.ch280 { height: 280px; }
.ch320 { height: 320px; }

/* ── TABLE ─────────────────────────────────────────── */
.table-wrap { overflow-x: auto; scrollbar-width: thin; scrollbar-color: var(--b1) transparent; }
/* Grab-and-drag panning (DragScroll) — the grabbing cursor and the selection lock
   only apply once a drag is actually under way, so a plain click still behaves. */
.table-wrap.dragging { cursor: grabbing; user-select: none; }
.table-wrap.dragging a { pointer-events: none; }

/* ═══════════════════════════════════════════════════════
   CHARGER CONTROL CENTRE — the Chargers page "Map" mode
   Ops strip on top, Google map + viewport/detail rail below.
   Everything is token-driven, so it follows the portal's theme;
   the map itself uses Google's own `colorScheme` (set in JS).
═══════════════════════════════════════════════════════ */
.cc { display: flex; flex-direction: column; }

/* ── Ops strip: one chip per operational state, each a filter ── */
.cc-strip {
  display: flex; flex-wrap: wrap; gap: 8px;
  padding: 12px 16px; border-bottom: 1px solid var(--b1);
}
.cc-chip {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 7px 12px; border-radius: var(--rf);
  background: var(--s2); border: 1px solid transparent;
  color: var(--t1); font: inherit; font-size: 12px; cursor: pointer;
  transition: background var(--tf), border-color var(--tf), transform var(--tf);
}
.cc-chip:hover { background: var(--s3); }
.cc-chip.is-on { border-color: var(--b3); background: var(--s3); }
.cc-chip--all { font-weight: 600; }
.cc-chip i { width: 10px; height: 10px; border-radius: 50%; flex: none; }
.cc-chip--warn i { width: 14px; height: 14px; border-radius: 0; color: var(--t3); background: none; }
.cc-chip-v { font-weight: 700; font-variant-numeric: tabular-nums; }
.cc-chip-l { color: var(--t2); white-space: nowrap; }
.cc-chip.is-on .cc-chip-l { color: var(--t1); }

/* ── Body: map + rail ── */
.cc-body { display: flex; height: 74vh; min-height: 480px; }
/* .cc-map is the positioning context; #chgMap (.cc-map-canvas) is handed to the
   SDK, which clears it — so the HUD panels sit alongside it, not inside. */
.cc-map { position: relative; flex: 1; min-width: 0; background: var(--s2); }
.cc-map-canvas { position: absolute; inset: 0; }
.cc-rail {
  width: 340px; flex: none; overflow-y: auto; overflow-x: hidden;
  border-left: 1px solid var(--b1); background: var(--s1);
  scrollbar-width: thin; scrollbar-color: var(--b1) transparent;
}

/* Google's own UI inherits page fonts badly — pin it back to the design system. */
.cc-map .gm-style, .cc-map .gm-style * { font-family: var(--font); }

/* Boot / failure states painted into the map slot before the SDK is up. */
.cc-boot {
  position: absolute; inset: 0; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 10px;
  color: var(--t2); font-size: 13px; text-align: center; padding: 24px;
}
.cc-boot svg { width: 30px; height: 30px; color: var(--t3); }
.cc-boot--err { color: var(--t1); }
.cc-boot-hint { color: var(--t3); font-size: 12px; max-width: 420px; line-height: 1.6; }
.cc-boot code {
  font-family: 'SF Mono', 'Fira Code', monospace; font-size: 11px;
  background: var(--s2); border-radius: var(--r1); padding: 1px 5px;
}

/* ── Floating HUD panels over the map ── */
.cc-hud {
  position: absolute; z-index: 2;
  background: var(--s1); border: 1px solid var(--b1); border-radius: var(--r2);
  box-shadow: 0 4px 18px rgba(0, 0, 0, .14);
}
:root[data-theme="dark"] .cc-hud { box-shadow: 0 4px 18px rgba(0, 0, 0, .5); }
.cc-hud:empty { display: none; }        /* no bare white pill before first paint */
.cc-hud--tl { top: 12px; left: 12px; display: flex; align-items: center; gap: 7px; padding: 8px 13px; }
.cc-hud--tr { top: 12px; right: 12px; display: flex; padding: 4px; gap: 2px; }
.cc-hud--bl { bottom: 12px; left: 12px; max-width: min(58%, 460px); padding: 9px 13px;
              display: flex; flex-wrap: wrap; align-items: center; gap: 6px 13px; }

.cc-vs-n   { font-size: 14px; font-weight: 700; color: var(--t1); font-variant-numeric: tabular-nums; }
.cc-vs-l   { font-size: 11px; color: var(--t2); }
.cc-vs-sep { width: 1px; height: 14px; background: var(--b2); margin: 0 3px; }

.cc-tool {
  display: flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; border: 0; border-radius: var(--r1);
  background: transparent; color: var(--t2); cursor: pointer;
  transition: background var(--tf), color var(--tf);
}
.cc-tool:hover  { background: var(--s2); color: var(--t1); }
.cc-tool.is-on  { background: var(--s3); color: var(--t1); }
.cc-tool svg    { width: 15px; height: 15px; }

/* Legend — the swatch mirrors the pin: white disc, coloured ring. The colour is
   set inline per state, so paint it on the border and keep the fill white. */
.cc-hud--bl .cc-lg-t {
  font-size: 10px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
  color: var(--t3); width: 100%;
}
.cc-hud--bl .ml-item { display: inline-flex; align-items: center; gap: 6px; font-size: 11px; color: var(--t2); }
.cc-hud--bl .ml-item i {
  width: 11px; height: 11px; border-radius: 50%; display: inline-block;
  border: 3px solid; background: #fff !important; box-sizing: border-box;
}
/* Legend key for the pulse itself — colourless, since any state can pulse. */
.cc-hud--bl .ml-item--live i { border-color: var(--t2); animation: chgBolt 1.6s ease-in-out infinite; }

/* ── Rail: viewport list ── */
.cc-rail-head {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 14px 16px; border-bottom: 1px solid var(--b1);
  position: sticky; top: 0; background: var(--s1); z-index: 1;
}
.cc-rail-title { font-size: 13px; font-weight: 600; color: var(--t1); }
.cc-rail-sub   { font-size: 11px; color: var(--t3); margin-top: 2px; }
.cc-rail-list  { padding: 6px; }
.cc-rail-more  { padding: 10px 12px; font-size: 11px; color: var(--t3); text-align: center; }
.cc-rail-empty {
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  padding: 48px 24px; color: var(--t3); font-size: 12px; text-align: center;
}
.cc-rail-empty svg { width: 24px; height: 24px; }

.cc-row {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 9px 10px; border: 0; border-radius: var(--r1);
  background: transparent; text-align: left; font: inherit; cursor: pointer;
  transition: background var(--tf);
}
.cc-row:hover { background: var(--s2); }
.cc-row-dot {
  width: 11px; height: 11px; flex: none; border-radius: 50%;
  border: 3px solid; background: #fff; box-sizing: border-box;
}
.cc-row-body { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: 2px; }
.cc-row-name {
  font-size: 12.5px; color: var(--t1); font-weight: 500;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cc-row-meta {
  font-size: 11px; color: var(--t3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cc-row-flag { width: 14px; height: 14px; flex: none; color: var(--t3); }

/* ── Rail: station detail ── */
.cc-d-head { padding: 16px; border-bottom: 1px solid var(--b1); position: relative; }
/* Accent bar in the station's own pin colour, so the rail and the map agree. */
.cc-d-head::before {
  content: ''; position: absolute; left: 0; top: 0; bottom: 0;
  width: 3px; background: var(--cc-accent, var(--t3));
}
.cc-d-back {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; margin-bottom: 8px;
  border: 1px solid var(--b1); border-radius: var(--r1);
  background: var(--s1); color: var(--t2); cursor: pointer; transition: background var(--tf);
}
.cc-d-back:hover { background: var(--s2); color: var(--t1); }
.cc-d-back svg { width: 14px; height: 14px; }
.cc-d-title  { font-size: 15px; font-weight: 650; color: var(--t1); line-height: 1.35; }
.cc-d-badges { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 8px; }
.cc-d-addr   { font-size: 11.5px; color: var(--t3); margin-top: 8px; line-height: 1.55; }

.cc-d-tiles { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px; background: var(--b1); }
.cc-d-tile  { background: var(--s1); padding: 12px 10px; text-align: center; }
.cc-d-tile-l {
  display: block; font-size: 9.5px; font-weight: 600; letter-spacing: .07em;
  text-transform: uppercase; color: var(--t3);
}
.cc-d-tile-v { display: block; font-size: 18px; font-weight: 700; color: var(--t1); margin-top: 4px;
               font-variant-numeric: tabular-nums; }
.cc-d-tile-v i { font-style: normal; font-size: 11px; font-weight: 500; color: var(--t3); margin-left: 2px; }

/* Driver-reported condition — distinct from the admin `status` field. */
.cc-d-live { margin: 14px 16px 0; padding: 11px 13px; border-radius: var(--r2);
             background: var(--s2); border: 1px solid var(--b1); }
.cc-d-live.is-cold { opacity: .62; }
.cc-d-live-top {
  display: flex; align-items: center; gap: 6px;
  font-size: 10px; font-weight: 600; letter-spacing: .06em;
  text-transform: uppercase; color: var(--t3);
}
.cc-d-live-top svg { width: 12px; height: 12px; }
.cc-d-live-top .badge { margin-left: auto; }
.cc-d-live-body { display: flex; align-items: center; gap: 8px; margin-top: 8px; }
.cc-d-live-when { font-size: 11px; color: var(--t3); }

.cc-d-sec   { padding: 14px 16px; border-top: 1px solid var(--b1); }
.cc-d-sec:first-of-type { border-top: 0; }
.cc-d-sec-t {
  font-size: 10px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
  color: var(--t3); margin-bottom: 9px;
}
.cc-d-row { display: flex; align-items: baseline; gap: 12px; padding: 4px 0; font-size: 12px; }
.cc-d-k   { color: var(--t3); width: 96px; flex: none; }
.cc-d-v   { color: var(--t1); min-width: 0; word-break: break-word; }
.cc-d-notes { font-size: 12px; color: var(--t1); line-height: 1.65; white-space: pre-wrap; }
.cc-d-notes.is-empty { color: var(--t3); font-style: italic; }

.cc-d-acts { display: flex; flex-wrap: wrap; gap: 6px; padding: 14px 16px; border-top: 1px solid var(--b1); }
.cc-d-warn {
  display: flex; gap: 8px; margin: 0 16px 16px; padding: 10px 12px;
  border-radius: var(--r2); background: var(--s2); border: 1px solid var(--b1);
  font-size: 11px; color: var(--t2); line-height: 1.6;
}
.cc-d-warn svg  { width: 14px; height: 14px; flex: none; margin-top: 1px; }
.cc-d-warn span { min-width: 0; }       /* let the message wrap instead of widening the rail */
.cc-d-warn code {
  font-family: 'SF Mono', 'Fira Code', monospace; font-size: 10.5px;
  overflow-wrap: anywhere;
}

/* Narrow viewports: the rail can't sit beside the map, so stack it under. */
@media (max-width: 1100px) {
  .cc-body { flex-direction: column; height: auto; }
  .cc-map  { height: 56vh; min-height: 360px; }
  .cc-rail { width: auto; max-height: 460px; border-left: 0; border-top: 1px solid var(--b1); }
  .cc-hud--bl { display: none; }        /* the legend would cover half the map */
}

/* ── Map pin — white disc, coloured ring, coloured bolt ── */
/* Advanced markers anchor their content's bottom-centre on the coordinate; this
   pin is a disc, so push it back down by half its height to sit centred. */
.chg-pin-wrap { transform: translateY(50%); }
.chg-pin {
  position: relative;
  width: 26px; height: 26px; border-radius: 50%;
  background: #fff; border: 3px solid currentColor;
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 2px 6px rgba(0, 0, 0, .35);
  transition: transform var(--tf, .15s);
}
.chg-pin:hover { transform: scale(1.18); }
.chg-pin svg { display: block; }
/* Hovered from the rail list, and picked — the second is the louder of the two
   because it survives the pointer leaving the map entirely. */
.chg-pin-wrap.is-hot .chg-pin { transform: scale(1.3); }
.chg-pin-wrap.is-sel .chg-pin {
  transform: scale(1.45);
  box-shadow: 0 0 0 4px rgba(255, 255, 255, .9), 0 4px 14px rgba(0, 0, 0, .45);
}
:root[data-theme="dark"] .chg-pin-wrap.is-sel .chg-pin {
  box-shadow: 0 0 0 4px rgba(23, 25, 29, .95), 0 4px 14px rgba(0, 0, 0, .7);
}

/* A live station breathes: the bolt pulses and a halo rings out in the pin's own
   colour. Only stations the app would actually route you to get this — offline,
   maintenance, coming-soon and disabled pins stay dead still. */
.chg-pin--live svg { animation: chgBolt 1.6s ease-in-out infinite; transform-origin: center; }
.chg-pin--live::after {
  content: ''; position: absolute; inset: -3px;
  border-radius: 50%; border: 2px solid currentColor;
  animation: chgHalo 1.6s ease-out infinite;
  pointer-events: none;
}
@keyframes chgBolt {
  0%, 100% { transform: scale(1);    opacity: 1;  }
  50%      { transform: scale(1.22); opacity: .55; }
}
@keyframes chgHalo {
  0%   { transform: scale(1);   opacity: .55; }
  70%  { transform: scale(1.9); opacity: 0;   }
  100% { transform: scale(1.9); opacity: 0;   }
}
@media (prefers-reduced-motion: reduce) {
  .chg-pin--live svg,
  .chg-pin--live::after { animation: none; }
  .chg-pin--live::after { opacity: 0; }
}
table { width: 100%; border-collapse: collapse; font-size: 13px; }
thead th {
  text-align: left; padding: 10px 16px;
  font-size: 10px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
  color: var(--t3); border-bottom: 1px solid var(--b1); white-space: nowrap;
}
tbody tr { border-bottom: 1px solid var(--b1); transition: background var(--tf); cursor: default; }
tbody tr:last-child { border-bottom: none; }
tbody tr:hover { background: var(--s2); }
td { padding: 11px 16px; color: var(--t1); white-space: nowrap; }
.td-dim  { color: var(--t2); }
.td-mono { font-variant-numeric: tabular-nums; font-size: 12px; font-family: 'SF Mono','Fira Code',monospace; }

/* Truncate long cell text with an ellipsis instead of overflowing the next column */
.cell-trunc { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ── PAGINATION ─────────────────────────────────────── */
.pager {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; padding: 12px 20px; border-top: 1px solid var(--b1); flex-wrap: wrap;
}
.pager-info { font-size: 12px; color: var(--t2); }
.pager-btns { display: flex; align-items: center; gap: 10px; }
.pager-page { font-size: 12px; color: var(--t2); font-variant-numeric: tabular-nums; }
.btn[disabled] { opacity: .4; pointer-events: none; }

/* ── TOOLBAR ────────────────────────────────────────── */
.toolbar {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 20px; border-bottom: 1px solid var(--b1); flex-wrap: wrap;
}
.toolbar-spacer { flex: 1; }
/* Search on a row of its own (Chargers / Pool). Sharing a row with five filter
   selects squeezed the box down to its 200px minimum; alone it gets the full
   card width. Sits flush on top of the filter toolbar — no divider between. */
.toolbar-srch { padding-bottom: 0; border-bottom: none; }
.toolbar-srch .srch { max-width: none; height: 38px; }

.srch {
  display: flex; align-items: center; gap: 8px;
  background: var(--s2); border: 1px solid var(--b1);
  border-radius: var(--r2); padding: 0 12px; height: 34px;
  min-width: 200px; flex: 1; max-width: 320px;
  transition: border-color var(--tf);
}
.srch:focus-within { border-color: var(--b2); }
.srch svg { width: 13px; height: 13px; color: var(--t3); flex-shrink: 0; }
.srch input {
  flex: 1; background: none; border: none; outline: none;
  color: var(--t1); font-size: 13px;
}
.srch input::placeholder { color: var(--t3); }
/* Clear (×) button — appears only while the box has text (pure CSS via the
   input's :placeholder-shown state, so no JS is needed to toggle it). */
.srch-clear {
  flex-shrink: 0; display: none; background: none; border: none;
  cursor: pointer; color: var(--t3); font-size: 17px; line-height: 1;
  padding: 0; width: 16px; height: 16px;
}
.srch-clear:hover { color: var(--t1); }
.srch input:not(:placeholder-shown) ~ .srch-clear { display: block; }

/* Add-Station duplicate suggestions (live, client-side against the loaded
   catalog) — warns staff before they re-add an existing site under a slightly
   different name. */
.dup-suggest {
  margin: -2px 0 8px; border: 1px solid var(--b1);
  border-radius: var(--r2); background: var(--s2);
  max-height: 190px; overflow-y: auto;
}
.dup-suggest-hdr {
  padding: 6px 10px; font-size: 11px; color: #e0a800;
  background: rgba(224,168,0,.08); border-bottom: 1px solid var(--b1);
}
.dup-suggest-item { padding: 7px 10px; border-bottom: 1px solid var(--b1); }
.dup-suggest-item:last-child { border-bottom: none; }
.dsi-name { color: var(--t1); font-weight: 500; font-size: 12px; }
.dsi-addr { color: var(--t3); font-size: 11px; margin-top: 2px; }

.fsel {
  height: 34px; padding: 0 10px;
  background: var(--s2); border: 1px solid var(--b1);
  border-radius: var(--r2); color: var(--t1); font-size: 12px;
  font-family: var(--font); outline: none; cursor: pointer;
  transition: border-color var(--tf);
}
.fsel:focus { border-color: var(--b2); }
.fsel option { background: var(--s2); }

/* ── PAGINATION ─────────────────────────────────────── */
.pager {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 20px; border-top: 1px solid var(--b1);
  font-size: 12px; color: var(--t2);
}
.pager-btns { display: flex; gap: 4px; }
.pager-btn {
  width: 30px; height: 30px; border-radius: var(--r1);
  display: flex; align-items: center; justify-content: center;
  background: var(--s2); border: 1px solid var(--b1);
  color: var(--t2); font-size: 12px; transition: var(--tf);
}
.pager-btn:hover  { border-color: var(--b2); color: var(--t1); }
.pager-btn.active { background: var(--w); color: #ffffff; border-color: var(--w); }
.pager-btn svg    { width: 13px; height: 13px; }

/* ── BADGES ─────────────────────────────────────────── */
.badge {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 8px; border-radius: var(--rf);
  font-size: 11px; font-weight: 500; border: 1px solid transparent;
}
.b-premium  { background: #EEF2FF; color: #4F46E5; border-color: #C7D2FE; }
.b-free     { background: transparent; color: var(--t2); border-color: var(--b1); }
.b-active   { background: #DCFCE7; color: #16A34A; border-color: #BBF7D0; }
.b-inactive { background: transparent; color: var(--t3); border-color: var(--b1); }
.b-online   { background: #DCFCE7; color: #16A34A; border-color: #BBF7D0; }
.b-offline  { background: #F3F4F6; color: var(--t3); border-color: var(--b1); }
.b-inuse    { background: #FEF3C7; color: #D97706; border-color: #FDE68A; }
.b-warn     { background: #FEF9C3; color: #CA8A04; border-color: #FEF08A; }
.b-info     { background: #DBEAFE; color: #2563EB; border-color: #BFDBFE; }
.b-error    { background: #FEE2E2; color: #DC2626; border-color: #FECACA; }
.b-cancel   { background: transparent; color: var(--t3); border-color: var(--b1); }
.b-dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex-shrink: 0; }

/* ── BUTTONS ─────────────────────────────────────────── */
.btn {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 8px 16px; border-radius: var(--r2);
  font-size: 13px; font-weight: 500;
  transition: background var(--tf), opacity var(--tf), border-color var(--tf);
  cursor: pointer; border: 1px solid transparent; white-space: nowrap;
}
.btn-p { background: var(--w); color: #ffffff; }
.btn-p:hover { background: var(--w-hover); }
.btn-s { background: var(--s2); color: var(--t1); border-color: var(--b1); }
.btn-s:hover { background: var(--s3); border-color: var(--b2); }
.btn-g { background: transparent; color: var(--t2); }
.btn-g:hover { background: var(--s2); color: var(--t1); }
.btn-d { background: rgba(0,0,0,.04); color: var(--t2); border-color: var(--b1); }
.btn-d:hover { background: rgba(0,0,0,.09); color: var(--w); }
.btn svg { width: 14px; height: 14px; }
.btn-sm { padding: 5px 11px; font-size: 12px; }
.btn-sm svg { width: 12px; height: 12px; }
.btn-ico {
  width: 30px; height: 30px; padding: 0;
  border-radius: var(--r1); justify-content: center;
}
.btn-ico svg { width: 13px; height: 13px; }

/* ── AVATAR ─────────────────────────────────────────── */
.av {
  width: 30px; height: 30px; border-radius: 50%;
  background: var(--s3); border: 1px solid var(--b1);
  display: flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 600; flex-shrink: 0;
}
.av-lg { width: 38px; height: 38px; font-size: 14px; }

.uc { display: flex; align-items: center; gap: 10px; }
.uc-name  { font-size: 13px; font-weight: 500; }
.uc-email { font-size: 11px; color: var(--t2); }

/* ── ACTIVITY FEED ───────────────────────────────────── */
.feed-item {
  display: flex; gap: 10px;
  padding: 10px 0; border-bottom: 1px solid var(--b1);
}
.feed-item:last-child { border-bottom: none; padding-bottom: 0; }
.feed-ico {
  width: 30px; height: 30px; border-radius: var(--r1);
  background: var(--s2); border: 1px solid var(--b1);
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
}
.feed-ico svg { width: 13px; height: 13px; color: var(--t2); }
.feed-body { flex: 1; min-width: 0; }
.feed-text { font-size: 12.5px; line-height: 1.4; }
.feed-text strong { font-weight: 500; }
.feed-time { font-size: 11px; color: var(--t3); margin-top: 2px; }

/* ── FORMS ─────────────────────────────────────────── */
.fg { margin-bottom: 16px; }
.flabel {
  display: block; font-size: 11px; font-weight: 600;
  letter-spacing: .05em; text-transform: uppercase;
  color: var(--t2); margin-bottom: 6px;
}
.finput {
  width: 100%; height: 40px; padding: 0 12px;
  background: var(--s2); border: 1px solid var(--b1);
  border-radius: var(--r2); color: var(--t1); font-size: 13px;
  font-family: var(--font); outline: none; transition: border-color var(--tf);
}
.finput:focus { border-color: var(--b2); }
/* Gated by the connector ticks (charger form): current not offered here */
.finput:disabled { opacity: 0.45; cursor: not-allowed; border-style: dashed; }
.ftarea {
  width: 100%; padding: 10px 12px; min-height: 90px;
  background: var(--s2); border: 1px solid var(--b1);
  border-radius: var(--r2); color: var(--t1); font-size: 13px;
  font-family: var(--font); outline: none; resize: vertical;
  transition: border-color var(--tf);
}
.ftarea:focus { border-color: var(--b2); }
.fsel2 {
  width: 100%; height: 40px; padding: 0 12px;
  background: var(--s2); border: 1px solid var(--b1);
  border-radius: var(--r2); color: var(--t1); font-size: 13px;
  font-family: var(--font); outline: none; cursor: pointer;
}
.fsel2 option { background: var(--s2); }
.fhint { font-size: 11px; color: var(--t3); margin-top: 5px; line-height: 1.45; }
.frow { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.frow-3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 14px; }

/* ── STATION FORM SECTIONS ─────────────────────────────
   The station form is long enough that a flat stack of inputs gives an
   operator no landmarks. Each section is a full-bleed row: a fixed left
   column naming it and saying in one line what it's for, the fields on the
   right. Every explanation lives in that rail instead of between the boxes,
   so the fields themselves stay a clean column to run down. */
.sform-sec {
  display: grid; grid-template-columns: 190px minmax(0, 1fr);
  gap: 0 40px; padding: 26px;
}
.sform-sec + .sform-sec { border-top: 1px solid var(--b1); }
.sform-lead-t { font-size: 13px; font-weight: 600; line-height: 1.3; }
.sform-lead-d { font-size: 11.5px; color: var(--t3); line-height: 1.55; margin-top: 6px; }
/* The last field in a section already has the section's padding under it. */
.sform-fields > *:last-child,
.sform-fields > *:last-child .fg { margin-bottom: 0; }

/* Full-bleed: the dividers should run the whole width of the modal, not stop
   at the body's padding. Only when the form IS the body — the Pool's candidate
   review wraps it in a warning and a source block, and there it stays inset. */
.modal-box--wide .modal-body { padding: 22px 26px; }
.sform { margin-left: -26px; margin-right: -26px; }
.sform:first-child { margin-top: -22px; }
.sform:last-child  { margin-bottom: -22px; }

/* Too narrow for a lead rail — the brief becomes a heading above its fields. */
@media (max-width: 900px) {
  .sform-sec { grid-template-columns: 1fr; gap: 16px; padding: 22px; }
}

/* Unit parked inside the field (DC power → "kW") rather than in the label. */
.funit-wrap { position: relative; }
.funit-wrap .finput { padding-right: 38px; }
.funit {
  position: absolute; right: 12px; top: 50%; transform: translateY(-50%);
  font-size: 11.5px; color: var(--t3); pointer-events: none;
}
.funit-wrap:has(input:disabled) .funit { opacity: .45; }

/* Connector plugs as tick-chips instead of a bare checkbox row. */
.fchips { display: flex; flex-wrap: wrap; gap: 8px; }
.fchip {
  display: flex; align-items: center; gap: 8px; cursor: pointer;
  font-size: 12.5px; padding: 9px 14px; border-radius: var(--r2);
  background: var(--s1); border: 1px solid var(--b1);
  transition: border-color var(--tf), color var(--tf);
}
.fchip:hover { border-color: var(--b2); }
.fchip:has(input:checked) { border-color: var(--b3); font-weight: 600; }

/* Full-row checkbox (lock coords, open 24h, disable) — the whole strip is the
   label, so the tick target isn't a 13px square. */
.fcheck {
  display: flex; align-items: center; gap: 10px; cursor: pointer;
  font-size: 13px; line-height: 1.4; padding: 9px 13px; min-height: 40px;
  background: var(--s1); border: 1px solid var(--b1);
  border-radius: var(--r2); transition: border-color var(--tf);
}
.fcheck:hover { border-color: var(--b2); }
.fcheck:has(input:checked) { border-color: var(--b3); }
.fcheck input { flex-shrink: 0; }

/* ── TOGGLE ─────────────────────────────────────────── */
.trow {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 0; border-bottom: 1px solid var(--b1);
}
.trow:last-child { border-bottom: none; }
.trow-left {}
.trow-label { font-size: 13px; font-weight: 500; }
.trow-desc  { font-size: 11px; color: var(--t2); margin-top: 2px; }
.tog {
  width: 38px; height: 21px; border-radius: var(--rf);
  background: var(--s3); border: 1px solid var(--b1);
  position: relative; cursor: pointer; transition: background var(--tm), border-color var(--tm);
  flex-shrink: 0;
}
.tog.on { background: var(--w); border-color: var(--w); }
.tog::after {
  content: ''; position: absolute;
  top: 2px; left: 2px; width: 15px; height: 15px;
  border-radius: 50%; background: var(--t3);
  transition: left var(--tm), background var(--tm);
}
.tog.on::after { left: 19px; background: #ffffff; }

/* ── LIVE DOT ────────────────────────────────────────── */
.live-dot {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12px; color: var(--t2);
}
.live-dot::before {
  content: ''; width: 7px; height: 7px; border-radius: 50%;
  background: var(--w); animation: lp 2s ease infinite;
}
@keyframes lp { 0%,100%{opacity:1} 50%{opacity:.25} }

/* ── PROGRESS ────────────────────────────────────────── */
.prog { height: 4px; background: var(--s3); border-radius: var(--rf); overflow: hidden; }
.prog-fill { height: 100%; background: var(--w); border-radius: var(--rf); transition: width .6s ease; }
.prog-fill.dim { background: rgba(255,255,255,.3); }

/* ── TABS ─────────────────────────────────────────────── */
.tabs { display: flex; border-bottom: 1px solid var(--b1); padding: 0 20px; }
.tab {
  padding: 12px 16px; font-size: 13px; font-weight: 500;
  color: var(--t2); border-bottom: 2px solid transparent;
  margin-bottom: -1px; cursor: pointer; transition: color var(--tf);
}
.tab:hover { color: var(--t1); }
.tab.active { color: var(--w); border-bottom-color: var(--w); }

/* ── MODAL ─────────────────────────────────────────────── */
.modal-overlay {
  position: fixed; inset: 0;
  background: rgba(0,0,0,.7); backdrop-filter: blur(6px);
  display: none; align-items: center; justify-content: center;
  z-index: 1000; padding: 24px;
}
.modal-overlay.open { display: flex; }
.modal-box {
  background: var(--s1); border: 1px solid var(--b2);
  border-radius: var(--r4);
  width: 100%; max-width: 540px; max-height: 90vh;
  display: flex; flex-direction: column;
  box-shadow: 0 8px 40px rgba(0,0,0,.10);
  animation: min .2s ease;
}
@keyframes min { from{opacity:0;transform:scale(.97) translateY(10px)} to{opacity:1;transform:none} }
.modal-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 18px 22px; border-bottom: 1px solid var(--b1);
}
.modal-title { font-size: 15px; font-weight: 600; }
/* Second line under a modal title — what the form is FOR, so the sections
   below don't have to explain themselves in their first field. */
.modal-sub {
  display: block; margin-top: 4px;
  font-size: 12px; font-weight: 400; color: var(--t2); line-height: 1.4;
}
.modal-close-btn {
  width: 28px; height: 28px; border-radius: var(--r1);
  display: flex; align-items: center; justify-content: center;
  color: var(--t2); transition: background var(--tf);
}
.modal-close-btn:hover { background: var(--s2); color: var(--t1); }
.modal-close-btn svg { width: 15px; height: 15px; }
.modal-body { padding: 22px; overflow-y: auto; flex: 1; }
/* Roomy variant (Modal.open opts.wide) for the long station form — at 540px
   every field was stacked one-per-line and the box read as a wall of inputs.
   (Its .modal-body padding is set with the .sform rules, which bleed past it.) */
.modal-box--wide { max-width: 1120px; max-height: 92vh; }
/* A two-line title makes the head taller than the ✕, which should stay at the top. */
.modal-box--wide .modal-head { align-items: flex-start; padding: 20px 26px; }
.modal-foot {
  display: flex; align-items: center; justify-content: flex-end; gap: 8px;
  padding: 14px 22px; border-top: 1px solid var(--b1);
}
.modal-box--wide .modal-foot { padding: 14px 26px; background: var(--s2); }
/* Status line on the left of the footer (e.g. which connectors are ticked). */
.modal-foot-note { margin-right: auto; font-size: 11.5px; color: var(--t3); }

/* ── TOASTS ─────────────────────────────────────────── */
.toast-stack {
  position: fixed; bottom: 24px; right: 24px;
  display: flex; flex-direction: column; gap: 8px; z-index: 2000;
}
.toast {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 14px;
  background: var(--s2); border: 1px solid var(--b2);
  border-radius: var(--r2); font-size: 13px;
  min-width: 240px; max-width: 360px;
  box-shadow: 0 4px 16px rgba(0,0,0,.08);
  animation: tin .2s ease;
}
@keyframes tin { from{opacity:0;transform:translateX(12px)} to{opacity:1;transform:none} }
.toast svg { width: 15px; height: 15px; flex-shrink: 0; color: var(--t2); }
.toast-msg { flex: 1; }
.toast-x {
  width: 22px; height: 22px; display: flex; align-items: center; justify-content: center;
  border-radius: var(--r1); color: var(--t3); cursor: pointer;
}
.toast-x:hover { color: var(--t1); }
.toast-x svg { width: 12px; height: 12px; }

/* ── LOADING / EMPTY ─────────────────────────────────── */
.loading-state {
  display: flex; flex-direction: column; align-items: center;
  justify-content: center; height: 220px; gap: 12px; color: var(--t2);
}
.spinner {
  width: 22px; height: 22px;
  border: 2px solid var(--b1); border-top-color: var(--t2);
  border-radius: 50%; animation: spin .7s linear infinite;
}
@keyframes spin { to{transform:rotate(360deg)} }
.empty-state {
  display: flex; flex-direction: column; align-items: center;
  justify-content: center; padding: 48px 24px;
  color: var(--t3); gap: 12px; text-align: center;
}
.empty-state svg { width: 36px; height: 36px; opacity: .35; }
.empty-state p { font-size: 13px; }

/* ── STATUS BANNER ───────────────────────────────────── */
.status-banner {
  background: var(--s1); border: 1px solid var(--b1); border-radius: var(--r3);
  padding: 14px 20px; display: flex; align-items: center; gap: 24px;
  margin-bottom: 20px; flex-wrap: wrap;
}
.sbi { display: flex; align-items: center; gap: 8px; font-size: 13px; }
.sbi strong { font-variant-numeric: tabular-nums; }
.sbi-div { width: 1px; height: 16px; background: var(--b1); }

/* ── CODE ─────────────────────────────────────────────── */
.code {
  font-family: 'SF Mono','Fira Code','Consolas',monospace; font-size: 11.5px;
  background: var(--s3); border: 1px solid var(--b1); border-radius: var(--r1);
  padding: 2px 6px;
}

/* ── DIVIDER ─────────────────────────────────────────── */
.div { height: 1px; background: var(--b1); margin: 16px 0; }

/* ── SECTION TITLE ───────────────────────────────────── */
.sec-title { font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--t3); margin-bottom: 12px; }

/* ── MAP PLACEHOLDER ─────────────────────────────────── */
.map-ph {
  background: var(--s2); border-radius: var(--r2);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 12px; color: var(--t3); height: 100%; min-height: 200px;
}
.map-ph svg { width: 32px; height: 32px; opacity: .4; }
.map-ph p { font-size: 12px; }

/* ── SPINNING REFRESH ─────────────────────────────────── */
.spin-anim { animation: spin .7s linear infinite; }

/* ──────────────────────────────────────────────────────
   RESPONSIVE BREAKPOINTS
────────────────────────────────────────────────────── */
@media (max-width: 1100px) {
  .stats-grid { grid-template-columns: 1fr 1fr; }
  .g31 { grid-template-columns: 1fr; }
  .g21 { grid-template-columns: 1fr; }
  .g3  { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 860px) {
  .topbar-search { display: none; }
  .g2 { grid-template-columns: 1fr; }
  .g3 { grid-template-columns: 1fr; }
}

@media (max-width: 640px) {
  .sidebar {
    position: fixed; top: 0; left: 0; bottom: 0;
    transform: translateX(-100%); z-index: 100;
  }
  .sidebar.open { transform: translateX(0); }
  .overlay.open { display: block; }
  .topbar-menu { display: flex; }
  .stats-grid { grid-template-columns: 1fr; }
  .content { padding: 16px; }
  .ph { flex-direction: column; align-items: stretch; }
  .frow, .frow-3 { grid-template-columns: 1fr; }
  .modal-box, .modal-box--wide { max-width: 100%; border-radius: var(--r3); }
  .toast-stack { left: 16px; right: 16px; bottom: 16px; }
  .toast { min-width: auto; }
}

/* ── LOGIN SCREEN ────────────────────────────────────── */
.login-screen {
  position: fixed; inset: 0; z-index: 9999;
  background: var(--bg);
  display: none; align-items: center; justify-content: center;
}
.login-screen.show { display: flex; }
.login-box {
  width: 100%; max-width: 380px;
  background: var(--s1); border: 1px solid var(--b2);
  border-radius: var(--r4); padding: 32px 28px;
  box-shadow: 0 8px 40px rgba(0,0,0,.10);
}
.login-logo {
  display: flex; align-items: center; gap: 14px;
  margin-bottom: 28px;
}
.login-error {
  background: rgba(0,0,0,.03); border: 1px solid var(--b2);
  border-radius: var(--r2); padding: 10px 14px;
  font-size: 12px; color: var(--t2); margin-bottom: 16px;
}
/* ── SCROLLBAR ───────────────────────────────────────── */
::-webkit-scrollbar { width: 4px; height: 4px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--b1); border-radius: 2px; }
::-webkit-scrollbar-thumb:hover { background: var(--b2); }

/* ═══════════════════════════════════════════════════════
   DATA PIPELINE  (js/pipeline.js)
   Nodes are HTML on a grid; the connectors are an SVG layer
   measured from the nodes' real boxes, and the packets ride
   a canvas above them. All three sit in the same stacking
   context so a reflow keeps them aligned.
═══════════════════════════════════════════════════════ */
.mt14 { margin-top: 14px; }

/* "this stream is synthetic" chip — don't let the page pass as prod traffic */
.pl-sim {
  font-size: 10px; font-weight: 600; letter-spacing: .4px; text-transform: uppercase;
  color: var(--t2); background: var(--s2); border: 1px solid var(--b1);
  padding: 3px 8px; border-radius: var(--rf); cursor: help;
}
/* The feed is live by default; this only fires when a poll comes back broken. */
.pl-sim--err { color: #B91C1C; background: #FEE2E2; border-color: #FCA5A5; }
.live-dot--paused::before { animation: none; background: var(--t3); }

/* ── Speed control ─────────────────────────────────── */
.pl-speed { display: flex; gap: 2px; background: var(--s2); border-radius: var(--rf); padding: 3px; }
.pl-speed-btn {
  border: 0; background: transparent; cursor: pointer;
  font: inherit; font-size: 11px; font-weight: 600; color: var(--t2);
  padding: 4px 10px; border-radius: var(--rf); transition: all var(--tf);
}
.pl-speed-btn:hover { color: var(--t1); }
.pl-speed-btn.on { background: var(--s1); color: var(--t1); box-shadow: 0 1px 3px rgba(0,0,0,.10); }

/* ── Stage ─────────────────────────────────────────── */
.pl-stage {
  position: relative;
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  grid-template-rows: auto auto 116px;   /* row 3 = clearance for the under-row loops */
  gap: 18px 26px;
  padding: 22px 24px 0;
  min-height: 380px;
}
/* Wide layout: one row of five, with the API node floating above `engine`. */
.pl-stage #pl-apis   { grid-column: 3; grid-row: 1; }
.pl-stage #pl-device { grid-column: 1; grid-row: 2; }
.pl-stage #pl-ingest { grid-column: 2; grid-row: 2; }
.pl-stage #pl-engine { grid-column: 3; grid-row: 2; }
.pl-stage #pl-db     { grid-column: 4; grid-row: 2; }
.pl-stage #pl-admin  { grid-column: 5; grid-row: 2; }

.pl-edges, .pl-packets { position: absolute; inset: 0; pointer-events: none; }
.pl-edges { z-index: 0; }
.pl-packets { z-index: 1; }

.pl-edge {
  fill: none;
  stroke: var(--b2);
  stroke-width: 1.5;
  stroke-linecap: round;
}
.pl-edge--dashed {
  stroke-dasharray: 3 7;
  animation: pl-flow 2.4s linear infinite;   /* matched to the packet pacing */
}
@keyframes pl-flow { to { stroke-dashoffset: -10; } }
@media (prefers-reduced-motion: reduce) {
  .pl-edge--dashed { animation: none; }
}

/* ── Node card ─────────────────────────────────────── */
.pl-node {
  position: relative; z-index: 2;
  align-self: center;
  background: var(--s1);
  border: 1px solid var(--b1);
  border-radius: var(--r2);
  padding: 12px 13px 10px;
  box-shadow: 0 1px 3px rgba(0,0,0,.05);
  transition: border-color var(--tm), box-shadow var(--tm), transform var(--tm);
}
.pl-node--hit {
  animation: pl-hit 460ms ease-out;
}
@keyframes pl-hit {
  0%   { border-color: var(--w); box-shadow: 0 0 0 0 rgba(37,99,235,.34); transform: translateY(-1px); }
  100% { border-color: var(--b1); box-shadow: 0 0 0 12px rgba(37,99,235,0); transform: none; }
}
@media (prefers-reduced-motion: reduce) { .pl-node--hit { animation: none; } }

.pl-node-head { display: flex; align-items: center; gap: 9px; }
.pl-node-ico {
  flex: 0 0 auto; width: 30px; height: 30px; border-radius: 8px;
  display: grid; place-items: center;
  background: var(--w-light); color: var(--w);
}
.pl-node-ico svg { width: 15px; height: 15px; }
.pl-node-id { min-width: 0; }
.pl-node-title { font-size: 12.5px; font-weight: 600; letter-spacing: -.2px; }
.pl-node-src {
  font-size: 10px; color: var(--t3); margin-top: 1px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.pl-node-meta {
  font-size: 10.5px; line-height: 1.45; color: var(--t2);
  margin: 9px 0 9px; min-height: 30px;
}
.pl-node-foot {
  display: flex; align-items: baseline; justify-content: space-between;
  padding-top: 8px; border-top: 1px solid var(--b1);
}
.pl-node-eps { font-size: 11px; font-weight: 700; color: var(--w); font-variant-numeric: tabular-nums; }
.pl-node-total { font-size: 10px; color: var(--t3); font-variant-numeric: tabular-nums; }

/* ── Legend ────────────────────────────────────────── */
.pl-legend {
  display: flex; flex-wrap: wrap; gap: 6px 14px;
  padding: 16px 24px 18px; border-top: 1px solid var(--b1); margin-top: 18px;
}
.pl-chip { display: inline-flex; align-items: center; gap: 6px; font-size: 11px; color: var(--t2); }
.pl-chip i { width: 7px; height: 7px; border-radius: 50%; display: inline-block; }

/* ── Upstream health ───────────────────────────────── */
.pl-health { display: flex; flex-direction: column; gap: 14px; }
.pl-svc { display: grid; grid-template-columns: 8px 1fr auto; grid-template-areas: 'dot name ms' '. bar bar'; gap: 4px 9px; align-items: center; }
.pl-svc-dot { grid-area: dot; width: 8px; height: 8px; border-radius: 50%; }
.pl-svc-dot--ok       { background: #10B981; box-shadow: 0 0 0 3px rgba(16,185,129,.14); }
.pl-svc-dot--degraded { background: #F59E0B; box-shadow: 0 0 0 3px rgba(245,158,11,.16); animation: lp 1.2s ease infinite; }
/* No telemetry — the app doesn't report on this service, so we claim nothing. */
.pl-svc-dot--none     { background: var(--s4); box-shadow: 0 0 0 3px rgba(148,163,184,.14); }
.pl-svc-name { grid-area: name; font-size: 12px; font-weight: 500; }
.pl-svc-ms   { grid-area: ms; font-size: 11px; color: var(--t2); font-variant-numeric: tabular-nums; }
.pl-svc-bar  { grid-area: bar; height: 3px; background: var(--s3); border-radius: var(--rf); overflow: hidden; }
.pl-svc-bar i { display: block; height: 100%; background: var(--w); border-radius: var(--rf); transition: width .8s ease; }

/* ── Event ticker ──────────────────────────────────── */
.pl-feed { max-height: 320px; overflow-y: auto; }
.pl-row {
  display: grid;
  grid-template-columns: 8px 92px 118px 1fr auto;
  align-items: center; gap: 12px;
  padding: 9px 20px;
  border-bottom: 1px solid var(--b1);
  font-size: 11.5px;
}
.pl-row:last-child { border-bottom: 0; }
.pl-row--new { animation: pl-slide 320ms ease-out; }
@keyframes pl-slide { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .pl-row--new { animation: none; } }
.pl-row--idle { color: var(--t3); grid-template-columns: 1fr; padding: 26px 20px; text-align: center; }
.pl-row-dot  { width: 8px; height: 8px; border-radius: 50%; }
.pl-row-ts   { color: var(--t3); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 10.5px; }
.pl-row-kind { font-weight: 600; }
.pl-row-text { color: var(--t2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pl-row-node {
  font-size: 10px; color: var(--t3); background: var(--s2);
  border-radius: var(--rf); padding: 2px 8px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}

/* ── Responsive ────────────────────────────────────── */
/* Three across. JS re-measures every node box, so the edges follow the reflow
   on their own — only the grid needs restating. */
@media (max-width: 1180px) {
  .pl-stage { grid-template-columns: repeat(3, 1fr); grid-template-rows: auto auto auto 92px; }
  .pl-stage #pl-apis   { grid-column: 2; grid-row: 1; }
  .pl-stage #pl-device { grid-column: 1; grid-row: 2; }
  .pl-stage #pl-ingest { grid-column: 2; grid-row: 2; }
  .pl-stage #pl-engine { grid-column: 3; grid-row: 2; }
  .pl-stage #pl-db     { grid-column: 1; grid-row: 3; }
  .pl-stage #pl-admin  { grid-column: 2; grid-row: 3; }
  .pl-row { grid-template-columns: 8px 78px 1fr auto; }
  .pl-row-kind { display: none; }
}

/* Single column, in pipeline order (the DOM lists `apis` first so it can sit
   above `engine` on wide screens — restate the rows here). */
@media (max-width: 760px) {
  .pl-stage { grid-template-columns: 1fr; grid-template-rows: none; padding: 18px 16px 0; gap: 16px; min-height: 0; }
  .pl-stage .pl-node   { grid-column: 1; }
  .pl-stage #pl-device { grid-row: 1; }
  .pl-stage #pl-ingest { grid-row: 2; }
  .pl-stage #pl-engine { grid-row: 3; }
  .pl-stage #pl-apis   { grid-row: 4; }
  .pl-stage #pl-db     { grid-row: 5; }
  .pl-stage #pl-admin  { grid-row: 6; }
  .pl-node-meta { min-height: 0; }
  .pl-row { grid-template-columns: 8px 1fr; }
  .pl-row-ts, .pl-row-node { display: none; }
}

/* ── Record corrections queue ──────────────────────────────────────────────
   A driver's proposed edit to a station. Every changed field is reviewed on
   its own, so the row's job is to make "what it says now → what they say"
   scannable at a glance and each tick independently obvious. Built on the
   existing tokens so it follows light/dark with everything else. */
.corr-fields { display: flex; flex-direction: column; gap: 7px; }

.corr-f {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 6px 9px; border: 1px solid var(--bd); border-radius: 8px;
  background: var(--bg);
}
.corr-tick {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 11.5px; font-weight: 600; color: var(--t2);
  cursor: pointer; user-select: none; white-space: nowrap;
}
.corr-tick input { cursor: pointer; margin: 0; }

.corr-vals {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 12px; min-width: 0; flex-wrap: wrap;
}
/* The OLD value is struck through rather than merely dimmed: this row exists
   to say one thing is being replaced by another, and the strike carries that
   without needing the reviewer to read left-to-right first. */
.corr-was { color: var(--t3); text-decoration: line-through; }
.corr-now { color: var(--t1); font-weight: 600; }

.corr-note {
  margin-top: 8px; padding: 7px 10px;
  border-left: 2px solid var(--bd); border-radius: 0 6px 6px 0;
  background: var(--bg); color: var(--t2);
  font-size: 12px; font-style: italic; line-height: 1.45;
}
