/* ============================================================
   Liberty City — interactive map
   Same HUD tokens as the checklist. Sidebar = quiet instrument
   panel, map = hero. No gradients, hairline borders.
   ============================================================ */

:root {
  --bg:      #111214;
  --panel:   #1A1C20;
  --panel-2: #1F2126;
  --text:    #EDEAE2;
  --muted:   #868D98;
  --accent:  #FF5FA8;
  --accent-hi: #ff85bd;
  --accent-rgb: 255,95,168;
  --line:    #2A2D33;

  --water:   #0d1a26;

  --sans: "IBM Plex Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --display: "Anton", "Arial Narrow", Impact, var(--sans);

  --radius: 6px;
  --side-w: 330px;
}

*, *::before, *::after { box-sizing: border-box; }
html, body { height: 100%; }

body.map-page {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  overflow: hidden;
}

.num { font-family: var(--mono); font-variant-numeric: tabular-nums; }

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

a { color: var(--accent); text-underline-offset: 2px; }
a:hover { color: var(--accent-hi); }

:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 3px; }

.skip-link {
  position: absolute; left: 12px; top: -60px; z-index: 1200;
  background: var(--accent); color: #111214; font-weight: 600;
  padding: 10px 14px; border-radius: var(--radius); text-decoration: none;
  transition: top .15s;
}
.skip-link:focus { top: 12px; }

/* ---------------- Shell ---------------- */

.map-shell { display: flex; height: 100%; width: 100%; }

#map {
  flex: 1 1 auto;
  min-width: 0;
  height: 100%;
  background: var(--water);
  outline: none;
}

/* ---------------- Sidebar ---------------- */

.side {
  flex: 0 0 var(--side-w);
  width: var(--side-w);
  height: 100%;
  display: flex;
  flex-direction: column;
  background: var(--panel);
  border-right: 1px solid var(--line);
  z-index: 900;
}

.side-head { padding: 14px 16px 13px; border-bottom: 1px solid var(--line); }

.side-title-row { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; row-gap: 8px; }

.side-title {
  font-family: var(--display); font-weight: 400;
  font-size: 27px; line-height: 1.05;
  letter-spacing: .075em; text-transform: uppercase;
  margin: 0; transform: skewX(-6deg);
  flex: 1 1 auto; min-width: 0;
}

.side-nav { display: flex; align-items: center; gap: 7px; flex: none; flex-wrap: wrap; row-gap: 6px; }
.side-nav a, .side-nav span {
  font-size: 10.5px; letter-spacing: .13em; text-transform: uppercase;
  text-decoration: none; color: var(--muted);
  padding: 4px 7px; border: 1px solid var(--line); border-radius: 4px;
  white-space: nowrap;
}
.side-nav a:hover { color: var(--text); border-color: #3A3E46; }
.side-nav .here { color: #111214; background: var(--accent); border-color: var(--accent); font-weight: 600; }

.side-sub {
  margin: 7px 0 8px;
  font-size: 11.5px; color: var(--muted);
  letter-spacing: .06em; text-transform: uppercase;
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
.side-sub .dot { color: var(--line); }
.side-sub .num { color: var(--text); font-weight: 600; font-size: 12.5px; }

.side-bar { height: 4px; background: var(--line); border-radius: 2px; overflow: hidden; }
.side-bar > span { display: block; height: 100%; width: 0%; background: var(--accent); transition: width .28s ease; }

/* search */
.side-search { padding: 12px 16px; border-bottom: 1px solid var(--line); position: relative; }
.search-field { position: relative; display: flex; align-items: center; }
.search-ico { position: absolute; left: 11px; color: var(--muted); display: flex; pointer-events: none; }

.side-search input[type="search"] {
  width: 100%;
  background: #141518; border: 1px solid var(--line); color: var(--text);
  font-family: var(--sans); font-size: 14px;
  padding: 9px 12px 9px 34px; border-radius: var(--radius);
}
.side-search input[type="search"]::placeholder { color: #6C737D; }
.side-search input[type="search"]:focus { border-color: var(--accent); }

.results {
  margin: 10px -16px -12px;
  border-top: 1px solid var(--line);
  max-height: 46vh; overflow-y: auto;
}
.results[hidden] { display: none; }
.result {
  display: flex; align-items: center; gap: 10px; width: 100%;
  background: none; border: 0; border-bottom: 1px solid var(--line);
  padding: 9px 16px; text-align: left; cursor: pointer;
  color: var(--text); font-family: var(--sans); font-size: 13.5px;
}
.result:hover, .result:focus-visible { background: var(--panel-2); }
.result-meta { display: block; font-size: 11px; color: var(--muted); letter-spacing: .04em; }
.result.found .result-title { color: var(--muted); text-decoration: line-through; text-decoration-thickness: 1px; }
.results-empty { padding: 14px 16px; color: var(--muted); font-size: 13px; }
.results-more { padding: 8px 16px 10px; color: #5F656E; font-size: 11.5px; font-family: var(--mono); }

/* tree */
.side-tree { flex: 1 1 auto; overflow-y: auto; overscroll-behavior: contain; }

.grp { border-bottom: 1px solid var(--line); }
.grp-head {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 16px 8px;
}
.grp-title {
  margin: 0; flex: 1 1 auto; min-width: 0;
  font-size: 10.5px; font-weight: 600; letter-spacing: .16em;
  text-transform: uppercase; color: var(--muted);
}
.grp-pip { width: 8px; height: 8px; flex: none; background: var(--cat-color, var(--line)); }
.grp-actions { display: flex; align-items: center; gap: 6px; flex: none; }
.linkbtn {
  background: none; border: 0; padding: 0; cursor: pointer;
  color: var(--muted); font-family: var(--sans); font-size: 10.5px;
  letter-spacing: .08em; text-transform: uppercase;
}
.linkbtn:hover { color: var(--accent); }
.sep { color: var(--line); font-size: 10px; }

.grp-cats { padding-bottom: 8px; }

.cat {
  display: flex; align-items: center; gap: 10px; width: 100%;
  background: none; border: 0; border-left: 2px solid transparent;
  padding: 7px 16px 7px 14px;
  cursor: pointer; text-align: left;
  color: var(--text); font-family: var(--sans); font-size: 13.5px;
  transition: background .12s, opacity .12s, border-color .12s;
}
.cat:hover { background: var(--panel-2); }
.cat[aria-pressed="true"] { border-left-color: #3A3E46; }
.cat[aria-pressed="false"] { opacity: .42; }
.cat-ico {
  flex: none; width: 22px; height: 22px;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 13px; color: var(--cat-color, #B9BEC7);
  background: #141518; border: 1px solid var(--line); border-radius: 50%;
}
.cat-title { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cat-count {
  flex: none; font-family: var(--mono); font-size: 11.5px;
  font-variant-numeric: tabular-nums; color: var(--muted); letter-spacing: -.01em;
}
.cat.done .cat-count { color: var(--accent); }
.cat.done .cat-ico { color: var(--accent); border-color: rgba(var(--accent-rgb),.4); }

.side-foot {
  flex: none; padding: 10px 16px 12px;
  border-top: 1px solid var(--line);
  color: #666C75; font-size: 11.5px;
}
.side-foot p { margin: 0 0 3px; }
.side-foot code { font-family: var(--mono); font-size: 10.5px; color: var(--muted); }

/* mobile toggle */
.side-toggle {
  display: none;
  position: absolute; left: 12px; top: 12px; z-index: 1000;
  align-items: center; gap: 8px;
  background: rgba(26,28,32,.95);
  border: 1px solid var(--line); border-radius: var(--radius);
  color: var(--text); font-family: var(--sans);
  font-size: 11.5px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase;
  padding: 9px 12px; cursor: pointer;
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
}
.side-scrim { display: none; }

/* ---------------- Markers ---------------- */

/* Compositor isolation for the marker layer.
   Measured: at z11 all 728 chips fit the viewport, and every drag frame cost
   110-130ms with *zero* marker JS running — the whole bill was the browser
   re-rasterising 728 bordered, round, glyph-bearing chips as the pane
   translated. Promoting the pane itself (ONE element, one extra texture) means
   its children are rasterised once and the drag only moves the finished layer.
   Deliberately just `will-change: transform`: `backface-visibility` /
   `perspective` hints are legacy WebKit workarounds, and each one is another
   property the compositor has to reason about per element. Nothing else in the
   sheet may take will-change — a hint on 728 chips would defeat the point by
   giving each one its own layer. */
.leaflet-marker-pane { will-change: transform; }

/* Hit-testing during movement.
   Every pointermove over the map otherwise walks 728 interactive icons, and a
   hit turns into a :hover match -> a transform transition -> a repaint, all
   while the pane is already translating. Neither hover nor a click is
   meaningful mid-gesture, so the pane simply opts out of the pointer for the
   duration. Leaflet puts `leaflet-dragging` on <body> (verified in
   vendor/leaflet.js, Draggable._onMove/finishDrag), hence the loose descendant
   selector; `is-zooming` is set by our own wheel handler on the container. */
.leaflet-dragging .leaflet-marker-pane,
.leaflet-container.is-zooming .leaflet-marker-pane { pointer-events: none; }

/* Up to 728 of these are on screen at once, so every declaration here is paid
   728 times on each paint. No box-shadow — a blurred layer per chip was the
   dominant paint cost while panning; the border carries the depth instead —
   and no transition outside a hover-capable pointer.
   `contain` is deliberately absent. Paint containment would clip the two things
   that overflow the 28x28 icon box, the found-check badge and the hover scale;
   layout containment would fit, but it also makes each marker a stacking
   context, and that is not a change worth making unmeasured. */
.mg-marker { background: none !important; border: 0 !important; }

.mg-chip {
  position: relative;
  width: 28px; height: 28px;
  display: flex; align-items: center; justify-content: center;
  background: #1A1C20;                              /* chip stays dark — glyph carries the hue */
  border: 1.5px solid var(--cat-line, #2A2D33);     /* subtle tint of the group hue */
  border-radius: 50%;
  color: var(--cat-color, #EDEAE2);
}
.mg-chip i { font-size: 14px; line-height: 1; display: block; color: inherit; }

.leaflet-marker-icon:focus-visible .mg-chip,
.mg-marker:focus-visible .mg-chip { outline: 2px solid var(--accent); outline-offset: 2px; }

/* found state always wins over the group hue */
.mg-marker.is-found .mg-chip { opacity: .4; color: var(--accent); border-color: rgba(var(--accent-rgb),.45); }

/* Hover-only affordances, and the only transition markers carry. Scoped to real
   pointers so touch devices never hold a transition on 728 elements, and kept
   after the found-state rule so its opacity override still wins. Nothing here
   can fire from the pane transform used during a zoom gesture — an inherited
   transform does not start a child transition, and none of these properties
   change while the pane moves. */
@media (hover: hover) {
  /* transform + border-color only. `opacity` used to be in this list, which put
     a third animatable property on all 728 chips for the sake of a hover step
     the eye reads as instant anyway — it now snaps. Never `transition: all`:
     that makes every property a candidate and Chrome tracks the lot. */
  .mg-chip { transition: transform .1s ease, border-color .1s ease; }
  .mg-marker:hover .mg-chip { transform: scale(1.14); border-color: var(--cat-color, #4A4F58); z-index: 2; }
  .mg-marker.is-found:hover .mg-chip { opacity: .75; color: var(--accent); border-color: rgba(var(--accent-rgb),.45); }
}

.mg-check {
  position: absolute; right: -3px; bottom: -3px;
  width: 13px; height: 13px; border-radius: 50%;
  background: var(--accent); color: #111214;
  display: none; align-items: center; justify-content: center;
  font-size: 9px; font-weight: 700; line-height: 1;
  border: 1.5px solid #111214;
}
.mg-marker.is-found .mg-check { display: flex; }

.mg-marker.is-active .mg-chip {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(var(--accent-rgb),.2), 0 2px 8px rgba(0,0,0,.6);
  opacity: 1;
}

/* ---- low-zoom dot mode ---------------------------------------------------
   Below zoom 12 the whole city is on screen and all 728 chips are painted at
   once — exactly the band where the drag lag was felt. At that scale a 14px
   icomoon glyph is unreadable anyway, so the chip collapses to a bare 12px
   dot: no text run to shape and raster, and the painted disc drops from
   28x28 to 12x12, roughly a fifth of the pixels. The hue moves from the glyph
   to the fill so categories stay distinguishable.
   `zoomed-out` is set on the map container by map.js on zoomend / gesture
   settle — never per frame. Nothing here changes geometry that Leaflet
   measures: the icon box stays 28x28 and the dot is centred inside it with a
   plain margin, so iconAnchor, popupAnchor and hit-testing are untouched. */
.leaflet-container.zoomed-out .mg-chip {
  width: 12px; height: 12px;
  margin: 8px;                                   /* (28 - 12) / 2 — stays on the anchor */
  border-width: 1px;
  border-color: #111214;
  background: var(--cat-color, #9AA1AB);
}
.leaflet-container.zoomed-out .mg-chip i { display: none; }
.leaflet-container.zoomed-out .mg-check { display: none; }

/* found: still amber, still dimmed — the one distinction worth keeping here */
.leaflet-container.zoomed-out .mg-marker.is-found .mg-chip {
  background: var(--accent); border-color: #111214; opacity: .4;
}
.leaflet-container.zoomed-out .mg-marker.is-active .mg-chip {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(var(--accent-rgb),.25);
  opacity: 1;
}
@media (hover: hover) {
  .leaflet-container.zoomed-out .mg-marker:hover .mg-chip { transform: scale(1.35); }
  .leaflet-container.zoomed-out .mg-marker.is-found:hover .mg-chip { opacity: .8; }
}

/* ---------------- Popup ---------------- */

.leaflet-popup-content-wrapper {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  color: var(--text);
  box-shadow: 0 10px 30px rgba(0,0,0,.6);
  padding: 0;
}
.leaflet-popup-content { margin: 0; width: 288px !important; line-height: 1.5; }
.leaflet-popup-tip { background: var(--panel); border: 1px solid var(--line); box-shadow: none; }
.leaflet-popup-close-button {
  color: var(--muted) !important;
  width: 26px !important; height: 26px !important;
  font-size: 18px !important; padding: 3px 0 0 !important;
}
.leaflet-popup-close-button:hover { color: var(--accent) !important; background: none !important; }

.pop-head { padding: 13px 34px 11px 15px; border-bottom: 1px solid var(--line); }
.pop-title { margin: 0 0 5px; font-size: 15px; font-weight: 600; line-height: 1.3; }
.pop-tags { display: flex; flex-wrap: wrap; gap: 6px; }
.pop-tag {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 11px; line-height: 1.3; padding: 3px 7px;
  border: 1px solid var(--line); border-radius: 4px;
  background: #17181C; color: var(--muted); white-space: nowrap;
}
.pop-tag i { font-size: 11px; }

.pop-body {
  padding: 12px 15px;
  font-size: 13px; color: #C7CBD2;
  max-height: 260px; overflow-y: auto;
}
.pop-body > *:first-child { margin-top: 0; }
.pop-body > *:last-child { margin-bottom: 0; }
.pop-body p { margin: 0 0 .6em; }
.pop-body ul { margin: .3em 0 .7em; padding-left: 1.15em; }
.pop-body li { margin: .18em 0; }
.pop-body strong { color: var(--text); font-weight: 600; }
.pop-body em { color: #D6D9DE; font-style: italic; }
.pop-body a { color: var(--accent); }
.pop-body .pop-none { color: #5F656E; font-family: var(--mono); font-size: 12.5px; }

.pop-foot { padding: 0 15px 13px; }
.pop-btn {
  width: 100%;
  font-family: var(--sans); font-size: 12px; font-weight: 600;
  letter-spacing: .08em; text-transform: uppercase;
  color: var(--text); background: #202329;
  border: 1px solid var(--line); border-radius: var(--radius);
  padding: 9px 12px; cursor: pointer;
  transition: background .12s, border-color .12s, color .12s;
}
.pop-btn:hover { background: #282C33; border-color: #3A3E46; }
.pop-btn[aria-pressed="true"] {
  background: var(--accent); border-color: var(--accent); color: #111214;
}
.pop-btn[aria-pressed="true"]:hover { background: var(--accent-hi); border-color: var(--accent-hi); }

/* ---------------- Leaflet chrome ---------------- */

.leaflet-container { background: var(--water); font-family: var(--sans); outline: none; }
.leaflet-container a { color: var(--accent); }

.leaflet-bar { border: 0; box-shadow: none; }
.leaflet-bar a, .leaflet-bar a:hover {
  background: rgba(26,28,32,.95);
  border: 1px solid var(--line);
  color: var(--text);
  width: 32px; height: 32px; line-height: 30px;
}
.leaflet-bar a:first-child { border-radius: var(--radius) var(--radius) 0 0; }
.leaflet-bar a:last-child { border-radius: 0 0 var(--radius) var(--radius); border-top: 0; }
.leaflet-bar a:hover { background: #282C33; color: var(--accent); }
.leaflet-bar a.leaflet-disabled { color: #4A4F58; background: rgba(26,28,32,.7); }

.leaflet-control-attribution {
  background: rgba(17,18,20,.86) !important;
  color: #666C75 !important;
  border: 1px solid var(--line); border-right: 0; border-bottom: 0;
  border-radius: var(--radius) 0 0 0;
  font-size: 10.5px; padding: 3px 8px;
}
.leaflet-control-attribution a { color: var(--muted) !important; }

/* readout */
.map-readout {
  background: rgba(17,18,20,.9);
  border: 1px solid var(--line); border-radius: var(--radius);
  padding: 6px 10px;
  font-family: var(--mono); font-size: 11px;
  color: var(--muted); letter-spacing: .04em;
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
}
.map-readout b { color: var(--text); font-weight: 600; }

/* ---------------- Tile style switch ----------------
   The bottom-left corner holds two controls now, and Leaflet stacks corner
   controls vertically by floating them. A flex row puts the style pill beside
   the zoom readout instead of above it; the 10px gap is Leaflet's own
   `.leaflet-left .leaflet-control` margin, so nothing here re-specifies it. */
.map-shell .leaflet-bottom.leaflet-left { display: flex; align-items: flex-end; }
.map-shell .leaflet-bottom.leaflet-left > .leaflet-control { float: none; clear: none; }

.map-style {
  display: inline-flex; gap: 3px; padding: 3px;
  background: rgba(17,18,20,.9);
  border: 1px solid var(--line); border-radius: var(--radius);
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
}
.map-style-btn {
  appearance: none; -webkit-appearance: none;
  border: 0; background: transparent; cursor: pointer;
  font-family: var(--mono); font-size: 10.5px; font-weight: 600;
  letter-spacing: .08em; text-transform: uppercase;
  color: var(--muted);
  padding: 4px 9px; border-radius: 4px; line-height: 1.5;
}
.map-style-btn:hover { color: var(--text); background: var(--panel-2); }
/* after :hover so the filled segment keeps the accent while the pointer is on it.
   The fill is var(--accent) — this game's pink — never a literal hue, so the one
   control stylesheet reads correctly whatever :root sets. */
.map-style-btn[aria-pressed="true"] { background: var(--accent); color: #111214; }
.map-style-btn[aria-pressed="true"]:hover { background: var(--accent-hi); color: #111214; }
.map-style-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ---- markers over the radar and classic pyramids -------------------------
   Measured, not guessed. Mean/median relative luminance of a representative
   z12 city tile and the z9 whole-island tile, per set:

     atlas    z12 mean 123, p50 154   z9 mean 201, p50 217
     radar    z12 mean  90, p50  80   z9 mean 109, p50 118
     classic  z12 mean 153, p50 204   z9 mean 193, p50 199

   The chip body is #1A1C20 — luminance 28 — and its border is `--cat-line`, a
   35% tint of the group hue over that dark fill, so the border is barely
   lighter than the body. Atlas is what the marker design was tuned against and
   is left byte-for-byte alone. The other two each fail in their own way, and
   each gets only the rule that fixes its own failure.

   Deliberately geometry-free, exactly as on the GTA V map: box-shadow paints
   outside the border box, and the border-width and 28x28 icon box are never
   touched, so iconAnchor, the dot's centring margin and hit-testing are
   identical in every style.

   Every border-colour rule below is gated on :not(.zoomed-out). In dot mode the
   border is the dark #111214 separator that holds the hue-filled disc off the
   map, and recolouring it to the hue would erase exactly the contrast these
   blocks exist to add. The halo is the dot's fix; the border is the chip's. */

/* Radar — the dark-on-dark case, and the worse of the two. 36% of a z12 radar
   tile sits in the 32-64 luminance band (the near-black building blocks) and a
   further 30% in 64-96: the chip's own body luminance of 28 is inside the
   dominant band, so a dark disc on dark blocks has almost no edge, and the
   faint --cat-line border has none at all.
   The halo here is *light*, not the dark ring the GTA V satellite mode uses.
   The failure is dark-on-dark, so the separator has to be the opposite polarity.
   It is invisible over radar's other extreme, the pale grey road fills at ~165
   — which is correct, because there the dark chip already has all the contrast
   it needs. The ring only has to work where the chip fails. */
.leaflet-container.style-radar:not(.zoomed-out) .mg-chip {
  border-color: var(--cat-color, #4A4F58);
  box-shadow: 0 0 0 2px rgba(237, 234, 226, .45);
}
/* found stays dimmed; it only gains the accent border over the hue one */
.leaflet-container.style-radar:not(.zoomed-out) .mg-marker.is-found .mg-chip {
  border-color: rgba(var(--accent-rgb), .55);
}
/* active already carries an accent ring — seat it on the light halo so the glow
   reads against the near-black blocks as well as against the slate water */
.leaflet-container.style-radar:not(.zoomed-out) .mg-marker.is-active .mg-chip {
  box-shadow: 0 0 0 2px rgba(237, 234, 226, .5), 0 0 0 5px rgba(var(--accent-rgb), .35), 0 2px 8px rgba(0, 0, 0, .6);
}
/* Radar dots are deliberately left alone. Below z12 the radar pyramid is a
   near-uniform mid slate (z9 p50 118, 80% of pixels in the 96-128 band), the
   dot is a saturated group hue, and the existing 1px #111214 border is already
   a dark separator against it — the one case where the shipped dot design is
   the right answer without help. Adding a light ring there would fight the dark
   ring that is doing the work. */

/* Classic — the opposite problem: the 2002 paper map. A z12 tile is 44% pure
   white (road fill, L > 224) cut by 28% pure black (the heavy road casing),
   with pale yellow-green blocks between. The dark chip reads perfectly against
   the paper, so it needs no halo at all; what it loses is the border, which is
   a dark tint and so disappears into both the black casing and, being so close
   to the body colour, into the chip itself against white. Full hue restores the
   only per-group cue at chip zoom. */
.leaflet-container.style-classic:not(.zoomed-out) .mg-chip {
  border-color: var(--cat-color, #4A4F58);
}
.leaflet-container.style-classic:not(.zoomed-out) .mg-marker.is-found .mg-chip {
  border-color: rgba(var(--accent-rgb), .55);
}
/* the accent ring at .2 alpha is washed out on near-white paper — seat it on a
   dark halo and lift the alpha */
.leaflet-container.style-classic:not(.zoomed-out) .mg-marker.is-active .mg-chip {
  box-shadow: 0 0 0 2px rgba(10, 11, 13, .75), 0 0 0 5px rgba(var(--accent-rgb), .45), 0 2px 8px rgba(0, 0, 0, .4);
}
/* Classic dots are the one dot case that does need help, and it is the mirror
   of the radar chip: light on light. Below z12 the classic pyramid is near-white
   paper (z9 p50 199, 82% of pixels in the 192-224 band) and the dot is a light
   group hue — #C0B2C7 is luminance 187, #F0997B is 167 — so the 1px #111214
   border is the only thing separating them, and 1px on a 12px disc is thin. A
   tight dark ring, not the chip's 2px: at 12px a wide halo reads as a bigger
   dot and the group hues start to crowd. */
.leaflet-container.style-classic.zoomed-out .mg-chip {
  box-shadow: 0 0 0 1.5px rgba(10, 11, 13, .55);
}
.leaflet-container.style-classic.zoomed-out .mg-marker.is-active .mg-chip {
  box-shadow: 0 0 0 1.5px rgba(10, 11, 13, .8), 0 0 0 4px rgba(var(--accent-rgb), .4);
}

/* ---------------- Responsive ---------------- */

@media (max-width: 860px) {
  .side-toggle { display: inline-flex; }
  .map-shell { position: relative; }

  .side {
    position: absolute; left: 0; top: 0; bottom: 0;
    z-index: 1100;
    box-shadow: 0 0 40px rgba(0,0,0,.6);
    transform: translateX(-101%);
    transition: transform .2s ease;
    max-width: 86vw;
  }
  body.side-open .side { transform: translateX(0); }
  body.side-open .side-scrim {
    display: block; position: absolute; inset: 0; z-index: 1050;
    background: rgba(0,0,0,.5);
  }
  body.side-open .side-toggle { left: auto; right: 12px; }
}

@media (max-width: 420px) {
  .side-title { font-size: 23px; }
  .leaflet-popup-content { width: 240px !important; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
}
