/* ════════════════════════════════════════════════════════════════════
   CANVASS PRO · app.css
   The command center. A premium weather-intelligence + field-sales
   instrument: dark, precise, editorial, data-dense but elegant. Character
   from STRUCTURE (hairlines, ruled rows, tabular numerics, a live feel),
   never from decoration. Left-aligned, asymmetric, confident.

   TOKEN LAW: every color, radius, and motion value is a CSS variable from
   /assets/tokens.css (spacing is hand-tuned px). Raw hex here is a defect.
   The only field-language
   colors (disposition + storm) arrive at runtime via inline style from JS,
   never written into this file. No em-dashes. Mobile-first, beautiful on
   desktop. The module surfaces (pins, stream, alerts, pro) carry their own
   token-pure CSS; this file owns the shell and the instrument frame.
   ════════════════════════════════════════════════════════════════════ */

/* ════════════════════════════════════════════════════════════════════
   0 · RESET + GROUND
   ════════════════════════════════════════════════════════════════════ */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0; background: var(--obsidian); color: var(--platinum);
  font-family: var(--body); line-height: 1.55; -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility; overflow-x: hidden;
}
a { color: inherit; text-decoration: none; }
button { font-family: inherit; cursor: pointer; color: inherit; }
input, textarea, select { font-family: inherit; }
::selection { background: color-mix(in srgb, var(--ember) 24%, transparent); color: var(--platinum); }
:focus-visible { outline: 2px solid var(--ember-hi); outline-offset: 2px; }
.skip-link { position: absolute; left: -999px; }
.skip-link:focus { left: 12px; top: 12px; z-index: 2000; background: var(--graphite); border: 1px solid var(--line-hi); border-radius: var(--r-control); padding: 8px 12px; }

/* a faint structural backdrop: two ruled hairlines bleeding off the ground,
   the "instrument grid" read, never a decorative gradient halo */
body::before {
  content: ""; position: fixed; inset: 0; z-index: -1; pointer-events: none;
  background:
    linear-gradient(var(--hairline) 1px, transparent 1px) 0 0 / 100% 96px,
    radial-gradient(120% 60% at 78% -8%, color-mix(in srgb, var(--ember) 4%, transparent), transparent 60%);
  opacity: .6;
}

/* ════════════════════════════════════════════════════════════════════
   1 · TYPOGRAPHIC UTILITIES
   ════════════════════════════════════════════════════════════════════ */
.mono { font-family: var(--mono); font-size: 11px; letter-spacing: .04em; }
.mono-cap {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--plat-faint);
}
.num { font-variant-numeric: tabular-nums; font-feature-settings: "tnum"; }
.num.gold {
  background: var(--grad-ember); -webkit-background-clip: text; background-clip: text;
  color: transparent;
}
.grow { flex: 1; min-width: 0; }
.spread { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; }

/* ════════════════════════════════════════════════════════════════════
   2 · BUTTONS · exactly ONE gold CTA per surface (brand law)
   Controls are hairline-ruled, calm, and crisp. Gold is reserved for the
   single money-moving action on a surface. The press feel is hardware.
   ════════════════════════════════════════════════════════════════════ */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  font-size: 13.5px; font-weight: 600; letter-spacing: .005em; padding: 11px 20px;
  border-radius: var(--r-control); border: 1px solid var(--line-hi);
  background: var(--graphite-2); color: var(--platinum);
  white-space: nowrap; box-shadow: var(--e1);
  /* the press-language group in 16.1 owns the transition */
}
.btn:hover { border-color: var(--plat-faint); background: var(--graphite-3); box-shadow: var(--e2); }
.btn:active { background: var(--graphite-2); box-shadow: var(--e-press); }
.btn:focus-visible { outline: none; box-shadow: var(--ring-ember); }
.btn-sm { padding: 0 14px; min-height: 36px; font-size: 12.5px; }
.btn-gold-sm {
  background: var(--grad-ember); color: var(--ember-ink); border: none; font-weight: 700;
  box-shadow: var(--e2), inset 0 1px 0 color-mix(in srgb, var(--ember-hi) 60%, transparent);
}
.btn-gold-sm:hover { background: var(--ember-hi); border: none; box-shadow: var(--e2), var(--ring-ember); }
.fm-press { transition: transform var(--m-fast) var(--ease-spring); }
.fm-press:active { transform: scale(.96); }
@media (prefers-reduced-motion: reduce) { .fm-press:active { transform: none; } }

/* ════════════════════════════════════════════════════════════════════
   3 · STATUS CHIPS · small ruled lozenges, never bubbly, never glowing
   ════════════════════════════════════════════════════════════════════ */
.chip {
  display: inline-block; font-family: var(--mono); font-size: 9.5px; letter-spacing: .14em;
  text-transform: uppercase; line-height: 1; border-radius: var(--r-chip);
  padding: 4px 7px; white-space: nowrap; vertical-align: middle;
  border: 1px solid transparent;
}
.chip.ok   { color: var(--green); background: var(--tint-green); border-color: color-mix(in srgb, var(--green) 30%, transparent); }
.chip.warn { color: var(--amber); background: var(--tint-amber); border-color: color-mix(in srgb, var(--amber) 30%, transparent); }
.chip.bad  { color: var(--red-text);   background: var(--tint-red);   border-color: color-mix(in srgb, var(--red) 30%, transparent); }
.chip.info { color: var(--trust-text); background: var(--tint-trust); border-color: color-mix(in srgb, var(--trust) 30%, transparent); }

/* ════════════════════════════════════════════════════════════════════
   4 · THE SHELL · topbar (the command bar header) + view
   The topbar carries the brand, the live weather telemetry, the mode badge,
   the sync state, and the alerts bell. A single ruled bar that feels live.
   ════════════════════════════════════════════════════════════════════ */
.topbar {
  /* z above the searchwrap (40) so the bar stays on top once the page scrolls;
     viewport-fit=cover means the notch insets must pad the bar itself */
  position: sticky; top: 0; z-index: 100; display: flex; align-items: center; gap: 14px;
  height: calc(58px + env(safe-area-inset-top));
  padding: env(safe-area-inset-top) max(18px, env(safe-area-inset-right)) 0 max(18px, env(safe-area-inset-left));
  background: var(--header-bg);
  -webkit-backdrop-filter: saturate(150%) blur(12px); backdrop-filter: saturate(150%) blur(12px);
  border-bottom: 1px solid var(--line);
}
.tb-brand {
  display: inline-flex; align-items: baseline; gap: .5em;
  font-family: var(--disp); font-size: 13px; letter-spacing: .16em; text-transform: uppercase;
  color: var(--platinum);
}
.tb-brand .tb-mark { align-self: center; flex: none; display: block; }
.tb-brand .room { color: var(--ember); }
.tb-right { margin-left: auto; display: flex; align-items: center; gap: 10px; }
.mode-badge {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--plat-faint); border: 1px solid var(--line); border-radius: var(--r-chip);
  padding: 5px 9px; white-space: nowrap;
}
.mode-badge::before { content: ""; width: 5px; height: 5px; border-radius: 50%; background: var(--plat-faint); flex-shrink: 0; }
.mode-badge.composed { color: var(--ember); border-color: color-mix(in srgb, var(--ember) 40%, var(--line)); }
.mode-badge.composed::before { background: var(--ember); box-shadow: 0 0 0 3px color-mix(in srgb, var(--ember) 22%, transparent); }
.sync {
  display: inline-flex; align-items: center; gap: 7px; font-size: 12.5px; font-weight: 600;
  color: var(--green); white-space: nowrap; font-variant-numeric: tabular-nums;
}
.sync::before { content: ""; width: 6px; height: 6px; border-radius: 1.5px; background: currentColor; flex-shrink: 0; }
.sync.queued { color: var(--amber); }
.sync.queued::before { animation: syncBlink 1.1s var(--ease) infinite; }
.sync.offline { color: var(--plat-faint); }
@keyframes syncBlink { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }
@media (prefers-reduced-motion: reduce) { .sync.queued::before { animation: none; } }

/* the alerts bell slot just holds the module-rendered bell button */
.tb-bell-slot { display: inline-flex; align-items: center; }

/* ── topbar weather telemetry · "money in the air right now" ──────────
   A one-line readout colored by the worst active cell (--c arrives inline).
   Faint when the sky is clear; lit and pulsing when the live stream is on. */
.wx-readout {
  display: inline-flex; align-items: center; gap: 8px;
  height: 34px; padding: 0 11px;
  background: color-mix(in srgb, var(--graphite-2) 70%, transparent);
  border: 1px solid var(--line); border-radius: var(--r-control);
  color: var(--platinum); white-space: nowrap;
  /* transform rides along so the .fm-press spring survives this later declaration */
  transition: transform var(--m-fast) var(--ease-spring), border-color var(--m-fast) var(--ease), background var(--m-fast) var(--ease);
}
.wx-readout:hover { border-color: var(--plat-faint); background: var(--graphite); }
.wx-readout .wx-dot {
  width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0;
  background: var(--c, var(--plat-faint));
}
.wx-readout.live { border-color: color-mix(in srgb, var(--c, var(--amber)) 50%, var(--line)); }
.wx-readout.live .wx-dot {
  box-shadow: 0 0 0 0 color-mix(in srgb, var(--c, var(--amber)) 55%, transparent);
  animation: wxBeat 1.6s var(--ease) infinite;
}
@keyframes wxBeat { 0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--c, var(--amber)) 55%, transparent); } 70% { box-shadow: 0 0 0 6px transparent; } 100% { box-shadow: 0 0 0 0 transparent; } }
@media (prefers-reduced-motion: reduce) { .wx-readout.live .wx-dot { animation: none; } }
.wx-readout.quiet .wx-dot { background: var(--plat-faint); box-shadow: none; }
.wx-fig { font-size: 12px; font-weight: 650; font-variant-numeric: tabular-nums; color: var(--platinum); }
.wx-readout.quiet .wx-fig { color: var(--plat-faint); font-weight: 500; }
.wx-sep { color: var(--plat-faint); }
/* the live readout figures lean into the cell color for the "money" read */
.wx-readout.live .wx-fig:last-of-type { color: var(--c, var(--amber)); }
/* a thumb-sized seat on touch screens; the visual stays a slim readout */
@media (pointer: coarse) { .wx-readout { min-height: 40px; } }

.view { display: block; padding: 16px 18px 30px; max-width: var(--max-w); margin: 0 auto; }
.map-foot { margin-top: 12px; }
@media (max-width: 720px) {
  .tb-right { gap: 8px; }
  .mode-badge { padding: 5px 7px; }
}
@media (max-width: 640px) {
  .view { padding: 12px 12px 24px; }
  .topbar { padding: env(safe-area-inset-top) max(12px, env(safe-area-inset-right)) 0 max(12px, env(safe-area-inset-left)); gap: 9px; height: calc(54px + env(safe-area-inset-top)); }
  /* on a phone the telemetry stays; the mode label can hide its text but keep its dot */
  .sync { font-size: 11.5px; }
}

/* ════════════════════════════════════════════════════════════════════
   5 · SEARCH · target an address / business / city / zip, jump the map
   ════════════════════════════════════════════════════════════════════ */
.searchwrap { position: relative; z-index: 40; margin-bottom: 14px; max-width: 580px; }
.searchbar {
  display: flex; align-items: center; gap: 10px; height: 48px; padding: 0 12px 0 14px;
  background: var(--graphite-2); border: 1px solid var(--line-hi); border-radius: var(--r-control);
  transition: border-color var(--m-fast) var(--ease), box-shadow var(--m-fast) var(--ease);
}
.searchbar:focus-within { border-color: var(--ember); box-shadow: var(--ring-ember); }
.search-ico { color: var(--plat-faint); flex-shrink: 0; transition: color var(--m-fast) var(--ease); }
.searchbar:focus-within .search-ico { color: var(--ember); }
#searchInput { flex: 1; min-width: 0; background: none; border: none; outline: none; color: var(--platinum); font: 500 15px var(--body); }
#searchInput::placeholder { color: var(--plat-faint); }
#searchInput::-webkit-search-cancel-button { display: none; }
.search-clear { position: relative; flex-shrink: 0; width: 27px; height: 27px; border: 1px solid var(--line); border-radius: var(--r-chip); background: none; color: var(--plat-dim); display: inline-flex; align-items: center; justify-content: center; }
.search-clear::before { content: ""; position: absolute; inset: -9px; }   /* 45px touch target, visual unchanged */
.search-clear:hover { color: var(--platinum); border-color: var(--plat-faint); }
.search-results {
  position: absolute; left: 0; right: 0; top: calc(100% + 6px); z-index: 50;
  background: var(--graphite); border: 1px solid var(--line-hi); border-radius: var(--r-card);
  box-shadow: var(--e3); overflow: hidden; max-height: 62vh; overflow-y: auto;
  animation: sheetUp 180ms var(--ease-exit);
}
.sr-group {
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .16em; text-transform: uppercase;
  color: var(--plat-faint); padding: 12px 14px 7px; background: var(--graphite-2);
  border-bottom: 1px solid var(--line);
}
.sr-row {
  display: flex; align-items: center; gap: 11px; width: 100%; text-align: left;
  padding: 12px 14px; background: none; border: none; border-bottom: 1px solid var(--line);
  color: var(--platinum); transition: background var(--m-fast) var(--ease);
}
.sr-row:last-child { border-bottom: none; }
.sr-row:hover, .sr-row.active { background: var(--tint-hover); }
.sr-row .sr-dot { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; }
.sr-row .sr-ico { color: var(--plat-faint); flex-shrink: 0; display: inline-flex; }
.sr-row .sr-text { min-width: 0; flex: 1; }
.sr-row .sr-head { font-size: 14px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sr-row .sr-tail { font-size: 12px; color: var(--plat-faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-top: 1px; }
.sr-row .sr-add { flex-shrink: 0; }
.sr-state { padding: 14px; font-size: 13px; color: var(--plat-faint); }
.sr-state.loading { color: var(--ember); }
.sr-state.loading::before { content: ""; display: inline-block; width: 7px; height: 7px; margin-right: 8px; border-radius: 50%; background: var(--ember); vertical-align: middle; animation: wxBeat 1.4s var(--ease) infinite; }
@media (prefers-reduced-motion: reduce) { .sr-state.loading::before { animation: none; } }
.fm-search-pin span { display: block; width: 14px; height: 14px; border-radius: 50% 50% 50% 0; transform: rotate(-45deg); background: var(--ember); border: 2px solid var(--obsidian); box-shadow: 0 0 0 3px color-mix(in srgb, var(--ember) 28%, transparent); }
@media (max-width: 640px) { .searchwrap { max-width: none; } }

/* ════════════════════════════════════════════════════════════════════
   6 · TOASTS · ruled cards, the system speaking quietly
   ════════════════════════════════════════════════════════════════════ */
.toasts { position: fixed; top: 66px; right: 16px; z-index: 1300; display: flex; flex-direction: column; gap: 8px; width: min(340px, calc(100vw - 32px)); pointer-events: none; }
.toast {
  pointer-events: auto;
  background: var(--graphite); border: 1px solid var(--line-hi); border-left: 2px solid var(--ember);
  border-radius: var(--r-control); padding: 11px 14px; font-size: 13.5px; line-height: 1.5;
  color: var(--platinum); box-shadow: 0 12px 34px rgba(0,0,0,.4);
  animation: sheetUp 220ms var(--ease-exit);
}
.toast .t-kind { font-family: var(--mono); font-size: 9.5px; letter-spacing: .14em; text-transform: uppercase; color: var(--ember); display: block; margin-bottom: 3px; }
.toast.gone { opacity: 0; transition: opacity var(--m-base) var(--ease); }

/* ════════════════════════════════════════════════════════════════════
   7 · THE FIELD INSTRUMENT · the real map (fieldmap.js), the product
   The frame is a ruled card; the map fills it; the readout + legend rule
   underneath. Leaflet overrides keep the chrome token-pure and quiet.
   ════════════════════════════════════════════════════════════════════ */
.map-stage { position: relative; }
.fieldmap {
  height: clamp(440px, calc(100vh - 372px), 760px);
  height: clamp(440px, calc(100dvh - 372px), 760px);
  border: 1px solid var(--line); border-radius: var(--r-card);
  overflow: hidden; background: var(--obsidian);
  isolation: isolate;   /* contain Leaflet's z-index panes so the sheet sits above */
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--platinum) 2%, transparent);
}
.fieldmap.fm-add, .fieldmap.fm-draw { cursor: crosshair; }

/* ── territory crafting handles · drag the gold corners to shape a zone,
      pull a midpoint out to add a corner ─────────────────────────────── */
.fm-vertex {
  box-sizing: border-box; border-radius: 50%;
  background: var(--ember); border: 2px solid var(--obsidian);
  box-shadow: 0 1px 5px rgba(0,0,0,.55), 0 0 0 1px color-mix(in srgb, var(--ember) 55%, transparent);
  cursor: grab; transition: transform var(--m-fast) var(--ease-spring), box-shadow var(--m-fast) var(--ease);
}
.fm-vertex:hover { transform: scale(1.22); box-shadow: 0 2px 8px rgba(0,0,0,.6), 0 0 0 3px color-mix(in srgb, var(--ember) 30%, transparent); }
.fm-vertex:active { cursor: grabbing; transform: scale(1.1); }
.fm-vertex-mid {
  box-sizing: border-box; border-radius: 50%;
  background: color-mix(in srgb, var(--ember) 30%, var(--obsidian));
  border: 1.5px dashed color-mix(in srgb, var(--ember) 75%, transparent);
  opacity: .72; cursor: copy; transition: opacity var(--m-fast) var(--ease), transform var(--m-fast) var(--ease-spring);
}
.fm-vertex-mid:hover { opacity: 1; transform: scale(1.25); }
@media (prefers-reduced-motion: reduce) {
  .fm-vertex, .fm-vertex-mid { transition: none; }
  .fm-vertex:hover, .fm-vertex-mid:hover { transform: none; }
}
.leaflet-container { background: var(--obsidian); font-family: var(--body); }
.leaflet-container .leaflet-control-attribution { background: var(--header-bg); color: var(--plat-faint); font-size: 9.5px; padding: 2px 6px; }
.leaflet-container .leaflet-control-attribution a { color: var(--plat-dim); }
.leaflet-bar { border: 1px solid var(--line) !important; box-shadow: 0 4px 14px rgba(0,0,0,.3) !important; border-radius: var(--r-control) !important; overflow: hidden; }
.leaflet-bar a { background: var(--graphite-2) !important; color: var(--platinum) !important; border-bottom: 1px solid var(--line) !important; width: 32px !important; height: 32px !important; line-height: 32px !important; }
.leaflet-bar a:hover { background: var(--graphite) !important; }
.leaflet-bar a:first-child { border-top-left-radius: var(--r-control); border-top-right-radius: var(--r-control); }
.leaflet-bar a:last-child { border-bottom-left-radius: var(--r-control); border-bottom-right-radius: var(--r-control); }
.leaflet-tooltip { background: var(--graphite-2); color: var(--platinum); border: 1px solid var(--line-hi); border-radius: var(--r-chip); font: 500 12px var(--body); box-shadow: none; padding: 4px 8px; }
.leaflet-tooltip-top:before { border-top-color: var(--line-hi); }

/* ── teardrop / coin pin animation hooks (kept; pins.js reuses these) ── */
.fm-pin { background: none; border: none; }
.fm-tear { filter: drop-shadow(0 2px 3px rgba(0,0,0,.4)); transition: transform var(--m-fast) var(--ease-spring); }
.fm-tear.pop { filter: drop-shadow(0 3px 6px rgba(0,0,0,.5)); }
/* .fm-tear.stamp animates in pins.css (pinCoinStamp owns the stamp beat) */
.fm-pin-un .fm-dot { display: block; width: 11px; height: 11px; border-radius: 50%; background: transparent; border: 1.5px solid var(--plat-faint); opacity: .65; }
@media (prefers-color-scheme: light) { .fm-pin-un .fm-dot { border-color: var(--plat-dim); background: color-mix(in srgb, var(--graphite) 50%, transparent); } }
.fm-stop { background: var(--ember); color: var(--ember-ink); font: 700 10px var(--mono); border-radius: 50%; display: flex; align-items: center; justify-content: center; border: 2px solid var(--obsidian); box-shadow: 0 1px 3px rgba(0,0,0,.4); }
.fm-terr-label { background: none !important; border: none !important; box-shadow: none !important; color: var(--platinum); font: 700 11px var(--body) !important; letter-spacing: .02em; text-shadow: 0 1px 3px rgba(0,0,0,.6); }
@media (prefers-color-scheme: light) { .fm-terr-label { color: var(--platinum); text-shadow: 0 1px 2px rgba(255,255,255,.7); } }

/* ── hot-lead pin halo · DataGrid says knock here first ─────────────── */
.fm-hot { overflow: visible; }
.fm-hot .fm-dot { border-color: var(--ember); background: color-mix(in srgb, var(--ember) 22%, transparent); }
.fm-hot-ring { position: absolute; left: 50%; top: 50%; width: 22px; height: 22px; margin: -11px 0 0 -11px; border-radius: 50%; border: 1.5px solid var(--ember); opacity: .7; animation: hotPulse 2.2s var(--ease) infinite; }
@keyframes hotPulse { 0% { transform: scale(.7); opacity: .8; } 70% { transform: scale(1.25); opacity: 0; } 100% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .fm-hot-ring { animation: none; } }

/* ── storm map layer ────────────────────────────────────────────────── */
.fm-storm-tag span { display: inline-block; white-space: nowrap; font: 700 10px var(--mono); letter-spacing: .04em; color: var(--sc); background: var(--obsidian); border: 1px solid var(--sc); border-radius: var(--r-chip); padding: 2px 6px; opacity: .95; }
@media (prefers-color-scheme: light) { .fm-storm-tag span { background: var(--graphite-2); } }
.fm-storm-cell span { display: block; width: 12px; height: 12px; border-radius: 50%; background: var(--sc); border: 2px solid var(--obsidian); box-shadow: 0 0 0 3px color-mix(in srgb, var(--sc) 30%, transparent); }

/* the map readout line + legend, ruled under the frame */
.map-foot { font-family: var(--mono); font-size: 10.5px; letter-spacing: .1em; text-transform: uppercase; color: var(--plat-faint); }
.map-legend { display: flex; gap: 14px; flex-wrap: wrap; padding: 10px 2px 0; font-family: var(--mono); font-size: 9.5px; letter-spacing: .1em; text-transform: uppercase; color: var(--plat-faint); }
.map-legend span { display: inline-flex; align-items: center; }

/* ════════════════════════════════════════════════════════════════════
   8 · THE COMMAND BAR · Run HUD (today's momentum) + rank chip
   The engagement engine: a goal ring, the knock funnel, the set rate, and
   the rank chip. Big tabular figures, mono labels, hairline rails.
   ════════════════════════════════════════════════════════════════════ */
.run-hud {
  position: relative; display: flex; align-items: center; gap: 24px; flex-wrap: wrap;
  padding: 15px 20px; margin-bottom: 14px;
  background:
    linear-gradient(180deg, color-mix(in srgb, var(--ember) 2%, var(--graphite-2)), var(--graphite-2));
  border: 1px solid var(--line); border-radius: var(--r-card);
  box-shadow: inset 0 1px 0 color-mix(in srgb, var(--platinum) 4%, transparent);
}
.rh-ring { position: relative; width: 60px; height: 60px; flex-shrink: 0; }
/* the goal ring pulses a single beat each time a knock advances it */
.goal-ring .gr-fill { transition: stroke-dashoffset var(--m-enter) var(--ease-exit), stroke var(--m-pulse) var(--ease); }
.goal-ring .gr-fill.full { filter: drop-shadow(0 0 6px color-mix(in srgb, var(--ember) 55%, transparent)); }
.rh-ring-c { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; line-height: 1; }
.rh-goal-n { font-size: 17px; font-weight: 750; letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.rh-goal-of { font-family: var(--mono); font-size: 10px; color: var(--plat-faint); margin-top: 2px; }
.rh-funnel { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }
.rh-stat { display: flex; flex-direction: column; gap: 4px; }
.rh-v { font-size: 23px; font-weight: 750; letter-spacing: -.025em; line-height: 1; font-variant-numeric: tabular-nums; }
.rh-v.gold { background: var(--grad-ember); -webkit-background-clip: text; background-clip: text; color: transparent; }
.rh-k { font-family: var(--mono); font-size: 10px; letter-spacing: .14em; text-transform: uppercase; color: var(--plat-faint); }
.rh-arrow { color: var(--line-hi); font-size: 17px; line-height: 1; }
@media (max-width: 720px) {
  .run-hud { gap: 14px; padding: 13px 14px; }
  .rh-funnel { gap: 14px; width: 100%; justify-content: space-between; }
  .rh-arrow { display: none; }
  .rh-v { font-size: 20px; }
}

/* ── the rank chip · level ring + rank name, opens the leaderboard ──── */
.rank-chip { display: inline-flex; align-items: center; gap: 9px; margin-left: auto; background: color-mix(in srgb, var(--obsidian) 50%, transparent); border: 1px solid var(--line); border-radius: var(--r-control); padding: 6px 13px 6px 7px; }
.rank-chip:hover { border-color: var(--plat-faint); }
.rank-ring .rk-fill { transition: stroke-dashoffset var(--m-enter) var(--ease-exit); }
.rk-meta { display: flex; flex-direction: column; line-height: 1.15; text-align: left; }
.rk-rank { font-size: 13px; font-weight: 700; color: var(--platinum); letter-spacing: .005em; }
.rk-xp { font: 500 10px var(--mono); letter-spacing: .06em; color: var(--plat-faint); }
@media (max-width: 720px) { .rank-chip { margin-left: 0; } }

/* ════════════════════════════════════════════════════════════════════
   9 · THE MAP TOOLBAR · mode segmented control + tools + filters
   ════════════════════════════════════════════════════════════════════ */
.map-bar { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; margin-bottom: 12px; }
.map-bar .r { margin-left: auto; }
.seg { display: inline-flex; border: 1px solid var(--line-hi); border-radius: var(--r-control); overflow: hidden; background: var(--graphite-2); }
.seg-b { font: 600 13px var(--body); padding: 0 18px; min-height: 40px; background: none; border: none; border-right: 1px solid var(--line); color: var(--plat-dim); }
.seg-b:last-child { border-right: none; }
.seg-b:hover { color: var(--platinum); background: var(--tint-hover); }
.seg-b.on { color: var(--ember-ink); background: var(--grad-ember); font-weight: 700; }
/* .seg clips its radius, so the keyboard ring must sit INSIDE the button box */
.seg-b:focus-visible { outline: 2px solid var(--ember-hi); outline-offset: -2px; }
.btn.storm-on { border-color: color-mix(in srgb, var(--ember) 55%, var(--line-hi)); color: var(--ember); background: color-mix(in srgb, var(--ember) 7%, transparent); }
.btn.field-on { border-color: color-mix(in srgb, var(--amber) 50%, var(--line-hi)); color: var(--amber); background: color-mix(in srgb, var(--amber) 7%, transparent); }

.map-filters { display: flex; gap: 7px; flex-wrap: wrap; align-items: center; margin-bottom: 12px; }
.fchip {
  display: inline-flex; align-items: center; font: 500 11px var(--mono); letter-spacing: .08em; text-transform: uppercase;
  padding: 0 12px; min-height: 36px; border: 1px solid var(--line); border-radius: var(--r-chip);
  color: var(--plat-dim); background: none;
}
.fchip:hover { color: var(--platinum); border-color: var(--line-hi); }
.fchip.on { color: var(--platinum); border-color: var(--plat-faint); background: var(--tint-hover); }
.fdivider { width: 1px; align-self: stretch; min-height: 24px; background: var(--line); margin: 0 4px; }
.fm-swatch { display: inline-block; width: 9px; height: 9px; border-radius: 50%; margin-right: 7px; vertical-align: -1px; }
.fchip .fm-swatch { width: 8px; height: 8px; margin-right: 7px; }

/* ── mode banners · the one obvious instruction per mode ────────────── */
.map-banner { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; padding: 11px 16px; margin-bottom: 12px; border: 1px solid var(--line); border-radius: var(--r-card); font-size: 13.5px; color: var(--plat-dim); background: var(--graphite-2); }
.map-banner .mb-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
.map-banner.add { border-color: color-mix(in srgb, var(--trust) 45%, var(--line)); }
.map-banner.add .mb-dot { background: var(--trust); box-shadow: 0 0 0 3px color-mix(in srgb, var(--trust) 22%, transparent); }
.map-banner.draw { border-color: color-mix(in srgb, var(--ember) 50%, var(--line)); }
.map-banner.draw .mb-dot { background: var(--ember); box-shadow: 0 0 0 3px color-mix(in srgb, var(--ember) 22%, transparent); }
.map-banner.draw b { color: var(--ember); font-variant-numeric: tabular-nums; }
/* .knock wears the base banner surface; no override needed */
.map-banner.rapid { border-color: color-mix(in srgb, var(--ember) 55%, var(--line)); background: color-mix(in srgb, var(--ember) 6%, var(--graphite-2)); }
.map-banner .mb-strong { font-weight: 700; color: var(--ember); }
.map-banner .mb-arm { color: var(--plat-dim); }
.map-banner .r, .map-banner > button:last-child { margin-left: auto; }
.rapid-pick { display: flex; gap: 6px; flex-wrap: wrap; }
.dispo-chip { display: inline-flex; align-items: center; }
.dispo-chip .fm-swatch { width: 8px; height: 8px; margin-right: 6px; }
.dispo-chip.on { color: var(--platinum); border-color: var(--plat-faint); background: var(--tint-hover); }

@media (max-width: 640px) {
  .fieldmap { height: calc(100dvh - 442px); min-height: 360px; }
  .seg { width: 100%; }
  .seg-b { flex: 1; padding: 0 8px; }
}

/* the undo chip floats over the map bottom */
.fm-undo {
  position: sticky; bottom: 14px; z-index: 70; display: flex; align-items: center; justify-content: space-between; gap: 14px;
  margin: -58px 14px 14px; padding: 8px 10px 8px 16px;
  background: var(--graphite-2); border: 1px solid var(--line-hi); border-radius: var(--r-card);
  font-size: 13.5px; box-shadow: var(--e3); animation: sheetUp 240ms var(--ease-exit);
}
.fm-undo[hidden] { display: none; }

/* ════════════════════════════════════════════════════════════════════
   10 · THE DOOR SHEET · score + enrich + the next-action law
   A right-docked panel on desktop, a bottom sheet on mobile. Every door
   has a next action; no door is a dead end.
   ════════════════════════════════════════════════════════════════════ */
#sheetScrim { position: fixed; inset: 0; background: var(--scrim); z-index: 1190; opacity: 0; pointer-events: none; transition: opacity var(--m-base) var(--ease); }
#sheetScrim.on { opacity: 1; pointer-events: auto; }
.sheet {
  position: fixed; left: 50%; transform: translateX(-50%); bottom: 0; width: min(560px, 100%);
  background: var(--graphite); border: 1px solid var(--line-hi); border-bottom: none; border-radius: var(--r-card) var(--r-card) 0 0;
  z-index: 1200; padding: 12px 20px max(18px, env(safe-area-inset-bottom)); box-shadow: var(--e3), var(--e-inset);
  max-height: 88dvh; overflow-y: auto;
  /* sheetUpC keeps the translateX(-50%) centering through the entrance */
  animation: sheetUpC 260ms var(--ease-exit);
}
@media (min-width: 721px) {
  .sheet { left: auto; right: 22px; bottom: 22px; transform: none; width: 380px; border: 1px solid var(--line-hi); border-radius: var(--r-card); animation-name: sheetUp; }
  #sheetScrim { background: transparent; }
  /* the docked panel must not deaden the map: clicks pass through; Escape
     and the close button still dismiss */
  #sheetScrim.on { pointer-events: none; }
}
.sheet-grip { width: 36px; height: 4px; border-radius: 2px; background: var(--line-hi); margin: 2px auto 12px; }
@media (min-width: 721px) { .sheet-grip { display: none; } }
.sheet-head { display: flex; align-items: flex-start; gap: 12px; margin-bottom: 14px; }
.sheet-head strong { font-size: 16px; letter-spacing: -.01em; line-height: 1.3; }
.sheet-sub { margin-top: 5px; font-size: 12.5px; color: var(--plat-dim); display: flex; align-items: center; flex-wrap: wrap; gap: 2px; }
.sheet-status { display: inline-flex; align-items: center; font-weight: 650; }
.sheet-x { position: relative; background: none; border: 1px solid var(--line-hi); border-radius: var(--r-control); color: var(--plat-dim); width: 30px; height: 30px; flex-shrink: 0; font-size: 13px; display: inline-flex; align-items: center; justify-content: center; }
.sheet-x::before { content: ""; position: absolute; inset: -9px; }   /* 48px touch target, visual unchanged */
.sheet-x:hover { color: var(--platinum); border-color: var(--plat-faint); }
/* ── the door-sheet segmented control · one read at a time ────────── */
.sheet-seg { display: inline-flex; width: 100%; border: 1px solid var(--line-hi); border-radius: var(--r-control); overflow: hidden; background: var(--graphite-2); margin-bottom: 16px; }
.sheet-seg .ssg-b { flex: 1; font: 600 12.5px var(--body); padding: 0 12px; min-height: 38px; background: none; border: none; border-right: 1px solid var(--line); color: var(--plat-dim); }
.sheet-seg .ssg-b:last-child { border-right: none; }
.sheet-seg .ssg-b:hover { color: var(--platinum); background: var(--tint-hover); }
.sheet-seg .ssg-b.on { color: var(--ember-ink); background: var(--grad-ember); font-weight: 700; }
.sheet-seg .ssg-b:focus-visible { outline: 2px solid var(--ember-hi); outline-offset: -2px; }
.ssheet-view[hidden] { display: none; }
.ssheet-view > .next-action { margin-top: 0; }
.sheet-title { font-size: 14px; font-weight: 650; letter-spacing: -.01em; color: var(--platinum); margin-bottom: 10px; }
.sheet-owner-empty { font-size: 13px; color: var(--plat-dim); line-height: 1.5; margin-bottom: 4px; }
.sheet-tools-log { margin-top: 12px; }
.sheet-tools-log .btn { flex: 1; }
.sheet-label { font-family: var(--mono); font-size: 9.5px; letter-spacing: .16em; text-transform: uppercase; color: var(--plat-faint); margin-bottom: 8px; }
.sheet-acts { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; }
.sheet-acts .dispo { display: flex; align-items: center; gap: 9px; min-height: 50px; padding: 0 14px; background: var(--obsidian); border: 1px solid var(--line); border-radius: var(--r-control); color: var(--platinum); font-size: 14px; font-weight: 600; text-align: left; }
.sheet-acts .dispo:hover { border-color: color-mix(in srgb, var(--dc) 60%, var(--line-hi)); }
.sheet-acts .dispo.on { border-color: var(--dc); background: color-mix(in srgb, var(--dc) 14%, var(--obsidian)); box-shadow: inset 2px 0 0 var(--dc); }
.sheet-acts .dispo .fm-swatch { width: 12px; height: 12px; margin: 0; }
.sheet-tools { display: flex; gap: 8px; margin-top: 12px; flex-wrap: wrap; }
.sheet-tools .btn { flex: 1; min-width: 0; }
.sheet-tools .sheet-del { color: var(--red); border-color: color-mix(in srgb, var(--red) 35%, var(--line-hi)); }
.sheet-tools .sheet-del:hover { border-color: var(--red); background: color-mix(in srgb, var(--red) 8%, transparent); }
/* a Pro badge sitting next to a gated tool reads inline, not floating */
.sheet-tools .pro-badge { align-self: center; }
.sheet-note { display: flex; gap: 8px; margin-top: 12px; }
.sheet-note input { flex: 1; background: var(--obsidian); border: 1px solid var(--line-hi); border-radius: var(--r-control); color: var(--platinum); padding: 11px 13px; font-size: 16px; transition: border-color var(--m-fast) var(--ease); }
.sheet-note input:focus { outline: none; border-color: var(--ember); }

/* ── the next-action law · no door is a dead end ──────────────────── */
.next-action { display: flex; align-items: center; gap: 11px; margin: 4px 0 14px; padding: 11px 13px; border: 1px solid color-mix(in srgb, var(--ember) 40%, var(--line)); border-radius: var(--r-control); background: color-mix(in srgb, var(--ember) 5%, transparent); }
.next-action .na-k { display: block; font: 500 10px var(--mono); letter-spacing: .14em; text-transform: uppercase; color: var(--ember); }
.next-action .na-v { display: block; font-size: 13.5px; color: var(--platinum); margin-top: 2px; }
.next-action .na-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--ember); flex-shrink: 0; box-shadow: 0 0 0 3px color-mix(in srgb, var(--ember) 20%, transparent); }

/* ── DataGrid AI score block · explainable, never a black box ──────── */
.score-block { display: flex; align-items: center; gap: 14px; padding: 13px 14px; margin-bottom: 14px; border: 1px solid var(--line); border-radius: var(--r-card); background: var(--obsidian); }
.score-block.hot { border-color: color-mix(in srgb, var(--ember) 55%, var(--line)); color: var(--ember); }
.score-block.warm { border-color: color-mix(in srgb, var(--trust) 45%, var(--line)); color: var(--trust); }
.score-block.cool { color: var(--plat-faint); }
.score-ring { flex-shrink: 0; }
.score-ring .sc-fill { transition: stroke-dashoffset 600ms var(--ease-exit); }
.score-meta { min-width: 0; }
.score-lab { font-size: 13.5px; font-weight: 700; color: var(--platinum); }
.score-lab .mono-cap { color: var(--plat-faint); margin-left: 6px; }
.score-why { display: flex; flex-direction: column; gap: 2px; margin-top: 5px; font-size: 11.5px; color: var(--plat-dim); }
.score-why b { color: var(--platinum); font-variant-numeric: tabular-nums; }
.score-more { display: inline-flex; align-items: center; gap: 7px; margin-top: 7px; background: none; border: none; padding: 0; font: 600 11px var(--mono); letter-spacing: .08em; text-transform: uppercase; color: var(--ember); }
.score-more:hover { color: var(--ember-hi); }
/* a Pro badge after the breakdown control sits inline with it */
.score-meta .pro-badge { margin-top: 7px; margin-left: 8px; vertical-align: middle; }
.score-full { margin-top: 8px; border-top: 1px solid var(--line); padding-top: 8px; }
.score-full .factor { display: flex; justify-content: space-between; gap: 12px; font-size: 12.5px; padding: 4px 0; color: var(--plat-dim); }
.score-full .factor b { color: var(--platinum); font-variant-numeric: tabular-nums; }

/* ── homeowner enrichment block ─────────────────────────────────────── */
.enrich-block { border: 1px solid var(--line); border-radius: var(--r-card); background: var(--obsidian); padding: 13px 14px; margin-bottom: 14px; }
.enrich-head { display: flex; justify-content: space-between; gap: 12px; margin-bottom: 8px; align-items: baseline; }
.enrich-row { font-size: 13.5px; color: var(--plat-dim); padding: 3px 0; }
.enrich-row strong { color: var(--platinum); }
.enrich-phone { display: flex; align-items: center; gap: 10px; padding: 7px 0; border-top: 1px solid var(--line); font-size: 13.5px; }
.enrich-phone .grow { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.enrich-note { margin-top: 9px; padding-top: 8px; border-top: 1px solid var(--line); color: var(--plat-faint); line-height: 1.5; }

/* ════════════════════════════════════════════════════════════════════
   11 · THE TERRITORY DRAWER
   ════════════════════════════════════════════════════════════════════ */
.terr-panel { position: fixed; right: 22px; bottom: 22px; width: min(380px, calc(100vw - 32px)); max-height: min(70vh, 560px); overflow-y: auto; background: var(--graphite); border: 1px solid var(--line-hi); border-radius: var(--r-card); z-index: 1200; padding: 16px 18px max(16px, env(safe-area-inset-bottom)); box-shadow: var(--e3), var(--e-inset); animation: sheetUp 240ms var(--ease-exit); }
@media (max-width: 720px) { .terr-panel { left: 0; right: 0; bottom: 0; width: 100%; border-radius: var(--r-card) var(--r-card) 0 0; max-height: 76dvh; } }
.terr-head { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }
.terr-head strong { font-size: 15px; }
.terr-list { display: flex; flex-direction: column; }
.terr-row { padding: 13px 0; border-bottom: 1px solid var(--line); }
.terr-row:last-child { border-bottom: none; }
.terr-row.focus { background: var(--tint-row); margin: 0 -10px; padding: 13px 10px; border-radius: var(--r-control); box-shadow: inset 2px 0 0 var(--ember); }
.terr-top { display: flex; align-items: center; gap: 10px; }
.terr-sw { width: 12px; height: 12px; border-radius: 3px; flex-shrink: 0; }
.terr-cov { display: flex; align-items: center; gap: 10px; margin: 9px 0; }
.terr-bar { flex: 1; height: 6px; border-radius: 3px; background: var(--line-hi); overflow: hidden; }
.terr-bar i { display: block; height: 100%; transition: width 500ms var(--ease-exit); }
.terr-meta { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin: 10px 0; }
.terr-acts { display: flex; gap: 6px; flex-wrap: wrap; }
.terr-acts .terr-del { color: var(--red); border-color: color-mix(in srgb, var(--red) 35%, var(--line-hi)); }
.terr-acts .terr-del:hover { border-color: var(--red); }

/* ════════════════════════════════════════════════════════════════════
   12 · THE STORM FINDER · catastrophic weather, by date
   ════════════════════════════════════════════════════════════════════ */
.storm-sheet { width: min(440px, 100%); }
.storm-controls { display: flex; flex-direction: column; gap: 9px; margin-bottom: 12px; }
.storm-date { display: flex; align-items: center; gap: 10px; }
.storm-date .mono-cap { flex-shrink: 0; }
.storm-date input[type="date"] { flex: 1; min-width: 0; color-scheme: dark; background: var(--obsidian); border: 1px solid var(--line-hi); border-radius: var(--r-control); color: var(--platinum); font: 500 14px var(--body); padding: 9px 11px; transition: border-color var(--m-fast) var(--ease); }
@media (prefers-color-scheme: light) { .storm-date input[type="date"] { color-scheme: light; } }
.storm-date input[type="date"]:focus { outline: none; border-color: var(--ember); }
.storm-chips { display: flex; gap: 6px; flex-wrap: wrap; }
.weather-report { border: 1px solid var(--line); border-radius: var(--r-card); padding: 14px; margin-bottom: 12px; background: var(--obsidian); }
.wr-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; }
.wr-grid > div { position: relative; padding-left: 11px; }
.wr-grid > div::before { content: ""; position: absolute; left: 0; top: 1px; bottom: 3px; width: 1px; background: var(--line); }
.wr-v { font-size: 21px; font-weight: 750; letter-spacing: -.03em; line-height: 1; font-variant-numeric: tabular-nums; }
.wr-v.gold { background: var(--grad-ember); -webkit-background-clip: text; background-clip: text; color: transparent; }
.wr-k { font: 500 10px var(--mono); letter-spacing: .1em; text-transform: uppercase; color: var(--plat-faint); margin-top: 5px; }
/* the live-hail row inside the Storm Finder (data-act map.livehail) */
.storm-livehail { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 4px 0 12px; padding: 11px 13px; border: 1px solid var(--line); border-radius: var(--r-control); background: var(--obsidian); }
.storm-livehail .grow { display: flex; flex-direction: column; gap: 2px; }
.storm-livehail .slh-k { font-size: 13.5px; font-weight: 600; color: var(--platinum); }
.storm-livehail .slh-sub { font-family: var(--mono); font-size: 10px; letter-spacing: .08em; text-transform: uppercase; color: var(--plat-faint); }
.storm-toggle { display: flex; align-items: center; gap: 8px; margin-top: 12px; font-size: 13px; color: var(--plat-dim); cursor: pointer; }
.storm-toggle input { width: 16px; height: 16px; accent-color: var(--ember); }
.storm-list { display: flex; flex-direction: column; }
.storm-row { padding: 13px 0; border-bottom: 1px solid var(--line); }
.storm-row:last-child { border-bottom: none; }
.storm-row.on { background: var(--tint-row); margin: 0 -10px; padding: 13px 10px; border-radius: var(--r-control); box-shadow: inset 2px 0 0 var(--ember); }
.storm-top { display: flex; align-items: center; gap: 10px; }
.storm-sw { width: 12px; height: 12px; border-radius: 3px; flex-shrink: 0; }
.storm-sz { font: 700 13px var(--body); white-space: nowrap; font-variant-numeric: tabular-nums; }
.storm-meta { margin: 7px 0 9px; }
.storm-acts { display: flex; gap: 6px; flex-wrap: wrap; }

/* ════════════════════════════════════════════════════════════════════
   13 · THE LEADERBOARD · the retention loop
   ════════════════════════════════════════════════════════════════════ */
.lead-sheet { width: min(460px, 100%); }
.lead-you {
  padding: 14px; margin-bottom: 12px; border: 1px solid color-mix(in srgb, var(--ember) 40%, var(--line)); border-radius: var(--r-card);
  background:
    linear-gradient(180deg, color-mix(in srgb, var(--ember) 9%, transparent), color-mix(in srgb, var(--ember) 4%, transparent));
  box-shadow: inset 0 1px 0 color-mix(in srgb, var(--ember-hi) 12%, transparent);
}
.lead-you .spread strong { font-size: 14.5px; }
.lead-xpbar { height: 6px; border-radius: 3px; background: var(--line-hi); overflow: hidden; margin: 9px 0 6px; }
.lead-xpbar i { display: block; height: 100%; background: var(--grad-ember); transition: width 600ms var(--ease-exit); }
.lead-period { display: flex; gap: 6px; margin: 12px 0; }
.lead-list { display: flex; flex-direction: column; }
.lead-row { display: flex; align-items: center; gap: 10px; padding: 12px 8px; border-bottom: 1px solid var(--line); font-size: 14px; }
.lead-row:last-child { border-bottom: none; }
.lead-row.you { background: var(--tint-row); border-radius: var(--r-control); box-shadow: inset 2px 0 0 var(--ember); }
.lead-rank { font: 700 13px var(--mono); color: var(--plat-faint); width: 20px; text-align: center; font-variant-numeric: tabular-nums; }
.lead-lvl { font: 700 10px var(--mono); letter-spacing: .06em; color: var(--ember-ink); background: var(--grad-ember); border-radius: var(--r-chip); padding: 3px 6px; }
.lead-stat { font-variant-numeric: tabular-nums; font-weight: 700; font-size: 13.5px; white-space: nowrap; }
.lead-stat .mono-cap { font-weight: 500; }

/* ════════════════════════════════════════════════════════════════════
   14 · PLAN MY DAY · appointments anchor, the route fills the gaps
   ════════════════════════════════════════════════════════════════════ */
.day-sheet { width: min(440px, 100%); }
.day-list { position: relative; }
/* a ruled spine the dots sit on, the "timeline" read */
.day-list::before { content: ""; position: absolute; left: 68px; top: 14px; bottom: 14px; width: 1px; background: var(--line); }
.day-item { position: relative; display: flex; align-items: flex-start; gap: 12px; padding: 12px 0; border-bottom: 1px solid var(--line); }
.day-item:last-child { border-bottom: none; }
.day-t { width: 64px; flex-shrink: 0; color: var(--plat-faint); font-size: 11px; padding-top: 2px; font-variant-numeric: tabular-nums; }
.day-dot { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; margin-top: 4px; background: var(--line-hi); border: 2px solid var(--graphite); box-sizing: content-box; z-index: 1; }
.day-item.appt .day-dot { background: var(--ember); }
.day-item.knock .day-dot { background: var(--trust); }
.day-item .why { display: block; font-size: 12.5px; color: var(--plat-faint); margin-top: 2px; }

/* ════════════════════════════════════════════════════════════════════
   15 · KEYFRAMES · the sheet/dropdown entrance (settles like hardware)
   ════════════════════════════════════════════════════════════════════ */
@keyframes sheetUp { from { transform: translateY(12px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
@media (min-width: 721px) { @keyframes sheetUp { from { transform: translateY(8px); opacity: 0; } to { transform: translateY(0); opacity: 1; } } }
/* sheetUpC is sheetUp's centered twin, for the mobile .sheet which is
   docked with left:50% + transform:translateX(-50%); sheetUp alone would
   overwrite that transform for the whole entrance and knock the sheet off
   center until the animation finished */
@keyframes sheetUpC { from { transform: translate(-50%, 12px); opacity: 0; } to { transform: translate(-50%, 0); opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  .search-results, .toast, .sheet, .terr-panel, .fm-undo { animation: none; }
}

/* ════════════════════════════════════════════════════════════════════
   16 · THE ENERGY PASS · make the instrument BREATHE
   The base surfaces stay matte; the energy lives in INTERACTIONS and the
   reward read. Spring/overshoot press feel on every control, a livelier Run
   HUD with the streak flame and a warm heartbeat, a more vivid leaderboard,
   satisfying chip/segment states, the You hub trophy surface, and the
   mobile-app clearances for the bottom tab bar + FAB. Token-only. Every
   energy color (flame, tier hue, badge) still arrives inline from JS.
   Reduced-motion degrades every spring to an instant settle.
   ════════════════════════════════════════════════════════════════════ */

/* ── 16.0 · the tab-bar metrics, hoisted to :root ───────────────────
   mobilenav.css pads .view / .sheet / .terr-panel for the bottom bar with
   calc(... + var(--mn-h) + ...), but it defines --mn-h only on .mobilenav
   (its own shell). On a .sheet (which is NOT inside .mobilenav) that var is
   undefined, the calc is invalid, and the padding resets to 0, so a bottom
   sheet can hide behind the bar. We hoist the metric here so every surface
   that clears the bar resolves it. The nav module's own .mobilenav value
   still wins for the bar itself (more specific element scope). */
:root { --mn-h: 60px; --mn-rail-w: 76px; }

/* ── 16.1 · the press language · a hardware tap that settles ─────────
   Controls get a spring overshoot on hover-lift and a confident press. We
   layer this on the EXISTING classes the app emits (never rename them). */
.btn, .seg-b, .fchip, .sheet-x, .search-clear, .rank-chip,
.sheet-acts .dispo, .dispo-chip {
  transition:
    transform var(--m-pulse) var(--ease-spring),
    color var(--m-fast) var(--ease),
    border-color var(--m-fast) var(--ease),
    background var(--m-fast) var(--ease),
    box-shadow var(--m-fast) var(--ease);
}
.btn:active, .seg-b:active, .fchip:active, .dispo-chip:active,
.sheet-x:active, .search-clear:active, .sheet-acts .dispo:active {
  transform: scale(.95);
}
/* the gold action presses like a real button, then springs back */
.btn-gold-sm:active { transform: translateY(1px) scale(.97); }
/* chips lift a hair on hover so the toolbar feels alive, not static */
.fchip:hover, .btn:hover { transform: translateY(-1px); }
.fchip:active, .btn:active { transform: translateY(0) scale(.96); }

/* the segmented mode control: the active tab gets a confident gold seat with
   a soft seated shadow (transient, part of the active state, not a halo) */
.seg-b.on { box-shadow: inset 0 -2px 0 color-mix(in srgb, var(--ember-deep) 60%, transparent); }
.seg-b { transition: transform var(--m-pulse) var(--ease-spring), color var(--m-fast) var(--ease), background var(--m-base) var(--ease-spring); }

@media (prefers-reduced-motion: reduce) {
  .btn, .seg-b, .fchip, .sheet-x, .search-clear, .rank-chip, .sheet-acts .dispo, .dispo-chip,
  .btn:hover, .fchip:hover, .btn:active, .fchip:active, .btn-gold-sm:active,
  .seg-b:active, .dispo-chip:active, .sheet-x:active, .search-clear:active, .sheet-acts .dispo:active {
    transform: none; transition: color var(--m-fast) var(--ease), border-color var(--m-fast) var(--ease), background var(--m-fast) var(--ease);
  }
}

/* ── 16.2 · the Run HUD · the momentum bar, alive ───────────────────
   The warm depth + live ring timings ride the base rules in section 8; here
   live the streak flame seated beside the rank chip and the 1px ember
   heartbeat under the HUD when a day streak is running (16.7). */
/* the count-up numbers carry a faint tabular emphasis as they tick (the FX
   engine adds .fx-tick; we keep the base crisp) */
.rh-v.fx-counting, .rh-goal-n.fx-counting { will-change: contents; }

/* the in-HUD streak chip sits between the funnel and the rank chip */
.hud-streak { display: inline-flex; align-items: center; margin-left: auto; }
.hud-streak:empty { display: none; }
.hud-streak + .rank-chip { margin-left: 12px; }
@media (max-width: 720px) {
  .hud-streak { margin-left: 0; }
  .hud-streak + .rank-chip { margin-left: auto; }
}

/* the rank chip lifts on hover (it opens the board, the daily draw) */
.rank-chip:hover { transform: translateY(-1px); border-color: color-mix(in srgb, var(--ember) 45%, var(--line-hi)); }
.rank-chip:active { transform: translateY(0) scale(.97); }

/* ── 16.3 · the disposition buttons in the sheet · a satisfying log ──
   Each presses with a spring and seats in its field color. The money rows
   (appt set, sold) get a hairline ember kiss on hover so the win reads. */
.sheet-acts .dispo:hover { transform: translateY(-1px); }
.sheet-acts .dispo:active { transform: scale(.97); }
.sheet-acts .dispo.on { box-shadow: inset 2px 0 0 var(--dc), 0 2px 12px color-mix(in srgb, var(--dc) 18%, transparent); }
@media (prefers-reduced-motion: reduce) {
  .sheet-acts .dispo:hover, .sheet-acts .dispo:active { transform: none; }
  .rank-chip:hover, .rank-chip:active { transform: none; }
}

/* ── 16.4 · the leaderboard · from a list to a stage ────────────────
   Gamify renders the podium body; the warmed "you" XP block lives on the
   base .lead-you rule in section 13. The fallback rows read calm. */
.lead-row { transition: background var(--m-fast) var(--ease); }
.lead-row.you { box-shadow: inset 2px 0 0 var(--ember), 0 0 0 1px color-mix(in srgb, var(--ember) 18%, transparent); }

/* ── 16.5 · the You hub sheet · the trophy room ─────────────────────
   The one surface allowed warmth (Gamify owns the inner saturation). The
   sheet itself is wider and carries a faint ember seam at the top edge. */
.you-sheet { width: min(440px, 100%); }
.you-sheet .sheet-head { align-items: center; }
.you-sheet .you-sound { margin-right: 4px; flex: 0 0 auto; }
.you-sheet .sheet-head strong { font-family: var(--disp); font-size: 15px; letter-spacing: .02em; }
@media (min-width: 721px) {
  .you-sheet { width: 380px; }
}

/* ── 16.6 · the mobile-app clearances · sit above the tab bar + FAB ──
   MobileNav toggles .mn-on-mobile / .mn-on-desktop on <body> and pads
   .sheet / .terr-panel itself (mobilenav.css), which already covers the
   You hub, leaderboard, storm, and day sheets since each also carries the
   base .sheet class. We only need to lift the floating undo chip here. */
.mn-on-mobile .fm-undo {
  bottom: calc(14px + var(--mn-h) + env(safe-area-inset-bottom));
}
/* the toast stack lifts clear of the FAB on mobile so a celebration ribbon
   and a toast never collide at the thumb */
@media (max-width: 720px) {
  .mn-on-mobile .toasts { top: auto; bottom: calc(80px + var(--mn-h) + env(safe-area-inset-bottom)); right: 12px; }
}

/* ── 16.7 · the warm heartbeat · a streak-live HUD accent ───────────
   When a day streak is live the Gamify chip carries .live; we echo a 1px
   ember underline on the HUD so the chrome has a human, alive accent. This
   is the only persistent warm mark on the base, and it is a hairline, not a
   glow. */
.run-hud:has(.gm-streak-chip.live) {
  border-bottom-color: color-mix(in srgb, var(--ember) 45%, var(--line));
}

/* ════════════════════════════════════════════════════════════════════
   16.9 · THE CONTROL DECK · the map-first phone read
   On a phone the map is the full-bleed hero; ALL of #mapChrome (the HUD,
   the mode bar, the filters, the banner, the legend) lifts into one fixed,
   draggable deck docked above the tab bar. PEEK shows the live essentials
   (the mode banner, a compact goal-ring + set-rate glance, the 3-mode
   segment, plus Locate + Route); a flick up (or a tap on the grip) OPENS it
   to the full HUD funnel + rank, the tool rail, the filter rail, the legend.
   Search floats as a top pill. Nothing is removed; the map owns the screen.
   Scoped to body.mn-fullbleed.mn-on-mobile + max-width 640; desktop rail and
   the 641-720 stacked path match none of it. Token-only, no raw hex.
   ════════════════════════════════════════════════════════════════════ */

/* inert off-mobile: the wrapper vanishes (children flow as today), grip hides */
#mapDeck { display: contents; }
.deck-grip { display: none; }

@media (max-width: 640px) {

  /* the view stops reserving stacked-chrome height; the map owns the screen */
  .mn-fullbleed.mn-on-mobile .view { padding: 0; min-height: 0; overflow: visible; }
  .mn-fullbleed.mn-on-mobile .map-foot { display: none; }   /* status lives in the deck/banner */

  /* ── SEARCH · a floating pill under the topbar, over the map ───────── */
  .mn-fullbleed.mn-on-mobile .searchwrap {
    position: fixed; z-index: 45; margin: 0; max-width: none;
    top: calc(54px + 8px + env(safe-area-inset-top));
    left: 10px; right: 10px;
    pointer-events: none;                       /* the gaps stay map-draggable */
  }
  .mn-fullbleed.mn-on-mobile .searchbar {
    height: 44px; pointer-events: auto;
    background: color-mix(in srgb, var(--graphite-2) 86%, transparent);
    -webkit-backdrop-filter: saturate(150%) blur(14px);
            backdrop-filter: saturate(150%) blur(14px);
    box-shadow: 0 8px 24px color-mix(in srgb, var(--obsidian) 55%, transparent);
  }
  .mn-fullbleed.mn-on-mobile .search-results { pointer-events: auto; max-height: 52vh; }

  /* Leaflet's top-left zoom control must clear the floating search pill */
  .mn-fullbleed.mn-on-mobile .fieldmap .leaflet-top.leaflet-left {
    top: calc(54px + 8px + 44px + 8px + env(safe-area-inset-top)); left: 8px;
  }

  /* ── THE DECK SHELL · fixed, docked above the tab bar ───────────────
     PEEK height is content-driven with a 46vh ceiling, so the tall
     territory-draw banner is never clipped. */
  .mn-fullbleed.mn-on-mobile #mapDeck {
    display: flex; flex-direction: column;
    position: fixed; left: 0; right: 0;
    bottom: calc(var(--mn-h) + env(safe-area-inset-bottom));
    z-index: 1180;
    background: var(--header-bg);
    -webkit-backdrop-filter: saturate(160%) blur(16px);
            backdrop-filter: saturate(160%) blur(16px);
    border-top: 1px solid var(--line-hi);
    border-radius: var(--r-card-lg) var(--r-card-lg) 0 0;
    box-shadow: var(--e3), var(--e-inset);
    overflow: hidden;
    max-height: calc(46vh + env(safe-area-inset-bottom));
    transition: max-height var(--m-base) var(--ease-spring);
    touch-action: none;                         /* the grip owns the vertical gesture */
  }
  .mn-fullbleed.mn-on-mobile #mapDeck[data-deck="open"] {
    max-height: calc(72dvh - env(safe-area-inset-bottom));
  }

  /* ── THE GRIP · drag handle + tap-to-toggle, a 44px touch target,
        the visual bar itself stays a slim centered 4px ─────────────────── */
  .mn-fullbleed.mn-on-mobile .deck-grip {
    display: block; flex: 0 0 auto; width: 100%; height: 44px;
    padding: 0; border: none; background: none; position: relative;
    cursor: grab; -webkit-tap-highlight-color: transparent;
  }
  .mn-fullbleed.mn-on-mobile .deck-grip::before {
    content: ""; position: absolute; left: 50%; top: 20px; transform: translateX(-50%);
    width: 38px; height: 4px; border-radius: var(--r-chip);
    background: var(--line-hi); transition: background var(--m-fast) var(--ease);
  }
  .mn-fullbleed.mn-on-mobile #mapDeck[data-deck="open"] .deck-grip::before { background: var(--plat-faint); }
  .mn-fullbleed.mn-on-mobile .deck-grip:active { cursor: grabbing; }

  /* ── #mapChrome becomes the scrollable deck body, a re-ordered column ─ */
  .mn-fullbleed.mn-on-mobile #mapChrome {
    flex: 1 1 auto; min-height: 0;
    display: flex; flex-direction: column; gap: 10px;
    padding: 0 12px 12px;
    overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch;
  }
  /* deck column order: banner pinned top, glance, act row, then the groups */
  .mn-fullbleed.mn-on-mobile #mapChrome > .map-banner { order: 1; margin: 0; }
  .mn-fullbleed.mn-on-mobile #mapChrome > .run-hud    { order: 2; margin: 0; }
  .mn-fullbleed.mn-on-mobile #mapChrome > .map-bar    { order: 3; margin: 0; }
  .mn-fullbleed.mn-on-mobile #mapChrome > .deck-group { order: 4; margin: 0; }

  /* PEEK = banner (when armed) + glance + act row; the groups are one flick away */
  .mn-fullbleed.mn-on-mobile #mapDeck[data-deck="peek"] .deck-group { display: none; }

  /* ── THE BANNER · promoted to the deck header, always visible at peek ─ */
  .mn-fullbleed.mn-on-mobile .map-banner {
    padding: 9px 12px; font-size: 12.5px; border-radius: var(--r-control);
  }

  /* ── COMPACT HUD · PEEK = goal ring + set-rate glance + rank ring.
        OPEN reveals the full funnel + rank meta. No datum removed, folded. ── */
  .mn-fullbleed.mn-on-mobile .run-hud {
    gap: 14px; padding: 6px 0 0; border: none; background: none; box-shadow: none;
    align-items: center; flex-wrap: nowrap;
  }
  .mn-fullbleed.mn-on-mobile .rh-ring { width: 40px; height: 40px; }
  .mn-fullbleed.mn-on-mobile .rh-ring svg { width: 40px; height: 40px; }
  .mn-fullbleed.mn-on-mobile .rh-goal-n { font-size: 13px; }
  .mn-fullbleed.mn-on-mobile .hud-streak { display: none; }   /* the streak lives in the You hub */
  .mn-fullbleed.mn-on-mobile .run-hud .rh-funnel { gap: 12px; flex: 1 1 auto; width: auto; justify-content: flex-start; }
  .mn-fullbleed.mn-on-mobile #mapDeck[data-deck="peek"] .run-hud .rh-funnel .rh-stat { display: none; }
  .mn-fullbleed.mn-on-mobile #mapDeck[data-deck="peek"] .run-hud .rh-funnel .rh-stat:last-child { display: flex; }
  .mn-fullbleed.mn-on-mobile #mapDeck[data-deck="peek"] .run-hud .rh-arrow { display: none; }
  .mn-fullbleed.mn-on-mobile .rank-chip { margin-left: auto; padding: 5px 10px 5px 6px; }
  .mn-fullbleed.mn-on-mobile #mapDeck[data-deck="peek"] .rank-chip .rk-meta { display: none; }
  .mn-fullbleed.mn-on-mobile #mapDeck[data-deck="open"] .run-hud .rh-funnel {
    flex-wrap: nowrap; overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: none;
  }
  .mn-fullbleed.mn-on-mobile #mapDeck[data-deck="open"] .run-hud .rh-funnel::-webkit-scrollbar { display: none; }
  .mn-fullbleed.mn-on-mobile #mapDeck[data-deck="open"] .run-hud .rh-stat { flex-direction: row; align-items: baseline; gap: 5px; }
  .mn-fullbleed.mn-on-mobile .run-hud .rh-arrow { display: none; }   /* arrows off in the deck; figures stay */

  /* ── MODE SEGMENT + TOOL RAIL · the .seg is sticky-left so the primary
        control never scrolls away; tool buttons scroll after it ──────── */
  .mn-fullbleed.mn-on-mobile .map-bar {
    gap: 8px; flex-wrap: nowrap; align-items: center;
    overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: none;
    -webkit-mask-image: linear-gradient(90deg, var(--obsidian) 0, var(--obsidian) calc(100% - 26px), transparent 100%);
            mask-image: linear-gradient(90deg, var(--obsidian) 0, var(--obsidian) calc(100% - 26px), transparent 100%);
  }
  .mn-fullbleed.mn-on-mobile .map-bar::-webkit-scrollbar { display: none; }
  .mn-fullbleed.mn-on-mobile .map-bar .r { display: none; }
  .mn-fullbleed.mn-on-mobile .map-bar .seg {
    position: sticky; left: 0; z-index: 2;
    width: auto; flex: 0 0 auto;
    box-shadow: 0 6px 18px color-mix(in srgb, var(--obsidian) 50%, transparent);
    background: color-mix(in srgb, var(--graphite-2) 92%, transparent);
  }
  .mn-fullbleed.mn-on-mobile .map-bar .seg-b { flex: 0 0 auto; padding: 0 13px; min-height: 44px; font-size: 12px; }
  .mn-fullbleed.mn-on-mobile .map-bar .btn { flex: 0 0 auto; min-height: 44px; padding: 0 13px; font-size: 12px; white-space: nowrap; }
  /* the act row (Rapid + Locate) is always on; the grouped rails fold with
     their .deck-group at peek, so no per-button exceptions are needed */
  .mn-fullbleed.mn-on-mobile .dg-row .wx-readout { min-height: 44px; flex: 0 0 auto; }

  /* ── FILTER RAIL · disposition chips + basemap, one scroll rail, no chip
        lost; overscroll contained so it never pans the map ──────────── */
  .mn-fullbleed.mn-on-mobile .map-filters {
    flex-wrap: nowrap; overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: none;
    -webkit-mask-image: linear-gradient(90deg, var(--obsidian) 0, var(--obsidian) calc(100% - 26px), transparent 100%);
            mask-image: linear-gradient(90deg, var(--obsidian) 0, var(--obsidian) calc(100% - 26px), transparent 100%);
  }
  .mn-fullbleed.mn-on-mobile .map-filters::-webkit-scrollbar { display: none; }
  .mn-fullbleed.mn-on-mobile .map-filters .fchip { flex: 0 0 auto; min-height: 44px; }
  .mn-fullbleed.mn-on-mobile .map-filters .fdivider { min-height: 28px; flex: 0 0 auto; }
  .mn-fullbleed.mn-on-mobile .map-legend { flex-wrap: wrap; padding-left: 0; padding-right: 0; }

  /* ── lift the floating undo + stream ticker clear of the PEEK deck ────
     z-index sits ABOVE the deck (1180) so undo stays reachable even when
     the deck is pulled open to 72dvh and this 46vh anchor undershoots it */
  .mn-fullbleed.mn-on-mobile .fm-undo {
    position: fixed; z-index: 1181; left: 12px; right: 12px; margin: 0;
    bottom: calc(var(--mn-h) + env(safe-area-inset-bottom) + 46vh + 12px);
  }
  .mn-fullbleed.mn-on-mobile #streamRoot { bottom: calc(46vh + 12px); }
}

/* ── REDUCED MOTION · the deck snaps between detents, no spring ──────── */
@media (max-width: 640px) and (prefers-reduced-motion: reduce) {
  .mn-fullbleed.mn-on-mobile #mapDeck { transition: none; }
  .mn-fullbleed.mn-on-mobile .deck-grip::before { transition: none; }
}

/* ════════════════════════════════════════════════════════════════════
   17 · THE VISUAL CALM LAYER · Apple-crisp chrome, same controls
   Clarity, deference, depth: the chrome defers to the map. One control
   tier is seated (the mode segment); active tool states carry a single
   accent tint; everything else is ghost text that lifts on hover.
   Hairlines replace boxed borders; mono carries every datum; ember
   still appears only where money or trust moves. Nothing is removed:
   same classes, same data-acts, only weight and grouping change. Every
   rule is a LATER same-specificity declaration over sections 1-16; the
   three deliberate specificity bumps are commented inline. No !important.
   ════════════════════════════════════════════════════════════════════ */

/* ── 17.0 · TOPBAR · brand + one status + bell, even air ──────────── */
.topbar { gap: var(--s-4); }
.tb-right { gap: var(--s-3); }
.sync {
  font-family: var(--mono); font-size: 10px; font-weight: 500;
  letter-spacing: .12em; text-transform: uppercase; color: var(--plat-faint);
}
/* .sync.queued (amber) and .sync.offline keep their earlier colors: the
   higher-specificity state rules survive this base quieting by design */
.mode-badge { border-color: transparent; padding: 0; }
.mode-badge.composed { color: var(--plat-faint); border-color: transparent; }
.mode-badge.composed::before { box-shadow: none; }   /* the lit dot alone says live */

/* ── 17.1 · GROUPS · mono overline headers over hairlines ───────────
   The Violet declutter grammar: a labeled, collapsible band, never a box.
   Collapse state renders from UI.groups into .closed every render. */
.deck-group { display: flex; flex-direction: column; gap: var(--s-2); margin-bottom: var(--s-3); min-width: 0; }
.dg-head {
  display: flex; align-items: center; gap: var(--s-2); width: 100%;
  background: none; border: none; padding: var(--s-1) 0; min-height: 28px;
  text-align: left; cursor: pointer; -webkit-tap-highlight-color: transparent;
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .16em;
  text-transform: uppercase; color: var(--plat-faint); user-select: none;
}
.dg-head:hover { color: var(--plat-dim); }
.dg-head::after { content: ""; flex: 1 1 auto; height: 1px; background: var(--hairline); }
.dg-head:focus-visible { outline: 2px solid var(--ember-hi); outline-offset: 2px; border-radius: var(--r-chip); }
.dg-caret { display: inline-block; font-size: 12px; line-height: 1; transform: rotate(90deg); transition: transform var(--m-fast) var(--ease); }
.deck-group.closed .dg-caret { transform: rotate(0deg); }
.deck-group.closed .dg-body { display: none; }
.dg-fig { color: var(--plat-dim); letter-spacing: .06em; text-transform: none; margin-left: var(--s-2); }
.dg-body { display: flex; flex-direction: column; gap: var(--s-2); }
.deck-group .map-bar, .deck-group .map-filters, .deck-group .map-legend { margin-bottom: 0; }
.dg-row .wx-readout { min-height: 36px; border-radius: var(--r-control); }

/* ── 17.2 · THE HUD · a ruled band, not a card; mono figures ────────
   16.7's streak :has() rule is higher specificity and still recolors the
   bottom hairline when a streak is live, by design. */
.run-hud {
  background: none; border: none; border-bottom: 1px solid var(--hairline);
  border-radius: 0; box-shadow: none;
  padding: var(--s-1) 0 var(--s-4); margin-bottom: var(--s-4);
}
.rh-v { font-family: var(--mono); font-weight: 500; font-size: 22px; letter-spacing: 0; }
.rh-v.gold {
  background: none; -webkit-background-clip: border-box; background-clip: border-box;
  color: var(--ember);   /* the money figure keeps ember, solid, no gradient */
}
.rh-goal-n { font-family: var(--mono); font-weight: 500; }
.rh-arrow { color: var(--line); font-size: 14px; }
.rank-chip { background: none; border-color: transparent; }
.rank-chip:hover { background: var(--tint-hover); border-color: transparent; }
@media (max-width: 720px) { .rh-v { font-size: 19px; } }

/* ── 17.3 · THE MODE SEGMENT · the one seated control ───────────────
   A recessed hairline track with a floating platinum knob. Gold leaves
   the segment; ember is reserved for money surfaces. */
.seg {
  padding: 2px; gap: 2px; overflow: visible;
  background: color-mix(in srgb, var(--obsidian) 55%, transparent);
  border: 1px solid var(--hairline);
}
.seg-b { border-right: none; border-radius: var(--r-inner); color: var(--plat-dim); }
.seg-b:hover { background: var(--tint-hover); color: var(--platinum); }
.seg-b.on {
  background: var(--graphite-3); color: var(--platinum);
  font-weight: 600; box-shadow: var(--e1);
}

/* ── 17.4 · THE TOOL RAIL · ghost text buttons, one accent when live ─
   Active states re-declared at .map-bar .btn.* (0,3,0) so they outrank
   both these ghosts and stormstream.css's later-file .btn.stream-on. */
.map-bar { gap: var(--s-1); margin-bottom: var(--s-4); }
.map-bar .btn {
  background: none; border-color: transparent; box-shadow: none;
  color: var(--plat-dim); padding: 0 12px; min-height: 36px; font-size: 12.5px;
}
.map-bar .btn:hover { background: var(--tint-hover); border-color: transparent; color: var(--platinum); box-shadow: none; }
.map-bar .btn:active { box-shadow: none; }
.map-bar .btn:focus-visible { box-shadow: var(--ring-ember); }   /* bump 1: the ghost keeps its ring */
.map-bar .btn.storm-on  { color: var(--ember); background: var(--tint-ember); border-color: transparent; }   /* bump 2 */
.map-bar .btn.field-on  { color: var(--amber); background: var(--tint-amber); border-color: transparent; }
.map-bar .btn.stream-on { color: var(--green); background: var(--tint-green); border-color: transparent; }   /* bump 3 */
.wx-readout { background: none; border-color: transparent; }
.wx-readout:hover { background: var(--tint-hover); border-color: transparent; }
.wx-readout.live { background: none; border-color: color-mix(in srgb, var(--c, var(--amber)) 40%, transparent); }
.wx-fig { font-family: var(--mono); font-size: 11px; font-weight: 500; letter-spacing: .02em; }

/* ── 17.5 · FILTER CHIPS · unselected ghost, selected one accent ────
   The selection accent is the Canvass Pro tool token (never ember; the
   money color stays reserved). */
.map-filters { gap: var(--s-1); margin-bottom: var(--s-4); }
.fchip { border-color: transparent; color: var(--plat-faint); padding: 0 11px; }
.fchip:hover { color: var(--platinum); border-color: transparent; background: var(--tint-hover); }
.fchip.on {
  color: var(--tool-canvasspro-text);
  background: color-mix(in srgb, var(--tool-canvasspro) 14%, transparent);
  border-color: transparent;
}
.fdivider { background: var(--hairline); }

/* ── 17.6 · THE MODE BANNER · a slim floating instruction pill ──────
   Fit-content, translucent, one hairline; the mode accent survives as a
   tinted hairline, not a boxed border. Radius stays on the ladder. */
.map-banner {
  width: fit-content; max-width: 100%; margin: 0 auto var(--s-4);
  padding: 7px 8px 7px 16px; gap: 10px;
  background: color-mix(in srgb, var(--graphite-2) 88%, transparent);
  -webkit-backdrop-filter: saturate(150%) blur(12px);
          backdrop-filter: saturate(150%) blur(12px);
  border: 1px solid var(--hairline); border-radius: var(--r-card);
  box-shadow: var(--e2); font-size: 13px;
}
.map-banner.add   { border-color: color-mix(in srgb, var(--trust) 30%, var(--hairline)); }
.map-banner.draw  { border-color: color-mix(in srgb, var(--ember) 35%, var(--hairline)); }
.map-banner.rapid { border-color: color-mix(in srgb, var(--ember) 35%, var(--hairline)); }

/* ── 17.7 · THE LEGEND · one quiet ruled line ─────────────────────── */
.map-legend {
  gap: var(--s-3) var(--s-4); padding: var(--s-3) 2px 0;
  border-top: 1px solid var(--hairline);
  font-size: 9px; letter-spacing: .08em; color: var(--plat-faint);
  flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none;
}
.map-legend::-webkit-scrollbar { display: none; }
.map-legend span { white-space: nowrap; }
.map-legend .fm-swatch { width: 7px; height: 7px; margin-right: 5px; }

/* ── 17.8 · THE YOU SHEET SETUP ROW · the demoted, rarely-daily levers ─ */
.you-sys { display: flex; align-items: center; gap: var(--s-2); margin-top: var(--s-4); padding-top: var(--s-3); border-top: 1px solid var(--line); }
.you-sys .mono-cap { margin-right: auto; }
.you-sheet .mode-badge { margin-right: var(--s-1); flex: 0 0 auto; }

/* ── 17.9 · THE DECK, RE-AIRED · mobile-scoped adjustments ────────── */
@media (max-width: 640px) {
  .mn-fullbleed.mn-on-mobile #mapChrome { gap: var(--s-4); }
  .mn-fullbleed.mn-on-mobile #mapChrome > .deck-group { margin: 0; }
  /* the banner is the deck header at peek: full-width, unboxed, the deck
     card itself is the surface (overrides 17.6's centered pill here) */
  .mn-fullbleed.mn-on-mobile .map-banner {
    width: 100%; margin: 0; background: none; border: none; box-shadow: none;
    -webkit-backdrop-filter: none; backdrop-filter: none;
    padding: 6px 2px; border-radius: 0; font-size: 12.5px;
  }
}

/* ── 17.10 · REDUCED MOTION · the calm layer adds no required motion ── */
@media (prefers-reduced-motion: reduce) {
  .dg-caret { transition: none; }
}

/* ── IMPORT DOORS · put a real street on the map (app.js openImport) ── */
.import-body { display: flex; flex-direction: column; }
.import-text {
  width: 100%; resize: vertical; min-height: 84px;
  background: var(--graphite-2); color: var(--platinum);
  border: 1px solid var(--line-hi); border-radius: var(--r-control);
  padding: 10px 12px; font: 400 14px var(--body); line-height: 1.5;
}
.import-text:focus { outline: none; border-color: var(--ember-deep); box-shadow: var(--ring-ember); }
.import-text::placeholder { color: var(--plat-faint); }
.import-busy { margin-top: 12px; padding: 9px 12px; border-radius: var(--r-control); background: var(--tint-ember); color: var(--ember-hi); text-align: center; }
.import-demo-note { margin: 0 0 14px; padding: 10px 12px; border-radius: var(--r-control); background: var(--tint-ember); border: 1px solid color-mix(in srgb, var(--ember) 26%, var(--line)); color: var(--ember-hi); line-height: 1.5; }

/* the /demo public activation CTA · rides the topbar in place of the sync chip */
.tb-getpro {
  display: inline-flex; align-items: center; white-space: nowrap;
  background: var(--grad-ember); color: var(--ember-ink); font-weight: 700;
  font-size: 12.5px; padding: 7px 13px; border-radius: var(--r-chip);
  box-shadow: var(--e2), inset 0 1px 0 color-mix(in srgb, var(--ember-hi) 60%, transparent);
  text-decoration: none; transition: box-shadow var(--m-base) var(--ease), background var(--m-base) var(--ease);
}
.tb-getpro:hover { background: var(--ember-hi); box-shadow: var(--e2), var(--ring-ember); }

/* ════════════════════════════════════════════════════════════════════
   THE LEARNING SCORE (the moat) · deck readout + per-door tuned line
   The base score stays the headline everywhere; this layer shows the
   operator-tuned delta. Cool while warming up, ember once it is tuned.
   ════════════════════════════════════════════════════════════════════ */
.learn-readout { margin: 0 0 8px; border: 1px solid var(--line); border-radius: var(--r-control); background: var(--obsidian); overflow: hidden; }
.learn-readout.ready { border-color: color-mix(in srgb, var(--ember) 30%, var(--line)); background: var(--tint-ember); }
.lr-head { width: 100%; display: flex; align-items: center; gap: 10px; padding: 9px 11px; background: none; border: none; text-align: left; color: inherit; }
.lr-head[disabled] { cursor: default; }
.lr-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--plat-faint); flex-shrink: 0; }
.learn-readout.ready .lr-dot { background: var(--ember); box-shadow: 0 0 0 3px color-mix(in srgb, var(--ember) 22%, transparent); }
.lr-text { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1; }
.lr-text b { font-size: 13px; font-weight: 700; color: var(--platinum); }
.learn-readout.ready .lr-text b { color: var(--ember-hi); }
.lr-sub { font-size: 11.5px; color: var(--plat-dim); line-height: 1.4; }
.lr-caret { margin-left: auto; color: var(--plat-faint); font-size: 16px; transition: transform var(--m-base) var(--ease); }
.lr-head[aria-expanded="true"] .lr-caret { transform: rotate(90deg); }
.learn-weights { padding: 4px 12px 12px; display: flex; flex-direction: column; gap: 7px; border-top: 1px solid color-mix(in srgb, var(--ember) 18%, var(--line)); }
.lw-row { display: grid; grid-template-columns: 88px 1fr 44px; align-items: center; gap: 9px; }
.lw-k { font-size: 11px; color: var(--plat-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.lw-bar { position: relative; height: 5px; border-radius: 3px; background: var(--graphite); overflow: hidden; }
.lw-fill { position: absolute; inset: 0 auto 0 0; height: 100%; border-radius: 3px; background: var(--grad-ember); }
.lw-fill.down { background: var(--plat-faint); opacity: 0.7; }
.lw-w { font-family: var(--mono); font-size: 11px; color: var(--ember-hi); text-align: right; font-variant-numeric: tabular-nums; }
.lw-row:has(.lw-fill.down) .lw-w { color: var(--plat-faint); }

/* the per-door tuned line inside the score block */
.score-learned { display: flex; align-items: center; gap: 9px; margin: 3px 0 8px; padding: 6px 9px; border-radius: var(--r-chip); background: var(--tint-ember); border: 1px solid color-mix(in srgb, var(--ember) 24%, var(--line)); }
.score-learned.down { background: color-mix(in srgb, var(--line) 40%, transparent); border-color: var(--line); }
.sl-badge { flex-shrink: 0; min-width: 26px; height: 22px; padding: 0 6px; display: inline-flex; align-items: center; justify-content: center; border-radius: var(--r-chip); background: var(--grad-ember); color: var(--ember-ink); font-weight: 800; font-size: 12.5px; }
.score-learned.down .sl-badge { background: var(--graphite); color: var(--plat-dim); box-shadow: var(--e-inset); }
.sl-text { font-size: 12px; color: var(--plat-dim); line-height: 1.4; }
.sl-text b { color: var(--ember-hi); font-weight: 700; }
.score-learned.down .sl-text b { color: var(--plat-dim); }
