/* ============================================================================
 * /assets/your_options_mapbox.css
 * Styles for the /your_options/ National Map modal — Mapbox GL.
 * Tokens align with the existing NF design system (--nf-*) and the
 * A+ mockup at plans/mockups/pin_and_card_mockup.html.
 * ============================================================================ */

:root {
  --nfm-bg:          #080d20;
  --nfm-card:        #131d3d;
  --nfm-card-2:      #0f1834;
  --nfm-ink:         #f3f7ff;
  --nfm-muted:       rgba(224,234,255,.72);
  --nfm-border:      rgba(255,255,255,.14);
  --nfm-border-soft: rgba(255,255,255,.08);
  --nfm-sky:         #4aa3ff;
  --nfm-sel:         #1ed1a9;
  --nfm-sel-2:       #37e8be;
  --nfm-sel-3:       #0e8a6e;
  --nfm-good:        #37c06a;
  --nfm-warn:        #e6a23c;
  --nfm-bad:         #e64444;
  --nfm-violet:      #a37bff;
  --nfm-teal:        #31d3c8;
  --nfm-gold:        #f4c967;
  --nfm-meld1:       #3ea7ff;
  --nfm-meld2:       #7d6bff;
  --nfm-meld3:       #b855d8;
  --nfm-meld4:       #e0418f;
  --nfm-meld5:       #e64444;

  --nfm-cork:        #b88b4a;
  --nfm-cork-2:      #9a713a;
}

/* ---------- Modal ---------- */
.nf-map-backdrop {
  position: fixed; inset: 0; z-index: 99990;
  background: rgba(2,6,23,.65);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  display: none;
  padding: 20px;
  overflow: auto;
}
.nf-map-backdrop[data-open="true"] { display: block; }

/* ---------- Fullscreen toggle button ----------
 * Lives at the top-right of the map stage on the dedicated page. Label
 * swaps "Open Map" ↔ "Close Map" via JS (boot reads the #map hash and
 * applies body.nf-map-page[data-mapview="fullscreen"] which the rules below react
 * to). Sized to 44×44 for WCAG touch on phones; visible at all
 * viewports. */
.nf-map-fs-toggle {
  position: absolute;
  top: 12px;
  right: 12px;
  z-index: 200;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 8px 14px;
  background: #0f172a;
  color: #f8fafc;
  border: 0;
  border-radius: 999px;
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
  box-shadow: 0 8px 18px -4px rgba(2,6,23,.45);
  transition: background 150ms ease, transform 150ms ease;
}
.nf-map-fs-toggle:hover { background: #1e293b; }
.nf-map-fs-toggle:active { transform: scale(0.97); }
.nf-map-fs-toggle:focus-visible { outline: 2px solid #0ea5e9; outline-offset: 2px; }

/* ---------- Fullscreen mode (body.nf-map-page[data-mapview="fullscreen"]) ----------
 * Triggered by the Open Map link's #map hash OR by tapping the toggle
 * button. The modal expands to fill the entire viewport using 100dvh
 * (dynamic viewport height — auto-adjusts for iOS Safari's address bar
 * showing/hiding without us having to listen for resize events).
 * Only the map shell is visible; everything else on the page (hero,
 * "What is...", "How to use..." sections) is below the fixed overlay
 * so the user lands directly in action mode. The toggle button stays
 * visible inside the overlay so the user can collapse back. */
/* !important on these because the page-mode rule at css:56-67
 * (body.nf-map-page .nf-map-backdrop) declares position:static !important
 * to make the dedicated page render in-flow. We need to beat that
 * !important when fullscreen mode is active. */
body.nf-map-page[data-mapview="fullscreen"] .nf-map-backdrop {
  position: fixed !important;
  inset: 0 !important;
  z-index: 99990 !important;
  padding: 0 !important;
  background: var(--nfm-bg) !important;
  overflow: hidden !important;
}
body.nf-map-page[data-mapview="fullscreen"] .nf-map-modal {
  height: 100dvh;
  max-height: 100dvh;
  width: 100%;
  max-width: 100vw;
  margin: 0;
  border-radius: 0;
  box-shadow: none;
}
body.nf-map-page[data-mapview="fullscreen"] .nf-map-grid {
  height: 100dvh;
}
body.nf-map-page[data-mapview="fullscreen"] .nf-map-stage {
  height: 100dvh;
}
body.nf-map-page[data-mapview="fullscreen"] .nf-map-canvas {
  height: 100% !important;        /* beats the clamp() at css:2447 */
  min-height: 100% !important;
  border-radius: 0;
}
/* Lock body scroll while fullscreen so vertical drag on the map stays
 * inside the map rather than scrolling the underlying page. */
body.nf-map-page[data-mapview="fullscreen"] {
  overflow: hidden;
}

/* ---------- Dedicated SEO page mode (body.nf-map-page) ----------
 * On /liver-transplant-waiting-list/ the map IS the page content, not a
 * modal. The HTML pre-sets data-open="true" on the backdrop and these
 * overrides strip the popover styling (fixed position, full-viewport
 * overlay, blur backdrop) so the same modal markup renders in normal
 * page flow. JS bypasses openModal() entirely (no body-scroll lock, no
 * scrollIntoView). Hides the close button and the modal-internal header
 * (the page H1 above already serves that role). */
body.nf-map-page .nf-map-backdrop {
  position: static !important;
  inset: auto !important;
  z-index: auto !important;
  background: transparent !important;
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
  /* 30px gutter on each side so the map card has comfortable breathing room
     from the page edge (was 10px, raised per UAT feedback). */
  padding: 0 30px !important;
  overflow: visible !important;
  display: block !important;
}
body.nf-map-page .nf-map-modal {
  margin: 0 auto;
  max-width: 1600px;
  height: min(80vh, 880px);
}
body.nf-map-page .nf-map-close,
body.nf-map-page .nf-map-header {
  display: none !important;
}

/* Page-mode grid: ALWAYS single-column. Map is full-width regardless of
   deck state. The deck is NOT a rail — it floats over the map as an
   absolute-positioned overlay (see .nf-map-deck rules at the bottom of
   this file). The grid is set to position:relative so the absolute deck
   anchors to its right/top edge. */
body.nf-map-page .nf-map-grid {
  position: relative !important;
  grid-template-columns: 1fr !important;
}
/* Defensive: any legacy splitter element on the new page is hidden. */
body.nf-map-page .nf-map-splitter { display: none !important; }
/* Defensive: legacy nf-map-card / nf-map-card-b slots are sunsetted. If
   any leak in via cached HTML, hide them. The new page's HTML doesn't
   include them at all, but ad-blockers and browser extensions that mutate
   markup have surprised us before. */
body.nf-map-page .nf-map-card,
body.nf-map-page .nf-map-card-b { display: none !important; }

/* ---------- §3 NF Navigator — fly-in / fly-out shell ----------
 * docs/architecture/nf_map_redesign_spec.md §3.
 *
 * Tab on the left edge of the map is always visible. Click toggles the
 * panel between collapsed (slid off-screen left) and expanded. Default
 * state is collapsed on page load (§3.4). Animation uses the `translate`
 * CSS property — does NOT create a stacking context, so Bug 3's popup
 * z-index (200) stays above the panel. */
.nf-nav-tab {
  position: absolute;
  left: 0;
  top: 24px;
  z-index: 16;
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 32px;
  min-height: 120px;
  padding: 12px 0;
  background: #f7f8fa;
  color: #0f172a;
  border: 1px solid #e5e7eb;
  border-left: none;
  border-radius: 0 12px 12px 0;
  cursor: pointer;
  font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  box-shadow: 2px 0 8px -4px rgba(2,6,23,.18);
  transition: background 150ms ease, box-shadow 150ms ease;
}
.nf-nav-tab:hover { background: #ffffff; box-shadow: 2px 0 12px -4px rgba(2,6,23,.28); }
.nf-nav-tab:focus-visible { outline: 2px solid #0ea5e9; outline-offset: 2px; }

/* Legend fly-tab — mirror of .nf-nav-tab on the RIGHT edge of the
 * canvas. Same dimensions, vertical text, chev that rotates on
 * data-open state. Tap toggles the legend in/out (slides off-right
 * via the .nf-map-legend[data-open="false"] translate rule below). */
.nf-legend-tab {
  position: absolute;
  right: 0;
  top: 24px;
  z-index: 16;
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 32px;
  min-height: 120px;
  padding: 12px 0;
  background: #f7f8fa;
  color: #0f172a;
  border: 1px solid #e5e7eb;
  border-right: none;
  border-radius: 12px 0 0 12px;
  cursor: pointer;
  font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  box-shadow: -2px 0 8px -4px rgba(2,6,23,.18);
  transition: background 150ms ease, box-shadow 150ms ease;
}
.nf-legend-tab:hover { background: #ffffff; box-shadow: -2px 0 12px -4px rgba(2,6,23,.28); }
.nf-legend-tab:focus-visible { outline: 2px solid #0ea5e9; outline-offset: 2px; }
.nf-legend-tab .nf-nav-tab-text {
  writing-mode: vertical-rl;
  text-orientation: mixed;
  user-select: none;
}
.nf-legend-tab .nf-nav-tab-chev {
  font-size: 16px;
  line-height: 1;
  transition: transform 200ms ease;
}
/* Chev rotation: ‹ when legend visible (closing affordance);
 * › when legend flown out (re-opening affordance). */
.nf-legend-tab[aria-expanded="false"] .nf-nav-tab-chev { transform: rotate(180deg); }

/* Legend fly-away animation — slide off-right when data-open=false.
 * `translate` is a separate CSS property; transitions cleanly between
 * (0 0) and (calc(100% + 32px) 0). */
.nf-map-legend {
  transition: translate 280ms cubic-bezier(0.4, 0, 0.2, 1), opacity 200ms ease;
}
.nf-map-legend[data-open="false"] {
  translate: calc(100% + 32px) 0;
  opacity: 0;
  pointer-events: none;
}
.nf-nav-tab .nf-nav-tab-text {
  writing-mode: vertical-rl;
  text-orientation: mixed;
  user-select: none;
}
.nf-nav-tab .nf-nav-tab-chev {
  font-size: 16px;
  line-height: 1;
  transition: transform 200ms ease;
}
/* When the panel is expanded, the chev rotates to point left (close hint). */
.nf-nav-tab[aria-expanded="true"] .nf-nav-tab-chev { transform: rotate(180deg); }

/* Slide animation on the existing .nf-nav panel.
 * The panel keeps its existing position:absolute/left:24px/top:24px from
 * the legacy floating-card layout. The tab stays at left:0; the panel
 * sits 24px to the right of the tab when expanded. */
.nf-nav {
  /* Use `translate` (not `transform`) per spec §2 Bug 3 stacking-context
   * note — `translate` does NOT create a stacking context in modern
   * browsers. */
  translate: 0 0;
  transition: translate 280ms cubic-bezier(0.4, 0, 0.2, 1),
              opacity   200ms ease;
  opacity: 1;
}
.nf-nav[data-collapsed="true"] {
  translate: calc(-100% - 32px) 0;  /* off-screen left, past the tab */
  opacity: 0;
  pointer-events: none;
}
@media (prefers-reduced-motion: reduce) {
  .nf-nav, .nf-nav-tab, .nf-nav-tab .nf-nav-tab-chev {
    transition: none !important;
  }
}

/* Mobile (<= 768px): tab pins to the LEFT edge of the map; panel flies
 * out to the LEFT (matches desktop pattern). User-requested 2026-05-07:
 * "the nf navigator flysout to the left - the flyout is anchored on
 * the left of the map canvas". The previous bottom-pinned tab + slide-up
 * pattern is retired. */
@media (max-width: 768px) {
  .nf-nav-tab {
    /* Inherit base desktop positioning: left:0, top:24px (vertical tab on left edge). */
    left: 0;
    top: 24px;
    bottom: auto;
    right: auto;
    /* Vertical tab sized for touch (≥44 high). */
    width: 32px;
    min-height: 120px;
    flex-direction: column;
    border: 1px solid #e5e7eb;
    border-left: none;
    border-radius: 0 12px 12px 0;
    box-shadow: 2px 0 8px -4px rgba(2,6,23,.18);
    padding-bottom: 0;
  }
  .nf-nav-tab .nf-nav-tab-text {
    writing-mode: vertical-rl;
    text-orientation: mixed;
  }
  /* Chevron rotation matches desktop: › when collapsed, ‹ when expanded. */
  .nf-nav-tab .nf-nav-tab-chev { transform: rotate(0); }
  .nf-nav-tab[aria-expanded="true"] .nf-nav-tab-chev { transform: rotate(180deg); }

  /* Inherit desktop collapsed translate (-100% off-left). The base
   * .nf-nav[data-collapsed="true"] rule at css:160-164 already does
   * this. No mobile override needed. */
}

.nf-map-modal {
  position: relative;
  max-width: 1600px;
  margin: 0 auto;
  background: var(--nfm-bg);
  color: var(--nfm-ink);
  border: 1px solid var(--nfm-border);
  border-radius: 18px;
  overflow: hidden;
  /* Flex column so the grid gets a bounded height and the card rail can
     scroll independently without swallowing bottom content (B1 fix). */
  display: flex;
  flex-direction: column;
  height: min(94vh, 960px);
  box-shadow: 0 18px 40px -12px rgba(0,0,0,.7);
}
.nf-map-header {
  position: sticky; top: 0;
  display: flex; justify-content: space-between; align-items: flex-start;
  padding: 16px 20px;
  background: linear-gradient(180deg, var(--nfm-bg) 85%, rgba(0,0,0,0));
  z-index: 10;
  gap: 12px;
}
.nf-map-title { margin: 0; font-size: 20px; font-weight: 800; }
.nf-map-sub   { margin: 3px 0 0; color: var(--nfm-muted); font-size: 13px; max-width: 900px; line-height: 1.45; }
.nf-map-sub sup { font-size: 9px; line-height: 0; vertical-align: super; }
.nf-map-footnote-ref { color: var(--nfm-sel-2); text-decoration: none; padding: 0 2px; }
.nf-map-footnote-ref:hover, .nf-map-footnote-ref:focus { text-decoration: underline; }

.nf-map-footer {
  flex-shrink: 0;
  border-top: 1px solid var(--nfm-border-soft);
  padding: 14px 20px 16px;
  background: var(--nfm-card-2);
  color: var(--nfm-muted);
  font-size: 11.5px;
  line-height: 1.5;
}
.nf-map-footnote { margin: 0 0 6px; max-width: 1100px; }
.nf-map-footnote sup { font-size: 9px; vertical-align: super; line-height: 0; color: var(--nfm-sel-2); }
.nf-map-footnote strong { color: var(--nfm-ink); }
.nf-map-legal { margin: 0; font-size: 11px; letter-spacing: .02em; color: var(--nfm-muted); }
.nf-map-legal::target,
#nfMapFootnoteSRTR:target { background: rgba(30,209,169,.08); border-radius: 4px; padding: 4px 6px; }
.nf-map-close {
  flex: none;
  border: 1px solid var(--nfm-border);
  background: var(--nfm-card);
  color: var(--nfm-ink);
  border-radius: 999px;
  padding: 8px 14px;
  cursor: pointer;
  font-weight: 700;
  font-size: 12px;
}
.nf-map-close:focus { outline: 2px solid var(--nfm-sel); outline-offset: 2px; }

.nf-map-grid {
  display: grid;
  /* --nf-card-rail-width: user-resizable card width. JS clamps to
     [320, viewport-400] and persists the preferred value to
     sessionStorage. Splitter column is 6px wide so it offers a clear
     grab target without wasting space. */
  --nf-card-rail-width: 520px;
  grid-template-columns: minmax(0, 1fr) 6px var(--nf-card-rail-width);
  gap: 0;
  /* Take remaining modal height so the card rail gets a bounded box and
     scrolls without swallowing content below the fold. */
  flex: 1 1 auto;
  min-height: 0;
}
/* Single card open (default): map + splitter + one rail. */
.nf-map-grid:not(.has-card-open) { grid-template-columns: 1fr; }
.nf-map-grid:not(.has-card-open) .nf-map-splitter { display: none; }
/* Two cards open (A/B compare view, E2): map | splitter | cardA | cardB.
   Splitter resizes the boundary between map and the FIRST card; cards
   keep their internal split per design (480px each). */
.nf-map-grid.has-compare-open { grid-template-columns: minmax(0, 1fr) 6px var(--nf-card-rail-width) 480px; }
@media (max-width: 1440px) {
  .nf-map-grid.has-compare-open { grid-template-columns: minmax(0, 1fr) 6px var(--nf-card-rail-width) 420px; }
}
@media (max-width: 1180px) {
  .nf-map-grid { grid-template-columns: 1fr; }
  .nf-map-grid .nf-map-splitter { display: none; }
  .nf-map-grid.has-compare-open { grid-template-columns: 1fr; grid-auto-rows: auto; }
}

/* The drag handle. Stays subtle until hover/active to avoid drawing the
   eye away from map content. ::before centers a vertical "grip" hint so
   the user can see this column is interactive. */
.nf-map-splitter {
  position: relative;
  cursor: col-resize;
  background: var(--nfm-border);
  transition: background .15s ease;
  user-select: none;
  touch-action: none;
}
.nf-map-splitter:hover,
.nf-map-splitter.is-dragging { background: var(--nfm-sel); }
.nf-map-splitter::before {
  content: "";
  position: absolute; top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: 2px; height: 28px;
  border-radius: 2px;
  background: rgba(255,255,255,.55);
  pointer-events: none;
}
.nf-map-splitter:focus-visible { outline: 2px solid var(--nfm-sel); outline-offset: -2px; }

.nf-map-card   { display: none; min-height: 0; }
.nf-map-card.is-open { display: block; }
/* Compare-B slot (E2 side-by-side view). JS adds .nf-map-card-b as a sibling. */
.nf-map-card.nf-map-card-b {
  display: none;
  border-left: 1px solid var(--nfm-border);
  background: linear-gradient(180deg, var(--nfm-card-2), var(--nfm-card));
}
.nf-map-card.nf-map-card-b.is-open { display: block; }

/* ---------- Map stage ----------
 * Stage flexes to fill the grid cell; canvas flexes inside the stage so the
 * map shrinks/grows with the modal viewport instead of forcing an
 * intrinsic 720px height that pushes the footer below the visible region.
 * min-height on the canvas guards against the map collapsing on tall
 * comparison cards. */
.nf-map-stage {
  position: relative;
  display: flex;
  flex-direction: column;
  min-height: 0;
  padding: 12px;
}
.nf-map-canvas {
  position: relative;
  width: 100%;
  flex: 1 1 auto;
  height: auto;
  min-height: 480px;
  border-radius: 14px;
  overflow: hidden;
  border: 1px solid var(--nfm-border);
  background: #9fb2c5;
}
.nf-map-canvas .mapboxgl-ctrl-attrib { font-size: 10px; }

/* ---------- NF Navigator (wireframe-aligned floating card) ----------
 * Visual canon: images/ChatGPT Image May 1, 2026, 04_33_38 PM.png
 * Floating card, 360px wide, 16px radius, light off-white panel, soft
 * shadow, SF Pro stack. Dropped the iPhone-notch hint and the heavier
 * device shadow — wireframe shows a plain floating card, not a phone. */
.nf-nav {
  position: absolute; left: 24px; top: 24px; z-index: 15;
  /* Fluid base — the panel never tries to be wider than its container, so
   * narrow stages (split-screen, small viewports) don't push the card
   * off-screen. Mobile drops position:absolute via the <=768px block. */
  width: min(360px, 100%);
  min-width: 280px;
  max-width: 100%;
  background: #f7f8fa;
  color: #0f172a;
  border: 1px solid #e5e7eb;
  border-radius: 16px;
  /* Stronger shadow + subtle outer ring lifts the panel off the dark map
   * so it reads as a deliberately floating card rather than a chrome edge. */
  box-shadow:
    0 24px 56px -16px rgba(2,6,23,.55),
    0 12px 24px -8px rgba(2,6,23,.32),
    0 1px 0 rgba(255,255,255,.55) inset;
  font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  font-size: 14px;
  max-height: calc(100vh - 120px);
  overflow: auto;
  overscroll-behavior: contain;
  -webkit-font-smoothing: antialiased;
  padding: 4px;
  /* Browser-native horizontal+vertical resize grip in the bottom-right
   * corner. Combines with the .nf-nav-head drag-to-move to give the user
   * full control: drag header to move, drag corner to resize. */
  resize: both;
}
.nf-nav-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 10px 12px 10px;
  background: #ffffff;
  border-radius: 12px 12px 0 0;
  border-bottom: 1px solid #eef2f7;
  /* Drag affordance — JS sets cursor:grab/grabbing on pointer events; the
   * CSS fallback below keeps the grab cursor visible even if JS hasn't
   * attached yet. user-select:none stops text from highlighting mid-drag. */
  user-select: none;
  cursor: grab;
  touch-action: none;
  position: relative;
}
.nf-nav-head:active { cursor: grabbing; }
/* Visible grip dots so the user knows the header is the drag handle. The
 * absolute-positioned ⋮⋮ glyph sits centered behind the title, doesn't
 * push the menu/settings buttons, and stays out of pointerdown's way (it
 * has pointer-events:none so the drag still picks up the underlying head). */
.nf-nav-head::before {
  content: "⋮⋮";
  position: absolute; left: 50%; top: 4px;
  transform: translateX(-50%);
  color: #cbd5e1;
  font-size: 14px; line-height: 1;
  letter-spacing: -2px;
  pointer-events: none;
}
.nf-nav-menu, .nf-nav-settings {
  background: transparent; border: 0; color: #6b7280;
  width: 28px; height: 28px; border-radius: 6px;
  font-size: 16px; cursor: pointer; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
}
.nf-nav-menu:hover, .nf-nav-settings:hover { background: #f3f4f6; color: #0f172a; }
.nf-nav-title { font-size: 14px; font-weight: 700; color: #0f172a; letter-spacing: -.005em; }

/* Each row is its own white card sitting on the off-white panel — matches
   the wireframe's "stacked sheet" look. Bottom-rounded only when last. */
.nf-nav-row {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 12px;
  background: #ffffff;
  border-bottom: 1px solid #eef2f7;
  font-size: 13px;
  color: #0f172a;
}
.nf-nav-row-input label {
  font-size: 13px; color: #475569; font-weight: 500;
  white-space: nowrap;
}
.nf-nav-row-input input {
  flex: 1; min-width: 0;
  background: transparent; border: 0; outline: none;
  color: #0f172a; font-size: 14px; text-align: right;
  padding: 4px 0;
}
.nf-nav-row-input input::placeholder { color: #94a3b8; }
.nf-nav-icon {
  flex: none; width: 20px; text-align: center; font-size: 16px;
  color: #64748b;
}
.nf-nav-chev {
  flex: none; color: #94a3b8; font-size: 18px; font-weight: 700;
}
.nf-nav-locate {
  flex: none; background: transparent; border: 0; cursor: pointer;
  color: #64748b; width: 28px; height: 28px; border-radius: 6px;
  font-size: 16px; display: inline-flex; align-items: center; justify-content: center;
}
.nf-nav-locate:hover { background: #f3f4f6; color: #0f172a; }

.nf-nav-row-picker {
  width: 100%;
  background: #ffffff; color: #0f172a;
  text-align: left;
  cursor: pointer;
  padding: 12px 12px;
  border: 0;
  border-bottom: 1px solid #eef2f7;
  display: flex; align-items: center; gap: 10px;
  font: inherit;
}
.nf-nav-row-picker:hover { background: #f8fafc; }
.nf-nav-row-label { font-size: 13px; color: #475569; font-weight: 500; white-space: nowrap; }
.nf-nav-row-value {
  flex: 1; text-align: right; color: #0f172a; font-weight: 600;
  font-size: 13px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.nf-nav-row-grid {
  display: grid;
  grid-template-columns: 1fr 1.2fr;
  gap: 12px;
  align-items: start;
  padding: 12px;
  background: #ffffff;
  border-bottom: 1px solid #eef2f7;
}
.nf-nav-field { display: flex; flex-direction: column; gap: 6px; }
.nf-nav-field > label {
  font-size: 12px; color: #475569; font-weight: 600;
  text-transform: none; letter-spacing: 0;
}
.nf-nav-stepper {
  display: inline-flex; align-items: center; gap: 4px;
  border: 1px solid #e5e7eb; border-radius: 8px;
  padding: 4px 6px; background: #f9fafb;
}
.nf-nav-stepper input {
  flex: 1; min-width: 0; width: 48px;
  background: transparent; border: 0; outline: none;
  font-size: 14px; font-weight: 700; color: #0f172a; text-align: center;
  -moz-appearance: textfield;
  padding: 2px 0;
}
.nf-nav-stepper input::-webkit-inner-spin-button,
.nf-nav-stepper input::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
.nf-nav-stepper button[data-step] {
  background: transparent; border: 0; cursor: pointer;
  color: #475569; font-size: 18px; font-weight: 700;
  width: 22px; line-height: 1; padding: 0;
}
.nf-nav-stepper button[data-step]:hover { color: #0f172a; }
.nf-nav-help {
  margin-left: 2px; width: 18px; height: 18px; border-radius: 50%;
  background: #e2e8f0; color: #475569; border: 0;
  font-size: 11px; font-weight: 700; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
}
.nf-nav-help:hover { background: #cbd5e1; color: #0f172a; }

/* Segmented control (Patient type). Wireframe shows the active segment as
   a dark-filled pill matching the Drive|Fly mode toggle treatment, not a
   subtle white pill. Inactive segments stay light gray. */
.nf-seg {
  display: inline-flex;
  background: #f1f5f9;
  border: 1px solid #e5e7eb;
  border-radius: 8px;
  padding: 2px;
  width: 100%;
  gap: 2px;
}
.nf-seg button {
  flex: 1; background: transparent; border: 0;
  color: #6b7280;
  font-size: 11px; font-weight: 600; padding: 5px 6px;
  border-radius: 6px; cursor: pointer;
  font-family: inherit;
}
.nf-seg button:hover { color: #0f172a; }
.nf-seg button.is-on {
  background: #0f172a; color: #ffffff;
  box-shadow: 0 1px 2px rgba(8,12,24,.18);
}

/* Drive | Fly mode toggle — wireframe shows full-width pill, active half
   filled dark with white text, inactive half white with gray text. */
.nf-nav-mode {
  display: flex; gap: 0;
  margin: 8px 4px;
  background: #ffffff;
  border: 1px solid #e5e7eb;
  border-radius: 10px;
  padding: 4px;
}
.nf-nav-mode button {
  flex: 1; background: transparent; border: 0;
  font-size: 13px; font-weight: 600; padding: 8px 10px;
  color: #6b7280; border-radius: 8px; cursor: pointer;
  font-family: inherit;
}
.nf-nav-mode button:hover { color: #0f172a; }
.nf-nav-mode button.is-on {
  background: #0f172a; color: #ffffff;
  box-shadow: 0 1px 2px rgba(8,12,24,.18);
}

.nf-nav-panel {
  background: #ffffff;
  border: 1px solid #eef2f7;
  border-radius: 12px;
  padding: 12px;
  margin: 0 4px 8px;
}
.nf-nav-panel[hidden] { display: none; }

/* Refresh map control — custom Mapbox IControl button. Inherits the
   .mapboxgl-ctrl-group frame so it sits flush with NavigationControl,
   GeolocateControl, and FullscreenControl in the bottom-right stack.
   Click action is wired in your_options_mapbox.js (resets to US bounds,
   re-runs anti-collision, re-renders panels). */
.nf-refresh-ctrl button.nf-refresh-btn {
  width: 29px; height: 29px;
  background: transparent;
  border: 0; padding: 0; cursor: pointer;
  font-size: 18px; font-weight: 700; line-height: 1;
  color: #334155;
}
.nf-refresh-ctrl button.nf-refresh-btn:hover { background: #f1f5f9; }
.nf-refresh-ctrl button.nf-refresh-btn:focus-visible {
  outline: 2px solid var(--nfm-sel); outline-offset: -2px;
}

/* ---- Drive bottom sheet (§ 3.3) ---- */
.nf-sheet { display: flex; flex-direction: column; gap: 8px; }
.nf-sheet-handle {
  /* Wireframe doesn't show the iOS-style drag handle on the panel —
     keep the element so existing markup doesn't break, but hide it. */
  display: none;
}
/* Duration block — big "20 min" with light "(16.1 mi)" beside, per
   wireframe Screen 1. Sits below the minimap, above the route chip. */
.nf-sheet-duration {
  display: flex; align-items: baseline; gap: 8px;
  padding: 4px 2px 0;
}
.nf-sheet-duration-big {
  font-size: 22px; font-weight: 800; color: #0f172a; letter-spacing: -.01em;
}
.nf-sheet-duration-sub {
  font-size: 13px; font-weight: 500; color: #64748b;
}
/* Minimap preview strip (§ wireframe — small route preview at top of
   Drive/Fly panel). Uses Mapbox Static Images API: route polyline +
   pin markers baked into a PNG. Cheap (no 2nd map instance), faithful
   to the wireframe style. */
.nf-sheet-mini, .nf-fly .nf-sheet-mini {
  width: 100%;
  border-radius: 12px;
  overflow: hidden;
  background: #e2e8f0;
  margin: 0 0 6px;
  border: 1px solid #e5e7eb;
  aspect-ratio: 360 / 140;
}
.nf-sheet-mini img {
  display: block; width: 100%; height: 100%; object-fit: cover;
}
/* Pending placeholder while the Mapbox Directions call is in flight — same
   aspect-ratio box so the panel doesn't shift when the real preview lands. */
.nf-sheet-mini-pending {
  position: relative;
  display: flex; align-items: center; justify-content: center;
  background: linear-gradient(135deg, #eef2f7 0%, #e2e8f0 100%);
}
.nf-mini-shimmer {
  position: absolute; inset: 0;
  background: linear-gradient(90deg, transparent 0%, rgba(255,255,255,0.55) 50%, transparent 100%);
  background-size: 200% 100%;
  animation: nf-mini-shimmer 1.6s linear infinite;
  pointer-events: none;
}
.nf-mini-pending-label {
  position: relative; z-index: 1;
  font-size: 12px; font-weight: 600; letter-spacing: 0.02em;
  color: #475569;
}
@keyframes nf-mini-shimmer {
  from { background-position: 200% 0; }
  to   { background-position: -200% 0; }
}
@media (prefers-reduced-motion: reduce) {
  .nf-mini-shimmer { animation: none; }
}
/* Clickable head — wireframe shows the title block doubling as a tap
   target that opens the full center card (replaces the dropped Details
   button). Looks like a row, behaves like a button. */
.nf-sheet-head {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 10px;
  background: transparent; border: 0; padding: 4px 2px;
  text-align: left; cursor: pointer; font-family: inherit;
  width: 100%;
}
.nf-sheet-head:hover { background: #f8fafc; border-radius: 8px; }
.nf-sheet-head-left { flex: 1; min-width: 0; }
.nf-sheet-head-chev {
  flex: none; color: #94a3b8; font-size: 22px; font-weight: 700;
  align-self: center; line-height: 1;
}
.nf-sheet-title { font-size: 14px; font-weight: 700; color: #0f172a; line-height: 1.25; }
.nf-sheet-sub { font-size: 12px; color: #64748b; margin-top: 2px; }
/* Save button now sits inline in the action row. .is-on flips heart to
   filled red so a saved plan is visible without hovering. */
.nf-sheet-save        { color: #ef4444; }
.nf-sheet-save.is-on  { background: #fef2f2; border-color: #fecaca; color: #dc2626; }
.nf-sheet-save:hover  { background: #fef2f2; }

.nf-sheet-chips { display: flex; flex-wrap: wrap; gap: 6px; padding: 0 2px; }
.nf-chip {
  display: inline-flex; align-items: center; gap: 6px;
  border: 1px solid #e5e7eb; background: #f8fafc;
  color: #0f172a;
  font-size: 11px; font-weight: 600;
  padding: 3px 9px; border-radius: 999px;
}
.nf-chip-traffic .dot {
  width: 8px; height: 8px; border-radius: 50%; background: #22c55e;
  display: inline-block;
}
.nf-chip-alerts { color: #16a34a; }
/* "Fastest route" chip — wireframe shows a single muted pill below the
   duration block. Tiny dot + text, no border emphasis. */
.nf-chip-route {
  background: #f1f5f9; border-color: #e2e8f0; color: #475569;
}
.nf-chip-route .dot {
  width: 6px; height: 6px; border-radius: 50%; background: #94a3b8;
  display: inline-block;
}

.nf-sheet-buttons {
  display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 6px;
}
.nf-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 4px;
  border-radius: 10px; padding: 9px 8px;
  font-size: 12px; font-weight: 700; cursor: pointer;
  font-family: inherit;
  border: 1px solid #e5e7eb;
  background: #ffffff;
  color: #0f172a;
  white-space: nowrap;
}
.nf-btn:hover { background: #f8fafc; }
/* Primary = Start in Drive panel, View Flights in Fly panel — wireframe
   shows green-pill primary, not the dark-pill default. */
.nf-btn.primary {
  background: #16a34a; color: #ffffff; border-color: #16a34a;
}
.nf-btn.primary:hover { background: #15803d; border-color: #15803d; }
.nf-btn.ghost { background: #ffffff; color: #0f172a; }

.nf-sheet-turns {
  margin-top: 8px;
  border-top: 1px solid #eef2f7;
  padding-top: 8px;
  max-height: 260px; overflow-y: auto;
  font-size: 13px;
}
.nf-sheet-turns[hidden] { display: none; }
/* Mapbox Directions plugin reskin for white turn-by-turn list. */
.nf-sheet-turns .mapboxgl-ctrl-directions { background: transparent; box-shadow: none; width: 100%; }
.nf-sheet-turns .directions-control-inputs,
.nf-sheet-turns .directions-control-instructions { background: transparent; padding: 0; }
.nf-sheet-turns .mapbox-directions-inputs input {
  background: #f9fafb; border: 1px solid #e5e7eb; color: #0f172a;
}
.nf-sheet-turns .mapboxgl-ctrl-directions .mapbox-directions-profile { display: none; }

/* ---- Fly panel (§ 3.4) ---- */
.nf-fly { display: flex; flex-direction: column; gap: 8px; }
.nf-fly-h3 {
  margin: 6px 2px 2px; font-size: 12px; font-weight: 700;
  color: #0f172a; letter-spacing: 0;
}
.nf-fly-row {
  display: flex; align-items: center; gap: 10px;
  background: #f9fafb; border: 1px solid #eef2f7;
  border-radius: 10px; padding: 10px 12px;
  cursor: pointer; text-align: left;
  font-family: inherit; width: 100%;
}
.nf-fly-row:hover { background: #f1f5f9; }
.nf-fly-icon { font-size: 14px; color: #6b7280; flex: none; width: 18px; text-align: center; }
.nf-fly-label { font-size: 11px; color: #6b7280; font-weight: 500; flex: none; }
.nf-fly-value {
  flex: 1; text-align: right; font-size: 12px; font-weight: 600; color: #0f172a;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.nf-fly-chev { flex: none; color: #94a3b8; font-size: 16px; }

/* New 3-step itinerary strip (wireframe Screen 2). Tight horizontal row:
   🚗 [drive min] · ✈ [flight time / Nonstop] · 🚗 [drive min]. Replaces
   the old 4-node ruler that showed IATA codes + Center label. */
.nf-iti3 {
  display: flex; align-items: center; justify-content: space-between;
  gap: 6px; padding: 12px 8px;
  background: #f9fafb; border: 1px solid #eef2f7;
  border-radius: 10px;
}
.nf-iti3-step {
  display: flex; flex-direction: column; align-items: center;
  flex: 1; min-width: 0; text-align: center;
}
.nf-iti3-icon { font-size: 16px; color: #475569; line-height: 1; }
.nf-iti3-time {
  font-size: 12px; font-weight: 700; color: #0f172a;
  margin-top: 4px; line-height: 1.1;
}
.nf-iti3-label {
  font-size: 10px; color: #6b7280; font-weight: 500;
  margin-top: 2px; letter-spacing: 0;
}
.nf-iti3-sep {
  flex: 0 0 12px; height: 1px; background: #cbd5e1; align-self: center;
}

/* Legacy itinerary ruler (kept in case other callers reference it) */
.nf-itinerary {
  display: flex; align-items: center; justify-content: space-between;
  gap: 4px; padding: 14px 4px;
  background: #f8fafc; border: 1px solid #e5e7eb;
  border-radius: 10px;
}
.nf-iti-node {
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  text-align: center; flex: none; min-width: 62px;
}
.nf-iti-code { font-size: 13px; font-weight: 800; color: #0f172a; }
.nf-iti-sub { font-size: 10px; color: #64748b; line-height: 1.15; max-width: 80px; }
.nf-iti-mid { min-width: 10px; }
.nf-iti-mid::before {
  content: ''; display: block; width: 10px; height: 10px;
  border-radius: 50%; background: #ffffff; border: 2px solid #94a3b8;
  margin: 0 auto;
}
.nf-iti-end .nf-iti-code { color: #b91c1c; }
.nf-iti-leg {
  flex: 1; display: flex; flex-direction: column; align-items: center; gap: 2px;
  position: relative; min-width: 0;
}
.nf-iti-leg::before {
  content: ''; position: absolute; left: 0; right: 0; top: 50%;
  height: 2px; background: #cbd5e1; transform: translateY(-50%); z-index: 0;
}
.nf-iti-icon {
  position: relative; z-index: 1; background: #f8fafc;
  padding: 0 6px; font-size: 14px; color: #0f172a;
}
.nf-iti-time {
  position: relative; z-index: 1; background: #f8fafc;
  font-size: 11px; font-weight: 700; color: #0f172a;
  padding: 0 6px;
}
.nf-iti-mode { font-size: 10px; color: #64748b; }

.nf-fly-metrics {
  display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 6px;
}
.nf-fly-metric {
  background: #ffffff; border: 1px solid #e5e7eb;
  border-radius: 10px; padding: 8px 10px;
  text-align: left;
}
.nf-fly-metric-label { font-size: 11px; color: #64748b; font-weight: 500; }
.nf-fly-metric-value {
  font-size: 15px; font-weight: 800; color: #0f172a; margin-top: 2px;
}
.nf-fly-metric-meta { font-size: 10px; color: #94a3b8; margin-top: 2px; }

.nf-fly-buttons { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 6px; }

/* Total-to-center summary line — present in both Drive and Fly panels.
   Time-critical for liver patients on the organ-offer call (donor
   viability window + transplant team arrival window). Bordered + slightly
   stronger than the chip row so it doesn't read as "just another stat". */
.nf-total-summary {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 8px;
  padding: 8px 10px;
  margin: 2px 0;
  background: #ecfeff;
  border: 1px solid #a5f3fc;
  border-left: 3px solid #06b6d4;
  border-radius: 8px;
}
.nf-total-label {
  font-size: 11px; font-weight: 600; color: #0e7490;
  letter-spacing: 0;
}
.nf-total-value {
  font-size: 15px; font-weight: 800; color: #083344;
  letter-spacing: -.005em;
}

/* ---- Footer (§ 0.3 short disclaimer) ---- */
.nf-nav-foot {
  padding: 8px 12px 10px;
  background: #ffffff;
  border-top: 1px solid #eef2f7;
  border-radius: 0 0 12px 12px;
}
.nf-nav-foot-text {
  display: block; font-size: 10px; color: #94a3b8; line-height: 1.4;
  text-align: center;
}

/* ---- Transplant center picker drawer (§ 3.5) ---- */
.nf-nav-picker {
  display: flex; flex-direction: column; gap: 8px;
  padding: 10px 12px;
}
.nf-nav-picker-head {
  display: flex; align-items: center; gap: 8px;
}
.nf-nav-picker-back {
  background: transparent; border: 0; cursor: pointer;
  font-size: 16px; color: #475569; padding: 4px 8px; border-radius: 6px;
}
.nf-nav-picker-back:hover { background: #f3f4f6; color: #0f172a; }
.nf-nav-picker-title { font-size: 15px; font-weight: 700; }
.nf-nav-picker-search {
  width: 100%; box-sizing: border-box;
  padding: 8px 10px; border: 1px solid #e5e7eb; border-radius: 8px;
  font-size: 13px; color: #0f172a; background: #f9fafb;
}
.nf-nav-picker-list {
  display: flex; flex-direction: column; gap: 4px;
  max-height: 50vh; overflow-y: auto;
}
.nf-nav-picker-item {
  display: block; width: 100%; text-align: left;
  background: #ffffff; border: 1px solid #e5e7eb; border-radius: 8px;
  padding: 8px 10px; cursor: pointer; font-family: inherit;
}
.nf-nav-picker-item:hover { background: #f8fafc; }
.nf-nav-picker-item.is-on { border-color: #0f172a; background: #f1f5f9; }
.nf-nav-picker-item b { font-size: 13px; color: #0f172a; display: block; }
.nf-nav-picker-item .nf-nav-picker-meta { font-size: 11px; color: #64748b; margin-top: 2px; }
.nf-nav-picker-item .nf-nav-picker-metrics { font-size: 11px; color: #475569; margin-top: 2px; }
.nf-nav-picker-item .nf-nav-picker-dist { font-size: 11px; color: #0ea5e9; margin-top: 2px; font-weight: 600; }

/* ---- Popovers (menu / settings / MELD help / picklists / capability tips) ----
 * Popovers are appended to document.body by openPopover(), so they live in
 * body's stacking context — sibling to .nf-map-backdrop (z-index: 99990).
 * z-index MUST be > the backdrop so the popover renders on top of the
 * modal's blur-darken layer; otherwise clicks open an invisible popover.
 * Below .nf-nav-local-modal (100010) so a tooltip modal can still cover. */
.nf-nav-popover {
  position: absolute; z-index: 100000;
  background: #ffffff; color: #0f172a;
  border: 1px solid #e5e7eb; border-radius: 10px;
  box-shadow: 0 10px 28px rgba(8,12,24,.18);
  padding: 10px 12px;
  font-size: 13px; min-width: 200px; max-width: 320px;
}
.nf-nav-popover h4 { margin: 0 0 6px; font-size: 13px; font-weight: 700; }
.nf-nav-popover button {
  display: block; width: 100%; text-align: left;
  background: transparent; border: 0; padding: 6px 0;
  cursor: pointer; font-family: inherit; font-size: 13px; color: #0f172a;
}
.nf-nav-popover button:hover { color: #0ea5e9; }
.nf-nav-popover label {
  display: flex; align-items: center; gap: 8px; margin: 6px 0;
  font-size: 13px; cursor: pointer;
}
.nf-nav-popover .nf-nav-popover-note {
  font-size: 12px; color: #64748b; margin-top: 6px; line-height: 1.4;
}

/* ---- Local tooltip modal (View Flights) ---- */
.nf-nav-local-modal {
  position: fixed; inset: 0; z-index: 100010;
  background: rgba(8,12,24,.35);
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
}
.nf-nav-local-modal .nf-nav-local-modal-inner {
  background: #ffffff; color: #0f172a;
  border: 1px solid #e5e7eb; border-radius: 12px;
  box-shadow: 0 10px 28px rgba(8,12,24,.22);
  padding: 18px 20px; max-width: 420px; width: 100%;
  font-size: 14px; line-height: 1.5;
}
.nf-nav-local-modal h3 { margin: 0 0 8px; font-size: 16px; }
.nf-nav-local-modal p { margin: 0 0 10px; }
.nf-nav-local-modal .nf-btn { margin-top: 6px; }

.nf-map-counter {
  position: absolute; right: 24px; top: 24px; z-index: 15;
  background: rgba(20,14,6,.92); color: #f7ecd6;
  border: 1px solid rgba(255,255,255,.15);
  padding: 6px 12px; border-radius: 999px;
  font-size: 11px; font-weight: 700;
}
.nf-map-counter b { color: #6bf3c5; }

.nf-hover-stats {
  position: absolute; left: 50%; bottom: 86px;
  transform: translateX(-50%);
  background: rgba(20,14,6,.95); color: #f7ecd6;
  border: 1px solid rgba(255,255,255,.18);
  padding: 8px 14px; border-radius: 10px;
  font-size: 11.5px; z-index: 15;
  display: none; gap: 14px; align-items: center;
  box-shadow: 0 6px 12px rgba(0,0,0,.5);
  white-space: nowrap; max-width: 92vw; overflow: hidden;
}
.nf-hover-stats.is-on { display: flex; }
.nf-hover-stats b { color: #fff; }
.nf-hover-stats .k { color: rgba(247,236,214,.7); margin-right: 3px; }
.nf-hover-stats .sep { color: rgba(247,236,214,.35); }

.nf-compare-chip {
  position: absolute; left: 50%; bottom: 26px;
  transform: translateX(-50%);
  background: rgba(8,30,22,.96); color: #f7ecd6;
  border: 1.5px solid rgba(30,209,169,.6);
  padding: 8px 14px; border-radius: 10px;
  font-size: 11.5px; z-index: 15;
  display: none; gap: 12px; align-items: center;
  box-shadow: 0 6px 14px rgba(0,0,0,.5);
  white-space: nowrap; max-width: 92vw; overflow: hidden;
}
.nf-compare-chip.is-on { display: flex; }
.nf-compare-chip b { color: #fff; }
.nf-compare-chip .k { color: rgba(247,236,214,.7); margin-right: 3px; }
.nf-compare-chip .sep { color: rgba(247,236,214,.35); }

/* Legend — collapsible floating card, top-right of map. Light-themed to
 * match the NF Navigator floating panel; same shadow recipe so they read
 * as a paired set of "floating UI cards" rather than chrome inset into
 * the dark map. Mobile breakpoint default-hides in favor of the compact
 * "Legend" reopen pill. */
.nf-map-legend {
  position: absolute; right: 24px; top: 160px; bottom: auto; z-index: 15;
  background: #f7f8fa; color: #0f172a;
  border: 1px solid #e5e7eb;
  padding: 12px 14px; border-radius: 14px;
  font-size: 11.5px;
  /* Fluid base — never wider than its container; the calc(100% - 24px)
   * leaves a 12px breathing margin on each side so the panel doesn't kiss
   * the map edge on a narrow stage. */
  width: min(280px, calc(100% - 24px));
  max-width: 100%;
  box-shadow:
    0 24px 56px -16px rgba(2,6,23,.55),
    0 12px 24px -8px rgba(2,6,23,.32),
    0 1px 0 rgba(255,255,255,.55) inset;
}
.nf-map-legend[data-open="false"] .nf-legend-body { display: none; }
.nf-map-legend[data-open="false"] { padding: 8px 12px; }
.nf-legend-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; user-select: none;
  cursor: grab; touch-action: none; position: relative;
}
.nf-legend-head:active { cursor: grabbing; }
.nf-legend-head::before {
  content: "⋮⋮";
  position: absolute; left: 50%; top: 2px;
  transform: translateX(-50%);
  color: #cbd5e1;
  font-size: 13px; line-height: 1;
  letter-spacing: -2px;
  pointer-events: none;
}
.nf-legend-toggle {
  background: transparent; border: 1px solid #cbd5e1;
  color: #475569; width: 22px; height: 22px; border-radius: 4px;
  font-weight: 800; cursor: pointer;
}
.nf-legend-toggle:hover { background: #eef2f7; color: #0f172a; }

/* Drag-to-move on mobile uses CODE WEIGHT (long-press + small threshold)
 * — see setupPanelDrag() in your_options_mapbox.js. No visible grip
 * element. Rest of the header keeps touch-action:auto so vertical
 * scroll wins on a brief tap-and-drag-down. Holding the header for
 * ~250ms (or moving > 8px horizontally) commits to drag mode. Pattern
 * mirrors setupMiniPopupDetach for the mini-popup detach-on-drag. */
.nf-legend-reopen {
  position: absolute; right: 24px; top: 160px; z-index: 15;
  background: #f7f8fa; color: #0f172a;
  border: 1px solid #e5e7eb; border-radius: 10px;
  padding: 6px 12px; font-size: 12px; font-weight: 700; cursor: pointer;
  box-shadow: 0 12px 24px -8px rgba(2,6,23,.32);
}
/* Phone-tier legend chip (the "Legend" button at the base of the map):
   meant for ≤480px only. On desktop/tablet the auto-rendered legend at
   render time is the ONLY launcher — there is no bottom-edge bar that
   re-opens it. The chip's click handler stays bound but is unreachable
   because the button is display:none. */
.nf-legend-chip { display: none; }
@media (max-width: 980px){
  .nf-map-legend { display: none; }
  .nf-legend-reopen { display: inline-block; }
}
@media (max-width: 480px){
  .nf-legend-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    position: absolute;
    left: 12px;
    bottom: 12px;
    z-index: 16;
    background: rgba(20, 14, 6, .82);
    color: #f7ecd6;
    border: 1px solid rgba(255,255,255,.18);
    border-radius: 999px;
    padding: 6px 12px;
    font-size: 12px;
    font-weight: 700;
    cursor: pointer;
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
  }
}
.nf-map-legend h4 { margin: 0; font-size: 11px; letter-spacing: .14em; text-transform: uppercase; color: #475569; }
.nf-map-legend .nf-legend-body { margin-top: 6px; }
.nf-map-legend .row { display: flex; align-items: center; gap: 8px; margin-top: 4px; line-height: 1.35; color: #1e293b; }
.nf-map-legend .sw { flex: none; width: 14px; height: 14px; border-radius: 3px; border: 1px solid rgba(15,23,42,.18); }
.nf-map-legend .sw.round { border-radius: 50%; }
.nf-map-legend .sw.line { width: 16px; height: 3px; background: linear-gradient(90deg, var(--nfm-sel-2), var(--nfm-sel)); border-radius: 2px; border: none; }
.nf-map-legend .sw.ivory  { background: #f4eeda; }
.nf-map-legend .sw.sel    { background: var(--nfm-sel); }
.nf-map-legend .sw.sel2   { background: var(--nfm-sel-2); box-shadow: 0 0 0 2px rgba(30,209,169,.35); }
.nf-map-legend .sw.violet { background: var(--nfm-violet); }
.nf-map-legend .sw.gold   { background: var(--nfm-gold); }
.nf-map-legend .sw.pink   { background: linear-gradient(180deg, #f7a8d2, #cc6ba4); }

/* Legend "region border" swatch — shows the heavy line that now outlines each
 * OPTN region on the map itself (per-region fills carry the region identity,
 * so we no longer need a separate 11-chip color grid). */
.nf-map-legend .sw.regborder {
  width: 18px; height: 3px; background: #475569; border-radius: 2px;
  border: none;
}
/* Pin swatches matching the live red/green/pink pin styling. */
.nf-map-legend .sw.pin {
  width: 14px; height: 18px; border: none; border-radius: 0;
  background: url('/images/transparent_red_pin_imamge.png') center/contain no-repeat;
  filter: drop-shadow(0 1px 2px rgba(0,0,0,.5));
}
.nf-map-legend .sw.pin.pin-adult { filter: hue-rotate(210deg) saturate(1.35) brightness(.95) drop-shadow(0 1px 2px rgba(0,0,0,.5)); }
.nf-map-legend .sw.pin.pin-peds  { filter: hue-rotate(270deg) saturate(1.25) drop-shadow(0 1px 2px rgba(0,0,0,.5)); }
.nf-map-legend .sw.pin.pin-combo { filter: saturate(.78) brightness(1.18) drop-shadow(0 1px 2px rgba(0,0,0,.5)); }
.nf-map-legend .sw.pin.pin-sel   { filter: hue-rotate(130deg) saturate(1.6) brightness(1.05) drop-shadow(0 1px 2px rgba(0,0,0,.5)); }
/* Pastel fill swatch keyed off OPTN region 1's color. */
.nf-map-legend .sw.fill-r1 {
  width: 14px; height: 14px; background: #b8e0d2; border: 1px solid rgba(58,45,22,.55);
  border-radius: 3px;
}
.nf-map-legend .row.note {
  margin-top: 8px; padding-top: 6px; border-top: 1px solid #e5e7eb;
  display: block; font-size: 10.5px; color: #475569; line-height: 1.4;
}

/* ---------- Pushpin Markers (D+2 rebuild, § 4.2) ----------
 * Every transplant-center pin uses the same red pushpin image
 * /images/transparent_red_pin_imamge.png. No per-OPTN color variants.
 * The legacy SVG-face rendering (.nf-pin-solo svg, --pin-fill, --rot,
 * REG_HEX-per-pin, fanFactor, PIN_GROUPS) has been retired. */
/* Spec §3.4 — kill any white background bleed under PNG pins. The
 * source PNG is RGB (color-type 2) so transparent edges are simulated by
 * the runtime canvas chroma-key in preparePinImage(); these explicit
 * background:transparent rules ensure no parent rule paints a white
 * rectangle behind the pin. */
.nf-pin,
.nf-pin img,
.mapboxgl-marker,
.mapboxgl-marker img { background: transparent !important; }

.nf-pin {
  position: relative;
  display: inline-flex;
  align-items: flex-end;
  justify-content: center;
  width: 32px; height: 44px;
  padding: 0; margin: 0;
  border: 0; cursor: pointer;
  pointer-events: auto;
  transform-origin: 50% 100%;
  transition: transform .14s ease-out, filter .14s ease-out, opacity .15s ease;
}
.nf-pin::before {
  content: '';
  position: absolute; inset: -6px;
  border-radius: 10px;
}
.nf-pin:focus { outline: none; }
.nf-pin:focus .pin-img { filter: drop-shadow(0 0 3px rgba(14,165,233,.9)); }
.nf-pin .pin-img {
  width: 32px; height: 44px;
  object-fit: contain;
  pointer-events: none;
  /* Default filter is the base drop-shadow; per-class filters below override
   * with hue-rotate to produce blue / purple / lighter-red variants. */
  filter: drop-shadow(0 2px 3px rgba(0,0,0,.35));
  display: block;
}
.nf-pin.is-hover .pin-img,
.nf-pin:hover .pin-img  { transform: translateY(-4px) scale(1.08); }

/* Pin color scheme — the base PNG is red; hue-rotate shifts it to the
 * required color per hospital_type. Saturation/brightness adjustments
 * compensate so each color reads cleanly against the region fills.
 *
 *   Adult-only       (hospital_type='adult_only')      → blue   ~210°
 *   Pediatric-only   (hospital_type='pediatric_only')  → purple ~270°
 *   Combined         (hospital_type='combined')        → lighter red
 *   Selected         (.is-sel)                         → green  ~130°
 *
 * Selected always wins over the per-type filter via !important so that
 * the green shows regardless of which color the pin was before clicking. */
.nf-pin-adult .pin-img {
  filter: hue-rotate(210deg) saturate(1.35) brightness(.95) drop-shadow(0 2px 3px rgba(0,0,0,.35));
}
.nf-pin-pediatric .pin-img {
  filter: hue-rotate(270deg) saturate(1.25) brightness(1.0) drop-shadow(0 2px 3px rgba(0,0,0,.35));
}
.nf-pin-combo .pin-img {
  /* "Lighter red, but not too light" — keep the red hue, drop saturation
   * a touch and bump brightness so it reads as a softened red without
   * becoming pink. */
  filter: saturate(.78) brightness(1.18) drop-shadow(0 2px 3px rgba(0,0,0,.35));
}
.nf-pin.is-sel .pin-img {
  transform: translateY(-2px) scale(1.15);
  filter: hue-rotate(130deg) saturate(1.6) brightness(1.05) drop-shadow(0 3px 6px rgba(0,80,40,.55)) !important;
}
.nf-pin.is-sel  { z-index: 5; }
.nf-pin:hover   { z-index: 4; }
.nf-cluster-dim .nf-pin:not(:hover) { opacity: .42; }

.nf-pin .nf-pin-name {
  position: absolute;
  bottom: calc(100% + 6px);
  left: 50%;
  transform: translateX(-50%);
  background: #0f172a;
  color: #ffffff;
  font-size: 11px;
  font-weight: 700;
  padding: 4px 8px;
  border-radius: 6px;
  white-space: nowrap;
  border: 1px solid rgba(15,23,42,.4);
  box-shadow: 0 4px 8px rgba(0,0,0,.35);
  opacity: 0;
  pointer-events: none;
  transition: opacity .12s;
  max-width: 260px;
  line-height: 1.3;
  z-index: 4;
}
.nf-pin:hover .nf-pin-name { opacity: 1; }

/* Legacy safety net — if stale JS renders an .nf-marker wrapper, don't blow up. */
.nf-marker { pointer-events: none; }
.nf-marker .pinwrap { position: relative; }

/* ---- Destination popup (spec §4.2) — N=1 pin click, sits above pin ---- */
.mapboxgl-popup.nf-dest-popup .mapboxgl-popup-content {
  padding: 10px 12px 9px;
  border-radius: 8px;
  width: 240px;
  box-shadow: 0 10px 28px rgba(0,0,0,.28), 0 2px 6px rgba(0,0,0,.16);
}
.nf-dest-card { font-size: 12px; color:#0f172a; line-height:1.35; }
.nf-dest-card b { display:block; font-size: 13px; line-height:1.25; }
.nf-dest-card .nf-dest-sub { color:#64748b; margin-top: 2px; }
.nf-dest-card .nf-region-chip {
  display:inline-block; margin-top: 6px;
  padding: 2px 8px; border-radius: 999px;
  background: #eef2ff; color:#3730a3; font-size: 11px; font-weight: 600;
}
.nf-dest-card .nf-dest-cta {
  display:block; width:100%; margin-top: 8px;
  background: transparent; color:#1e40af; border: 0; padding: 4px 0 0;
  font-size: 12px; font-weight: 600; text-align: left; cursor: pointer;
}
.nf-dest-card .nf-dest-cta:hover { text-decoration: underline; }

/* ---- Pin popups z-index (Bug 3 fix) -----------------------------------
 * Mapbox Popup defaults to z-index: auto. Inside .nf-map-stage's stacking
 * context, .nf-nav (z-index: 15) would otherwise paint on top of the
 * popup, hiding the mini card behind the navigator. None of .nf-map-canvas,
 * .mapboxgl-map, or .mapboxgl-canvas-container creates a stacking context,
 * so a z-index here propagates up to compete with .nf-nav directly.
 * Tier 200 matches docs/architecture/nf_map_redesign_spec.md §2 Bug 3. */
.mapboxgl-popup.nf-mini-popup,
.mapboxgl-popup.nf-dest-popup,
.mapboxgl-popup.nf-stack-popup {
  z-index: 200;
}

/* ---- Mini card with MELD histogram (spec §4.3) ------------------------ */
.mapboxgl-popup.nf-mini-popup .mapboxgl-popup-content {
  padding: 12px 14px 10px;
  border-radius: 12px;
  /* Fluid base — the popup's mapbox parent gets tiny on small screens, so
   * the inner card has to clamp to its parent rather than insisting on a
   * fixed 280px and overflowing past the map edge. */
  width: min(280px, calc(100% - 24px));
  max-width: 100%;
  /* Larger floating-card shadow so the mini card reads as deliberately
   * lifted above the map (matches NF Navigator panel elevation). */
  box-shadow:
    0 22px 48px -12px rgba(2,6,23,.55),
    0 8px 18px -4px rgba(2,6,23,.30),
    0 0 0 1px rgba(15,23,42,.06);
}

/* ---- Detached mini card ----------------------------------------------
 * After a drag, the mini popup is removed from Mapbox and its content is
 * re-parented into this floating wrapper anchored in screen space inside
 * .nf-map-stage. The pin stays on the map; the card stays wherever the
 * user dropped it regardless of pan/zoom. */
.nf-mini-detached {
  position: absolute;
  z-index: 14;
  /* Fluid base — clamps to the stage width on narrow viewports while the
   * desktop max stays 360px. The 16px slack keeps the floater from kissing
   * the stage edges when the user drops it near a corner. */
  width: min(360px, calc(100% - 16px));
  max-width: 100%;
  background: #ffffff;
  border-radius: 12px;
  padding: 12px 14px 10px;
  box-shadow:
    0 22px 48px -12px rgba(2,6,23,.55),
    0 8px 18px -4px rgba(2,6,23,.30),
    0 0 0 1px rgba(15,23,42,.06);
}
.nf-mini-detached-close {
  position: absolute; top: 6px; right: 6px;
  width: 24px; height: 24px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 0; background: rgba(15,23,42,.06);
  color: #475569; font-size: 18px; font-weight: 700; line-height: 1;
  border-radius: 999px; cursor: pointer;
  z-index: 1;
}
.nf-mini-detached-close:hover { background: rgba(15,23,42,.12); color: #0f172a; }
/* Head + name/sub/region-chip rules also apply to the detached floater
 * because the mobile collapse extracts .nf-mini-head out of .nf-mini-card
 * and parents it directly under .nf-mini-detached (so the head stays
 * visible and draggable when the body is collapsed). */
:is(.nf-mini-card, .nf-mini-detached) .nf-mini-head { margin-bottom: 8px; position: relative; }
:is(.nf-mini-card, .nf-mini-detached) .nf-mini-name { display:block; font-size: 13px; color:#0f172a; line-height:1.25; padding-right: 56px; }
:is(.nf-mini-card, .nf-mini-detached) .nf-mini-sub  { font-size: 11px; color:#64748b; margin-top: 2px; padding-right: 56px; }
:is(.nf-mini-card, .nf-mini-detached) .nf-region-chip {
  position: absolute; top: 0; right: 0;
  display:inline-block;
  padding: 2px 8px; border-radius: 999px;
  background: #eef2ff; color:#3730a3;
  font-size: 10px; font-weight: 600; line-height: 1.4;
}
.nf-mini-card .nf-mini-histo-wrap { position: relative; padding-top: 4px; padding-bottom: 18px; }
.nf-mini-card .nf-mini-histo {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  align-items: end;
  gap: 4px;
  height: 64px;
  padding-bottom: 14px;
  border-bottom: 1px solid #e5e7eb;
}
.nf-mini-card .nf-mini-bar {
  position: relative;
  background: #c7d2fe;
  border-radius: 3px 3px 0 0;
  min-height: 2px;
}
.nf-mini-card .nf-mini-bar.is-active { background: #4f46e5; }
.nf-mini-card .nf-mini-bar > span {
  position: absolute; bottom: 100%; left: 50%; transform: translate(-50%, -2px);
  font-size: 10px; color:#475569; white-space: nowrap;
}
.nf-mini-card .nf-mini-marker {
  position: absolute; bottom: 0; transform: translateX(-50%);
  font-size: 18px; line-height: 1; color: #4f46e5;
  pointer-events: none;
}
/* Mini-card vertical tail dropping from the ▾ marker through the bars to
   the axis line. Visually anchors the cumulative-% caption to the chart:
   "X% below MELD Y" reads as the area to the left of this line. */
.nf-mini-card .nf-mini-tail {
  position: absolute;
  top: 18px; bottom: 18px;
  width: 2px;
  background: #4f46e5;
  transform: translateX(-50%);
  pointer-events: none;
  border-radius: 1px;
  opacity: .85;
}
.nf-mini-card .nf-mini-cap {
  font-size: 12px; color: #334155; margin-top: 2px; line-height: 1.35;
}
.nf-mini-card .nf-mini-cta {
  display:block; width:100%; margin-top: 8px;
  background: #0f172a; color: #ffffff; border: 0; border-radius: 6px;
  padding: 7px 10px; font-size: 12px; font-weight: 600; cursor: pointer;
}
.nf-mini-card .nf-mini-cta:hover { background: #1e293b; }

/* ---------- Right-rail card ---------- */
.nf-map-card {
  border-left: 1px solid var(--nfm-border);
  background: linear-gradient(180deg, var(--nfm-card), var(--nfm-card-2));
  overflow-y: auto;
  overscroll-behavior: contain;
  /* Fill parent grid cell so the card scrolls independently of the map (B1). */
  height: 100%;
  min-height: 0;
  position: relative;
}

/* Sticky section headers inside the card (B2) — keeps group context while
   scrolling through a long SRTR card. */
.nf-map-card .nf-grp {
  position: sticky;
  top: 0;
  background: linear-gradient(180deg, var(--nfm-card) 85%, rgba(19,29,61,0));
  padding: 8px 0 4px;
  z-index: 4;
  margin: 0 0 6px;
}
.nf-empty-card {
  padding: 60px 30px; text-align: center; color: var(--nfm-muted); font-size: 13px;
}
.nf-empty-card h3 { margin: 0 0 8px; color: var(--nfm-ink); font-size: 16px; }
.nf-ribbon {
  position: absolute; top: 10px; left: 10px; z-index: 2;
  background: var(--nfm-sel); color: #001126;
  font-size: 10px; letter-spacing: .16em; text-transform: uppercase;
  font-weight: 800; padding: 4px 8px; border-radius: 4px;
}
/* Per-card close button — sits at top-right of each rail card. Closing
   deselects the underlying pin so the rail collapses cleanly via the
   existing updateCardVisibility flow. Sticky-positioned so it stays
   visible while the user scrolls the long SRTR card body. */
.nf-card-close {
  position: sticky; top: 8px; float: right;
  z-index: 6; margin: 8px 8px 0 0;
  width: 28px; height: 28px; padding: 0;
  border: 1px solid var(--nfm-border);
  background: rgba(255,255,255,.95);
  color: var(--nfm-ink);
  font-size: 18px; font-weight: 700; line-height: 1;
  border-radius: 50%; cursor: pointer;
  box-shadow: 0 1px 3px rgba(0,0,0,.12);
  display: inline-flex; align-items: center; justify-content: center;
}
.nf-card-close:hover  { background: #fff; box-shadow: 0 2px 6px rgba(0,0,0,.18); }
.nf-card-close:focus-visible { outline: 2px solid var(--nfm-sel); outline-offset: 2px; }
.nf-hero {
  position: relative; aspect-ratio: 16/7;
  background: linear-gradient(135deg,#1b2a55,#0e1630);
}
.nf-hero img { width: 100%; height: 100%; object-fit: cover; display: block; opacity: .9; }
/* Header CTAs overlaying the hero image. Both pills sit in a flex row
   anchored bottom-left, matching Intermountain's painted CTA layout so
   our buttons visually replace theirs on that card. Style is deliberately
   Intermountain-inspired (dark-indigo solid + white outlined) so the same
   template reads as polished CTAs on cards that don't have painted CTAs.
   renderCard populates per-row; the tracking framework rewrites
   .nf-hero-refer hrefs through /api/redirect.php once data-center-*
   attrs are stamped. */
/* CTAs sit inside .nf-body directly beneath .nf-sub (the city/state ·
   age · OPTN region line). They share .nf-body's padding so no manual
   left margin is needed; they never overlap the hero image. */
.nf-hero-cta {
  margin: 10px 0 4px 0;
  display: flex; flex-wrap: wrap; gap: 8px;
  position: relative;
  max-width: 100%;
}
/* Specificity bumped via parent scope (.nf-hero-cta) so we beat
   `body.nf a { color: inherit; }` from styles.css line 147 — without that
   the refer pill rendered as inherited color (white-on-white). NOTE: the
   parent moved from .nf-hero to .nf-hero-cta when CTAs were lifted out of
   the hero into normal flow; selectors had to follow. */
.nf-hero-cta .nf-hero-phone,
.nf-hero-cta .nf-hero-refer {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 9px 16px;
  font-size: 13px; font-weight: 700; line-height: 1;
  border-radius: 999px;
  text-decoration: none;
  cursor: pointer;
  transition: background .15s ease, color .15s ease, border-color .15s ease, transform .15s ease, box-shadow .15s ease;
}
.nf-hero-cta .nf-hero-phone {
  background: #1f1247;
  color: #fff;
  border: 1px solid #1f1247;
  box-shadow: 0 2px 6px rgba(0,0,0,.35);
}
.nf-hero-cta .nf-hero-refer {
  background: #fff;
  color: #1f1247;
  border: 1.5px solid #1f1247;
  box-shadow: 0 2px 6px rgba(0,0,0,.25);
}
.nf-hero-cta .nf-hero-phone:hover { background: #2a1a5e; border-color: #2a1a5e; transform: translateY(-1px); }
.nf-hero-cta .nf-hero-refer:hover { background: #f3eefb; color: #1f1247; transform: translateY(-1px); }
.nf-hero-cta .nf-hero-phone:focus-visible,
.nf-hero-cta .nf-hero-refer:focus-visible {
  outline: 2px solid #6b47d6; outline-offset: 2px;
}
.nf-hero-icon { font-size: 13px; line-height: 1; }
/* Desktop (no SignalWire yet): phone stays clickable for visual parity but
   does nothing on click. JS adds .is-inert when (pointer: fine). */
.nf-hero-cta .nf-hero-phone.is-inert { cursor: default; }
/* Body padding is unchanged from the legacy layout; .nf-hero-cta now
   lives inside .nf-body and inherits this horizontal padding. */
.nf-body { padding: 8px 16px 18px; }
.nf-title { font-size: 17px; font-weight: 800; margin: 0; line-height: 1.15; }
.nf-sub { margin: 3px 0 0; color: var(--nfm-muted); font-size: 12.5px; }
.nf-rule { height: 1px; background: var(--nfm-border-soft); margin: 12px 0; }
.nf-grp {
  font-size: 10px; letter-spacing: .18em; text-transform: uppercase;
  color: var(--nfm-muted); margin: 0 0 8px;
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
.nf-badge {
  background: rgba(30,209,169,.14); color: var(--nfm-sel-2);
  border: 1px solid rgba(30,209,169,.4);
  padding: 1px 6px; border-radius: 4px;
  font-weight: 700; letter-spacing: .08em; text-transform: none;
}
.nf-fromu { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.nf-big   { font-size: 22px; font-weight: 800; color: var(--nfm-sel-2); }
.nf-chip {
  display: inline-flex; gap: 6px; align-items: center;
  border: 1px solid var(--nfm-border); border-radius: 999px;
  padding: 3px 9px; font-size: 11.5px;
  background: rgba(74,163,255,.08); color: #d6e6ff; white-space: nowrap;
}
.nf-chip-good { color: #b9f0d2; background: rgba(55,192,106,.10); border-color: rgba(55,192,106,.45); }
.nf-chip-warn { color: #ffd9a8; background: rgba(230,162,60,.12); border-color: rgba(230,162,60,.45); }

/* Your MELD marker (D+2 rename — was "Fit Lens" pre-nf_navigator_spec) */
.nf-fit {
  border: 1px solid rgba(30,209,169,.35);
  background: rgba(30,209,169,.05);
  border-radius: 12px; padding: 14px 12px 10px;
}
.nf-fit-ruler {
  position: relative; height: 22px;
  background: linear-gradient(90deg,#1e2a55,#3c2260);
  border-radius: 6px; margin: 8px 0 6px; overflow: visible;
}
/* Bin-edge ticks — left:% values MUST match TICK_POS in the JS (0/15/32/56/88)
 * so the ▼ marker always lines up on the underlying MELD bin edge. */
.nf-fit-tick {
  position: absolute; top: 0; bottom: 0;
  width: 1px; background: rgba(255,255,255,.35); pointer-events: none;
}
.nf-fit-tick.t-edge { background: rgba(255,255,255,.55); width: 2px; }
.nf-fit-marker {
  position: absolute; top: -6px; transform: translateX(-50%);
  display: flex; flex-direction: column; align-items: center; z-index: 2;
}
.nf-fit-marker svg { filter: drop-shadow(0 2px 2px rgba(0,0,0,.6)); }
.nf-fit-marker b {
  font-size: 11px; color: var(--nfm-sel-2); margin-top: 1px; font-weight: 800;
  background: #0b1a3d; padding: 1px 6px; border-radius: 4px; border: 1px solid var(--nfm-border);
}
/* Wrapper hosts the histogram + the vertical "tail" line dropping from the
   MELD marker. Position-relative so the tail's left:% is keyed to the
   same x-axis as the ruler above. */
.nf-fit-histo-wrap { position: relative; }
.nf-fit-histo {
  display: flex; height: 30px; border-radius: 6px; overflow: hidden;
  border: 1px solid var(--nfm-border);
}
.nf-fit-tail {
  position: absolute; top: -22px; bottom: -2px; width: 2px;
  background: linear-gradient(180deg, #37e8be 0%, rgba(55,232,190,.85) 100%);
  box-shadow: 0 0 0 1px rgba(0,0,0,.25);
  transform: translateX(-50%);
  pointer-events: none; z-index: 3;
}
.nf-fit-histo span {
  display: flex; align-items: center; justify-content: center;
  font-size: 10.5px; font-weight: 800; color: rgba(255,255,255,.95);
  min-width: 0; padding: 0 2px;
}
.nf-fit-histo span.is-hi { outline: 2px solid #fff; outline-offset: -2px; z-index: 1; position: relative; }
/* Bin labels positioned at the geometric CENTER of each bin's proportional
 * ruler segment so the "6–10"/"11–14"/… caption sits under its real bin,
 * not an even fifth. Midpoints of TICK_POS pairs: 7.5, 23.5, 44, 72, 94. */
.nf-fit-binlbl { position: relative; height: 14px; margin-top: 4px; font-size: 9.5px; color: var(--nfm-muted); }
.nf-fit-binlbl span { position: absolute; top: 0; transform: translateX(-50%); white-space: nowrap; }
.nf-fit-caption { margin: 8px 0 0; font-size: 12px; color: var(--nfm-muted); }

/* Plain-language explainer paragraph above each chart on the card.
   Sits between the section header (.nf-grp) and the chart itself. */
.nf-chart-explain {
  margin: 4px 0 10px;
  font-size: 12px;
  line-height: 1.5;
  color: var(--nfm-muted);
}
.nf-mini-explain {
  margin: 8px 0 6px;
  font-size: 11.5px;
  line-height: 1.45;
  color: var(--nfm-muted);
}
.nf-fit-caption b { color: var(--nfm-ink); }

/* Wait box-whisker. Labels stagger across two rows because all four
 * percentiles share the same X-axis and crash into each other at fast-
 * turnover centers (Houston Methodist, Tampa General, etc.) where p25 /
 * median / p75 sit within a few percent of each other. Median stays on
 * the inner row (closest to the bar, most prominent); p25 + p90 use the
 * inner row too (they're at the extremes and rarely collide); p75 lifts
 * to the outer row so it never sits on top of median. */
/* Box-plot visual is now pure shapes — numeric labels moved to a single
   clean row in .nf-waitstats below the chart so they never overlap or
   wrap. padding-top reverted to a tight value since labels no longer
   sit above the chart. */
.nf-wait-wrap { position: relative; padding-top: 10px; padding-bottom: 28px; }
.nf-wait { position: relative; height: 40px; background: var(--nfm-border-soft); border-radius: 8px; overflow: visible; }
.nf-wait .axis { position: absolute; left: 0; right: 0; top: 50%; height: 1px; background: rgba(255,255,255,.08); }
.nf-wait .box { position: absolute; top: 12px; bottom: 12px; background: linear-gradient(180deg, var(--nfm-sel-2), var(--nfm-sel)); border-radius: 4px; opacity: .85; }
.nf-wait .whi { position: absolute; top: 50%; height: 1px; background: var(--nfm-sel); opacity: .55; }
.nf-wait .cap { position: absolute; top: 6px; bottom: 6px; width: 2px; background: var(--nfm-sel); opacity: .7; border-radius: 2px; }
.nf-wait .med { position: absolute; top: 4px; bottom: 4px; width: 3px; background: #fff; border-radius: 2px; z-index: 2; }
.nf-wait .scale { position: absolute; left: 0; right: 0; top: 42px; display: flex; justify-content: space-between; font-size: 10px; color: var(--nfm-muted); }

/* Caption sentence + percentile-stats row sit below the chart. Both
   indent 15px from the right edge so they don't crowd the card border.
   Both have a `title` attribute (set in the template) the browser
   renders as a hover/long-press tooltip. */
.nf-waitcap {
  margin: 14px 15px 0 0;
  font-size: 12px;
  color: var(--nfm-muted);
  line-height: 1.45;
}
.nf-waitstats {
  margin: 6px 15px 0 0;
  display: flex;
  flex-wrap: nowrap;
  gap: 14px;
  font-size: 11.5px;
  color: var(--nfm-muted);
  white-space: nowrap;
  overflow-x: auto;          /* if the card is very narrow, scroll instead of wrap */
}
.nf-wait-stat {
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
}
.nf-wait-stat b {
  font-weight: 700;
  color: var(--nfm-muted);
  letter-spacing: 0.02em;
}
.nf-wait-stat--med b {
  color: #fff;
}
.nf-waitcap { margin: 6px 0 0; font-size: 12px; color: var(--nfm-muted); }
.nf-waitcap b { color: var(--nfm-ink); }

/* Outcome flow */
.nf-flow { display: flex; height: 30px; border-radius: 6px; overflow: hidden; border: 1px solid var(--nfm-border); }
.nf-flow span { display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: 800; color: #001; min-width: 0; padding: 0 4px; overflow: hidden; white-space: nowrap; }
.nf-flow .tx { background: var(--nfm-good); }
.nf-flow .st { background: var(--nfm-warn); }
.nf-flow .dt { background: var(--nfm-bad); color: #fff; }
.nf-flowcap  { margin: 6px 0 0; font-size: 12px; color: var(--nfm-muted); }
.nf-flowcap b { color: var(--nfm-ink); }

/* Survival bars */
.nf-metric { display: grid; grid-template-columns: 120px 60px 1fr; gap: 10px; align-items: center; margin: 6px 0; font-size: 13px; }
.nf-metric .nf-k { color: var(--nfm-muted); }
.nf-metric .nf-v { font-weight: 800; text-align: right; }
.nf-bar { height: 8px; border-radius: 999px; background: var(--nfm-border-soft); overflow: hidden; }
.nf-bar > span { display: block; height: 100%; background: linear-gradient(90deg, var(--nfm-sky), var(--nfm-sel-2)); border-radius: 999px; }
.nf-bar-inv > span { background: linear-gradient(90deg, var(--nfm-good), var(--nfm-warn), var(--nfm-bad)); }

/* Capability dots */
.nf-caps { display: grid; grid-template-columns: 1fr 1fr; gap: 6px 14px; }
.nf-cap  { display: flex; align-items: center; gap: 8px; font-size: 12.5px; color: #dfeaff; }
.nf-cap .d { flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--nfm-sel-2); box-shadow: 0 0 0 2px rgba(30,209,169,.18); }
.nf-cap.off { color: var(--nfm-muted); }
.nf-cap.off .d { background: transparent; border: 1px solid var(--nfm-border); box-shadow: none; }

/* Per-center data correction note (in wait-time section). Amber callout
   so it reads as supplemental info, not a stat. */
.nf-data-note {
  margin: 10px 0 0;
  padding: 10px 12px;
  background: rgba(230, 162, 60, .08);
  border: 1px solid rgba(230, 162, 60, .35);
  border-radius: 8px;
  font-size: 12px;
  line-height: 1.45;
  color: var(--nfm-ink);
}
.nf-data-note-head { margin: 0 0 4px; font-size: 12px; }
.nf-data-note-list { margin: 4px 0 6px; padding-left: 18px; }
.nf-data-note-list li { margin: 2px 0; }
.nf-data-note-foot { margin: 4px 0 0; color: var(--nfm-muted); font-size: 11.5px; }
.nf-data-note-foot a { color: var(--nfm-sel); text-decoration: underline; }

/* Card-foot disclaimer — short, italicized, muted. Repeated in mini
   card, navigator, and map for consistent voice. NF_DISCLAIMER is the
   single source of truth. */
.nf-disclaimer {
  margin: 8px 0 0;
  font-size: 11px;
  font-style: italic;
  color: var(--nfm-muted);
  text-align: center;
}

/* Mini-card data note + disclaimer. Compact and muted so they don't
   crowd the histogram. */
.nf-mini-card .nf-mini-data-note {
  margin: 6px 0 0;
  padding: 6px 8px;
  background: rgba(230, 162, 60, .10);
  border-left: 3px solid rgba(230, 162, 60, .55);
  border-radius: 4px;
  font-size: 11px;
  line-height: 1.35;
  color: #334155;
}
.nf-mini-card .nf-mini-disclaimer {
  margin: 6px 0 0;
  font-size: 10px;
  font-style: italic;
  color: #64748b;
  text-align: center;
  line-height: 1.3;
}

/* Persistent map-corner disclaimer pill. Bottom-center so it doesn't
   collide with the navigator (top-left), legend (top-right area), or
   mapbox attribution (bottom-right). Pointer-events: none — display
   only, not interactive. */
/* Disclaimer is a static flex child of .nf-map-stage so it physically
   sits at the bottom edge of the map area, beneath the canvas. Earlier
   absolute positioning meant the strip floated over the canvas at a
   bottom offset, which mid-flow with the deck overlay above could look
   like a pill in the middle of the map. Static layout removes any
   "where is it really?" ambiguity. */
.nf-map-disclaimer {
  flex: 0 0 auto;
  margin-top: 6px;
  padding: 5px 12px;
  text-align: center;
  background: rgba(255, 255, 255, .92);
  color: #475569;
  font-size: 10.5px;
  font-style: italic;
  border-top: 1px solid rgba(15, 23, 42, .06);
  border-bottom-left-radius: 12px;
  border-bottom-right-radius: 12px;
  pointer-events: none;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
@media (max-width: 768px) {
  .nf-map-disclaimer { font-size: 9.5px; padding: 4px 8px; }
}

/* Risk chips */
.nf-riskrow { display: flex; flex-wrap: wrap; gap: 6px; }
.nf-rchip {
  display: inline-flex; align-items: center; gap: 6px;
  border: 1px solid rgba(230,162,60,.5); background: rgba(230,162,60,.12);
  color: #ffd9a8; border-radius: 999px; padding: 3px 10px; font-size: 11.5px; cursor: help;
}
/* "None" chip used when a center has zero active risk flags. Distinct
   green/neutral palette so it doesn't read as a warning chip; non-
   interactive (disabled <button>) since it's purely informational. */
.nf-rchip-none {
  border-color: rgba(30,209,169,.45);
  background: rgba(30,209,169,.10);
  color: var(--nfm-sel-2);
  font-weight: 700;
  cursor: default;
  font-family: inherit;
}

/* Action grid (E1 reorder) — row 1 is the primary "Ask about listing"
 * full-width button that includes the phone number. Row 2 is the ghost
 * "Program site". Row 3 is compare / share side-by-side. */
.nf-cta { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 12px; }
.nf-cta .btn { font-size: 13px; padding: 10px 12px; border-radius: 10px; font-weight: 700; }
.nf-cta .js-listing {
  grid-column: 1 / -1;
  background: var(--nfm-sel);
  color: #001126;
  border: 0;
  text-align: center;
}
.nf-cta .js-listing:hover { background: var(--nfm-sel-2); }
.nf-cta .js-site { grid-column: 1 / -1; text-align: center; }

/* Share toast (E3) */
.nf-share-toast {
  position: fixed;
  left: 50%;
  bottom: 40px;
  transform: translateX(-50%);
  background: rgba(20,14,6,.95);
  color: #f7ecd6;
  padding: 10px 18px;
  border-radius: 999px;
  font-size: 12.5px;
  font-weight: 700;
  border: 1px solid rgba(30,209,169,.5);
  z-index: 100000;
  box-shadow: 0 6px 18px rgba(0,0,0,.6);
  opacity: 0;
  pointer-events: none;
  transition: opacity .22s ease;
}
.nf-share-toast.is-on { opacity: 1; }

/* Compare basket chip (E2) */
.nf-compare-basket {
  position: absolute;
  left: 50%;
  bottom: 72px;
  transform: translateX(-50%);
  background: rgba(8,30,22,.96);
  color: #f7ecd6;
  border: 1.5px solid rgba(30,209,169,.7);
  padding: 8px 14px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 700;
  z-index: 16;
  display: none;
  gap: 10px;
  align-items: center;
  box-shadow: 0 6px 14px rgba(0,0,0,.5);
  white-space: nowrap;
}
.nf-compare-basket.is-on { display: inline-flex; }
.nf-compare-basket button {
  background: rgba(255,255,255,.12);
  border: 1px solid rgba(255,255,255,.25);
  color: #f7ecd6;
  border-radius: 999px;
  padding: 4px 10px;
  font-weight: 700;
  font-size: 11.5px;
  cursor: pointer;
}
.nf-compare-basket button:hover { background: rgba(255,255,255,.22); }

/* Per-metric diff highlight (E2 — when 2 cards are shown side by side,
 * flag the better side). */
.nf-diff-better { box-shadow: inset 0 0 0 2px rgba(55,192,106,.7); border-radius: 6px; }
.nf-diff-worse  { opacity: .78; }

/* Recenter-US custom button — rendered inside the settings popover in D+2. */
.nf-nav-popover .nf-recenter-btn,
.nf-map-controls .nf-recenter-btn {
  background: #f1f5f9;
  border: 1px solid #e5e7eb;
  color: #0f172a;
  border-radius: 8px;
  padding: 6px 10px;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
}
.nf-nav-popover .nf-recenter-btn:hover,
.nf-map-controls .nf-recenter-btn:hover { background: #e2e8f0; }

/* ---------- Stack popup (D+1 Fix 7) ----------
 * When N>1 programs share a city, we render ONE pin with an ×N DOM badge.
 * Clicking the pin opens a Mapbox Popup with a vertical list of hospital
 * rows; each row is a button that selects the center and re-renders the
 * right-rail card. */
.nf-stack-popup .mapboxgl-popup-content {
  background: #ffffff; color: #0f172a;
  border: 1px solid #e5e7eb;
  padding: 6px; border-radius: 10px;
  box-shadow: 0 10px 28px rgba(8,12,24,.18);
}
.nf-stack-popup .mapboxgl-popup-tip { border-top-color: #ffffff; }
.nf-stack-row {
  display: flex; flex-direction: column; gap: 4px; align-items: flex-start;
  background: transparent; border: none;
  border-bottom: 1px solid #eef2f7;
  color: #0f172a; padding: 8px 10px; width: 100%; cursor: pointer;
  text-align: left; font-family: inherit;
}
.nf-stack-row:last-child { border-bottom: none; }
.nf-stack-row:hover { background: #f1f5f9; }
.nf-stack-name { font-weight: 700; font-size: 13px; }
.nf-stack-meta { display: flex; gap: 6px; flex-wrap: wrap; }
.nf-stack-chip {
  font-size: 10px; font-weight: 700; padding: 2px 6px; border-radius: 999px;
  background: #e0f2fe; color: #075985;
}
.nf-stack-chip.good   { background: #dcfce7; color: #166534; }
.nf-stack-chip.warn   { background: #fef3c7; color: #92400e; }
.nf-stack-chip.danger { background: #fee2e2; color: #991b1b; }

/* Stack badge (§ 4.2) — white pill with black border, top-right corner. */
.nf-stack-badge {
  position: absolute;
  top: -4px; right: -6px;
  background: #ffffff;
  color: #111111;
  border: 1.5px solid #111111;
  border-radius: 999px;
  min-width: 18px; height: 18px;
  font-size: 11px; font-weight: 800;
  padding: 0 5px;
  display: inline-flex; align-items: center; justify-content: center;
  pointer-events: none;
}

/* In-modal "Back to comparison table" breadcrumb (F1) */
.nf-back-to-table {
  margin-top: 8px;
  display: inline-block;
  color: var(--nfm-muted);
  font-size: 12px;
  text-decoration: none;
  border-bottom: 1px dashed rgba(247,236,214,.3);
}
.nf-back-to-table:hover { color: var(--nfm-ink); }

.nf-sources { margin-top: 10px; font-size: 11px; color: var(--nfm-muted); line-height: 1.5; }

/* B8: pin tap feedback — touch-only via (hover: none). Stylus and mouse
 * users get the existing :hover lift; touch users get a brief :active
 * lift since they have no hover state. Not gated on viewport width — a
 * narrow desktop window with a mouse should still get hover, not tap. */
@media (hover: none) {
  .nf-pin:active .pin-img { transform: translateY(-2px) scale(1.05); }
}

/* ---------- Floating-card phone-tier collapse + Reset + Undo toast ----- */

/* Detached mini-card body wrapper. Default expanded — no max-height clamp,
 * so the histogram + drive minutes lay out at their natural size. The
 * collapsed state (data-collapsed="1" on the host) clamps max-height to 0
 * with overflow:hidden, animated for 120ms so the tap feels responsive
 * but not jumpy.
 *
 * Trade-off: collapsed cards hide histogram and drive minutes; mitigation
 * is the visible center name + chevron rotation. Per-card independent so
 * collapsing one never hides another. */
.nf-mini-detached-body {
  transition: max-height 120ms ease;
}
.nf-mini-detached[data-collapsed="1"] .nf-mini-detached-body {
  max-height: 0;
  overflow: hidden;
}

/* Toggle chevron — universal collapse affordance, visible at every
 * breakpoint. Sits to the LEFT of the close button (which is at right:6px);
 * the toggle parks at right:38px (close width 24 + 8px gutter + 6px close
 * offset) so both buttons sit on the same horizontal line. */
.nf-mini-detached-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  position: absolute;
  top: 6px;
  right: 38px;
  width: 32px;
  height: 32px;
  border: 0;
  background: rgba(15,23,42,.06);
  color: #475569;
  font-size: 16px;
  font-weight: 700;
  line-height: 1;
  border-radius: 999px;
  cursor: pointer;
  z-index: 1;
  padding: 0;
}
.nf-mini-detached-toggle:hover {
  background: rgba(15,23,42,.12);
  color: #0f172a;
}

/* Reset button in the Navigator header. 28×28 matches .nf-nav-menu and
 * .nf-nav-settings on desktop; the @media block below promotes it to
 * 44×44 at the phone breakpoint to satisfy WCAG 2.5.5 like the other
 * Navigator chrome.
 *
 * Trade-off: one-tap reset can wipe a comparison the patient spent time
 * building. Mitigation: 8s Undo toast restores the full pre-reset
 * snapshot. */
.nf-nav-reset {
  background: transparent; border: 0; color: #6b7280;
  width: 28px; height: 28px; border-radius: 6px;
  font-size: 16px; cursor: pointer; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
}
.nf-nav-reset:hover { background: #f3f4f6; color: #0f172a; }

/* Undo toast — pinned top-center of the map stage, above the legend chip
 * (z=16) and detached cards (z=14) but below the Mapbox-managed popovers.
 * Single instance: the JS singleton replaces the previous toast on a
 * second reset, so we never need to stack these. */
.nf-toast {
  position: absolute;
  top: 14px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 18;
  background: #0f172a;
  color: #f8fafc;
  border-radius: 999px;
  padding: 8px 14px;
  font-size: 13px;
  font-weight: 500;
  box-shadow: 0 12px 28px -8px rgba(2,6,23,.55);
  display: inline-flex;
  align-items: center;
  gap: 4px;
  white-space: nowrap;
}
.nf-toast-undo {
  background: transparent;
  border: 0;
  color: #5eead4;
  font-weight: 700;
  font-size: 13px;
  cursor: pointer;
  padding: 2px 6px;
  border-radius: 4px;
}
.nf-toast-undo:hover { background: rgba(94, 234, 212, .12); }

/* ============================================================
 * Universal collapse — base rules (applied at every breakpoint)
 *
 * Two sets of cards collapse via a chevron in their header:
 *   - .nf-nav, .nf-map-legend, .nf-mini-detached  → universal
 *     (chevron visible at every viewport so a desktop user can free
 *     vertical real estate without leaving the modal).
 *   - .nf-map-card  → mobile-only (gated inside the <=768px block
 *     below). Desktop right-rail card is a deliberate persistent
 *     surface; collapsing it on desktop is novel UX and out of scope.
 *
 * The body wrapper (.nf-card-body) is a sibling of the sticky close
 * button and the header, so collapsing the body never hides the
 * close button or the drag handle (the header is always reachable).
 * ============================================================ */
.nf-card-toggle {
  width: 28px; height: 28px;
  border: 0; background: transparent; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 14px; color: #475569; line-height: 1;
  border-radius: 6px;
  position: relative;
}
.nf-card-toggle:hover { background: rgba(15,23,42,.06); color: #0f172a; }
/* Touch-target halo: extends the hit zone beyond the visible 28×28 so
 * a finger tap doesn't have to land precisely on the chevron glyph. */
.nf-card-toggle::before {
  content: ""; position: absolute; inset: -6px;
  pointer-events: auto;
}
/* Default: hide the .nf-map-card chevron outside the mobile media query.
 * The mobile block flips this back to inline-flex. */
.nf-map-card .nf-card-toggle { display: none; }

/* Body-hide for cards that ARE universal-collapse. The .nf-map-card
 * counterpart is gated mobile-only inside the <=768px block. */
.nf-nav[data-collapsed="1"] > .nf-card-body,
.nf-map-legend[data-collapsed="1"] > .nf-card-body,
.nf-mini-detached[data-collapsed="1"] > .nf-mini-detached-body {
  display: none;
}

/* .nf-card-body must establish a positioning context so absolutely-
 * positioned children inside the .nf-map-card template (.nf-ribbon at
 * top:10px; left:10px) keep their original anchor when wrapped. */
.nf-card-body { position: relative; }

/* Pin tap halo for touch devices — extends hit area to ~44×44 without
 * changing visual size. Mirrors the ::before halo pattern already used
 * for stepper buttons / help glyph. */
@media (hover: none) and (pointer: coarse) {
  .nf-pin { position: relative; }
  .nf-pin::before {
    content: "";
    position: absolute; inset: -6px;
    border-radius: 50%;
  }
}

/* ============================================================
 * UAT Phase 1 — capability filter facet, closest-NMP hero strip,
 * faded-pin treatment, and capability tooltip popovers.
 *
 * The facet slots inside #nfNavigator between the patient-type grid
 * and the Drive/Fly mode toggle (your_options/index.html line ~687).
 * The closest-NMP strip slots between the mode toggle and the Drive
 * panel (line ~692). Both are hidden by default; JS unhides on first
 * paint when its render conditions are met.
 * ============================================================ */
.nf-filter-facet {
  background: #ffffff;
  border-bottom: 1px solid #eef2f7;
  padding: 10px 12px;
  font-size: 13px;
  color: #0f172a;
}
.nf-filter-facet-header {
  display: flex; align-items: center; justify-content: space-between;
  gap: 8px;
}
.nf-filter-facet-title {
  font-size: 13px; color: #475569; font-weight: 600;
  letter-spacing: -.005em;
}
.nf-filter-facet-toggle {
  display: none; /* desktop hides chevron; mobile @media reveals it */
  background: transparent; border: 0; cursor: pointer;
  color: #64748b; width: 28px; height: 28px; border-radius: 6px;
  font-size: 14px;
  align-items: center; justify-content: center;
  padding: 0;
}
.nf-filter-facet-toggle:hover { background: #f3f4f6; color: #0f172a; }
.nf-filter-facet-body { margin-top: 8px; }
.nf-filter-facet-note {
  font-size: 11px; color: #64748b; margin: 6px 0 0;
  line-height: 1.4;
}

/* ---- Caregiver picklist row (5 picklists + Reset all) -------------------
 * Each picklist is a button with a label, a count badge (hidden when 0),
 * and a caret. Active picklists get a tinted background. Tap opens a
 * standard nf-nav-popover with a multi-select checkbox list (see the
 * .nf-filter-pick-* rules below). Spec §2 / §3.
 */
.nf-filter-picklist-row { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.nf-filter-picklist {
  display: inline-flex; align-items: center; gap: 6px;
  background: #f1f5f9; color: #0f172a;
  border: 1px solid #cbd5e1; border-radius: 999px;
  padding: 6px 12px;
  font: inherit; font-size: 12.5px; font-weight: 600;
  cursor: pointer;
  transition: background 120ms ease, border-color 120ms ease, color 120ms ease;
}
.nf-filter-picklist:hover { background: #e2e8f0; }
.nf-filter-picklist[aria-pressed="true"],
.nf-filter-picklist.nf-filter-picklist-active {
  background: var(--nfm-sel);
  border-color: var(--nfm-sel-3);
  color: #08151f;
}
.nf-filter-picklist:focus-visible {
  outline: 2px solid var(--nfm-sel);
  outline-offset: 2px;
}
.nf-filter-picklist-label { line-height: 1; }
.nf-filter-picklist-badge {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 18px; height: 18px; padding: 0 5px;
  font-size: 11px; font-weight: 800; line-height: 1;
  background: #0e8a6e; color: #fff;
  border-radius: 999px;
}
/* Bumped 50% (10→15px) for visibility. Rotates 180° when the parent
   button reads aria-expanded="true" so the triangle direction matches
   the popover state — open = ▴, closed = ▾ — giving the user a clear
   "click again to collapse" affordance. */
.nf-filter-picklist-caret {
  display: inline-block;
  font-size: 15px;
  line-height: 1;
  opacity: .8;
  transition: transform 150ms ease, opacity 150ms ease;
}
.nf-filter-picklist[aria-expanded="true"] .nf-filter-picklist-caret {
  transform: rotate(180deg);
  opacity: 1;
}
.nf-filter-picklist-reset {
  background: transparent; border: 0;
  color: #b91c1c; font: inherit; font-size: 12px; font-weight: 600;
  text-decoration: underline; text-underline-offset: 2px;
  cursor: pointer; padding: 6px 4px;
}
.nf-filter-picklist-reset:hover { color: #7f1d1d; }
.nf-filter-picklist-reset:focus-visible {
  outline: 2px solid var(--nfm-sel); outline-offset: 2px; border-radius: 4px;
}

/* ---- Picklist popover body (multi-select checkbox list) ----------------- */
.nf-nav-popover.nf-filter-pick-pop {
  max-width: 320px;
  max-height: 70vh;
  overflow-y: auto;
}
.nf-filter-pick-list {
  display: flex; flex-direction: column; gap: 2px;
  margin: 6px 0 0;
}
.nf-filter-pick-row {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 4px; border-radius: 6px;
  font-size: 13px; line-height: 1.3; color: #0f172a;
  cursor: pointer;
}
.nf-filter-pick-row:hover { background: #f1f5f9; }
.nf-filter-pick-row.nf-filter-pick-sub {
  margin-left: 18px; font-size: 12.5px;
}
.nf-filter-pick-row.nf-filter-pick-disabled {
  opacity: .5; cursor: not-allowed;
}
.nf-filter-pick-row input[type="checkbox"] {
  width: 16px; height: 16px; flex-shrink: 0;
  accent-color: #0e8a6e;
}
.nf-filter-pick-label { flex: 1; }
.nf-filter-pick-actions {
  display: flex; justify-content: flex-end;
  margin-top: 8px; padding-top: 8px;
  border-top: 1px solid #eef2f7;
}
.nf-filter-pick-clear {
  background: transparent; border: 0;
  color: #b91c1c; font: inherit; font-size: 12px; font-weight: 600;
  text-decoration: underline; cursor: pointer; padding: 4px;
}
.nf-filter-pick-clear:hover { color: #7f1d1d; }

/* D6 insurance disclosure banner inside the picklist popover. Spec §6 —
 * we record the user's intent but don't silently filter to empty until
 * center_insurance_acceptance ships. */
.nf-insurance-pending-disclosure {
  margin: 0 0 8px;
  padding: 8px 10px;
  background: #fef3c7; border: 1px solid #fcd34d;
  border-radius: 6px;
  font-size: 12px; line-height: 1.4; color: #78350f;
}

/* D8 SRTR-risk banner — surfaces in-state long-wait + Medicaid risk text
 * above the picklist row. Hidden by default; renderSrtrRiskBanner controls. */
.nf-srtr-risk-banner {
  margin: 0 0 8px;
  padding: 10px 12px;
  background: linear-gradient(135deg, rgba(220,38,38,.08), rgba(220,38,38,.02));
  border: 1px solid rgba(220,38,38,.4);
  border-radius: 8px;
  font-size: 12.5px; line-height: 1.45; color: #7f1d1d;
}
.nf-srtr-risk-banner b { color: #581717; }
.nf-srtr-risk-banner a {
  color: #b91c1c; font-weight: 700;
  text-decoration: none; white-space: nowrap;
}
.nf-srtr-risk-banner a:hover { text-decoration: underline; }

.nf-filter-chip-info {
  margin-left: 2px;
  display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; border-radius: 50%;
  font-size: 12px; font-weight: 700;
  background: rgba(15,23,42,.08); color: #475569;
  cursor: help;
}
.nf-filter-picklist[aria-pressed="true"] .nf-filter-chip-info {
  background: rgba(8,21,31,.18); color: #08151f;
}
.nf-filter-chip-info:focus-visible {
  outline: 2px solid var(--nfm-sel); outline-offset: 1px;
}

/* Capability tooltip popover. Reuses .nf-nav-popover positioning (set in
 * openPopover) and adds tooltip-specific shape via the .nf-cap-tip-pop
 * class added on creation. */
.nf-nav-popover.nf-cap-tip-pop {
  max-width: 300px;
}
.nf-cap-tip {
  display: block;
}
.nf-cap-tip-short {
  font-size: 13px; line-height: 1.5; color: #0f172a;
}
.nf-cap-tip-more {
  display: inline-block; margin-top: 8px;
  font-size: 12.5px; font-weight: 700;
  color: #0e8a6e; text-decoration: none;
}
.nf-cap-tip-more:hover { text-decoration: underline; }

/* Faded pin — visual-filter mode 'fade' (default). Cull mode hides via
 * style.display=none (set by applyVisualFilters step 4). */
.nf-pin.nf-pin-faded {
  opacity: 0.35;
  filter: saturate(0.6);
  transition: opacity 180ms ease, filter 180ms ease;
}
.nf-pin.is-sel.nf-pin-faded {
  /* Defensive — selected-action exemption in applyVisualFilters step 1
   * should already have removed the class, but if a race left it on,
   * force full visibility so the user's chosen pin is never dim. */
  opacity: 1 !important;
  filter: none !important;
}

/* Top-performer gold halo (D9). Painted on every center where >=80% of
 * NF_TOP_PERFORMER_CAP_FIELDS resolve true via capOf() (computeTopPerformerIds).
 * Pure CSS overlay — no DOM change. The ring is ALWAYS painted on top-
 * performer pins regardless of whether the picklist filter is active —
 * it's a permanent surface signal, like a badge. The picklist filter only
 * controls whether non-top-performers are CULLED from the map.
 *
 * COMMENTED OUT 2026-05-06 per user request: keep the top-performer
 * "award" (Navigator hero strip, picklist filter, halo on chips/cards)
 * but remove the pulsing gold ring on the map pin itself. The
 * .nf-pin-top-performer class is still toggled by paintTopPerformerRing
 * (so the JS path stays intact); restoring the visual is a one-line
 * uncomment when needed.
 */
/*
.nf-pin.nf-pin-top-performer {
  position: relative;
}
.nf-pin.nf-pin-top-performer::after {
  content: "";
  position: absolute;
  inset: -6px;
  border-radius: 50%;
  border: 2px solid #f5b301;
  box-shadow: 0 0 10px 2px rgba(245,179,1,.55);
  pointer-events: none;
  animation: nf-pin-top-performer-pulse 2.4s ease-in-out infinite;
}
@keyframes nf-pin-top-performer-pulse {
  0%, 100% { box-shadow: 0 0 10px 2px rgba(245,179,1,.55); }
  50%      { box-shadow: 0 0 14px 4px rgba(245,179,1,.85); }
}
@media (prefers-reduced-motion: reduce) {
  .nf-pin.nf-pin-top-performer::after { animation: none; }
}
*/

/* In-card capability chips — the wrapper for the .nf-cap labels in the
 * SRTR rail card. Tipped variants get a small ⓘ icon trailing the label. */
.nf-cap.nf-cap-tipped {
  cursor: help;
}
.nf-cap .nf-cap-label { flex: 1; }
.nf-cap.nf-cap-tipped .nf-filter-chip-info {
  background: rgba(255,255,255,.08); color: var(--nfm-muted);
}
.nf-cap.nf-cap-tipped .nf-filter-chip-info:hover {
  background: rgba(255,255,255,.16); color: var(--nfm-ink);
}

/* "Top-performer center" hero strip. Slots between the Drive/Fly mode
 * toggle and the #nfDrivePanel. Two render modes (origin set vs. not),
 * both painted by renderTopPerformerStrip(). Gold-tinted gradient
 * matches the top-performer pin halo so users see a visual relationship
 * between strip → ring on the map. */
.nf-top-performer-strip {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px; margin: 8px 12px;
  background: linear-gradient(135deg, rgba(245,179,1,.16), rgba(245,179,1,.04));
  border: 1px solid rgba(245,179,1,.55);
  border-radius: 10px;
}
.nf-top-performer-strip-icon { font-size: 18px; color: #b67903; }
.nf-top-performer-strip-body {
  display: flex; flex-direction: column; flex: 1;
  min-width: 0;
}
.nf-top-performer-strip-title {
  font-size: 11px; color: #475569; font-weight: 600;
}
.nf-top-performer-strip-name {
  font-weight: 700; font-size: 13.5px; color: #0f172a;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.nf-top-performer-strip-dist { font-size: 12px; color: #475569; }
.nf-top-performer-strip-cta {
  flex: none;
  padding: 8px 12px; border-radius: 8px;
  background: var(--nfm-sel); color: #08151f; border: 0;
  font: inherit; font-weight: 700; font-size: 12.5px;
  cursor: pointer;
}
.nf-top-performer-strip-cta:hover { background: var(--nfm-sel-2); }
.nf-top-performer-strip-cta:focus-visible {
  outline: 2px solid var(--nfm-sel-3); outline-offset: 2px;
}

/* Hard-cull toggle in the Settings popover (UAT Phase 1, §9). */
.nf-set-cull {
  display: flex; align-items: center; gap: 6px; margin-top: 6px;
  font-size: 13px;
}
.nf-set-cull-label { line-height: 1.3; }
.nf-set-cull-note {
  font-size: 11px !important;
  color: #64748b !important;
  margin-top: 4px !important;
  line-height: 1.4;
}

/* ============================================================
 * Mobile: in-flow scrollable map (matches repo pattern at <=768px)
 *
 * The map is no longer a fixed-overlay modal at this width — it
 * becomes a normal page section that scrolls with the page,
 * mirroring the rest of the site's mobile layout (styles.css 1362+,
 * your_options.css 262+, donate-page.css 537+).
 *
 * Trade-off: distraction-free fullscreen map gone on phones;
 * mitigation is a tall explicit height — the map sits prominently
 * under the navigator panel and is still the largest single element,
 * just scrollable past instead of trapping the viewport.
 * ============================================================ */
@media (max-width: 768px) {
  /* ---- Backdrop: convert from fixed overlay to in-flow page section ---- */
  .nf-map-backdrop {
    position: static;
    padding: 0;
    background: none;
    inset: auto;
    z-index: auto;
    /* On mobile the backdrop is always in-flow once opened. Ensure it is
     * never display:none when the page loads so the in-flow layout
     * reserves no space until the button is clicked. JS controls
     * data-open and the CSS rule below shows it. */
    display: none;
  }
  .nf-map-backdrop[data-open="true"] {
    display: block;
  }

  /* ---- Modal: strip fixed dimensions, become natural block ---- */
  .nf-map-modal {
    display: block;
    height: auto;
    max-height: none;
    /* Remove overflow:hidden so the map canvas is NEVER clipped by the
     * modal's rounded-corner clip on mobile. The canvas needs its full
     * height visible; overflow:hidden on the modal is what caused the
     * WebGL context to render into a 0px clip region. */
    overflow: visible;
    /* Full-bleed on narrow phones; centered with breathing room otherwise. */
    width: min(var(--nf-maxw, 1200px), calc(100% - 16px));
    margin: 12px auto;
    border-radius: 14px;
    box-shadow: var(--nf-shadow, 0 6px 20px rgba(15,23,42,.08));
  }
  /* Page-mode height-lock override. The base page-mode rule at css:69-73
   * (`body.nf-map-page .nf-map-modal { height: min(80vh, 880px); }`) has
   * specificity (0,2,1) — without this prefix it beats the bare
   * `.nf-map-modal { height: auto }` above (0,1,0) and locks the modal
   * to 80vh on phones. With 80vh the in-flow nav reserves layout space
   * that pushes the canvas into a thin band at the bottom of the modal,
   * making the map appear to "disappear" on mobile (the user lands at
   * scroll-y=0 inside dark modal background, has to scroll to find the
   * map). Empirically verified: tests/mobile-map-diagnostic.spec.js
   * recorded modal computed height = 675.188px = 80vh of 844 before
   * this fix. Specificity of body.nf-map-page .nf-map-modal here is
   * (0,2,1) inside @media — matches page-mode and wins because it's
   * later in source order. */
  body.nf-map-page .nf-map-modal {
    height: auto;
    max-height: none;
    margin: 12px auto;
  }

  /* ---- Grid: single-column stacked layout ---- */
  .nf-map-grid {
    grid-template-columns: 1fr;
    grid-auto-rows: auto;
    /* Critical: height:auto so the grid expands to contain the canvas
     * instead of collapsing it. The desktop flex:1 + min-height:0
     * shrinks children to 0 in a fixed-height context; on mobile we
     * need the grid height to grow with content. */
    height: auto;
    /* Flex:1 must be cleared too (grid is a flex child of .nf-map-modal
     * via flex-direction:column; on mobile the modal is display:block
     * so this is moot, but belt-and-suspenders). */
    flex: none;
    min-height: 0;
  }

  /* ---- Map stage: full-width column, position:relative for overlays ---- */
  .nf-map-stage {
    /* Keep position:relative so the absolute overlays (.nf-map-counter,
     * .nf-hover-stats etc.) position themselves inside the stage. */
    position: relative;
    width: 100%;
    box-sizing: border-box;
    /* Padding reduced for mobile breathing room. */
    padding: 8px;
    /* display:flex + flex-direction:column carried from desktop is fine;
     * the canvas is flex:none with an explicit height, so it won't
     * collapse. Override min-height:0 so the stage expands correctly. */
    min-height: 0;
  }

  /* ---- Map canvas: EXPLICIT PIXEL HEIGHT — the root fix ----
   *
   * Mapbox GL JS reads the container's offsetWidth / offsetHeight at
   * init time (new mapboxgl.Map({ container: 'nfMap' })). If either
   * dimension is 0 the WebGL canvas is created at 0×0 and the map
   * never renders — this is the "map does not work at all on mobile"
   * symptom.
   *
   * aspect-ratio alone is UNRELIABLE at init because:
   *   1. The browser computes aspect-ratio height AFTER layout; if JS
   *      creates the Map() synchronously (before the next rAF), the
   *      container's offsetHeight is still 0.
   *   2. A flex:none child in a flex column with no explicit height
   *      falls back to content height = 0 when it has no children.
   *
   * FIX: set an EXPLICIT pixel height.  Use clamp() so the map is tall
   * on large phones (414px wide → 500px tall) and fits on small phones
   * (375px wide → 450px tall) without overflowing the viewport.
   *
   * Keep min-height as a hard floor and width:100% as the standard
   * Mapbox pattern. Remove flex:1 (the desktop value) so the canvas
   * does not try to fill the remaining flex space when there's none.
   * ------------------------------------------------------------------ */
  .nf-map-canvas {
    /* Explicit pixel height — the single most important rule for mobile. */
    height: clamp(300px, 75vw, 520px);
    /* Belt-and-suspenders: min-height prevents any browser from
     * collapsing below this floor even if clamp() misbehaves. */
    min-height: 300px;
    /* Do NOT use height:auto or aspect-ratio alone here — both require
     * a resolved width first, which may not exist at Map() init time. */
    width: 100%;
    /* Remove the flex:1 desktop value; the canvas should not flex-grow. */
    flex: none;
    /* Ensure the canvas is always visible — no display:none, no
     * visibility:hidden, no opacity:0. */
    display: block;
    /* overflow:hidden clips the WebGL surface on some browsers.
     * Use overflow:clip to prevent scrollbars while still allowing
     * the canvas to paint to its full declared dimensions. */
    overflow: clip;
    /* Maintain border-radius for visual polish. */
    border-radius: 10px;
  }

  /* Mapbox injects a canvas child; ensure it fills the container fully. */
  .nf-map-canvas .mapboxgl-canvas-container,
  .nf-map-canvas .mapboxgl-canvas-container.mapboxgl-interactive,
  .nf-map-canvas canvas.mapboxgl-canvas {
    width: 100% !important;
    height: 100% !important;
    /* Bug 1 (docs/architecture/nf_map_redesign_spec.md §2): pan-x/pan-y steal
     * touches from Mapbox gestures when paired with cooperativeGestures:false.
     * 'manipulation' lets Mapbox handle pan + pinch + rotate uniformly; the
     * browser still optimizes double-tap zoom inhibition. */
    touch-action: manipulation;
    pointer-events: auto !important;
  }

  /* ---- Overlay widgets: none should block touch on the canvas ---- */
  /* The counter chip stays absolute-positioned at top-right of the stage.
   * Ensure it has pointer-events:none so touches pass through to the canvas
   * when the user taps near the top-right corner of the map. */
  .nf-map-counter {
    pointer-events: none;
  }
  /* The persistent disclaimer pill is already pointer-events:none (desktop);
   * re-assert it here in case of override. */
  .nf-map-disclaimer {
    pointer-events: none;
  }

  /* ---- Splitter: always hidden on single-column mobile layout ---- */
  .nf-map-splitter { display: none !important; }

  /* ---- Navigator: OVERLAY anchored to LEFT edge of canvas ----
   * User intent (2026-05-07): nav flies out to the left (matches desktop
   * pattern), anchored to left edge of canvas, width auto-syncs to phone
   * screen via JS-managed --nf-canvas-w CSS variable.
   *
   * Position:absolute keeps the nav OFF the in-flow stack so it doesn't
   * push the canvas down (the original "map disappears" bug). Tab
   * affordance at css:171-198 lives at top-left of canvas (vertical
   * tab); panel slides in from left when tab tapped. */
  .nf-nav {
    position: absolute;
    /* Stage has padding:8px on mobile (css:2412). Match it so the nav's
     * left/top edges align with the canvas's content rect, not the
     * stage's padding edge. */
    left: 8px;
    top: 8px;
    /* Border-box so width:var includes the panel's border + padding.
     * Without this, the desktop default (content-box) inflates the
     * rendered width by border (2px) + padding (8px) past --nf-canvas-w,
     * pushing the nav past the canvas's right edge. */
    box-sizing: border-box;
    /* Width adapts to phone model via the JS-managed --nf-canvas-w CSS
     * var (ResizeObserver on .nf-map-canvas). Clamped so the nav stays
     * usable on tiny screens (≥280px) without covering the entire
     * canvas on larger phones (caps at 360px so the user sees a strip
     * of map peeking out). On a 390px iPhone the nav is ~331px (85%
     * of 390); on a 320px iPhone SE it falls to the 280 floor. JS
     * fallback if --nf-canvas-w isn't set yet: 85% of stage minus
     * padding so the nav still has a sane initial render. */
    width: clamp(280px, calc(var(--nf-canvas-w, 100%) * 0.85), 360px);
    max-width: calc(100vw - 16px);
    /* Clear desktop max-height+overflow so the panel fills its column. */
    max-height: 100vh;
    overflow-y: auto;
    /* Clear any JS-injected transform from drag-to-move sessions. */
    transform: none !important;
    resize: none;
    /* Surface scroll inside the nav body; the head's drag detection
     * (wirePanelDrag) handles long-press to drag without conflicting. */
    touch-action: pan-y;
  }

  /* ---- Expanded deck card (the "big main hospital card") ----
   * User-reported 2026-05-07: "the main card... it needs to fit to the
   * screen too, it presently does not, so it's having the same canvas
   * bug as the others did". Root: --nf-deck-expanded-w defaults to
   * 420px (css:2772) which overflows the canvas on a 390px iPhone.
   * Fix: clamp the width to the JS-managed --nf-canvas-w. We do NOT
   * change the deck's right-anchor positioning — the desktop
   * `.nf-map-deck { right: 16px }` rule + `.nf-deck-card[data-state=
   * "expanded"] { right: 0 }` keep the card anchored to the deck
   * stack's right edge, growing leftward into the canvas. With the
   * width clamp, the leftward growth fits inside the canvas instead
   * of overflowing past its left edge. The previous version (which
   * overrode left/right on this element AND the deck container) broke
   * initDeckDrag at js:3019-3050 — that code reads/writes
   * `deck.style.right` based on parent.right - deck.right and
   * conflicts with a left-anchored deck. */
  /* Specificity note: the desktop base rule .nf-deck-card[data-state=
   * "expanded"] at css:3043 is LATER in the stylesheet than this
   * @media block, so a same-specificity (0,2,0) selector loses by
   * source order. Prefixing with body.nf-map-page raises this rule to
   * (0,2,1) which beats the base (0,2,0) regardless of order. The
   * page-mode prefix is correct because this is a dedicated-page-only
   * concern (the legacy modal flow doesn't use the deck). */
  body.nf-map-page .nf-deck-card[data-state="expanded"] {
    box-sizing: border-box;
    /* clamp(280px, 95% canvas, 420px desktop max). 95% leaves a thin
     * strip of map showing on the left so the user can tell the card
     * is over the map, not full-cover. */
    width: clamp(280px, calc(var(--nf-canvas-w, 100%) * 0.95), 420px);
    max-width: calc(100vw - 16px);
    max-height: calc(100% - 32px);
  }

  /* ---- Legend: anchored TOP-RIGHT of canvas (mirrors nav top-left).
   * User intent (2026-05-07): "lets have legend flyaway to the right
   * side of map and sit on that side just as the NF navigator flysaway
   * on the left side of map". The legend now flies out to the right
   * via the .nf-map-legend[data-open="false"] translate rule; the
   * .nf-legend-tab on the right edge is the affordance to bring it
   * back. The previous bottom-docked collapse pattern is retired on
   * mobile; the – toggle is hidden (replaced by the tab). */
  .nf-map-legend {
    position: absolute;
    right: 8px;
    top: 8px;
    bottom: auto;
    left: auto;
    width: auto;
    max-width: calc(100% - 56px);   /* leave room for the .nf-nav-tab on left */
    transform: none !important;
    resize: none;
    touch-action: pan-y;
    max-height: 50vh;
    overflow-y: auto;
  }
  /* The desktop – collapse button is replaced by the right-edge tab on
   * mobile. Hide the in-head toggle so we don't surface two redundant
   * affordances. */
  .nf-legend-toggle { display: none; }
  /* Override the universal "body display:none when data-open=false"
   * rule (css:1017) on mobile so the WHOLE legend (head + body) flies
   * off-right as a unit. Without this override the body collapses to
   * 0 height before the translate animates, and the user only sees a
   * thin head-strip slide off. */
  .nf-map-legend[data-open="false"] .nf-legend-body { display: block; }
  /* No state-driven [data-collapsed="false"] / [data-open="true"]
   * override is needed here. When data-collapsed flips to "false" the
   * desktop selector .nf-nav[data-collapsed="true"] (css:160-164)
   * stops matching, so translate/opacity/pointer-events fall back to
   * the base .nf-nav rule's defaults (translate:0 0, opacity:1) and
   * the inherent pointer-events:auto. The CSS transition at css:156
   * animates the slide. Adding an !important override here was
   * defensive cruft that confused the cascade story. */

  /* Re-show the legend at <=768px even though the broader 980px rule
   * hides it. Mobile in-flow design needs the legend visible inline. */
  .nf-map-legend { display: block; }
  /* The desktop "Legend" reopen pill is irrelevant when the legend is
   * in-flow and chevron-collapsible inline. */
  .nf-legend-reopen { display: none !important; }
  /* Default scroll-friendly touch-action on the panel headers.
   * NO !important: wirePanelDrag (your_options_mapbox.js) sets
   * touchAction inline at boot ('pan-y' on mobile so vertical scroll
   * wins, 'none' once long-press / horizontal-threshold commits the
   * drag). An !important here would block the JS from arming drag
   * mode at all. CSS `auto` is the no-JS fallback default. */
  .nf-nav-head, .nf-legend-head {
    touch-action: auto;
    cursor: default;
  }

  /* ---- Map card: collapsible on mobile via chevron ---- */
  .nf-map-card .nf-card-toggle { display: inline-flex; }
  .nf-map-card[data-collapsed="1"] > .nf-card-body { display: none; }

  /* ---- Header / footer / internal padding: tighter on mobile ---- */
  .nf-map-header { padding: 12px 14px; }
  .nf-map-footer { padding: 12px 14px 14px; }
  .nf-nav-row-grid { grid-template-columns: 1fr; gap: 10px; }

  /* ---- WCAG 2.5.5 — interactive controls ≥ 44×44 CSS px on touch ---- */
  .nf-nav-menu,
  .nf-nav-settings,
  .nf-nav-locate,
  .nf-nav-reset,
  .nf-mini-detached-close,
  .nf-map-close {
    width: 44px;
    height: 44px;
  }
  .nf-mini-detached-close { font-size: 22px; }

  /* ---- Stepper: compact visual + ::before touch-halo ---- */
  .nf-nav-stepper button[data-step] {
    position: relative;
    width: 36px;
    height: 36px;
    font-size: 20px;
  }
  .nf-nav-stepper button[data-step]::before {
    content: "";
    position: absolute;
    inset: -4px;
  }
  .nf-nav-help {
    position: relative;
    width: 24px;
    height: 24px;
  }
  .nf-nav-help::before {
    content: "";
    position: absolute;
    inset: -10px;
  }

  /* ---- Cooperative gestures overlay (Mapbox touch interactivity) ----
   * When cooperativeGestures:true is set in the Map options, Mapbox
   * shows a full-canvas overlay requiring two-finger scroll. The overlay
   * uses position:absolute and covers the entire canvas. Ensure it:
   *   1. Does not block single-tap pin selection (pointer-events on the
   *      actual overlay are controlled by Mapbox internally — we cannot
   *      override without breaking the gesture logic).
   *   2. Is readable on a dark map (the overlay has its own styling from
   *      Mapbox; we just ensure our rules don't accidentally hide it). */
  .mapboxgl-cooperative-gesture-screen {
    /* Allow the native Mapbox overlay to show and function. Do not
     * set display:none or pointer-events:none here — that would break
     * the two-finger-to-scroll UX guard. */
    z-index: 16;
  }
}

/* ============================================================
 * UAT mobile rules — filter facet collapse, 44×44 picklist tap targets,
 * closest-NMP strip vertical stack, and full-width picklist popover on
 * narrow phones. Breakpoint at 640px (filter-facet collapse layer); the
 * in-flow page conversion is the separate <=768px block above.
 * ============================================================ */
@media (max-width: 640px) {
  .nf-filter-facet-toggle { display: inline-flex; }
  .nf-filter-facet[data-collapsed="true"] .nf-filter-facet-body {
    display: none;
  }
  /* WCAG 2.5.5 — interactive controls >= 44x44 CSS px on touch viewports. */
  .nf-filter-picklist {
    min-height: 44px;
    padding: 10px 12px;
  }
  .nf-filter-chip-info {
    width: 32px; height: 32px;
    padding: 6px;
  }
  /* Picklist popover goes full-width on phones so the checkbox list and
   * D6 disclosure banner stay readable. */
  .nf-nav-popover.nf-filter-pick-pop {
    left: 8px !important;
    right: 8px !important;
    max-width: calc(100vw - 16px);
  }
  .nf-filter-pick-row {
    min-height: 44px;
    padding: 10px 6px;
  }
  .nf-top-performer-strip {
    flex-direction: column;
    align-items: stretch;
  }
  .nf-top-performer-strip-cta {
    width: 100%;
    padding: 12px;
    font-size: 13px;
  }
  .nf-top-performer-strip-name { white-space: normal; }
}

/* ============================================================
 * Phone tier (<=520px): tighter padding + full-bleed feel.
 * ============================================================ */
@media (max-width: 520px) {
  .nf-map-modal {
    width: 100%;
    margin: 8px 0;
    border-radius: 0;
    box-shadow: none;
  }
  .nf-map-canvas {
    /* Narrow phones (375–520px): explicit height so Mapbox GL gets a
     * non-zero container at init time. clamp() provides a sensible range:
     *   375px phone → clamp(300, 80vw=300, 450) = 300px
     *   414px phone → clamp(300, 80vw=331, 450) = 331px
     *   520px phone → clamp(300, 80vw=416, 450) = 416px
     * This replaces the old 260px floor which was too small and unreliable.
     * The <=768px rule already sets height:clamp(300px,75vw,520px);
     * this block tightens the formula for the narrowest phones. */
    height: clamp(300px, 80vw, 450px);
    min-height: 300px;
  }
  .nf-map-header { padding: 10px 12px; }
  .nf-map-footer { padding: 10px 12px 12px; }
  .nf-map-stage  { padding: 6px; }
}

/* ============================================================================
 * §4. Hospital cards — deck (desktop) / accordion (mobile)
 *
 * The deck replaces the legacy two-card right-rail. Cards are
 * playing-card-sized (≈ 75% of a real 2.5"×3.5" deck of cards) when in
 * compact state. Compact card content is hand-rolled simple HTML built by
 * buildDeckCard() — name, city/state, median wait, 1-yr survival, age
 * badge, hero thumb. Expanded state lazy-renders the full hospital card
 * via the nfMapCardTpl template.
 *
 * Stack visual:
 *   - Top card (data-deck-pos=0): fully visible, in the deck "front" position.
 *   - Cards behind (pos=1..7): translated DOWN-RIGHT with a slight rotation,
 *     so their top edge peeks below+right of the front card — the
 *     "fan of cards on a table" feel.
 *
 * Mobile (≤768px): the deck flows below the map, full-width, no peek-stack.
 * Each card is tap-to-expand accordion-style.
 *
 * Soft cap 5 (visual fade beyond), hard cap 8 (FIFO drop in JS).
 * ========================================================================== */

/* Compact card dimensions: 75% of a real 2.5"×3.5" playing card = 1.875"×2.625"
   ≈ 180×252 at 96 DPI. */
:root {
  --nf-deck-w: 180px;
  --nf-deck-h: 252px;
  /* Vertical fan: each behind-card peeks out by --nf-deck-footer-h, which
     also sizes the hospital-name footer band so the visible peek strip
     matches the band edge-for-edge. 44px holds two lines of small text
     (hospital name + city · age) at 12px / 11px line-height. */
  --nf-deck-footer-h: 44px;
  --nf-deck-peek-y: 44px;
  --nf-deck-expanded-w: 420px;
}

/* Deck container — floats OVER the map at the top-right corner. NOT a
   rail; not a grid column. Position absolute so the map underneath stays
   full-width regardless of deck state. */
.nf-map-deck {
  position: absolute;
  top: 16px;
  right: 16px;
  z-index: 150;          /* above map pins (~10), below mini popups (200) */
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  pointer-events: none;  /* container is invisible — only cards capture clicks */
  max-height: calc(100% - 32px);
}
.nf-map-deck > *      { pointer-events: auto; } /* re-enable on interactive children */
.nf-map-deck[data-deck-state="empty"] { display: none; }

/* Floating header — small count chip + Close-all pill. Sits above the
   stack; only visible when 2+ cards are open. The class selector beats
   the user-agent [hidden]{display:none} rule, so we restate display:none
   explicitly when the JS sets header.hidden=true. Same for the close-all
   button. */
.nf-deck-header {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  margin-bottom: 8px;
  background: rgba(20, 14, 6, .82);
  color: #f7ecd6;
  border-radius: 999px;
  font-size: 11.5px;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  box-shadow: 0 4px 10px rgba(0, 0, 0, .35);
}
.nf-deck-header[hidden],
.nf-deck-closeall[hidden] { display: none !important; }
.nf-deck-count { opacity: .9; }
.nf-deck-closeall {
  background: rgba(255, 255, 255, .12);
  border: 1px solid rgba(255, 255, 255, .25);
  color: #f7ecd6;
  font-size: 11px;
  padding: 3px 9px;
  border-radius: 999px;
  cursor: pointer;
  transition: background .15s ease;
}
.nf-deck-closeall:hover { background: rgba(255, 255, 255, .25); }
.nf-deck-closeall:focus-visible { outline: 2px solid var(--nfm-sel); outline-offset: 2px; }

/* Deck stack — relative anchor for absolutely-positioned compact cards.
   Sized to hold the playing-card stack (top card + peek depth × 7 max).
   The stack stays at compact width regardless of card state; the expanded
   card uses right:0 anchoring to grow LEFTWARD past the stack's left edge
   (the deck container has overflow:visible so this is fine). */
.nf-deck-stack {
  position: relative;
  width: var(--nf-deck-w);
  /* Soft cap is 5 cards = 1 front (full height) + 4 behind (each peeking
     by --nf-deck-peek-y at the bottom). Hard cap is 8 (defensive). Size
     for the soft cap; the 6th add evicts oldest before reaching here. */
  min-height: calc(var(--nf-deck-h) + 4 * var(--nf-deck-peek-y));
}

/* The deck card wrapper. Compact = absolutely positioned within the deck
   stack (so cards can fan/peek behind each other). Expanded = the SAME
   element scales up to the full overlay width with internal scroll, holding
   the legacy main-card content (histogram, MELD ruler, wait list, program
   capabilities, SRTR risk, all of it) — see [data-state="expanded"] below. */
.nf-deck-card {
  position: absolute;
  top: 0;
  left: 0;
  width: var(--nf-deck-w);
  height: var(--nf-deck-h);
  background: linear-gradient(180deg, #fdf6e8 0%, #f4e9cf 100%);
  color: #2a1c0a;
  /* Solid stroke on every card edge so the 1/8in peek between stacked
     cards reads as a distinct boundary, not blurred-into-adjacent-card. */
  border: 1px solid #8a7340;
  border-radius: 14px;
  /* Directional shadow (down+right only, low blur) so the shadow of a
     behind card doesn't extend onto its own top/left peek edge — that
     edge stays a crisp visual line against the card stacked over it. */
  box-shadow: 4px 4px 8px rgba(0, 0, 0, .35);
  overflow: hidden;
  cursor: pointer;
  transition: transform 220ms cubic-bezier(.2,.8,.2,1),
              width 220ms cubic-bezier(.2,.8,.2,1),
              height 220ms cubic-bezier(.2,.8,.2,1),
              box-shadow 220ms ease-out,
              opacity 220ms ease-out;
  will-change: transform, width, height;
}
.nf-deck-card:hover { box-shadow: 0 10px 24px rgba(0, 0, 0, .55); }
.nf-deck-card:focus-within { outline: 2px solid var(--nfm-sel); outline-offset: 2px; }
/* Drag affordance: compact cards show grab cursor; while dragging, all
   pointer events on the deck switch to grabbing so any card under the
   pointer reads as picked-up. */
.nf-deck-card[data-state="compact"] {
  cursor: grab;
  /* Block native HTML5 drag-image gesture on touch + the text-selection
     gesture on mouse, both of which would intercept pointermove and
     prevent our drag handler from firing. */
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
}
.nf-deck-card[data-state="compact"] img {
  -webkit-user-drag: none;
  user-drag: none;
  pointer-events: none;
}
.nf-map-deck.is-dragging,
.nf-map-deck.is-dragging .nf-deck-card[data-state="compact"] { cursor: grabbing !important; }
.nf-map-deck.is-dragging .nf-deck-card { transition: none; }

/* The × close pill in the top-right corner. */
.nf-deck-x {
  position: absolute;
  top: 6px; right: 6px;
  z-index: 2;
  width: 24px; height: 24px;
  border-radius: 50%;
  border: 1px solid rgba(0,0,0,.18);
  background: rgba(255,255,255,.92);
  color: #5a2c08;
  font-size: 16px; line-height: 22px;
  cursor: pointer;
  padding: 0;
}
.nf-deck-x:hover { background: #fff; color: #b91c1c; }

/* Compact body — playing-card content layout (top to bottom):
     thumbnail → age badge → hospital name → city/state → 2 metrics → details btn */
.nf-deck-compact {
  display: flex;
  flex-direction: column;
  height: 100%;
  /* Bottom padding leaves room for the absolutely-positioned name footer
     so the Details button + stats don't run underneath it. */
  padding: 10px 12px calc(var(--nf-deck-footer-h) + 8px);
  gap: 4px;
}
.nf-deck-thumb {
  width: 100%;
  aspect-ratio: 16 / 7;
  background: linear-gradient(135deg, #2b3a52, #16202e);
  border-radius: 8px;
  overflow: hidden;
  flex: 0 0 auto;
}
.nf-deck-thumb img {
  width: 100%; height: 100%;
  object-fit: cover; object-position: center;
  display: block;
}
.nf-deck-age {
  align-self: flex-start;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: #fff;
  background: #1b4f8a;
  padding: 2px 8px;
  border-radius: 999px;
  margin-top: 6px;
}
/* Name + location now live inside .nf-deck-footer, which is the
   ~44px peek band at the bottom of every card. White-on-dark for
   strong contrast against the cream card body, so the stripe reads
   instantly when only this band is visible (peek state). */
.nf-deck-footer {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: var(--nf-deck-footer-h);
  padding: 6px 12px;
  background: linear-gradient(180deg, #1f2937 0%, #0f1825 100%);
  color: #f7ecd6;
  border-top: 1px solid rgba(255, 255, 255, .08);
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 1px;
  border-bottom-left-radius: 14px;
  border-bottom-right-radius: 14px;
  /* Clicks on the footer bubble to the wrapping .nf-deck-card click
     handler (which calls promoteToTop for behind-cards, toggleDeckCardState
     for the front card). No pointer-events:none — we want the footer
     itself to be the click target so the visible peek strip is the
     literal hit area. */
}
.nf-deck-name {
  margin: 0;
  font-size: 13px;
  line-height: 1.2;
  font-weight: 700;
  color: #f7ecd6;
  display: -webkit-box;
  -webkit-line-clamp: 1;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.nf-deck-loc {
  margin: 0;
  font-size: 10.5px;
  color: rgba(247, 236, 214, .72);
  letter-spacing: .01em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Hide the footer when the card is expanded — the expanded body has
   its own header/name treatment from the legacy template. */
.nf-deck-card[data-state="expanded"] .nf-deck-footer { display: none; }
.nf-deck-stats {
  margin: 6px 0 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 11.5px;
}
.nf-deck-stats > div {
  display: flex; justify-content: space-between;
  border-top: 1px dashed rgba(0,0,0,.18);
  padding-top: 4px;
}
.nf-deck-stats dt { font-weight: 600; color: #5a4423; margin: 0; }
.nf-deck-stats dd { font-weight: 700; color: #2a1c0a; margin: 0; }
.nf-deck-expand-btn {
  margin-top: auto;
  border: 1px solid rgba(0,0,0,.18);
  background: rgba(255,255,255,.7);
  color: #1b4f8a;
  font-size: 11px;
  font-weight: 700;
  padding: 6px 10px;
  border-radius: 8px;
  cursor: pointer;
}
.nf-deck-expand-btn:hover { background: #fff; }

/* State toggle — show compact OR expanded body, never both. */
.nf-deck-card[data-state="compact"]  .nf-deck-expanded { display: none; }
.nf-deck-card[data-state="expanded"] .nf-deck-compact  { display: none; }
/* Defensive: even if the [hidden] attribute leaks onto the expanded body,
   the expanded state must remain visible — this beats the UA [hidden] rule. */
.nf-deck-card[data-state="expanded"] .nf-deck-expanded { display: block; }

/* Expanded state: same element grows from 180×252 to 420×auto, anchored
   at the right edge of the stack so it stays in the deck's top-right
   corner (where the small card was) and extends LEFTWARD into the map.
   Background switches to a dark hospital-card surface so the legacy
   template content (which assumes dark theme) reads correctly. */
.nf-deck-card[data-state="expanded"] {
  position: absolute !important;
  top: 0 !important;
  right: 0 !important;
  left: auto !important;
  bottom: auto !important;
  transform: none !important;
  width: var(--nf-deck-expanded-w);
  height: auto;
  max-height: calc(100vh - 180px);
  background: #1f2937;       /* dark hospital-card surface */
  color: #f7ecd6;
  border: 1px solid #475569;
  border-radius: 12px;
  cursor: default;
  z-index: 30;               /* above any compact peeks behind */
  overflow-y: auto;          /* internal scroll for the tall hospital content */
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
  box-shadow: 0 12px 32px rgba(0, 0, 0, .55);
}
/* The legacy template's nested .nf-card-close (×) is redundant with our
   .nf-deck-x — hide it inside expanded bodies to avoid double × buttons. */
.nf-deck-card[data-state="expanded"] .js-card-close { display: none; }
/* Legacy template paints a "Selected" ribbon overlay; not needed inside
   the deck (every deck card is by definition selected). */
.nf-deck-card[data-state="expanded"] .nf-ribbon { display: none; }
/* Reset the legacy nf-body padding so it fits within the 420px expanded card. */
.nf-deck-card[data-state="expanded"] .nf-body { padding: 12px 14px; }
.nf-deck-card[data-state="expanded"] .nf-hero { height: 140px; }
.nf-deck-card[data-state="expanded"] .nf-deck-x {
  /* Re-style the × so it reads against the dark expanded background. */
  background: rgba(255,255,255,.12);
  border-color: rgba(255,255,255,.25);
  color: #f7ecd6;
}
.nf-deck-card[data-state="expanded"] .nf-deck-x:hover { background: rgba(255,255,255,.22); color: #fff; }

.nf-deck-collapse-btn {
  display: block;
  margin: 12px 12px 8px;
  border: 1px solid var(--nfm-border);
  background: rgba(255,255,255,.06);
  color: #f7ecd6;
  font-size: 12px;
  padding: 6px 12px;
  border-radius: 8px;
  cursor: pointer;
}
.nf-deck-collapse-btn:hover { background: rgba(255,255,255,.12); }

/* Fan-stack offset is owned by JS (applyDeckPositions) which writes
   inline transform/z-index/opacity per card index. Keeping the layout
   in JS means a single source of truth for FAN_Y, opacity ramp, and
   z-stack order — and inline styles beat any rogue CSS override (e.g.
   prefers-reduced-motion clobbering transform). Only state-agnostic
   visual treatments live here.
   Behind cards (pos>0) get a pointer cursor so the user reads the
   peek strip as clickable; the front card already shows the grab
   cursor for drag from the .nf-deck-card[data-state="compact"] rule
   above. */
.nf-deck-card[data-state="compact"][data-deck-pos]:not([data-deck-pos="0"]) {
  cursor: pointer;
}
.nf-deck-card[data-state="compact"][data-deck-pos]:not([data-deck-pos="0"]):hover .nf-deck-footer {
  /* Brighten the peek footer on hover so the user sees which card
     they're about to promote. */
  background: linear-gradient(180deg, #2a3b54 0%, #16243a 100%);
}

/* Reduced-motion users: skip the transition only. The fan-stack offset
   is static positioning (not animation) so leave transform alone —
   without it every card collapses onto the same xy coordinate and the
   "5 distinct cards" affordance is lost. */
@media (prefers-reduced-motion: reduce) {
  .nf-deck-card { transition: none; }
}

/* Mobile (≤768px): vertical stack below the map. No peek fan — every
   card is full-width and tap-to-expand inline (accordion). Map collapses
   to a sticky 35vh strip at the top so the user can scroll the deck. */
@media (max-width: 768px) {
  :root {
    --nf-deck-w: 100%;
    --nf-deck-h: auto;
  }
  .nf-deck-stack {
    min-height: 0;
    padding: 12px;
  }
  .nf-deck-card {
    position: relative;
    top: auto; left: auto;
    width: 100%;
    height: auto;
    margin-bottom: 12px;
    transform: none !important;
  }
  .nf-deck-card[data-state="compact"] { min-height: 240px; }
  .nf-deck-card[data-state="compact"][data-deck-pos] {
    transform: none !important;
    opacity: 1;
  }
}
