/* ===================================================================
   devmap.css — clean v0.3 consolidation (D34). One stylesheet; warm-
   paper tokens come from dev.css. Detail-LEFT / nav-RIGHT shell,
   legend, Google-style basemap tile + tilt. No accreted cruft.
   =================================================================== */
html, body { height: 100%; }
body { overflow: hidden; overscroll-behavior-y: none; } /* META-B: block Android document pull-to-refresh reloading the map */

.dev-shell { display: grid; grid-template-rows: calc(56px + env(safe-area-inset-top, 0px)) 1fr; height: 100vh; height: 100dvh; } /* META-B dvh; P-fix: header row grows by the notch inset */
/* P-fix (mobile safe-area): viewport-fit=cover draws the chrome edge-to-edge UNDER the notch +
   rounded corners; pad the top header so its content (logo / sign-in) clears them and stays readable. */
#dev-header { padding: env(safe-area-inset-top, 0px) env(safe-area-inset-right, 0px) 0 env(safe-area-inset-left, 0px); box-sizing: border-box; }
/* v0.13.0 — overlay architecture (D45). The map fills the shell; rail
   and panel float as fixed overlays on top. Map never resizes from the
   accordion — the white-space bug from grid-template-columns animation
   is gone by construction. Lens (#dev-detail) already uses this pattern
   on the left; now both sides are consistent. */
/* META-A (mobile/iPad arc) — suppress hover-only popups where the primary
   pointer cannot hover (finger). (hover:none) is FALSE on an iPad trackpad/
   Pencil, so those keep their hover popups. ALL hover popups (project / parcel
   / community / area) use the .dev-hover-pop container (map.js + area-panel.js),
   so suppressing the container hides their inner .dev-hp content too. A tap-shown
   popup adds .dev-hover-pop--tap to opt out (P2.1 area-tap). Do NOT also suppress
   .dev-hp here — its container carries --tap but the inner .dev-hp does not, so
   that clause would blank the tapped popup's own content. */
@media (hover: none) {
  .dev-hover-pop:not(.dev-hover-pop--tap) { display: none !important; }
}
.dev-main { position: relative; min-height: 0; }

/* D80.C14 (C5) — Skip-link for keyboard a11y. Hidden until focused;
   jumps to #dev-nav so screen-reader / keyboard users skip past the
   map canvas + Mapbox controls + 95+ photo/event cards that come
   before the navigation panel. Per WCAG 2.4.1. */
.dev-skiplink {
  position: absolute;
  top: -100px;
  left: 8px;
  z-index: 10001;
  padding: 10px 16px;
  background: var(--ink-1);
  color: var(--surface-1);
  text-decoration: none;
  font: 500 13px/1 var(--font-body);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  transition: top var(--duration-fast) var(--ease-out);
}
.dev-skiplink:focus-visible {
  top: 8px;
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}
#dev-map { position: absolute; inset: 0; overflow: hidden; background: var(--bg-subtle); }
.mapboxgl-map { position: absolute; inset: 0; }

/* Rail: 60px (v0.13.1 spec), pinned to the right edge, sits above the
   panel so the toggle stays clickable when the panel is collapsed. The
   inner .dev-rail (in dev.css) carries the background + border-left;
   we just position the wrapper here. */
#dev-rail {
  position: absolute; top: 0; right: 0; bottom: 0;
  width: 60px; display: flex; z-index: 6;
}
#dev-rail .dev-rail { width: 60px; }

/* Panel: 360px wide, pinned right of the rail. Sliding off-screen via
   transform — map underneath is always the full viewport. Buffer of
   8px past the rail width so the leading edge clears it cleanly. */
#dev-nav {
  position: absolute; top: 0; right: 60px; bottom: 0;
  /* D78.T1a — was 360px hardcoded, asymmetric with #dev-detail's
     clamp(420px, 32vw, 540px). The Today list + photo strip needed
     more horizontal room; the photo strip's scrollbar was always
     visible at 360 because two 160px cards + gap couldn't fit.
     Now matches the project-detail panel width. */
  width: clamp(420px, 32vw, 540px); overflow-x: hidden; overflow-y: auto;
  border-left: 1px solid var(--border); background: var(--bg-paper);
  z-index: 5;
  transform: translateX(0);
  transition: transform var(--duration-slow) var(--ease-in-out),
    opacity var(--duration-base) var(--ease-out);
}
#dev-nav.nav-switching { opacity: 0; }
#dev-nav .panel { border: none; border-radius: 0; height: auto; }

/* D76.B — Mobile panel layout fix. At < 540vw, the default 360px
 * panel + 60px rail = 420px need, so a 375vw phone clips the panel
 * by 45px on the left (Phase 1 audit found x=-44). Constrain to
 * available width so the panel never extends off-canvas. The 8px
 * (--space-2) buffer keeps it clear of the rail's leading edge.
 * Per HIG §5.2 #5.4 §9.4 — mobile panel never renders with x < 0. */
@media (max-width: 540px) {
  #dev-nav {
    /* F-5: was calc(100vw - 60px - 8px) → left an 8px map sliver between
     * the panel's far edge and the viewport. The panel is right-anchored at
     * the rail, so dropping the 8px buffer makes it meet the left edge
     * cleanly (no orphan sliver) while still clearing the 60px rail. */
    width: min(360px, calc(100vw - 60px));
  }
}

.dev-main.nav-collapsed #dev-nav {
  transform: translateX(calc(100% + 68px));
  border-left: none;
}

/* Push Mapbox's bottom-right control cluster left of the rail so zoom +
   compass + geolocate + fullscreen + attribution don't sit under the
   overlay. When the panel is OPEN, anchor the controls just left of
   the panel's leading edge (60 rail + 360 panel + 16 gap = 436px).
   When the panel is COLLAPSED, slide them back next to the rail
   (60 + 8 = 68px). The transition matches the panel's .28s slide so
   they move together. */
.mapboxgl-ctrl-bottom-right {
  right: 436px !important;
  transition: right var(--duration-slow) var(--ease-in-out);
}
.dev-main.nav-collapsed .mapboxgl-ctrl-bottom-right {
  right: 68px !important;
}

/* v0.13.3 — thin custom scrollbar on panel-internal scroll containers.
   Native 16px bar reads as out-of-family with the rest of the chrome;
   6px in --border-strong, transparent track, scrollbar-width:thin for
   FF. Webkit and Gecko both honored. Buys ~10px of usable content
   width back. */
#dev-nav,
#dev-detail .dev-detail-scroll,
.admin-view {
  scrollbar-width: thin;
  scrollbar-color: var(--border-strong) transparent;
}
#dev-nav::-webkit-scrollbar,
#dev-detail .dev-detail-scroll::-webkit-scrollbar,
.admin-view::-webkit-scrollbar {
  width: 6px; height: 6px;
}
#dev-nav::-webkit-scrollbar-track,
#dev-detail .dev-detail-scroll::-webkit-scrollbar-track,
.admin-view::-webkit-scrollbar-track {
  background: transparent;
}
#dev-nav::-webkit-scrollbar-thumb,
#dev-detail .dev-detail-scroll::-webkit-scrollbar-thumb,
.admin-view::-webkit-scrollbar-thumb {
  background: var(--border-strong);
  border-radius: 3px;
}
#dev-nav::-webkit-scrollbar-thumb:hover,
#dev-detail .dev-detail-scroll::-webkit-scrollbar-thumb:hover,
.admin-view::-webkit-scrollbar-thumb:hover {
  background: var(--text-faint);
}
.dev-rail-accordion {
  position: absolute; left: 0; bottom: calc(10px + env(safe-area-inset-bottom, 0px)); width: 60px; height: 44px; /* P3: 44px touch target; P6: clear the home indicator in standalone PWA mode */
  display: flex; align-items: center; justify-content: center;
  background: var(--bg-card); border: none;
  border-top: 1px solid var(--border);
  color: var(--text-muted); font: 600 17px/1 var(--font-body);
  cursor: pointer;
}
.dev-rail-accordion:hover { color: var(--text); background: var(--bg-subtle); }

/* left detail (Project Lens) slides over the map — map never resizes.
   D65.B — width now responsive: 420px minimum, 540px maximum, scaling
   with viewport between. Fixes the tab-bar horizontal-scroll issue on
   6/7-tab projects (was: hard-coded 420px → tabs overflowed by 53–147px). */
#dev-detail {
  position: absolute; top: 0; left: 0; bottom: 0;
  width: clamp(420px, 32vw, 540px);
  background: var(--bg-card); border-right: 1px solid var(--border);
  box-shadow: var(--shadow-lg); transform: translateX(-100%);
  transition: transform var(--duration-slow) var(--ease-in-out); z-index: 6;
  display: flex; flex-direction: column; overflow: hidden;
}
/* D68.14 — Mobile: panel reserves room for the right rail.
   F-5: was calc(100vw - 52px) — but the rail is 60px wide, so the panel's
   right edge ran 8px UNDER the rail, and the rail (z-6, above) clipped the
   project card's right edge. Reserve the full 60px so the panel meets the
   rail's leading edge with no underlap. */
@media (max-width: 480px) {
  #dev-detail {
    width: calc(100vw - 60px);
  }
}
/* P4 (mobile/iPad arc) — the 541–1023px dead zone. #dev-detail (left) and
   #dev-nav (right) are both clamp(420,32vw,540) overlays, so at e.g. 768px they
   overlap in the middle and cover the whole map. Collapse the right nav while a
   project detail is open so one panel + a usable map strip remain (the desktop
   floating layout takes over at >=1024; ≤480 already full-widths the detail). */
@media (min-width: 541px) and (max-width: 1023px) {
  .dev-main.detail-open #dev-nav { transform: translateX(calc(100% + 68px)); }
}
.dev-main.detail-open #dev-detail { transform: translateX(0); }

/* D80.E9 — Floating panels at ≥1024vw. Adds a 16px gap around both
   the project detail panel and the Today/right panel so the map peeks
   through at top, sides, and bottom (Figma canvas pattern). Below
   1024vw, layout stays edge-pinned (mobile + tablet portrait already
   has different concerns — see D76.B handling at 540vw).
   Border treatment switches from a single edge stroke to a full
   1px border + 12px radius, making each panel read as a deliberate
   card floating over the basemap.
   Mapbox controls bumped right by 16px to clear the new gap. Slide-
   off transforms extended by 16px so closed/collapsed panels fully
   clear the viewport (otherwise the 16px-from-edge anchor would
   leave a sliver visible).  */
@media (min-width: 1024px) {
  #dev-detail {
    top: 16px;
    left: 16px;
    bottom: 16px;
    border: 1px solid var(--border);
    border-radius: 12px;
    /* slide off-screen accounting for the 16px left anchor */
    transform: translateX(calc(-100% - 16px));
  }
  .dev-main.detail-open #dev-detail { transform: translateX(0); }
  #dev-nav {
    top: 16px;
    right: 76px; /* 60 rail + 16 gap */
    bottom: 16px;
    border: 1px solid var(--border);
    border-radius: 12px;
  }
  .dev-main.nav-collapsed #dev-nav {
    /* slide further to clear the 16px right anchor (was 100% + 68) */
    transform: translateX(calc(100% + 84px));
  }
  .mapboxgl-ctrl-bottom-right {
    /* D82.R4.3 fix — was static 452px (=60 rail + 360 old-panel + 16
       gap + 16 D80.E9 gap). With Today panel widened to clamp(420,
       32vw, 540) post-D78.T1a, the panel's left edge moved further
       inward at wider viewports — and the controls (at static 452)
       got covered. Use calc so the offset always tracks the actual
       panel width: rail (60) + gap (16) + panel + buffer (8). */
    right: calc(60px + 16px + clamp(420px, 32vw, 540px) + 8px) !important;
  }
  .dev-main.nav-collapsed .mapboxgl-ctrl-bottom-right {
    right: 84px !important; /* was 68; +16 for the floating gap */
  }
}

/* ═══════════════════════════════════════════════════════════════════════
   MOB2 (owner 2026-06-11) — phone app-shell: no header, bottom tab bar,
   panels as full sheets, map-first boot. Phones = ≤540px (the existing
   phone band; the P4 iPad dead-zone starts at 541px so the two regimes
   never overlap). Desktop + iPad are untouched by construction.

   The bar IS the existing #dev-rail, re-laid — NOT a new component. Four
   modules inject/observe into #dev-rail (ui.js admin + active-state sync,
   nav-registry ordering/owner-gating, your-halifax + headroom injection
   observers) and freshness-stamp .click()s the admin button — restyling
   the node preserves every contract; replacing it forks them all.

   z-order at ≤540: detail sheet 6 < nav sheet 8 (a tab tap must surface
   over an open project) < bar 9 (sheets slide BEHIND the bar) < loader
   9000 (dev-loader.css) < skip-link 10001.
   ═══════════════════════════════════════════════════════════════════════ */
@media (max-width: 540px) {
  .dev-shell {
    /* MOB2.VV (2026-06-12): size the phone shell to the ACTUALLY-VISIBLE area.
       --app-height is set by viewport.js from window.visualViewport.height —
       the only signal that subtracts an OVERLAY toolbar (the iOS Messages
       SFSafariViewController bottom bar) that 100dvh/100vh do NOT. The 100svh
       fallback is the toolbar-SHOWN (smallest) height, so even before JS runs
       the shell can't extend under the chrome; 100vh is the last-ditch fallback
       for engines without svh. Desktop/iPad (>540px) keep line-9's 100dvh. */
    height: 100vh;
    height: 100svh;
    height: var(--app-height, 100svh);
    /* Home-indicator inset is meaningful ONLY in the installed PWA (added in the
       display-mode:standalone block below). In Safari and the in-app browser
       env(safe-area-inset-bottom) is the WRONG signal (it measures the home
       indicator, not the in-app toolbar, and reads ~0 in browser states), so
       the base bar height carries no inset — the visualViewport height already
       lands the bar at the true bottom. */
    --hdm-bar-h: 56px;
    grid-template-rows: 1fr; /* header row removed WITH the header — else a blank 56px band */
  }
  #dev-header { display: none; } /* still painted by ui.js init — auth.js / search-bar / ticker wiring stays inert (search + ticker are already hidden at this width) */

  /* ── Bottom tab bar (the restyled right rail) ─────────────────────── */
  #dev-rail {
    top: auto; left: 0; right: 0; bottom: 0;
    width: 100%; height: var(--hdm-bar-h);
    z-index: 9;
  }
  #dev-rail .dev-rail {
    width: 100%; height: 100%;
    flex-direction: row; align-items: stretch; justify-content: space-around;
    padding: 4px 8px; /* bottom home-indicator inset added in standalone only (below) */
    box-sizing: border-box;
    border-left: none; border-top: 1px solid var(--border);
    gap: 0;
  }
  .dev-rail-icon {
    flex: 1 1 0; max-width: 110px; height: auto; min-height: 48px;
  }
  /* active accent rotates left-edge → top-edge for the horizontal bar */
  .dev-rail-icon.active { box-shadow: inset 0 3px 0 var(--gold); }
  .dev-rail-sep { display: none; } /* vertical-rail group dividers don't translate to a tab bar */
  /* Hidden, NOT removed: ui.js, your-halifax.js and headroom-mount.js all
     programmatically .click() this to expand a collapsed nav — display:none
     keeps those calls working. The tab-toggle gesture replaces it visually. */
  .dev-rail-accordion { display: none; }

  /* ── Panels become full sheets above the bar ──────────────────────── */
  #dev-nav {
    top: 0; left: 0; right: 0; bottom: var(--hdm-bar-h);
    width: 100%; max-width: none;
    border-left: none;
    padding-top: env(safe-area-inset-top, 0px); /* content clears the notch (no header paints it now) */
    box-sizing: border-box;
    z-index: 8; /* over an open project sheet — a tab tap must surface its panel */
  }
  /* collapse = slide DOWN behind the bar (replaces the desktop translateX) */
  .dev-main.nav-collapsed #dev-nav {
    transform: translateY(calc(100% + 24px));
  }
  #dev-detail {
    top: 0; left: 0; right: 0; bottom: var(--hdm-bar-h);
    width: 100%;
    padding-top: env(safe-area-inset-top, 0px);
    box-sizing: border-box;
    border-right: none;
  }

  /* ── Map chrome above the bar ─────────────────────────────────────── */
  .mapboxgl-ctrl-bottom-right {
    right: 8px !important;
    bottom: calc(var(--hdm-bar-h) + 4px);
  }
  .dev-main.nav-collapsed .mapboxgl-ctrl-bottom-right { right: 8px !important; }
  .mapboxgl-ctrl-bottom-left { bottom: calc(var(--hdm-bar-h) + 4px); }
  /* pinch-zoom is native on touch — the +/- buttons are redundant chrome.
     id-scoped: mapbox-gl.css's .mapboxgl-ctrl-group button (0,1,1) outranks a
     bare class here, so a single-class selector silently loses. */
  #dev-map .mapboxgl-ctrl-zoom-in, #dev-map .mapboxgl-ctrl-zoom-out { display: none !important; }
  /* P3 touch-target floor on the remaining map buttons (Mapbox default 29px).
     The 3d-toggle needs the extra class: the base 29px #dev-map .dev-3d-toggle
     rule sits LATER in this file, so equal specificity would lose to it. */
  #dev-map .mapboxgl-ctrl-group button, #dev-map .mapboxgl-ctrl.dev-3d-toggle button {
    width: 44px; height: 44px;
  }
}
/* Standalone PWA: the status bar is black-translucent (white text) and no
   header paints behind it anymore — a soft dark scrim keeps the clock and
   battery legible over the light map. Browser-mode Safari paints its own
   chrome, so this is scoped to the installed app. */
@media (max-width: 540px) and (display-mode: standalone) {
  .dev-main::before {
    content: "";
    position: absolute; top: 0; left: 0; right: 0;
    height: calc(env(safe-area-inset-top, 0px) + 6px);
    background: linear-gradient(to bottom, rgba(20, 20, 20, 0.4), transparent);
    z-index: 4; pointer-events: none;
  }
  /* MOB2.VV: the home-indicator inset is real ONLY here (installed PWA, no
     browser chrome below). Grow the bar by it and pad its content above it,
     so icons clear the indicator and the bar background covers it. In Safari /
     the in-app browser this block doesn't apply (display-mode: browser), so
     no inset is double-counted against the visualViewport height. */
  .dev-shell { --hdm-bar-h: calc(56px + env(safe-area-inset-bottom, 0px)); }
  #dev-rail .dev-rail { padding-bottom: calc(4px + env(safe-area-inset-bottom, 0px)); }
}

#dev-detail .dev-detail-bar {
  display: flex; align-items: center; padding: 8px 14px;
  border-bottom: 1px solid var(--border); background: var(--bg-card); flex: 0 0 auto;
  gap: 12px;
}
#dev-detail .dev-detail-close {
  font: 500 var(--text-sm)/1 var(--font-body); color: var(--text-muted);
  background: transparent; border: none; cursor: pointer;
  padding: 4px 8px; border-radius: var(--radius-sm);
}
#dev-detail .dev-detail-close:hover { color: var(--text); background: var(--bg-subtle); }

/* D82.iterate — Stage label in the close bar. The top bar carries
   a coloured fill matched to the project's stage (proposed/approved/
   construction/completed/inactive) — the panel's very first line
   becomes the stage signal. The label sits to the right of Close,
   bold, white-on-stage-colour. Map legend colours stay the single
   source (DevConfig.STAGES); CSS just mirrors them here. */
#dev-detail .dev-detail-stage-label {
  margin-left: auto;
  font: 700 var(--text-sm)/1 var(--font-display);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #fff;
  padding: 5px 11px;
  border-radius: var(--radius-pill);
  background: var(--stage-color, var(--text-muted));
  white-space: nowrap;
}
#dev-detail[data-stage="proposed"] {
  --stage-color: #7c6cae;
}
#dev-detail[data-stage="approved"] {
  --stage-color: #2563eb;
}
#dev-detail[data-stage="construction"] {
  --stage-color: var(--stage-construction);
}
#dev-detail[data-stage="construction"] .dev-detail-stage-label {
  /* the gold reads better with ink text */
  color: #1f1408;
}
#dev-detail[data-stage="completed"] {
  --stage-color: #16a34a;
}
#dev-detail[data-stage="inactive"] {
  --stage-color: #9aa0a6;
}
/* D87.2.6.redo2 (P2.3) — Parcel close-bar pill. Pre-fix the parcel
 * data-stage state had no --stage-color defined, so the pill fell
 * back to var(--text-muted) (grey). Lloyd flagged this as the actual
 * target: the pill on the same horizontal line as the close button,
 * reading "Parcel" in grey, was the thing he wanted brighter.
 * Apply the multi-unit teal family — same colour as the parcel
 * polygons on the map — so the bar reads "this is a parcel" in
 * the consistent visual language. Use #5eead4 (vivid teal-300) for
 * the pill fill so dark text reads cleanly. */
#dev-detail[data-stage="parcel"] {
  --stage-color: #5eead4;
}
#dev-detail[data-stage="parcel"] .dev-detail-stage-label {
  color: #0f3030;
}
/* Bar background gets a soft tint of the stage colour + a thick
   bottom border in full stage colour, so the band reads clearly
   without overpowering the panel content. */
#dev-detail[data-stage] .dev-detail-bar {
  border-bottom: 3px solid var(--stage-color, var(--border));
  background: color-mix(in srgb, var(--stage-color, transparent) 12%, var(--bg-card));
}
/* D77.T4 — `.dev-detail-sources-toggle` rules removed alongside the
   checkbox markup (citation popovers replace it). */
#dev-detail .dev-detail-scroll { overflow-y: auto; flex: 1 1 auto; }
#dev-detail .dev-detail-scroll .panel { border: none; border-radius: 0; height: auto; }

/* v0.13.5.B (D45) — sticky-footer CTA sits as a sibling of the
   scroll container so it stays visible regardless of scroll depth.
   Border + paper-toned background lift it off the scrolling body. */
#dev-detail .dev-detail-footer {
  flex: 0 0 auto;
  background: var(--bg-paper);
  border-top: 1px solid var(--border);
}
.dev-lens-cta {
  padding: 14px 18px; display: flex; flex-direction: column; gap: 8px;
}
.dev-lens-cta .btn {
  width: 100%; text-align: center;
}

/* v0.13.5.B — header credits line (developer · architect, promoted
   from the Attribution section). Sits under panel-meta. */
.panel-credits {
  font: 500 11px/1.4 var(--font-body);
  color: var(--text-muted); margin-top: 4px;
  letter-spacing: 0.01em;
}

/* v0.13.5.B — Sources & freshness section. One row per source, with a
   small coloured dot driven by age (mirrors the Admin Projects tab). */
.dev-src-list { display: flex; flex-direction: column; gap: 8px; padding: 4px 0; }
.dev-src-row {
  display: grid;
  grid-template-columns: 10px 1fr auto auto;
  gap: 10px; align-items: center;
  font: 500 12px/1.3 var(--font-body);
}
.dev-src-dot {
  width: 7px; height: 7px; border-radius: 50%;
  box-shadow: 0 0 0 1px rgba(0,0,0,0.04);
}
.dev-src-age { color: var(--text-muted); }
.dev-src-count {
  color: var(--text-muted); font-variant-numeric: tabular-nums;
  min-width: 28px; text-align: right;
}

/* v0.13.5.B — Attribute resolution table with conflicts inline.
   <details>/<summary> for the expand-on-click affordance (no JS).
   Compact ⚠ icon on the head row when sources disagree. */
.dev-attr-list { display: flex; flex-direction: column; gap: 2px; padding: 4px 0; }
.dev-attr-row {
  border-radius: var(--radius-sm);
  background: transparent;
  transition: background-color var(--duration-fast) var(--ease-out);
}
.dev-attr-row[open],
.dev-attr-row:hover { background: var(--bg-subtle); }
.dev-attr-head {
  display: grid;
  grid-template-columns: 1fr auto auto 16px;
  gap: 10px; align-items: center;
  padding: 6px 10px;
  font: 500 12px/1.3 var(--font-body);
  cursor: pointer; list-style: none;
}
.dev-attr-head::-webkit-details-marker { display: none; }
.dev-attr-name { color: var(--text); }
.dev-attr-value { color: var(--text); }
.dev-attr-source { color: var(--text-muted); }
.dev-attr-date { color: var(--text-muted); }
.dev-attr-warn {
  color: var(--accent-gold); font-size: 13px;
  display: inline-flex; align-items: center; justify-content: center;
}
.dev-attr-head.has-conflict .dev-attr-value::after {
  /* subtle hint that the visible value isn't the only answer */
  content: " *"; color: var(--accent-gold); font-weight: 600;
}
.dev-attr-sibs {
  padding: 0 10px 8px 10px; display: flex; flex-direction: column; gap: 4px;
}
.dev-attr-sib {
  display: grid;
  grid-template-columns: 1fr auto auto;
  gap: 10px; padding: 4px 0 4px 16px;
  font: 500 11px/1.3 var(--font-body);
  color: var(--text-muted);
  border-left: 2px solid var(--border);
}

/* legend (generated from DevConfig — single source). Spec-faithful
   (handover §2.7/§3.1): one .map-overlay-style panel, bottom-left.
   The Satellite "Layers" tile is gone (D40), so the legend drops to
   just above the compact attribution — no overlap. Open by default;
   right-edge chevron collapses it to a compact chip (v0.4.2). */
.dev-legend {
  position: absolute; left: 12px; bottom: 92px; z-index: 4;
  pointer-events: auto;
  background: rgba(250,250,249,0.86); backdrop-filter: blur(8px) saturate(180%); -webkit-backdrop-filter: blur(8px) saturate(180%);
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  box-shadow: var(--shadow-sm); padding: 9px 12px; font: 11px/1.3 var(--font-body);
}
/* MOB2 (owner 2026-06-11): hide the legend entirely on phones — even compacted
   (170×150) it ate map space on a small viewport, and the phone surface is a
   demo surface for a sole user. Desktop + iPad keep it (Lloyd keeps it visible
   there by design, no collapse — ui.js renderLegend comment). Map state is
   unaffected: multi-unit defaults live in map.js _multiUnitState and the API
   floors min_units at 4, so the layer renders identically with no legend
   mounted. The element still mounts (renderLegend is unconditional) so a
   resize/rotation across 640px restores it automatically. */
@media (max-width: 640px) {
  .dev-legend { display: none; }
}
.dev-legend-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; margin-bottom: 6px;
}
.dev-legend-title {
  font-size: 9px; font-weight: 700; letter-spacing: .07em;
  text-transform: uppercase; color: var(--text-muted);
}
.dev-legend-row { display: flex; align-items: center; gap: 7px; padding: 2px 6px; color: var(--text); border-radius: 3px; transition: background var(--duration-fast) var(--ease-out); margin: 0 -6px; }
.dev-legend-row:hover { background: rgba(255,255,255,0.06); }
.dev-legend-row.is-active { background: rgba(212,168,75,0.18); color: #d4a84b; font-weight: 600; }
.dev-legend-sw { width: 11px; height: 11px; border-radius: 3px; border: 1px solid rgba(0,0,0,.15); }

/* D85.3 — Multi-unit filter section. Quietly indented under the stage
 * block; chips use the same monospace-feel rhythm as the legend rows. */
.dev-legend-head--mu {
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid var(--border);
}
.dev-legend-vis-toggle {
  font: 9px/1.1 var(--font-body); font-weight: 600;
  letter-spacing: .04em;
  padding: 2px 6px; border-radius: 3px;
  border: 1px solid var(--border); background: rgba(255,255,255,0.6);
  color: var(--text); cursor: pointer;
  transition: background var(--duration-fast) var(--ease-out),
              color var(--duration-fast) var(--ease-out);
}
.dev-legend-vis-toggle:hover { background: rgba(255,255,255,0.95); }
.dev-legend-vis-toggle[data-visible="0"] { color: var(--text-faint); background: transparent; }
.dev-legend-mu-body { gap: 6px; display: flex; flex-direction: column; }
.dev-legend-mu-chiprow, .dev-legend-mu-kindrow {
  display: flex; gap: 4px; margin: 4px -6px 0;
  padding: 0 6px;
}
.dev-legend-mu-chip {
  font: 10px/1.1 var(--font-body); font-weight: 600;
  letter-spacing: .03em;
  padding: 3px 7px; border-radius: 3px;
  border: 1px solid var(--border); background: rgba(255,255,255,0.5);
  color: var(--text-muted); cursor: pointer;
  transition: all var(--duration-fast) var(--ease-out);
}
.dev-legend-mu-chip:hover {
  background: rgba(255,255,255,0.95); color: var(--text);
}
.dev-legend-mu-chip.is-active {
  background: #3d8e8e; color: #fff;
  border-color: #2a6a6a;
}
.dev-legend-mu-chip--kind {
  /* Lighter visual weight for kind chips (default-both, toggles off) */
  flex: 1;
}
.dev-legend-mu-chip--kind:not(.is-active) {
  background: transparent;
  border-style: dashed;
}

/* D92.F2 — Community (city-overview) legend section. Same head styling
   as multi-unit (gold-ramp + teal-parcel), but read-only (no chips). */
.dev-legend-head--cm {
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid rgba(255, 255, 255, 0.06);
}
.dev-legend-cm-body { gap: 4px; display: flex; flex-direction: column; }
.dev-legend-row--ramp,
.dev-legend-row--teal {
  cursor: help;  /* no click action — explainer rows only */
}
.dev-legend-ramp {
  width: 24px; height: 11px;
  border-radius: 3px;
  border: 1px solid rgba(0,0,0,.15);
  flex-shrink: 0;
}

/* ════════════════════════════════════════════════════════════════
   DEVMAP-CHROME · S2 — Map legend → "Pipeline · by stage" glass card
   (#1259). Flag-gated under .chrome-glass; the classic legend above is
   untouched (these scoped rules come later in the file AND out-rank the
   bare .dev-legend selectors). The per-row count + distribution-bar DOM
   is built by ui.js renderLegend ONLY when the flag is on. Swatches keep
   their map colours so the legend stays a faithful key to the pins; gold
   energy is reserved for the Under-construction row (it owns gold on the
   map). README §3 + owner decisions (light base, gold=energy, AA scrim).
   ════════════════════════════════════════════════════════════════ */
.chrome-glass .dev-legend {
  background: var(--glass-fill-text);          /* text zone → AA over any basemap */
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-border);
  border-radius: var(--glass-radius);
  box-shadow: var(--shadow-glass);
  padding: 11px 13px 12px;
  min-width: 190px;
}
.chrome-glass .dev-legend-head { margin-bottom: 9px; gap: 12px; }
.chrome-glass .dev-legend-title {
  color: var(--glass-ink-2);
  font-size: 9.5px; font-weight: 700; letter-spacing: .1em;
}
.chrome-glass .dev-legend-total {
  font: 600 11px/1 var(--font-mono);
  font-variant-numeric: tabular-nums;
  color: var(--glass-ink); letter-spacing: 0;
}
/* stage rows: swatch · label · distribution bar (flex) · count */
.chrome-glass .dev-legend-body .dev-legend-row {
  gap: 9px; padding: 4px 8px; margin: 0 -8px;
  border-radius: 7px; color: var(--glass-ink-2);
}
.chrome-glass .dev-legend-body .dev-legend-row:hover { background: rgba(20,16,8,0.05); }
.chrome-glass .dev-legend-sw {
  width: 10px; height: 10px; border-radius: 3px;
  border: 1px solid rgba(20,16,8,0.18); flex: 0 0 auto;
}
.chrome-glass .dev-legend-label {
  font-size: 11.5px; color: var(--glass-ink);
  white-space: nowrap; flex: 0 0 auto;
}
.chrome-glass .dev-legend-bar {
  flex: 1 1 auto; min-width: 24px; height: 3px;
  background: rgba(20,16,8,0.08); border-radius: 2px; overflow: hidden;
}
.chrome-glass .dev-legend-bar-fill {
  height: 100%; border-radius: 2px; background: var(--glass-ink-faint);
}
.chrome-glass .dev-legend-count {
  font: 600 11px/1 var(--font-mono);
  font-variant-numeric: tabular-nums;
  color: var(--glass-ink); flex: 0 0 auto;
  min-width: 28px; text-align: right;
}
/* Under construction owns the gold on the map — emphasize its row.
   Text stays near-black bold for AA; gold comes from the wash + ring +
   glow + bar-fill + the gold swatch (owner decision 4: contrast guaranteed). */
.chrome-glass .dev-legend-row[data-stage="construction"] {
  background: rgba(212, 168, 75, 0.16);
  box-shadow: inset 0 0 0 1px rgba(212, 168, 75, 0.32),
              0 0 12px rgba(212, 168, 75, 0.18);
}
.chrome-glass .dev-legend-row[data-stage="construction"] .dev-legend-label,
.chrome-glass .dev-legend-row[data-stage="construction"] .dev-legend-count {
  color: var(--glass-ink); font-weight: 700;
}
.chrome-glass .dev-legend-row[data-stage="construction"] .dev-legend-bar-fill {
  background: var(--gold-active);
}


/* 2D⇄3D state toggle (bottom-right nav cluster) — single labelled
   button, Google/Apple idiom, replaces the old ▲▼ stepper (v0.5.2) */
#dev-map .dev-3d-toggle button {
  width: 29px; height: 29px; font: 700 11px/1 var(--font-body);
  letter-spacing: .03em; background: #fff; color: #444;
  border: none; cursor: pointer;
}
#dev-map .dev-3d-toggle button:hover { background: #f5f5f5; color: #111; }
#dev-map .dev-3d-toggle button[aria-pressed="true"] {
  color: var(--accent-gold-hover);
}

/* D82.R4.3 satellite mode reverted — .dev-mode-toggle CSS removed. */

/* Mapbox controls — Google-ish: white, ~2px radius, soft shadow */
#dev-map .mapboxgl-ctrl-group {
  border-radius: 2px; box-shadow: 0 1px 4px rgba(0,0,0,.3); border: none;
}

/* ════════════════════════════════════════════════════════════════
   DEVMAP-CHROME · S1 — Map controls → warm-paper glass cluster (#1259)
   Flag-gated (body.chrome-glass). Replaces the stock flat-white 2px
   buttons + harsh 0 1px 4px shadow with the system glass material.
   CSS-ONLY — zero behavior change. The .chrome-glass prefix both gates
   AND out-ranks mapbox-gl.css's .mapboxgl-ctrl-group button (0,1,1).
   ════════════════════════════════════════════════════════════════ */
.chrome-glass #dev-map .mapboxgl-ctrl-group,
.chrome-glass #dev-map .dev-3d-toggle {
  border-radius: var(--glass-radius-chip);
  background: var(--glass-fill);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-border);
  box-shadow: var(--shadow-glass);
  overflow: hidden;
}
.chrome-glass #dev-map .mapboxgl-ctrl-group button,
.chrome-glass #dev-map .dev-3d-toggle button {
  background: transparent;
  color: var(--glass-ink-2);
  transition: background var(--duration-fast) var(--ease-out),
              color var(--duration-fast) var(--ease-out);
}
.chrome-glass #dev-map .mapboxgl-ctrl-group button + button {
  border-top: 1px solid rgba(20, 16, 8, 0.08);   /* hairline zoom-stepper divider */
}
.chrome-glass #dev-map .mapboxgl-ctrl-group button:hover,
.chrome-glass #dev-map .dev-3d-toggle button:hover {
  background: rgba(20, 16, 8, 0.05);
  color: var(--glass-ink);
}
/* 2D⇄3D toggle → glass pill; gold = the active (3D) dimension (energy) */
.chrome-glass #dev-map .dev-3d-toggle button[aria-pressed="true"] {
  background: var(--gold-active);
  color: #16130c;
  box-shadow: var(--glass-highlight);
}

/* ════════════════════════════════════════════════════════════════
   DEVMAP-CHROME · S3 — Right icon rail → warm-paper glass (#1259)
   Flag-gated (.chrome-glass) + DESKTOP/iPad ONLY (min-width:541px) so the
   shipped MOB2 ≤540 bottom-bar reuse of #dev-rail stays byte-identical.
   The rail is RESKINNED IN PLACE (edge-flush, not floated): the holistic
   16px-gutter float is the deferred layout-law pass — floating here would
   ripple into the controls offset, the panel positioning, the nav-toggle,
   and the HUD top:88px assumption (S4, not yet built). CSS-ONLY — every
   #dev-rail .click()/observer contract is untouched (nav-registry reconcile,
   [data-rail-jump], owner-gate hidden, ui.js active-sync, the 4 injecting
   modules, freshness-stamp admin click): we only restyle existing classes.
   Canonical composition L131-140 (Refined Map - Layout System.dc.html):
   glass column, #3a352a icons, gold active pill + tiny mono label, hairlines.
   ════════════════════════════════════════════════════════════════ */
@media (min-width: 541px) {
  .chrome-glass #dev-rail .dev-rail {
    background: var(--glass-fill);
    -webkit-backdrop-filter: var(--glass-blur);
    backdrop-filter: var(--glass-blur);
    border-left: 1px solid var(--glass-border);
    box-shadow: var(--glass-highlight), -8px 0 28px rgba(20, 16, 8, 0.14);
  }
  /* resting glyphs lifted from --text-faint (#9ca3af, near-invisible) to the
     canonical rail-icon ink #3a352a — clearly present without shouting */
  .chrome-glass #dev-rail .dev-rail-icon { color: #3a352a; }
  .chrome-glass #dev-rail .dev-rail-icon:hover {
    background: rgba(20, 16, 8, 0.06);
    color: var(--glass-ink);
  }
  /* active tab → glowing gold pill WITH its label (gold = live/selected).
     7px mono label rides below the glyph inside the 48px tile (fits even the
     longest intel labels), per the composition's micro-label idiom. */
  .chrome-glass #dev-rail .dev-rail-icon.active {
    background: var(--gold-active);
    color: #1f1408;
    border-radius: var(--glass-radius-chip);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.4), 0 3px 10px var(--gold-glow);
  }
  .chrome-glass #dev-rail .dev-rail-icon.active:hover { background: var(--gold-active); }
  .chrome-glass #dev-rail .dev-rail-icon.active { gap: 2px; }
  .chrome-glass #dev-rail .dev-rail-icon.active .dev-rail-glyph { color: #1f1408; }
  /* micro-label rides below the glyph; wraps so long labels (the "today" tab
     reads "Last 30 days" under IA-v2) stay inside the 48px tile, short ones
     ("Search", "Movement") stay one line. */
  .chrome-glass #dev-rail .dev-rail-icon.active .dev-rail-label {
    display: block; max-width: 46px; margin-top: 1px;
    font: 700 6.5px/1.08 var(--font-mono);
    letter-spacing: .02em; text-transform: uppercase; text-align: center;
    white-space: normal; color: #1f1408;
  }
  /* scope-tier dividers (nav-registry inserts these under IA-v2) →
     a quiet warm hairline on the glass instead of the grey --border */
  .chrome-glass #dev-rail .dev-rail-sep { background: rgba(20, 16, 8, 0.12); }
}

/* ════════════════════════════════════════════════════════════════
   DEVMAP-CHROME · S4 — Top HUD → warm-paper glass (#1259)
   Flag-gated (.chrome-glass). RESKIN-IN-PLACE: the strip stays full-width
   56px (the floating 16px-gutter bar is the deferred layout-law pass). Here
   it gains the glass material, a hero-stat emphasis on "units in pipeline"
   (owner decision 5 — the dramatic 40-48px display lands when the floating
   bar can grow taller), and a live gold pulse on the milestones tile.
   CSS-ONLY — targets the existing data-ticker-key values (no header.js / JS
   change). Count-up is deferred to the motion/float pass; the sparkline is
   DATA-BLOCKED (no time-series in /ticker or /today) so it is correctly absent.
   ════════════════════════════════════════════════════════════════ */
.chrome-glass .dev-topbar {
  background: var(--glass-fill-text);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border-bottom: 1px solid var(--glass-border);
  box-shadow: var(--shadow-glass);
}
.chrome-glass .dev-brand-text small { color: var(--glass-ink-muted); }
.chrome-glass .dev-brand-text strong { color: var(--glass-ink); }
.chrome-glass .dev-ticker { color: var(--glass-ink-muted); }
.chrome-glass .dev-tick { color: var(--glass-ink-muted); }
.chrome-glass .dev-tick strong { color: var(--glass-ink); }
.chrome-glass .dev-tick:hover { background: rgba(20, 16, 8, 0.05); color: var(--glass-ink); }
.chrome-glass .dev-tick-sep { color: var(--glass-ink-faint); }
/* hero stat — "units in pipeline" leads (owner decision 5). In the in-place
   56px strip this reads as a gold-edged chip + an enlarged display value;
   the full 40-48px hero arrives when the float pass gives the bar room. */
.chrome-glass .dev-tick[data-ticker-key="units"] {
  padding: 2px 9px; margin: 0; border-radius: 9px;
  background: rgba(212, 168, 75, 0.12);
  box-shadow: inset 0 0 0 1px rgba(212, 168, 75, 0.28);
}
.chrome-glass .dev-tick[data-ticker-key="units"]:hover { background: rgba(212, 168, 75, 0.16); }
/* hero value enlarged just enough to lead without growing the wrapping
   in-place strip (keeps the 56px bar from overflowing — the dramatic
   40-48px hero is the float-pass deliverable, where the bar can grow). */
.chrome-glass .dev-tick[data-ticker-key="units"] strong {
  font-family: var(--font-display); font-size: 15px; line-height: 1; color: var(--glass-ink);
}
/* live tile — "milestones · 30d" carries a pulsing gold dot (the now cue) */
.chrome-glass .dev-tick[data-ticker-key="eventsToday"]::before {
  content: ""; width: 5px; height: 5px; border-radius: 999px;
  background: #d4a84b; box-shadow: 0 0 6px var(--gold-glow-strong);
  margin-right: 3px; align-self: center;
  animation: chromeGlassPulse 1.6s ease-in-out infinite;
}
.chrome-glass .dev-topbar-contact { color: var(--glass-ink-2); }
.chrome-glass .dev-topbar-contact:hover { color: var(--glass-ink); background: rgba(20, 16, 8, 0.05); }
@keyframes chromeGlassPulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50%      { opacity: .5; transform: scale(.8); }
}
@media (prefers-reduced-motion: reduce) {
  .chrome-glass .dev-tick[data-ticker-key="eventsToday"]::before { animation: none; }
}

/* ════════════════════════════════════════════════════════════════
   DEVMAP-CHROME · S6 — "Today / Past 30 days" feed → warm-paper editorial
   glass (#1259). Flag-gated (.chrome-glass), scoped #dev-today. CSS-ONLY:
   the stage proxy is the bucket key on .panel-section[data-section], so the
   monogram tint + leading stage accent are pure CSS — no today.js change, and
   every .dev-evt[data-slug] / .dev-photo-card[data-slug] click+flyTo+keyboard
   contract is untouched (we only restyle existing DOM). The 24h sparkline is
   DATA-BLOCKED (no time-series in /today) → dropped; the existing .pulse
   carries liveness. devmap.css loads after dev.css → out-ranks the base rules.
   ════════════════════════════════════════════════════════════════ */
/* panel head — the one elevated zone */
.chrome-glass #dev-today .panel-head {
  background: var(--glass-fill-text);
  border-bottom: 1px solid var(--glass-border);
  box-shadow: var(--shadow-glass);
}
.chrome-glass #dev-today .panel-title { color: var(--glass-ink); }
.chrome-glass #dev-today .panel-meta { color: var(--glass-ink-muted); }
.chrome-glass #dev-today .panel-meta .pulse {
  background: #d4a84b; box-shadow: 0 0 7px var(--gold-glow-strong);
}
/* section heads — quiet titles + a leading stage accent bar (stage read first) */
.chrome-glass #dev-today .panel-section-title { color: var(--glass-ink); }
.chrome-glass #dev-today .panel-section-count {
  color: var(--glass-ink-faint);
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
}
.chrome-glass #dev-today .panel-section[data-section] .panel-section-head {
  border-left: 2px solid transparent; padding-left: 8px;
}
.chrome-glass #dev-today .panel-section[data-section="broke_ground"] .panel-section-head { border-left-color: #d4a84b; }
.chrome-glass #dev-today .panel-section[data-section="filed"]    .panel-section-head { border-left-color: var(--stage-proposed-warm); }
.chrome-glass #dev-today .panel-section[data-section="approved"] .panel-section-head { border-left-color: var(--stage-approved-warm); }
.chrome-glass #dev-today .panel-section[data-section="completed"] .panel-section-head { border-left-color: var(--stage-completed-warm); }
/* event cards — warm-paper rows; hover = faint warm lift, not flat grey */
.chrome-glass #dev-today .dev-evt:hover {
  background: rgba(212, 168, 75, 0.06);
  box-shadow: inset 0 0 0 1px rgba(20, 16, 8, 0.05);
}
.chrome-glass #dev-today .dev-evt-verb { color: var(--glass-ink-2); }
.chrome-glass #dev-today .dev-evt-name { color: var(--glass-ink); }
.chrome-glass #dev-today .dev-evt-meta { color: var(--glass-ink-muted); }
.chrome-glass #dev-today .dev-evt-empty,
.chrome-glass #dev-today .dev-evt-quiet { color: var(--glass-ink-muted); }
/* photo thumbs → small framed glass plates */
.chrome-glass #dev-today .dev-evt-thumb:not(.no-photo) {
  border-radius: var(--glass-radius-chip);
  box-shadow: inset 0 0 0 1px rgba(20, 16, 8, 0.10), var(--glass-highlight);
}
/* monogram tile (no photo) → stage-tinted by the parent bucket; initials stay
   neutral ink-2 (AA over the light tint), the tint + accent bar carry the stage */
.chrome-glass #dev-today .dev-evt-thumb.no-photo {
  background: rgba(140, 132, 114, 0.12);
  border: 1px solid rgba(20, 16, 8, 0.10);
  color: var(--glass-ink-2);
}
.chrome-glass #dev-today [data-section="broke_ground"] .dev-evt-thumb.no-photo { background: rgba(212, 168, 75, 0.16); border-color: rgba(212, 168, 75, 0.34); }
.chrome-glass #dev-today [data-section="filed"]    .dev-evt-thumb.no-photo { background: rgba(138, 127, 158, 0.16); border-color: rgba(138, 127, 158, 0.34); }
.chrome-glass #dev-today [data-section="approved"] .dev-evt-thumb.no-photo { background: rgba(95, 113, 150, 0.16); border-color: rgba(95, 113, 150, 0.34); }
.chrome-glass #dev-today [data-section="completed"] .dev-evt-thumb.no-photo { background: rgba(95, 143, 104, 0.16); border-color: rgba(95, 143, 104, 0.34); }
/* photo strip → small glass plates */
.chrome-glass #dev-today .dev-photo-card {
  border-radius: var(--glass-radius-chip);
  box-shadow: inset 0 0 0 1px rgba(20, 16, 8, 0.10), var(--glass-highlight);
  overflow: hidden;
}

/* ════════════════════════════════════════════════════════════════
   DEVMAP-CHROME · S7 — Project inspector (#dev-detail / panel-v5) → the
   focused glass card (#1259). Flag-gated (.chrome-glass). panel-v5 already
   carries the stage band (--pv5-stage-color), hero, spec strip, construction
   programme + cited-source pills (cohesion/VL/ledger arcs) — and the glass
   palette was partly derived from it — so S7 FRAMES it in the glass system
   rather than rebuilding: at desktop the floating panel becomes a rounded
   glass card; CONSTRUCTION projects get a soft gold energy on the stage band
   (gold = the live signal, reserved — not a ring around every open panel);
   cited-source labels harmonize to glass ink. CSS-ONLY — no panel-v5/JS change;
   all tab/click/observer contracts untouched. (The floating gutter is refined
   in the deferred layout-law pass.)
   ════════════════════════════════════════════════════════════════ */
@media (min-width: 1024px) {
  .chrome-glass #dev-detail {
    border-radius: var(--glass-radius-lg);
    border: 1px solid var(--glass-border);
    box-shadow: var(--shadow-glass);
  }
}
/* construction = energy: a soft gold wash inside the stage band (the band
   already carries the gold stage color; this lifts it into the gold-glow voice) */
.chrome-glass .pv5-card[data-stage-kind="construction"] .pv5-card__band {
  box-shadow: inset 0 -1px 0 rgba(212, 168, 75, 0.45),
              inset 0 14px 26px -18px rgba(212, 168, 75, 0.55);
}
/* cited-source provenance labels → consistent glass ink-muted voice */
.chrome-glass .pv5-section__source,
.chrome-glass .pv5-act__source { color: var(--glass-ink-muted); }

/* ════════════════════════════════════════════════════════════════
   DEVMAP-CHROME · S5 — First-paint loader → map-behind glass console (#1259)
   Flag-gated (.chrome-glass) + DESKTOP/iPad ONLY (min-width:541px) so the MOB2
   ≤540 dark goldlight phone loader stays byte-identical. Turns the opaque
   --surface-3 cover into a soft vignette SCRIM (the still-mounting map shows
   through, dimmed) behind a warm-paper GLASS console; the count headline is
   bumped to a hero size. CSS-ONLY — the DevLoader state machine + the existing
   gold sweep / determinate underline / checklist + the is-exiting→camera-dive
   dissolve are all untouched; the dramatic single-number count-up restructure
   is the deferred motion pass.
   ════════════════════════════════════════════════════════════════ */
@media (min-width: 541px) {
  .chrome-glass .dev-loader {
    background: radial-gradient(130% 100% at 50% 42%, transparent 36%, rgba(20, 16, 8, 0.30) 100%);
  }
  .chrome-glass .dev-loader__card {
    background: var(--glass-fill-text);
    -webkit-backdrop-filter: var(--glass-blur);
    backdrop-filter: var(--glass-blur);
    border: 1px solid var(--glass-border);
    border-radius: var(--glass-radius-lg);
    box-shadow: var(--shadow-glass);
  }
  .chrome-glass .dev-loader__eyebrow { color: var(--glass-ink-2); }
  .chrome-glass .dev-loader__headline { color: var(--glass-ink); font-size: 26px; }
  .chrome-glass .dev-loader__status { color: var(--glass-ink-2); }
  .chrome-glass .dev-loader__sep { color: var(--glass-ink-faint); }
  .chrome-glass .dev-loader__checklist li { color: var(--glass-ink-muted); }
}

/* ════════════════════════════════════════════════════════════════
   DEVMAP-CHROME · LAYOUT-LAW FLOAT PASS (#1259) — the canonical composition's
   floating geometry (owner Gate-1: "full composition"). Flag-gated
   (.chrome-glass) + DESKTOP ONLY (min-width:1024) so the iPad dead-zone band
   (541-1023) + MOB2 (≤540) keep their shipped layout. The shell is a 2-row
   grid (header strip + #dev-main holding map/rail/panels); here the header
   row collapses, #dev-header floats over a now FULL-BLEED map, the rail joins
   the 16px gutter as a rounded glass column, the panels (already floating from
   D80.E9) drop below the floated HUD and the right panel clears the floating
   rail, controls retrack, and the legend joins the gutter + hides when a
   project is open (State B). Aesthetics/layout only — camera-recenter +
   one-panel-at-a-time are flow, handled separately. Reversible via the flag.
   ════════════════════════════════════════════════════════════════ */
@media (min-width: 1024px) {
  /* full-bleed map: collapse the header row → #dev-main fills the viewport,
     #dev-header floats out of grid flow over the map */
  .chrome-glass .dev-shell { grid-template-rows: 1fr; }
  .chrome-glass #dev-header {
    position: absolute; top: 16px; left: 16px; right: 16px;
    height: auto; padding: 0; z-index: 7;
  }
  /* HUD → a floating rounded glass bar (S4 gave it the glass material) */
  .chrome-glass .dev-topbar {
    border: 1px solid var(--glass-border);
    border-radius: var(--glass-radius-lg);
  }
  /* rail → floating rounded glass column in the gutter */
  .chrome-glass #dev-rail { top: 88px; right: 16px; bottom: 16px; width: 56px; }
  .chrome-glass #dev-rail .dev-rail {
    width: 100%;
    border: 1px solid var(--glass-border);
    border-radius: var(--glass-radius-lg);
    box-shadow: var(--shadow-glass);
  }
  /* panels drop below the floating HUD (16 + 56 + 16 = 88); the right panel
     clears the floating rail (16 + 56 + 12 = 84, was 60 + 16 = 76). Explicit
     rounded glass card so the float is self-contained. */
  .chrome-glass #dev-detail { top: 88px; border-radius: var(--glass-radius-lg); }
  /* panel-v5 deliberately flattens `#dev-detail:has(.panel-v5)` (border:none;
     border-radius:0; background:transparent) so its stage card paints itself —
     and that rule (panel-v5.css, loaded after devmap.css, equal 1,1,0) wins over
     the bare #dev-detail above. Re-round the container with a :has() qualifier
     (1,2,0, beats it) + restore the float shadow; #dev-detail's overflow:hidden
     then clips the card to the rounded corners, so the inspector matches the
     other floating glass panels. */
  .chrome-glass #dev-detail:has(.panel-v5) {
    border-radius: var(--glass-radius-lg);
    box-shadow: var(--shadow-glass);
  }
  .chrome-glass #dev-nav { top: 88px; right: 84px; border-radius: var(--glass-radius-lg); }
  .chrome-glass .dev-main.nav-collapsed #dev-nav { transform: translateX(calc(100% + 84px)); }
  /* controls track the floating rail (+ the open right panel) */
  .chrome-glass .mapboxgl-ctrl-bottom-right {
    right: calc(16px + 56px + 12px + clamp(420px, 32vw, 540px) + 8px) !important;
  }
  .chrome-glass .dev-main.nav-collapsed .mapboxgl-ctrl-bottom-right { right: 84px !important; }
  /* legend joins the gutter; hides under the detail panel when a project opens (State B) */
  .chrome-glass .dev-legend { left: 16px; }
  .chrome-glass .dev-main.detail-open .dev-legend {
    opacity: 0; pointer-events: none;
    transition: opacity var(--duration-base) var(--ease-out);
  }
}

/* ════════════════════════════════════════════════════════════════
   DEVMAP-CHROME · OWNER-FEEDBACK FIXES 2026-06-16 (local, in review).
   #1 HUD two-row → single curated row; #2 Today colour-cliff → one warm
   surface; #3 scrollbar → glass-harmonized; #5 reload card-overlap →
   hide panels during boot. Flag-gated; CSS-only.
   ════════════════════════════════════════════════════════════════ */
/* #1 — single curated row: drop the 2 lower-priority stats from the bar
   (owner: 4-tile row, hero = Units) + never wrap. */
.chrome-glass .dev-ticker { flex-wrap: nowrap; }
.chrome-glass .dev-tick[data-ticker-key="completed12mo"],
.chrome-glass .dev-tick[data-ticker-key="existingDwellings"] { display: none; }
.chrome-glass .dev-tick { white-space: nowrap; }

/* #2 — kill the head/body colour cliff: make the whole Today panel ONE warm
   surface (the #dev-nav glass), head distinguished by a hairline not a colour
   band, body + sections transparent so there's no seam at "Latest photos". */
.chrome-glass #dev-nav { background: var(--glass-fill-text); }
.chrome-glass #dev-today,
.chrome-glass #dev-today .panel-section--photos { background: transparent; }
.chrome-glass #dev-today .panel-head {
  background: transparent;
  box-shadow: none;
  border-bottom: 1px solid rgba(20, 16, 8, 0.08);
}

/* #3 — glass-harmonized scrollbar (was a hard grey bar): a thin warm pill
   thumb on a transparent track, padded via background-clip. */
.chrome-glass #dev-nav::-webkit-scrollbar,
.chrome-glass #dev-detail .dev-detail-scroll::-webkit-scrollbar { width: 9px; height: 9px; }
.chrome-glass #dev-nav::-webkit-scrollbar-track,
.chrome-glass #dev-detail .dev-detail-scroll::-webkit-scrollbar-track { background: transparent; }
.chrome-glass #dev-nav::-webkit-scrollbar-thumb,
.chrome-glass #dev-detail .dev-detail-scroll::-webkit-scrollbar-thumb {
  background: rgba(20, 16, 8, 0.18);
  border: 2px solid transparent; background-clip: content-box;
  border-radius: 999px;
}
.chrome-glass #dev-nav::-webkit-scrollbar-thumb:hover,
.chrome-glass #dev-detail .dev-detail-scroll::-webkit-scrollbar-thumb:hover {
  background: rgba(20, 16, 8, 0.30); background-clip: content-box;
}
.chrome-glass #dev-nav, .chrome-glass #dev-detail .dev-detail-scroll {
  scrollbar-width: thin; scrollbar-color: rgba(20, 16, 8, 0.22) transparent;
}

/* #5 — boot: fully hide the panels (was opacity 0.6) so a reload never shows the
   PREVIOUS cards over the new ones while the scrim loader plays. They fade in
   clean once data-loading flips false. */
.chrome-glass .dev-shell[data-loading="true"] #dev-nav,
.chrome-glass .dev-shell[data-loading="true"] #dev-detail {
  opacity: 0;
  transition: opacity var(--duration-base) var(--ease-out);
}

/* ════════════════════════════════════════════════════════════════
   DEVMAP-CHROME · OWNER-FEEDBACK ROUND 2 2026-06-16 (local, in review).
   #1a inspector "panel-on-glass" double layer; #1b rail toggle; #2 scrollbar
   glassier; #3 scale by the logo; #4 legend collapsible. Flag-gated.
   ════════════════════════════════════════════════════════════════ */
/* #1a — the inspector read as the OLD panel-v5 card sitting on a separate glass
   rectangle (double layer): #dev-detail is the float glass card, but .pv5-card
   painted its own opaque card on top. Blend the card INTO the glass so the
   inspector is ONE surface (the stage band keeps its tint; content rides the glass). */
.chrome-glass #dev-detail .pv5-deck,
.chrome-glass #dev-detail .pv5-card,
.chrome-glass #dev-detail .pv5-card__tab-content { background: transparent; }
.chrome-glass #dev-detail .pv5-card { box-shadow: none; border: none; }

/* #1b — the rail expand/collapse toggle (›) was unstyled + 60px wide (overflowed
   the 56px floated rail). Fit it + give it the glass-rail voice. */
.chrome-glass #dev-rail .dev-rail-accordion {
  width: 100%; left: 0; color: var(--glass-ink-2);
  border-top: 1px solid rgba(20, 16, 8, 0.08);
  transition: background var(--duration-fast) var(--ease-out), color var(--duration-fast) var(--ease-out);
}
.chrome-glass #dev-rail .dev-rail-accordion:hover {
  background: rgba(20, 16, 8, 0.06); color: var(--glass-ink);
}

/* #2(refine) — scrollbar to MATCH the glass: warm translucent thumb, gold on
   hover (the system accent), transparent track. Overrides round-1's dark thumb. */
.chrome-glass #dev-nav::-webkit-scrollbar-thumb,
.chrome-glass #dev-detail .dev-detail-scroll::-webkit-scrollbar-thumb {
  background: rgba(140, 132, 114, 0.45);
  border: 2px solid transparent; background-clip: content-box; border-radius: 999px;
}
.chrome-glass #dev-nav::-webkit-scrollbar-thumb:hover,
.chrome-glass #dev-detail .dev-detail-scroll::-webkit-scrollbar-thumb:hover {
  background: rgba(212, 168, 75, 0.55); background-clip: content-box;
}
.chrome-glass #dev-nav, .chrome-glass #dev-detail .dev-detail-scroll {
  scrollbar-color: rgba(140, 132, 114, 0.5) transparent;
}

/* #3 — keep the map scale pinned at the very bottom-left, just above the Mapbox
   logo, clear of the legend (a quiet map annotation). */
.chrome-glass .mapboxgl-ctrl-bottom-left .mapboxgl-ctrl-scale {
  margin: 0 0 4px 4px;
  background: rgba(252, 251, 249, 0.55);
  border-color: rgba(20, 16, 8, 0.18);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
}

/* #4 — legend collapsible (was perpetually open, eating the left side). A chevron
   in the head collapses the stage rows + multi-unit filter to just the head, smoothly. */
.chrome-glass .dev-legend-collapse-btn {
  margin-left: auto; width: 22px; height: 22px; flex: 0 0 auto;
  border: none; background: transparent; color: var(--glass-ink-muted); cursor: pointer;
  border-radius: 6px; display: inline-flex; align-items: center; justify-content: center;
  font: 600 11px/1 var(--font-body);
  transition: transform var(--duration-base) var(--ease-out), background var(--duration-fast) var(--ease-out), color var(--duration-fast) var(--ease-out);
}
.chrome-glass .dev-legend-collapse-btn:hover { background: rgba(20, 16, 8, 0.06); color: var(--glass-ink); }
.chrome-glass .dev-legend.is-collapsed .dev-legend-collapse-btn { transform: rotate(-90deg); }
.chrome-glass .dev-legend-body,
.chrome-glass .dev-legend-head--mu,
.chrome-glass .dev-legend-mu-body {
  overflow: hidden;
  transition: max-height var(--duration-slow) var(--ease-out),
              opacity var(--duration-base) var(--ease-out),
              margin var(--duration-base) var(--ease-out),
              padding var(--duration-base) var(--ease-out);
  max-height: 480px; opacity: 1;
}
.chrome-glass .dev-legend.is-collapsed .dev-legend-body,
.chrome-glass .dev-legend.is-collapsed .dev-legend-head--mu,
.chrome-glass .dev-legend.is-collapsed .dev-legend-mu-body {
  max-height: 0; opacity: 0; margin-top: 0; margin-bottom: 0;
  padding-top: 0; padding-bottom: 0; border-top-color: transparent; pointer-events: none;
}
.chrome-glass .dev-legend.is-collapsed .dev-legend-head { margin-bottom: 0; }

/* ════════════════════════════════════════════════════════════════
   DEVMAP-CHROME · OWNER-FEEDBACK ROUND 3 2026-06-16 (local, in review).
   #1 rail toggle bg matched the explorer grey, not the rail glass; #2 legend
   floated mid-left (not bottom-anchored) over the scale/logo; #3 the inspector
   card was made fully transparent (see-through to the map) — wrong; it must be
   semi-opaque glass like the other panels.
   ════════════════════════════════════════════════════════════════ */
/* #1 — the rail accordion (›) had bg #f5f5f4 (the explorer-panel grey); the rail
   itself is --glass-fill. It sits OVER the rail glass, so go transparent → the
   rail's own glass shows through and it reads as one surface. */
.chrome-glass #dev-rail .dev-rail-accordion { background: transparent; }
.chrome-glass #dev-rail .dev-rail-accordion:hover { background: rgba(20, 16, 8, 0.06); }

/* #2 — legend overlapped the map credits + read as "floating mid-left".
   The Mapbox bottom-left stack (scale · logo · attribution) is ALREADY pinned
   at the very bottom-left (bottom:0; its computed top:687 is just the resolved
   used-value of a bottom-anchored absolute box, NOT a bug — verified live). The
   real issue was the legend: at bottom:44 its tall body (~262px expanded)
   overlapped the ~56px credit stack (legend bottom y698 vs stack top y687) and
   floated up the left edge. Lift it to clear the credits so the scale/logo sit
   cleanly BELOW it; the body grows UPWARD from this bottom anchor (and the
   round-2 toggle collapses it to a tidy bottom-left chip). */
.chrome-glass .dev-legend { bottom: 64px; }

/* #3 — the inspector was see-through (both #dev-detail and .pv5-card transparent).
   Give the container the SAME warm glass surface as the other panels (semi-opaque
   + blur); the transparent card blends into it → one solid glass inspector, not a
   window onto the map. (Pairs with the round-1 #1a card-blend + the corner-fix.)
   DEPENDENCY: this must out-specify panel-v5.css's `#dev-detail:has(.panel-v5)
   { background: transparent }` flatten. We win by SPECIFICITY — (1,2,0) vs (1,1,0)
   — NOT by load order (devmap.css actually loads BEFORE panel-v5.css). If anyone
   equalizes the selectors (adds .chrome-glass to the panel-v5 rule, or simplifies
   this to `.chrome-glass #dev-detail`), the inspector goes see-through again. */
.chrome-glass #dev-detail:has(.panel-v5) {
  background: var(--glass-fill-text);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
}

/* ════════════════════════════════════════════════════════════════
   DEVMAP-CHROME · ROUND 4 — mobile/tablet glass simplification 2026-06-16.
   When glass became the public default, the single-row HUD stat ticker
   (round-1 #1, nowrap, a GLOBAL rule) only ever fit the WIDE desktop header.
   Below that it broke the in-flow header: at <=1023 the un-shrinkable ticker
   forced the whole page ~1236px wide, pushing the Today panel + rail OFF the
   right edge (verified: classic at 768 = 768px wide, all on-screen; glass =
   1236px). In the 1024-1279 floated band the 4-tile row also spilled past the
   gutter-floated header (~31px) into a small page scroll. Owner direction:
   "mobile should be simpler than desktop" — so the ticker is a wide-desktop
   affordance and progressively sheds tiles as width shrinks.
   ════════════════════════════════════════════════════════════════ */
/* The ticker sheds tiles by priority as the header narrows. The hero
   ("units in pipeline") is the ONE aggregate with no other home (the Today
   panel shows event cards, not totals), so it is protected to the smallest
   band; the rest drop. Separators are position-based sibling nodes, so we hide
   them and lean on the ticker's flex gap. Base dev.css already hides the search
   bar <=720 and the whole ticker <=540 — these rules layer on top of that.

   TABLET 541-1023: hero only. */
@media (min-width: 541px) and (max-width: 1023px) {
  .chrome-glass .dev-tick:not([data-ticker-key="units"]),
  .chrome-glass .dev-ticker .dev-tick-sep { display: none; }
}
/* 721-1023: the 320px search bar returns here and competes with the hero stat
   for the in-flow 56px row, so shrink the brand to its mark (the logo still
   identifies; "Halifax Developments" text returns >=1024). Without this the
   hero + search + full brand + Contact overflow the page and push the Today
   panel + rail off the right edge. */
@media (min-width: 721px) and (max-width: 1023px) {
  .chrome-glass .dev-brand-text { display: none; }
}
/* Floated-but-narrow desktop (gutter header ~992-1248px): the 4-tile row spills
   past the bar until ~1280, so keep the hero + active. */
@media (min-width: 1024px) and (max-width: 1279px) {
  .chrome-glass .dev-tick[data-ticker-key="underConstruction"],
  .chrome-glass .dev-tick[data-ticker-key="eventsToday"],
  .chrome-glass .dev-ticker .dev-tick-sep { display: none; }
}

/* v0.10.0 — kind-aware hover card (Apple×Bloomberg×Ive). The eyebrow
   states WHAT the item is (Development vs Parcel); warm-paper,
   hairline, one stage accent, mono tabular facts. */
.dev-hover-pop .mapboxgl-popup-content {
  padding: 10px 12px; border-radius: var(--radius-md);
  /* D80.C6 (B1) — added saturate(180%) + reduced opacity 0.98→0.86 so the
     glass effect actually reads as glass instead of milky. Per V3 §3 + D80
     Phase 2 D4. */
  background: rgba(250,250,249,0.86); backdrop-filter: blur(10px) saturate(180%); -webkit-backdrop-filter: blur(10px) saturate(180%);
  border: 1px solid var(--border); box-shadow: var(--shadow-md);
}
.dev-hover-pop .mapboxgl-popup-tip { display: none; }
.dev-hp { max-width: 240px; }
.dev-hp-kind {
  font: 700 9px/1 var(--font-body); letter-spacing: .12em;
  text-transform: uppercase; margin-bottom: 5px;
}
.dev-hp-kind--muted { color: var(--text-faint); }
/* D-Ingest.H — Multi-unit dot popup. Quiet teal accent matches the dot
 * colour on the map so the hover popup reads as a continuation. */
.dev-hp-kind--multi { color: #3d8e8e; }
.dev-hp--multi-unit .dev-hp-meta strong { color: var(--text); font-weight: 600; }
.dev-hp-title {
  font: 600 13.5px/1.25 var(--font-body); color: var(--text);
  letter-spacing: -0.01em;
}
.dev-hp-row {
  display: flex; align-items: center; gap: 8px;
  margin-top: 7px; flex-wrap: wrap;
}
.dev-hp-chip {
  font: 700 9px/1 var(--font-body); letter-spacing: .06em;
  text-transform: uppercase; color: #fff;
  padding: 4px 7px; border-radius: var(--radius-pill, 999px); white-space: nowrap;
}
.dev-hp-facts {
  font: 500 10.5px/1 var(--font-mono); color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}
.dev-hp-meta {
  font: 500 10.5px/1.3 var(--font-mono); color: var(--text-muted);
  font-variant-numeric: tabular-nums; margin-top: 5px;
}
.dev-hp-cue {
  font: 600 10px/1 var(--font-body); color: var(--text-faint);
  margin-top: 8px; letter-spacing: .01em;
}

/* D97.P4 — Area-overview hover panel. Wider than the standard .dev-hp
   (max-width:240px) because the rich content (4-row stage breakdown +
   2-row dollar table + headline + last-activity) doesn't fit cleanly.
   Inherits the warm-paper glass background from .dev-hover-pop. */
.dev-hp--area { max-width: 300px; }
.dev-hp-kind--area { color: #b8923f; }  /* brand amber, matches area outline */
.dev-hp-area-headline {
  display: flex; align-items: baseline; gap: 6px;
  margin: 8px 0 4px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--border);
}
.dev-hp-area-headline__num {
  font: 600 22px/1 var(--font-mono); color: var(--text);
  font-variant-numeric: tabular-nums; letter-spacing: -0.02em;
}
.dev-hp-area-headline__lbl {
  font: 500 10.5px/1.2 var(--font-body); color: var(--text-muted);
}
.dev-hp-area-table {
  width: 100%; border-collapse: collapse; margin-top: 4px;
  font: 500 11px/1.4 var(--font-mono); font-variant-numeric: tabular-nums;
}
.dev-hp-area-table td {
  padding: 3px 0; color: var(--text-muted);
}
.dev-hp-area-table td:last-child {
  text-align: right; color: var(--text); font-weight: 600;
}
.dev-hp-area-divider {
  height: 1px; background: var(--border); margin: 6px 0;
}
.dev-hp-meta--hint {
  color: var(--text-faint); margin-top: 6px;
}

/* v0.11.0 — Admin panel (lives in #dev-nav, switched by the rail
   icon). Ive/Bloomberg system: mono tabular numerics, hairline
   dividers, no decorative colour. Inline dev-gate when locked. */
.admin-panel { display: flex; flex-direction: column; height: 100%; }
.admin-panel .panel-head { border-bottom: 1px solid var(--border); }
.admin-panel .panel-meta {
  font: 700 9px/1 var(--font-body); letter-spacing: .12em;
  color: var(--text-faint); margin-top: 0;
}
.admin-lock {
  font: 600 10px/1 var(--font-body); letter-spacing: .08em;
  text-transform: uppercase; color: var(--text-muted);
  background: transparent; border: 1px solid var(--border);
  border-radius: var(--radius-sm); padding: 5px 9px; cursor: pointer;
}
.admin-lock:hover { color: var(--text); border-color: var(--text-muted); }

/* v0.12.0 — gate: centred sign-in card, calm hierarchy, ink focus. */
.admin-gate {
  padding: 36px 22px; display: flex; flex-direction: column;
  gap: 8px; min-height: 380px;
}
.admin-gate-eyebrow {
  font: 700 9px/1 var(--font-body); letter-spacing: .14em;
  text-transform: uppercase; color: var(--accent-gold);
  margin-bottom: 6px;
}
.admin-gate-title {
  font: 600 22px/1.15 var(--font-display); letter-spacing: -0.01em;
  color: var(--text); margin: 0;
}
.admin-gate-cue {
  font: 400 13px/1.5 var(--font-body); color: var(--text-muted);
  margin: 0 0 16px 0; max-width: 30ch;
}
.admin-gate-form { display: flex; gap: 8px; }
.admin-gate-input {
  flex: 1; font: 500 14px/1 var(--font-mono);
  padding: 11px 13px; border-radius: var(--radius-sm);
  border: 1px solid var(--border-strong); background: var(--bg-paper);
  color: var(--text); transition: border-color var(--duration-fast) var(--ease-out), box-shadow var(--duration-fast) var(--ease-out);
}
.admin-gate-input::placeholder { color: var(--text-faint); }
.admin-gate-input:focus {
  outline: none; border-color: var(--text);
  box-shadow: 0 0 0 3px rgba(216,160,53,.15);
}
.admin-gate-submit {
  padding: 11px 16px; font: 600 13px/1 var(--font-body);
  border-radius: var(--radius-sm);
}
.admin-gate-err {
  font: 500 12px/1.4 var(--font-body); color: var(--status-error);
  margin: 4px 0 0 0;
}
.admin-gate-help {
  font: 500 11px/1.4 var(--font-body); color: var(--text-faint);
  margin: auto 0 0 0; padding-top: 16px;
}

/* D106.ADMIN — hero KPI bar (always-visible above tabs).
   4-up grid with traffic-light tone bands (ok/warn/fail). */
.admin-hero {
  padding: 12px 12px 0;
  border-bottom: 1px solid var(--border);
  background: var(--bg-paper);
}
.admin-hero-grid {
  /* D107.POLISH — auto-fit with min 140px so 4-digit values don't crowd
     and 2-up on narrow viewports doesn't require a separate media query. */
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 8px;
  padding-bottom: 12px;
}
.admin-hero-card {
  position: relative;
  padding: 10px 12px;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.admin-hero-card::before {
  content: ""; position: absolute; inset: 0 auto 0 0; width: 3px;
  background: var(--text-muted); opacity: 0.4;
}
.admin-hero-card--ok::before   { background: #4ade80; opacity: 0.9; }
.admin-hero-card--warn::before { background: #facc15; opacity: 0.9; }
.admin-hero-card--fail::before { background: #ef4444; opacity: 0.95; }
.admin-hero-eyebrow {
  font: 600 9.5px/1.2 var(--font-body); letter-spacing: .08em;
  text-transform: uppercase; color: var(--text-muted);
}
.admin-hero-value {
  font: 700 22px/1.1 var(--font-display, var(--font-body));
  color: var(--text); margin-top: 4px;
}
.admin-hero-sub {
  font: 500 10.5px/1.2 var(--font-body); color: var(--text-faint);
  margin-top: 3px;
}
.admin-hero-card--skel .admin-skel-line {
  display: block; height: 10px; border-radius: 2px;
  background: var(--bg-sunken); margin: 4px 0;
  animation: pv5-pulse 1.4s ease-in-out infinite;
}
.admin-hero-card--skel .admin-hero-value { height: 22px; }
.admin-hero-err {
  font: 500 11px/1.3 var(--font-body); color: var(--text-muted);
  padding: 4px 0 12px;
}
@media (max-width: 768px) {
  .admin-hero-grid { grid-template-columns: repeat(2, 1fr); }
}

/* D106.ADMIN — bridges tab: stats + chips + table */
.admin-bridges-stats {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px;
  padding: 10px 12px;
}
.admin-bridges-stat {
  padding: 8px 10px; background: var(--bg-elev);
  border: 1px solid var(--border); border-radius: var(--radius-md);
  text-align: center;
}
.admin-bridges-stat-value {
  font: 700 18px/1.1 var(--font-display, var(--font-body)); color: var(--text);
}
.admin-bridges-stat-label {
  font: 600 10px/1.2 var(--font-body); letter-spacing: .04em;
  text-transform: uppercase; color: var(--text-muted); margin-top: 2px;
}
.admin-bridges-stat--ok   { border-color: rgba(74, 222, 128, 0.4); }
.admin-bridges-stat--warn { border-color: rgba(250, 204, 21, 0.5); }
.admin-bridges-stat--fail { border-color: rgba(239, 68, 68, 0.5); }
.admin-bridges-chips {
  display: flex; flex-wrap: wrap; gap: 6px; align-items: center;
  padding: 0 12px 10px;
  font: 500 11px/1.3 var(--font-body); color: var(--text-muted);
}
.admin-bridges-chips-label { color: var(--text-faint); margin-right: 4px; }
.admin-bridges-chip {
  padding: 3px 8px; background: var(--bg-elev);
  border: 1px solid var(--border); border-radius: 999px;
  font: 500 10.5px/1.2 var(--font-body); color: var(--text);
}
.admin-suspicion-cell { width: 18px; text-align: center; }
.admin-suspicion-dot {
  display: inline-block; width: 8px; height: 8px; border-radius: 50%;
  background: #4ade80;
}
.admin-suspicion-dot--medium { background: #facc15; }
.admin-suspicion-dot--high   { background: #ef4444; }
.admin-bridges-note {
  font: 400 11px/1.4 var(--font-body); color: var(--text-faint);
  max-width: 320px;
  /* D107.POLISH — single-line truncate with tooltip on hover for full text */
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
@media (max-width: 768px) {
  .admin-bridges-stats { grid-template-columns: repeat(2, 1fr); }
}

/* D107.POLISH — clickable suspicion filter chips on Bridges tab */
.admin-bridges-filter-chip {
  padding: 4px 10px; background: var(--bg-elev);
  border: 1px solid var(--border); border-radius: 999px;
  font: 600 10.5px/1.2 var(--font-body); color: var(--text);
  cursor: pointer; transition: background 120ms, border-color 120ms, color 120ms;
}
.admin-bridges-filter-chip:hover { background: var(--bg-paper); }
.admin-bridges-filter-chip.is-active {
  background: var(--text); color: var(--bg-paper); border-color: var(--text);
}
.admin-bridges-filter-chip--ok.is-active   { background: #16a34a; border-color: #16a34a; color: white; }
.admin-bridges-filter-chip--warn.is-active { background: #d4a84b; border-color: #d4a84b; color: #1a1611; }
.admin-bridges-filter-chip--fail.is-active { background: #c84545; border-color: #c84545; color: white; }
.admin-bridges-chips--sources { margin-top: -4px; }

/* D107.POLISH — scrollable table wrapper (Bridges + Projects + Activity).
   Caps long tables at a sensible height with internal scrolling so the
   admin panel doesn't become a giant page-level scroll. */
.admin-table-scroll {
  max-height: 480px;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}
.admin-table-scroll .admin-table { margin: 0; }
.admin-table-scroll .admin-table th {
  position: sticky; top: 0;
  background: var(--bg-paper);
  z-index: 1;
  box-shadow: inset 0 -1px 0 var(--border);
}

/* D107.POLISH — Projects rows: clickable + muted treatment for
   unnamed (PID-only) entries. */
.admin-projects-row {
  transition: background 120ms;
}
.admin-projects-row:hover {
  background: var(--bg-elev);
}
.admin-projects-row:focus {
  background: var(--bg-elev);
  outline: 2px solid var(--gold, #d4a84b);
  outline-offset: -2px;
}
.admin-projects-row--unnamed td:nth-child(2) {
  /* Muted italic for "PID 40789323"-style rows — present but de-emphasized */
  color: var(--text-faint);
  font-style: italic;
}

.admin-tabs {
  display: flex; gap: 4px; padding: 8px 12px;
  border-bottom: 1px solid var(--border); background: var(--bg-paper);
}
.admin-tab {
  font: 600 11px/1 var(--font-body); letter-spacing: .03em;
  color: var(--text-muted); background: transparent; border: none;
  padding: 7px 10px; border-radius: var(--radius-sm); cursor: pointer;
  /* v0.13.2 — match the rail's single coordinated transition spec. */
  transition: color var(--duration-fast) var(--ease-out), background-color var(--duration-fast) var(--ease-out);
}
.admin-tab:hover { color: var(--text); background: var(--bg-subtle); }
.admin-tab.active { color: var(--text); background: var(--bg-sunken);
  box-shadow: inset 0 -2px 0 var(--accent-gold); }

.admin-view { padding: 14px 16px 24px; overflow-y: auto; }
.admin-loading, .admin-error, .admin-placeholder {
  font: 500 12px/1.4 var(--font-body); color: var(--text-muted);
}
.admin-error { color: var(--status-error); }

/* v0.12.3 — loading skeleton: tasteful shimmer rows that replace
   the raw "Loading…" text. Bars use the paper/border tokens so they
   read as quiet placeholders, not noise. */
.admin-skel-list { display: flex; flex-direction: column; gap: 9px; padding: 4px 0; }
.admin-skel-row {
  height: 11px; border-radius: 3px;
  background: linear-gradient(90deg,
    var(--bg-subtle) 0%, var(--border) 50%, var(--bg-subtle) 100%);
  background-size: 220% 100%;
  animation: admin-skel-shimmer 1.25s ease-in-out infinite;
}
.admin-skel-row.short { width: 38%; }
.admin-skel-row.mid { width: 64%; }
.admin-skel-row.full { width: 92%; }
@keyframes admin-skel-shimmer {
  0% { background-position: 100% 0; }
  100% { background-position: -100% 0; }
}
@media (prefers-reduced-motion: reduce) {
  .admin-skel-row { animation: none; background: var(--bg-sunken); }
}

.admin-block { margin-bottom: 18px; }
.admin-h {
  font: 700 10px/1 var(--font-body); letter-spacing: .08em;
  text-transform: uppercase; color: var(--text-muted);
  margin: 0 0 8px 0;
}
.admin-stat-row {
  /* v0.13.3 — responsive: wraps to fit the 344px content area instead
     of forcing 5 columns into a 425px minimum. With 5 stats and a
     344px container, this lands at 3 cols then 2-on-the-wrap. */
  display: grid; gap: 6px;
  grid-template-columns: repeat(auto-fit, minmax(92px, 1fr));
}
.admin-stat {
  background: var(--bg-card); border: 1px solid var(--border);
  border-radius: var(--radius-sm); padding: 8px 10px;
}
.admin-stat-label {
  font: 600 9px/1 var(--font-body); letter-spacing: .06em;
  text-transform: uppercase; color: var(--text-muted); margin-bottom: 4px;
}
.admin-stat-value {
  font: 600 18px/1 var(--font-mono); color: var(--text);
  font-variant-numeric: tabular-nums; letter-spacing: -0.02em;
}
.admin-kv { display: flex; align-items: center; gap: 10px; }
.admin-kv .admin-stat-label { margin: 0; }
.admin-kv .admin-stat-value { font-size: 15px; }

.admin-table {
  width: 100%; border-collapse: collapse;
  font: 500 11px/1.3 var(--font-mono);
  font-variant-numeric: tabular-nums;
}
.admin-table th {
  text-align: left; font: 700 9px/1 var(--font-body);
  letter-spacing: .06em; text-transform: uppercase;
  color: var(--text-muted); padding: 6px 8px; border-bottom: 1px solid var(--border);
}
.admin-table td {
  padding: 6px 8px; border-bottom: 1px solid var(--border);
  color: var(--text); vertical-align: top;
}
.admin-table tr.is-err td { color: var(--status-error); }
.admin-table td.num { text-align: right; }

/* v0.13.5.A (D45) — freshness light cells for Projects + Sources tabs.
   Small dot in the leading column, colour-coded by recency. */
.admin-table .freshness-cell {
  width: 14px; padding-left: 8px; padding-right: 4px;
}
.freshness-dot {
  display: inline-block; width: 7px; height: 7px;
  border-radius: 50%; vertical-align: middle;
  box-shadow: 0 0 0 1px rgba(0,0,0,0.04);
}

/* Projects table: row hover + click affordance (the table replaces the
   old per-project Inspector; click any row -> opens the Project View). */
.admin-table--projects tr.admin-projects-row {
  cursor: pointer;
  transition: background-color var(--duration-fast) var(--ease-out);
}
.admin-table--projects tr.admin-projects-row:hover,
.admin-table--projects tr.admin-projects-row:focus {
  background: var(--bg-subtle);
  outline: none;
}

/* v0.11.1 — Inspector: search + result rows + project detail. */
.admin-search { margin-bottom: 10px; }
.admin-search-input {
  width: 100%; font: 500 13px/1 var(--font-body);
  padding: 9px 11px; border-radius: var(--radius-sm);
  border: 1px solid var(--border-strong); background: var(--bg-paper);
  color: var(--text);
  transition: border-color var(--duration-fast) var(--ease-out), box-shadow var(--duration-fast) var(--ease-out);
}
.admin-search-input:focus {
  outline: none; border-color: var(--text);
  box-shadow: 0 0 0 3px rgba(216,160,53,.12);
}
.admin-results { display: flex; flex-direction: column; gap: 2px; margin-bottom: 12px; }
.admin-result {
  display: flex; flex-direction: column; align-items: flex-start; gap: 2px;
  text-align: left; padding: 8px 10px; border: 1px solid var(--border);
  background: var(--bg-paper); border-radius: var(--radius-sm); cursor: pointer;
}
.admin-result:hover { border-color: var(--text-muted); background: var(--bg-subtle); }
.admin-result-title { font: 600 12px/1.2 var(--font-body); color: var(--text); }
.admin-result-meta { font: 500 10px/1.2 var(--font-mono); color: var(--text-muted); }

.admin-dl {
  display: grid; grid-template-columns: 80px 1fr; gap: 4px 10px; margin: 0;
}
.admin-dl dt {
  font: 700 9px/1.2 var(--font-body); letter-spacing: .06em;
  text-transform: uppercase; color: var(--text-muted); padding-top: 2px;
}
.admin-dl dd {
  margin: 0; font: 500 12px/1.3 var(--font-body); color: var(--text);
  word-break: break-word;
}
.admin-dl dd.mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.admin-pid-list {
  margin: 0; padding: 0; list-style: none;
  display: grid; grid-template-columns: 1fr 1fr; gap: 2px 8px;
}
.admin-pid-list li {
  font: 500 11px/1.3 var(--font-mono); color: var(--text);
  font-variant-numeric: tabular-nums;
}

/* v0.11.2 — Activity days selector inline */
.admin-search { display: flex; align-items: center; gap: 8px; }
.admin-days {
  font: 500 12px/1 var(--font-body);
  padding: 6px 8px; border-radius: var(--radius-sm);
  border: 1px solid var(--border-strong); background: var(--bg-paper);
  color: var(--text); cursor: pointer;
}

.preview-flag {
  position: fixed; bottom: 8px; left: 50%; transform: translateX(-50%);
  z-index: 99; background: var(--accent-gold); color: #111;
  font: 600 11px/1 var(--font-body); padding: 4px 12px; border-radius: 999px; opacity: .9;
}

/* ─── D65.F — Admin Pipeline tab (data-consistency invariants UI) ─── */
.admin-inv-list {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-direction: column; gap: 4px;
}
.admin-inv {
  display: grid; grid-template-columns: 18px 56px 1fr; gap: 6px;
  align-items: baseline; padding: 6px 8px; border-radius: var(--radius-sm);
  font: 500 12px/1.4 var(--font-body);
}
.admin-inv--pass { background: rgba(34, 139, 80, 0.06); color: var(--text); }
.admin-inv--warn { background: rgba(216, 160, 53, 0.10); color: var(--text); }
.admin-inv--fail { background: rgba(200, 74, 42, 0.10); color: #6f2218; }
.admin-inv-sym {
  font: 700 13px/1 var(--font-body); text-align: center;
}
.admin-inv--pass .admin-inv-sym { color: #228b50; }
.admin-inv--warn .admin-inv-sym { color: #a17a18; }
.admin-inv--fail .admin-inv-sym { color: #c84a2a; }
.admin-inv-code {
  font: 600 10px/1.2 var(--font-mono); text-transform: uppercase;
  letter-spacing: 0.06em; color: var(--text-muted);
}
.admin-inv-msg { color: var(--text); }
.admin-inv-detail {
  grid-column: 2 / -1; margin: 4px 0 0; padding: 6px 8px;
  font: 500 11px/1.4 var(--font-mono); white-space: pre-wrap;
  background: rgba(0, 0, 0, 0.03); border-radius: var(--radius-sm);
  color: var(--text-muted);
}
.admin-cell-actions { text-align: right; }
.admin-copy {
  appearance: none; border: 1px solid var(--border); background: var(--bg-paper);
  font: 500 10px/1.2 var(--font-body); padding: 3px 7px;
  border-radius: var(--radius-sm); cursor: pointer; color: var(--text-muted);
  transition: color var(--duration-fast) var(--ease-out), border-color var(--duration-fast) var(--ease-out);
}
.admin-copy:hover { color: var(--text); border-color: var(--text-muted); }
.admin-mono { font-family: var(--font-mono); font-size: 11px; }
.admin-num { text-align: right; font-variant-numeric: tabular-nums; }
.admin-meta {
  font: 500 11px/1.4 var(--font-body); color: var(--text-muted);
  margin: 6px 0 0;
}
.admin-meta--footer {
  margin-top: 16px; padding-top: 8px; border-top: 1px solid var(--border);
  font-style: italic;
}
/* D66.G — ETL run-health table row highlight for overdue workers */
.admin-row-warn { background: rgba(216, 160, 53, 0.08); }
.admin-row-warn td { color: var(--text); }

/* ============================================================ */
/* D108.ADMIN.LIFT — design intent + plumbing surfacing         */
/* ============================================================ */
/* Stays in panel-v5/Today's light theme (right rail is light   */
/* by design). Levels admin typography to Outfit + JetBrains    */
/* Mono to match panel-v5 craft. Adds tone bands on every       */
/* admin-block so operational state reads instantly. Brings the */
/* convergent stage palette (D96.S12) into Stage Counts. Adds   */
/* a spinal ribbon above the tabs that shows the real data flow */
/* (Sources → Obs → Resolver → Project → Showcase → Map).       */
/* Hover-reveal copy/open micro-actions + "Why?" popovers.      */
/* ============================================================ */

/* --- block-level chrome ------------------------------------- */
.admin-block {
  position: relative;
  margin: 18px 0;
  padding: 14px 14px 14px 16px;
  background: var(--surface-3, var(--bg-elev));
  border: 1px solid var(--line, var(--border));
  border-radius: 10px;
  border-left: 3px solid var(--admin-block-tone, var(--line, var(--border)));
}
.admin-block--ok   { --admin-block-tone: #16a34a; }
.admin-block--warn { --admin-block-tone: #d97706; }
.admin-block--fail { --admin-block-tone: #dc2626; }
.admin-block--info { --admin-block-tone: var(--gold, #d4a84b); }

.admin-block .admin-h {
  font: 600 14px/1.25 var(--font-display, var(--font-body));
  letter-spacing: -0.005em;
  color: var(--text);
  margin: 0 0 10px;
}
.admin-block .admin-h .admin-h-sub {
  display: block;
  font: 500 11px/1.3 var(--font-body);
  color: var(--text-muted);
  letter-spacing: 0;
  text-transform: none;
  margin-top: 2px;
}

/* --- stage-color chips for Stage Counts -------------------- */
.admin-stage-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 4px 0 0;
}
.admin-stage-card {
  flex: 1 1 auto;
  min-width: 88px;
  padding: 8px 10px;
  background: var(--surface-1, #fff);
  border: 1px solid var(--line, var(--border));
  border-left: 3px solid var(--stage-color, var(--line));
  border-radius: 8px;
}
.admin-stage-card[data-stage="proposed"]     { --stage-color: #7c6cae; }
.admin-stage-card[data-stage="approved"]     { --stage-color: #2563eb; }
.admin-stage-card[data-stage="construction"] { --stage-color: var(--stage-construction); }
.admin-stage-card[data-stage="completed"]    { --stage-color: #16a34a; }
.admin-stage-card[data-stage="inactive"]     { --stage-color: #9aa0a6; }
.admin-stage-card[data-stage="multi_unit"]   { --stage-color: #5eead4; }
.admin-stage-card-label {
  font: 600 10px/1 var(--font-body);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.admin-stage-card-value {
  font: 700 22px/1 var(--font-mono);
  font-variant-numeric: tabular-nums;
  color: var(--text);
  margin-top: 6px;
}

/* --- spinal ribbon ----------------------------------------- */
.admin-spine {
  margin: 0 16px 12px;
  padding: 12px 12px 10px;
  background: var(--surface-1, #fff);
  border: 1px solid var(--line, var(--border));
  border-radius: 10px;
}
.admin-spine-eyebrow {
  font: 600 9.5px/1 var(--font-body);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: 10px;
}
/* D108.ADMIN.LIFT iterate-1: 6-column grid, no inline arrows.            */
/* The arrows were charming at 800px but at 540px (the actual panel       */
/* width) they squeezed every node into ~70px and forced "11h ago" to    */
/* break into two lines. The directional metaphor is already carried by  */
/* the left-to-right label sequence — Sources → Observations →          */
/* Resolver → Projects → Showcase → Map reads in order even without     */
/* glyphs. Saved space goes to the values, which are the point.         */
.admin-spine-row {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 4px;
}
.admin-spine-node {
  min-width: 0;
  padding: 5px 6px 4px;
  background: transparent;
  border-radius: 6px;
  position: relative;
  transition: background var(--duration-fast, 120ms) ease;
  /* Each node carries a subtle right separator so the sequence still  */
  /* reads as a flow (sequence-by-separator, not sequence-by-arrow).   */
  border-right: 1px solid var(--line, var(--border));
}
.admin-spine-node:last-child { border-right: none; }
.admin-spine-node:hover { background: var(--surface-3, var(--bg-elev)); }
.admin-spine-node-head {
  display: block;
  font: 600 8.5px/1 var(--font-body);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  padding-right: 8px; /* reserve space for the absolute-positioned dot */
}
.admin-spine-node-head span:first-child + span {
  /* (legacy selector — head text is now the only child) */
}
.admin-spine-node-dot {
  position: absolute;
  top: 6px; right: 6px;
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--admin-dot, var(--text-faint));
}
.admin-spine-node[data-tone="ok"]   { --admin-dot: #16a34a; }
.admin-spine-node[data-tone="warn"] { --admin-dot: #d97706; }
.admin-spine-node[data-tone="fail"] { --admin-dot: #dc2626; }
.admin-spine-node-value {
  font: 700 15px/1.1 var(--font-mono);
  font-variant-numeric: tabular-nums;
  color: var(--text);
  margin-top: 4px;
  letter-spacing: -0.015em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.admin-spine-node-sub {
  font: 500 9px/1.3 var(--font-body);
  color: var(--text-faint);
  margin-top: 1px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Legacy arrow class kept as a no-op so the DOM-emitter can stay      */
/* unchanged. Hidden (display:none) on narrow; if we ever widen, can   */
/* re-show with a media query. */
.admin-spine-arrow { display: none; }

/* --- ETL Health stalled-first treatment -------------------- */
.admin-etl-stalled { margin: 6px 0 12px; display: grid; gap: 8px; }
.admin-etl-stalled-card {
  padding: 10px 12px;
  background: rgba(220, 38, 38, 0.05);
  border: 1px solid rgba(220, 38, 38, 0.25);
  border-left: 3px solid #dc2626;
  border-radius: 8px;
}
.admin-etl-stalled-card .worker {
  font: 600 12px/1.2 var(--font-mono); color: var(--text);
}
.admin-etl-stalled-card .layer {
  font: 500 11px/1.2 var(--font-mono); color: var(--text-muted); margin-top: 2px;
}
.admin-etl-stalled-card .meta {
  font: 500 11px/1.3 var(--font-body); color: #b04040; margin-top: 4px;
}
.admin-etl-stalled-empty {
  font: 500 12px/1.4 var(--font-body); color: #16a34a;
  padding: 8px 10px;
  background: rgba(22, 163, 74, 0.06);
  border: 1px solid rgba(22, 163, 74, 0.18);
  border-left: 3px solid #16a34a;
  border-radius: 8px;
}
.admin-cadence-group {
  border: 1px solid var(--line, var(--border));
  border-radius: 8px;
  margin-top: 8px;
  background: var(--surface-1, #fff);
}
.admin-cadence-group > summary {
  padding: 8px 12px;
  font: 600 11px/1.3 var(--font-body);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-muted);
  cursor: pointer;
  user-select: none;
  list-style: none;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
}
.admin-cadence-group > summary::-webkit-details-marker { display: none; }
.admin-cadence-group > summary::after {
  content: "\25B8";
  font-size: 10px;
  color: var(--text-faint);
  transition: transform var(--duration-fast, 120ms) ease;
}
.admin-cadence-group[open] > summary::after { transform: rotate(90deg); }
.admin-cadence-group .admin-cadence-count {
  margin-left: auto;
  font: 600 10px/1 var(--font-mono);
  color: var(--text);
}
.admin-cadence-group .admin-cadence-body {
  border-top: 1px solid var(--line, var(--border));
  max-height: 320px;
  overflow-y: auto;
  padding: 4px 0;
}
.admin-cadence-group .admin-cadence-row {
  display: grid;
  grid-template-columns: 1fr 1fr auto;
  gap: 6px;
  padding: 5px 12px;
  font: 500 11px/1.3 var(--font-mono);
  align-items: center;
}
.admin-cadence-group .admin-cadence-row:hover { background: var(--surface-3, var(--bg-elev)); }
.admin-cadence-group .admin-cadence-row .layer {
  color: var(--text-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.admin-cadence-group .admin-cadence-row .age {
  color: var(--text-faint);
  font-size: 10.5px;
  text-align: right;
}

/* --- micro-actions (copy / open / why) --------------------- */
.admin-action-pill {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  appearance: none;
  border: 1px solid var(--line, var(--border));
  background: var(--surface-1, #fff);
  font: 500 10px/1 var(--font-body);
  padding: 3px 7px;
  border-radius: 4px;
  cursor: pointer;
  color: var(--text-muted);
  opacity: 0.55;
  transition: opacity var(--duration-fast, 120ms) ease,
              color var(--duration-fast, 120ms) ease,
              border-color var(--duration-fast, 120ms) ease;
}
*:hover > .admin-action-pill,
tr:hover .admin-action-pill,
.admin-block:hover .admin-action-pill { opacity: 1; }
.admin-action-pill:hover {
  color: var(--text);
  border-color: var(--text-muted);
}
.admin-action-pill:focus-visible {
  outline: 2px solid var(--gold, #d4a84b);
  outline-offset: 1px;
  opacity: 1;
}
.admin-action-pill[data-copied="1"] {
  color: #16a34a;
  border-color: rgba(22, 163, 74, 0.4);
  opacity: 1;
}

/* --- "Why?" info dot --------------------------------------- */
.admin-why {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 13px; height: 13px;
  border-radius: 50%;
  font: 600 9px/1 var(--font-body);
  background: var(--surface-3, var(--bg-elev));
  color: var(--text-muted);
  margin-left: 6px;
  cursor: help;
  user-select: none;
  border: 1px solid var(--line, var(--border));
  vertical-align: 1px;
}
.admin-why:hover { color: var(--text); }

/* --- big stat (Stripe-style) for Pipeline status ---------- */
.admin-bignum-row {
  display: flex;
  gap: 12px;
  align-items: flex-end;
  margin: 6px 0 0;
}
.admin-bignum {
  flex: 1 1 auto;
  padding: 10px 12px;
  background: var(--surface-1, #fff);
  border: 1px solid var(--line, var(--border));
  border-radius: 8px;
}
.admin-bignum-eyebrow {
  font: 600 9.5px/1 var(--font-body);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.admin-bignum-value {
  font: 700 24px/1 var(--font-mono);
  font-variant-numeric: tabular-nums;
  color: var(--text);
  margin-top: 6px;
  letter-spacing: -0.01em;
}
.admin-bignum-sub {
  font: 500 11px/1.2 var(--font-body);
  color: var(--text-faint);
  margin-top: 2px;
}

/* --- typography tightening across admin -------------------- */
.admin-panel,
.admin-panel * { -webkit-font-smoothing: antialiased; }
.admin-num, .admin-mono { font-variant-numeric: tabular-nums; }
.admin-stat-value { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.admin-table th {
  font: 600 9.5px/1.3 var(--font-body);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-muted);
}

/* --- "Why?" popover (anchored, lightweight) --------------- */
.admin-pop {
  position: absolute;
  z-index: 50;
  max-width: 340px;
  padding: 10px 12px;
  background: var(--surface-1, #fff);
  border: 1px solid var(--line-strong, var(--border-strong));
  border-radius: 8px;
  box-shadow: 0 10px 30px -10px rgba(0,0,0,0.18),
              0 2px 6px rgba(0,0,0,0.06);
  font: 500 11.5px/1.4 var(--font-body);
  color: var(--text);
}
.admin-pop-eyebrow {
  font: 600 9.5px/1 var(--font-body);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: 6px;
}
.admin-pop-sql {
  font: 500 10.5px/1.4 var(--font-mono);
  color: var(--text-muted);
  background: var(--surface-3, var(--bg-elev));
  border: 1px solid var(--line, var(--border));
  border-radius: 4px;
  padding: 6px 8px;
  margin-top: 6px;
  white-space: pre-wrap;
  word-break: break-word;
  max-height: 180px;
  overflow-y: auto;
}
