/* ═══════════════════════════════════════════════════════════════════════════
   Sizani — every style for the street map sizani-map.js builds.

   Same contract as sizani.css and sizani-live.css: the JS structure is the source of
   truth, this file's design intent is the source of taste, and every selector below
   names a class the script actually emits (or one MapLibre puts on its own elements).

   Rules this file holds itself to:
   · EVERY class is `sz-map-` prefixed. Nothing collides with app.js, sizani.css's sz-
     set or sizani-live.css's sz-live- set. MapLibre's own `maplibregl-` classes are
     touched only under a `.sz-map-host` ancestor.
   · NOTHING is defined on :root. style.css owns the one :root. The colours here are the
     literal values of sizani-live.css's --szl-* tokens (subject gold #9b6b13 / #765008,
     ink #10131d, scene red #be4246) so the two maps — this one and the drawn fallback —
     read as one product; they are literals because a MapLibre marker is not inside the
     .sz-live scope and would not inherit them.
   · Nothing decorative sits over the map. No pattern, no overlay, no watermark. The one
     control on it is MapLibre's compact attribution, which is a licence condition.
   · The canvas fills the HOST: the host is position:relative, the map is absolute
     inset:0, and the caller decides the size with the host's aspect-ratio or min-height.
   · Colour never carries meaning alone: the pulse is stopped by a class the caller
     removes when the phone goes quiet, and the caller says "Last seen 2 min ago" beside
     it. The dot's colour does not change, because the dot cannot know.
   · Every animation is switched off wholesale at the bottom of this file under
     prefers-reduced-motion. The glide itself is JS and checks the same query.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ═══ the host and the canvas ═══ */

.sz-map-host {
  position: relative;
  overflow: hidden;
  /* the ground before the first tiles land, so the frame does not flash white */
  background: #eff4f2;
}
.sz-map-host > .sz-map {
  position: absolute;
  inset: 0;
}
.sz-map-host > .sz-map-dark { background: #1d1810; }
.sz-map-host .maplibregl-map { font-family: inherit; }

/* MapLibre focuses the canvas for keyboard panning. A ring for keyboard users, none
   for a mouse click. */
.sz-map .maplibregl-canvas:focus { outline: none; }
.sz-map .maplibregl-canvas:focus-visible {
  outline: 3px solid rgba(199, 154, 46, .6);
  outline-offset: -3px;
}

/* Tap-to-pick: the cursor says the map is a control now. */
.sz-map-pick .maplibregl-canvas-container.maplibregl-interactive,
.sz-map-pick .maplibregl-canvas-container.maplibregl-interactive:active { cursor: crosshair; }

/* ═══ attribution — "© OpenStreetMap contributors" is a licence condition (ODbL) ═══
   MapLibre's compact control: an (i) button that opens to the text. It stays on its
   own light plate on both themes so the text is readable over any tile. */
.sz-map-host .maplibregl-ctrl-attrib {
  font-size: 11px;
  line-height: 18px;
  background: rgba(255, 253, 246, .85);
  color: #343947;
}
.sz-map-host .maplibregl-ctrl-attrib a { color: #343947; }
.sz-map-host .maplibregl-ctrl-attrib.maplibregl-compact { border-radius: 12px; }

/* ═══ markers ═══
   All markers are display only — no popups, no drags — so they let taps and drags
   through to the map. A destination tap in pick mode lands on the map, not on the pin. */
.sz-map-now,
.sz-map-me,
.sz-map-dest,
.sz-map-scene { pointer-events: none; }

/* ── the subject: a gold dot, a pulse while live, an arrow when the phone knows which way ── */
.sz-map-now {
  width: 36px;
  height: 36px;
}
.sz-map-now-dot {
  position: absolute;
  left: 9px; top: 9px;
  width: 18px; height: 18px;
  border-radius: 50%;
  background: #aa7817;
  border: 3px solid #ffffff;
  box-sizing: border-box;
  box-shadow: 0 0 0 5px rgba(199, 154, 46, .18), 0 1px 4px rgba(0, 0, 0, .24);
}
.sz-map-now-ring {
  position: absolute;
  left: 11px; top: 11px;
  width: 14px; height: 14px;
  border-radius: 50%;
  background: #9b6b13;
  opacity: 0;
}
/* The pulse exists only while the caller says the fix is fresh. It is taken off, not
   recoloured, when the phone goes quiet — the sentence beside the map says why. */
.sz-map-now-live .sz-map-now-ring {
  opacity: .28;
  animation: sz-map-ping 2.2s ease-out infinite;
}
@keyframes sz-map-ping {
  0%   { transform: scale(1);   opacity: .34; }
  70%  { transform: scale(2.5); opacity: 0; }
  100% { transform: scale(2.5); opacity: 0; }
}

/* The heading arrow turns with --sz-heading, set by the script per frame. It is a
   rotated frame the size of the marker with a triangle at its top edge, so the arrow
   orbits the dot rather than spinning on it. Two triangles: a white one behind for the
   halo, the gold one in front. Hidden until a fix carries a heading — an arrow pointing
   nowhere in particular would be a claim about direction. */
.sz-map-now-arrow {
  position: absolute;
  inset: 0;
  display: none;
  transform: rotate(var(--sz-heading, 0deg));
  transform-origin: 50% 50%;
}
.sz-map-now-has-heading .sz-map-now-arrow { display: block; }
.sz-map-now-arrow::before,
.sz-map-now-arrow::after {
  content: '';
  position: absolute;
  left: 50%;
  width: 0; height: 0;
  border-style: solid;
  border-color: transparent;
}
.sz-map-now-arrow::before {
  top: 0;
  transform: translateX(-50%);
  border-width: 0 7px 10.5px 7px;
  border-bottom-color: #ffffff;
}
.sz-map-now-arrow::after {
  top: 1.5px;
  transform: translateX(-50%);
  border-width: 0 5px 8px 5px;
  border-bottom-color: #765008;
}

/* ── the viewer: an ink dot with a white ring ── */
.sz-map-me {
  width: 20px;
  height: 20px;
}
.sz-map-me-dot {
  position: absolute;
  left: 4px; top: 4px;
  width: 12px; height: 12px;
  border-radius: 50%;
  background: #10131d;
  border: 3px solid #ffffff;
  box-sizing: border-box;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .35);
}

/* ── pins: destination (gold) and scene (red). Anchored at the tip; the label sits
      above the pin inside the same element so the tip stays on the coordinate. ── */
.sz-map-dest,
.sz-map-scene {
  display: flex;
  flex-direction: column;
  align-items: center;
}
.sz-map-pin {
  width: 20px;
  height: 28px;
  filter: drop-shadow(0 1px 1.5px rgba(60, 45, 10, .35));
}
.sz-map-pin svg { display: block; overflow: visible; }
.sz-map-dest .sz-map-pin-body { fill: #9b6b13; stroke: #765008; stroke-width: 1.1; }
.sz-map-dest .sz-map-pin-eye  { fill: #fff8e6; }
.sz-map-scene .sz-map-pin-body { fill: #be4246; stroke: #7d1c14; stroke-width: 1.1; }
.sz-map-scene .sz-map-pin-eye  { fill: #ffffff; }

.sz-map-pin-label {
  margin-bottom: 3px;
  padding: 2px 8px;
  border-radius: 9px;
  background: #ffffff;
  border: 1px solid #e9e9e7;
  color: #10131d;
  font-size: 12px;
  font-weight: 700;
  line-height: 15px;
  white-space: nowrap;
  max-width: 180px;
  overflow: hidden;
  text-overflow: ellipsis;
  box-shadow: 0 1px 2px rgba(60, 45, 10, .08);
}
.sz-map-pin-label[hidden] { display: none; }

/* ═══ dark theme — the siren's map. The basemap swallows a thin gold stroke, so every
   mark gets a white halo; the label plate turns to the house dark with light ink. ═══ */
.sz-map-dark .sz-map-dest .sz-map-pin-body,
.sz-map-dark .sz-map-scene .sz-map-pin-body { stroke: #ffffff; stroke-width: 1.5; }
.sz-map-dark .sz-map-pin { filter: drop-shadow(0 0 2px rgba(255, 255, 255, .55)); }
.sz-map-dark .sz-map-now-dot { box-shadow: 0 0 0 1.5px rgba(255, 255, 255, .55), 0 1px 3px rgba(0, 0, 0, .5); }
.sz-map-dark .sz-map-me-dot  { box-shadow: 0 0 0 1.5px rgba(255, 255, 255, .55), 0 1px 3px rgba(0, 0, 0, .5); }
.sz-map-dark .sz-map-pin-label {
  background: #241f16;
  border-color: rgba(246, 239, 224, .22);
  color: #f6efe0;
  box-shadow: 0 1px 2px rgba(0, 0, 0, .4);
}

/* ═══ reduced motion — no pulse; the glide is switched off in the script by the same query ═══ */
@media (prefers-reduced-motion: reduce) {
  .sz-map-now-live .sz-map-now-ring { animation: none !important; opacity: .3; }
}
