/* ABC — map view. Loaded after app.css and after vendor/maplibre-gl.css, so it
   can lean on the app's tokens and still win against MapLibre's own control
   styling, which is built for a white basemap and looks wrong on a dark one.

   Every marker here is an HTML element rather than something painted into the
   WebGL canvas — see the header of map.js for why. That is what lets the two
   themes be real themes and lets a pin be a focusable button. */

/* The ring each pin is drawn with. Its job is separating pins from each other
   where they cluster, so it is the map's own backdrop rather than a colour:
   near-black under the dark theme, white under the light one. */
:root { --mk-ring: #0b0d11; --mk-hq-glyph: #06231a; }
:root[data-theme="light"] { --mk-ring: #ffffff; --mk-hq-glyph: #ffffff; }

/* ---------- the box the map lives in ---------- */

.map-mount {
  position: relative;
  height: clamp(360px, 62vh, 720px);
  background: var(--panel-2);
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  overflow: hidden;
}
.map-canvas { position: absolute; inset: 0; }
.map-wait {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: 12.5px; color: var(--faint);
}
.maplibregl-canvas:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* ---------- markers ----------
   MapLibre writes `transform: translate(...)` onto the marker element itself to
   position it, so nothing here may set a transform on .mk — the diamond is
   rotated on the inner dot instead, and the HQ tag is positioned rather than
   laid out. Getting this wrong slides every pin off its coordinate. */

.mk {
  width: 15px; height: 15px; padding: 0;
  background: none; border: none; line-height: 0;
  cursor: pointer;
}
.mk-hq { cursor: default; }

.mk-dot {
  display: block; width: 15px; height: 15px;
  border: 2px solid var(--mk-ring);
  box-sizing: border-box;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .45);
}

/* Shape carries the distinction, not colour: a prospect is a circle and a
   competitor is a diamond, so the map still reads in greyscale, in print, and
   to anyone who does not separate blue from red. The colours agree with the
   shapes rather than doing the work alone, and every pin's accessible name says
   "Prospect" or "Competitor" in words. */
.dot-firm { border-radius: 50%; background: var(--accent); }
.dot-comp {
  width: 13px; height: 13px; margin: 1px;
  border-radius: 2px; background: var(--bad);
  transform: rotate(45deg);
}
.dot-hq {
  width: 19px; height: 19px; margin: -2px;
  border-radius: 50%; background: var(--good);
  color: var(--mk-hq-glyph); font-size: 11px; line-height: 15px; text-align: center;
  font-weight: 700;
}

.mk-firm:hover .mk-dot, .mk-comp:hover .mk-dot { filter: brightness(1.25); }
.mk-firm:focus-visible, .mk-comp:focus-visible { outline: none; }
.mk-firm:focus-visible .mk-dot, .mk-comp:focus-visible .mk-dot {
  box-shadow: 0 0 0 3px var(--accent), 0 1px 3px rgba(0, 0, 0, .45);
}
/* A ticked firm keeps its shape and gains a halo — the selection is an addition
   to the pin, never a recolouring of it. */
.mk-sel .mk-dot { box-shadow: 0 0 0 3px var(--accent-soft), 0 0 0 4px var(--accent); }

/* Absolutely positioned so the marker's own box stays exactly the dot: MapLibre
   centres the element on the coordinate, and a label in the flow would drag the
   dot off the address it belongs to. */
.mk-tag {
  position: absolute; left: 100%; top: 50%; margin-left: 6px;
  transform: translateY(-50%);
  font-size: 10px; font-weight: 700; letter-spacing: .8px; text-transform: uppercase;
  color: var(--good); white-space: nowrap; line-height: 1;
  text-shadow: 0 1px 3px var(--bg), 0 0 6px var(--bg);
}

.mk-county {
  pointer-events: none; user-select: none;
  font-size: 10.5px; font-weight: 700; letter-spacing: 1.4px; text-transform: uppercase;
  color: var(--muted); white-space: nowrap;
  text-shadow: 0 1px 3px var(--bg), 0 0 8px var(--bg), 0 0 8px var(--bg);
}
.mk-county-out { color: var(--faint); letter-spacing: 1px; font-weight: 400; }

/* ---------- legend ---------- */

.map-legend {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px 18px;
  padding: 9px 14px; font-size: 11.5px; color: var(--muted);
  background: var(--panel-2);
}
.map-key { display: inline-flex; align-items: center; gap: 7px; white-space: nowrap; }
/* The legend swatches are the same elements the map draws, at the same size, so
   the key cannot drift away from the thing it explains. */
.map-key .mk-dot { flex-shrink: 0; box-shadow: none; }
.map-key .dot-comp { margin: 0 2px; }
.map-key .dot-hq { margin: 0; }

.key-line { display: inline-block; width: 22px; height: 0; flex-shrink: 0; }
.key-solid { border-top: 2px solid var(--text); opacity: .55; }
.key-dash { border-top: 2px dashed var(--text); opacity: .55; }
.key-out { border-top: 1px solid var(--faint); }

/* ---------- selection strip and notes ---------- */

.map-sel {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 8px 12px; margin-bottom: 12px;
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--panel); font-size: 12.5px; color: var(--text);
}
.map-sel-off { color: var(--muted); background: transparent; border-style: dashed; }

.map-note { padding: 11px 14px; font-size: 12px; color: var(--muted); line-height: 1.6; }
.map-note code {
  font-family: var(--mono); font-size: 11.5px;
  background: var(--panel-3); padding: 1px 5px; border-radius: 4px;
}
table.map-missing { min-width: 520px; }

/* The checkbox column app.js adds to the firms table. Sized so the header and
   the cell line up and the tick is comfortably clickable without the column
   stealing width from the firm name. */
table.grid td.pickcell, table.grid th.pickcell { width: 34px; padding-left: 12px; padding-right: 0; }
table.grid .pickbox { width: 15px; height: 15px; accent-color: var(--accent); cursor: pointer; vertical-align: middle; }

/* ---------- MapLibre's own controls ----------
   Shipped for a white basemap: a white pill with dark icons. Rebuilt on the
   app's surfaces, and the icons — which are background images, not text — are
   inverted rather than recoloured, because there is nothing else to grab. */

.maplibregl-ctrl-group {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 6px;
  box-shadow: 0 1px 4px rgba(0, 0, 0, .35);
}
.maplibregl-ctrl-group button + button { border-top: 1px solid var(--border); }
.maplibregl-ctrl-group button { background: transparent; }
.maplibregl-ctrl-group button:hover { background: var(--panel-3); }
.maplibregl-ctrl-group button:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; box-shadow: none; }
.maplibregl-ctrl-group button .maplibregl-ctrl-icon { filter: invert(1) brightness(1.4); }
:root[data-theme="light"] .maplibregl-ctrl-group button .maplibregl-ctrl-icon { filter: none; }
:root[data-theme="light"] .maplibregl-ctrl-group { box-shadow: 0 1px 4px rgba(20, 28, 40, .18); }

.maplibregl-ctrl-scale {
  background: var(--panel);
  border: 1px solid var(--border); border-top: none;
  color: var(--muted);
  font-family: var(--font); font-size: 10.5px;
  padding: 1px 5px;
  opacity: .92;
}

/* ---------- narrow screens ----------
   1152px is the tightest desktop this app is checked at; below it the sidebar
   is usually collapsed and the map wants the height back rather than the
   width, since a county is taller than it is wide on this coast. */
@media (max-width: 1152px) {
  .map-mount { height: clamp(320px, 54vh, 560px); }
  .map-legend { gap: 6px 14px; font-size: 11px; }
}

/* ============================== layer card ==============================
   The control card Scott asked for (2026-10-03), the same shape as Earth
   Tracker's left card: real <button> switches, grouped, each carrying its own
   count for the current view. It sits OVER the canvas rather than beside it so
   the map keeps the full width of the pane, and it is width-capped so a long
   firmType ("Land Subdivision & Lot Development") wraps inside the card instead
   of widening it. */
.map-stage { position: relative; }
.map-card {
  position: absolute; top: 10px; left: 10px; z-index: 5;
  width: 232px; max-height: calc(100% - 20px);
  background: var(--panel); border: 1px solid var(--border); border-radius: 8px;
  box-shadow: 0 6px 18px rgba(0, 0, 0, .28);
  font-size: 12px; overflow: hidden;
  display: flex; flex-direction: column;
}
.map-card-head {
  padding: 7px 10px; font-weight: 600; letter-spacing: .02em; text-transform: uppercase;
  font-size: 10.5px; color: var(--muted); border-bottom: 1px solid var(--border);
}
/* Groups share the vertical space; only a group that cannot fit scrolls, so the
   card itself never becomes a scrolling column. */
.map-sw-group { border-bottom: 1px solid var(--border); flex: 0 0 auto; display: flex; flex-direction: column; min-height: 0; }
.map-sw-group:last-child { border-bottom: 0; }
.map-sw-head {
  display: flex; align-items: center; justify-content: space-between; gap: 6px;
  padding: 5px 10px 3px; color: var(--muted); font-size: 10.5px; text-transform: uppercase; letter-spacing: .02em;
}
.map-sw-acts { display: flex; gap: 6px; text-transform: none; letter-spacing: 0; }
/* Eight rows before it scrolls inside itself: enough that Kinds and State
   never scroll at all, and the 20-odd sub-industries stay in a card that fits
   over the map instead of running past the bottom of it. */
.map-sw-rows { padding: 0 4px 5px; max-height: 196px; overflow-y: auto; min-height: 0; }
.map-sw {
  display: flex; align-items: center; gap: 6px; width: 100%;
  padding: 3px 6px; border: 0; border-radius: 5px; background: none; cursor: pointer;
  color: var(--muted); font: inherit; text-align: left; line-height: 1.25;
}
.map-sw:hover { background: var(--hover); color: var(--text); }
.map-sw.on { color: var(--text); }
.sw-box {
  flex: 0 0 auto; width: 10px; height: 10px; border-radius: 3px;
  border: 1px solid var(--border-strong, var(--border)); background: transparent;
}
.map-sw.on .sw-box { background: var(--accent); border-color: var(--accent); }
.sw-dot { flex: 0 0 auto; width: 9px; height: 9px; border-radius: 50%; background: var(--muted); }
.sw-label { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
.sw-n { flex: 0 0 auto; font-variant-numeric: tabular-nums; opacity: .75; }
.map-sw:not(.on) .sw-dot { opacity: .35; }

/* Pin families. Five hues far enough apart to read at pin size, each matching
   what it is rather than being picked off a ramp: residential blue, industrial
   amber (steel/warehouse), commercial green, brokerage violet, specialty teal. */
.fam-res { background: #4f8ef7; }
.fam-ind { background: #e0a526; }
.fam-com { background: #35a76a; }
.fam-brk { background: #a46ae0; }
.fam-spc { background: #27a8b0; }
.fam-none { background: #8c99ab; }
.fam-comp { background: #d4564f; }
.fam-hq { background: #f2c230; }
.mk-firm .mk-dot.fam-res { background: #4f8ef7; }
.mk-firm .mk-dot.fam-ind { background: #e0a526; }
.mk-firm .mk-dot.fam-com { background: #35a76a; }
.mk-firm .mk-dot.fam-brk { background: #a46ae0; }
.mk-firm .mk-dot.fam-spc { background: #27a8b0; }
.mk-firm .mk-dot.fam-none { background: #8c99ab; }

@media (max-width: 760px) {
  /* On a phone the card would cover the map it is filtering. */
  .map-card { position: static; width: auto; max-height: none; margin: 0 0 8px; box-shadow: none; }
}

/* Said on the card itself when the tile service is unreachable, so an empty
   basemap is explained where the switch that chose it lives. */
.sw-note { padding: 2px 10px 7px; font-size: 10.5px; line-height: 1.35; color: var(--muted); }
