/* ─────────────────────────────────────────────────────────────────────
   gps-squid design system — rally pit-wall console.

   Constraint: the Svelte bundle is pre-compiled and source isn't in
   this repo, so the bulk of the squid's UI is rendered by code we
   can't touch. Everything below is CSS overrides on top of Bootstrap 5
   dark + the hand-rolled chrome (status strip, pairing card, modal).
   Inline DOM-surgery in index.twig handles structure; this file
   handles taste.
   ───────────────────────────────────────────────────────────────────── */

@import url('https://fonts.bunny.net/css?family=ibm-plex-sans:400,500,600,700|ibm-plex-mono:400,500,600,700&display=swap');

:root {
  --bg:               #0b0f17;
  --surface:          #11161f;
  --surface-elev:     #181f2c;
  --border:           #1c2331;
  --border-strong:    #2a3346;

  --text:             #f1f5f9;
  --text-muted:       #94a3b8;
  --text-dim:         #64748b;

  /* Rally amber: single accent. Visible under sun glare on Pi
     touchscreens, distinct from every consumer-SaaS dashboard. */
  --accent:           #f59e0b;
  --accent-strong:    #fbbf24;
  --accent-soft:      rgba(245, 158, 11, 0.15);

  --ok:               #10b981;
  --ok-soft:          rgba(16, 185, 129, 0.15);
  --warn:             #f59e0b;
  --err:              #ef4444;
  --err-soft:         rgba(239, 68, 68, 0.15);
  --info:             #3b82f6;

  --font-sans: 'IBM Plex Sans', ui-sans-serif, system-ui, -apple-system, sans-serif;
  --font-mono: 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, Monaco, monospace;

  --radius-sm: 4px;
  --radius-md: 6px;
  --radius-lg: 10px;

  --shadow-sm: 0 1px 2px rgba(0,0,0,0.4);
  --shadow-md: 0 4px 12px rgba(0,0,0,0.5);
}

/* ── Base + Bootstrap dark overrides ─────────────────────────────── */

html[data-bs-theme='dark'] {
  --bs-body-bg:           var(--bg);
  --bs-body-color:        var(--text);
  --bs-border-color:      var(--border);
  --bs-secondary-bg:      var(--surface);
  --bs-tertiary-bg:       var(--surface-elev);
  --bs-emphasis-color:    var(--text);
  --bs-link-color:        var(--accent-strong);
  --bs-link-hover-color:  var(--accent);
}

body {
  font-family: var(--font-sans);
  background:  var(--bg);
  color:       var(--text);
  font-size:   14px;
  line-height: 1.5;
}

code, kbd, samp, pre, .font-monospace {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}

/* ── Hide redundant bundle chrome ────────────────────────────────────
   The Svelte bundle renders its own <header><nav> with "GPS Squid -
   RSB12 - ONLINE | tabs" + a "Status: …" line, plus an <h1> per route
   ("Connected devices - auto (REGISTER UPLOAD)" / "DB Devices" / etc.).
   Once we collapse all of that into our single fleet-status-strip
   (which carries connection state + event + tabs + upload day + host
   + Update button), those bundle-rendered rows are pure clutter. */
body > header,
body > nav.navbar,
body > div > header,
.col.text-center:has(> :only-child) {
  display: none !important;
}

/* Bundle's per-route H1 ("Connected devices - auto (REGISTER UPLOAD)",
   "DB Devices", etc.) duplicates what the active tab in the strip
   already says. Hide it on routes where it's pure duplication; keep
   it on /config where the bundle uses H1 ("Config", "Actions") for
   real section headings inside the form. */
main h1 {
  display: none !important;
}
body[data-route="config"] main h1 {
  display: revert !important;
}
/* The bundle's status line "Status: uploadDevicesHistory …" lives in
   a Bootstrap col with no class hooks, but it's the only top-level
   `.col.text-center` we render. Hiding via :has selector above. */

/* Rally-content notice only matters on /config (where operators are
   tempted to edit rally fields and need to be redirected to gps-checker).
   Hidden by default — JS toggles a body[data-route=config] class. */
.fleet-managed-notice {
  display: none;
}
body[data-route="config"] .fleet-managed-notice {
  display: block;
}

/* ── Status strip — the new top bar ──────────────────────────────── */

.fleet-status-strip {
  position: sticky;
  top: 0;
  z-index: 100;
  display: grid;
  grid-template-columns:
    /* brand */ auto
    /* state */ minmax(110px, auto)
    /* event */ minmax(180px, auto)
    /* tabs  */ 1fr
    /* actions */ minmax(180px, auto);
  gap: 1rem;
  align-items: center;
  padding: 0.55rem 1rem;
  background: linear-gradient(180deg, #11161f 0%, #0d121a 100%);
  border-bottom: 1px solid var(--border-strong);
  font-family: var(--font-mono);
  font-size: 0.78rem;
}

/* A1 Events brand mark — far-left of the strip, links back to the
   company site. White ring gives the black-disc logo enough contrast
   on the dark surface; hover bumps the ring opacity. */
.fleet-status-strip .ss-brand {
  display: inline-flex;
  flex-shrink: 0;
  text-decoration: none;
  line-height: 0;
}
.fleet-status-strip .ss-brand img {
  width: 32px;
  height: 32px;
  /* Logo PNG already has an opaque white circle baked in (see
     scripts/build-logo.py — runs at image bake time). No CSS halo
     needed — the disc reads on any background. */
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
  transition: filter 120ms ease;
}
.fleet-status-strip .ss-brand:hover img {
  filter: brightness(1.05);
}

.fleet-status-strip .ss-state {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.fleet-status-strip .ss-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--text-dim);
  flex-shrink: 0;
}

.fleet-status-strip.is-online .ss-state { color: var(--ok); }
.fleet-status-strip.is-online .ss-dot {
  background: var(--ok);
  box-shadow: 0 0 8px var(--ok), 0 0 0 3px rgba(16, 185, 129, 0.2);
  animation: ss-pulse 2.4s ease-in-out infinite;
}
.fleet-status-strip.is-pending .ss-state { color: var(--accent-strong); }
.fleet-status-strip.is-pending .ss-dot { background: var(--accent); box-shadow: 0 0 6px var(--accent); }
.fleet-status-strip.is-offline .ss-state { color: var(--err); }
.fleet-status-strip.is-offline .ss-dot { background: var(--err); }

@keyframes ss-pulse {
  0%, 100% { box-shadow: 0 0 8px var(--ok), 0 0 0 3px rgba(16, 185, 129, 0.18); }
  50%      { box-shadow: 0 0 12px var(--ok), 0 0 0 5px rgba(16, 185, 129, 0.08); }
}

.fleet-status-strip .ss-event {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  text-align: left;
  min-width: 0;
}

/* Tabs centred in the strip. Replaces the bundle's secondary nav. */
.fleet-status-strip .ss-tabs {
  display: flex;
  gap: 0.25rem;
  align-items: center;
  justify-content: center;
}
.fleet-status-strip .ss-tabs a {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-muted);
  text-decoration: none;
  padding: 0.4rem 0.8rem;
  border-radius: var(--radius-sm);
  transition: color 120ms, background 120ms;
  white-space: nowrap;
}
.fleet-status-strip .ss-tabs a:hover {
  color: var(--text);
  background: var(--surface-elev);
}
.fleet-status-strip .ss-tabs a.is-active {
  color: var(--accent-strong);
  background: var(--accent-soft);
  box-shadow: inset 0 -2px 0 var(--accent);
}
.fleet-status-strip .ss-event-name {
  font-size: 0.95rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}
.fleet-status-strip .ss-event-meta {
  font-size: 0.68rem;
  color: var(--text-muted);
  letter-spacing: 0.06em;
  margin-top: 0.15rem;
}
.fleet-status-strip .ss-event.is-unassigned .ss-event-name { color: var(--accent); }

.fleet-status-strip .ss-actions {
  display: flex;
  gap: 0.5rem;
  align-items: center;
  justify-content: flex-end;
}

.fleet-status-strip .ss-host {
  display: inline-flex;
  flex-direction: column;
  align-items: flex-start;
  font-family: var(--font-mono);
  color: var(--text);
  line-height: 1.15;
  white-space: nowrap;
}
.fleet-status-strip .ss-host-label {
  font-size: 0.58rem;
  color: var(--text-dim);
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.fleet-status-strip .ss-host strong {
  font-size: 0.9rem;
  letter-spacing: 0.04em;
  /* Hostnames are case-insensitive for networking, but operators use the
     submitted RSB… casing as the visible device identity. */
  text-transform: none;
}

/* Update button (lives inside .ss-actions; was floating before) */
#manual_update_btn {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 0.35rem 0.7rem;
  background: transparent;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  color: var(--text-muted);
  cursor: pointer;
  transition: all 120ms ease;
}
#manual_update_btn:hover {
  border-color: var(--accent);
  color: var(--accent-strong);
  background: var(--accent-soft);
}
#manual_update_btn:disabled {
  opacity: 0.5;
  cursor: progress;
}
#manual_update_status {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.05em;
  max-width: 280px;
  text-align: right;
}
#manual_update_status.ok  { color: var(--ok); }
#manual_update_status.err { color: var(--err); }

/* ── Server-managed sub-notice ───────────────────────────────────── */

.fleet-managed-notice {
  background: var(--surface);
  color: var(--text-muted);
  padding: 0.45rem 1rem;
  border-bottom: 1px solid var(--border);
  font-size: 0.7rem;
  text-align: center;
  letter-spacing: 0.05em;
}
.fleet-managed-notice strong { color: var(--accent-strong); font-weight: 600; }
.fleet-managed-notice code {
  font-family: var(--font-mono);
  background: var(--bg);
  padding: 1px 6px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  color: var(--text);
  font-size: 0.85em;
}

/* ── Pairing card (when not yet enrolled) ────────────────────────── */

.fleet-pairing {
  margin: 1.75rem auto 1rem;
  max-width: 480px;
  padding: 1.75rem;
  background: var(--surface);
  border: 1px solid var(--accent);
  border-radius: var(--radius-lg);
  box-shadow: 0 0 0 1px var(--accent-soft), var(--shadow-md);
  text-align: center;
  font-family: var(--font-mono);
}
.fleet-pairing .label {
  font-size: 0.7rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--accent);
  font-weight: 600;
}
.fleet-pairing .code {
  font-size: 2.5rem;
  letter-spacing: 0.32em;
  font-weight: 700;
  margin: 1rem 0 0.75rem;
  color: var(--text);
  text-shadow: 0 0 24px var(--accent-soft);
}
.fleet-pairing .hint {
  font-size: 0.78rem;
  color: var(--text-muted);
  line-height: 1.6;
  letter-spacing: 0.02em;
}
.fleet-pairing .hint strong { color: var(--accent-strong); }

/* ── Footer ──────────────────────────────────────────────────────── */

#app_footer {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  background: var(--bg);
  color: var(--text-dim);
  font-family: var(--font-mono);
  font-size: 0.66rem;
  text-align: center;
  padding: 0.4rem 0.5rem;
  letter-spacing: 0.14em;
  border-top: 1px solid var(--border);
  z-index: 1;
}
#app_footer a { color: var(--accent-strong); text-decoration: none; }
#app_footer a:hover { color: var(--accent); }
body { padding-bottom: 1.75rem; }

/* ── Bootstrap component overrides ───────────────────────────────── */

.btn {
  font-family: var(--font-sans);
  font-weight: 500;
  border-radius: var(--radius-sm);
}
.btn-primary {
  --bs-btn-bg: var(--accent);
  --bs-btn-border-color: var(--accent);
  --bs-btn-color: #000;
  --bs-btn-hover-bg: var(--accent-strong);
  --bs-btn-hover-border-color: var(--accent-strong);
  --bs-btn-hover-color: #000;
  --bs-btn-active-bg: var(--accent);
  --bs-btn-active-border-color: var(--accent);
  --bs-btn-active-color: #000;
  font-weight: 600;
}
.btn-success {
  --bs-btn-bg: var(--ok);
  --bs-btn-border-color: var(--ok);
  --bs-btn-hover-bg: #059669;
  --bs-btn-hover-border-color: #059669;
}
.btn-danger {
  --bs-btn-bg: var(--err);
  --bs-btn-border-color: var(--err);
  --bs-btn-hover-bg: #dc2626;
  --bs-btn-hover-border-color: #dc2626;
}
.btn-outline-primary {
  --bs-btn-color: var(--accent-strong);
  --bs-btn-border-color: var(--accent);
  --bs-btn-hover-bg: var(--accent);
  --bs-btn-hover-color: #000;
  --bs-btn-hover-border-color: var(--accent);
}

.form-control, .form-select {
  font-family: var(--font-mono);
  background-color: var(--surface);
  border-color: var(--border-strong);
  color: var(--text);
  font-size: 0.9rem;
}
.form-control:focus, .form-select:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px var(--accent-soft);
  background-color: var(--surface);
  color: var(--text);
}
.form-floating > label {
  color: var(--text-muted);
  font-family: var(--font-sans);
  font-size: 0.85rem;
}

.form-check-input:checked {
  background-color: var(--accent);
  border-color: var(--accent);
}
.form-check-input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px var(--accent-soft);
}
.form-switch .form-check-input:checked {
  background-color: var(--accent);
}

.table {
  --bs-table-bg: transparent;
  --bs-table-color: var(--text);
  --bs-table-border-color: var(--border);
  --bs-table-striped-bg: rgba(255, 255, 255, 0.02);
  font-family: var(--font-sans);
}
.table th {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text-muted);
  font-weight: 600;
  border-bottom: 1px solid var(--border-strong);
  padding: 0.6rem 0.75rem;
  white-space: nowrap;
}
.table td {
  font-family: var(--font-mono);
  font-size: 0.85rem;
  font-variant-numeric: tabular-nums;
  padding: 0.5rem 0.75rem;
  vertical-align: middle;
}

.nav-tabs {
  border-bottom: 1px solid var(--border-strong);
  padding: 0 1rem;
}
.nav-tabs .nav-link {
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: 0.78rem;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  border: 1px solid transparent;
  border-bottom: none;
  padding: 0.55rem 0.95rem;
  margin-bottom: -1px;
}
.nav-tabs .nav-link:hover {
  color: var(--text);
  border-color: transparent;
  background: var(--surface);
}
.nav-tabs .nav-link.active {
  color: var(--accent-strong);
  background: var(--surface);
  border-color: var(--border-strong);
  border-bottom-color: var(--surface);
}

.alert {
  border-radius: var(--radius-md);
  font-family: var(--font-sans);
  border: 1px solid currentColor;
  font-size: 0.88rem;
}
.alert-success { background: var(--ok-soft); color: var(--ok); border-color: var(--ok); }
.alert-danger  { background: var(--err-soft); color: var(--err); border-color: var(--err); }
.alert-warning { background: var(--accent-soft); color: var(--accent-strong); border-color: var(--accent); }

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}
.card-header {
  background: var(--surface-elev);
  border-bottom-color: var(--border);
  font-family: var(--font-mono);
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-muted);
  font-weight: 600;
}

.modal-content {
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-lg);
}
.modal-header { border-bottom-color: var(--border); }
.modal-footer { border-top-color: var(--border); }

.badge {
  font-family: var(--font-mono);
  font-weight: 600;
  letter-spacing: 0.05em;
  border-radius: var(--radius-sm);
}

/* ── /config refinement ───────────────────────────────────────────────
   Operators land here to flip mode flags, restart, reboot. The bundle
   renders the form as a flat <table> with bare inputs and the action
   buttons in a separate cluster. Wrap the whole config column + the
   actions column in proper card surfaces, give the bare-table layout
   breathing room, and tone the destructive cluster (DB DELETE / reboot
   / shutdown) so it stops shouting before the operator has decided. */
body[data-route="config"] main {
  padding: 1.25rem 1.5rem 2rem;
  max-width: 1200px;
  margin: 0 auto;
}

/* Two-column responsive grid scoped to /config (Config | Actions).
   Bundle uses `.container-xl` (Bootstrap-XL container) wrapping a
   `.row` with two `.col-12.col-xl-6` children. Targeting both
   `.container` and `.container-xl` covers either layout. */
body[data-route="config"] main > .row,
body[data-route="config"] main > .container > .row,
body[data-route="config"] main > .container-xl > .row,
body[data-route="config"] main > .container-fluid > .row {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.25rem;
  margin: 0;
}
@media (min-width: 900px) {
  body[data-route="config"] main > .row,
  body[data-route="config"] main > .container > .row,
  body[data-route="config"] main > .container-xl > .row,
  body[data-route="config"] main > .container-fluid > .row {
    grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
  }
}
body[data-route="config"] main > .row > .col,
body[data-route="config"] main > .row > [class*="col-"],
body[data-route="config"] main > .container > .row > .col,
body[data-route="config"] main > .container > .row > [class*="col-"],
body[data-route="config"] main > .container-xl > .row > .col,
body[data-route="config"] main > .container-xl > .row > [class*="col-"],
body[data-route="config"] main > .container-fluid > .row > .col,
body[data-route="config"] main > .container-fluid > .row > [class*="col-"] {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 1.5rem;
  width: auto !important;
  max-width: none !important;
  flex: none !important;
}
body[data-route="config"] main > .row h1,
body[data-route="config"] main > .container > .row h1,
body[data-route="config"] main > .container-xl > .row h1,
body[data-route="config"] main > .container-fluid > .row h1 {
  margin-top: 0;
  margin-bottom: 1.1rem;
  padding-bottom: 0.75rem;
  border-bottom: 1px solid var(--border);
  font-family: var(--font-mono);
  font-size: 0.9rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-muted);
}

/* The mode/upload/download/training/register checkboxes render as
   a vertically-stacked TABLE with no spacing. Make rows clickable
   anywhere with proper switch hit zones. */
body[data-route="config"] main table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
}
body[data-route="config"] main table tr {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  padding: 0.45rem 0;
  border-bottom: 1px solid var(--border);
}
body[data-route="config"] main table tr:last-child {
  border-bottom: none;
}
body[data-route="config"] main table td {
  padding: 0;
  border: none;
  font-family: var(--font-sans);
  font-size: 0.9rem;
  color: var(--text);
}
body[data-route="config"] main table td:nth-child(2) {
  justify-self: end;
}

/* Native checkboxes restyled as toggle switches via :checked + ::before
   trickery, since DOM-surgery to wrap each in .form-switch is fragile. */
body[data-route="config"] input[type="checkbox"].form-check-input {
  appearance: none;
  -webkit-appearance: none;
  width: 2.4rem;
  height: 1.3rem;
  border-radius: 999px;
  background: var(--surface-elev);
  border: 1px solid var(--border-strong);
  position: relative;
  cursor: pointer;
  transition: background 150ms, border-color 150ms;
  outline: none;
  flex-shrink: 0;
}
body[data-route="config"] input[type="checkbox"].form-check-input::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 2px;
  transform: translateY(-50%);
  width: 1rem;
  height: 1rem;
  border-radius: 50%;
  background: var(--text-muted);
  transition: left 150ms, background 150ms;
}
body[data-route="config"] input[type="checkbox"].form-check-input:checked {
  background: var(--accent);
  border-color: var(--accent);
}
body[data-route="config"] input[type="checkbox"].form-check-input:checked::before {
  left: calc(100% - 1.1rem);
  background: #fff;
}
body[data-route="config"] input[type="checkbox"].form-check-input:focus-visible {
  box-shadow: 0 0 0 3px var(--accent-soft);
}

/* Mode dropdown wider for better readability */
body[data-route="config"] main select.form-select {
  min-width: 9rem;
}

/* Action buttons: arrange in a clean 2-row grid (safe / destructive),
   with breathing room. */
body[data-route="config"] main .btn-success,
body[data-route="config"] main .btn-info,
body[data-route="config"] main .btn-warning {
  margin: 0.25rem 0.5rem 0.25rem 0;
  padding: 0.5rem 1.05rem;
  font-size: 0.85rem;
}
body[data-route="config"] main .btn-danger {
  margin: 0.25rem 0.5rem 0.25rem 0;
  padding: 0.5rem 1.05rem;
  font-size: 0.85rem;
  /* Slightly muted danger so reboot/shutdown doesn't scream — operator
     reads the label, then the visual weight follows the choice. */
  --bs-btn-color: rgba(239, 68, 68, 0.85);
  --bs-btn-border-color: rgba(239, 68, 68, 0.55);
}
body[data-route="config"] main .btn-danger:hover {
  --bs-btn-color: #fff;
  --bs-btn-border-color: var(--err);
}

/* MAP UPLOAD DAY card already styled by index.twig inline. Keep it
   visually distinct as the FIRST setting an operator sees on /config. */
#upload_day_row {
  margin-top: 0 !important;
}

/* ── Operator polish ─────────────────────────────────────────────── */

/* H1/H2/H3 are non-interactive — strip the browser focus ring the
   bundle inadvertently triggers on focus-trapped tabs. Looked like a
   stray rectangular border around every heading. */
h1, h2, h3, h4, h5, h6 {
  outline: none !important;
}

/* The Svelte bundle dumps the entire config object as syntax-highlighted
   JSON at the bottom of /config. Useful for the original developer; pure
   visual debt for the operator (it shows mode flags + categories +
   tracks + maps inline, all of which are already represented as form
   controls or are server-managed). Hide the raw block so the page ends
   at the action buttons. */
pre,
code.hljs,
pre code {
  display: none !important;
}

/* Section headings on /config etc. are H1, but they're really "section
   heading" weight — tighten the size + spacing so they don't dominate
   the layout. */
h1 {
  font-size: 1.5rem;
  letter-spacing: -0.01em;
  margin-bottom: 1.25rem;
}
h2 {
  font-size: 1.15rem;
  letter-spacing: -0.005em;
  margin-bottom: 0.9rem;
}

/* Status text the bundle renders mid-page ("Status: uploadDevicesHistory…")
   — render as a subtle pill. Not a load-bearing operator signal but
   reassuring that the daemon is alive. */
body > div:not([id]) > div:first-child:has(> :only-child) {
  /* heuristic — best effort, fallthrough is fine */
  font-family: var(--font-mono);
  font-size: 0.7rem;
  color: var(--text-muted);
  letter-spacing: 0.04em;
}

/* Bare checkboxes that the Svelte form-check renders without a
   .form-switch wrapper. Use the modern accent-color trick to tint them
   in our rally amber without DOM-surgery. */
input[type="checkbox"].form-check-input {
  accent-color: var(--accent);
  width: 1.05rem;
  height: 1.05rem;
  cursor: pointer;
}
input[type="checkbox"].form-check-input:focus {
  outline: 2px solid var(--accent-soft);
  outline-offset: 2px;
}

/* Action buttons on /config — group by intent. Default-styled below.
   The destructive cluster (DB DELETE / reboot / shutdown) gets a
   muted background so it doesn't compete for attention with the
   regular controls. */
.btn-success {
  --bs-btn-bg: var(--ok);
  --bs-btn-border-color: var(--ok);
  --bs-btn-color: #fff;
  --bs-btn-hover-bg: #059669;
  --bs-btn-hover-border-color: #059669;
  --bs-btn-hover-color: #fff;
  font-weight: 600;
}
.btn-info {
  --bs-btn-bg: transparent;
  --bs-btn-border-color: var(--accent);
  --bs-btn-color: var(--accent-strong);
  --bs-btn-hover-bg: var(--accent-soft);
  --bs-btn-hover-border-color: var(--accent);
  --bs-btn-hover-color: var(--accent-strong);
}
.btn-danger {
  --bs-btn-bg: transparent;
  --bs-btn-border-color: var(--err);
  --bs-btn-color: var(--err);
  --bs-btn-hover-bg: rgba(239, 68, 68, 0.12);
  --bs-btn-hover-border-color: var(--err);
  --bs-btn-hover-color: #fff;
}
.btn-warning {
  --bs-btn-bg: transparent;
  --bs-btn-border-color: var(--accent);
  --bs-btn-color: var(--accent);
  --bs-btn-hover-bg: var(--accent-soft);
}

/* Connected device hero on /: bundle uses inline yellow/orange. Heavy
   override so the card matches the rest of the system. The bundle
   inlines `style="background:..."` on a parent of this h1, so we
   target the H1 directly and re-style its surrounding container via
   adjacent-sibling. */
[style*="background"] h1.svelte-ahoge3,
[style*="background-color"] h1.svelte-ahoge3 {
  /* still legible regardless of bundle bg */
  text-shadow: 0 0 1px rgba(0,0,0,0.2);
}
/* Generic: any inline-styled container the bundle uses to "highlight"
   a state. Replace its inline background with our surface + accent
   border, regardless of which inline color it picked. */
div[style*="background: yellow" i],
div[style*="background:#ffc" i],
div[style*="background: #ffa" i],
div[style*="background: orange" i],
div[style*="background-color: yellow" i],
div[style*="background-color: orange" i] {
  background: var(--surface) !important;
  border: 1px solid var(--accent) !important;
  border-radius: var(--radius-lg) !important;
  box-shadow: 0 0 0 1px var(--accent-soft), var(--shadow-md) !important;
  color: var(--text) !important;
  padding: 1.25rem !important;
}
/* Same heuristic for green-tinted "OK" cards, red error cards. */
div[style*="background: green" i],
div[style*="background-color: green" i] {
  background: var(--ok-soft) !important;
  border: 1px solid var(--ok) !important;
  border-radius: var(--radius-lg) !important;
  color: var(--text) !important;
}
div[style*="background: red" i],
div[style*="background-color: red" i] {
  background: var(--err-soft) !important;
  border: 1px solid var(--err) !important;
  border-radius: var(--radius-lg) !important;
  color: var(--text) !important;
}

/* Empty-state card injected by index.twig when there are no connected
   Garmin drives. Operator's resting state most of the day. */
.fleet-empty-state {
  margin: 2rem auto;
  max-width: 520px;
  padding: 2rem 1.5rem;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-lg);
  text-align: center;
  font-family: var(--font-sans);
  box-shadow: var(--shadow-md);
}
.fleet-empty-state .fleet-empty-icon {
  width: 56px;
  height: 56px;
  margin: 0 auto 1rem;
  border-radius: 50%;
  background: var(--accent-soft);
  border: 2px solid var(--accent);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.6rem;
  color: var(--accent-strong);
  animation: fleet-empty-pulse 2.4s ease-in-out infinite;
}
.fleet-empty-state .fleet-empty-title {
  font-family: var(--font-mono);
  font-size: 0.85rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent-strong);
}
.fleet-empty-state .fleet-empty-body {
  font-size: 0.9rem;
  color: var(--text-muted);
  margin-top: 0.5rem;
  line-height: 1.55;
}
.fleet-empty-state .fleet-empty-hint {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  color: var(--text-dim);
  letter-spacing: 0.06em;
  margin-top: 1rem;
  padding-top: 1rem;
  border-top: 1px solid var(--border);
}
@keyframes fleet-empty-pulse {
  0%, 100% { box-shadow: 0 0 0 0 var(--accent-soft); }
  50%      { box-shadow: 0 0 0 12px rgba(245, 158, 11, 0); }
}

/* Tab nav — style the secondary "GPS Squid - RSB12 - ONLINE | tabs"
   header more deliberately. Bundle wraps it in <header> + <nav>. */
header > nav, header > div, .navbar {
  background: var(--surface) !important;
  border-bottom: 1px solid var(--border-strong) !important;
  padding: 0.6rem 1rem !important;
}
header a,
.navbar a {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-muted);
  text-decoration: none !important;
  padding: 0.35rem 0.75rem;
  border-radius: var(--radius-sm);
  transition: color 120ms, background 120ms;
}
header a:hover,
.navbar a:hover {
  color: var(--text);
  background: var(--surface-elev);
}
header a.active,
.navbar a.active,
header a[aria-current],
.navbar a[aria-current] {
  color: var(--accent-strong);
  background: var(--accent-soft);
}

/* Inline status pill (reusable) */
.fleet-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.18rem 0.55rem;
  border-radius: var(--radius-sm);
  font-size: 0.68rem;
  font-family: var(--font-mono);
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.fleet-pill.ok   { background: var(--ok-soft);     color: var(--ok); }
.fleet-pill.err  { background: var(--err-soft);    color: var(--err); }
.fleet-pill.warn { background: var(--accent-soft); color: var(--accent-strong); }

/* ── Device-archive modal (preserved layout, restyled) ───────────── */

.fleet-delete-btn {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 0.28rem 0.65rem;
  border: 1px solid var(--err);
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--err);
  cursor: pointer;
  transition: all 120ms ease;
}
.fleet-delete-btn:hover { background: var(--err-soft); }

#fleet_delete_modal {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.75);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 2000;
  font-family: var(--font-sans);
}
.fleet-delete-card {
  background: var(--surface);
  border: 1px solid var(--err);
  border-radius: var(--radius-lg);
  padding: 1.5rem;
  min-width: 400px;
  max-width: 480px;
  color: var(--text);
  box-shadow: var(--shadow-md), 0 0 0 1px var(--err-soft);
}
.fleet-delete-card h3 {
  margin: 0 0 0.5rem;
  font-size: 0.92rem;
  color: var(--err);
  font-weight: 600;
  font-family: var(--font-mono);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.fleet-delete-card p { margin: 0.3rem 0; font-size: 0.88rem; line-height: 1.55; }
.fleet-delete-card code {
  font-family: var(--font-mono);
  background: var(--bg);
  padding: 1px 6px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  color: var(--text);
}
.fleet-delete-card .fleet-delete-note {
  color: var(--text-muted);
  font-size: 0.78rem;
  margin-top: 0.5rem;
}
.fleet-delete-card label {
  display: block;
  margin: 0.85rem 0 0.3rem;
  font-size: 0.68rem;
  color: var(--text-muted);
  font-family: var(--font-mono);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  font-weight: 600;
}
.fleet-delete-card input {
  width: 100%;
  padding: 0.5rem 0.65rem;
  background: var(--bg);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  color: var(--text);
  font-family: var(--font-mono);
  font-size: 0.9rem;
  box-sizing: border-box;
}
.fleet-delete-card input:focus {
  outline: none;
  border-color: var(--err);
  box-shadow: 0 0 0 2px var(--err-soft);
}
.fleet-delete-card .fleet-delete-error {
  margin-top: 0.5rem;
  color: var(--err);
  font-size: 0.78rem;
  font-family: var(--font-mono);
}
.fleet-delete-card .fleet-delete-actions {
  display: flex;
  justify-content: flex-end;
  gap: 0.5rem;
  margin-top: 1.25rem;
}
.fleet-delete-card button {
  padding: 0.45rem 1rem;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface-elev);
  color: var(--text);
  cursor: pointer;
  font-family: var(--font-mono);
  font-size: 0.74rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.fleet-delete-card button:hover { background: var(--border-strong); }
.fleet-delete-card #fleet_delete_go {
  background: var(--err);
  border-color: var(--err);
  color: #fff;
}
.fleet-delete-card #fleet_delete_go:hover { background: #dc2626; border-color: #dc2626; }
.fleet-delete-card #fleet_delete_go:disabled {
  opacity: 0.4;
  cursor: not-allowed;
  background: var(--surface-elev);
  border-color: var(--border-strong);
  color: var(--text-dim);
}

/* ── Alerts container (existing positional behavior) ─────────────── */

#alert_container {
  position: fixed;
  top: 4rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
  z-index: 50;
  pointer-events: none;
  padding: 0 1rem;
}
#alert_container > .alert {
  pointer-events: all;
  max-width: 600px;
  width: 100%;
}

/* ── AEV-126: compact device cards — 4 visible at once ──────────── */

/* Fix specificity: bundle.css uses TRIPLE-scoped selectors
   (.fs-50.svelte-ahoge3.svelte-ahoge3 — 3 classes) with !important.
   A 2-class override loses even with !important because specificity
   still wins when both are !important from the same stylesheet origin.
   Match with triple-scoped selectors here. */
/* GPS device ID — most important at-a-glance identifier. */
.fs-50.svelte-ahoge3.svelte-ahoge3 { font-size: 1.5rem !important; font-weight: 700 !important; }
/* Status / error messages and device name label. */
.fs-30.svelte-ahoge3.svelte-ahoge3 { font-size: 1.1rem !important; }
#devices.svelte-ahoge3 .device .label.svelte-ahoge3 { font-size: 1.1rem !important; font-weight: 600 !important; }

/* Operator-facing replacements for the bundle's raw status enums. */
[data-operator-status] {
  font-weight: 600;
}
[data-operator-status="is-ok"] {
  display: inline-block;
  color: #052e16 !important;
  background: #f0fdf4 !important;
  border: 1px solid #166534;
  border-radius: var(--radius-sm);
  padding: 0.15rem 0.45rem;
}
[data-operator-status="is-warning"] {
  display: inline-block;
  color: #fff8e1 !important;
  background: #7a4300 !important;
  border: 1px solid #f6b73c;
  border-radius: var(--radius-sm);
  padding: 0.15rem 0.45rem;
}
[data-operator-status="is-error"] {
  display: inline-block;
  color: #450a0a !important;
  background: #fef2f2 !important;
  border: 1px solid #991b1b;
  border-radius: var(--radius-sm);
  padding: 0.15rem 0.45rem;
}
[data-operator-status="is-neutral"] {
  display: inline-block;
  color: #111827 !important;
  background: #f8fafc !important;
  border: 1px solid #64748b;
  border-radius: var(--radius-sm);
  padding: 0.15rem 0.45rem;
}

/* Prevent body scroll only on the Connected page (where #devices exists).
   :has() is Chromium-only but that's all that runs on Pi touchscreens. */
body:has(#devices) { overflow: hidden; }

/* 2×2 grid pinned to the viewport height below the fleet-status-strip.
   52px ≈ strip height: 32px brand logo + 2×0.55rem padding + 1px border.
   grid-template-rows: 1fr 1fr forces equal row heights regardless of
   card content length — long error messages clip inside their cell. */
#devices.svelte-ahoge3 {
  display: grid !important;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
  gap: 0.5rem;
  padding: 0.5rem;
  height: calc(100dvh - 52px);
  overflow: hidden;
  box-sizing: border-box;
}

/* Each card fills its grid cell and centers content vertically so
   whitespace is distributed evenly rather than pooling below the text.
   min-height:0 lets the grid actually constrain the row height;
   overflow:hidden clips any content that still exceeds the cell. */
#devices.svelte-ahoge3 .device.svelte-ahoge3 {
  display: flex !important;
  flex-direction: column !important;
  justify-content: center !important;
  align-items: center !important;
  margin-bottom: 0 !important;
  padding: 0.75rem !important;
  overflow: hidden;
  min-height: 0;
  border-radius: var(--radius-md) !important;
  word-break: break-word;
}

/* Very narrow screens (<480px): single column, 4 equal rows. */
@media (max-width: 479px) {
  #devices.svelte-ahoge3 {
    grid-template-columns: 1fr;
    grid-template-rows: repeat(4, 1fr);
  }
}

/* ── Narrow screens (Pi touchscreens, ~7" / 800px wide) ──────────── */

@media (max-width: 768px) {
  .fleet-status-strip {
    grid-template-columns: 1fr;
    gap: 0.55rem;
    text-align: center;
    padding: 0.6rem 0.75rem;
  }
  .fleet-status-strip .ss-event { align-items: center; }
  .fleet-status-strip .ss-actions { justify-content: center; }
  .fleet-status-strip .ss-tabs { justify-content: center; flex-wrap: wrap; }
  .fleet-status-strip .ss-brand { justify-self: center; }
  .fleet-pairing .code { font-size: 2rem; letter-spacing: 0.22em; }
  .fleet-delete-card { min-width: 0; width: 92vw; }
}

/* ── Slim Squid registration form (A1 Events) ─────────────────────
   The Connected page packs each plugged-in GPS into a quarter-screen
   grid cell (#devices is a 2×2 grid with overflow:hidden, above).
   RegisterForm renders ~10 fields across two Bootstrap columns, which
   overflow the cell and get clipped — worst on a phone. To register we
   only need the rider BIB and the GPS number/total; we also keep the
   device serial (Device ID) and model (Description) on screen, read-only,
   for the operator to sanity-check. Everything else is hidden and the
   form is stacked into one tight column that fits the cell.

   The Svelte bundle can't be rebuilt from this repo (no source here), so
   we key on the inputs' stable ids — same technique as the :has()
   overrides earlier in this file. */

/* Hide the fields we don't need:
   - Map type  → auto-detected from the Garmin on connect (GarminDevice.js)
   - Category  → the class, derived from the BIB server-side
   - first/last name → free-text, optional
   - Label printed → automation bookkeeping, not an operator input
   NOTE: Label itself is KEPT visible (read-only). It's the multi-GPS
   download key (e.g. 123_2-2) and the operator's only check that it
   didn't reset to the bare BIB when a 2nd device's BIB is edited —
   hiding it risks two devices colliding under the same .gpx name. */
.form-floating:has(> #i_map_type),
.form-floating:has(> #i_category),
.form-floating:has(> #i_first_name),
.form-floating:has(> #i_last_name),
.form-floating:has(> #i_label_printed) {
  display: none !important;
}

/* BIB shares a Bootstrap row with the now-hidden Category half — let it
   span the full row instead of staying boxed to the left 50%. */
form:has(#i_rider_id) .col-md-6:has(#i_rider_id) {
  flex: 0 0 100% !important;
  max-width: 100% !important;
}

/* Stack the form's two columns and tighten everything so BIB +
   GPS number/total + the read-only Serial/Model + the register button
   fit the quarter-cell, including on a phone. */
form:has(#i_rider_id) {
  flex-direction: column !important;
  margin-top: 0.4rem !important;
}
form:has(#i_rider_id) .mb-3 {
  margin-bottom: 0.4rem !important;
}
/* Shrink the tall Bootstrap floating fields a touch; nudge the value text
   and floating label to match the reduced height so they don't overlap. */
form:has(#i_rider_id) .form-floating > .form-control,
form:has(#i_rider_id) .form-floating > .form-select {
  min-height: 3rem;
  height: 3rem;
  padding-top: 1.2rem;
  padding-bottom: 0.2rem;
}
form:has(#i_rider_id) .form-floating > label {
  padding: 0.5rem 0.75rem;
}


/* When a register form is OPEN, the operator is focused on that one device
   and needs the whole form (BIB → Serial/Model → button), which is taller
   than the fixed quarter-cell. Release that card from the grid's fixed
   height + overflow clip so the page scrolls instead of hiding the lower
   fields. The compact 2x2 idle view (no form open) is unchanged. */
#devices.svelte-ahoge3:has(form:not(.d-none) #i_rider_id) {
  height: auto !important;
  overflow: visible !important;
  grid-template-rows: auto !important;
}
#devices.svelte-ahoge3 .device.svelte-ahoge3:has(form:not(.d-none) #i_rider_id) {
  overflow: visible !important;
  min-height: 0 !important;
  justify-content: flex-start !important;
}

/* The Connected page locks body scroll (body:has(#devices){overflow:hidden}
   earlier in this file). With a form open the page can be taller than the
   viewport, so also release body scroll while a registration form is open —
   otherwise the lower fields / submit button stay unreachable on a phone or
   7" Pi even though the grid + card no longer clip. */
body:has(#devices.svelte-ahoge3 form:not(.d-none) #i_rider_id) {
  overflow: auto !important;
}

/* ── Phone portrait: stack device cards in a scrollable column ─────────
   The #devices 2x2 fixed-viewport grid is a kiosk layout for the Pi's
   ~800px landscape touchscreen. On a phone (<=768px) cramming up to 4
   cards into the viewport with overflow:hidden clips them and is unusable.
   There, switch to a single scrollable column: drop the fixed height +
   clip, let each card size to its content, and re-enable body scroll. The
   Pi landscape kiosk view (>768px wide) is unchanged. */
@media (max-width: 768px) {
  body:has(#devices) { overflow: auto !important; }
  #devices.svelte-ahoge3 {
    display: flex !important;
    flex-direction: column !important;
    height: auto !important;
    min-height: 0 !important;
    overflow: visible !important;
    gap: 0.6rem !important;
  }
  #devices.svelte-ahoge3 .device.svelte-ahoge3 {
    height: auto !important;
    min-height: 0 !important;
    overflow: visible !important;
    justify-content: flex-start !important;
    margin-bottom: 0 !important;
  }
}
