:root {
  --ink: #12141a;
  --paper: #fff;
  --muted: #6b7280;
  --known: #1a7f5a;
  --unknown: #c2410c;
  --water: #2563eb;
  --line: #e5e7eb;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font: 14px/1.5 system-ui, -apple-system, "Segoe UI", sans-serif;
  color: var(--ink);
}

#map { position: absolute; inset: 0; }

.muted { color: var(--muted); }

/* A car park whose terms are known must not look like one whose terms are a
   blank. The colour is the whole point of the distinction. */
.pin {
  border-radius: 50%;
  border: 2px solid var(--paper);
  box-shadow: 0 1px 4px rgb(0 0 0 / 0.4);
}

.pin-known { background: var(--known); }
.pin-unknown { background: var(--unknown); }
.pin-water { background: var(--water); opacity: 0.85; }

.pop { min-width: 190px; }
.pop h2 { margin: 0 0 2px; font-size: 14px; }
.walk { margin: 0 0 8px; color: var(--muted); font-size: 12.5px; }

.row {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding: 3px 0;
  border-top: 1px solid var(--line);
}

.label { color: var(--muted); }
.value { font-variant-numeric: tabular-nums; }

.warn {
  margin: 8px 0 0;
  font-size: 11.5px;
  color: var(--unknown);
}

.k-lim  { background: var(--water); }
.k-cust { background: var(--unknown); }
.k-paid { background: #475569; }

.zoom-note {
  margin: 0 0 10px;
  padding: 7px 10px;
  background: #eff6ff;
  border-radius: 4px;
  font-size: 12.5px;
}

.tariff {
  margin: 8px 0 0;
  padding: 7px 9px;
  background: #f8fafc;
  border-radius: 4px;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}

/* The dock: the filter and the key in one row, along the bottom where a thumb
   reaches. Each chip carries its category's colour, so there is no separate
   legend to drift out of step with it. */
.dock {
  position: fixed;
  z-index: 600;
  left: 50%;
  /* max() rather than a sum. Adding to env(safe-area-inset-bottom) stacks our
     gap on top of a value that already includes the iOS toolbar zone, which
     left the row floating well clear of the bottom edge with dead map beneath
     it. max() keeps it off the home indicator without paying twice. */
  bottom: max(12px, env(safe-area-inset-bottom));
  transform: translateX(-50%);
  display: flex;
  flex-wrap: nowrap;
  justify-content: center;
  gap: 2px;
  max-width: calc(100vw - 20px);
  padding: 6px;
  background: rgb(255 255 255 / 0.86);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border: 1px solid var(--line);
  border-radius: 16px;
  box-shadow: 0 2px 16px rgb(0 0 0 / 0.14);
}

.chip {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 8px 12px;
  font: inherit;
  font-size: 12.5px;
  font-weight: 500;
  color: var(--ink);
  background: transparent;
  border: 0;
  border-radius: 11px;
  cursor: pointer;
}

.chip:hover { background: #f1f5f9; }

/* Off reads as off at a glance: the dot drains and the label recedes. */
.chip.off { color: var(--muted); }

.addr {
  margin: 0 0 8px;
  font-size: 12.5px;
  color: var(--muted);
}

/* Top right. It was bottom right until an over-eager regex deleted this whole
   block, leaving a button with no position, size or background — which is why
   somebody asked for a locate button while looking at one. Top right is empty,
   conventional, and competes with nothing. */
.locate {
  position: fixed;
  z-index: 600;
  right: calc(12px + env(safe-area-inset-right));
  top: calc(12px + env(safe-area-inset-top));
  display: flex;
  align-items: center;
  justify-content: center;
  width: 42px;
  height: 42px;
  padding: 0;
  color: var(--ink);
  background: rgb(255 255 255 / 0.92);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border: 1px solid var(--line);
  border-radius: 50%;
  box-shadow: 0 2px 10px rgb(0 0 0 / 0.16);
  cursor: pointer;
}

.locate:hover { background: #fff; }
.locate svg { width: 20px; height: 20px; }
.locate.seeking { color: var(--water); animation: pulse 1.1s ease-in-out infinite; }
.locate.failed { color: var(--unknown); }

@keyframes pulse { 50% { opacity: 0.45; } }

/* Says how much the current filters are keeping off the map, because an empty
   map and a filtered one look identical otherwise. */
/* `display: block` beats the browser's own `[hidden] { display: none }`, which
   is how a "0 more here, hidden by the filters" banner came to sit on the map
   permanently. Anything setting display must exempt the hidden state. */
.hidden-note[hidden],
.zoom-note[hidden] { display: none; }

.hidden-note {
  display: block;
  width: 100%;
  margin: 0 0 10px;
  padding: 7px 10px;
  font: inherit;
  font-size: 12.5px;
  text-align: left;
  color: #92400e;
  background: #fffbeb;
  border: 1px solid #fde68a;
  border-radius: 4px;
  cursor: pointer;
}

.hidden-note:hover { background: #fef3c7; }

/* Phones. The panel was taking the top half of the screen to say things that
   are read once, so everything below the first line collapses behind a tap,
   and the chips shrink to fit two rows rather than four. */
@media (max-width: 560px) {

  .chip {
    padding: 7px 9px;
    font-size: 11.5px;
    gap: 5px;
  }

  .dock {
    bottom: max(6px, env(safe-area-inset-bottom));
    gap: 3px;
    padding: 5px;
  }

  .locate { width: 46px; height: 46px; }
}

/* Tap target for the collapsed panel, shown only where the panel collapses. */

/* Icon only. The label is kept in the markup for the accessible name and for
   anything that reads the page rather than looks at it. */
.chip span { display: none; }

.chip svg {
  width: 20px;
  height: 20px;
  display: block;
}

/* On, the icon carries its category's colour — the same colour as the marker
   it filters, so the row is the key as well as the control. Off, it drains to
   grey, which reads as off at a glance without needing a strikethrough. */
.chip[data-kind="free"]     { color: var(--known); }
.chip[data-kind="limited"]  { color: var(--water); }
.chip[data-kind="customer"] { color: var(--unknown); }
.chip[data-kind="disabled"] { color: #0284c7; }
.chip[data-kind="paid"]     { color: #475569; }
.chip[data-kind="ev"]       { color: #7c3aed; }
.chip[data-kind="unknown"]  { color: #475569; }

.chip.off { color: #cbd5e1; }

.chip[data-kind] { padding: 9px; }

@media (max-width: 560px) {
  .chip[data-kind] { padding: 8px; }
  .chip svg { width: 19px; height: 19px; }
}

/* What is left where the panel was: two short messages that only appear when
   they have something to say. */
.toasts {
  position: fixed;
  z-index: 500;
  top: calc(10px + env(safe-area-inset-top));
  left: 50%;
  transform: translateX(-50%);
  /* Narrow enough to clear the locate button, which shares this edge. */
  width: min(320px, calc(100vw - 90px));
}

.toasts :is(p, button) { margin: 0 0 6px; }

/* The attribution has to stay visible — it is the ODbL requirement — but it
   sits bottom right by default, which is where the dock now is. Moved left and
   made quiet so the two do not fight over the same corner. */
.leaflet-bottom.leaflet-right {
  left: 0;
  right: auto;
}

.leaflet-control-attribution {
  font-size: 10px;
  background: rgb(255 255 255 / 0.72);
}
