/* =============================================================================
   CLEAR analytical workspace — stylesheet (FCLEAR-APP-0002A)
   Owner: WS1 (claude-01). Integrated into templates/clear/map.html by CLAUDE-00.

   Plain CSS, no build step, no external fonts/CDNs. Font stacks degrade to
   system faces when IBM Plex is not installed locally.

   This file styles two overlapping layers on purpose:
     1. The new DOM-contract classes (.clear-tier1, .clear-workspace,
        .clear-pane, .clear-tile, .clear-hg-*, ...) that carry the redesign.
     2. Every class the previous inline <style> block in map.html styled
        (.clear-map-*, .layer-*, .maplibregl-*). Existing `data-clear-*` hooks
        are preserved verbatim per the DOM contract, and some markup this file
        does not own may still reference the old classes — nothing may regress
        while the integrator migrates markup, so old selectors stay themed
        with the new tokens rather than being deleted.
   ========================================================================== */

/* -----------------------------------------------------------------------
   1. Design tokens
   ----------------------------------------------------------------------- */
:root {
  /* commercial profile (default) — source of truth: design package, never
     sampled from mockups */
  --brand-ink: #1C465F;
  --brand-accent: #9ED6E6;
  --brand-ui: #9ECFEC;
  --sig-reg: #1C465F;
  --sig-com: #2E8C97;

  --canvas: #e9eef2;
  --surface: #ffffff;
  --surface-2: #f5f8fa;
  --surface-3: #eef3f7;
  --line: #dce4ea;
  --line-strong: #c4d0da;
  --ink: #16242f;
  --muted: #5e7387;
  --faint: #8598a6;
  --tile-border: #dce2ea;
  --good: #2e7d5b;
  --moderate: #b8860b;
  --unavail: #94a6b3;
  --focus: #1C465F;

  --r-sm: 6px;
  --r-md: 9px;
  --r-lg: 13px;
  --sh-1: 0 1px 2px rgba(16, 32, 48, .07);
  --sh-2: 0 2px 4px rgba(16, 32, 48, .06), 0 12px 28px -18px rgba(16, 32, 48, .3);
  --sh-3: 0 -2px 20px rgba(16, 32, 48, .13);

  /* No network access at runtime: IBM Plex is first-choice but every stack
     degrades cleanly through widely-installed faces to system-ui. */
  --f: 'IBM Plex Sans', Inter, system-ui, -apple-system, 'Segoe UI', sans-serif;
  --m: 'IBM Plex Mono', ui-monospace, 'SF Mono', Menlo, monospace;

  /* --- back-compat: the previous inline stylesheet's variables, re-declared
     so any rule that hasn't migrated to the tokens above still resolves.
     Mapped onto the new tokens where the old value and a token are close
     enough that re-pointing keeps the same intent (and now respects the
     foundation profile automatically); left as literal values where there is
     no sensible new-token equivalent (layer icon colours, size scales). */
  --clear-font-family: var(--f);
  --clear-shell-navy: var(--brand-ink);
  --clear-header-text: #ffffff;
  --clear-muted-on-navy: rgba(255, 255, 255, 0.72);
  --clear-primary-blue: var(--brand-ink);
  --clear-blue: var(--brand-ink);
  --clear-blue-dark: var(--ink);
  --clear-blue-soft: var(--surface-3);
  --clear-green: #2ca56f;
  --clear-green-soft: #e5f7ee;
  --clear-teal: var(--sig-com);
  --clear-teal-soft: #e2f2f5;
  --clear-purple: #7c4cc2;
  --clear-orange: #e98a24;
  --clear-wildfire: #e65f2d;
  --clear-mint: #a8e6ce;
  --clear-gray: var(--muted);
  --clear-border: var(--line);
  --clear-control-bg: var(--surface);
  --clear-card-radius: var(--r-lg);
  --clear-control-radius: var(--r-md);
  --clear-panel: var(--surface);
  --clear-panel-soft: var(--surface-2);
  --clear-map-bg: var(--canvas);
  --clear-text: var(--ink);
  --clear-text-muted: var(--muted);
  --clear-shadow: var(--sh-2);
  --clear-shadow-soft: var(--sh-1);
  --clear-panel-shadow: var(--sh-1);
  --clear-overlay-shadow: var(--sh-3);
  --clear-dashboard-value-size: 23px;
  --clear-dashboard-unit-scale: 0.8em;
  --clear-dashboard-secondary-size: 13px;
  --clear-condition-value-size: 20px;
  --clear-condition-unit-scale: 0.8em;
  --clear-condition-category-size: 12px;
  --clear-aqi-good: #16a34a;
  --clear-aqi-moderate: #ca8a04;
  --clear-aqi-unhealthy-sensitive: #f97316;
  --clear-aqi-unhealthy: #dc2626;
  --clear-aqi-very-unhealthy: #b91c1c;
  --clear-aqi-hazardous: #ff0000;
  --clear-aqi-unavailable: #64748b;
  --clear-history-pm25-good: #218c46;
  --clear-history-pm25-moderate: #e0ab16;
  --clear-history-pm25-usg: #ef8a28;
  --clear-history-pm25-unhealthy: #d64545;
  --clear-history-pm25-very-unhealthy: #75429a;
  --clear-history-pm25-hazardous: #7d2634;
  --clear-history-pm25-unavailable: var(--unavail);
  --clear-header-height: 86px;
  --clear-nav-height: 54px;
  --clear-left-width: 340px;
  --clear-detail-panel-width: 552px;
  --clear-right-width: var(--clear-detail-panel-width);
  --clear-focus: 0 0 0 3px rgba(28, 70, 95, 0.28);

  /* history-graph provenance palette (FCLEAR-APP-0001Q, extended here) */
  --clear-hg-regulatory: var(--sig-reg);
  --clear-hg-community: var(--sig-com);
  --clear-hg-grid: var(--line);
  --clear-hg-axis: var(--muted);
  --clear-hg-gap: var(--surface-3);
  --clear-hg-transition: var(--line-strong);
}

[data-clear-profile="foundation"] {
  --brand-ink: #012F68;
  --brand-accent: #029AA1;
  --brand-ui: #029AA1;
  --sig-reg: #012F68;
  --sig-com: #029AA1;
  --focus: #012F68;
  --clear-focus: 0 0 0 3px rgba(1, 47, 104, 0.28);
}

/* -----------------------------------------------------------------------
   2. Base / reset
   ----------------------------------------------------------------------- */
html,
body {
  height: 100%;
  margin: 0;
  overflow: hidden;
  background: var(--canvas);
  color: var(--ink);
  font-family: var(--f);
}

* { box-sizing: border-box; }
button, input, select { font: inherit; }
button { cursor: pointer; }
button:disabled, select:disabled { cursor: not-allowed; }

/* Focus rings use the profile's --focus token and are suppressed for pointer
   interaction (:focus-visible only) per the accessibility contract. */
a, button, input, select, [tabindex] { outline: none; }
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}
/* legacy box-shadow focus treatment, kept for un-migrated controls */
button:focus-visible, a:focus-visible, input:focus-visible, select:focus-visible {
  box-shadow: var(--clear-focus);
}

@media (prefers-reduced-motion: reduce) {
  * { scroll-behavior: auto !important; }
  .clear-pane,
  .clear-rail,
  .clear-scrim,
  .clear-hg-scroll,
  .clear-hg-pindot,
  .clear-hg-focusdot,
  .clear-map-history-year-row {
    transition: none !important;
    animation: none !important;
  }
}

/* Numeric/identifier legibility: mono face + tabular figures wherever a
   column of digits needs to line up (readouts, coordinates, distances,
   axis labels, IDs). Non-obvious because it's applied by intent, not by
   element type — some <span> text is prose and must stay in --f. */
.clear-mono,
.clear-tier2-actions,
.clear-coord,
.clear-tile-value,
.clear-tile-unit,
.clear-hg-vlabel,
.clear-hg-ylabel,
.clear-hg-tip,
[data-clear-condition-pm25], [data-clear-condition-o3], [data-clear-condition-no2],
[data-clear-condition-so2], [data-clear-condition-co],
.clear-metric-primary, .clear-condition-number, .clear-map-history-value,
.clear-map-history-year-marker {
  font-family: var(--m);
  font-variant-numeric: tabular-nums;
}

/* -----------------------------------------------------------------------
   2b. App shell — viewport-height layout (defect 3)
   .clear-app was previously an unstyled div: it had no explicit height, so
   its children (tier1/tier2/workspace) sized to their content instead of the
   viewport and the whole page grew — the rail and pane never got a chance to
   hit their own overflow:auto because there was no bounded box to overflow.
   100dvh is primary (correct on mobile browser chrome show/hide); 100vh is
   the fallback for engines without dvh support.
   ----------------------------------------------------------------------- */
.clear-app {
  display: flex;
  flex-direction: column;
  height: 100vh;
  height: 100dvh;
  min-height: 0;
  overflow: hidden;
  background: var(--canvas);
}
.clear-tier1,
.clear-tier2 { flex: 0 0 auto; }

/* =============================================================================
   3. Tier 1 — product shell
   ========================================================================== */
.clear-tier1 {
  display: flex;
  align-items: center;
  gap: 14px;
  min-width: 0;
  height: 44px;
  padding: 0 16px;
  background: var(--brand-ink);
  color: #fff;
}
.clear-tier1-brand {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  flex: 0 0 auto;
  color: #fff;
  text-decoration: none;
  /* The lockup is a link, so it takes the full height of the bar it sits in. Where the bar is
     at least 44px this yields the 44px minimum target. Below 767px the Foundation bar is a
     deliberate 34px compact treatment (see the rule near the foundation mobile block), and the
     link is pinned to that height there rather than overflowing it: an over-tall box would
     extend above the viewport and under tier 2, which paints later, so the extra height would
     not be clickable anyway and would only misreport the real target. */
  min-height: 44px;
  border-radius: var(--r-sm);
}
.clear-tier1-brand:focus-visible {
  outline: 3px solid #fff;
  outline-offset: 2px;
}
.clear-tier1-mark {
  width: 28px; height: 28px; border-radius: var(--r-sm); object-fit: contain; flex: 0 0 auto;
}

/* FCLEAR-APP-0002A branding correction, matched to the approved Commercial header mockup.
   ONE authoritative lung silhouette asset, drawn twice with different presentation:

     tier 1  white silhouette directly on the navy bar, no tile, wordmark as text beside it
     tier 2  the same silhouette in the pale --brand-accent, inside the rounded white tile

   Both are painted with a CSS mask, so the colour is entirely presentation and the mark's
   geometry is exactly the approved asset -- nothing is recoloured in the file, redrawn or traced.
   --clear-mark-src is set inline from deployment_profile.header_logo_url so the asset stays a
   straight swap and the stylesheet hard-codes no path. */
.clear-tier1-lung {
  /* The asset's aspect is 835:697, so a 20px box renders the silhouette ~20x16.7 -- the mockup's
     ~19x16. Sized by box rather than by cropping or rescaling the asset. */
  display: inline-block; flex: 0 0 auto; width: 20px; height: 20px;
  background-color: #fff;
  -webkit-mask: var(--clear-mark-src) no-repeat center / contain;
          mask: var(--clear-mark-src) no-repeat center / contain;
}
.clear-tile-lung {
  display: block; width: 30px; height: 30px;
  background-color: var(--brand-accent);
  -webkit-mask: var(--clear-mark-src) no-repeat center / contain;
          mask: var(--clear-mark-src) no-repeat center / contain;
}
.clear-tier1-wordmark { font-size: 14px; font-weight: 700; letter-spacing: .01em; white-space: nowrap; }
.clear-tier1-nav {
  display: flex;
  align-items: center;
  gap: 4px;
  min-width: 0;
  overflow-x: auto;
  flex: 1 1 auto;
}
.clear-tier1-link {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  height: 28px;
  padding: 0 10px;
  border: 0;
  border-radius: var(--r-sm);
  background: transparent;
  color: rgba(255, 255, 255, .78);
  font-size: 12.5px;
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
}
.clear-tier1-link:hover { background: rgba(255, 255, 255, .10); color: #fff; }
.clear-tier1-link.is-active { background: rgba(255, 255, 255, .16); color: #fff; }
.clear-tier1-link:disabled, .clear-tier1-link[aria-disabled="true"] { color: rgba(255, 255, 255, .38); cursor: not-allowed; }
.clear-tier1-link:disabled:hover, .clear-tier1-link[aria-disabled="true"]:hover { background: transparent; }
.clear-tier1-meta { flex: 0 0 auto; display: flex; align-items: center; gap: 10px; min-width: 0; color: rgba(255, 255, 255, .78); font-size: 12px; }

/* =============================================================================
   4. Tier 2 — map chrome (lockup, search, actions)
   ========================================================================== */
.clear-tier2 {
  display: flex;
  align-items: center;
  gap: 14px;
  min-width: 0;
  height: 56px;
  padding: 0 16px;
  background: var(--surface);
  border-bottom: 1px solid var(--line);
}
.clear-lockup { display: flex; align-items: center; gap: 10px; min-width: 0; flex: 0 0 auto; }

/* The brand tile is CSS chrome — a white rounded frame around the mark — so
   the profile logo asset never needs to bake in its own presentation. Sizes
   below match the 44/38/40px contract for the three chrome contexts. */
.clear-brand-tile {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: var(--r-md);
  background: #fff;
  border: 1px solid var(--tile-border);
  box-shadow: var(--sh-1);
  flex: 0 0 auto;
}
.clear-brand-tile img { width: 28px; height: 28px; object-fit: contain; display: block; }
.clear-lockup-text { display: flex; flex-direction: column; min-width: 0; line-height: 1.15; }
.clear-lockup-name { font-size: 16px; font-weight: 700; color: var(--brand-ink); letter-spacing: -.01em; }
.clear-lockup-descriptor { font-size: 11.5px; font-weight: 600; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.clear-search {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1 1 320px;
  min-width: 0;
  max-width: 420px;
  height: 40px;
  padding: 0 12px;
  border-radius: var(--r-md);
  background: var(--surface-2);
  border: 1px solid var(--line);
}
.clear-search:focus-within { border-color: var(--focus); box-shadow: 0 0 0 3px color-mix(in srgb, var(--focus) 20%, transparent); }
.clear-search svg { width: 16px; height: 16px; color: var(--faint); flex: 0 0 auto; }
.clear-search input { flex: 1 1 auto; min-width: 0; border: 0; outline: 0; background: transparent; color: var(--ink); font-size: 13px; font-family: var(--f); }
.clear-search input::placeholder { color: var(--faint); }

.clear-tier2-actions { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; margin-left: auto; }
.clear-action {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: 38px;
  padding: 0 12px;
  border-radius: var(--r-md);
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--ink);
  font-size: 12.5px;
  font-weight: 700;
  font-family: var(--f);
  white-space: nowrap;
}
.clear-action:hover { background: var(--surface-2); }
.clear-action svg { width: 16px; height: 16px; flex: 0 0 auto; }
.clear-action.is-primary { background: var(--brand-ink); border-color: var(--brand-ink); color: #fff; }
.clear-action.is-primary:hover { background: color-mix(in srgb, var(--brand-ink) 88%, #000); }
.clear-action[aria-pressed="true"] { background: var(--surface-3); border-color: var(--line-strong); }
/* Below 1320px the label text hides, the icon + aria-label remain — the
   button never moves into a menu (no hamburger above phone widths). */
@media (max-width: 1319px) {
  .clear-action-label { display: none; }
  .clear-action { padding: 0 10px; width: 38px; justify-content: center; }
}
.clear-user-chip { display: inline-flex; align-items: center; gap: 8px; height: 40px; padding: 0 4px 0 0; border: 0; background: transparent; color: var(--ink); }

/* =============================================================================
   5. Workspace layout
   ========================================================================== */
main.clear-workspace,
.clear-workspace {
  position: relative;
  display: flex;
  flex: 1 1 auto; /* fills the remaining height under .clear-app's tier1/tier2 */
  min-width: 0; /* mandatory safeguard: without this the pane's intrinsic
                   content width can push the flex container wider than the
                   viewport instead of yielding to the map */
  min-height: 0;
  height: 100%;
  overflow: hidden;
  background: var(--canvas);
}

.clear-rail {
  flex: 0 0 320px;
  min-width: 0;
  background: var(--surface);
  border-right: 1px solid var(--line);
  overflow-y: auto;
  overflow-x: hidden;
  padding: 18px 20px 0;
  display: flex;
  flex-direction: column;
}

.clear-canvas {
  position: relative;
  flex: 1 1 auto;
  min-width: 0;
  min-height: 0;
  height: 100%;
  overflow: hidden;
  background: #cddae5;
}

.clear-pane {
  flex: 0 0 468px;
  min-width: 0; /* mandatory safeguard: a wide history chart must not force
                   this track past its flex-basis and crush the map */
  background: var(--surface);
  border-left: 1px solid var(--line);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.clear-scrim {
  position: absolute;
  inset: 0;
  z-index: 15;
  background: rgba(15, 27, 38, .38);
}
.clear-scrim[hidden] { display: none; }

/* --- Responsive modes ---------------------------------------------------
   Layout is driven by matching media queries (guaranteed correct before JS
   runs) *and* by the [data-clear-pane-mode] attribute the JS mode broker
   sets from its matchMedia list, per the DOM contract's "both" requirement —
   the attribute is also what lets JS gate sheet-drag behaviour to sheet mode
   only. The breakpoints below intentionally mirror each other. */

/* overlay: 1121–1319 — rail stays in-flow at 300px, pane becomes a floating
   drawer over the full-width map. */
@media (max-width: 1319px) {
  .clear-rail { flex-basis: 300px; }
  .clear-pane {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    flex-basis: auto;
    width: 414px;
    z-index: 20;
    box-shadow: var(--sh-3);
  }
}
.clear-workspace[data-clear-pane-mode="overlay"] .clear-rail { flex-basis: 300px; }
.clear-workspace[data-clear-pane-mode="overlay"] .clear-pane {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  flex-basis: auto;
  width: 414px;
  z-index: 20;
  box-shadow: var(--sh-3);
}

/* overlay: 768–1120 — rail also becomes a dismissible overlay with scrim. */
@media (max-width: 1120px) {
  .clear-rail {
    position: absolute;
    top: 0;
    left: 0;
    bottom: 0;
    width: 300px;
    z-index: 21;
    box-shadow: var(--sh-3);
    transform: translateX(-100%);
    transition: transform .2s ease;
  }
  .clear-rail.is-open { transform: translateX(0); }
}

/* sheet: ≤767 — map-first; rail is off-canvas behind a hamburger, pane
   becomes a bottom sheet. The map is never display:none at any width. */
@media (max-width: 767px) {
  .clear-rail {
    position: absolute;
    top: 0;
    left: 0;
    bottom: 0;
    width: min(84vw, 320px);
    z-index: 21;
    box-shadow: var(--sh-3);
    transform: translateX(-100%);
    transition: transform .2s ease;
  }
  .clear-rail.is-open { transform: translateX(0); }
  .clear-pane {
    position: fixed;
    inset: auto 0 0 0;
    top: auto;
    width: auto;
    height: 238px;
    max-height: 92vh;
    border-left: 0;
    border-top: 1px solid var(--line);
    border-radius: var(--r-lg) var(--r-lg) 0 0;
    box-shadow: var(--sh-3);
    z-index: 22;
    transition: height .2s ease;
  }
  .clear-pane[data-clear-pane-state="expanded"] { height: 92vh; }
}
.clear-workspace[data-clear-pane-mode="sheet"] .clear-pane {
  position: fixed;
  inset: auto 0 0 0;
  top: auto;
  width: auto;
  height: 238px;
  max-height: 92vh;
  border-left: 0;
  border-top: 1px solid var(--line);
  border-radius: var(--r-lg) var(--r-lg) 0 0;
  box-shadow: var(--sh-3);
  z-index: 22;
}
.clear-workspace[data-clear-pane-mode="sheet"] .clear-pane[data-clear-pane-state="expanded"] { height: 92vh; }

.clear-pane-grip {
  display: none;
  width: 100%;
  padding: 10px 0 6px;
  border: 0;
  background: transparent;
  flex: 0 0 auto;
}
.clear-pane-grip::before {
  content: "";
  display: block;
  width: 36px;
  height: 4px;
  margin: 0 auto;
  border-radius: 999px;
  background: var(--line-strong);
}
@media (max-width: 767px) {
  .clear-pane-grip { display: block; }
}

/* =============================================================================
   6. Floating map chrome — controls, legend, coordinate pill
   ========================================================================== */
.clear-map-floating-row { position: absolute; z-index: 5; display: flex; align-items: center; gap: 10px; }
.clear-map-floating-row.top-left { top: 16px; left: 18px; }
.clear-map-floating-row.top-right { top: 16px; right: 48px; }

.clear-map-toolbar-button {
  height: 40px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface);
  color: var(--ink);
  padding: 0 14px;
  box-shadow: var(--sh-1);
  font-size: 13px;
  font-weight: 700;
  font-family: var(--f);
}
.clear-map-toolbar-button[aria-disabled="true"] { color: var(--muted); }

/* FCLEAR-APP-0002B, Gate B finding F: "clicking the Basemap control appears to do nothing".
   The control was already honest -- its title has always explained that no Standard basemap is
   published -- but `.clear-action` had no disabled treatment at all, so Basemap and Help rendered
   as fully clickable and the explanation only ever appeared on hover. A user clicks, nothing
   happens, and the reason is invisible. This mirrors the treatment `.clear-tier1-link` and
   `.clear-map-toolbar-button` already carry (:305, :588); it is not a new visual language.
   It disappears on its own the moment a control becomes enabled. */
.clear-action[aria-disabled="true"] { color: var(--faint); cursor: not-allowed; }
.clear-action[aria-disabled="true"]:hover { background: transparent; border-color: var(--line); }
.clear-action[aria-disabled="true"] .clear-action-state { opacity: .75; }
.clear-map-status-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--good); box-shadow: 0 0 0 3px color-mix(in srgb, var(--good) 18%, transparent); }

.clear-map-aq-card {
  position: absolute;
  z-index: 5;
  left: 14px;
  bottom: 88px;
  width: 232px;
  border-radius: var(--r-md);
  padding: 13px 15px 14px;
  background: rgba(13, 39, 65, .94);
  color: #fff;
  box-shadow: var(--sh-3);
  backdrop-filter: blur(8px);
}
.clear-map-aq-kicker { font-size: 10px; font-weight: 800; letter-spacing: .13em; text-transform: uppercase; color: rgba(255, 255, 255, .70); font-family: var(--f); }
.clear-map-aq-title { margin-top: 5px; font-size: 15px; font-weight: 800; line-height: 1.2; }
.clear-map-aq-body { margin-top: 7px; color: rgba(255, 255, 255, .76); font-size: 12px; line-height: 1.4; }
.clear-map-aq-progress { margin-top: 11px; height: 6px; border-radius: 999px; background: rgba(255, 255, 255, .17); overflow: hidden; }
.clear-map-aq-progress span { display: block; width: 0; height: 100%; background: var(--brand-accent); border-radius: inherit; }
.clear-map-aq-value { margin-top: 10px; font-size: 26px; line-height: 1; font-weight: 800; color: #fff; font-family: var(--m); font-variant-numeric: tabular-nums; }
.clear-map-aq-value small { font-size: 12px; margin-left: 4px; color: rgba(255, 255, 255, .8); }
.clear-map-aq-foot { margin-top: 10px; color: rgba(255, 255, 255, .84); font-size: 11px; line-height: 1.45; }

.clear-coord,
.clear-coordinate-pill,
.clear-map-coordinate-pill {
  position: absolute;
  z-index: 5;
  right: 18px;
  bottom: 18px;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-height: 34px;
  padding: 0 13px;
  border-radius: 999px;
  background: rgba(11, 28, 46, .86);
  color: #fff;
  box-shadow: var(--sh-1);
  backdrop-filter: blur(8px);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .01em;
}
.clear-coord span + span, .clear-coordinate-pill span + span, .clear-map-coordinate-pill span + span { padding-left: 10px; border-left: 1px solid rgba(255, 255, 255, .20); }

.clear-watermark,
.clear-map-watermark { position: absolute; z-index: 4; right: 24px; bottom: 74px; width: 142px; height: auto; opacity: .76; pointer-events: none; user-select: none; }

.clear-map-status { position: absolute; z-index: 6; max-width: 340px; border-radius: var(--r-md); padding: 13px 14px; background: rgba(13, 39, 65, .88); color: #fff; box-shadow: var(--sh-2); backdrop-filter: blur(8px); }
.clear-map-status strong { display: block; margin-bottom: 4px; font-size: 13px; }
.clear-map-status div { font-size: 12px; line-height: 1.4; color: rgba(255, 255, 255, .82); }
.clear-map-basemap-status { top: 74px; left: 18px; }
.clear-map-error { background: rgba(126, 36, 36, .92); }

/* =============================================================================
   7. Cards & disclosure
   ========================================================================== */
.clear-card {
  min-width: 0; /* mandatory safeguard — see .clear-pane */
  border: 1px solid var(--line);
  background: var(--surface);
  border-radius: var(--r-lg);
  box-shadow: var(--sh-1);
  margin-bottom: 10px;
}
.clear-card-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 13px 14px 0; }
.clear-card-head h3 { margin: 0; font-size: 14px; font-weight: 700; color: var(--ink); }
.clear-card-tools { display: flex; align-items: center; gap: 6px; }
.clear-card-body { padding: 10px 14px 14px; }

.clear-disclosure {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--surface);
  color: var(--brand-ink);
  padding: 0 10px;
  height: 30px;
  font-size: 12px;
  font-weight: 700;
  font-family: var(--f);
}
.clear-disclosure::after { content: "▾"; font-size: 10px; transition: transform .15s ease; }
.clear-disclosure[aria-expanded="true"]::after { transform: rotate(180deg); }
.clear-disclosure-body { margin-top: 10px; }
.clear-disclosure-body[hidden] { display: none; }

/* =============================================================================
   8. Analytical pane — identity, tabs, panels
   ========================================================================== */
.clear-pane-identity { padding: 16px 18px 14px; border-bottom: 1px solid var(--line); }
.clear-pane-identity[hidden] { display: none; }
.clear-pane-tabs {
  display: flex;
  align-items: stretch;
  gap: 0;
  padding: 0 14px;
  border-bottom: 1px solid var(--line);
  overflow-x: auto;
  flex: 0 0 auto;
}
.clear-pane-tab {
  position: relative;
  min-width: max-content;
  height: 46px;
  border: 0;
  background: transparent;
  color: var(--muted);
  padding: 0 12px;
  font-size: 13px;
  font-weight: 700;
  font-family: var(--f);
}
.clear-pane-tab[aria-selected="true"] { color: var(--brand-ink); }
.clear-pane-tab[aria-selected="true"]::after {
  content: "";
  position: absolute;
  left: 10px;
  right: 10px;
  bottom: 0;
  height: 3px;
  border-radius: 999px 999px 0 0;
  background: var(--brand-ink);
}
.clear-pane-tab:disabled { color: var(--faint); }

.clear-pane-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden; padding: 16px; background: var(--surface-2); }
.clear-tabpanel[hidden] { display: none; }
.clear-pane-actions { display: grid; grid-template-columns: 1fr 1fr 1fr 34px; gap: 8px; padding: 14px 16px 16px; background: var(--surface); border-top: 1px solid var(--line); flex: 0 0 auto; }

/* Overview answer strip — states what is known before any chart, per the
   design thesis: the answer comes before the evidence. */
.clear-answer-strip { padding: 12px 14px; border-radius: var(--r-md); background: var(--surface-3); color: var(--ink); font-size: 13px; line-height: 1.5; margin-bottom: 12px; }
.clear-registry-caveat { display: inline-flex; align-items: center; gap: 6px; margin-top: 6px; color: var(--muted); font-size: 11.5px; }

/* =============================================================================
   9. Pollutant tiles — the only pollutant selector in the document
   ========================================================================== */
.clear-tiles {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 6px;
}
.clear-tile {
  min-width: 0;
  border: 1px solid var(--tile-border);
  border-radius: var(--r-md);
  background: var(--surface);
  padding: 8px 6px 7px;
  text-align: left;
  min-height: 76px;
}
.clear-tile-label { display: block; color: var(--ink); font-size: 12px; font-weight: 700; }
.clear-tile-value { display: block; margin-top: 6px; color: var(--ink); font-size: 18px; line-height: 1.05; font-weight: 800; letter-spacing: -.01em; }
.clear-tile-unit { font-size: .62em; font-weight: 700; margin-left: 2px; }
.clear-tile-condition { display: block; margin-top: 5px; color: var(--muted); font-size: 11px; font-weight: 700; }
.clear-tile:hover { border-color: var(--line-strong); }
.clear-tile.is-active { border: 2px solid var(--brand-ink); background: color-mix(in srgb, var(--brand-ink) 6%, var(--surface)); padding: 7px 5px 6px; }
.clear-tile:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }

/* PM10-style "not currently served" tile: reads as absence of data, never as
   good/zero/low. No condition colour, no value, no unit — just --unavail. */
.clear-tile.is-unavailable {
  border-style: dashed;
  color: var(--unavail);
  cursor: default;
}
.clear-tile.is-unavailable .clear-tile-label { color: var(--muted); }
.clear-tile.is-unavailable .clear-tile-condition { color: var(--unavail); font-weight: 600; text-transform: none; }

@media (max-width: 767px) {
  .clear-tiles { grid-auto-flow: column; grid-auto-columns: 118px; grid-template-columns: none; overflow-x: auto; padding-bottom: 4px; }
}

/* =============================================================================
   10. Reporting sources / nearby / radius / evidence rows
   ========================================================================== */
.clear-source-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 10px;
  align-items: start;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface-2);
}
.clear-source-row + .clear-source-row { margin-top: 8px; }
.clear-source-row strong { display: block; color: var(--ink); font-size: 12px; line-height: 1.3; }
.clear-source-row span { display: block; color: var(--muted); font-size: 11.5px; line-height: 1.45; }
.clear-source-badge { flex: 0 0 auto; border-radius: 999px; padding: 3px 8px; font-size: 11px; font-weight: 700; white-space: nowrap; }
.clear-source-badge.is-regulatory { background: color-mix(in srgb, var(--sig-reg) 12%, var(--surface)); color: var(--sig-reg); }
.clear-source-badge.is-community { background: color-mix(in srgb, var(--sig-com) 12%, var(--surface)); color: var(--sig-com); }

.clear-radius-block { display: grid; gap: 12px; }
.clear-radius-toolbar { display: flex; flex-wrap: wrap; gap: 8px; }
.clear-radius-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.clear-radius-row label { color: var(--muted); font-size: 12px; font-weight: 700; }
.clear-radius-row output { font-family: var(--m); font-variant-numeric: tabular-nums; font-size: 12px; color: var(--ink); }
.clear-radius-disclaimer { margin: 0; color: var(--muted); font-size: 10.5px; line-height: 1.45; }

.clear-nearby-row,
.clear-detail-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 10px;
  padding: 8px 0;
  border-top: 1px solid var(--line);
}
.clear-nearby-row:first-child,
.clear-detail-row:first-child { border-top: 0; padding-top: 0; }
.clear-nearby-distance { font-family: var(--m); font-variant-numeric: tabular-nums; color: var(--muted); font-size: 12px; white-space: nowrap; }

.clear-evidence-row { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; gap: 10px; align-items: center; padding: 9px 0; border-top: 1px solid var(--line); }
.clear-evidence-row:first-child { border-top: 0; padding-top: 0; }
.clear-evidence-class { font-size: 12px; font-weight: 700; color: var(--ink); }
.clear-evidence-count { font-family: var(--m); font-variant-numeric: tabular-nums; font-size: 12px; color: var(--muted); }

/* =============================================================================
   11. History graph (.clear-hg-*)
   Regulatory = solid line, --sig-reg. Community = hollow diamond marker,
   --sig-com, never a line. Gaps = hatched band, never a line. Provenance is
   structural (different mark + geometry), never colour-only.
   ========================================================================== */
.clear-hg-toolbar { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.clear-hg-ranges { display: inline-flex; border: 1px solid var(--line); border-radius: var(--r-sm); overflow: hidden; }
.clear-hg-range { appearance: none; border: 0; background: var(--surface); color: var(--ink); font: inherit; font-family: var(--f); font-size: 11px; letter-spacing: .04em; padding: 5px 10px; cursor: pointer; }
.clear-hg-range + .clear-hg-range { border-left: 1px solid var(--line); }
.clear-hg-range.is-active { background: var(--sig-reg); color: #fff; }
.clear-hg-range:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }

.clear-hg-serieses { display: inline-flex; align-items: center; gap: 10px; font-size: 11px; color: var(--muted); font-family: var(--f); }
.clear-hg-series-static { display: inline-flex; align-items: center; gap: 5px; }
.clear-hg-series-toggle { appearance: none; border: 1px solid var(--line); background: var(--surface); border-radius: var(--r-sm); font: inherit; font-family: var(--f); font-size: 11px; color: var(--muted); padding: 4px 8px; cursor: pointer; display: inline-flex; align-items: center; gap: 5px; }
.clear-hg-series-toggle.is-active { border-color: var(--sig-com); color: var(--ink); }
.clear-hg-series-toggle:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }
.clear-hg-swatch { width: 9px; height: 9px; border-radius: 2px; flex: 0 0 auto; }
.clear-hg-swatch.is-regulatory { background: var(--sig-reg); border-radius: 1px; }
.clear-hg-swatch.is-community { background: transparent; border: 2px solid var(--sig-com); transform: rotate(45deg); }
.clear-hg-swatch.is-community.is-complete { background: var(--sig-com); }

/* Mandatory safeguard: a wide, unbroken chart must scroll horizontally
   inside its own track rather than forcing the pane wider than 100%. */
.clear-hg-scroll {
  max-width: 100%;
  overflow-y: hidden;
  overscroll-behavior-x: contain;
  /* NOT `scroll-behavior: smooth`. This scroller is DIRECT MANIPULATION: the pan handler writes
     scrollLeft once per animation frame while the finger moves. With smooth behaviour the browser
     animates towards each of those writes instead of applying it, so every frame starts a fresh
     eased animation towards a target the finger has already left -- the rendered timeline lags the
     finger and the gesture feels heavy. Measured on iPhone as the dominant cause. The only other
     scrollLeft writers here (keyboard month navigation, and the initial scroll to the newest
     month) also want an immediate reposition, so `auto` is correct for the whole component.

     `-webkit-overflow-scrolling: touch` was removed with it: it puts the scroller on a legacy iOS
     compositor scroll layer where programmatic scrollLeft is applied out of band from the touch
     stream, and it is redundant on modern iOS, which gives momentum scrolling by default. */
  scroll-behavior: auto;
  /* The scrollbar is part of the design: it is how the user knows the timeline continues past the
     viewport. It is deliberately always visible on a scrollable range, not overlay-on-hover. */
  /* The scrollbar is part of the design: it is how the user sees that the timeline continues past
     the viewport. `scrollbar-width: thin` yielded an OVERLAY scrollbar that reserved no space and
     was invisible until scrolled, so the timeline looked like it simply ended. `scroll` reserves
     the track permanently and the webkit rules below give it a visible thumb. Measured: the track
     must occupy real height, not 0. */
  overflow-x: scroll;
  scrollbar-color: var(--line-strong, #c7d2dd) var(--surface-3, #eef2f6);
  padding-bottom: 2px;
}
.clear-hg-scroll::-webkit-scrollbar { height: 10px; }
.clear-hg-scroll::-webkit-scrollbar-track { background: var(--surface-3, #eef2f6); border-radius: 999px; }
.clear-hg-scroll::-webkit-scrollbar-thumb {
  background: var(--line-strong, #c7d2dd); border-radius: 999px;
  border: 2px solid var(--surface, #fff);
}
.clear-hg-scroll::-webkit-scrollbar-thumb:hover { background: var(--muted, #5b7285); }
.clear-hg-canvas { display: block; }
.clear-hg-canvas:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.clear-hg-svg { display: block; }

.clear-hg-grid {}
.clear-hg-gridline { stroke: var(--line); stroke-width: 1; }
.clear-hg-yeartick { stroke: var(--line); stroke-width: 1; stroke-dasharray: 2 3; }
.clear-hg-vlabel, .clear-hg-ylabel { fill: var(--muted); font-size: 9px; }

/* Ordinary gaps: a hatched band, never a connecting line and never a solid
   fill — a repeating diagonal pattern reads as "unknown", not "zero". */
.clear-hg-gap { fill: var(--surface-3); }
.clear-hg-gap.is-hatched {
  fill: repeating-linear-gradient(45deg, var(--line) 0 2px, transparent 2px 6px);
}
.clear-hg-gap.is-uncovered_after_termination { fill: var(--surface-3); opacity: .6; }

path.clear-hg-reg { stroke: var(--sig-reg); stroke-width: 1.8; fill: none; stroke-linejoin: round; stroke-linecap: round; }
path.clear-hg-reg.is-provisional { stroke-dasharray: 3 2; }
circle.clear-hg-reg { fill: var(--sig-reg); stroke: none; }
circle.clear-hg-point,
circle.clear-hg-point-single { stroke: #fff; stroke-width: 1.4; }

/* Community: discrete diamond markers only, never a line, never merged with the Regulatory
   series. Hollow (.is-partial) is the default appearance; filled (.is-complete) is drawn only
   when the governed contract establishes a full 12-of-12-month year -- a shape/fill distinction,
   never colour-only, so it survives grayscale. */
.clear-hg-comm { stroke: var(--sig-com); stroke-width: 1.8; }
.clear-hg-comm.is-partial { fill: var(--surface); }
.clear-hg-comm.is-complete { fill: var(--sig-com); }
.clear-hg-comm:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }

/* Data-driven legend keys beside the Community toggle -- only the marker meanings actually
   present in this model's Community years are rendered (FCLEAR-APP-0014 point 7). */
.clear-hg-community-legend { display: inline-flex; align-items: center; gap: 10px; margin-left: 6px; }
.clear-hg-legend-key { display: inline-flex; align-items: center; gap: 4px; font-size: 10px; color: var(--muted); font-family: var(--f); }

/* Governed source-segment boundary label: neutral structural text, distinct from the dashed
   `.clear-hg-transition` rule it annotates. A one-month-apart pair of boundaries is consolidated
   into a single label (see hgAppendSegmentBoundaryLabels) rather than left to overprint. */
.clear-hg-transition-label { fill: var(--muted); font-size: 8px; font-family: var(--f); }
.clear-hg-transition-bracket { stroke: var(--muted); stroke-width: .75; }

.clear-hg-transition { stroke: var(--line-strong); stroke-width: 1; stroke-dasharray: 3 2; }
.clear-hg-focusline { stroke: var(--sig-reg); stroke-width: 1; opacity: .45; }
.clear-hg-focusdot { fill: #fff; stroke: var(--sig-reg); stroke-width: 1.8; }

/* Pinned state is a stronger, persistent variant of the transient hover
   focus ring — click pins a month, a second click (or Esc) unpins it. */
.clear-hg-pinline { stroke: var(--brand-ink); stroke-width: 1.5; opacity: .7; }
.clear-hg-pindot { fill: #fff; stroke: var(--brand-ink); stroke-width: 2.4; }

/* One invisible full-height rect per month: generous, y-position-independent
   hit targets for hover/click/keyboard nearest-month resolution. */
.clear-hg-hit { fill: transparent; pointer-events: all; cursor: pointer; }

.clear-hg-hint { margin: 4px 0 0; font-size: 10px; color: var(--faint); font-family: var(--f); }

/* Fixed region below the chart — never floats, never follows the cursor,
   never overlays the plot. */
.clear-hg-tip { min-height: 46px; margin-top: 6px; font-size: 11px; line-height: 1.45; color: var(--ink); }
.clear-hg-tip-class { display: inline-block; font-size: 10px; letter-spacing: .05em; text-transform: uppercase; font-family: var(--f); }
.clear-hg-tip-class.is-regulatory { color: var(--sig-reg); }
.clear-hg-tip-class.is-community { color: var(--sig-com); }
.clear-hg-tip-flag { color: var(--moderate); font-family: var(--f); }
.clear-hg-tip-inferred { color: var(--faint); font-size: 10px; font-family: var(--f); }

.clear-hg-empty { font-size: 12px; color: var(--muted); margin: 6px 0; font-family: var(--f); }
.clear-hg-details-toggle { margin-top: 8px; }
.clear-hg-table { margin-top: 8px; max-width: 100%; overflow-x: auto; }
.clear-hg-table table { border-collapse: collapse; width: 100%; font-size: 12px; }
.clear-hg-table th { position: sticky; top: 0; background: var(--surface); text-align: left; color: var(--muted); font-size: 10px; letter-spacing: .06em; text-transform: uppercase; padding: 6px 8px; border-bottom: 1px solid var(--line); }
.clear-hg-table td { padding: 6px 8px; border-bottom: 1px solid var(--surface-3); }

.clear-hg-visually-hidden { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

@media (prefers-reduced-motion: reduce) {
  .clear-hg-scroll { scroll-behavior: auto; }
}

/* =============================================================================
   12. Legacy structural shell — pre-redesign class names.
   These stay themed with the new tokens so nothing loses its styling if the
   integrator has not yet migrated a given fragment of markup.
   ========================================================================== */
.clear-map-app {
  height: 100vh;
  display: grid;
  grid-template-rows: var(--clear-header-height) var(--clear-nav-height) minmax(0, 1fr);
  background: var(--clear-map-bg);
}

.clear-map-app-header,
.clear-map-primary-nav {
  background: var(--clear-shell-navy);
  color: var(--clear-header-text);
}

.clear-map-app-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: 12px 24px 10px 20px;
  border-bottom: 0;
  box-shadow: none;
}

.clear-map-app-brand { display: flex; align-items: center; gap: 14px; min-width: 0; }
.clear-map-app-brand img { width: 48px; height: 48px; border-radius: var(--r-md); object-fit: contain; flex: 0 0 auto; box-shadow: var(--sh-1); }
.clear-map-app-kicker { font-size: 11px; font-weight: 800; letter-spacing: .18em; text-transform: uppercase; color: var(--clear-muted-on-navy); }
.clear-map-app-title { margin: 3px 0 0; font-size: 23px; line-height: 1.08; font-weight: 800; color: #fff; }
.clear-map-app-subtitle { margin-top: 5px; font-size: 12.5px; color: rgba(255, 255, 255, .78); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.clear-map-app-subtitle-attribution { font-size: .92em; opacity: .88; }

.clear-map-app-tools { display: flex; align-items: center; gap: 14px; min-width: 0; }
.clear-map-header-search {
  width: 295px;
  height: 44px;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 14px;
  border-radius: var(--r-md);
  background: rgba(255, 255, 255, .13);
  border: 1px solid rgba(255, 255, 255, .14);
}
.clear-map-search-icon { width: 17px; height: 17px; color: rgba(255, 255, 255, .84); flex: 0 0 auto; }
.clear-map-header-search input, .clear-map-canvas-search input { width: 100%; min-width: 0; border: 0; outline: 0; background: transparent; }
.clear-map-header-search input { color: #fff; font-size: 14px; }
.clear-map-header-search input::placeholder { color: rgba(255, 255, 255, .66); }
.clear-map-header-divider { width: 1px; height: 40px; background: rgba(255, 255, 255, .18); }
.clear-map-icon-button {
  width: 44px; height: 44px; display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid rgba(255, 255, 255, .16); border-radius: var(--r-md); background: rgba(255, 255, 255, .10); color: #fff;
}
.clear-map-user-chip { display: flex; align-items: center; gap: 11px; min-width: 216px; border: 0; background: transparent; color: #fff; padding: 0; text-align: left; }
.clear-map-user-avatar { width: 40px; height: 40px; border-radius: 50%; background: var(--brand-ink); display: inline-flex; align-items: center; justify-content: center; font-size: 13px; font-weight: 800; color: #fff; flex: 0 0 auto; }
.clear-map-user-meta { min-width: 0; line-height: 1.32; }
.clear-map-user-meta strong, .clear-map-user-meta span { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.clear-map-user-meta strong { font-size: 14px; font-weight: 800; }
.clear-map-user-meta span { font-size: 12px; color: rgba(255, 255, 255, .72); }

.clear-map-primary-nav {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 4px 18px 10px;
  overflow-x: auto;
  border-top: 0;
}
.clear-map-nav-link, .clear-map-nav-button {
  height: 36px;
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 0 13px;
  border-radius: var(--r-md);
  border: 0;
  background: transparent;
  color: rgba(255, 255, 255, .86);
  text-decoration: none;
  font-size: 13px;
  font-weight: 700;
  white-space: nowrap;
  flex: 0 0 auto;
}
.clear-map-nav-link.active { background: #fff; color: var(--clear-blue-dark); box-shadow: var(--sh-1); }
.clear-map-nav-link:not(.active):hover, .clear-map-nav-button:not(:disabled):hover { background: rgba(255, 255, 255, .10); }
.clear-map-nav-button:disabled { opacity: 1; }
.clear-map-nav-icon { width: 18px; height: 18px; display: inline-flex; align-items: center; justify-content: center; }
.clear-map-nav-icon svg, .clear-map-button-icon svg, .clear-map-search-icon svg { width: 100%; height: 100%; display: block; }

.clear-map-workspace {
  display: grid;
  grid-template-columns: var(--clear-left-width) minmax(0, 1fr) var(--clear-right-width);
  min-width: 0;
  min-height: 0;
  height: 100%;
  overflow: hidden;
  background: var(--clear-map-bg);
}

.clear-map-sidebar, .clear-map-detail-panel { background: var(--clear-panel); min-height: 0; overflow-y: auto; overflow-x: hidden; }
.clear-map-sidebar { border-right: 1px solid var(--clear-border); padding: 18px 20px 0; display: flex; flex-direction: column; }
.clear-map-panel-section + .clear-map-panel-section { margin-top: 22px; padding-top: 18px; border-top: 1px solid var(--clear-border); }
.clear-map-section-header { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 12px; }
.clear-map-section-kicker { font-size: 11px; font-weight: 800; letter-spacing: .16em; color: var(--muted); text-transform: uppercase; }
.clear-map-reset-button { border: 0; background: transparent; color: var(--clear-blue); font-size: 12px; font-weight: 700; padding: 5px 0; }

.clear-map-layer-list { display: grid; gap: 3px; }
.clear-map-layer-item { min-height: 43px; display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 8px; border-radius: var(--r-md); padding: 5px 2px; }
.clear-map-layer-item.is-active { background: var(--clear-blue-soft); }
.clear-map-layer-item.is-regulatory-active { background: color-mix(in srgb, var(--sig-reg) 10%, var(--surface)); }
.clear-map-layer-item.is-community-active { background: color-mix(in srgb, var(--sig-com) 10%, var(--surface)); }
.clear-map-layer-item.disabled { color: var(--clear-gray); }
.clear-map-layer-item label { display: flex; align-items: center; gap: 10px; min-width: 0; }
.clear-map-layer-item input { width: 15px; height: 15px; accent-color: var(--brand-ink); flex: 0 0 auto; }
.clear-map-layer-name { min-width: 0; font-size: 13px; font-weight: 700; color: var(--clear-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.clear-map-layer-item[data-clear-layer-row="regulatory-air-monitors"] .clear-map-layer-name,
.clear-map-layer-item[data-clear-layer-row="community-air-sensors"] .clear-map-layer-name {
  overflow: visible;
  text-overflow: clip;
}
.clear-map-layer-item.disabled .clear-map-layer-name { color: var(--clear-gray); font-weight: 700; }
.clear-map-layer-state { font-size: 12px; line-height: 1.2; color: var(--ink); text-align: right; min-width: 58px; font-weight: 600; font-family: var(--m); font-variant-numeric: tabular-nums; }
.clear-map-layer-item.is-active .clear-map-layer-state,
.clear-map-layer-item.is-regulatory-active .clear-map-layer-state,
.clear-map-layer-item.is-community-active .clear-map-layer-state { font-weight: 800; }
.clear-map-layer-icon { width: 24px; height: 24px; border-radius: 50%; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; color: #fff; font-size: 12px; font-weight: 800; box-shadow: none; }
.layer-hospital { background: var(--clear-blue); }
.layer-monitor { background: var(--sig-reg); }
.layer-community { background: var(--sig-com); }
.layer-facility { background: var(--clear-purple); }
.layer-public-school { background: #2563eb; }
.layer-private-school { background: #b45309; }
.layer-postsecondary-school { background: #7c3aed; }
.layer-permit { background: var(--clear-orange); }
.layer-toxics { background: #a64d79; }
.layer-wildfire { background: var(--clear-wildfire); }
.layer-air { background: #7457d8; }
.layer-regulatory-airnow { background: var(--sig-reg); }

.clear-map-layer-subsection { margin: 15px 0 7px; color: var(--muted); font-size: 11px; font-weight: 800; letter-spacing: .16em; text-transform: uppercase; }
.clear-map-layer-subsection:first-of-type { margin-top: 2px; }

.clear-map-filter-list { display: grid; gap: 12px; }
.clear-map-filter label { display: block; margin-bottom: 6px; font-size: 12px; font-weight: 700; color: var(--muted); }
.clear-map-filter select { width: 100%; height: 44px; border-radius: var(--r-md); border: 1px solid var(--clear-border); background: var(--clear-panel-soft); color: var(--clear-text-muted); padding: 0 12px; }
.clear-map-source-status { margin-top: auto; display: flex; align-items: center; gap: 8px; padding: 14px 0 15px; color: var(--clear-text-muted); font-size: 12px; line-height: 1.35; border-top: 1px solid var(--line); background: transparent; }
.clear-map-source-status-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--good); color: var(--good); flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; }
.clear-map-source-status-dot::before { content: none; }
.clear-map-source-refresh { margin-left: auto; width: 18px; height: 18px; color: var(--clear-blue); display: inline-flex; align-items: center; justify-content: center; }
.clear-map-source-refresh svg { width: 15px; height: 15px; }

.clear-map-canvas { position: relative; min-width: 0; min-height: 0; height: 100%; overflow: hidden; background: #cddae5; }
.clear-map-surface { position: absolute; inset: 0; width: 100%; height: 100%; }
.clear-map-canvas-search { width: 315px; height: 44px; display: flex; align-items: center; gap: 10px; padding: 0 14px; border-radius: var(--r-md); background: #fff; border: 1px solid rgba(15, 35, 55, .10); box-shadow: var(--sh-1); }
.clear-map-canvas-search .clear-map-search-icon { color: var(--muted); }
.clear-map-canvas-search input { color: var(--clear-text); font-size: 14px; }
.clear-map-canvas-search input::placeholder { color: var(--faint); }

.clear-map-detail-panel { border-left: 1px solid var(--clear-border); display: flex; flex-direction: column; }
.clear-map-detail-header { padding: 19px 24px 16px; border-bottom: 1px solid var(--clear-border); }
.clear-map-detail-header-row { display: grid; grid-template-columns: 42px minmax(0, 1fr) 34px; gap: 13px; align-items: start; }
.clear-map-detail-icon { width: 38px; height: 38px; border-radius: 50%; background: var(--clear-blue); color: #fff; display: inline-flex; align-items: center; justify-content: center; font-size: 18px; font-weight: 800; box-shadow: none; margin-top: 0; }
.clear-map-detail-title-line { display: flex; align-items: center; gap: 8px; min-width: 0; justify-content: flex-start; }
.clear-map-detail-title { margin: 0; color: var(--clear-text); font-size: 18px; line-height: 1.22; font-weight: 700; min-width: 0; letter-spacing: -.01em; }
.clear-map-detail-badge { flex: 0 0 auto; border-radius: 999px; padding: 4px 8px; background: var(--clear-green-soft); color: #137448; font-size: 11px; font-weight: 800; }
.clear-map-detail-close { width: 32px; height: 32px; border: 1px solid var(--clear-border); border-radius: var(--r-md); background: #fff; color: var(--muted); display: inline-flex; align-items: center; justify-content: center; }
.clear-map-detail-address { margin-top: 5px; color: var(--clear-text-muted); font-size: 13px; line-height: 1.42; }
.clear-map-detail-submeta { margin-top: 8px; display: flex; flex-wrap: wrap; gap: 5px 8px; color: var(--muted); font-size: 12px; }
.clear-map-detail-submeta span { display: inline-flex; align-items: center; min-height: 16px; }
.clear-map-detail-submeta span + span::before { content: "•"; margin-right: 8px; color: var(--faint); }
.clear-map-detail-tabs { min-height: 52px; display: flex; align-items: stretch; gap: 0; padding: 0 18px; border-bottom: 1px solid var(--clear-border); overflow-x: auto; }
.clear-map-tab { position: relative; min-width: max-content; border: 0; background: transparent; color: var(--muted); padding: 0 13px; font-size: 13px; font-weight: 800; }
.clear-map-tab[aria-selected="true"] { color: var(--clear-blue); }
.clear-map-tab[aria-selected="true"]::after { content: ""; position: absolute; left: 12px; right: 12px; bottom: 0; height: 3px; border-radius: 999px 999px 0 0; background: var(--clear-blue); }
.clear-map-detail-body { min-height: 0; flex: 1 1 auto; overflow-y: auto; overflow-x: hidden; padding: 20px; background: var(--surface-2); }
.clear-map-detail-empty { display: grid; place-items: center; min-height: 100%; padding: 36px 24px; text-align: center; color: var(--clear-text-muted); }
.clear-map-detail-empty[hidden] { display: none; }
.clear-map-detail-empty-icon { width: 68px; height: 68px; border-radius: var(--r-lg); display: inline-flex; align-items: center; justify-content: center; background: var(--clear-blue-soft); color: var(--clear-blue); font-size: 28px; font-weight: 800; margin-bottom: 16px; }
.clear-map-detail-empty h3 { margin: 0 0 8px; color: var(--clear-text); font-size: 22px; line-height: 1.15; }
.clear-map-detail-empty p { margin: 0; font-size: 14px; line-height: 1.55; max-width: 280px; }
.clear-map-overview-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; margin-bottom: 14px; }
.clear-map-metric-card, .clear-map-detail-card { border: 1px solid var(--clear-border); background: #fff; border-radius: var(--r-lg); box-shadow: var(--sh-1); min-width: 0; }
.clear-map-metric-card { padding: 11px 12px; min-height: 92px; }
.clear-map-metric-label { color: var(--ink); font-size: 12px; line-height: 1.2; font-weight: 700; }
.clear-map-metric-value { margin-top: 6px; color: var(--clear-text); font-size: 13px; line-height: 1.35; font-weight: 700; }
.clear-map-metric-primary { display: block; color: var(--good); font-size: var(--clear-dashboard-value-size); line-height: 1.05; font-weight: 800; letter-spacing: -.02em; }
.clear-map-metric-secondary { display: block; margin-top: 5px; color: var(--muted); font-size: var(--clear-dashboard-secondary-size); line-height: 1.28; font-weight: 700; }
.clear-metric-reading { display: inline-grid; gap: 3px; align-items: start; }
.clear-metric-number { display: block; font-size: 1em; line-height: 1; font-weight: 800; }
.clear-metric-unit { display: block; font-size: var(--clear-dashboard-unit-scale); line-height: 1.05; font-weight: 700; white-space: nowrap; }
.clear-metric-status, .clear-metric-comparison { display: block; }
.clear-metric-comparison { margin-top: 4px; color: var(--muted); font-size: 12.5px; line-height: 1.25; font-weight: 700; }
.clear-map-detail-card { padding: 13px; margin-bottom: 10px; }
.clear-map-detail-card h3 { margin: 0 0 9px; font-size: 15px; color: var(--clear-text); }
.clear-map-detail-card p { margin: 0; color: var(--clear-text-muted); font-size: 13px; line-height: 1.5; }
.clear-map-detail-meta { display: grid; gap: 6px; margin: 0; }
.clear-map-detail-meta div { display: grid; grid-template-columns: 125px minmax(0, 1fr); gap: 10px; padding: 8px 0; border-top: 1px solid var(--surface-3); }
.clear-map-detail-meta div:first-child { border-top: 0; }
.clear-map-detail-meta dt { color: var(--muted); font-size: 12px; font-weight: 700; }
.clear-map-detail-meta dd { margin: 0; color: var(--clear-text); font-size: 12px; font-weight: 700; min-width: 0; overflow-wrap: anywhere; font-family: var(--m); }
.clear-map-condition-grid { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 6px; }
.clear-map-condition-source-note { margin-top: 9px; color: var(--clear-text-muted); font-size: 11.5px; line-height: 1.42; }
.clear-map-condition-source-list { margin-top: 12px; display: grid; gap: 8px; }
.clear-map-condition-source-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 10px; align-items: start; padding: 10px 12px; border: 1px solid var(--surface-3); border-radius: var(--r-md); background: var(--surface-2); }
.clear-map-condition-source-row strong { display: block; color: var(--clear-text); font-size: 12px; line-height: 1.3; }
.clear-map-condition-source-row span { display: block; color: var(--clear-text-muted); font-size: 11.5px; line-height: 1.45; }
.clear-map-panel-note { margin-top: 10px; color: var(--clear-text-muted); font-size: 11px; line-height: 1.45; }
.clear-map-link-action { margin-top: 10px; border: 1px solid var(--clear-border); border-radius: var(--r-md); background: #fff; color: var(--clear-blue); min-height: 32px; padding: 0 10px; font-size: 12px; font-weight: 800; }
.clear-map-condition { border: 1px solid var(--surface-3); border-radius: var(--r-md); padding: 10px 8px; text-align: center; background: var(--surface-2); min-height: 92px; }
.clear-map-condition strong { display: block; color: var(--ink); font-size: 12px; margin-bottom: 5px; font-weight: 800; text-align: center; }
.clear-map-condition span { display: block; margin-top: 6px; color: var(--clear-text); font-size: var(--clear-condition-value-size); line-height: 1.05; font-weight: 800; text-align: center; letter-spacing: -.01em; }
.clear-condition-reading { display: grid; gap: 2px; align-items: start; }
.clear-condition-number { display: block; font-size: 1em; line-height: 1; font-weight: 800; }
/* The pollutant tile's reading is the primary number on the card. The pre-redesign rule
   sized it explicitly; without this it inherits 1em and the tiles read as body text. */
.clear-tile .clear-condition-number { font-size: 24px; }

.clear-condition-unit { display: block; font-size: var(--clear-condition-unit-scale); line-height: 1.05; font-weight: 700; white-space: nowrap; }
.clear-map-condition small { display: block; margin-top: 5px; color: var(--clear-text-muted); font-size: var(--clear-condition-category-size); line-height: 1.22; font-weight: 700; text-align: center; }
/* The governed condition-category word under each tile value. The rule above is scoped to
   the pre-redesign selector, which no longer matches any element, so the category text was
   left unstyled by the rename. Same declarations, current selector. */
.clear-tile > small { display: block; margin-top: 5px; color: var(--muted); font-size: var(--clear-condition-category-size); line-height: 1.22; font-weight: 800; }

.clear-aqi-category-good { color: var(--clear-aqi-good) !important; }
.clear-aqi-category-moderate { color: var(--clear-aqi-moderate) !important; }
.clear-aqi-category-unhealthy-sensitive { color: var(--clear-aqi-unhealthy-sensitive) !important; }
.clear-aqi-category-unhealthy { color: var(--clear-aqi-unhealthy) !important; }
.clear-aqi-category-very-unhealthy { color: var(--clear-aqi-very-unhealthy) !important; }
.clear-aqi-category-hazardous { color: var(--clear-aqi-hazardous) !important; }
.clear-aqi-category-unavailable { color: var(--clear-aqi-unavailable) !important; }
.clear-map-condition-summary { margin-bottom: 8px; color: var(--muted); font-size: 12px; line-height: 1.45; }
.clear-map-history-subhead { margin: -5px 0 10px; color: var(--muted); font-size: 12px; line-height: 1.4; }
.clear-map-history-status { margin: 0 0 9px; color: var(--muted); font-size: 12px; line-height: 1.45; }
.clear-map-history-timeline { display: grid; gap: 0; min-width: 0; max-width: 100%; overflow: hidden; }
.clear-map-history-row { display: grid; grid-template-columns: minmax(0, 1fr) repeat(3, 44px); column-gap: 6px; align-items: center; min-width: 0; min-height: 29px; }
.clear-map-history-timeline.has-community .clear-map-history-row { grid-template-columns: minmax(72px, 1fr) repeat(3, 30px) 10px repeat(3, 30px); column-gap: 4px; }
.clear-map-history-row[role="row"] + .clear-map-history-row[role="row"] { border-top: 1px solid var(--surface-3); }
.clear-map-history-header { min-height: 21px; color: var(--muted); font-size: 10px; font-weight: 800; letter-spacing: .08em; }
.clear-map-history-group-header { min-height: 22px; padding-top: 1px; border-bottom: 0 !important; }
.clear-map-history-group { text-align: center; white-space: nowrap; }
.clear-map-history-group-regulatory { grid-column: 2 / span 3; }
.clear-map-history-group-community { grid-column: 6 / span 3; }
.clear-map-history-column-header span:not(:first-child) { text-align: right; }
.clear-map-history-community-divider { align-self: stretch; justify-self: center; width: 1px; min-width: 1px; background: var(--line); margin: 4px 0; }
.clear-map-history-group-header .clear-map-history-community-divider { margin: 2px 0; }
.clear-map-history-month { position: relative; display: flex; align-items: center; min-width: 0; color: var(--ink); font-size: 12px; font-weight: 700; }
.clear-map-history-timeline.is-graph { display: block; }
.clear-map-history-month::before { content: ""; width: 7px; height: 7px; margin-right: 9px; border: 2px solid var(--unavail); border-radius: 50%; background: var(--unavail); flex: 0 0 auto; }
/* FCLEAR-APP-0014 (F-2): the .is-pm25-* AQI-category painting rules that used to key off this
   dot were removed -- Regulatory high's averaging basis is not established, so no health-category
   color is drawn here. The --clear-history-pm25-* tokens above are left untouched and retained. */
.clear-map-history-row:not(:last-child) .clear-map-history-month::after { content: ""; position: absolute; left: 5px; top: 23px; bottom: -20px; width: 1px; background: var(--line); }
/* Governed value, restored: this row's background is the literal #f5f9fd, not --surface-2
   (#f5f8fa). The redesign re-tokenised it and shifted the colour. Same defect class the
   suite already caught once on the condition-category colours. */
.clear-map-history-year-row { width: 100%; padding: 0; border: 0; background: #f5f9fd; color: inherit; font: inherit; cursor: pointer; }
.clear-map-history-year-row:hover { background: var(--surface-3); }
.clear-map-history-year-row:focus-visible { position: relative; z-index: 1; outline: 2px solid var(--focus); outline-offset: -2px; }
.clear-map-history-year { position: relative; display: flex; align-items: center; gap: 7px; min-width: 0; color: var(--ink); font-size: 12px; font-weight: 800; text-align: left; }
.clear-map-history-year::after { content: ""; position: absolute; left: 5px; top: 24px; bottom: -20px; width: 1px; background: var(--line); }
.clear-map-history-year-marker { width: 12px; flex: 0 0 12px; color: var(--muted); font-size: 13px; font-weight: 800; text-align: center; }
.clear-map-history-value { min-width: 0; overflow: hidden; color: var(--ink); font-size: 11px; font-weight: 800; text-align: right; white-space: nowrap; }
.clear-map-history-value.is-missing { color: var(--faint); font-weight: 700; }
.clear-map-history-sources { display: grid; gap: 8px; margin-top: 11px; }
.clear-map-history-source { border-top: 1px solid var(--surface-3); padding-top: 9px; }
.clear-map-history-source h4 { margin: 0 0 5px; color: var(--muted); font-size: 11px; letter-spacing: .08em; font-weight: 800; }
.clear-map-history-source strong { display: block; color: var(--clear-text); font-size: 12px; line-height: 1.35; font-weight: 700; overflow-wrap: anywhere; }
.clear-map-history-source p { margin-top: 3px; color: var(--muted); font-size: 12px; line-height: 1.4; }
.clear-map-history-error { color: #8f4141 !important; }
.clear-map-radius-card { display: grid; gap: 12px; }
.clear-map-radius-toolbar { display: flex; flex-wrap: wrap; gap: 8px; }
.clear-map-radius-toolbar .clear-map-link-action { margin-top: 0; }
.clear-map-radius-toolbar .clear-map-link-action.is-active { background: var(--clear-blue); border-color: var(--clear-blue); color: #fff; }
.clear-map-radius-controls { display: grid; gap: 10px; }
.clear-map-radius-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.clear-map-radius-row label { color: var(--muted); font-size: 12px; font-weight: 700; }
.clear-map-radius-row output { color: var(--clear-text); font-size: 12px; font-weight: 700; }
.clear-map-radius-slider { width: 100%; }
.clear-map-radius-select { width: 100%; height: 36px; border-radius: var(--r-md); border: 1px solid var(--clear-border); background: var(--clear-panel-soft); color: var(--clear-text); padding: 0 10px; }
.clear-map-radius-disclaimer { margin: 0; color: var(--clear-text-muted); font-size: 10.5px; line-height: 1.45; }
.clear-map-radius-status { color: var(--ink); font-size: 12px; line-height: 1.45; }
.clear-map-nearest-card { border: 1px solid var(--clear-border); border-radius: var(--r-lg); padding: 13px; background: #fff; }
.clear-map-nearest-main { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.clear-map-nearest-name { min-width: 0; color: var(--clear-text); font-size: 13px; font-weight: 700; overflow-wrap: anywhere; }
.clear-map-nearest-badge { border-radius: 999px; padding: 3px 8px; background: var(--clear-green-soft); color: #137448; font-size: 11px; font-weight: 700; white-space: nowrap; }
.clear-map-nearest-meta { margin-top: 8px; color: var(--muted); font-size: 12px; line-height: 1.4; }
.clear-map-nearest-status { margin-top: 8px; display: flex; align-items: center; gap: 7px; color: var(--muted); font-size: 12px; }
.clear-map-comparison-panel { display: grid; gap: 10px; }
.clear-map-comparison-row { display: grid; gap: 3px; padding-bottom: 10px; border-bottom: 1px solid var(--surface-3); }
.clear-map-comparison-row:last-child { border-bottom: 0; padding-bottom: 0; }
.clear-map-comparison-row strong { color: var(--clear-text); font-size: 12px; line-height: 1.25; font-weight: 800; }
.clear-map-comparison-row span { color: var(--muted); font-size: 12px; line-height: 1.35; font-weight: 700; }
.clear-map-monitor-row { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 8px; align-items: start; padding: 7px 0; border-top: 1px solid var(--clear-border); }
.clear-map-monitor-row:first-child { border-top: 0; padding-top: 0; }
.clear-map-monitor-index { color: var(--clear-text-muted); font-size: 12px; font-weight: 800; padding-top: 2px; }
.clear-map-monitor-copy { min-width: 0; }
.clear-map-nearest-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--good); flex: 0 0 auto; }
.clear-map-nearest-dot.is-aging { background: var(--moderate); }
.clear-map-nearest-dot.is-stale, .clear-map-nearest-dot.is-unavailable { background: #b64747; }
button.clear-map-condition { width: 100%; appearance: none; cursor: pointer; font: inherit; }
.clear-map-condition.is-active { border: 2px solid var(--clear-blue); background: color-mix(in srgb, var(--clear-blue) 6%, #fff); box-shadow: inset 0 0 0 1px #fff; }
.clear-map-condition:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.clear-map-condition-state { display: inline-block; margin-top: 7px; padding: 2px 5px; border-radius: 3px; background: var(--clear-blue); color: #fff !important; font-size: 10px !important; font-weight: 800; letter-spacing: .02em; }
.clear-map-actions { display: grid; grid-template-columns: 1fr 1fr 1fr 34px; gap: 8px; padding: 14px 18px 18px; background: #fff; border-top: 1px solid var(--clear-border); }
.clear-map-action { min-height: 38px; border-radius: var(--r-md); border: 1px solid var(--clear-border); background: #fff; color: var(--clear-text); font-size: 12px; font-weight: 800; }
.clear-map-action.primary { background: var(--clear-blue); color: #fff; border-color: var(--clear-blue); }
.clear-map-foundation-marker { width: 22px; height: 22px; display: flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 0; background: transparent; box-shadow: none; cursor: pointer; }
.clear-map-foundation-marker img { display: block; width: 22px; height: 22px; object-fit: contain; }
.clear-map-foundation-marker:focus-visible { outline: none; box-shadow: var(--clear-focus), var(--sh-1); }

/* -----------------------------------------------------------------------
   13. MapLibre chrome overrides + popups
   ----------------------------------------------------------------------- */
.maplibregl-popup-content { border-radius: var(--r-lg); padding: 14px 16px; font-family: var(--f); box-shadow: var(--sh-1); }
.clear-map-popup h3 { margin: 0 0 8px; font-size: 15px; color: var(--clear-text); }
.clear-map-popup p { margin: 0 0 6px; font-size: 12px; color: var(--clear-text-muted); }
.clear-map-popup p:last-child { margin-bottom: 0; }
.clear-map-popup .muted { color: var(--muted); }
.maplibregl-ctrl-bottom-left { display: flex; flex-direction: column; align-items: flex-start; gap: 5px; }
.maplibregl-ctrl-bottom-left .maplibregl-ctrl { margin-left: 14px; margin-bottom: 0; }
.maplibregl-ctrl-bottom-left .maplibregl-ctrl:first-child { margin-bottom: 12px; }
.maplibregl-ctrl-top-right { top: 96px; right: 14px; }
.maplibregl-ctrl-top-right .maplibregl-ctrl { border-radius: var(--r-md); box-shadow: var(--sh-1); overflow: hidden; }
.maplibregl-ctrl-scale { height: 20px; line-height: 18px; padding: 0 7px; border: 1px solid #111; border-top: 0; border-radius: 0; background: rgba(255, 255, 255, .92); color: #111; font-size: 10px; font-weight: 700; box-shadow: none; }
.maplibregl-ctrl-attrib { border: 1px solid rgba(15, 35, 55, .18); border-radius: 5px; background: rgba(255, 255, 255, .88); color: var(--ink); font-size: 10px; box-shadow: none; }
.maplibregl-ctrl-attrib a { color: var(--brand-ink); }

/* -----------------------------------------------------------------------
   14. Removed: the legacy fixed-breakpoint block.
   The pre-redesign stylesheet hid the analytical pane entirely below 1180px
   (.clear-map-detail-panel{display:none}) and the rail below 880px. Those
   selectors no longer exist in the markup, and carrying the rules forward
   would have re-created the exact defect FCLEAR-APP-0002A exists to fix.
   The responsive contract now lives in section 5 on .clear-workspace /
   .clear-rail / .clear-pane, where the pane MOVES between docked, overlay
   and bottom-sheet modes and is never display:none.
   ----------------------------------------------------------------------- */

/* =============================================================================
   15. Inline SVG sizing (defect 1)
   Every inline <svg> in the template carries a viewBox but no width/height,
   so with no rule to constrain it an icon renders at its layout-parent's
   full intrinsic size — the map search icon filling the canvas, the empty
   -state pin filling the pane. Each icon wrapper below gets an explicit box
   and its child svg is told to fill that box exactly; the catch-all at the
   end is the defensive backstop for any icon wrapper not listed here.
   ========================================================================== */
.clear-tier1-icon { width: 16px; height: 16px; display: inline-flex; align-items: center; justify-content: center; margin-right: 8px; flex: 0 0 auto; }
.clear-tier1-icon svg { width: 16px; height: 16px; display: block; }

.clear-action-icon { width: 16px; height: 16px; display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; }
.clear-action-icon svg { width: 16px; height: 16px; display: block; }

.clear-search-icon { width: 16px; height: 16px; display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; color: var(--faint); }
.clear-search-icon svg { width: 16px; height: 16px; display: block; }

.clear-rail-toggle svg { width: 20px; height: 20px; display: block; }
.clear-pane-close svg { width: 16px; height: 16px; display: block; }
.clear-pane-caveat svg { width: 14px; height: 14px; display: block; flex: 0 0 auto; }
.clear-layer-icon svg { width: 13px; height: 13px; display: block; }
.clear-pane-empty-icon svg { width: 44px; height: 44px; display: block; }
.clear-nearest-jump svg { width: 16px; height: 16px; display: block; }

/* Defensive base rule: any icon inside the app that isn't covered above
   still gets clamped to its box instead of expanding past it. */
/* Icons must not stretch to fill their container. The history chart is the deliberate exception:
   it is sized in real pixels and lives in its own horizontal scroller, and because it carries a
   viewBox, clamping its width does not clip it -- it SCALES THE WHOLE CHART DOWN. That is what
   compressed 13 years into the pane width and shrank the plot vertically at the same time. The
   clamp is scoped rather than removed, because every other inline svg in the app still needs it. */
.clear-app svg:not(.clear-hg-svg) { flex: none; max-width: 100%; }
.clear-hg-svg { flex: none; max-width: none; }

/* =============================================================================
   16. Tier 1 / Tier 2 — remaining missing classes
   ========================================================================== */
.clear-tier1-attribution { display: inline-flex; align-items: baseline; gap: 4px; white-space: nowrap; }
.clear-tier1-attribution-mark { color: rgba(255, 255, 255, .6); font-weight: 500; }

/* Rail affordance, not a product-nav hamburger — hidden above the rail's own
   overlay breakpoint (1120px) so there is never a hamburger above phone
   widths for the tier-1 nav. */
.clear-rail-toggle {
  display: none;
  width: 38px;
  height: 38px;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface);
  color: var(--ink);
  flex: 0 0 auto;
}
@media (max-width: 1120px) {
  .clear-rail-toggle { display: inline-flex; }
}

.clear-user-avatar {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: var(--brand-ink);
  color: #fff;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  font-weight: 800;
  flex: 0 0 auto;
}
.clear-user-meta { display: flex; flex-direction: column; min-width: 0; line-height: 1.28; text-align: left; }
.clear-user-meta strong { font-size: 12.5px; font-weight: 700; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.clear-user-meta span { font-size: 11px; font-weight: 600; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* =============================================================================
   17. Left rail — remaining missing classes
   ========================================================================== */
.clear-rail-section + .clear-rail-section { margin-top: 22px; padding-top: 18px; border-top: 1px solid var(--line); }
.clear-rail-purpose { padding-bottom: 4px; }
.clear-rail-about { padding-bottom: 18px; }
.clear-rail-kicker { font-size: 11px; font-weight: 800; letter-spacing: .14em; text-transform: uppercase; color: var(--muted); }
.clear-rail-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 12px; }
.clear-rail-head .clear-rail-kicker { margin-bottom: 0; }
.clear-rail-reset { border: 0; background: transparent; color: var(--brand-ink); font-size: 12px; font-weight: 700; padding: 4px 0; }
.clear-rail-note { margin: 8px 0 0; color: var(--muted); font-size: 12px; line-height: 1.5; }
.clear-rail-attribution { margin-top: 6px; }
.clear-rail-attribution span { color: var(--faint); }
.clear-rail-subhead { margin: 15px 0 7px; color: var(--muted); font-size: 11px; font-weight: 800; letter-spacing: .14em; text-transform: uppercase; }
.clear-rail-subhead:first-of-type { margin-top: 2px; }

.clear-layer-list { display: grid; gap: 2px; }
.clear-layer-item { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-height: 34px; padding: 5px 2px; border-radius: var(--r-sm); }
.clear-layer-item.is-active { background: var(--surface-3); }
.clear-layer-item.is-regulatory-active { background: color-mix(in srgb, var(--sig-reg) 10%, var(--surface)); }
.clear-layer-item.is-community-active { background: color-mix(in srgb, var(--sig-com) 10%, var(--surface)); }
.clear-layer-item label { display: flex; align-items: center; gap: 9px; min-width: 0; flex: 1 1 auto; }
.clear-layer-item input[type="checkbox"] { width: 14px; height: 14px; accent-color: var(--brand-ink); flex: 0 0 auto; }
.clear-layer-icon {
  width: 16px;
  height: 16px;
  border-radius: 4px;
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-size: 9px;
  font-weight: 800;
}
.clear-layer-name { min-width: 0; font-size: 13px; font-weight: 700; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* These two names are long and were deliberately un-truncated by an earlier package;
   the generic ellipsis rule above would have silently reintroduced the truncation. */
.clear-layer-item[data-clear-layer-row="regulatory-air-monitors"] .clear-layer-name,
.clear-layer-item[data-clear-layer-row="community-air-sensors"] .clear-layer-name {
  overflow: visible;
  text-overflow: clip;
  white-space: normal;
}
.clear-layer-state { flex: 0 0 auto; min-width: 44px; text-align: right; font-family: var(--m); font-variant-numeric: tabular-nums; font-size: 11.5px; font-weight: 700; color: var(--muted); }
.clear-layer-item.is-active .clear-layer-state,
.clear-layer-item.is-regulatory-active .clear-layer-state,
.clear-layer-item.is-community-active .clear-layer-state { color: var(--ink); font-weight: 800; }

.clear-filter-list { display: grid; gap: 12px; }
.clear-filter label { display: block; margin-bottom: 6px; font-size: 12px; font-weight: 700; color: var(--muted); }
.clear-filter select { width: 100%; height: 38px; border-radius: var(--r-md); border: 1px solid var(--line); background: var(--surface-2); color: var(--ink); padding: 0 10px; font-size: 12.5px; }
.clear-filter select:disabled { color: var(--faint); }
.clear-filter .clear-rail-note { margin-top: 6px; }

.clear-source-status { margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--line); display: flex; align-items: center; gap: 8px; color: var(--muted); font-size: 11.5px; line-height: 1.35; }
.clear-source-status-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--good); flex: 0 0 auto; }

/* =============================================================================
   18. Canvas floating chrome — remaining missing classes
   ========================================================================== */
.clear-canvas-search-row { position: absolute; z-index: 5; top: 16px; left: 18px; }
.clear-canvas-search {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 240px;
  max-width: calc(100% - 36px);
  height: 40px;
  padding: 0 12px;
  border-radius: var(--r-md);
  background: var(--surface);
  border: 1px solid var(--line);
  box-shadow: var(--sh-1);
}
.clear-canvas-search input { flex: 1 1 auto; min-width: 0; border: 0; outline: 0; background: transparent; color: var(--ink); font-size: 13px; font-family: var(--f); }
.clear-canvas-search input::placeholder { color: var(--faint); }

.clear-aq-card {
  position: absolute;
  z-index: 5;
  top: 70px;
  left: 18px;
  width: 220px;
  border-radius: var(--r-md);
  padding: 13px 15px 14px;
  background: rgba(13, 39, 65, .94);
  color: #fff;
  box-shadow: var(--sh-3);
  backdrop-filter: blur(8px);
}
.clear-aq-kicker { font-size: 10px; font-weight: 800; letter-spacing: .13em; text-transform: uppercase; color: rgba(255, 255, 255, .70); font-family: var(--f); }
.clear-aq-title { margin-top: 5px; font-size: 15px; font-weight: 800; line-height: 1.2; }
.clear-aq-body { margin-top: 7px; color: rgba(255, 255, 255, .76); font-size: 12px; line-height: 1.4; }
.clear-aq-value { margin-top: 10px; font-size: 26px; line-height: 1; font-weight: 800; color: #fff; font-family: var(--m); font-variant-numeric: tabular-nums; }
.clear-aq-value[hidden] { display: none; }
.clear-aq-progress { margin-top: 11px; height: 6px; border-radius: 999px; background: rgba(255, 255, 255, .17); overflow: hidden; }
.clear-aq-progress span { display: block; width: 0; height: 100%; background: var(--brand-accent); border-radius: inherit; }
.clear-aq-foot { margin-top: 10px; color: rgba(255, 255, 255, .84); font-size: 11px; line-height: 1.45; }

.clear-legend-card {
  position: absolute;
  z-index: 5;
  left: 14px;
  bottom: 18px;
  width: 200px;
  border-radius: var(--r-md);
  padding: 12px 14px 13px;
  background: var(--surface);
  border: 1px solid var(--line);
  box-shadow: var(--sh-2);
}
.clear-legend-kicker { font-size: 10px; font-weight: 800; letter-spacing: .13em; text-transform: uppercase; color: var(--muted); margin-bottom: 8px; }
.clear-legend-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 7px; }
.clear-legend-list li { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--ink); font-weight: 600; }
.clear-legend-dot { width: 9px; height: 9px; border-radius: 50%; flex: 0 0 auto; }
.clear-legend-dot.is-facility { background: var(--clear-purple); }
.clear-legend-dot.is-place { background: var(--clear-blue); }
.clear-legend-dot.is-regulatory { background: var(--sig-reg); }
.clear-legend-dot.is-community { background: var(--sig-com); }

/* =============================================================================
   19. Analytical pane — remaining missing classes
   ========================================================================== */
.clear-pane-identity-row { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 12px; align-items: start; }
.clear-pane-identity-icon { width: 34px; height: 34px; border-radius: 50%; background: var(--brand-ink); color: #fff; display: inline-flex; align-items: center; justify-content: center; font-size: 15px; font-weight: 800; flex: 0 0 auto; }
.clear-pane-identity-text { min-width: 0; }
.clear-pane-title-line { display: flex; align-items: center; gap: 8px; min-width: 0; }
.clear-pane-title { margin: 0; color: var(--ink); font-size: 16px; line-height: 1.25; font-weight: 700; min-width: 0; letter-spacing: -.01em; }
.clear-pane-badge { flex: 0 0 auto; border-radius: 999px; padding: 3px 8px; background: var(--clear-green-soft); color: #137448; font-size: 10.5px; font-weight: 800; }
.clear-pane-badge[hidden] { display: none; }
.clear-pane-address { margin-top: 4px; color: var(--muted); font-size: 12.5px; line-height: 1.4; }
.clear-pane-submeta { margin-top: 6px; display: flex; flex-wrap: wrap; gap: 4px 8px; color: var(--muted); font-size: 11.5px; }
.clear-pane-submeta span:empty { display: none; }
.clear-pane-submeta span + span:not(:empty)::before { content: "•"; margin-right: 8px; color: var(--faint); }
.clear-pane-close { width: 28px; height: 28px; border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--surface); color: var(--muted); display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; }
.clear-pane-close:hover { background: var(--surface-2); }
.clear-pane-caveat { display: inline-flex; align-items: center; gap: 6px; margin-top: 10px; color: var(--muted); font-size: 11.5px; }
.clear-pane-caveat[hidden] { display: none; }

.clear-pane-empty { display: flex; align-items: center; justify-content: center; min-height: 100%; padding: 40px 24px; text-align: center; }
.clear-pane-empty[hidden] { display: none; }
.clear-pane-empty-icon { width: 44px; height: 44px; margin: 0 auto 16px; color: var(--brand-ink); opacity: .55; }
.clear-pane-empty h3 { margin: 0 0 8px; color: var(--ink); font-size: 17px; line-height: 1.25; }
.clear-pane-empty p { margin: 0; color: var(--muted); font-size: 13px; line-height: 1.55; max-width: 280px; }

.clear-pane-note { margin: 10px 0 0; color: var(--muted); font-size: 11.5px; line-height: 1.5; }

.clear-answer-text { margin: 0; }

.clear-metric-row { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; margin-bottom: 10px; }
.clear-metric-card { border: 1px solid var(--line); background: var(--surface); border-radius: var(--r-lg); box-shadow: var(--sh-1); padding: 11px 12px; min-width: 0; min-height: 88px; }
.clear-metric-label { color: var(--ink); font-size: 11.5px; line-height: 1.25; font-weight: 700; }
.clear-metric-value { margin-top: 8px; display: flex; flex-direction: column; gap: 3px; }
.clear-metric-primary { display: block; font-size: 16px; line-height: 1.1; font-weight: 800; color: var(--ink); letter-spacing: -.01em; }
.clear-metric-secondary { display: block; font-size: 11px; line-height: 1.3; font-weight: 700; color: var(--muted); }

.clear-card-kicker { font-size: 11px; font-weight: 700; color: var(--muted); font-family: var(--m); font-variant-numeric: tabular-nums; white-space: nowrap; }
.clear-condition-summary { margin-bottom: 10px; color: var(--muted); font-size: 12px; line-height: 1.5; }

/* Pollutant tile inner typography. Bare tags, not classes, because the
   template leaves the value/meta spans unclassed (only data-attributes
   select them) — targeted by the same attribute list the mono-font rule
   already uses, so the PM10 "not currently served" tile (which uses real
   classes, not these data-attributes) is never touched by this block. */
.clear-tile > strong { display: block; font-size: 11px; font-weight: 700; color: var(--ink); }
[data-clear-condition-pm25], [data-clear-condition-o3], [data-clear-condition-no2],
[data-clear-condition-so2], [data-clear-condition-co] {
  display: block;
  margin-top: 6px;
  font-size: 14px;
  font-weight: 800;
  line-height: 1.05;
  letter-spacing: -.01em;
}
[data-clear-condition-pm25-meta], [data-clear-condition-o3-meta], [data-clear-condition-no2-meta],
[data-clear-condition-so2-meta], [data-clear-condition-co-meta] {
  display: block;
  margin-top: 4px;
  font-size: 9.5px;
  font-weight: 700;
}
.clear-tile-state {
  display: block;
  margin-top: 6px;
  color: var(--brand-ink);
  font-size: 9.5px;
  font-weight: 800;
  letter-spacing: .04em;
  text-transform: uppercase;
}
.clear-tile-state[hidden] { display: none; }
.clear-tiles-hint { margin: 8px 0 0; color: var(--faint); font-size: 10.5px; line-height: 1.4; }

/* PM10 "not currently served" tile — real classes, styled to read as absence
   of data, never as a good/low/zero reading (see section 9's is-unavailable
   rule for the tile-level treatment). */
.clear-tile-unavailable-text { display: block; margin-top: 6px; color: var(--muted); font-size: 11px; font-weight: 700; }
.clear-tile-unavailable-note { display: block; margin-top: 4px; color: var(--unavail); font-size: 10px; font-weight: 600; }

.clear-condition-source-note { margin-top: 10px; color: var(--muted); font-size: 11.5px; line-height: 1.45; }
.clear-condition-source-note[hidden] { display: none; }
.clear-condition-source-list { margin-top: 10px; display: grid; gap: 8px; }
.clear-condition-source-list[hidden] { display: none; }

.clear-history-subhead { margin: -4px 0 10px; color: var(--muted); font-size: 12px; line-height: 1.4; }
.clear-history-status { margin: 0 0 10px; color: var(--muted); font-size: 12px; line-height: 1.45; }
.clear-history-timeline { display: grid; gap: 0; min-width: 0; max-width: 100%; overflow: hidden; }
.clear-history-sources { display: grid; gap: 8px; margin-top: 12px; }

/* Always-visible "About this chart" affordance (FCLEAR-APP-0014 decision #4). The governed
   sentence is static template text; [data-clear-history-about-heading] (F-1) and
   [data-clear-history-about-detail] are the two nodes this component manages around it --
   inserted/updated in place, never duplicating on a pollutant switch. */
[data-clear-history-about] { margin: 10px 0; padding: 10px 12px; background: var(--surface-3); border-left: 3px solid var(--sig-reg); border-radius: 3px; font-size: 12px; line-height: 1.45; color: var(--ink); }
[data-clear-history-about] [data-clear-history-about-heading] { margin: 0 0 6px; font-size: 12px; font-weight: 800; color: var(--ink); }
[data-clear-history-about] [data-clear-history-about-detail] { margin: 6px 0 0; color: var(--muted); }
[data-clear-history-sources-link] { margin: 6px 0 10px; }
.clear-hg-sources-detail { font-size: 12px; color: var(--muted); font-family: var(--f); }
.clear-hg-sources-detail summary { cursor: pointer; color: var(--sig-reg); font-weight: 600; }
.clear-hg-sources-detail summary:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.clear-hg-sources-detail p { margin: 6px 0 0; line-height: 1.4; }

.clear-sources-compact { display: grid; gap: 8px; margin-bottom: 12px; }
.clear-nearest-card { border: 1px solid var(--line); border-radius: var(--r-lg); padding: 13px; background: var(--surface); }
.clear-nearest-main { display: flex; align-items: center; gap: 8px; }
.clear-nearest-name { flex: 1 1 auto; min-width: 0; color: var(--ink); font-size: 13px; font-weight: 700; overflow-wrap: anywhere; }
.clear-nearest-badge { flex: 0 0 auto; border-radius: 999px; padding: 3px 8px; background: var(--surface-3); color: var(--muted); font-size: 10.5px; font-weight: 700; white-space: nowrap; }
.clear-nearest-jump { flex: 0 0 auto; width: 16px; height: 16px; border: 0; background: transparent; color: var(--brand-ink); display: inline-flex; align-items: center; justify-content: center; font-size: 15px; line-height: 1; padding: 0; }
.clear-nearest-jump:disabled { color: var(--faint); cursor: not-allowed; }
.clear-nearest-meta { margin-top: 8px; color: var(--muted); font-size: 11.5px; line-height: 1.4; }
.clear-nearest-status { margin-top: 8px; display: flex; align-items: center; gap: 7px; color: var(--muted); font-size: 11.5px; }
.clear-nearest-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--good); flex: 0 0 auto; }
.clear-nearest-dot.is-unavailable { background: var(--unavail); }
.clear-nearest-dot.is-aging { background: var(--moderate); }
.clear-nearest-dot.is-stale { background: #b64747; }

.clear-link-action { display: inline-flex; align-items: center; gap: 6px; margin-top: 10px; border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--surface); color: var(--brand-ink); height: 30px; padding: 0 10px; font-size: 12px; font-weight: 700; font-family: var(--f); }
.clear-link-action:disabled { color: var(--faint); border-color: var(--line); cursor: not-allowed; }

.clear-radius-status { color: var(--ink); font-size: 12px; line-height: 1.5; }
.clear-radius-controls { display: grid; gap: 10px; margin-top: 10px; }
.clear-radius-sublabel { display: block; margin-top: 4px; color: var(--muted); font-size: 12px; font-weight: 700; }
.clear-radius-slider { width: 100%; accent-color: var(--brand-ink); }
.clear-radius-select { width: 100%; height: 34px; border-radius: var(--r-md); border: 1px solid var(--line); background: var(--surface-2); color: var(--ink); padding: 0 10px; font-size: 12.5px; }

.clear-meta-list { display: grid; gap: 6px; margin: 0; }
.clear-meta-list div { display: grid; grid-template-columns: 120px minmax(0, 1fr); gap: 10px; padding: 8px 0; border-top: 1px solid var(--surface-3); }
.clear-meta-list div:first-child { border-top: 0; }
.clear-meta-list dt { color: var(--muted); font-size: 12px; font-weight: 700; }
.clear-meta-list dd { margin: 0; color: var(--ink); font-size: 12px; font-weight: 700; min-width: 0; overflow-wrap: anywhere; font-family: var(--m); }

.clear-pane-action { min-height: 38px; border-radius: var(--r-md); border: 1px solid var(--line); background: var(--surface); color: var(--ink); font-size: 12px; font-weight: 800; font-family: var(--f); }
.clear-pane-action.is-primary { background: var(--brand-ink); color: #fff; border-color: var(--brand-ink); }
.clear-pane-action:disabled { color: var(--faint); cursor: not-allowed; }
.clear-pane-action.is-primary:disabled { background: color-mix(in srgb, var(--brand-ink) 55%, var(--surface-3)); border-color: transparent; color: rgba(255, 255, 255, .75); }


/* -----------------------------------------------------------------------
   20. FCLEAR-APP-0002A integration pass — phone refinements.
   Captured from a rendered 390x844 screenshot: the tier-1 product nav
   overflowed the header, the lockup descriptor competed with the mark for
   width, and the five-tab strip clipped "Evidence".
   ----------------------------------------------------------------------- */
@media (max-width: 767px) {
  /* The product nav is reached through the rail toggle on phone. Leaving it in
     the header pushed sections off-screen with no way to scroll to them. */
  .clear-tier1-nav { display: none; }
  .clear-tier1 { gap: 10px; }
  .clear-tier1-wordmark { font-size: 15px; }

  /* DESIGN-SPEC 2: on phone the lockup reduces to the mark plus CLEAR. */
  .clear-lockup-descriptor { display: none; }

  /* Five tabs do not fit 390px. Scroll them rather than clipping or wrapping;
     the active tab is scrolled into view by the shell controller. */
  .clear-pane-tabs {
    overflow-x: auto;
    overflow-y: hidden;
    flex-wrap: nowrap;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }
  .clear-pane-tabs::-webkit-scrollbar { display: none; }
  .clear-pane-tab { flex: 0 0 auto; }

  /* Pollutant tiles scroll horizontally on phone (DESIGN-SPEC 7). */
  .clear-tiles {
    grid-auto-flow: column;
    grid-auto-columns: minmax(84px, 1fr);
    grid-template-columns: none;
    overflow-x: auto;
    scrollbar-width: none;
  }
  .clear-tiles::-webkit-scrollbar { display: none; }
}

/* -----------------------------------------------------------------------
   21. FCLEAR-APP-0002A — analytical pane renderer output.
   These classes are emitted from JavaScript (Reporting Sources, the source
   segment register, Evidence rows). They were missing rules, which made the
   Reporting Sources row overlap its own text on a 468px pane.
   ----------------------------------------------------------------------- */
.clear-source-row { grid-template-columns: minmax(0, 1fr); gap: 6px; }
.clear-source-row-main { display: flex; align-items: center; gap: 8px; min-width: 0; }
.clear-source-row-name {
  min-width: 0; flex: 1 1 auto;
  font-size: 12.5px; font-weight: 700; color: var(--ink); line-height: 1.35;
  overflow-wrap: anywhere;
}
.clear-source-row-meta {
  min-width: 0;
  font-family: var(--m); font-variant-numeric: tabular-nums;
  font-size: 11px; color: var(--muted); line-height: 1.5; overflow-wrap: anywhere;
}
.clear-source-row.is-absent { background: transparent; border-style: dashed; }
.clear-source-row.is-absent .clear-source-row-name { font-weight: 600; color: var(--muted); }
.clear-source-list { display: grid; gap: 8px; }

.clear-chip {
  flex: 0 0 auto; border-radius: 999px; padding: 2px 8px;
  font-size: 10.5px; font-weight: 800; letter-spacing: .04em; text-transform: uppercase;
  white-space: nowrap; border: 1px solid transparent;
}
.clear-chip.is-regulatory { background: color-mix(in srgb, var(--sig-reg) 12%, #fff); color: var(--sig-reg); border-color: color-mix(in srgb, var(--sig-reg) 26%, #fff); }
.clear-chip.is-community  { background: color-mix(in srgb, var(--sig-com) 12%, #fff); color: var(--sig-com); border-color: color-mix(in srgb, var(--sig-com) 30%, #fff); }

/* Source segment register: one row per governed segment. */
.clear-register { display: grid; gap: 8px; }
.clear-register-row {
  min-width: 0; padding: 9px 11px;
  border: 1px solid var(--line); border-left: 3px solid var(--sig-reg);
  border-radius: var(--r-sm); background: var(--surface-2);
}
.clear-register-row.is-gap { border-left-color: var(--line-strong); background: var(--surface-3); }
.clear-register-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  min-width: 0; margin-bottom: 3px;
}
.clear-register-head strong { min-width: 0; font-size: 12px; color: var(--ink); overflow-wrap: anywhere; }
.clear-register-dist {
  flex: 0 0 auto;
  font-family: var(--m); font-variant-numeric: tabular-nums; font-size: 11px; color: var(--muted);
}
.clear-register-meta {
  font-family: var(--m); font-variant-numeric: tabular-nums;
  font-size: 10.5px; color: var(--muted); line-height: 1.5; overflow-wrap: anywhere;
}
.clear-register-reason { margin-top: 3px; font-size: 11px; font-weight: 700; color: var(--sig-reg); }
.clear-register-row.is-gap .clear-register-reason { color: var(--muted); font-weight: 600; }
.clear-register-flag { margin-top: 3px; font-size: 10.5px; font-weight: 700; color: var(--moderate); }
.clear-inferred { font-weight: 700; color: var(--faint); }

/* Evidence rows. */
.clear-evidence-row { min-width: 0; padding: 9px 0; border-bottom: 1px solid var(--line); }
.clear-evidence-row:last-child { border-bottom: 0; }
.clear-evidence-head { display: flex; align-items: center; gap: 8px; min-width: 0; margin-bottom: 4px; }
.clear-evidence-head strong { min-width: 0; font-size: 12.5px; color: var(--ink); overflow-wrap: anywhere; }
.clear-evidence-meta {
  font-size: 11.5px; color: var(--muted); line-height: 1.55; overflow-wrap: anywhere;
}
.clear-evidence-meta + .clear-evidence-meta { margin-top: 4px; }

/* Answer strip caveat and the FRS registry caveat block. */
.clear-answer-caveat { margin: 6px 0 0; font-size: 11.5px; color: var(--muted); line-height: 1.5; }
.clear-pane-caveat-block {
  margin: 0 0 10px; padding: 8px 10px;
  border: 1px dashed var(--line-strong); border-radius: var(--r-sm);
  background: var(--surface-3); color: var(--muted);
  font-size: 11.5px; line-height: 1.5;
}
.clear-pane-caveat-block[hidden] { display: none; }

/* An unclassified reporting source must be visually distinct from a governed class, never
   borrowing Regulatory or Community styling. Independent QA finding: coercing unknown -> regulatory
   presented a classification the data does not support. */
.clear-chip.is-unknown {
  background: var(--surface-3);
  color: var(--muted);
  border-color: var(--line-strong);
  border-style: dashed;
}
.clear-source-row-name:first-letter { text-transform: none; }

/* =======================================================================
   22. FCLEAR-APP-0002A — VISUAL FIDELITY PASS
   Gate B was rejected: the components were present but had been translated
   into the OLD application's density rather than into the approved design
   language. Every value below is measured against the approved stills in
   mockup-new/clear-design-package/mockups/ (authored at 1600x863, 1280x863
   and 390x783 CSS, exported at DPR 2).
   ======================================================================= */

/* --- 22.1 Analytical workspace width -----------------------------------
   The mockup's pane is ~469px at a 1600px viewport, which is what we had.
   But the operator's principle is "map primary WHILE analysis genuinely
   usable", not "maximise map pixels". On a large monitor the map can afford
   to give up width so the analysis stops reading as a sidebar. */
/* The pane is a flex item sized by flex-basis; the grid rule further up is dead legacy markup, so
   overriding --clear-right-width did nothing. Size the real track, and keep min-width:0 intact. */
@media (min-width: 1600px) { .clear-pane[data-clear-map-detail-panel] { flex-basis: 560px; } }
@media (min-width: 1920px) { .clear-pane[data-clear-map-detail-panel] { flex-basis: 640px; } }
@media (min-width: 2400px) { .clear-pane[data-clear-map-detail-panel] { flex-basis: 720px; } }

/* --- 22.2 Type scale ---------------------------------------------------
   Measured deltas against the stills. Density was being bought with tiny
   type; the mockup buys it with whitespace instead. */
.clear-pane-title { font-size: 19px; line-height: 1.2; letter-spacing: -.015em; }
.clear-pane-address { font-size: 13.5px; line-height: 1.45; }
.clear-pane-submeta { font-size: 13px; line-height: 1.45; }
.clear-pane-tab { font-size: 15px; }
.clear-card-head h3 { font-size: 15px; letter-spacing: .01em; }
.clear-card-kicker { font-size: 11.5px; }
.clear-answer-text { font-size: 15.5px; line-height: 1.6; }
.clear-answer-caveat { font-size: 12.5px; line-height: 1.55; }
.clear-pane-note { font-size: 12.5px; line-height: 1.55; }
.clear-condition-summary { font-size: 13.5px; line-height: 1.5; }
.clear-source-row-name { font-size: 13.5px; }
.clear-source-row-meta { font-size: 12px; }
.clear-evidence-meta { font-size: 12.5px; }
.clear-register-meta { font-size: 11.5px; }
.clear-metric-primary { font-size: 20px; }
.clear-metric-label { font-size: 11.5px; }

/* --- 22.3 Pollutant tiles are a core interaction ------------------------
   Measured 14px for the tile value against ~26px in the still. The primary
   analytical number was rendering at little over half size. Six tiles are
   allowed to wrap rather than be crushed into one unreadable row. */
.clear-tiles {
  grid-template-columns: repeat(auto-fit, minmax(74px, 1fr));
  gap: 7px;
}
@media (min-width: 1600px) { .clear-tiles { grid-template-columns: repeat(6, minmax(0, 1fr)); } }
.clear-tile {
  /* Measured 149px tall against the still's ~80px. The governed active-state chip ("FIND IT NOW")
     adds a line the design does not have, so it is pinned to the tile's foot instead of pushing
     every tile taller -- the grid stretches all tiles to the tallest one. */
  position: relative;
  padding: 10px 8px 9px;
  border-radius: var(--r-md);
  min-height: 86px;
  gap: 1px;
}
.clear-tile > strong { font-size: 13px; letter-spacing: .01em; }
/* The large size belongs to the READING, not to the placeholder word. Applying it to the whole
   value span made "Unavailable" render at 27px and overflow the tile. */
.clear-tile .clear-condition-reading { font-size: 27px; line-height: 1.05; letter-spacing: -.02em; }
.clear-tile .clear-condition-number { font-size: 27px; font-weight: 800; }
.clear-tile [data-clear-condition-pm25].clear-aqi-category-unavailable,
.clear-tile [data-clear-condition-o3].clear-aqi-category-unavailable,
.clear-tile [data-clear-condition-no2].clear-aqi-category-unavailable,
.clear-tile [data-clear-condition-so2].clear-aqi-category-unavailable,
.clear-tile [data-clear-condition-co].clear-aqi-category-unavailable {
  display: block;
  /* "Unavailable" is a single governed word that must neither break mid-syllable nor clip. At
     10.5px it measures ~54px and fits the ~69px tile content box. */
  font-size: 10.5px;
  line-height: 1.3;
  font-weight: 700;
  letter-spacing: -.01em;
  overflow-wrap: normal;
  word-break: keep-all;
  hyphens: none;
}
/* The meta line repeats "Unavailable" under the value. One statement is enough on a tile. */
.clear-tile [data-clear-condition-pm25-meta].clear-aqi-category-unavailable,
.clear-tile [data-clear-condition-o3-meta].clear-aqi-category-unavailable,
.clear-tile [data-clear-condition-no2-meta].clear-aqi-category-unavailable,
.clear-tile [data-clear-condition-so2-meta].clear-aqi-category-unavailable,
.clear-tile [data-clear-condition-co-meta].clear-aqi-category-unavailable { display: none; }
.clear-tile .clear-condition-unit { font-size: 11.5px; font-weight: 700; }
.clear-tile > small { font-size: 12px; margin-top: 4px; }
.clear-tile.is-active { box-shadow: inset 0 0 0 2px var(--brand-ink); border-color: var(--brand-ink); }
.clear-tile-state {
  position: absolute;
  left: 0; right: 0; bottom: 3px;
  font-size: 9.5px;
  letter-spacing: .04em;
  text-align: center;
  pointer-events: none;
}
.clear-tile.is-active { padding-bottom: 16px; }
/* The unavailable tile must not shout a large number it does not have. */
.clear-tile.is-unavailable .clear-tile-unavailable-text { font-size: 13px; line-height: 1.3; font-weight: 700; }
.clear-tile.is-unavailable .clear-tile-unavailable-note { font-size: 11.5px; }
.clear-tiles-hint { font-size: 12px; line-height: 1.5; }

/* --- 22.4 History is a primary reason to open the pane ------------------ */
.clear-history-subhead { font-size: 12.5px; }
.clear-history-status { font-size: 12.5px; line-height: 1.5; }
.clear-hg-range { font-size: 12.5px; padding: 5px 10px; }
.clear-hg-series-static, .clear-hg-series-toggle { font-size: 12px; }
.clear-hg-tip { font-size: 12.5px; line-height: 1.6; }
.clear-hg-hint { font-size: 11.5px; }
.clear-hg-vlabel, .clear-hg-ylabel { font-size: 11px; }

/* --- 22.5 Place identity is the anchor of the whole analysis ------------ */
.clear-pane-identity { padding: 18px 20px 14px; }
.clear-pane-identity-icon { width: 40px; height: 40px; border-radius: 11px; font-size: 15px; }
.clear-pane-caveat { font-size: 12px; padding: 6px 10px; }
.clear-pane-badge { font-size: 10.5px; letter-spacing: .06em; }

/* --- 22.6 Card rhythm: the mockup buys clarity with whitespace ---------- */
.clear-card { border-radius: var(--r-lg); }
.clear-card-head { padding: 14px 18px 10px; }
.clear-card-body { padding: 0 18px 16px; }
.clear-tabpanel { padding: 16px 18px 20px; }
.clear-card + .clear-card { margin-top: 14px; }
.clear-answer-strip { padding: 14px 16px; border-radius: var(--r-md); margin-bottom: 14px; }

/* --- 22.7 Left rail joins the same design system ------------------------ */
.clear-rail { padding: 18px 18px 8px; }
.clear-rail-kicker { font-size: 11.5px; letter-spacing: .1em; }
.clear-rail-subhead { font-size: 11px; letter-spacing: .1em; margin: 14px 0 8px; }
.clear-layer-name { font-size: 14px; font-weight: 600; }
.clear-layer-state { font-size: 12px; }
.clear-layer-item { padding: 8px 10px; border-radius: var(--r-sm); }
.clear-rail-note { font-size: 12.5px; line-height: 1.55; }
.clear-filter label { font-size: 12.5px; }
.clear-filter select { font-size: 13.5px; padding: 9px 10px; }
.clear-source-status { font-size: 12px; }
.clear-rail-reset { font-size: 12px; }

/* --- 22.8 Chrome hierarchy: tier 1 is a product bar, tier 2 is the
   working surface. They must not read as two equally dense toolbars.

   Scale matched to the approved Commercial mockup, measured off the mockup PNG rather than
   estimated: the mockup is 3200px wide at DPR 2, so its 84px navy band is 42 CSS px. The previous
   values ran roughly 24% tall in both bands. Geometry, navigation membership, profile behaviour
   and the mark itself are unchanged -- this is scale and spacing only, and the 44px lung tile is
   deliberately preserved because it already matched. ----- */
.clear-tier1 { height: 42px; gap: 14px; padding: 0 16px; }
.clear-tier1-link { font-size: 12.5px; height: 28px; padding: 0 10px; }
.clear-tier1-wordmark { font-size: 14.5px; }  /* +10%: balances the lung mark, stays above the nav labels */
.clear-tier2 { min-height: 55px; height: 55px; gap: 14px; padding: 0 16px; }
.clear-lockup-name { font-size: 18px; letter-spacing: -.01em; }
.clear-lockup-descriptor { font-size: 10.5px; }
.clear-search input { font-size: 14px; }
.clear-action { font-size: 13.5px; }
.clear-user-chip strong { font-size: 13.5px; }

/* The Current Air card carried two helper lines that pushed History below the fold. The design
   keeps one. The second (source provenance) belongs with the sources, not above the graph. */
.clear-tiles-hint { margin: 8px 0 0; }
[data-clear-card="current-air"] [data-clear-condition-note] { display: none; }
.clear-answer-strip { padding: 12px 14px; margin-bottom: 12px; }
.clear-answer-text { font-size: 15px; line-height: 1.5; }
.clear-answer-caveat { margin-top: 4px; }
[data-clear-card="current-air"] .clear-card-body { padding-bottom: 12px; }
[data-clear-card="current-air"] .clear-condition-summary { margin-bottom: 8px; }

/* =======================================================================
   23. FCLEAR-APP-0002A — independent visual review (WS8) findings.
   ======================================================================= */

/* WS8 #3 (HIGH): the mockup shows all six tiles on ONE row at 1600px AND at
   1280px. The auto-fit floor of 74px dropped to three per row inside the
   414px overlay drawer. Hold six columns down to the overlay band. */
@media (min-width: 1121px) { .clear-tiles { grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 5px; } }
@media (min-width: 1121px) and (max-width: 1599px) {
  .clear-tile { padding: 9px 5px 8px; }
  .clear-tile > strong { font-size: 11.5px; }
  .clear-tile .clear-condition-reading, .clear-tile .clear-condition-number { font-size: 21px; }
  .clear-tile [data-clear-condition-pm25].clear-aqi-category-unavailable,
  .clear-tile [data-clear-condition-o3].clear-aqi-category-unavailable,
  .clear-tile [data-clear-condition-no2].clear-aqi-category-unavailable,
  .clear-tile [data-clear-condition-so2].clear-aqi-category-unavailable,
  .clear-tile [data-clear-condition-co].clear-aqi-category-unavailable { font-size: 9px; }
  .clear-tile > small { font-size: 10.5px; }
}

/* WS8 #8 (HIGH): tier 1 must recede behind tier 2. Icons are gone from the
   markup; quieten the remaining link treatment so the rows are not twins. */
.clear-tier1-link { font-weight: 500; opacity: .82; padding: 5px 9px; }
.clear-tier1-link.is-active { opacity: 1; font-weight: 700; }
.clear-tier1-nav { gap: 2px; }

/* WS8 #7 (MEDIUM/HIGH): the rail carried 24px coloured letter badges -- the
   old application's role-badge pattern, absent from the approved design. A
   small colour dot keeps the map-legend value without the admin look. */
.clear-layer-icon {
  width: 9px; height: 9px; min-width: 9px;
  border-radius: 50%;
  font-size: 0; line-height: 0;
  padding: 0; border: 0;
  overflow: hidden;
}
.clear-layer-icon svg { display: none; }

/* WS8 #2 (MEDIUM): "Current Air" and "HISTORY" are adjacent card headers in
   the same pane and the mockup gives them ONE treatment. Make the kicker
   treatment structural rather than dependent on the literal string's case. */
.clear-card-head h3 {
  text-transform: uppercase;
  letter-spacing: .08em;
  font-size: 12.5px;
  color: var(--muted);
}
.clear-pane-title, .clear-peek-name { text-transform: none; letter-spacing: -.015em; }

/* WS8 #10 / section 31: the collapsed-sheet composition is now the compact selected-place
   dashboard, defined in section 31 and shared with desktop and tablet. */

/* On phone, Commercial keeps its one-bar map-first treatment. Foundation deliberately opts into
   the same existing Tier-1 component under its own profile: the canonical Foundation silhouette
   and unwrapped wordmark remain visible, while the four Foundation sections scroll horizontally
   inside the bar. This is not a new row and it never affects `.clear-tier1--workflows`. */
@media (max-width: 767px) { .clear-tier1 { display: none; } }

@media (max-width: 767px) {
  body[data-clear-profile="foundation"] .clear-tier1 {
    display: flex;
    height: 34px;
    gap: 8px;
    padding: 0 10px;
  }
  body[data-clear-profile="foundation"] .clear-tier1-brand { gap: 6px; min-height: 0; height: 100%; }
  body[data-clear-profile="foundation"] .clear-tier1-lung { width: 16px; height: 16px; }
  body[data-clear-profile="foundation"] .clear-tier1-wordmark { font-size: 14px; }
  body[data-clear-profile="foundation"] .clear-tier1-meta { display: none; }
  body[data-clear-profile="foundation"] .clear-tier1-nav {
    display: flex;
    align-self: stretch;
    overflow-x: auto;
    scrollbar-width: none;
  }
  body[data-clear-profile="foundation"] .clear-tier1-nav::-webkit-scrollbar { display: none; }
  body[data-clear-profile="foundation"] .clear-tier1-link {
    height: 26px;
    padding: 0 7px;
    font-size: 12px;
  }
}

/* Final tightening: at six-across the active tile clipped its own reading and state chip. */
@media (min-width: 1600px) {
  .clear-tile { padding: 10px 6px 9px; }
  .clear-tile .clear-condition-reading, .clear-tile .clear-condition-number { font-size: 24px; }
}
.clear-tile-state {
  font-size: 8.5px;
  padding: 0 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* =======================================================================
   24. FCLEAR-APP-0002A — user acceptance corrections.
   ======================================================================= */

/* --- 24.1 Pane / map balance -------------------------------------------
   The 560/640/720 escalation overcorrected: on a real desktop it took so much
   width that the map stopped being usable, violating "map remains primary".
   Clamp the pane instead, and switch to overlay EARLIER rather than letting
   rail + pane squeeze the map. */
.clear-pane[data-clear-map-detail-panel] { flex-basis: clamp(468px, 30vw, 500px); }
@media (min-width: 1600px) { .clear-pane[data-clear-map-detail-panel] { flex-basis: clamp(490px, 31vw, 540px); } }
@media (min-width: 1920px) { .clear-pane[data-clear-map-detail-panel] { flex-basis: clamp(520px, 30vw, 580px); } }
@media (min-width: 2400px) { .clear-pane[data-clear-map-detail-panel] { flex-basis: 600px; } }

/* --- 24.2 Desktop pane collapse: let the user reclaim the map ----------
   Presentation state only. Nothing about the selection, the active pollutant,
   the pinned month or the monitor relationship is touched. */
.clear-pane-collapse {
  position: absolute; top: 10px; right: 10px; z-index: 6;
  width: 26px; height: 26px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--line); border-radius: var(--r-sm);
  background: var(--surface); color: var(--muted); cursor: pointer;
}
.clear-pane-collapse svg { width: 14px; height: 14px; }
.clear-pane { position: relative; }
[data-clear-pane-mode="sheet"] .clear-pane-collapse { display: none; }

/* FCLEAR-APP-0002B Gate B. This is no longer only a user-invoked state: with nothing selected it
   is the LOAD state, because the product is map first and an empty analytical pane must not take
   a third of the workspace before a question has been asked.

   Both guards are deliberate and mirror each other, which is this stylesheet's standing convention
   for the responsive contract (see section 5): the MEDIA QUERY is correct before JS runs, and the
   `:not([data-clear-pane-mode="sheet"])` attribute guard is correct after it does. Either one
   alone would be enough at rest; together they close the FIRST PAINTED FRAME, where the markup
   ships `data-clear-pane-mode="docked"` and `data-clear-pane-collapsed="true"` and the broker has
   not yet resolved the real mode. Without the media guard, a 390px phone would spend that frame
   applying `width: 0` to the bottom sheet -- which would zero-width the phone air-quality rail,
   the very surface FCLEAR-APP-0002A added to stop an empty 238px panel standing over a 390px map.
   The sheet's map-first behaviour is its collapsed detent, never a zero width. */
@media (min-width: 768px) {
  .clear-workspace[data-clear-pane-collapsed="true"]:not([data-clear-pane-mode="sheet"])
    .clear-pane[data-clear-map-detail-panel] {
    flex-basis: 0; width: 0; min-width: 0; border-left: 0; overflow: hidden;
    /* The overlay drawer carries a shadow. At zero width that shadow is all that is left of it,
       and it paints a dark bar down the right edge of a map that is supposed to be unobstructed. */
    box-shadow: none;
  }
  .clear-workspace[data-clear-pane-collapsed="true"]:not([data-clear-pane-mode="sheet"])
    .clear-pane > * { display: none; }
}

/* The reopen affordance. It is anchored to the RIGHT EDGE, vertically centred, rather than to the
   top-right corner, and the reason is a measured collision rather than taste: at and below 1120px
   FCLEAR-APP-0002C's canvas search row spans the full canvas width at `top: 16px` with
   `z-index: 40`, so a top-right button sat underneath it and could not be clicked. The 0002C
   search contract -- one input at every width, that z-index, its 12px gutters -- is deliberately
   NOT retuned to make room; the pane's own affordance moves instead, to the one edge that belongs
   to the pane. One position at every width, so there is no second breakpoint here either.

   `min-height: 44px` is the tap-target floor QA F-8 established for this shell. */
.clear-pane-reopen {
  position: absolute; top: 50%; right: 0; transform: translateY(-50%); z-index: 7;
  display: none; align-items: center; gap: 7px;
  min-height: 44px;
  padding: 9px 12px 9px 11px;
  border: 1px solid var(--line); border-right: 0;
  border-radius: var(--r-md) 0 0 var(--r-md);
  background: var(--surface); color: var(--brand-ink);
  font: 700 13px/1 var(--f); cursor: pointer; box-shadow: var(--sh-2);
}
.clear-workspace[data-clear-pane-collapsed="true"] .clear-pane-reopen { display: inline-flex; }
/* The sheet has no reopen button at any time: its grip and its peek card are its own affordances,
   and the media query keeps that true in the pre-JS frame as well. */
[data-clear-pane-mode="sheet"] .clear-pane-reopen { display: none !important; }
@media (max-width: 767px) { .clear-pane-reopen { display: none !important; } }

/* --- 24.3 Evidence rows: a source name must never render one character per
   line. The grid was letting the identity column shrink to min-content. ---- */
[data-clear-evidence-body] .clear-evidence-row { display: block; width: 100%; }
[data-clear-evidence-body] .clear-evidence-head {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 8px;
  width: 100%; margin-bottom: 5px;
}
[data-clear-evidence-body] .clear-evidence-head .clear-chip { flex: 0 0 auto; }
[data-clear-evidence-body] .clear-evidence-head strong {
  /* The identity gets the whole remaining line and a real minimum, so it can
     never be squeezed into a one-character column. */
  flex: 1 1 100%;
  min-width: 12rem;
  overflow-wrap: break-word;
  word-break: normal;
  white-space: normal;
  font-size: 13.5px; line-height: 1.35;
}
@media (min-width: 1px) {
  [data-clear-evidence-body] .clear-evidence-meta {
    display: block; width: 100%; min-width: 0;
    white-space: normal; word-break: normal; overflow-wrap: break-word;
  }
}
[data-clear-evidence-body] .clear-source-row,
[data-clear-nearby-body] .clear-source-row { grid-template-columns: minmax(0, 1fr); }
[data-clear-evidence-body] .clear-source-row-name,
[data-clear-nearby-body] .clear-source-row-name {
  flex: 1 1 100%; min-width: 12rem; word-break: normal; overflow-wrap: break-word;
}

/* --- 24.4 Air Quality density: make the sections visually distinct and put
   the segment register behind a disclosure so ordinary use is not a wall. --- */
[data-clear-air-quality-body] .clear-card + .clear-card { margin-top: 16px; }
.clear-register { max-height: 340px; overflow-y: auto; }

/* --- 24.5 Map balance, measured -----------------------------------------
   With rail 320 + pane 468 the map fell to 578px (42%) at 1366 and 652px (45%)
   at 1440 -- the uncomfortable case. Two changes, per the operator's rule that
   the pane should go to overlay rather than the map being squeezed:
     - hold the docked layout only from 1500px up;
     - trim the rail at mid widths, since rail + pane together caused it.
   Measured after: 1366 and 1440 use the overlay drawer with a full-width map;
   1600 gives the map ~52%. */
@media (min-width: 1320px) and (max-width: 1499px) {
  .clear-workspace[data-clear-pane-mode] { --clear-force-overlay: 1; }
}
@media (max-width: 1499px) {
  .clear-pane[data-clear-map-detail-panel] {
    position: absolute; top: 0; right: 0; bottom: 0; z-index: 5;
    flex-basis: auto; width: 414px;
    box-shadow: var(--sh-2);
  }
}
@media (min-width: 1500px) and (max-width: 1699px) { .clear-rail { flex-basis: 280px; width: 280px; } }

/* FCLEAR-APP-0002A: the basemap control names the active basemap. It is a state read-out, not a
   selector, because the governed map estate publishes only the Light style today (drift D-15). */
.clear-action-state {
  display: inline-block; margin-left: 6px; padding: 1px 6px; border-radius: 999px;
  background: var(--chip-bg, rgba(15, 42, 66, .08)); color: var(--muted);
  font-size: 11px; font-weight: 700; letter-spacing: .02em; vertical-align: baseline;
}


/* ============================================================================================
   25. Analytical pane density, matched to the approved mockup (01-commercial-wide-overview).
   The pane had drifted into a documentation panel: verbose prose above the tiles, a tall
   toolbar stack above the plot, and a graph that was a minority of its own card. The mockup is
   a compact analytical workspace -- one insight sentence, one tight tile row, then a large
   graph. Presentation only: no governed fact is removed, and every value still comes from the
   same resolved state.
   ============================================================================================ */

/* --- 25.1 Insight summary: compact, scannable, caveat subordinate -------------------------- */
.clear-answer-strip { padding: 12px 14px; }
.clear-answer-text { font-size: 14.5px; line-height: 1.45; }
.clear-answer-text strong { font-weight: 700; }
.clear-answer-caveat { margin-top: 5px; font-size: 11px; line-height: 1.35; opacity: .72; }

/* --- 25.2 Current Air: the mockup goes header -> tiles, with no prose in between ------------ */
/* The nearest-site line duplicates the card kicker and the Air Quality metric card. Demoted to a
   compact caption rather than a full-width summary block. */
.clear-condition-summary {
  font-size: 11.5px; line-height: 1.3; color: var(--muted);
  margin: 0 0 8px; padding: 0;
}
/* Governed explanatory prose stays in the document for Air Quality and for assistive tech, but
   must not compete with the analysis in the default Overview view. It remains available in the
   Air Quality tab, where the same nodes are rendered. */
[data-clear-card="current-air"] .clear-condition-source-note,
[data-clear-card="current-air"] .clear-condition-source-list { display: none; }
[data-clear-card="current-air"] .clear-card-head { padding-bottom: 8px; }
[data-clear-card="current-air"] .clear-card-body { padding-bottom: 12px; }

.clear-tiles { gap: 6px; }
.clear-tile { min-height: 72px; padding: 6px 3px 5px; gap: 1px; }
.clear-tile > strong { font-size: 11.5px; letter-spacing: .01em; }
/* Size the NUMBER, not the whole reading span: the span also carries the word "Unavailable", and
   at 22px in a 60px tile that word overflowed and broke mid-syllable. */
.clear-tile .clear-condition-number { font-size: 22px; line-height: 1.05; }
.clear-tile-state { font-size: 8.5px; letter-spacing: .04em; padding: 1px 3px; }
/* PM10's governed unavailable copy is kept verbatim and sits in the same shell as the others.
   Only its typography is tightened, so it no longer stretches the whole row to its own height --
   the tile grid sizes every tile to the tallest one. */
.clear-tile.is-unavailable .clear-tile-unavailable-text { font-size: 9.5px; line-height: 1.15; }
.clear-tile.is-unavailable .clear-tile-unavailable-note { font-size: 8.5px; line-height: 1.15; opacity: .8; }

.clear-tiles-hint { margin: 7px 0 0; font-size: 11px; line-height: 1.35; color: var(--muted); }

/* --- 25.3 History: the plot is the point ---------------------------------------------------- */
/* The card carried a subhead AND a status paragraph above a two-row toolbar -- ~160px of chrome
   before any data. The mockup shows one subline, then the graph. */
[data-clear-environmental-history-card] .clear-history-status { display: none; }
[data-clear-environmental-history-card] .clear-history-subhead {
  margin: 0 0 8px; font-size: 11.5px; line-height: 1.3; color: var(--muted);
}
[data-clear-environmental-history-card] .clear-card-head { padding-bottom: 6px; }
.clear-hg-toolbar {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  margin: 0 0 8px; padding: 0;
}
.clear-hg-hint { margin: 6px 0 0; font-size: 10.5px; line-height: 1.3; opacity: .8; }
.clear-hg-tip { margin-top: 8px; }


/* --- 25.4 Tile row height is set by its tallest tile ---------------------------------------- */
/* The grid stretches every tile to the tallest, so PM10's two-line governed unavailable copy and
   the word "Unavailable" on empty tiles were dictating the height of the whole row -- 107px
   against the mockup's ~62px. The copy is kept verbatim; only its typography is tightened, and
   the "Unavailable" word is sized to fit a 60px tile instead of being clipped to "Unavailabl". */
.clear-tile .clear-condition-reading { font-size: 9.5px; line-height: 1.15; letter-spacing: -.01em; }
.clear-tile .clear-condition-number { font-size: 21px; line-height: 1.02; letter-spacing: -.02em; }
.clear-tile .clear-condition-unit { font-size: 8.5px; line-height: 1.1; }
.clear-tile.is-unavailable .clear-tile-unavailable-text { font-size: 8.5px; line-height: 1.1; }
.clear-tile.is-unavailable .clear-tile-unavailable-note { font-size: 8px; line-height: 1.1; opacity: .75; }
.clear-tile { min-height: 0; padding: 5px 3px 4px; }
.clear-tile > strong { font-size: 11px; line-height: 1.1; }


/* ============================================================================================
   26. Live acceptance corrections. Every item here was raised against the RUNNING product, not
   against a mockup crop, so each is a real interaction defect rather than a styling preference.
   ============================================================================================ */

/* --- 26.1 The collapse control must never sit on top of the close button -------------------- */
/* It was absolutely positioned at top-right of the pane, which is exactly where the identity
   row's close button lives -- two controls, one target. Moved to the pane's LEFT EDGE, vertically
   centred, which is the operator's second suggested model. It now collides with nothing, remains
   available whether or not a place is selected, and keeps its own click target. */
.clear-pane-collapse {
  position: absolute; top: 50%; left: 0; right: auto; transform: translateY(-50%);
  z-index: 6;
  width: 18px; height: 46px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--line); border-right: 0;
  border-radius: var(--r-sm) 0 0 var(--r-sm);
  background: var(--surface); color: var(--muted); cursor: pointer;
  box-shadow: var(--sh-1);
}
.clear-pane-collapse:hover { color: var(--ink); background: var(--surface-3); }
.clear-pane-collapse svg { width: 12px; height: 12px; }

/* --- 26.2 Every tab must be visible on desktop, never scrolled ------------------------------ */
/* The strip was overflow-x:auto with min-width:max-content tabs, so Evidence fell off the end of
   an ordinary desktop pane. The tabs now share the row and shrink their padding rather than their
   legibility. Horizontal scrolling is retained ONLY for the phone sheet.
   FCLEAR-APP-0002B, Gate B finding F-02: this rule was written for five equal tabs. The merged
   `pulm.ai & Evidence` tab replaced three of them, so the row now carries three tabs of very
   unequal natural width. `flex: 1 1 0` gave each an equal third, which is 419px of content in a
   413px box -- the long label's ink ran into the last pixel column at every width below 1600, and
   at 768 landscape it pushed `Overview` off its left edge too. Tabs now take their natural width
   and shrink only when they must, and the padding is tightened. Legibility is unchanged: the same
   font size, the same nowrap, no truncation and no ellipsis. */
.clear-pane-tabs { overflow-x: visible; padding: 0 6px; }
.clear-pane-tab {
  flex: 0 1 auto; min-width: 0; padding: 0 2px;
  font-size: 12.5px; text-align: center; white-space: nowrap;
}

/* --- 26.3 Five governed tiles, sized to be readable ----------------------------------------- */
/* With PM10 removed the row is five columns instead of six, so each tile gains real width and the
   value/unit/status typography returns to a readable size instead of collapsing. */
.clear-tiles { grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 7px; }
.clear-tile { min-height: 76px; padding: 8px 5px 7px; }
.clear-tile > strong { font-size: 12px; }
.clear-tile .clear-condition-number { font-size: 24px; line-height: 1.05; }
.clear-tile .clear-condition-unit { font-size: 10px; }
.clear-tile .clear-condition-reading { font-size: 12px; line-height: 1.2; }
.clear-tile-state { font-size: 9px; }
@media (min-width: 1121px) {
  .clear-tiles { grid-template-columns: repeat(5, minmax(0, 1fr)); }
}

/* --- 26.4 The sticky footer must not own the bottom of the workspace ------------------------ */
/* Three large buttons, two of them permanently disabled placeholders for actions this release
   does not implement, were consuming vertical space that History needed. Unavailable actions are
   hidden rather than shown as dead affordances; they remain in the DOM for assistive tech and
   return the moment they are enabled. */
.clear-pane-actions { padding: 8px 14px; gap: 8px; }
.clear-pane-action { height: 30px; font-size: 12.5px; padding: 0 10px; }
.clear-pane-action:disabled { display: none; }
.clear-pane-actions:empty { display: none; }

/* --- 26.5 One spacing scale for the pane ---------------------------------------------------- */
/* Gutters were set per-component and drifted. These pin the pane to a single 14px gutter and a
   12px card rhythm so the left/right edges line up from identity to footer. */
.clear-pane-body { padding: 12px 14px 14px; }
.clear-pane-identity { padding: 12px 14px 10px; }
.clear-tabpanel { padding: 12px 0 4px; }
.clear-card + .clear-card { margin-top: 12px; }
.clear-card-head { padding: 12px 14px 8px; }
.clear-card-body { padding: 0 14px 12px; }
.clear-answer-strip { margin-bottom: 12px; }

/* TOUCH GESTURES BELONG TO THE BROWSER.
   ------------------------------------------------------------------------------------------
   This was `touch-action: pan-y`, which was the cause of the iOS defect reported on BOTH Safari
   and Chrome (both are WebKit on iOS, so the common denominator is WebKit plus our code).

   `pan-y` declares that the browser may pan VERTICALLY for a touch starting here -- and therefore
   that it may NOT pan horizontally. Native horizontal scrolling of the timeline was switched off
   at the CSS level, so the only thing that could move it was our JS scrollLeft writes. WebKit then
   arbitrated the gesture, decided the touch belonged to the sheet's vertical scroller, and fired
   pointercancel; our pan stopped there. Each swipe contributed only the few pixels delivered
   before cancellation, which is exactly the reported symptom -- one swipe barely moves, several
   swipes advance the timeline a little.

   `auto` gives the gesture back to WebKit, which already does directional locking natively and
   far better than we can: a horizontal swipe scrolls the nearest horizontally scrollable ancestor
   (this element), a vertical swipe scrolls the nearest vertically scrollable one (the sheet body).
   The History container owns horizontal, the bottom sheet owns vertical, one gesture goes to
   exactly one of them, and momentum/inertia is the platform's. The JS pan now declines touch
   pointers outright, so the two never act on the same touch stream.

   Do not reintroduce a touch-action value that constrains an axis here. */
.clear-hg-scroll { touch-action: auto; }
.clear-hg-scroll.is-panning { user-select: none; }

/* The grab affordance belongs only where drag-to-pan actually exists, which is now mouse and pen
   only. On a touch device the surface scrolls natively and there is no drag cursor to advertise. */
@media (hover: hover) and (pointer: fine) {
  .clear-hg-scroll { cursor: grab; }
  .clear-hg-scroll.is-panning { cursor: grabbing; }
}
.clear-hg-scroll.is-panning .clear-hg-canvas { pointer-events: none; }

/* --- 26.6 History header carries the range controls, as the mockup does -------------------- */
.clear-card-head-with-ranges {
  display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: nowrap;
}
.clear-card-head-with-ranges .clear-hg-ranges { flex: 0 0 auto; margin: 0; }
/* With the ranges hoisted, the toolbar carries only the series legend, so it collapses from a
   two-row band into one compact line and the plot rises accordingly. */
.clear-hg-toolbar { margin: 0 0 6px; gap: 6px; }
.clear-hg-serieses { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.clear-hg-range { font-size: 11.5px; padding: 3px 7px; }


/* ============================================================================================
   27. Left rail compaction and Environmental Status responsive density.
   Measured against the approved mockup rail: ~209px wide, ~32px row pitch, ~15px checkbox,
   ~30px filter controls, labels on one line. The live rail was 280px with a 38px pitch, 38px
   filters, and BOTH monitor labels wrapping to two lines.
   ============================================================================================ */

/* --- 27.1 Rail geometry --------------------------------------------------------------------- */
/* The rail was also GROWING to 300px as the viewport shrank, which is backwards: it took map
   width exactly when the map had least to spare. It is now a fixed compact width, so tightening
   it returns width to the map rather than consuming more. */
.clear-rail { flex-basis: 248px; width: 248px; padding: 14px 12px 8px; }
@media (min-width: 1500px) and (max-width: 1699px) { .clear-rail { flex-basis: 248px; width: 248px; } }
@media (min-width: 1700px) { .clear-rail { flex-basis: 256px; width: 256px; } }

/* --- 27.2 Layer rows: a compact layer controller, not a settings form ----------------------- */
.clear-rail-head { margin-bottom: 8px; }
.clear-rail-kicker { font-size: 10.5px; letter-spacing: .12em; }
.clear-rail-subhead { margin: 12px 0 5px; font-size: 10.5px; letter-spacing: .12em; }
.clear-layer-item {
  min-height: 30px; padding: 4px 7px; border-radius: var(--r-sm);
  display: flex; align-items: center; gap: 7px;
}
.clear-layer-item label { display: flex; align-items: center; gap: 7px; min-width: 0; flex: 1 1 auto; }
.clear-layer-item input[type="checkbox"] { width: 15px; height: 15px; flex: 0 0 auto; margin: 0; }
.clear-layer-icon { flex: 0 0 auto; }
/* One line. "Regulatory Monitors" and "Community Sensors" both wrapped at the old width; they fit
   here. The governed no-ellipsis rule for those two names is preserved -- this clips rather than
   truncating with an ellipsis, exactly as before. */
.clear-layer-name { font-size: 13px; font-weight: 600; white-space: nowrap; min-width: 0; }
.clear-layer-state { font-size: 11.5px; flex: 0 0 auto; margin-left: auto; }

/* --- 27.3 Filters: shorter controls, tighter stack ------------------------------------------ */
.clear-filter { margin-top: 8px; }
.clear-filter label { font-size: 11.5px; margin-bottom: 3px; }
.clear-filter select { height: 30px; padding: 0 8px; font-size: 12.5px; }
.clear-rail-reset { font-size: 11.5px; }

/* --- 27.4 About this data stays a footnote, not a section ----------------------------------- */
.clear-rail-note { margin-top: 10px; font-size: 11.5px; line-height: 1.4; }

/* --- 27.5 Environmental Status: three densities, keyed to the MAP viewport ------------------ */
/* The card is good at large widths and must not be redesigned. It simply has to tighten as the
   map is squeezed. Pollutant, value, unit, condition and freshness survive at every density --
   only secondary framing is dropped, and it remains available in the analytical pane. */

/* COMPACT: smaller desktop and tablet. */
@media (max-width: 1439px) {
  .clear-aq-card { max-width: 232px; padding: 10px 12px; }
  .clear-aq-kicker { font-size: 9.5px; letter-spacing: .1em; }
  .clear-aq-title { font-size: 13px; }
  .clear-aq-value { font-size: 22px; }
  /* Network summary and represented-location count are framing, not the reading. */
  .clear-aq-body { display: none; }
  .clear-aq-progress { display: none; }
  .clear-aq-foot { font-size: 10.5px; line-height: 1.3; }
}

/* MINIMAL: narrow map. A status chip, not a panel over the map. */
@media (max-width: 900px) {
  .clear-aq-card {
    max-width: 168px; padding: 7px 9px; border-radius: var(--r-sm);
  }
  .clear-aq-kicker { font-size: 9px; }
  /* "Environmental Status" is the card's own framing; the pollutant kicker already names what
     this is, so the title is dropped before any governed value is. */
  .clear-aq-title { display: none; }
  .clear-aq-value { font-size: 19px; line-height: 1.1; }
  .clear-aq-foot { font-size: 9.5px; line-height: 1.25; }
  /* FCLEAR-APP-0002B Gate B, A4: `display: none` here was a SECOND, CSS-side legend state model
     that the Legend button could not see. The narrow-map decision it encoded (the legend is not a
     permanent overlay on a squeezed map) is preserved exactly -- it is now expressed as the
     shell's initial/auto-close state in section 34.4, driven by this same 900px boundary, so
     there is one source of truth and the button can never disagree with the panel. */
}


/* --- 27.6 Two corrections found by measuring the rendered rail ------------------------------ */

/* The rail was still 300px in the overlay pane-mode band, because
   `.clear-workspace[data-clear-pane-mode="overlay"] .clear-rail` outranks a bare `.clear-rail`.
   Matched here at the same specificity so the compact width holds in every mode. */
.clear-workspace[data-clear-pane-mode="overlay"] .clear-rail,
.clear-workspace[data-clear-pane-mode="docked"] .clear-rail { flex-basis: 248px; width: 248px; }
@media (max-width: 1319px) { .clear-rail { flex-basis: 248px; width: 248px; } }

/* "Regulatory Monitors" and "Community Sensors" carry a deliberate rule that stops them being
   TRUNCATED WITH AN ELLIPSIS -- an earlier package fixed that by letting them wrap instead. The
   no-ellipsis guarantee is the governed part and is kept exactly (overflow visible, text-overflow
   clip); only the wrapping is dropped, because at the compact rail width both names fit on one
   line. If a future translation did overflow, it clips -- it never renders a misleading ellipsis. */
.clear-layer-item[data-clear-layer-row="regulatory-air-monitors"] .clear-layer-name,
.clear-layer-item[data-clear-layer-row="community-air-sensors"] .clear-layer-name {
  overflow: visible;
  text-overflow: clip;
  white-space: nowrap;
}
/* The count column reserved 44px on a 248px rail, which is what pushed those two names to wrap. */
.clear-layer-state { min-width: 28px; }


/* --- 28. Map controls follow the visible map, not the container edge ------------------------ */
/* --clear-map-ctrl-right is published by clearShellUpdateMapControlOffset from the MEASURED
   overlap between the analytical pane and the map container, so the controls stay inside the
   visible map in docked, overlay, collapsed and sheet modes without any breakpoint-keyed magic
   number. The fallback keeps them correct before the first measurement. */
.maplibregl-ctrl-top-right { right: var(--clear-map-ctrl-right, 14px); }
.maplibregl-ctrl-bottom-right { right: var(--clear-map-ctrl-right, 14px); bottom: var(--clear-map-ctrl-bottom, 14px); }
.maplibregl-ctrl-bottom-left { bottom: var(--clear-map-ctrl-bottom, 14px); }


/* =======================================================================
   29. FCLEAR-APP-0002A — phone no-selection state.

   Reported outstanding item: on phone with nothing selected the collapsed
   bottom sheet rendered a 238px empty white panel over a 390px-wide map.
   Every child of the collapsed sheet is display:none except the peek, and
   the peek is hidden until a place is loaded -- so the sheet was 238px of
   nothing, taking 28% of an 844px viewport from the map that the binding
   decision calls primary.

   The sheet now reduces to a thin air-quality status rail in exactly that
   state. It carries the governed monitoring-network reading and is accented
   with the governed condition colour. It is presentation only: it does not
   fetch, does not change the selection, and does not alter the sheet's
   collapsed/expanded contract -- the grip still expands to the full panel,
   where the "Select a place on the map" guidance lives.
   ======================================================================= */

.clear-pane-idle { display: none; }
.clear-pane-idle[hidden] { display: none !important; }

/* Shown ONLY in the sheet's collapsed state with nothing selected. `:not([data-clear-detail-state
   ="loaded"])` covers the initial, cleared, loading and error states alike -- in none of them is
   there a place to describe, and in all of them the network summary is still the honest answer. */
.clear-workspace[data-clear-pane-mode="sheet"]:not([data-clear-detail-state="loaded"])
  .clear-pane[data-clear-pane-state="collapsed"] .clear-pane-idle:not([hidden]) {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 2px 16px 14px;
}

/* The rail replaces the fixed 238px sheet height with its own content height. Specificity beats
   both the `@media (max-width: 767px) .clear-pane` rule and the pane-mode rule, so no media query
   is needed here and the two stay in agreement. */
.clear-workspace[data-clear-pane-mode="sheet"]:not([data-clear-detail-state="loaded"])
  .clear-pane[data-clear-pane-state="collapsed"] {
  height: auto;
}

/* Condition-colour accent. The category classes set `color` (with !important), so painting the
   bar with currentColor reuses the governed category mapping exactly rather than restating it --
   including `unavailable`, which must read as absent, not as a reading. */
.clear-idle-accent {
  flex: 0 0 auto;
  width: 4px;
  align-self: stretch;
  min-height: 34px;
  border-radius: 999px;
  background: currentColor;
}

.clear-idle-text { min-width: 0; flex: 1 1 auto; }
.clear-idle-kicker {
  font-size: 9.5px; font-weight: 800; letter-spacing: .12em;
  text-transform: uppercase; color: var(--muted); font-family: var(--f);
}
.clear-idle-kicker sub { font-size: .8em; }
.clear-idle-meta {
  margin-top: 3px;
  font-size: 11.5px; line-height: 1.35; color: var(--muted);
}
.clear-idle-reading {
  flex: 0 0 auto;
  font-family: var(--m); font-variant-numeric: tabular-nums;
  font-size: 22px; font-weight: 800; line-height: 1; letter-spacing: -.02em;
  white-space: nowrap;
}
.clear-idle-reading small { font-size: 11px; margin-left: 4px; font-family: var(--f); font-weight: 700; }
/* Absence is stated in words at body size, never in the numeral's display size. */
.clear-idle-reading.clear-aqi-category-unavailable { font-size: 12px; font-family: var(--f); font-weight: 700; }

/* On phone the idle rail carries the identical governed network reading, so the floating card
   would be a second copy of the same fact over the smallest map in the estate. It is suppressed
   only while the rail is showing it, and returns the moment a selection replaces the rail with
   the place peek -- so exactly one surface states the network summary at any time. */
@media (max-width: 767px) {
  .clear-workspace[data-clear-pane-mode="sheet"]:not([data-clear-detail-state="loaded"]) .clear-aq-card { display: none; }
}


/* =======================================================================
   30. FCLEAR-APP-0002A — Current Air tile row: one column per governed tile.

   CORRECTED RATIONALE. This section first claimed the row still declared SIX
   columns for five tiles, and that the resulting narrow tile was what made the
   row ~100px against the mockup's ~72px. That was a misdiagnosis, caught by
   independent QA (kimi-01) and confirmed against the pre-change stylesheet:
   section 26.3 already declared `repeat(5, minmax(0, 1fr))` both globally and
   at >=1121px, and both sit AFTER the `repeat(6)` rules at equal specificity.
   The row was already five equal columns at every width, so this change does
   NOT alter the rendered column count or tile width.

   What it is still worth keeping is robustness. Two dead `repeat(6)` rules
   remain earlier in this file, live-looking but permanently overridden, and a
   hard-coded count is exactly what goes stale when the governed tile set
   changes. An implicit column track gives one equal column per tile whatever
   the count is, so restoring PM10 when serving exists stays the markup-only
   change the template comment promises, with no stylesheet edit and no third
   stale count to override.

   WHAT THIS DOES NOT FIX: the row-height gap is still open. Measured 106px at
   1600px with real readings against the mockup's ~72px. The excess is in the
   composition, not the column count -- the reading block alone measures 38px
   because the value and its unit are separate stacked lines, and the active
   tile reserves bottom padding for the governed "Find It Now" chip, which the
   mockup does not carry at all. Closing it means changing type scale and
   margins, or dropping governed content. Reported, not silently tuned.
   ======================================================================= */

@media (min-width: 1121px) {
  .clear-tiles {
    grid-auto-flow: column;
    grid-auto-columns: minmax(0, 1fr);
    grid-template-columns: none;
  }
}

/* With the tile ~20% wider the reading and the condition word each fit on one line, so the row
   no longer needs to reserve the height two wrapped lines used to take. The floor stays high
   enough for the tallest governed content -- label, reading, condition and the active-state chip
   pinned to the foot -- and the grid still equalises the tiles to the tallest of them. */
@media (min-width: 1121px) {
  .clear-tile { min-height: 72px; }
}


/* =======================================================================
   31. FCLEAR-APP-0002A — COMPACT SELECTED-PLACE DASHBOARD.

   Gate B defect: selecting a place produced largely linear text with weak
   hierarchy and no grouping -- it read as diagnostic output rather than a
   product surface. It was also two different undesigned surfaces: the
   collapsed sheet's peek on phone, and the pane identity header on desktop
   and tablet, which is why it looked wrong in both places.

   This is ONE component for every breakpoint, built to the approved mockup
   (mockups/04-commercial-phone-collapsed.png): identity with a category chip,
   a ruled metric block, a ruled source row with the distance right-aligned,
   then the expand affordance. Ruled groups and a label/value hierarchy, so it
   is scannable in a second or two.

   It does NOT redesign the expanded analytical pane. The tabs, cards and
   History below it are untouched.
   ======================================================================= */

.clear-pane-peek { display: none; }
.clear-pane-peek[hidden] { display: none !important; }

/* Shown in the collapsed phone sheet, and on desktop/tablet as the pane's identity header. */
[data-clear-pane-mode="sheet"] .clear-pane[data-clear-pane-state="collapsed"] .clear-pane-peek:not([hidden]),
.clear-workspace[data-clear-detail-state="loaded"]:not([data-clear-pane-mode="sheet"]) .clear-pane-peek:not([hidden]) {
  display: block;
  background: var(--surface);
}

/* Where the dashboard renders it IS the identity, so the old linear identity block stands down.
   Its hooks stay in the DOM -- the dashboard mirrors them -- so nothing that reads them breaks. */
[data-clear-pane-mode="sheet"] .clear-pane[data-clear-pane-state="collapsed"] .clear-pane-identity,
.clear-workspace[data-clear-detail-state="loaded"]:not([data-clear-pane-mode="sheet"]) .clear-pane-identity {
  display: none;
}

/* The collapsed sheet shows the compact dashboard and NOTHING else. Without this the tabs, the
   panel body and the sticky footer all render underneath it -- which the fixed 238px height used
   to hide by clipping, so releasing that height unfolded the entire analytical pane into the
   collapsed state. The clip was doing this rule's job; now the rule does it. */
[data-clear-pane-mode="sheet"] .clear-pane[data-clear-pane-state="collapsed"] .clear-pane-tabs,
[data-clear-pane-mode="sheet"] .clear-pane[data-clear-pane-state="collapsed"] .clear-pane-body,
[data-clear-pane-mode="sheet"] .clear-pane[data-clear-pane-state="collapsed"] .clear-pane-actions {
  display: none;
}

/* Measured off mockups/04-commercial-phone-collapsed.png (780x1566 @DPR2) and reconciled against
   prototype/clear-prototype.html, which carries the real code for this state. Sizes below are the
   measured values, not approximations. Divergences from the package are marked DIVERGENCE with a
   reason; everything else is the package.

   --- identity --------------------------------------------------------------------------------- */
.clear-peek-head {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 12px 15px 10px;
  border-bottom: 1px solid var(--line);
}
/* The package hides the icon square in the collapsed phone sheet but shows it in the docked and
   overlay identity, so it follows the breakpoint rather than the component. */
.clear-peek-icon {
  flex: 0 0 auto;
  width: 30px; height: 30px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--r-sm);
  background: var(--brand-ink); color: #fff;
  font: 800 13px/1 var(--f);
}
[data-clear-pane-mode="sheet"] .clear-peek-icon { display: none; }

.clear-peek-headtext { flex: 1 1 auto; min-width: 0; }
.clear-peek-nameline { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; min-width: 0; }
.clear-peek-name {
  margin: 0; min-width: 0;
  font-size: 14px; font-weight: 700; line-height: 1.4;
  color: var(--ink); letter-spacing: -.01em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Mono, uppercase, tinted from the same token family the mockup samples exactly. */
.clear-peek-badge {
  flex: 0 0 auto;
  padding: 2px 6px; border-radius: 4px;
  background: color-mix(in srgb, var(--good) 13%, transparent);
  color: var(--good);
  font-family: var(--m); font-size: 9.6px; font-weight: 600;
  letter-spacing: .07em; text-transform: uppercase; white-space: nowrap;
}
.clear-peek-badge[hidden] { display: none; }
.clear-peek-locality {
  margin-top: 2px; font-size: 11.85px; line-height: 1.5; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* DIVERGENCE: the package hides the classifier line in the collapsed sheet. Kept because the
   operator's brief requires the place type on the compact surface at every breakpoint. */
.clear-peek-type {
  margin-top: 1px; font-size: 11px; line-height: 1.45; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.clear-peek-type[hidden] { display: none; }
.clear-peek-close {
  flex: 0 0 auto;
  width: 28px; height: 28px; padding: 0;
  display: grid; place-items: center;
  border: 0; border-radius: var(--r-sm);
  background: none; color: var(--muted); cursor: pointer;
}
.clear-peek-close:hover { background: var(--surface-2); color: var(--ink); }
.clear-peek-close:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }

/* DIVERGENCE: the package hides the registry caveat in the collapsed sheet, which reads against
   DESIGN-SPEC 4.1 calling it "a permanent affordance, not a tooltip-only disclosure". Kept
   visible: suppressing a governed disclosure is the riskier of the two readings. Recorded as
   drift for an operator decision rather than settled here. */
.clear-pane-peek .clear-pane-caveat { margin: 10px 15px 0; }
/* QA F-4/F-5/F-6: the card carried three different row gutters (11/9/10px), a 2px stagger between
   the header's 13px inset and the body's 15px, and one full-bleed rule against one inset rule.
   Unified: a single 15px gutter, a single 10px vertical step, and both rules full-bleed. The
   package's own 13px/15px asymmetry is an artefact of its two containers and is not reproduced. */

/* --- the pollutant metric block ------------------------------------------------------------- */
/* The number is INK, not the condition colour. The package carries the air-quality condition in
   exactly one place -- a 5px dot before the condition word -- and nowhere else: not the numeral,
   not the condition text, not a bar, tint or border. */
.clear-peek-metric {
  display: flex; align-items: center; gap: 11px;
  padding: 10px 15px;
}
.clear-peek-metric-value {
  flex: 0 0 auto;
  font-family: var(--m); font-variant-numeric: tabular-nums;
  font-size: 24px; font-weight: 600; line-height: 1; color: var(--ink);
  /* QA F-1: without Plex Mono the fallback's wide digit advance made "2.8" read as separate
     glyphs. Tightened just enough to restore the mockup's rendered density. */
  letter-spacing: -.02em;
}
.clear-peek-metric-meta { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.clear-peek-metric-label { font-size: 11.2px; font-weight: 600; color: var(--muted); line-height: 1.5; }
.clear-peek-metric-unit { margin-left: 4px; }
.clear-peek-metric-cond {
  display: flex; align-items: center; gap: 4px;
  font-size: 11.5px; line-height: 1.5; color: var(--muted);
  min-width: 0;
}
.clear-peek-dot { width: 5px; height: 5px; border-radius: 50%; background: currentColor; flex: 0 0 auto; }
/* Absence is stated in words at body size, never as a large numeral. */
.clear-peek-metric.is-unavailable .clear-peek-metric-value {
  font-family: var(--f); font-size: 12px; font-weight: 600; color: var(--muted);
}

/* --- the reporting source row --------------------------------------------------------------- */
/* No caption above this row: in the package the BADGE is the label. The row is the series, the
   name and the distance on one line, the distance flushed right. */
.clear-peek-source {
  display: flex; align-items: center; flex-wrap: wrap; gap: 9px;
  padding: 10px 15px;
  border-top: 1px solid var(--line);
}
.clear-peek-source .clear-source-badge {
  flex: 0 0 auto; min-width: 74px; text-align: center;
  padding: 2px 6px; border-radius: 4px;
  font-family: var(--m); font-size: 9.6px; font-weight: 600;
  letter-spacing: .07em; text-transform: uppercase;
}
.clear-peek-source-name {
  flex: 1 1 auto; min-width: 0;
  font-size: 12.65px; font-weight: 400; color: var(--ink); line-height: 1.5;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.clear-peek-source-dist {
  flex: 0 0 auto;
  font-family: var(--m); font-variant-numeric: tabular-nums;
  font-size: 11.5px; color: var(--muted); white-space: nowrap;
}
/* DIVERGENCE: the package has no caveat line here. Kept, quietly, because the brief requires that
   the compact surface never imply the reading was taken at the selected place, and because the
   badge and distance alone do not say where the measurement happened. */
.clear-peek-source-caveat {
  flex: 1 0 100%; margin: 1px 0 0;
  /* QA F-7: this is the card's only governance disclaimer and it measured 2.98:1 against white,
     well under the 4.5:1 floor for small text. --muted is 4.91:1, and the size comes up with it. */
  font-size: 11px; line-height: 1.45; color: var(--muted);
}
.clear-peek-source-absent {
  flex: 1 1 100%; margin: 0;
  font-size: 12px; line-height: 1.45; color: var(--muted);
}

/* --- expand affordance ----------------------------------------------------------------------- */
.clear-peek-action {
  display: flex; align-items: center; justify-content: center; gap: 6px;
  width: calc(100% - 30px); margin: 0 15px 12px;
  padding: 9px;
  border: 0; border-radius: var(--r-sm);
  background: var(--brand-ink); color: #fff;
  font-family: var(--f); font-size: 12.8px; font-weight: 600; line-height: 1.5;
  cursor: pointer;
}
.clear-peek-action svg { width: 13px; height: 13px; }
.clear-peek-action:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
/* On desktop and tablet the full analysis is already on screen below this card, so an expand
   control would point at nothing. The tabs are the affordance there. */
.clear-workspace:not([data-clear-pane-mode="sheet"]) .clear-peek-action { display: none; }
.clear-workspace:not([data-clear-pane-mode="sheet"]) .clear-pane-peek { padding-bottom: 12px; border-bottom: 1px solid var(--line); }

/* The collapsed sheet takes the card's own height. At the package's fixed 238px the expand button
   fell outside the sheet and off the bottom of a 390x844 screen entirely -- measured 273px of card
   in a 238px box. Letting the height follow the content is what keeps the affordance reachable,
   and it is the same treatment the no-selection rail already uses, so the sheet has one rule for
   its height rather than two competing constants. The expanded state is untouched. */
.clear-workspace[data-clear-pane-mode="sheet"][data-clear-detail-state="loaded"]
  .clear-pane[data-clear-pane-state="collapsed"] {
  height: auto;
}

/* QA F-8: 28px and 37px controls are under the ~40px tap-target floor, and on phone the close is
   the card's only dismiss control. Enlarged by hit area rather than by appearance -- the negative
   margins keep the glyph exactly where the mockup puts it. */
@media (max-width: 767px) {
  .clear-peek-close { width: 40px; height: 40px; margin: -6px -6px -6px 0; }
  .clear-peek-action { padding: 12px 9px; }
}

/* --- mobile: exactly one air-quality surface at a time --------------------------------------- */
/* The thin AQ rail carries the network reading while nothing is selected; this card carries the
   PLACE reading once something is. Showing the floating network card as well put two different
   large readings on one phone screen -- 6.8 network against 3.8 at the place -- which reads as a
   contradiction rather than as two facts. The network summary remains in the expanded pane. */
@media (max-width: 767px) {
  .clear-workspace[data-clear-pane-mode="sheet"] .clear-aq-card { display: none; }
}

/* =============================================================================
   32. FCLEAR-APP-0002A — SEARCH PLACEMENT.

   Two search inputs exist in this shell: the tier-2 header search
   (`.clear-tier2 .clear-search`) and the map-canvas search
   (`.clear-canvas-search-row`). Both are INERT — no listeners, no autocomplete,
   no endpoint. Search FUNCTIONALITY is deferred to a separate governed package;
   this section governs PLACEMENT only.

   The defect: neither carried a responsive rule, so both rendered together at
   every width. Measured on the deployed build, 360px -> 1920px, twenty widths:
   BOTH visible at all twenty.

   Measured usable header capacity (rendered width of the tier-2 search, and
   whether its own placeholder still fits):

       vw     header search   placeholder   tier-2 overflow
       1920      420px          fits            none
       1600      420px          fits            none
       1500      396px          fits            none
       1440      336px          CLIPPED         none
       1366      262px          CLIPPED         none
       1320      216px          CLIPPED         none
       1280      420px          fits            none
       1200      420px          fits            none
       1120      351px          fits            none
       1024      255px          CLIPPED         none
        900      131px          CLIPPED         none
        834       65px          CLIPPED         none
        768       26px          CLIPPED         28px
        390       26px          CLIPPED        269px

   Two things follow from that table.

   1. 1120/1121 is the real capacity boundary. At 1121+ the header is still a
      full desktop bar and the search holds 351-420px. At 1120 and below it
      collapses through 255 -> 131 -> 65 -> 26px, and below 768 the header
      itself overflows the viewport and pushes the user chip off-screen. 1121
      is also where this stylesheet already moves the rail into a dismissible
      drawer and reveals the hamburger, so the header changes character at
      exactly the same width. The search follows that boundary rather than a
      device label.

   2. The 1320-1499 dip is NOT caused by search placement. Above 1320 the
      Legend/Basemap/Help labels are still rendered, so the actions are wide and
      `flex: 1 1 320px; min-width: 0` makes the search absorb every pixel of the
      shortfall. That is why 1366 (262px) is more cramped than 1280 (420px).
      Fixing it means moving the `.clear-action-label` collapse breakpoint,
      which is navigation behaviour, not search placement. REPORTED, NOT
      CHANGED — see drift D-25. A second breakpoint here would flip the search
      between header and canvas twice on the way down, and would hand a 1366px
      laptop the constrained treatment while a smaller 1280px laptop kept the
      desktop one.

   3. Removing the header stub does NOT on its own take tier 2 back inside the
      viewport at every narrow width, and an earlier version of this comment
      claimed it did. It does at 768 and 700, where the 26px stub plus its 14px
      gap was the whole shortfall. Below that the row still overflows, because
      `.clear-tier2-actions` needs 411px by itself -- five 38px icon buttons,
      40px of gaps and a 181px user chip -- against an irreducible tier-2 content
      width of 602px. Measured after this pass: 0 at 768 and 700, then 2 / 122 /
      188 / 212 / 242 at 600 / 480 / 414 / 390 / 360. That is a pre-existing
      header capacity defect with no search component. REPORTED, NOT CHANGED --
      see drift D-26.

   The two queries below are exact complements, so "never both" and "never
   neither" are structural rather than asserted, and both are media queries so
   the state is correct before JS runs — this shell never places the search
   from script. `display: none` (not visibility/opacity) is deliberate: the
   hidden input must leave the accessibility tree and the tab order, or a
   screen-reader or keyboard user still meets two searches.
   ========================================================================== */

/* DESKTOP / LARGE LAPTOP — the header hosts the search; the canvas one is gone. */
@media (min-width: 1121px) {
  .clear-canvas-search-row { display: none; }
}

/* TABLET / MOBILE / CONSTRAINED — the canvas hosts the search; the header one is gone. */
@media (max-width: 1120px) {
  .clear-tier2 .clear-search { display: none; }

  /* The canvas bar is now the ONLY search, so it stops being a 204px shrink-to-fit
     chip and takes over the header search's own size contract instead: grow with
     the space available, but never past the 420px `.clear-search` is itself capped
     to. Nothing here is a new constant — 420px is that cap, and the 12px gutters
     are measured off mockups/04-commercial-phone-collapsed.png (780px at DPR 2, so
     390 CSS px: card edges at 12px and 378px, 366px wide, 40px tall).

     One rule rather than a phone-specific second one, because two would not be
     monotonic: a 700px landscape phone would get a wider bar than a 768px tablet.
     At 390 this resolves to exactly the mockup's 366px, and it is 420px from 480px
     upward — the same width the control has in the header at 1200px and above, so
     the search keeps its size and only changes surface.

     `width: auto` and `max-width` both have to be restated: the base rule pins
     width to 240px and caps it at `calc(100% - 36px)`, and that percentage
     resolves against the absolutely-positioned row's own shrink-to-fit width,
     which silently clamped a declared 320px down to a rendered 284px. */
  .clear-canvas-search-row { left: 12px; right: 12px; }
  .clear-canvas-search { width: auto; max-width: 420px; }
}

/* The vertical offset stays at the 16px this stylesheet uses for all canvas chrome.
   The mockup places the bar 1px below the header's bottom border, which welds a
   bordered card to another border and reads as a rendering artefact rather than as
   intent; 16px also keeps the bar clear of the Environmental Status card at top:70px.
   That single deviation from the mockup is recorded in visual-validation.md so the
   operator can redirect it at Gate B. */

/* =============================================================================
   33. FCLEAR-APP-0002C — SEARCH RESULTS POPUP.

   One popup style serving BOTH placements settled by FCLEAR-APP-0002A: the tier-2
   header search at >=1121px and the map-canvas search at <=1120px. The popup is a
   sibling of whichever `<label>` wraps the input, so it anchors to the input the
   user is actually typing in without either placement needing its own component.

   Anchoring works because the two containers already establish the right
   positioning context: `.clear-tier2` is a flex row in normal flow, and
   `.clear-canvas-search-row` is absolutely positioned over the map. Making the
   label the containing block in both cases keeps one rule instead of two.
   ========================================================================== */

/* ONLY the header label. `.clear-canvas-search-row` is deliberately left alone: FCLEAR-APP-0002A
   positions it `absolute` with `left: 12px; right: 12px` to hit the measured mockup gutters, and
   an absolutely-positioned element is ALREADY a containing block for absolutely-positioned
   descendants. Adding `position: relative` here overrode that `absolute`, the left/right pair
   stopped sizing the row, and the phone search bar's right edge moved from 378px to 402px --
   twelve pixels off the right edge of a 390px viewport. Caught by the 0002A runtime placement
   suite, which is exactly what it is for. */
/* Both LABELS are the containing block for their own popup, which is appended inside them.
   `.clear-canvas-search-row` is deliberately NOT touched: FCLEAR-APP-0002A positions that row
   `absolute` with `left: 12px; right: 12px` to hit the measured mockup gutters, and overriding
   its `position` moved the phone search bar's right edge from 378px to 402px -- off the edge of a
   390px viewport. The label inside it is a static flex item, so making it relative is free. */
.clear-tier2 .clear-search,
.clear-canvas-search { position: relative; }

/* The popup's own z-index is not enough on the canvas.
   `.clear-canvas-search-row` is absolutely positioned with `z-index: 5`, which makes it a
   STACKING CONTEXT: the popup's `z-index: 40` ranks it against its siblings inside that row, not
   against the rest of the map chrome. The Environmental Status card is also `z-index: 5` and
   comes later in the DOM, so at 1120px it painted on top of the first result and made it
   unclickable -- caught by hit-testing, not by any DOM assertion.
   Raising the ROW lifts the whole search context above the other canvas cards. Only the stacking
   is changed here; FCLEAR-APP-0002A's `position`, `left` and `right` on this row are untouched,
   because those are what hold the measured mockup gutters. */
.clear-canvas-search-row { z-index: 40; }

.clear-search-results {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
  z-index: 40; /* above the map canvas chrome (z-index 5) and the pane overlay's shadow */
  margin: 0;
  padding: 4px;
  list-style: none;
  max-height: 320px;
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  box-shadow: var(--sh-3);
}
.clear-search-results[hidden] { display: none; }

/* The header search is a flex item, so its popup needs a width to resolve against;
   the canvas row is already sized by its own left/right gutters. */
.clear-tier2 .clear-search .clear-search-results { min-width: 320px; }

.clear-search-result {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 8px 10px;
  border-radius: var(--r-sm, 6px);
  cursor: pointer;
}

/* Hover and keyboard share ONE visual state. A separate hover colour would let the
   pointer and the arrow keys disagree about which row is current, which is exactly
   the ambiguity a combobox must not have. */
.clear-search-result:hover,
.clear-search-result.is-active {
  background: var(--surface-2);
}
.clear-search-result.is-active {
  outline: 2px solid var(--focus);
  outline-offset: -2px;
}

.clear-search-result-name {
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
  /* Governed names run long. Clip to one line rather than reflowing the row height,
     so arrow-key travel stays predictable. */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.clear-search-result-meta {
  font-size: 11.5px;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Touch targets. 44px is the floor the phone refinements already adopted for the
   peek controls, and a result row is the primary target on a phone. */
@media (max-width: 767px) {
  .clear-search-result { padding: 11px 10px; }
  .clear-search-results { max-height: 60vh; }
}

@media (prefers-reduced-motion: reduce) {
  .clear-search-results { scroll-behavior: auto; }
}


/* ============================================================================================
   34. FCLEAR-APP-0002B — Gate B correction pass, Lane A.

   Every item below was raised by the operator against the RUNNING product. Sources of truth:
   the Revision 2 icon authority (`icons/defs.py` in the design package) for glyph geometry, and
   the existing `.layer-*` / `iconColor` values for colour, which are NOT redefined here --
   provenance colour and icon geometry are governed separately and stay that way.
   ============================================================================================ */

/* --- 34.1 The tab row must read as two groups, not one run-on phrase ------------------------ */
/* `Overview Air Quality [mark] pulm.ai & Evidence` ran together as a single sentence. Two
   changes, both purely spatial: a real gap between the analytical tabs, and the merged pulm.ai
   tab pushed to the END of the row with an auto margin so it cannot be read as a third word of
   "Overview Air Quality".

   THIS MUST NOT REINTRODUCE F-02's OVERFLOW. Measured on the base image, the three tabs need
   62.89 + 71.25 + 146.27 = 280.41px of content plus 12px of strip padding = 292.41px, inside a
   strip that is 413px at every desktop gate from 1440 down to 768 and 375px at the narrowest
   phone. A 14px gap costs 14px once (the auto margin absorbs the second gap), taking the
   requirement to 306.41px -- still 68.59px inside the narrowest measured strip. `flex: 0 1 auto`
   from 26.2 is untouched, so if a future translation ever did exceed the row the tabs still
   shrink rather than clip the strip.

   The auto margin is a MARGIN, not `justify-content`, so it degrades correctly: when there is no
   free space it collapses to zero and the phone strip's `overflow-x: auto` (section 20) still
   scrolls. Keyboard order, roving focus, `aria-selected` and the active underline are untouched. */
.clear-pane-tabs { gap: 14px; }
.clear-pane-tab-pulmai { margin-left: auto; }

/* --- 34.2 Left rail: governed glyphs, not coloured dots ------------------------------------- */
/* Supersedes 23 (WS8 #7), which replaced 24px letter badges with a 9px dot and hid the row's
   `<svg>` outright. The operator's Gate B finding is that the rail must speak the same icon
   vocabulary as the map and the layer list, so the badge returns -- at the rail's own compact
   scale, carrying the governed glyph rather than a letter. The letter badges WS8 objected to do
   not come back: there is no text in these badges at all. */
.clear-layer-icon {
  width: 17px; height: 17px; min-width: 17px;
  border-radius: 5px;
  padding: 0; border: 0;
  overflow: visible;
  font-size: 0; line-height: 0;
  display: inline-flex; align-items: center; justify-content: center;
  color: #fff;
}
.clear-layer-icon svg { display: block; width: 11px; height: 11px; fill: currentColor; }

/* --- 34.3 Selected entity icon replaces the letter badge ------------------------------------ */
/* The pane header showed a generic letter ("H"). It now carries the governed glyph for the
   feature's real class. `is-neutral` is the honest fallback for an unknown or ungoverned class
   and for the pre-selection state: `glyph-place`, the design package's generic located-thing
   marker, in the package's neutral badge colour. It is never a claim about what the feature is.
   Colour for a GOVERNED class is still written inline by the renderer, from the same values the
   map markers use, so the header and the map cannot drift apart. */
.clear-pane-identity-icon svg { display: block; width: 19px; height: 19px; fill: currentColor; }
.clear-peek-icon svg { display: block; width: 17px; height: 17px; fill: currentColor; }
.clear-pane-identity-icon.is-neutral,
.clear-peek-icon.is-neutral { background: #5E7387; }

/* --- 34.4 VISIBLE LAYERS is a controlled panel with ONE state model ------------------------- */
/* Three defects, all reported against the running product:
     1. the box sat at `bottom: 18px`, directly on top of the MapLibre scale bar and attribution,
     2. it was visible while the Legend button rendered inactive,
     3. clicking Legend did nothing.

   `workspace.dataset.clearLegendOpen` is now the only state. The panel's `hidden`, the button's
   `aria-pressed` and its `aria-expanded` are all written from it by `clearShellSetLegendOpen`,
   and nothing else writes any of the three. `display: none` for the narrow band was deleted from
   27.5 for exactly that reason -- it was a second model the button could not read.

   The vertical offset is MEASURED, not guessed: `clearShellUpdateLegendOffset` publishes
   `--clear-legend-bottom` from the real height of `.maplibregl-ctrl-bottom-left`, which is where
   ScaleControl and AttributionControl are added (`clear_map.js:8297-8298`), plus the same
   `--clear-map-ctrl-bottom` inset the controls themselves follow. The fallback covers the window
   before the first measurement. */
.clear-legend-card {
  bottom: var(--clear-legend-bottom, 92px);
  max-height: calc(100% - var(--clear-legend-bottom, 92px) - 14px);
  overflow-y: auto;
}
.clear-legend-card[hidden] { display: none; }

/* =============================================================================
   pulm.ai ENVIRONMENTAL ASSESSMENT — map overlay (FCLEAR-APP-0009)

   An independent viewport-level layer over the lower map, NOT a pane tab and not
   anchored to the selected feature. The map stays dominant: the compact state is
   a single short card and the overlay never spans the viewport.

   POSITION IS MEASURED, NOT ASSUMED. Three custom properties are published by
   `clearShellUpdateAssessGeometry` from real element rectangles:

     --clear-assess-bottom  from the top of whichever bottom-band control sits
                            under the overlay (attribution, scale bar, coordinate
                            pill), so it can never cover any of them
     --clear-assess-left    from the right edge of the legend card when open
     --clear-assess-right   from the left edge of the analytical pane when the
                            pane overlays the canvas

   Every fallback below is the CONSERVATIVE value — larger insets than measurement
   will produce — because the window between first paint and first measurement must
   not put the card on top of the attribution. Same rule as
   `--clear-legend-bottom`.
   ========================================================================== */
.clear-assess {
  position: absolute;
  z-index: 6;                      /* above the watermark (4) and the cards (5) */
  left: var(--clear-assess-left, 232px);
  right: var(--clear-assess-right, 232px);
  bottom: var(--clear-assess-bottom, 104px);
  margin-inline: auto;
  /* WIDTH IS THE BAND, capped. Both insets are set and measured, so `width: auto` makes the box
     exactly the free space between the legend and the analytical pane; `max-width` caps it and
     `margin-inline: auto` centres what is left over.
     Neither of the two obvious alternatives is correct here. `fit-content` shrank the card to its
     content -- 540px of an available 788 -- and a 29-word interpretation wrapped to three lines.
     `width: 100%` resolves against the CONTAINING BLOCK rather than against the inset band, which
     silently discards the right inset: measured at Denver Health, the card ran 208px underneath
     the expanded analytical pane and the pane intercepted the click on "View assessment". */
  width: auto;
  min-width: 0;
  /* §2's target is roughly 600-780px wide and 70-110px tall in the default state at 1440px. The
     width is a max, not a fixed size: the card is centred in the space between the legend and the
     analytical pane, both measured, so on a narrower free band it shrinks rather than colliding. */
  max-width: min(760px, 100%);
  border-radius: var(--r-md);
  background: var(--surface, #fff);
  border: 1px solid var(--line, #dce4ea);
  box-shadow: var(--sh-3);
  overflow: hidden;

  /* FCLEAR-APP-0012A. THE SURFACE IS BOUNDED BY THE VIEWPORT, NOT BY ITS CONTENT.
     ---------------------------------------------------------------------------
     This box is bottom-anchored and had no `top` and no `max-height`, so its height was whatever
     its content wanted and it grew UPWARD off the top of the screen. Measured before the fix, at
     Children's Hospital Colorado: 2627px tall with its top at y=-1636 at 1920x1080, and 3050px
     tall at y=-2371 at 1366x768. The header and the collapse control were both off-screen.

     `--clear-assess-max-h` is published by `clearShellUpdateAssessGeometry` from the MEASURED
     application chrome and the measured bottom obstacle band, so the bound follows the real layout
     rather than an assumption about it. The calc() here is the fallback for the window between
     bind and first measure, and uses dvh so a mobile browser's collapsing toolbar cannot make the
     surface taller than the visible area. */
  max-height: var(--clear-assess-max-h, calc(100dvh - 168px));
  /* Column layout is what pins the header and gives the body the remaining height to scroll in.
     Without it, `max-height` alone would simply clip the overflow that `overflow: hidden` hides. */
  display: flex;
  flex-direction: column;
}
/* Wide desktop only. Below the breakpoint the overlay does not exist as a surface
   at all, so narrow and mobile behaviour is unchanged by construction rather than
   by a JS guard that could be reached in the wrong order. */
.clear-assess { display: none; }
.clear-workspace[data-clear-assess-wide="1"] .clear-assess { display: flex; }
.clear-assess[hidden] { display: none !important; }

/* FCLEAR-APP-0012A. The header never scrolls away. `flex: 0 0 auto` in the column pins it, and
   `position: sticky` is belt and braces for any future layout that is not the column. It is opaque
   so scrolled content cannot show through it. */
.clear-assess__head {
  flex: 0 0 auto;
  position: sticky;
  top: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 7px 12px;
  border-bottom: 1px solid var(--line, #dce4ea);
  background: linear-gradient(180deg, rgba(18, 102, 163, .06), rgba(18, 102, 163, 0)),
              var(--surface, #fff);
}
.clear-assess__mark { flex: 0 0 auto; display: block; }
.clear-assess__brand {
  flex: 0 0 auto;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .01em;
  color: var(--ink, #16242f);
}
/* "· Environmental Assessment", appended only when there is an assessment to name,
   so the loading state reads as pulm.ai working rather than as a finished panel. */
.clear-assess__title {
  /* The title never shrinks. At a 540px band the header holds the mark, the brand, this title,
     the freshness stamp and the button, and the total wants ~566px -- so something must give. It
     must not be the title: measured at Denver Health it read "· Environmental As…", which is the
     one string on the header that names what the reader is looking at. The timestamp is metadata
     and yields instead. */
  flex: 0 0 auto;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .02em;
  color: var(--muted, #5b6b7a);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.clear-assess__title:empty { display: none; }
.clear-assess__x {
  margin-left: auto;
  flex: 0 0 auto;
  width: 24px;
  height: 24px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: var(--muted, #5b6b7a);
  cursor: pointer;
}
.clear-assess__x svg { width: 14px; height: 14px; }
.clear-assess__x:hover { background: var(--clear-blue-soft, #eef5fb); color: var(--ink, #16242f); }
.clear-assess__x:focus-visible { outline: 2px solid var(--clear-blue, #1266a3); outline-offset: 1px; }
.clear-assess__x[hidden] { display: none; }

/* FCLEAR-APP-0012A. The DETAIL body is the scroll container, and it is the only one.
   `.clear-assess__full` already scrolled the model's prose, but every deterministic section added
   since -- actions, confidence, disclosure, navigation, footer and the whole AIR TOXICS domain --
   is a SIBLING of it and was therefore unbounded. Making the state panel itself the scroller means
   a section added in future is inside the bound by construction rather than by remembering to nest
   it. `min-height: 0` is required for a flex child to be allowed to shrink below its content. */
.clear-assess__b {
  padding: 10px 12px 11px;
  min-width: 0;
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
}


/* THE COLLAPSED STRIP.
   Target height 85-125px at 1440px. The previous layout was a two-column flex row whose right
   column held one button and one timestamp; that column reserved horizontal space it never used
   and forced the left column to wrap, which is where most of the 318px height came from. The
   button now sits on the header row and this is a single column with a tight vertical rhythm.
   Every gap below is a `margin-top` on the following element, so an element that is hidden costs
   no space at all -- the industry line and the action are both conditional. */
.clear-assess__b--strip {
  display: block;
  padding: 7px 12px 8px;
  /* FCLEAR-APP-0012A. The detail body scrolls; the collapsed strip is short by design and must
     never grow a scrollbar or shrink below its content. */
  flex: 0 0 auto;
  overflow: visible;
}
.clear-assess__b--strip > * { margin: 0; }
.clear-assess__b--strip > * + * { margin-top: 4px; }

/* §15's ACTION + POLLUTANTS row: the two share the width instead of stacking. `align-items:
   center` keeps a one-line action vertically aligned with the chip row, and the chips are pushed
   to the end so they read as a status strip rather than as a continuation of the sentence. */
.clear-assess__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 4px 12px;
}
.clear-assess__row > .clear-assess__act { flex: 1 1 auto; min-width: 0; }
.clear-assess__row > .clear-assess__chips { flex: 0 0 auto; }
.clear-assess__b--strip > [hidden] { display: none; }

/* PLACE. Small and quiet: the reader clicked it, so it confirms rather than announces. */
.clear-assess__b--strip .clear-assess__place {
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .01em;
  color: var(--muted, #5b6b7a);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* §3 PRIMARY INTERPRETATION. The largest text on the strip, because it is the answer. */
.clear-assess__interp {
  font-size: 12.5px;
  line-height: 1.36;
  color: var(--ink, #16242f);
}

/* §5 PRIMARY ACTION. Title and reason are separate elements with a real boundary between them,
   which is what stops "Compare nearby monitorsPollutants here...". The reason wraps onto its own
   line at any width rather than depending on inline spacing surviving. */
.clear-assess__act {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 2px 6px;
  padding: 3px 7px;
  border-radius: 5px;
  background: var(--clear-blue-soft, #eef5fb);
  border: 1px solid rgba(20, 86, 127, .12);
}
.clear-assess__act[hidden] { display: none; }
.clear-assess__act-label {
  font-size: 12px;
  font-weight: 800;
  color: #14567f;
}
.clear-assess__act-why {
  font-size: 11px;
  line-height: 1.35;
  color: var(--clear-ink-3, #5b6472);
}
.clear-assess__act-why:empty { display: none; }

/* §9 NEARBY CONTEXT. One line, and only when the composition is materially notable. */
.clear-assess__ind {
  font-size: 11px;
  line-height: 1.35;
  color: var(--clear-ink-3, #5b6472);
}
.clear-assess__ind[hidden], .clear-assess__ind:empty { display: none; }

/* FCLEAR-APP-0012. THE ONE TOXICS CONTEXT LINE ON THE COLLAPSED STRIP.
   Same 11px metadata treatment as the nearby-context line above it, deliberately: it is context
   of the same weight and must not read as a headline or as a live reading. It is a single short
   line, so the strip grows by at most one 15px line and only when there is toxics evidence to
   report. No chip, no tone, no colour that could imply a severity CLEAR cannot assign. */
.clear-assess__tox {
  font-size: 11px;
  line-height: 1.35;
  color: var(--clear-ink-3, #5b6472);
}
.clear-assess__tox[hidden], .clear-assess__tox:empty { display: none; }

/* FCLEAR-APP-0012A. THE EXPANDED SURFACE AS AN INTERPRETATION LAYOUT.
   Sections are separated by a rule and a consistent rhythm rather than by nesting depth, so the
   reader sees six short blocks instead of one long document. Record-level detail lives inside
   <details> and costs nothing until it is opened. */
.clear-assess__sec {
  margin-top: 10px;
  padding-top: 9px;
  border-top: 1px solid var(--clear-line-2, #e3e8ee);
}
.clear-assess__sec:first-of-type { margin-top: 2px; padding-top: 0; border-top: 0; }
.clear-assess__sec[hidden] { display: none; }
.clear-assess__sec > h4 {
  margin: 0 0 5px;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--clear-ink-2, #33404f);
}
/* The lede is the one sentence a reader must not miss, so it is the only thing here set larger
   than the body. Everything else is deliberately quieter. */
.clear-assess__lede {
  margin: 0 0 5px;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--clear-ink-1, #1d2733);
}
.clear-assess__sub {
  margin: 0 0 4px;
  font-size: 11.5px;
  line-height: 1.45;
  color: var(--clear-ink-3, #5b6472);
}
.clear-assess__sub:empty { display: none; }
/* A caveat is not decoration. It carries the statement that stops a reader over-reading the
   number above it, so it is always rendered and never behind a disclosure. */
.clear-assess__caveat {
  margin: 0 0 5px;
  font-size: 10.5px;
  line-height: 1.4;
  color: var(--clear-ink-3, #5b6472);
  font-style: italic;
}
.clear-assess__caveat:empty { display: none; }
.clear-assess__act--detail { display: block; margin-top: 6px; }
.clear-assess__act--detail .clear-assess__basis { display: block; }

/* AIR TOXICS: four rows, still visibly distinct, each one summary-first. */
.clear-assess__tox-domain[hidden] { display: none; }
.clear-assess__tox-row {
  margin: 0 0 9px;
  padding-left: 8px;
  border-left: 2px solid var(--clear-line-2, #e3e8ee);
}
.clear-assess__tox-row[hidden] { display: none; }
.clear-assess__tox-row h5 {
  margin: 0 0 3px;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--clear-ink-2, #33404f);
}
.clear-assess__tox-head {
  margin: 0 0 3px;
  font-size: 12px;
  line-height: 1.45;
  color: var(--clear-ink-1, #1d2733);
}
.clear-assess__tox-head:empty { display: none; }
.clear-assess__tox-permit {
  margin: 4px 0 0;
  font-size: 11px;
  line-height: 1.4;
  color: var(--clear-ink-3, #5b6472);
}
.clear-assess__tox-permit:empty { display: none; }
.clear-assess__tox-list { margin: 4px 0 0; padding-left: 14px; list-style: disc; }
.clear-assess__tox-list:empty { display: none; }
.clear-assess__tox-list li { margin-bottom: 4px; font-size: 11px; line-height: 1.4; }
.clear-assess__tox-primary { display: block; color: var(--clear-ink-1, #1d2733); }
.clear-assess__tox-meta {
  display: block;
  font-size: 10px;
  line-height: 1.35;
  color: var(--clear-ink-3, #5b6472);
}
.clear-assess__tox-meta:empty { display: none; }

/* DISCLOSURE. Native <details>: keyboard-operable and screen-reader-announced without script, and
   its closed height is one line. The marker is styled as a control so it reads as pressable. */
.clear-assess__disc { margin: 5px 0 0; }
.clear-assess__disc[hidden] { display: none; }
.clear-assess__disc > summary {
  cursor: pointer;
  font-size: 11px;
  font-weight: 600;
  color: var(--clear-accent, #14567f);
  padding: 3px 0;
  list-style: revert;
}
.clear-assess__disc > summary:focus-visible {
  outline: 2px solid var(--clear-accent, #14567f);
  outline-offset: 2px;
  border-radius: 3px;
}
.clear-assess__disc[open] > summary { margin-bottom: 4px; }
.clear-assess__disc-note {
  margin: 6px 0 0;
  font-size: 10px;
  line-height: 1.35;
  color: var(--clear-ink-3, #5b6472);
}

/* A COMPACT TABLE, not a spreadsheet. Six narrow columns scroll horizontally inside the surface
   rather than forcing the surface itself wider. */
.clear-assess__tbl { display: block; overflow-x: auto; }
.clear-assess__tr {
  display: grid;
  grid-template-columns: minmax(96px, 1.3fr) minmax(88px, 1fr) minmax(78px, .8fr)
                         minmax(56px, .6fr) minmax(96px, 1.2fr) minmax(60px, .6fr);
  gap: 6px;
  padding: 3px 0;
  border-bottom: 1px solid var(--clear-line-2, #eef2f6);
}
.clear-assess__tr--h .clear-assess__td {
  font-weight: 700;
  color: var(--clear-ink-2, #33404f);
  text-transform: uppercase;
  letter-spacing: .03em;
  font-size: 9.5px;
}
.clear-assess__td {
  font-size: 10.5px;
  line-height: 1.35;
  color: var(--clear-ink-1, #1d2733);
  min-width: 0;
  overflow-wrap: anywhere;
}

.clear-assess__tox-limits { margin: 4px 0 0; padding-left: 14px; list-style: disc; }
.clear-assess__tox-limits li {
  margin-bottom: 2px;
  font-size: 10px;
  line-height: 1.35;
  color: var(--clear-ink-3, #5b6472);
}

/* The freshness line lives on the header row now: it is metadata, and a row of its own for one
   timestamp was 14px plus a gap on every card. */
.clear-assess__head .clear-assess__fresh {
  margin-left: auto;
  flex: 0 1 auto;
  min-width: 0;
  font-size: 10px;
  color: var(--muted, #5b6b7a);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.clear-assess__head .clear-assess__fresh:empty { display: none; }
/* With the timestamp claiming `margin-left: auto`, the button no longer needs to. */
.clear-assess__head .clear-assess__go { margin-left: 0; }

/* §2/§18: present, but not visually dominant. A text affordance on the header row, not a
   filled button competing with the interpretation. */
.clear-assess__head .clear-assess__go {
  margin-left: auto;
  flex: 0 0 auto;
  border: 0;
  background: transparent;
  padding: 2px 4px;
  border-radius: 5px;
  font-size: 11px;
  font-weight: 700;
  color: var(--clear-blue, #1266a3);
  cursor: pointer;
  white-space: nowrap;
}
.clear-assess__head .clear-assess__go[hidden] { display: none; }
.clear-assess__head .clear-assess__go:hover { background: var(--clear-blue-soft, #eef5fb); }
.clear-assess__head .clear-assess__go:focus-visible {
  outline: 2px solid var(--clear-blue, #1266a3);
  outline-offset: 1px;
}
/* The close button keeps its place at the far right when both are present. */
.clear-assess__head .clear-assess__go + .clear-assess__x { margin-left: 4px; }

/* §4 POLLUTANT STATE ROW. One badge per governed pollutant, band word only. */
.clear-assess__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}
.clear-assess__chips:empty { display: none; }
.clear-assess__chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  border-radius: 999px;
  padding: 2px 7px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .01em;
  border: 1px solid transparent;
  white-space: nowrap;
}
.clear-assess__chip::before {
  content: "";
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: currentColor;
  flex: 0 0 auto;
}
/* The pollutant name reads first; its band is quieter, because the row is for orientation. */
.clear-assess__chip b { font-weight: 800; }
.clear-assess__chip i { font-style: normal; font-weight: 600; opacity: .8; }
/* SUBTLE emphasis on the notable chip -- a ring, not a colour change. Severity comes from the
   band; this only says "this is the one the sentence above is about". */
.clear-assess__chip[data-notable="1"] {
  box-shadow: 0 0 0 2px rgba(18, 102, 163, .16);
}
.clear-assess__chip[data-tone="calm"]     { background: var(--clear-green-soft, #e8f6ee); color: #137448; border-color: rgba(19, 116, 72, .18); }
.clear-assess__chip[data-tone="watch"]    { background: #fdf3e0; color: #8a5a05; border-color: rgba(138, 90, 5, .18); }
.clear-assess__chip[data-tone="caution"]  { background: #fdeceb; color: #a5321f; border-color: rgba(165, 50, 31, .20); }
.clear-assess__chip[data-tone="alert"]    { background: #f6e6f2; color: #7a1d5c; border-color: rgba(122, 29, 92, .20); }
.clear-assess__chip[data-tone="none"]     { background: #f2f5f7; color: #5b6b7a; border-color: rgba(91, 107, 122, .18); }

/* WHAT YOU CAN DO NOW, in the expanded detail. */
.clear-assess__actions { margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--line, #dce4ea); }
.clear-assess__actions[hidden] { display: none; }
.clear-assess__actions h4 { margin: 0 0 6px; font-size: 11.5px; font-weight: 800; color: var(--ink, #16242f); letter-spacing: .01em; }
.clear-assess__actions ul { margin: 0; padding: 0; list-style: none; display: grid; gap: 6px; }
.clear-assess__actions li { display: grid; gap: 2px; }
.clear-assess__action-label { font-size: 12px; font-weight: 700; color: var(--ink, #16242f); }
.clear-assess__action-why { font-size: 11px; line-height: 1.4; color: var(--muted, #5b6b7a); }
.clear-assess__basis { margin: 8px 0 0; font-size: 10.5px; line-height: 1.45; color: var(--faint, #8598a6); }
.clear-assess__basis:empty { display: none; }

/* §11: an action is a title and a supporting sentence on separate lines with real spacing, at
   every width. The grid above already gives each `li` two rows; these guard the case the defect
   actually came from -- an empty or missing reason must not close the gap between two actions,
   and a long reason must wrap rather than push the next label onto the same visual line. */
.clear-assess__actions li + li { margin-top: 2px; }
.clear-assess__action-label { display: block; }
.clear-assess__action-why { display: block; overflow-wrap: anywhere; }
.clear-assess__action-why:empty { display: none; }

/* §13: the public statement of the confidence limitation, above the strict disclosure. */
.clear-assess__conf {
  margin: 10px 0 0;
  font-size: 11.5px;
  line-height: 1.45;
  color: var(--ink, #16242f);
}
.clear-assess__conf:empty { display: none; }

/* §6/§10: SECONDARY NAVIGATION. After the content, visually lighter than an action, and never
   under the "What you can do now" heading. A row of quiet links, not a stack of buttons. */
.clear-assess__links {
  margin-top: 10px;
  padding-top: 9px;
  border-top: 1px solid var(--line, #dce4ea);
  display: flex;
  flex-wrap: wrap;
  gap: 4px 14px;
}
.clear-assess__links[hidden], .clear-assess__links:empty { display: none; }
.clear-assess__nav {
  border: 0;
  background: transparent;
  padding: 3px 0;
  font-family: inherit;
  font-size: 11px;
  font-weight: 700;
  color: var(--clear-blue, #1266a3);
  cursor: pointer;
  white-space: nowrap;
}
.clear-assess__nav:hover { text-decoration: underline; text-underline-offset: 2px; }
.clear-assess__nav:focus-visible {
  outline: 2px solid var(--clear-blue, #1266a3);
  outline-offset: 2px;
  border-radius: 3px;
}

/* "View evidence" is a link-styled button because it LEAVES the overlay for the pane tab, and
   that must not look like the primary action of the card. */
.clear-assess__link {
  border: 0;
  background: transparent;
  padding: 5px 2px;
  font-family: inherit;
  font-size: 11.5px;
  font-weight: 700;
  color: var(--clear-blue, #1266a3);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 2px;
}
.clear-assess__link:focus-visible { outline: 2px solid var(--clear-blue, #1266a3); outline-offset: 2px; }
.clear-assess__b[hidden] { display: none; }

.clear-assess__place {
  margin: 0 0 5px;
  font-size: 12.5px;
  font-weight: 700;
  line-height: 1.3;
  color: var(--ink, #16242f);
}
.clear-assess__place:empty { display: none; }

.clear-assess__prompt,
.clear-assess__wait {
  margin: 0;
  font-size: 12px;
  line-height: 1.45;
  color: var(--muted, #5b6b7a);
}
/* The working indicator. Text first: the panel must not animate under reduced
   motion, and a reader who cannot see a pulse must still be told what is
   happening. Mirrors `.pv-synth__busy` in clear_pulmai.css. */
.clear-assess__wait::before {
  content: "";
  display: inline-block;
  width: 7px;
  height: 7px;
  margin-right: 7px;
  vertical-align: baseline;
  border-radius: 50%;
  background: var(--clear-blue, #1266a3);
  animation: clear-assess-pulse 1.4s ease-in-out infinite;
}
@keyframes clear-assess-pulse { 0%, 100% { opacity: .30; } 50% { opacity: 1; } }

/* FCLEAR-APP-0012B / Loop F. THE TYPED STATE SENTENCE.

   Same size and colour as the prompt and the waiting line, and deliberately NOT
   `.clear-assess__wait`: that class carries the pulsing dot, which says "something is still
   happening". FACTS_AVAILABLE, NO_GOVERNED_EVIDENCE and TECHNICAL_FAILURE are all settled
   answers, and animating them would tell a reader to keep waiting for something that is not
   coming. PROCESSING keeps the pulse, because for PROCESSING it is true. */
.clear-assess__note {
  margin: 0;
  font-size: 12px;
  line-height: 1.45;
  color: var(--muted, #5b6b7a);
  overflow-wrap: anywhere;
}
.clear-assess__note:empty { display: none; }
/* Navigation under NO_GOVERNED_EVIDENCE is the one affordance that state has, so it is separated
   from the sentence above it rather than reading as a continuation of it. */
.clear-assess__b[data-clear-assess-state="no-evidence"] .clear-assess__links { margin-top: 7px; }

.clear-assess__sum {
  margin: 0;
  font-size: 12px;
  line-height: 1.45;
  color: var(--ink, #16242f);
  overflow-wrap: anywhere;
  /* Clamped so a long derived summary cannot grow the strip past the height the map budget
     allows. The summary is already bounded at 70 words server-side; this is the second guard, and
     the full text is always one click away in the detail view. */
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
/* The governed confidence sentence. Present and whole, never paraphrased, and
   de-emphasised so it qualifies the summary without crowding it. */
.clear-assess__qual {
  margin: 7px 0 0;
  font-size: 11px;
  line-height: 1.45;
  color: var(--muted, #5b6b7a);
}
.clear-assess__qual:empty { display: none; }

.clear-assess__foot {
  margin-top: 9px;
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}
.clear-assess__go {
  flex: 0 0 auto;
  border: 1px solid var(--clear-blue, #1266a3);
  border-radius: 999px;
  padding: 5px 12px;
  background: var(--clear-blue, #1266a3);
  color: #fff;
  font-size: 11.5px;
  font-weight: 700;
  font-family: inherit;
  cursor: pointer;
}
.clear-assess__go:hover { filter: brightness(1.06); }
.clear-assess__go:focus-visible { outline: 2px solid var(--brand-ink, #0d2741); outline-offset: 2px; }
.clear-assess__fresh {
  min-width: 0;
  font-size: 10.5px;
  line-height: 1.35;
  color: var(--faint, #8598a6);
}
.clear-assess__fresh:empty { display: none; }

/* DETAIL. Expands in place so the reader stays spatially oriented on the map.
   Bounded by the measured space above the control band and scrolls inside itself,
   so expanding can never push the card over the attribution. */
.clear-assess[data-clear-assess-open="1"] { max-width: min(620px, 100%); }
/* FCLEAR-APP-0012A. The prose no longer carries its own cap. It used to be the only bounded
   region, which produced a scrollbar INSIDE the card while the card itself ran off the screen, and
   a reader had to find and use the inner scroller to read a narrative whose heading they could not
   see. The detail body above is now the single scroll container, so the prose simply flows. */
.clear-assess__full {
  min-width: 0;
}
.clear-assess__full h4 {
  margin: 11px 0 4px;
  font-size: 11.5px;
  font-weight: 800;
  line-height: 1.35;
  letter-spacing: .01em;
  color: var(--ink, #16242f);
}
.clear-assess__full h4:first-child { margin-top: 0; }
.clear-assess__full p {
  margin: 0 0 6px;
  font-size: 12px;
  line-height: 1.5;
  color: var(--ink, #16242f);
  overflow-wrap: anywhere;
}
.clear-assess__full ul { margin: 0 0 6px; padding-left: 16px; }
.clear-assess__full li {
  margin: 0 0 3px;
  font-size: 12px;
  line-height: 1.45;
  color: var(--ink, #16242f);
  overflow-wrap: anywhere;
}
.clear-assess__full > :last-child { margin-bottom: 0; }
.clear-assess__disc {
  margin: 9px 0 0;
  padding-top: 8px;
  border-top: 1px solid var(--line, #dce4ea);
  font-size: 10.5px;
  line-height: 1.45;
  color: var(--muted, #5b6b7a);
}
.clear-assess__disc:empty { display: none; }

@media (prefers-reduced-motion: reduce) {
  .clear-assess__wait::before { animation: none !important; opacity: .85 !important; }
}

/* The Legend button uses the SAME active treatment every other toggling tier-2 action uses
   (section 4, `[aria-pressed="true"]`); it is restated for `aria-expanded` only so a reader of
   this section can see that the two attributes are kept in lockstep, not so a second style
   exists. */
.clear-action[data-clear-legend-button][aria-expanded="true"] {
  background: var(--surface-3);
  border-color: var(--line-strong);
  color: var(--brand-ink);
}


/* =============================================================================
   FIRST-TIME MAP ORIENTATION (FCLEAR-APP-0010 §18-§20)

   Non-blocking by construction: `aria-modal="false"`, no backdrop, no focus trap
   and no pointer-events shield. The map stays pannable underneath while the card
   is up, which is what makes "Explore map" an honest second option rather than
   the only way to reach the product.
   ========================================================================== */
.clear-intro {
  position: absolute;
  z-index: 8;                       /* above the assessment overlay (6) while it is up */
  left: 50%;
  transform: translateX(-50%);
  bottom: 22px;
  width: min(420px, calc(100% - 32px));
}
.clear-intro[hidden] { display: none; }
.clear-intro__card {
  border-radius: var(--r-md);
  background: var(--surface, #fff);
  border: 1px solid var(--line, #dce4ea);
  box-shadow: var(--sh-3);
  overflow: hidden;
}
.clear-intro__brand {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 7px 12px;
  border-bottom: 1px solid var(--line, #dce4ea);
  font-size: 12px;
  font-weight: 800;
  color: var(--ink, #16242f);
  background: linear-gradient(180deg, rgba(18, 102, 163, .06), rgba(18, 102, 163, 0));
}
.clear-intro__step { font-size: 10.5px; font-weight: 700; color: var(--faint, #8598a6); }
.clear-intro__step:empty { display: none; }
.clear-intro__x {
  margin-left: auto;
  width: 24px; height: 24px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 0; border-radius: 6px; background: transparent;
  color: var(--muted, #5b6b7a); cursor: pointer;
}
.clear-intro__x svg { width: 14px; height: 14px; }
.clear-intro__x:hover { background: var(--clear-blue-soft, #eef5fb); color: var(--ink, #16242f); }
.clear-intro__x:focus-visible { outline: 2px solid var(--clear-blue, #1266a3); outline-offset: 1px; }

.clear-intro__b { padding: 12px 13px 13px; }
.clear-intro__b[hidden] { display: none; }
.clear-intro__t { margin: 0 0 5px; font-size: 14px; line-height: 1.25; font-weight: 800; color: var(--ink, #16242f); }
.clear-intro__p { margin: 0; font-size: 12px; line-height: 1.5; color: var(--muted, #5b6b7a); }
.clear-intro__note { margin: 8px 0 0; font-size: 11px; line-height: 1.4; color: var(--faint, #8598a6); }
.clear-intro__note:empty { display: none; }

.clear-intro__row,
.clear-intro__foot { display: flex; align-items: center; gap: 8px; }
.clear-intro__row { margin-top: 11px; }
.clear-intro__foot { padding: 0 13px 13px; justify-content: flex-end; }
.clear-intro__foot[hidden] { display: none; }
.clear-intro__go,
.clear-intro__alt {
  border-radius: 999px;
  padding: 6px 13px;
  font-family: inherit;
  font-size: 11.5px;
  font-weight: 700;
  cursor: pointer;
}
.clear-intro__go { border: 1px solid var(--clear-blue, #1266a3); background: var(--clear-blue, #1266a3); color: #fff; }
.clear-intro__go:hover { filter: brightness(1.06); }
.clear-intro__alt { border: 1px solid var(--line, #dce4ea); background: var(--surface, #fff); color: var(--ink, #16242f); }
.clear-intro__alt:hover { background: var(--clear-blue-soft, #eef5fb); }
.clear-intro__go:focus-visible,
.clear-intro__alt:focus-visible { outline: 2px solid var(--brand-ink, #0d2741); outline-offset: 2px; }

/* Phone: a bottom sheet, full width, clear of the sheet grip. Same card, same copy. */
@media (max-width: 767px) {
  .clear-intro { left: 8px; right: 8px; bottom: 12px; width: auto; transform: none; }
}

/* FCLEAR-APP-0012B / Loop F. The assessment's state announcement: present to assistive technology
   on every state change, absent from the visual design, which already shows the state in the panel
   or in the freshness slot. Same technique as .clear-hg-visually-hidden; kept as its own class so
   a change to one surface cannot silently move the other. */
.clear-assess__sr {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* FCLEAR-APP-0012B / Loop F. The typed state's own row: one sentence, and the one action that can
   help when there is one. Sized as a quiet qualifier rather than as a headline -- the strip's
   interpretation is still the thing to read first, and this says why the narrative is missing. */
.clear-assess__staterow {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 6px 16px 0;
}
.clear-assess__staterow[hidden] { display: none; }
.clear-assess__staterow .clear-assess__note { flex: 1 1 auto; margin: 0; }
.clear-assess__retry {
  flex: 0 0 auto;
  border: 1px solid var(--clear-assess-border, #d9e2ec);
  background: transparent;
  border-radius: 6px;
  padding: 3px 10px;
  font: inherit;
  font-size: 12px;
  cursor: pointer;
  white-space: nowrap;
}
.clear-assess__retry:hover { background: rgba(30, 136, 229, 0.08); }
.clear-assess__retry:focus-visible { outline: 2px solid #1E88E5; outline-offset: 2px; }
.clear-assess__retry[hidden] { display: none; }

/* ============================================================================================
   FCLEAR-APP-0013 Lane C — the ANALYSIS POINT pin and the geocoding disclosure.
   ============================================================================================ */

/* THE PIN (D7).

   IT MUST NOT BE CONFUSABLE WITH ANY ENTITY MARKER, and on this map that is a concrete
   requirement rather than a matter of taste: hospitals, facilities, schools, colleges,
   regulatory monitors and community sensors are ALL drawn as filled round badges carrying a
   registered map image, in six different hues (see addFacilityLayers and the registered
   `clear-*-marker` images). Another coloured disc would read as a seventh kind of place — and
   the whole point of an analysis point is that it is NOT a place CLEAR holds a record for.

   So the pin is not a disc and not a teardrop. It is an open surveyor's reticle: a HOLLOW ring,
   cross hairs running through it and out past its edge, and a small solid core marking the exact
   coordinate. Nothing else on this map is hollow and nothing else has hairs, so it stays
   distinguishable at every zoom, in monochrome, and to a reader who cannot separate the six
   badge hues from one another.

   The core is what sits on the coordinate, which is why the marker is anchored 'center' rather
   than 'bottom' like the badge markers: a reticle floating above its own point would misstate by
   its own height the one thing it exists to state. */
.clear-analysis-pin {
  position: relative;
  width: 38px;
  height: 38px;
  cursor: grab;
  /* The pin is an indicator, not a hit target for the layers underneath: dragging is handled by
     the marker itself, and everything else should reach the map. */
  touch-action: none;
}
.clear-analysis-pin:active { cursor: grabbing; }

.clear-analysis-pin__ring,
.clear-analysis-pin__cross,
.clear-analysis-pin__core {
  position: absolute;
  left: 50%;
  top: 50%;
  display: block;
  transform: translate(-50%, -50%);
  pointer-events: none;
}

/* The hollow ring. The white outer ring is a halo, not decoration: over dark basemap imagery a
   single dark stroke disappears, and the pin has to stay legible on every basemap the estate may
   publish, not only on the one Light style shipped today. */
.clear-analysis-pin__ring {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  border: 2.5px solid #0d66d0;
  box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.95), 0 1px 4px rgba(15, 30, 50, 0.35);
  background: transparent;
}

/* Cross hairs, drawn as one element plus its ::before so the markup stays three spans. */
.clear-analysis-pin__cross,
.clear-analysis-pin__cross::before {
  background: #0d66d0;
  box-shadow: 0 0 0 1.5px rgba(255, 255, 255, 0.9);
}
.clear-analysis-pin__cross {
  width: 2px;
  height: 36px;
  border-radius: 1px;
}
.clear-analysis-pin__cross::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 36px;
  height: 2px;
  border-radius: 1px;
  transform: translate(-50%, -50%);
}

/* The coordinate itself. Deliberately small: it is a point, and a large dot would imply an area
   the analysis does not claim. */
.clear-analysis-pin__core {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #0d66d0;
  box-shadow: 0 0 0 2px #ffffff;
}

@media (prefers-reduced-motion: reduce) {
  .clear-analysis-pin { transition: none; }
}

/* THE GEOCODING DISCLOSURE (D6).

   Anchored to the search control and shown while the reader is in it. It sits BELOW the results
   popup — `--clear-search-list-offset` is published by clear_map.js from the live height of the
   list — so it never displaces a single autocomplete row. Placing it above the list would have
   pushed every result down on every search, address or not, which would have made the common
   interaction worse in order to caption the rare one. */
.clear-search-disclosure {
  position: absolute;
  top: calc(100% + 6px + var(--clear-search-list-offset, 0px));
  left: 0;
  right: 0;
  /* Above the results popup's own z-index (40) so it is never painted under a long list. */
  z-index: 41;
  display: none;
  margin: 0;
  padding: 8px 10px;
  font-size: 11.5px;
  line-height: 1.45;
  color: var(--muted);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  box-shadow: var(--sh-3);
}

/* The header search is a flex item whose popup has no intrinsic width to resolve against, so it
   is given the same floor the results list is given. */
.clear-tier2 .clear-search .clear-search-disclosure { min-width: 320px; }

/* Shown whenever the reader is in the control — which is exactly when they could be about to
   submit an address, and before anything has been sent anywhere. Not a toggle, not a dialog and
   not behind a "learn more": the sentence is simply there at the input. */
.clear-search:focus-within .clear-search-disclosure,
.clear-canvas-search:focus-within .clear-search-disclosure { display: block; }
