/* ===========================================================================
   styles.css — dark, high-contrast, thumb-friendly.
   Designed to be readable in a car: big numbers, large touch targets, and a
   colour scheme that does not blind you at night.
   ======================================================================== */

/* ===========================================================================
   DESIGN TOKENS — a night instrument, not a dark theme

   This app is read in a car, after dark, usually at the moment you have
   started to worry about making it. Three decisions follow from that, and
   everything else in the stylesheet follows from these three.

   1. THE GROUND IS WARM.
      Instrument lighting in a car is amber and deliberately low in blue,
      because blue light is what destroys your dark adaptation. So the ground
      here has brown in it rather than the blue-black that every dark-mode
      interface reaches for, and the illumination is amber.

   2. NOTHING GLOWS TO SAY YOU ARE FINE.
      A real instrument panel lights up when something needs you and stays
      dark when it does not — there is no green lamp for "the engine is
      working". So "you make it" is simply bone white, unlit. Amber means you
      are into the reserve you promised yourself. Red means you do not get
      there. Colour on this screen is always an exception.

      The previous palette painted the happy state a bright green, which is
      both the convention and the reason the app looked like every other dark
      app: a near-black ground under one saturated accent.

   3. THE TYPE IS DIN.
      The road-sign and engineering standard, and the native lettering of this
      subject. It ships on every platform this app runs on under a different
      name, so it costs nothing and works offline: Bahnschrift on Windows,
      DIN Alternate on iOS, Roboto Condensed on Android. Condensed numerals
      are also the functionally correct choice — more digits, larger, in the
      same width, which is the constraint every instrument cluster has.
   ======================================================================== */

:root {
  /* ---- Ground ----------------------------------------------------------- */
  --ink:      #14110d;   /* the binnacle */
  --panel:    #1e1a15;   /* an instrument face */
  --panel-2:  #2a241c;   /* raised control */
  --well:     #100e0a;   /* inset: inputs, tracks */
  --rule:     #392f24;
  --rule-2:   #292219;

  /* ---- Illumination ----------------------------------------------------- */
  --bone:      #f4ecdc;  /* primary readouts */
  --bone-dim:  #b0a591;  /* secondary text */
  --bone-mute: #8d8271;  /* labels, captions */

  --amber:     #ffae1a;  /* the instrument lamp: live, selected, caution */
  --amber-dim: rgba(255,174,26,.14);
  --alarm:     #ff5646;  /* reserved: you do not get there */
  --alarm-dim: rgba(255,86,70,.15);

  /* Aliases kept so the map and search modules, which speak in these names,
     do not need rewriting to follow the palette. */
  --bg:        var(--ink);
  --bg-card:   var(--panel);
  --bg-raise:  var(--panel-2);
  --bg-input:  var(--well);
  --line:      var(--rule);
  --line-soft: var(--rule-2);
  --text:      var(--bone);
  --text-dim:  var(--bone-dim);
  --text-mute: var(--bone-mute);
  --ok:        var(--bone);
  --warn:      var(--amber);
  --danger:    var(--alarm);
  --ok-dim:    rgba(244,236,220,.08);
  --warn-dim:  var(--amber-dim);
  --danger-dim: var(--alarm-dim);
  --accent:    var(--amber);
  --accent-dk: #d68f0f;

  /* ---- Energy breakdown -------------------------------------------------
     Four categories in one stacked bar, so ADJACENT separation is what
     matters. Re-stepped for the warm ground and revalidated: every slot
     inside the dark lightness band, above the chroma floor, above 3:1
     contrast, worst adjacent pair well clear of both CVD and normal-vision
     floors. The amber is deliberately NOT among them — that hue belongs to
     the instrument lamp and must not turn up as a data category. */
  --k-aero:  #4d90e0;
  --k-roll:  #e2673a;
  --k-grade: #9080e0;
  --k-aux:   #23a173;

  /* ---- Type -------------------------------------------------------------
     Two roles, and the split is strict. The data face carries every number,
     label, heading and control — anything you read at a glance. The text
     face carries prose, because condensed type is not what you want for a
     sentence you actually have to read. */
  --face-data: Bahnschrift, "DIN Alternate", "DIN Condensed", "Roboto Condensed",
               "Avenir Next Condensed", "Arial Narrow", "Segoe UI", system-ui, sans-serif;
  --face-text: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;

  /* ---- Geometry ---------------------------------------------------------
     Instruments are not pill-shaped. The radius drops to something closer to
     a machined bezel than a rounded card, and steps rather than repeating. */
  --radius:    10px;
  --radius-md: 7px;
  --radius-sm: 5px;

  --ease: cubic-bezier(.4, 0, .2, 1);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--face-text);
  -webkit-text-size-adjust: 100%;
}

body {
  /* Respect the notch / home indicator on phones. */
  padding: env(safe-area-inset-top) env(safe-area-inset-right)
           env(safe-area-inset-bottom) env(safe-area-inset-left);
}

/* ---- Screen switching ---------------------------------------------------- */
.screen { display: none; max-width: 560px; margin: 0 auto; padding: 16px 16px 40px; }
.screen.active { display: block; }

/* ---- Header --------------------------------------------------------------
   The mark is a battery cell with a bolt, drawn in the same stroke weight as
   the interface icons so it belongs to them rather than sitting on top. The
   wordmark is set in the data face at a width that matches it. */
.app-header { padding: 20px 2px 6px; }
.wordmark { display: flex; align-items: center; gap: 10px; }
.wordmark-mark {
  width: 25px; height: 25px; flex: none;
  fill: none; stroke: var(--bone); stroke-width: 1.7; stroke-linejoin: round;
}
.wordmark-mark .bolt { fill: var(--amber); stroke: var(--amber); stroke-width: 1.1; }
.app-header h1 {
  margin: 0;
  font: 700 25px/1 var(--face-data);
  letter-spacing: .005em;
  text-transform: uppercase;
  color: var(--bone);
}
.tagline {
  margin: 9px 0 0 35px;
  font: 400 12.5px/1.45 var(--face-text);
  color: var(--bone-mute);
  max-width: 32ch;
}

/* ---- Cards ---------------------------------------------------------------
   Quieter than the panel above them, and deliberately so: these are the
   controls, not the answer. Flat, hairline-bordered, no lift. */
.card {
  background: var(--panel);
  border: 1px solid var(--rule-2);
  border-radius: var(--radius);
  padding: 15px;
  margin: 11px 0;
}
.card.compact { padding: 13px; margin: 9px 0; }
.card h2 {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 0 14px;
  font: 600 11px/1 var(--face-data);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--bone-mute);
  white-space: nowrap;
}
.card h2::after { content: ''; flex: 1; height: 1px; background: var(--rule-2); }
.card-head { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; }
.card-head h2 { flex: 1; margin: 0; min-width: 0; }
.card-note {
  flex: none;
  font: 500 11px/1 var(--face-data);
  letter-spacing: .04em;
  color: var(--bone-mute);
  font-variant-numeric: tabular-nums;
}
.card-note:empty { display: none; }
.card h3 { margin: 0 0 6px; font: 600 14.5px/1.2 var(--face-data); }
.sub-head {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 0 10px;
  font: 600 10.5px/1 var(--face-data);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--bone-mute);
  white-space: nowrap;
}
.sub-head i { flex: 1; height: 1px; background: var(--rule-2); }
.sub-head em {
  font-style: normal;
  text-transform: none;   /* a unit is written Wh/km, never WH/KM */
  letter-spacing: .02em;
  font-size: 11px;
}

/* ---- Form fields --------------------------------------------------------- */
.field { display: block; margin-bottom: 16px; }
.field:last-child { margin-bottom: 0; }
.field > span,
.field-label {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  font-size: 14px;
  font-weight: 600;
  margin-bottom: 7px;
}
.field em, .field-label em { color: var(--text-dim); font-style: normal; font-weight: 400; }
/* A slider's readout is a VALUE, not a state. It used to be accent green,
   which put the app's one meaningful colour on a dozen numbers that mean
   nothing in particular — and left the colour with nothing to say when it
   appeared on something that did. */
output {
  font: 700 14px/1 var(--face-data);
  letter-spacing: .01em;
  color: var(--bone);
  font-variant-numeric: tabular-nums;
}

input[type="number"], select {
  width: 100%;
  padding: 12px 12px;
  font-size: 16px;               /* 16px stops iOS zooming on focus */
  color: var(--text);
  background: var(--bg-input);
  border: 1px solid var(--line);
  border-radius: 11px;
  appearance: none;
}
select {
  background-image: linear-gradient(45deg, transparent 50%, var(--text-dim) 50%),
                    linear-gradient(135deg, var(--text-dim) 50%, transparent 50%);
  background-position: calc(100% - 19px) 50%, calc(100% - 14px) 50%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  padding-right: 36px;
}
input:focus-visible, select:focus-visible, button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Range sliders — deliberately chunky so they work with a thumb. */
input[type="range"] {
  width: 100%;
  height: 34px;
  background: transparent;
  appearance: none;
  margin: 0;
}
input[type="range"]::-webkit-slider-runnable-track {
  height: 6px; border-radius: 3px; background: var(--bg-input); border: 1px solid var(--line);
}
input[type="range"]::-webkit-slider-thumb {
  appearance: none; width: 26px; height: 26px; margin-top: -11px;
  border-radius: 50%; background: var(--amber); border: 3px solid var(--panel);
  box-shadow: 0 2px 8px rgba(0,0,0,.5);
}
input[type="range"]::-moz-range-track {
  height: 6px; border-radius: 3px; background: var(--bg-input); border: 1px solid var(--line);
}
input[type="range"]::-moz-range-thumb {
  width: 22px; height: 22px; border-radius: 50%;
  background: var(--amber); border: 3px solid var(--panel);
}

.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.hint {
  display: block;
  margin-top: 6px;
  font: 400 12px/1.45 var(--face-text);
  color: var(--bone-mute);
}
.hint.center { text-align: center; }

.check { display: flex; align-items: center; gap: 10px; font-size: 14px; margin-top: 10px; }
.check input { width: 20px; height: 20px; accent-color: var(--accent); }

.custom-fields {
  border: 1px dashed var(--line);
  border-radius: 12px;
  padding: 14px;
  margin: 0 0 16px;
  background: rgba(255,255,255,.02);
}
.hidden { display: none !important; }

/* ---- Segmented control (climate level, trip mode) ------------------------ */
.segmented {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 5px;
  background: var(--bg-input);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  padding: 5px;
}
.segmented button {
  min-height: 44px;
  padding: 12px 4px;
  font: 600 13.5px/1 var(--face-data);
  letter-spacing: .04em;
  color: var(--bone-dim);
  background: transparent;
  border: 0;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background .15s var(--ease), color .15s var(--ease);
}
.segmented button:hover { color: var(--text); }
/* Selected, not shouting. A solid white pill here competed with the primary
   button and with the white slider thumbs; three different things claiming to
   be the loudest element is how a screen loses its hierarchy. */
.segmented button.on {
  background: var(--amber-dim);
  color: var(--amber);
  box-shadow: inset 0 0 0 1px rgba(255,174,26,.42);
}

/* The climate control carries a price on every option, not just the chosen
   one — see paintClimateCosts(). Four numbers side by side are what make the
   setting legible; one number would only ever confirm what you just tapped. */
.segmented.costed button {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  padding: 9px 2px 8px;
  line-height: 1.1;
}
.segmented.costed b { font: 600 13px/1 var(--face-data); letter-spacing: .04em; }
.segmented.costed em {
  font: 600 11px/1 var(--face-data);
  font-style: normal;
  letter-spacing: .02em;
  color: var(--bone-mute);
  font-variant-numeric: tabular-nums;
}
.segmented.costed button.on em { color: var(--amber); opacity: .8; }

/* ---- Buttons -------------------------------------------------------------
   The primary action is near-white rather than green. In an app whose job is
   telling you whether you are safe, a green button competes with a green
   verdict for the same meaning — so the button gives the colour up. */
button.primary {
  display: block;
  width: 100%;
  margin-top: 18px;
  padding: 16px;
  font: 700 15.5px/1 var(--face-data);
  letter-spacing: .09em;
  text-transform: uppercase;
  color: #17120a;
  background: var(--amber);
  border: 0;
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: transform .12s var(--ease), background .15s var(--ease);
}
button.primary:hover { background: #ffbe45; }
button.primary:active { background: var(--accent-dk); transform: scale(.988); }
/* The compact primary sits beside another button in a split row, so it gets
   a tighter setting — at the full uppercase tracking "Start navigation" broke
   across two lines in half the width. */
button.primary.compact {
  margin-top: 0;
  padding: 14px 12px;
  font-size: 13.5px;
  letter-spacing: .05em;
}

button.secondary {
  padding: 12px 20px;
  font-size: 15px;
  font-weight: 600;
  color: var(--text);
  background: var(--bg-raise);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  cursor: pointer;
}
button.secondary:hover { border-color: #453a2c; }
button.ghost {
  padding: 8px 12px;
  font-size: 15px;
  color: var(--text-dim);
  background: transparent;
  border: 0;
  cursor: pointer;
}

/* ===========================================================================
   THE INSTRUMENT PANEL
   ======================================================================== */

.panel {
  position: relative;
  margin: 14px 0 22px;
  padding: 0 15px 16px;
  background: var(--panel);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  /* The lamp behind the glass. It is warm and it comes from the top, the way
     a binnacle is lit — not a coloured halo behind a card. */
  box-shadow:
    inset 0 60px 90px -70px rgba(255,174,26,.22),
    inset 0 1px 0 rgba(255,236,205,.05),
    0 24px 48px -34px #000;
}


/* The rail: a label, a hairline, and the trip it belongs to. This is the
   panel's only chrome, and it exists to say what you are looking at. */
.panel-rail {
  display: flex;
  align-items: center;
  gap: 11px;
  margin: 0 -15px;
  padding: 13px 15px 12px;
  border-bottom: 1px solid var(--rule-2);
}
.panel-eyebrow {
  font: 600 11px/1 var(--face-data);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--amber);
  white-space: nowrap;
}
.panel-rail::after { content: ''; flex: 1; height: 1px; background: var(--rule-2); order: 1; }
.panel-trip {
  order: 2;
  font: 500 11.5px/1 var(--face-data);
  letter-spacing: .04em;
  color: var(--bone-mute);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* ---- The descent plot ----------------------------------------------------
   The signature. Charge on the vertical, distance on the horizontal, so the
   line falls the way the battery does. What it shows that a percentage
   cannot: the RATE, where you cross into your reserve, and — as a second,
   dimmer line — what easing off would buy you.

   It is drawn with no fill under the curve and no gradient. A plot on an
   instrument is ink on a face; the moment it gets a soft coloured wash it
   stops looking measured and starts looking decorative. */
.plot { margin: 0 -15px; padding: 18px 15px 0; }
.plot-frame { position: relative; }
#pPlot {
  display: block;
  width: 100%;
  height: 156px;
  overflow: visible;
}
#pPlot line, #pPlot path, #pPlot circle, #pPlot rect { vector-effect: non-scaling-stroke; }

/* The reserve: charge you have already promised yourself you will not spend,
   hatched rather than filled so it reads as out of bounds. */
.plot-reserve { fill: url(#hatch); stroke: none; opacity: .5; }
#hatch line { stroke: var(--bone-mute); stroke-width: 1; }
.plot-reserve-edge { stroke: var(--bone-mute); stroke-width: 1; stroke-dasharray: 1 4; opacity: .8; }

.plot-grid line { stroke: var(--rule-2); stroke-width: 1; }

.plot-line {
  fill: none;
  stroke: var(--bone);
  stroke-width: 2.5;
  stroke-linecap: round;
}
.panel.tight .plot-line { stroke: var(--amber); }
.panel.bad   .plot-line { stroke: var(--alarm); }

/* The counterfactual. Dashed and dim: it is not what is happening. */
.plot-ghost {
  fill: none;
  stroke: var(--bone-mute);
  stroke-width: 1.5;
  stroke-dasharray: 5 4;
  stroke-linecap: round;
  opacity: .75;
}

.plot-dest { stroke: var(--amber); stroke-width: 1.5; opacity: .75; }
.plot-dot {
  fill: var(--bone);
  stroke: var(--panel);
  stroke-width: 3;
}
.panel.tight .plot-dot { fill: var(--amber); }
.panel.bad   .plot-dot { fill: var(--alarm); }
.plot-dot.hidden { display: none !important; }

/* The two readouts sit in their own strip ABOVE the plot.
   They were inside it, and there is no safe place in there: the line sweeps
   corner to corner, so any spot that is clear at one charge level is under
   the curve at another. The arrival figure is still positioned at the
   destination's x, so it points at the rule below it without ever touching
   the line. */
.plot-heads { position: relative; height: 40px; margin-bottom: 2px; }
.plot-head {
  position: absolute;
  bottom: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  white-space: nowrap;
  pointer-events: none;
}
.plot-head b {
  font: 700 15px/1 var(--face-data);
  letter-spacing: .01em;
  font-variant-numeric: tabular-nums;
  color: var(--bone-dim);
}
.plot-head small {
  font: 500 9px/1 var(--face-data);
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--bone-mute);
}
.plot-head.now { left: 0; }
.plot-head.arrival { align-items: center; transform: translateX(-50%); }
.plot-head.arrival b { font-size: 27px; color: var(--bone); }
.panel.tight .plot-head.arrival b { color: var(--amber); }
.panel.bad   .plot-head.arrival b { color: var(--alarm); }
.plot-head.arrival.edge-right { align-items: flex-end; transform: translateX(-100%); }

.plot-axis {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin: 9px 0 0;
  font: 500 11px/1 var(--face-data);
  letter-spacing: .05em;
  color: var(--bone-mute);
  font-variant-numeric: tabular-nums;
}
.plot-ghost-key { display: inline-flex; align-items: center; gap: 6px; text-align: center; }
.plot-ghost-key::before {
  content: '';
  width: 16px;
  height: 0;
  border-top: 1.5px dashed var(--bone-mute);
  flex: none;
}
.plot-ghost-key:empty { display: none; }

/* ---- Verdict -------------------------------------------------------------
   Icon and words always, never colour alone — and here the "you make it"
   state carries no colour at all, so the words are doing the whole job. */
.verdict {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  margin: 16px 0 0;
  padding: 11px 12px;
  border-radius: var(--radius-sm);
  font: 400 13.5px/1.45 var(--face-text);
  border: 1px solid transparent;
}
.verdict > span { min-width: 0; }
.verdict::before {
  content: '';
  width: 16px;
  height: 16px;
  margin-top: 1px;
  flex: none;
  background: currentColor;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center;  mask-position: center;
  -webkit-mask-size: 100% 100%;   mask-size: 100% 100%;
}
.verdict.big { font-size: 15px; padding: 13px; margin: 12px 0; }
.verdict.ok {
  background: rgba(244,236,220,.045);
  color: var(--bone-dim);
  border-color: var(--rule);
}
.verdict.ok strong { color: var(--bone); }
.verdict.tight { background: var(--amber-dim); color: var(--amber); border-color: rgba(255,174,26,.3); }
.verdict.bad   { background: var(--alarm-dim); color: var(--alarm); border-color: rgba(255,86,70,.34); }
.verdict.ok::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6.5 9.2 17.3 4 12.1'/%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6.5 9.2 17.3 4 12.1'/%3E%3C/svg%3E");
}
.verdict.tight::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 3.2 1.6 20.8h20.4z'/%3E%3Cpath d='M12 9.4v4.4'/%3E%3Cpath d='M12 17.4h.01'/%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 3.2 1.6 20.8h20.4z'/%3E%3Cpath d='M12 9.4v4.4'/%3E%3Cpath d='M12 17.4h.01'/%3E%3C/svg%3E");
}
.verdict.bad::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2.2' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='9.2'/%3E%3Cpath d='M15.2 8.8 8.8 15.2M8.8 8.8l6.4 6.4'/%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2.2' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='9.2'/%3E%3Cpath d='M15.2 8.8 8.8 15.2M8.8 8.8l6.4 6.4'/%3E%3C/svg%3E");
}

/* ---- Readout row ---------------------------------------------------------
   Five figures under one rule, divided by hairlines. Deliberately NOT four
   equal boxes: this is a strip of gauges, and gauges sit in a row sharing a
   baseline, not in cards. */
.readout {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 14px 0;
  margin-top: 17px;
  padding-top: 13px;
  border-top: 1px solid var(--rule-2);
}
.stat { position: relative; padding-right: 5px; min-width: 0; }
.stat + .stat { padding-left: 8px; }
.stat + .stat::before {
  content: '';
  position: absolute;
  left: 0; top: 1px; bottom: 3px;
  width: 1px;
  background: var(--rule-2);
}
/* In the two-column layout the divider belongs between the pair, not before
   every cell — cells 1 and 3 start a row and must not carry a left rule. */
.readout > .stat:nth-child(odd) { padding-left: 0; }
.readout > .stat:nth-child(odd)::before { display: none; }

@media (min-width: 420px) {
  .readout { grid-template-columns: repeat(4, 1fr); gap: 0; }
  .readout > .stat:nth-child(odd) { padding-left: 8px; }
  .readout > .stat:nth-child(odd)::before { display: block; }
  .readout > .stat:first-child { padding-left: 0; }
  .readout > .stat:first-child::before { display: none; }
  .stat span { font-size: 18px; }
}
/* nowrap on both lines: at 375px a four-column strip has about 64px per
   figure, and "2h 46m" breaking across two lines turned a readout into a
   paragraph. */
.stat span {
  display: block;
  font: 700 17px/1 var(--face-data);
  letter-spacing: 0;
  font-variant-numeric: tabular-nums;
  color: var(--bone);
  white-space: nowrap;
}
.stat label {
  display: block;
  margin-top: 5px;
  font: 500 9px/1.25 var(--face-data);
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--bone-mute);
  white-space: nowrap;
}
.stat-note {
  margin-top: 11px;
  font: 400 11.5px/1.45 var(--face-text);
  color: var(--bone-mute);
}
.stat-note:empty { display: none; }

/* ---- Energy breakdown ---------------------------------------------------- */
.breakdown { margin-top: 20px; }
.breakdown-bar {
  display: flex;
  gap: 2px;                     /* the surface gap between stacked segments */
  height: 9px;
  border-radius: 2px;
  background: var(--well);
  overflow: hidden;
}
.seg { height: 100%; transition: width .3s var(--ease); }
.seg-aero  { background: var(--k-aero); }
.seg-roll  { background: var(--k-roll); }
.seg-grade { background: var(--k-grade); }
.seg-aux   { background: var(--k-aux); }

.legend {
  list-style: none;
  margin: 12px 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px 18px;
  font: 400 12px/1.2 var(--face-text);
  color: var(--bone-dim);
}
.legend li { display: flex; align-items: center; gap: 8px; min-width: 0; }
.legend li > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.legend i { width: 8px; height: 8px; border-radius: 1px; flex: none; }
.legend b {
  margin-left: auto;
  color: var(--bone);
  font: 700 12.5px/1 var(--face-data);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.k-aero { background: var(--k-aero); } .k-roll { background: var(--k-roll); }
.k-grade { background: var(--k-grade); } .k-aux { background: var(--k-aux); }

/* ---- Advice -------------------------------------------------------------- */
.advice {
  margin-top: 16px;
  padding: 11px 0 0;
  border-top: 1px solid var(--rule-2);
  font: 400 13px/1.55 var(--face-text);
  color: var(--bone-dim);
}
.advice:empty { display: none; }
.advice strong { color: var(--bone); font-weight: 600; }

/* ---- Live screen --------------------------------------------------------- */
.live-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 6px 0 10px;
}
.gps-state { font-size: 12.5px; color: var(--text-dim); }
.gps-state.live { color: var(--accent); }
.gps-state.error { color: var(--danger); }

/* ---- Live hero -----------------------------------------------------------
   The countdown leads HERE, because once you are moving the question really
   has become "how long have I got?". On the setup screen the same figure is
   a stat, and arrival leads instead. */
.hero {
  text-align: center;
  padding: 26px 16px 24px;
  background: var(--panel);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  box-shadow:
    inset 0 52px 80px -66px rgba(255,174,26,.2),
    inset 0 1px 0 rgba(255,236,205,.05);
}
.hero-label {
  font: 600 11px/1 var(--face-data);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--bone-mute);
}
.hero-value {
  margin: 10px 0 5px;
  font: 700 58px/0.95 var(--face-data);
  letter-spacing: .005em;
  font-variant-numeric: tabular-nums;
  color: var(--bone);
}
.hero-clock { font: 500 12.5px/1 var(--face-data); letter-spacing: .04em; color: var(--bone-mute); }
.hero.warn .hero-value { color: var(--warn); }
.hero.bad  .hero-value { color: var(--danger); }
.hero.warn { box-shadow: inset 0 52px 80px -60px rgba(255,174,26,.34), inset 0 1px 0 rgba(255,236,205,.05); }
.hero.bad  { box-shadow: inset 0 52px 80px -60px rgba(255,86,70,.34), inset 0 1px 0 rgba(255,236,205,.05); }
/* Paused is not a countdown, so it does not get a countdown's colour. */
.hero.paused .hero-value { color: var(--bone-dim); }
.hero.paused { box-shadow: inset 0 1px 0 rgba(255,236,205,.04); }

.live-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin: 12px 0; }
.tile {
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  padding: 13px 8px 11px;
  text-align: center;
}
.tile-value {
  display: block;
  font: 700 23px/1 var(--face-data);
  letter-spacing: .005em;
  font-variant-numeric: tabular-nums;
  color: var(--bone);
}
.tile label {
  display: block;
  margin-top: 5px;
  font: 500 9.5px/1.2 var(--face-data);
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--bone-mute);
}

.calibrate-row { display: flex; gap: 9px; margin-top: 10px; }
.calibrate-row input { flex: 1; }

.trip-log { display: grid; grid-template-columns: 1fr 1fr; gap: 10px 14px; }
.trip-log > div { display: flex; justify-content: space-between; font-size: 13.5px; }
.trip-log span { color: var(--text-dim); }
.trip-log b { font-variant-numeric: tabular-nums; }

.disclaimer {
  text-align: center; font-size: 11.5px; color: var(--text-dim);
  margin-top: 22px; line-height: 1.5; opacity: .8;
}

/* ---- Search fields ------------------------------------------------------- */
.searchbox { position: relative; }

/* One consistent input shell, used by the car picker and both place pickers:
   an optional leading icon, the input itself, then trailing action buttons. */
.search-field {
  display: flex;
  align-items: center;
  gap: 2px;
  background: var(--bg-input);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding-right: 4px;
  transition: border-color .15s, box-shadow .15s, background .15s;
}
.search-field:focus-within {
  border-color: var(--accent);
  background: #17130d;
  box-shadow: 0 0 0 3px rgba(255,174,26,.14);
}
.search-field input {
  flex: 1;
  min-width: 0;
  min-height: 48px;
  padding: 12px 6px 12px 14px;
  font-size: 16px;              /* 16px stops iOS zooming the page on focus */
  color: var(--text);
  background: transparent;
  border: 0;
  border-radius: 12px;
}
.search-field input:focus { outline: none; }
.search-field input::placeholder { color: var(--text-dim); }
.search-field:has(.field-icon) input { padding-left: 4px; }

/* Icons are stroked rather than filled, so one rule styles every glyph. */
.field-icon {
  width: 19px; height: 19px; flex: none;
  margin-left: 13px;
  fill: none; stroke: var(--text-dim); stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
}
.field-action {
  width: 40px; height: 40px; flex: none;
  display: grid; place-items: center;
  background: transparent; border: 0; border-radius: 10px; cursor: pointer;
}
.field-action svg {
  width: 18px; height: 18px;
  fill: none; stroke: var(--text-dim); stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
}
.field-action:hover svg { stroke: var(--text); }
.field-action:active { background: var(--bg-raise); }
#useMyLocation svg { stroke: var(--accent); }

/* ---- Suggestion lists ---------------------------------------------------- */
.suggestions {
  list-style: none;
  margin: 6px 0 0;
  padding: 5px;
  background: var(--bg-raise);
  border: 1px solid var(--line);
  border-radius: 13px;
  max-height: 300px;
  overflow-y: auto;
  /* Absolute so an open list overlays the map instead of shoving it down the
     page; z-index clears Leaflet's own stacking context. */
  position: absolute;
  left: 0; right: 0;
  z-index: 1200;
  box-shadow: 0 14px 40px rgba(0,0,0,.55);
}
.suggestions li {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 10px 11px;
  border-radius: 10px;
  font-size: 14.5px;
  line-height: 1.3;
  cursor: pointer;
}
.suggestions li:hover, .suggestions li.active { background: rgba(255,174,26,.13); }
.suggestions li.active { box-shadow: inset 0 0 0 1px rgba(255,174,26,.35); }

.sg-icon {
  width: 32px; height: 32px; flex: none;
  display: grid; place-items: center;
  background: var(--bg-input);
  border: 1px solid var(--line);
  border-radius: 9px;
}
.sg-icon svg {
  width: 16px; height: 16px;
  fill: none; stroke: var(--text-dim); stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
}
.suggestions li.active .sg-icon svg,
.suggestions li:hover .sg-icon svg { stroke: var(--accent); }

.sg-text { flex: 1; min-width: 0; }
.sg-title {
  display: block; font-weight: 600;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.sg-sub {
  display: block; font-size: 12px; color: var(--text-dim); margin-top: 2px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.sg-dist {
  flex: none; font-size: 11.5px; color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}
.suggestions li.empty, .suggestions li.loading {
  color: var(--text-dim); cursor: default; justify-content: center; padding: 14px;
}
.suggestions li.empty:hover, .suggestions li.loading:hover { background: transparent; }

/* ---- Selected car chip --------------------------------------------------- */
.selected-chip {
  display: flex; align-items: center; gap: 11px;
  padding: 10px 10px 10px 13px;
  background: var(--bg-raise);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  font-size: 15px; font-weight: 600;
}
.selected-chip .chip-icon {
  width: 22px; height: 22px; flex: none;
  fill: none; stroke: var(--text-dim); stroke-width: 1.7;
  stroke-linecap: round; stroke-linejoin: round;
}
.selected-chip span { flex: 1; min-width: 0; }
/* 44px minimum on every tap target — this app gets used in a moving car. */
.selected-chip button {
  min-height: 44px; padding: 6px 14px; flex: none;
  font-size: 12.5px; font-weight: 600;
  color: var(--text-dim); background: var(--bg-input);
  border: 1px solid var(--line); border-radius: 9px; cursor: pointer;
}
.selected-chip button:hover { color: var(--text); }

/* ---- "Searching near X" region chip -------------------------------------- */
.region-row {
  display: flex; align-items: center; gap: 9px;
  padding: 9px 9px 9px 12px;
  margin-bottom: 12px;
  background: var(--bg-input);
  border: 1px solid var(--line);
  border-radius: 11px;
  font-size: 13px;
}
.region-icon {
  width: 17px; height: 17px; flex: none;
  fill: none; stroke: var(--text-dim); stroke-width: 1.8;
  stroke-linecap: round; stroke-linejoin: round;
}
.region-text {
  flex: 1; min-width: 0; color: var(--text-dim);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.region-text b { color: var(--text); font-weight: 600; }
.region-row button {
  min-height: 40px; padding: 5px 12px; flex: none;
  font-size: 12px; font-weight: 600;
  color: var(--text); background: transparent;
  border: 1px solid var(--line); border-radius: var(--radius-sm); cursor: pointer;
}
.region-row button:hover { border-color: #4a3e2f; }
#regionEditor { margin-bottom: 12px; }

/* ---- Origin / destination pair ------------------------------------------- */
.route-inputs {
  display: grid;
  grid-template-columns: 18px 1fr 44px;
  align-items: stretch;
  gap: 8px;
  margin-bottom: 12px;
}

/* The rail visually links the two fields, the way a maps app does. */
.route-rail {
  display: flex; flex-direction: column; align-items: center;
  padding: 20px 0;
}
.rail-dot {
  width: 10px; height: 10px; border-radius: 50%;
  border: 2.5px solid var(--accent); flex: none;
}
.rail-line {
  flex: 1; width: 0;
  border-left: 2px dotted var(--line);
  margin: 5px 0;
  min-height: 22px;
}
.rail-square {
  width: 9px; height: 9px; border-radius: 2px;
  background: var(--warn); flex: none;
}

.route-fields { display: flex; flex-direction: column; gap: 10px; min-width: 0; }

.swap-btn {
  width: 44px; height: 44px; margin-top: 3px; align-self: start;
  display: grid; place-items: center;
  background: var(--bg-input); border: 1px solid var(--line);
  border-radius: 11px; cursor: pointer;
}
.swap-btn svg {
  width: 19px; height: 19px;
  fill: none; stroke: var(--text-dim); stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
}
.swap-btn:hover svg { stroke: var(--accent); }
.swap-btn:active { background: var(--bg-raise); }

/* Popup shown when a pin is dropped on the map. */
.leaflet-popup-content-wrapper {
  background: var(--bg-raise); color: var(--text);
  border: 1px solid var(--line); border-radius: 12px;
  box-shadow: 0 12px 34px rgba(0,0,0,.55);
}
.leaflet-popup-tip { background: var(--bg-raise); border: 1px solid var(--line); }
.leaflet-popup-content { margin: 12px 13px; font: inherit; }
.leaflet-popup-close-button { color: var(--text-dim) !important; }
.pin-popup .pin-name { font-size: 13.5px; font-weight: 600; margin-bottom: 9px; }
.pin-popup .pin-sub { font-size: 11.5px; color: var(--text-dim); font-weight: 400; }
.pin-popup .pin-actions { display: flex; gap: 7px; }
.pin-popup button {
  flex: 1; min-height: 38px; padding: 8px 10px; white-space: nowrap;
  font-size: 12.5px; font-weight: 700; cursor: pointer;
  border-radius: 9px; border: 1px solid var(--line);
  background: var(--bg-input); color: var(--text);
}
.pin-popup button.as-start { background: var(--accent); color: #17120a; border-color: var(--accent); }

.link-btn {
  display: block; width: 100%;
  min-height: 44px;
  margin: -4px 0 16px;
  padding: 9px;
  font-size: 13px; font-weight: 600;
  /* Not the chart's blue. That hue belongs to "air drag" everywhere else in
     the app, and spending it on an unrelated link dilutes it. */
  color: var(--text-dim); background: transparent;
  border: 1px solid var(--line); border-radius: var(--radius-sm); cursor: pointer;
}

.segmented.two { grid-template-columns: repeat(2, 1fr); margin-bottom: 16px; }

/* ===========================================================================
   MAP + NAVIGATION
   The map used to be a 220px box with the standard OpenStreetMap tiles
   CSS-inverted to fake a dark theme. Inverting a map image also inverts its
   labels and its colour-coding, so motorways came out the wrong colour and
   text read like a photographic negative. Both problems are fixed here: real
   dark-designed tiles (see BASEMAPS in navigation.js), and a full-screen map.
   ======================================================================== */

/* ---- Full-screen map screens --------------------------------------------- */
.map-screen, .nav-screen {
  position: fixed;
  inset: 0;
  max-width: none;
  padding: 0;
  overflow: hidden;
}
.map-screen.active, .nav-screen.active { display: block; }

.fullmap { position: absolute; inset: 0; background: #242f3e; z-index: 0; }

/* ---- Basemap surface -----------------------------------------------------
   The colour you see wherever a tile has not arrived yet. Leaflet leaves that
   gap transparent, so it shows the container — and a near-black container
   under the pale basemap is the flash people read as "the map glitched" when
   zooming. Matching each style's own background makes the gap invisible
   instead of merely brief.

   These are the `land` entries from js/basemap-style.js and have to move with
   them. */
.leaflet-container { background: #242f3e; font: inherit; }
.leaflet-container[data-basemap="light"]     { background: #f5f3f3; }
.leaflet-container[data-basemap="satellite"] { background: #241d14; }
.fullmap[data-basemap="light"]     { background: #f5f3f3; }
.fullmap[data-basemap="satellite"] { background: #241d14; }

/* Tiles fade in over the surface rather than snapping, which turns the
   remaining load time into something that reads as arriving. The vector
   basemap gets the same treatment on its canvas: it draws in one go once the
   style is ready, and without this that arrival is a hard cut. */
.basemap-tile { transition: opacity .18s var(--ease); }
.basemap-gl { animation: basemap-in .22s var(--ease) both; }
@keyframes basemap-in { from { opacity: 0; } to { opacity: 1; } }
.leaflet-control-attribution {
  background: rgba(20,17,13,.82) !important;
  color: var(--text-dim) !important;
  font-size: 9.5px !important;
}
.leaflet-control-attribution a { color: var(--text-dim) !important; }
/* A dark chip is invisible against the dark basemap and a bruise against the
   pale one, so it follows the basemap rather than the app chrome. */
.leaflet-container[data-basemap="light"] .leaflet-control-attribution {
  background: rgba(255,255,255,.86) !important;
  color: #6b727c !important;
}
.leaflet-container[data-basemap="light"] .leaflet-control-attribution a {
  color: #6b727c !important;
}

/* ---- Map markers --------------------------------------------------------- */
.map-pin {
  width: 16px; height: 16px; border-radius: 50%;
  border: 3px solid #131009; box-shadow: 0 0 0 2px currentColor, 0 2px 8px rgba(0,0,0,.6);
}
.map-pin.start { background: var(--accent); color: var(--accent); }
.map-pin.end { background: var(--warn); color: var(--warn); }

/* The driver's own position: a heading cone under a solid dot. */
.me-dot {
  width: 20px; height: 20px; border-radius: 50%;
  background: var(--bone);
  border: 3px solid #17120a;
  box-shadow: 0 0 0 6px rgba(244,236,220,.16), 0 2px 10px rgba(0,0,0,.75);
}

/* ---- Top overlay (search) ------------------------------------------------ */
.map-top {
  position: absolute;
  top: 0; left: 0; right: 0;
  z-index: 1000;
  padding: calc(env(safe-area-inset-top) + 10px) 10px 0;
  pointer-events: none;
}
.map-top > * { pointer-events: auto; }

.map-search-card {
  display: flex;
  align-items: flex-start;
  gap: 6px;
  padding: 8px;
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: 15px;
  box-shadow: 0 8px 28px rgba(0,0,0,.5);
}
.map-search-card .route-inputs { flex: 1; margin: 0; min-width: 0; }

.icon-btn {
  width: 40px; height: 40px; flex: none;
  display: grid; place-items: center;
  background: transparent; border: 0; border-radius: 11px; cursor: pointer;
}
.icon-btn svg {
  width: 22px; height: 22px;
  fill: none; stroke: var(--text); stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
}
.icon-btn:active { background: var(--bg-input); }

.map-top .region-row { margin: 8px 0 0; box-shadow: 0 6px 20px rgba(0,0,0,.45); }
.map-top #regionEditor { margin: 8px 0 0; }

/* ---- Floating map controls ----------------------------------------------- */
.map-controls, .nav-controls {
  position: absolute;
  right: 12px;
  z-index: 900;
  display: flex; flex-direction: column; gap: 9px;
}
/* Sit just above the sheet, whatever height it currently is. `--sheet-h` is
   published by trackSheetHeight() in app.js; the fallbacks are the collapsed
   heights, used only for the instant before the first measurement lands. */
.map-controls { bottom: calc(var(--sheet-h, 200px) + 14px); }
.nav-controls { bottom: calc(var(--sheet-h, 140px) + 14px); }
.map-controls, .nav-controls { transition: bottom .28s cubic-bezier(.4,0,.2,1); }

.map-fab {
  width: 46px; height: 46px;
  display: grid; place-items: center;
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: 13px;
  box-shadow: 0 6px 20px rgba(0,0,0,.5);
  cursor: pointer;
}
.map-fab svg {
  width: 21px; height: 21px;
  fill: none; stroke: var(--text); stroke-width: 1.9;
  stroke-linecap: round; stroke-linejoin: round;
}
.map-fab.on svg { stroke: var(--accent); }
.map-fab.off svg { stroke: var(--text-dim); opacity: .5; }
.map-fab:active { background: var(--bg-raise); }

.layer-menu {
  position: absolute; right: 68px; z-index: 950;
  bottom: 210px;
  display: flex; flex-direction: column; gap: 4px;
  padding: 5px;
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: 13px;
  box-shadow: 0 8px 26px rgba(0,0,0,.55);
}
.layer-menu button {
  padding: 10px 18px; min-height: 40px;
  font-size: 13.5px; font-weight: 600; text-align: left;
  color: var(--text-dim); background: transparent;
  border: 0; border-radius: 9px; cursor: pointer;
}
.layer-menu button.on { background: rgba(255,174,26,.15); color: var(--accent); }

.map-status {
  position: absolute;
  left: 12px; right: 12px; bottom: calc(var(--sheet-h, 200px) + 14px);
  z-index: 880;
  transition: bottom .28s cubic-bezier(.4,0,.2,1);
  text-align: center; font-size: 13px; font-weight: 600;
  color: var(--text);
  background: rgba(20,17,13,.92);
  border: 1px solid var(--line);
  border-radius: 11px;
  padding: 10px 12px;
  box-shadow: 0 6px 20px rgba(0,0,0,.5);
}
.map-status:empty { display: none; }
.map-status.error { color: var(--danger); border-color: rgba(255,86,70,.4); }
.map-status.busy { color: var(--text-dim); }

/* ---- Bottom sheet -------------------------------------------------------- */
.sheet {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  z-index: 1000;
  background: var(--bg-card);
  border-top: 1px solid var(--line);
  border-radius: 20px 20px 0 0;
  box-shadow: 0 -10px 34px rgba(0,0,0,.55);
  /* Never cover the map completely. Even fully expanded a strip of map stays
     visible, so the driver keeps their bearings and always has something to
     tap back to. */
  max-height: 72%;
  display: flex; flex-direction: column;
  transition: transform .28s cubic-bezier(.4,0,.2,1);
  padding-bottom: env(safe-area-inset-bottom);
}
.sheet-handle {
  display: block; width: 100%;
  min-height: 44px;                 /* thin grab-bar, comfortable tap target */
  padding: 16px 0 12px;
  background: transparent; border: 0; cursor: grab;
  /* Stop the browser claiming vertical drags for page scrolling, or the
     pointermove events never reach us and the sheet cannot be pulled. */
  touch-action: none;
  -webkit-user-select: none; user-select: none;
}
.sheet-handle:active { cursor: grabbing; }
.sheet-handle::before {
  content: ''; display: block;
  width: 52px; height: 5px; margin: 0 auto;
  background: var(--text-dim); border-radius: 3px;
  opacity: .55;
}
.sheet-handle:hover::before { opacity: .9; }
.sheet-peek { padding: 0 14px 14px; flex: none; }
.sheet-body {
  padding: 0 14px 14px;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  display: none;
}
.sheet.expanded .sheet-body { display: block; }
.sheet-empty { margin: 6px 0 0; font-size: 13.5px; color: var(--text-dim); text-align: center; }


/* ---- Route alternatives -------------------------------------------------- */
.route-alts { display: flex; flex-direction: column; gap: 8px; }
.route-alt {
  display: flex; align-items: center; gap: 12px;
  width: 100%;
  padding: 12px;
  text-align: left;
  background: var(--bg-input);
  border: 1.5px solid var(--line);
  border-radius: 13px;
  cursor: pointer;
}
.route-alt.on { border-color: var(--accent); background: rgba(255,174,26,.09); }
.route-alt-main { flex: 1; min-width: 0; }
.route-alt-time {
  font-size: 17px; font-weight: 700; color: var(--text);
  font-variant-numeric: tabular-nums;
}
.route-alt-sub {
  font-size: 12px; color: var(--text-dim); margin-top: 3px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.route-alt-energy { flex: none; text-align: right; }
.route-alt-soc {
  font-size: 17px; font-weight: 700; font-variant-numeric: tabular-nums;
}
.route-alt-soc.ok { color: var(--accent); }
.route-alt-soc.tight { color: var(--warn); }
.route-alt-soc.bad { color: var(--danger); }
.route-alt-energy span { display: block; font-size: 10px; color: var(--text-dim); margin-top: 2px; }
.route-badge {
  display: inline-block; margin-top: 6px;
  padding: 2px 7px; border-radius: 5px;
  font-size: 9.5px; font-weight: 700; letter-spacing: .5px; text-transform: uppercase;
}
.route-badge.fastest { background: rgba(77,144,224,.18); color: var(--k-aero); }
.route-badge.efficient { background: rgba(255,174,26,.18); color: var(--accent); }

.sheet-actions { display: flex; gap: 8px; margin-top: 12px; }
.sheet-actions button { flex: 1; }

/* ---- Directions list ----------------------------------------------------- */
.directions-title {
  margin: 4px 0 10px; font-size: 12px; font-weight: 700;
  letter-spacing: 1.2px; text-transform: uppercase; color: var(--text-dim);
}
.directions { list-style: none; margin: 0; padding: 0; }
.directions li {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 12px 4px;
  border-bottom: 1px solid var(--line);
}
.directions li:last-child { border-bottom: 0; }
.directions li.done { opacity: .38; }
.directions li.current { background: rgba(255,174,26,.07); border-radius: 10px; }
.dir-icon {
  width: 30px; height: 30px; flex: none; margin-top: 1px;
  fill: none; stroke: var(--text); stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
}
.directions li.current .dir-icon { stroke: var(--accent); }
.dir-text { flex: 1; min-width: 0; font-size: 14.5px; line-height: 1.35; }
.dir-dist {
  flex: none; font-size: 12.5px; color: var(--text-dim);
  font-variant-numeric: tabular-nums; margin-top: 2px;
}

/* ---- Navigation banner --------------------------------------------------- */
.nav-banner {
  position: absolute;
  top: 0; left: 0; right: 0;
  z-index: 1000;
  display: flex; align-items: center; gap: 14px;
  margin: calc(env(safe-area-inset-top) + 8px) 10px 0;
  padding: 14px 12px;
  background: linear-gradient(180deg, #282118, #1b1712);
  border: 1px solid var(--line);
  border-radius: 17px;
  box-shadow: 0 10px 32px rgba(0,0,0,.6);
}
.nav-arrow {
  width: 44px; height: 44px; flex: none;
  fill: none; stroke: var(--accent); stroke-width: 2.1;
  stroke-linecap: round; stroke-linejoin: round;
}
.nav-banner-text { flex: 1; min-width: 0; }
.nav-dist {
  font: 700 27px/1.05 var(--face-data);
  letter-spacing: .01em; font-variant-numeric: tabular-nums;
  color: var(--bone);
}
.nav-instr {
  font-size: 14.5px; line-height: 1.3; margin-top: 3px; color: var(--text);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.nav-close { flex: none; }
.nav-banner.rerouting { border-color: rgba(255,174,26,.5); }

.nav-then {
  position: absolute;
  top: 0; left: 10px; right: 10px;
  z-index: 999;
  margin-top: calc(env(safe-area-inset-top) + 92px);
  padding: 8px 14px;
  font: 400 12.5px/1.35 var(--face-text); color: var(--bone-dim);
  background: rgba(32,26,18,.95);
  border: 1px solid var(--line);
  border-top: 0;
  border-radius: 0 0 13px 13px;
  box-shadow: 0 8px 22px rgba(0,0,0,.45);
}
.nav-then b { color: var(--text); font-weight: 600; }

.nav-screen .gps-state {
  position: absolute; left: 12px; z-index: 880;
  /* Shrink-wrap the text, but stop short of the floating button column (46px
     wide + 12px gutter) so a long diagnostic cannot run underneath it and lose
     its last few words. A `right` here instead would stretch "Waiting for
     GPS…" into a mostly-empty bar. */
  max-width: calc(100% - 82px);
  bottom: calc(var(--sheet-h, 140px) + 14px);
  transition: bottom .28s cubic-bezier(.4,0,.2,1);
  padding: 6px 11px; font-size: 11.5px;
  background: rgba(20,17,13,.9);
  border: 1px solid var(--line); border-radius: 9px;
}

/* ---- Navigation sheet ---------------------------------------------------- */
.nav-eta {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px;
  text-align: center; margin-bottom: 10px;
}
.nav-eta-main b {
  display: block;
  font: 700 22px/1.1 var(--face-data);
  letter-spacing: .01em;
  font-variant-numeric: tabular-nums;
  color: var(--bone);
}
.nav-eta-main span {
  display: block;
  margin-top: 4px;
  font: 500 9.5px/1 var(--face-data);
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--bone-mute);
}
/* Unlit while it is fine. The tight and bad rules below are the only ones
   that light it, which is the whole point of the palette. */
.nav-eta-main.battery b { color: var(--bone); }
.nav-eta-main.battery.tight b { color: var(--warn); }
.nav-eta-main.battery.bad b { color: var(--danger); }

.nav-sheet .verdict { margin: 0; }
.nav-sheet .hero { margin-top: 12px; }
.nav-sheet .card { background: var(--bg-input); }

/* ---- Start driving / pause ----------------------------------------------- */
.drive-toggle {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 13px 16px;
  margin-bottom: 12px;
  text-align: left;
  border-radius: 13px;
  cursor: pointer;
  border: 1.5px solid var(--accent);
  background: var(--accent);
  color: #17120a;
}
.drive-toggle .drive-icon {
  width: 22px; height: 22px; flex: none;
  fill: currentColor; stroke: none;
}
/* The label is the button's name and must never wrap — "Start driving" broke
   across two lines with 1900px of empty button beside it, because `flex: 1`
   let it shrink while the subtitle claimed the whole row. The subtitle is the
   part that should give way instead. */
.drive-label { flex: none; white-space: nowrap; font-size: 16px; font-weight: 700; }
.drive-sub {
  flex: 1; min-width: 0;
  font-size: 11.5px; font-weight: 500; opacity: .75;
}
/* Driving: calmer, since it is the steady state rather than a call to action. */
.drive-toggle.driving {
  background: var(--bg-input);
  border-color: var(--line);
  color: var(--text);
}
.drive-toggle.driving .drive-icon { fill: var(--warn); }
.drive-toggle:active { filter: brightness(.92); }

.hero.paused .hero-value { color: var(--text); }
.hero.paused { background: var(--bg-card); }

/* ---- Simulated drive badge ----------------------------------------------- */
.sim-badge {
  position: absolute;
  /* Below the turn banner and its "then…" line, whatever height those are —
     `--nav-top-h` is measured by paintNavBanner(). A fixed offset here printed
     the badge straight across the "then" line whenever one was showing. */
  top: calc(var(--nav-top-h, 108px) + 10px);
  left: 50%; transform: translateX(-50%);
  z-index: 1001;
  padding: 6px 14px;
  font-size: 11px; font-weight: 800; letter-spacing: 1px;
  color: #2a0508;
  background: var(--danger);
  border-radius: 8px;
  box-shadow: 0 4px 16px rgba(0,0,0,.55);
  white-space: nowrap;
}

/* ---- Diagnostics --------------------------------------------------------- */
.diag {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 6px 14px;
  margin: 10px 0 0;
  font-size: 12.5px;
}
.diag dt { color: var(--text-dim); }
.diag dd {
  margin: 0; text-align: right;
  font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
}
.diag-value.ok { color: var(--accent); }
.diag-value.warn { color: var(--warn); }
.diag-value.bad { color: var(--danger); }

.diag-advice {
  margin: 12px 0 0; padding: 10px 12px;
  font-size: 12px; line-height: 1.45;
  color: var(--text-dim);
  background: var(--bg-input);
  border-left: 3px solid var(--line);
  border-radius: 0 9px 9px 0;
}
.diag-advice.ok { color: var(--accent); border-left-color: var(--accent); }
.diag-advice.warn { color: var(--warn); border-left-color: var(--warn); }
.diag-advice.bad { color: var(--danger); border-left-color: var(--danger); }

.diag-errors {
  margin-top: 10px; padding: 9px 11px;
  font-size: 11.5px; line-height: 1.4;
  color: var(--danger);
  background: rgba(255,86,70,.1);
  border: 1px solid rgba(255,86,70,.35);
  border-radius: 9px;
  overflow-wrap: anywhere;
}

.sim-row { display: flex; align-items: flex-end; gap: 12px; margin-top: 14px; }
.sim-row button { flex: none; }
.sim-speed { flex: 1; min-width: 0; }
.sim-speed span {
  display: flex; justify-content: space-between;
  font-size: 12.5px; font-weight: 600; margin-bottom: 4px;
}
.sim-speed input { width: 100%; }
button.secondary.on { background: var(--danger); color: #2a0508; border-color: var(--danger); }

/* ---- Setup screen: the button that opens the map -------------------------- */
.trip-open {
  display: flex; align-items: center; gap: 12px;
  width: 100%; padding: 13px;
  text-align: left; cursor: pointer;
  background: var(--bg-input);
  border: 1px solid var(--line);
  border-radius: 13px;
}
.trip-open:active { background: var(--bg-raise); }
.trip-open-rail {
  display: flex; flex-direction: column; align-items: center; flex: none;
  align-self: stretch; padding: 4px 0;
}
.trip-open-rail .rail-line { min-height: 14px; }
.trip-open-text { flex: 1; min-width: 0; }
.trip-open-from, .trip-open-to {
  display: block; font-size: 14px; padding: 3px 0;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  color: var(--text-dim);
}
.trip-open-from.set, .trip-open-to.set { color: var(--text); font-weight: 600; }
.trip-open-map {
  width: 24px; height: 24px; flex: none;
  fill: none; stroke: var(--text-dim); stroke-width: 1.7;
  stroke-linecap: round; stroke-linejoin: round;
}

/* ---- Route summary chips ------------------------------------------------- */
.chips { display: grid; grid-template-columns: repeat(4, 1fr); gap: 7px; margin: 10px 0; }
.chip {
  background: var(--bg-input); border: 1px solid var(--line);
  border-radius: 11px; padding: 10px 6px; text-align: center;
}
.chip b { display: block; font-size: 15px; font-variant-numeric: tabular-nums; }
.chip span { display: block; font-size: 9.5px; color: var(--text-dim); margin-top: 3px; line-height: 1.2; }

/* ---- Elevation profile --------------------------------------------------- */
.profile-wrap { margin: 12px 0 6px; }
.profile {
  display: block; width: 100%; height: 90px;
  background: var(--bg-input);
  border: 1px solid var(--line);
  border-radius: 11px;
}
.profile-labels {
  display: flex; justify-content: space-between;
  font-size: 11px; color: var(--text-dim); margin-top: 5px;
}
.profile-labels span:nth-child(2) { color: var(--text); font-weight: 600; }

.auto-badge {
  font-size: 9.5px; font-weight: 700; letter-spacing: .6px; text-transform: uppercase;
  color: #17120a; background: var(--accent);
  padding: 2px 6px; border-radius: 5px; font-style: normal;
}

/* ---- Folding away the advanced controls ----------------------------------
   Both screens had every control on display at once, which made the setup
   form long and the driving sheet a wall of panels. These fold the things
   that are either auto-filled or rarely touched, while the summary on the
   right keeps their current value visible — tidied, not hidden. */
.disclosure {
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 0 14px;
  margin-top: 12px;
}
.disclosure > summary {
  display: flex; align-items: center; gap: 10px;
  /* 48px keeps this a comfortable target in a moving car. */
  min-height: 48px;
  font-size: 14.5px; font-weight: 650;
  color: var(--text);
  cursor: pointer;
  list-style: none;
  -webkit-user-select: none; user-select: none;
}
.disclosure > summary::-webkit-details-marker { display: none; }
/* The chevron was two borders on a square rotated 45 degrees. A rotated box
   has a bigger bounding box than the box itself — 8px square becomes 11.3px
   across — and transformed overflow counts towards scrollable overflow, so
   the summary row was 2px wider than its container at every width. A masked
   glyph rotating 180 degrees keeps the same bounding box at both ends. */
.disclosure > summary::after {
  content: '';
  width: 16px; height: 16px;
  margin-left: auto;
  flex: none;
  background: var(--text-dim);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E") center/15px no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E") center/15px no-repeat;
  transition: transform .2s var(--ease);
}
.disclosure[open] > summary::after { transform: rotate(180deg); }
.disclosure > summary > em {
  margin-left: auto;
  min-width: 0;
  font-style: normal; font-size: 13px; font-weight: 500;
  color: var(--text-dim);
  text-align: right;
  /* Never let a long summary push the chevron off the edge. */
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.disclosure > summary > em:empty { display: none; }
.disclosure > summary > em + ::after { margin-left: 10px; }
.disclosure > *:not(summary) { margin-bottom: 14px; }
.disclosure > summary:focus-visible { outline: 2px solid var(--accent); border-radius: 8px; }

/* A disclosure that has something wrong inside it says so on the closed row. */
.disclosure.attention { border-color: rgba(255,86,70,.45); }
.disclosure.attention > summary > em { color: var(--danger); }

.disclosure .trip-log { display: flex; justify-content: space-between; gap: 8px; }

/* ===========================================================================
   VISUAL REFINEMENT
   ---------------------------------------------------------------------------
   The palette and layout were already right; what was missing was depth and
   hierarchy. Every card looked identical, so nothing led the eye, and the
   search list was a column of grey squares.

   Nothing here changes a size, a hit target or a contrast ratio — the app
   still has to be readable at a glance in a moving car, which is a stronger
   constraint than looking nice.
   ======================================================================== */

/* Cards gain a hairline of light along the top edge, the way a raised surface
   catches light. One pixel, and they stop reading as flat rectangles.

   NOTE: no `position` here. An earlier version added `position: relative` to
   this list, which included `.sheet` — and that overrode the sheet's
   `position: absolute`, so the bottom sheet fell into normal flow and covered
   the map controls. Only the one element that needs a positioned parent for a
   pseudo-element gets one, below. */
.card, .disclosure, .tile, .hero {
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .04), 0 1px 2px rgba(0, 0, 0, .25);
}

/* Search results: tint the icon by category. Finding the city among fifteen
   shops becomes a colour judgement rather than a reading task. */
.sg-icon { transition: background .15s, border-color .15s; }
.suggestions li[data-kind="city"]   .sg-icon { background: rgba(77,144,224,.13); border-color: rgba(77,144,224,.30); }
.suggestions li[data-kind="city"]   .sg-icon svg { stroke: var(--k-aero); }
.suggestions li[data-kind="road"]   .sg-icon { background: rgba(226,103,58,.13); border-color: rgba(226,103,58,.30); }
.suggestions li[data-kind="road"]   .sg-icon svg { stroke: var(--k-roll); }
.suggestions li[data-kind="charge"] .sg-icon { background: rgba(255,174,26,.14); border-color: rgba(255,174,26,.32); }
.suggestions li[data-kind="charge"] .sg-icon svg { stroke: var(--amber); }
.suggestions li[data-kind="rail"]   .sg-icon,
.suggestions li[data-kind="air"]    .sg-icon { background: rgba(144,128,224,.12); border-color: rgba(144,128,224,.28); }
.suggestions li[data-kind="rail"]   .sg-icon svg,
.suggestions li[data-kind="air"]    .sg-icon svg { stroke: var(--k-grade); }
.suggestions li[data-kind="home"]   .sg-icon svg { stroke: var(--text); }

.suggestions li[data-kind="poi"]    .sg-icon { background: rgba(244,236,220,.07); }
.suggestions li[data-kind="poi"]    .sg-icon svg { stroke: var(--text); }

/* On a phone the address is the part that gets squeezed, and the address is
   how you tell two branches of the same chain apart. Buy it room back from
   the icon and the gaps rather than from the text. */
@media (max-width: 460px) {
  .suggestions li { gap: 9px; padding: 9px 9px; }
  .sg-icon { width: 28px; height: 28px; border-radius: 8px; }
  .sg-icon svg { width: 15px; height: 15px; }
}

/* The distance badge earns a little emphasis: after the location work, it is
   the fastest way to tell "this is the one near me" from "this is not".
   Kept deliberately tight — at 390 px wide every pixel it takes is a pixel of
   address the reader loses, and "Al Amir Qadad…" helps nobody. */
.sg-dist {
  font-variant-numeric: tabular-nums;
  font-size: 11.5px;
  color: var(--text-dim);
  background: var(--bg-input);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 2px 7px;
  align-self: center;
  flex: none;
  white-space: nowrap;
}

/* "Searching…" gets a moving sheen, so a slow geocoder reads as working
   rather than stuck. This matters more than it looks: when one provider is
   unreachable a search legitimately takes a few seconds. */
.suggestions li.loading {
  background: linear-gradient(90deg,
    transparent 0%, rgba(255,174,26,.10) 45%, rgba(255,174,26,.10) 55%, transparent 100%);
  background-size: 220% 100%;
  animation: sheen 1.3s ease-in-out infinite;
}
@keyframes sheen {
  from { background-position: 120% 0; }
  to   { background-position: -20% 0; }
}

/* The chosen segment gets a little lift instead of a flat fill. */
.segmented button.on {
  box-shadow: 0 2px 8px rgba(255, 174, 26, .30);
}
.segmented button:not(.on):hover { background: rgba(255, 255, 255, .04); color: var(--text); }

/* A live countdown that changes width as its digits change is unreadable at a
   glance, and every one of these updates once a second. */
.route-alt-time, .nav-eta b, .nav-eta .eta-value,
.diag-value, .chip b, .sheet .hero-clock {
  font-variant-numeric: tabular-nums;
}

/* Rounded ends on the energy bar, and a touch of separation between segments. */
.bar { border-radius: 999px; overflow: hidden; }
.seg + .seg { box-shadow: inset 1px 0 0 rgba(20, 17, 13, .55); }

/* ---- Sheet on a wide screen ---------------------------------------------
   A bottom sheet is a phone idea. Stretched across a 1280px desktop it made
   the "Start driving" button nearly two metres of green with its label
   stranded on the far left, and buried the map under a full-width slab.
   Docking it as a floating side panel keeps the reading column at a sane
   width and leaves the map visible — the point of a navigation screen.

   This block lives at the end of the file on purpose: it overrides rules
   declared later than the sheet section (.gps-state, .map-status) at equal
   specificity, so source order is what makes it win. Do not move it up. */
@media (min-width: 760px) {
  .sheet {
    left: 16px; right: auto;
    bottom: 16px;
    width: 400px;
    border: 1px solid var(--line);
    border-radius: 20px;
    /* Clear the turn banner at the top rather than sliding under it. */
    max-height: calc(100% - 150px);
  }
  /* The panel no longer sits under them, so the floating controls stop
     chasing its height and just rest in the corner. */
  .map-controls, .nav-controls { bottom: 24px; }
  .nav-screen .gps-state { left: 432px; bottom: 24px; max-width: calc(100% - 502px); }
  .map-status { left: 432px; right: 16px; bottom: 24px; }
}

/* Users who ask for reduced motion get no transitions. */
@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}
