/* Tesla nav UI styles. Component selectors mirror Tesla's namespace
   format (CidNav/RouteLineLabelDuration → .t-cidnav-route-line-label-duration).
   Geometry comes from firmware_extract/analysis/ — not guessed. */

*,*::before,*::after {
  box-sizing: border-box; margin: 0; padding: 0;
  /* No iOS-style gray flash on tap; the active-state visuals are
     handled per-component with explicit :active rules. */
  -webkit-tap-highlight-color: transparent;
}

/* Hint to user agents about the current colour palette so native
   chrome (form controls, scrollbars) renders coherently. The data
   attribute swap below keeps the value in sync per theme. */
html { color-scheme: dark; }
html[data-tesla-theme="day"] { color-scheme: light; }
html[data-tesla-theme="darkDay"] { color-scheme: dark; }

/* When backdrop-filter isn't supported (Firefox < 103, older Safari
   on iPad), our translucent pills become unreadable over the map.
   Promote the surface to an opaque background in that case. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .t-shell__left,
  .t-first-turn,
  .TurnList,
  .t-bottom-view,
  .t-search-pill,
  .t-current-location,
  .t-places,
  .t-info-window,
  .t-settings,
  .TripPlanCard,
  .t-edit-trip,
  .t-charger-list,
  .t-rs-pill,
  .t-don-popup,
  .t-modal-backdrop {
    background-color: var(--t-c-bg-primary);
  }
}

html, body {
  height: 100%;
  background: var(--t-c-bg-primary);
  color: var(--t-c-text-primary);
  font-family: var(--t-font);
  /* Fluid base font — matches the --t-fs-base ramp so chrome and text
     scale together. vw (not vmin) so tall phones stay at the phone
     size rather than jumping to the tablet size in portrait. */
  font-size: var(--t-fs-base);
  overflow: hidden;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  /* Web-app zoom lockdown.  `touch-action: pan-x pan-y` allows
     single-finger pan but blocks the two-finger pinch-zoom gesture
     AND the double-tap zoom on the page root.  Descendant elements
     that legitimately need pinch (the MapLibre canvas — see
     `.t-shell__map-container { touch-action: none }` below) opt-IN
     by overriding this value on themselves.
     Combined with `user-scalable=no` in the viewport meta tag this
     gives a "native app" feel across every browser we ship to
     (desktop Chromium, mobile Safari, mobile Chrome, Tesla MCU's
     Chromium fork).  Ctrl+wheel zoom is also blocked because the
     wheel goes through this root element first. */
  touch-action: pan-x pan-y;
  /* Stop iOS rubber-band bounce outside the bottom sheet. */
  overscroll-behavior: none;
}
/* MapLibre owns its own gesture pipeline (pinch-zoom, two-finger
   pan, rotate).  The canvas needs `touch-action: none` so the
   browser hands raw touch events to MapLibre instead of consuming
   them for browser-level scrolling.  This lives BELOW the body
   declaration so it wins per CSS cascade. */
.t-shell__map,
.t-shell__map-container,
#t-map {
  touch-action: none;
}

button {
  background: none; border: none; cursor: pointer;
  font-family: inherit; color: inherit;
  /* Icon-only buttons shouldn't trigger the iOS "Save Image…" callout
     on long-press; copy text from normal `<button>` is still allowed
     because we re-enable callout on inputs/textareas below. */
  -webkit-touch-callout: none;
}
input, textarea, [contenteditable] { -webkit-touch-callout: default; }
/* Prevent iOS Safari from auto-zooming the page when focusing an input
   whose computed font-size is < 16 px. Our search pill / sliders /
   asst input all inherit body font-size; bump form elements to 16+. */
input, textarea, select { font-size: max(calc(var(--ui-font-scale) * 16px), 1em); }

img {
  display: block; max-width: 100%;
  user-select: none; -webkit-user-select: none;
  -webkit-user-drag: none;
}

/* Keyboard focus ring — only when the user is actually keyboard-
   navigating, not on every mouse click. */
:focus { outline: none; }
:focus-visible {
  outline: calc(var(--ui-content-scale) * 2px) solid var(--t-c-blue-bright);
  outline-offset: calc(var(--ui-content-scale) * 2px);
}

/* ═══ App shell ═══════════════════════════════════════════════════════ */

/* ═══ Shell layout — mobile-first, layered ═════════════════════════════
   Map is ALWAYS the full canvas. Every other element floats over it
   as an absolute-positioned overlay. No grid columns competing for
   width — eliminates the "map gets 16px while the panel takes 280"
   bug we had at the 480-768 px range.

   Default (mobile-first) layout:
     * Map        — fills 100% of the shell.
     * Left panel — bottom sheet anchored to bottom, full-width minus
                    margins, max-height 60dvh. Scrolls inside itself.
     * Right pill — floats top-right, vertical column of buttons.
     * Search pill / notifications live inside the left panel and
                    stay sticky at its top so they survive scrolling.

   Tablet portrait (≥769 px) and up: left panel moves to top-left as
   a sidebar (cap 460 px wide). See media queries far below. */
.t-shell {
  position: fixed; inset: 0;
  background: var(--t-c-bg-primary);
  /* No horizontal safe-area padding here — the map fills the full
     viewport edge-to-edge, and the sheet snaps to the bottom edge
     full-width. Individual chrome elements (right-strip pill,
     current-location badge, etc.) apply their own env()
     safe-area-insets where they actually need them. */
  /* Tesla "Video limited" banner — the car-UI shell shrinks the
     chromium widget from the top by the banner's height (~60 px) on
     show/hide.  We deliberately do NOT compensate with a `transform`
     on the shell: CSS spec makes a transformed ancestor become the
     containing block for its `position: fixed` descendants, so a
     `transform: translateY(-banner)` here would anchor `.t-shell__left`
     (the bottom sheet) to the SHIFTED shell bottom — bottom flickers
     on every banner toggle.  Since both top and bottom can't be
     screen-stable simultaneously when the chromium widget itself
     shifts, we prefer a stable BOTTOM (driver's hand-zone during
     guidance) and accept the top edge moving down by the banner
     height.  The `--t-stable-h`-driven sheet sizing in
     `.t-shell__left` below keeps the sheet's TOTAL height constant
     across the toggle so internal reflows don't compound the shift. */
}

.t-shell__map {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
}

.t-shell__map-container {
  position: absolute; inset: 0;
}

.t-shell__overlays {
  position: absolute; inset: 0;
  pointer-events: none;
  z-index: 4;
}
.t-shell__overlays > * { pointer-events: auto; }

/* Speed cluster — posted-limit sign + live speed badge. Pinned to the
   bottom-right corner of the map area, just above the right-strip and
   clear of the sheet on mobile. Self-hides outside Driving so the rest
   of the views aren't crowded. */
/* Yandex-style speed cluster — a solid dark current-speed disc with the
   posted-limit sign overlapping it on the right. Top-right, beside the
   compass / right-strip so it's always visible. EU = red-ring circle
   (number only); US = MUTCD rectangle (text + number) via data-style. */
.t-speed-cluster {
  position: absolute;
  top: calc(max(calc(var(--ui-content-scale) * 16px), env(safe-area-inset-top, calc(var(--ui-content-scale) * 16px))) + calc(var(--ui-content-scale) * 4px));
  right: calc(max(calc(var(--ui-content-scale) * 20px), env(safe-area-inset-right, calc(var(--ui-content-scale) * 20px))) + calc(var(--ui-content-scale) * 96px));
  display: flex;
  align-items: center;
  z-index: 6;
}
.t-speed-current {
  width: calc(var(--ui-content-scale) * 68px);
  height: calc(var(--ui-content-scale) * 68px);
  display: flex; align-items: center; justify-content: center;
  background: #141821; color: #fff;
  border-radius: 50%;
  font-family: Inter, sans-serif;
  box-shadow: 0 calc(var(--ui-content-scale) * 4px) calc(var(--ui-content-scale) * 12px) rgba(0,0,0,0.5);
  z-index: 1;
  transition: background-color 200ms ease;
}
.t-speed-current__val { font-size: calc(var(--ui-font-scale) * 28px); font-weight: 800; line-height: 1; }
.t-speed-current--over { background: var(--t-c-red); color: #fff; }

/* EU red-ring sign (default) — overlaps the speed disc on its right. */
.t-speed-limit {
  width: calc(var(--ui-content-scale) * 70px);
  height: calc(var(--ui-content-scale) * 70px);
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  background: #fff; color: #111;
  border: calc(var(--ui-content-scale) * 7px) solid var(--t-c-red);
  border-radius: 50%;
  font-family: Inter, sans-serif;
  /* Small overlap only — enough to read as a connected pair, but the disc
     stays out from under the sign so the centered speed number is fully
     visible even at two/three digits. */
  margin-left: calc(var(--ui-content-scale) * -8px);
  z-index: 2;
  box-shadow: 0 0 calc(var(--ui-content-scale) * 12px) rgba(255,64,64,0.55),
              0 calc(var(--ui-content-scale) * 4px) calc(var(--ui-content-scale) * 12px) rgba(0,0,0,0.45);
}
.t-speed-limit__title { display: none; }
.t-speed-limit__val {
  font-size: calc(var(--ui-font-scale) * 30px);
  font-weight: 800;
  line-height: 1;
}
/* US MUTCD rectangle — "SPEED LIMIT" text + number, black border, no ring. */
.t-speed-limit[data-style="us"] {
  width: calc(var(--ui-content-scale) * 64px);
  height: calc(var(--ui-content-scale) * 82px);
  border-radius: calc(var(--ui-content-scale) * 6px);
  border: calc(var(--ui-content-scale) * 3px) solid #111;
  padding: calc(var(--ui-content-scale) * 4px) 0;
  box-shadow: 0 calc(var(--ui-content-scale) * 4px) calc(var(--ui-content-scale) * 12px) rgba(0,0,0,0.45);
}
.t-speed-limit[data-style="us"] .t-speed-limit__title {
  display: block;
  font-size: calc(var(--ui-font-scale) * 10px); color: #111; font-weight: 700;
  letter-spacing: 0.02em; line-height: 1.05; text-align: center;
}
.t-speed-limit[data-style="us"] .t-speed-limit__val {
  font-size: calc(var(--ui-font-scale) * 32px);
  margin-top: calc(var(--ui-content-scale) * 2px);
}
@media (prefers-reduced-motion: reduce) {
  .t-speed-current { transition: none; }
}

/* Mobile default: bottom sheet sized by `--sheet-h` (set on <html>
   + inline on the sheet itself by app.rs from state.sheet_pct).
   The sheet's HEIGHT is the visible portion, so inner scrollers
   compute their available space against the right number — that's
   what makes overflow-y:auto kick in for long content. Three snap
   points on release: 12 / 55 / 90 % dvh.

   Smoothness comes from `contain: strict` (the sheet's layout +
   paint + size are isolated from the page) plus a GPU promotion
   hint via `translateZ(0)`. The height change triggers a reflow
   ONLY inside the sheet, not the whole document. */
.t-shell__left {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  /* Layered fallback chain:
       1. `vh` — legacy fixed viewport-height (old Chromium / old
          Tesla MCU firmware).
       2. `dvh` — dynamic viewport-height (modern engines).
       3. `--t-stable-h` — pixel value captured at boot by the
          banner-stabiliser bridge; survives Tesla banner toggles by
          never shrinking.  Wins when present.
     Last declaration wins per CSS cascade, so engines that understand
     `--t-stable-h` use it. */
  height: calc(var(--sheet-h, 55) * 1vh);
  height: calc(var(--sheet-h, 55) * 1dvh);
  height: calc(var(--sheet-h, 55) * var(--t-stable-h, 1dvh) / 100);
  display: flex; flex-direction: column;
  padding: 0 calc(var(--ui-content-scale) * 12px);
  padding-bottom: calc(calc(var(--ui-content-scale) * 14px) + env(safe-area-inset-bottom, 0));
  gap: calc(var(--ui-content-scale) * 10px);
  z-index: 5;
  /* Transparent click-through container. Empty space inside the sheet
     (the area beneath the SearchPill / view content / Notifications)
     was capturing every click and blocking map pan/long-press. The
     container is now invisible AND non-interactive; only its visible
     children (with their own backgrounds) intercept pointer events. */
  pointer-events: none;
  overflow: visible;
  background: transparent;
  border-radius: 0;
  box-shadow: none;
  /* Sheet root permits vertical pan — the JS classifier in app.rs
     decides per-gesture whether the pan drags the sheet (capture
     the pointer + prevent_default) or scrolls an inner list. If
     this were `none` the captured pointer would suppress native
     scroll on children, defeating the gate. */
  touch-action: pan-y;
  /* Isolate layout / paint to the sheet's own subtree. With this,
     a height change does NOT reflow the page — only the sheet's
     own contents reflow, and the surrounding map composite is
     untouched. */
  contain: layout style paint;
  /* Hint to the compositor that this surface is on a separate
     layer; combined with `contain`, this keeps the bg stable
     during height changes instead of flashing through. */
  transform: translateZ(0);
  transition: height 240ms cubic-bezier(0.32, 0.72, 0, 1);
}
.t-shell__left.is-dragging {
  transition: none;
}
.t-shell__left > * {
  pointer-events: auto;
  flex-shrink: 0;
}

/* Drag-handle affordance at the top of the sheet — iPhone-style pill.
   Pointer events are handled on the sheet, not the grabber, so the
   grabber is purely visual. */
.t-sheet-grabber {
  position: sticky; top: 0;
  display: flex; align-items: center; justify-content: center;
  height: calc(var(--ui-content-scale) * 22px);
  margin: 0 calc(var(--ui-content-scale) * -12px) calc(var(--ui-content-scale) * 4px);
  user-select: none;
  -webkit-user-select: none;
  background: var(--t-c-bg-nav-primary);
  border-radius: calc(var(--ui-content-scale) * 18px) calc(var(--ui-content-scale) * 18px) 0 0;
  z-index: 1;
  /* The parent sheet is now pointer-events: none so the empty space
     below doesn't trap map clicks. The grabber owns the sheet's
     drag gesture exclusively — pointer-events: auto here lets it
     catch the drag while the rest of the empty space stays
     click-through. Drag handlers in app.rs are wired to this div. */
  pointer-events: auto;
  cursor: ns-resize;
  touch-action: none;
}
.t-sheet-grabber__bar {
  width: calc(var(--ui-content-scale) * 42px); height: calc(var(--ui-content-scale) * 5px); border-radius: calc(var(--ui-content-scale) * 3px);
  background: var(--t-c-overlay-5);
}
.t-shell__left.is-dragging .t-sheet-grabber__bar {
  background: var(--t-c-overlay-7);
}

/* Mobile default: vertical pill floats top-right above the map.
   Top inset uses the BOOT-TIME safe-area-inset captured by the
   banner-stabiliser bridge (`--t-stable-safe-top`) so the strip
   doesn't slide when Tesla mutates env(safe-area-inset-top) on
   banner show/hide.  Fallback to 12px when the bridge hasn't run. */
.t-shell__right-strip {
  position: absolute;
  top: max(calc(var(--ui-content-scale) * 12px), var(--t-stable-safe-top, calc(var(--ui-content-scale) * 12px)));
  right: max(calc(var(--ui-content-scale) * 8px), env(safe-area-inset-right, calc(var(--ui-content-scale) * 8px)));
  display: flex; flex-direction: column;
  gap: calc(var(--ui-content-scale) * 12px);
  pointer-events: none;
  z-index: 5;
}
.t-shell__right-strip > * { pointer-events: auto; }
/* While driving the MAIN controls pill auto-hides (the compass/heading pill
   above it stays put); a map touch reveals it — see map_chrome_revealed.
   Slides out to the right + fades, and drops pointer-events while hidden. */
.t-rs-pill--hidden {
  opacity: 0;
  transform: translateX(calc(var(--ui-content-scale) * 28px));
  pointer-events: none;
}

/* ═══ Search pill (Phase 5 — firmware-canonical expanding pill) ═══════
   Collapsed: single input row, same height as the prior implementation.
   Expanded: same input row pinned to the top, plus a body section
   below holding the Home/Work shortcut rows and the PlacesPanel
   filter-chip + result list. Body grows up to the height of the
   left column; inner content scrolls.
*/
.t-search-pill {
  display: flex;
  flex-direction: column;
  width: 100%;
  background: var(--t-c-bg-nav-primary);
  backdrop-filter: blur(calc(var(--ui-content-scale) * 20px));
  -webkit-backdrop-filter: blur(calc(var(--ui-content-scale) * 20px));
  border-radius: calc(var(--ui-content-scale) * 14px);
  border: calc(var(--ui-content-scale) * 1px) solid var(--t-c-overlay-3);
  margin-bottom: 0;
  overflow: hidden;     /* keep the body's scroll inside the rounded corners */
  transition: max-height 220ms ease-out;
  max-height: clamp(calc(var(--ui-content-scale) * 44px), calc(1.8vw + calc(var(--ui-content-scale) * 38px)), calc(var(--ui-content-scale) * 60px));
}
.t-search-pill--expanded {
  /* Fill the available vertical space inside the left column. */
  max-height: calc(100% - var(--t-s-md));
}
.t-search-pill__input-row {
  display: flex;
  align-items: center;
  width: 100%;
  flex: 0 0 clamp(calc(var(--ui-content-scale) * 44px), calc(1.8vw + calc(var(--ui-content-scale) * 38px)), calc(var(--ui-content-scale) * 60px));
  padding: 0 var(--t-s-lg);
  gap: var(--t-s-md);
}
.t-search-pill input {
  flex: 1;
  height: 100%;
  background: transparent;
  border: none;
  color: var(--t-c-text-primary);
  font-size: var(--t-fs-large);
  font-family: inherit;
  outline: none;
  min-width: 0;
}
.t-search-pill input::placeholder { color: var(--t-c-text-tertiary); }
.t-search-pill__icon {
  width: var(--t-icon-sm); height: var(--t-icon-sm);
  opacity: 0.6;
}
.t-search-pill__close {
  width: calc(var(--ui-content-scale) * 32px); height: calc(var(--ui-content-scale) * 32px);
  border-radius: 50%;
  background: var(--t-c-overlay-4);
  border: none;
  display: flex; align-items: center; justify-content: center;
  color: var(--t-c-text-primary);
  cursor: pointer;
  flex: 0 0 auto;
  transition: background 120ms;
}
.t-search-pill__close:hover { background: var(--t-c-overlay-6); }
.t-search-pill__close:active { transform: scale(0.94); }
.t-search-pill__close .t-mask-icon { width: calc(var(--ui-content-scale) * 16px); height: calc(var(--ui-content-scale) * 16px); }

/* Chip-takeover header: replaces the search input when the user taps
   Charging / Hungry / Lucky. Same height as the input row so the
   pill shape stays stable across mode switches. */
.t-search-pill__takeover-header {
  display: flex;
  align-items: center;
  width: 100%;
  flex: 0 0 clamp(calc(var(--ui-content-scale) * 44px), calc(1.8vw + calc(var(--ui-content-scale) * 38px)), calc(var(--ui-content-scale) * 60px));
  padding: 0 var(--t-s-lg);
  gap: var(--t-s-md);
}
.t-search-pill__takeover-back {
  width: calc(var(--ui-content-scale) * 32px); height: calc(var(--ui-content-scale) * 32px);
  border-radius: 50%;
  background: transparent;
  border: none;
  display: flex; align-items: center; justify-content: center;
  color: var(--t-c-text-primary);
  cursor: pointer;
  flex: 0 0 auto;
  transition: background 120ms;
}
.t-search-pill__takeover-back:hover  { background: var(--t-c-overlay-4); }
.t-search-pill__takeover-back:active { transform: scale(0.94); }
.t-search-pill__takeover-back .t-mask-icon { width: calc(var(--ui-content-scale) * 18px); height: calc(var(--ui-content-scale) * 18px); }
.t-search-pill__takeover-title {
  flex: 1 1 auto;
  text-align: center;
  font-size: var(--t-fs-large);
  font-weight: var(--t-weight-medium);
  color: var(--t-c-text-primary);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* Expanded body — divider above, scrollable list, padding matches the
   firmware SearchCompletion layout. */
.t-search-pill__body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  touch-action: pan-y;
  overscroll-behavior: contain;
  border-top: calc(var(--ui-content-scale) * 1px) solid var(--t-c-bg-divider);
}

/* Home / Work shortcuts — single row, two equal columns. Matches the
   Tesla MCU shape: flat icon + single-line label, no background pill,
   no secondary "Tap to set..." line. */
.t-search-pill__shortcuts {
  display: grid;
  grid-template-columns: 1fr 1fr;
  border-bottom: calc(var(--ui-content-scale) * 1px) solid var(--t-c-overlay-2);
}
.t-search-pill__shortcut {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: var(--t-s-sm);
  padding: var(--t-s-md) var(--t-s-lg);
  cursor: pointer;
  transition: background 120ms;
}
.t-search-pill__shortcut + .t-search-pill__shortcut {
  border-left: calc(var(--ui-content-scale) * 1px) solid var(--t-c-overlay-2);
}
.t-search-pill__shortcut:hover  { background: var(--t-c-overlay-2); }
.t-search-pill__shortcut:active { background: var(--t-c-overlay-3); }
.t-search-pill__shortcut-icon {
  width: calc(var(--ui-content-scale) * 22px); height: calc(var(--ui-content-scale) * 22px);
  color: var(--t-c-text-primary);
  flex: 0 0 auto;
}
.t-search-pill__shortcut-label {
  font-size: var(--t-fs-large);
  color: var(--t-c-text-primary);
  font-weight: var(--t-weight-medium);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* When PlacesPanel is nested inside the expanded pill body, drop its
   outer chrome — the pill provides padding + scroll. */
.t-search-pill__body .t-places {
  padding: 0;
  background: transparent;
  border-radius: 0;
  height: auto;
  min-height: 0;
}
.t-search-pill__body .t-places__scroll {
  overflow: visible;    /* pill body owns the scroll */
  height: auto;
}

/* ═══ Route-line labels (navigation.uiml RouteLineLabelView) ══════════
   Tesla anchors a chip at the midpoint of every alternative-route
   polyline on the map. Selected route gets a blue-bg / white-text
   chip; alternates get a neutral surface / muted text. Tapping an
   alt switches the active route. Wasm reprojects on every map
   `move`/`zoom` tick (`state.map_view_version`). */
.t-route-line-labels {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 4;
}
/* Route badge — a water-drop pin: a rounded pill floating above the route
   with a downward pointer whose tip lands exactly on the anchor point on
   the line. The anchor pixel is set via left/top; the transform lifts the
   whole pin by its own height + pointer so the tip sits on (x, y). */
.t-rll {
  --t-rll-tip: calc(var(--ui-content-scale) * 7px);
  position: absolute;
  transform: translate(-50%, calc(-100% - var(--t-rll-tip)));
  transform-origin: bottom center;
  pointer-events: auto;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  padding: calc(var(--ui-content-scale) * 5px) calc(var(--ui-content-scale) * 13px);
  border-radius: 999px;
  background: var(--t-c-bg-nav-primary);
  border: none;
  box-shadow: 0 calc(var(--ui-content-scale) * 3px) calc(var(--ui-content-scale) * 10px) rgba(0, 0, 0, 0.4);
  backdrop-filter: blur(calc(var(--ui-content-scale) * 14px));
  -webkit-backdrop-filter: blur(calc(var(--ui-content-scale) * 14px));
  /* Alts default to muted text; selected variant overrides below. */
  color: var(--t-c-route-alt-duration);
  transition: transform 120ms ease-out;
  white-space: nowrap;
}
/* The drop tip — a downward triangle whose colour tracks the pill bg. */
.t-rll::after {
  content: "";
  position: absolute;
  top: 100%;
  left: 50%;
  width: 0;
  height: 0;
  transform: translate(-50%, -1px);
  border-left: var(--t-rll-tip) solid transparent;
  border-right: var(--t-rll-tip) solid transparent;
  border-top: var(--t-rll-tip) solid var(--t-c-bg-nav-primary);
}
.t-rll:hover { transform: translate(-50%, calc(-100% - var(--t-rll-tip))) scale(1.05); }
.t-rll--single { padding: calc(var(--ui-content-scale) * 5px) calc(var(--ui-content-scale) * 13px); }
.t-rll--selected {
  background: var(--t-c-blue);
  color: #fff;
  z-index: 1;
}

/* Lane-guidance badge (Yandex-style) — a blue rounded card floating above a
   junction with a downward tail pointing to it. A row of lane arrows: the lane
   valid for the maneuver is bright white, the rest dimmed. Distance below. */
/* Lane-guidance speech bubble. The CARD carries ONE drop-shadow that covers the
   card AND its overflowing tail child, so the tail reads as an integral part of
   the bubble (no seam / no stuck-on triangle). */
.t-lane-card {
  position: absolute;
  transform: translate(-50%, -50%);
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: calc(var(--ui-content-scale) * 3px);
  padding: calc(var(--ui-content-scale) * 9px) calc(var(--ui-content-scale) * 13px);
  border-radius: calc(var(--ui-content-scale) * 15px);
  background: var(--t-c-blue);
  white-space: nowrap;
  pointer-events: none;
  z-index: 6;
  filter: drop-shadow(0 calc(var(--ui-content-scale) * 3px) calc(var(--ui-content-scale) * 8px) rgba(0, 0, 0, 0.45));
  -webkit-filter: drop-shadow(0 calc(var(--ui-content-scale) * 3px) calc(var(--ui-content-scale) * 8px) rgba(0, 0, 0, 0.45));
}
/* Tail: BEHIND the card bg + content (same blue -> invisible on the card,
   visible only where it overflows onto the road). Pivots at its left-middle. */
.t-lane-tail {
  position: absolute;
  z-index: -1;
  transform-origin: 0 50%;
  pointer-events: none;
}
.t-lane-row {
  display: flex;
  align-items: flex-end;
  gap: calc(var(--ui-content-scale) * 4px);
}
.t-lane-arw {
  width: calc(var(--ui-content-scale) * 29px);
  height: calc(var(--ui-content-scale) * 34px);
}
.t-lane-badge__dist {
  font-size: calc(var(--ui-content-scale) * 16px);
  font-weight: var(--t-weight-bold);
  color: #fff;
  letter-spacing: 0.2px;
}
.t-rll--selected::after { border-top-color: var(--t-c-blue); }
.t-rll__row {
  display: flex;
  align-items: center;
  gap: calc(var(--ui-content-scale) * 6px);
}
.t-rll__row--two {
  font-size: var(--t-fs-base);
  opacity: 0.85;
}
.t-rll__duration {
  font-size: var(--t-fs-large);
  font-weight: var(--t-weight-bold);
  letter-spacing: 0;
}
.t-rll--selected .t-rll__duration { color: #fff; }
.t-rll__desc {
  font-size: var(--t-fs-base);
  font-weight: var(--t-weight-medium);
  color: inherit;
}
/* Phase 4 — extras line (traffic-lights count + toll fee from
   the wire). Sits next to the description with a separator dot.
   Slightly de-emphasised so the description stays the primary
   read. */
.t-rll__extras {
  font-size: var(--t-fs-base);
  color: inherit;
  opacity: 0.85;
  margin-left: calc(var(--ui-content-scale) * 6px);
}
.t-rll__extras::before {
  content: "·";
  margin-right: calc(var(--ui-content-scale) * 6px);
  opacity: 0.6;
}
.t-rll__row--two .t-rll__extras:first-child::before {
  content: none;          /* no leading dot when there's no description */
  margin-right: 0;
}

/* ═══ Upcoming rest area (navigation.uiml) ════════════════════════════
   Firmware spec: PositionType:absolute, Right:100 from map-area right
   edge, two horizontal cards each 240×80. We clear the viewport top
   via safe-area-inset-top + a small visual buffer so the cards never
   clip on devices without a Tesla-style top status bar, and stay
   clear of the right-strip pill on the right. */
.t-rest-area {
  display: flex; flex-direction: row;
  gap: calc(var(--ui-content-scale) * 1px);
  position: absolute;
  right: calc(max(calc(var(--ui-content-scale) * 16px), env(safe-area-inset-right, calc(var(--ui-content-scale) * 16px))) + calc(var(--ui-content-scale) * 88px));
  top: calc(max(calc(var(--ui-content-scale) * 16px), env(safe-area-inset-top, calc(var(--ui-content-scale) * 16px))) + calc(var(--ui-content-scale) * 4px));
  z-index: 4;
}
.t-rest-area__card {
  width: calc(var(--ui-content-scale) * 240px);
  border-radius: var(--t-r-card);
  overflow: hidden;
  box-shadow: var(--t-shadow-card);
}
.t-rest-area__card--first { background: var(--t-c-rest-area-first); }
.t-rest-area__card--second { background: var(--t-c-rest-area-second); }
.t-rest-area__row {
  width: calc(var(--ui-content-scale) * 240px); min-height: calc(var(--ui-content-scale) * 80px);
  padding: calc(var(--ui-content-scale) * 5px) calc(var(--ui-content-scale) * 20px);
  display: flex; align-items: center;
}
.t-rest-area__icon {
  width: calc(var(--ui-content-scale) * 48px); height: calc(var(--ui-content-scale) * 48px);
  margin-right: calc(var(--ui-content-scale) * 10px);
  flex-shrink: 0;
}
.t-rest-area__labels {
  flex: 1;
  display: flex; flex-direction: column;
  justify-content: space-between;
  align-self: stretch;
  padding: calc(var(--ui-content-scale) * 6px) 0;
  min-width: 0;
}
.t-rest-area__mileage {
  font-size: var(--t-size-body1);
  font-weight: var(--t-weight-medium);
  color: rgba(255,255,255,0.90);
  line-height: 1.1;
}
.t-rest-area__name {
  font-size: var(--t-size-caption1);
  color: rgba(255,255,255,0.60);
  line-height: 1.1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ═══ Speed radar zone (navigation.uiml) ══════════════════════════════
   The capsule background-image URL is set as the CSS custom
   property `--t-asset-speed-capsule` from JS at boot (see the shim
   in index.html), so the asset base stays runtime-configurable. */
.t-speed-radar {
  width: calc(var(--ui-content-scale) * 70px); height: calc(var(--ui-content-scale) * 220px);
  padding: calc(var(--ui-content-scale) * 3px) 0 calc(var(--ui-content-scale) * 16px) 0;
  background-image: var(--t-asset-speed-capsule);
  background-repeat: no-repeat;
  background-size: contain;
  background-position: center;
  display: flex; flex-direction: column; align-items: center;
}
.t-speed-radar__inner {
  width: calc(var(--ui-content-scale) * 70px); height: calc(var(--ui-content-scale) * 201px);
  padding: calc(var(--ui-content-scale) * 6px) 0;
  display: flex; flex-direction: column;
  align-items: center; justify-content: space-between;
}
.t-speed-radar__sign {
  width: calc(var(--ui-content-scale) * 66px); height: calc(var(--ui-content-scale) * 66px);
  background: var(--t-c-pure-white);
  border-radius: 50%;
  border: calc(var(--ui-content-scale) * 6px) solid var(--t-c-red);
  display: flex; align-items: center; justify-content: center;
  font-size: var(--t-fs-2xlarge);
  font-weight: 700;
  color: var(--t-c-pure-black);
  font-family: var(--t-font-mono);
}
.t-speed-radar__labels {
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  flex: 1;
  padding: calc(var(--ui-content-scale) * 6px) 0;
}
.t-speed-radar__value {
  font-size: var(--t-fs-xlarge);
  font-family: var(--t-font-mono);
  font-weight: 500;
  color: var(--t-c-text-primary);
}
.t-speed-radar__value--over { color: var(--t-c-red); }
.t-speed-radar__title {
  font-size: var(--t-fs-base);
  color: var(--t-c-text-secondary);
}


/* QuietMode — firmware NAVGUI_quietMode + NavigationQuietMapAction.
 * Reduces the nav chrome's visual intensity so the driver can focus
 * on the road.  Tesla dims the panel + softens label colours; CSS
 * mirror: 35 % opacity on the sheet chrome.  Children stay
 * interactive (pointer-events untouched). */
.t-shell__left[data-quiet="true"] {
  opacity: 0.35;
  transition: opacity 240ms cubic-bezier(.32,.72,0,1);
}
.t-shell__left[data-quiet="true"]:hover,
.t-shell__left[data-quiet="true"]:focus-within {
  opacity: 1;
}

/* ═══ Turn panel wrapper — FirstTurn + TurnList + Grabber ═════════════
 * Single continuous chrome.  Width clamps between phone-friendly
 * 280 px and Tesla MCU's 430 px (`UnifiedTurnListWidth` from
 * styles-common.conf:222 — real MCU is 1920 wide so 430 px ≈ 22 %).
 * The shared bg + rounded border live ONLY on the wrapper so the
 * FirstTurn / TurnList / Grabber siblings appear as one card. */
.t-turn-panel {
  background: var(--t-c-bg-nav-primary);
  backdrop-filter: blur(calc(var(--ui-content-scale) * 20px));
  -webkit-backdrop-filter: blur(calc(var(--ui-content-scale) * 20px));
  border-radius: var(--t-r-card);
  box-shadow: var(--t-shadow-card);
  /* Panel is a swipe-to-collapse surface; the .TurnListScroll child keeps
     touch-action:pan-y so the list still scrolls. */
  touch-action: none;
  width: clamp(calc(var(--ui-content-scale) * 280px), 35vw, calc(var(--ui-content-scale) * 430px));
  max-width: calc(var(--ui-content-scale) * 430px);
  align-self: flex-start;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  color: var(--t-c-text-primary);
  transition: flex 240ms cubic-bezier(.32,.72,0,1);
}
/* When the turn list is shown, the panel grows to fill the column
 * so the TurnList scroll has room.  When hidden, the panel shrink-
 * wraps to FirstTurn + grabber so the grabber sits flush below the
 * FirstTurn card (no empty vertical gap). */
.t-turn-panel.is-list-shown  { flex: 1 1 auto; }
.t-turn-panel.is-list-hidden { flex: 0 0 auto; }

/* ═══ First-turn card (turn_list.uiml) ════════════════════════════════
 * Lives INSIDE `.t-turn-panel`.  No bg / radius / shadow — those are
 * on the wrapper so the cards visually merge into one continuous
 * panel.  Same for `.TurnList` below. */
.t-first-turn {
  background: transparent;
  width: 100%;
  align-self: stretch;
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  box-shadow: none;
  border-radius: 0;
  color: inherit;
}
.t-first-turn__top {
  display: flex; align-items: center;
  /* firmware [FirstTurn] TopContainer Padding:20,30,30,30 (t,r,b,l) */
  padding: calc(var(--ui-content-scale) * 20px) calc(var(--ui-content-scale) * 30px)
           calc(var(--ui-content-scale) * 30px) calc(var(--ui-content-scale) * 30px);
}
.t-first-turn__image {
  /* Sized to match the turn-list rows (t-normal-turn__image) so the glyphs read
     uniform — the straight-arrow first turn otherwise fills the taller firmware
     90px box floor-to-ceiling and dwarfs the compact L-shaped turn arrows. */
  width: clamp(calc(var(--ui-content-scale) * 48px), calc(2.4vw + calc(var(--ui-content-scale) * 40px)), calc(var(--ui-content-scale) * 70px));
  height: clamp(calc(var(--ui-content-scale) * 48px), calc(2.4vw + calc(var(--ui-content-scale) * 40px)), calc(var(--ui-content-scale) * 70px));
  /* firmware TurnImage Margin:-10 — but NOT on the right: a negative right
     margin pulls the labels leftward under the icon (the labels carry no left
     margin), so the icon overlaps the text. Keep the offset on the other three
     sides for card-edge alignment / vertical centering. */
  margin: calc(var(--ui-content-scale) * -10px) 0
          calc(var(--ui-content-scale) * -10px) calc(var(--ui-content-scale) * -10px);
  flex-shrink: 0;
}
.t-first-turn__labels {
  /* firmware LabelsContainer Margin:20,0,0,0 — top only, NOT left (the
     prior margin-left added horizontal space firmware doesn't have). */
  margin: calc(var(--ui-content-scale) * 20px) 0 0 0;
  flex: 1;
  display: flex; flex-direction: column;
  min-width: 0;
}
.t-first-turn__top-row {
  display: flex; align-items: center;
  justify-content: space-between;
  gap: calc(var(--ui-content-scale) * 20px);
}
.t-first-turn__mileage {
  /* Fluid type: ~28 on phone up to 42 on Tesla MCU. */
  font-size: calc(var(--ui-font-scale) * 42px);
  font-weight: var(--t-weight-medium);
  color: var(--t-c-text-primary);
  line-height: 1.0;
  letter-spacing: -0.02em;
  font-family: var(--t-font-mono);
}
.t-first-turn__exit {
  padding: calc(var(--ui-content-scale) * 5px) calc(var(--ui-content-scale) * 10px);
  background: var(--t-c-overlay-5);
  border-radius: calc(var(--ui-content-scale) * 4px);
  font-size: var(--t-size-caption1);
  color: var(--t-c-text-primary);
  text-align: center;
}
.t-first-turn__bottom-row {
  display: flex; align-items: center;
  justify-content: space-between;
  margin-top: calc(var(--ui-content-scale) * 5px);
}
.t-first-turn__street {
  font-size: var(--t-fs-large);
  color: var(--t-c-text-secondary);
  flex: 1;
  min-width: 0;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.t-first-turn__shield {
  display: flex; flex-direction: column;
  align-items: center;
  margin-left: var(--t-s-lg);
  min-width: clamp(calc(var(--ui-content-scale) * 40px), calc(1.5vw + calc(var(--ui-content-scale) * 36px)), calc(var(--ui-content-scale) * 50px));
}
.t-first-turn__cardinal {
  font-size: var(--t-fs-base);
  color: var(--t-c-text-primary);
  margin: 0 calc(var(--ui-content-scale) * 6px);
}
.t-first-turn__shield-label {
  font-size: var(--t-fs-base);
  background: var(--t-c-pure-white);
  color: var(--t-c-pure-black);
  font-weight: 700;
  padding: calc(var(--ui-content-scale) * 2px) calc(var(--ui-content-scale) * 6px);
  border-radius: calc(var(--ui-content-scale) * 3px);
  margin-top: calc(var(--ui-content-scale) * 2px);
}
.t-first-turn__divider {
  height: calc(var(--ui-content-scale) * 2px);
  background: var(--t-c-bg-divider);
  align-self: stretch;
  margin: 0 calc(var(--ui-content-scale) * 20px);
}
/* Lane-nav pill — single-status badge derived from the wire's
   LaneNavInterval.type. Two visible variants: warn (PossiblyAvailable)
   and bad (Unavailable). Available is silent. */
.t-first-turn__lane-pill {
  margin: calc(var(--ui-content-scale) * 8px) calc(var(--ui-content-scale) * 20px) 0;
  padding: calc(var(--ui-content-scale) * 6px) calc(var(--ui-content-scale) * 12px);
  border-radius: calc(var(--ui-content-scale) * 6px);
  font-size: var(--t-fs-base);
  font-weight: var(--t-weight-medium);
  text-align: center;
  letter-spacing: 0.02em;
}
.t-first-turn__lane-pill--warn {
  background: var(--t-c-warning-bg);
  color: var(--t-c-yellow);
}
.t-first-turn__lane-pill--bad {
  background: var(--t-c-error-bg);
  color: var(--t-c-red);
}

/* ═══ Normal turn rows (turn_list.uiml) ═══════════════════════════════ */
.t-normal-turn {
  display: flex;
  align-items: center;
  padding: var(--t-s-lg) var(--t-s-xl) var(--t-s-lg) var(--t-s-lg);
  width: 100%;
  color: var(--t-c-text-primary);
}
.t-normal-turn__image {
  width: clamp(calc(var(--ui-content-scale) * 48px), calc(2.4vw + calc(var(--ui-content-scale) * 40px)), calc(var(--ui-content-scale) * 70px));
  height: clamp(calc(var(--ui-content-scale) * 48px), calc(2.4vw + calc(var(--ui-content-scale) * 40px)), calc(var(--ui-content-scale) * 70px));
  flex-shrink: 0;
}
.t-normal-turn__street {
  font-size: var(--t-fs-large);
  color: var(--t-c-text-secondary);
  flex: 1;
  margin-left: var(--t-s-xl);
  min-width: 0;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.t-normal-turn__mileage {
  /* firmware NormalTurn/ItemMileage = Text/Body1 (styles-common.conf:578) */
  font-size: var(--t-size-body1);
  color: var(--t-c-text-secondary);
  margin-left: var(--t-s-md);
  white-space: nowrap;
}

/* ═══ Turn list container — wraps the firmware UIML scroll body. ═══════
 * The UIML doesn't name the outer pane (it sits inside the sheet that
 * `turn_list.uiml` is templated into); these two classes wrap the
 * area that scrolls the NavWayPointList + NormalTurnView rows. */
.TurnList {
  /* Inherits chrome from `.t-turn-panel`.  Borderless / transparent
   * so the turn list merges visually with the FirstTurn above it. */
  background: transparent;
  box-shadow: none;
  border-radius: 0;
  margin-top: 0;
  width: 100%;
  align-self: stretch;
  display: flex; flex-direction: column;
  overflow: hidden;
  flex: 1 1 auto;
  min-height: 0;
  transition: flex-basis 240ms cubic-bezier(.32,.72,0,1),
              max-height 240ms cubic-bezier(.32,.72,0,1);
}
/* Firmware show/hide (NavigationWindow::hideAllNavUI / showAllNavUI):
 * the entire left-column nav chrome (FirstTurn + TurnList) slides
 * OFF-SCREEN to the left when hidden — it does NOT shrink in place.
 * Triggered by tap on the map (hide), tap/swipe up on the grabber
 * (show), or swipe down (hide). */
.TurnList--expanded {
  flex: 1 1 auto;
  transition: transform 240ms cubic-bezier(.32,.72,0,1),
              opacity   240ms cubic-bezier(.32,.72,0,1);
}
.TurnList--collapsed {
  flex: 0 0 0;
  max-height: 0;
  min-height: 0;
  margin: 0;
  padding: 0;
  border: none;
  overflow: hidden;
  opacity: 0;
  transform: translateX(-110%);
  pointer-events: none;
  transition: transform 240ms cubic-bezier(.32,.72,0,1),
              opacity   240ms cubic-bezier(.32,.72,0,1),
              flex-basis 240ms cubic-bezier(.32,.72,0,1),
              max-height 240ms cubic-bezier(.32,.72,0,1);
}
.TurnListScroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  display: flex; flex-direction: column;
  touch-action: pan-y;
  overscroll-behavior: contain;
}

/* ═══ Split bottom view (turn_list.uiml) ══════════════════════════════ */
.t-bottom-view {
  background: var(--t-c-bg-nav-primary);
  backdrop-filter: blur(calc(var(--ui-content-scale) * 20px));
  -webkit-backdrop-filter: blur(calc(var(--ui-content-scale) * 20px));
  border-radius: var(--t-r-card);
  /* The whole view is a swipe surface (up=open More, down=close); it has
     no inner scroll, so claim the vertical gesture from native scroll. */
  touch-action: none;
  display: flex; flex-direction: column;
  overflow: hidden;
  box-shadow: var(--t-shadow-card);
  /* Same responsive width as the turn panel so the two chrome
   * surfaces line up column-true (UnifiedTurnListWidth = 430 px
   * upper bound, phone-friendly 280 px floor). */
  width: clamp(calc(var(--ui-content-scale) * 280px), 35vw, calc(var(--ui-content-scale) * 430px));
  max-width: calc(var(--ui-content-scale) * 430px);
  align-self: flex-start;
}
/* TurnListBottomBar (turn_list.uiml:114-116) — UnifiedTurnListWidth=430,
 * JustifyContent: center, TouchPadding:0,15,0,15 (calc(var(--ui-content-scale) * 15px) hit area top+bottom).
 * The grab handle itself is rendered as a flat pill via MaskedIcon →
 * .t-bottom-view__grab-pill (around line 3623 of this file). */
.t-bottom-view__grabber {
  display: flex; justify-content: center;
  padding: calc(var(--ui-content-scale) * 15px) 0;
  cursor: pointer;
  /* own the vertical swipe (open/close More) instead of native scroll */
  touch-action: none;
}
.t-bottom-view__content {
  padding: 0 var(--t-s-lg) var(--t-s-lg);
  display: flex; flex-direction: column;
}
/* SplitTurnListNavArrivalInfoView (turn_list.uiml:164-169) — hlayout,
 * AlignItems:center, JustifyContent:spaceBetween. ArrivalTime on the
 * left, Time/Distance pair on the right. */
.t-bottom-view__arrival {
  display: flex; align-items: center;
  justify-content: space-between;
  margin-bottom: calc(var(--ui-content-scale) * 6px);          /* TopContainer Margin:0,0,0,6 */
}
/* NavArrivalInfoView/ArrivalTimeLabel — FontSize:20 bold,
 * Color:nav_v2/arrival_info (var(--t-c-nav-arrival-info) night). */
.t-bottom-view__arrival-time {
  font-size: calc(var(--ui-font-scale) * 20px);
  font-weight: var(--t-weight-bold);
  color: var(--t-c-nav-arrival-info);
  font-family: var(--t-font);
}
/* SplitTurnListBottomView/TimeToDestinationLabel +
 * DistanceToDestinationLabel — same FontSize:20 bold +
 * nav_v2/arrival_info colour, sit next to each other with a gap. */
.t-bottom-view__arrival-right {
  display: flex; align-items: center;
  gap: calc(var(--ui-content-scale) * 12px);
  font-size: calc(var(--ui-font-scale) * 20px);
  font-weight: var(--t-weight-bold);
  color: var(--t-c-nav-arrival-info);
}
.t-bottom-view__dest-row {
  display: flex; align-items: center;
  justify-content: space-between;
  align-self: stretch;
}
.t-bottom-view__dest-marker {
  width: calc(var(--ui-content-scale) * 24px); height: calc(var(--ui-content-scale) * 24px);
  margin-right: calc(var(--ui-content-scale) * 10px);
  border-radius: 50%;
  background: var(--t-c-blue);
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  /* Pin glyph sits on a coloured circle — stays white in all themes. */
  color: var(--t-c-on-accent);
}
.t-bottom-view__dest-marker svg { width: calc(var(--ui-content-scale) * 14px); height: calc(var(--ui-content-scale) * 14px); fill: currentColor; }
.t-bottom-view__dest-marker .t-mask-icon { width: calc(var(--ui-content-scale) * 14px); height: calc(var(--ui-content-scale) * 14px); }
.t-bottom-view__dest-name {
  font-size: var(--t-size-body2);
  color: var(--t-c-text-secondary);
  flex: 1;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.t-bottom-view__battery {
  display: flex; align-items: center;
  gap: calc(var(--ui-content-scale) * 5px); margin-left: calc(var(--ui-content-scale) * 20px);
  direction: ltr;
}

.t-battery {
  width: calc(var(--ui-content-scale) * 36px); height: calc(var(--ui-content-scale) * 18px);
  border: calc(var(--ui-content-scale) * 2px) solid var(--t-c-text-secondary);
  border-radius: calc(var(--ui-content-scale) * 3px);
  position: relative; padding: calc(var(--ui-content-scale) * 2px);
}
.t-battery::after {
  content: "";
  position: absolute;
  right: calc(var(--ui-content-scale) * -4px); top: calc(var(--ui-content-scale) * 4px);
  width: calc(var(--ui-content-scale) * 2px); height: calc(var(--ui-content-scale) * 6px);
  background: var(--t-c-text-secondary);
  border-radius: 0 calc(var(--ui-content-scale) * 1px) calc(var(--ui-content-scale) * 1px) 0;
}
.t-battery__fill {
  height: 100%;
  background: var(--t-c-green);
  border-radius: calc(var(--ui-content-scale) * 1px);
  transition: width var(--t-trans-normal);
}
.t-battery__fill--low { background: var(--t-c-yellow); }
.t-battery__fill--critical { background: var(--t-c-red); }
.t-battery__pct {
  font-size: var(--t-size-body2);
  color: var(--t-c-text-secondary);
  font-variant-numeric: tabular-nums;
}

/* SplitTurnListBottomView/Divider — DividerColor:Background/lines.
 * Resolved: night #FFFFFF:0D (rgba(255,255,255,0.05)). */
.t-bottom-view__divider {
  height: calc(var(--ui-content-scale) * 2px);
  background: var(--t-c-bg-divider);
  margin: calc(var(--ui-content-scale) * 16px) 0;
}
/* TurnListButtonsContainer (turn_list.uiml:152-158) — hlayout,
 * AlignItems:center, with specific widths: NoA=80, End Trip=270,
 * More=80. Heights:60 (default Tesla button height). */
.t-bottom-view__buttons {
  display: flex; align-items: center;
  justify-content: center;
  gap: calc(var(--ui-content-scale) * 20px);                    /* NoAToggle Margin:0,0,20,0 + MoreButton Margin:20,0,0,0 */
}
.t-button-divider {
  width: calc(var(--ui-content-scale) * 2px); height: calc(var(--ui-content-scale) * 50px);     /* ClusterNavigationCard/VDivider 50×2 */
  background: var(--t-c-bg-divider);
  margin: 0 var(--t-s-md);
  flex-shrink: 0;
}
/* Tesla TurnListButton family (turn_list.uiml:143-150 + styles-common.conf:475-480):
 * NoA=80, End Trip=270, More=80 in firmware (UnifiedTurnListWidth=430).
 *
 * Tesla's runtime uses 9-slice control/buttons/square_button_default_60.png
 * (NineSlice 10,10,10,10). CSS `background-size: 100% 100%` would distort
 * the corner cuts, so we paint the equivalent appearance directly — flat
 * rounded rectangle with the same Background/transparent_primary fill +
 * Text/secondary label. The visual result matches firmware without the
 * stretched-PNG artefacts.
 *
 * On narrow viewports the End Trip button flexes to fill while NoA + More
 * keep a 56-min touch target. */
.t-tl-btn {
  min-height: calc(var(--ui-content-scale) * 60px);
  border: none;
  border-radius: calc(var(--ui-content-scale) * 6px);
  background: var(--t-c-overlay-5);    /* Background/transparent_primary */
  color: var(--t-c-text-secondary);
  font-size: calc(var(--ui-font-scale) * 18px);
  font-weight: var(--t-weight-medium);
  padding: 0 calc(var(--ui-content-scale) * 12px);
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
  transition: var(--t-trans-quick);
  min-width: 0;
}
.t-tl-btn:hover { background: var(--t-c-overlay-7); color: var(--t-c-text-primary); }
.t-tl-btn:active { transform: scale(0.98); }
/* End Trip — Tesla Width:270 ideal; here it takes whatever's left so the
 * row fits any column width. The label uses Body1=24 emphasis since
 * "End Trip" is the primary action of this row. */
.t-tl-btn--end {
  flex: 1 1 auto;
  min-width: 0;
  font-size: calc(var(--ui-font-scale) * 22px);
}
/* NoA toggle — Width:80 firmware. flex 0 0 80 means it never grows or
 * shrinks; on viewports narrower than ~430 the End Trip flex absorbs
 * the deficit without squashing NoA. */
.t-tl-btn--noa {
  flex: 0 0 calc(var(--ui-content-scale) * 80px);
  font-size: calc(var(--ui-font-scale) * 14px);
  letter-spacing: 0.02em;
}
/* NoA active = Tesla blue glow (square_button_toggle_selected.png). */
.t-tl-btn--noa.active {
  background: var(--t-c-blue-bright);
  color: #FFFFFF;
  box-shadow: 0 0 0 calc(var(--ui-content-scale) * 1px) rgba(62,106,225,0.55), 0 0 calc(var(--ui-content-scale) * 12px) rgba(62,106,225,0.30);
}
/* More button — same fixed 80 width, identical floor. */
.t-tl-btn--more {
  flex: 0 0 calc(var(--ui-content-scale) * 80px);
}
.t-tl-btn--more img {
  width: calc(var(--ui-content-scale) * 24px); height: calc(var(--ui-content-scale) * 24px);
  opacity: 0.85;
}

/* ═══ MoreInfo — turn_list.uiml:183-197 ════════════════════════════════
 * Firmware-faithful 1:1 with styles-M3.conf:1793 + styles-common.conf:501:
 *   MoreInfo:           JustifyContent:spacebetween; Height:240 (3×80)
 *   TurnListMoreButton: Width:370, Height:80, Text/Body2 (calc(var(--ui-content-scale) * 22px)),
 *                       ImagePadding:-40,0,-300,0 → icon 40 px from
 *                       left of button, LabelPadding:-110,0,0,0 →
 *                       label sits ~110 px right of icon.
 *   MoreInfoButtonColors: icon = Text/primary always,
 *                         label = Text/secondary (primary on hover).
 *   Chevron <ImageView Margin="0,0,40,0"> → 40 px right margin.
 *
 * Row total layout (in a 430-px panel):
 *   [── 24 px ─── icon ── 16 px ── label ───── chevron ── 40 px ──]
 *   [───────────────── 80 px tall ──────────────────────────────]
 */
.MoreInfo {
  display: flex;
  flex-direction: column;
}
.MoreInfoRow {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: calc(var(--ui-content-scale) * 80px);                  /* TurnListMoreButton Height:80 */
  width: 100%;
  cursor: pointer;
  color: var(--t-c-text-secondary);   /* MoreInfoButtonColors */
  padding-left: calc(var(--ui-content-scale) * 24px);            /* aligned with row content column */
  transition: color 120ms ease-out;
}
.MoreInfoRow:hover { color: var(--t-c-text-primary); }
.MoreInfoRow__left {
  display: flex;
  align-items: center;
  gap: calc(var(--ui-content-scale) * 16px);                     /* icon → label spacing */
}
.MoreInfoRow .TurnListMoreButton__icon {
  width: calc(var(--ui-content-scale) * 32px);
  height: calc(var(--ui-content-scale) * 32px);
  background-color: var(--t-c-text-primary); /* ButtonImageNormalColor */
  flex-shrink: 0;
}
.MoreInfoRow .TurnListMoreButton__label {
  font-size: calc(var(--ui-font-scale) * 22px);               /* Text/Body2 */
  color: inherit;                /* secondary in normal, primary on hover */
  line-height: 1.2;
}
.MoreInfoRow__chevron {
  width: calc(var(--ui-content-scale) * 14px);
  height: calc(var(--ui-content-scale) * 24px);
  opacity: 0.6;
  margin-right: calc(var(--ui-content-scale) * 40px);            /* turn_list.uiml:187 Margin:0,0,40,0 */
  flex-shrink: 0;
}

/* ═══ Current location bubble ═════════════════════════════════════════ */
.t-current-location {
  background: var(--t-c-bg-nav-primary);
  backdrop-filter: blur(calc(var(--ui-content-scale) * 20px));
  -webkit-backdrop-filter: blur(calc(var(--ui-content-scale) * 20px));
  border-radius: var(--t-r-card);
  padding: var(--t-s-sm) var(--t-s-md);
  display: inline-flex;
  flex-direction: column;
  max-width: min(calc(var(--ui-content-scale) * 380px), calc(100vw - calc(var(--ui-content-scale) * 32px)));
  position: absolute;
  right: max(var(--t-s-lg), env(safe-area-inset-right, var(--t-s-lg)));
  bottom: max(var(--t-s-lg), env(safe-area-inset-bottom, var(--t-s-lg)));
  z-index: 4;
  box-shadow: var(--t-shadow-card);
}
.t-current-location__street {
  font-size: var(--t-fs-xlarge);
  font-weight: var(--t-weight-bold);
  color: var(--t-c-text-primary);
  line-height: 1.2;
}
.t-current-location__region {
  font-size: var(--t-fs-base);
  color: var(--t-c-text-secondary);
  line-height: 1.2;
}

/* ═══ Places search panel ═════════════════════════════════════════════ */
.t-places {
  display: flex; flex-direction: column;
  background: var(--t-c-bg-nav-primary);
  backdrop-filter: blur(calc(var(--ui-content-scale) * 20px));
  -webkit-backdrop-filter: blur(calc(var(--ui-content-scale) * 20px));
  border-radius: var(--t-r-card);
  overflow: hidden;
  /* Fills the sheet's remaining flex slot. The sheet root is
     100 dvh tall, so the card stretches all the way down — but
     it's clipped by the viewport because the sheet itself is
     translated below the visible area. */
  flex: 1 1 auto;
  min-height: 0;
  box-shadow: var(--t-shadow-card);
}
.t-places__scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  display: flex; flex-direction: column;
  touch-action: pan-y;
  overscroll-behavior: contain;
}
.t-place-row {
  min-height: clamp(calc(var(--ui-content-scale) * 72px), calc(3vw + calc(var(--ui-content-scale) * 60px)), calc(var(--ui-content-scale) * 105px));
  display: flex; align-items: center;
  padding: var(--t-s-sm) 0 var(--t-s-sm) var(--t-s-lg);
  border-bottom: calc(var(--ui-content-scale) * 1px) solid var(--t-c-bg-transparent-secondary);
  transition: var(--t-trans-quick);
}
.t-place-row:hover { background: var(--t-c-overlay-1); }
.t-place-row:last-child { border-bottom: none; }
.t-place-row__drag {
  width: calc(var(--ui-content-scale) * 24px);
  display: flex; flex-direction: column;
  align-items: center; gap: calc(var(--ui-content-scale) * 3px);
  margin-right: calc(var(--ui-content-scale) * 16px);
  cursor: grab;
  flex-shrink: 0;
}
.t-place-row__drag span {
  width: calc(var(--ui-content-scale) * 16px); height: calc(var(--ui-content-scale) * 2px);
  background: var(--t-c-text-secondary);
  border-radius: calc(var(--ui-content-scale) * 1px);
}
.t-place-row__labels {
  flex: 1;
  display: flex; flex-direction: column;
  justify-content: center;
  gap: calc(var(--ui-content-scale) * 5px);
  min-width: 0;
}
.t-place-row__title {
  font-size: var(--t-size-body2);
  color: var(--t-c-text-primary);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.t-place-row__subtitle {
  font-size: var(--t-size-caption1);
  color: var(--t-c-text-secondary);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Today's opening hours, shown between address and any charger/info
   lines. Green for "Open" / "Open 24/7", red-muted for "Closed". */
.t-place-row__hours {
  margin-top: calc(var(--ui-content-scale) * 2px);
  font-size: var(--t-fs-base);
  color: var(--t-c-text-secondary);
}
.t-place-row__hours-label { font-weight: var(--t-weight-medium); }
.t-place-row__hours--open .t-place-row__hours-label {
  color: var(--t-c-green);
}
.t-place-row__hours--closed {
  color: var(--t-c-red, var(--t-c-error-fg));
  font-weight: var(--t-weight-medium);
}
.t-place-row__charger-info {
  display: flex; gap: calc(var(--ui-content-scale) * 8px);
  margin-top: calc(var(--ui-content-scale) * 2px);
  font-size: var(--t-fs-base);
  color: var(--t-c-text-secondary);
}
.t-place-row__charger-info strong {
  color: var(--t-c-text-primary);
  font-weight: var(--t-weight-medium);
}
.t-place-row__details {
  width: clamp(calc(var(--ui-content-scale) * 60px), calc(3vw + calc(var(--ui-content-scale) * 52px)), calc(var(--ui-content-scale) * 85px));
  height: clamp(calc(var(--ui-content-scale) * 60px), calc(3vw + calc(var(--ui-content-scale) * 52px)), calc(var(--ui-content-scale) * 85px));
  display: flex; flex-direction: column;
  align-items: center; justify-content: space-between;
  padding: var(--t-s-xs) 0;
  margin-right: var(--t-s-xs);
  border-left: calc(var(--ui-content-scale) * 1px) solid var(--t-c-bg-transparent-secondary);
  flex-shrink: 0;
}
/* Neutral rounded-rect pill — matches the cream/off-white pill the
   Tesla MCU draws to the right of every recent/result row, with the
   small open-ring marker icon above the km text. The coloured-pin
   variants below override the surface for saved Home / Work only. */
.t-place-row__pin {
  width: clamp(calc(var(--ui-content-scale) * 44px), calc(2.5vw + calc(var(--ui-content-scale) * 36px)), calc(var(--ui-content-scale) * 56px));
  height: clamp(calc(var(--ui-content-scale) * 44px), calc(2.5vw + calc(var(--ui-content-scale) * 36px)), calc(var(--ui-content-scale) * 56px));
  border-radius: calc(var(--ui-content-scale) * 12px);
  background: var(--t-c-overlay-4);
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  color: var(--t-c-text-primary);
}
.t-place-row__pin svg { width: calc(var(--ui-content-scale) * 28px); height: calc(var(--ui-content-scale) * 28px); fill: currentColor; }
.t-place-row__pin .t-mask-icon { width: calc(var(--ui-content-scale) * 22px); height: calc(var(--ui-content-scale) * 22px); }
.t-place-row__pin--home {
  background: var(--t-c-blue);
  color: var(--t-c-on-accent);
  border-radius: 50%;
}
.t-place-row__pin--work {
  background: var(--t-c-pin-work);
  color: var(--t-c-on-accent);
  border-radius: 50%;
}
.t-place-row__distance {
  font-size: var(--t-fs-base);
  color: var(--t-c-text-secondary);
  margin-top: calc(var(--ui-content-scale) * 4px);
}

/* ═══ Info window (map_info.uiml) ═════════════════════════════════════
   Left-side panel — verified against real Tesla MCU screenshots
   (TUMO, Florence, Basketball Court). Fills the left column's full
   height; scroll body holds the content below the close-button row.
*/
.t-info-window {
  background: var(--t-c-bg-nav-primary);
  backdrop-filter: blur(calc(var(--ui-content-scale) * 20px));
  -webkit-backdrop-filter: blur(calc(var(--ui-content-scale) * 20px));
  border-radius: var(--t-r-card);
  width: 100%;
  padding: 0;
  display: flex; flex-direction: column;
  overflow: hidden;
  margin-top: 0;
  flex: 1 1 auto;
  min-height: 0;
  box-shadow: var(--t-shadow-card);
}

/* Phase 6 — critical_information warning row. Red chrome + warning
   icon. Sits above the access section in render_body. */
.t-info-window__critical-row {
  display: flex; align-items: center;
  gap: var(--t-s-sm);
  padding: var(--t-s-md);
  margin: var(--t-s-sm) 0;
  background: rgba(229, 71, 71, 0.18);   /* red 0.18 alpha */
  border-radius: var(--t-r-card);
  color: var(--t-c-red);
}
.t-info-window__critical-row .t-mask-icon { flex-shrink: 0; }
.t-info-window__critical-row span {
  font-size: var(--t-fs-base);
  line-height: 1.4;
}

/* Phase 6 — free-text access restriction / instruction rows. Quiet
   chrome — no background, secondary text colour. */
.t-info-window__access-text {
  display: flex; flex-direction: column;
  gap: var(--t-s-xs);
  padding: var(--t-s-sm) 0;
}
.t-info-window__access-text-row {
  font-size: var(--t-fs-base);
  color: var(--t-c-text-secondary);
  line-height: 1.4;
}

/* Phase 6 — Trailer-friendly chip. Single icon + label row. */
.t-info-window__traits-row {
  display: flex; align-items: center;
  gap: var(--t-s-sm);
  padding: var(--t-s-sm) 0;
  font-size: var(--t-fs-base);
  color: var(--t-c-text-primary);
}

/* Phase 6 — Find Lower Price Charging button. Blue accent text on
   transparent ground, right-chevron trailing. */
.t-info-window__lower-cost-btn {
  display: flex; align-items: center;
  width: 100%;
  gap: var(--t-s-sm);
  padding: var(--t-s-sm) 0;
  background: transparent;
  border: none;
  color: var(--t-c-blue);
  font-size: var(--t-fs-base);
  font-weight: var(--t-weight-medium);
  cursor: pointer;
}
.t-info-window__lower-cost-btn span { flex: 1; text-align: left; }
.t-info-window__lower-cost-btn:hover { color: var(--t-c-text-primary); }

/* Phase 6 — Payment methods section. Title row + one icon+label
   row per accepted method. */
.t-info-window__payment {
  margin: var(--t-s-md) 0;
}
.t-info-window__payment-title {
  font-size: var(--t-fs-base);
  color: var(--t-c-text-secondary);
  font-weight: var(--t-weight-medium);
  margin-bottom: var(--t-s-sm);
}
.t-info-window__payment-row {
  display: flex; align-items: center;
  gap: var(--t-s-sm);
  padding: var(--t-s-xs) 0;
  font-size: var(--t-fs-base);
  color: var(--t-c-text-primary);
}
/* Top row: type label on the left, close button on the right. Sits
   in the natural document flow — no absolute positioning, so the
   scroll body below can use its full width without padding-right
   reserved for a floating X. */
.t-info-window__top-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--t-s-md);
  flex: 0 0 auto;
  /* Firmware InfoWindowDismissButton sits 22 px from top + right
     edges of the 430-wide panel; mirror that here so the close
     button has breathing room and doesn't hug the corner. */
  padding: calc(var(--ui-content-scale) * 16px) calc(var(--ui-content-scale) * 18px) calc(var(--ui-content-scale) * 8px);
}
/* Right-only variant — used by PoiView (single close button, no
   back arrow or type chip). With `space-between` + one child the
   button stuck to the LEFT; `flex-end` puts it on the right where
   it belongs. */
.t-info-window__top-row--right {
  justify-content: flex-end;
  padding: var(--t-s-md) var(--t-s-md) 0 var(--t-s-xl);
  flex: 0 0 auto;
}
.t-info-window__top-row .t-info-window__type {
  margin-bottom: 0;
  flex: 1 1 auto;
  min-width: 0;
}
.t-info-window__close {
  /* Fixed square. The earlier clamp() gave fractional pixel sizes at
     intermediate viewport widths, which made the button non-circular
     and the masked icon antialiased fuzzy. flex:0 0 auto pins width
     so the parent's `justify-content` can't stretch it. */
  width: calc(var(--ui-content-scale) * 36px);
  height: calc(var(--ui-content-scale) * 36px);
  flex: 0 0 auto;
  border-radius: 50%;
  background: var(--t-c-overlay-4);
  display: flex; align-items: center; justify-content: center;
  color: var(--t-c-text-primary);
  flex: 0 0 auto;
  transition: var(--t-trans-quick);
}
.t-info-window__close:hover { background: var(--t-c-overlay-6); }
.t-info-window__close:active { transform: scale(0.94); }
.t-info-window__close svg {
  width: var(--t-icon-sm);
  height: var(--t-icon-sm);
  fill: currentColor;
}
.t-info-window__scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: var(--t-s-md) var(--t-s-xl) var(--t-s-xl);
  touch-action: pan-y;
  overscroll-behavior: contain;
}
.t-info-window__closure-banner {
  background: var(--t-c-red);
  color: var(--t-c-on-accent);
  padding: var(--t-s-md) var(--t-s-lg);
  border-radius: calc(var(--ui-content-scale) * 6px);
  display: flex; align-items: center; gap: var(--t-s-md);
  margin-bottom: var(--t-s-lg);
  font-size: var(--t-fs-large);
}
.t-info-window__closure-banner img {
  width: var(--t-icon-sm); height: var(--t-icon-sm);
}
.t-info-window__closure-banner--partial { background: rgba(244,197,52,0.95); color: var(--t-c-pure-black); }
.t-info-window__type {
  font-size: var(--t-size-caption1);
  color: var(--t-c-text-secondary);
  display: flex; align-items: center; gap: calc(var(--ui-content-scale) * 5px);
  margin-bottom: calc(var(--ui-content-scale) * 6px);
}
.t-info-window__type img { width: calc(var(--ui-content-scale) * 18px); height: calc(var(--ui-content-scale) * 18px); }
.t-info-window__title {
  /* Screenshot-verified: title is the most prominent element; sits
     directly under the close-button row with no chip above it.
     `--t-fs-xlarge` is the largest defined font-size token
     (clamp 20–28 px viewport-fluid). Was `--t-fs-h2` which doesn't
     exist — caused title to fall back to browser default 16 px and
     look invisible next to the rating row. */
  font-size: var(--t-fs-xlarge);
  font-weight: var(--t-weight-bold);
  color: var(--t-c-text-primary);
  line-height: 1.2;
  margin: 0 0 var(--t-s-xs) 0;
}
.t-info-window__subtitle {
  font-size: var(--t-size-caption1);
  color: var(--t-c-text-secondary);
  line-height: 1.2;
  margin-bottom: calc(var(--ui-content-scale) * 18px);
}
.t-info-window__rate {
  display: flex; align-items: center; gap: calc(var(--ui-content-scale) * 10px);
  margin-bottom: calc(var(--ui-content-scale) * 12px);
}
.t-info-window__rate-title {
  font-size: var(--t-size-body2);
  color: var(--t-c-text-primary);
  font-weight: var(--t-weight-medium);
  font-family: var(--t-font-mono);
}
.t-info-window__rate-tier {
  font-size: var(--t-fs-base);
  padding: calc(var(--ui-content-scale) * 4px) calc(var(--ui-content-scale) * 12px);
  border-radius: calc(var(--ui-content-scale) * 5px);
  background: var(--t-c-success-bg);
  color: var(--t-c-green);
  font-weight: var(--t-weight-medium);
}
.t-info-window__rate-tier--peak {
  background: var(--t-c-caution-bg);
  color: var(--t-c-orange);
}
.t-info-window__billing-table {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: calc(var(--ui-content-scale) * 12px);
  padding: calc(var(--ui-content-scale) * 16px) 0;
  border-top: calc(var(--ui-content-scale) * 1px) solid var(--t-c-bg-divider);
  margin-bottom: calc(var(--ui-content-scale) * 16px);
}
.t-info-window__billing-cell { display: flex; flex-direction: column; gap: calc(var(--ui-content-scale) * 4px); }
.t-info-window__billing-cell-title { font-size: var(--t-fs-base); color: var(--t-c-text-secondary); }
.t-info-window__billing-cell-value {
  font-size: var(--t-fs-large);
  color: var(--t-c-text-primary);
  font-variant-numeric: tabular-nums;
  font-family: var(--t-font-mono);
}
.t-info-window__access-row {
  display: flex; align-items: center;
  gap: calc(var(--ui-content-scale) * 10px);
  font-size: var(--t-size-caption1);
  color: var(--t-c-text-secondary);
  padding: calc(var(--ui-content-scale) * 6px) 0;
}
.t-info-window__access-row img { width: calc(var(--ui-content-scale) * 22px); height: calc(var(--ui-content-scale) * 22px); }

/* Live availability — per-stall list driven by _zaryad.live block
   that zaryad_fetcher.py decodes at refresh time. The badge in the
   header colours by available/total ratio; per-stall dots colour
   by status (Available / Connected / Not Connecting). */
.t-info-window__live {
  margin: calc(var(--ui-content-scale) * 12px) 0;
  padding: calc(var(--ui-content-scale) * 12px);
  border-radius: calc(var(--ui-content-scale) * 12px);
  background: var(--t-c-overlay-4);
}
.t-info-window__live-header {
  display: flex; justify-content: space-between; align-items: center;
  margin-bottom: calc(var(--ui-content-scale) * 8px);
}
.t-info-window__live-title {
  font-size: var(--t-fs-medium);
  font-weight: var(--t-weight-medium);
  color: var(--t-c-text-primary);
}
.t-info-window__live-badge {
  padding: calc(var(--ui-content-scale) * 3px) calc(var(--ui-content-scale) * 8px);
  border-radius: calc(var(--ui-content-scale) * 999px);
  font-size: var(--t-size-caption1);
  font-weight: var(--t-weight-medium);
}
.t-info-window__live-badge--ok   { background: var(--t-c-success-bg);  color: var(--t-c-success-fg); }
.t-info-window__live-badge--low  { background: var(--t-c-warning-bg); color: var(--t-c-warning-fg); }
.t-info-window__live-badge--busy { background: var(--t-c-error-bg);  color: var(--t-c-error-fg); }
.t-info-window__live-stalls {
  display: flex; flex-direction: column; gap: calc(var(--ui-content-scale) * 4px);
}
.t-info-window__live-row {
  display: flex; align-items: center; gap: calc(var(--ui-content-scale) * 8px);
  font-size: var(--t-size-caption1);
  color: var(--t-c-text-primary);
}
.t-info-window__live-stall { flex: 1; color: var(--t-c-text-secondary); }
.t-info-window__live-status { color: var(--t-c-text-primary); }
.t-info-window__live-dot {
  width: calc(var(--ui-content-scale) * 8px); height: calc(var(--ui-content-scale) * 8px); border-radius: 50%;
  background: var(--t-c-text-secondary);
  flex-shrink: 0;
}
.t-info-window__live-dot--ok   { background: var(--t-c-success-fg); }
.t-info-window__live-dot--busy { background: var(--t-c-warning); }
.t-info-window__live-dot--off  { background: var(--t-c-error-fg); }
.t-info-window__live-site-note {
  margin-top: calc(var(--ui-content-scale) * 6px);
  font-size: var(--t-size-caption2);
  color: var(--t-c-text-secondary);
  font-style: italic;
}
.t-info-window__live-fresh {
  margin-top: calc(var(--ui-content-scale) * 8px);
  font-size: var(--t-size-caption2);
  color: var(--t-c-text-secondary);
}
.t-info-window__hours-row {
  display: flex; align-items: center;
  gap: calc(var(--ui-content-scale) * 10px);
  font-size: var(--t-size-caption1);
  color: var(--t-c-text-secondary);
  padding: calc(var(--ui-content-scale) * 6px) 0;
}
.t-info-window__hours-row img { width: calc(var(--ui-content-scale) * 18px); height: calc(var(--ui-content-scale) * 18px); }
.t-info-window__connectors {
  display: flex; flex-wrap: wrap;
  gap: calc(var(--ui-content-scale) * 6px);
  padding: calc(var(--ui-content-scale) * 6px) 0;
}
.t-info-window__connector-chip {
  padding: calc(var(--ui-content-scale) * 3px) calc(var(--ui-content-scale) * 9px);
  border-radius: calc(var(--ui-content-scale) * 999px);
  background: var(--t-c-overlay-6);
  font-size: var(--t-size-caption2);
  color: var(--t-c-text-primary);
}

/* Nearby-amenity chips — OSM-derived, rendered with masked icons + label. */
.t-info-window__amenity-row {
  display: flex; flex-wrap: wrap; gap: calc(var(--ui-content-scale) * 6px);
  padding: calc(var(--ui-content-scale) * 6px) 0;
}
.t-info-window__amenity-chip {
  display: inline-flex; align-items: center; gap: calc(var(--ui-content-scale) * 4px);
  padding: calc(var(--ui-content-scale) * 3px) calc(var(--ui-content-scale) * 8px) calc(var(--ui-content-scale) * 3px) calc(var(--ui-content-scale) * 6px);
  border-radius: calc(var(--ui-content-scale) * 999px);
  background: var(--t-c-overlay-4);
  font-size: var(--t-size-caption2);
  color: var(--t-c-text-primary);
}
.t-info-window__amenity-chip img { width: calc(var(--ui-content-scale) * 14px); height: calc(var(--ui-content-scale) * 14px); }

.t-info-window__address {
  display: flex; justify-content: space-between;
  margin: calc(var(--ui-content-scale) * 16px) 0;
  padding-top: calc(var(--ui-content-scale) * 16px);
  border-top: calc(var(--ui-content-scale) * 1px) solid var(--t-c-bg-divider);
}
.t-info-window__address-text {
  font-size: var(--t-fs-medium);
  color: var(--t-c-text-primary);
  line-height: 1.4;
}
.t-info-window__address-distance {
  font-size: var(--t-fs-large);
  color: var(--t-c-text-primary);
  font-weight: var(--t-weight-medium);
  white-space: nowrap;
  margin-left: calc(var(--ui-content-scale) * 12px);
}
.t-info-window__actions {
  display: flex; align-items: center;
  gap: var(--t-s-md);
  margin: var(--t-s-lg) 0;
  flex-wrap: wrap;
}
.t-action-btn {
  width: clamp(calc(var(--ui-content-scale) * 44px), calc(2vw + calc(var(--ui-content-scale) * 36px)), calc(var(--ui-content-scale) * 56px));
  height: clamp(calc(var(--ui-content-scale) * 44px), calc(2vw + calc(var(--ui-content-scale) * 36px)), calc(var(--ui-content-scale) * 56px));
  border-radius: 50%;
  background: var(--t-c-overlay-4);
  display: flex; align-items: center; justify-content: center;
  transition: var(--t-trans-quick);
  flex-shrink: 0;
}
.t-action-btn:hover { background: var(--t-c-overlay-7); }
.t-action-btn:active { transform: scale(0.95); }
.t-action-btn img {
  width: var(--t-icon-sm); height: var(--t-icon-sm);
}
.t-action-btn--primary {
  background: var(--t-c-blue-bright);
  /* Icon inside is a MaskedIcon painted with currentColor. The
     button sits on a saturated blue surface in every theme, so
     force the foreground to pure white instead of inheriting the
     theme-aware body text colour (which would render near-black on
     blue under the day palette). */
  color: var(--t-c-on-accent);
}
.t-action-btn--primary:hover { background: var(--t-c-blue-hover); }
/* .t-action-btn--nav lives under `.t-info-window__actions` (its only use site)
   so it can out-specify that block's base sizing — see there. */
.t-info-window__home-row {
  display: flex; align-items: center;
  justify-content: space-between;
  padding: calc(var(--ui-content-scale) * 14px) calc(var(--ui-content-scale) * 16px);
  background: var(--t-c-overlay-2);
  border-radius: calc(var(--ui-content-scale) * 6px);
  margin-bottom: calc(var(--ui-content-scale) * 8px);
  font-size: var(--t-size-caption1);
  color: var(--t-c-text-primary);
  transition: var(--t-trans-quick);
}
.t-info-window__home-row:hover { background: var(--t-c-overlay-4); }
.t-info-window__home-row-left { display: flex; align-items: center; gap: calc(var(--ui-content-scale) * 12px); }
.t-info-window__home-row-left img { width: calc(var(--ui-content-scale) * 22px); height: calc(var(--ui-content-scale) * 22px); }
.t-info-window__amenities {
  display: flex; align-items: center;
  gap: calc(var(--ui-content-scale) * 12px);
  padding-top: calc(var(--ui-content-scale) * 18px);
  border-top: calc(var(--ui-content-scale) * 1px) solid var(--t-c-bg-divider);
  flex-wrap: wrap;
  margin-top: 0;
}
.t-amenity-btn {
  width: calc(var(--ui-content-scale) * 52px); height: calc(var(--ui-content-scale) * 52px);
  border-radius: 50%;
  background: var(--t-c-overlay-3);
  display: flex; align-items: center; justify-content: center;
  transition: var(--t-trans-quick);
}
.t-amenity-btn:hover { background: var(--t-c-overlay-6); }
.t-amenity-btn img { width: calc(var(--ui-content-scale) * 26px); height: calc(var(--ui-content-scale) * 26px); }

/* ═══ Edit trip ═══════════════════════════════════════════════════════ */
/* EditTrip — edit_trip.uiml:3.  Style `EditTrip/Width` =
 * UnifiedTurnListWidth (430 px on MCU).  NOT fullscreen; same column
 * width as the turn panel so it looks like a sibling popup, not a
 * separate page. */
.t-edit-trip {
  background: var(--t-c-bg-nav-primary);
  backdrop-filter: blur(calc(var(--ui-content-scale) * 20px));
  -webkit-backdrop-filter: blur(calc(var(--ui-content-scale) * 20px));
  border-radius: var(--t-r-card);
  overflow: hidden;
  display: flex; flex-direction: column;
  margin-top: 0;
  box-shadow: var(--t-shadow-card);
  width: clamp(calc(var(--ui-content-scale) * 280px), 35vw, calc(var(--ui-content-scale) * 430px));
  max-width: calc(var(--ui-content-scale) * 430px);
  align-self: flex-start;
  flex: 0 1 auto;
  min-height: 0;
  max-height: 100%;
}
/* Header — `EditTrip/HeaderContainer` → `EditTargetSOC/HeaderContainer`
 * = "Height:88; Flex:1; JustifyContent:center; AlignItems:center;".
 * Title is Text/Body2 (22px) primary. */
.t-edit-trip__header {
  min-height: calc(var(--ui-content-scale) * 88px);
  display: flex;
  align-items: center;
  justify-content: center;
}
.t-edit-trip__header-title {
  font-size: calc(var(--ui-font-scale) * 22px);             /* Text/Body2 */
  color: var(--t-c-text-primary);
}
/* TopDivider / BottomDivider — width:parent, height:2,
 * Style:NavTurnListBottomDivider (DividerColor1:Background/
 * transparent_secondary). */
.t-edit-trip__divider {
  width: 100%;
  height: calc(var(--ui-content-scale) * 2px);
  background: var(--t-c-bg-transparent-secondary, rgba(255,255,255,0.10));
  flex-shrink: 0;
}
/* Scroll body — `EditTrip/Scroll` = "margin:0,20,0,20" (20 px
 * left+right inside the panel) + a small `padding-top: calc(var(--ui-content-scale) * 14px)` so the
 * first row breathes below the divider (matches Tesla reference). */
.t-edit-trip__items {
  flex: 1 1 auto;
  min-height: 0;
  margin: 0 calc(var(--ui-content-scale) * 20px);
  padding-top: calc(var(--ui-content-scale) * 14px);
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  touch-action: pan-y;
  overscroll-behavior: contain;
}
/* DestinationItem — `EditTrip/Item` = "width:390;Margin:0,0,0,0".
 * Rows stack tightly (no top gap) — the dotted line in the previous
 * row's pin column provides the visual separation, just like the
 * firmware does. */
.t-edit-trip__item {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  width: 100%;
  max-width: calc(var(--ui-content-scale) * 390px);
}
/* DragBar — stops_drag_bar.png native 28×14.  The asset ships as
 * white-on-transparent (night theme variant); we render via
 * mask-image + background-color:currentColor so it follows the
 * panel's primary text colour in both light and dark themes.
 * The element itself receives pointer events for press-and-drag
 * reorder; cursor reflects state. */
.t-edit-trip__drag-bar {
  display: block;
  width: calc(var(--ui-content-scale) * 28px);
  height: calc(var(--ui-content-scale) * 14px);
  margin: calc(var(--ui-content-scale) * 20px) calc(var(--ui-content-scale) * 4px) 0 0;
  flex-shrink: 0;
  cursor: grab;
  background-color: currentColor;
  -webkit-mask-size: contain;
          mask-size: contain;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  -webkit-mask-position: center;
          mask-position: center;
  touch-action: none;            /* let pointermove flow during drag */
}
.t-edit-trip__drag-bar:active { cursor: grabbing; }

/* PinAndDots column — flex-column, centred-x, stretches to row
 * height so the dots tile fills exactly the gap between this pin
 * and the next row's pin. */
.t-edit-trip__pin-and-dots {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin: 0 calc(var(--ui-content-scale) * 12px);
  flex-shrink: 0;
  align-self: stretch;
  color: var(--t-c-text-primary);   /* drives currentColor of children */
}

/* Pin — pin_icon.png (40×40 white-on-transparent).  Theme-recoloured
 * via mask-image so it reads correctly on both light and dark panels.
 * Firmware Margin:0,15,0,10 → 15 top, 10 bottom (Qt LTRB). */
.t-edit-trip__pin {
  display: block;
  width: calc(var(--ui-content-scale) * 24px);
  height: calc(var(--ui-content-scale) * 24px);
  margin: calc(var(--ui-content-scale) * 15px) 0 calc(var(--ui-content-scale) * 8px);
  flex-shrink: 0;
  background-color: currentColor;
  -webkit-mask-size: contain;
          mask-size: contain;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  -webkit-mask-position: center;
          mask-position: center;
}

/* Dots — dotted_line.png is a 2×8 *tile* (one dot + gap), shipped
 * white-on-transparent in night_maps/.  Tile it vertically via
 * mask-repeat:repeat-y and colour via currentColor so the line is
 * visible in light theme.  Stretches via flex:1 to bridge to the
 * next pin without a gap. */
.t-edit-trip__dots {
  width: calc(var(--ui-content-scale) * 2px);
  flex: 1 1 auto;
  min-height: calc(var(--ui-content-scale) * 48px);
  background-color: currentColor;
  opacity: 0.6;
  -webkit-mask-repeat: repeat-y;
          mask-repeat: repeat-y;
  -webkit-mask-position: center top;
          mask-position: center top;
  -webkit-mask-size: calc(var(--ui-content-scale) * 2px) calc(var(--ui-content-scale) * 8px);
          mask-size: calc(var(--ui-content-scale) * 2px) calc(var(--ui-content-scale) * 8px);
}
/* LocationLabels — flexes to claim all remaining row width, shrinks
 * below content size when needed, and clips overflow so a long place
 * name can NEVER bleed into the X delete button.  No fixed max-width
 * — the row adapts to the panel's clamp(280, 35vw, 430) size. */
.t-edit-trip__labels {
  display: flex;
  flex-direction: column;
  justify-content: center;
  margin: calc(var(--ui-content-scale) * 8px) calc(var(--ui-content-scale) * 8px) 0 0;
  gap: calc(var(--ui-content-scale) * 4px);
  flex: 1 1 0;
  min-width: 0;
  overflow: hidden;
}
.t-edit-trip__label-primary {
  font-size: calc(var(--ui-font-scale) * 22px);
  color: var(--t-c-text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.t-edit-trip__label-secondary {
  font-size: calc(var(--ui-font-scale) * 18px);
  color: var(--t-c-text-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Delete — stops_delete.png, Margin:0,20,0,0 (20 top). */
.t-edit-trip__delete {
  margin: calc(var(--ui-content-scale) * 20px) 0 0 0;
  width: calc(var(--ui-content-scale) * 28px);
  height: calc(var(--ui-content-scale) * 28px);
  background: transparent;
  border: none;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  padding: 0;
  flex-shrink: 0;
}
.t-edit-trip__delete-icon {
  width: calc(var(--ui-content-scale) * 24px);
  height: calc(var(--ui-content-scale) * 24px);
  background-color: var(--t-c-text-secondary);
}
.t-edit-trip__delete:hover .t-edit-trip__delete-icon {
  background-color: var(--t-c-red);
}
.t-edit-trip__delete-spacer {
  width: calc(var(--ui-content-scale) * 28px);
  margin: calc(var(--ui-content-scale) * 20px) 0 0 0;
  flex-shrink: 0;
}
/* AddItem — edit_trip.uiml:20-24 + EditTrip/AddItem inherits
 * EditTrip/Item (width:390) + adds Margin:20,10,0,20 (20 top, 10
 * right, 0 bottom, 20 left in firmware's margin order). */
.t-edit-trip__add-item {
  display: flex;
  align-items: center;
  width: 100%;
  max-width: calc(var(--ui-content-scale) * 390px);
  margin: calc(var(--ui-content-scale) * 20px) 0 calc(var(--ui-content-scale) * 20px) calc(var(--ui-content-scale) * 20px);
  cursor: pointer;
  color: var(--t-c-text-secondary);
  transition: color 120ms ease-out;
}
.t-edit-trip__add-item:hover { color: var(--t-c-text-primary); }
.t-edit-trip__add-plus {
  width: calc(var(--ui-content-scale) * 24px);
  height: calc(var(--ui-content-scale) * 24px);
  background-color: currentColor;
  flex-shrink: 0;
}
.t-edit-trip__add-pin {
  width: calc(var(--ui-content-scale) * 24px);
  height: calc(var(--ui-content-scale) * 24px);
  margin: 0 calc(var(--ui-content-scale) * 12px);
  opacity: 0.4;
  background-color: currentColor;
  flex-shrink: 0;
  -webkit-mask-size: contain;
          mask-size: contain;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  -webkit-mask-position: center;
          mask-position: center;
}
.t-edit-trip__add-label {
  font-size: calc(var(--ui-font-scale) * 22px);             /* Text/Body2 */
  margin-right: calc(var(--ui-content-scale) * 10px);
  color: inherit;
}
/* BottomButtons container — padding:20,0,20,0 (20 top, 20 bottom);
 * margin:0,20,0,20 (20 left/right).  Done left + Cancel right
 * (firmware source order, justifyContent:spaceBetween). */
.t-edit-trip__footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: calc(var(--ui-content-scale) * 20px);
  gap: calc(var(--ui-content-scale) * 12px);
}
/* Both buttons — Nav/TurnListButton width:185 height:60. */
.t-edit-trip__done-btn,
.t-edit-trip__cancel-btn {
  flex: 1 1 0;
  min-width: 0;
  max-width: calc(var(--ui-content-scale) * 185px);
  min-height: calc(var(--ui-content-scale) * 60px);
  border-radius: calc(var(--ui-content-scale) * 6px);          /* matches Tesla button corner */
  border: none;
  font-size: calc(var(--ui-font-scale) * 22px);             /* Text/Body2 */
  cursor: pointer;
  transition: background 120ms ease-out;
}
/* Done — square_button_toggle_selected.png = Tesla blue */
.t-edit-trip__done-btn {
  background: var(--t-c-blue-bright);
  color: #FFFFFF;
}
.t-edit-trip__done-btn:hover:not(:disabled) { background: var(--t-c-blue-hover); }
.t-edit-trip__done-btn:disabled { opacity: 0.4; cursor: not-allowed; }
/* Cancel — default Nav/TurnListButton (Background/transparent_primary). */
.t-edit-trip__cancel-btn {
  background: var(--t-c-overlay-5);
  color: var(--t-c-text-primary);
}
.t-edit-trip__cancel-btn:hover { background: var(--t-c-overlay-7); }

/* ═══ Notification banners ════════════════════════════════════════════ */
.t-notification-stack {
  display: flex; flex-direction: column;
  gap: var(--t-s-sm);
  margin-top: 0;
}
.t-notification {
  background: var(--t-c-blue-bright);
  padding: var(--t-s-md) var(--t-s-lg);
  border-radius: calc(var(--ui-content-scale) * 10px);
  display: flex; align-items: center; justify-content: space-between;
  position: relative;
  overflow: hidden;
  color: var(--t-c-on-accent);
}
.t-notification { cursor: pointer; }
/* Connection-lost variant. Yellow (severe-but-not-fatal) so it reads
 * as "something the user should know" but doesn't compete with a
 * navigation error banner. Inner icon + text + sub layout matches
 * the BetterRoute card so the whole stack reads consistent. */
.t-notification--connection-lost {
  background: var(--t-c-amber);
  color: var(--t-c-on-accent);
  cursor: default;
  align-items: flex-start;
  gap: calc(var(--ui-content-scale) * 12px);
}
.t-notification--connection-lost .t-notification__icon {
  font-size: calc(var(--ui-font-scale) * 18px); line-height: 1; margin-top: calc(var(--ui-content-scale) * 2px);
}
.t-notification--connection-lost .t-notification__text {
  display: flex; flex-direction: column; gap: calc(var(--ui-content-scale) * 2px);
}
.t-notification--connection-lost .t-notification__title {
  font-weight: 600;
}
.t-notification--connection-lost .t-notification__sub {
  font-size: var(--t-fs-small); opacity: 0.92;
}
.t-notification--better-route .t-notification__progress {
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 0%;
  background: var(--t-c-overlay-5);
}
.t-notification__close {
  position: relative; z-index: 2;
  width: calc(var(--ui-content-scale) * 28px); height: calc(var(--ui-content-scale) * 28px); border-radius: 50%;
  background: rgba(0,0,0,0.25);
  border: 0; color: var(--t-c-on-accent);
  margin-left: calc(var(--ui-content-scale) * 10px); cursor: pointer;
  font-size: var(--t-fs-small);
}
.t-notification--charger-outage { background: var(--t-c-banner-red); }
.t-notification--high-cost { background: var(--t-c-banner-blue); }
.t-notification--pay-to-park { background: var(--t-c-banner-neutral); }
.t-notification__left {
  display: flex; align-items: center;
  gap: var(--t-s-md);
  position: relative; z-index: 1;
  min-width: 0; flex: 1 1 auto;
}
.t-notification__icon {
  width: var(--t-icon-md); height: var(--t-icon-md);
  background: var(--t-c-overlay-8);
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: var(--t-fs-large);
  flex-shrink: 0;
}
.t-notification__icon img {
  width: calc(var(--t-icon-md) * 0.6);
  height: calc(var(--t-icon-md) * 0.6);
}
.t-notification__label {
  font-size: var(--t-fs-large);
  font-weight: var(--t-weight-medium);
  color: var(--t-c-on-accent);
  min-width: 0;
  overflow: hidden; text-overflow: ellipsis;
}
.t-notification__op {
  font-size: var(--t-fs-base);
  color: rgba(255,255,255,0.7);
  position: relative; z-index: 1;
  white-space: nowrap;
}
@keyframes t-progress-fill {
  from { width: 0; }
  to { width: 100%; }
}


/* ═══ Nav card (no-trip home shortcut card) ══════════════════════════
   Two rows: Navigate (top), Home/Work (bottom). Both rows + the card
   itself use fluid sizing tokens, so the card naturally scales from
   ~112 px tall on a 360-wide phone to ~160 px tall on Tesla MCU. No
   fixed pixel heights anywhere. */
.t-nav-card {
  background: var(--t-c-bg-nav-primary);
  backdrop-filter: blur(calc(var(--ui-content-scale) * 20px));
  -webkit-backdrop-filter: blur(calc(var(--ui-content-scale) * 20px));
  border-radius: var(--t-r-card);
  width: 100%;
  display: flex; flex-direction: column;
  overflow: hidden;
  box-shadow: var(--t-shadow-card);
}
.t-nav-card__top {
  min-height: var(--t-card-row-h);
  display: flex; align-items: center;
  padding: 0 var(--t-s-lg);
}
.t-nav-card__navigate-btn {
  width: 100%; height: 100%;
  background: transparent;
  border-radius: 0;
  display: flex; align-items: center; gap: var(--t-s-md);
  padding: var(--t-s-md) 0;
  color: var(--t-c-text-secondary);
  font-size: var(--t-fs-large);
  transition: color var(--t-trans-quick), background var(--t-trans-quick);
}
/* Hover: brighten the label only, no background. The button fills
   the whole top row of the card, so any bg change would grey out
   the entire row — never wanted as feedback. */
.t-nav-card__navigate-btn:hover {
  color: var(--t-c-text-primary);
  background: transparent;
}
.t-nav-card__navigate-btn:active {
  background: transparent;
}
.t-nav-card__navigate-btn img {
  width: var(--t-icon-md); height: var(--t-icon-md);
  opacity: 0.6;
}
.t-nav-card__divider {
  height: calc(var(--ui-content-scale) * 2px);
  background: var(--t-c-bg-divider);
  margin: 0 var(--t-s-lg);
}
.t-nav-card__bottom {
  min-height: var(--t-card-row-h);
  display: flex;
  align-items: stretch;
}
.t-nav-card__shortcut {
  flex: 1;
  display: flex; align-items: center; justify-content: center;
  gap: var(--t-s-md);
  padding: var(--t-s-md) 0;
  font-size: var(--t-fs-large);
  color: var(--t-c-text-secondary);
  transition: var(--t-trans-quick);
}
.t-nav-card__shortcut:hover { color: var(--t-c-text-primary); }
.t-nav-card__shortcut img {
  width: var(--t-icon-md); height: var(--t-icon-md);
  opacity: 0.6;
}
.t-nav-card__shortcut.disabled { opacity: 0.4; pointer-events: none; }
.t-nav-card__shortcut-divider {
  width: calc(var(--ui-content-scale) * 2px);
  background: var(--t-c-bg-divider);
  height: 60%;
  align-self: center;
}

/* ═══ Suggestions card ═══════════════════════════════════════════════ */
.t-suggestions {
  background: var(--t-c-bg-nav-primary);
  backdrop-filter: blur(calc(var(--ui-content-scale) * 20px));
  -webkit-backdrop-filter: blur(calc(var(--ui-content-scale) * 20px));
  border-radius: var(--t-r-card);
  margin-top: 0;
  padding: var(--t-s-md) var(--t-s-lg);
  display: flex; flex-direction: column;
  gap: var(--t-s-sm);
  box-shadow: var(--t-shadow-card);
}
.t-suggestion-item {
  display: flex; align-items: center;
  gap: var(--t-s-md);
  padding: var(--t-s-sm) 0;
  transition: var(--t-trans-quick);
}
.t-suggestion-item:hover { opacity: 0.8; }
.t-suggestion-item__pin {
  width: var(--t-icon-md); height: var(--t-icon-md);
  border-radius: 50%;
  background: var(--t-c-blue);
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  /* SVG glyph inside uses fill:currentColor — force white so the
     pin reads correctly on the blue circle in every theme. */
  color: var(--t-c-on-accent);
}
.t-suggestion-item__pin svg {
  width: calc(var(--t-icon-md) * 0.55);
  height: calc(var(--t-icon-md) * 0.55);
  fill: currentColor;
}
.t-suggestion-item__pin .t-mask-icon {
  width: calc(var(--t-icon-md) * 0.55);
  height: calc(var(--t-icon-md) * 0.55);
}
.t-suggestion-item__pin--charger { background: var(--t-c-red); }
.t-suggestion-item__labels {
  flex: 1; min-width: 0;
  display: flex; flex-direction: column;
}
.t-suggestion-item__name {
  font-size: var(--t-fs-large);
  color: var(--t-c-text-primary);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.t-suggestion-item__address {
  font-size: var(--t-fs-base);
  color: var(--t-c-text-secondary);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.t-suggestion-item__distance {
  font-size: var(--t-fs-base);
  color: var(--t-c-text-secondary);
  white-space: nowrap;
}

/* ═══ Charger pin overlay (map markers) ═══════════════════════════════ */
.t-charger-pin {
  width: calc(var(--ui-content-scale) * 32px); height: calc(var(--ui-content-scale) * 40px);
  background: var(--t-c-red);
  border-radius: calc(var(--ui-content-scale) * 16px) calc(var(--ui-content-scale) * 16px) calc(var(--ui-content-scale) * 16px) 0;
  transform: rotate(-45deg);
  position: absolute;
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  font-size: var(--t-fs-medium);
  color: var(--t-c-on-accent);
  font-weight: 700;
  box-shadow: var(--t-shadow-strong);
}

/* ═══ Responsive breakpoints (mobile-first overrides) ══════════════════
   Default shell (above) = phone portrait — map is the full canvas,
   left panel is a bottom sheet, right pill floats top-right. These
   rules enhance for wider viewports.

     ≥640 px  — phone landscape / small tablet: shorter bottom sheet.
     ≥768 px  — tablet portrait: panel promotes to a top-left sidebar.
     ≥1024 px — desktop: roomier sidebar + larger right strip gap.
     ≥1600 px — Tesla MCU / ultrawide: widest sidebar. */

/* ── Phone landscape / small tablet (≥640) ─────────────────────────── */
@media (min-width: 640px) {
  /* Still a draggable sheet at this width; only the default snap mid
     value (when state.sheet_pct == 55) lands a touch shorter. */
}

/* ── Tablet portrait & up (≥768) — left panel becomes a sidebar ─────── */
@media (min-width: 768px) {
  .t-shell__left {
    /* Sidebar mode — undo all of the mobile sheet machinery and
       become a regular top-anchored side panel. */
    position: fixed;
    top: max(calc(var(--ui-content-scale) * 16px), env(safe-area-inset-top, calc(var(--ui-content-scale) * 16px)));
    left: max(calc(var(--ui-content-scale) * 16px), env(safe-area-inset-left, calc(var(--ui-content-scale) * 16px)));
    bottom: max(calc(var(--ui-content-scale) * 16px), env(safe-area-inset-bottom, calc(var(--ui-content-scale) * 16px)));
    right: auto;
    width: clamp(calc(var(--ui-content-scale) * 320px), 36vw, calc(var(--ui-content-scale) * 380px));
    height: auto;
    max-height: none;
    transform: none;
    will-change: auto;
    contain: none;
    padding: 0;
    gap: calc(var(--ui-content-scale) * 14px);
    background: none;
    box-shadow: none;
    border-radius: 0;
    overflow-y: auto;
    transition: none;
    /* Sidebar — natural touch behaviour, no JS gesture interception. */
    touch-action: auto;
  }
  /* The sheet grabber is mobile-only; the sidebar has no use for it. */
  .t-sheet-grabber { display: none; }
  .t-shell__right-strip {
    top: max(calc(var(--ui-content-scale) * 16px), env(safe-area-inset-top, calc(var(--ui-content-scale) * 16px)));
    right: max(calc(var(--ui-content-scale) * 16px), env(safe-area-inset-right, calc(var(--ui-content-scale) * 16px)));
    gap: calc(var(--ui-content-scale) * 16px);
  }
}

/* ── Small desktop (≥1024) — roomier sidebar ───────────────────────── */
@media (min-width: 1024px) {
  .t-shell__left { width: clamp(calc(var(--ui-content-scale) * 360px), 30vw, calc(var(--ui-content-scale) * 430px)); gap: calc(var(--ui-content-scale) * 16px); }
}

/* ── Tesla MCU + ultrawide (≥1600) — widest sidebar ────────────────── */
@media (min-width: 1600px) {
  /* firmware UnifiedTurnListWidth = 430 (styles-common.conf:218) */
  .t-shell__left { width: calc(var(--ui-content-scale) * 430px); }
}

/* Hide the rest-area widget on narrow viewports (no room next to the
   junction view + right strip). */
@media (max-width: 900px) {
  .t-rest-area { display: none; }
}

/* Anchor adjustments for the bottom-sheet layout (phones). The current
   location bubble + junction view sit ABOVE the sheet, hugging the
   right edge so they don't fight the right-strip pill. Overlay
   positions track --sheet-h so they slide up/down with the sheet
   itself instead of overlapping or floating away from it.

   When the sheet is large (>= 70 %) the map area shrinks to a thin
   strip behind Safari's chrome — map overlays lose meaning and start
   colliding with the URL bar. Fade them out so the user sees the
   panel uncluttered. */
@media (max-width: 767px) {
  .t-current-location {
    right: max(calc(var(--ui-content-scale) * 8px), env(safe-area-inset-right, calc(var(--ui-content-scale) * 8px)));
    bottom: calc(var(--sheet-h) * 1dvh + calc(var(--ui-content-scale) * 8px));
    max-width: calc(100vw - calc(var(--ui-content-scale) * 96px));
    padding: calc(var(--ui-content-scale) * 4px) calc(var(--ui-content-scale) * 8px);
    /* No transition on `bottom` — the overlay tracks --sheet-h
       which changes per drag frame, so transitions would lag the
       finger. opacity still transitions for the fade-when-tall
       behaviour below. */
    transition: opacity 180ms ease;
  }
  .t-current-location__street { font-size: var(--t-fs-base); }
  .t-current-location__region { font-size: var(--t-fs-mini); }
  .t-junction-view {
    top: max(calc(var(--ui-content-scale) * 12px), env(safe-area-inset-top, calc(var(--ui-content-scale) * 12px)));
    right: max(calc(var(--ui-content-scale) * 12px), env(safe-area-inset-right, calc(var(--ui-content-scale) * 12px)));
    width: min(calc(var(--ui-content-scale) * 280px), calc(100vw - calc(var(--ui-content-scale) * 80px)));
    height: clamp(calc(var(--ui-content-scale) * 120px), 28vw, calc(var(--ui-content-scale) * 180px));
  }
}

/* Sheet-expanded state — when state.sheet_pct >= 70 the Rust side
   adds `.is-sheet-tall` to .t-shell. Floating *overlays* fade because
   the map area has shrunk to a thin strip behind Safari's chrome where
   they'd collide with the URL bar. The right-strip stays visible — the
   user still needs Tracking / Satellite / Traffic / Quiet / Charger /
   Weather / 3D / Settings reachable, and the strip lives at the top-
   right corner well clear of the sheet. */
@media (max-width: 767px) {
  .t-shell.is-sheet-tall .t-current-location,
  .t-shell.is-sheet-tall .t-rest-area {
    opacity: 0;
    pointer-events: none;
    transition: opacity 200ms ease;
  }
  /* Smooth fade in when collapsing back. */
  .t-current-location,
  .t-shell__right-strip {
    transition: opacity 200ms ease,
                bottom 220ms cubic-bezier(0.32, 0.72, 0, 1),
                max-height 220ms cubic-bezier(0.32, 0.72, 0, 1);
  }
}

/* ═══ Settings view ═══════════════════════════════════════════════════ */
.t-settings {
  background: var(--t-c-bg-nav-primary);
  backdrop-filter: blur(calc(var(--ui-content-scale) * 20px));
  -webkit-backdrop-filter: blur(calc(var(--ui-content-scale) * 20px));
  border-radius: var(--t-r-card);
  display: flex; flex-direction: column;
  width: 100%;
  flex: 1 1 auto;
  min-height: 0;
  margin-top: 0;
  overflow: hidden;
  box-shadow: var(--t-shadow-card);
}
.t-settings__header {
  display: flex; align-items: center; justify-content: space-between;
  padding: var(--t-s-lg);
  border-bottom: calc(var(--ui-content-scale) * 2px) solid var(--t-c-bg-divider);
}
.t-settings__title {
  font-size: var(--t-fs-xlarge);
  font-weight: var(--t-weight-medium);
  color: var(--t-c-text-primary);
}
.t-settings__close {
  width: var(--t-icon-md); height: var(--t-icon-md);
  min-width: calc(var(--ui-content-scale) * 44px); min-height: calc(var(--ui-content-scale) * 44px);
  border-radius: 50%;
  background: var(--t-c-overlay-3);
  color: var(--t-c-text-secondary);
  display: flex; align-items: center; justify-content: center;
}
.t-settings__close svg {
  width: clamp(calc(var(--ui-content-scale) * 14px), 0.6vw + calc(var(--ui-content-scale) * 12px), calc(var(--ui-content-scale) * 18px));
  height: clamp(calc(var(--ui-content-scale) * 14px), 0.6vw + calc(var(--ui-content-scale) * 12px), calc(var(--ui-content-scale) * 18px));
}
.t-settings__scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  display: flex; flex-direction: column;
  touch-action: pan-y;
  overscroll-behavior: contain;
}
.t-settings__row {
  display: flex; align-items: center;
  gap: var(--t-s-md);
  padding: var(--t-s-md) var(--t-s-lg);
  border-bottom: calc(var(--ui-content-scale) * 1px) solid var(--t-c-bg-transparent-secondary);
  cursor: pointer;
  transition: background var(--t-trans-quick);
}
.t-settings__row:hover { background: var(--t-c-overlay-2); }
.t-settings__row-icon {
  width: var(--t-icon-sm); height: var(--t-icon-sm);
  flex-shrink: 0;
  opacity: 0.85;
}
.t-settings__row-labels { flex: 1; display: flex; flex-direction: column; gap: calc(var(--ui-content-scale) * 2px); min-width: 0; }
.t-settings__row-label {
  font-size: var(--t-fs-large);
  color: var(--t-c-text-primary);
}
.t-settings__row-desc {
  font-size: var(--t-fs-base);
  color: var(--t-c-text-secondary);
}
.t-settings__row-value {
  display: flex; align-items: center; gap: calc(var(--ui-content-scale) * 6px);
  font-size: var(--t-fs-base);
  color: var(--t-c-text-secondary);
}
.t-settings__row-chevron { display: inline-flex; width: calc(var(--ui-content-scale) * 14px); height: calc(var(--ui-content-scale) * 14px); opacity: 0.6; }
.t-settings__divider { height: calc(var(--ui-content-scale) * 1px); background: var(--t-c-bg-divider); margin: calc(var(--ui-content-scale) * 12px) calc(var(--ui-content-scale) * 20px); }
.t-settings__switch {
  width: calc(var(--ui-content-scale) * 44px); height: calc(var(--ui-content-scale) * 24px);
  background: var(--t-c-overlay-5);
  border-radius: calc(var(--ui-content-scale) * 12px);
  position: relative;
  transition: background var(--t-trans-normal);
}
.t-settings__switch.on { background: var(--t-c-blue-bright); }
.t-settings__switch-knob {
  position: absolute;
  top: calc(var(--ui-content-scale) * 2px); left: calc(var(--ui-content-scale) * 2px);
  width: calc(var(--ui-content-scale) * 20px); height: calc(var(--ui-content-scale) * 20px);
  background: var(--t-c-pure-white);
  border-radius: 50%;
  transition: left var(--t-trans-normal);
}
.t-settings__switch.on .t-settings__switch-knob { left: calc(var(--ui-content-scale) * 22px); }

/* ═══ Vehicle section (Settings → Vehicle) ═══════════════════════════ */
/* Pack-size + current battery % live here. Tuning these is what makes
 * the trip planner insert chargers for medium-range trips — without
 * the row the user can't tell the backend the truth about their
 * energy state. */
.t-settings__vehicle {
  display: flex; flex-direction: column;
  gap: calc(var(--ui-content-scale) * 6px);
  padding: calc(var(--ui-content-scale) * 4px) 0 calc(var(--ui-content-scale) * 12px) 0;
}
.t-settings__section-title {
  font-size: var(--t-fs-base);
  font-weight: 600;
  color: var(--t-c-text-secondary);
  padding: calc(var(--ui-content-scale) * 12px) calc(var(--ui-content-scale) * 16px) calc(var(--ui-content-scale) * 4px) calc(var(--ui-content-scale) * 16px);
  letter-spacing: calc(var(--ui-content-scale) * 0.5px);
  text-transform: uppercase;
}
.t-settings__row--input,
.t-settings__row--slider { align-items: flex-start; }
.t-settings__num {
  width: calc(var(--ui-content-scale) * 78px);
  padding: calc(var(--ui-content-scale) * 6px) calc(var(--ui-content-scale) * 10px);
  border-radius: calc(var(--ui-content-scale) * 8px);
  border: calc(var(--ui-content-scale) * 1px) solid var(--t-c-bg-divider);
  background: var(--t-c-overlay-1);
  color: var(--t-c-text-primary);
  text-align: right;
  font-size: var(--t-fs-base);
  font-variant-numeric: tabular-nums;
}
.t-settings__num:focus { outline: calc(var(--ui-content-scale) * 2px) solid var(--t-c-blue-bright); }
.t-settings__slider {
  width: calc(100% - calc(var(--ui-content-scale) * 32px));
  margin: calc(var(--ui-content-scale) * 4px) calc(var(--ui-content-scale) * 16px) 0 calc(var(--ui-content-scale) * 16px);
  accent-color: var(--t-c-blue-bright);
}
.t-settings__scale {
  display: flex; justify-content: space-between;
  font-size: var(--t-fs-small); color: var(--t-c-text-secondary);
  padding: 0 calc(var(--ui-content-scale) * 16px) calc(var(--ui-content-scale) * 8px) calc(var(--ui-content-scale) * 16px);
}

/* ═══ Lane guidance row ═══════════════════════════════════════════════ */
.t-lane-guidance {
  display: flex; align-items: center; justify-content: center;
  gap: calc(var(--ui-content-scale) * 6px);
  padding: calc(var(--ui-content-scale) * 16px) calc(var(--ui-content-scale) * 20px);
}
.t-lane-arrow {
  width: calc(var(--ui-content-scale) * 36px); height: calc(var(--ui-content-scale) * 36px);
}

/* ═══ Junction view overlay ══════════════════════════════════════════ */
.t-junction-view {
  position: absolute;
  top: max(var(--t-s-lg), env(safe-area-inset-top, var(--t-s-lg)));
  right: max(calc(var(--ui-content-scale) * 110px), calc(env(safe-area-inset-right, 0) + calc(var(--ui-content-scale) * 110px)));
  width: clamp(calc(var(--ui-content-scale) * 240px), calc(20vw + calc(var(--ui-content-scale) * 120px)), calc(var(--ui-content-scale) * 360px));
  height: clamp(calc(var(--ui-content-scale) * 140px), calc(12vw + calc(var(--ui-content-scale) * 80px)), calc(var(--ui-content-scale) * 200px));
  background: rgba(20,20,20,0.92);
  border-radius: var(--t-r-card);
  overflow: hidden;
  box-shadow: var(--t-shadow-deep);
  z-index: 6;
  /* Always-dark HUD-style overlay — white text/arrows in all themes. */
  color: var(--t-c-on-accent);
}
.t-junction-view__art { width: 100%; height: 100%; object-fit: cover; }
.t-junction-view__overlay {
  position: absolute;
  top: var(--t-s-md); left: var(--t-s-md);
  display: flex; align-items: center; gap: var(--t-s-md);
  background: rgba(0,0,0,0.65);
  padding: var(--t-s-xs) var(--t-s-md);
  border-radius: calc(var(--ui-content-scale) * 24px);
}
.t-junction-view__arrow {
  width: clamp(calc(var(--ui-content-scale) * 40px), calc(2vw + calc(var(--ui-content-scale) * 32px)), calc(var(--ui-content-scale) * 60px));
  height: clamp(calc(var(--ui-content-scale) * 40px), calc(2vw + calc(var(--ui-content-scale) * 32px)), calc(var(--ui-content-scale) * 60px));
}
.t-junction-view__distance {
  font-size: var(--t-fs-xlarge);
  font-weight: var(--t-weight-medium);
  /* always-dark HUD (bg rgba(20,20,20,.92)) — text must stay light in
     all themes, so on-accent, not the theme-flipping text token. */
  color: var(--t-c-on-accent);
  font-family: var(--t-font-mono);
}

/* ═══ Traffic light countdown ════════════════════════════════════════ */
.t-tlc {
  position: absolute;
  top: calc(var(--ui-content-scale) * 240px); right: calc(var(--ui-content-scale) * 110px);
  display: flex; flex-direction: column; align-items: center; gap: calc(var(--ui-content-scale) * 4px);
  z-index: 5;
}
.t-tlc__ring {
  width: calc(var(--ui-content-scale) * 56px); height: calc(var(--ui-content-scale) * 56px);
  border: calc(var(--ui-content-scale) * 4px) solid;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: rgba(0,0,0,0.5);
}
.t-tlc__seconds {
  font-size: var(--t-fs-xlarge);
  font-weight: var(--t-weight-bold);
  /* sits on the always-dark ring (bg rgba(0,0,0,.5)) over the map —
     keep light in all themes. */
  color: var(--t-c-on-accent);
  font-family: var(--t-font-mono);
}
.t-tlc__label {
  font-size: var(--t-fs-mini);
  letter-spacing: 0.08em;
  color: var(--t-c-text-secondary);
  text-transform: uppercase;
}

/* ═══ Lane change confirmation popup ═════════════════════════════════ */
.t-lane-change {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  z-index: 10;
  max-width: calc(100vw - calc(var(--ui-content-scale) * 32px));
}
.t-lane-change__bg {
  width: min(calc(var(--ui-content-scale) * 460px), calc(100vw - calc(var(--ui-content-scale) * 32px)));
  height: clamp(calc(var(--ui-content-scale) * 140px), calc(10vw + calc(var(--ui-content-scale) * 100px)), calc(var(--ui-content-scale) * 200px));
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
  position: relative;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
}
.t-lane-change__arrow {
  width: clamp(calc(var(--ui-content-scale) * 40px), calc(3vw + calc(var(--ui-content-scale) * 32px)), calc(var(--ui-content-scale) * 64px));
  height: clamp(calc(var(--ui-content-scale) * 40px), calc(3vw + calc(var(--ui-content-scale) * 32px)), calc(var(--ui-content-scale) * 64px));
  position: absolute;
  top: var(--t-s-xl);
}
.t-lane-change__text {
  position: absolute;
  bottom: calc(var(--ui-content-scale) * 60px);
  text-align: center;
}
.t-lane-change__title {
  font-size: var(--t-fs-xlarge); font-weight: var(--t-weight-bold);
  color: var(--t-c-on-accent);
}
.t-lane-change__reason {
  font-size: var(--t-fs-base);
  color: rgba(255,255,255,0.7);
  margin-top: calc(var(--ui-content-scale) * 4px);
}
.t-lane-change__cancel {
  position: absolute; bottom: calc(var(--ui-content-scale) * 16px);
  background: var(--t-c-overlay-5);
  color: var(--t-c-on-accent); font-size: var(--t-fs-base);
  padding: calc(var(--ui-content-scale) * 6px) calc(var(--ui-content-scale) * 14px);
  border-radius: calc(var(--ui-content-scale) * 14px);
}

/* ═══ Photo carousel ══════════════════════════════════════════════════ */
.t-photo-carousel {
  display: flex; flex-direction: row;
  gap: calc(var(--ui-content-scale) * 8px);
  margin: calc(var(--ui-content-scale) * 16px) 0;
  overflow-x: auto;
  scrollbar-width: thin;
  touch-action: pan-x;
  overscroll-behavior: contain;
}
.t-photo-thumb {
  width: calc(var(--ui-content-scale) * 120px); height: calc(var(--ui-content-scale) * 90px);
  flex-shrink: 0;
  border-radius: calc(var(--ui-content-scale) * 6px);
  overflow: hidden;
}
.t-photo-thumb img { width: 100%; height: 100%; object-fit: cover; }

/* ═══ Rating stars ════════════════════════════════════════════════════ */
.t-rating { display: inline-flex; align-items: center; gap: calc(var(--ui-content-scale) * 1px); }
.t-rating__star { width: calc(var(--ui-content-scale) * 16px); height: calc(var(--ui-content-scale) * 16px); }

/* ═══ Reviews ═════════════════════════════════════════════════════════ */
.t-reviews { margin: calc(var(--ui-content-scale) * 20px) 0; }
.t-reviews__divider { height: calc(var(--ui-content-scale) * 1px); background: var(--t-c-bg-divider); margin-bottom: calc(var(--ui-content-scale) * 16px); }
.t-reviews__title {
  font-size: var(--t-size-body1);
  font-weight: var(--t-weight-medium);
  color: var(--t-c-text-primary);
  margin-bottom: calc(var(--ui-content-scale) * 16px);
}
.t-review { padding: calc(var(--ui-content-scale) * 14px) 0; border-top: calc(var(--ui-content-scale) * 1px) solid var(--t-c-bg-transparent-secondary); }
.t-review__top { display: flex; align-items: center; gap: calc(var(--ui-content-scale) * 10px); }
.t-review__age { font-size: var(--t-fs-base); color: var(--t-c-text-tertiary); }
.t-review__text { font-size: var(--t-fs-base); color: var(--t-c-text-secondary); line-height: 1.4; margin-top: calc(var(--ui-content-scale) * 8px); }

/* ═══ Place filter chips ══════════════════════════════════════════════ */
.t-place-filter-chips {
  display: flex; gap: calc(var(--ui-content-scale) * 8px);
  padding: calc(var(--ui-content-scale) * 12px) calc(var(--ui-content-scale) * 16px) calc(var(--ui-content-scale) * 8px);
  overflow-x: auto;
  scrollbar-width: thin;
  touch-action: pan-x;
  overscroll-behavior: contain;
  scroll-snap-type: x proximity;
}
/* Firmware chips are bare text — no rounded background pill, no
   capsule on active. Inactive = muted; active = primary text colour
   with bolder weight. Matches the Tesla MCU shape (Screenshots 1, 2). */
.t-place-filter-chip {
  padding: var(--t-s-xs) 0;
  margin-right: var(--t-s-lg);
  background: transparent;
  border: 0;
  color: var(--t-c-text-secondary);
  font-size: var(--t-fs-large);
  font-weight: var(--t-weight-medium);
  white-space: nowrap;
  transition: var(--t-trans-quick);
  cursor: pointer;
}
.t-place-filter-chip:hover  { color: var(--t-c-text-primary); }
.t-place-filter-chip.active {
  color: var(--t-c-text-primary);
  font-weight: var(--t-weight-bold);
  background: transparent;
}

/* ═══ Right-strip pills + map-control buttons ═════════════════════════
   Matches existing nav-edge-controls.css RE which decompiled
   NavigationWindowControls::initControls. Two pills:
     - .t-rs-pill--orient  single tracking button at top
     - .t-rs-pill--main    vertical stack of buttons, no gaps inside
   Icons rendered as CSS masks coloured by currentColor (theme-aware). */
.t-rs-pill {
  /* Use the SAME panel background as the SearchPill / InfoWindow so
     the right-strip matches the rest of the chrome at every theme.
     The previous --t-pill-bg token was a different translucent
     overlay (~70% opacity at night) which made the strip read
     darker/lighter than the search pill across themes. */
  background: var(--t-c-bg-nav-primary);
  backdrop-filter: blur(calc(var(--ui-content-scale) * 20px));
  -webkit-backdrop-filter: blur(calc(var(--ui-content-scale) * 20px));
  border-radius: var(--t-r-card);
  display: flex;
  flex-direction: column;
  align-items: center;
  /* Never let the pill exceed the viewport — short windows + 8
     buttons would overflow. Default ceiling = 100dvh minus chrome
     padding; mobile @media tightens this further. */
  max-height: calc(100dvh - calc(var(--ui-content-scale) * 32px));
  overflow-y: auto;
  overscroll-behavior: contain;
  touch-action: pan-y;
  scrollbar-width: none;             /* keeps the pill visually clean */
  color: var(--t-c-text-primary);    /* drives currentColor for icons */
  flex-shrink: 0;
  transition: opacity 260ms ease, transform 260ms ease;
}
.t-rs-pill::-webkit-scrollbar { display: none; }
.t-rs-pill--orient {
  /* single-button pill */
}
.t-rs-pill--main {
  /* multi-button pill: buttons flush, no padding/gap */
}

.t-mc-btn {
  /* Window-tracking like the views (vw), × the Display-size setting.
     Calibrated to ~80px at a typical desktop width; caps at 80, floors
     at 56. Was var(--t-row-h) which is --ui-scale-capped → fixed on
     every desktop window; this makes the button resize with the window
     the same way the panels do. */
  width: calc(var(--ui-user-scale) * clamp(56px, calc(4vw + 24px), 80px));
  height: calc(var(--ui-user-scale) * clamp(56px, calc(4vw + 24px), 80px));
  display: flex; align-items: center; justify-content: center;
  background: transparent;
  border: 0;
  padding: 0;
  cursor: pointer;
  /* OFF state — icon takes the SECONDARY text color (dim/muted).
     Theme-aware via the token: at night the secondary white(60%);
     at day the secondary black(55%); at darkDay the secondary
     white(65%). Combined with opacity below the off icon reads
     clearly dimmer than the on icon WITHOUT changing the pill bg. */
  color: var(--t-c-text-secondary);
  opacity: 0.85;
  transition: color var(--t-trans-quick),
              opacity var(--t-trans-quick);
}
/* Hover / mouse-down only bump the OPACITY of the icon — the
   button container background stays transparent (the pill's
   translucent bg shows through in all states). Firmware does
   not add any tint or fill to map-control buttons. */
.t-mc-btn:hover  { opacity: 0.85; }
.t-mc-btn:active { opacity: 1;    }   /* mouse-down momentary */

/* ON state — bright primary text color + full opacity. The button
   container background stays transparent (the pill's translucent
   bg shows through unchanged) — only the ICON GLYPH changes its
   color (text-secondary muted → text-primary bright). At night
   that's a clear ~30% white → 90% white shift; at day it's a
   ~55% black → 85% black shift; at darkDay similar to night.
   No background overlay. */
.t-mc-btn.pressed {
  color: var(--t-c-text-primary);
  opacity: 1;
  background: transparent;
}

/* Icon = a CSS mask tinted by currentColor (which is theme-aware via
   the pill's color). Same PNG works for off/on/day/night. */
.t-mc-btn__icon {
  display: block;
  /* Firmware draws each map-control glyph at its NATIVE px (40/50/60)
     centred in the 80px button — so traffic/quiet (60) and tracking (50)
     are intentionally larger than the 40px glyphs. We mirror that: the
     icon is its native size scaled by (button / 80), via --mc-icon-native
     (set per button, default 40). Tracks the window + Display setting
     through the shared button expression. Was a uniform vmin box that
     flattened every glyph to the same small size. */
  width: calc(var(--ui-user-scale) * clamp(56px, calc(4vw + 24px), 80px) * var(--mc-icon-native, 40) / 80);
  height: calc(var(--ui-user-scale) * clamp(56px, calc(4vw + 24px), 80px) * var(--mc-icon-native, 40) / 80);
  background: currentColor;       /* the tint */
  -webkit-mask-size: contain;
          mask-size: contain;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  -webkit-mask-position: center;
          mask-position: center;
  pointer-events: none;
  transition: transform var(--t-trans-normal);
}

/* ═══ MapCompassLabels — horizontal rolling-scale at top of tracking
   button. Only ~3 letters are visible at a time; the strip slides
   horizontally as the car heading changes. */
.t-mc-btn--tracking {
  position: relative;
  overflow: hidden;       /* clips the rolling strip to button bounds */
}
/* Tracking-button arrow sits BELOW the cardinal tape — shift it down
   by ~10% of button height so the glyph clears the labels at the top. */
.t-mc-btn--tracking .t-mc-btn__icon {
  transform: translateY(8%);
}
/* ─── MapCompassLabels — horizontal rolling tape ───────────────────────
   Sits at the TOP of the tracking button (NOT around the whole button).
   8 cardinal labels positioned by `left: 50% + delta_deg * 1.6%`, where
   delta = (label_angle − car_heading) wrapped to (-180, 180].  Labels
   slide horizontally as heading changes; the one above the arrow is the
   current direction.  Mirrors firmware MapCompassLabels (libQtCarGUI.so).
   Tape height ~20% of button = enough to clear the arrow icon below. */
.t-mc-compass-tape {
  position: absolute;
  left: 0; right: 0;
  top: 6%;
  height: 26%;
  pointer-events: none;
  z-index: 2;
  color: var(--t-c-text-secondary);
  /* overflow hidden lives on the button (`.t-mc-btn--tracking`) so the
     edges of the tape get clipped to the button's rounded shape. */
}
.t-mc-compass-label {
  position: absolute;
  top: 50%;
  /* `left` and `transform: translateX(-50%)` live inline so the label
     can slide horizontally based on its delta from current heading. */
  margin-top: calc(-0.5 * var(--t-fs-tiny));
  display: block;
  font-size: var(--t-fs-tiny);
  font-weight: var(--t-weight-medium);
  line-height: 1;
  white-space: nowrap;
  letter-spacing: 0.04em;
  text-align: center;
  transition: opacity 160ms linear,
              color 160ms linear,
              font-weight 160ms linear;
}
.t-mc-compass-label--active {
  opacity: 1;
  color: var(--t-c-text-primary);
  font-weight: var(--t-weight-bold);
}
.t-mc-compass-label--side {
  opacity: 0.55;
}
.t-mc-compass-label--hidden {
  opacity: 0;
}

/* ═══ Charger list panel (NearbyChargersList) ═════════════════════════
   Tesla in-car "Charging" panel — opened by Chargers filter chip or
   ChargerButton tap. */
.t-charger-list {
  background: var(--t-c-bg-nav-primary);
  backdrop-filter: blur(calc(var(--ui-content-scale) * 20px));
  -webkit-backdrop-filter: blur(calc(var(--ui-content-scale) * 20px));
  border-radius: var(--t-r-card);
  display: flex; flex-direction: column;
  width: 100%;
  flex: 1 1 auto;
  min-height: 0;
  overflow: hidden;
  box-shadow: var(--t-shadow-card);
  margin-top: 0;
}
.t-charger-list__header {
  display: flex; align-items: center; justify-content: space-between;
  padding: var(--t-s-md) var(--t-s-md) var(--t-s-xs) var(--t-s-lg);
}
.t-charger-list__title {
  font-size: var(--t-fs-xlarge);
  font-weight: var(--t-weight-medium);
  color: var(--t-c-text-primary);
}
.t-charger-list__close {
  width: var(--t-icon-md); height: var(--t-icon-md);
  min-width: calc(var(--ui-content-scale) * 44px); min-height: calc(var(--ui-content-scale) * 44px);
  border-radius: 50%;
  background: var(--t-c-overlay-3);
  color: var(--t-c-text-secondary);
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
}
.t-charger-list__close svg {
  width: clamp(calc(var(--ui-content-scale) * 14px), calc(0.6vw + calc(var(--ui-content-scale) * 12px)), calc(var(--ui-content-scale) * 18px));
  height: clamp(calc(var(--ui-content-scale) * 14px), calc(0.6vw + calc(var(--ui-content-scale) * 12px)), calc(var(--ui-content-scale) * 18px));
}

.t-charger-list__tier-row {
  display: flex; align-items: center; justify-content: center;
  gap: calc(var(--ui-content-scale) * 64px);
  padding: calc(var(--ui-content-scale) * 4px) 0 calc(var(--ui-content-scale) * 12px);
  border-bottom: calc(var(--ui-content-scale) * 1px) solid var(--t-c-bg-divider);
}
.t-charger-list__tier-btn {
  background: transparent;
  border: 0; padding: calc(var(--ui-content-scale) * 8px) calc(var(--ui-content-scale) * 12px);
  font-size: var(--t-fs-medium);
  color: var(--t-c-text-secondary);
  cursor: pointer;
  border-radius: calc(var(--ui-content-scale) * 6px);
  transition: var(--t-trans-quick);
  opacity: 0.55;
}
.t-charger-list__tier-btn.active {
  opacity: 1;
  color: var(--t-c-text-primary);
}
.t-charger-list__bolt { font-size: var(--t-fs-large); }
.t-charger-list__bolt--triple { font-size: var(--t-fs-base); letter-spacing: calc(var(--ui-content-scale) * -2px); }

/* Firmware ChargerPowerFilterButton — 1_charge.png (low) and
   3_charge.png (high) painted Tesla SC red via mask-image. The PNGs
   are 44×20 monochrome white-on-transparent; we paint them red via
   currentColor. Selected/deselected alphas mirror the firmware
   `ChargerPowerIconSelected` (1.0) / `ChargerPowerIconDeselected`
   (0.3) styles. */
.t-charger-list__tier-img {
  /* Override the base .t-mask-icon 24×24 size — the firmware filter
     icon sits noticeably larger than a turn-list glyph. */
  width: calc(var(--ui-content-scale) * 88px);
  height: calc(var(--ui-content-scale) * 40px);
  color: var(--t-c-charger-tesla);          /* Tesla SC red — firmware `chargeNowLabel` */
  opacity: 0.3;            /* Deselected (firmware default state) */
  transition: opacity var(--t-trans-quick);
  /* Match the source PNG aspect via the mask defaults already set
     by .t-mask-icon — mask-size/repeat/position carry from that
     base. Override mask-size to "contain" so the bolt cluster
     scales into the full 88×40 box. */
  -webkit-mask-size: contain;
  mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
}
.t-charger-list__tier-img.is-selected { opacity: 1.0; }
/* Override the wrapper-button's opacity dim so the per-img value wins. */
.t-charger-list__tier-btn { opacity: 1; }
.t-charger-list__tier-btn.active { opacity: 1; }

.t-charger-list__scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  touch-action: pan-y;
  overscroll-behavior: contain;
}
.t-charger-row {
  display: flex; align-items: center; justify-content: space-between;
  padding: calc(var(--ui-content-scale) * 16px) calc(var(--ui-content-scale) * 20px);
  border-bottom: calc(var(--ui-content-scale) * 1px) solid var(--t-c-bg-transparent-secondary);
  transition: background var(--t-trans-quick);
  cursor: pointer;
}
.t-charger-row:hover { background: var(--t-c-overlay-1); }
.t-charger-row:last-child { border-bottom: none; }
.t-charger-row__left {
  display: flex; flex-direction: column; gap: calc(var(--ui-content-scale) * 3px);
  min-width: 0; flex: 1;
}
.t-charger-row__name {
  font-size: var(--t-size-caption1);
  font-weight: var(--t-weight-medium);
  color: var(--t-c-text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: calc(var(--ui-content-scale) * 250px);
}
.t-charger-row__city {
  font-size: var(--t-fs-base);
  color: var(--t-c-text-secondary);
}
.t-charger-row__operator {
  font-size: var(--t-fs-small);
  color: var(--t-c-text-tertiary);
  margin-top: calc(var(--ui-content-scale) * 6px);
}
.t-charger-row__right {
  display: flex; flex-direction: column;
  align-items: center; gap: calc(var(--ui-content-scale) * 2px);
  margin-left: calc(var(--ui-content-scale) * 12px);
}
.t-charger-row__bolt {
  width: calc(var(--ui-content-scale) * 38px); height: calc(var(--ui-content-scale) * 38px);
  border-radius: 50%;
  background: var(--t-c-overlay-5);
  color: var(--t-c-text-primary);
  display: flex; align-items: center; justify-content: center;
  position: relative;
}
.t-charger-row__bolt--tesla { background: var(--t-c-red); color: var(--t-c-on-accent); }
.t-charger-row__bolt svg { width: calc(var(--ui-content-scale) * 20px); height: calc(var(--ui-content-scale) * 20px); }
.t-charger-row__bolt .t-mask-icon { width: calc(var(--ui-content-scale) * 20px); height: calc(var(--ui-content-scale) * 20px); }
.t-charger-row__badge {
  position: absolute;
  bottom: calc(var(--ui-content-scale) * -2px); right: calc(var(--ui-content-scale) * -4px);
  min-width: calc(var(--ui-content-scale) * 16px); min-height: calc(var(--ui-content-scale) * 16px);
  border-radius: calc(var(--ui-content-scale) * 8px);
  background: var(--t-c-bg-primary);
  color: var(--t-c-text-primary);
  font-size: var(--t-fs-mini);
  font-weight: var(--t-weight-bold);
  display: flex; align-items: center; justify-content: center;
  padding: 0 calc(var(--ui-content-scale) * 4px);
  border: calc(var(--ui-content-scale) * 1px) solid var(--t-c-overlay-6);
}
.t-charger-row__distance {
  font-size: var(--t-fs-base);
  font-weight: var(--t-weight-medium);
  color: var(--t-c-text-primary);
  margin-top: calc(var(--ui-content-scale) * 2px);
}
.t-charger-row__kw {
  font-size: var(--t-fs-small);
  color: var(--t-c-text-secondary);
}
/* Live availability pill in the per-row right column. Colours match
   the InfoWindow live-section badge so the same data reads
   consistently from list and detail views. */
.t-charger-row__live {
  margin-top: calc(var(--ui-content-scale) * 4px);
  padding: calc(var(--ui-content-scale) * 2px) calc(var(--ui-content-scale) * 7px);
  border-radius: calc(var(--ui-content-scale) * 999px);
  font-size: var(--t-size-caption2);
  font-weight: var(--t-weight-medium);
  align-self: flex-end;
}
.t-charger-row__live--ok   { background: var(--t-c-success-bg);  color: var(--t-c-success-fg); }
.t-charger-row__live--low  { background: var(--t-c-warning-bg); color: var(--t-c-warning-fg); }
.t-charger-row__live--busy { background: var(--t-c-error-bg);  color: var(--t-c-error-fg); }
.t-charger-row__live--off  { background: var(--t-c-error-bg);  color: var(--t-c-error-fg); opacity: 0.7; }

.t-place-filter-chip {
  scroll-snap-align: start;
}

/* ── DriveOnNav popups + NoA toggle ─────────────────────────────────── */

/* Generic modal backdrop, used by both DriveOnNav popups + any future
   confirmation modal. Pointer-events on so the backdrop captures clicks
   for dismissal. */
.t-modal-backdrop {
  position: fixed; inset: 0;
  background: var(--t-c-scrim);
  backdrop-filter: blur(calc(var(--ui-content-scale) * 8px));
  -webkit-backdrop-filter: blur(calc(var(--ui-content-scale) * 8px));
  z-index: 1000;
  display: flex; align-items: center; justify-content: center;
  pointer-events: auto;
}

/* DriveOnNavConfigPopup style hint from styles-common.conf:
     DriveOnNavInfoContent = "Padding:40,30,50,35; Width:840"
   → 840px wide, padding top:40 right:30 bottom:50 left:35. */
.t-don-popup {
  width: min(calc(var(--ui-content-scale) * 840px), calc(100vw - calc(var(--ui-content-scale) * 32px)));
  max-height: calc(100dvh - calc(var(--ui-content-scale) * 64px));   /* dvh handles iOS URL-bar resize */
  background: var(--t-pill-bg);
  color: var(--t-c-text-primary);
  border-radius: calc(var(--ui-content-scale) * 18px);
  box-shadow: var(--t-shadow-deep);
  display: flex; flex-direction: column;
  overflow: hidden;
  contain: layout style;             /* isolate reflow from page */
}
.t-don-popup__header {
  padding: clamp(calc(var(--ui-content-scale) * 24px), 4vw, calc(var(--ui-content-scale) * 40px)) clamp(calc(var(--ui-content-scale) * 16px), 4vw, calc(var(--ui-content-scale) * 35px)) calc(var(--ui-content-scale) * 12px);
  font-size: calc(var(--ui-font-scale) * 28px);
  font-weight: var(--t-weight-medium);
  letter-spacing: -0.01em;
}
.t-don-popup__scroll {
  flex: 1 1 auto; overflow-y: auto;
  padding: 0 clamp(calc(var(--ui-content-scale) * 16px), 4vw, calc(var(--ui-content-scale) * 35px)) calc(var(--ui-content-scale) * 16px);
  font-size: calc(var(--ui-font-scale) * 15px); line-height: 1.55;
  color: var(--t-c-text-secondary);
  touch-action: pan-y;
  overscroll-behavior: contain;
}
.t-don-popup__scroll p { margin: 0 0 calc(var(--ui-content-scale) * 14px) 0; }
.t-don-popup__body {
  flex: 1 1 auto; overflow-y: auto;
  padding: 0 clamp(calc(var(--ui-content-scale) * 16px), 4vw, calc(var(--ui-content-scale) * 35px)) clamp(calc(var(--ui-content-scale) * 16px), 4vw, calc(var(--ui-content-scale) * 24px));
  touch-action: pan-y;
  overscroll-behavior: contain;
}
.t-don-popup__actions {
  padding: calc(var(--ui-content-scale) * 16px) clamp(calc(var(--ui-content-scale) * 16px), 4vw, calc(var(--ui-content-scale) * 35px)) clamp(calc(var(--ui-content-scale) * 20px), 4vw, calc(var(--ui-content-scale) * 32px));
  display: flex; gap: calc(var(--ui-content-scale) * 12px);
  justify-content: flex-end;
  flex-wrap: wrap;             /* prevents overflow on narrow phones */
}
.t-don-popup__btn {
  min-height: calc(var(--ui-content-scale) * 48px);
  padding: 0 clamp(calc(var(--ui-content-scale) * 14px), 4vw, calc(var(--ui-content-scale) * 28px));
  border-radius: calc(var(--ui-content-scale) * 24px);
  border: 0; cursor: pointer;
  font-size: calc(var(--ui-font-scale) * 16px);
  font-weight: var(--t-weight-medium);
  flex: 1 1 auto;             /* full-width on phone, natural on desktop */
  min-width: max-content;
  background: var(--t-c-overlay-5);
  color: var(--t-c-text-primary);
}
.t-don-popup__btn--primary {
  background: var(--t-c-blue-bright); color: var(--t-c-on-accent);
}
.t-don-popup__btn--disabled,
.t-don-popup__btn:disabled {
  opacity: 0.45; cursor: default;
}

.t-don-section { margin-top: calc(var(--ui-content-scale) * 24px); }
.t-don-section:first-child { margin-top: 0; }
.t-don-section__title {
  font-size: var(--t-fs-large); font-weight: var(--t-weight-medium);
  margin-bottom: calc(var(--ui-content-scale) * 6px);
}
.t-don-section__desc {
  font-size: var(--t-fs-base); color: var(--t-c-text-secondary);
  margin-bottom: calc(var(--ui-content-scale) * 14px);
}
.t-don-radio-row { display: flex; flex-direction: column; gap: calc(var(--ui-content-scale) * 8px); }
.t-don-radio {
  display: flex; align-items: center; gap: calc(var(--ui-content-scale) * 14px);
  padding: calc(var(--ui-content-scale) * 14px) calc(var(--ui-content-scale) * 16px);
  background: var(--t-c-overlay-2);
  border: calc(var(--ui-content-scale) * 1px) solid var(--t-c-overlay-3);
  border-radius: calc(var(--ui-content-scale) * 12px);
  cursor: pointer;
  color: var(--t-c-text-primary);
}
.t-don-radio.active {
  border-color: var(--t-c-blue-bright);
  background: var(--t-c-info-bg);
}
.t-don-radio__dot {
  width: calc(var(--ui-content-scale) * 18px); height: calc(var(--ui-content-scale) * 18px);
  border-radius: 50%;
  border: calc(var(--ui-content-scale) * 2px) solid var(--t-c-overlay-knob);
  position: relative;
  flex: 0 0 calc(var(--ui-content-scale) * 18px);
}
.t-don-radio.active .t-don-radio__dot {
  border-color: var(--t-c-blue-bright);
}
.t-don-radio.active .t-don-radio__dot::after {
  content: "";
  position: absolute; inset: calc(var(--ui-content-scale) * 3px);
  background: var(--t-c-blue-bright); border-radius: 50%;
}
.t-don-radio__text { display: flex; flex-direction: column; align-items: flex-start; }
.t-don-radio__label { font-size: var(--t-fs-base); font-weight: var(--t-weight-medium); }
.t-don-radio__sub   { font-size: var(--t-fs-small); color: var(--t-c-text-secondary); margin-top: calc(var(--ui-content-scale) * 2px); }

/* iOS-style sliding toggle, shared by Settings + DriveOnNavConfigPopup. */
.t-don-toggle {
  width: calc(var(--ui-content-scale) * 52px); height: calc(var(--ui-content-scale) * 30px); border-radius: calc(var(--ui-content-scale) * 16px);
  background: var(--t-c-overlay-7);
  border: 0; padding: calc(var(--ui-content-scale) * 2px);
  cursor: pointer; position: relative;
}
.t-don-toggle.on { background: var(--t-c-blue-bright); }
.t-don-toggle__knob {
  display: block; width: calc(var(--ui-content-scale) * 26px); height: calc(var(--ui-content-scale) * 26px);
  background: var(--t-c-pure-white); border-radius: 50%;
  transform: translateX(0); transition: transform 160ms ease;
  box-shadow: var(--t-shadow-mid);
}
.t-don-toggle.on .t-don-toggle__knob { transform: translateX(calc(var(--ui-content-scale) * 22px)); }
.t-don-toggle-row { display: flex; }

/* NoA row inside the trip summary card. */
.t-noa-row {
  display: flex; align-items: center;
  gap: calc(var(--ui-content-scale) * 14px);
  padding: calc(var(--ui-content-scale) * 14px) calc(var(--ui-content-scale) * 16px);
  margin-top: calc(var(--ui-content-scale) * 12px);
  background: var(--t-c-overlay-1);
  border-radius: calc(var(--ui-content-scale) * 14px);
}
.t-noa-toggle {
  width: calc(var(--ui-content-scale) * 52px); height: calc(var(--ui-content-scale) * 30px); border-radius: calc(var(--ui-content-scale) * 16px);
  background: var(--t-c-overlay-7);
  border: 0; padding: calc(var(--ui-content-scale) * 2px);
  cursor: pointer; position: relative;
  flex: 0 0 calc(var(--ui-content-scale) * 52px);
}
.t-noa-toggle.on { background: var(--t-c-blue-bright); }
.t-noa-toggle__knob {
  display: block; width: calc(var(--ui-content-scale) * 26px); height: calc(var(--ui-content-scale) * 26px);
  background: var(--t-c-pure-white); border-radius: 50%;
  transform: translateX(0); transition: transform 160ms ease;
  box-shadow: var(--t-shadow-mid);
}
.t-noa-toggle.on .t-noa-toggle__knob { transform: translateX(calc(var(--ui-content-scale) * 22px)); }
.t-noa-row__text { flex: 1 1 auto; display: flex; flex-direction: column; min-width: 0; }
.t-noa-row__label { font-size: var(--t-fs-base); font-weight: var(--t-weight-medium); }
.t-noa-row__sub   { font-size: var(--t-fs-small); color: var(--t-c-text-secondary); }
.t-noa-row__info {
  width: calc(var(--ui-content-scale) * 28px); height: calc(var(--ui-content-scale) * 28px); border-radius: 50%;
  background: var(--t-c-overlay-4);
  color: var(--t-c-text-primary);
  border: 0; cursor: pointer;
  font-style: italic; font-family: serif;
}

/* ── EditTargetSOCPopup + SetBatteryPercentageButton ────────────────── */
.t-soc-popup .t-don-popup__body { padding-top: calc(var(--ui-content-scale) * 12px); }
.t-soc-popup__info {
  font-size: var(--t-fs-base); line-height: 1.5;
  color: var(--t-c-text-secondary);
  margin-bottom: calc(var(--ui-content-scale) * 28px);
}
.t-soc-popup__energy-row {
  display: flex; align-items: baseline; justify-content: space-between;
  margin-bottom: calc(var(--ui-content-scale) * 14px);
}
.t-soc-popup__energy-label { font-size: var(--t-fs-base); color: var(--t-c-text-secondary); }
.t-soc-popup__energy-value { font-size: var(--t-fs-2xlarge); font-weight: var(--t-weight-medium); }
.t-soc-popup__slider {
  width: 100%; -webkit-appearance: none; appearance: none;
  height: calc(var(--ui-content-scale) * 6px); border-radius: calc(var(--ui-content-scale) * 3px);
  background: var(--t-c-overlay-6);
  outline: none;
  /* Native range gesture — claim the horizontal drag so any ancestor
     touch-action policy can't override the thumb manipulation. */
  touch-action: none;
}
.t-soc-popup__slider::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: calc(var(--ui-content-scale) * 28px); height: calc(var(--ui-content-scale) * 28px); border-radius: 50%;
  background: var(--t-c-pure-white);
  box-shadow: var(--t-shadow-strong);
  cursor: pointer;
}
.t-soc-popup__slider::-moz-range-thumb {
  width: calc(var(--ui-content-scale) * 28px); height: calc(var(--ui-content-scale) * 28px); border-radius: 50%;
  background: var(--t-c-pure-white); border: 0;
  box-shadow: var(--t-shadow-strong);
  cursor: pointer;
}
.t-soc-popup__scale {
  display: flex; justify-content: space-between;
  font-size: var(--t-fs-small); color: var(--t-c-text-secondary);
  margin-top: calc(var(--ui-content-scale) * 8px);
}
/* Planner-feasibility hint under the slider — shown only when the
 * trip's destination_soe_bounds narrow the achievable range from the
 * absolute 10–95 % slider domain. Quiet text (secondary colour) so it
 * informs without competing with the slider value. */
.t-soc-popup__hint {
  font-size: var(--t-fs-small);
  color: var(--t-c-text-secondary);
  margin-top: calc(var(--ui-content-scale) * 6px);
  font-style: italic;
}
.t-soc-inline-btn {
  display: block; width: 100%;
  margin-top: calc(var(--ui-content-scale) * 12px);
  padding: calc(var(--ui-content-scale) * 12px) calc(var(--ui-content-scale) * 16px);
  background: var(--t-c-overlay-2);
  border: calc(var(--ui-content-scale) * 1px) solid var(--t-c-overlay-4);
  border-radius: calc(var(--ui-content-scale) * 14px);
  color: var(--t-c-text-primary);
  font-size: var(--t-fs-base);
  cursor: pointer;
  text-align: left;
}
.t-soc-inline-btn:hover { background: var(--t-c-overlay-3); }

/* ── AutoNavSuggestionView — floating map overlay ──────────────────── */
/* Was inline in HomeView; now a small floating chip on the right side
   of the map (below the junction view). Only renders when Home is the
   active view AND there's a high-confidence prediction. */
.t-auto-nav-card {
  position: absolute;
  top: calc(env(safe-area-inset-top, calc(var(--ui-content-scale) * 16px)) + calc(var(--ui-content-scale) * 24px));
  right: calc(env(safe-area-inset-right, calc(var(--ui-content-scale) * 16px)) + calc(var(--ui-content-scale) * 96px));
  width: min(calc(var(--ui-content-scale) * 320px), calc(100vw - calc(var(--ui-content-scale) * 32px)));
  padding: calc(var(--ui-content-scale) * 14px) calc(var(--ui-content-scale) * 16px);
  background: var(--t-pill-bg);
  color: var(--t-c-text-primary);
  border-radius: calc(var(--ui-content-scale) * 16px);
  box-shadow: var(--t-shadow-card);
  backdrop-filter: blur(calc(var(--ui-content-scale) * 20px));
  -webkit-backdrop-filter: blur(calc(var(--ui-content-scale) * 20px));
  z-index: 5;
}
/* On phones it would fight the right strip + sheet — hide on mobile.
   Predictive suggestions belong in the bottom sheet's NavCard anyway. */
@media (max-width: 767px) {
  .t-auto-nav-card { display: none; }
}
.t-auto-nav-card__close {
  position: absolute; top: calc(var(--ui-content-scale) * 12px); right: calc(var(--ui-content-scale) * 12px);
  width: calc(var(--ui-content-scale) * 28px); height: calc(var(--ui-content-scale) * 28px); border-radius: 50%;
  background: var(--t-c-overlay-4); border: 0;
  display: flex; align-items: center; justify-content: center;
  color: var(--t-c-text-primary); cursor: pointer;
}
.t-auto-nav-card__close span { display: inline-flex; width: calc(var(--ui-content-scale) * 14px); height: calc(var(--ui-content-scale) * 14px); }
.t-auto-nav-card__top {
  display: flex; gap: calc(var(--ui-content-scale) * 14px); align-items: flex-start;
  padding-right: calc(var(--ui-content-scale) * 32px);        /* keep clear of the X */
}
.t-auto-nav-card__pin {
  width: calc(var(--ui-content-scale) * 44px); height: calc(var(--ui-content-scale) * 44px); border-radius: 50%;
  background: var(--t-c-overlay-4);
  display: flex; align-items: center; justify-content: center;
  flex: 0 0 calc(var(--ui-content-scale) * 44px);
}
.t-auto-nav-card__pin svg { width: calc(var(--ui-content-scale) * 22px); height: calc(var(--ui-content-scale) * 22px); }
.t-auto-nav-card__labels { display: flex; flex-direction: column; min-width: 0; }
.t-auto-nav-card__reason {
  font-size: var(--t-fs-small); text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--t-c-text-secondary);
  margin-bottom: calc(var(--ui-content-scale) * 4px);
}
.t-auto-nav-card__name {
  font-size: var(--t-fs-large); font-weight: var(--t-weight-medium);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.t-auto-nav-card__address {
  font-size: var(--t-fs-small); color: var(--t-c-text-secondary);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.t-auto-nav-card__meta {
  margin-top: calc(var(--ui-content-scale) * 12px);
  display: flex; gap: calc(var(--ui-content-scale) * 6px); align-items: baseline;
  font-size: var(--t-fs-base); color: var(--t-c-text-secondary);
}
.t-auto-nav-card__eta { color: var(--t-c-text-primary); font-weight: var(--t-weight-medium); font-size: var(--t-fs-medium); }
.t-auto-nav-card__dot { color: var(--t-c-text-secondary); }
.t-auto-nav-card__cta {
  margin-top: calc(var(--ui-content-scale) * 14px); width: 100%; min-height: calc(var(--ui-content-scale) * 48px);
  background: var(--t-c-blue-bright); color: var(--t-c-on-accent);
  border: 0; border-radius: calc(var(--ui-content-scale) * 24px);
  font-size: var(--t-fs-medium); font-weight: var(--t-weight-medium);
  cursor: pointer;
}
.t-auto-nav-card__cta:hover { filter: brightness(1.06); }

/* ── SuperchargerQueueStatusCard (4 states) ─────────────────────────── */
.t-sc-queue {
  position: absolute;
  left: 50%; transform: translateX(-50%);
  /* Desktop: bottom-center. Phones bump up via media query below so
     the card doesn't hide behind the bottom-sheet panel. */
  bottom: max(calc(var(--ui-content-scale) * 24px), env(safe-area-inset-bottom, calc(var(--ui-content-scale) * 24px)));
  z-index: 700;
  pointer-events: auto;
}
@media (max-width: 767px) {
  .t-sc-queue {
    bottom: calc(var(--sheet-h) * 1dvh + calc(var(--ui-content-scale) * 8px));
    /* Tracks --sheet-h per frame; no transition. */
  }
}
.t-sc-queue__card {
  background: var(--t-pill-bg);
  color: var(--t-c-text-primary);
  border-radius: calc(var(--ui-content-scale) * 18px);
  box-shadow: var(--t-shadow-deep);
  padding: calc(var(--ui-content-scale) * 18px) calc(var(--ui-content-scale) * 20px);
  /* Fluid width — caps at 540 but shrinks on small phones with
     side margins respected. min-width removed so it can collapse. */
  width: min(calc(var(--ui-content-scale) * 540px), calc(100vw - calc(var(--ui-content-scale) * 32px)));
  display: flex;
  align-items: center;
  gap: calc(var(--ui-content-scale) * 16px);
}
.t-sc-queue__card--loading,
.t-sc-queue__card--active,
.t-sc-queue__card--error {
  flex-direction: column; align-items: stretch;
}
.t-sc-queue__icon {
  width: calc(var(--ui-content-scale) * 56px); height: calc(var(--ui-content-scale) * 56px);
  flex: 0 0 calc(var(--ui-content-scale) * 56px);
  object-fit: contain;
}
.t-sc-queue__text { flex: 1 1 auto; min-width: 0; }
.t-sc-queue__caption {
  font-size: var(--t-fs-small); text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--t-c-text-secondary);
}
.t-sc-queue__title {
  font-size: var(--t-fs-medium); font-weight: var(--t-weight-medium);
  margin: calc(var(--ui-content-scale) * 2px) 0;
}
.t-sc-queue__btn {
  min-height: calc(var(--ui-content-scale) * 48px); padding: 0 calc(var(--ui-content-scale) * 24px);
  border-radius: calc(var(--ui-content-scale) * 24px); border: 0;
  font-size: var(--t-fs-base); font-weight: var(--t-weight-medium);
  cursor: pointer;
}
.t-sc-queue__btn--primary {
  background: var(--t-c-blue-bright); color: var(--t-c-on-accent);
}
.t-sc-queue__btn--secondary {
  background: var(--t-c-overlay-5);
  color: var(--t-c-text-primary);
}
.t-sc-queue__btn[disabled] { opacity: 0.45; cursor: default; }
.t-sc-queue__top-row {
  display: flex; align-items: center; gap: calc(var(--ui-content-scale) * 14px);
}
.t-sc-queue__bottom-row {
  margin-top: calc(var(--ui-content-scale) * 14px);
  display: flex; justify-content: flex-end;
}
.t-sc-queue__status { flex: 1 1 auto; }
.t-sc-queue__error-msg {
  font-size: var(--t-fs-base); color: var(--t-c-text-primary);
  flex: 1 1 auto;
}
/* Shimmer placeholder for the loading state — mimics
   SuperchargerQueueLoadingShimmer in cards.uiml. */
.t-sc-queue__shimmer {
  flex: 1 1 auto; height: calc(var(--ui-content-scale) * 18px);
  border-radius: calc(var(--ui-content-scale) * 9px);
  background: linear-gradient(90deg,
    var(--t-c-overlay-2) 0%,
    var(--t-c-overlay-7) 50%,
    var(--t-c-overlay-2) 100%);
  background-size: 200% 100%;
  animation: t-shimmer 1.2s linear infinite;
}
@keyframes t-shimmer {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

/* ── ChargerClosurePopup ────────────────────────────────────────────── */
.t-closure-popup { width: min(calc(var(--ui-content-scale) * 560px), calc(100vw - calc(var(--ui-content-scale) * 32px))); }
.t-closure-popup__body {
  align-items: center; text-align: center;
  padding-top: calc(var(--ui-content-scale) * 28px);
}
.t-closure-popup__icon {
  width: calc(var(--ui-content-scale) * 96px); height: calc(var(--ui-content-scale) * 96px);
  margin: calc(var(--ui-content-scale) * 8px) auto calc(var(--ui-content-scale) * 18px);
  display: block;
  object-fit: contain;
}
.t-closure-popup__site {
  font-size: var(--t-fs-large); font-weight: var(--t-weight-medium);
  margin-bottom: calc(var(--ui-content-scale) * 8px);
}
.t-closure-popup__status {
  font-size: var(--t-fs-base); color: var(--t-c-text-secondary);
  line-height: 1.5;
  max-width: calc(var(--ui-content-scale) * 420px); margin: 0 auto;
}

/* ── PointOfNoReturnPopup ───────────────────────────────────────────── */
.t-ponr-popup { width: min(calc(var(--ui-content-scale) * 600px), calc(100vw - calc(var(--ui-content-scale) * 32px))); }
.t-ponr-popup__body {
  align-items: center; text-align: center;
  padding-top: calc(var(--ui-content-scale) * 28px);
}
.t-ponr-popup__icon {
  width: calc(var(--ui-content-scale) * 96px); height: calc(var(--ui-content-scale) * 96px);
  margin: calc(var(--ui-content-scale) * 8px) auto calc(var(--ui-content-scale) * 18px);
  display: block; object-fit: contain;
}
.t-ponr-popup__title {
  font-size: var(--t-fs-xlarge); font-weight: var(--t-weight-medium);
  margin-bottom: calc(var(--ui-content-scale) * 12px);
}
.t-ponr-popup__body-text {
  font-size: var(--t-fs-base); color: var(--t-c-text-secondary);
  line-height: 1.5;
  max-width: calc(var(--ui-content-scale) * 480px); margin: 0 auto;
}

/* ── Notification kind colors (firmware-mapped) ────────────────────── */
.t-notification--severe-weather       { background: var(--t-c-banner-amber); }
.t-notification--ccs-only             { background: var(--t-c-banner-indigo); }
.t-notification--rerouting            { background: var(--t-c-banner-blue); }
.t-notification--precondition        { background: var(--t-c-banner-orange); }
.t-notification--destination-weather  { background: var(--t-c-banner-green); }
.t-notification--route-reason         { background: var(--t-c-banner-slate); }

/* ── MapInfoButton + MapUpdateButton ───────────────────────────────── */
.t-info-btn-wrap { position: relative; display: inline-block; }
.t-info-btn {
  width: calc(var(--ui-content-scale) * 22px); height: calc(var(--ui-content-scale) * 22px); border-radius: 50%;
  background: var(--t-c-overlay-5);
  border: 0; color: var(--t-c-text-primary);
  font-style: italic; font-family: serif;
  cursor: pointer; line-height: calc(var(--ui-font-scale) * 22px);
}
.t-info-btn__tooltip {
  position: absolute; top: calc(var(--ui-content-scale) * 28px); right: 0;
  z-index: 100;
  min-width: calc(var(--ui-content-scale) * 220px); max-width: calc(var(--ui-content-scale) * 320px);
  padding: calc(var(--ui-content-scale) * 10px) calc(var(--ui-content-scale) * 12px);
  background: var(--t-pill-bg);
  color: var(--t-c-text-primary);
  font-size: var(--t-fs-small); line-height: 1.4;
  border-radius: calc(var(--ui-content-scale) * 10px);
  box-shadow: var(--t-shadow-strong);
}
.t-map-update {
  display: flex; align-items: center;
  gap: calc(var(--ui-content-scale) * 16px);
  padding: calc(var(--ui-content-scale) * 14px) calc(var(--ui-content-scale) * 16px);
  background: var(--t-c-info-bg);
  border: calc(var(--ui-content-scale) * 1px) solid rgba(62, 106, 225, 0.35);
  border-radius: calc(var(--ui-content-scale) * 14px);
  margin: calc(var(--ui-content-scale) * 12px) calc(var(--ui-content-scale) * 16px);
}
.t-map-update__text { flex: 1 1 auto; min-width: 0; }
.t-map-update__title {
  font-size: var(--t-fs-base); font-weight: var(--t-weight-medium);
  color: var(--t-c-text-primary);
}
.t-map-update__sub {
  font-size: var(--t-fs-small); color: var(--t-c-text-secondary);
}
.t-map-update__btn {
  min-height: calc(var(--ui-content-scale) * 36px); padding: 0 calc(var(--ui-content-scale) * 18px);
  background: var(--t-c-blue-bright); color: var(--t-c-on-accent);
  border: 0; border-radius: calc(var(--ui-content-scale) * 18px);
  font-size: var(--t-fs-small); cursor: pointer;
}

/* ── OptimizedRoutePopup ───────────────────────────────────────────── */
.t-optroute-popup { width: min(calc(var(--ui-content-scale) * 640px), calc(100vw - calc(var(--ui-content-scale) * 32px))); }
.t-optroute-popup__destination {
  font-size: var(--t-fs-base); color: var(--t-c-text-secondary);
  margin-bottom: calc(var(--ui-content-scale) * 16px);
}
.t-optroute-popup__compare {
  display: flex; align-items: center; gap: calc(var(--ui-content-scale) * 16px);
  margin-bottom: calc(var(--ui-content-scale) * 14px);
}
.t-optroute-popup__col {
  flex: 1 1 0;
  padding: calc(var(--ui-content-scale) * 16px);
  background: var(--t-c-overlay-2);
  border-radius: calc(var(--ui-content-scale) * 14px);
  text-align: center;
}
.t-optroute-popup__col--new {
  background: var(--t-c-info-bg);
  border: calc(var(--ui-content-scale) * 1px) solid rgba(62, 106, 225, 0.35);
}
.t-optroute-popup__col-title {
  font-size: var(--t-fs-small); text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--t-c-text-secondary);
  margin-bottom: calc(var(--ui-content-scale) * 8px);
}
.t-optroute-popup__col-time {
  font-size: var(--t-fs-xlarge); font-weight: var(--t-weight-medium);
  margin-bottom: calc(var(--ui-content-scale) * 4px);
}
.t-optroute-popup__col-dist { font-size: var(--t-fs-small); color: var(--t-c-text-secondary); }
.t-optroute-popup__arrow { font-size: var(--t-fs-large); color: var(--t-c-text-secondary); }
.t-optroute-popup__savings {
  text-align: center; font-size: var(--t-fs-base);
  color: var(--t-c-success-fg); font-weight: var(--t-weight-medium);
  margin-top: calc(var(--ui-content-scale) * 8px);
}

/* ── ToggleRow shared by MapSettingsPopup + future panels ─────────── */
.t-toggle-row {
  display: flex; align-items: center; justify-content: space-between;
  padding: calc(var(--ui-content-scale) * 12px) 0;
  border-bottom: calc(var(--ui-content-scale) * 1px) solid var(--t-c-overlay-3);
}
.t-toggle-row:last-child { border-bottom: 0; }
.t-toggle-row__label {
  font-size: var(--t-fs-base); color: var(--t-c-text-primary);
}

/* ── EnergyConsumptionDrivingView ──────────────────────────────────── */
.t-energy-view { width: min(calc(var(--ui-content-scale) * 880px), calc(100vw - calc(var(--ui-content-scale) * 32px))); }
.t-energy-view__total-row { margin-bottom: calc(var(--ui-content-scale) * 12px); }
.t-energy-view__total { display: flex; align-items: baseline; gap: calc(var(--ui-content-scale) * 8px); }
.t-energy-view__total-value { font-size: var(--t-fs-2xlarge); font-weight: var(--t-weight-medium); }
.t-energy-view__total-unit  { font-size: var(--t-fs-base); color: var(--t-c-text-secondary); }
.t-energy-view__total-diff  { font-size: var(--t-fs-small); color: var(--t-c-text-secondary); }
.t-energy-view__chart {
  width: 100%; height: calc(var(--ui-content-scale) * 220px);
  background: var(--t-c-overlay-1);
  border-radius: calc(var(--ui-content-scale) * 12px);
  margin: calc(var(--ui-content-scale) * 14px) 0;
  overflow: hidden;
}
.t-energy-view__chart svg { width: 100%; height: 100%; display: block; }
.t-energy-view__chart-proj   { fill: none; stroke: var(--t-c-overlay-knob); stroke-width: 2; stroke-dasharray: 4 4; }
.t-energy-view__chart-actual { fill: none; stroke: var(--t-c-blue-bright);             stroke-width: 2.5; }
.t-energy-view__chart-empty { display: flex; align-items: center; justify-content: center;
  height: 100%; color: var(--t-c-text-secondary); }
.t-energy-view__split { display: flex; gap: calc(var(--ui-content-scale) * 24px); align-items: flex-start; }
.t-energy-view__breakdown { flex: 1 1 0; }
.t-energy-view__tip { flex: 1 1 0; }
.t-energy-view__breakdown-head {
  display: flex; justify-content: space-between;
  font-size: var(--t-fs-mini); letter-spacing: 0.05em; text-transform: uppercase;
  color: var(--t-c-text-secondary);
  padding: calc(var(--ui-content-scale) * 4px) 0 calc(var(--ui-content-scale) * 10px); border-bottom: calc(var(--ui-content-scale) * 1px) solid var(--t-c-overlay-4);
}
.t-energy-view__row {
  display: grid;
  grid-template-columns: 1fr calc(var(--ui-content-scale) * 110px) calc(var(--ui-content-scale) * 60px);
  align-items: center;
  padding: calc(var(--ui-content-scale) * 10px) 0; border-bottom: calc(var(--ui-content-scale) * 1px) solid var(--t-c-overlay-2);
}
.t-energy-view__row-label { font-size: var(--t-fs-base); color: var(--t-c-text-primary); }
.t-energy-view__row-value { font-size: var(--t-fs-small); color: var(--t-c-text-secondary); text-align: right; }
.t-energy-view__row-diff  { font-size: var(--t-fs-small); text-align: right; }
.t-energy-view__row-diff--high { color: var(--t-c-error-fg); }
.t-energy-view__row-diff--low  { color: var(--t-c-success-fg); }
.t-energy-view__tip-title { font-size: var(--t-fs-mini); text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--t-c-text-secondary); margin-bottom: calc(var(--ui-content-scale) * 8px); }
.t-energy-view__tip-body { font-size: var(--t-fs-base); line-height: 1.5; color: var(--t-c-text-primary); }

/* ── Weather views ─────────────────────────────────────────────────── */
.t-weather-popup { width: min(calc(var(--ui-content-scale) * 680px), calc(100vw - calc(var(--ui-content-scale) * 32px))); }
.t-weather-popup__summary {
  display: grid; grid-template-columns: 1fr 1fr calc(var(--ui-content-scale) * 80px);
  gap: calc(var(--ui-content-scale) * 18px); align-items: center; margin-bottom: calc(var(--ui-content-scale) * 18px);
}
.t-weather-popup__temp     { font-size: var(--t-fs-hero); font-weight: 300; line-height: 1; }
.t-weather-popup__outside-label { font-size: var(--t-fs-small); color: var(--t-c-text-secondary); margin-top: calc(var(--ui-content-scale) * 4px); }
.t-weather-popup__condition { font-size: var(--t-fs-large); font-weight: var(--t-weight-medium); }
.t-weather-popup__highlow { display: flex; gap: calc(var(--ui-content-scale) * 14px); color: var(--t-c-text-secondary); font-size: var(--t-fs-base); margin-top: calc(var(--ui-content-scale) * 4px); }
.t-weather-popup__icon { font-size: var(--t-fs-hero); text-align: right; }
.t-weather-popup__forecast {
  display: flex; gap: calc(var(--ui-content-scale) * 10px); overflow-x: auto;
  padding-bottom: calc(var(--ui-content-scale) * 8px);
  margin-bottom: calc(var(--ui-content-scale) * 16px);
  touch-action: pan-x;
  overscroll-behavior: contain;
}
.t-weather-forecast-item {
  flex: 0 0 calc(var(--ui-content-scale) * 80px);
  display: flex; flex-direction: column; align-items: center; gap: calc(var(--ui-content-scale) * 6px);
  padding: calc(var(--ui-content-scale) * 10px) calc(var(--ui-content-scale) * 8px);
  background: var(--t-c-overlay-2); border-radius: calc(var(--ui-content-scale) * 12px);
}
.t-weather-forecast-item__time { font-size: var(--t-fs-small); color: var(--t-c-text-secondary); }
.t-weather-forecast-item__icon { font-size: var(--t-fs-xlarge); }
.t-weather-forecast-item__temp { font-size: var(--t-fs-base); font-weight: var(--t-weight-medium); }
.t-weather-forecast-item__precip { font-size: var(--t-fs-mini); color: var(--t-c-info-fg); min-height: calc(var(--ui-content-scale) * 14px); }
.t-weather-popup__precip-btn {
  width: 100%; min-height: calc(var(--ui-content-scale) * 44px);
  background: var(--t-c-overlay-4); border: 0; border-radius: calc(var(--ui-content-scale) * 22px);
  color: var(--t-c-text-primary); font-size: var(--t-fs-base);
  margin-bottom: calc(var(--ui-content-scale) * 16px); cursor: pointer;
}
.t-weather-popup__current-info {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: calc(var(--ui-content-scale) * 10px) calc(var(--ui-content-scale) * 24px); padding: calc(var(--ui-content-scale) * 12px) 0;
  border-top: calc(var(--ui-content-scale) * 1px) solid var(--t-c-overlay-3);
}
.t-weather-popup__detail-row { display: flex; justify-content: space-between; padding: calc(var(--ui-content-scale) * 4px) 0; font-size: var(--t-fs-base); }
.t-weather-popup__detail-name { color: var(--t-c-text-secondary); }
.t-weather-popup__timestamp { font-size: var(--t-fs-small); color: var(--t-c-text-secondary); margin-top: calc(var(--ui-content-scale) * 12px); text-align: right; }

.t-weather-player {
  position: absolute; left: 50%;
  bottom: max(calc(var(--ui-content-scale) * 96px), calc(env(safe-area-inset-bottom, 0) + calc(var(--ui-content-scale) * 96px)));
  transform: translateX(-50%);
  display: flex; align-items: center; gap: calc(var(--ui-content-scale) * 12px);
  padding: calc(var(--ui-content-scale) * 8px) calc(var(--ui-content-scale) * 14px);
  background: var(--t-pill-bg);
  border-radius: calc(var(--ui-content-scale) * 22px);
  box-shadow: var(--t-shadow-strong);
  z-index: 500;
}
.t-weather-player__btn { width: calc(var(--ui-content-scale) * 32px); height: calc(var(--ui-content-scale) * 32px); border-radius: 50%; background: var(--t-c-blue-bright); color: var(--t-c-on-accent); border: 0; cursor: pointer; font-size: var(--t-fs-small); }
.t-weather-player__time { font-size: var(--t-fs-small); color: var(--t-c-text-primary); }
.t-weather-player__close { width: calc(var(--ui-content-scale) * 24px); height: calc(var(--ui-content-scale) * 24px); border-radius: 50%; background: var(--t-c-overlay-5); border: 0; color: var(--t-c-text-primary); cursor: pointer; font-size: var(--t-fs-mini); }

/* ── TripStopView ──────────────────────────────────────────────────── */
.t-trip-stop { width: min(calc(var(--ui-content-scale) * 520px), calc(100vw - calc(var(--ui-content-scale) * 32px))); }
.t-trip-stop__name { font-size: var(--t-fs-xlarge); font-weight: var(--t-weight-medium); margin-bottom: calc(var(--ui-content-scale) * 4px); }
.t-trip-stop__addr { font-size: var(--t-fs-base); color: var(--t-c-text-secondary); margin-bottom: calc(var(--ui-content-scale) * 18px); }
.t-trip-stop__row { display: flex; justify-content: space-between; padding: calc(var(--ui-content-scale) * 10px) 0; border-bottom: calc(var(--ui-content-scale) * 1px) solid var(--t-c-overlay-2); font-size: var(--t-fs-base); }

/* ── TNavSuggestionsCard (multi) ───────────────────────────────────── */
.t-tnav-card {
  margin: calc(var(--ui-content-scale) * 12px) calc(var(--ui-content-scale) * 16px);
  padding: calc(var(--ui-content-scale) * 14px);
  background: var(--t-pill-bg);
  border-radius: calc(var(--ui-content-scale) * 16px);
}
.t-tnav-card__top { display: flex; gap: calc(var(--ui-content-scale) * 10px); margin-bottom: calc(var(--ui-content-scale) * 12px); }
.t-tnav-card__nav-btn {
  flex: 1 1 auto; min-height: calc(var(--ui-content-scale) * 44px); border: 0;
  background: var(--t-c-blue-bright); color: var(--t-c-on-accent);
  border-radius: calc(var(--ui-content-scale) * 22px); font-size: var(--t-fs-base); font-weight: var(--t-weight-medium); cursor: pointer;
}
.t-tnav-card__shortcut {
  display: inline-flex; align-items: center; gap: calc(var(--ui-content-scale) * 8px);
  min-height: calc(var(--ui-content-scale) * 44px); padding: 0 calc(var(--ui-content-scale) * 14px);
  background: var(--t-c-overlay-4); border: 0;
  color: var(--t-c-text-primary);
  border-radius: calc(var(--ui-content-scale) * 22px); font-size: var(--t-fs-small); cursor: pointer;
}
.t-tnav-card__shortcut svg { width: calc(var(--ui-content-scale) * 16px); height: calc(var(--ui-content-scale) * 16px); }
.t-tnav-card__scroll {
  display: flex; gap: calc(var(--ui-content-scale) * 10px); overflow-x: auto; padding-bottom: calc(var(--ui-content-scale) * 4px);
  touch-action: pan-x; overscroll-behavior: contain;
}
.t-tnav-card__item {
  flex: 0 0 calc(var(--ui-content-scale) * 220px);
  display: flex; align-items: center; gap: calc(var(--ui-content-scale) * 10px);
  padding: calc(var(--ui-content-scale) * 10px) calc(var(--ui-content-scale) * 12px);
  background: var(--t-c-overlay-2); border-radius: calc(var(--ui-content-scale) * 12px);
  cursor: pointer;
}
.t-tnav-card__item-pin {
  width: calc(var(--ui-content-scale) * 32px); height: calc(var(--ui-content-scale) * 32px); border-radius: 50%;
  background: var(--t-c-overlay-4);
  display: flex; align-items: center; justify-content: center;
  flex: 0 0 calc(var(--ui-content-scale) * 32px);
}
.t-tnav-card__item-pin svg { width: calc(var(--ui-content-scale) * 16px); height: calc(var(--ui-content-scale) * 16px); }
.t-tnav-card__item-labels { min-width: 0; }
.t-tnav-card__item-name { font-size: var(--t-fs-small); font-weight: var(--t-weight-medium); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.t-tnav-card__item-addr { font-size: var(--t-fs-mini); color: var(--t-c-text-secondary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* ── VoiceRecCard ──────────────────────────────────────────────────── */
.t-voice-card {
  position: fixed; left: 50%; bottom: calc(var(--ui-content-scale) * 80px); transform: translateX(-50%);
  width: calc(var(--ui-content-scale) * 320px);
  padding: calc(var(--ui-content-scale) * 22px) calc(var(--ui-content-scale) * 18px);
  background: var(--t-pill-bg);
  border-radius: calc(var(--ui-content-scale) * 18px);
  box-shadow: var(--t-shadow-popup);
  text-align: center;
  z-index: 900;
}
.t-voice-card__bg-pulse {
  position: absolute; inset: calc(var(--ui-content-scale) * -6px);
  border-radius: calc(var(--ui-content-scale) * 22px);
  border: calc(var(--ui-content-scale) * 2px) solid var(--t-c-blue-bright);
  animation: t-voice-pulse 1.4s ease-in-out infinite;
}
@keyframes t-voice-pulse { 0%,100% { opacity: 0.5; transform: scale(1); } 50% { opacity: 1; transform: scale(1.02); } }
.t-voice-card__icon { font-size: var(--t-fs-display); margin-bottom: calc(var(--ui-content-scale) * 10px); }
.t-voice-card__title { font-size: var(--t-fs-large); font-weight: var(--t-weight-medium); margin-bottom: calc(var(--ui-content-scale) * 4px); }
.t-voice-card__hint { font-size: var(--t-fs-small); color: var(--t-c-text-secondary); margin-bottom: calc(var(--ui-content-scale) * 14px); }
.t-voice-card__close { min-height: calc(var(--ui-content-scale) * 38px); padding: 0 calc(var(--ui-content-scale) * 20px); background: var(--t-c-overlay-5); border: 0; color: var(--t-c-text-primary); border-radius: calc(var(--ui-content-scale) * 19px); cursor: pointer; }

/* ── CarAssistCard ─────────────────────────────────────────────────── */
.t-car-assist { width: min(calc(var(--ui-content-scale) * 620px), calc(100vw - calc(var(--ui-content-scale) * 32px))); }
.t-car-assist__hero { font-size: var(--t-fs-base); color: var(--t-c-text-secondary); margin-bottom: calc(var(--ui-content-scale) * 14px); }
.t-car-assist__suggestions { display: flex; flex-wrap: wrap; gap: calc(var(--ui-content-scale) * 8px); margin-bottom: calc(var(--ui-content-scale) * 14px); }
.t-car-assist__chip { padding: calc(var(--ui-content-scale) * 8px) calc(var(--ui-content-scale) * 14px); background: var(--t-c-overlay-3); border: 0; border-radius: calc(var(--ui-content-scale) * 18px); color: var(--t-c-text-primary); font-size: var(--t-fs-small); cursor: pointer; }
.t-car-assist__input {
  width: 100%; min-height: calc(var(--ui-content-scale) * 44px);
  padding: 0 calc(var(--ui-content-scale) * 14px); border-radius: calc(var(--ui-content-scale) * 22px);
  background: var(--t-c-overlay-3); border: calc(var(--ui-content-scale) * 1px) solid var(--t-c-overlay-4);
  color: var(--t-c-text-primary); font-size: var(--t-fs-base);
}

/* ── UpcomingLaneChangePopup + ELDA + SC Geofence ─────────────────── */
.t-upcoming-lc, .t-elda {
  position: absolute; left: 50%; bottom: calc(var(--ui-content-scale) * 200px);
  transform: translateX(-50%);
  display: flex; align-items: center; gap: calc(var(--ui-content-scale) * 12px);
  padding: calc(var(--ui-content-scale) * 12px) calc(var(--ui-content-scale) * 18px);
  background: rgba(0,0,0,0.85);
  color: var(--t-c-on-accent);
  border-radius: calc(var(--ui-content-scale) * 14px);
  z-index: 600;
}
.t-elda { background: var(--t-c-banner-alert); }
.t-upcoming-lc__arrow, .t-elda__arrow { font-size: var(--t-fs-2xlarge); }
.t-upcoming-lc__title, .t-elda__title { font-size: var(--t-fs-base); font-weight: var(--t-weight-medium); }
.t-upcoming-lc__sub, .t-elda__sub { font-size: var(--t-fs-small); color: rgba(255,255,255,0.7); }
.t-upcoming-lc__cancel, .t-elda__ack {
  min-height: calc(var(--ui-content-scale) * 34px); padding: 0 calc(var(--ui-content-scale) * 14px);
  background: var(--t-c-overlay-7); border: 0;
  color: var(--t-c-on-accent); border-radius: calc(var(--ui-content-scale) * 17px); cursor: pointer;
  font-size: var(--t-fs-small);
}

.t-sc-geofence {
  position: absolute; left: 50%; top: calc(var(--ui-content-scale) * 80px);
  transform: translateX(-50%);
  display: flex; align-items: center; gap: calc(var(--ui-content-scale) * 12px);
  padding: calc(var(--ui-content-scale) * 14px) calc(var(--ui-content-scale) * 18px);
  background: var(--t-pill-bg);
  border-radius: calc(var(--ui-content-scale) * 14px);
  box-shadow: var(--t-shadow-strong);
  z-index: 600;
}
.t-sc-geofence__icon { font-size: var(--t-fs-xlarge); }
.t-sc-geofence__title { font-size: var(--t-fs-base); font-weight: var(--t-weight-medium); }
.t-sc-geofence__stalls { font-size: var(--t-fs-small); color: var(--t-c-text-secondary); }
.t-sc-geofence__close { width: calc(var(--ui-content-scale) * 24px); height: calc(var(--ui-content-scale) * 24px); border-radius: 50%; background: var(--t-c-overlay-5); border: 0; color: var(--t-c-text-primary); cursor: pointer; font-size: var(--t-fs-mini); }

/* ── Subcomponent layout helpers ──────────────────────────────────── */
.t-upcoming-lc__text { display: flex; flex-direction: column; min-width: 0; flex: 1 1 auto; }
.t-elda__text       { display: flex; flex-direction: column; min-width: 0; flex: 1 1 auto; }
.t-sc-geofence__text { display: flex; flex-direction: column; min-width: 0; flex: 1 1 auto; }
.t-weather-popup__temp-col { display: flex; flex-direction: column; align-items: flex-start; }
.t-weather-popup__desc-col { display: flex; align-items: flex-start; gap: calc(var(--ui-content-scale) * 14px); }
.t-weather-popup__detail-value { color: var(--t-c-text-primary); }

/* ── Settings → Demo Triggers section ─────────────────────────────── */
.t-settings__section-label {
  margin-top: calc(var(--ui-content-scale) * 18px);
  font-size: var(--t-fs-mini); text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--t-c-text-secondary);
}
.t-settings__section-hint {
  font-size: var(--t-fs-small); color: var(--t-c-text-secondary);
  margin: calc(var(--ui-content-scale) * 6px) 0 calc(var(--ui-content-scale) * 10px); line-height: 1.45;
}
.t-trigger-grid {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: calc(var(--ui-content-scale) * 8px);
  margin-bottom: calc(var(--ui-content-scale) * 24px);
}
.t-trigger-btn {
  min-height: calc(var(--ui-content-scale) * 42px); padding: 0 calc(var(--ui-content-scale) * 12px);
  background: var(--t-c-overlay-3);
  border: calc(var(--ui-content-scale) * 1px) solid var(--t-c-overlay-4);
  border-radius: calc(var(--ui-content-scale) * 10px);
  color: var(--t-c-text-primary);
  font-size: var(--t-fs-small);
  text-align: left;
  cursor: pointer;
}
.t-trigger-btn:hover { background: var(--t-c-overlay-5); }

.t-weather-player__info {
  width: calc(var(--ui-content-scale) * 24px); height: calc(var(--ui-content-scale) * 24px); border-radius: 50%;
  background: var(--t-c-overlay-5); border: 0;
  color: var(--t-c-text-primary); cursor: pointer;
  font-style: italic; font-family: serif;
}

/* ═══ Cross-device polish ═══════════════════════════════════════════════
   Adds layered touch + perf optimisations on top of the responsive
   grid above. Together with `clamp()` / `min()` / `dvh` in the rest of
   the stylesheet, these rules cover phones, tablets, Tesla MCU + cluster,
   and desktop without any JS reflow code. */

/* Touch-only environments don't have a real hover — but Safari (and
   to a lesser extent Chrome on Android) keeps a STICKY :hover state
   on the last-tapped element AND all its ancestors. If we used a
   universal `*:hover` reset, the sheet root (which has a solid
   background) would inherit the rule via its tapped descendants and
   the bg would vanish on every press — that was the bug.
   Instead, explicitly cancel hover backgrounds ONLY on the elements
   that actually defined :hover bg rules above. The chrome containers
   (.t-shell__left, .t-info-window, .t-places, etc.) keep their
   backgrounds because they're not in this list. */
@media (hover: none) {
  .t-tl-btn:hover,
  .MoreInfoRow:hover,
  .t-place-row:hover,
  .t-info-window__close:hover,
  .t-action-btn:hover,
  .t-action-btn--primary:hover,
  .t-info-window__home-row:hover,
  .t-amenity-btn:hover,
  .t-edit-trip__delete:hover,
  .t-edit-trip__done-btn:hover,
  .t-edit-trip__cancel-btn:hover,
  .t-nav-card__navigate-btn:hover,
  .t-nav-card__shortcut:hover,
  .t-suggestion-item:hover,
  .t-settings__row:hover,
  .t-place-filter-chip:hover,
  .t-mc-btn:hover,
  .t-charger-row:hover,
  .t-soc-inline-btn:hover,
  .t-auto-nav-card__cta:hover,
  .t-trigger-btn:hover,
  .t-don-radio:hover,
  .t-don-popup__btn:hover,
  .t-charger-list__close:hover,
  .t-charger-list__tier-btn:hover {
    background-color: revert;
    background: revert;
    color: revert;
    opacity: revert;
    filter: revert;
  }
  /* No revert block needed for `.pressed` / `.active` / `.on` —
     those classes are set deliberately by component state and the
     rules outside this media query apply on all devices. The earlier
     `background-color: revert` here was a bug: `revert` restores
     the UA default (transparent), which UNDID the explicit
     `var(--t-pill-highlight)` background on active toggle buttons —
     that's why active charger / traffic / weather toggles looked
     identical to inactive ones on the in-car touchscreen. */
}

/* Coarse pointer (touch-only — phone, in-car) → grow small buttons to
   a comfortable 44×44 minimum. Keeps the design at desktop sizes when
   a mouse is in use. */
@media (pointer: coarse) {
  .t-info-btn,
  .t-auto-nav-card__close,
  .t-notification__close,
  .t-noa-row__info,
  .t-sc-geofence__close,
  .t-weather-player__close,
  .t-weather-player__info,
  .t-charger-list__close,
  .t-settings__close {
    min-width: calc(var(--ui-content-scale) * 44px);
    min-height: calc(var(--ui-content-scale) * 44px);
  }
  /* The Settings demo-trigger grid → one column on coarse pointers
     so each button has room. */
  .t-trigger-grid { grid-template-columns: 1fr; }
}

/* Honour the system motion preference — disables our progress-bar fill,
   compass rotation, voice-card pulse, etc. for users with vestibular
   sensitivity. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* Performance: isolate layout/paint inside floating overlays so a
   pop-up open/close doesn't reflow the whole shell. */
.t-modal-backdrop,
.t-don-popup,
.t-sc-queue,
.t-weather-player,
.t-junction-view,
.t-lane-change,
.t-upcoming-lc,
.t-elda,
.t-sc-geofence {
  contain: layout style paint;
}

/* Hint the browser that the progress-bar fill width is the primary
   thing changing — promotes it to a layer once, avoids per-frame
   relayout. Apply only while the bar is actually animating. */
.t-notification__progress { will-change: width; }

/* Tesla MCU + cluster — they're not "mobile" but they are touch.
   Use the same coarse-pointer rules. Tag here for future overrides. */
@media (hover: none) and (pointer: coarse) and (min-width: 1600px) {
  /* Future Tesla-MCU-specific overrides go here. */
}

@media (max-width: 767px) {
  .t-weather-player {
    bottom: calc(var(--sheet-h) * 1dvh + calc(var(--ui-content-scale) * 56px));
  }
}

/* ═══ Mobile-specific compactness ═══════════════════════════════════════
   Tightens every chrome element so the bottom sheet's ~55 dvh is
   enough room for the NavCard + AutoNav + first suggestion row,
   and the right-strip pill fits 8 buttons within the visible map
   area above the sheet. */
@media (max-width: 767px) {
  /* Smaller right-strip buttons (44 = touch target minimum). The
     pill itself becomes vertically scrollable as a safety net for
     very short viewports where 8 × 44 wouldn't fit. */
  :root { --t-row-h: calc(var(--ui-content-scale) * 44px); }
  .t-rs-pill {
    /* Reserve whatever room sits ABOVE the sheet — 24 px breathing
       room for the top-safe-area + clearance from the sheet's
       rounded corner. Re-evaluates as --sheet-h changes. No
       transition on max-height (tracks the finger via --sheet-h). */
    max-height: calc((100 - var(--sheet-h)) * 1dvh - calc(var(--ui-content-scale) * 24px));
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-width: none;          /* hide thumb on mobile */
  }
  .t-rs-pill::-webkit-scrollbar { display: none; }

  /* Compact the various flat-card panels on mobile so they fit a
     smaller sheet without losing legibility. min-height (not height)
     so the fluid card-row tokens inside don't clip if the user has
     bumped the OS text scale up. */
  .t-nav-card { min-height: clamp(calc(var(--ui-content-scale) * 116px), 30vh, calc(var(--ui-content-scale) * 148px)); }
  .t-auto-nav-card { margin: 0; padding: calc(var(--ui-content-scale) * 12px); }
  .t-auto-nav-card__pin { width: calc(var(--ui-content-scale) * 36px); height: calc(var(--ui-content-scale) * 36px); flex: 0 0 calc(var(--ui-content-scale) * 36px); }
  .t-auto-nav-card__pin svg { width: calc(var(--ui-content-scale) * 18px); height: calc(var(--ui-content-scale) * 18px); }
  .t-auto-nav-card__cta { min-height: calc(var(--ui-content-scale) * 44px); }
  .t-suggestion-item {
    padding: calc(var(--ui-content-scale) * 8px) calc(var(--ui-content-scale) * 10px);
    gap: calc(var(--ui-content-scale) * 10px);
  }
  .t-suggestion-item__pin {
    width: calc(var(--ui-content-scale) * 28px); height: calc(var(--ui-content-scale) * 28px); flex: 0 0 calc(var(--ui-content-scale) * 28px);
  }
  .t-tnav-card { margin: 0; padding: calc(var(--ui-content-scale) * 12px); }

  /* Search pill compacted. Fonts inherit the fluid scale — no need
     to override per-breakpoint anymore. */
  .t-search-pill {
    min-height: calc(var(--ui-content-scale) * 48px); max-width: 100%;
    padding: 0 calc(var(--ui-content-scale) * 14px);
  }

  /* Compass ring on the tracking button — at 44px buttons the ring
     radius shrinks so the labels stay inside the button. Set the
     ring radius via a CSS var the inline label transforms can read. */
  .t-mc-compass-label { font-size: var(--t-fs-tiny); }

  /* Notification stack: full-width, slight inset from sheet edge. */
  .t-notification-stack { margin-top: 0; gap: calc(var(--ui-content-scale) * 6px); }
  .t-notification { padding: calc(var(--ui-content-scale) * 12px) calc(var(--ui-content-scale) * 14px); border-radius: calc(var(--ui-content-scale) * 12px); }
  .t-notification__label { font-size: var(--t-fs-base); }
  .t-notification__op { font-size: var(--t-fs-small); }
  .t-notification__close { width: calc(var(--ui-content-scale) * 26px); height: calc(var(--ui-content-scale) * 26px); }

  /* SC queue card on mobile */
  .t-sc-queue__card { padding: calc(var(--ui-content-scale) * 14px); }
  .t-sc-queue__title { font-size: var(--t-fs-base); }
  .t-sc-queue__btn { min-height: calc(var(--ui-content-scale) * 40px); font-size: var(--t-fs-base); padding: 0 calc(var(--ui-content-scale) * 16px); }
}

/* Very-narrow phones (≤400px) — even tighter compaction so iPhone
   SE (375×667) and similar don't feel cramped. Overlay positions
   still follow --sheet-h; only the chrome compaction changes. */
@media (max-width: 400px) {
  .t-nav-card { min-height: clamp(calc(var(--ui-content-scale) * 108px), 28vh, calc(var(--ui-content-scale) * 132px)); height: auto; }
}

/* ═══ Active-trip BottomView — pinned to the bottom of the nav column ═══
   Mirrors Tesla firmware: BottomView is the last child of the 430-wide
   UnifiedTurnListWidth column, naturally anchoring to the bottom-left
   of the screen. `margin-top:auto` pushes it past any FirstTurn / turn
   list content; the column itself is already flex-direction:column. */
.t-shell__left > .t-bottom-view {
  margin-top: auto;
  /* width is the responsive clamp on .t-bottom-view itself — do NOT
   * override to 100% here.  `.t-shell__left` is a position:fixed
   * full-viewport container (left:0;right:0), so 100% would stretch
   * the BottomView edge-to-edge and break alignment with the turn
   * panel above (which uses the same clamp). */
}

/* ═══ Trim SearchPill margin — double-spacing with parent gap ════════ */
.t-search-pill { margin-bottom: 0; }

/* ═══ Helper classes promoted from inline styles ═════════════════════ */
.t-arrival {
  background: var(--t-c-bg-nav-primary);
  border-radius: calc(var(--ui-content-scale) * 10px);
  padding: clamp(calc(var(--ui-content-scale) * 20px), calc(2vw + calc(var(--ui-content-scale) * 16px)), calc(var(--ui-content-scale) * 36px));
  text-align: center;
}
.t-arrival__flag {
  font-size: var(--t-fs-display);
  margin-bottom: var(--t-s-lg);
}
.t-arrival__title {
  font-size: var(--t-fs-2xlarge);
  font-weight: var(--t-weight-medium);
  margin-bottom: var(--t-s-sm);
  color: var(--t-c-text-primary);
}
.t-arrival__sub {
  font-size: var(--t-fs-large);
  color: var(--t-c-text-secondary);
  margin-bottom: var(--t-s-xl);
}

.t-info-window__home-row-add {
  font-size: var(--t-fs-large);
  color: var(--t-c-text-secondary);
}

.t-places__empty {
  padding: var(--t-s-xl);
  color: var(--t-c-text-secondary);
  font-size: var(--t-fs-medium);
}

/* ═══ Masked-icon helper ═════════════════════════════════════════════
   `<MaskedIcon src="...">` renders a span whose mask-image is the PNG
   and whose paint is `currentColor`. The icon's intrinsic colour stops
   mattering — only its alpha channel does — so a single asset renders
   correctly in night, day, and darkDay. `color` cascades from the
   parent's theme-aware text colour. */
.t-mask-icon {
  display: inline-block;
  width: var(--t-icon-md);
  height: var(--t-icon-md);
  background-color: currentColor;
  -webkit-mask-size: contain;
          mask-size: contain;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  -webkit-mask-position: center;
          mask-position: center;
  flex-shrink: 0;
  pointer-events: none;
}
.t-mask-icon--sm { width: var(--t-icon-sm); height: var(--t-icon-sm); }
.t-mask-icon--lg { width: var(--t-icon-lg); height: var(--t-icon-lg); }

/* Make sure chrome surfaces propagate a theme-aware ink colour so the
   .t-mask-icon glyphs inherit `currentColor` correctly. */
.t-shell__left,
.t-info-window,
.t-settings,
.MoreInfo,
.TripPlanCard,
.t-nav-card,
.t-bottom-view,
.t-amenity-row,
.t-info-window__amenities,
.t-info-window__home-row,
.t-place-row,
.t-suggestion-item,
.t-trip-stop,
.t-charger-list,
.t-don-popup,
.t-energy-view,
.t-weather-popup {
  color: var(--t-c-text-primary);
}

/* Override mask-icon size in specific contexts where we want smaller
   or larger glyphs. */
.t-bottom-view__grab-pill {
  width: clamp(calc(var(--ui-content-scale) * 36px), calc(2vw + calc(var(--ui-content-scale) * 32px)), calc(var(--ui-content-scale) * 56px));
  height: calc(var(--ui-content-scale) * 5px);
  background-color: var(--t-c-overlay-5);
  /* the grab pill is a flat bar — don't mask, just paint a flat
     coloured rectangle. */
  -webkit-mask-image: none !important;
          mask-image: none !important;
}
.t-info-window__type-icon { opacity: 0.6; }
.t-amenity-btn .t-mask-icon { width: var(--t-icon-md); height: var(--t-icon-md); }
.MoreInfoRow__chevron.t-mask-icon { opacity: 0.6; }

/* ListWayPointView — turn_list.uiml:71–96
 * styles-common.conf:558–566. Selector names == UIML name= attrs. */
.ListWayPointView {
  display: flex;
  flex-direction: column;
  padding: calc(var(--ui-content-scale) * 20px) calc(var(--ui-content-scale) * 30px) calc(var(--ui-content-scale) * 20px) calc(var(--ui-content-scale) * 20px);     /* ListWayPointView/Container */
}
.ListWayPointView .HorizontalContainer {
  display: flex;
  align-items: center;              /* AlignItems:center; Flex:1; */
  flex: 1;
}
.ListWayPointView .TurnImageContainer {
  width: clamp(calc(var(--ui-content-scale) * 40px), 5vw, calc(var(--ui-content-scale) * 70px));
  display: flex; flex-direction: column;
  align-items: center; justify-content: flex-start;
  align-self: stretch;
  position: relative;
}
/* WayPointDots — firmware NavTurnList::WayPointDots draws a dotted
 * vertical line from this icon down to the next waypoint icon. We
 * mirror it with a column of dot characters sized to fill the slack
 * between this row's icon and the next row's icon. */
.ListWayPointView .WayPointDots {
  flex: 1;
  width: calc(var(--ui-content-scale) * 3px);
  margin-top: calc(var(--ui-content-scale) * 4px);
  background-image: radial-gradient(circle, var(--t-c-text-tertiary, rgba(255,255,255,0.4)) calc(var(--ui-content-scale) * 1.2px), transparent calc(var(--ui-content-scale) * 1.5px));
  background-size: calc(var(--ui-content-scale) * 3px) calc(var(--ui-content-scale) * 8px);
  background-repeat: repeat-y;
  background-position: center top;
  min-height: calc(var(--ui-content-scale) * 16px);
}
.ListWayPointView .ImageView {
  width: clamp(calc(var(--ui-content-scale) * 36px), 4.5vw, calc(var(--ui-content-scale) * 56px));
  height: clamp(calc(var(--ui-content-scale) * 36px), 4.5vw, calc(var(--ui-content-scale) * 56px));
  object-fit: contain;
  flex-shrink: 0;
}
.ListWayPointView .ArrivalContainer {
  flex: 1;
  display: flex; flex-direction: column;
  margin-left: calc(var(--ui-content-scale) * 20px);                /* Margin:20,0,0,0 */
}
.ListWayPointView .LabelsContainer {
  flex: 1;
  display: flex; flex-direction: column;
}
.ListWayPointView .ArrivalInfoContainer {
  display: flex; align-items: center;
}
.ListWayPointView .ArrivalTimeLabel {
  font-size: calc(var(--ui-font-scale) * 18px);                  /* Text/Caption1 */
  color: var(--t-c-text-secondary);
  margin: 0 calc(var(--ui-content-scale) * 20px) 0 0;               /* Margin:0,0,20,0 */
  min-height: calc(var(--ui-content-scale) * 24px);
  line-height: 1.3;
}
.ListWayPointView .TitleContainer {
  display: flex; flex-direction: column;
  flex: 1;
}
.ListWayPointView .TitleLabel {
  font-size: calc(var(--ui-font-scale) * 24px);                  /* Text/Body1 */
  color: var(--t-c-text-primary);
  max-height: calc(var(--ui-content-scale) * 60px);                 /* MaxHeight:60 */
  overflow: hidden;
  text-overflow: ellipsis;
  word-wrap: break-word;
}
.ListWayPointView .SuperchargerLabel,
.ListWayPointView .SubtitleLabel {
  font-size: calc(var(--ui-font-scale) * 18px);                  /* Text/Caption1 secondary */
  color: var(--t-c-text-secondary);
  line-height: 1.3;
}
.ListWayPointView .BatteryContainer {
  display: flex; align-items: center;
  margin: 0 0 0 0;
  margin-top: calc(var(--ui-content-scale) * 5px);                  /* Margin:0,5,0,0 */
  gap: calc(var(--ui-content-scale) * 6px);
}
.ListWayPointView .BatteryDisplay {
  display: flex; align-items: center;
  gap: calc(var(--ui-content-scale) * 5px);                         /* PercentLabel Margin:5,0,0,0 */
}
/* BatteryIcon — Tesla's C++ widget renders a horizontal pill with
 * fractional fill. CSS equivalent: a 36×18 outlined rect with an
 * inner fill bar sized by arrival_pct. Colour follows the same
 * green/yellow/red thresholds the BottomView Battery component uses. */
.t-lw-batt {
  width: calc(var(--ui-content-scale) * 36px); height: calc(var(--ui-content-scale) * 18px);
  border: calc(var(--ui-content-scale) * 2px) solid var(--t-c-text-secondary);
  border-radius: calc(var(--ui-content-scale) * 3px);
  padding: calc(var(--ui-content-scale) * 2px);
  position: relative;
  flex-shrink: 0;
}
.t-lw-batt::after {
  content: "";
  position: absolute;
  right: calc(var(--ui-content-scale) * -4px); top: calc(var(--ui-content-scale) * 4px);
  width: calc(var(--ui-content-scale) * 2px); height: calc(var(--ui-content-scale) * 6px);
  background: var(--t-c-text-secondary);
  border-radius: 0 calc(var(--ui-content-scale) * 1px) calc(var(--ui-content-scale) * 1px) 0;
}
.t-lw-batt__fill {
  height: 100%;
  background: var(--t-c-green);
  border-radius: calc(var(--ui-content-scale) * 1px);
  transition: width var(--t-trans-normal);
}
.t-lw-batt__fill--low      { background: var(--t-c-yellow); }
.t-lw-batt__fill--critical { background: var(--t-c-red); }
.t-lw-batt__pct,
.ListWayPointView .PercentLabel {
  font-size: calc(var(--ui-font-scale) * 18px);              /* Caption1 — PercentLabel style */
  color: var(--t-c-text-secondary);
  font-variant-numeric: tabular-nums;
}
/* Arrow between arrival and departure SOC. Tesla's UIML doesn't
 * include this glyph (it's drawn programmatically when departure
 * differs from arrival, i.e. the stop is charging-then-leaving).
 * Caption1 = 18px to match the percent labels. */
.t-lw-batt__arrow {
  font-size: calc(var(--ui-font-scale) * 18px);
  color: var(--t-c-text-tertiary);
  margin: 0 calc(var(--ui-content-scale) * 2px);
}
/* ChargeTimeContainer — turn_list.uiml:88 + styles-common.conf:563–564.
 * Margin:5,0,0,0; AlignItems:center.  Inner ChargingText uses
 * Text/Caption1; Color:Text/secondary; Margin:5,0,0,0. */
.ListWayPointView .ChargeTimeContainer {
  display: flex; align-items: center;
  margin: 0 0 0 calc(var(--ui-content-scale) * 5px);
}
.ListWayPointView .ChargingText {
  font-size: calc(var(--ui-font-scale) * 18px);
  color: var(--t-c-text-secondary);
  margin-left: calc(var(--ui-content-scale) * 5px);
  font-variant-numeric: tabular-nums;
}
/* RightSideArrivalContainer — turn_list.uiml:92, MinWidth:30,
 * AlignItems:flexend; JustifyContent:center. */
.ListWayPointView .RightSideArrivalContainer {
  min-width: calc(var(--ui-content-scale) * 30px);
  display: flex; align-items: center; justify-content: flex-end;
}
.ListWayPointView .Chevron {
  width: calc(var(--ui-content-scale) * 14px); height: calc(var(--ui-content-scale) * 24px);
  opacity: 0.6;
  object-fit: contain;
}

/* "+" button on UpcomingRestArea cards. Tappable adds the rest area as
   a waypoint and fires /api/route. */
.t-rest-area__add            { margin-left: auto; min-width: calc(var(--ui-content-scale) * 34px); min-height: calc(var(--ui-content-scale) * 34px); border-radius: 50%;
                               background: var(--t-c-overlay-5);
                               color: inherit; font-size: calc(var(--ui-font-scale) * 20px); line-height: 1; border: none; cursor: pointer; }
.t-rest-area__add:hover      { background: var(--t-c-overlay-7); }
.t-rest-area__add:disabled   { opacity: 0.5; cursor: default; }
.t-rest-area__sub            { font-size: var(--t-fs-mini); opacity: 0.55; }

/* Skip-charger button in TripStopView — visually distinct from the
   neutral "Done" action because it's destructive. */
.t-don-popup__btn--danger    { background: var(--t-c-error-bg); color: var(--t-c-error-fg); }
.t-don-popup__btn--danger:hover { background: var(--t-c-error-bg); }

/* Edit Trip: locked × placeholder on origin/destination rows so the row
   doesn't collapse where a delete button would otherwise sit. */
.t-edit-trip__delete--locked { width: calc(var(--ui-content-scale) * 28px); height: calc(var(--ui-content-scale) * 28px); opacity: 0; pointer-events: none; }

/* Trip extras — Phase 3 tasks #10–#12. Renders destination SOE bounds,
   planner-reason chips, and the low-SOE penalty inline in TripSummary
   whenever the route response actually carries that data. Hidden when
   all three fields are empty so simple trips stay clean. */
.t-trip-extras            { display: flex; flex-direction: column; gap: calc(var(--ui-content-scale) * 6px);
                            margin: calc(var(--ui-content-scale) * 10px) 0 calc(var(--ui-content-scale) * 6px);
                            padding: calc(var(--ui-content-scale) * 10px) calc(var(--ui-content-scale) * 12px);
                            border-radius: calc(var(--ui-content-scale) * 12px);
                            background: var(--t-c-overlay-2);
                            font-size: var(--t-fs-mini); }
.t-trip-extras__row       { display: flex; flex-wrap: wrap; align-items: baseline; gap: calc(var(--ui-content-scale) * 8px); }
.t-trip-extras__label     { opacity: 0.6; }
.t-trip-extras__value     { font-weight: 600; }
.t-trip-extras__hint      { opacity: 0.55; font-size: var(--t-fs-mini); }
.t-trip-extras__chip      { padding: calc(var(--ui-content-scale) * 3px) calc(var(--ui-content-scale) * 8px); border-radius: calc(var(--ui-content-scale) * 999px);
                            background: var(--t-c-caution-bg); color: var(--t-c-caution-fg);
                            font-size: var(--t-fs-mini); }
.t-trip-extras__row--reasons { gap: calc(var(--ui-content-scale) * 6px); }
.t-trip-extras__row--penalty .t-trip-extras__value { color: var(--t-c-caution-fg); }

/* Elevation chart — Phase 3 task #13. Inline SVG height-vs-distance
   curve with min/max labels and a soft area-fill under the line. The
   chart sits in the TripSummary card whenever elevation_profile has at
   least two samples. */
.t-elevation              { display: flex; flex-direction: column; gap: calc(var(--ui-content-scale) * 4px);
                            margin: calc(var(--ui-content-scale) * 10px) 0 calc(var(--ui-content-scale) * 6px); padding: calc(var(--ui-content-scale) * 8px) calc(var(--ui-content-scale) * 12px);
                            border-radius: calc(var(--ui-content-scale) * 12px);
                            background: var(--t-c-overlay-2); }
.t-elevation__header      { display: flex; justify-content: space-between;
                            font-size: var(--t-fs-mini); opacity: 0.6; }
.t-elevation__title       { text-transform: uppercase; letter-spacing: 0.04em; }
.t-elevation__svg         { width: 100%; height: calc(var(--ui-content-scale) * 56px);
                            stroke: var(--t-c-blue-bright); fill: none; }
.t-elevation__line        { stroke-width: 1.5; vector-effect: non-scaling-stroke; }
.t-elevation__area        { fill: rgba(62,106,225,0.18); stroke: none; }
.t-elevation__legend      { display: flex; justify-content: space-between;
                            font-size: var(--t-fs-mini); opacity: 0.55; }

/* ── InfoWindow rating + open/closed badge row ─────────────────────── */
.t-info-window__detail-row {
    display: flex; align-items: center; gap: calc(var(--ui-content-scale) * 12px);
    margin: calc(var(--ui-content-scale) * 4px) 0 calc(var(--ui-content-scale) * 12px) 0;
    flex-wrap: wrap;
}
.t-info-window__rating-num {
    font-size: var(--t-fs-small);
    color: var(--t-c-text-primary);
    opacity: 0.85;
    font-weight: 500;
}
.t-info-window__open-badge {
    font-size: var(--t-fs-mini);
    padding: calc(var(--ui-content-scale) * 3px) calc(var(--ui-content-scale) * 10px); border-radius: calc(var(--ui-content-scale) * 999px);
    text-transform: uppercase; letter-spacing: 0.04em; font-weight: 600;
}
.t-info-window__open-badge--open   { background: var(--t-c-success-bg); color: var(--t-c-success-fg); }
.t-info-window__open-badge--closed { background: var(--t-c-error-bg); color: var(--t-c-error-fg); }

/* Disabled / active states for InfoWindow action buttons. */
.t-action-btn[disabled] {
    opacity: 0.35; cursor: not-allowed;
    pointer-events: none;
}
.t-action-btn--active {
    background: var(--t-c-blue-bright); color: #fff;
}

/* ── Autocomplete predictions dropdown ─────────────────────────────── */
.t-places__autocomplete {
    display: flex; flex-direction: column;
    margin-bottom: calc(var(--ui-content-scale) * 8px);
    border-radius: calc(var(--ui-content-scale) * 12px); overflow: hidden;
    background: var(--t-c-overlay-2);
}
.t-places__autocomplete-row {
    padding: calc(var(--ui-content-scale) * 12px) calc(var(--ui-content-scale) * 16px);
    border-bottom: calc(var(--ui-content-scale) * 1px) solid var(--t-c-bg-divider);
    cursor: pointer;
}
.t-places__autocomplete-row:last-child { border-bottom: none; }
.t-places__autocomplete-row:hover  { background: var(--t-c-overlay-4, rgba(255,255,255,0.04)); }
.t-places__autocomplete-row:active { background: var(--t-c-overlay-8, rgba(255,255,255,0.08)); }
.t-places__autocomplete-main {
    font-size: var(--t-fs-base); color: var(--t-c-text-primary);
    font-weight: 500;
}
.t-places__autocomplete-sub  {
    font-size: var(--t-fs-mini); color: var(--t-c-text-secondary);
    margin-top: calc(var(--ui-content-scale) * 2px);
}

/* ── Charger cluster marker — count badge inside the firmware sprite ─ */
/* The DOM element itself is built by index.html's _makeClusterEl; this
   rule styles only the inner count span so the digit renders centred
   over the sprite without affecting the sprite background-image. */
.t-charger-cluster__count {
    pointer-events: none;
    user-select: none;
    line-height: 1;
}

/* ── Notification colour classes for the kinds added since the original
       palette. Each picks a unique tint so the stack is scannable. ────── */
.t-notification--map-update          { border-left: calc(var(--ui-content-scale) * 4px) solid var(--t-c-blue-bright); }
.t-notification--max-speed           { border-left: calc(var(--ui-content-scale) * 4px) solid var(--t-c-yellow); }
.t-notification--lane-change         { border-left: calc(var(--ui-content-scale) * 4px) solid var(--t-c-success-fg); }
.t-notification--charger-arrival     { border-left: calc(var(--ui-content-scale) * 4px) solid var(--t-c-success-fg); }
.t-notification--destination-closing { border-left: calc(var(--ui-content-scale) * 4px) solid var(--t-c-yellow); }
.t-notification--valet-only          { border-left: calc(var(--ui-content-scale) * 4px) solid var(--t-c-yellow); }
.t-notification--no-restroom         { border-left: calc(var(--ui-content-scale) * 4px) solid var(--t-c-yellow); }

/* Phase 3 — route-fetch inline state + lost-GPS banner. The
   InfoWindow shows a loading line when the initial /api/route
   call is in flight, and an error line when it fails inline
   (replaces an easy-to-miss toast). The lost-GPS banner sits
   above FirstTurn while the GPS feed is older than
   GPS_LOST_THRESHOLD_MS. */
.t-info-window__route-loading {
  color: var(--t-c-text-secondary);
  font-size: var(--t-fs-small);
  padding: var(--t-s-sm) 0;
}
.t-info-window__route-error {
  color: var(--t-c-error-fg);
  font-size: var(--t-fs-small);
  padding: var(--t-s-sm) 0;
}
.t-action-btn.is-loading { opacity: 0.5; }
.t-lost-gps-banner {
  display: flex;
  flex-direction: column;
  gap: calc(var(--ui-content-scale) * 2px);
  padding: var(--t-s-md, calc(var(--ui-content-scale) * 10px)) var(--t-s-lg, calc(var(--ui-content-scale) * 14px));
  margin: var(--t-s-sm, calc(var(--ui-content-scale) * 6px)) var(--t-s-md, calc(var(--ui-content-scale) * 10px));
  border-radius: var(--t-r-card);
  background: var(--t-c-error-bg);
  border-left: calc(var(--ui-content-scale) * 4px) solid var(--t-c-error-fg);
}
.t-lost-gps-banner__title {
  color: var(--t-c-error-fg);
  font-weight: 600;
  font-size: var(--t-fs-medium);
}
.t-lost-gps-banner__sub {
  color: var(--t-c-text-secondary);
  font-size: var(--t-fs-small);
}

/* Phase 5 — maneuver enrichment styles. Roundabout-exit badge sits
   on the FirstTurn arrow; next-next row reads "Then <icon> <street>
   in <distance>"; NormalTurn shield row stacks cardinal/shield/exit
   chips under the street name. */
.t-first-turn__image-wrap { position: relative; display: inline-block; }
.t-first-turn__exit-badge {
  position: absolute;
  top: calc(var(--ui-content-scale) * 4px); right: calc(var(--ui-content-scale) * 4px);
  min-width: calc(var(--ui-content-scale) * 22px); min-height: calc(var(--ui-content-scale) * 22px);
  padding: 0 calc(var(--ui-content-scale) * 6px);
  border-radius: calc(var(--ui-content-scale) * 11px);
  background: var(--t-c-blue-bright, var(--t-c-blue-bright));
  color: #fff;
  font-weight: 700;
  font-size: calc(var(--ui-font-scale) * 14px);
  display: flex; align-items: center; justify-content: center;
}
.t-first-turn__next-next {
  display: flex; align-items: center;
  gap: var(--t-s-sm, calc(var(--ui-content-scale) * 6px));
  padding: var(--t-s-sm, calc(var(--ui-content-scale) * 6px)) var(--t-s-md, calc(var(--ui-content-scale) * 10px));
  color: var(--t-c-text-secondary);
  font-size: var(--t-fs-small);
}
.t-first-turn__next-next-prefix { opacity: 0.7; }
.t-first-turn__next-next-icon { display: inline-flex; }
.t-first-turn__next-next-label { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.t-first-turn__next-next-dist { opacity: 0.8; }

.t-normal-turn__body { display: flex; flex-direction: column; gap: calc(var(--ui-content-scale) * 2px); flex: 1; min-width: 0; }
.t-normal-turn__shield-row {
  display: flex; align-items: center;
  gap: var(--t-s-sm, calc(var(--ui-content-scale) * 6px));
  font-size: var(--t-fs-mini);
  color: var(--t-c-text-secondary);
}
.t-normal-turn__cardinal,
.t-normal-turn__shield,
.t-normal-turn__exit {
  padding: calc(var(--ui-content-scale) * 1px) calc(var(--ui-content-scale) * 6px);
  border-radius: calc(var(--ui-content-scale) * 4px);
  background: var(--t-c-overlay-3, rgba(255,255,255,0.06));
}

/* Phase 7 — arrival summary, charger branch, and lost-GPS banner
   styling. The arrival view now renders a hero (flag + destination
   name) plus a metrics grid (trip duration, distance, arrival time,
   battery) plus an optional charger row and walking-distance hint. */
.t-arrival__hero { display: flex; flex-direction: column; align-items: center; gap: var(--t-s-sm); }
.t-arrival__dest {
  font-size: var(--t-fs-large);
  color: var(--t-c-text-secondary);
  margin-bottom: var(--t-s-lg);
}
.t-arrival__metrics {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--t-s-md);
  margin: var(--t-s-lg) 0;
  text-align: left;
}
.t-arrival__metric {
  display: flex; flex-direction: column; gap: calc(var(--ui-content-scale) * 2px);
  padding: var(--t-s-md);
  background: var(--t-c-overlay-3, rgba(255,255,255,0.04));
  border-radius: calc(var(--ui-content-scale) * 8px);
}
.t-arrival__metric-label {
  font-size: var(--t-fs-mini);
  color: var(--t-c-text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.t-arrival__metric-value {
  font-size: var(--t-fs-large);
  font-weight: 600;
  color: var(--t-c-text-primary);
}
.t-arrival__charger {
  display: flex; align-items: center; justify-content: center;
  gap: var(--t-s-sm);
  margin: var(--t-s-md) 0;
  color: var(--t-c-text-primary);
  font-weight: 500;
}
/* Native-color SC glyph — sized to match the surrounding text row, with
   the firmware Tesla red preserved. */
.t-arrival__charger-icon {
  width: calc(var(--ui-content-scale) * 28px);
  height: calc(var(--ui-content-scale) * 28px);
  object-fit: contain;
  display: block;
}
.t-arrival__walk {
  margin: var(--t-s-md) 0;
  color: var(--t-c-text-secondary);
  font-style: italic;
}

/* Mask-icon size step used by the arrival hero. */
.t-mask-icon--xl {
  width: calc(var(--ui-content-scale) * 80px); height: calc(var(--ui-content-scale) * 80px);
}

/* ─── Vehicle profile UI (2026-05-21) ─────────────────────────────
   - Onboarding modal — first-run kWh+SOC + optional preset picker
   - Vehicle picker — search modal with grouped preset list
   - Settings → Vehicle — long-form profile editor */
.t-onboarding__backdrop,
.t-vehicle-picker__backdrop {
  position: fixed; inset: 0;
  background: rgba(0,0,0,0.78);
  display: flex; align-items: center; justify-content: center;
  z-index: 100;
}
.t-onboarding,
.t-vehicle-picker {
  background: var(--t-c-bg-nav-primary, var(--t-c-bg-primary));
  border-radius: calc(var(--ui-content-scale) * 12px);
  padding: var(--t-s-xl, calc(var(--ui-content-scale) * 20px));
  width: min(calc(var(--ui-content-scale) * 440px), 92vw);
  max-height: 88vh;
  display: flex; flex-direction: column;
  color: var(--t-c-text-primary, #fff);
  box-shadow: 0 calc(var(--ui-content-scale) * 24px) calc(var(--ui-content-scale) * 60px) rgba(0,0,0,0.5);
}
.t-onboarding__title,
.t-vehicle-picker__title,
.t-vehicle-settings__title {
  font-size: var(--t-fs-2xlarge, calc(var(--ui-font-scale) * 22px));
  font-weight: 600;
  margin-bottom: var(--t-s-sm, calc(var(--ui-content-scale) * 6px));
}
.t-onboarding__sub {
  color: var(--t-c-text-secondary, var(--t-c-text-secondary));
  margin-bottom: var(--t-s-lg, calc(var(--ui-content-scale) * 16px));
}
.t-onboarding__field,
.t-vehicle-settings__field {
  display: flex; flex-direction: column;
  gap: calc(var(--ui-content-scale) * 4px);
  margin: var(--t-s-md, calc(var(--ui-content-scale) * 10px)) 0;
}
.t-onboarding__label,
.t-vehicle-settings__label {
  font-size: var(--t-fs-small);
  color: var(--t-c-text-secondary, var(--t-c-text-secondary));
}
.t-vehicle-settings__val {
  color: var(--t-c-text-primary, #fff);
  font-weight: 500;
}
.t-onboarding__input {
  background: var(--t-c-overlay-3);
  border: calc(var(--ui-content-scale) * 1px) solid rgba(255,255,255,0.12);
  border-radius: calc(var(--ui-content-scale) * 6px);
  padding: calc(var(--ui-content-scale) * 10px);
  color: inherit;
  font-size: var(--t-fs-large, calc(var(--ui-font-scale) * 16px));
  width: 100%;
}
.t-onboarding__slider,
.t-vehicle-settings__slider {
  width: 100%;
}
.t-onboarding__actions {
  display: flex; gap: var(--t-s-sm, calc(var(--ui-content-scale) * 6px));
  margin-top: var(--t-s-lg, calc(var(--ui-content-scale) * 16px));
}
.t-onboarding__btn,
.t-vehicle-settings__change,
.t-vehicle-settings__advanced-toggle {
  flex: 1; padding: calc(var(--ui-content-scale) * 12px) calc(var(--ui-content-scale) * 16px);
  border-radius: calc(var(--ui-content-scale) * 8px);
  background: var(--t-c-overlay-4);
  color: inherit;
  font-weight: 500;
  border: 0;
  cursor: pointer;
}
.t-onboarding__btn--primary {
  background: var(--t-c-blue-bright, var(--t-c-blue-bright));
  color: #fff;
}
.t-onboarding__hint {
  color: var(--t-c-text-secondary, var(--t-c-text-secondary));
  font-size: var(--t-fs-mini);
  margin-top: var(--t-s-md, calc(var(--ui-content-scale) * 10px));
  line-height: 1.4;
}
.t-vehicle-picker__header {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: var(--t-s-sm, calc(var(--ui-content-scale) * 6px));
}
.t-vehicle-picker__close {
  background: transparent; border: 0; color: inherit;
  font-size: calc(var(--ui-font-scale) * 28px); line-height: 1; padding: calc(var(--ui-content-scale) * 4px) calc(var(--ui-content-scale) * 8px); cursor: pointer;
}
.t-vehicle-picker__search {
  width: 100%; padding: calc(var(--ui-content-scale) * 10px);
  background: var(--t-c-overlay-3);
  border: calc(var(--ui-content-scale) * 1px) solid rgba(255,255,255,0.12);
  border-radius: calc(var(--ui-content-scale) * 6px);
  color: inherit; font-size: var(--t-fs-base, calc(var(--ui-font-scale) * 14px));
  margin-bottom: var(--t-s-sm, calc(var(--ui-content-scale) * 6px));
}
.t-vehicle-picker__scroll {
  flex: 1; overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}
.t-vehicle-picker__region-label {
  font-size: var(--t-fs-mini);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--t-c-text-secondary, var(--t-c-text-secondary));
  margin: var(--t-s-md, calc(var(--ui-content-scale) * 10px)) 0 var(--t-s-xs, calc(var(--ui-content-scale) * 4px));
}
.t-vehicle-picker__row {
  display: flex; flex-direction: column;
  align-items: flex-start;
  width: 100%; padding: calc(var(--ui-content-scale) * 10px) calc(var(--ui-content-scale) * 12px);
  background: transparent; border: 0; border-radius: calc(var(--ui-content-scale) * 8px);
  color: inherit;
  text-align: left;
  cursor: pointer;
}
.t-vehicle-picker__row:hover,
.t-vehicle-picker__row:active {
  background: var(--t-c-overlay-3);
}
.t-vehicle-picker__row-name { font-weight: 500; }
.t-vehicle-picker__row-sub {
  font-size: var(--t-fs-mini);
  color: var(--t-c-text-secondary, var(--t-c-text-secondary));
}
.t-vehicle-picker__empty {
  padding: var(--t-s-lg, calc(var(--ui-content-scale) * 16px));
  color: var(--t-c-text-secondary, var(--t-c-text-secondary));
  text-align: center;
}
.t-vehicle-picker__footer {
  margin-top: var(--t-s-sm, calc(var(--ui-content-scale) * 6px));
  font-size: var(--t-fs-mini);
  color: var(--t-c-text-secondary, var(--t-c-text-secondary));
  text-align: center;
}
.t-vehicle-settings {
  margin: var(--t-s-md, calc(var(--ui-content-scale) * 10px)) 0;
}
.t-vehicle-settings__active {
  display: flex; align-items: center; justify-content: space-between;
  margin: var(--t-s-sm, calc(var(--ui-content-scale) * 6px)) 0 var(--t-s-md, calc(var(--ui-content-scale) * 10px));
}
.t-vehicle-settings__active-name {
  font-weight: 500;
}
.t-vehicle-settings__advanced {
  padding: var(--t-s-md, calc(var(--ui-content-scale) * 10px)) 0;
  border-top: calc(var(--ui-content-scale) * 1px) solid rgba(255,255,255,0.08);
  margin-top: var(--t-s-md, calc(var(--ui-content-scale) * 10px));
}

/* ============================================================================
 * Trip-plan v4 surfaces — UIML-grounded styling
 *
 * Source of truth: tesla_nav_server/firmware_extract/analysis/*.md.  Every
 * font size, padding, colour and width is justified inline with a file:line
 * cite into the analysis docs (those are the resolved style tables, not
 * speculation).
 *
 * Tesla margin/padding ordering convention: L,T,R,B (Qt) → translated here
 * into CSS top right bottom left.  Multi-value colour tokens follow Tesla's
 * `night day [darkday]` order.
 * ========================================================================== */


/* ── TripPlanSummaryView (turn_list.md:110-126) ────────────────────────
 * vlayout: AlternativeTripPlan/TripPlanSummaryContainer
 *   ├── TopRowLabels (hlayout, AlignItems:center, Direction:languageaware)
 *   │     └── TripDuration  style: SummaryLabelSelected  (larger, primary)
 *   ├── BottomRowLabels (hlayout, AlignItems:center)
 *   │     ├── NumStops      style: SummaryLabel
 *   │     ├── TripDistance  style: SummaryLabel
 *   │     └── FinalArrivalTime (TimeLabel, SummaryLabel)
 *   └── TripPlanSummaryDescription (visible when not_empty)
 * Resolved fonts (turn_list.md:436-451): Body1 = 24, Body2 = 22, Caption1 = 18.
 * SummaryLabelSelected = the "selected" emphasis variant; baseline Tesla pattern
 * is a heavier weight + higher contrast text vs SummaryLabel which sits at
 * Text/secondary.
 * Background: Background/nav_primary (var(--t-c-bg-primary) night) — already on parent.
 */
/* Trip-summary rules live in their canonical location at line ~1550 of
 * this file (styles-common.conf-resolved values: Padding:30,0,30,0,
 * Margin:0,20,0,20, Body1=24 primary/secondary, Caption1=18 description).
 * The duplicate-and-invented appendix block that used to live here
 * (arrival-soc pill, italic description, yellow warning chip,
 * --t-fs-xlarge mono duration) has been removed; none of those affordances
 * exist in AlternativeTripPlan/* per the resolved style chains. */


/* ── TripPlanOptionsView (turn_list.md:95-108) ─────────────────────────
 * Horizontal scrollable row of TripPlanOption tabs ("Fastest" /
 * "Shortest" / "Avoid Tolls" in firmware; FASTEST / BEST_AMENITIES /
 * FEWER_STOPS here).  OptionContainer is vlayout with a single OptionLabel.
 * Selected tab carries the accent underline.  Spinner at right edge.
 */
.t-profile-picker {
  display: flex;
  gap: var(--t-s-sm);
  padding: var(--t-s-md) 0 var(--t-s-sm);
  margin: 0 0 var(--t-s-md);
  border-bottom: calc(var(--ui-content-scale) * 1px) solid var(--t-c-bg-divider);
  overflow-x: auto;
  scrollbar-width: none;
}
.t-profile-picker::-webkit-scrollbar { display: none; }
.t-profile-picker__tab {
  flex: 1 1 0;
  min-width: calc(var(--ui-content-scale) * 96px);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: calc(var(--ui-content-scale) * 2px);
  padding: var(--t-s-sm) var(--t-s-md);
  background: transparent;
  color: var(--t-c-text-secondary);
  border: calc(var(--ui-content-scale) * 1px) solid transparent;
  border-radius: var(--t-r-card);
  cursor: pointer;
  transition: var(--t-trans-quick);
  text-align: left;
  font-family: var(--t-font);
}
.t-profile-picker__tab:hover {
  background: var(--t-c-overlay-3);
  color: var(--t-c-text-primary);
}
.t-profile-picker__tab.is-active {
  /* Tesla "selected option" pattern — accent bottom border + brighter text. */
  background: var(--t-c-overlay-4);
  color: var(--t-c-text-primary);
  border-color: var(--t-c-overlay-border);
  box-shadow: inset 0 calc(var(--ui-content-scale) * -2px) 0 var(--t-c-blue-bright);
}
.t-profile-picker__name {
  font-size: var(--t-fs-medium);
  font-weight: var(--t-weight-medium);
}
.t-profile-picker__totals {
  font-size: var(--t-fs-small);
  opacity: 0.75;
  font-variant-numeric: tabular-nums;
}


/* ListWayPointView (turn_list.uiml:74-99) — rules live in the canonical
 * block above (around line 3557). The invented SC badge / low-SOE red /
 * operator-nameplate meta-row chrome that used to live here has been
 * removed; SuperchargerLabel in firmware is just another Caption1
 * subtitle line, not a coloured chip, and low-SOE is communicated via
 * the proper TripPlannerBanner channel rather than tinting the row. */


/* ── SplitTurnListBottomView extensions (turn_list.md:271-308) ─────────
 * Bottom view itself is already styled (.t-bottom-view block above).
 * The arrival-SOC chip is the only addition — projected destination SOC
 * shown next to the live battery readout (Spec P3.6).  Tesla style is a
 * thin caption beside the BatteryDisplay, languageaware spacing.
 */
/* Projected arrival-SOC chip removed — Tesla's
 * SplitNavTurnListDestinationInfo only shows the LIVE battery via
 * BatteryDisplay (icon + PercentLabel). The projected arrival number
 * lives in TripPlanSummaryView and at the start-of-trip POI card,
 * not as a chrome on the active driving dock. */


/* edit_trip.uiml uses the SAME pin_icon.png for every DestinationItem
 * row regardless of stop type. Earlier invented variants
 * (--origin / --auto / --user) removed; the renderer now points an
 * <img> at icons::TL_PIN_ICON and sized via the .t-edit-trip__pin
 * rule above. */


/* ── RouteLineLabelView (navigation.md:266-289) ────────────────────────
 * The current Rust component already emits a stable class list per row.
 * Geometry from the analysis doc:
 *   - Container padding asymmetric 20/7/20/26 (top:7 right:20 bottom:26 left:20)
 *     when above the line; mirrored to 20/26/20/7 below.  We can't easily
 *     know which side at CSS layer, so we lean on the larger-bottom
 *     variant (the firmware default for "label sits above route").
 *   - DurationLabel  FontSize:21 Bold
 *   - DescriptionLabel FontSize:15 Medium
 *   - TollSymbol     FontSize:18, centered (overlay on the toll PNG)
 *   - Colour conditional on route_info.selected — selected:#FFFFFF /
 *     alt:var(--t-c-route-alt-duration) (duration); selected:rgba(255,255,255,0.60) /
 *     alt:rgba(65,65,67,0.60) (description); toll currency:
 *     selected:var(--t-c-blue) / alt:var(--t-c-route-alt-toll).
 * The existing route_line_label.rs renders div.t-route-line-label /
 * .t-route-line-label--selected so we hook the styling there.
 */
.t-route-line-label {
  position: absolute;
  display: inline-flex;
  flex-direction: column;
  align-items: flex-start;
  padding: calc(var(--ui-content-scale) * 7px) calc(var(--ui-content-scale) * 20px) calc(var(--ui-content-scale) * 26px);   /* top right bottom left — Tesla 20/7/20/26 above-line */
  pointer-events: auto;
  user-select: none;
  white-space: nowrap;
  transform: translate(-50%, -100%);
  color: var(--t-c-route-alt-duration);
}
.t-route-line-label--below {
  padding: calc(var(--ui-content-scale) * 26px) calc(var(--ui-content-scale) * 20px) calc(var(--ui-content-scale) * 7px);   /* flipped variant when label is below the line */
  transform: translate(-50%, 0);
}
.t-route-line-label--selected {
  color: var(--t-c-route-selected-duration);
}
.t-route-line-label__duration {
  /* DurationLabel FontSize:21 Bold (navigation.md:270). */
  font-size: var(--t-fs-large);   /* fluid analog of 21px */
  font-weight: var(--t-weight-bold);
  line-height: 1.05;
  font-family: var(--t-font-mono);
  color: inherit;
}
.t-route-line-label__description {
  /* DescriptionLabel FontSize:15 Medium (navigation.md:271). */
  font-size: var(--t-fs-small);
  font-weight: var(--t-weight-medium);
  margin-top: calc(var(--ui-content-scale) * 2px);
  color: var(--t-c-route-alt-desc);
}
.t-route-line-label--selected .t-route-line-label__description {
  color: var(--t-c-route-selected-desc);
}
.t-route-line-label__toll {
  /* CurrencySymbol overlay — Fs:18 centered on the toll background PNG.
   * Implementing without the toll PNG asset: render the symbol as a
   * chip-style badge that still reads as "toll cost ahead".  When the
   * Toll feature ships the proper image, swap to inline-background. */
  margin-top: calc(var(--ui-content-scale) * 4px);
  padding: calc(var(--ui-content-scale) * 2px) calc(var(--ui-content-scale) * 6px);
  border-radius: calc(var(--ui-content-scale) * 4px);
  font-size: var(--t-fs-base);   /* Fs:18 fluid analog */
  font-family: var(--t-font-mono);
  color: var(--t-c-route-alt-toll);
  background: var(--t-c-overlay-4);
}
.t-route-line-label--selected .t-route-line-label__toll {
  color: var(--t-c-route-selected-toll);
  background: rgba(17, 108, 216, 0.18);
}


/* ── ChargerClosurePopupContent (charging.md:60-78) ────────────────────
 * vlayout, hero icon at top + site name + status string.  Sits on the
 * standard modal scrim (existing .t-modal-backdrop) and renders inside
 * the existing .t-don-popup container.  The closure-popup-specific
 * styling is just the icon size + the spacing for those two labels.
 */
.t-closure-popup__icon {
  display: block;
  margin: 0 auto var(--t-s-md);
  width: clamp(calc(var(--ui-content-scale) * 64px), calc(6vw + calc(var(--ui-content-scale) * 32px)), calc(var(--ui-content-scale) * 96px));
  height: clamp(calc(var(--ui-content-scale) * 64px), calc(6vw + calc(var(--ui-content-scale) * 32px)), calc(var(--ui-content-scale) * 96px));
  object-fit: contain;
}
.t-closure-popup__site {
  font-size: var(--t-fs-large);
  font-weight: var(--t-weight-medium);
  color: var(--t-c-text-primary);
  text-align: center;
  margin-bottom: var(--t-s-xs);
}
.t-closure-popup__status {
  font-size: var(--t-fs-base);
  color: var(--t-c-text-secondary);
  text-align: center;
  line-height: 1.4;
}


/* ── ArrivalView Start-Charging CTA ──────────────────────────────────
 * No dedicated UIML — we lean on the cluster_navigation_card-M3 pattern
 * for the "primary action" button.  Tesla blue, full width, Body1 sized
 * label, 60px high (firmware standard for primary CTAs).
 */
.t-arrival__charge-cta {
  display: block;
  width: 100%;
  margin-top: var(--t-s-md);
  padding: 0 var(--t-s-lg);
  min-height: clamp(calc(var(--ui-content-scale) * 48px), calc(2vw + calc(var(--ui-content-scale) * 40px)), calc(var(--ui-content-scale) * 60px));
  background: var(--t-c-blue-bright);
  color: var(--t-c-on-accent);
  border: none;
  border-radius: var(--t-r-button);
  font-size: var(--t-fs-large);
  font-weight: var(--t-weight-medium);
  letter-spacing: 0.02em;
  cursor: pointer;
  transition: var(--t-trans-quick);
}
.t-arrival__charge-cta:hover { background: var(--t-c-blue-hover); }


/* ── SpeedRadarZoneView (navigation.md:33-87) ──────────────────────────
 * The 70×220 vertical capsule that surfaces inside an average-speed
 * enforcement zone.  Component scaffolding (speed_radar_zone.rs) is
 * still TODO; this rule pre-positions the container so the component
 * mounts visually correct on day one.
 *   - Container: 70 wide × 220 tall, absolute at x:19 y:18, padding
 *     0,3,0,16 (Tesla l/t/r/b → CSS top:3 right:0 bottom:16 left:0)
 *   - Background: maps/speed_capsule.png  (stencil asset)
 *   - Speed sign placeholder: 66×66 square at top
 *   - LabelValue: Fs:24 mono Text/primary; "Red" when over
 *   - LabelTitle: Fs:14 Text/secondary, center wordwrap
 */
.t-speed-radar-zone {
  position: absolute;
  top: calc(var(--ui-content-scale) * 18px);
  left: calc(var(--ui-content-scale) * 19px);
  width: calc(var(--ui-content-scale) * 70px);
  height: calc(var(--ui-content-scale) * 220px);
  padding: calc(var(--ui-content-scale) * 3px) 0 calc(var(--ui-content-scale) * 16px) 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
  background-image: url("/static/tesla_assets/night_maps/maps/speed_capsule.png");
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
  pointer-events: none;
  z-index: 4;
}
.t-speed-radar-zone__sign {
  width: calc(var(--ui-content-scale) * 66px);
  height: calc(var(--ui-content-scale) * 66px);
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
}
.t-speed-radar-zone__labels {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 0 calc(var(--ui-content-scale) * 6px);
  text-align: center;
}
.t-speed-radar-zone__value {
  font-size: var(--t-fs-medium);   /* Fs:24 fluid analog */
  font-family: var(--t-font-mono);
  font-weight: var(--t-weight-medium);
  color: var(--t-c-text-primary);
  line-height: 1.1;
  letter-spacing: 0;
}
.t-speed-radar-zone__value--over { color: var(--t-c-red); }
.t-speed-radar-zone__title {
  font-size: var(--t-fs-tiny);     /* Fs:14 fluid analog */
  color: var(--t-c-text-secondary);
  margin-top: calc(var(--ui-content-scale) * 2px);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* ═══ MaskedIcon size overrides per context ═══════════════════════════════
   Phase 1: when the wasm replaced hand-drawn SVG / Unicode glyphs with
   <MaskedIcon>, the existing context-specific size rules (`.X svg { ... }`)
   no longer applied. The base .t-mask-icon + size-modifier rules sit later
   in this file, so cascade order would otherwise have them win over the
   context rules. These overrides keep the icon at the original context
   size regardless of which size-modifier MaskedIcon was given. */

/* Bottom-view destination marker — 14px child in a 24px coloured pin. */
.t-bottom-view__dest-marker .t-mask-icon {
  width: calc(var(--ui-content-scale) * 14px); height: calc(var(--ui-content-scale) * 14px);
}

/* Place row pin — 22px open-ring marker in the neutral rounded-rect
   pill. Home / Work coloured variants size the same. */
.t-place-row__pin .t-mask-icon {
  width: calc(var(--ui-content-scale) * 22px); height: calc(var(--ui-content-scale) * 22px);
}

/* Suggestion-item pin — 55% of icon-md in a md-sized pin chip. */
.t-suggestion-item__pin .t-mask-icon {
  width: calc(var(--t-icon-md) * 0.55);
  height: calc(var(--t-icon-md) * 0.55);
}

/* Charger row bolt — 20px child in a 38px coloured circle. */
.t-charger-row__bolt .t-mask-icon {
  width: calc(var(--ui-content-scale) * 20px); height: calc(var(--ui-content-scale) * 20px);
}

/* Search pill icon — leading glyph in the input pill. */
.t-search-pill__icon.t-mask-icon {
  width: var(--t-icon-sm);
  height: var(--t-icon-sm);
}

/* Close (X) buttons — 36×36 round chip with a 16×16 X glyph centered.
   Fixed pixels (not var(--t-icon-sm)) — the design-token clamp gave
   sub-pixel sizes at intermediate viewport widths, making the icon
   antialias fuzzy. Matches the dropped-pin close button exactly. */
.t-info-window__close .t-mask-icon,
.t-settings__close .t-mask-icon,
.t-charger-list__close .t-mask-icon,
.t-sc-geofence__close .t-mask-icon {
  width: calc(var(--ui-content-scale) * 16px);
  height: calc(var(--ui-content-scale) * 16px);
}
/* Info-window closure-banner warning icon — sits inline with text. */
.t-info-window__closure-icon.t-mask-icon {
  width: var(--t-icon-sm);
  height: var(--t-icon-sm);
}

/* Info-window Home/Work add (+) buttons — same as close-button sizing. */
.t-info-window__home-row-add .t-mask-icon {
  width: var(--t-icon-sm);
  height: var(--t-icon-sm);
}

/* drag-bar is rendered as a plain <div> (not a MaskedIcon component)
 * in edit_trip.rs, so no compound override is needed any more.  Left
 * intentionally empty to preserve nearby file structure. */

/* Edit-trip delete (×) — 24px PNG inside the 28px button. */
.t-edit-trip__delete .t-mask-icon {
  width: calc(var(--ui-content-scale) * 24px); height: calc(var(--ui-content-scale) * 24px);
}

/* Trip-summary charge-stops bolt — 24px PNG inside the row icon slot. */
.t-charge-stops__bolt .t-mask-icon {
  width: calc(var(--ui-content-scale) * 24px); height: calc(var(--ui-content-scale) * 24px);
}

/* Trip-summary charge-stops trash — matches stops-delete sizing. */
.t-charge-stops__trash .t-mask-icon {
  width: calc(var(--ui-content-scale) * 22px); height: calc(var(--ui-content-scale) * 22px);
}

/* SC geofence card — 28px bolt PNG in the leading slot. */
.t-sc-geofence__icon .t-mask-icon {
  width: calc(var(--ui-content-scale) * 28px); height: calc(var(--ui-content-scale) * 28px);
}

/* Notification icon slot — uniform 24px PNG regardless of kind. */
.t-notification__icon .t-mask-icon {
  width: calc(var(--ui-content-scale) * 24px); height: calc(var(--ui-content-scale) * 24px);
}

/* ═══ InfoWindow visual refinements — screenshot-verified ═══════════════
   Verified against real Tesla MCU images: TUMO Center for Creative
   Technologies, Florence Restaurant, Tumo Basketball Court (Day theme).

   Layout from top: title → rating + "N reviews" (blue link) →
   open-until-time (green) → action buttons (compact, conditional) →
   Nearby Parking row → address + distance → photos → reviews.
*/

/* Rating row: filled stars + clickable "N reviews" link in blue. */
.t-info-window__rating-row {
  display: flex;
  align-items: center;
  gap: var(--t-s-sm);
  margin: var(--t-s-xs) 0 var(--t-s-xs);
}
.t-info-window__rating-row .t-rating {
  gap: calc(var(--ui-content-scale) * 1px);
}
.t-info-window__rating-row .t-rating__star {
  width: calc(var(--ui-content-scale) * 18px); height: calc(var(--ui-content-scale) * 18px);
}
.t-info-window__reviews-link {
  color: var(--t-c-blue);
  font-size: var(--t-fs-base);
  text-decoration: none;
  cursor: pointer;
  font-weight: var(--t-weight-medium);
}
.t-info-window__reviews-link:hover { text-decoration: underline; }

/* Open-status line — green when open / red when closed. Sits on its
   own row beneath the rating, NOT inline with the stars. */
.t-info-window__open-line {
  font-size: var(--t-fs-base);
  font-weight: var(--t-weight-medium);
  margin: 0 0 var(--t-s-md) 0;
}
.t-info-window__open-line--open   { color: var(--t-c-success-fg); }
.t-info-window__open-line--closed { color: var(--t-c-red); }

/* Action button row — screenshot-verified. Tesla MCU buttons are
   ROUNDED RECTANGLES (~14px corner radius), ~70px square, light
   gray overlay background, dark icon centered. Buttons appear or
   disappear by data availability (handled in the Rust component
   with <Show>). */
.t-info-window__actions {
  display: flex;
  align-items: center;
  gap: var(--t-s-md);
  margin: var(--t-s-md) 0 var(--t-s-lg);
}
.t-info-window__actions .t-action-btn {
  /* Size + icon match real Tesla MCU TUMO/Florence/Basketball Court
     screenshots — 56 px square rounded rectangles with 22 px icons,
     not the chunky 70 px I had before. */
  width: calc(var(--ui-content-scale) * 56px); height: calc(var(--ui-content-scale) * 56px);
  border-radius: calc(var(--ui-content-scale) * 14px);            /* rounded rectangle, NOT circle */
  background: var(--t-c-overlay-4);
  display: flex; align-items: center; justify-content: center;
  border: none;
  color: var(--t-c-text-primary);
  cursor: pointer;
  flex: 0 0 auto;
  padding: 0;
  transition: background 120ms;
}
.t-info-window__actions .t-action-btn:hover  { background: var(--t-c-overlay-6); }
.t-info-window__actions .t-action-btn:active { transform: scale(0.94); }
/* Navigate = the primary action: SAME height as the square buttons, but wider
   (a pill) and always blue in day + night (white icon reads on blue in either).
   Must live here — the descendant `.t-info-window__actions .t-action-btn` rule
   above outranks a bare `.t-action-btn--nav`, so the modifier needs the same
   specificity to win. */
.t-info-window__actions .t-action-btn--nav {
  width: calc(var(--ui-content-scale) * 96px);
  border-radius: 999px;
  background: var(--t-c-blue-bright);
  color: var(--t-c-on-accent);
}
.t-info-window__actions .t-action-btn--nav:hover  { background: var(--t-c-blue-hover); }
.t-info-window__actions .t-action-btn .t-mask-icon {
  width: calc(var(--ui-content-scale) * 22px); height: calc(var(--ui-content-scale) * 22px);
}
.t-info-window__actions .t-action-btn--active {
  background: var(--t-c-yellow);
  /* dark ink on a light (yellow) accent — white fails contrast here */
  color: var(--t-c-on-light);
}

/* Nearby Parking row — light gray rounded rectangle with "P" square
   icon + label + chevron. Verified in all three POI screenshots. */
.t-info-window__parking-row {
  display: flex;
  align-items: center;
  gap: var(--t-s-md);
  width: 100%;
  padding: var(--t-s-md) var(--t-s-md);
  background: var(--t-c-overlay-3);
  border: none;
  border-radius: var(--t-r-card);
  color: var(--t-c-text-primary);
  cursor: pointer;
  margin-bottom: var(--t-s-lg);
  transition: background 120ms;
}
.t-info-window__parking-row:hover { background: var(--t-c-overlay-4); }
.t-info-window__parking-icon {
  width: calc(var(--ui-content-scale) * 32px); height: calc(var(--ui-content-scale) * 32px);
  border-radius: calc(var(--ui-content-scale) * 6px);
  background: var(--t-c-overlay-5);
  display: flex; align-items: center; justify-content: center;
  font-size: var(--t-fs-large);
  font-weight: var(--t-weight-bold);
  color: var(--t-c-text-primary);
  flex: 0 0 auto;
}
.t-info-window__parking-labels {
  flex: 1; min-width: 0; text-align: left;
}
.t-info-window__parking-primary {
  font-size: var(--t-fs-base);
  color: var(--t-c-text-primary);
}
.t-info-window__parking-chevron {
  flex: 0 0 auto;
  opacity: 0.6;
}

/* ═══ Phase 2 — Charging Required ════════════════════════════════════════
   Wire-driven state when the planner returns NOT_POSSIBLE /
   INTERNAL_ERROR or metrics_reason.infeasible_edge. Surfaces:
     * Drive button: red label "Charging Required", disabled
     * Destination chip in BottomView: red text
     * Notification stack: red banner with warning icon
     * Modal popup: charging_required_popup.rs
*/

/* Drive-button states. The base button stays green/blue (default
   action). When unreachable, it goes red with a darker disabled tint
   so the user gets the same "can't proceed" affordance Tesla shows. */
.t-trip-summary__drive-btn--unreachable {
  background: var(--t-c-red) !important;
  color: var(--t-c-on-accent) !important;
  opacity: 0.85;
  cursor: not-allowed;
}
.t-trip-summary__drive-btn--unreachable:hover {
  opacity: 0.85;       /* no hover lift — button is disabled */
}
.t-trip-summary__drive-btn--disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

/* Destination name in BottomView turns red when the trip is
   unreachable. Matches firmware DestinationNameLabel color shift. */
.t-bottom-view__dest-name--unreachable {
  color: var(--t-c-red) !important;
}

/* Charging-required notification chrome — red severity, modelled on
   the existing ChargerOutage variant. */
.t-notification--charging-required {
  background: var(--t-c-red);
  color: var(--t-c-on-accent);
}
.t-notification--charging-required .t-notification__icon {
  color: var(--t-c-on-accent);
}
.t-notification--charging-required .t-notification__title {
  color: var(--t-c-on-accent);
  font-weight: var(--t-weight-medium);
}
.t-notification--charging-required .t-notification__sub {
  color: var(--t-c-on-accent);
  opacity: 0.85;
}

/* Modal popup chrome — narrower than the closure popup, centered icon
   at the top of the body. */
.t-charging-required-popup {
  max-width: calc(var(--ui-content-scale) * 480px);
  width: 100%;
}
.t-charging-required-popup__body {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: var(--t-s-xl) var(--t-s-xl) var(--t-s-md);
}
.t-charging-required-popup__icon {
  color: var(--t-c-red);
  margin-bottom: var(--t-s-md);
}
.t-charging-required-popup__title {
  font-size: var(--t-fs-xlarge);
  font-weight: var(--t-weight-medium);
  color: var(--t-c-text-primary);
  margin-bottom: var(--t-s-xs);
}
.t-charging-required-popup__dest {
  font-size: var(--t-fs-medium);
  color: var(--t-c-text-secondary);
  margin-bottom: var(--t-s-md);
}
.t-charging-required-popup__reason {
  font-size: var(--t-fs-base);
  color: var(--t-c-text-primary);
  line-height: 1.4;
  max-width: calc(var(--ui-content-scale) * 380px);
}

/* ═══ Firmware-canonical InfoWindow extras ═════════════════════════════
   Each block below maps 1:1 onto a sub-template in firmware
   `map_info.uiml`. Comment headers reference the UIML element so
   future agents can compare visually. */

/* Top-row back arrow (firmware `InfoWindowBackButton`, absolute X:22,
   Y:22). Sits left of any type chip; only renders when we're in a
   sub-flow (amenity search, sub-destination drill). The Y:82 variant
   for closure-banner case rides on `.t-info-window__top-row--shifted`
   propagated by `info_window.rs`. */
.t-info-window__back {
  width: calc(var(--ui-content-scale) * 36px); height: calc(var(--ui-content-scale) * 36px);
  border-radius: 50%;
  background: var(--t-c-overlay-4);
  border: 0;
  display: flex; align-items: center; justify-content: center;
  color: var(--t-c-text-primary);
  cursor: pointer;
  margin-right: var(--t-s-sm);
  transition: background 120ms;
  flex: 0 0 auto;
}
.t-info-window__back:hover  { background: var(--t-c-overlay-6); }
.t-info-window__back:active { transform: scale(0.94); }
.t-info-window__back .t-mask-icon { width: calc(var(--ui-content-scale) * 16px); height: calc(var(--ui-content-scale) * 16px); }
/* Closure-banner pushes both close+back down 60 px so they don't
   collide with the banner row (firmware Y:22 → Y:82). */
.t-info-window__top-row--shifted { margin-top: calc(var(--ui-content-scale) * 60px); }

/* Firmware `InfoWindowRatingsAndHoursContainer` — stars + reviews
   link + price ($..$$$$) on one row; status line + today's hours
   summary stack below. POI-only. */
.t-info-window__ratings-container {
  margin: var(--t-s-md) 0 var(--t-s-sm);
  display: flex; flex-direction: column; gap: calc(var(--ui-content-scale) * 4px);
}
.t-info-window__hours-summary {
  font-size: var(--t-fs-base);
  color: var(--t-c-text-secondary);
}
.t-info-window__price-level {
  font-size: var(--t-fs-base);
  color: var(--t-c-text-secondary);
  margin-left: var(--t-s-md);
  font-weight: var(--t-weight-medium);
}

/* Container divs that group firmware ChargerInfoContainer and
   ChargerPricingContainer children. Cosmetic only — gives a slight
   vertical rhythm between charger sub-sections without changing the
   per-row styles. */
.t-info-window__charger-info,
.t-info-window__pricing {
  display: flex; flex-direction: column; gap: var(--t-s-sm);
  margin-top: var(--t-s-md);
}

/* Firmware `InfoWindowAddressExtraInfoContainer` — parking_level and
   access_code lines under the address row. */
.t-info-window__address-extra {
  margin-top: var(--t-s-xs);
  display: flex; flex-direction: column; gap: calc(var(--ui-content-scale) * 2px);
}
.t-info-window__address-extra-row {
  font-size: var(--t-fs-base);
  color: var(--t-c-text-secondary);
}

/* Firmware `NavSetHomeButton` / `NavSetWorkButton`
   (InfoWindowButtonFullWidth): 100% width × 80 px tall, icon LEFT +
   label CENTER + state glyph RIGHT (+ when unset, ✓ when set). */
.t-info-window__setplace-btn {
  display: flex;
  align-items: center;
  width: 100%;
  min-height: calc(var(--ui-content-scale) * 80px);
  margin-top: var(--t-s-sm);
  padding: 0 calc(var(--ui-content-scale) * 24px);
  background: var(--t-c-overlay-3);
  border: 0;
  border-radius: calc(var(--ui-content-scale) * 14px);
  color: var(--t-c-text-primary);
  cursor: pointer;
  transition: background 120ms;
  font-family: inherit;
}
.t-info-window__setplace-btn:hover  { background: var(--t-c-overlay-5); }
.t-info-window__setplace-btn:active { transform: scale(0.99); }
.t-info-window__setplace-btn--set   { background: var(--t-c-overlay-4); }
.t-info-window__setplace-icon { width: calc(var(--ui-content-scale) * 24px); height: calc(var(--ui-content-scale) * 24px); flex: 0 0 auto; }
.t-info-window__setplace-label {
  flex: 1 1 auto;
  text-align: center;
  font-size: var(--t-fs-large);
  font-weight: var(--t-weight-medium);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.t-info-window__setplace-state {
  flex: 0 0 auto;
  width: calc(var(--ui-content-scale) * 28px); height: calc(var(--ui-content-scale) * 28px);
  display: flex; align-items: center; justify-content: center;
  font-size: var(--t-fs-large);
  font-weight: var(--t-weight-bold);
  color: var(--t-c-text-secondary);
}
.t-info-window__setplace-btn--set .t-info-window__setplace-state {
  color: var(--t-c-green);
}

/* Firmware Diner / Queue / MoreDestinations full-width buttons. Same
   shape as the SetPlace button but with the disclosure chevron on
   the right for MoreDestinations. */
.t-info-window__diner-btn,
.t-info-window__queue-btn,
.t-info-window__more-dest-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: calc(var(--ui-content-scale) * 80px);
  margin-top: var(--t-s-sm);
  padding: 0 calc(var(--ui-content-scale) * 24px);
  background: var(--t-c-overlay-3);
  border: 0;
  border-radius: calc(var(--ui-content-scale) * 14px);
  color: var(--t-c-text-primary);
  font-size: var(--t-fs-large);
  font-weight: var(--t-weight-medium);
  cursor: pointer;
  transition: background 120ms;
  font-family: inherit;
  gap: var(--t-s-sm);
}
.t-info-window__more-dest-btn { justify-content: space-between; }
.t-info-window__diner-btn:hover,
.t-info-window__queue-btn:hover,
.t-info-window__more-dest-btn:hover { background: var(--t-c-overlay-5); }
.t-info-window__diner-btn:active,
.t-info-window__queue-btn:active,
.t-info-window__more-dest-btn:active { transform: scale(0.99); }

/* Firmware ParkingContainer — `Nearby Parking` button + divider +
   `ParkingOptionsLabel`. The outer container has the 2 px border the
   firmware draws around the parking section. */
.t-info-window__parking-container {
  margin-top: var(--t-s-md);
  border: calc(var(--ui-content-scale) * 1px) solid var(--t-c-overlay-4);
  border-radius: calc(var(--ui-content-scale) * 14px);
  overflow: hidden;
}
.t-info-window__parking-container .t-info-window__parking-row {
  margin-top: 0;            /* parent container owns spacing now */
  border-radius: calc(var(--ui-content-scale) * 14px) calc(var(--ui-content-scale) * 14px) 0 0;
}
.t-info-window__parking-divider {
  height: calc(var(--ui-content-scale) * 1px);
  background: var(--t-c-overlay-3);
  margin: 0;
}
.t-info-window__parking-options {
  padding: var(--t-s-sm) var(--t-s-md);
  font-size: var(--t-fs-base);
  color: var(--t-c-text-secondary);
}

/* Firmware AmenitiesContainerView — divider + "Find Nearby Amenities"
   heading + the 7-button row. Inline AmenitySearchView appears
   directly below when the user taps one. */
.t-info-window__divider {
  height: calc(var(--ui-content-scale) * 1px);
  background: var(--t-c-overlay-3);
  margin: var(--t-s-lg) 0 var(--t-s-md);
}
.t-info-window__amenities-container {
  margin-top: var(--t-s-md);
}
.t-info-window__amenities-heading {
  font-size: var(--t-fs-base);
  color: var(--t-c-text-primary);
  margin-bottom: var(--t-s-sm);
  font-weight: var(--t-weight-medium);
}
.t-info-window__amenity-search {
  margin-top: var(--t-s-md);
  display: flex; flex-direction: column; gap: var(--t-s-sm);
}
.t-info-window__amenity-result {
  display: flex;
  align-items: center;
  gap: var(--t-s-md);
  padding: var(--t-s-sm);
  border-radius: calc(var(--ui-content-scale) * 10px);
  cursor: pointer;
  transition: background 120ms;
}
.t-info-window__amenity-result:hover  { background: var(--t-c-overlay-4); }
.t-info-window__amenity-result:active { background: var(--t-c-overlay-5); }
.t-info-window__amenity-result-photo {
  width: calc(var(--ui-content-scale) * 64px); height: calc(var(--ui-content-scale) * 64px);
  border-radius: calc(var(--ui-content-scale) * 8px);
  background: var(--t-c-overlay-3);
  overflow: hidden;
  flex: 0 0 auto;
  display: flex; align-items: center; justify-content: center;
}
.t-info-window__amenity-result-photo img {
  width: 100%; height: 100%; object-fit: cover;
}
.t-info-window__amenity-result-labels {
  flex: 1 1 auto; min-width: 0;
  display: flex; flex-direction: column; gap: calc(var(--ui-content-scale) * 2px);
}
.t-info-window__amenity-result-name {
  font-size: var(--t-fs-base);
  color: var(--t-c-text-primary);
  font-weight: var(--t-weight-medium);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.t-info-window__amenity-result-open {
  font-size: var(--t-fs-base);
  color: var(--t-c-green);
}
.t-info-window__amenity-result-rating {
  font-size: var(--t-fs-base);
  color: var(--t-c-text-secondary);
  display: flex; align-items: center; gap: calc(var(--ui-content-scale) * 4px);
}
.t-info-window__amenity-result-star { color: var(--t-c-star); }
.t-info-window__see-all {
  font-size: var(--t-fs-base);
  color: var(--t-c-blue-bright);
  align-self: flex-start;
  margin-top: var(--t-s-xs);
  text-decoration: none;
}
.t-info-window__see-all:hover { text-decoration: underline; }

/* Firmware TraitsContainerView — "Convenience Features" heading +
   chip rows (currently just Trailer Friendly). */
.t-info-window__traits-container {
  margin-top: var(--t-s-md);
}
.t-info-window__traits-heading {
  font-size: var(--t-fs-base);
  color: var(--t-c-text-primary);
  font-weight: var(--t-weight-medium);
  margin-bottom: var(--t-s-sm);
}

/* ═══ DroppedPinView ══════════════════════════════════════════════════
   Standalone minimal panel for the long-press / no-featureId tap. A
   separate component (components/dropped_pin_view.rs) — not a styling
   variant of the full InfoWindow. Renders title + 2 wide action pills
   + Set as Home + Set as Work + 2-line address at the bottom.
   Verified against the Tesla MCU 10 Abelian St screenshot. */
.t-dropped-pin {
  background: var(--t-c-bg-nav-primary);
  backdrop-filter: blur(calc(var(--ui-content-scale) * 20px));
  -webkit-backdrop-filter: blur(calc(var(--ui-content-scale) * 20px));
  border-radius: var(--t-r-card);
  width: 100%;
  padding: calc(var(--ui-content-scale) * 30px);
  display: flex; flex-direction: column;
  gap: var(--t-s-md);
}
.t-dropped-pin__top {
  display: flex; justify-content: flex-end;
  margin: calc(var(--ui-content-scale) * -10px) calc(var(--ui-content-scale) * -10px) 0 0;
}
.t-dropped-pin__close {
  width: calc(var(--ui-content-scale) * 36px); height: calc(var(--ui-content-scale) * 36px);
  border-radius: 50%;
  background: var(--t-c-overlay-4);
  border: 0;
  display: flex; align-items: center; justify-content: center;
  color: var(--t-c-text-primary);
  cursor: pointer;
  transition: background 120ms;
}
.t-dropped-pin__close:hover  { background: var(--t-c-overlay-6); }
.t-dropped-pin__close:active { transform: scale(0.94); }
.t-dropped-pin__close .t-mask-icon { width: calc(var(--ui-content-scale) * 16px); height: calc(var(--ui-content-scale) * 16px); }

.t-dropped-pin__title {
  font-size: var(--t-fs-xlarge);
  font-weight: var(--t-weight-bold);
  color: var(--t-c-text-primary);
  line-height: 1.2;
  margin: 0;
}

.t-dropped-pin__actions {
  display: flex;
  gap: var(--t-s-sm);
  width: 100%;
}
.t-dropped-pin__action {
  flex: 1 1 50%;
  min-height: calc(var(--ui-content-scale) * 80px);
  border-radius: calc(var(--ui-content-scale) * 14px);
  background: var(--t-c-overlay-4);
  border: 0;
  display: flex; align-items: center; justify-content: center;
  color: var(--t-c-text-primary);
  cursor: pointer;
  transition: background 120ms;
}
.t-dropped-pin__action:hover  { background: var(--t-c-overlay-6); }
.t-dropped-pin__action:active { transform: scale(0.99); }
.t-dropped-pin__action .t-mask-icon,
.t-dropped-pin__action img {
  width: calc(var(--ui-content-scale) * 26px); height: calc(var(--ui-content-scale) * 26px);
}
.t-dropped-pin__action--active {
  background: var(--t-c-blue);
  color: var(--t-c-on-accent);
}

.t-dropped-pin__setplace {
  display: flex;
  align-items: center;
  width: 100%;
  min-height: calc(var(--ui-content-scale) * 80px);
  padding: 0 calc(var(--ui-content-scale) * 24px);
  background: var(--t-c-overlay-3);
  border: 0;
  border-radius: calc(var(--ui-content-scale) * 14px);
  color: var(--t-c-text-primary);
  cursor: pointer;
  transition: background 120ms;
  font-family: inherit;
}
.t-dropped-pin__setplace:hover  { background: var(--t-c-overlay-5); }
.t-dropped-pin__setplace:active { transform: scale(0.99); }
.t-dropped-pin__setplace--set   { background: var(--t-c-overlay-4); }
.t-dropped-pin__setplace-icon { width: calc(var(--ui-content-scale) * 24px); height: calc(var(--ui-content-scale) * 24px); flex: 0 0 auto; }
.t-dropped-pin__setplace-label {
  flex: 1 1 auto;
  text-align: left;
  margin-left: var(--t-s-md);
  font-size: var(--t-fs-large);
  font-weight: var(--t-weight-medium);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.t-dropped-pin__setplace-state {
  flex: 0 0 auto;
  width: calc(var(--ui-content-scale) * 28px); height: calc(var(--ui-content-scale) * 28px);
  display: flex; align-items: center; justify-content: center;
  font-size: var(--t-fs-large);
  font-weight: var(--t-weight-bold);
  color: var(--t-c-text-secondary);
}
.t-dropped-pin__setplace--set .t-dropped-pin__setplace-state {
  color: var(--t-c-green);
}

.t-dropped-pin__address {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  margin-top: var(--t-s-sm);
  gap: var(--t-s-md);
}
.t-dropped-pin__address-lines {
  flex: 1 1 auto; min-width: 0;
  display: flex; flex-direction: column;
  gap: calc(var(--ui-content-scale) * 2px);
}
.t-dropped-pin__address-line1 {
  font-size: var(--t-fs-base);
  color: var(--t-c-text-primary);
  font-weight: var(--t-weight-medium);
}
.t-dropped-pin__address-line2 {
  font-size: var(--t-fs-base);
  color: var(--t-c-text-secondary);
}
.t-dropped-pin__address-distance {
  font-size: var(--t-fs-base);
  color: var(--t-c-text-secondary);
  flex: 0 0 auto;
}

/* ═══ TripPlanView + StartOfTripPOIView ════════════════════════════════
   Firmware NavTurnList::StartOfTripPOIView (turn_list.uiml:264-275).
   Sits above the TripSummary card while the user reviews the plan.
   Padding mirrors firmware: 30 px outer, 30 px between groups. */
.t-trip-plan {
  display: flex; flex-direction: column;
  flex: 1 1 auto; min-height: 0;
  height: 100%;
}
/* Scroll body holds the firmware-canonical template stack (alt-plan
   tabs, summary card, maneuver list, charger waypoints, elevation,
   trip-extras). Bottom dock is pinned outside the scroll. */
.t-trip-plan__scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  display: flex; flex-direction: column;
  gap: var(--t-s-md);
  padding-bottom: var(--t-s-md);
}
/* TripPlanBottomBar — firmware SplitTurnListBottomView dock,
   pinned to the bottom of the trip-plan column. Above the
   shell's safe-area inset; height is whatever the buttons need. */
.t-trip-plan-bar {
  flex: 0 0 auto;
  background: var(--t-c-bg-nav-primary);
  border-radius: calc(var(--ui-content-scale) * 14px);
  padding: calc(var(--ui-content-scale) * 14px) calc(var(--ui-content-scale) * 16px);
  margin-top: var(--t-s-sm);
  display: flex; align-items: center;
  gap: var(--t-s-sm);
  position: relative;
  box-shadow: 0 calc(var(--ui-content-scale) * -4px) calc(var(--ui-content-scale) * 12px) rgba(0,0,0,0.2);
}
/* SwipeDestination — firmware turn_list.uiml:101-112. Whole row is
   the swipe surface; transform: translateX(dx) follows the finger
   while dragging right. */
.t-swipe-dest {
  flex: 1 1 auto;
  display: flex; align-items: center;
  gap: var(--t-s-md);
  min-height: calc(var(--ui-content-scale) * 72px);
  padding: 0 var(--t-s-md);
  background: var(--t-c-blue);
  border-radius: calc(var(--ui-content-scale) * 12px);
  color: var(--t-c-on-accent);
  cursor: grab;
  touch-action: pan-y;
  user-select: none;
  -webkit-user-select: none;
  transition: transform 80ms ease-out, background 120ms;
}
.t-swipe-dest:active { cursor: grabbing; }
.t-swipe-dest__image {
  width: calc(var(--ui-content-scale) * 40px); height: calc(var(--ui-content-scale) * 40px);
  border-radius: calc(var(--ui-content-scale) * 8px);
  background-color: rgba(255,255,255,0.15);
  background-image: url("/img/maps/info_window/navigate.png");
  background-size: calc(var(--ui-content-scale) * 24px) calc(var(--ui-content-scale) * 24px);
  background-position: center;
  background-repeat: no-repeat;
  flex: 0 0 auto;
}
.t-swipe-dest__labels {
  flex: 1 1 auto; min-width: 0;
  display: flex; flex-direction: column;
  gap: calc(var(--ui-content-scale) * 2px);
}
.t-swipe-dest__title {
  font-size: var(--t-fs-base);
  font-weight: var(--t-weight-medium);
  line-height: 1.2;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.t-swipe-dest__subtitle {
  font-size: var(--t-fs-mini);
  opacity: 0.8;
  line-height: 1.2;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.t-swipe-dest__hint {
  flex: 0 0 auto;
  font-size: var(--t-fs-mini);
  opacity: 0.85;
  letter-spacing: 0.03em;
}
.t-swipe-dest__hint::after {
  content: " ›";
  font-size: var(--t-fs-large);
  vertical-align: middle;
}
.t-swipe-dest--unreachable {
  background: var(--t-c-red);
  cursor: not-allowed;
}
.t-swipe-dest--disabled {
  opacity: 0.55;
  cursor: not-allowed;
}
.t-trip-plan-bar__more {
  flex: 0 0 auto;
  width: calc(var(--ui-content-scale) * 56px); height: calc(var(--ui-content-scale) * 56px);
  background: var(--t-c-overlay-4);
  border: 0;
  border-radius: calc(var(--ui-content-scale) * 12px);
  color: var(--t-c-text-primary);
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  font-size: calc(var(--ui-font-scale) * 24px); line-height: 1;
  transition: background 120ms;
}
.t-trip-plan-bar__more:hover { background: var(--t-c-overlay-6); }
.t-start-of-trip {
  background: var(--t-c-bg-nav-primary);
  backdrop-filter: blur(calc(var(--ui-content-scale) * 20px));
  -webkit-backdrop-filter: blur(calc(var(--ui-content-scale) * 20px));
  border-radius: var(--t-r-card);
  padding: calc(var(--ui-content-scale) * 30px);
  display: flex; flex-direction: column;
  gap: var(--t-s-md);
}
.t-start-of-trip__dest {
  display: flex; align-items: center;
  gap: var(--t-s-sm);
}
.t-start-of-trip__dest-icon {
  width: calc(var(--ui-content-scale) * 22px); height: calc(var(--ui-content-scale) * 22px);
  color: var(--t-c-text-primary);
  flex: 0 0 auto;
}
.t-start-of-trip__dest-name {
  font-size: var(--t-fs-xlarge);
  font-weight: var(--t-weight-bold);
  color: var(--t-c-text-primary);
  flex: 1 1 auto;
  min-width: 0;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.t-start-of-trip__rating-hours {
  display: flex; flex-direction: column;
  gap: calc(var(--ui-content-scale) * 4px);
}
.t-start-of-trip__hours {
  font-size: var(--t-fs-base);
  color: var(--t-c-text-secondary);
}
.t-start-of-trip__arrival {
  margin-top: var(--t-s-sm);
}
.t-start-of-trip__arrival-calculating {
  font-size: var(--t-fs-base);
  color: var(--t-c-text-secondary);
  font-style: italic;
}
.t-start-of-trip__arrival-row {
  display: flex; align-items: center;
  gap: var(--t-s-md);
  flex-wrap: wrap;
}
.t-start-of-trip__arrival-time {
  font-size: var(--t-fs-large);
  font-weight: var(--t-weight-medium);
  color: var(--t-c-text-primary);
}
.t-start-of-trip__arrival-dur,
.t-start-of-trip__arrival-soc {
  font-size: var(--t-fs-base);
  color: var(--t-c-text-secondary);
}
.t-start-of-trip__photos {
  margin-top: var(--t-s-sm);
}
.t-start-of-trip__cancel {
  margin-top: var(--t-s-sm);
  width: 100%;
  min-height: calc(var(--ui-content-scale) * 60px);
  background: var(--t-c-overlay-4);
  color: var(--t-c-text-primary);
  border: 0;
  border-radius: calc(var(--ui-content-scale) * 14px);
  font-size: var(--t-fs-large);
  font-weight: var(--t-weight-medium);
  cursor: pointer;
  font-family: inherit;
  transition: background 120ms;
}
.t-start-of-trip__cancel:hover  { background: var(--t-c-overlay-6); }
.t-start-of-trip__cancel:active { transform: scale(0.99); }

/* Trip-summary charge-stop SuperchargerLabel line — operator + class
   + max kW (firmware ListWayPointView.SuperchargerLabel). */
.t-charge-stops__supercharger {
  font-size: var(--t-fs-base);
  color: var(--t-c-text-secondary);
  margin-top: calc(var(--ui-content-scale) * 2px);
}
/* Tweak: Drive button gets a subtle right-pointing arrow on the swipe
   gesture so the user sees the affordance. CSS-only — no extra DOM. */
.t-trip-summary__drive-btn::after {
  content: "›";
  margin-left: var(--t-s-sm);
  opacity: 0.6;
  font-weight: var(--t-weight-medium);
}
.t-trip-summary__drive-btn--unreachable::after,
.t-trip-summary__drive-btn--disabled::after { content: ""; margin-left: 0; }

/* ───────────────────────────────────────────────────────────────────
 *  TripPlanCard — firmware compact trip-overview card.
 *
 *  ONE dark rounded surface containing the profile-name title, the
 *  summary line, the waypoint list, and footer actions. Mounts in
 *  RouteOverview / GuidanceRouteOverview only. Width is constrained
 *  to match the firmware screenshot (narrow, ~420px), aligned to the
 *  left edge of the sheet, NOT stretched.
 * ─────────────────────────────────────────────────────────────────── */
.TripPlanCard {
  background: var(--t-c-bg-nav-primary);
  backdrop-filter: blur(calc(var(--ui-content-scale) * 20px));
  -webkit-backdrop-filter: blur(calc(var(--ui-content-scale) * 20px));
  border-radius: var(--t-r-card);
  box-shadow: var(--t-shadow-card);
  /* Responsive — clamp(phone-floor, 35vw, MCU-spec 430 px). */
  width: clamp(calc(var(--ui-content-scale) * 280px), 35vw, calc(var(--ui-content-scale) * 430px));
  max-width: calc(var(--ui-content-scale) * 430px);
  align-self: flex-start;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  flex: 0 1 auto;
  pointer-events: auto;

}
/* TripPlanOptionsView inside the card — turn_list.uiml:44-49
 * styles-common.conf:522-529.  Single-profile case still renders the
 * one OptionLabel as the surface title (photo: "Fastest & Best
 * Amenities").  ≥2 profiles → horizontal swipeable tab strip. */
.TripPlanCard .TripPlanOptionsView {
  display: flex;
  flex-direction: column;
  align-items: stretch;
}
.TripPlanCard .TripPlanScrollableView {
  display: flex;
  flex-direction: row;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  align-items: center;
  padding: calc(var(--ui-content-scale) * 16px) calc(var(--ui-content-scale) * 24px) 0 calc(var(--ui-content-scale) * 24px);       /* tight top padding inside card */
}
.TripPlanCard .TripPlanScrollableView::-webkit-scrollbar { display: none; }
.TripPlanCard .OptionsContainer {
  display: flex;
  flex-direction: row;
  align-items: center;
}
.TripPlanCard .TripPlanOption {
  display: flex;
  align-items: center;
  cursor: pointer;
  margin-right: calc(var(--ui-content-scale) * 24px);              /* gap between tabs */
}
.TripPlanCard .TripPlanOption:last-child { margin-right: 0; }
.TripPlanCard .OptionLabel {
  font-size: calc(var(--ui-font-scale) * 18px);                 /* Caption1 weight title */
  color: var(--t-c-text-secondary);
  white-space: nowrap;
  font-weight: var(--t-weight-medium, 500);
}
.TripPlanCard .OptionLabelSelected {
  color: var(--t-c-text-primary);
}
.TripPlanCard .TripPlanOptionsDivider {
  display: none;                   /* no full-width divider inside the card */
}
.TripPlanCard .TripPlanSummary {
  padding: calc(var(--ui-content-scale) * 8px) calc(var(--ui-content-scale) * 24px) calc(var(--ui-content-scale) * 16px) calc(var(--ui-content-scale) * 24px);
  display: flex;
  flex-direction: column;
  gap: calc(var(--ui-content-scale) * 2px);
}
.TripPlanCard .TripDuration {
  font-size: calc(var(--ui-font-scale) * 28px);
  color: var(--t-c-text-primary);
  line-height: 1.15;
}
.TripPlanCard .TripPlanSummaryLine {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0 calc(var(--ui-content-scale) * 14px);
}
.TripPlanCard .NumStops,
.TripPlanCard .TripDistance,
.TripPlanCard .FinalArrivalTime {
  font-size: calc(var(--ui-font-scale) * 18px);
  color: var(--t-c-text-secondary);
  line-height: 1.2;
  font-variant-numeric: tabular-nums;
}
.TripPlanCard__waypoints {
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  touch-action: pan-y;
  overscroll-behavior: contain;
}
/* Action strip — "Set Arrival Energy" + "Remove all charging stops".
 * Firmware renders these as RichTextLabelView links (Caption1 in
 * highlight colour), NOT 80-px TurnListMoreButton row buttons.
 * The strip is indented by 90px (icon column width + 20px margin =
 * 70 + 20) so the links align with the destination row's content
 * column — the user perceives them as "under the battery". */
.TripPlanCard__actions {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  padding: calc(var(--ui-content-scale) * 4px) calc(var(--ui-content-scale) * 24px) calc(var(--ui-content-scale) * 18px) calc(var(--ui-content-scale) * 90px);
  gap: calc(var(--ui-content-scale) * 8px);
}
.TripPlanActionLink {
  background: transparent;
  border: none;
  padding: 0;
  margin: 0;
  font: inherit;
  font-size: calc(var(--ui-font-scale) * 18px);               /* Text/Caption1 */
  color: var(--t-c-text-highlight, var(--t-c-info-fg));
  cursor: pointer;
  text-align: left;
  line-height: 1.3;
}
.TripPlanActionLink:hover { opacity: 0.85; }

/* TurnListBottomBar — turn_list.uiml:111-113.  Drag grabber that
 * toggles collapsed/expanded turn list in driving mode.  Firmware
 * grabber.png is 60×6 with TouchPadding: 0,15,0,15 (calc(var(--ui-content-scale) * 15px) vertical
 * drag zone above + below). */
.TurnListBottomBar {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: calc(var(--ui-content-scale) * 36px);                  /* 6px image + 15px above/below */
  cursor: pointer;
  user-select: none;
  /* Own the vertical gesture — without this the browser claims the
     drag as a native scroll (pointercancel fires, dy never accrues) so
     only taps registered. Lets the swipe-to-expand/collapse handlers see
     pointermove. */
  touch-action: none;
}
.TurnListBottomBar__Grabber {
  width: calc(var(--ui-content-scale) * 60px);
  height: calc(var(--ui-content-scale) * 6px);
  background-color: var(--t-c-text-secondary);
  opacity: 0.6;
}
.TurnListBottomBar:hover .TurnListBottomBar__Grabber { opacity: 0.9; }

/* Selection halo for route waypoint pins — firmware
 * PinMarkerView::setHighlighted(true) → nav_v2/selected_icon ring.
 * tesla_sc.png has no shipped `_selected` variant; we approximate with
 * a blue circular outer ring + drop-shadow, matching the colour
 * (`Background/highlight` / Tesla blue) used elsewhere by the selected
 * style group. */
.t-waypoint-selected {
  border-radius: 50%;
  box-shadow:
    0 0 0 calc(var(--ui-content-scale) * 4px) rgba(74, 144, 226, 0.9),    /* tight inner ring */
    0 0 calc(var(--ui-content-scale) * 18px) calc(var(--ui-content-scale) * 4px) rgba(74, 144, 226, 0.55); /* outer glow */
  transition: box-shadow 120ms ease-out;
}



/* ─── Vehicle picker (full-screen modal opened from Settings) ───────── */
.t-veh-picker-backdrop {
  position: fixed; inset: 0;
  background: var(--t-c-scrim);
  backdrop-filter: blur(calc(var(--ui-content-scale) * 8px));
  -webkit-backdrop-filter: blur(calc(var(--ui-content-scale) * 8px));
  z-index: 1100;
}
.t-veh-picker {
  position: fixed; inset: calc(var(--ui-content-scale) * 24px); max-width: calc(var(--ui-content-scale) * 880px); margin: 0 auto;
  background: var(--t-pill-bg);
  color: var(--t-c-text-primary);
  border-radius: calc(var(--ui-content-scale) * 18px);
  box-shadow: var(--t-shadow-deep);
  z-index: 1101;
  display: flex; flex-direction: column;
  overflow: hidden;
}
.t-veh-picker__head {
  display: flex; align-items: center; justify-content: space-between;
  padding: calc(var(--ui-content-scale) * 18px) calc(var(--ui-content-scale) * 22px) calc(var(--ui-content-scale) * 10px) calc(var(--ui-content-scale) * 22px);
  border-bottom: calc(var(--ui-content-scale) * 1px) solid var(--t-c-bg-divider);
}
.t-veh-picker__title { font-size: calc(var(--ui-font-scale) * 22px); font-weight: 500; }
.t-veh-picker__close {
  border: 0; background: transparent;
  color: var(--t-c-text-primary);
  font-size: calc(var(--ui-font-scale) * 22px); cursor: pointer;
  padding: calc(var(--ui-content-scale) * 4px) calc(var(--ui-content-scale) * 10px);
}
.t-veh-picker__searchrow {
  display: flex; align-items: center; gap: calc(var(--ui-content-scale) * 12px);
  padding: calc(var(--ui-content-scale) * 14px) calc(var(--ui-content-scale) * 22px);
  border-bottom: calc(var(--ui-content-scale) * 1px) solid var(--t-c-bg-divider);
}
.t-veh-picker__search {
  flex: 1;
  border: calc(var(--ui-content-scale) * 1px) solid var(--t-c-bg-divider);
  background: var(--t-c-overlay-3);
  color: var(--t-c-text-primary);
  border-radius: calc(var(--ui-content-scale) * 10px);
  padding: calc(var(--ui-content-scale) * 10px) calc(var(--ui-content-scale) * 14px);
  font-size: calc(var(--ui-font-scale) * 16px);
  outline: none;
}
.t-veh-picker__search:focus { border-color: var(--t-c-blue-bright); }
.t-veh-picker__count {
  color: var(--t-c-text-secondary);
  font-size: calc(var(--ui-font-scale) * 13px);
  white-space: nowrap;
}
.t-veh-picker__list {
  flex: 1;
  overflow-y: auto;
  padding: calc(var(--ui-content-scale) * 8px) 0;
}
.t-veh-picker__group { margin: 0; }
.t-veh-picker__group-title {
  font-size: calc(var(--ui-font-scale) * 11px);
  letter-spacing: 0.06em;
  color: var(--t-c-text-secondary);
  padding: calc(var(--ui-content-scale) * 14px) calc(var(--ui-content-scale) * 22px) calc(var(--ui-content-scale) * 4px) calc(var(--ui-content-scale) * 22px);
  text-transform: uppercase;
}
.t-veh-picker__row {
  display: flex; align-items: center; gap: calc(var(--ui-content-scale) * 12px);
  padding: calc(var(--ui-content-scale) * 12px) calc(var(--ui-content-scale) * 22px);
  cursor: pointer;
  border-bottom: calc(var(--ui-content-scale) * 1px) solid var(--t-c-bg-divider);
}
.t-veh-picker__row:hover {
  background: var(--t-c-overlay-2);
}
.t-veh-picker__row.is-selected {
  background: var(--t-c-info-bg);
}
.t-veh-picker__row-main { flex: 1; min-width: 0; }
.t-veh-picker__row-model {
  font-size: calc(var(--ui-font-scale) * 15px); font-weight: 500;
  display: flex; align-items: center; gap: calc(var(--ui-content-scale) * 8px);
}
.t-veh-picker__row-meta {
  font-size: calc(var(--ui-font-scale) * 12px); color: var(--t-c-text-secondary);
  margin-top: calc(var(--ui-content-scale) * 2px);
}
.t-veh-picker__badge {
  font-size: calc(var(--ui-font-scale) * 10px); letter-spacing: 0.04em;
  padding: calc(var(--ui-content-scale) * 2px) calc(var(--ui-content-scale) * 6px);
  border-radius: calc(var(--ui-content-scale) * 6px);
  text-transform: uppercase;
}
.t-veh-picker__badge--firm {
  background: var(--t-c-info-bg);
  color: var(--t-c-blue-bright);
}
.t-veh-picker__check {
  color: var(--t-c-blue-bright);
  font-size: calc(var(--ui-font-scale) * 20px);
}
.t-veh-picker__error {
  padding: calc(var(--ui-content-scale) * 14px) calc(var(--ui-content-scale) * 22px);
  background: var(--t-c-error-bg);
  color: var(--t-c-error-fg);
  font-size: calc(var(--ui-font-scale) * 13px);
  border-bottom: calc(var(--ui-content-scale) * 1px) solid var(--t-c-bg-divider);
}
.t-veh-picker__error-hint {
  color: var(--t-c-text-secondary);
  font-size: calc(var(--ui-font-scale) * 11px);
  margin-top: calc(var(--ui-content-scale) * 4px);
}
.t-veh-picker__empty {
  padding: calc(var(--ui-content-scale) * 40px) calc(var(--ui-content-scale) * 22px);
  text-align: center;
  color: var(--t-c-text-secondary);
  font-size: calc(var(--ui-font-scale) * 14px);
}

/* ── Fluidity / anti-overflow safety net ────────────────────────────
   Views may carry a fixed (scaled) size, but the layout must never
   "fuck up" when the browser window shrinks: panels stay within the
   viewport and the content inside reflows instead of overflowing.

   The core fix is `min-width: 0` on flex children that hold flexible
   content. Flex items default to `min-width: auto`, which refuses to
   shrink below their content's intrinsic width — that's what forces a
   long street name / address / title to blow out the row and push
   siblings off-screen on a narrow window. `min-width: 0` only takes
   effect WHEN space is constrained, so it never shrinks anything that
   already fits — it just lets text columns ellipsis/wrap instead of
   overflowing. Pair it with the per-element `overflow`/`white-space`
   rules already on those labels. */

/* Nothing inside the nav column may exceed the column's own width. */
.t-shell__left > * { max-width: 100%; min-width: 0; }

/* Flexible text columns + scroll regions: allow shrink. Targeted by the
   project's BEM suffix convention so this stays a safety net, not a
   blanket `* { min-width: 0 }`. */
[class*="__labels"], [class*="__label"], [class*="__title"],
[class*="__subtitle"], [class*="__sub"], [class*="__name"],
[class*="__desc"], [class*="__info"], [class*="__text"],
[class*="__body"], [class*="__main"], [class*="__meta"],
[class*="__details"], [class*="__col"], [class*="__column"],
[class*="__row-labels"],
[class*="__scroll"], [class*="__list"] {
  min-width: 0;
}
