/* ============================================================================
   LCB — Wada structural system
   ----------------------------------------------------------------------------
   Loaded AFTER each page's inline <style>, so these rules win at equal
   specificity and act as the shared visual contract.

   Source: Nonarkara/palette — Sanzo Wada's 348 recorded colour combinations.
   We take *structure* and *value*, not all 159 colours.

     --paper    #f7f5ef  dominant field      (the exhibition's own white)
     --ink      #111314  Wada Black          counter-field, 17.1:1 with paper
     --plate    #12354e  Dark Tyrian Blue    structural depth, 11.7:1 with paper
     --wada-hi  #fdbf68  Cream Yellow        rare signal only

   Relationship follows the exhibition's two-colour plate rule: paper carries
   ~62% of the surface, ink the decisive ~38% concentrated in the hub bezel,
   panel rules and active states. Route-family colours are a CLOSED signal
   system (green open / red closed / orange restricted / blue port / yellow
   warning) and are deliberately left untouched — never recolour a status to
   suit a mood.

   Measured against --paper #f7f5ef:
     --ink-3  #767168  4.61:1  (previous #a9a59a was 2.34:1 — an AA failure
                                carrying every structural micro-label)
     --ink-2  #706b62  5.03:1
   ========================================================================== */

:root {
  /* --- field + ink ------------------------------------------------------- */
  --paper:      #f7f5ef;
  --panel:      #ffffff;
  --ink:        #111314;
  --ink-2:      #706b62;
  --ink-3:      #767168;   /* 4.61:1 — passes AA at 8px. Was 2.34:1.      */
  --line:       #e2ded1;
  --line-2:     #c9c4b4;

  /* --- structural plates -------------------------------------------------- */
  --plate:      #12354e;   /* Dark Tyrian Blue */
  --plate-ink:  #0b2438;   /* one step deeper for hover/active             */
  --wada-hi:    #fdbf68;   /* Cream Yellow — rare signal, never decoration  */
  --wada-hi-ink:#111314;

  /* --- semantics (unchanged — closed signal system) ----------------------- */
  --accent:     #1f6e43;
  --neg:        #b3261e;

  /* --- route families (unchanged — the civic vocabulary) ------------------ */
  --rt-ink:     #111314;
  --rt-green:   #00853F;
  --rt-purple:  #B933AD;
  --rt-yellow:  #FCCC0A;
  --rt-orange:  #FF6319;
  --rt-blue:    #0039A6;
  --road:       #c8c4b8;
  --road-strong:#98948a;
}

/* ============================================================================
   1. HUB BEZEL — the counter-field.
   Ink plate across the top of every instrument page. Paper text. The map keeps
   the paper; the chrome reads as a machined frame around it.
   ========================================================================== */

.hub {
  background: var(--ink) !important;
  border-bottom: 0 !important;
  padding: 10px 18px !important;
  color: var(--paper);
  box-shadow: inset 0 -3px 0 var(--plate);
}
.hub .hub-code    { color: var(--wada-hi) !important; font-size: 9.5px !important; letter-spacing: 0.2em !important; }
.hub .hub-title   { color: var(--paper) !important; }
.hub .hub-subtitle{ color: #b8b3a6 !important; }
.hub .hub-meta    { color: #a9a496 !important; }
.hub .hub-meta-line { color: inherit !important; }

/* The LCB identity disc becomes the one solid warm block in the bezel. */
.hub .disc--ink {
  background: var(--wada-hi) !important;
  color: var(--ink) !important;
  border-radius: 0 !important;
}

/* Status counts: ink-on-paper chips so they read at a glance, not as loose
   coloured numerals floating in white space. */
.hub .hub-stats { gap: 0 !important; border-left: 1px solid #3a3833; padding-left: 14px; }
.hub .hub-stat {
  background: transparent !important;
  border: 0 !important;
  border-right: 1px solid #3a3833 !important;
  padding: 2px 12px 2px 10px !important;
  min-width: 0 !important;
}
.hub .hub-stat:last-child { border-right: 0 !important; }
.hub .hub-stat .v {
  font-size: 21px !important;
  line-height: 1 !important;
  font-weight: 700 !important;
}
.hub .hub-stat .l { color: #a9a496 !important; font-size: 9px !important; letter-spacing: 0.1em; }

/* Nav + actions on the bezel. */
.hub .nav-links a {
  color: var(--paper) !important;
  border: 1px solid #3a3833 !important;
  background: transparent !important;
  border-radius: 0 !important;
  min-height: 26px;
  display: inline-flex; align-items: center;
}
.hub .nav-links a:hover { background: #26251f !important; border-color: #6f6b60 !important; }
.hub .nav-links a[aria-current="page"] {
  background: var(--wada-hi) !important;
  border-color: var(--wada-hi) !important;
  color: var(--ink) !important;
}
.hub .hub-link {
  background: transparent !important;
  color: var(--paper) !important;
  border-color: #4a473f !important;
  border-radius: 0 !important;
  min-height: 26px;
  display: inline-flex; align-items: center;
}
.hub .hub-link:hover { background: var(--paper) !important; color: var(--ink) !important; border-color: var(--paper) !important; }

.hub .bio-trigger {
  background: transparent !important;
  border-color: #4a473f !important;
  border-radius: 0 !important;
  color: var(--paper) !important;
  min-height: 28px;
}
.hub .bio-trigger:hover { border-color: var(--paper) !important; }
.hub .bio-trigger strong { color: var(--paper) !important; }
.hub .bio-trigger span   { color: #a9a496 !important; }
.hub .bio-trigger img   { border-radius: 0 !important; }

.hub .radarctl {
  background: var(--plate) !important;
  border-color: var(--paper) !important;
  color: var(--paper) !important;
  border-radius: 0 !important;
}
.hub .radarctl button {
  background: transparent !important;
  color: var(--paper) !important;
  border-color: #6b8296 !important;
  min-width: 28px; min-height: 28px;
}
.hub .radarctl button:hover { background: var(--paper) !important; color: var(--ink) !important; }

/* ============================================================================
   2. PANEL PLATES — hierarchy floor.
   Section headers were 8.5px gray on a hairline: invisible. Now they carry a
   hard 2px ink rule, a solid geometry square, and a 10.5px ink label.
   ========================================================================== */

.panel-h {
  font-size: 10.5px !important;
  letter-spacing: 0.14em !important;
  font-weight: 700 !important;
  color: var(--ink) !important;
  padding-bottom: 5px !important;
  margin-bottom: 8px !important;
  border-bottom: 2px solid var(--ink) !important;
}
.panel-h > span:first-child {
  display: inline-flex;
  align-items: center;
  gap: 7px;
}
/* Geometry as grammar: a filled square marks every section, the way the
   exhibition marks a division. It is redundant with the label, never alone. */
.panel-h > span:first-child::before {
  content: "";
  width: 9px; height: 9px;
  background: var(--plate);
  flex: none;
}
.panel-h .code {
  background: var(--ink) !important;
  color: var(--paper) !important;
  font-size: 8.5px !important;
  letter-spacing: 0.12em !important;
  font-weight: 700 !important;
  padding: 2px 6px !important;
  border-radius: 0 !important;
}
.panel-collapse {
  background: var(--ink) !important;
  color: var(--paper) !important;
  border-color: var(--ink) !important;
  border-radius: 0 !important;
  min-width: 24px; min-height: 24px;
}
.panel-collapse:hover { background: var(--plate) !important; border-color: var(--plate) !important; }

/* The aside itself is a paper field, not a white void. */
.aside { background: var(--paper) !important; }
.aside--right { border-left-color: var(--line-2) !important; }
.aside::-webkit-scrollbar-thumb { background: var(--line-2) !important; }

/* ============================================================================
   3. LAYER ROWS — grouped so 19 rows stop reading as a wall.
   Group plates are inserted in the markup; order is preserved.
   ========================================================================== */

.layer-row {
  padding: 5px 0 !important;
  border-top: 1px solid var(--line) !important;
  align-items: center;
}
/* Give the row a hard left rule on hover so the clickable area is obvious. */
.layer-row:hover { background: color-mix(in srgb, var(--plate) 5%, transparent); }
.layer-row .label-text { font-size: 12px !important; color: var(--ink) !important; font-weight: 600 !important; }
.layer-row .sub { color: var(--ink-2) !important; font-size: 10px !important; }
.layer-row .meta .n { font-size: 12.5px !important; }
.layer-row .meta .lab {
  color: var(--ink-2) !important;
  font-size: 8px !important;
  letter-spacing: 0.12em !important;
  font-weight: 700 !important;
}

/* Group header — a solid plate between runs of rows. */
.layer-group {
  display: flex;
  align-items: center;
  gap: 7px;
  margin: 10px 0 2px;
  padding: 3px 7px;
  background: var(--plate);
  color: var(--paper);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.layer-group::before {
  content: "";
  width: 6px; height: 6px;
  background: var(--wada-hi);
  flex: none;
}
.layer-group:first-child { margin-top: 0; }

/* ============================================================================
   4. OPS PANEL — colour-blocked status edges.
   The card carries its verdict on a solid edge, so the right rail can be
   scanned without reading a single number. Text label always accompanies it.
   ========================================================================== */

.ops-grid { gap: 8px !important; }
.ops-card {
  border: 1px solid var(--line-2) !important;
  border-left: 4px solid var(--line-2) !important;
  border-radius: 0 !important;
  background: var(--panel) !important;
  padding: 8px 10px 9px !important;
}
.ops-card-h { color: var(--ink-2) !important; font-size: 8.5px !important; letter-spacing: 0.14em !important; }
.ops-metric { color: var(--ink) !important; }
.ops-row { border-top-color: var(--line) !important; }
.ops-k { color: var(--ink-2) !important; }
.ops-chip {
  border-radius: 0 !important;
  border-color: var(--line-2) !important;
  background: var(--paper) !important;
  color: var(--ink-2) !important;
  /* WCAG 2.5.8 AA — these were 19px */
  min-height: 24px;
  display: inline-flex; align-items: center;
}
.ops-chip-btn:hover { border-color: var(--ink) !important; color: var(--ink) !important; }
.ops-chip-hot  { background: #fbeae8 !important; border-color: var(--neg) !important; color: var(--neg) !important; }
.ops-chip-warm { background: #fdf3e0 !important; border-color: #b6930c !important; color: #6f5a06 !important; }

.ops-card.good     { border-left-color: var(--accent) !important; }
.ops-card.moderate { border-left-color: #b6930c !important; }
.ops-card.sensitive,
.ops-card.unhealthy     { border-left-color: var(--neg) !important; }
.ops-card--flood.good     { border-color: var(--line-2) !important; border-left-color: var(--accent) !important; }
.ops-card--flood.moderate { border-color: #b6930c !important; border-left-color: #b6930c !important; }
.ops-card--flood.sensitive,
.ops-card--flood.unhealthy { border-color: var(--neg) !important; border-left-color: var(--neg) !important; }
.ops-card--air.good     { border-color: var(--line-2) !important; border-left-color: var(--accent) !important; }
.ops-card--air.moderate { border-color: #b6930c !important; border-left-color: #b6930c !important; }
.ops-card--air.sensitive,
.ops-card--air.unhealthy { border-color: var(--neg) !important; border-left-color: var(--neg) !important; }

/* ============================================================================
   5. 3D MODE MARKER
   #c9ff38 acid lime sat outside the palette and read as a debug flag. Mode
   identity now uses the structural plate + Cream Yellow, which still shouts
   but belongs to the system.
   ========================================================================== */

.map3d-bar-title {
  background: var(--ink) !important;
  border-color: var(--ink) !important;
  color: var(--paper) !important;
  border-radius: 0 !important;
}
.map3d-bar-title .pill {
  background: var(--wada-hi) !important;
  color: var(--ink) !important;
  border-radius: 0 !important;
}
.map3d-chip {
  background: var(--ink) !important;
  color: var(--paper) !important;
  border-color: var(--ink) !important;
  border-radius: 0 !important;
  min-height: 26px;
  display: inline-flex; align-items: center;
}
.map3d-chip:hover { background: var(--plate) !important; color: var(--paper) !important; }
.map3d-chip--exit { background: var(--wada-hi) !important; color: var(--ink) !important; }
.map3d-chip--exit:hover { background: var(--paper) !important; color: var(--ink) !important; }

/* ============================================================================
   6. LEGIBILITY FLOOR — microtype that used to sit at 2.3:1
   ========================================================================== */

/* Top strip vs Leaflet zoom control — they shared the map's top-left origin,
   so the first alert chip rendered *behind* the +/- buttons. Inset the strip
   past the control instead of moving either. */
@media (min-width: 721px) {
  .map-topstrip { left: 52px !important; }
}
@media (max-width: 720px) {
  .map-topstrip { left: 46px !important; }
}

/* The top band belongs to ONE stack: alerts + route time controls. Three other
   absolutely-positioned map chips were sharing it and rendering on top —
   #situationMapChip sat directly over the Leaflet zoom control and #mapOverlay
   over the last truck-class chip. Moved to a deliberate bottom stack so the
   primary instrument reads first and nothing overlaps anything.

   bottom: 44  .btn-3d                (left)
   bottom: 92  .situationMapChip      (left)   .mapOverlay (right)
   bottom: 140 .activeRoutesChip      (right, only when routes are restricted) */
#situationMapChip  { top: auto !important; bottom: 92px !important; left: 12px !important; right: auto !important; }
.map-overlay-top   { top: auto !important; bottom: 92px !important; right: 12px !important; }
.active-routes-chip{ top: auto !important; bottom: 140px !important; right: 12px !important; }

.leaflet-control-attribution,
.leaflet-control-attribution a {
  color: var(--ink-3) !important;
  /* Leaflet ships this link at 11px tall. It is a legal attribution and should
     still be reachable — pad the hit area without changing the type size. */
  min-height: 24px;
  display: inline-flex;
  align-items: center;
  padding: 0 4px;
}
.road-label {
  background: color-mix(in srgb, var(--paper) 88%, transparent) !important;
  color: var(--ink) !important;
  border: 1px solid var(--line-2) !important;
  font-size: 9.5px !important;
}
.leaflet-control-zoom a {
  background: var(--paper) !important;
  color: var(--ink) !important;
  border-color: var(--line-2) !important;
  border-radius: 0 !important;
}
.leaflet-control-zoom a:hover { background: var(--ink) !important; color: var(--paper) !important; }
.leaflet-bar { border: 1px solid var(--line-2) !important; box-shadow: none !important; }

/* Focus: a hard warm ring, visible on ink, paper and map alike. */
:where(.hub, .panel, .rtc, .map-topstrip, .ops-card) :focus-visible {
  outline: 2px solid var(--wada-hi) !important;
  outline-offset: 2px !important;
}
body :focus-visible { outline: 2px solid var(--plate); outline-offset: 2px; }

/* ============================================================================
   8. MOBILE HUB
   At 375px the bezel wrapped to ~265px: the eyebrow code broke over three
   lines and the title over four, pushing the map down to ~150px. On a phone
   the map is the point, so the chrome yields: the eyebrow and the publication
   stamp are provenance, not operation, and drop out; the status counts keep
   their own strip because they are the answer to "can I drive this road?".
   ========================================================================== */

@media (max-width: 880px) {
  .hub {
    flex-wrap: wrap !important;
    align-items: center;
    gap: 6px 8px !important;
    padding: 7px 10px !important;
  }
  /* Flatten .hub-left so its children become flex items of .hub and can be
     ordered into three compact rows instead of wrapping by accident. */
  .hub-left    { display: contents; }
  .hub-code    { display: none !important; }
  .hub-subtitle{ display: none !important; }
  .hub-meta    { display: none !important; }
  .nav-links   { display: none !important; }   /* duplicated by .hub-link */

  .disc--lg    { order: 1; width: 32px; height: 32px; font-size: 12px; }
  .hub-left > div:nth-child(2) { order: 2; flex: 1 1 0; min-width: 0; }
  .sidebar-toggle { order: 3; flex: none; }
  .hub-stats   { order: 4; flex: 1 1 100% !important; }
  .hub-actions { order: 5; flex: 1 1 100%; justify-content: flex-end; }

  /* One line, never three. The full title stays on desktop and in <title>. */
  .hub-title {
    font-size: 13px !important;
    line-height: 1.2;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  /* Status counts keep their own compact full-width strip — this is the answer
     to "can I drive this road right now?" */
  .hub-stats {
    border-left: 0 !important;
    border-top: 1px solid #3a3833;
    padding: 5px 0 0 !important;
    gap: 0 !important;
    display: flex !important;
    align-items: baseline;
  }
  .hub-stat { flex: 1 1 0; padding: 0 6px !important; border-right: 1px solid #3a3833 !important; }
  .hub-stat:first-child { padding-left: 0 !important; }
  .hub-stat:last-child { border-right: 0 !important; }
  .hub-stat .v { font-size: 16px !important; line-height: 1; }
  .hub-stat .l { font-size: 8px !important; line-height: 1.2; }

  .hub-actions { gap: 6px !important; }
  .nav-links a, .hub-link { font-size: 10px !important; min-height: 26px; padding: 4px 8px !important; }
  .bio-trigger strong { font-size: 10px !important; }
  .bio-trigger span   { display: none !important; }
  .bio-trigger img    { width: 22px; height: 22px; }
  .bio-trigger        { padding: 2px 7px 2px 2px !important; }

  /* Bottom stack. #situationMapChip and .map-overlay-top are hidden here on
     purpose: both restate facts the alert bar immediately above already
     carries in full ("5 police checkpoints active", "N restricted now"), and
     on a 375px screen they overlapped each other and the 3D button.
     .active-routes-chip is kept — it is the only place naming the routes
     currently restricted — and parked at the map's bottom edge. */
  #situationMapChip   { display: none !important; }
  .map-overlay-top    { display: none !important; }
  .btn-3d             { bottom: 44px !important; left: 12px !important; font-size: 11px !important; padding: 7px 10px !important; }
  .active-routes-chip { top: auto !important; bottom: 12px !important; left: 12px !important; right: 12px !important;
                        padding: 6px 9px !important; font-size: 10px !important; }
}

/* ============================================================================
   9. MOTION / PREFERENCE SAFETY
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  * { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; }
}
@media (prefers-contrast: more) {
  :root { --ink-3: #55524a; --line: #9d9887; --line-2: #6f6b60; }
}
