:root {
  --bg: #f4f6f4;
  --panel: #ffffff;
  --ink: #16211c;
  --muted: #5d6b64;
  --line: #dfe5e0;
  --accent: #1f7a4d;
  --accent-soft: #e6f2ec;
  --warn: #b45309;
  --radius: 12px;
  --shadow: 0 1px 2px rgba(16, 32, 24, 0.06), 0 8px 24px rgba(16, 32, 24, 0.06);
}

* {
  box-sizing: border-box;
}

html,
body {
  height: 100%;
  margin: 0;
}

body {
  background: var(--bg);
  color: var(--ink);
  font: 15px/1.5 ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  -webkit-font-smoothing: antialiased;
}

.layout {
  display: grid;
  grid-template-columns: 420px 1fr;
  height: 100%;
}

.panel {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--bg);
  border-right: 1px solid var(--line);
}

.panel-scroll {
  flex: 1;
  overflow-y: auto;
  padding: 20px;
  -webkit-overflow-scrolling: touch;
}

/* The grab handle only exists on the mobile sheet. */
.sheet-handle {
  display: none;
}

.brand {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  margin-bottom: 18px;
}

.brand-mark {
  font-size: 30px;
  line-height: 1;
}

.brand h1 {
  margin: 0;
  font-size: 21px;
  letter-spacing: -0.01em;
}

.tagline {
  margin: 4px 0 0;
  color: var(--muted);
  font-size: 13px;
}

.card {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 16px;
  margin-bottom: 14px;
  box-shadow: var(--shadow);
}

.card h2 {
  margin: 0 0 12px;
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--muted);
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.field {
  display: block;
  margin-bottom: 12px;
}

.field > span {
  display: block;
  font-size: 12px;
  font-weight: 600;
  color: var(--muted);
  margin-bottom: 5px;
}

input[type="text"],
.field input {
  width: 100%;
  padding: 9px 11px;
  border: 1px solid var(--line);
  border-radius: 9px;
  font: inherit;
  background: #fff;
  color: inherit;
}

.field input:focus {
  outline: 2px solid var(--accent);
  outline-offset: -1px;
  border-color: transparent;
}

/* The `hidden` attribute is a UA rule of the lowest possible weight, so any
   class here that sets `display` silently defeats it — which is how the
   step-free toggle (`display: grid`) kept showing in Bike mode after being
   hidden in JS. Settle it once, for every element in the app, rather than
   per component. */
[hidden] {
  display: none !important;
}

.mode-row {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 6px;
}

/* Four modes do not fit one row at panel width without the labels shrinking
   to the point of being unreadable, so they wrap into two rows on narrow
   panels and sit in one on wide ones. */
.mode-row-4 {
  grid-template-columns: repeat(2, 1fr);
}

@media (min-width: 420px) {
  .mode-row-4 {
    grid-template-columns: repeat(4, 1fr);
  }
}

.when-row {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: 6px;
  align-items: center;
}

.when-row select,
.when-row input {
  padding: 8px 7px;
  border: 1px solid var(--line);
  border-radius: 9px;
  background: #fff;
  font: inherit;
  font-size: 13px;
  min-width: 0;
}

.when-row select:focus,
.when-row input:focus {
  outline: 2px solid var(--accent);
  outline-offset: -1px;
  border-color: transparent;
}

.mode {
  padding: 9px 4px;
  border: 1px solid var(--line);
  background: #fff;
  border-radius: 9px;
  font: inherit;
  font-size: 13px;
  cursor: pointer;
  transition: background 0.12s, border-color 0.12s;
}

.mode:hover {
  border-color: var(--accent);
}

.mode.is-active {
  background: var(--accent-soft);
  border-color: var(--accent);
  font-weight: 600;
}

.primary {
  width: 100%;
  padding: 11px;
  border: 0;
  border-radius: 9px;
  background: var(--accent);
  color: #fff;
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}

.primary:hover {
  background: #196540;
}

.primary:disabled {
  opacity: 0.55;
  cursor: progress;
}

.link-btn {
  border: 0;
  background: none;
  color: var(--accent);
  font: inherit;
  font-size: 12px;
  text-transform: none;
  letter-spacing: 0;
  cursor: pointer;
  padding: 0;
}

.status {
  margin: 10px 0 0;
  font-size: 13px;
  color: var(--muted);
  min-height: 18px;
}

.status.is-error {
  color: #b91c1c;
}

.hint {
  margin: -4px 0 12px;
  font-size: 12px;
  color: var(--muted);
}

.weight {
  margin-bottom: 10px;
}

.weight-head {
  display: flex;
  justify-content: space-between;
  font-size: 13px;
  margin-bottom: 3px;
}

.weight-head b {
  font-weight: 600;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.weight input[type="range"] {
  width: 100%;
  accent-color: var(--accent);
}

.route {
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 11px 12px;
  margin-bottom: 9px;
  cursor: pointer;
  background: #fff;
  transition: box-shadow 0.12s, border-color 0.12s;
}

.route:hover {
  box-shadow: var(--shadow);
}

/* With no colour strip on the card, selection has to carry itself. */
.route.is-selected {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px var(--accent-soft), var(--shadow);
}

.route-top {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 8px;
}

.route-name {
  font-weight: 650;
  font-size: 15px;
}

.route-score {
  font-variant-numeric: tabular-nums;
  font-size: 13px;
  color: var(--muted);
}

.route-score b {
  font-size: 17px;
  color: var(--ink);
}

.route-sub {
  color: var(--muted);
  font-size: 13px;
  margin-top: 2px;
  font-variant-numeric: tabular-nums;
}

.badges {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: 8px;
}

.badge {
  font-size: 11px;
  font-weight: 600;
  padding: 2px 7px;
  border-radius: 99px;
  background: var(--accent-soft);
  color: #14603c;
}

.badge.warn {
  background: #fdf1e0;
  color: var(--warn);
}

.bars {
  margin-top: 9px;
  display: grid;
  gap: 4px;
}

/* --------------------------------------------------------------- stale --- */

/* Nothing in this app searches on its own, so when an input changes the
   results on screen are simply the previous answer. Saying that plainly beats
   both of the alternatives: silently re-running an expensive search, or
   leaving a stale list looking current. */
.stale-note {
  margin: 8px 0 0;
  padding: 8px 10px;
  border-radius: 8px;
  border-left: 3px solid var(--warn);
  background: #fdf1e0;
  font-size: 12px;
  line-height: 1.45;
  color: #7c4510;
}

.stale-chip {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  padding: 2px 7px;
  border-radius: 99px;
  background: #fdf1e0;
  color: var(--warn);
  vertical-align: 2px;
}

/* The button is the only way to run a search now, so when one is pending it
   stops being a quiet default and asks for the click. */
.primary.is-pending {
  box-shadow: 0 0 0 3px rgba(180, 83, 9, 0.25);
}

/* ---------------------------------------------------------------- heat --- */

/* The hour strip is a picker as well as a chart, so every cell is a real
   button: keyboard reachable, with a hit target taller than the mark it
   draws. Cells are separated by a surface gap rather than a border, so the
   ramp's own steps carry the reading. */
.heat-strip {
  display: flex;
  gap: 2px;
  margin: 2px 0 6px;
}

.heat-hour {
  flex: 1 1 0;
  min-width: 0;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  display: grid;
  gap: 3px;
  justify-items: center;
}

.heat-bar {
  width: 100%;
  height: 30px;
  border-radius: 4px;
  background: var(--line);
  box-shadow: inset 0 0 0 0 #fff;
}

/* The selected hour is ringed in ink, not recoloured: the cell has to keep
   showing its own heat band while it is selected. */
.heat-hour.is-on .heat-bar {
  box-shadow: 0 0 0 2px #fff, 0 0 0 4px #111827;
}

.heat-hour:hover .heat-bar,
.heat-hour:focus-visible .heat-bar {
  box-shadow: 0 0 0 2px #fff, 0 0 0 3px var(--muted);
}

.heat-hour:focus-visible {
  outline: none;
}

.heat-tick {
  font-size: 9.5px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  line-height: 1;
  white-space: nowrap;
}

.heat-hour.is-on .heat-tick {
  color: var(--ink);
  font-weight: 700;
}

.heat-readout {
  font-size: 12px;
  color: var(--muted);
  min-height: 1.3em;
  margin-top: 2px;
}

.heat-readout b {
  color: var(--ink);
}

/* ------------------------------------------------------------- transit --- */

/* The trip at a glance: walk › 700 › walk. Read before the score is. */
.legs {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
  margin: 8px 0 2px;
}

.leg {
  font-size: 11px;
  font-weight: 600;
  padding: 2px 7px;
  border-radius: 99px;
  border: 1px solid var(--line);
  white-space: nowrap;
}

.leg-walk {
  color: var(--muted);
  background: #fff;
}

/* A route number with no colour in the feed still has to look like a route
   number, so the neutral treatment is the fallback rather than nothing. */
.leg-ride {
  background: #334155;
  border-color: #334155;
  color: #fff;
}

.leg-join {
  color: var(--muted);
  font-size: 11px;
}

.toggle {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 9px;
  align-items: start;
  margin-top: 10px;
  padding: 9px 10px;
  border: 1px solid var(--line);
  border-radius: 9px;
  cursor: pointer;
}

.toggle:hover {
  border-color: var(--accent);
}

.toggle input {
  margin: 2px 0 0;
  width: 15px;
  height: 15px;
  accent-color: var(--accent);
  cursor: pointer;
}

.toggle-text b {
  font-size: 13px;
  font-weight: 600;
}

.toggle-text small {
  display: block;
  margin-top: 3px;
  font-size: 11px;
  color: var(--muted);
  line-height: 1.4;
}

/* A measured result the app wants read, not skimmed past — the cost of
   routing step-free, or the fact that there is no step-free way at all. */
.finding {
  margin: 0 0 10px;
  padding: 9px 11px;
  border-radius: 9px;
  border-left: 3px solid var(--accent);
  background: var(--accent-soft);
  font-size: 12.5px;
  line-height: 1.45;
}

.finding.is-blocked {
  border-left-color: var(--warn);
  background: #fdf1e0;
}

.ride {
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 10px 11px;
  margin-bottom: 8px;
}

.ride:last-child {
  margin-bottom: 0;
}

.ride-head {
  display: flex;
  align-items: center;
  gap: 7px;
  flex-wrap: wrap;
}

.ride-badge {
  font-size: 12px;
  font-weight: 700;
  padding: 2px 8px;
  border-radius: 99px;
  background: #334155;
  color: #fff;
  font-variant-numeric: tabular-nums;
}

.ride-name {
  font-size: 13px;
  font-weight: 600;
}

.ride-toward,
.ride-ride {
  font-size: 11px;
  color: var(--muted);
  margin-top: 3px;
}

.ride-stop {
  display: grid;
  grid-template-columns: 62px 1fr;
  gap: 8px;
  font-size: 12.5px;
  margin-top: 6px;
  align-items: baseline;
}

.ride-stop b {
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.stop-code {
  color: var(--muted);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
}

/* Boarding and alighting points on the map. Hollow, so the line colour reads
   through them and it is obvious which line the stop belongs to. */
.stop-pin {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: #fff;
  border: 3px solid #334155;
  box-shadow: 0 1px 4px rgba(16, 32, 24, 0.4);
}

.stop-alight {
  background: #334155;
  box-shadow: 0 0 0 2px #fff, 0 1px 4px rgba(16, 32, 24, 0.4);
}

.bar {
  display: grid;
  grid-template-columns: 58px 1fr 38px;
  align-items: center;
  gap: 7px;
  font-size: 11px;
  color: var(--muted);
}

.bar-track {
  height: 5px;
  border-radius: 99px;
  background: #eef1ee;
  overflow: hidden;
}

.bar-fill {
  height: 100%;
  border-radius: 99px;
  background: var(--accent);
}

.bar-val {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.stats {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}

.stat {
  background: #fafbfa;
  border: 1px solid var(--line);
  border-radius: 9px;
  padding: 9px 10px;
}

.stat-label {
  font-size: 11px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.stat-value {
  font-size: 18px;
  font-weight: 650;
  font-variant-numeric: tabular-nums;
  margin-top: 2px;
}

.stat-note {
  font-size: 11px;
  color: var(--muted);
  margin-top: 2px;
}

.map-wrap {
  position: relative;
}

/* Map furniture lives in one bottom-left column, next to the sidebar, so a
   desktop user is not crossing the window to reach the controls. The weights
   panel sits above the legend and grows upward when opened. */
.map-stack {
  position: absolute;
  left: 12px;
  bottom: 22px;
  z-index: 600;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 8px;
  width: 290px;
  max-width: calc(100% - 24px);
}

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

.map-legend {
  background: rgba(255, 255, 255, 0.95);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 9px 11px;
  font-size: 12px;
  box-shadow: var(--shadow);
}

.legend-row {
  display: flex;
  align-items: center;
  gap: 7px;
  margin-top: 4px;
}

.legend-swatch {
  width: 16px;
  height: 3px;
  border-radius: 99px;
  flex: none;
}

.foot {
  color: var(--muted);
  font-size: 11px;
  line-height: 1.45;
  padding: 0 4px 20px;
}

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



/* ---------------------------------------------- place search combobox --- */

.combo {
  position: relative;
}

.combo input {
  padding-right: 34px;
}

.combo-btn {
  position: absolute;
  top: 50%;
  right: 6px;
  transform: translateY(-50%);
  width: 24px;
  height: 24px;
  border: 0;
  border-radius: 6px;
  background: none;
  color: var(--muted);
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
}

.combo-btn:hover {
  background: var(--accent-soft);
  color: var(--accent);
}

.suggestions {
  position: absolute;
  z-index: 900;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  margin: 0;
  padding: 4px;
  list-style: none;
  max-height: 268px;
  overflow-y: auto;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 10px;
  box-shadow: 0 8px 28px rgba(16, 32, 24, 0.16);
}

.suggestion {
  padding: 7px 9px;
  border-radius: 7px;
  cursor: pointer;
  display: flex;
  gap: 8px;
  align-items: baseline;
}

.suggestion:hover,
.suggestion.is-active {
  background: var(--accent-soft);
}

.suggestion-icon {
  flex: none;
  font-size: 13px;
  width: 16px;
  text-align: center;
}

.suggestion-text {
  min-width: 0;
}

.suggestion-label {
  font-size: 14px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.suggestion-detail {
  font-size: 12px;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.swap-btn {
  display: block;
  /* The field above already contributes 12px, so pull back 4 to leave the
     same 8px of air on both sides of the button. */
  margin: -4px 0 8px auto;
  padding: 3px 9px;
  border: 1px solid var(--line);
  border-radius: 99px;
  background: #fff;
  color: var(--muted);
  font: inherit;
  font-size: 12px;
  cursor: pointer;
}

.swap-btn:hover {
  border-color: var(--accent);
  color: var(--accent);
}

.pick-hint code {
  background: #eef1ee;
  padding: 1px 4px;
  border-radius: 4px;
  font-size: 11px;
}

/* --------------------------------------------------------- map tools --- */

.map-tools {
  position: absolute;
  top: 12px;
  right: 12px;
  z-index: 500;
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 6px 14px;
}

/* Placing the trip and switching layers are different jobs, so they are
   different groups. The gap and the rule between them carry that without
   spending a word on it. */
.tool-group {
  display: flex;
  gap: 6px;
  position: relative;
}

.tool-group + .tool-group {
  border-left: 1px solid var(--line);
  padding-left: 8px;
}

/* The two picking buttons start an action; the layer buttons toggle a state.
   Tinting the pair marks them as the ones that do something next. */
.pick-btn.is-action {
  border-color: rgba(31, 122, 77, 0.45);
  color: var(--accent);
  font-weight: 600;
}

.pick-btn.is-action:hover:not(.is-armed) {
  background: #fff;
  border-color: var(--accent);
}

.pick-btn.is-armed:hover {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

.pick-btn {
  padding: 7px 11px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.96);
  font: inherit;
  font-size: 13px;
  cursor: pointer;
  box-shadow: var(--shadow);
}

.pick-btn:hover {
  border-color: var(--accent);
}

.pick-btn.is-armed {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
  font-weight: 600;
}

.map-picking {
  cursor: crosshair;
}

/* What "armed" looks like, in the place someone is actually looking: over the
   map, not in the sidebar status line they have their back to. */
.pick-banner {
  position: absolute;
  /* Clear of the button row it is explaining; centred, so it reads as being
     about the map rather than about the toolbar. */
  top: 58px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 620;
  display: flex;
  align-items: center;
  gap: 10px;
  max-width: calc(100% - 24px);
  padding: 9px 9px 9px 14px;
  border-radius: 999px;
  background: var(--accent);
  color: #fff;
  font-size: 13px;
  font-weight: 600;
  box-shadow: 0 6px 20px rgba(16, 32, 24, 0.28);
}

.pick-banner-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: #fff;
  flex: none;
  animation: pick-pulse 1.4s ease-in-out infinite;
}

@keyframes pick-pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: 0.45; transform: scale(0.72); }
}

@media (prefers-reduced-motion: reduce) {
  .pick-banner-dot { animation: none; }
}

.pick-banner-text {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.pick-banner-cancel {
  flex: none;
  border: 0;
  border-radius: 999px;
  padding: 5px 12px;
  background: rgba(255, 255, 255, 0.18);
  color: #fff;
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
}

.pick-banner-cancel:hover { background: rgba(255, 255, 255, 0.3); }
.pick-banner-cancel:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }

/* Two runs of one simulation, named and directly selectable. */
.seg {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 2px;
  margin: 7px 0 2px;
  padding: 2px;
  border-radius: 7px;
  background: rgba(15, 23, 42, 0.08);
}

.seg-btn {
  border: 0;
  border-radius: 5px;
  padding: 5px 6px;
  background: transparent;
  color: var(--muted, #5b6b63);
  font: inherit;
  font-size: 11.5px;
  font-weight: 600;
  cursor: pointer;
}

.seg-btn:hover { color: var(--ink, #14211b); }

.seg-btn.is-on {
  background: #fff;
  color: var(--accent);
  box-shadow: 0 1px 2px rgba(16, 32, 24, 0.16);
}

.seg-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* -------------------------------------------------------- directions --- */

.directions {
  list-style: none;
  margin: 0;
  padding: 0;
  max-height: 420px;
  overflow-y: auto;
}

.directions.is-collapsed {
  display: none;
}

.dir-step {
  display: grid;
  grid-template-columns: 22px 1fr auto;
  gap: 9px;
  align-items: start;
  padding: 8px 6px;
  border-top: 1px solid var(--line);
  cursor: pointer;
  border-radius: 6px;
}

.dir-step:first-child {
  border-top: 0;
}

.dir-step:hover,
.dir-step.is-active {
  background: var(--accent-soft);
}

.dir-arrow {
  font-size: 15px;
  color: var(--accent);
  text-align: center;
  line-height: 1.35;
}

.dir-text {
  font-size: 14px;
  line-height: 1.35;
}

.dir-meta {
  margin-top: 2px;
  font-size: 11px;
  color: var(--muted);
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
}

.dir-dist {
  font-size: 12px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  padding-top: 1px;
}

.chip {
  border-radius: 99px;
  padding: 1px 6px;
  font-weight: 600;
  font-size: 10px;
  letter-spacing: 0.01em;
}

.chip-shade {
  background: #e6f2ec;
  color: #14603c;
}

.chip-green {
  background: #eef7e6;
  color: #3f6212;
}

.chip-road {
  background: #fdf1e0;
  color: var(--warn);
}

/* ------------------------------------------------------ impact sources --- */

.sources {
  margin-top: 12px;
  border-top: 1px solid var(--line);
  padding-top: 9px;
}

.sources summary {
  display: flex;
  align-items: center;
  gap: 7px;
  min-height: 30px;
  cursor: pointer;
  font-size: 12.5px;
  color: var(--muted);
  list-style: none;
}

.sources summary::-webkit-details-marker {
  display: none;
}

/* One glyph, rotated — same treatment as the scoring-weights chevron, and
   big enough to see and to hit. */
.sources summary::before {
  content: "▸";
  display: grid;
  place-items: center;
  flex: none;
  width: 20px;
  height: 20px;
  border-radius: 6px;
  font-size: 14px;
  line-height: 1;
  transition: transform 0.15s, background 0.12s, color 0.12s;
}

.sources summary:hover::before {
  background: rgba(31, 122, 77, 0.12);
  color: var(--accent);
}

.sources[open] summary::before {
  transform: rotate(90deg);
}

.sources ul {
  margin: 8px 0 0;
  padding: 0;
  list-style: none;
}

.sources li {
  font-size: 11.5px;
  line-height: 1.4;
  color: var(--muted);
  padding: 4px 0;
  border-top: 1px dotted var(--line);
}

.sources li b {
  color: var(--ink);
  font-weight: 600;
  display: block;
}

/* --------------------------------------------------------- water stops --- */

.water-stop {
  display: grid;
  grid-template-columns: 22px 1fr auto;
  gap: 9px;
  align-items: baseline;
  padding: 7px 6px;
  border-top: 1px solid var(--line);
  border-radius: 6px;
  cursor: pointer;
}

.water-stop:first-child {
  border-top: 0;
}

.water-stop:hover {
  background: #eaf4fb;
}

.water-icon {
  text-align: center;
  font-size: 13px;
}

.water-name {
  font-size: 14px;
}

.water-meta {
  font-size: 11px;
  color: var(--muted);
}

.water-at {
  font-size: 12px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.chip-water {
  background: #e0f0fb;
  color: #075985;
}

/* Boarding is the instruction in a transit trip you cannot afford to skim. */
.dir-step.is-transit {
  background: #f4f6f9;
}

.dir-step.is-transit .dir-text {
  font-weight: 600;
}

.dir-step.is-transit .dir-arrow {
  font-size: 14px;
}

.water-pin {
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: #0284c7;
  border: 2px solid #fff;
  box-shadow: 0 1px 4px rgba(16, 32, 24, 0.4);
  font-size: 11px;
}

.dry-warning {
  color: var(--warn);
  font-weight: 600;
}

/* ------------------------------------------------- on-map route labels --- */

/* The divIcon container is zero-sized and sits exactly on the anchor point,
   so the card centres itself on the line with a transform. */
.route-label .route-pill {
  position: absolute;
  transform: translate(-50%, -50%);
  pointer-events: auto;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 5px 9px;
  border-radius: 8px;
  background: #fff;
  border: 1px solid #d7dbd8;
  box-shadow: 0 1px 4px rgba(16, 32, 24, 0.3);
  color: var(--muted);
  white-space: nowrap;
  cursor: pointer;
  transition: transform 0.1s, box-shadow 0.1s;
}

.route-label .route-pill:hover {
  transform: translate(-50%, -50%) scale(1.05);
  box-shadow: 0 2px 8px rgba(16, 32, 24, 0.36);
}

.route-label .route-pill.is-selected {
  background: var(--accent);
  border-color: var(--accent);
  color: rgba(255, 255, 255, 0.85);
  box-shadow: 0 2px 8px rgba(16, 32, 24, 0.4);
}

.route-pill-icon {
  font-size: 13px;
  line-height: 1;
}

.route-pill-text {
  display: flex;
  flex-direction: column;
  line-height: 1.15;
}

.route-pill-text b {
  font: 650 13px/1.15 ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  color: var(--ink);
}

.route-label .route-pill.is-selected .route-pill-text b {
  color: #fff;
}

.route-pill-text small {
  font-size: 10.5px;
  font-weight: 500;
}

/* ------------------------------------------------------ endpoint pins --- */

.pin-start {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: #fff;
  border: 3px solid #3c4043;
  box-shadow: 0 1px 4px rgba(16, 32, 24, 0.45);
}

.pin-destination {
  line-height: 0;
  filter: drop-shadow(0 1px 3px rgba(16, 32, 24, 0.4));
}

/* A short bar that reads as the line drawn on the map, replacing the old
   full-height colour strip on the card edge. */
.route-swatch {
  display: inline-block;
  width: 16px;
  height: 4px;
  border-radius: 99px;
  margin-right: 7px;
  vertical-align: middle;
  position: relative;
  top: -1px;
}

/* -------------------------------------------- collapsible map panel --- */

.map-panel {
  width: 100%;
  background: rgba(255, 255, 255, 0.97);
  border: 1px solid var(--line);
  border-radius: 10px;
  box-shadow: 0 4px 18px rgba(16, 32, 24, 0.18);
  overflow: hidden;
}

.map-panel-toggle {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
  padding: 9px 12px;
  border: 0;
  background: none;
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
  cursor: pointer;
}

.map-panel-toggle:hover {
  background: var(--accent-soft);
}

.map-panel-toggle .chev {
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border-radius: 6px;
  color: var(--muted);
  font-size: 15px;
  line-height: 1;
  transition: transform 0.15s, background 0.12s;
}

.map-panel-toggle:hover .chev {
  background: rgba(31, 122, 77, 0.12);
  color: var(--accent);
}

.map-panel-toggle[aria-expanded="true"] .chev {
  transform: rotate(180deg);
}

.map-panel-body {
  padding: 2px 12px 12px;
  border-top: 1px solid var(--line);
  /* Never taller than the map it floats over, and tighter on short screens so
     the legends above it keep some room. */
  max-height: min(46vh, 420px);
  overflow-y: auto;
}

.map-panel-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
  margin: 10px 0 8px;
}


/* =========================================================== responsive ===
   Desktop is a fixed sidebar beside a full-height map. Below 900px that
   becomes a map on top and a normally-scrolling panel underneath, because a
   nested scroll area inside a short viewport is miserable on a phone.
   ======================================================================== */

.legend-row {
  width: 100%;
  border: 0;
  background: none;
  font: inherit;
  font-size: 12px;
  color: var(--ink);
  text-align: left;
  padding: 3px 5px;
  border-radius: 6px;
  cursor: pointer;
}

.legend-row:hover {
  background: var(--accent-soft);
}

.legend-row.is-selected {
  background: var(--accent-soft);
  font-weight: 650;
}

@media (max-width: 900px) {
  html,
  body {
    height: auto;
  }

  .layout {
    grid-template-columns: 1fr;
    grid-template-rows: auto auto;
    height: auto;
  }

  /* Map first, and tall enough to actually read a route on. It scrolls away
     with the page: pinning it would eat half the viewport for the whole of a
     long directions list. */
  .map-wrap {
    order: -1;
    height: 52vh;
    min-height: 300px;
  }

  /* The map is short here, so its floating furniture must not swallow it.
     Legend and weights share the bottom edge, each about half-width. */
  .map-legend {
    left: 8px;
    bottom: 8px;
    max-width: 46%;
    font-size: 11px;
    padding: 7px 8px;
  }

  .map-panel {
    right: 8px;
    bottom: 8px;
    width: 46%;
    min-width: 168px;
  }

  .map-panel-body {
    max-height: 34vh;
  }

  .map-tools {
    top: 8px;
    right: 8px;
    left: 8px;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 5px;
  }

  .pick-btn {
    padding: 8px 10px;
    font-size: 12px;
  }

  .directions {
    max-height: none;
  }
}

@media (max-width: 560px) {
  .brand h1 {
    font-size: 19px;
  }

  .card {
    padding: 13px;
  }

  .mode {
    padding: 11px 3px;
  }

  .primary {
    padding: 13px;
  }

  .swap-btn,
  .link-btn {
    padding: 6px 10px;
  }

  .stats {
    grid-template-columns: 1fr;
  }

  .dir-step,
  .water-stop {
    padding: 10px 6px;
  }

  /* Below this width the two floating boxes cannot sit side by side, so the
     legend gives way — the route list in the panel says the same thing. */
  .map-legend {
    display: none;
  }

  .map-panel {
    right: 8px;
    left: 8px;
    width: auto;
  }

  .route-pill-text b {
    font-size: 12px;
  }
}

/* Touch sizing is about the pointer, not the screen width — a 768px tablet
   needs the same targets as a 375px phone. */
@media (pointer: coarse) {
  /* 16px is the threshold below which iOS zooms the page on focus. */
  .field input {
    font-size: 16px;
    padding: 11px;
  }

  .combo-btn {
    width: 36px;
    height: 36px;
    right: 3px;
    font-size: 17px;
  }

  .combo input {
    padding-right: 42px;
  }

  .link-btn {
    min-height: 32px;
    padding: 4px 8px;
  }

  .swap-btn {
    min-height: 34px;
    padding: 7px 12px;
  }

  .legend-row {
    padding: 7px 6px;
  }
}

/* Coarse pointers get no hover-only affordances. */
@media (hover: none) {
  .route:hover {
    box-shadow: none;
  }

  .route-label .route-pill:hover {
    transform: translate(-50%, -50%);
    box-shadow: 0 1px 4px rgba(16, 32, 24, 0.3);
  }
}

/* ======================================================= mobile sheet ===
   Below 900px the sidebar becomes a bottom sheet over a full-screen map,
   draggable between three snap points: peek, half, and full. Dragging is
   confined to the handle so it never fights the scrolling list inside.
   ====================================================================== */

@media (max-width: 900px) {
  html,
  body {
    height: 100%;
    overflow: hidden;
  }

  .layout {
    display: block;
    height: 100%;
  }

  /* Map fills the window; the sheet floats over it. */
  .map-wrap {
    position: absolute;
    inset: 0;
    height: auto;
    min-height: 0;
  }

  .panel {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    height: 94dvh;
    z-index: 800;
    border-right: 0;
    border-top: 1px solid var(--line);
    border-radius: 16px 16px 0 0;
    box-shadow: 0 -6px 26px rgba(16, 32, 24, 0.22);
    transition: transform 0.28s cubic-bezier(0.32, 0.72, 0, 1);
    will-change: transform;
  }

  /* While a finger is down the sheet must track it exactly, not ease. */
  .panel.is-dragging {
    transition: none;
  }

  .panel-scroll {
    /* Height is driven by the sheet's snap point, so it must not also flex. */
    flex: none;
    padding: 2px 14px 32px;
    overscroll-behavior: contain;
  }

  .sheet-handle {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 5px;
    width: 100%;
    flex: none;
    padding: 9px 12px 7px;
    border: 0;
    background: none;
    font: inherit;
    cursor: grab;
    /* Claim the gesture: the browser must not scroll the page instead. */
    touch-action: none;
  }

  .panel.is-dragging .sheet-handle {
    cursor: grabbing;
  }

  .sheet-grip {
    width: 40px;
    height: 4px;
    border-radius: 99px;
    background: #c8d0ca;
  }

  .sheet-peek {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1px;
    min-width: 0;
    max-width: 100%;
  }

  /* One line each, ellipsed — a long trip name must not wrap the sheet open. */
  .sheet-trip,
  .sheet-sub {
    max-width: 86vw;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .sheet-trip {
    font-size: 13.5px;
    font-weight: 650;
    color: var(--ink);
  }

  .sheet-sub {
    font-size: 11.5px;
    color: var(--muted);
  }

  /* Bottom-anchored map furniture would sit under the sheet, so it moves up
     top. The legend goes entirely — the sheet's route list says the same. */
  .map-legend {
    display: none;
  }

  .map-stack {
    top: 54px;
    bottom: auto;
    left: 8px;
    width: 160px;
  }

  .map-panel {
    width: 100%;
    min-width: 0;
  }

  .map-panel-body {
    max-height: 42vh;
  }

  /* Both sit along the top edge, so the tools are capped to whatever the
     weights panel leaves rather than a percentage that overlaps it on a
     narrow phone. */
  .map-tools {
    left: auto;
    max-width: calc(100% - 200px);
  }
}

/* ----------------------------------------------------- route profile --- */

.profile-svg {
  width: 100%;
  height: auto;
  display: block;
  overflow: visible;
  touch-action: none;
}

.profile-label {
  font-size: 8.5px;
  font-weight: 600;
  fill: var(--muted);
}

.profile-track {
  fill: #eef1ee;
}

.profile-water {
  fill: #0284c7;
  stroke: #fff;
  stroke-width: 1.2;
}

.profile-turn {
  stroke: #c3ccc6;
  stroke-width: 1;
}

.profile-tick {
  font-size: 8px;
  fill: var(--muted);
}

.profile-cursor {
  stroke: var(--ink);
  stroke-width: 1;
  opacity: 0.5;
  pointer-events: none;
}

/* Transparent, but it is what receives the pointer across the whole plot —
   pointer-events: all so a zero-alpha fill still hit-tests. */
.profile-hit {
  fill: transparent;
  pointer-events: all;
  cursor: crosshair;
}

.profile-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 10px;
  margin-top: 8px;
  font-size: 11px;
  color: var(--muted);
}

.profile-key {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}

.profile-key i {
  width: 10px;
  height: 10px;
  border-radius: 3px;
  display: inline-block;
}

.profile-readout {
  margin-top: 6px;
  min-height: 17px;
  font-size: 12px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.profile-none {
  opacity: 0.75;
}

/* ------------------------------------------------ walkability overlay --- */

/* Crisp cells rather than a blurred wash: each pixel is a real 75 m
   measurement, and smoothing it invents values between them. Multiply darkens
   the basemap, which keeps street geometry legible through the colour. */
.walk-overlay {
  image-rendering: pixelated;
  mix-blend-mode: multiply;
}

/* The jobs layer is the opposite operation: `screen` adds light rather than
   removing it, so it reads as a glow over the walkability colour instead of
   muddying it. The blur is what turns 150 m cells into a heatmap — the
   underlying data is blocky, and for a density surface smoothing is the
   honest rendering rather than an invention. */
.econ-overlay {
  mix-blend-mode: screen;
  filter: blur(5px);
}

.walk-ramp {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 1px;
  margin: 6px 0 3px;
}

/* Mirrors RAMP in walkability.js — red through yellow to green. */
.walk-ramp span {
  height: 8px;
}

.walk-ramp span:nth-child(1) { background: rgb(165, 0, 38); }
.walk-ramp span:nth-child(2) { background: rgb(244, 109, 67); }
.walk-ramp span:nth-child(3) { background: rgb(254, 224, 139); }
.walk-ramp span:nth-child(4) { background: rgb(166, 217, 106); }
.walk-ramp span:nth-child(5) { background: rgb(26, 152, 80); }

.walk-ramp-labels {
  display: flex;
  justify-content: space-between;
  font-size: 10px;
  color: var(--muted);
}

.walk-note {
  margin-top: 5px;
  font-size: 10px;
  color: var(--muted);
  line-height: 1.35;
}

/* --------------------------------------------------------- priority --- */

.priority-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.priority-site {
  display: grid;
  grid-template-columns: 26px 1fr auto;
  gap: 9px;
  align-items: baseline;
  padding: 8px 6px;
  border-top: 1px solid var(--line);
  border-radius: 6px;
  cursor: pointer;
}

.priority-site:first-child {
  border-top: 0;
}

.priority-site:hover {
  background: #fdf0f3;
}

.priority-rank {
  font-size: 12px;
  font-weight: 700;
  color: #9f1239;
  text-align: center;
}

.priority-name {
  font-size: 14px;
  line-height: 1.3;
}

.priority-meta {
  font-size: 11px;
  color: var(--muted);
  margin-top: 2px;
}

.priority-score {
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
  white-space: nowrap;
}

/* The priority ramp mirrors colorFor() in priority.js: one hue, alpha rising
   with the score. Sequential, because the value is a magnitude. */
.prio-ramp {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 1px;
  margin: 6px 0 3px;
}

.prio-ramp span {
  height: 8px;
  background: #be123c;
}

.prio-ramp span:nth-child(1) { opacity: 0.35; }
.prio-ramp span:nth-child(2) { opacity: 0.48; }
.prio-ramp span:nth-child(3) { opacity: 0.6; }
.prio-ramp span:nth-child(4) { opacity: 0.72; }
.prio-ramp span:nth-child(5) { opacity: 0.85; }

/* A slider sitting at zero has to say why, or it reads as broken. */
.weight-note {
  margin: 2px 0 4px;
  font-size: 10.5px;
  line-height: 1.4;
  color: var(--muted);
}

.econ-ramp {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 1px;
  margin: 6px 0 3px;
}

/* Mirrors HEAT in economy.js — purple to white hot, shown on a dark strip
   because a screen-blended glow is invisible against white. */
.econ-ramp {
  background: #1f2937;
  padding: 2px;
  border-radius: 3px;
}

.econ-ramp span {
  height: 8px;
}

.econ-ramp span:nth-child(1) { background: rgb(107, 33, 168); }
.econ-ramp span:nth-child(2) { background: rgb(168, 85, 247); }
.econ-ramp span:nth-child(3) { background: rgb(200, 150, 251); }
.econ-ramp span:nth-child(4) { background: rgb(233, 213, 255); }
.econ-ramp span:nth-child(5) { background: rgb(255, 255, 255); }

/* ------------------------------------------------------- map scales --- */

/* Legends for the layer overlays, bottom-right and right-aligned. The trip
   tools and layer switches are top-right, the weights panel and route key are
   bottom-left — so each corner does one job. */
.map-scales {
  position: absolute;
  right: 12px;
  bottom: 22px;
  z-index: 600;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 8px;
  width: 250px;
  max-height: calc(100% - 44px);
  overflow-y: auto;
  overflow-x: hidden;
  scrollbar-width: thin;
}

.map-scales .map-legend {
  width: 100%;
}

/* Map buttons carry an icon and a label; below 900px only the icon survives,
   because three text buttons plus the legend column do not fit a phone. The
   title attribute keeps the meaning available to a pointer and a screen
   reader either way. */
.btn-icon {
  font-style: normal;
}

.btn-text {
  margin-left: 5px;
}

@media (max-width: 900px) {
  /* Six text buttons will not fit a phone; the icons carry them, and the title
     attribute keeps the meaning for a pointer and a screen reader. */
  .map-tools .btn-text {
    display: none;
  }

  .map-tools .pick-btn {
    min-width: 42px;
    padding: 9px 10px;
    text-align: center;
  }

  /* Icons hugging the right. They wrap rather than running off the edge: at
     400px a single row of seven put Demand and Priority past the right edge
     entirely, where nothing could reach them. */
  .map-tools {
    top: 8px;
    right: 8px;
    left: auto;
    max-width: calc(100% - 16px);
    flex-wrap: wrap;
    justify-content: flex-end;
    row-gap: 6px;
  }

  /* Each group stays whole when the row breaks, so the trip pair never splits
     across two lines. */
  .tool-group {
    flex-wrap: nowrap;
  }

  /* The sheet owns the bottom, so both columns hang below the button row —
     panel on the left, scales on the right, narrow enough to clear each other
     on a 375px screen. */
  .map-scales {
    top: 54px;
    right: 8px;
    bottom: auto;
    width: 160px;
    max-height: 42vh;
  }
}

/* ------------------------------------------------- priority scatter --- */

.sc {
  width: 100%;
  height: auto;
  display: block;
  margin: 4px 0 2px;
  overflow: visible;
}

/* Context, not a series: neutral so the chosen cells carry the only colour. */
.sc-bg { fill: #9aa8a0; opacity: 0.45; }

.sc-site {
  fill: #be123c;
  stroke: var(--panel);
  stroke-width: 1.5; /* the 2px-ish surface ring that keeps overlaps readable */
}

.sc-iso {
  fill: none;
  stroke: #be123c;
  stroke-width: 1.2;
  stroke-dasharray: 3 3;
  opacity: 0.55;
}

.sc-grid { stroke: var(--line); stroke-width: 1; }
.sc-tick { font-size: 8px; fill: var(--muted); font-variant-numeric: tabular-nums; }
.sc-axis { font-size: 8.5px; fill: var(--muted); }

.sc-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 12px;
  margin: 2px 0 10px;
  font-size: 11px;
  color: var(--muted);
}

.sc-key { display: inline-flex; align-items: center; gap: 5px; }

.sc-key i {
  display: inline-block;
  width: 9px;
  height: 9px;
  border-radius: 50%;
}

.sc-dot-site { background: #be123c; }
.sc-dot-bg { background: #9aa8a0; opacity: 0.55; }
.sc-dash {
  width: 14px !important;
  height: 0 !important;
  border-top: 1.5px dashed #be123c;
  border-radius: 0 !important;
  opacity: 0.7;
}

/* Foot traffic, in the one hue left — walkability owns red-green, jobs purple,
   priority crimson. Composited normally rather than screen-blended: screen
   lightens, and against a light street basemap it erased the layer. */
.dem-overlay {
  filter: blur(2px);
  opacity: 0.92;
}

.dem-ramp {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 1px;
  margin: 6px 0 3px;
  background: rgba(15, 23, 42, 0.12);
  padding: 2px;
  border-radius: 3px;
}

.dem-ramp span { height: 8px; }
.dem-ramp span:nth-child(1) { background: rgb(254, 215, 170); }
.dem-ramp span:nth-child(2) { background: rgb(251, 146, 60); }
.dem-ramp span:nth-child(3) { background: rgb(234, 88, 12); }
.dem-ramp span:nth-child(4) { background: rgb(180, 66, 15); }
.dem-ramp span:nth-child(5) { background: rgb(124, 45, 18); }

/* ------------------------------------------------------- scenario ------- */

/* The what-if built on the priority ranking. It lives inside the priority
   card because it is the second half of the same sentence: here is where the
   problem is, here is what fixing it buys. */
.scenario {
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 12px 14px;
  margin: 12px 0 14px;
  background: var(--raised, #f4f7f4);
}

.scn-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 10px;
}

.scn-head strong { font-size: 13.5px; }

.scn-control { display: block; margin-bottom: 12px; }

.scn-label {
  display: block;
  font-size: 12.5px;
  margin-bottom: 5px;
}

.scn-label b { color: var(--accent); }

.scn-label em {
  display: block;
  font-style: normal;
  font-size: 11px;
  color: var(--muted);
  margin-top: 1px;
}

.scn-control input[type="range"] { width: 100%; accent-color: var(--accent); }

.scn-figures {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin: 12px 0 14px;
}

.scn-fig {
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 10px 11px;
}

.scn-big {
  display: block;
  font-size: 22px;
  font-weight: 700;
  line-height: 1.05;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}

.scn-cap {
  display: block;
  font-size: 10.5px;
  line-height: 1.35;
  color: var(--muted);
  margin-top: 4px;
}

.scn-bars { margin-bottom: 10px; }

.scn-bar-row {
  display: grid;
  grid-template-columns: 42px 1fr 40px;
  align-items: center;
  gap: 8px;
  margin-bottom: 5px;
}

.scn-bar-label { font-size: 11.5px; color: var(--muted); }

.scn-bar {
  display: block;
  height: 14px;
  border-radius: 3px;
  background: rgba(15, 23, 42, 0.08);
  overflow: hidden;
}

.scn-bar i {
  display: block;
  height: 100%;
  background: #94a3b8;
  border-radius: 3px;
  transition: width 0.18s ease;
}

.scn-bar i.is-after { background: var(--accent); }

.scn-bar-val {
  font-size: 11.5px;
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.scn-axis {
  font-size: 10.5px;
  color: var(--muted);
  margin: 4px 0 0;
}

.scn-note {
  font-size: 12px;
  line-height: 1.5;
  color: var(--muted);
  margin: 0;
}

.scn-note b { color: var(--ink); }

@media (prefers-reduced-motion: reduce) {
  .scn-bar i { transition: none; }
}

/* Each headline figure carries its own definition, because "burden" and
   "trip-passes" are exact and mean nothing to someone reading them cold. */
.scn-cap em {
  display: block;
  font-style: normal;
  font-size: 9.5px;
  line-height: 1.35;
  color: var(--muted);
  opacity: 0.85;
  margin-top: 3px;
}

.scn-intro {
  font-size: 11.5px;
  line-height: 1.45;
  color: var(--muted);
  margin: -4px 0 12px;
}

.legend-note {
  margin: -4px 0 12px;
  line-height: 1.5;
}

/* ------------------------------------------------------- recentre ------- */

/* Sits under the zoom control, where a map app's recentre button belongs.
   Quiet until the map has actually wandered off what it is showing. */
.recenter-btn {
  position: absolute;
  top: 88px;
  left: 10px;
  z-index: 520;
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 1px solid rgba(0, 0, 0, 0.2);
  border-radius: 5px;
  background: #fff;
  color: var(--muted, #5b6b63);
  cursor: pointer;
  box-shadow: 0 1px 4px rgba(16, 32, 24, 0.22);
}

.recenter-btn svg {
  width: 19px;
  height: 19px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.9;
  stroke-linecap: round;
}

.recenter-btn svg .ring { opacity: 0.45; }

.recenter-btn:hover { color: var(--ink, #14211b); }
.recenter-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* The map has moved away from what it is showing, so the button has
   something to do. Same signal Google's gives: colour, not a new control. */
.recenter-btn.is-away {
  color: var(--accent);
  border-color: rgba(31, 122, 77, 0.5);
}

@media (max-width: 900px) {
  .recenter-btn {
    width: 38px;
    height: 38px;
  }
  .recenter-btn svg { width: 21px; height: 21px; }
}
