/* The Map tool — /map.
   Ported from the 3.0 kit's Tools.dc.html, which is the developed version of this
   screen. (The 3.1 kit has a MapNearby.jsx too, but its map is an empty placeholder
   slot and its detail sits in a panel below; 3.0's is a real Leaflet map inside a
   single full-height shell, with the detail opening inline in the list.)

   Loaded via yield :page_stylesheets, not on every page — a full-height split shell
   has nothing to say to any other surface.

   Everything here resolves through --zw-* tokens. Two of them are new and this is
   their first consumer: --zw-measure-tool for the 1440px working surface, and
   --zw-header-h, which is what turns the kit's magic `calc(100vh - 210px)` into
   something legible. */

/* The page matches the site header exactly rather than the kit's 1440px tool measure.
   The header is `max-w-7xl` with `px-4 sm:px-6 lg:px-8`, and a tool surface wider than
   the menu above it reads as a broken page rather than a wide one. Mirrored here as
   values rather than shared utilities so the two can be compared at a glance — the
   system test measures both and fails if they drift. */
.zw-map-page {
  width: 100%;
  max-width: 80rem; /* Tailwind max-w-7xl, the site header's measure */
  margin: 0 auto;
  padding: 28px 1rem 56px; /* px-4 */
}

@media (min-width: 640px) {
  .zw-map-page { padding-inline: 1.5rem; } /* sm:px-6 */
}

@media (min-width: 1024px) {
  .zw-map-page { padding-block: 44px 72px; padding-inline: 2rem; } /* lg:px-8 */
}

/* --- the filter bar ------------------------------------------------------- */

.zw-map-filters {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  padding-bottom: var(--space-4);
  margin-bottom: var(--space-4);
  border-bottom: 1px solid var(--zw-border-warm);
}

.zw-map-filters__rule {
  width: 1px;
  height: 22px;
  margin: 0 6px;
  background: var(--zw-border-warm);
  flex-shrink: 0;
}

/* A category pill. The dot carries the pin's colour, so the list, the pills and the
   map cannot disagree about what a category looks like — see MapHelper. */
.zw-map-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  font-size: 13px;
  font-weight: 600;
  background: transparent;
  border: 1px solid var(--zw-border-warm-2);
  border-radius: var(--zw-radius-pill);
  cursor: pointer;
  color: var(--zw-muted);
  white-space: nowrap;
  transition: background var(--dur-2) var(--zw-ease-out), border-color var(--dur-2) var(--zw-ease-out);
}

.zw-map-pill:hover { background: var(--zw-panel); }

.zw-map-pill[aria-pressed="true"] {
  background: var(--zw-surface-warm);
  border-color: var(--zw-ink-3);
  color: var(--zw-ink);
}

.zw-map-pill__dot {
  width: 7px;
  height: 7px;
  border-radius: var(--zw-radius-pill);
  flex: none;
}

.zw-map-pill__count { font-variant-numeric: tabular-nums; }

.zw-map-pill:focus-visible,
.zw-map-row:focus-visible {
  outline: 2px solid var(--zw-blue-700);
  outline-offset: 2px;
}

/* --- the shell ------------------------------------------------------------ */

/* One card holding both halves, rather than two cards side by side. The list scrolls
   inside it while the map stays put, which is the whole reason for a fixed height. */
.zw-map-shell {
  display: grid;
  grid-template-columns: minmax(0, 400px) minmax(0, 1fr);
  align-items: stretch;
  height: calc(100vh - var(--zw-header-h) - 150px);
  min-height: 620px;
  background: var(--zw-surface);
  border: 1px solid var(--zw-border-warm-2);
  border-radius: var(--zw-radius-md);
  box-shadow: var(--zw-shadow-hairline);
  overflow: hidden;
}

.zw-map-list {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
  border-right: 1px solid var(--zw-border-warm-2);
  background: var(--zw-surface);
}

.zw-map-list__header {
  flex: none;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  padding: 11px 14px;
  border-bottom: 1px solid var(--zw-border-warm);
}

.zw-map-list__scroll {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
}

.zw-map-list__footer {
  flex: none;
  padding: 11px 14px;
  border-top: 1px solid var(--zw-border-warm);
  background: var(--zw-paper-3);
  font-size: 13px;
  line-height: 1.5;
  color: var(--zw-faint);
}

.zw-map-list__section {
  padding: 9px 16px;
  background: var(--zw-panel);
  border-bottom: 1px solid var(--zw-border-warm);
}

/* z-index 0 is load-bearing, not decoration. Leaflet's panes run to 700 and its controls
   to 1000, so without a stacking context here the map paints straight over the site
   header. The 2.x map div carried a `z-0` utility for exactly this reason; the rebuild
   dropped it and the menu went under the pins. */
.zw-map-canvas {
  position: relative;
  z-index: 0;
  min-width: 0;
  height: 100%;
}

/* The marker itself: a filled circle carrying a white glyph, ringed in white. Identical
   to .zw-map-row__pin on purpose — a row and its pin are the same object. */
.zw-map-disc {
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--zw-radius-pill);
  outline-offset: -2px;
  transition:
    width 160ms var(--zw-ease-out),
    height 160ms var(--zw-ease-out);
}

/* The cluster is the inverse of a pin: white ground, dark numeral, white ring. */
.zw-map-cluster {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--zw-surface);
  color: var(--zw-ink);
  font-size: 13px;
  font-weight: 600;
  line-height: 1;
  border-radius: var(--zw-radius-pill);
  box-shadow: 0 1px 3px rgba(28, 28, 30, 0.22), 0 0 0 2px var(--zw-surface);
}

/* Shown for a moment when someone scrolls over the map without the meta key. The map
   deliberately does not swallow the wheel — see requireMetaToZoom in map_controller. */
.zw-map-hint {
  position: absolute;
  inset: 0;
  z-index: 500;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(28, 28, 30, 0.32);
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--dur-2) var(--zw-ease-out);
}

.zw-map-hint[data-visible="true"] { opacity: 1; }

.zw-map-hint__label {
  padding: 10px 18px;
  font-size: 15px;
  font-weight: 600;
  color: var(--zw-ink);
  background: var(--zw-surface);
  border-radius: var(--zw-radius-pill);
  box-shadow: var(--zw-shadow-float);
}

/* Leaflet paints its own tiles; this is only what shows before they arrive. */
.zw-map-canvas__leaflet {
  width: 100%;
  height: 100%;
  min-width: 0;
  background: var(--zw-tool-map-tint);
}

/* --- a row ---------------------------------------------------------------- */

.zw-map-row {
  width: 100%;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  gap: var(--space-3);
  align-items: start;
  padding: 15px 16px;
  background: none;
  border: none;
  cursor: pointer;
  text-align: left;
  font: inherit;
}

.zw-map-place {
  border-bottom: 1px solid var(--zw-border-warm-inner);
  background: var(--zw-surface);
  transition: background var(--dur-2) var(--zw-ease-out);
}

.zw-map-place:hover { background: var(--zw-paper-3); }
.zw-map-place[data-selected="true"] { background: var(--zw-surface-warm); }

/* The pin's colour again, as a filled disc behind a white glyph. The white outline
   is what keeps it legible against a row that is itself tinted when selected. */
.zw-map-row__pin {
  margin-top: 1px;
  width: 28px;
  height: 28px;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--zw-radius-pill);
  color: #fff;
  outline: 2px solid var(--zw-surface);
  outline-offset: -2px;
}

.zw-map-row__body {
  display: grid;
  gap: 4px;
  min-width: 0;
}

.zw-map-row__name {
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--zw-ink);
}

.zw-map-row__meta {
  display: flex;
  align-items: center;
  gap: 7px;
  flex-wrap: wrap;
  font-size: 13px;
  color: var(--zw-muted);
}

.zw-map-row__kind { font-weight: 600; }

/* Each detail carries its own leading separator so the two wrap together — otherwise a
   narrow list ends a line on a stray "·". */
.zw-map-row__detail { white-space: nowrap; }
.zw-map-row__sep { color: var(--zw-whisper); margin-right: 7px; }

.zw-map-row__blurb {
  margin-top: 1px;
  font-size: 13px;
  line-height: 1.45;
  color: var(--zw-faint);
}

.zw-map-row__distance {
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  color: var(--zw-muted);
  white-space: nowrap;
}

/* --- the inline detail ---------------------------------------------------- */

/* 3.0 opens the detail inside the row rather than in a panel under the map, so the
   place you clicked never moves and the map keeps its full height. */
.zw-map-detail { padding: 0 16px 16px; }

.zw-map-detail__facts {
  display: grid;
  gap: 7px;
  padding-top: var(--space-3);
  border-top: 1px solid var(--zw-border-warm-inner);
}

.zw-map-detail__fact {
  display: flex;
  gap: 9px;
  font-size: 14px;
  color: var(--zw-ink-2);
}

.zw-map-detail__label {
  flex: none;
  width: 74px;
  color: var(--zw-muted);
}

.zw-map-detail__note {
  margin: var(--space-3) 0 0;
  font-size: 14px;
  line-height: 1.5;
  color: var(--zw-muted);
}

.zw-map-detail__actions {
  margin-top: 14px;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
}

/* Only shown once a category is selected — with single-select there is a state you
   cannot leave by clicking another pill, so it needs an explicit way out. */
.zw-map-clear {
  margin-left: 4px;
  padding: 6px 10px;
  font-size: 13px;
  background: none;
  border: none;
  border-radius: var(--zw-radius-pill);
  cursor: pointer;
  color: var(--zw-muted);
  white-space: nowrap;
  transition: background var(--dur-2) var(--zw-ease-out), color var(--dur-2) var(--zw-ease-out);
}

.zw-map-clear:hover { background: var(--zw-panel); color: var(--zw-ink); }
.zw-map-clear[hidden] { display: none; }

/* Save and Share sit with Directions in the open row. Sized like the filter pills rather
   than like buttons: they are row-level affordances, not the page's action. */
.zw-map-action {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  font-size: 13px;
  font-weight: 600;
  background: transparent;
  border: 1px solid var(--zw-border-warm-2);
  border-radius: var(--zw-radius-pill);
  cursor: pointer;
  color: var(--zw-muted);
  white-space: nowrap;
  font-family: inherit;
  transition: background var(--dur-2) var(--zw-ease-out), color var(--dur-2) var(--zw-ease-out);
}

.zw-map-action:hover { background: var(--zw-surface-warm); color: var(--zw-ink); }

/* Saved is the one place a heart earns a colour of its own. Clay rather than the danger
   red, which means something else entirely. */
.zw-map-action[aria-pressed="true"] {
  background: var(--zw-sand-tint);
  border-color: var(--zw-clay);
  color: var(--zw-clay);
}

/* Directions / website / phone. 3.0 keeps the row's weight on Save and Share. */
.zw-map-link {
  margin-left: 2px;
  font-size: 13px;
  font-weight: 600;
  color: var(--link);
  text-decoration: none;
}

.zw-map-link:hover { text-decoration: underline; }
.zw-map-link--quiet { color: var(--zw-muted); }

.zw-map-empty {
  padding: 26px 20px;
  text-align: center;
}

.zw-map-empty__title {
  font-size: 15px;
  font-weight: 600;
  color: var(--zw-ink);
}

.zw-map-empty__sub {
  margin: 6px 0 0;
  font-size: 14px;
  line-height: 1.5;
  color: var(--zw-faint);
}

/* --- narrow screens ------------------------------------------------------- */

/* Below the split, the list stacks above a fixed-height map. A full-height two-pane
   shell has nowhere to go on a phone, and the list is the half that answers the
   question — so it gets the scroll and the map gets a fixed slice. */
@media (max-width: 860px) {
  .zw-map-page { padding: 28px 20px 56px; }

  .zw-map-shell {
    grid-template-columns: minmax(0, 1fr);
    height: auto;
    min-height: 0;
  }

  .zw-map-list {
    border-right: none;
    border-bottom: 1px solid var(--zw-border-warm-2);
    max-height: 460px;
  }

  .zw-map-canvas { height: 320px; }
}
