/* The map explorer: the map, its filter bar, the station menu, the period pop-up, the
   station panel with its charts, and journeys with their playback bar. */
/* ---------- charts */
.chart-card { padding: 14px 18px 12px; display: flex; flex-direction: column; min-width: 0; }
.chart-head { display: flex; justify-content: space-between; align-items: center; gap: 12px; margin-bottom: 8px; flex-wrap: wrap; }
.legend { display: flex; gap: 18px; font-size: 14px; color: var(--ink-2); align-items: center; }
.legend i { display: inline-block; margin-right: 7px; vertical-align: middle; }
.legend .line { width: 18px; height: 3px; background: var(--teal); border-radius: 2px; }
.legend .band { width: 22px; height: 14px; background: rgba(23, 138, 148, .2); border-radius: 3px; }
.legend .median { width: 20px; border-top: 2px dashed var(--violet); }
.chart-box { position: relative; min-height: 0; flex: 1; }
.chart-empty { position: absolute; inset: 0; display: grid; place-items: center; text-align: center; color: var(--muted); padding: 20px; }

/* dual range slider */
.range { position: relative; height: 34px; }
.range .track { position: absolute; left: 0; right: 0; top: 50%; height: 5px; margin-top: -2.5px; border-radius: 3px; background: #d7e0e6; }
.range .fill { position: absolute; top: 50%; height: 5px; margin-top: -2.5px; background: var(--teal); border-radius: 3px; }
.range input[type="range"] { position: absolute; inset: 0; width: 100%; margin: 0; background: none; pointer-events: none; appearance: none; -webkit-appearance: none; height: 34px; }
.range input[type="range"]::-webkit-slider-thumb { pointer-events: auto; -webkit-appearance: none; width: 20px; height: 20px; border-radius: 50%; background: var(--teal); border: 3px solid #fff; box-shadow: 0 0 0 1.5px var(--teal); cursor: grab; }
.range input[type="range"]::-moz-range-thumb { pointer-events: auto; width: 16px; height: 16px; border-radius: 50%; background: var(--teal); border: 3px solid #fff; box-shadow: 0 0 0 1.5px var(--teal); cursor: grab; }
.range input[type="range"]::-moz-range-track { background: none; }
.range input[type="range"]:focus-visible::-webkit-slider-thumb { box-shadow: 0 0 0 4px rgba(23,138,148,.35); }

.play { width: 44px; height: 44px; border-radius: 50%; border: 1px solid var(--line-strong); background: #fff; display: grid; place-items: center; cursor: pointer; flex: none; }
.play svg { width: 18px; height: 18px; }


/* ---------- map
   The map fills the page and everything else floats on it: a slim filter bar along the
   top, the selected station's details in a panel on the right that can be put away, and
   a journey's playback bar along the bottom. Below 900px it stacks instead.
   Each piece of the page is styled in one place below, in this order: the map and its
   controls, the filter bar, the station menu, the period pop-up, the panel (figures,
   journey list, charts, statistics), station pins and popups, and journeys on the map. */
.main-flush { padding: 0; }
.main-flush > .messages { margin: 12px; }
.mx-wrap { --panel-w: 400px; --gap: 14px; --float: 0 4px 16px rgba(19, 42, 62, .14);
           position: relative; height: 100vh; min-height: 560px; overflow: hidden; }
.mx { position: absolute; inset: 0; overflow: hidden; }
#map { position: absolute; inset: 0; background: #a9d3ec; }
/* The tile credit must stay visible, but it need not compete with the map. */
#map .leaflet-control-attribution { font-size: 9px; line-height: 1.3; max-width: 60%; opacity: 0.55;
                                    background: rgba(255, 255, 255, 0.5); }
#map .leaflet-control-attribution:hover { opacity: 1; }

/* Zoom and scale in the same frosted look as the bar and popups. */
#map .leaflet-control-zoom { border: 1px solid rgba(255, 255, 255, .9); border-radius: 12px; overflow: hidden;
                             background: rgba(255, 255, 255, .78); -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px);
                             box-shadow: 0 0 0 1px rgba(19, 42, 62, .08), 0 6px 18px rgba(19, 42, 62, .14); }
#map .leaflet-control-zoom a { width: 36px; height: 36px; line-height: 34px; border: 0; background: transparent;
                               font: 600 20px/34px var(--font); color: var(--ink); transition: background-color .15s, color .15s; }
#map .leaflet-control-zoom a + a { border-top: 1px solid rgba(19, 42, 62, .10); }
#map .leaflet-control-zoom a:hover { background: var(--teal-soft); color: var(--teal-strong); }
#map .leaflet-control-zoom a.leaflet-disabled { color: var(--line-strong); background: transparent; }
/* The scale in a small frosted pill like the zoom buttons: the distance, and under it the
   measuring bracket at its true length. */
#map .leaflet-control-scale { margin-bottom: 14px; margin-left: 14px; padding: 5px 10px 7px; border-radius: 10px;
                              border: 1px solid rgba(255, 255, 255, .9); background: rgba(255, 255, 255, .78);
                              -webkit-backdrop-filter: blur(12px) saturate(1.3); backdrop-filter: blur(12px) saturate(1.3);
                              box-shadow: 0 0 0 1px rgba(19, 42, 62, .08), 0 6px 18px rgba(19, 42, 62, .14); }
#map .leaflet-control-scale-line { padding: 0 6px 2px; border: 2px solid var(--ink-2); border-top: 0; border-radius: 0 0 3px 3px;
                                   background: transparent; font: 700 11px/1.3 var(--font); color: var(--ink-2); text-shadow: none; }
/* Leaflet's right-hand controls stay clear of an open panel, and the bottom ones lift
   clear of the playback bar while a journey is shown. */
.mx-wrap:not(.panel-closed) .mx .leaflet-right { right: calc(var(--panel-w) + var(--gap)); }
.map-card.has-journeys .leaflet-bottom.leaflet-right,
.map-card.has-journeys .leaflet-bottom.leaflet-left { bottom: 66px; }

/* ----- filter bar
   Frosted, along the top. A grid, so the four tiles (stations, measurement, period,
   journeys) are always exactly the same width, sharing the room up to 240px each, with
   the details toggle at the far end. The tiles are soft filled blocks of one height and
   shape: no outline until hovered, teal when open or on. */
.mx-bar { position: absolute; z-index: 600; top: var(--gap); left: var(--gap); right: calc(var(--panel-w) + var(--gap) * 2);
          display: grid; grid-template-columns: repeat(4, minmax(0, 240px)) minmax(max-content, 1fr); align-items: center;
          gap: 6px; padding: 6px; container: bar / inline-size;
          border-radius: 14px; border: 1px solid rgba(255, 255, 255, .9);
          background: rgba(255, 255, 255, .78); -webkit-backdrop-filter: blur(12px) saturate(1.3); backdrop-filter: blur(12px) saturate(1.3);
          box-shadow: 0 0 0 1px rgba(19, 42, 62, .08), 0 6px 20px rgba(19, 42, 62, .14); }
.mx-wrap.panel-closed .mx-bar { right: var(--gap); }
/* The tile look, shared by the station count, the measurement menu and the toggles. */
.mx-bar .select, .mx-count, .mx-details, .mx-journeys {
  height: 38px; border: 1px solid transparent; border-radius: 10px; background-color: rgba(236, 242, 245, .9);
  color: var(--ink); transition: background-color .15s, border-color .15s, color .15s; }
.mx-bar .select:hover, .mx-count:hover, .mx-details:hover, .mx-journeys:hover { background-color: #fff; border-color: var(--line-strong); }
.mx-count[aria-expanded="true"], .mx-details[aria-pressed="true"] { background-color: var(--teal-soft); border-color: rgba(23, 138, 148, .45); color: var(--teal-strong); }
.mx-bar .mx-count, .mx-bar .select, .mx-bar .mx-date, .mx-bar .mx-journeys { width: 100%; min-width: 0; max-width: none; }
.mx-bar .select { font-size: 14px; font-weight: 600; padding-left: 14px; text-overflow: ellipsis; }

/* The station count, which opens the station menu. */
.mx-count { display: inline-flex; align-items: center; justify-content: space-between; gap: 10px; padding: 0 16px; overflow: hidden;
            font: inherit; font-weight: 700; font-size: 15px; white-space: nowrap; cursor: pointer; }
.mx-count::after { content: ""; width: 8px; height: 8px; border-right: 2px solid currentColor; border-bottom: 2px solid currentColor;
                   transform: translateY(-2px) rotate(45deg); opacity: .6; transition: transform .15s; }
.mx-count[aria-expanded="true"]::after { transform: translateY(2px) rotate(225deg); }

/* The period, as a tile opening the period pop-up. With a journey picked the tile names the
   journey instead and gains a clear (×); the dates then follow the journey and are not
   offered, so they cannot reset it. */
.mx-date { display: inline-flex; align-items: center; position: relative; container: datetile / inline-size; }
.mx-datechip { flex: 1; min-width: 0; overflow: hidden; display: inline-flex; align-items: center; gap: 8px; height: 38px; padding: 0 13px;
               font: inherit; font-size: 14px; font-weight: 600; white-space: nowrap; cursor: pointer;
               border: 1px solid transparent; border-radius: 10px; background: rgba(236, 242, 245, .9); color: var(--ink);
               transition: background-color .15s, border-color .15s, color .15s; }
.mx-datechip #date-label { overflow: hidden; text-overflow: ellipsis; }
.mx-datechip svg { width: 17px; height: 17px; flex: none; color: var(--ink-2); }
.mx-datechip:hover { background: #fff; border-color: var(--line-strong); }
.mx-datechip[aria-expanded="true"] { background: var(--teal-soft); border-color: rgba(23, 138, 148, .45); color: var(--teal-strong); }
.mx-date.has-journey .mx-datechip { font-size: 13px; background: var(--teal-soft); border-color: rgba(23, 138, 148, .45); color: var(--teal-strong);
                                    border-top-right-radius: 0; border-bottom-right-radius: 0; }
.mx-date.has-journey .mx-datechip svg { color: var(--teal-strong); }
.mx-date-clear { display: grid; place-items: center; width: 30px; height: 38px; padding: 0; cursor: pointer;
                 border: 1px solid rgba(23, 138, 148, .45); border-left: 0; border-radius: 0 10px 10px 0; background: var(--teal-soft); color: var(--teal-strong); }
.mx-date-clear svg { width: 14px; height: 14px; }
.mx-date-clear:hover { background: var(--teal); color: #fff; }
/* As the tile narrows, a picked journey's end time ("–15:38") goes first, then the icon
   and "Walk ·", leaving the date, time and × (slimmer, so one click still clears it).
   Keyed on the tile's own width, so it holds on any screen. */
@container datetile (max-width: 229px) {
  .mx-date.has-journey .dl-end { display: none; }
}
@container datetile (max-width: 193px) {
  .mx-date.has-journey .mx-datechip svg,
  .mx-date.has-journey .dl-kind { display: none; }
  .mx-bar .mx-date.has-journey .mx-datechip { padding: 0 5px 0 7px; justify-content: center; font-size: 12.5px; }
  .mx-date.has-journey .mx-date-clear { width: 24px; }
  .mx-date.has-journey .mx-date-clear svg { width: 12px; height: 12px; }
}

/* The journeys toggle: its label says what a click does, the count stands out in teal,
   the switch (at the far edge) shows the state. */
.mx-journeys { display: inline-flex; align-items: center; justify-content: flex-start; gap: 8px; padding: 0 7px 0 13px; overflow: hidden;
             font-family: inherit; font-size: 14px; font-weight: 600; white-space: nowrap; cursor: pointer; container: routes / inline-size; }
.mx-journeys #journeys-word { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.mx-journeys .jw-noun { display: inline-block; }
.mx-journeys-n { flex: none; min-width: 22px; padding: 2px 7px; border-radius: 999px; background: var(--teal); color: #fff;
               font-size: 12px; font-weight: 700; line-height: 1.35; text-align: center; font-variant-numeric: tabular-nums;
               box-shadow: 0 1px 3px rgba(23, 138, 148, .35); }
.mx-journeys .switch { width: 42px; height: 24px; margin-left: auto; pointer-events: none; }
.mx-journeys .switch::after { width: 18px; height: 18px; }
.mx-journeys[aria-checked="true"] .switch { background: var(--teal); }
.mx-journeys[aria-checked="true"] .switch::after { transform: translateX(18px); }
.mx-journeys:disabled { cursor: default; color: var(--muted); }
.mx-journeys:disabled:hover { background-color: rgba(236, 242, 245, .9); border-color: transparent; }
.mx-journeys:disabled .switch { opacity: .5; }
/* A narrow tile drops "Hide"/"Show" (the switch already says which) and keeps "Journeys". */
@container routes (max-width: 167px) {
  #journeys-verb { display: none; }
  .mx-journeys .jw-noun::first-letter { text-transform: uppercase; }
}

/* The details toggle, at the bar's right end. When the bar is short of room (a laptop
   screen with the panel open) it keeps only its icon, its name still on hover. */
.mx-details { justify-self: end; display: inline-flex; align-items: center; gap: 7px; padding: 0 13px;
              font: inherit; font-size: 14px; font-weight: 600; white-space: nowrap; cursor: pointer; }
.mx-details svg { width: 17px; height: 17px; }
@container bar (max-width: 800px) {
  .mx-details { font-size: 0; gap: 0; padding: 0 11px; }
}

/* ----- station menu
   One line per station, dropped from the count and only as tall as the list, so it
   covers a corner of the map and no more. */
.station-menu { position: absolute; z-index: 650; top: calc(var(--gap) + 56px); left: var(--gap); width: 330px;
                max-height: min(480px, calc(100% - 140px)); overflow-y: auto;
                background: #fff; border-radius: 12px; box-shadow: var(--float); }
.sm-search { position: sticky; top: 0; z-index: 1; padding: 7px 7px 2px; background: #fff; }
.sm-search .input { width: 100%; height: 34px; font-size: 14px; border-color: var(--line); }
.sm-search svg { left: 20px; }
/* Under the search box: how many are on the map on the left; Sort and Hide all / Show all
   (for the stations listed) on the right. */
.sm-tools { display: flex; align-items: center; gap: 6px; margin: 8px 12px 2px; padding-bottom: 7px; border-bottom: 1px solid var(--line); }
.sm-tools .sm-head { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sm-sort-label { font-size: 11.5px; color: var(--muted); }
/* What the figures are and for which dates, centred above the list in quiet text. */
.sm-colhead { display: flex; justify-content: center; margin: 7px 12px 0; }
.sm-colhead span { max-width: 100%; font-size: 11.5px; font-weight: 600; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sm-sort { height: 24px; padding: 0 20px 0 6px; border: 1px solid var(--line); border-radius: 7px; background-color: #fff;
           font: inherit; font-size: 12px; color: var(--ink-2); cursor: pointer; appearance: none;
           background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' fill='none' stroke='%233d5163' stroke-width='1.6'%3E%3Cpath d='M1 1l4 4 4-4'/%3E%3C/svg%3E");
           background-repeat: no-repeat; background-position: right 6px center; }
.sm-head { font-size: 10.5px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--muted); }
.sm-all { padding: 2px 4px; border: 0; border-radius: 6px; background: none; font: inherit; font-size: 12.5px; font-weight: 600;
          color: var(--teal-strong); cursor: pointer; }
.sm-all:hover { text-decoration: underline; }
.sm-list { list-style: none; margin: 0; padding: 5px; }
.sm-list button { width: 100%; text-align: left; font: inherit; padding: 7px 9px; border: 0; border-radius: 8px;
                  background: transparent; color: var(--ink); cursor: pointer; }
.sm-list button:hover { background: #f1f6f8; }
.sm-list button[aria-current="true"] { background: var(--teal-soft); }
.sm-dot { flex: none; width: 9px; height: 9px; border-radius: 50%; background: #1e3c58; }
.sm-dot.hollow { background: transparent; box-shadow: inset 0 0 0 2px var(--line-strong); }
.sm-name { flex: 1; min-width: 0; font-weight: 600; font-size: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sm-empty { padding: 12px; font-size: 13px; color: var(--muted); text-align: center; }
/* Each row in fixed columns, so the dots, names, figures and eyes line up down the list:
   the row is the station's button (dot, name, figures) and its eye. Shown: a teal eye on a
   soft teal circle. Hidden: a grey crossed eye, the name greyed and a "Hidden" tag. */
.sm-row { display: grid; grid-template-columns: minmax(0, 1fr) 32px; align-items: center; gap: 4px; }
.sm-row > button:first-child { display: grid; grid-template-columns: 10px minmax(0, 1fr) 92px; align-items: center; gap: 10px; }
.sm-list .sm-eye { display: grid; place-items: center; width: 30px; height: 30px; padding: 0; border-radius: 50%;
                   background: var(--teal-soft); color: var(--teal-strong); transition: background-color .15s, color .15s; }
.sm-list .sm-eye:hover { background: #cfe9eb; }
.sm-eye svg { width: 16px; height: 16px; }
.sm-list .is-hidden .sm-eye { background: transparent; color: var(--muted); }
.sm-list .is-hidden .sm-eye:hover { background: #eef3f6; color: var(--ink); }
.sm-row.is-hidden .sm-name { color: var(--muted); font-weight: 500; }
/* On the right of each row: the mean for the chosen dates over whether it is still reporting
   ("Live" in green, otherwise how long ago), or a "Hidden" tag. */
.sm-figures { display: flex; flex-direction: column; align-items: flex-end; gap: 1px; line-height: 1.2; text-align: right; }
.sm-mean { font-size: 13px; font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; white-space: nowrap; }
.sm-mean small { font-size: 10.5px; font-weight: 600; color: var(--muted); }
.sm-none { font-size: 11.5px; color: var(--muted); }
.sm-tag { padding: 1px 7px; border-radius: 8px; background: #eef3f6; font-size: 10.5px; font-weight: 700; letter-spacing: .02em; color: var(--muted); }
.sm-status { font-size: 10.5px; color: var(--muted); white-space: nowrap; }
.sm-status.live { display: inline-flex; align-items: center; gap: 4px; font-weight: 700; color: #2f9e5e; }
.sm-status.live::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: #2f9e5e; }
/* Stations without a location, at the foot of the menu beside the hollow rings that mark
   them: a soft amber note with the way to fix it, instead of a box over the map. */
.sm-note { display: flex; align-items: flex-start; gap: 9px; margin: 0 6px 6px; padding: 8px 10px;
           border-radius: 9px; background: #fdf6e6; border: 1px solid #f1e0b6; font-size: 12.5px; line-height: 1.4; color: #6b4a06; }
.sm-note-ring { flex: none; width: 9px; height: 9px; margin-top: 4px; border-radius: 50%; box-shadow: inset 0 0 0 2px #c9a24a; }
.sm-note strong { display: block; color: #5a3d03; }
.sm-note-names { margin-right: 4px; }
.sm-note a { font-weight: 600; color: var(--teal-strong); }

/* ----- period pop-up
   Frosted, under the date tile: the two dates side by side, then play, the slider and the
   day count on one row; the date boxes are kept solid to read. With a journey picked it
   is a small note instead: a small-caps heading, the journey's day and times, its kind,
   length and readings as pills, and the way back beneath a hairline. */
.date-pop { position: absolute; z-index: 650; top: calc(var(--gap) + 58px); width: 340px; padding: 12px 12px 10px; border-radius: 12px;
            border: 1px solid rgba(255, 255, 255, .9); background: rgba(255, 255, 255, .78);
            -webkit-backdrop-filter: blur(12px) saturate(1.3); backdrop-filter: blur(12px) saturate(1.3);
            box-shadow: 0 0 0 1px rgba(19, 42, 62, .08), 0 8px 24px rgba(19, 42, 62, .16); }
.time-strip { display: grid; gap: 4px; margin: 0 0 8px; }
.time-strip-dates { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.time-strip-dates .input { height: 32px; padding: 0 8px; font-size: 13.5px; flex: 1; min-width: 116px; }
.time-strip-slider { display: flex; align-items: center; gap: 10px; }
.time-strip-slider .range-wrap { flex: 1; min-width: 0; }
.time-strip-slider .range { height: 22px; }
.time-strip-slider .range input[type="range"] { height: 22px; }
.time-strip-slider .range input[type="range"]::-webkit-slider-thumb { width: 15px; height: 15px; border-width: 2px; }
.time-strip-slider .range input[type="range"]::-moz-range-thumb { width: 12px; height: 12px; border-width: 2px; }
/* A day back or on, either side of the slider. */
.period-step { display: grid; place-items: center; width: 30px; height: 30px; flex: none; padding: 0; border-radius: 50%;
               border: 1px solid var(--line-strong); background: #fff; color: var(--ink-2); cursor: pointer; }
.period-step:hover:not(:disabled) { background: var(--teal-soft); border-color: rgba(23, 138, 148, .45); color: var(--teal-strong); }
.period-step:disabled { opacity: .4; cursor: default; }
.period-step svg { width: 16px; height: 16px; }
.date-pop .time-strip { margin: 0; padding: 0; border: 0; background: none; gap: 10px; }
.date-pop .time-strip-dates { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); align-items: center; gap: 8px; }
.date-pop .time-strip-dates .input { width: 100%; height: 34px; padding: 0 8px; font-size: 13.5px; border-color: var(--line); background: rgba(255, 255, 255, .92); }
.date-pop .time-strip-dates .muted { font-size: 12.5px; }
.date-pop .time-strip-slider .range-wrap { flex: 1; min-width: 0; padding: 0 9px; }
.date-pop .time-strip-slider .play { width: 26px; height: 26px; border-color: var(--line); background: rgba(255, 255, 255, .92); }
.date-pop .time-strip-slider .play svg { width: 13px; height: 13px; }
.date-pop #days { order: 3; flex: none; margin-left: 2px; padding: 2px 8px; border-radius: 10px;
                  background: var(--teal-soft); color: var(--teal-strong); font-weight: 600; font-size: 11.5px; }
.date-pop:has(.date-journey:not([hidden])) { width: auto; padding: 10px 12px 8px; }
.date-journey { display: grid; gap: 3px; justify-items: center; text-align: center; white-space: nowrap; }
.ds-title { font-size: 10px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--teal-strong); }
.ds-when { font-size: 14px; font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; }
.ds-meta { display: flex; justify-content: center; gap: 5px; margin-top: 3px; }
.ds-pill { padding: 1px 8px; border-radius: 8px; background: rgba(231, 237, 241, .9); font-size: 11px; font-weight: 600; color: var(--ink-2); }
.ds-meta .jl-kind { justify-self: auto; }
.date-journey .ds-all { justify-self: stretch; margin-top: 7px; padding: 6px 0 0; height: auto; border: 0; border-top: 1px solid rgba(19, 42, 62, .1); border-radius: 0; background: none; text-align: center; justify-content: center;
                        font-size: 12.5px; font-weight: 600; color: var(--teal-strong); box-shadow: none; }
.date-journey .ds-all:hover { background: none; text-decoration: underline; }

/* ----- panel
   The selected station's details, floating on the right. Put away, it slides off and the
   bar takes the room back. Its header (name and close) stays pinned while it scrolls. */
.mx-panel { position: absolute; z-index: 600; top: var(--gap); right: var(--gap); bottom: var(--gap);
            width: var(--panel-w); overflow-y: auto; padding: 16px 18px 14px; display: flex; flex-direction: column; gap: 14px;
            background: rgba(255, 255, 255, .97); border: 0; border-radius: 12px; box-shadow: var(--float);
            transition: transform .2s ease, opacity .2s ease; }
.mx-wrap.panel-closed .mx-panel { transform: translateX(calc(100% + var(--gap) * 2)); opacity: 0; pointer-events: none; }
.mx-panel-head { position: sticky; top: -16px; z-index: 5; display: flex; align-items: flex-start; gap: 12px;
                 margin-top: -16px; padding-top: 16px; padding-bottom: 12px; border-bottom: 1px solid var(--line); background: #fff; }
.mx-panel-title { flex: 1; min-width: 0; }
.mx-panel-title h2 { margin: 0; font-size: 20px; font-weight: 700; line-height: 1.25; letter-spacing: -.015em; overflow-wrap: anywhere; }
.mx-panel-title h2 .code { font-weight: 500; color: var(--muted); }
/* What the panel shows (measurement and dates, or the picked journey), as the same teal pill
   as the station menu's, under the station's name. */
.mx-panel-title #st-sub { display: inline-block; max-width: 100%; margin-top: 5px; padding: 2px 10px; border-radius: 999px;
                          background: var(--teal-soft); font-size: 12px; font-weight: 600; line-height: 1.4; color: var(--teal-strong);
                          white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mx-panel-head .icon-btn { flex: none; width: 32px; height: 32px; padding: 0; place-items: center; border-radius: 50%;
                           background: #eef3f6; color: var(--ink-2); transition: background .15s, color .15s; }
.mx-panel-head .icon-btn:hover { background: #dfe8ee; color: var(--ink); }
.mx-panel-head .icon-btn svg { width: 16px; height: 16px; }
.mx-section { border-top: 1px solid var(--line); padding-top: 12px; }
.mx-section h3 { margin: 0; font-size: 15px; font-weight: 700; }
.mx-section .chart-head { margin-bottom: 4px; }
.mx-section .legend { gap: 14px; margin-bottom: 8px; }

/* The headline: one strip of three facts split by hairlines (the latest reading, the mean
   over the period, how many readings), each with one small line beneath, kept level. */
.mini-metrics { display: grid; grid-template-columns: 1.15fr 1fr 1fr; border: 1px solid var(--line); border-radius: 11px; background: #f8fbfc; }
.mm { padding: 10px 6px 9px; min-width: 0; text-align: center; display: flex; flex-direction: column; align-items: center; }
.mm + .mm { border-left: 1px solid var(--line); }
.mm-label { font-size: 11px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--muted); }
.mini-metrics .v { margin-top: 2px; font-size: 21px; font-weight: 700; line-height: 1.15; font-variant-numeric: tabular-nums; white-space: nowrap; }
.mini-metrics .v small { margin-left: 2px; font-size: 12px; font-weight: 600; color: var(--muted); }
.mm-main .v { font-size: 25px; color: var(--teal-strong); }
.mm-sub { margin-top: auto; padding-top: 3px; font-size: 10px; line-height: 1.3; color: var(--muted); white-space: nowrap; }

/* The journey list: one line each, about five shown before it scrolls; the type chips
   above it filter the list. */
.sm-chips { display: flex; gap: 4px; }
.chip { font: inherit; font-size: 12px; padding: 2px 9px; border-radius: 12px; border: 1px solid var(--line); background: #fff; color: var(--ink-2); cursor: pointer; }
.chip:hover { border-color: var(--teal); }
.chip[aria-pressed="true"] { background: var(--teal); border-color: var(--teal); color: #fff; font-weight: 600; }
.mx-journey-list .chart-head { align-items: center; }
.jl-list { list-style: none; margin: 0; padding: 3px; max-height: 196px; overflow-y: auto;
             border: 1px solid var(--line); border-radius: 10px; background: #f8fbfc; }
.jl-list button { width: 100%; display: grid; grid-template-columns: 8px minmax(0, 1fr) 50px 52px 42px; align-items: center; gap: 9px;
                    text-align: left; font: inherit; font-size: 13px; padding: 6px 9px; border: 0; border-radius: 7px;
                    background: transparent; color: var(--ink); cursor: pointer; }
.jl-list button:hover { background: #fff; }
.jl-list button[aria-current="true"] { background: var(--teal-soft); }
.jl-list button[aria-current="true"] .jl-when { font-weight: 700; }
.jl-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--line-strong); }
.jl-dot.walk { background: var(--teal); }
.jl-dot.all { background: transparent; box-shadow: inset 0 0 0 2px var(--teal); } /* a ring: "every journey" */
.jl-when { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Type as a small pill (teal for a walk, grey indoors), length and readings right-aligned
   in tabular figures so the digits line up down the list. */
.jl-kind { justify-self: start; padding: 1px 7px; border-radius: 8px; font-size: 10.5px; font-weight: 700; letter-spacing: .02em;
             background: #e7edf1; color: var(--ink-2); white-space: nowrap; }
.jl-kind.walk { background: var(--teal-soft); color: var(--teal-strong); }
.jl-len, .jl-count { font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; text-align: right; white-space: nowrap; }
.jl-bubbles { grid-column: 3 / -1; display: flex; justify-content: flex-end; gap: 5px; min-width: 0; }
.jl-note { flex: none; max-width: 100%; padding: 1px 9px; border-radius: 8px; background: #e7edf1;
             font-size: 11px; font-weight: 600; color: var(--ink-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* The whole-period row sits apart from the journeys beneath it. */
.jl-list li:first-child { margin-bottom: 3px; padding-bottom: 3px; border-bottom: 1px solid var(--line); }
.jl-list button[aria-current="true"] .jl-note { background: rgba(255, 255, 255, .75); color: var(--teal-strong); }
.jl-list .sm-empty { padding: 10px; }

/* The over-time chart: title with its legend beneath, then its own menus in a full-width
   row (averaging the wider, CI, Reset zoom while zoomed in, enlarge), then the plot. */
.mx-chart .chart-head { flex-direction: column; flex-wrap: nowrap; align-items: stretch; gap: 8px; margin-bottom: 10px; }
.mx-chart .legend { margin: 3px 0 0; gap: 14px; font-size: 12px; color: var(--muted); }
.mx-chart .legend .line { width: 14px; }
.mx-chart .legend .band { width: 16px; height: 10px; }
.chart-title { position: relative; display: flex; align-items: center; gap: 7px; }
.select-sm { height: 30px; font-size: 13px; padding: 0 28px 0 10px; max-width: 170px; background-position: right 10px center; }
.chart-ctrls { display: flex; gap: 6px; }
.chart-ctrls .select-sm { max-width: none; }
.chart-ctrls #aggregation { flex: 1.6 1 0; min-width: 0; }
.chart-ctrls #ci { flex: 1 1 0; min-width: 0; }
.mx-chart #ci, .mx-chart #aggregation { width: auto; border-color: var(--line); color: var(--ink-2); }
.chart-btn { flex: none; display: grid; place-items: center; width: 30px; height: 30px; padding: 0; border: 1px solid var(--line);
             border-radius: 8px; background: #fff; color: var(--ink-2); cursor: pointer; }
.chart-btn:hover { border-color: var(--teal); color: var(--teal-strong); }
.chart-btn svg { width: 15px; height: 15px; }
/* Shown in the menu row only while zoomed in, in the teal of something switched on. */
.zoom-reset { flex: none; height: 30px; padding: 0 11px; border: 1px solid rgba(23, 138, 148, .45); border-radius: 8px;
              background: var(--teal-soft); color: var(--teal-strong); font: inherit; font-size: 12.5px; font-weight: 600; white-space: nowrap; cursor: pointer; }
.zoom-reset:hover { background: #fff; }
.mx-series { height: 220px; flex: none; }
.mx-hist { height: 150px; flex: none; }
#series { cursor: crosshair; }
/* With nothing to plot, show only the message: an empty chart's axis numbers behind it
   look like data that is not there. */
.mx-panel .chart-box:has(> .chart-empty:not([hidden])) canvas { visibility: hidden; }
.mx-panel .chart-empty { inset: 0; border: 1px dashed var(--line-strong); border-radius: 10px; background: #fafcfd; font-size: 13px; line-height: 1.4; padding: 18px 28px; }
.mx-panel .chart-empty:empty { display: none; }
/* While new numbers load the old chart fades, after a beat so quick changes do not flicker. */
.chart-box canvas { transition: opacity .15s; }
.chart-box.is-loading canvas { opacity: .35; transition-delay: .15s; }
/* Enlarged: the chart section moves into this pop-up, and its enlarge button becomes the
   close (×) in the top right corner. */
.chart-dialog { width: min(1100px, 92vw); height: min(640px, 84vh); padding: 20px 24px; border: 0; border-radius: 16px;
                background: #fff; box-shadow: 0 20px 60px rgba(19, 42, 62, .3); }
.chart-dialog::backdrop { background: rgba(19, 42, 62, .45); -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px); }
.chart-dialog .mx-chart { display: flex; flex-direction: column; height: 100%; border-top: 0; padding-top: 0; }
.chart-dialog .chart-head { flex: none; }
.chart-dialog .chart-ctrls { max-width: 520px; }
.chart-dialog .mx-series { flex: 1; height: auto; min-height: 0; }
.chart-dialog h3 { font-size: 18px; }
.chart-dialog #chart-full { position: absolute; top: 14px; right: 14px; width: 32px; height: 32px; border-radius: 50%; }

/* Statistics: six figures in the same hairline grid as the headline strip (label, value,
   and the CI or IQR beneath where there is one), the dates in the heading, and a note
   only when there are no readings. */
.stats-period { font-size: 12px; color: var(--muted); white-space: nowrap; }
.mx-stats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); margin: 10px 0 8px;
            border: 1px solid var(--line); border-radius: 11px; background: #f8fbfc; overflow: hidden; }
.mx-stats .stat { padding: 9px 8px 8px; display: flex; flex-direction: column; align-items: center; gap: 1px; text-align: center; min-width: 0; }
.mx-stats .stat:nth-child(n+4) { border-top: 1px solid var(--line); }
.mx-stats .stat:not(:nth-child(3n+1)) { border-left: 1px solid var(--line); }
.mx-stats .stat-label { font-size: 10.5px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--muted); white-space: nowrap; }
.mx-stats .stat-value { font-size: 16px; white-space: nowrap; }
.mx-stats .stat-value small { margin-left: 2px; font-size: 11px; font-weight: 600; color: var(--muted); }
.mx-stats .stat-sub { font-size: 10.5px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
.mx-stats .stat-sub[data-period] { display: none; }
#stats-note { margin: 0; font-size: 11.5px; line-height: 1.4; }
#stats-note:empty { display: none; }
.mx-actions { display: flex; gap: 8px; justify-content: center; margin-top: auto; padding-top: 4px; }
.mx-actions .btn svg { width: 17px; height: 17px; }

/* ----- station pins and popups
   Pins: a soft shadow lifts them off the map; the selected one also glows teal. Popups
   and name labels in frosted glass: the map shows faintly through, blurred so the text
   stays readable, inside a fine light rim. Scoped to #map so Leaflet's own styles, which
   load after ours, do not win. */
#map .st-pin { background: none; border: 0; }
#map .st-pin svg { display: block; width: 100%; height: 100%; overflow: visible; transform-origin: 50% 100%; transition: transform .15s;
                   filter: drop-shadow(0 2px 3px rgba(19, 42, 62, .45)); }
#map .st-pin:hover svg { transform: scale(1.1); }
#map .st-pin-empty svg { filter: drop-shadow(0 1px 2px rgba(19, 42, 62, .3)); }
#map .st-pin-on svg { filter: drop-shadow(0 0 7px rgba(23, 138, 148, .8)) drop-shadow(0 2px 3px rgba(19, 42, 62, .4)); }
#map .station-label { padding: 3px 10px; border-radius: 999px; border: 1px solid rgba(255, 255, 255, .85);
                      background: rgba(255, 255, 255, .72); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
                      box-shadow: 0 0 0 1px rgba(19, 42, 62, .10), 0 3px 10px rgba(19, 42, 62, .16);
                      font-family: var(--font); font-weight: 700; font-size: 13px; color: var(--ink); white-space: nowrap; }
#map .station-label::before { display: none; }
#map .leaflet-popup-content-wrapper, #map .leaflet-popup-tip {
  background: rgba(255, 255, 255, .58); -webkit-backdrop-filter: blur(10px) saturate(1.3); backdrop-filter: blur(10px) saturate(1.3); }
#map .leaflet-popup-content-wrapper { border-radius: 14px; padding: 0; border: 1px solid rgba(255, 255, 255, .85);
                                 box-shadow: 0 0 0 1px rgba(19, 42, 62, .10), 0 8px 26px rgba(19, 42, 62, .20); }
#map .leaflet-popup-content { margin: 11px 24px 10px; font-family: var(--font); min-width: 0; width: auto !important; text-align: center; }
#map .leaflet-popup-tip { box-shadow: none; border: 1px solid rgba(19, 42, 62, .08); }
.leaflet-container a.leaflet-popup-close-button { top: 6px; right: 6px; width: 22px; height: 22px; border-radius: 50%;
                                                  font: 16px/22px var(--font); color: var(--muted); }
.leaflet-container a.leaflet-popup-close-button:hover { background: #eef3f6; color: var(--ink); }
/* The popup's content: name, then mean and latest side by side split by a hairline, then
   the median and how many readings beneath another. */
.pop-title { line-height: 1.2; margin-bottom: 8px; }
.pop-name { display: block; font-size: 14.5px; font-weight: 700; color: var(--ink); }
.pop-code { display: block; font-size: 11.5px; font-weight: 500; color: var(--muted); }
.pop-figs { display: grid; grid-template-columns: 1fr 1fr; }
.pop-figs > div { display: flex; flex-direction: column; align-items: center; padding: 0 10px; }
.pop-figs > div + div { border-left: 1px solid rgba(19, 42, 62, .12); }
.pop-label { font-size: 10px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--muted); white-space: nowrap; }
.pop-value { display: inline-flex; align-items: center; gap: 5px; font-size: 19px; font-weight: 700; line-height: 1.25; color: var(--teal-strong); font-variant-numeric: tabular-nums; white-space: nowrap; }
.pop-value small { font-size: 11.5px; font-weight: 600; color: var(--muted); }
.pop-dot { width: 9px; height: 9px; border-radius: 50%; flex: none; box-shadow: 0 0 0 2px #fff, 0 0 0 3px rgba(19, 42, 62, .12); }
.pop-when { font-size: 11px; color: var(--muted); }
.pop-empty { font-size: 12.5px; color: var(--muted); }
.pop-meta { white-space: nowrap; font-size: 11.5px; color: var(--muted); margin: 8px 0 0; padding-top: 6px; border-top: 1px solid rgba(19, 42, 62, .12); }
.pop-link { font-weight: 600; text-decoration: none; }

/* ----- journeys on the map
   Coloured dots and a faint line, Start and End as small dark squares, a moving cursor
   during playback, the colour key (top left) and the playback bar (along the bottom). */
.journey-dot { cursor: pointer; }
/* Where the sensor is during playback: an arrow in a soft, slowly breathing halo. */
#map .journey-here { background: none; border: 0; pointer-events: none; }
.journey-here-halo { position: absolute; inset: 0; border-radius: 50%; background: rgba(23, 138, 148, .28);
                     animation: journey-here 1.8s ease-in-out infinite; }
.journey-here-arrow { position: relative; display: block; width: 100%; height: 100%; transition: transform .2s ease;
                      filter: drop-shadow(0 1px 3px rgba(19, 42, 62, .45)); }
@keyframes journey-here { 0%, 100% { transform: scale(.7); opacity: .9; } 50% { transform: scale(1.15); opacity: .35; } }
@media (prefers-reduced-motion: reduce) { .journey-here-halo { animation: none; } .journey-here-arrow { transition: none; } }
.journey-tip { font-variant-numeric: tabular-nums; }
#map .journey-end { background: none; border: 0; }
#map .journey-end svg { display: block; width: 100%; height: 100%; filter: drop-shadow(0 1px 3px rgba(19, 42, 62, .45)); }
/* The colour key in the frosted look: a small-caps heading with the unit quieter, the bands
   as rounded colour pills against tabular numbers, and a note in grey under a hairline. */
.colour-key { position: absolute; top: calc(var(--gap) + 62px); left: var(--gap); z-index: 500; min-width: 132px; max-width: 200px;
                padding: 10px 12px 9px; font-size: 13px; border-radius: 12px;
                border: 1px solid rgba(255, 255, 255, .9); background: rgba(255, 255, 255, .78);
                -webkit-backdrop-filter: blur(12px) saturate(1.3); backdrop-filter: blur(12px) saturate(1.3);
                box-shadow: 0 0 0 1px rgba(19, 42, 62, .08), 0 6px 18px rgba(19, 42, 62, .14); }
.colour-key-head { display: flex; align-items: baseline; gap: 5px; margin-bottom: 7px;
                     font-size: 10.5px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--ink-2); }
.colour-key-head .muted { font-size: 11px; font-weight: 600; letter-spacing: 0; text-transform: none; }
.colour-key ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 5px; }
.colour-key li { display: flex; align-items: center; gap: 9px; white-space: nowrap; font-variant-numeric: tabular-nums;
                   font-size: 12.5px; font-weight: 600; color: var(--ink); }
.colour-key li i { flex: none; width: 18px; height: 8px; border-radius: 4px; box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .08); }
.colour-key #colour-key-note { margin-top: 8px; padding-top: 6px; border-top: 1px solid rgba(19, 42, 62, .1); white-space: normal;
                            font-size: 11px; line-height: 1.35; color: var(--muted); text-align: center; }
/* The playback bar in the same frosted look as the filter bar: a teal play button, a slim
   slider that fills in teal as the journey plays, the time and the reading (its dot in the
   reading's band colour), and a speed toggle. */
.playback-bar { position: absolute; left: var(--gap); right: var(--gap); bottom: var(--gap); z-index: 500;
             display: flex; align-items: center; gap: 12px; padding: 7px 10px 7px 8px; border-radius: 14px;
             border: 1px solid rgba(255, 255, 255, .9); background: rgba(255, 255, 255, .78);
             -webkit-backdrop-filter: blur(12px) saturate(1.3); backdrop-filter: blur(12px) saturate(1.3);
             box-shadow: 0 0 0 1px rgba(19, 42, 62, .08), 0 6px 20px rgba(19, 42, 62, .14); }
.mx-wrap:not(.panel-closed) .playback-bar { right: calc(var(--panel-w) + var(--gap) * 2); }
.playback-bar .play { width: 38px; height: 38px; border: 0; background: var(--teal); color: #fff;
                   box-shadow: 0 2px 6px rgba(23, 138, 148, .35); transition: background .15s, transform .1s; }
.playback-bar .play:hover { background: var(--teal-strong); }
.playback-bar .play:active { transform: scale(.95); }
.playback-bar .play svg { width: 15px; height: 15px; }
.playback-main { flex: 1; min-width: 0; display: flex; align-items: center; gap: 12px; }
/* The slider and, above it on hover, a preview of the moment under the pointer. */
.scrub-wrap { position: relative; flex: 1; min-width: 60px; display: flex; }
.scrub-preview { position: absolute; bottom: calc(100% + 10px); transform: translateX(-50%); padding: 4px 9px; border-radius: 8px;
                 background: var(--navy); color: #fff; font-size: 12px; font-weight: 600; white-space: nowrap; pointer-events: none;
                 font-variant-numeric: tabular-nums; box-shadow: 0 3px 10px rgba(19, 42, 62, .25); }
.scrub-preview::after { content: ""; position: absolute; left: 50%; top: 100%; margin-left: -5px; border: 5px solid transparent; border-top-color: var(--navy); }
.scrub { --p: 0%; flex: 1; min-width: 60px; height: 22px; margin: 0; appearance: none; -webkit-appearance: none;
         accent-color: var(--teal); background: transparent; cursor: pointer; }
.scrub::-webkit-slider-runnable-track { height: 6px; border-radius: 3px; background: linear-gradient(90deg, var(--teal) var(--p), #d9e3e9 var(--p)); }
.scrub::-moz-range-track { height: 6px; border-radius: 3px; background: linear-gradient(90deg, var(--teal) var(--p), #d9e3e9 var(--p)); }
.scrub::-webkit-slider-thumb { -webkit-appearance: none; width: 16px; height: 16px; margin-top: -5px; border-radius: 50%;
                               background: #fff; border: 3px solid var(--teal); box-shadow: 0 1px 4px rgba(19, 42, 62, .3); }
.scrub::-moz-range-thumb { width: 12px; height: 12px; border-radius: 50%; background: #fff; border: 3px solid var(--teal); box-shadow: 0 1px 4px rgba(19, 42, 62, .3); }
.playback-readout { flex: none; display: flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--ink-2); font-variant-numeric: tabular-nums; white-space: nowrap; }
.playback-readout #playback-when { color: var(--muted); }
.playback-readout #playback-value { --band: var(--line-strong); display: inline-flex; align-items: center; gap: 6px; padding: 3px 10px;
                              border-radius: 12px; background: rgba(236, 242, 245, .9); font-weight: 700; color: var(--ink); }
.playback-readout #playback-value::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--band); }
.playback-readout #playback-value:empty { display: none; }
.playback-speed { flex: none; height: 30px; min-width: 40px; padding: 0 9px; border-radius: 9px; border: 1px solid transparent;
               background: rgba(236, 242, 245, .9); font: inherit; font-size: 13px; font-weight: 700; color: var(--ink-2); cursor: pointer;
               font-variant-numeric: tabular-nums; }
.playback-speed:hover { background: #fff; border-color: var(--line-strong); }


/* ---------- responsive */
@media (max-width: 1280px) {
  .mx-wrap { --panel-w: 360px; }
  .colour-key { max-width: 150px; font-size: 12px; }
}
/* Too narrow to float a panel over the map: the map takes the top of the screen and the
   station's details follow underneath, always shown. */
@media (max-width: 900px) {
  .mx-wrap { height: auto; min-height: 0; }
  .mx { position: relative; height: 62vh; min-height: 380px; }
  .mx-wrap .mx-bar, .mx-wrap.panel-closed .mx-bar { right: var(--gap); }
  .mx-wrap .playback-bar, .mx-wrap:not(.panel-closed) .playback-bar { right: var(--gap); }
  .mx-wrap .mx .leaflet-right, .mx-wrap:not(.panel-closed) .mx .leaflet-right { right: 0; }
  .mx-panel, .mx-wrap.panel-closed .mx-panel { position: static; width: auto; transform: none; opacity: 1; pointer-events: auto;
                                               box-shadow: none; border-radius: 0; overflow: visible; }
  #panel-close, .mx-details { display: none; }
}
/* On a phone the page keeps the same 16px margin as every other page (base.css), the map included. */
@media (max-width: 760px) {
  .main-flush { padding: 16px; }
}
