/* City of Raleigh — Housing Landscape — shared styles
   Brand tokens from the raleigh-branding skill. Fonts: Calibri (approved City
   body face) with system fallbacks; no Arial per brand guidance. */

:root {
  --raleigh-green: #0D6937;
  --leaf-green:    #73AB45;
  --mid-green:     #4C8C40;
  --chartreuse:    #A8C23E;
  --teal:          #189ABC;
  --navy:          #01426A;
  --amber:         #FBAE40;
  --body-text:     #414042;
  --border:        #BFBFBF;
  --light-fill:    #F2F2F2;
  --green-tint:    #DAEFD3;
  --green-tint-alt:#F3F9EF;
  --white:         #FFFFFF;
  --muted-text:    #595959;   /* passes 4.5:1 on white and on the light fill */
  --header-h: 60px;
  --font-body: Calibri, "Segoe UI", Candara, "Trebuchet MS", sans-serif;
}

* { box-sizing: border-box; }
html, body { margin: 0; }
body {
  font-family: var(--font-body);
  color: var(--body-text);
  background: var(--light-fill);
}
/* Sticky header offset target so anchor jumps clear the fixed header. */
[id] { scroll-margin-top: calc(var(--header-h) + 8px); }

/* --- Welcome / onboarding modal -------------------------------------------- */
.welcome-overlay {
  display: none; position: fixed; inset: 0; background: rgba(20, 30, 20, .55);
  z-index: 1000; align-items: center; justify-content: center; padding: 20px;
}
.welcome-overlay.open { display: flex; }
.welcome-modal {
  position: relative; background: var(--white); border-radius: 10px;
  width: 100%; max-width: 620px; max-height: 85vh; overflow-y: auto;
  box-shadow: 0 12px 40px rgba(0,0,0,.35); padding: 32px 32px 20px;
  border-top: 8px solid var(--raleigh-green);
}
/* Per-section "About" boxes. These replaced the multi-step welcome pop-up, so the
   guidance stays reachable next to the content it describes. Built on <details>
   so collapsing needs no JS and keyboard/screen-reader behaviour comes free. */
.info-wrap { max-width: 1400px; margin: 0 auto; padding: 0 24px; }
.info-box {
  background: var(--green-tint-alt);
  border: 1px solid var(--green-tint); border-left: 4px solid var(--raleigh-green);
  border-radius: 6px; padding: 0 16px; margin: 14px 0 6px;
}
.info-box > summary {
  cursor: pointer; list-style: none; padding: 12px 0;
  font-size: 1rem; font-weight: 700; color: var(--raleigh-green);
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
}
.info-box > summary::-webkit-details-marker { display: none; }
.info-box > summary::after { content: "Show"; font-size: .72rem; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; color: var(--muted-text); }
.info-box[open] > summary::after { content: "Hide"; }
.info-box > summary:hover { text-decoration: underline; }
.info-box-body { padding: 0 0 14px; font-size: .9rem; line-height: 1.55; }
.info-box-body p { margin: 0 0 10px; }
.info-box-body p:last-child { margin-bottom: 0; }
.info-box-body ul { margin: 0 0 10px; padding-left: 20px; }
.info-box-body li { margin-bottom: 3px; }
.info-subhead { font-weight: 700; color: var(--raleigh-green); margin-bottom: 4px !important; }
.info-cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 4px 24px; }

/* 2020 Bond section: one status filter governs the project-level widgets. Cards
   whose source has no complete/pipeline dimension are badged so it is obvious
   they are not responding to the filter rather than appearing broken. */
.bond-filter-bar {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  background: var(--green-tint-alt); border: 1px solid var(--green-tint);
  border-radius: 6px; padding: 10px 14px; margin-top: 4px;
}
.bond-filter-bar label { font-size: .9rem; }
.bond-filter-bar select { padding: 6px 8px; font: inherit; font-size: .85rem; border: 1px solid var(--border); border-radius: 4px; }
.bond-filter-note { font-size: .78rem; color: var(--muted-text); flex: 1 1 260px; }
.status-badge {
  display: inline-block; vertical-align: middle; margin-left: 6px;
  font-size: .68rem; font-weight: 600; letter-spacing: .02em; text-transform: uppercase;
  color: var(--muted-text); background: var(--light-fill); border: 1px solid var(--border);
  border-radius: 10px; padding: 2px 8px;
}
.status-badge-live { color: var(--raleigh-green); background: var(--green-tint); border-color: var(--leaf-green); }

/* Reconciliation dialog — same shell as the welcome modal, but wider (it holds a
   table) and independent of the welcome flow's step/panel logic. */
.info-overlay {
  display: none; position: fixed; inset: 0; background: rgba(20, 30, 20, .55);
  z-index: 1000; align-items: center; justify-content: center; padding: 20px;
}
.info-overlay.open { display: flex; }
.info-modal {
  position: relative; background: var(--white); border-radius: 10px;
  width: 100%; max-width: 900px; max-height: 85vh; overflow-y: auto;
  box-shadow: 0 12px 40px rgba(0,0,0,.35); padding: 32px 32px 24px;
  border-top: 8px solid var(--raleigh-green);
}
.info-modal h2 { color: var(--raleigh-green); font-size: 1.2rem; margin: 0 0 12px; }
.info-modal p { margin: 0 0 14px; line-height: 1.5; font-size: .92rem; }
.recon-table { width: 100%; border-collapse: collapse; font-size: .82rem; }
.recon-table th, .recon-table td { padding: 7px 9px; border-bottom: 1px solid var(--border); text-align: right; }
.recon-table th:first-child, .recon-table td:first-child { text-align: left; }
.recon-table thead th { background: var(--green-tint-alt); color: var(--raleigh-green); font-weight: 600; }
.recon-table tbody tr:last-child td { border-bottom: none; }
.recon-table .recon-pos { color: #0D6937; }
.recon-table .recon-neg { color: #A8322D; }

.welcome-close {
  position: absolute; top: 14px; right: 16px; border: none; background: none;
  font-size: 1.6rem; line-height: 1; color: #888; cursor: pointer; padding: 4px 8px;
}
.welcome-close:hover { color: var(--raleigh-green); }
.welcome-panel { display: none; }
.welcome-panel.active { display: block; }
.welcome-panel h2 { color: var(--raleigh-green); font-size: 1.3rem; margin: 0 0 14px; }
.welcome-panel p { margin: 0 0 12px; line-height: 1.5; font-size: .92rem; }
.welcome-panel ul { margin: 0 0 12px; padding-left: 22px; }
.welcome-panel li { margin-bottom: 4px; font-size: .92rem; line-height: 1.45; }
.welcome-subhead { font-weight: 700; color: var(--raleigh-green); margin: 16px 0 6px !important; }
.welcome-agree-row {
  display: flex; align-items: center; gap: 10px; font-size: .9rem; font-weight: 600;
  color: var(--raleigh-green); background: var(--green-tint-alt); border: 1px solid var(--green-tint);
  border-radius: 4px; padding: 10px 12px; margin-top: 8px; cursor: pointer;
}
.welcome-agree-row input { width: 16px; height: 16px; flex: 0 0 auto; cursor: pointer; }
/* Single-panel dialog now, so the footer just right-aligns the one button. */
.welcome-footer {
  display: flex; align-items: center; justify-content: flex-end; gap: 12px;
  border-top: 1px solid var(--light-fill); margin-top: 20px; padding-top: 16px;
}
.welcome-buttons { display: flex; gap: 8px; }
.welcome-buttons button:disabled { opacity: .5; cursor: not-allowed; }

/* --- Header --------------------------------------------------------------- */
.app-header {
  height: var(--header-h);
  background: var(--raleigh-green);
  color: var(--white);
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 0 18px;
  border-bottom: 4px solid var(--leaf-green);
  position: sticky;
  top: 0;
  z-index: 30;
}
.app-header img.logo { height: 40px; width: auto; display: block; background: var(--white); padding: 3px 8px; border-radius: 3px; }
.app-header .title { font-size: 1.15rem; font-weight: 700; letter-spacing: .2px; line-height: 1.1; }
.app-header .title small { display: block; font-weight: 400; font-size: .72rem; opacity: .9; }
.app-header nav { margin-left: auto; display: flex; gap: 6px; }
.app-header nav a {
  color: var(--white); text-decoration: none; font-size: .9rem; font-weight: 600;
  padding: 7px 14px; border-radius: 4px; opacity: .85;
}
.app-header nav a:hover { opacity: 1; background: rgba(255,255,255,.14); }
/* Was white on leaf green, 2.75:1. The current section is now marked with a
   rule under it instead, which leaves the text white on the masthead's own dark
   green at 6.2:1. WCAG 1.4.3. */
.app-header nav a.active {
  opacity: 1; background: transparent; font-weight: 700;
  box-shadow: inset 0 -3px 0 0 var(--chartreuse);
  border-radius: 4px 4px 0 0;
}

/* Keyboard focus. The browser default is faint and disappears entirely on the
   green masthead, so every focusable thing gets the same ring, and anything
   focused is scrolled clear of the sticky masthead. WCAG 2.4.7 and 2.4.11. */
:focus-visible {
  outline: 3px solid var(--raleigh-green);
  outline-offset: 2px;
  border-radius: 3px;
  scroll-margin-top: calc(var(--header-h) + 14px);
}
.app-header a:focus-visible, .sidebar-handle:focus-visible {
  outline-color: var(--white);
}
.sidebar:focus-visible { outline-offset: -3px; }

/* Off screen until it is tabbed to. WCAG 2.4.1. */
.skip-link {
  position: absolute; left: 8px; top: -60px; z-index: 60;
  background: var(--white); color: var(--raleigh-green);
  font-weight: 700; font-size: .9rem; padding: 10px 14px;
  border: 2px solid var(--raleigh-green); border-radius: 0 0 6px 6px;
  transition: top .12s ease-out;
}
.skip-link:focus { top: 0; }

/* --- Layout: map section (sidebar + map), then dashboard below ----------- */
.map-section {
  display: flex;
  height: calc(100vh - var(--header-h) - 4px);
  min-height: 520px;
  border-bottom: 10px solid var(--leaf-green);
}
.sidebar {
  width: 340px; flex: 0 0 340px; background: var(--white);
  border-right: 1px solid var(--border); overflow-y: auto; padding: 0;
}
/* Column flex so the attribute table can dock under the map and take real
   layout space instead of covering it. arcgis-map was absolutely positioned;
   as a flex child it needs min-height:0 or it refuses to shrink below its
   content height and pushes the dock off the bottom of the section. */
.main { flex: 1 1 auto; position: relative; min-width: 0; display: flex; flex-direction: column; }
.main > arcgis-map { position: relative; inset: auto; flex: 1 1 auto; min-height: 0; }

/* ---- attribute table dock (Census choropleths) ------------------------- */
#attrDock {
  flex: 0 0 auto; height: 300px; display: flex; flex-direction: column;
  background: var(--white); border-top: 3px solid var(--leaf-green);
}
#attrDock[hidden] { display: none; }
#attrDockBar {
  flex: 0 0 auto; display: flex; align-items: center; gap: 8px;
  padding: 5px 10px; border-bottom: 1px solid var(--border); background: #f7f7f5;
}
#attrDockTabs { display: flex; gap: 4px; flex: 1 1 auto; min-width: 0; overflow-x: auto; }
#attrDockTabs button {
  font: inherit; font-size: .78rem; padding: 4px 10px; cursor: pointer;
  border: 1px solid var(--border); border-radius: 4px 4px 0 0;
  background: #fff; color: var(--muted-text); white-space: nowrap;
}
#attrDockTabs button[aria-selected="true"] {
  background: var(--raleigh-green); border-color: var(--raleigh-green); color: #fff; font-weight: 600;
}
#attrDockClose {
  font: inherit; font-size: .75rem; padding: 4px 9px; cursor: pointer;
  border: 1px solid var(--border); border-radius: 4px; background: #fff; color: var(--muted-text);
}
#attrDockBody { flex: 1 1 auto; min-height: 0; position: relative; }
/* One table container per layer, stacked; only the selected tab is shown. */
#attrDockBody > div { position: absolute; inset: 0; }
#attrDockBody > div[hidden] { display: none; }

/* Section heading strip that separates the map from the dashboard. Sticky
   under the app header; the second one (dashboard) is later in the DOM so
   it visually takes over the fixed spot once scrolled up to meet it. */
.section-band {
  background: var(--white); border-bottom: 1px solid var(--border);
  padding: 14px 24px 12px;
  position: sticky; top: var(--header-h); z-index: 20;
}
.section-band h1 { color: var(--raleigh-green); font-size: 1.4rem; margin: 0 0 2px; }
.section-band p { margin: 0; color: var(--muted-text); font-size: .88rem; }

/* --- Sidebar sections ---------------------------------------------------- */
.panel-section { padding: 14px 16px; border-bottom: 1px solid var(--light-fill); }
.panel-section h2 {
  margin: 0 0 10px; font-size: .78rem; text-transform: uppercase; letter-spacing: .6px;
  color: var(--raleigh-green); border-left: 3px solid var(--leaf-green); padding-left: 8px;
}
.panel-intro { font-size: .82rem; line-height: 1.4; color: var(--body-text); }
.field { margin-bottom: 12px; }
.field-row { display: flex; gap: 10px; }
.field-row .field { flex: 1 1 0; min-width: 0; }
.field label { display: block; font-size: .8rem; font-weight: 600; margin-bottom: 4px; }
.field select, .field input[type="text"] {
  width: 100%; padding: 7px 8px; font: inherit; font-size: .85rem;
  border: 1px solid var(--border); border-radius: 4px; background: var(--white); color: var(--body-text);
}
/* WCAG 2.2 2.5.8: the box and its row are a 24px target, which also makes them
   easier to hit on a phone. */
.checks label {
  display: flex; align-items: center; gap: 8px; font-size: .85rem;
  margin-bottom: 4px; padding: 4px 2px; min-height: 24px; cursor: pointer;
}
.checks input[type="checkbox"], .checks input[type="radio"] {
  width: 18px; height: 18px; flex: 0 0 auto; accent-color: var(--raleigh-green);
}
/* Any/All segmented control, on the label row of the filter it governs so its
   scope is unambiguous. Paired with the field label via aria-labelledby. */
.field-head { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-bottom: 6px; }
.field-head label { margin-bottom: 0; }
.seg-caption { font-size: .72rem; color: var(--muted-text); text-transform: uppercase; letter-spacing: .03em; margin-left: auto; }
.seg { display: inline-flex; border: 1px solid var(--border); border-radius: 4px; overflow: hidden; }
.seg-btn {
  font: inherit; font-size: .76rem; font-weight: 600; line-height: 1;
  padding: 5px 10px; border: none; background: var(--white); color: var(--muted-text); cursor: pointer;
}
.seg-btn + .seg-btn { border-left: 1px solid var(--border); }
.seg-btn:hover { background: var(--green-tint-alt); color: var(--raleigh-green); }
.seg-btn.is-active { background: var(--raleigh-green); color: var(--white); }
.btn-row { display: flex; gap: 8px; margin-top: 6px; }
button.btn {
  font: inherit; font-weight: 600; font-size: .82rem; cursor: pointer;
  border: 1px solid var(--raleigh-green); background: var(--raleigh-green); color: var(--white);
  padding: 7px 12px; border-radius: 4px;
}
button.btn.secondary { background: var(--white); color: var(--raleigh-green); }
button.btn:hover { filter: brightness(1.08); }
/* Jump-to-charts: centered, tight green frame (same font size) */
#jumpBtn { display: block; margin: 10px auto 0; padding: 4px 12px; }

/* --- Dual-range slider (City funding amount) ----------------------------- */
.range-wrap { position: relative; height: 26px; margin: 8px 2px 4px; }
.range-wrap .range-track, .range-wrap .range-fill {
  position: absolute; top: 11px; height: 4px; border-radius: 2px;
}
.range-wrap .range-track { left: 0; right: 0; background: var(--border); }
.range-wrap .range-fill  { background: var(--leaf-green); }
.range-wrap input[type="range"] {
  position: absolute; left: 0; top: 0; width: 100%; height: 26px; margin: 0;
  -webkit-appearance: none; appearance: none; background: none; pointer-events: none;
}
.range-wrap input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none; pointer-events: auto; cursor: pointer;
  width: 15px; height: 15px; border-radius: 50%; background: var(--raleigh-green);
  border: 2px solid #fff; box-shadow: 0 0 2px rgba(0,0,0,.45);
}
.range-wrap input[type="range"]::-moz-range-thumb {
  pointer-events: auto; cursor: pointer; width: 15px; height: 15px; border-radius: 50%;
  background: var(--raleigh-green); border: 2px solid #fff;
}
.range-wrap input[type="range"]::-moz-range-track { background: none; }
.range-inputs { display: flex; align-items: center; gap: 6px; margin-top: 2px; }
.range-inputs input[type="number"] {
  width: 100%; padding: 6px 7px; font: inherit; font-size: .82rem;
  border: 1px solid var(--border); border-radius: 4px; color: var(--body-text);
}
.range-inputs span { font-size: .78rem; color: var(--muted-text); }
.range-label { font-size: .74rem; color: var(--raleigh-green); font-weight: 700; margin-top: 4px; }

.legend-item { display: flex; align-items: center; gap: 8px; font-size: .82rem; margin-bottom: 6px; }
.swatch { width: 14px; height: 14px; border-radius: 50%; flex: 0 0 auto; border: 1px solid rgba(0,0,0,.25); }

.note {
  font-size: .74rem; color: var(--muted-text); line-height: 1.35; background: var(--green-tint-alt);
  border: 1px solid var(--green-tint); border-radius: 4px; padding: 8px 10px; margin-top: 8px;
}
.note ul { margin: 6px 0 0; padding-left: 16px; }
.count-pill {
  display: inline-block; background: var(--green-tint); color: var(--raleigh-green);
  border-radius: 10px; padding: 1px 9px; font-size: .78rem; font-weight: 700; margin-left: 6px;
}

/* --- Popups -------------------------------------------------------------- */
.pop table { border-collapse: collapse; width: 100%; font-size: .82rem; }
.pop td { padding: 2px 6px; vertical-align: top; }
.pop td.k { color: var(--muted-text); white-space: nowrap; }
.pop .ami-bar { display:flex; height: 10px; border-radius: 3px; overflow: hidden; margin: 4px 0; }

/* --- Dashboard ----------------------------------------------------------- */
.dash-wrap { width: 100%; max-width: 1500px; margin: 0 auto; padding: 20px 24px 60px; }
.dash-wrap h1 { color: var(--raleigh-green); font-size: 1.5rem; margin: 4px 0 2px; }
/* Source-of-truth / caveat badges shown under widgets. */
.src-badge {
  display: inline-block; font-size: .68rem; font-weight: 700; letter-spacing: .3px;
  text-transform: uppercase; color: var(--raleigh-green); background: var(--green-tint);
  border-radius: 10px; padding: 2px 9px; margin-top: 8px;
}
.caveat {
  font-size: .72rem; color: #8a5a00; line-height: 1.35; background: #FFF7E6;
  border: 1px solid #F3D08A; border-radius: 4px; padding: 7px 9px; margin-top: 8px;
}

/* EXTERNAL build: strip the source / caveat boxes that run horizontally above
 * each chart section, keeping only the quarterly-update note (#citywideCaveat).
 * These are hidden rather than removed from the DOM so the chart code can still
 * write into #distCaveat / #fundingCaveat / #pipelineCaveat / #bondCaveat
 * without needing a null guard at every call site.
 *
 * A caveat marked .card-note lives inside a card and documents that card's own
 * content rather than sourcing the section, so it is kept on both builds.
 * (Marked with a class rather than matched by nesting: :not(#citywideCaveat)
 * carries ID specificity, which a `.card .caveat` override would lose to.) */
body.hide-source-notes .src-badge,
body.hide-source-notes .caveat:not(#citywideCaveat):not(.card-note) { display: none !important; }

/* Build identity badge in the masthead. */
.version-badge {
  display: inline-block; vertical-align: middle; margin-left: 10px;
  font-size: .62rem; font-weight: 700; letter-spacing: .6px; text-transform: uppercase;
  border-radius: 10px; padding: 3px 9px; white-space: nowrap;
}
.version-badge.version-public   { background: var(--green-tint); color: var(--raleigh-green); border: 1px solid var(--leaf-green); }
.version-badge.version-internal { background: #FDECEA; color: #A8322D; border: 1px solid #A8322D; }
.dash-wrap .sub { color: var(--muted-text); font-size: .9rem; margin-bottom: 18px; }
/* min(150px, 100%) rather than a flat 150px: in a narrow card three counters
   cannot each be 150px wide, and the old rule let the figures run out past the
   tile instead of letting the tiles shrink. Reported 23 September 2026 on the
   bond gauge, where $77,575,867 was cut off mid-number. */
.kpi-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(150px, 100%), 1fr)); gap: 14px; margin-bottom: 22px; }
.kpi {
  background: var(--white); border: 1px solid var(--border); border-top: 4px solid var(--leaf-green);
  border-radius: 6px; padding: 14px 16px;
}
/* The figure shrinks with the tile rather than overflowing it, and a very long
   one wraps instead of being clipped. */
.kpi .num {
  font-size: clamp(1.15rem, 3.6vw, 1.8rem); font-weight: 800; color: var(--raleigh-green);
  line-height: 1.05; overflow-wrap: anywhere;
}
.kpi .lbl { font-size: .78rem; color: #555; margin-top: 6px; }
.card-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(340px, 1fr)); gap: 18px; }
.card { background: var(--white); border: 1px solid var(--border); border-radius: 6px; padding: 16px 18px; }
.card h3 { margin: 0 0 12px; font-size: 1rem; color: var(--raleigh-green); }
.card .chart-box { position: relative; width: 100%; height: 280px; }
.card.wide { grid-column: 1 / -1; }

/* A chart with its counters beside it rather than stacked above. The chart takes
   the room it needs to stay readable; the counters take a fixed, narrower column
   and stack one on top of the other. Collapses back to one column on narrow
   screens, where side by side would squeeze both. */
.split-chart-kpis { display: grid; grid-template-columns: minmax(0, 2fr) minmax(190px, 0.8fr); gap: 20px; align-items: start; }
.split-chart-kpis .kpi-row { margin-bottom: 0; }
.kpi-stack { grid-template-columns: 1fr; }
@media (max-width: 760px) { .split-chart-kpis { grid-template-columns: 1fr; } }

/* Dashboard data table (yearly + total sums) */
.data-table { width: 100%; border-collapse: collapse; font-size: .82rem; }
.data-table th, .data-table td { padding: 6px 8px; border-bottom: 1px solid var(--light-fill); text-align: right; white-space: nowrap; }
.data-table th { color: var(--raleigh-green); border-bottom: 2px solid var(--leaf-green); }
.data-table th:first-child, .data-table td:first-child { text-align: left; position: sticky; left: 0; background: var(--white); }
.data-table td.total-col, .data-table th.total-col { font-weight: 800; color: var(--raleigh-green); background: var(--green-tint-alt); }
.data-table tr.total-row td { font-weight: 800; border-top: 2px solid var(--leaf-green); }
.table-scroll { overflow-x: auto; overflow-y: auto; max-height: 400px; }
.card.bond { border-top: 4px solid var(--amber); }

.footer-note {
  font-size: .72rem; color: var(--muted-text); padding: 14px 16px; line-height: 1.4;
  border-top: 1px solid var(--light-fill);
}

/* ---- attribute table contents (Census choropleth dock) ------------------ */
.attr-meta {
  padding: 5px 10px; font-size: .74rem; color: #555;
  border-bottom: 1px solid var(--border); background: #fcfcfb;
}
.attr-scroll { position: absolute; inset: 27px 0 0 0; overflow: auto; }
.attr-table { border-collapse: collapse; width: 100%; font-size: .76rem; }
.attr-table th, .attr-table td {
  padding: 3px 10px; text-align: left; border-bottom: 1px solid #eee; white-space: nowrap;
}
.attr-table th {
  position: sticky; top: 0; z-index: 1; cursor: pointer; user-select: none;
  background: #f2f4f0; color: var(--raleigh-green); font-weight: 600;
  border-bottom: 1px solid var(--border);
}
.attr-table th.sorted { background: #e6ece1; }
.attr-table th.n, .attr-table td.n { text-align: right; font-variant-numeric: tabular-nums; }
.attr-table tbody tr:nth-child(even) { background: #fafafa; }
.attr-table tbody tr:hover { background: #eef4ea; }
.attr-table .nd { color: #999; font-style: italic; }


/* ==========================================================================
   Small screens: phones, small Chromebooks, and tablets held upright.
   Checked at 360x640, 390x844, 768x1024, 820x1180, 844x390 and 932x430 on
   22 September 2026, after the dashboard went live and was reached from a
   phone. Below roughly 900px the 340px filter panel left a phone about 50px of
   map, and the masthead links pushed the whole page sideways.

   The panel now slides over the map instead of sitting beside or below it, and
   the map keeps the full width and height of the section either way.
   ========================================================================== */
/* Hidden at every size but the ones below, where the stylesheet lays the panel
   over the map. The button is always in the page; only this decides if it shows. */
.sidebar-handle { display: none; }

@media (max-width: 900px) {
  .map-section {
    position: relative;
    flex-direction: column;
    height: auto;
    min-height: 0;
    overflow: hidden;              /* the panel slides out of view, not the page */
  }
  .main { height: 72vh; min-height: 300px; }

  .sidebar {
    position: absolute; top: 0; bottom: 0; left: 0; z-index: 8;
    width: min(86%, 360px); flex: 0 0 auto; max-width: none;
    border-right: 1px solid var(--border);
    box-shadow: 4px 0 14px rgba(0,0,0,.18);
    overflow-y: auto; -webkit-overflow-scrolling: touch;
    transform: translateX(-102%);
    transition: transform .22s ease-out;
  }
  .map-section[data-panel="open"] .sidebar { transform: none; }

  /* The tab that opens it, on the left edge of the map. It travels with the
     panel, so the control that opened it is the control that closes it. */
  .sidebar-handle {
    position: absolute; top: 12px; left: 0; z-index: 9;
    display: flex !important; align-items: center; gap: 6px;
    font: inherit; font-size: .82rem; font-weight: 700; cursor: pointer;
    padding: 9px 11px; color: var(--white); background: var(--raleigh-green);
    border: 0; border-radius: 0 6px 6px 0; box-shadow: 2px 2px 6px rgba(0,0,0,.25);
    transition: transform .22s ease-out;
  }
  .map-section[data-panel="open"] .sidebar-handle {
    transform: translateX(min(86vw, 360px));
    background: var(--mid-green);
  }
  .sidebar-handle-text { letter-spacing: .3px; }

  /* Someone who prefers less movement gets the same panel without the slide. */
  @media (prefers-reduced-motion: reduce) {
    .sidebar, .sidebar-handle { transition: none; }
  }
}

@supports (height: 100dvh) {
  @media (max-width: 900px) { .main { height: 72dvh; } }
}

/* A phone held sideways. The section carries a 520px floor for laptops, which is
   taller than the whole screen here, so the map ran off the bottom. The map
   takes what the screen has instead, and the masthead stays on one row. */
@media (orientation: landscape) and (max-height: 520px) {
  .map-section { min-height: 0; }
  .main { height: calc(100vh - var(--header-h) - 4px); min-height: 180px; }
  .app-header { height: var(--header-h); flex-wrap: nowrap; }
  .app-header nav { margin-left: auto; width: auto; }
  .app-header nav a { flex: 0 0 auto; }
  /* Sideways there is no room for a tall tab, and the panel needs every line. */
  .sidebar-handle { top: 8px; padding: 7px 10px; font-size: .78rem; }
}
@supports (height: 100dvh) {
  @media (orientation: landscape) and (max-height: 520px) {
    .main { height: calc(100dvh - var(--header-h) - 4px); }
  }
}

@media (max-width: 640px) {
  /* The masthead stops being one row. Without this the three section links run
     off the right edge and take the whole page with them. */
  .app-header {
    height: auto; min-height: var(--header-h);
    flex-wrap: wrap; row-gap: 4px; padding: 8px 12px;
  }
  .app-header img.logo { height: 30px; }
  .app-header .title { font-size: 1rem; }
  .app-header .title small { font-size: .68rem; }
  .app-header nav { margin-left: 0; width: 100%; gap: 4px; }
  .app-header nav a { flex: 1 1 0; text-align: center; font-size: .8rem; padding: 6px 4px; }
  /* A sticky band under a masthead that is now two rows tall would cover the
     content it labels. */
  .section-band { position: static; }
  .section-band h1 { font-size: 1.15rem; }
  .dash-wrap { padding-left: 12px; padding-right: 12px; }
  .card { padding: 12px 12px; }
  .kpi { padding: 11px 12px; }
  .kpi .num { font-size: clamp(1.05rem, 6vw, 1.45rem); }
  /* Two counters to a row rather than one very wide one. */
  .kpi-row { grid-template-columns: repeat(auto-fit, minmax(min(128px, 100%), 1fr)); gap: 10px; }
  .welcome-modal, .info-modal { padding: 16px 14px; max-height: 88vh; }
  /* A fixed-height chart is unreadable on a narrow screen when it also has to
     hold a legend. */
  .card .chart-box { height: 240px; }
}

/* Nothing on the page may push it sideways; wide tables scroll inside their
   own box instead. */
html, body { overflow-x: hidden; }
@supports (overflow-x: clip) { html, body { overflow-x: clip; } }

/* Shown in the map's place only if a build sets UI.mapUnavailableHtml. Empty by
   default, so a browser that cannot run the map simply shows no map. */
.map-unavailable {
  margin: 14px; padding: 14px 16px; max-width: 640px;
  font-size: .9rem; line-height: 1.5; color: var(--body-text);
  background: var(--green-tint-alt); border-left: 4px solid var(--leaf-green); border-radius: 4px;
}
