/* ---------------------------------------------------------------------------
   Census Mobility Map — dark theme override
   ---------------------------------------------------------------------------
   This page is a Vite build dropped in from another repository, so it cannot
   be restyled at source from here. It shipped light — #f5f7fb page, white
   panels — which made it the only page on the site not in the same visual
   world as the rest, with the shared dark header bar sitting on top of it
   like it had been bolted on.

   Re-theming it from outside is cheap because the bundle is disciplined: all
   of its own color lives in eleven custom properties on :root, and its
   panels already read --panel / --border / --text / --shadow rather than
   hard-coding anything. Redefining those eight is most of the work. The rest
   of this file covers the handful of places that hard-code a light value —
   its own search box and results list, and MapLibre's bundled control CSS.

   The build links this after the bundle's own stylesheet, so equal-specificity
   :root wins on source order.

   The map itself is re-colored by `patches` in site.config.mjs: the basemap
   style URL and the line and tract colors are compiled into the JS bundle,
   out of reach of CSS. The line colors there must equal the legend swatches
   at the end of this file.
   --------------------------------------------------------------------------- */

:root {
  --bg:     #030712;                        /* --ob-bg */
  --panel:  var(--ob-panel);
  --border: var(--ob-panel-border);
  --text:   #f9fafb;                        /* --ob-fg */
  --muted:  rgba(249, 250, 251, 0.70);
  --orange: #fb923c;                        /* --ob-orange */
  --purple: #c084fc;                        /* --ob-purple */
  --shadow: var(--ob-panel-shadow);
}

/* --- the page's own light hold-outs --------------------------------------- */

.results {
  background: var(--panel);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
}

.result[aria-selected="true"],
.result:hover { background: rgba(192, 132, 252, 0.16); }

.searchbox input {
  background: rgba(255, 255, 255, 0.06);
  color: var(--text);
}

.searchbox input::placeholder { color: var(--muted); }

/* #111 on #fff was a dark button on a light page. On a dark panel it reads as
   a hole, so these take the same treatment ui.css gives a primary button:
   the accent as the fill, dark ink on top. */
.searchbox button,
.retry-btn,
.skip-link {
  background: var(--purple);
  color: #1a0b2e;
}

.retry-btn { border-color: transparent; }

/* The bundle shows the skip link at the top of the screen, under the header
   bar; it drops below the bar instead, as on the other maps. */
.skip-link:focus { top: calc(var(--ob-bar-h) + 8px); }

/* Form controls take the page font; left alone they render in the browser's
   default (Arial). */
button, input, select, textarea { font-family: inherit; }

/* --- MapLibre's own control CSS ------------------------------------------- */

.maplibregl-ctrl-group { background: #0c1220; }            /* --ob-surface-flat */
.maplibregl-ctrl-group button + button { border-top-color: var(--border); }
/* MapLibre's blue focus glow; brand.css's purple ring takes its place. */
.maplibregl-ctrl-group button:focus:focus-visible { box-shadow: none; }

/* The zoom and compass glyphs are dark SVGs meant for a white control. */
.maplibregl-ctrl-group button .maplibregl-ctrl-icon { filter: invert(1); }

.maplibregl-popup-content {
  background: #0c1220;
  color: var(--text);
}

.maplibregl-popup-anchor-top .maplibregl-popup-tip,
.maplibregl-popup-anchor-top-left .maplibregl-popup-tip,
.maplibregl-popup-anchor-top-right .maplibregl-popup-tip { border-bottom-color: #0c1220; }

.maplibregl-popup-anchor-bottom .maplibregl-popup-tip,
.maplibregl-popup-anchor-bottom-left .maplibregl-popup-tip,
.maplibregl-popup-anchor-bottom-right .maplibregl-popup-tip { border-top-color: #0c1220; }

.maplibregl-popup-anchor-left .maplibregl-popup-tip { border-right-color: #0c1220; }
.maplibregl-popup-anchor-right .maplibregl-popup-tip { border-left-color: #0c1220; }

.maplibregl-ctrl-scale {
  background-color: rgba(12, 18, 32, 0.75);
  border-color: var(--border);
  color: var(--text);
}

.maplibregl-ctrl-attrib,
.maplibregl-ctrl-attrib.maplibregl-compact {
  background: rgba(3, 7, 18, 0.82);
  color: var(--muted);
}

.maplibregl-ctrl-attrib a { color: var(--purple); }

/* --- credits and the legend ------------------------------------------------
   The page's own credit footer, a bar along the bottom that wrapped to three
   lines on a phone, is now the shared .ob-credits pill (brand.css) in the
   bottom-right corner. That leaves the bottom-left to the legend, which the
   bundle held 56px up to clear the old footer. On a phone the legend sits a
   row above the pill instead: open, it is wider than the space beside the
   pill, so it hides while the Layers panel is open (below). */
#legendCard { bottom: var(--ob-map-inset); }
@media (max-width: 768px) {
  #legendCard { bottom: var(--ob-credits-clear); }
  /* The legend stays open on a phone (map-panels.js), so while the Layers
     panel is open it steps aside rather than cover the
     Data card. */
  body:has(#menuBtn[aria-expanded="true"]) #legendCard { display: none; }
}

/* --- a narrower Layers column --------------------------------------------
   The bundle lets its cards grow to 460px, and the search row pushed them to
   about 370: a quarter of a laptop screen given to controls before any map.
   At 300px the layer toggles, two to a row, wrapped their labels, so they
   are one to a row, a list as on the bus lanes map. On a phone the bundle's own 86vw
   still applies. */
@media (min-width: 769px) {
  .panel { width: 300px; }
  .panel .card { max-width: none; }
  /* The panel and its Data card run down the left edge, past where the legend
     sits on a short screen, so with the panel open the legend moves to its
     right: still the bottom-left of the map. */
  .panel:not(.closed) ~ #legendCard { left: calc(var(--ob-map-inset) * 2 + 300px); }
}
.card .grid:has(> .check) { grid-template-columns: 1fr; gap: 6px; }

/* The Data card is a load monitor, not a control. Its heading is a group
   label and its lines are small and muted, so it reads as status under the
   panel. */
#dataPanel { padding: 8px 14px; }
#dataPanel h2 {
  margin: 0;
  font-size: 0.75rem;
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ob-muted);
}
#dataPanel .about-notes {
  margin-top: 8px; padding-top: 6px; border-top: 1px solid var(--ob-border);
  font-size: 0.75rem; color: var(--ob-muted);
}
#dataPanel .about-notes summary {
  min-height: var(--ob-control-h); display: flex; align-items: center;
  cursor: pointer; list-style: none; color: var(--ob-purple);
}
#dataPanel .about-notes summary::-webkit-details-marker { display: none; }
#dataPanel .about-notes summary::before { content: "\25B8"; margin-right: 0.35rem; }
#dataPanel .about-notes[open] summary::before { content: "\25BE"; }
#dataPanel .about-notes summary:focus-visible { outline: 2px solid var(--ob-purple); outline-offset: 2px; border-radius: 4px; }
#dataPanel .about-notes p { margin: 6px 0 0; line-height: 1.45; }
#dataPanel .loadrow { font-size: 0.75rem; color: var(--ob-muted); margin: 2px 0 0; }

/* --- the Layers panel's groups --------------------------------------------
   Each a <details> whose summary is styled like the legend's (below), with a
   small-caps heading like the card titles. map-panels.js folds the one marked
   data-phone-closed on a phone. */
.grp { margin-top: 10px; padding-top: 8px; border-top: 1px solid var(--ob-border); }
.grp > summary {
  min-height: 24px;
  font-size: 0.75rem; font-weight: 600; letter-spacing: 0.05em;
  text-transform: uppercase; color: var(--ob-muted);
}

/* --- the Data card: one status line, the three originals under Details ------ */
.status-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 4px; }
.status-line { margin: 0; font-size: 0.75rem; line-height: 1.4; color: var(--ob-muted); }
.status-line[data-state="loading"] { color: var(--ob-blue); }
.status-line[data-state="failed"] { color: var(--orange); }
.status-row .retry-btn { flex: none; width: auto; margin: 0; padding: 4px 10px; font-size: 0.75rem; border-radius: var(--ob-radius-sm); }
#dataPanel .status-details { margin-top: 4px; padding-top: 0; border-top: 0; }
#dataPanel #usWarn { margin-top: 4px; font-size: 0.75rem; }

/* --- the Data card's status lines -----------------------------------------
   "Loading rail…" and "Retry 3…" were #2563eb, a blue picked for a white
   panel: about 3:1 on the dark one, and nearer 1.5:1 where the map shows
   through it. The site's own blue, as on the rest of the page. The amber
   tract warning is set inline in the bundle's markup, so it needs
   !important to be reached at all. */
/* .loadrow in front: the bundle's own rule is .loadrow .status-text.loading,
   which outranked this one without it, so the first version never applied. */
.loadrow .status-text.loading { color: var(--ob-blue); }
#usWarn { color: var(--orange) !important; }

/* --- the shared panel kit -------------------------------------------------
   The same grammar as ui.css's .ob-panel, which Transit Fares' sidebar and
   the bus lanes map's panels also follow: one corner radius, one title style, group
   headings in small caps, legend rows at a readable size, and controls with
   the site's fill, edge and purple accent. Values come from the brand.css
   tokens, never restated here. */

.card,
#legendCard {
  border-radius: var(--ob-radius-panel);
  padding: 12px 14px;
}

/* The panel title, the map's name as on the bus lanes map; the page's h1. */
.card h1 {
  margin: 0;
  font-size: 0.875rem;
  font-weight: 600;
  line-height: 1.3;
}

.subtitle { margin-top: 2px; font-size: 0.75rem; color: var(--ob-muted); }
.card .label { font-size: 0.75rem; }

/* The legend is a <details> card, as on the bus lanes map: its heading folds it, and
   map-panels.js folds it on a phone at load. The heading is a group label, as
   "View options" is in Transit Fares' sidebar, since the card has no title. */
#legendCard summary,
.grp > summary {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  cursor: pointer;
  list-style: none;
}
#legendCard summary::-webkit-details-marker,
.grp > summary::-webkit-details-marker { display: none; }
#legendCard summary::after,
.grp > summary::after { content: "\25BE"; font-size: 0.6875rem; color: var(--ob-muted); }
#legendCard:not([open]) summary::after,
.grp:not([open]) > summary::after { content: "\25B8"; }
#legendCard[open] summary { margin-bottom: 6px; }
@media (pointer: coarse) {
  #legendCard summary, .grp > summary { min-height: var(--ob-control-h); }
  /* The panel's sliders, fields and retry button, which the bundle sizes for a mouse. */
  #opacity, #zoom { height: var(--ob-control-h); }
  #tractMetric, #zoomInput, #retryBtn { min-height: var(--ob-control-h); }
}
#legendCard summary:focus-visible,
.grp > summary:focus-visible { outline: 2px solid var(--purple); outline-offset: 2px; border-radius: 4px; }
#legendCard h2 {
  margin: 0;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ob-muted);
}

/* The bundle set legend rows at 10px, and 9px on a phone: under the size
   anything on this site is set at. 12px matches the other two apps. */
#legendCard { max-width: 260px; }
#legendCard .legend li {
  margin: 0;
  padding: 2px 0;
  gap: 8px;
  font-size: 0.75rem;
  line-height: 1.35;
}
#legendCard .legend .swatch {
  width: 14px;
  height: 10px;
  border-radius: 3px;
  border: 0;             /* a dark hairline drawn for a white card */
}

/* Which classes the legend shows (class-breaks.js), one line under the list. */
#legendCard .legend-note {
  margin: 6px 0 0;
  font-size: 0.75rem;
  line-height: 1.35;
  color: var(--ob-muted);
}
#legendCard .legend-note:empty { display: none; }
/* Said when there is nothing to color (panel.js writes why). */
#legendCard .legend-empty { margin: 0; font-size: 0.75rem; line-height: 1.4; color: var(--ob-muted); }

/* The bundle's .hint is 11px; the floor on this site is 12px. */
.hint { font-size: 0.75rem; }

/* Controls: the same fill, edge and radius as .ob-input. */
#tractMetric,
#zoomInput,
.searchbox input {
  background: var(--ob-surface-flat);
  color: var(--text);
  border: 1px solid var(--ob-control-border) !important;   /* #zoomInput sets its border inline */
  border-radius: var(--ob-radius-sm) !important;
  box-shadow: none;
}
#tractMetric { padding: 6px 8px; font-size: 0.8125rem; }
.searchbox input { padding: 8px 10px; }
.searchbox button { border-radius: var(--ob-radius-sm); box-shadow: none; }

input[type="range"],
input[type="checkbox"] { accent-color: var(--purple); }

/* Focus was drawn in two different blues. One purple ring, as everywhere
   else on the site. */
.menu-btn:focus,
input:focus-visible,
select:focus-visible,
.searchbox button:focus-visible,
.result:focus-visible,
#map:focus-visible { outline-color: var(--purple); }

/* The Layers panel takes focus itself when it opens on a phone (a patch in
   site.config.mjs). A keyboard is shown where focus went; a tap is not. */
/* The Layers panel and the Data card under it are taller than a short
   screen (a 768px-high laptop, a small phone), and the bundle gave the panel no
   way to scroll, so the lowest rows were out of reach. */
.panel { max-height: calc(100dvh - 56px - var(--ob-bar-h) - var(--ob-map-inset)); overflow-y: auto; overscroll-behavior: contain; }
.panel:focus { outline: none; }

/* The landmark around the map and its panels. Absolute and full-screen, so
   the map and panels are placed against the viewport as before. */
#main { position: absolute; inset: 0; }

/* The closed panel slides off-screen, but was still reachable by Tab, so
   focus landed on controls no one could see. Hidden once the slide ends. */
.panel { transition: transform .25s ease, visibility 0s; }
.panel.closed { visibility: hidden; transition: transform .25s ease, visibility 0s linear .25s; }
.panel:focus-visible {
  outline: 2px solid var(--purple);
  outline-offset: 2px;
  border-radius: var(--ob-radius-panel);
}

/* Zoom buttons: the same look as the bus lanes map's. */
.maplibregl-ctrl-group {
  border: 1px solid var(--ob-panel-border);
  border-radius: var(--ob-radius-sm);
  box-shadow: var(--ob-panel-shadow);
}

/* The legend's line swatches, in the map's line colors: map-theme.js sets
   the --line-* properties from its themes. Set per class rather than through
   --orange/--purple, which also color the buttons. A 2px swatch was hard to
   read at 12px. The panel stays dark in both themes, so in light each swatch
   sits on a chip of the light basemap's ground (--line-chip), as its line
   does, where dark green would otherwise vanish. */
:root { --bike-swatch-h: 3px; }
.line { background: var(--line-chip); border-radius: 3px; }
.line.track   { color: var(--line-track); }
.line.lane,
.line.shared  { color: var(--line-lane); }
.line.transit { color: var(--line-rail); }
.line.transit::after { height: 4px; box-shadow: 0 0 0 1px var(--line-ground); }
/* Shared lanes are dotted on the map, so their swatch is too. */
.line.shared::after {
  background: radial-gradient(circle, currentColor 1.5px, transparent 1.6px) 1px 50% / 6px 100% repeat-x;
}
html[data-map-theme="light"] .line::after { left: 3px; right: 3px; }

/* The Basemap control (.ob-seg in brand.css), sized to its label column. */
.ob-seg { align-self: flex-start; margin-top: 4px; }

/* --- one size for the controls, as on the other maps ---------------------- */

.menu-btn { min-height: var(--ob-control-h-lg); padding: 8px 14px; }
.searchbox input { min-height: var(--ob-control-h-lg); font-size: 0.875rem; }
.searchbox button { min-height: var(--ob-control-h-lg); }
.check { min-height: var(--ob-control-h); }
.maplibregl-ctrl-group button { width: var(--ob-control-h); height: var(--ob-control-h); }

/* On a phone the panel is 320px wide, as on the other two maps (the bundle's
   86vw made it 335px at 390), over a dimmed map. The bundle styles .backdrop
   in no way, so it was a transparent layer. */
@media (max-width: 768px) {
  .panel { width: 320px; max-width: calc(100vw - 2 * var(--ob-map-inset)); }
  /* Stop above the credits pill, so the last row is not under it. */
  .panel { max-height: calc(100dvh - 56px - var(--ob-bar-h) - var(--ob-credits-clear)); }
}
.backdrop { position: fixed; inset: 0; z-index: 1990; background: rgba(3, 7, 18, 0.6); }
.backdrop[hidden] { display: none; }

/* The basemap would not load: one notice, like the other maps. */
.map-notice[hidden] { display: none; }
.map-notice {
  position: fixed; top: calc(var(--ob-bar-h) + var(--ob-map-inset)); left: 50%; z-index: 9980;
  transform: translateX(-50%);
  max-width: calc(100vw - 2 * var(--ob-map-inset) - 120px);
  padding: 8px 12px; font-size: 0.8125rem;
  background: var(--ob-panel); color: var(--ob-fg);
  border: 1px solid var(--ob-panel-border); border-radius: var(--ob-radius-panel);
  box-shadow: var(--ob-panel-shadow);
}
/* On a phone the top-left corner holds the Layers button, so the notice sits just below it. */
@media (max-width: 768px) {
  .map-notice { left: var(--ob-map-inset); transform: none; max-width: calc(100vw - 2 * var(--ob-map-inset) - 64px); top: calc(var(--ob-bar-h) + var(--ob-map-inset) + var(--ob-control-h-lg) + 8px); }
  /* The open panel is where the notice would be. */
  body:has(.menu-btn[aria-expanded="true"]) .map-notice { display: none; }
}
