/* src/ui/style.css — all interface styling. Colours follow the controls card and the keyboard diagram, by function:
   go = green (--ok, the throttle bar), brake = red (--serious, the brake bar), steer = blue (--steer, the wheel's hand),
   transmission = the selector's green, lights/signals = amber, other = purple. */
:root { --bg: #0f1115; --panel: rgba(20, 23, 30, 0.92); --line: #2a2f3a; --text: #e8eaf0; --muted: #98a0b3; --accent: #3fb6ff; --minor: #e8a020; --serious: #e04a3a; --dangerous: #ff2b2b; --ok: #3ccf6e;
  --steer: #2196d6; --transmission: #23a866; --signals: #e9a318; --other: #8e55e0; }
* { box-sizing: border-box; }
/* a side that text sits against is a LOGICAL one (inline-start / inline-end, text-align: start): Arabic turns the page right to left (i18n.js direction, main.js sets <html dir>), and the side panels, their accents and the key hints follow it; the HUD keeps its physical corners, as a dashboard does */
/* … and what is drawn as the car or the keyboard keeps its physical order in a right-to-left page — the brake pedal left of the wheel strip, P R N D, the left indicator lamp on the left, J K L and A F as the keys lie — while each word on them runs in its own direction */
.steer-row, .hud-selector, .hud-lamps, .ctl-card { direction: ltr; }
.ctl-card small, .ctl-legend > span, .ctl-more { unicode-bidi: plaintext; }
html, body { margin: 0; height: 100%; background: var(--bg); color: var(--text); font: 14px/1.4 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; overflow: hidden; }
/* the browser draws its own pieces dark too (color-scheme: scrollbars, the select popups, the range slider), and every scrollbar is a slim pill of the button-border grey on no track: the city list, the routes, the panels and the start column all scroll */
:root { color-scheme: dark; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track, ::-webkit-scrollbar-corner { background: transparent; }
::-webkit-scrollbar-thumb { background: #3a4150; border: 2px solid transparent; border-radius: 8px; background-clip: padding-box; }
::-webkit-scrollbar-thumb:hover { background-color: #4b5468; }
/* Firefox has no scrollbar pseudo-elements: the standard properties give it the same thin quiet bar, and only it, since Chrome would honour them over the pseudo-elements */
@supports not selector(::-webkit-scrollbar) { :root { scrollbar-width: thin; scrollbar-color: #3a4150 transparent; } }
#view { position: fixed; inset: 0; }
#view canvas { display: block; width: 100% !important; height: 100% !important; }
button { background: #232834; color: var(--text); border: 1px solid #3a4150; border-radius: 8px; padding: 8px 14px; font: inherit; cursor: pointer; }
button:hover { border-color: var(--accent); }
button.primary { background: var(--accent); color: #08131c; border-color: transparent; font-weight: 600; }
button:disabled { opacity: 0.45; cursor: default; }
input, select { background: #1b1f27; color: var(--text); border: 1px solid #3a4150; border-radius: 6px; padding: 7px 10px; font: inherit; }
.muted { color: var(--muted); } .small { font-size: 12px; }
h1 { font-size: 24px; margin: 0 0 8px; } h2 { font-size: 20px; margin: 0 0 10px; } h3 { font-size: 13px; text-transform: uppercase; letter-spacing: .8px; color: var(--muted); margin: 16px 0 6px; }

/* loading */
#loading { position: fixed; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; background: var(--bg); z-index: 50; gap: 8px; }
.spinner { width: 28px; height: 28px; border: 3px solid #2a2f3a; border-top-color: var(--accent); border-radius: 50%; animation: spin 0.9s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
/* the lockup is the heading: alt text carries the name, and width/height on the tag hold the space while the file is on its way */
.brand { line-height: 0; }
.brand img { height: auto; }
#loading .brand { margin: 0 0 2px; } #loading .brand img { width: 232px; }
#loading pre { max-width: 80vw; white-space: pre-wrap; color: #ff8a8a; font-size: 12px; }
/* the controls card (ui/controls-card.js) under the spinner, something to read while the block is built (main.js drawLoadCard);
   not over the frozen frame of a block change mid-drive, which is a pause, not a start */
.load-card { margin-top: 26px; padding: 14px 20px 10px; background: var(--panel); border: 1px solid var(--line); border-radius: 14px; }
.load-card:empty, #loading.freeze .load-card { display: none; }
.load-card-note { margin: 8px 0 0; text-align: center; font-size: 12px; color: var(--muted); }
/* a block change mid-drive (main.js changeBlock): the loader over a still of the last frame, so the road is paused rather than gone */
#loading.freeze { background: rgba(15, 17, 21, 0.35); }
#loading .freeze-frame { position: absolute; inset: 0; width: 100%; height: 100%; z-index: -1; filter: brightness(0.5) saturate(0.6); }

/* start screen */
#start { position: fixed; inset: 0; background: var(--bg); z-index: 20; display: none; }
#start.show { display: block; }
.start-layout { display: grid; grid-template-columns: 360px 1fr; grid-template-rows: 100%; height: 100%; }
/* overflow-wrap: a street name longer than the column breaks rather than widening it (the column would scroll sideways otherwise) */
.start-side { padding: 18px; overflow: hidden; border-inline-end: 1px solid var(--line); display: flex; flex-direction: column; gap: 8px; min-height: 0; overflow-wrap: anywhere; }
.start-side .brand-row { margin: 2px 0 12px; } .start-side .brand img { width: 168px; }
.start-place { color: var(--muted); margin: -6px 0 2px; font-size: 14px; }
/* the tabs under the city line (overlays.js renderStartScreen): Routes, Custom route and, under an i at the end of the row, what this
   city is — drawn as the city picker's tabs are, the one showing underlined in the accent; a tab's body is the column's one scrolling
   part, so the chosen card and Start driving in the foot under it stay in reach whatever is up */
.start-tabs { display: flex; gap: 16px; margin-top: 2px; border-bottom: 1px solid var(--line); flex: 0 0 auto; }
.start-tabs button { margin-bottom: -1px; padding: 6px 2px 7px; border: none; border-bottom: 2px solid transparent; border-radius: 0; background: none; color: var(--muted); font-weight: 600; font-size: 13px; }
.start-tabs button:hover { color: var(--text); }
.start-tabs button[aria-selected="true"] { color: var(--text); border-bottom-color: var(--accent); }
.start-tabs button.info { margin-inline-start: auto; padding-inline: 3px; }
.start-tabs button.info svg { display: block; width: 18px; height: 18px; }
.start-tab { display: flex; flex-direction: column; gap: 8px; flex: 1 1 auto; min-height: 0; overflow: auto; padding-top: 4px; }
.start-tab[hidden] { display: none; }
.start-tab > h3:first-child { margin-top: 6px; }
.start-foot { display: flex; flex-direction: column; gap: 8px; flex: 0 0 auto; padding-top: 10px; border-top: 1px solid var(--line); }
.start-map { position: relative; min-height: 0; overflow: hidden; }
.start-map canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; cursor: crosshair; }
/* Quick drive (overlays.js renderStartScreen): the one button a first visit needs, its second line saying what it will do */
.quick { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; padding: 12px 14px; font-size: 17px; }
.quick small { text-align: left; font-size: 12px; font-weight: 400; color: #123; opacity: .85; }
/* the categories (setCategories): a 2 × 2 grid, the chosen one lit, "none here" under a kind the loaded area cannot offer */
.cats { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
.cats button { text-align: start; padding: 8px 10px; background: #171b23; border: 1px solid var(--line); border-radius: 8px; font-weight: 600; font-size: 13px; }
.cats button.on { border-color: var(--accent); background: #1b2536; }
.cats button small { display: block; font-weight: 400; font-size: 11px; color: var(--muted); }
.cats button:nth-child(odd):last-child { grid-column: 1 / -1; }   /* an odd last kind takes the whole last row rather than half of it (six kinds now: no odd one, kept for the next) */
.cat-blurb { font-size: 12px; color: var(--muted); margin: 0; }
/* Plan your own route: one search over streets and places, each row tagged with which it is; the stops as numbered rows
   with their own up / down / remove; the plan's route as a row like the offered ones. An empty list takes no room (nor
   the column's gap) */
#plan-search { width: 100%; }
.plan-results { display: flex; flex-direction: column; }
.plan-item { padding: 6px 8px; border-radius: 6px; cursor: pointer; display: flex; align-items: center; gap: 8px; }
.plan-item:hover { background: #1f2430; }
.plan-item .name { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.plan-item .sub { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kind-tag { font-size: 10px; text-transform: uppercase; letter-spacing: .5px; color: var(--muted); border: 1px solid var(--line); border-radius: 4px; padding: 0 4px; flex: 0 0 auto; }
.plan-stops { display: flex; flex-direction: column; gap: 4px; }
.plan-stop { display: flex; align-items: center; gap: 6px; background: #171b23; border: 1px solid var(--line); border-radius: 8px; padding: 4px 8px; font-size: 12.5px; }
.plan-stop b { width: 16px; color: var(--muted); font-weight: 600; }
.plan-stop span { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.plan-stop button { padding: 2px 7px; font-size: 12px; }
.plan-note { font-size: 12px; color: var(--muted); margin: 0; }
#plan-clear { align-self: flex-start; font-size: 12.5px; padding: 6px 10px; }
.plan-results:empty, .plan-stops:empty, .plan-status:empty { display: none; }
/* the suggested starts, under the plan on the Custom route tab */
.presets { display: flex; flex-wrap: wrap; gap: 6px; }
.presets button { font-size: 12.5px; padding: 6px 10px; }
.start-chosen { background: #171b23; border: 1px solid var(--line); border-radius: 8px; padding: 10px; min-height: 48px; }
/* the routes offered (overlays.js renderStartScreen setRoutes): a row per route with its colour, the selected one lit. The city's routes
   of a kind are dozens: the list gives way first when the tab is taller than the column (a scroll container's min-height is not its
   content's), down to a few rows, and scrolls inside; only past that does the tab itself scroll */
.routes { display: flex; flex-direction: column; gap: 4px; flex: 0 1 auto; min-height: 96px; overflow-y: auto; }
.route-item { display: flex; align-items: center; gap: 8px; text-align: start; padding: 6px 8px; background: #171b23; border: 1px solid var(--line); border-radius: 8px; }
.route-item:hover { background: #1f2430; }
.route-item.on { border-color: var(--accent); background: #1b2536; }
.route-item.hover { background: #202634; }   /* the pointer on the row, or on the route's line on the map (setHover) */
.route-item b { font-size: 13px; white-space: nowrap; }
.route-item span { font-size: 11.5px; color: var(--muted); flex: 1 1 auto; min-width: 0; }
.route-item .sw { width: 12px; height: 12px; border-radius: 50%; flex: 0 0 auto; }
#route-new { align-self: flex-start; font-size: 12.5px; padding: 6px 10px; }
/* the head of the start screen's and the city picker's side panel (overlays.js brandRowHtml): the lockup with the language dropdown
   (languagePickHtml) to its right — a small pill showing the current language alone, the browser's preferred one on a first visit */
.brand-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.brand-row .brand { margin: 0; }
.brand-row .brand img { display: block; }   /* the lockup's box is the picture itself: no line box under it, so centring the pill has the mark to go by */
/* the pill is centred on the wordmark, not the lockup: the mark is taller than the letters (the word spans 27–69 of the
   file's 81, its middle 9% of the height below the middle of the whole). Centred and then nudged down by half its own
   top margin — 6 px, the owner's setting — so it holds its place whatever height the lockup takes: a narrow column
   squeezes the lockup well under 38 px, and a fixed offset would leave the pill hanging below the letters. */
.brand-row .lang-pick { margin-top: 12px; }
/* field-sizing: the pill is as wide as the language showing in it, not as its widest option (overlays.js fitLanguagePick measures it where this is unknown) */
.lang-pick { field-sizing: content; padding: 3px 8px; font-size: 12px; color: var(--muted); background: #171b23; border: 1px solid var(--line); border-radius: 12px; cursor: pointer; flex: 0 0 auto; }
.lang-pick:hover, .lang-pick:focus-visible { border-color: var(--accent); color: var(--text); outline: none; }
/* the callout (setCallout): the chosen route's card beside its start on the map, its left edge in the route's colour;
   absolute over the canvas and only as big as itself, so the map around it still pans and zooms. The page places it. */
.map-callout { position: absolute; z-index: 2; background: var(--panel); border: 1px solid var(--line); border-inline-start: 4px solid var(--accent); border-radius: 10px; padding: 10px 12px; max-width: 260px; box-shadow: 0 8px 24px rgba(0,0,0,.45); font-size: 12.5px; overflow-wrap: anywhere; }
.map-callout > b { display: block; padding-inline-end: 20px; }
.map-callout .map-callout-close { position: absolute; top: 5px; inset-inline-end: 5px; width: 22px; height: 22px; padding: 0; border-radius: 50%; font-size: 14px; line-height: 1; }
.map-callout-actions { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.map-callout-actions button { padding: 5px 10px; font-size: 12.5px; }
.map-tip { position: absolute; z-index: 3; pointer-events: none; background: var(--panel); color: var(--text); border: 1px solid var(--line); border-radius: 6px; padding: 4px 8px; font-size: 12px; white-space: nowrap; box-shadow: 0 4px 12px rgba(0,0,0,.35); }
.map-tip.muted { color: var(--muted); }
.map-tip.warn { color: var(--text); border-color: var(--serious); border-inline-start-width: 4px; background: rgba(70, 20, 20, 0.92); white-space: normal; max-width: 260px; }

/* HUD */
#hud { position: fixed; inset: 0; pointer-events: none; display: none; z-index: 10; }
#hud.show { display: block; }
.hud-top-left { position: absolute; left: 16px; top: 14px; }
.hud-street { background: var(--panel); border-radius: 10px; padding: 8px 14px; font-size: 18px; font-weight: 600; display: flex; flex-direction: column; }
.hud-street #hud-street-uk { font-size: 12px; font-weight: 400; color: var(--muted); }
/* max-width: the junction line can carry a cue after it (tram rails that ask for a stop short of the line), and a
   single line of that runs a third of the way across the screen; it wraps under the street name instead. */
.hud-next { margin-top: 6px; background: var(--panel); border-radius: 8px; padding: 6px 12px; font-size: 13px; color: #d5dbe8; min-height: 16px; max-width: 42ch; }
.hud-next:empty { display: none; }
/* the turn-by-turn card of a guided drive (hud.js setNav): the arrow beside the distance, the verb, the street and the
   "then" line, the way left along the foot. Its left border is the route's colour — the one the start map drew the
   route in — so the line on the map and the card that drives it read as one thing; the limit disc follows in the flow. */
.hud-nav { display: none; margin-top: 6px; background: var(--panel); border-radius: 10px; padding: 8px 12px; min-width: 220px; max-width: 42ch; border-inline-start: 6px solid var(--accent); }
.hud-nav.show { display: grid; grid-template-columns: 44px 1fr; grid-template-rows: auto auto; column-gap: 10px; align-items: center; }
.nav-arrow { width: 44px; height: 44px; }
.nav-arrow svg { width: 100%; height: 100%; }
.nav-dist { font-size: 20px; font-weight: 700; line-height: 1.1; font-variant-numeric: tabular-nums; }
.nav-what { font-size: 14px; font-weight: 600; }
.nav-street { font-size: 12.5px; color: #d5dbe8; }
.nav-then { font-size: 12px; color: var(--muted); display: flex; align-items: center; gap: 4px; margin-top: 2px; }
.nav-then:empty { display: none; }
.nav-then svg { width: 16px; height: 16px; }
.nav-foot { grid-column: 1 / -1; font-size: 11.5px; color: var(--muted); margin-top: 4px; border-top: 1px solid var(--line); padding-top: 4px; }
.nav-foot:empty { display: none; }
.nav-foot.off { color: var(--minor); }
/* in the flow under the street and the junction line, not at a fixed 96px: the junction line wraps to two when it
   carries the tram-rails cue, and a fixed disc was overlapped by it */
.hud-limit { margin-top: 10px; width: 62px; height: 62px; border-radius: 50%; background: #fff; border: 7px solid #d21e2c; display: flex; align-items: center; justify-content: center; color: #111; font-weight: 800; font-size: 22px; }
.hud-limit.over { box-shadow: 0 0 0 4px rgba(255, 60, 60, 0.6); animation: pulse 0.8s infinite alternate; }
@keyframes pulse { to { box-shadow: 0 0 0 8px rgba(255, 60, 60, 0.15); } }
.hud-bottom-left { position: absolute; left: 16px; bottom: 16px; background: var(--panel); border-radius: 12px; padding: 12px 16px; min-width: 260px; }
.hud-speed { font-size: 46px; font-weight: 700; line-height: 1; font-variant-numeric: tabular-nums; }
.hud-speed small { font-size: 14px; margin-inline-start: 6px; color: var(--muted); font-weight: 400; }
.hud-rpm { height: 6px; background: #2a2f3a; border-radius: 3px; margin: 8px 0; overflow: hidden; }
.hud-rpm div { height: 100%; width: 0; background: linear-gradient(90deg, #3ccf6e, #ffd24b 70%, #ff3b3b); }
.hud-selector { display: flex; gap: 6px; margin: 6px 0; }
.hud-selector span { width: 30px; height: 30px; border-radius: 6px; background: #1b1f27; display: flex; align-items: center; justify-content: center; font-weight: 700; color: var(--muted); }
.hud-selector span.on { background: var(--transmission); color: #fff; }
.hud-selector span.on[data-g="R"] { background: #ffb300; color: #1a1200; transform: scale(1.25); }   /* R: big and amber, as the cluster draws it (render/cockpit-display.js) */
#hud.cabin .hud-bottom-left { display: none; }   /* from the driver's seat the cluster on the cabin display is right there (ui/hud.js setCabin) */
.hud-lamps { display: flex; gap: 8px; align-items: center; margin-top: 4px; }
.lamp { font-size: 12px; font-weight: 700; color: #3b4150; padding: 2px 4px; border-radius: 4px; }
.lamp.on { color: #6fdc8c; } .lamp.dipped { color: #7ee36a; } .lamp.warn { color: #ff4d4d; } .lamp.blue { color: #59a8ff; }
.lamp.ind { font-size: 16px; } .lamp.ind.on { color: #6fdc8c; text-shadow: 0 0 8px #6fdc8c; }
.hud-bottom-right { position: absolute; right: 16px; bottom: 16px; display: flex; flex-direction: column; align-items: flex-end; gap: 6px; }
#hud-minimap { width: 220px; height: 220px; border-radius: 50%; border: 3px solid rgba(255,255,255,0.25); background: #ddd; }
.hud-session { background: var(--panel); border-radius: 8px; padding: 5px 10px; font-size: 12px; color: var(--muted); }
.hud-keys { position: absolute; right: 16px; top: 14px; color: var(--muted); font-size: 12px; background: var(--panel); padding: 5px 10px; border-radius: 8px; }
/* the offer beside the cursor while a click on the road would give the mouse the wheel (main.js offerWheel; hud.js
   showTip places it): the cursor itself is a pointer over the road then (#view.offer), and nothing where the mouse
   has the wheel, since there is no cursor under pointer lock */
.hud-tip { position: absolute; display: none; background: var(--panel); border-radius: 8px; padding: 5px 10px; font-size: 12.5px; white-space: nowrap; box-shadow: 0 4px 14px rgba(0, 0, 0, 0.4); }
.hud-tip.show { display: block; }
#view.offer canvas { cursor: pointer; }
.hud-toasts { position: absolute; left: 50%; top: 14px; transform: translateX(-50%); width: min(560px, 60vw); display: flex; flex-direction: column; gap: 8px; }
.toast { background: var(--panel); border-inline-start: 6px solid var(--minor); border-radius: 10px; padding: 10px 14px; animation: drop 0.25s ease-out; }
.toast.serious { border-inline-start-color: var(--serious); } .toast.dangerous { border-inline-start-color: var(--dangerous); background: rgba(70, 20, 20, 0.92); }
.toast-title { font-weight: 700; font-size: 15px; } .toast-what { color: #d9dde8; font-size: 13px; } .toast-advice { color: #9fd0ff; font-size: 13px; margin-top: 2px; }
@keyframes drop { from { transform: translateY(-10px); opacity: 0; } }
.hud-hint { position: absolute; left: 50%; bottom: 24px; transform: translateX(-50%); background: rgba(30, 60, 90, 0.92); border-radius: 10px; padding: 8px 14px; font-size: 13.5px; max-width: 60vw; opacity: 0; transition: opacity .3s; }
.hud-hint.show { opacity: 1; }
/* The steering strip. A wheel that holds its angle needs its angle shown: the bright mark is the driver's hand,
   the dim bar behind it is how much steering that is actually buying at this speed, and the tick is dead centre. */
.hud-steer { position: absolute; left: 50%; bottom: 96px; transform: translateX(-50%); width: 266px; text-align: center; }
/* the pedals at either end of the strip: the car's own pedal travel (car.brake, car.throttle), whichever hand is on
   them — ↑ ↓, or the mouse's left and right buttons while it has the wheel. Red is the brake and green the
   accelerator here, on the controls card and on the mouse it draws, so none of the three needs a legend. */
.steer-row { display: flex; align-items: center; gap: 8px; }
.steer-track { flex: 1; }
.pedal { position: relative; width: 9px; height: 26px; border-radius: 4px; background: rgba(20, 23, 30, 0.72); border: 1px solid var(--line); overflow: hidden; }
.pedal i { position: absolute; left: 0; right: 0; bottom: 0; height: 0; }
.pedal.brake i { background: var(--serious); } .pedal.throttle i { background: var(--ok); }
.steer-track { position: relative; height: 10px; border-radius: 5px; background: rgba(20, 23, 30, 0.72); border: 1px solid var(--line); overflow: hidden; }
.steer-centre { position: absolute; left: 50%; top: 1px; bottom: 1px; width: 2px; margin-left: -1px; background: rgba(232, 234, 240, 0.5); }
.steer-lock { position: absolute; top: 2px; bottom: 2px; background: rgba(33, 150, 214, 0.5); border-radius: 2px; }
.steer-hand { position: absolute; top: -2px; bottom: -2px; width: 4px; margin-left: -2px; background: var(--steer); border-radius: 2px;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.5); }
.steer-hand.centred { background: var(--ok); }
/* one line, centred under the strip even when it is wider than the strip: a wrapped note pushed the strip up under the card */
.steer-note { position: relative; left: 50%; transform: translateX(-50%); width: max-content; max-width: 90vw; margin-top: 5px; font-size: 12px; color: var(--muted); text-shadow: 0 1px 3px rgba(0, 0, 0, 0.8); }
.steer-note:empty { display: none; }
/* the controls at a glance (ui/controls-card.js): above the strip for the first half minute of a session's first
   drive, with a × (usable only while there is a cursor, i.e. the mouse is not the wheel) and a thin bar running
   down; then the one line that stands in its place until Tab has been pressed once. The same card, without the
   chrome, heads the controls sheet (.ctl-panel-card). */
.hud-card { position: absolute; left: 50%; bottom: 160px; transform: translateX(-50%); display: none; pointer-events: auto; background: var(--panel); border: 1px solid var(--line); border-radius: 14px; padding: 12px 18px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.45); }
.hud-card.show { display: block; animation: drop 0.25s ease-out; }
.hud-card-foot { margin-top: 6px; text-align: center; font-size: 12px; color: var(--muted); }
.hud-card-close { position: absolute; top: 6px; right: 6px; width: 24px; height: 24px; padding: 0; border-radius: 50%; font-size: 15px; line-height: 1; }
.hud-card-timer { position: absolute; left: 14px; right: 14px; bottom: 4px; height: 2px; background: var(--accent); border-radius: 1px; transform-origin: left; }
.hud-card-note { position: absolute; left: 50%; bottom: 160px; transform: translateX(-50%); background: var(--panel); border-radius: 8px; padding: 5px 10px; font-size: 12.5px; color: var(--muted); white-space: nowrap; }
.hud-card-note:empty { display: none; }
.ctl-card { display: flex; align-items: center; gap: 24px; }
.ctl-mouse { display: block; font-family: inherit; }
.ctl-keys { display: flex; flex-direction: column; align-items: center; gap: 5px; }
.ctl-krow { display: flex; gap: 5px; }
.cap { width: 42px; height: 42px; border-radius: 8px; background: #1c2029; border: 1px solid #3a4150; display: flex; flex-direction: column; align-items: center; justify-content: center; font-weight: 700; font-size: 17px; line-height: 1; color: var(--text); }
.cap small { font-size: 9.5px; font-weight: 600; margin-top: 2px; opacity: 0.8; }
.cap.go { background: var(--ok); color: #06200f; border-color: transparent; } .cap.brake { background: var(--serious); color: #fff; border-color: transparent; } .cap.steer { background: var(--steer); color: #e8f4ff; border-color: transparent; }
.cap.transmission { background: var(--transmission); color: #eafff2; border-color: transparent; font-size: 13px; } .cap.wide { width: 136px; } .cap.wide small { font-size: 9px; }
/* the indicators, in the signals colour: a drawn key, because they are graded in both modes (rules/catalog.js).
   The pair spans the same width as the three steering keys above it, so the cluster stays a rectangle. */
.cap.signals { background: var(--signals); color: #2a1a02; border-color: transparent; } .cap.signals small { opacity: 0.85; }
.cap.pair { width: 65.5px; }
.ctl-legend { display: flex; gap: 12px; font-size: 11.5px; color: var(--muted); margin-top: 3px; }
.ctl-more { font-size: 11px; color: var(--muted); }
.ctl-panel-card { display: flex; justify-content: center; margin: 8px 0 4px; }
/* the key that does the same as a button, after its label: Controls [Tab], Close [Esc] */
.key-hint { display: inline-block; margin-inline-start: 8px; padding: 1px 6px; border-radius: 4px; background: #1b1f27; border: 1px solid #3a4150; font-size: 11px; color: var(--muted); vertical-align: 1px; }
/* the offer that appears when the car is wedged (vehicle/recovery.js); clickable, so the key is never the only way */
.hud-stuck { position: absolute; left: 50%; bottom: 68px; transform: translateX(-50%); display: none; pointer-events: auto;
  background: var(--minor); color: #21160a; border: none; border-radius: 10px; padding: 9px 16px; font-size: 13.5px; font-weight: 600;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.45); animation: pulse-stuck 1.4s infinite alternate; }
.hud-stuck.show { display: block; }
.hud-stuck:hover { background: #ffc25a; border: none; }
@keyframes pulse-stuck { to { box-shadow: 0 6px 18px rgba(0, 0, 0, 0.45), 0 0 0 7px rgba(232, 160, 32, 0.18); } }
#replay-banner { position: fixed; left: 50%; top: 14px; transform: translateX(-50%); background: #4a2a80; padding: 8px 16px; border-radius: 10px; z-index: 12; display: none; }
#replay-banner.show { display: block; }

/* overlays */
#overlay { position: fixed; inset: 0; background: rgba(5, 8, 14, 0.55); z-index: 30; display: none; align-items: center; justify-content: center; padding: 20px; }
#overlay.show { display: flex; }
.panel { background: #141821; border: 1px solid var(--line); border-radius: 14px; padding: 18px 22px; max-height: 92vh; overflow: auto; box-shadow: 0 20px 60px rgba(0,0,0,0.5); }
.panel-head { display: flex; justify-content: space-between; align-items: center; gap: 12px; }
.menu-panel { width: 420px; }
.menu-buttons { display: flex; flex-direction: column; gap: 8px; }
.settings { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 14px; }
.settings label { display: flex; flex-direction: column; gap: 3px; font-size: 12.5px; color: var(--muted); }
.report-panel { width: min(1000px, 94vw); }
.report-summary { display: flex; align-items: center; gap: 16px; padding: 12px 16px; border-radius: 10px; margin: 8px 0 12px; background: #1b2a1f; }
.report-summary.fail { background: #2c1a1a; }
.report-summary .big { font-size: 28px; font-weight: 800; color: var(--ok); }
.report-summary.fail .big { color: var(--serious); }
table.faults { width: 100%; border-collapse: collapse; font-size: 13px; }
table.faults th { text-align: start; color: var(--muted); font-weight: 600; padding: 6px 8px; border-bottom: 1px solid var(--line); }
table.faults td { padding: 8px; border-bottom: 1px solid #1f242e; vertical-align: top; }
table.faults tr.minor .sev { color: var(--minor); } table.faults tr.serious .sev { color: var(--serious); } table.faults tr.dangerous .sev { color: var(--dangerous); }
.report-foot { display: flex; justify-content: flex-end; gap: 8px; margin-top: 12px; }

/* controls diagram */
.controls-panel { width: min(900px, 96vw); }
.keyboard { display: flex; flex-direction: column; gap: 5px; margin: 10px 0; }
.kb-row { display: flex; gap: 5px; }
.key { width: 56px; height: 50px; background: #1c2029; border-radius: 6px; padding: 4px 5px; position: relative; font-size: 10px; color: #6b7387; display: flex; flex-direction: column; justify-content: space-between; }
.key.wide { width: 84px; } .key.space { width: 340px; }
.key-label { font-weight: 700; font-size: 11px; } .key-name { color: #fff; font-size: 10.5px; line-height: 1.15; }
/* the keys by group (vehicle/controls.js): the card's colours (.cap above), so the two pictures read as one */
.key.go { background: var(--ok); color: #06200f; } .key.go .key-name { color: #06200f; } .key.brake { background: var(--serious); color: #fff; } .key.steer { background: var(--steer); color: #e8f4ff; }
.key.transmission { background: var(--transmission); color: #eafff2; } .key.signals { background: var(--signals); color: #1a1200; } .key.signals .key-name { color: #1a1200; } .key.other { background: var(--other); color: #f3ecff; }
.legend { display: flex; gap: 18px; font-size: 12.5px; color: var(--muted); }
.legend .sw, .ctl-legend .sw { display: inline-block; width: 12px; height: 12px; border-radius: 3px; margin-inline-end: 6px; vertical-align: -1px; }
.sw.go { background: var(--ok); } .sw.brake { background: var(--serious); } .sw.steer { background: var(--steer); } .sw.transmission { background: var(--transmission); } .sw.signals { background: var(--signals); } .sw.other { background: var(--other); }

/* ---- simple mode: the four-key drive (controls.js SIMPLE_BINDINGS) */
#hud.simple .hud-rpm, #hud.simple #lamp-engine, #hud.simple #lamp-hb, #hud.simple #lamp-lights,
#hud.simple #lamp-high, #hud.simple #lamp-hazard, #hud.simple #lamp-wipers { display: none; }
.simple-keys { display: flex; flex-direction: column; gap: 6px; margin: 10px 0; }
.simple-keys div { display: flex; align-items: baseline; gap: 10px; }
.simple-keys b { background: #1c2029; color: var(--text); border-radius: 6px; padding: 4px 9px; font-size: 14px; }
.simple-keys b.go { background: var(--ok); color: #06200f; } .simple-keys b.brake { background: var(--serious); color: #fff; } .simple-keys b.transmission { background: var(--transmission); color: #eafff2; }
.simple-keys b.signals { background: var(--signals); color: #2a1a02; } .simple-keys b.other { background: var(--other); color: #f3ecff; }
.simple-keys span { color: #d9dde8; font-size: 13.5px; }
.settings label.wide { grid-column: 1 / -1; }

/* the start screen's way back to the city picker, and the loaded-area line (src/ui/overlays.js renderStartScreen) */
.start-place button.link { background: none; border: none; padding: 0 0 0 4px; color: var(--accent); font-size: 13px; text-decoration: underline; text-underline-offset: 2px; }
.start-place button.link:hover { color: #fff; }

/* the city picker (src/ui/city-map.js): the world map with a marker on every built city, the list of them beside it */
#cities { position: fixed; inset: 0; background: var(--bg); z-index: 20; display: none; }
#cities.show { display: block; }
.cities-layout { display: grid; grid-template-columns: clamp(240px, 23vw, 310px) minmax(0, 1fr); grid-template-rows: 100%; height: 100%; }
.cities-side { padding: 18px; overflow: auto; border-inline-end: 1px solid var(--line); display: flex; flex-direction: column; gap: 8px; min-height: 0; }
.cities-side .brand-row { margin: 2px 0 14px; } .cities-side .brand img { width: 168px; }
.cities-side .brand { flex: 1; min-width: 0; } .cities-side .brand img { max-width: 100%; }
.cities-lead { font-size: 18px; font-weight: 600; margin: 0; }
/* what this is, on the first visit only (city-map.js firstVisit): the tagline over one line of explanation */
/* the column under the search: for someone new the four reasons to practise (ui/city-map.js BENEFITS: an icon, a title, a line each)
   with a × in the corner; after UI.benefitsUntilDrives drives or that ×, two tabs — the cities driven lately and the recommended ones,
   or every city by country. A search in progress shows the matches whatever was up; [hidden] must win over the flex displays below */
.cities-benefits { position: relative; margin: 4px 0 2px; padding: 12px 12px 4px; padding-inline-end: 30px; background: #141821; border: 1px solid var(--line); border-radius: 12px; }
.cities-benefits ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 12px; }
.cities-benefits li { display: flex; gap: 10px; align-items: flex-start; }
.cities-benefits svg { flex: 0 0 auto; width: 26px; height: 26px; margin-top: 1px; color: var(--accent); }
.cities-benefits b { display: block; font-size: 13.5px; }
.cities-benefits li span { display: block; font-size: 12px; line-height: 1.35; color: var(--muted); }
.cities-benefits-close { position: absolute; top: 6px; inset-inline-end: 6px; width: 24px; height: 24px; padding: 0; border: none; border-radius: 6px; background: none; color: var(--muted); font-size: 18px; line-height: 1; }
.cities-benefits-close:hover, .cities-benefits-close:focus-visible { color: var(--text); background: #1f2430; outline: none; }
.cities-tabs { display: flex; gap: 16px; margin-top: 2px; border-bottom: 1px solid var(--line); }
.cities-tabs button { margin-bottom: -1px; padding: 6px 2px 7px; border: none; border-bottom: 2px solid transparent; border-radius: 0; background: none; color: var(--muted); font-weight: 600; font-size: 13px; }
.cities-tabs button:hover { color: var(--text); }
.cities-tabs button[aria-selected="true"] { color: var(--text); border-bottom-color: var(--accent); }
.cities-suggested { display: flex; flex-direction: column; min-height: 120px; overflow: auto; flex: 1; }
.cities-suggested h3:first-child { margin-top: 6px; }
.city-row { display: block; width: 100%; text-align: start; padding: 5px 8px; border: none; border-radius: 6px; background: none; }
.city-row:hover, .city-row:focus-visible { background: #1f2430; outline: none; }
.city-row span { display: block; font-size: 11.5px; color: var(--muted); }
/* the two links at the foot of the column, a line each: the labels are long in several languages and never fit side by side */
.cities-foot { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; margin-top: auto; padding-top: 8px; }
.cities-why { font-size: 12.5px; color: var(--accent); text-decoration: none; }
.cities-why:hover, .cities-why:focus-visible { text-decoration: underline; text-underline-offset: 2px; }
.cities-why .ext { display: inline-block; width: 12px; height: 12px; margin-inline-start: 4px; vertical-align: -1px; }
[dir="rtl"] .cities-why .ext { transform: scaleX(-1); }
.cities-mail { font-size: 12.5px; color: var(--accent); text-decoration: none; white-space: nowrap; }
.cities-mail:hover, .cities-mail:focus-visible { text-decoration: underline; text-underline-offset: 2px; }
.cities-benefits[hidden], .cities-suggested[hidden], .cities-list[hidden] { display: none; }
#city-search { width: 100%; margin-top: 6px; }
.cities-list { display: flex; flex-direction: column; min-height: 120px; overflow: auto; flex: 1; }
.cities-country h3 { margin: 10px 0 3px; }
.cities-country button { display: block; width: 100%; text-align: start; background: none; border: none; border-radius: 6px; padding: 5px 8px; }
.cities-country button:hover, .cities-country button:focus-visible { background: #1f2430; outline: none; }
.cities-country button[hidden], .cities-country[hidden] { display: none; }
.cities-map { position: relative; min-height: 0; overflow: hidden; background: #0b1420; }   /* the sea */
.world { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.world .land path { fill: #182331; fill-rule: evenodd; stroke: #293a4a; stroke-width: 0.8px; stroke-linejoin: round; }
.world .leaders path, .world .tip path { fill: none; stroke: #6a8395; stroke-width: 0.75px; opacity: 0.65; pointer-events: none; }
/* A city: one disc and a label, packed by city-map-layout.js, which also picks the font size (set on the svg: 12 px on a
   wide desktop, 11 px otherwise) and the disc radius (4.5 px, 3.5 compact). Desktop names are all visible; compact views
   show the rest in the tip layer on hover or keyboard/list focus. The unseen .hit circle behind the disc, and the name
   while it shows, take the click too. B and C names (the registry's priority) are a shade quieter than A names. */
.world .city { cursor: pointer; outline: none; }
.world .city circle { fill: var(--accent); stroke: #0b1420; stroke-width: 1.5px; }
.world .city circle.hit { fill: transparent; stroke: none; }
.world text { fill: #e8eaf0; dominant-baseline: central; paint-order: stroke; stroke: #0b1420; stroke-width: 3px; stroke-linejoin: round; }
.world .city.priority-B text, .world .city.priority-C text { opacity: 0.88; }
.world .city:hover text, .world .city:focus text, .world .city.hot text { fill: #fff; opacity: 1; }
.world .city.unlabelled text { opacity: 0; pointer-events: none; }
.world .city:hover circle:not(.hit), .world .city:focus circle:not(.hit), .world .city.hot circle:not(.hit) { r: 7; fill: #fff; }
.world .city.featured circle:not(.hit) { stroke: #fff; stroke-width: 2.5px; }
/* the card at the top of the map (city-map.js setFeatured): the city to drive without aiming at its marker — the one
   driven last time, else the nearest to where the visitor is (functions/api/geo.js); no card when neither is known */
.cities-featured { position: absolute; left: 50%; top: 14px; transform: translateX(-50%); max-width: calc(100% - 28px); }
.cities-featured:empty { display: none; }
.cities-featured button { display: flex; flex-direction: column; align-items: center; gap: 1px; min-width: 220px; padding: 10px 24px; border-radius: 12px; box-shadow: 0 6px 24px rgba(0, 0, 0, 0.45); }
.cities-featured button:hover, .cities-featured button:focus-visible { background: #fff; outline: none; }
.cities-featured button b { font-size: 18px; white-space: nowrap; }
.cities-featured button span { font-size: 12px; font-weight: 400; opacity: 0.75; }
/* the hovered marker's name when its own label is hidden, in the slot the layout kept for it: one text above every disc (city-map.js tip) */
.world .tip { display: none; }
.world .tip.show { display: block; }
.world .tip a { cursor: pointer; }
.world .tip rect { fill: #0b1420; stroke: #6a8395; stroke-width: 0.7px; }
.world .tip text { fill: #fff; font-weight: 600; }
@media (max-width: 720px) { .cities-layout { grid-template-columns: 1fr; grid-template-rows: 38% 62%; } .cities-side { border-inline-end: none; border-bottom: 1px solid var(--line); } .cities-list { min-height: 60px; } }
