/* وين نلقى (Wenalga)
 *
 * Direction: instrument, not luxury. The reader is a driver, one-handed, in daylight glare,
 * on a bad connection, low on fuel.
 *
 * The badge is the whole interface. Someone glancing at this while a queue moves needs one
 * answer per row, not a chart to interpret. Confidence is carried by FORM as well as colour -
 * solid = confirmed, dashed = a single report, ghosted = nothing recent - so the meaning
 * survives sunlight, colour blindness, a cheap screen and dark mode.
 *
 * RTL: physical left/right is never used. Logical properties only.
 */

/* ============================================================================================
   Tokens
   ============================================================================================ */

:root {
  --ink:     #101418;
  --surface: #FCFCFA;
  --raise:   #FFFFFF;
  --petrol:  #0E4F52;
  --petrol-soft: #E3F0EE;
  --ember:   #A9541B;
  --ember-soft: #FBEEE2;
  --slate:   #737B82;
  --slate-soft: #EFF1F2;
  --line:    #E4E5E2;
  --muted:   #9AA1A6;

  /* Status colours. Green/red is the pairing drivers already read instantly, so it is worth
     the one cost it carries: roughly one man in twelve cannot separate those two hues. That
     cost is covered by never letting colour be the ONLY signal - a confirmed badge is filled
     and a single report is dashed, so confidence survives even when the hue does not, and
     every badge says what it means in words. */
  --ok:      #1F7A43;
  --ok-soft: #E4F3E9;
  --bad:     #B3261E;
  --bad-soft: #FBE9E7;

  --banner-warn-bg: #FFF4E6;  --banner-warn-fg: #7A4A12;  --banner-warn-line: #F0DCC0;
  --banner-bad-bg:  #FBE9E7;  --banner-bad-fg:  #8A2B20;  --banner-bad-line:  #F0C8C2;
  --ghost: #F4F4F2;

  --map-filter: grayscale(1) contrast(0.92) brightness(1.06);

  /* The brand surface. Petrol is spent in exactly ONE place - the masthead - so that it still
     signifies something. It deliberately does not leak into rows, badges or buttons.
     These are their own tokens rather than reusing --petrol because --petrol is lifted in
     dark mode (it has to carry on near-black as a text colour); a masthead painted with the
     lifted value would glow. The brand block stays deep in both themes. */
  --brand-bg:    #0E4F52;
  --brand-fg:    #FCFCFA;
  --brand-dim:   rgba(252, 252, 250, 0.74);
  --brand-line:  rgba(252, 252, 250, 0.22);
  --brand-track: #3E7476;

  --pad: 1rem;
  --radius: 10px;
  --font: "IBM Plex Sans Arabic", system-ui, -apple-system, "Segoe UI", sans-serif;
}

/* Dark is opt-in via the toggle. Light stays the default because this is read through a
   windscreen in daylight. */
:root[data-theme="dark"] {
  --ink:     #E8EAEC;
  --surface: #0F1214;
  --raise:   #171B1E;
  /* Petrol at its light value disappears against near-black; this is the same hue lifted
     until it carries on a dark ground. */
  --petrol:  #4FB3A6;
  --petrol-soft: #16302F;
  --ember:   #E0904A;
  --ember-soft: #2E2115;
  --slate:   #8B949B;
  --slate-soft: #1E2427;
  --line:    #2A3034;
  --muted:   #6E7880;

  /* Lifted so they carry on a near-black ground; the light values go muddy there. */
  --ok:      #4ADE80;
  --ok-soft: #16301F;
  --bad:     #F87171;
  --bad-soft: #2C1917;

  --banner-warn-bg: #2A2113;  --banner-warn-fg: #E8C48A;  --banner-warn-line: #4A3A1E;
  --banner-bad-bg:  #2C1917;  --banner-bad-fg:  #E9A79C;  --banner-bad-line:  #4C2A25;
  --ghost: #20262A;

  /* Dark map tiles without a paid provider: invert, rotate the hues back, desaturate. */
  --map-filter: invert(1) hue-rotate(180deg) grayscale(1) brightness(0.92) contrast(0.95);

  /* Deepened, not lifted: on a near-black page the masthead should still read as a distinct
     block without becoming the brightest thing on screen. */
  --brand-bg:    #0B393C;
  --brand-track: #2F6265;
}

* { box-sizing: border-box; }

html, body {
  margin: 0; padding: 0;
  background: var(--surface); color: var(--ink);
  font-family: var(--font); font-size: 16px; line-height: 1.5;
  -webkit-text-size-adjust: 100%;
}

.hidden { display: none !important; }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

:focus-visible { outline: 2px solid var(--petrol); outline-offset: 2px; }

/* Western numerals (0-9) sitting inside Arabic text reorder under bidi unless isolated -
   the likeliest RTL rendering bug in this app. */
.station-meta, .strap-summary, .strap-updated, .total-reports, .detail-age {
  unicode-bidi: isolate; font-variant-numeric: tabular-nums;
}

/* ============================================================================================
   Masthead
   ============================================================================================ */

/* The one place petrol is spent. Everything below it stays on paper. */
.masthead {
  padding: 0.9rem var(--pad) 0.85rem;
  background: var(--brand-bg); color: var(--brand-fg);
}

.masthead-row {
  display: flex; align-items: center; justify-content: space-between; gap: 0.75rem;
}

.wordmark { margin: 0; font-size: 1.55rem; font-weight: 700; letter-spacing: -0.01em; }

.lockup {
  display: flex; align-items: center; gap: 0.5rem;
  min-height: 44px;              /* it is a link home, so it is a tap target like any other */
  color: inherit; text-decoration: none;
}
/* Locked ratio: the mark's cap height tracks the wordmark rather than a fixed pixel size, so
   the lockup holds together if the type scale moves. */
.lockup-mark { inline-size: 1.32em; block-size: 1.32em; flex-shrink: 0; display: block; }
.wordmark-text { display: block; }

.masthead-actions { display: flex; gap: 0.4rem; flex-shrink: 0; }

/* Demoted: these are the least important controls on the page and had been carrying the same
   visual weight as the title. On the brand block they read as quiet outlines. */
.icon-btn {
  min-height: 44px; padding-inline: 0.8rem;
  font-family: inherit; font-size: 0.82rem; font-weight: 500;
  color: var(--brand-dim); background: transparent;
  border: 1px solid var(--brand-line); border-radius: var(--radius); cursor: pointer;
}
.icon-btn:hover { color: var(--brand-fg); border-color: var(--brand-fg); }

.tagline { margin: 0.35rem 0 0; font-size: 0.88rem; color: var(--brand-dim); }
.total-reports { color: var(--brand-dim); font-variant-numeric: tabular-nums; }

/* ============================================================================================
   The mark — one shape, three scales: masthead lockup, station row, map pin
   ============================================================================================
   FILL = THE ANSWER (a full pin means fuel), EDGE = THE CONFIDENCE (solid means confirmed,
   dashed means a single source). That split is what keeps colour from being the only signal:
   متوفر and بلاغ واحد differ by edge, not hue, and لا توجد معلومات and غير متوفر differ by
   edge weight as well as hue - on top of both stating their meaning in words. */
.sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

.pin-track { fill: var(--brand-track); }
.pin-fill  { fill: var(--brand-fg); }
.pin-edge  { fill: none; stroke: var(--brand-fg); stroke-width: 4.5; stroke-linejoin: round; }

/* ============================================================================================
   The persistent fuel switch
   ============================================================================================ */

.view-switch {
  display: flex; gap: 0; padding-inline: var(--pad);
  border-block-end: 1px solid var(--line); background: var(--surface);
}

/* Renders as <a> on the list (the fuel belongs in the URL) and as <button> on a station page
   (so switching fuel does not throw you off the station). A button carries the browser's own
   background and border, so both are reset here explicitly - without this the switch turns
   into two white boxes the moment you open a station. */
.switch-link {
  flex: 1; text-align: center;
  padding: 0.75rem 0.5rem; min-height: 48px;
  display: flex; align-items: center; justify-content: center;
  font-family: inherit; font-size: 1rem; font-weight: 500;
  color: var(--slate); text-decoration: none; cursor: pointer;
  background: none; -webkit-appearance: none; appearance: none;
  border: 0; border-block-end: 2px solid transparent; margin-block-end: -1px;
}

.switch-link.active {
  color: var(--ink); font-weight: 700; border-block-end-color: var(--petrol);
}

/* ============================================================================================
   Banners
   ============================================================================================ */

.banner { padding: 0.7rem var(--pad); font-size: 0.9rem; font-weight: 500; text-align: center; }

.banner-local, .banner-demo {
  background: var(--banner-warn-bg); color: var(--banner-warn-fg);
  border-block: 1px solid var(--banner-warn-line);
}
/* Not dismissible anywhere in the markup or the JS: fabricated data must never be able to
   look like real reports. */
.banner-demo { font-weight: 600; }

.banner-offline, .banner-error {
  background: var(--banner-bad-bg); color: var(--banner-bad-fg);
  border-block: 1px solid var(--banner-bad-line);
}

/* Quiet by design. This is a fallback notice, not the app's headline - it had been the second
   thing on screen at full body size, pushing the first station below the fold. Start-aligned
   and set small so it informs without competing. */
.note {
  margin: 0; padding: 0.35rem var(--pad); font-size: 0.78rem; line-height: 1.5;
  color: var(--slate); text-align: start;
  background: var(--ghost); border-block-end: 1px solid var(--line);
  /* Flex, not inline text, so the retry button can hold a full 44px target without a
     44px-tall inline box shoving the sentence apart. */
  display: flex; flex-wrap: wrap; align-items: center; gap: 0 0.4rem;
}
/* Compact type, full-size target. An earlier pass set min-height:0 here to tighten the note
   and silently shrank this to a 29px tap target - on the one control a user with no location
   has to hit. */
.note .link-btn {
  min-height: 44px; padding-inline: 0;
  font-size: 0.78rem; color: var(--petrol); font-weight: 600;
}

/* ============================================================================================
   Strap
   ============================================================================================ */

.strap {
  display: flex; align-items: center; justify-content: space-between; gap: 0.75rem;
  padding: 0.7rem var(--pad);
  background: var(--raise); border-block-end: 1px solid var(--line);
}

.strap-city { flex-shrink: 0; }

#city-select {
  min-height: 44px; padding-inline: 0.6rem;
  font-family: inherit; font-size: 0.95rem; font-weight: 600;
  color: var(--ink); background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--radius);
}

.strap-figures { text-align: start; min-width: 0; }
.strap-summary { display: block; font-size: 0.95rem; font-weight: 600; }
.strap-updated { display: block; font-size: 0.76rem; color: var(--muted); }

/* ============================================================================================
   Map
   ============================================================================================ */

#map { height: 38vh; min-height: 220px; width: 100%; background: var(--ghost); }
#map .leaflet-tile-pane { filter: var(--map-filter); }
#map .leaflet-container { font-family: var(--font); background: var(--ghost); }

/* Pins carry the status of the one fuel the page is showing. Only honest because the switch
   means a page is never about two things at once. */
.pin {
  display: block; width: 14px; height: 14px; border-radius: 50%;
  border: 2px solid var(--raise); box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.25);
  background: var(--muted);
}
.pin.state-yes { background: var(--ok); }
.pin.state-no { background: var(--bad); }
/* Hollow, not just paler: a single report reads as unconfirmed by shape, which survives on a
   sunlit screen and for a colour-blind reader. */
.pin.state-single_yes { background: var(--raise); box-shadow: 0 0 0 2px var(--ok); }
.pin.state-single_no { background: var(--raise); box-shadow: 0 0 0 2px var(--bad); }
.pin.state-none { background: var(--muted); opacity: 0.5; }

/* Clusters stay NEUTRAL with a count. A cluster colour would average away disagreement
   between the stations inside it - the same dishonesty as a station-level status. */
.marker-cluster { background: color-mix(in srgb, var(--petrol) 22%, transparent); border-radius: 50%; }
.marker-cluster div {
  width: 30px; height: 30px; margin: 5px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--petrol); color: #fff;
  font-family: var(--font); font-size: 0.78rem; font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.popup { font-family: var(--font); font-size: 0.9rem; line-height: 1.7; min-width: 12rem; }
.popup-sub { color: var(--slate); font-size: 0.85rem; unicode-bidi: isolate; }

.popup-actions { display: flex; gap: 0.4rem; margin-block-start: 0.6rem; }

.popup-open {
  flex: 1; min-height: 40px;
  font-family: inherit; font-size: 0.85rem; font-weight: 600;
  color: var(--ink); background: var(--raise);
  border: 1px solid var(--line); border-radius: var(--radius); cursor: pointer;
}
.popup-actions .nav-btn { flex: 1; }
.popup-badge { font-weight: 600; }
.popup-badge.state-yes, .popup-badge.state-single_yes { color: var(--ok); }
.popup-badge.state-no, .popup-badge.state-single_no { color: var(--bad); }

/* --- map toggle + key ------------------------------------------------------------------ */

.map-bar { padding: 0.15rem var(--pad); border-block-end: 1px solid var(--line); }

/* Secondary action, secondary weight. A full-width bordered box gave "show the map" the same
   presence as the list it sits above, when the list is the thing that answers the question. */
.map-toggle {
  min-height: 44px; padding: 0.3rem 0;
  font-family: inherit; font-size: 0.85rem; font-weight: 500;
  color: var(--petrol); background: none;
  border: 0; cursor: pointer;
  text-decoration: underline; text-underline-offset: 3px;
}

.map-legend {
  margin: 0; padding: 0.5rem var(--pad);
  font-size: 0.78rem; color: var(--slate);
  border-block-end: 1px solid var(--line);
}
.key {
  display: inline-block; width: 10px; height: 10px; border-radius: 50%;
  margin-inline-start: 0.6rem; vertical-align: middle;
}
.key-yes { background: var(--ok); }
.key-no { background: var(--bad); }
.key-single { background: var(--raise); box-shadow: 0 0 0 2px var(--ok); }
.key-none { background: var(--muted); opacity: 0.5; }
.leaflet-popup-content-wrapper, .leaflet-popup-tip { background: var(--raise); color: var(--ink); }

/* ============================================================================================
   Missing station
   ============================================================================================ */

/* A rare action sitting in prime position. It keeps its place (the map above it is what you
   look at to notice a gap) but not its weight - it had been the same size and underline as
   "show the map" directly above, so the two read as a pair of equals. */
.missing { padding: 0.1rem var(--pad); border-block-end: 1px solid var(--line); }
.missing > .link-btn { font-size: 0.78rem; color: var(--muted); }

.link-btn {
  min-height: 44px; padding: 0.3rem 0;
  font-family: inherit; font-size: 0.85rem; color: var(--slate);
  background: none; border: 0; cursor: pointer;
  text-decoration: underline; text-underline-offset: 3px;
}

.missing-panel { padding-block: 0.4rem 0.6rem; }
.missing-help { margin: 0 0 0.5rem; font-size: 0.83rem; color: var(--slate); }
.missing-msg { margin: 0.4rem 0 0; font-size: 0.83rem; color: var(--ember); }

/* States the chosen point back before anything is sent. A location the reporter never saw
   is a location nobody can trust. */
.missing-where {
  margin: 0.5rem 0; padding: 0.45rem 0.6rem;
  font-size: 0.83rem; color: var(--slate);
  background: var(--ghost); border-radius: var(--radius);
  unicode-bidi: isolate; font-variant-numeric: tabular-nums;
}

/* --- picking a point on the map --------------------------------------------------------- */

.map-holder { position: relative; }

/* Sits dead centre over the map; the confirm button reads the map's centre, so what the
   crosshair covers is exactly what gets submitted. */
.map-crosshair {
  position: absolute; inset-block-start: 50%; inset-inline-start: 50%;
  width: 24px; height: 24px; margin: -12px 0 0 -12px;
  transform: translateX(50%);
  border: 3px solid var(--ink); border-radius: 50%;
  box-shadow: 0 0 0 2px var(--surface), 0 1px 6px rgba(0, 0, 0, 0.35);
  pointer-events: none; z-index: 500;
}
.map-crosshair::after {
  content: ""; position: absolute; inset-block-start: 50%; inset-inline-start: 50%;
  width: 4px; height: 4px; margin: -2px 0 0 -2px;
  background: var(--ink); border-radius: 50%;
}

.map-pick-bar {
  display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap;
  padding: 0.6rem var(--pad);
  background: var(--banner-warn-bg); color: var(--banner-warn-fg);
  border-block-end: 1px solid var(--banner-warn-line);
}
.map-pick-help { flex: 1; min-width: 12ch; font-size: 0.85rem; font-weight: 500; }
.map-pick-bar .link-btn { color: inherit; }

.inline-form { display: flex; gap: 0.5rem; }

.inline-input {
  flex: 1; min-width: 0; min-height: 44px; padding-inline: 0.7rem;
  font-family: inherit; font-size: 0.9rem;
  background: var(--raise); border: 1px solid var(--line);
  border-radius: var(--radius); color: var(--ink);
}

.inline-send {
  flex-shrink: 0; min-height: 44px; padding-inline: 1rem;
  font-family: inherit; font-size: 0.85rem; font-weight: 500;
  background: var(--ink); color: var(--surface);
  border: 0; border-radius: var(--radius); cursor: pointer;
}
.inline-send:disabled { opacity: 0.55; cursor: default; }

/* ============================================================================================
   List
   ============================================================================================ */

.sheet { background: var(--surface); }

.sheet-title {
  margin: 0; padding: 0.85rem var(--pad) 0.4rem;
  font-size: 0.78rem; font-weight: 600; letter-spacing: 0.08em; color: var(--slate);
}

#station-list { list-style: none; margin: 0; padding: 0; }

.empty-note { padding: 1.5rem var(--pad); color: var(--slate); font-size: 0.94rem; }

/* The launch-day screen. Petrol-tinted rather than grey so it reads as an invitation the app
   is making, not an error it is reporting. */
.invite {
  margin: 0.75rem var(--pad) 0.25rem;
  padding: 0.85rem 0.95rem;
  background: var(--petrol-soft);
  border: 1px solid color-mix(in srgb, var(--petrol) 22%, transparent);
  border-radius: var(--radius);
  font-size: 0.9rem; line-height: 1.65;
}
.invite-title { display: block; color: var(--petrol); font-weight: 600; }
.invite-body { display: block; color: var(--ink); }

.station-row { border-block-end: 1px solid var(--line); }

/* The row itself never carries a status class. Its two fuels are independent and it has no
   combined state; only the badge inside it is ever coloured. */
.station-row.expanded { background: var(--raise); }

/* Marks the row whose map pin is currently open. A tint alone would be lost against the
   expanded state, so the edge marker does the work - and it is the only thing tying a pin to
   a row now that tapping a pin no longer scrolls the page. Never a status colour: the row has
   two independent fuels and no combined state. */
.station-row.highlighted {
  background: var(--ghost);
  box-shadow: inset 3px 0 0 0 var(--ink);
}
:root[dir="rtl"] .station-row.highlighted,
html[dir="rtl"] .station-row.highlighted {
  box-shadow: inset -3px 0 0 0 var(--ink);
}

.station-head { display: flex; align-items: stretch; }

/* Tapping the body expands the report buttons; the chevron opens the history page. Two
   targets, two outcomes. */
.station-body {
  flex: 1; min-width: 0;
  display: flex; align-items: center; justify-content: space-between; gap: 0.75rem;
  padding: 0.8rem var(--pad);
  font-family: inherit; text-align: start;
  background: none; border: 0; color: inherit; cursor: pointer;
}

.station-id { min-width: 0; }

.station-name {
  display: block; font-size: 1rem; font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Usually the only thing telling two "محطة وقود" apart: 65% of Libyan stations have no name
   of their own. Quiet, but load-bearing. */
.station-meta {
  display: block; font-size: 0.82rem; color: var(--slate);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.station-chevron {
  flex-shrink: 0; width: 44px;
  font-family: inherit; font-size: 1.05rem; line-height: 1;
  color: var(--muted); background: none; border: 0;
  border-inline-start: 1px solid var(--line); cursor: pointer;
}
.station-chevron:hover { color: var(--ink); }

/* ============================================================================================
   The badge - the answer
   ============================================================================================ */

/* Mark + words travel together. The mark is scannable at a glance down a long list; the words
   are what make it unambiguous. Neither is load-bearing alone. */
.station-status { flex-shrink: 0; display: flex; align-items: center; gap: 0.5rem; }

/* The same pin as the masthead, at row scale. Colour comes from the state class via
   currentColor, so the shape rules never repeat a hue. */
.row-mark { inline-size: 28px; block-size: 28px; flex-shrink: 0; display: block; }
.row-mark .pin-track { fill: var(--slate-soft); }
.row-mark .pin-fill  { fill: currentColor; }
.row-mark .pin-edge  { stroke: currentColor; stroke-width: 5; }

.row-mark.state-yes,
.row-mark.state-single_yes { color: var(--ok); }
.row-mark.state-no,
.row-mark.state-single_no  { color: var(--bad); }
.row-mark.state-none       { color: var(--muted); }

/* Dashed edge = one source. Same rule as the badge, so the two never disagree. */
.row-mark.state-single_yes .pin-edge,
.row-mark.state-single_no .pin-edge { stroke-dasharray: 7 5; }

/* One report reads as a pale pin, not a solid one. Lightness carries the difference from
   "متوفر" independently of hue, which matters on the one screen where hue is least reliable. */
.row-mark.state-single_yes .pin-fill { fill-opacity: 0.32; }

/* Nothing to say: a visibly empty vessel, not an alarm. Drawn at full opacity - ghosted back
   any further and it stopped reading as a deliberate element and started reading as a smudge. */
.row-mark.state-none .pin-edge { stroke-width: 4.5; }

.badge {
  flex-shrink: 0;
  display: inline-flex; align-items: center;
  padding: 0.32rem 0.7rem;
  border-radius: 999px;
  font-size: 0.85rem; font-weight: 600;
  border: 1px solid transparent; white-space: nowrap;
}

/* Confirmed: solid fill. */
.badge.state-yes { background: var(--ok); color: #fff; }
.badge.state-no { background: var(--bad); color: #fff; }

/* A single report is information, not agreement. Dashed says so before the words do, and
   keeps saying it on a screen where colour has washed out. */
.badge.state-single_yes,
.badge.state-single_no {
  background: transparent; border-style: dashed; font-weight: 500;
}
.badge.state-single_yes { color: var(--ok); border-color: color-mix(in srgb, var(--ok) 60%, transparent); }
.badge.state-single_no { color: var(--bad); border-color: color-mix(in srgb, var(--bad) 60%, transparent); }

/* Nothing recent enough to say anything. Ghosted, never alarming. */
.badge.state-none { background: var(--ghost); color: var(--muted); font-weight: 500; }

/* ============================================================================================
   Report controls
   ============================================================================================ */

.report-controls { padding: 0 var(--pad) 0.9rem; }

/* The cooldown receipt. Sits where the button pair was, at the same height so nothing jumps.
   Quiet on purpose - it confirms and then gets out of the way; the person has reported and is
   driving. It carries no countdown: the buttons come back on their own. */
.reported-note {
  margin: 0;
  min-height: 48px;
  display: flex; align-items: center;
  font-size: 0.9rem; font-weight: 500; color: var(--slate);
}
.reported-note.state-yes { color: var(--ok); }
.reported-note.state-no { color: var(--bad); }

.button-pair { display: flex; gap: 0.5rem; }

.report-btn {
  flex: 1; min-height: 48px; padding: 0.4rem 0.5rem;
  font-family: inherit; font-size: 0.92rem; font-weight: 600;
  background: var(--raise); border: 1px solid var(--line);
  border-radius: var(--radius); color: var(--ink); cursor: pointer;
}

.report-btn.positive { border-color: color-mix(in srgb, var(--petrol) 55%, transparent); color: var(--petrol); }
.report-btn.negative { border-color: color-mix(in srgb, var(--slate) 55%, transparent); color: var(--slate); }
.report-btn:disabled { opacity: 0.55; cursor: default; }

.row-extras { margin-block-start: 0.4rem; }
.row-message { margin-block-start: 0.5rem; font-size: 0.84rem; color: var(--ember); }

/* The "and the other fuel?" prompt. They are standing at the pump; it costs one tap and is
   where most diesel coverage will come from. */
.cross-prompt {
  margin-block-start: 0.7rem; padding: 0.7rem;
  background: var(--petrol-soft); border-radius: var(--radius);
}
.cross-q { font-size: 0.9rem; font-weight: 600; margin-block-end: 0.5rem; }
.cross-prompt .link-btn { display: block; margin-block-start: 0.3rem; }

/* ============================================================================================
   Detail page
   ============================================================================================ */

.detail { padding: 1rem var(--pad) 2rem; max-width: 46rem; margin-inline: auto; }

.back-link {
  display: inline-block; min-height: 44px; line-height: 44px;
  color: var(--slate); text-decoration: none; font-size: 0.9rem;
}

.detail-name { margin: 0.2rem 0 0.2rem; font-size: 1.3rem; }
.detail-sub { margin: 0 0 1.2rem; color: var(--slate); font-size: 0.9rem; }

.detail-block {
  padding: 0.9rem; margin-block-end: 0.9rem;
  background: var(--raise); border: 1px solid var(--line); border-radius: var(--radius);
}

.detail-block-head {
  display: flex; align-items: center; justify-content: space-between; gap: 0.75rem;
}
.detail-cat { font-size: 1rem; font-weight: 700; }
.detail-age { margin: 0.5rem 0 0; font-size: 0.82rem; color: var(--muted); }

.chart { margin-block-start: 0.9rem; }
.chart-title { font-size: 0.78rem; color: var(--slate); margin-block-end: 0.4rem; }
.chart-empty { margin: 0; font-size: 0.86rem; color: var(--muted); }

/* 24 hourly bars, newest at the RTL start edge. */
.chart-bars { display: flex; gap: 2px; height: 46px; align-items: stretch; }
.chart-bar { flex: 1; border-radius: 2px; background: var(--ghost); }
.chart-bar.state-yes { background: var(--ok); }
.chart-bar.state-no { background: var(--bad); }
.chart-bar.state-none { background: var(--ghost); }

.chart-legend {
  display: flex; flex-wrap: wrap; gap: 0.75rem;
  margin-block-start: 0.5rem; font-size: 0.76rem; color: var(--slate);
}
.legend-item { display: inline-flex; align-items: center; gap: 0.3rem; }
.legend-swatch { width: 10px; height: 10px; border-radius: 2px; background: var(--ghost); }
.legend-swatch.state-yes { background: var(--ok); }
.legend-swatch.state-no { background: var(--bad); }

/* Navigation hand-off: one button, the phone chooses the app. */
.nav-btn {
  display: block; text-align: center;
  min-height: 48px; line-height: 48px;
  margin-block-end: 0.6rem;
  font-size: 0.95rem; font-weight: 600;
  color: var(--surface); background: var(--ink);
  border-radius: var(--radius); text-decoration: none;
}

.nav-btn.compact {
  flex: 1; margin: 0;
  min-height: 40px; line-height: 40px; font-size: 0.85rem;
}

.detail > .nav-btn { margin-block: 0.6rem 1.2rem; }

/* ============================================================================================
   About
   ============================================================================================ */

.about { padding: 1.2rem var(--pad) 2rem; max-width: 46rem; margin-inline: auto; }
.about h2 { font-size: 1.05rem; margin: 1.4rem 0 0.4rem; }
.about h2:first-child { margin-top: 0; }
.about p { margin: 0 0 0.7rem; font-size: 0.94rem; }
.about a { color: var(--petrol); }

.about-warn {
  padding: 0.7rem 0.85rem; border-inline-start: 3px solid var(--ember);
  background: var(--banner-warn-bg); color: var(--banner-warn-fg);
  border-radius: 0 var(--radius) var(--radius) 0;
}

.about-list { margin: 0; padding-inline-start: 1.1rem; font-size: 0.94rem; }
.about-list li { margin-block-end: 0.55rem; }

/* ============================================================================================
   Colophon
   ============================================================================================ */

.colophon { padding: 1.2rem var(--pad) 2.5rem; font-size: 0.8rem; color: var(--muted); }
.colophon p { margin: 0 0 0.5rem; }
/* inline-flex + min-height rather than padding: this is the only route to the about page, and
   it had been a 19px-tall target. */
.footer-link { display: inline-flex; align-items: center; min-height: 44px; color: var(--slate); }
.footer-link.active { color: var(--petrol); font-weight: 600; }

/* ============================================================================================
   Self-test output
   ============================================================================================ */

.selftest {
  margin: 0.5rem; padding: 0.6rem;
  background: #0B0E10; color: #7BE0A0;
  font-size: 0.72rem; font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  white-space: pre-wrap; overflow-x: auto; direction: ltr; text-align: left;
}

/* ============================================================================================
   Motion
   ============================================================================================ */

@media (prefers-reduced-motion: no-preference) {
  .station-row { animation: row-in 380ms cubic-bezier(0.2, 0.8, 0.2, 1) both; }
  .station-row:nth-child(1) { animation-delay: 0ms; }
  .station-row:nth-child(2) { animation-delay: 35ms; }
  .station-row:nth-child(3) { animation-delay: 70ms; }
  .station-row:nth-child(4) { animation-delay: 105ms; }
  .station-row:nth-child(5) { animation-delay: 140ms; }
  .station-row:nth-child(n + 6) { animation-delay: 175ms; }
}

@keyframes row-in {
  from { opacity: 0; transform: translateY(5px); }
  to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .station-row { animation: none; }
}

/* ============================================================================================
   Wider screens
   ============================================================================================ */

@media (min-width: 720px) {
  .masthead, .note, .banner, .strap, .view-switch, .missing { padding-inline: 2rem; }
  #map { height: 46vh; }
  .sheet, .colophon { max-width: 760px; margin-inline: auto; }
}
