/* Traffic Violence Dashboard: a dashboard built on brand.css tokens and ui.css.

   A plain dark ground (no nebula), the title without the gradient, and color
   kept for the two modes. The mode colors are validated as a pair on --ob-bg
   (lightness band, color-vision separation, contrast), and never carry
   meaning alone: every dot sits beside a word.

   Layout: three columns when wide (summary and filters | map or trends |
   people and detail), each scrolling on its own inside the viewport. Below
   1200px it becomes one scrolling column with Map / People / Trends tabs, and
   a person's detail opens full screen. */

:root {
  /* The two modes keep their colors in both themes: the pair passes the
     lightness, color-vision and contrast checks on #030712 and on white. */
  --sd-ped: #ea580c;
  --sd-bike: #3b82f6;
  --sd-mixed: #6b7280;             /* a stack of both modes */
  --sd-side-w: 22rem;
  --sd-panel-w: 24rem;
}

/* Dark, the site's own ground, is the default. The light theme below is a
   full theme rather than only a basemap swap (the maps' convention), since a
   dashboard is mostly text, tables and charts. Its tokens are scoped to the
   dashboard, so the site header keeps the brand's dark bar. The choice is
   stored under the maps' key, ob-map-theme, and set on <html> as
   data-map-theme before first paint by js/theme.js. */
.sd-app, .sd-about {
  /* Set here, not only on <body>: an inherited color is resolved where it is
     declared, so text would otherwise keep the dark theme's ink in light. */
  color: var(--ob-fg);
  color-scheme: dark;
  --sd-line: var(--ob-border);
  --sd-raise: #0b1120;
  /* The side columns are raised off the map: their own surface, a firmer
     edge, and a shadow cast onto it. The dark basemap is near black, so the
     dark surface is a step lighter than the page. */
  --sd-shell: #0f1729;
  --sd-edge: rgba(148, 163, 184, 0.28);
  --sd-cast: rgba(0, 0, 0, 0.7);
  --sd-text2: #d1d5db;
  --sd-link-line: rgba(249, 250, 251, 0.35);
  --sd-map-bg: #0b0f19;
  --sd-tip: #111827;
  --sd-hover: rgba(255, 255, 255, 0.04);
  --sd-control-hover: #1f2937;
  --sd-disabled: #4b5563;
  --sd-rate-bg: rgba(192, 132, 252, 0.08);
  --sd-stroke: #030712;            /* a dot's outline */
  --sd-grid: rgba(148, 163, 184, 0.12);
  /* Bike network: the census map's dark-theme greens, drawn thin under the dots. */
  --sd-track: #86efac;
  --sd-lane: #14b8a6;
}

html[data-map-theme="light"] body.sd-page { background: #f5f6f8; }
html[data-map-theme="light"] .sd-app,
html[data-map-theme="light"] .sd-about {
  color-scheme: light;
  --ob-bg: #f5f6f8;
  --ob-fg: #111827;               /* 17:1 on white */
  --ob-muted: #4b5563;            /* 7.6:1 on white */
  --ob-border: #e3e6eb;
  --ob-control-border: #858d9b;   /* 3.3:1: a control's edge must clear 3:1 */
  --ob-surface-flat: #ffffff;
  --ob-purple: #7e22ce;           /* the accent, deepened to 7:1 for text and focus on white */
  --ob-panel: rgba(255, 255, 255, 0.95);
  --ob-panel-border: rgba(15, 23, 42, 0.14);
  --ob-panel-shadow: 0 6px 24px rgba(15, 23, 42, 0.12);
  --sd-raise: #ffffff;
  --sd-shell: #ffffff;
  --sd-edge: rgba(15, 23, 42, 0.2);
  --sd-cast: rgba(15, 23, 42, 0.28);
  --sd-text2: #374151;
  --sd-link-line: rgba(17, 24, 39, 0.35);
  --sd-map-bg: #e8eaed;
  --sd-tip: #ffffff;
  --sd-hover: rgba(15, 23, 42, 0.04);
  --sd-control-hover: #f1f3f5;
  --sd-disabled: #a1a8b3;
  --sd-rate-bg: rgba(126, 34, 206, 0.06);
  --ob-on-accent: #ffffff;
  --ob-credits-bg: rgba(255, 255, 255, 0.9);
  --sd-stroke: #1f2937;
  --sd-grid: rgba(15, 23, 42, 0.08);
  /* The census map's light-theme greens. */
  --sd-track: #166534;
  --sd-lane: #0891b2;
}
.sd-theme { display: flex; align-items: center; gap: 0.6rem; }

/* Other pages get border-box from Tailwind's preflight; this one loads no Tailwind. */
.sd-page *, .sd-page *::before, .sd-page *::after { box-sizing: border-box; }
/* `hidden` must win over the display a component sets (the legend's rows are flex). */
.sd-page [hidden] { display: none !important; }

.sd-page {
  margin: 0;
  background: var(--ob-bg);
  color: var(--ob-fg);
  font-family: var(--ob-font);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}
.sd-page p, .sd-page h1, .sd-page h2, .sd-page h3, .sd-page ul, .sd-page ol, .sd-page dl { margin: 0; }
.sd-page a { color: inherit; text-decoration-color: var(--sd-link-line, rgba(249, 250, 251, 0.35)); text-underline-offset: 0.2em; }
.sd-page a:hover { text-decoration-color: currentColor; }
.sd-page :focus-visible { outline: 2px solid var(--ob-purple); outline-offset: 2px; border-radius: 4px; }

/* --- shell --------------------------------------------------------------- */

.sd-app {
  display: grid;
  grid-template-columns: var(--sd-side-w) minmax(0, 1fr) var(--sd-panel-w);
  /* The left column's foot (theme, method, downloads) stays in view below
     its scrolling part; the map and the people run the full height. */
  grid-template-rows: minmax(0, 1fr) auto;
  height: calc(100dvh - var(--ob-bar-h));
}
.sd-side, .sd-panel, .sd-side-foot { background: var(--sd-shell); position: relative; z-index: 1000; }
.sd-side, .sd-panel { overflow-y: auto; overscroll-behavior: contain; }
.sd-side, .sd-side-foot { grid-column: 1; border-right: 1px solid var(--sd-edge); box-shadow: 8px 0 22px -6px var(--sd-cast); }
.sd-side { grid-row: 1; padding: 1.25rem 1.25rem 1rem; display: flex; flex-direction: column; gap: 1rem; }
/* The column scrolls; its blocks keep their height rather than shrinking to fit (which clipped the stats). */
.sd-side > * { flex-shrink: 0; }
.sd-panel { grid-column: 3; grid-row: 1 / 3; border-left: 1px solid var(--sd-edge); box-shadow: -8px 0 22px -6px var(--sd-cast); }
.sd-main { grid-column: 2; grid-row: 1 / 3; position: relative; display: flex; flex-direction: column; min-width: 0; min-height: 0; }

/* The view switch floats over the top of the map or trends. */
.sd-tabs { grid-column: 2; grid-row: 1; align-self: start; justify-self: center; margin-top: 0.75rem; z-index: 600; box-shadow: var(--ob-panel-shadow); }
.sd-tab--people { display: none; }
/* ob-seg styles aria-pressed; these are tabs, so the same look follows aria-selected. */
.sd-tabs button[aria-selected="true"] { background: var(--ob-purple); color: var(--ob-on-accent); font-weight: 600; }
/* The shared focus ring is the accent, which vanishes on a pressed (accent) button. */
.ob-seg button[aria-pressed="true"]:focus-visible,
.sd-tabs button[aria-selected="true"]:focus-visible { outline-color: var(--ob-on-accent); }
/* Controls inside a card are secondary to the view switch: a quieter pressed state. */
.sd-card-head .ob-seg button[aria-pressed="true"] { background: var(--sd-control-hover); color: var(--ob-fg);
  box-shadow: inset 0 -2px 0 var(--ob-purple); }
.sd-card-head .ob-seg button[aria-pressed="true"]:focus-visible { outline-color: var(--ob-purple); }
.sd-card-controls { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.sd-view { flex: 1; min-height: 0; }
.sd-app:not([data-view="map"]) .sd-view--map { display: none; }
.sd-app:not([data-view="trends"]) .sd-view--trends { display: none; }

/* --- type ---------------------------------------------------------------- */

.sd-head { display: flex; flex-direction: column; gap: 0.35rem; }
.sd-head .sd-lead { margin-top: 0.4rem; }
.sd-title { font-size: 1.6rem; font-weight: 800; letter-spacing: -0.02em; line-height: 1.15; text-wrap: balance; margin-top: 0.3rem; }
.sd-title--sm { font-size: 1.25rem; margin: 0; }
.sd-lead { margin-top: 0.75rem; font-size: 0.95rem; color: var(--sd-text2); }
.sd-h { font-size: 1rem; font-weight: 700; letter-spacing: -0.005em; }
.sd-note { font-size: 0.8rem; color: var(--ob-muted); line-height: 1.5; }
.sd-linkbtn { background: none; border: 0; padding: 0; color: inherit; font: inherit; cursor: pointer;
  text-decoration: underline; text-decoration-color: var(--sd-link-line); text-underline-offset: 0.2em; }
.sd-linkbtn:hover { text-decoration-color: currentColor; }

/* --- readout: what the map and list show, in a few lines ------------------ */

.sd-readout { display: flex; flex-direction: column; gap: 0.35rem; padding: 0.8rem 0.9rem;
  border: 1px solid var(--sd-line); border-radius: var(--ob-radius-sm); background: var(--sd-shell); }
.sd-page .sd-readout p { margin: 0; }
.sd-scope { font-size: 0.72rem; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ob-muted);
  text-wrap: balance; }
.sd-big { display: flex; align-items: baseline; flex-wrap: wrap; gap: 0 0.4rem; line-height: 1.05; }
#sd-count { font-size: 2.6rem; font-weight: 750; letter-spacing: -0.03em; }
.sd-big-unit { font-size: 1rem; font-weight: 600; }
.sd-atleast { font-size: 0.85rem; font-weight: 500; color: var(--ob-muted); }
.sd-pace { font-size: 0.85rem; color: var(--ob-muted); }
.sd-pace strong { color: var(--ob-fg); font-weight: 600; }
.sd-pace .up { color: var(--sd-ped); }
:root[data-map-theme="light"] .sd-pace .up { color: #c2410c; }
.sd-split { display: flex; flex-direction: column; gap: 0.35rem; margin-top: 0.2rem; }
.sd-split-bar { display: flex; height: 0.5rem; border-radius: 999px; overflow: hidden; background: var(--sd-line); }
.sd-split-bar span { display: block; height: 100%; transition: flex-basis 0.3s ease, opacity 0.2s; }
.sd-split-ped { background: var(--sd-ped); }
.sd-split-bike { background: var(--sd-bike); }
.sd-split-keys { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 0.1rem 0.5rem; }
.sd-split-key { display: inline-flex; align-items: center; gap: 0.35rem; padding: 0.15rem 0; background: none; border: 0;
  color: inherit; font: inherit; font-size: 0.85rem; cursor: pointer; border-radius: 4px; }
.sd-split-key strong { font-weight: 700; }
.sd-split-key:hover { text-decoration: underline; text-underline-offset: 0.2em; }
.sd-split-key[aria-pressed="true"] { font-weight: 600; }
.sd-split.has-mode .sd-split-key[aria-pressed="false"], .sd-split.has-mode .sd-split-bar .is-off { opacity: 0.75; }
.sd-split.has-mode .sd-split-bar .is-off { opacity: 0.35; }
.sd-wide { font-size: 0.78rem; color: var(--ob-muted); border-top: 1px solid var(--sd-line); padding-top: 0.4rem; margin-top: 0.15rem !important; }
@media (prefers-reduced-motion: reduce) { .sd-split-bar span { transition: none; } }

/* --- stats (the trends view's condition tiles) ------------------------------ */

.sd-stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px; background: var(--sd-line);
  border: 1px solid var(--sd-line); border-radius: var(--ob-radius-sm); overflow: hidden; }
.sd-stat { background: var(--sd-shell); padding: 0.7rem 0.8rem; display: flex; flex-direction: column; }
/* Each number sits at the foot of its tile, so they line up however many
   lines a label takes ("Biking & scooters" wraps). */
.sd-page .sd-stat .sd-stat-value { margin-top: auto; }       /* beats the page's p { margin: 0 } */
.sd-page .sd-stat--hero .sd-stat-value { margin-top: 0; }
.sd-stat--hero { grid-column: 1 / -1; }
.sd-stat.is-off .sd-stat-value, .sd-stat.is-off .sd-stat-label { opacity: 0.45; }   /* the mode the filter leaves out */
.sd-stat-label { font-size: 0.75rem; color: var(--ob-muted); display: flex; align-items: center; gap: 0.35rem; }
.sd-stat-value { font-size: 1.5rem; font-weight: 700; letter-spacing: -0.02em; line-height: 1.2; }
.sd-stat--hero .sd-stat-value { font-size: 2.6rem; }
.sd-stat-note { font-size: 0.8rem; color: var(--ob-muted); }

.sd-dot { display: inline-block; width: 0.6rem; height: 0.6rem; border-radius: 50%; flex: none; }
.sd-dot--pedestrian { background: var(--sd-ped); }
.sd-dot--bicyclist { background: var(--sd-bike); }
.sd-dot--stack { background: var(--sd-mixed); box-shadow: 0 0 0 2px var(--sd-edge); }

/* --- filters ------------------------------------------------------------- */

.sd-filter-box summary { cursor: pointer; list-style: none; display: flex; align-items: center; gap: 0.4rem; }
.sd-filter-box summary::-webkit-details-marker { display: none; }
.sd-filter-box summary::before { content: '▸'; font-size: 0.8em; transition: transform 0.15s; }
.sd-filter-box[open] summary::before { transform: rotate(90deg); }
.sd-filters { display: flex; flex-direction: column; gap: 0.6rem; margin-top: 0.6rem; }
.sd-filter-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0.6rem; }
.sd-field--wide { grid-column: 1 / -1; }
.sd-field { display: flex; flex-direction: column; gap: 0.2rem; min-width: 0; }
.sd-field .ob-input { width: 100%; }
.sd-checks { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem 1rem; }
.sd-check { display: flex; align-items: center; gap: 0.4rem; min-height: 2.25rem; font-size: 0.9rem; cursor: pointer; }
.sd-check input { accent-color: var(--ob-purple); width: 1.15rem; height: 1.15rem; }
.sd-checks .sd-linkbtn { margin-left: auto; font-size: 0.9rem; color: var(--ob-muted); padding: 0.55rem 0.25rem; }
.sd-side-foot { grid-row: 2; display: flex; flex-direction: column; gap: 0.4rem; padding: 0.75rem 1.25rem 1rem;
  border-top: 1px solid var(--sd-line); font-size: 0.9rem; }
.sd-filter-count { font-weight: 600; letter-spacing: 0; text-transform: none; color: var(--ob-purple); }

/* --- map ----------------------------------------------------------------- */

.sd-view--map { position: relative; }
#sd-map { position: absolute; inset: 0; background: var(--sd-map-bg); }
/* The shared credits pill is fixed to the viewport on the full-screen maps;
   here the map is one column, so it sits in the map's own corner. */
.sd-view--map .ob-credits { position: absolute; z-index: 700; }
.sd-unmapped { position: absolute; top: var(--ob-map-inset); left: var(--ob-map-inset); z-index: 500; display: flex; align-items: center; gap: 0.5rem;
  background: var(--ob-panel); border: 1px solid var(--ob-panel-border); border-radius: 999px; box-shadow: var(--ob-panel-shadow);
  padding: 0.3rem 0.8rem 0.3rem 0.3rem; color: var(--ob-fg); font: inherit; font-size: 0.8rem; cursor: pointer; backdrop-filter: blur(6px); }
.sd-unmapped:hover { background: var(--sd-control-hover); }
.sd-unmapped[aria-pressed="true"] { border-color: var(--ob-purple); box-shadow: 0 0 0 1px var(--ob-purple), var(--ob-panel-shadow); }
/* Area, not diameter, follows the count (sized in JS). Both modes, so neither color. */
.sd-unmapped-dot { display: grid; place-items: center; border-radius: 50%; flex: none; font-weight: 700; font-size: 0.8rem;
  background: var(--sd-rate-bg); border: 1px solid var(--ob-muted); color: var(--ob-fg); transition: width 0.2s, height 0.2s; }
.sd-unmapped[aria-pressed="true"] .sd-unmapped-dot { background: var(--ob-purple); border-color: var(--ob-purple); color: var(--ob-on-accent); }
.sd-unmapped-text { display: flex; flex-direction: column; align-items: flex-start; line-height: 1.25; }
.sd-unmapped-label { color: var(--ob-muted); white-space: nowrap; }
.sd-unmapped-hint { font-size: 0.72rem; color: var(--ob-fg); }
.sd-unmapped-hint:empty { display: none; }
.sd-map-empty { position: absolute; top: 40%; left: 50%; transform: translate(-50%, -50%); z-index: 550; margin: 0;
  background: var(--ob-panel); border: 1px solid var(--ob-panel-border); border-radius: var(--ob-radius-sm);
  box-shadow: var(--ob-panel-shadow); padding: 0.75rem 1rem; text-align: center; }
.sd-map-empty:not([hidden]) { display: flex; flex-direction: column; gap: 0.4rem; align-items: center; }
.sd-legend { position: absolute; left: var(--ob-map-inset); bottom: var(--ob-map-inset); z-index: 500; background: var(--ob-panel); border: 1px solid var(--ob-panel-border);
  border-radius: var(--ob-radius-sm); padding: 0.4rem 0.75rem; font-size: 0.8rem; backdrop-filter: blur(6px); }
.sd-legend summary { cursor: pointer; color: var(--ob-muted); }
.sd-legend ul { list-style: none; margin: 0.4rem 0 0; padding: 0; display: grid; gap: 0.25rem; }
.sd-legend li { display: flex; align-items: center; gap: 0.5rem; }
.sd-layer { margin-top: 0.5rem; padding-top: 0.45rem; border-top: 1px solid var(--ob-panel-border); font-size: 0.8rem; }
.sd-bike-key { margin-top: 0.35rem !important; }
.sd-line { display: inline-block; width: 1rem; height: 0; border-top: 2.5px solid; flex: none; }
.sd-line--track { border-color: var(--sd-track); }
.sd-line--lane { border-color: var(--sd-lane); }
.sd-line--shared { border-top-style: dashed; border-color: var(--sd-lane); }
.leaflet-container { font: inherit; }
/* Leaflet's zoom buttons are white by default; these match the site's map panels. */
.leaflet-bar { border: 1px solid var(--ob-panel-border) !important; box-shadow: var(--ob-panel-shadow) !important; border-radius: var(--ob-radius-sm) !important; overflow: hidden; }
.leaflet-bar a, .leaflet-bar a:hover, .leaflet-bar a:focus { background: var(--ob-panel); color: var(--ob-fg); border-bottom-color: var(--ob-panel-border); backdrop-filter: blur(6px); }
.leaflet-bar a:hover, .leaflet-bar a:focus { background: var(--sd-control-hover); }
.leaflet-bar a.leaflet-disabled { background: var(--ob-panel); color: var(--sd-disabled); }
.leaflet-tooltip, .sd-stack-popup .leaflet-popup-content-wrapper { background: var(--sd-tip); color: var(--ob-fg); border: 1px solid var(--ob-panel-border); box-shadow: var(--ob-panel-shadow); font-size: 0.85rem; line-height: 1.35; }
.leaflet-tooltip-top::before { border-top-color: var(--sd-tip); }
.sd-stack-popup .leaflet-popup-tip { background: var(--sd-tip); }
.sd-tip-sub { color: var(--ob-muted); font-size: 0.75rem; }

/* --- trends -------------------------------------------------------------- */

/* Positioned, so hidden captions and other absolute pieces inside scroll with it
   instead of spilling below the dashboard and lengthening the page. */
.sd-view--trends { position: relative; overflow-y: auto; padding: 4.5rem 1.25rem 1.5rem; display: flex; flex-direction: column; gap: 1rem;
  /* Content fades out under the floating Map / Trends switch as it scrolls. */
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, transparent 2.5rem, #000 4.5rem);
  mask-image: linear-gradient(to bottom, transparent 0, transparent 2.5rem, #000 4.5rem); }
.sd-card { background: var(--sd-raise); border: 1px solid var(--sd-line); border-radius: var(--ob-radius-sm); padding: 1rem; display: flex; flex-direction: column; gap: 0.75rem; }
.sd-card-head { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }
.sd-card-head .sd-h { margin-right: auto; }
.sd-chart { position: relative; height: 300px; }
.sd-chart.is-empty canvas { visibility: hidden; }
.sd-trend-empty:not([hidden]) { position: absolute; inset: 0; display: flex; flex-direction: column; gap: 0.4rem;
  align-items: center; justify-content: center; margin: 0; color: var(--ob-muted); }
/* Wide tables scroll inside their card: the row labels stay put, and the
   right edge fades to say there is more. */
.sd-card .ob-table-scroll.is-scrollable { -webkit-mask-image: linear-gradient(to left, transparent 0, #000 1.5rem);
  mask-image: linear-gradient(to left, transparent 0, #000 1.5rem); }
.sd-card .ob-table th[scope="row"] { position: sticky; left: 0; background: var(--sd-raise); z-index: 1; }
.sd-conditions { display: grid; grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr)); gap: 1px; background: var(--sd-line);
  border: 1px solid var(--sd-line); border-radius: var(--ob-radius-sm); overflow: hidden; }
.sd-conditions .sd-stat { background: var(--sd-raise); }
.sd-rate { background: var(--sd-rate-bg); }
.sd-th-sub { font-weight: 400; letter-spacing: 0; text-transform: none; color: var(--ob-muted); }
.sd-card tfoot th, .sd-card tfoot td { border-top: 1px solid var(--ob-panel-border); font-weight: 600; }

/* --- people list --------------------------------------------------------- */

.sd-panel-head { position: sticky; top: 0; z-index: 1; background: var(--sd-shell); padding: 1rem 1rem 0.6rem; border-bottom: 1px solid var(--sd-line); }
.sd-list { list-style: none; padding: 0; }
.sd-list li + li { border-top: 1px solid var(--sd-line); }
.sd-row { display: flex; align-items: center; gap: 0.7rem; padding: 0.6rem 1rem; text-decoration: none; min-height: 44px; }
.sd-page a.sd-row { text-decoration: none; }
.sd-row:hover { background: var(--sd-hover); }
/* ui.css's row hover is a white tint, invisible on a light ground. */
html[data-map-theme="light"] .sd-app .ob-table tbody tr:hover { background: var(--sd-hover); }
.sd-row-main { display: flex; flex-direction: column; flex: 1; min-width: 0; }
.sd-row-title { font-weight: 500; color: var(--sd-text2); }
/* A name is what the list is for: named people read first. */
.sd-row--named .sd-row-title { font-weight: 700; color: var(--ob-fg); }
.sd-nowrap { white-space: nowrap; }
.sd-row-sub { font-size: 0.8rem; color: var(--ob-muted); }
.sd-more { margin: 0.75rem auto 1.25rem; display: block; }
.sd-empty { padding: 1.5rem 1rem; display: flex; flex-direction: column; gap: 0.6rem; align-items: flex-start; color: var(--ob-muted); }
/* Muted, so names rather than badges carry the color down the list. */
.sd-badge-news { background: transparent; border: 1px solid var(--sd-edge); color: var(--ob-muted); font-weight: 500; white-space: nowrap; }

/* --- person detail ------------------------------------------------------- */

.sd-detail { padding: 0 1.1rem 2rem; display: flex; flex-direction: column; gap: 0.75rem; }
.sd-detail > div + div, #sd-detail-body { display: flex; flex-direction: column; gap: 0.75rem; }
.sd-detail-bar { position: sticky; top: 0; z-index: 1; background: var(--sd-shell); display: flex; justify-content: space-between;
  padding: 0.9rem 0 0.6rem; border-bottom: 1px solid var(--sd-line); font-size: 0.9rem; }
.sd-detail-context { display: none; }
.sd-show-map { display: none; }
.sd-detail-name { font-size: 1.6rem; font-weight: 800; letter-spacing: -0.02em; line-height: 1.15; text-wrap: balance; margin-top: 0.25rem; }
.sd-detail-name:focus { outline: none; }
.sd-detail-sub { color: var(--ob-muted); font-size: 0.9rem; }
.sd-detail-sub .sd-dot { margin-right: 0.4rem; vertical-align: 0.05em; }
.sd-detail-sub .ob-badge { margin-left: 0.3rem; }
.sd-detail-lead { font-size: 1rem; }
.sd-story { margin: 0; border-left: 3px solid var(--sd-line); padding-left: 0.9rem; color: var(--sd-text2); }
#sd-detail-body .sd-h { margin-top: 0.75rem; }
.sd-links, .sd-sources, .sd-timeline { padding-left: 1.2rem; display: flex; flex-direction: column; gap: 0.25rem; }
.sd-sources li, .sd-links li { overflow-wrap: anywhere; }
.sd-facts { display: grid; grid-template-columns: max-content 1fr; gap: 0.3rem 1rem; font-size: 0.9rem; }
.sd-facts dt { color: var(--ob-muted); }
.sd-facts dd { margin: 0; }
.sd-cite { font-size: 0.8em; color: var(--ob-muted); white-space: nowrap; }
.sd-page a.sd-cite { text-decoration: none; }
.sd-sources li { border-radius: 4px; transition: background-color 0.6s; }
.sd-sources li.sd-flash { background: var(--sd-rate-bg); }
.sd-correct { margin-top: 0.75rem; padding: 0.9rem 1rem; border: 1px solid var(--sd-line); border-radius: var(--ob-radius-sm); font-size: 0.9rem; }

/* --- about --------------------------------------------------------------- */

.sd-about { width: min(44rem, calc(100vw - 2rem)); max-height: calc(100dvh - 4rem); padding: 0; border: 1px solid var(--ob-panel-border);
  border-radius: var(--ob-radius-panel); background: var(--sd-raise); box-shadow: var(--ob-panel-shadow); }
.sd-about::backdrop { background: rgba(3, 7, 18, 0.7); }
html[data-map-theme="light"] .sd-about::backdrop { background: rgba(15, 23, 42, 0.35); }
.sd-about-body { padding: 0 1.5rem 1.5rem; display: flex; flex-direction: column; gap: 0.7rem; }
.sd-about-bar { position: sticky; top: 0; background: var(--sd-raise); display: flex; justify-content: space-between; align-items: center;
  padding: 1.1rem 0 0.7rem; border-bottom: 1px solid var(--sd-line); }
.sd-about .sd-h { margin-top: 0.6rem; }
.sd-about ul:not(.sd-about-jump) { padding-left: 1.2rem; display: flex; flex-direction: column; gap: 0.4rem; }

/* --- narrow: one column, tabs, full-screen detail ------------------------ */

/* Wide: the left column fits a laptop screen without scrolling. Tighter
   type and spacing than the narrow filter sheet, County and Search side by
   side, and the foot on two lines. A very short window still scrolls, with
   a thin bar. */
@media (min-width: 1200px) {
  .sd-side { padding: 1rem 1.15rem 0.9rem; gap: 0.8rem; scrollbar-width: thin; scrollbar-color: var(--sd-edge) transparent; }
  .sd-head { gap: 0.2rem; }
  .sd-title { font-size: 1.45rem; }
  .sd-head .sd-lead { margin-top: 0.3rem; font-size: 0.88rem; line-height: 1.45; }
  .sd-stat { padding: 0.5rem 0.7rem; }
  .sd-readout { padding: 0.6rem 0.75rem; gap: 0.25rem; }
  .sd-split-key { font-size: 0.8rem; }
  #sd-count { font-size: 2.2rem; }
  .sd-stat-value { font-size: 1.25rem; }
  .sd-stat-note { font-size: 0.76rem; }
  #sd-lag { font-size: 0.74rem; line-height: 1.4; }
  .sd-filters { gap: 0.5rem; margin-top: 0.45rem; }
  .sd-filter-grid { gap: 0.5rem; }
  .sd-field--wide { grid-column: auto; }
  .sd-field .ob-label { font-size: 0.78rem; }
  .sd-side .ob-input { padding: 0.35rem 0.55rem; font-size: 0.88rem; min-height: 2.1rem; }
  .sd-check { font-size: 0.85rem; }
  .sd-side-foot { flex-direction: row; flex-wrap: wrap; align-items: center; gap: 0.35rem 1rem; padding: 0.6rem 1.15rem 0.75rem; font-size: 0.85rem; }
  .sd-side-foot .sd-note { flex-basis: 100%; font-size: 0.74rem; }
}

/* A short laptop screen: the intro and the lag note give way (the About has
   both), so the stats and filters still fit. */
@media (min-width: 1200px) and (max-height: 820px) {
  .sd-head .sd-lead, #sd-lag { display: none; }
}

/* Narrow-only pieces, hidden on a wide screen. */
.sd-mbar, .sd-grab, .sd-side-close, .sd-sheet-title, .sd-mfilter, .sd-scrim { display: none; }

@media (max-width: 1199.98px) {
  /* An app, not a page: a compact bar, the map filling the screen beneath
     it, the people in a sheet over the map's lower part (peek, half, full),
     and the summary and filters in a sheet of their own. */
  .sd-app { --sd-mbar-h: 3.25rem; --sd-peek: 8.75rem;
    position: fixed; inset: var(--ob-bar-h) 0 0; height: auto; display: block; overflow: clip; }

  /* One slim row: the count for the current filters, and Map / Trends. */
  .sd-mbar { display: flex; align-items: center; position: absolute; inset: 0 0 auto;
    height: var(--sd-mbar-h); padding: 0 10rem 0 1rem; background: var(--sd-shell); border-bottom: 1px solid var(--sd-edge);
    box-shadow: 0 6px 18px -8px var(--sd-cast); z-index: 1200; }
  .sd-mbar-stat { flex: 1; min-width: 0; font-size: 0.85rem; font-weight: 600; line-height: 1.2;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .sd-mbar-stat strong { font-size: 1.15rem; font-weight: 800; letter-spacing: -0.01em; }
  .sd-mbar-least { font-weight: 400; color: var(--ob-muted); }
  .sd-mbar-scope { font-weight: 400; font-size: 0.8rem; color: var(--ob-muted); }
  .sd-mfilter { flex: none; font: inherit; font-size: 0.85rem; font-weight: 600; color: var(--ob-fg); background: var(--sd-control-hover);
    border: 1px solid var(--ob-control-border); border-radius: 999px; padding: 0.3rem 0.8rem; min-height: 32px; cursor: pointer;
    display: inline-flex; align-items: center; gap: 0.35rem; }
  .sd-mfilter-count:not(:empty) { background: var(--ob-purple); color: var(--ob-on-accent); border-radius: 999px;
    font-size: 0.72rem; min-width: 1.2rem; padding: 0 0.3rem; text-align: center; }

  .sd-tabs { position: absolute; top: calc((var(--sd-mbar-h) - 32px) / 2); right: 1rem; z-index: 1300; margin: 0; box-shadow: none; }
  .sd-tabs button { padding: 5px 12px; min-height: 32px; }
  .sd-tab--people { display: none !important; }

  .sd-main { position: absolute; inset: var(--sd-mbar-h) 0 0; }
  .sd-view--map { position: absolute; inset: 0; }
  .sd-view--trends { position: absolute; inset: 0; padding: 1rem 1rem 2rem; overflow-y: auto; -webkit-mask-image: none; mask-image: none; }
  /* Map furniture clears the sheet's peek. */
  .sd-legend, .sd-view--map .ob-credits { bottom: calc(var(--sd-peek) + 0.6rem); }
  .sd-legend { left: 0.75rem; }

  /* The people sheet. */
  .sd-panel { position: absolute; left: 0; right: 0; bottom: 0; z-index: 1100; height: calc(100% - var(--sd-mbar-h) - 0.75rem);
    border: 1px solid var(--sd-edge); border-bottom: 0; border-radius: 16px 16px 0 0; box-shadow: 0 -8px 24px -8px var(--sd-cast);
    transform: translateY(calc(100% - var(--sd-peek))); transition: transform 0.28s cubic-bezier(0.2, 0.8, 0.2, 1);
    overflow-y: hidden; overscroll-behavior: contain; touch-action: pan-y; }
  .sd-app[data-sheet="half"] .sd-panel { transform: translateY(45%); overflow-y: auto; }
  .sd-app[data-sheet="full"] .sd-panel { transform: none; overflow-y: auto; }
  .sd-app.is-dragging .sd-panel { transition: none; }
  .sd-app[data-view="trends"] .sd-panel { transform: translateY(100%); visibility: hidden; }
  .sd-grab { display: flex; justify-content: center; align-items: center; position: sticky; top: 0; z-index: 3; width: 100%;
    height: 1.4rem; padding: 0; border: 0; background: var(--sd-shell); cursor: grab; touch-action: none; }
  .sd-grab span { width: 2.6rem; height: 0.3rem; border-radius: 999px; background: var(--ob-control-border); }
  .sd-panel-head { top: 1.4rem; padding-top: 0.2rem; touch-action: none; display: flex; align-items: center; gap: 0.75rem; }
  .sd-panel-title { flex: 1; min-width: 0; }
  .sd-detail-bar { top: 1.4rem; }
  .sd-detail-context, .sd-show-map { display: block; }
  .sd-detail-context { margin-top: 0.4rem; }

  /* The filters: a short sheet from the bottom, over a dimmed map, opened by
     the Filter button beside the count. Just the filters, the theme and the
     links; the intro and stats are for the wide layout (the bar has the count). */
  .sd-scrim:not([hidden]) { display: block; position: absolute; inset: 0; z-index: 1350; background: rgba(3, 7, 18, 0.5); }
  .sd-side { position: absolute; left: 0; right: 0; bottom: 0; top: auto; max-height: 88%; z-index: 1400; border: 1px solid var(--sd-edge);
    border-bottom: 0; border-radius: 16px 16px 0 0; padding: 0 1rem; overflow-y: auto; gap: 0.75rem;
    box-shadow: 0 -8px 24px -8px var(--sd-cast);
    transform: translateY(100%); visibility: hidden; transition: transform 0.25s ease, visibility 0s linear 0.25s; }
  .sd-app.filters-open .sd-side { transform: none; visibility: visible; transition: transform 0.25s ease; }
  .sd-side .sd-readout, .sd-side #sd-lag { display: none; }
  .sd-side .sd-head { padding-bottom: 0.5rem; }
  .sd-side .sd-title { font-size: 1.15rem; }
  .sd-panel .sd-mkey { display: flex; align-items: center; gap: 0.35rem; margin: 0.15rem 0 0; font-size: 0.75rem; color: var(--ob-muted); }
  .sd-mkey .sd-dot + .sd-dot, .sd-mkey span + .sd-dot { margin-left: 0.5rem; }
  .sd-app:not(.is-ready) .sd-side-foot { visibility: hidden; }
  /* Touch targets of at least 44px, by padding or an invisible hit area. */
  .sd-theme .ob-seg button, .sd-mfilter, .sd-tabs button, .sd-side-close .ob-btn, .sd-sheet-title .sd-linkbtn { min-height: 44px; }
  .sd-tabs { top: calc((var(--sd-mbar-h) - 44px) / 2); }
  .sd-grab { height: 2.75rem; }
  .sd-more { min-height: 44px; }
  .sd-panel-head, .sd-detail-bar { top: 2.75rem; }
  .sd-detail-bar .sd-linkbtn, .sd-detail-bar button, .sd-linkbtn { min-height: 44px; display: inline-flex; align-items: center; }
  .leaflet-bar a { width: 44px !important; height: 44px !important; line-height: 44px !important; }
  .sd-legend summary { min-height: 44px; display: flex; align-items: center; }
  .sd-cite, a.sd-cite, .sd-list a { position: relative; }
  .sd-cite::after { content: ''; position: absolute; inset: -14px -10px; }
  .sd-mbar { padding-right: 12.5rem; }
  .sd-mbar-scope { display: block; }
  .sd-mbar-stat { white-space: normal; }
  .sd-sheet-title { display: flex; align-items: center; justify-content: space-between; order: 0; position: sticky; top: 0; z-index: 2;
    margin: 0 -1rem; padding: 1rem 1rem 0.5rem; background: var(--sd-shell); }
  .sd-sheet-title .sd-h { font-size: 1.1rem; }
  .sd-sheet-title .sd-linkbtn { font-size: 0.9rem; color: var(--ob-muted); }
  .sd-filter-box { order: 1; }
  .sd-filter-box summary { display: none; }
  .sd-filters { margin-top: 0; }
  .sd-checks .sd-linkbtn { display: none; }
  .sd-side .sd-side-foot { order: 5; flex-direction: row; flex-wrap: wrap; align-items: center; gap: 0.4rem 1rem;
    border: 0; border-top: 1px solid var(--sd-line); box-shadow: none; padding: 0.75rem 0 0.25rem; background: none; }
  .sd-side .sd-side-foot .sd-note { flex-basis: 100%; }
  .sd-side-close { display: block; order: 99; position: sticky; bottom: 0; margin: 0 -1rem; padding: 0.75rem 1rem calc(0.75rem + env(safe-area-inset-bottom, 0px));
    background: var(--sd-shell); border-top: 1px solid var(--sd-line); }
  .sd-side-close .ob-btn { width: 100%; justify-content: center; }
}
@media (max-width: 1199.98px) and (prefers-reduced-motion: reduce) {
  .sd-panel, .sd-side { transition: none !important; }
}
@media (max-width: 520px) {
  .sd-stat--hero .sd-stat-value { font-size: 2.2rem; }
}

.sd-about-jump { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 0.25rem 1rem; }
.sd-about-jump a { color: var(--ob-muted); }
@media (max-width: 1199.98px) { .sd-app[data-sheet="peek"] .sd-panel { touch-action: none; } }

.sd-bars { display: grid; gap: 0.35rem; margin: 0.5rem 0; }
.sd-bar-row { display: grid; grid-template-columns: 6.5rem 1fr 3.5rem; align-items: center; gap: 0.6rem; font-size: 0.85rem; }
.sd-bar-track { display: flex; height: 0.9rem; border-radius: 3px; overflow: hidden; min-width: 2px; }
.sd-bar-track > span { display: block; height: 100%; }
.sd-bar-n { text-align: right; font-weight: 600; }

.sd-mkey { display: none; }

.sd-bars--season { position: relative; }
.sd-bars--season::after { content: ''; position: absolute; top: 0; bottom: 0; width: 2px; background: var(--ob-fg);
  left: calc(6.5rem + 0.6rem + (100% - 6.5rem - 3.5rem - 1.2rem) * var(--base, 71) / 100); pointer-events: none; }

.sd-page .sd-conditions .sd-stat .sd-stat-value { margin-top: 0; }
#sd-city-table td:nth-child(2) { white-space: nowrap; color: var(--ob-muted); }
.sd-uninc { text-transform: none; letter-spacing: 0; font-weight: 400; font-style: italic; color: var(--ob-muted); white-space: nowrap; }

.sd-subseg { align-self: flex-start; }

/* Keyboard users can jump past the filters and map to the people. */
.sd-skip { position: absolute; left: 0.5rem; top: -3rem; z-index: 3000; padding: 0.5rem 0.8rem; background: var(--sd-raise);
  color: var(--ob-fg); border: 2px solid var(--ob-purple); border-radius: var(--ob-radius-sm); }
.sd-skip:focus { top: calc(var(--ob-bar-h) + 0.5rem); }
.sd-mbar.is-none .sd-mbar-stat strong { font-size: 1rem; }
@media (max-width: 1199.98px) {
  /* The county name column gives the numbers room. */
  .sd-card .ob-table th[scope="row"] { max-width: 8rem; white-space: normal; }
  .sd-side-foot a { display: inline-block; padding-block: 0.35rem; }
}
/* A phone on its side: the site bar gives way, and the sheet and chart fit. */
@media (max-width: 1199.98px) and (max-height: 500px) {
  nav.ob-bar { display: none; }
  html.ob-doc body { padding-top: 0; }
  .sd-app { top: 0; --sd-peek: 6.5rem; }
  .sd-app[data-sheet="half"] .sd-panel { transform: translateY(35%); }
  .sd-chart { height: min(360px, 60vh); }
}

.sd-row-main .sd-badge-news { align-self: flex-start; margin-top: 0.25rem; }
.sd-row-title { hyphens: manual; }

/* Sortable column heads: the whole head is the button. */
.sd-sort { all: unset; box-sizing: border-box; cursor: pointer; display: inline-block; text-align: inherit; font: inherit;
  text-transform: inherit; letter-spacing: inherit; color: inherit; padding: 0.25rem 0; }
.sd-sort:hover { text-decoration: underline; text-underline-offset: 0.2em; }
.sd-sort:focus-visible { outline: 2px solid var(--ob-purple); outline-offset: 2px; border-radius: 4px; }
.sd-sort-arrow { display: inline-block; min-width: 0.9em; margin-left: 0.15em; font-size: 0.7em; }

/* The hover tip on the time-of-year and age bars. */
.sd-tip { position: fixed; z-index: 4000; max-width: 19rem; padding: 0.55rem 0.75rem; font-size: 0.8rem; line-height: 1.4;
  background: var(--sd-raise); color: var(--ob-fg); border: 1px solid var(--sd-edge); border-radius: var(--ob-radius-sm);
  box-shadow: 0 6px 20px -6px var(--sd-cast); pointer-events: none; }
.sd-bar-row[data-tip] { border-radius: 4px; }
.sd-bar-row[data-tip]:hover, .sd-bar-row[data-tip]:focus-visible { background: var(--sd-hover); }

/* People at the same point: one numbered marker, a list on click. Sized from
   the dots' radius (--sd-stack-d, set as the map zooms); the number appears
   from zoom 11. */
.sd-stack { background: none; border: 0; }
.sd-stack span { display: grid; place-items: center; box-sizing: border-box; width: var(--sd-stack-d, 16px); height: var(--sd-stack-d, 16px);
  transform: translate(-50%, -50%); border-radius: 50%; border: 2px solid var(--sd-stroke); box-shadow: 0 0 0 1.5px var(--sd-edge);
  font: 700 0 system-ui, sans-serif; color: #fff; font-variant-numeric: tabular-nums; }
.sd-stack-count .sd-stack span { font-size: 0.75rem; line-height: 1; }
.sd-stack-pedestrian span { background: var(--sd-ped); }
.sd-stack-bicyclist span { background: var(--sd-bike); }
.sd-stack-mixed span { background: var(--sd-mixed); }
.sd-stack-popup .leaflet-popup-content-wrapper { border-radius: 0.5rem; }
.sd-stack-popup .leaflet-popup-content { margin: 0.5rem 0.75rem; }
.sd-stack-list a { display: block; padding: 0.3rem 0; color: inherit; text-decoration: none; border-top: 1px solid var(--sd-line); }
.sd-stack-list a:first-child { border-top: 0; }
.sd-stack-list a:hover b { text-decoration: underline; }

/* The legend on a phone is a bare word: a chevron says it opens. */
.sd-legend summary { list-style: none; }
.sd-legend summary::-webkit-details-marker { display: none; }
.sd-legend summary::before { content: '\25B8'; display: inline-block; margin-right: 0.35rem; transition: transform 0.15s; }
.sd-legend[open] summary::before { transform: rotate(90deg); }
@media (prefers-reduced-motion: reduce) { .sd-legend summary::before { transition: none; } }

/* Long explanations sit behind a "How to read this" line. */
.sd-how { margin: 0.5rem 0 0; }
.sd-how summary { cursor: pointer; color: var(--ob-muted); font-size: 0.85rem; list-style: none; min-height: 1.75rem; display: flex; align-items: center; }
.sd-how summary::-webkit-details-marker { display: none; }
.sd-how summary::before { content: '\25B8'; display: inline-block; margin-right: 0.35rem; transition: transform 0.15s; }
.sd-how[open] summary::before { transform: rotate(90deg); }
.sd-how p { margin-top: 0.25rem; }
@media (prefers-reduced-motion: reduce) { .sd-how summary::before { transition: none; } }
