/* ============================================================================
   Fullscreen map — Apple Maps model.
   The map IS the page: it fills the viewport and bleeds under the status bar /
   browser chrome. Everything else floats above it as liquid-glass bubbles.
   ========================================================================== */

body.map-page {
  overflow: hidden;
  height: 100dvh;
  /* The aurora/grain would show through the map's own edges; the map covers all. */
}
body.map-page .aurora, body.map-page .grain { display: none; }

.mapstage { position: fixed; inset: 0; z-index: 0; }
#map { width: 100%; height: 100%; background: var(--bone-deep); }
.leaflet-container { font-family: var(--sans); background: var(--bone-deep); }
.leaflet-control-container .leaflet-top,
.leaflet-control-container .leaflet-bottom { display: none; } /* we draw our own */

/* Map-local values. Everything else on this page rides base.css's tokens; these
   three are one-offs where a shared token gave the wrong RESULT rather than just
   the wrong colour, so they are declared here with both dark selectors (an
   explicit theme is an attribute, which a media query cannot see). */
:root {
  --grab-bar:       rgba(20,23,26,0.20);  /* the sheet's only handle            */
  --chip-bg:        rgba(20,23,26,0.07);  /* settlement chip, resting           */
  --chip-bg-hover:  rgba(20,23,26,0.12);  /* ...and hover: always MORE, not less */

  /* ── the map's own material ──────────────────────────────────────────────
     base.css's --surface-* family is tuned for panels resting on the SITE's
     own ground, where the thing behind the glass is known. Map chrome floats
     over arbitrary imagery, and in dark those tokens are a 7-19% white FILM —
     enough to read as a card against near-black tiles, and not remotely enough
     to occlude anything bright. Measured with the price-heat layer on and the
     view parked on the hottest cell in the country, the brass fill came
     straight through the glass and took the top bar to 2.8:1, the mode
     segments to 1.5:1 and the scale labels to 1.03:1 — in the one state where
     those numbers matter most, because the layer painting that colour IS the
     thing being read.

     So the map declares its own two materials, and the split is the one Apple
     Maps uses: CHROME (small, bold, high-contrast controls) may stay properly
     translucent, while a CARD — anything carrying prose, a list or a legend —
     is a near-opaque surface that happens to be blurred. Light chrome is the
     0.80/0.62 white this file shipped with, unchanged; only the cards get more
     opaque there, and only because they measured 3.6-4.2:1. */
  --map-chrome-1: rgba(255,255,255,0.80);
  --map-chrome-2: rgba(255,255,255,0.62);
  --map-card-1:   rgba(251,249,245,0.96);
  --map-card-2:   rgba(251,249,245,0.93);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) {
    --grab-bar:      rgba(255,255,255,0.30);
    --chip-bg:       rgba(255,255,255,0.10);
    --chip-bg-hover: rgba(255,255,255,0.17);
    /* Lighter than --bone (#101311), so these still read as LIFTED — dark
       elevation is a lighter surface, not a bigger shadow. */
    --map-chrome-1: rgba(31,35,31,0.90);
    --map-chrome-2: rgba(24,28,24,0.84);
    --map-card-1:   rgba(31,35,31,0.97);
    --map-card-2:   rgba(25,29,25,0.95);
  }
}
:root[data-theme='dark'] {
  --grab-bar:      rgba(255,255,255,0.30);
  --chip-bg:       rgba(255,255,255,0.10);
  --chip-bg-hover: rgba(255,255,255,0.17);
  --map-chrome-1: rgba(31,35,31,0.90);
  --map-chrome-2: rgba(24,28,24,0.84);
  --map-card-1:   rgba(31,35,31,0.97);
  --map-card-2:   rgba(25,29,25,0.95);
}

/* ══ FLOATING CHROME ═══════════════════════════════════════════════════════
   Safe-area aware: on iOS the top bubbles sit clear of the notch while the map
   itself continues underneath it. */
.map-ui {
  position: fixed; inset: 0; z-index: 20;
  pointer-events: none; /* only the bubbles catch events */
  padding: calc(env(safe-area-inset-top, 0px) + 12px) calc(env(safe-area-inset-right, 0px) + 12px)
           calc(env(safe-area-inset-bottom, 0px) + 12px) calc(env(safe-area-inset-left, 0px) + 12px);
  display: flex; flex-direction: column;
}
.map-ui > * { pointer-events: auto; }

/* Shared bubble material — one definition so every floating control matches. */
.bub {
  background: linear-gradient(150deg, var(--map-chrome-1) 0%, var(--map-chrome-2) 100%);
  -webkit-backdrop-filter: saturate(200%) blur(26px); backdrop-filter: saturate(200%) blur(26px);
  box-shadow: var(--glass-rim), 0 6px 18px -8px rgba(var(--shadow-rgb),0.26), 0 18px 44px -22px rgba(var(--shadow-rgb),0.3);
  border: 0;
  border-radius: var(--r-pill);
  color: var(--ink);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .bub { background: var(--map-card-1); }
}

/* ── top row: brand pill + filter pills ────────────────────────────────── */
.map-top { display: flex; align-items: center; gap: 10px; min-height: 42px; }
/* The row is chrome, not a lid: only the bubbles themselves should catch the
   finger, so the empty air between them still pans the map. */
.map-ui .map-top { pointer-events: none; }
.map-ui .map-top > * { pointer-events: auto; }
.map-brand {
  display: inline-flex; align-items: center; gap: 9px;
  height: 42px; padding: 0 16px 0 12px;
  font-family: var(--display); font-size: 1.06rem; font-weight: 600;
  letter-spacing: -0.03em; font-variation-settings: 'opsz' 34, 'SOFT' 20, 'WONK' 1;
  transition: transform 0.4s var(--ease-out), box-shadow 0.4s var(--ease-out);
  flex: 0 0 auto;
}
.map-brand:hover { transform: translateY(-1px); }
.map-brand .wm { display: inline; }
.map-brand em { font-style: normal; color: var(--brass); }
.map-brand svg { color: var(--ink-3); flex: 0 0 auto; }

.map-filters { display: flex; gap: 8px; align-items: center; overflow-x: auto; scrollbar-width: none; padding: 1px; flex: 1 1 auto; }
.map-filters::-webkit-scrollbar { display: none; }
/* Fade the pills out at the scroller's edges instead of guillotining them.
   A gradient scrim would be a lie over a map (there is no surface to fade
   into), so the mask fades the pills themselves — they read as sliding under
   the edge, which is exactly what they do. The end fade is switched off once
   the row is scrolled to its end (map-page.js sets .at-end). */
.map-filters {
  --fade-s: 0px;
  --fade-e: 26px;
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 var(--fade-s),
                      #000 calc(100% - var(--fade-e)), transparent 100%);
          mask-image: linear-gradient(90deg, transparent 0, #000 var(--fade-s),
                      #000 calc(100% - var(--fade-e)), transparent 100%);
}
.map-filters.at-end { --fade-e: 0px; }
.map-filters.scrolled { --fade-s: 26px; }
.fpill {
  display: inline-flex; align-items: center; gap: 6px;
  height: 42px; padding: 0 15px; white-space: nowrap; cursor: pointer;
  font-size: 0.88rem; font-weight: 600;
  transition: transform 0.34s var(--ease-out), background 0.24s var(--ease), color 0.24s var(--ease);
}
.fpill:hover { transform: translateY(-1px); }
.fpill.on {
  background: linear-gradient(168deg, var(--fill-1) 0%, var(--fill-2) 100%);
  color: var(--fill-fg);
  box-shadow: inset 0 1px 0 var(--spec-soft), 0 8px 22px -10px rgba(var(--shadow-rgb),0.6);
}
.fpill .n { opacity: 0.5; font-variant-numeric: tabular-nums; }

/* ── right rail: round glass buttons ───────────────────────────────────── */
.map-rail {
  position: absolute;
  right: calc(env(safe-area-inset-right, 0px) + 12px);
  top: 50%; transform: translateY(-50%);
  display: flex; flex-direction: column; gap: 9px;
}
.rbtn {
  width: 46px; height: 46px; border-radius: var(--r-pill);
  display: grid; place-items: center; cursor: pointer;
  transition: transform 0.34s var(--ease-out), background 0.26s var(--ease), color 0.26s var(--ease);
}
.rbtn:hover { transform: scale(1.06); }
.rbtn:active { transform: scale(0.95); }
.rbtn.on {
  background: linear-gradient(168deg, var(--brass-lit) 0%, var(--brass) 100%);
  color: #23180A;
  box-shadow: inset 0 1px 0 var(--spec-mid), 0 8px 24px -8px var(--brass-glow);
}
.rbtn svg { width: 20px; height: 20px; }
.rbtn-group { display: flex; flex-direction: column; gap: 0; border-radius: var(--r-lg); overflow: hidden; }
.rbtn-group .rbtn { border-radius: 0; width: 46px; height: 44px; box-shadow: none; background: transparent; }
/* No divider between + and −: the hairline stopped short of the pill's rounded
   sides and read as a cut-off line rather than a separator. Hover already tells
   you which half you are on. */
.rbtn-group .rbtn:hover { transform: none; background: var(--surface-1); }

/* Toast-style hint that fades in beside the rail. */
.map-note {
  position: absolute; right: calc(env(safe-area-inset-right, 0px) + 68px); top: 50%;
  transform: translateY(-50%) translateX(8px);
  max-width: 232px; padding: 11px 14px; border-radius: var(--r-md);
  font-size: 0.79rem; line-height: 1.45; color: var(--ink-2);
  opacity: 0; pointer-events: none;
  transition: opacity 0.34s var(--ease-out), transform 0.34s var(--ease-out);
}
.map-note.show { opacity: 1; transform: translateY(-50%); }
@media (max-width: 700px) {
  .map-note { right: auto; left: 12px; right: 68px; max-width: none; }
}

/* ── attribution ───────────────────────────────────────────────────────── */
.map-credit {
  position: absolute; left: calc(env(safe-area-inset-left, 0px) + 12px);
  bottom: calc(env(safe-area-inset-bottom, 0px) + 12px);
  padding: 5px 11px; border-radius: var(--r-pill);
  font-size: 0.66rem; color: var(--ink-3);
  background: var(--map-chrome-2);
  -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px);
  box-shadow: inset 0 1px 0 var(--surface-1);
}
@media (max-width: 900px) { .map-credit { display: none; } }

/* ══ RESULT SHEET ══════════════════════════════════════════════════════════
   Desktop: a floating panel on the left, Apple-Maps-for-Mac style.
   Mobile: a bottom sheet with three detents, dragged by its grabber. */
.sheet {
  position: absolute;
  left: calc(env(safe-area-inset-left, 0px) + 12px);
  top: calc(env(safe-area-inset-top, 0px) + 74px);
  bottom: calc(env(safe-area-inset-bottom, 0px) + 12px);
  width: 372px;
  display: flex; flex-direction: column;
  border-radius: var(--r-lg);
  background: linear-gradient(160deg, var(--map-card-1) 0%, var(--map-card-2) 100%);
  -webkit-backdrop-filter: saturate(200%) blur(30px); backdrop-filter: saturate(200%) blur(30px);
  box-shadow: var(--glass-rim), 0 24px 60px -24px rgba(var(--shadow-rgb),0.34);
  overflow: hidden;
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .sheet { background: var(--map-card-1); }
}
.sheet-grab { display: none; }
.sheet-head { padding: 15px 18px 11px; flex: 0 0 auto; }
.sheet-title { font-family: var(--display); font-size: 1.12rem; font-weight: 600; color: var(--ink); font-variation-settings: 'opsz' 26, 'SOFT' 14; letter-spacing: -0.02em; }
.sheet-sub { font-size: 0.8rem; color: var(--ink-3); margin-top: 1px; }
.sheet-list { overflow-y: auto; flex: 1 1 auto; padding: 4px 8px 12px; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; }

.mrow {
  display: grid; grid-template-columns: 88px 1fr auto; align-items: center; gap: 12px;
  padding: 9px; border-radius: var(--r-md);
  transition: background-color 0.22s var(--ease), transform 0.32s var(--ease-out);
}
.mrow-b { min-width: 0; }
/* The explicit "open this listing" affordance. On touch the row's first tap
   selects it on the map (see map-page.js), so the navigation needs a target of
   its own rather than being the row's only meaning. */
.mrow-go {
  display: none;
  width: 34px; height: 34px; border-radius: 999px;
  place-items: center; color: var(--ink-3);
  background: var(--surface-1);
  transition: color var(--t-base, .3s) var(--ease), background-color var(--t-base, .3s) var(--ease);
}
.mrow-go svg { width: 15px; height: 15px; }
@media (pointer: coarse) {
  .mrow-go { display: grid; width: 44px; height: 44px; }
  .mrow.active .mrow-go { color: var(--ink); background: var(--surface-3); }
}
.mrow:hover, .mrow.active { background: var(--surface-2); }
.mrow.active { box-shadow: inset 3px 0 0 var(--brass); }
.mrow-img { border-radius: 14px; overflow: hidden; background: var(--bone-deep); aspect-ratio: 88/66; }
.mrow-img img { width: 100%; height: 100%; object-fit: cover; }
.mrow-noimg { width: 100%; height: 100%; background: var(--bone-deep); }
.mrow-price { font-family: var(--display); font-weight: 600; font-size: 1.04rem; color: var(--ink); font-variation-settings: 'opsz' 24; letter-spacing: -0.02em; }
/* 0.75rem, not 0.72: 11.5px is under the 12px floor this site holds to. */
.mrow-price span { font-family: var(--sans); font-size: 0.75rem; font-weight: 600; color: var(--ink-3); }
.mrow-place { font-size: 0.86rem; color: var(--ink-2); margin-top: 1px; }
.mrow-meta { font-size: 0.775rem; color: var(--ink-3); margin-top: 1px; }

@media (max-width: 900px) {
  .sheet {
    left: 8px; right: 8px; width: auto; top: auto;
    bottom: 0;
    height: 72dvh;
    border-radius: var(--r-xl) var(--r-xl) 0 0;
    padding-bottom: env(safe-area-inset-bottom, 0px);
    transform: translateY(var(--sheet-y, calc(100% - 128px)));
    transition: transform 0.44s var(--ease-out);
    touch-action: none;
  }
  .sheet.dragging { transition: none; }
  /* The grabber is the sheet's only handle and it measured 22px tall — half a
     finger. The bar you see stays 4.5px; the row around it carries the target.
     detents() in map-page.js reserves the matching extra peek height. */
  .sheet-grab {
    display: block; position: relative; height: 44px; flex: 0 0 auto; cursor: grab;
  }
  .sheet-grab::before {
    content: ''; position: absolute; top: 15px; left: 50%; transform: translateX(-50%);
    width: 40px; height: 4.5px; border-radius: 999px; background: var(--grab-bar);
  }
  .sheet-head { padding: 0 18px 10px; }

  /* The rail lives at the TOP on a phone, under the two-row bar.
     It used to sit above the sheet's peek and then fade out whenever the sheet
     or a layer panel rose — which meant that with the price card open all five
     controls were dead, including the one that would have closed the card, and
     the only exit was a 29px ✕. Apple's own rule for map chrome is to anchor it
     clear of the sheet's LOWEST resting position and leave it fixed to the map;
     the top-right corner is the one region no sheet ever reaches, so the rail
     goes there and simply stays put. */
  .map-rail {
    top: calc(env(safe-area-inset-top, 0px) + 122px);
    bottom: auto; transform: none;
  }
  .map-note {
    top: calc(env(safe-area-inset-top, 0px) + 122px);
    bottom: auto; transform: translateX(8px);
  }
  .map-note.show { transform: none; }
}

/* ══ PRICE PINS ════════════════════════════════════════════════════════════
   Two layers on purpose: .mpin-hit is the finger (≥44px in both axes, invisible)
   and .mpin is the pill you see. Inflating the pill itself to 44px would put a
   dozen fat lozenges on the map; a transparent margin costs nothing visually.
   The wrapper also owns the positioning transform, so .mpin is free to use its
   own transform for the selected-state lift. */
.mpin-hit {
  position: relative;
  display: inline-block;
  transform: translate(-50%, -100%);
  padding: 7px 8px 13px; /* bottom padding holds the tail + the anchor gap */
  cursor: pointer;
}
.mpin-hit.is-cluster { transform: translate(-50%, -50%); padding: 6px; }

/* A pin is NOT a glass chip. It is a label that has to stay legible on top of
   whatever the basemap happens to be under it, so it owns explicit colours
   instead of borrowing the translucent --surface-* family: a 19% white film
   reads fine over the pale voyager tiles and turns to smoke over the dark ones.
   The light values below are this file's originals, unchanged.

   In dark the capsule goes DARKER than the surrounding chrome, not lighter — a
   white lozenge every 40px on a near-black map is a field of headlights. What
   separates it from the map is therefore a RIM, not a shadow: a drop shadow on
   a black ground is invisible and cannot carry the silhouette. */
.mpin {
  --pin-bg:  rgba(255,255,255,0.94);
  --pin-fg:  var(--ink);
  --pin-rim: inset 0 1px 0 rgba(255,255,255,0.9);
  position: relative;
  display: inline-flex; align-items: center; white-space: nowrap;
  min-height: 31px; padding: 0 11px; border-radius: var(--r-pill);
  font-size: 0.78rem; font-weight: 700; letter-spacing: -0.01em;
  background: var(--pin-bg); color: var(--pin-fg);
  box-shadow: var(--pin-rim), 0 3px 10px rgba(var(--shadow-rgb),0.24), 0 10px 24px -12px rgba(var(--shadow-rgb),0.4);
  -webkit-backdrop-filter: saturate(180%) blur(10px); backdrop-filter: saturate(180%) blur(10px);
  transition: transform 0.32s var(--ease-out), background 0.22s var(--ease), color 0.22s var(--ease);
}
.mpin::after {
  content: ''; position: absolute; left: 50%; bottom: -5px; transform: translateX(-50%);
  border: 5px solid transparent; border-top-color: var(--pin-bg);
  filter: drop-shadow(0 2px 2px var(--tint-ink));
}
.mpin.rent { --pin-bg: rgba(36,69,59,0.94); --pin-fg: #EAF3EF; }

/* Dark pins. Both selectors, because an explicit choice is an attribute and a
   media query cannot see it. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) .mpin {
    --pin-bg:  rgba(31,35,31,0.95);
    --pin-rim: inset 0 0 0 1px rgba(255,255,255,0.24);
  }
  :root:not([data-theme='light']) .mpin.rent {
    --pin-bg:  rgba(27,57,48,0.95);
    --pin-fg:  #DCEDE5;
    --pin-rim: inset 0 0 0 1px rgba(94,156,134,0.60);
  }
}
:root[data-theme='dark'] .mpin {
  --pin-bg:  rgba(31,35,31,0.95);
  --pin-rim: inset 0 0 0 1px rgba(255,255,255,0.24);
}
:root[data-theme='dark'] .mpin.rent {
  --pin-bg:  rgba(27,57,48,0.95);
  --pin-fg:  #DCEDE5;
  --pin-rim: inset 0 0 0 1px rgba(94,156,134,0.60);
}
.mpin.active {
  background: linear-gradient(168deg, var(--brass-lit), var(--brass)); color: #23180A;
  transform: scale(1.07);
}
.mpin-hit.is-active { z-index: 500; }
.mpin.active::after { border-top-color: var(--brass); }

/* ── cluster bubble ───────────────────────────────────────────────────────
   Several listings that would otherwise print on top of each other collapse
   into one count. Deliberately a different object from a price: round, ink,
   no tail — it points at an area, not at an address. Tapping it zooms to its
   members, or fans them out when they share one coordinate (district-centroid
   listings genuinely do). */
.mpin.cluster {
  justify-content: center;
  min-width: 44px; height: 44px; padding: 0 7px;
  font-family: var(--display);
  font-size: 1.02rem; font-weight: 600; font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
  background: linear-gradient(168deg, var(--fill-1) 0%, var(--fill-2) 100%);
  color: var(--fill-fg);
  box-shadow: inset 0 1px 0 var(--spec-soft),
              0 0 0 5px var(--spec-mid),
              0 4px 14px rgba(var(--shadow-rgb),0.28), 0 16px 34px -16px rgba(var(--shadow-rgb),0.5);
  -webkit-backdrop-filter: none; backdrop-filter: none;
}
.mpin.cluster::after { display: none; }
.mpin.cluster.big { min-width: 52px; height: 52px; font-size: 1.14rem; }
.mpin.cluster.active {
  background: linear-gradient(168deg, var(--brass-lit), var(--brass)); color: #23180A;
}
/* Faint leader lines while a cluster is fanned out. */
.mpin-spoke { stroke: var(--ink); stroke-opacity: 0.32; }
/* While a fan is open the rest of the map steps back, so the ring reads as one
   object on top of context rather than as pins colliding with pins. */
.mpin-hit { transition: opacity 0.24s var(--ease); }
.leaflet-container.has-fan .mpin-hit { opacity: 0.26; }
.leaflet-container.has-fan .mpin-hit.is-fan { opacity: 1; }

/* ══ POPUP ═════════════════════════════════════════════════════════════════ */
.leaflet-popup-content-wrapper {
  border-radius: var(--r-md);
  background: linear-gradient(150deg, var(--map-card-1), var(--map-card-2));
  -webkit-backdrop-filter: saturate(200%) blur(26px); backdrop-filter: saturate(200%) blur(26px);
  box-shadow: var(--glass-rim), 0 20px 50px -18px rgba(var(--shadow-rgb),0.4);
  padding: 0; overflow: hidden;
}
.leaflet-popup-content { margin: 0; width: auto !important; }
.leaflet-popup-tip { background: var(--map-card-2); box-shadow: none; }
.mpop { width: 218px; }
.mpop img { width: 100%; height: 122px; object-fit: cover; }
.mpop-b { padding: 11px 13px 13px; }
.mpop-b strong { font-family: var(--display); font-size: 1.1rem; color: var(--ink); display: block; letter-spacing: -0.02em; }
.mpop-b div { font-size: 0.84rem; color: var(--ink-3); margin-top: 1px; }
.mpop-approx { font-size: 0.72rem !important; color: var(--brass) !important; margin-top: 5px !important; }
.mpop-b a { display: inline-block; margin-top: 9px; font-weight: 650; font-size: 0.85rem; color: var(--brass); }

/* ── price heat layer ─────────────────────────────────────────────────────
   Floating panel, same glass language as the rest of the map chrome. Sits
   bottom-left so it clears the results sheet on the right and the rail. */
.heat-panel {
  position: absolute;
  /* Bottom-RIGHT: the results sheet occupies the left column on desktop and the
     rail sits mid-right, so this corner is the only one that never collides. */
  right: max(14px, env(safe-area-inset-right));
  bottom: max(16px, env(safe-area-inset-bottom));
  z-index: 620;
  width: min(320px, calc(100vw - 28px));
  padding: 12px 13px 11px;
  border-radius: var(--r-md);
  display: flex;
  flex-direction: column;
  gap: 9px;
}
.heat-panel[hidden] { display: none; }
/* .bub gives these their rim and blur; the BACKING has to be card-grade,
   because the heat panel in particular is read against the colour field it is
   itself painting on the map. */
.heat-panel, .cad-panel { background: linear-gradient(150deg, var(--map-card-1) 0%, var(--map-card-2) 100%); }

.heat-modes { display: flex; gap: 4px; background: var(--hairline-2); padding: 3px; border-radius: var(--r-pill); }
.hmode {
  flex: 1 1 0;
  border: 0;
  background: none;
  font: inherit;
  font-size: .78rem;
  font-weight: 600;
  color: var(--ink-2);
  padding: 6px 4px;
  border-radius: var(--r-pill);
  cursor: pointer;
  white-space: nowrap;
  transition: background .18s var(--ease), color .18s var(--ease);
}
.hmode.on { background: var(--surface-3); color: var(--ink); box-shadow: 0 1px 3px rgba(var(--shadow-rgb),0.10); }

.heat-row { display: flex; gap: 8px; }
.heat-sel { flex: 1 1 0; display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.heat-sel > span { font-size: .75rem; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-3); }
.heat-sel .select { width: 100%; min-width: 0; padding: 5px 8px; font-size: .82rem; }

.heat-scale { display: flex; flex-direction: column; gap: 4px; }
.heat-bar { height: 9px; border-radius: var(--r-pill); box-shadow: inset 0 0 0 1px var(--hairline); }
.heat-ticks { display: flex; justify-content: space-between; font-size: .75rem; color: var(--ink-2); font-variant-numeric: tabular-nums; }

.heat-src { font-size: .72rem; line-height: 1.42; margin: 0; }

.heat-close {
  position: absolute;
  top: 8px; right: 9px;
  border: 0; background: none; cursor: pointer;
  font-size: .95rem; line-height: 1; color: var(--ink-3);
  padding: 3px 5px; border-radius: 8px;
}
.heat-close::after { content: ''; position: absolute; inset: -12px; }
.heat-close:hover { color: var(--ink); background: var(--hairline-2); }

/* popup */
.heat-pop { min-width: 190px; font-size: .84rem; }
.heat-pop strong { display: block; margin-bottom: 6px; font-size: .95rem; color: var(--ink); }
.hp-row { display: flex; justify-content: space-between; gap: 14px; align-items: baseline; padding: 2px 0; }
.hp-row > span { color: var(--ink-3); }
.hp-row > b { color: var(--ink); font-variant-numeric: tabular-nums; white-space: nowrap; }
.hp-diff { margin-top: 4px; padding-top: 5px; border-top: 1px solid var(--hairline); }
.hp-sub { display: block; font-size: .72rem; color: var(--ink-4); margin: -1px 0 4px; }
.heat-pop .up { color: var(--forest); }
.heat-pop .down { color: var(--clay); }

#heatBtn.on { color: var(--clay); }

@media (max-width: 720px) {
  /* Keep clear of the results sheet handle on phones (peek detent = 150px).
     The rail no longer lives down here (it moved to the top), so the card is
     free to own the bottom band without stealing any control. */
  .heat-panel { bottom: calc(env(safe-area-inset-bottom) + 162px); width: calc(100vw - 24px); right: 12px; left: 12px; }
  .hmode { font-size: .74rem; }
}

/* Finger-sized controls wherever there IS a finger. Keyed on pointer type, not
   on viewport width: a 900px tablet in portrait is still touched, and a 700px
   desktop window is still moused. */
@media (pointer: coarse) {
  .hmode, .cad-mode { min-height: 44px; }
  .cad-input, .heat-sel .select { min-height: 44px; }
  /* These two were ~29px effective (a 20px glyph plus a −12px ::after). A close
     button is the escape hatch for a panel that covers the map; it is the LAST
     control that should be hard to hit. */
  .heat-close, .cad-x { width: 44px; height: 44px; display: grid; place-items: center; }
  .heat-close::after, .cad-x::after { inset: 0; }
}

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

/* Median tick. The colour ramp is median-anchored (see map-heat.js norm()), so
   the middle of the bar is the median value, not the arithmetic midpoint. */
.heat-ticks { position: relative; }
.heat-mid {
  position: absolute; left: 50%; transform: translateX(-50%);
  color: var(--ink-3); white-space: nowrap;
}

/* ── cadastre lookup (hrsz-kereső) ────────────────────────────────────────
   Top-centre: the search is the primary action while the cadastre layer is on,
   and both side columns are already spoken for (results sheet left, rail +
   heat panel right). */
.cad-panel {
  position: absolute;
  top: calc(env(safe-area-inset-top, 0px) + 66px);
  left: 50%;
  transform: translateX(-50%);
  z-index: 640;
  width: min(420px, calc(100vw - 24px));
  padding: 10px 12px 9px;
  border-radius: var(--r-md);
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.cad-panel[hidden] { display: none; }

.cad-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.cad-title { font-size: .72rem; letter-spacing: .09em; text-transform: uppercase; color: var(--ink-3); font-weight: 600; }
.cad-x {
  position: relative;
  border: 0; background: none; cursor: pointer; color: var(--ink-3);
  font-size: .9rem; line-height: 1; padding: 3px 5px; border-radius: 8px;
}
.cad-x::after { content: ''; position: absolute; inset: -12px; }
.cad-x:hover { color: var(--ink); background: var(--hairline-2); }

.cad-row { display: flex; gap: 7px; align-items: center; }
.cad-row[hidden] { display: none; }
.cad-input { flex: 1 1 auto; min-width: 0; padding: 7px 11px; font-size: .9rem; }

/* Selected settlement reads as a chip you can click to go back a step. */
.cad-town {
  display: inline-flex; align-items: center; gap: 5px;
  border: 0; cursor: pointer; font: inherit; font-size: .82rem; font-weight: 600;
  color: var(--ink); background: var(--chip-bg);
  padding: 6px 9px; border-radius: var(--r-pill); white-space: nowrap;
  max-width: 42%; overflow: hidden; text-overflow: ellipsis; flex: 0 1 auto;
}
.cad-town:hover { background: var(--chip-bg-hover); }

.cad-modes { display: flex; gap: 3px; background: var(--hairline-2); padding: 2px; border-radius: var(--r-pill); flex: 0 0 auto; }
.cad-mode {
  border: 0; background: none; font: inherit; font-size: .76rem; font-weight: 600;
  color: var(--ink-2); padding: 5px 9px; border-radius: var(--r-pill); cursor: pointer;
}
.cad-mode.on { background: var(--surface-3); color: var(--ink); box-shadow: 0 1px 3px rgba(var(--shadow-rgb),0.10); }

.cad-drop {
  max-height: 260px; overflow-y: auto; overscroll-behavior: contain;
  display: flex; flex-direction: column; gap: 1px;
  border-top: 1px solid var(--hairline); padding-top: 6px;
}
.cad-drop[hidden] { display: none; }
.cad-opt {
  border: 0; background: none; font: inherit; text-align: left; cursor: pointer;
  padding: 8px 10px; border-radius: 10px; color: var(--ink); font-size: .88rem;
}
.cad-opt:hover, .cad-opt:focus-visible { background: var(--surface-2); }
.cad-opt small { color: var(--ink-3); font-size: .78em; }
.cad-empty { padding: 10px; color: var(--ink-3); font-size: .85rem; }

.cad-hint { margin: 0; font-size: .72rem; color: var(--ink-3); line-height: 1.4; }

/* ── parcel bubble ────────────────────────────────────────────────────── */
.cad-popup .leaflet-popup-content-wrapper {
  border-radius: var(--r-md);
  background: linear-gradient(150deg, var(--map-card-1) 0%, var(--map-card-1) 100%);
  -webkit-backdrop-filter: saturate(180%) blur(20px); backdrop-filter: saturate(180%) blur(20px);
  box-shadow: var(--glass-rim), 0 14px 40px -14px rgba(var(--shadow-rgb),0.34);
}
.cad-popup .leaflet-popup-content { margin: 13px 15px; }
.cad-popup .leaflet-popup-tip { background: var(--map-card-1); }

.cad-pop { display: flex; flex-direction: column; gap: 3px; min-width: 200px; }
.cad-pop-hrsz {
  font-family: var(--display); font-size: 1.32rem; font-weight: 600; color: var(--ink);
  line-height: 1.15; font-variant-numeric: tabular-nums;
}
.cad-pop-hrsz span { font-family: var(--sans); font-size: .62em; font-weight: 500; color: var(--ink-3); }
.cad-pop-place { font-size: .88rem; color: var(--ink-2); font-weight: 600; }
.cad-pop-addr { font-size: .85rem; color: var(--ink-3); }
.cad-pop-tag {
  align-self: flex-start; margin-top: 3px;
  font-size: .7rem; letter-spacing: .04em; color: var(--ink-3);
  border: 1px solid var(--tint-ink); border-radius: var(--r-pill); padding: 2px 8px;
}
.cad-pop-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  margin-top: 10px; padding: 9px 14px; border-radius: var(--r-pill);
  background: linear-gradient(168deg, var(--brass-lit) 0%, var(--brass) 100%);
  color: #23180A !important; font-weight: 700; font-size: .86rem; text-decoration: none;
  white-space: nowrap;
  box-shadow: inset 0 1px 0 var(--spec-mid), 0 6px 18px -8px var(--brass-glow);
}
.cad-pop-btn:hover { filter: brightness(1.05); }
.cad-pop-note { margin: 8px 0 0; font-size: .7rem; line-height: 1.45; color: var(--ink-3); }

@media (max-width: 720px) {
  /* Clears the two-row top bar (brand row + filter row) below 700px. */
  .cad-panel { top: calc(env(safe-area-inset-top, 0px) + 120px); width: calc(100vw - 20px); }
  .cad-town { max-width: 34%; }
  .cad-hint { display: none; }

  /* The search panel is full-width and top-anchored (it has to be — the
     keyboard opens from the bottom), and the rail is now top-right, so the two
     would sit on top of each other. Rather than retiring the rail — which is
     how every control on this map became unreachable in the first place — it
     steps down below the panel. --cad-h is written by map-cadastre.js from the
     panel's real height, so it stays right as the dropdown grows and shrinks. */
  .map-ui.cad-open .map-rail {
    top: calc(env(safe-area-inset-top, 0px) + 132px + var(--cad-h, 96px));
  }
  .map-ui.cad-open .map-note {
    top: calc(env(safe-area-inset-top, 0px) + 132px + var(--cad-h, 96px));
  }
  .map-rail, .map-note { transition: top var(--t-slow, 0.44s) var(--ease-out); }
}
@media (max-width: 720px) and (min-width: 701px) {
  .cad-panel { top: calc(env(safe-area-inset-top, 0px) + 66px); }
}
@media (prefers-reduced-motion: reduce) { .cad-opt, .cad-town, .cad-mode { transition: none; } }


/* ── language pill (map page) ────────────────────────────────────────────
   The map runs without site chrome, so the switcher rides in the top bar next
   to the brand. Sized to match .fpill so the row reads as one control strip. */
.map-top .lang-pill-compact { padding: 2px; flex: 0 0 auto; }
.map-top .lang-opt {
  min-width: 30px; height: 26px; padding: 0 0.42em;
  font-size: 0.7rem; font-weight: 650; letter-spacing: 0.05em;
  border-radius: 999px; color: var(--ink-3);
}
.map-top .lang-opt.on { color: var(--ink); background: var(--surface-solid); }

@media (max-width: 700px) {
  /* ── two rows, not one ────────────────────────────────────────────────
     At 390px the three groups were fighting over one 366px line: the filter
     scroller was left with 113px of the 459px it needs, so four of five pills
     were unreachable and the fifth was sliced by an invisible container edge
     mid-screen. Brand + language keep the first line; the filters get a line of
     their own, bled to the viewport edges so a half-visible pill is cut by the
     SCREEN — which reads as "scroll me" — rather than by a box. */
  .map-top { flex-wrap: wrap; row-gap: 8px; column-gap: 8px; }
  .map-brand { order: 1; height: 44px; }
  .map-top .lang-pill-compact { order: 2; margin-left: auto; }

  .map-filters {
    order: 3;
    flex: 1 0 100%;
    margin-inline: calc(-1 * (env(safe-area-inset-left, 0px) + 12px))
                   calc(-1 * (env(safe-area-inset-right, 0px) + 12px));
    padding-inline: calc(env(safe-area-inset-left, 0px) + 12px)
                    calc(env(safe-area-inset-right, 0px) + 12px);
    padding-block: 1px;
    scroll-padding-inline: calc(env(safe-area-inset-left, 0px) + 12px);
    scroll-snap-type: x proximity;
    overscroll-behavior-x: contain;
  }
  .fpill { height: 44px; scroll-snap-align: start; }

  /* 30×26 at 11.2px was both under the 12px type floor and a poor target.
     44px of vertical hit area already comes from .lang-opt::after in base.css. */
  .map-top .lang-pill-compact { padding: 3px; }
  .map-top .lang-opt { min-width: 44px; height: 34px; font-size: 0.78rem; padding: 0 0.4em; }
}

/* ── parcel card: area + albetétek ─────────────────────────────────────────
   A condominium block is one földrészlet with one hrsz and many separately
   titled flats. The official client puts them behind an "Albetétek (n db)"
   dialog; inside a Leaflet popup on a phone a second modal is worse than an
   inline disclosure, so this expands in place. */
.cad-pop-area { font-size: .78rem; color: var(--ink-3); margin-top: 2px; }
.cad-pop-sub {
  display: inline-block; margin-left: 8px;
  border: 0; background: var(--chip-bg); color: var(--ink-2);
  font: inherit; font-size: .74rem; font-weight: 600;
  padding: 3px 9px; border-radius: var(--r-pill); cursor: pointer;
  transition: background-color var(--t-fast, .18s) var(--ease);
}
.cad-pop-sub:hover { background: var(--chip-bg-hover); color: var(--ink); }
.cad-alb-host { margin-top: 6px; }
.cad-alb-load { font-size: .78rem; color: var(--ink-3); padding: 5px 0; }
.cad-alb { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; max-height: 200px; overflow-y: auto; }
.cad-alb li {
  display: flex; align-items: baseline; gap: 8px;
  padding: 5px 7px; border-radius: 9px; background: var(--surface-1);
  font-size: .78rem;
}
.cad-alb-h { font-weight: 650; color: var(--ink); white-space: nowrap; }
.cad-alb-l { color: var(--ink-3); flex: 1 1 auto; min-width: 0; }
.cad-alb .cad-pop-btn { padding: 2px 8px; font-size: .7rem; margin: 0; }
@media (pointer: coarse) { .cad-pop-sub { min-height: 36px; padding: 8px 12px; } }
