:root {
  --ink: #2a3140;
  --ink-soft: #5d6677;
  --glass: rgb(250 248 243 / 0.55);
  --glass-edge: rgb(255 255 255 / 0.65);
  --halo: 0 1px 10px rgb(255 255 255 / 0.55);
  --scrim: rgb(246 244 238 / 0.1);
  --green: #78be20;
  --accent: #1d3f8f;
  --serif: 'Instrument Serif', 'Iowan Old Style', Georgia, serif;
  --sans: 'DM Sans', system-ui, sans-serif;
}

.app[data-phase="night"] {
  --ink: #eef0fa;
  --ink-soft: #b6bcd6;
  --glass: rgb(22 26 50 / 0.45);
  --glass-edge: rgb(160 170 220 / 0.2);
  --halo: 0 1px 12px rgb(0 0 20 / 0.6);
  --scrim: rgb(8 10 30 / 0.55);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
  overflow: hidden;
  background: #e3edf1;
  color: var(--ink);
  font-family: var(--sans);
  -webkit-font-smoothing: antialiased;
}

button { font: inherit; color: inherit; cursor: pointer; }
a { color: inherit; }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }

.app { position: fixed; inset: 0; color: var(--ink); } /* here, not on body, so night colours apply */
/* A game, not a page: no double-tap zoom, no text selection, no long-press
   callouts or tap flashes, except where you type. */
html, body, .app { touch-action: pan-x pan-y; -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
.app { -webkit-touch-callout: none; -webkit-tap-highlight-color: transparent; }
@media (pointer: coarse) { .app { -webkit-user-select: none; user-select: none; } }
.app input, .app textarea { -webkit-user-select: text; user-select: text; -webkit-touch-callout: default; }
.scene { position: absolute; inset: 0; }
.scene canvas { display: block; width: 100%; height: 100%; touch-action: none; }
.vignette {
  position: absolute; inset: 0; pointer-events: none;
  background:
    linear-gradient(180deg, var(--scrim) 0%, transparent 9%, transparent 93%, var(--scrim) 100%),
    radial-gradient(ellipse at 50% 45%, transparent 58%, rgb(30 30 60 / 0.14) 100%);
}

/* Fade in when ready; fade away when the pointer rests. */
.ui, .labels { transition: opacity 1.6s ease; }
body:not(.ready) .ui { opacity: 0; }
/* Loading train (index.html): runs along a stretch of green line under the
   centred logo, pausing at the middle station, then fades out when ready. */
.loader {
  position: absolute; left: 50%; top: calc(44% + 64px); width: min(300px, 78vw); transform: translateX(-50%);
  display: flex; flex-direction: column; align-items: center; gap: 10px; pointer-events: none;
  transition: opacity 0.6s ease;
}
body.ready .loader { opacity: 0; visibility: hidden; transition: opacity 0.6s ease, visibility 0s linear 0.6s; }
.loader-track { position: relative; width: 100%; height: 44px; overflow: hidden; }
.loader-track::before {
  content: ''; position: absolute; left: 0; right: 0; bottom: 4px; height: 4px; border-radius: 2px;
  background: #78be20; box-shadow: 0 0 0 2px #10150c;
}
.loader-stop {
  position: absolute; bottom: 1px; width: 10px; height: 10px; margin-left: -5px; border-radius: 50%;
  background: #fbfaf6; box-shadow: 0 0 0 2px #10150c; z-index: 1;
}
.loader-train {
  position: absolute; left: 0; bottom: 8px; width: 110px; height: auto; z-index: 2;
  animation: loader-run 4.2s cubic-bezier(0.45, 0, 0.55, 1) infinite, loader-bob 0.36s ease-in-out infinite;
}
.loader-wheels circle { transform-box: fill-box; transform-origin: center; }
/* In from the left, a stop at the middle station, out to the right. */
@keyframes loader-run {
  0% { translate: -120px 0; }
  38%, 58% { translate: calc(min(300px, 78vw) / 2 - 55px) 0; }
  100% { translate: calc(min(300px, 78vw) + 20px) 0; }
}
@keyframes loader-bob { 50% { transform: translateY(-1px); } }
@media (prefers-reduced-motion: reduce) {
  .loader-train { animation: none; translate: calc(min(300px, 78vw) / 2 - 55px) 0; }
}

/* Loading: the logo shows alone, centred and breathing (index.html places
   it), then glides into its corner as the rest of the interface fades in. */
body.logo-intro:not(.ready) .title { opacity: 1; }
body.logo-intro:not(.ready) .title .place { opacity: 0; }
body.logo-intro .title .place { transition: opacity 1.2s ease 0.5s; }
body.logo-intro .logo { transform-origin: center; transition: transform 1.1s cubic-bezier(0.65, 0, 0.25, 1); }
body.logo-intro:not(.ready) .logo { transition: none; animation: logo-breathe 2.4s ease-in-out infinite; }
@keyframes logo-breathe { 50% { opacity: 0.72; } }
@media (prefers-reduced-motion: reduce) {
  body.logo-intro:not(.ready) .logo { animation: none; }
  body.logo-intro .logo { transition-duration: 0.01s; }
}
body.ui-hidden .ui, body.ui-hidden .labels { opacity: 0 !important; pointer-events: none; }
/* Cinematic mode (src/cinema.js): no interface, letterbox bars. Any touch or key ends it. */
body.cinematic .ui, body.cinematic .labels { opacity: 0 !important; pointer-events: none !important; }
.app::before, .app::after {
  content: ''; position: absolute; left: 0; right: 0; height: 9vh; background: #05060a; z-index: 50;
  pointer-events: none; transform: scaleY(0); transition: transform 0.9s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.app::before { top: 0; transform-origin: top; }
.app::after { bottom: 0; transform-origin: bottom; }
body.cinematic .app::before, body.cinematic .app::after { transform: scaleY(1); }
/* Phones and touch screens keep the whole (small) screen for the picture. */
@media (max-width: 700px), (pointer: coarse) {
  .app::before, .app::after { display: none; }
}
body.cinematic.cinema-film #scene canvas { filter: contrast(1.08) saturate(1.15); }
/* Attract mode (idle on the start screen): the logo and prompt in the
   bottom third, over the cinematic shots, like an old game's demo. */
.attract {
  position: absolute; inset: 0; z-index: 60; display: flex; flex-direction: column; align-items: center; justify-content: flex-end;
  gap: 14px; padding: 0 16px 11vh; pointer-events: none; opacity: 0; transition: opacity 0.8s ease;
}
body.attract-mode .attract { opacity: 1; }
.attract-logo { width: min(400px, 78vw); height: auto; filter: drop-shadow(0 4px 18px rgb(0 0 0 / 0.45)); }
.attract-start {
  margin: 0; color: #fff; font: italic 700 clamp(16px, 2.4vw, 22px) var(--display); letter-spacing: 0.02em;
  text-shadow: 0 2px 0 #10150c, 0 0 12px rgb(0 0 0 / 0.6);
}
.attract-tap { display: none; }
@media (pointer: coarse) { .attract-click { display: none; } .attract-tap { display: inline; } }
body.cinematic.cinema-film .vignette { background: radial-gradient(ellipse at 50% 50%, transparent 45%, rgb(8 8 16 / 0.45) 100%); }
/* Cinematic mode with the interface on: the followed train, where it is and
   the conditions, set low on the left like a film's title card. */
.cine-card {
  position: absolute; left: max(16px, 4.5vw, env(safe-area-inset-left)); bottom: calc(9vh + 26px); z-index: 55;
  max-width: min(520px, calc(100vw - 32px));
  color: #fff; text-shadow: 0 1px 2px rgb(0 0 0 / 0.55), 0 0 18px rgb(0 0 0 / 0.4);
  pointer-events: none; opacity: 0; transform: translateY(6px);
  transition: opacity 0.5s ease, transform 0.5s ease;
}
body.cinematic:not(.ui-hidden):not(.attract-mode) .cine-card.has-train {
  opacity: 1; transform: none; transition: opacity 1.4s ease 1.2s, transform 1.4s cubic-bezier(0.2, 0.8, 0.2, 1) 1.2s;
}
.cine-card p { margin: 0; }
.cine-train { font: 500 13px/1 var(--sans); letter-spacing: 0.02em; opacity: 0.78; }
.cine-terminus { margin-top: 7px !important; font: italic 700 clamp(26px, 3.4vw, 40px)/1.05 var(--display); letter-spacing: 0.01em; }
.cine-station { margin-top: 5px !important; font: 400 clamp(15px, 1.5vw, 18px)/1.25 var(--sans); opacity: 0.92; }
.cine-meta { margin-top: 10px !important; font: 500 12px/1 var(--sans); letter-spacing: 0.02em; opacity: 0.72; font-variant-numeric: tabular-nums; }
@media (max-width: 700px), (pointer: coarse) {
  .cine-card { bottom: calc(22px + env(safe-area-inset-bottom)); }
  .cine-terminus { font-size: 24px; }
  .cine-station { font-size: 14px; }
}
body.ui-hidden .tools { opacity: 0.3 !important; pointer-events: auto; }
/* With the interface hidden, only the settings and show-interface buttons
   remain (faintly), and anything opened from them shows in full. */
body.ui-hidden .tools .tool:not(#settings-button):not(#hide) { display: none; }
body.ui-hidden .settings:not([hidden]), body.ui-hidden .light-menu:not([hidden]) { opacity: 1 !important; pointer-events: auto; }
body.ui-hidden .ride-controls { opacity: 1 !important; pointer-events: auto; }
body.ui-hidden .ride-actions { opacity: 0.35 !important; }
body.ui-hidden .ride-action { pointer-events: auto; }
body.ui-hidden .ride-stick {
  opacity: 0.35;
  pointer-events: auto;
  transition: opacity 0.2s ease;
}
body.ui-hidden .ride-stick:hover {
  opacity: 0.85;
}
body.ui-hidden .ride-stick.is-pressed {
  opacity: 0.85;
  transition: none;
}
body.ui-hidden .seat-prompt.is-visible { opacity: 0.85 !important; pointer-events: auto; }

.title { position: absolute; top: 30px; left: 34px; pointer-events: none; text-shadow: var(--halo); }
.title h1 { margin: 0; line-height: 0; }
.logo { width: 272px; height: auto; filter: drop-shadow(0 2px 8px rgb(20 30 50 / 0.18)); }
.place {
  position: relative; display: flex; border: 0; font: inherit; cursor: pointer; pointer-events: auto;
  transition: transform 0.2s ease, box-shadow 0.2s ease;
  width: 190px; min-height: 81px; margin-top: 8px; padding: 4px 10px 7px;
  background: #00005c; color: #fff; text-align: center; text-shadow: none;
  display: flex; flex-direction: column; justify-content: center; opacity: 0;
}
.place.show { animation: place-in 1.8s ease forwards; }
.place { box-shadow: 0 6px 18px rgb(0 0 60 / 0.22); padding-bottom: 20px; }
.place:hover, .place[aria-expanded="true"] { transform: translateY(-1px); box-shadow: 0 9px 24px rgb(0 0 60 / 0.3); }
.place:focus-visible { outline: 2px solid var(--green); outline-offset: 3px; }
.place-change {
  position: absolute; left: 0; right: 0; bottom: 0; height: 17px; display: flex; align-items: center; justify-content: center; gap: 3px;
  background: rgb(255 255 255 / 0.14); color: #dfe4ff; font: 600 9px/1 var(--sans); letter-spacing: 0.02em;
}
.place-change svg { width: 10px; height: 10px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; transition: transform 0.2s; }
.place[aria-expanded="true"] .place-change svg { transform: rotate(180deg); }
.station-menu {
  position: absolute; top: calc(100% + 6px); left: 0; width: 260px; max-height: min(420px, 62vh, 62dvh); overflow: auto; padding: 5px;
  border: 1px solid var(--glass-edge); border-radius: 12px; background: var(--glass); pointer-events: auto;
  backdrop-filter: blur(18px) saturate(1.2); -webkit-backdrop-filter: blur(18px) saturate(1.2); box-shadow: 0 12px 34px rgb(20 30 60 / 0.2);
  text-shadow: none;
}
.station-menu[hidden] { display: none; }
.station-option {
  display: flex; align-items: center; gap: 9px; width: 100%; padding: 5px 7px; border: 0; border-radius: 8px;
  background: transparent; text-align: left;
}
.station-option:hover, .station-option:focus-visible { background: rgb(255 255 255 / 0.45); outline: none; }
.station-option[aria-selected="true"] { background: #00005c; color: #fff; }
.station-option-code {
  flex: none; width: 30px; height: 30px; border-radius: 50%; display: grid; place-items: center;
  background: var(--green); color: #fff; font: 600 11px/1 var(--sans);
}
.station-option-code.long { font-size: 9px; }
.station-option-names { display: flex; flex-direction: column; min-width: 0; }
.station-option-en { font: 600 13px/1.2 var(--sans); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.station-option-th { font: 500 11px/1.3 'Noto Sans Thai', Tahoma, sans-serif; opacity: 0.75; }

.light-tool { position: relative; }
.light-tool .live-badge {
  position: absolute; bottom: -5px; left: 50%; transform: translateX(-50%); padding: 1px 4px; border-radius: 4px;
  background: #d3312a; color: #fff; font: 700 7px/1.2 var(--sans); letter-spacing: 0.06em;
}
.light-menu {
  position: absolute; top: 70px; right: 30px; display: flex; gap: 4px; padding: 5px;
  border: 1px solid var(--glass-edge); border-radius: 999px; background: var(--glass);
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px); box-shadow: 0 10px 28px rgb(20 30 60 / 0.16);
  animation: menu-in 0.18s ease;
}
.light-menu[hidden] { display: none; }
.settings {
  position: absolute; top: 70px; right: 30px; width: min(250px, calc(100vw - 32px)); padding: 12px 14px;
  border: 1px solid var(--glass-edge); border-radius: 12px; background: var(--glass);
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px); box-shadow: 0 10px 28px rgb(20 30 60 / 0.2);
}
.settings[hidden] { display: none; }
.settings h2 { margin: 0 0 10px; font: 600 13px var(--sans); }
.settings-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin: -4px -6px 6px 0; }
.settings-head h2 { margin: 0; }
#settings-close {
  display: grid; place-items: center; width: 32px; height: 32px; padding: 0; border: 0; border-radius: 50%;
  background: transparent; color: var(--ink); font-size: 22px; line-height: 1; opacity: 0.6; cursor: pointer;
}
#settings-close:hover { opacity: 1; background: color-mix(in srgb, var(--ink) 8%, transparent); }
#settings-close:focus-visible { outline: 2px solid var(--green); outline-offset: 2px; }
.settings-label { display: flex; justify-content: space-between; gap: 12px; font-size: 12px; }
.settings-label output { font-variant-numeric: tabular-nums; font-weight: 600; }
.settings input[type="range"] { display: block; width: 100%; margin: 10px 0; accent-color: var(--green); cursor: pointer; }
.settings p { margin: 0; color: var(--ink-soft); font-size: 10px; line-height: 1.4; }
.settings input:focus-visible { outline: 2px solid var(--green); outline-offset: 3px; }
.settings-advanced { margin-top: 10px; border-top: 1px solid var(--glass-edge); padding-top: 8px; }
.settings-advanced summary { cursor: pointer; font-size: 12px; font-weight: 600; }
.settings-advanced[open] summary { margin-bottom: 8px; }
.settings-advanced .settings-label { margin-top: 6px; align-items: center; }
.settings-advanced input[type="range"] { margin: 6px 0; }
.settings select { font: inherit; font-size: 12px; padding: 2px 4px; border-radius: 4px; }
.settings-check { display: flex; align-items: center; gap: 6px; margin: 8px 0 0; font-size: 12px; cursor: pointer; }
.settings-check input { accent-color: var(--green); }
.settings-flight-btn {
  display: inline-flex; align-items: center; gap: 8px; margin: 10px 0 2px; padding: 6px 12px;
  border: 2px solid var(--edge); border-radius: 4px; background: var(--panel); color: var(--ink);
  font: italic 700 12px/1 var(--display); letter-spacing: 0.02em; cursor: pointer;
  box-shadow: var(--drop); transform: skewX(var(--slant)); transition: background 0.15s, transform 0.15s;
}
.settings-flight-btn > * { transform: skewX(calc(-1 * var(--slant))); }
.settings-flight-btn:hover { background: var(--racer); color: #10150c; transform: skewX(var(--slant)) translateY(-1px); }
.settings-flight-btn[aria-pressed="true"] { background: var(--racer); color: #10150c; }
.settings-flight-btn svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
@media (pointer: coarse) {
  .settings-flight-btn { min-height: 40px; font-size: 14px; margin: 8px 0 2px; }
}
.settings { max-height: calc(100% - 110px); overflow-y: auto; } /* of the app, which is the visible screen (100vh runs under phone toolbars) */
.light-option {
  display: grid; place-items: center; min-width: 32px; height: 32px; padding: 0 6px; border: 0; border-radius: 999px; background: transparent;
}
.light-option svg { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.light-option:hover { background: rgb(255 255 255 / 0.4); }
.light-option[aria-pressed="true"] { background: var(--ink); color: #fbfaf6; }
.app[data-phase="night"] .light-option[aria-pressed="true"] { color: #161a32; }
.live-pill { display: inline-flex; align-items: center; gap: 4px; font: 700 10px/1 var(--sans); letter-spacing: 0.08em; }
.live-dot { width: 7px; height: 7px; border-radius: 50%; background: #d3312a; box-shadow: 0 0 0 0 rgb(211 49 42 / 0.6); animation: live-pulse 2s infinite; }
@keyframes live-pulse { 70% { box-shadow: 0 0 0 5px rgb(211 49 42 / 0); } 100% { box-shadow: 0 0 0 0 rgb(211 49 42 / 0); } }
@keyframes menu-in { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }

.train-popup {
  position: absolute; left: 0; top: 0; width: 210px; padding: 11px 12px 12px; margin-top: -12px;
  border: 1px solid var(--glass-edge); border-radius: 14px; background: var(--glass); pointer-events: auto;
  backdrop-filter: blur(16px) saturate(1.2); -webkit-backdrop-filter: blur(16px) saturate(1.2);
  box-shadow: 0 12px 30px rgb(20 30 60 / 0.2); opacity: 0; scale: 0.85; transform-origin: 50% 100%;
  transition: opacity 0.25s ease, scale 0.3s cubic-bezier(0.2, 1.4, 0.4, 1); will-change: transform;
}
.train-popup[hidden] { display: none; }
.train-popup { z-index: 1; } /* above the station name labels it opens beside */
.train-popup.open { opacity: 1; scale: 1; }
.train-popup.offscreen { opacity: 0; pointer-events: none; }
.train-popup::after {
  content: ''; position: absolute; left: 50%; bottom: -7px; width: 12px; height: 12px; margin-left: -6px; transform: rotate(45deg);
  background: inherit; border-right: 1px solid var(--glass-edge); border-bottom: 1px solid var(--glass-edge);
}
.popup-title { margin: 0 18px 2px 0; font: 600 13px/1.25 var(--sans); }
.popup-detail { margin: 0 0 9px; font-size: 11px; color: var(--ink-soft); }
.popup-close { position: absolute; top: 6px; right: 6px; width: 22px; height: 22px; padding: 0; border: 0; border-radius: 50%; background: transparent; font-size: 15px; line-height: 1; }
.popup-close:hover { background: rgb(255 255 255 / 0.4); }
.popup-ride {
  width: 100%; height: 34px; border: 0; border-radius: 10px; background: var(--green); color: #102004;
  font: 700 13px var(--sans); box-shadow: 0 3px 10px rgb(80 140 20 / 0.35); transition: transform 0.15s, filter 0.15s;
}
.popup-ride:hover { transform: translateY(-1px); filter: brightness(1.06); }
.popup-ride:focus-visible, .popup-close:focus-visible, .light-option:focus-visible { outline: 2px solid var(--green); outline-offset: 2px; }

.boarding-flash { position: absolute; inset: 0; background: #f6f8f4; opacity: 0; pointer-events: none; }

.place-name-th {
  display: block; width: 100%; white-space: nowrap;
  font: 500 28px/1.25 'Noto Sans Thai', 'Sukhumvit Set', Tahoma, sans-serif;
}
.place-bottom { display: flex; align-items: center; justify-content: center; gap: 5px; min-width: 0; }
.place-name-en {
  display: block; width: auto; min-width: 0; white-space: nowrap;
  font: 600 21px/1 var(--sans);
}
.place-name-en.wrap { flex: 1; white-space: normal; overflow-wrap: anywhere; line-height: 1.1; }
.place-code {
  flex: none; width: 32px; height: 32px; border: 1px solid currentColor; border-radius: 50%;
  display: grid; place-items: center; font: 500 16px/1 var(--sans);
}
.place-code.long { width: 36px; height: 36px; font-size: 12px; }
@keyframes place-in { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }

.tools { position: absolute; top: 28px; right: 30px; display: flex; gap: 6px; }
/* Inside the portfolio pop-out its close button covers the top-right corner. */
@media (min-width: 701px) { html.framed .tools { right: 64px; } }
.tool {
  display: grid; place-items: center; width: 34px; height: 34px; padding: 0;
  border: 1px solid var(--glass-edge); border-radius: 50%; background: var(--glass);
  backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); text-decoration: none;
  transition: background 0.3s, border-color 0.3s;
}
.tool:hover { background: color-mix(in srgb, var(--glass) 55%, white 45%); }
.tool svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.tool[aria-pressed="true"] svg { stroke: var(--green); stroke-width: 2; }
.tool:focus-visible, .attribution:focus-visible { outline: 2px solid var(--green); outline-offset: 2px; }

.labels { position: absolute; inset: 0; pointer-events: none; overflow: hidden; }
/* Station names over the map: a hairline up from each nearby station to
   its name; in the free view on a soft frosted card (see src/station-labels.js). */
.station-labels { position: absolute; inset: 0; transition: opacity 0.5s ease; }
.station-labels.is-hidden { opacity: 0; }
.station-labels.is-hidden .station-label { pointer-events: none; }
.station-label {
  position: absolute; left: 0; top: 0; display: flex; flex-direction: column; align-items: center;
  will-change: transform, opacity; color: #1b2230;
  --halo: 0 0 3px rgb(255 255 255 / 0.9), 0 0 8px rgb(255 255 255 / 0.6);
  pointer-events: auto;
  cursor: pointer;
  user-select: none;
  touch-action: none; /* fingers on a name still move the map (MapGestures) */
}
.station-label-en { display: inline-block; }
.station-label:hover .station-label-en {
  color: var(--green);
  text-shadow: 0 0 6px rgb(0 230 118 / 0.9), 0 0 14px rgb(0 230 118 / 0.5);
  transform: scale(1.08);
  transition: transform 0.15s ease, color 0.15s ease;
}
.station-label[hidden] { display: none; }
.app[data-phase="night"] .station-label { color: #f4f6ff; --halo: 0 0 3px rgb(6 8 24 / 0.9), 0 0 8px rgb(6 8 24 / 0.6); }
body.in-intro .station-label {
  --halo: 0 0 4px rgb(255 255 255 / 1), 0 0 12px rgb(0 230 118 / 0.7);
}
/* Overview: names on small cards in the panels' trim (dark edge, offset
   drop), readable over the busy map. */
body.in-intro .station-label-text {
  padding: 3px 8px 4px; border: 1.5px solid var(--edge); border-radius: 3px;
  background: #fbfaf6; color: #10150c; box-shadow: var(--drop); text-shadow: none;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
body.in-intro .station-label-en { font: 700 12.5px/1.1 var(--display); letter-spacing: 0.01em; }
body.in-intro .station-label-th { opacity: 0.6; }
body.in-intro .station-label-line { width: 2px; background: var(--edge); opacity: 0.75; box-shadow: none; }
body.in-intro .station-label:hover .station-label-text { background: var(--racer); transform: translate(-1px, -2px); box-shadow: var(--drop-big); }
body.in-intro .station-label:hover .station-label-en { color: #10150c; text-shadow: none; transform: none; }
.station-label-text { display: flex; flex-direction: column; align-items: center; padding-bottom: 4px; white-space: nowrap; text-shadow: var(--halo); }
.station-label-en { font: 600 12px/1.15 var(--sans); letter-spacing: 0.02em; }
.station-label-th { font: 500 9.5px/1.2 'Noto Sans Thai', Tahoma, sans-serif; opacity: 0.72; }
.station-label-line { width: 1px; background: currentColor; opacity: 0.45; box-shadow: 0 0 2px rgb(255 255 255 / 0.35); }
body:not(.in-intro) .app[data-phase="night"] .station-label-line { box-shadow: 0 0 2px rgb(0 0 20 / 0.5); }
/* Free view: names on a soft frosted card (a lighter cousin of the overview's
   cards) so they hold up against both sky and towers, with a firmer leader
   and a dot where it meets the station. */
body:not(.in-intro) .station-label-text {
  padding: 3px 9px 4px; border: 1px solid rgb(16 21 12 / 0.55); border-radius: 4px;
  background: rgb(251 250 246 / 0.9); color: #10150c; text-shadow: none;
  box-shadow: 0 2px 6px rgb(10 20 40 / 0.28), 0 0 0 2px rgb(255 255 255 / 0.25);
  backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px);
  transition: background 0.15s ease, transform 0.15s ease;
}
body:not(.in-intro) .station-label-en { font: 700 13.5px/1.15 var(--display, var(--sans)); letter-spacing: 0.01em; }
body:not(.in-intro) .station-label-th { font-size: 10.5px; opacity: 0.7; }
body:not(.in-intro) .station-label-line {
  position: relative; width: 2px; background: rgb(16 21 12 / 0.8); opacity: 1;
  box-shadow: 0 0 0 1px rgb(255 255 255 / 0.55);
}
body:not(.in-intro) .station-label-line::after {
  content: ''; position: absolute; left: 50%; bottom: -3px; width: 6px; height: 6px; margin-left: -3px;
  border-radius: 50%; background: #10150c; box-shadow: 0 0 0 1.5px #fff;
}
body:not(.in-intro) .station-label:hover .station-label-text { background: var(--racer); transform: translateY(-2px); }
body:not(.in-intro) .station-label:hover .station-label-en { color: #10150c; text-shadow: none; transform: none; }
body:not(.in-intro) .app[data-phase="night"] .station-label-text { background: rgb(14 18 34 / 0.86); color: #f4f6ff; border-color: rgb(244 246 255 / 0.4); box-shadow: 0 2px 8px rgb(0 0 10 / 0.5); }
body:not(.in-intro) .app[data-phase="night"] .station-label-line { background: rgb(244 246 255 / 0.85); box-shadow: 0 0 0 1px rgb(6 8 24 / 0.6); }
body:not(.in-intro) .app[data-phase="night"] .station-label-line::after { background: #f4f6ff; box-shadow: 0 0 0 1.5px rgb(6 8 24 / 0.9), 0 0 8px rgb(6 8 24 / 0.6); }
/* Places (malls, parks, sights, points of interest): quieter than stations.
   No card or leader, a small tinted badge and a light name with a halo
   (see src/place-labels.js). */
.place-labels { position: absolute; inset: 0; pointer-events: none; transition: opacity 0.5s ease; }
.place-labels.is-hidden { opacity: 0; }
.place-label {
  position: absolute; left: 0; top: 0; display: flex; align-items: center; gap: 4px;
  will-change: transform, opacity; white-space: nowrap; color: #2b3342;
  --badge: #6b7280;
  text-shadow: 0 0 2px rgb(255 255 255 / 0.95), 0 0 6px rgb(255 255 255 / 0.7);
}
.place-label[hidden] { display: none; }
.place-badge {
  display: grid; place-items: center; width: 16px; height: 16px; flex: none; border-radius: 50%;
  background: var(--badge); box-shadow: 0 0 0 1.5px rgb(255 255 255 / 0.85), 0 1px 3px rgb(10 20 40 / 0.3);
}
.place-badge svg { width: 11px; height: 11px; fill: none; stroke: #fff; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
.place-name { font: 500 11px/1.1 var(--sans); letter-spacing: 0.01em; }
.place-mall { --badge: #8a6bbf; }
.place-park { --badge: #4f9a52; }
.place-sight { --badge: #c98a2b; }
.place-poi { --badge: #3d8f9a; }
body.in-intro .place-name { font-weight: 600; }
.app[data-phase="night"] .place-label { color: #e4e8f4; text-shadow: 0 0 2px rgb(6 8 24 / 0.95), 0 0 6px rgb(6 8 24 / 0.7); }
.app[data-phase="night"] .place-badge { box-shadow: 0 0 0 1.5px rgb(6 8 24 / 0.8), 0 0 6px rgb(244 246 255 / 0.25); }
.train-tag {
  position: absolute; left: 0; top: 0; padding: 2px 8px; border-radius: 999px;
  background: var(--accent); color: #fff; font-size: 10px; font-weight: 600; letter-spacing: 0.06em;
}


.ride-hint {
  position: absolute; left: 50%; bottom: 158px; transform: translateX(-50%); margin: 0; padding: 5px 12px;
  border-radius: 999px; background: var(--glass); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  font-size: 11px; color: var(--ink-soft); text-align: center; white-space: nowrap;
}
.ride-hint[hidden] { display: none; }
body.is-riding .title .place { opacity: 0.5; }

.ride-controls[hidden], .ride-actions[hidden] { display: none; }
/* The left of the view is the stick's: a thumb put down anywhere there
   brings the stick to it (as in mobile shooters), and it goes back to its
   resting place on release. */
.ride-controls {
  position: absolute; left: 0; bottom: 0; width: 48%; height: 58%;
  pointer-events: auto; user-select: none; -webkit-user-select: none; touch-action: none;
}
.ride-stick {
  position: absolute; left: 30px; bottom: 60px; width: 132px; height: 132px; border-radius: 50%;
  border: 2px solid var(--glass-edge); background: var(--glass);
  backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
  box-shadow: 0 4px 14px rgb(20 30 50 / 0.16);
  touch-action: none; pointer-events: auto;
}
.ride-knob {
  position: absolute; left: 50%; top: 50%; width: 56px; height: 56px; margin: -28px 0 0 -28px;
  border-radius: 50%; background: var(--ink); opacity: 0.55; pointer-events: none;
  transition: transform 0.12s ease-out;
}
.ride-stick.is-pressed .ride-knob { opacity: 0.85; transition: none; }
.ride-stick.is-floating { transition: none; }
.ride-stick.is-returning { transition: transform 0.18s ease-out; }
.ride-stick.is-sprinting { border-color: var(--racer, #a8e62e); }
body:not(.ready) .ride-stick, body:not(.ready) .ride-controls { pointer-events: none; }
/* Jump, under the right thumb. */
.ride-actions {
  position: absolute; right: max(18px, env(safe-area-inset-right)); bottom: calc(max(10px, env(safe-area-inset-bottom)) + 112px);
  display: flex; flex-direction: column; align-items: center; gap: 12px; z-index: 2;
}
.ride-action {
  display: grid; place-items: center; width: 52px; height: 52px; padding: 0; border: 2px solid var(--edge); border-radius: 50%;
  background: var(--panel); color: var(--ink); box-shadow: var(--drop); cursor: pointer; touch-action: none;
  user-select: none; -webkit-user-select: none; -webkit-touch-callout: none;
}
.ride-action.ride-jump { width: 62px; height: 62px; }
.ride-action svg { width: 24px; height: 24px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.ride-action.is-pressed { background: var(--racer, #a8e62e); color: #10150c; }
.ride-action.is-pressed { transform: scale(0.94); }
/* The map compass, under the station sign: a round dial like the other
   round buttons, its needle pointing north. Once north is up, a slanted
   plate (like the tools) says what the next tap does: 2D or 3D. It only
   shows on the map, never on the loading screen or the intro. */
.compass {
  position: relative; display: grid; place-items: center; width: 48px; height: 48px; margin: 12px 0 8px; padding: 0; /* room below for the 2D/3D plate */
  border: 2px solid var(--edge); border-radius: 50%; background: var(--panel); color: var(--ink);
  box-shadow: var(--drop); text-shadow: none; cursor: pointer; pointer-events: auto; touch-action: manipulation; -webkit-tap-highlight-color: transparent;
  transition: opacity 0.3s ease, visibility 0s linear 0s, transform 0.15s ease;
}
.compass[hidden] { display: none; }
.compass:hover { transform: translateY(-1px); }
.compass:active { transform: scale(0.94); }
.compass:focus-visible { outline: 2px solid var(--green); outline-offset: 2px; }
.compass::before { /* inner bezel */
  content: ''; position: absolute; inset: 3px; border: 1.5px solid currentColor; border-radius: 50%; opacity: 0.18;
}
.compass-rose { position: absolute; inset: 0; will-change: transform; }
.compass-rose svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.compass-ticks { fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; opacity: 0.4; }
.compass-letter { fill: #e0402b; font: italic 700 8.5px var(--display); }
.compass-n { fill: #e0402b; stroke: var(--edge); stroke-width: 1.1; stroke-linejoin: round; }
.compass-s { fill: var(--panel); stroke: var(--edge); stroke-width: 1.1; stroke-linejoin: round; }
.app[data-phase="night"] .compass-n, .app[data-phase="night"] .compass-s { stroke: currentColor; }
.compass-hub { fill: var(--edge); }
.app[data-phase="night"] .compass-hub { fill: currentColor; }
.compass-mode {
  position: absolute; left: 50%; bottom: -9px; padding: 1px 5px; border: 1.5px solid var(--edge); border-radius: 3px;
  background: var(--racer); color: #10150c; box-shadow: 2px 2px 0 rgb(16 21 12 / 0.28);
  font: italic 700 9px/1.2 var(--display); letter-spacing: 0.03em; transform: translateX(-50%) skewX(var(--slant));
}
.compass-mode[hidden] { display: none; }
body:not(.ready) .compass, body.in-intro .compass, body.attract-mode .compass, body.cinematic .compass {
  opacity: 0; visibility: hidden; pointer-events: none; transition: opacity 0.3s ease, visibility 0s linear 0.3s;
}
body.is-riding .compass { display: none; }
/* First/third person switch while riding or walking: a round icon button on
   the right edge, in reach of the thumb that looks around (the left one has
   the stick). On touch screens it sits just above Jump. */
.perspective {
  position: absolute; right: 30px; top: 50%; transform: translateY(-50%); display: grid; place-items: center;
  width: 46px; height: 46px; padding: 0; border: 2px solid var(--edge); border-radius: 50%; background: var(--panel); color: var(--ink);
  box-shadow: var(--drop); cursor: pointer; touch-action: manipulation; -webkit-tap-highlight-color: transparent;
}
.perspective[hidden] { display: none; }
.perspective svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.perspective[aria-pressed="true"] .perspective-third, .perspective:not([aria-pressed="true"]) .perspective-first { display: none; }
.perspective:hover { transform: translateY(calc(-50% - 1px)); }
.perspective:active { transform: translateY(-50%) scale(0.95); }
.perspective:focus-visible { outline: 2px solid var(--green); outline-offset: 2px; }
body.ui-hidden .perspective { opacity: 1 !important; }
/* Clear of the tool column that runs down the right edge on small screens. */
@media (max-width: 900px) {
  .perspective { right: calc(max(16px, env(safe-area-inset-right)) + 46px); }
}
@media (pointer: coarse) {
  .perspective { top: auto; transform: none; width: 52px; height: 52px; right: calc(max(18px, env(safe-area-inset-right)) + 5px); bottom: calc(max(10px, env(safe-area-inset-bottom)) + 196px); }
  .perspective:hover { transform: none; }
  .perspective:active { transform: scale(0.94); }
}
/* Touch: a Sit (or Stand) prompt just below the middle of the view, shown
   only when a seat is right in front (see main.js). */
.seat-prompt {
  position: absolute; left: 50%; top: 58%; transform: translate(-50%, 6px); display: flex; align-items: center; gap: 7px;
  padding: 9px 18px 9px 14px; border: 2px solid var(--edge); border-radius: 999px; background: var(--panel); color: var(--ink);
  box-shadow: var(--drop); font: italic 700 14px var(--display); letter-spacing: 0.04em; cursor: pointer;
  opacity: 0; pointer-events: none; transition: opacity 0.2s ease, transform 0.2s ease;
}
.seat-prompt svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.seat-prompt.is-visible { opacity: 1; pointer-events: auto; transform: translate(-50%, 0); }
.seat-prompt:active { transform: translate(-50%, 0) scale(0.95); }

/* The route display: one panel along the bottom, the time of day on the
   left and the stations and trains around you (drawn by line-ribbon.js)
   beside it. The overhead map's button has the corner to itself. */
.bottom {
  position: absolute; left: max(114px, calc(50% - 470px)); right: max(114px, calc(50% - 470px)); bottom: 30px;
  display: flex; align-items: center; gap: 8px; padding: 10px 10px 10px 22px;
}
.status {
  display: grid; grid-template-columns: auto auto minmax(0, 1fr); align-items: baseline; column-gap: 5px; row-gap: 3px;
  flex: none; max-width: 190px; margin: 0; padding-right: 22px; font-size: 12px; line-height: 1.3; color: var(--ink-soft);
}
.status > * { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#clock { grid-column: 1 / -1; font-variant-numeric: tabular-nums; font-weight: 700; color: var(--ink); }
#clock + .sep { display: none; }
#trains-sep[hidden], #trains:empty { display: none; }
#trains { grid-column: 1 / -1; }
#trains-sep { display: none; }
/* While trains reconnect: a tag sitting on the panel's top edge. */
.service-note {
  position: absolute; left: 12px; bottom: calc(100% + 6px); max-width: calc(100% - 24px); padding: 3px 9px;
  border: 1.5px solid var(--edge); border-radius: 3px; background: var(--panel); color: var(--ink); box-shadow: var(--drop);
}
.service-note button {
  margin-left: 6px; border: 1px solid var(--glass-edge); background: var(--glass); border-radius: 999px;
  padding: 3px 10px; font-size: 11px; backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
}
.service-note[hidden] { display: none; }
.is-illustrative #trains { color: #b5641a; font-weight: 600; }
.ribbon { flex: 1; min-width: 0; height: 78px; display: block; touch-action: none; user-select: none; -webkit-user-select: none; }
.status { align-self: stretch; align-content: center; margin-right: 6px; border-right: 1.5px solid rgb(16 21 12 / 0.14); }
.app[data-phase="night"] .status { border-right-color: rgb(255 255 255 / 0.12); }
/* ‹ › either side of the stations: a station back or on. */
.line-step {
  flex: none; display: grid; place-items: center; width: 40px; height: 64px; padding: 0;
  border: 2px solid var(--edge); border-radius: 5px; background: transparent; color: var(--ink);
  touch-action: manipulation; transition: background 0.15s, transform 0.15s;
}
.line-step svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
.line-step:hover { background: var(--racer); color: #10150c; }
.line-step:active { transform: scale(0.94); }
.line-step:focus-visible { outline: 2px solid var(--green); outline-offset: 2px; }
.line-map {
  position: absolute; right: 30px; bottom: 30px; z-index: 3;
  display: grid; place-items: center; align-content: center; gap: 4px; width: 68px; height: 68px; padding: 0;
  border: 2px solid var(--edge); border-radius: 6px; background: var(--panel); color: var(--ink); box-shadow: var(--drop-big);
  transition: background 0.15s, transform 0.15s, opacity 1.6s ease;
}
.line-map[hidden] { display: none; }
.line-map svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.line-map span { font: italic 700 12px/1 var(--display); letter-spacing: 0.02em; }
.line-map:hover { background: var(--racer); color: #10150c; transform: translateY(-1px); }
.line-map:focus-visible { outline: 2px solid var(--green); outline-offset: 2px; }

.info {
  position: absolute; top: 74px; right: 30px; width: min(380px, calc(100% - 36px)); max-height: calc(100% - 160px); overflow: auto;
  padding: 16px 18px 6px; border: 1px solid var(--glass-edge); border-radius: 16px; background: var(--glass);
  backdrop-filter: blur(18px) saturate(1.2); -webkit-backdrop-filter: blur(18px) saturate(1.2);
  font-size: 12px; line-height: 1.55; box-shadow: 0 12px 34px rgb(30 34 60 / 0.16);
}
.info[hidden] { display: none; }
.info-head { display: flex; justify-content: space-between; align-items: baseline; }
.info h2 { margin: 0 0 4px; font-family: var(--serif); font-weight: 400; font-size: 22px; }
.info-head button { border: 0; background: none; font-size: 20px; line-height: 1; padding: 0 2px; }
.info p { margin: 8px 0 10px; color: var(--ink-soft); }
.info strong { color: var(--ink); font-weight: 600; }
kbd { display: inline-block; min-width: 18px; padding: 0 4px; margin: 0 1px; border: 1px solid var(--glass-edge); border-radius: 4px; font: 600 10px var(--sans); text-align: center; background: rgb(255 255 255 / 0.25); }
.attribution { position: absolute; right: 18px; bottom: 12px; border: 0; background: none; padding: 0; font-size: 10px; color: var(--ink-soft); text-shadow: var(--halo); }
.attribution:hover { color: var(--ink); }

.failed #trains { color: #b3261e; }


/* ---------- Racer trim ----------
   Taken from the logo: slanted panels, lime-to-forest green, hard black
   edges and drop shadows, italic sporty lettering. Kept light: the scene
   stays the star. */
:root {
  --display: 'Chakra Petch', 'DM Sans', system-ui, sans-serif;
  --edge: #10150c;
  --drop: 3px 3px 0 rgb(16 21 12 / 0.28);
  --drop-big: 4px 4px 0 rgb(16 21 12 / 0.3);
  --panel: rgb(250 250 245 / 0.9);
  --racer: linear-gradient(100deg, #c2f03a 0%, #7cc92a 45%, #2f7a22 100%);
  --slant: -11deg;
}
.app[data-phase="night"] {
  --panel: rgb(22 27 46 / 0.9);
  --drop: 3px 3px 0 rgb(0 0 0 / 0.5);
  --drop-big: 4px 4px 0 rgb(0 0 0 / 0.55);
}

/* Top-right buttons: slanted plates. */
.tools { gap: 8px; }
.tool {
  width: 38px; height: 32px; border: 2px solid var(--edge); border-radius: 4px;
  background: var(--panel); box-shadow: var(--drop); transform: skewX(var(--slant));
  backdrop-filter: none; -webkit-backdrop-filter: none; transition: transform 0.15s, background 0.2s;
}
.tool > * { transform: skewX(calc(-1 * var(--slant))); }
.tool:hover { background: var(--panel); transform: skewX(var(--slant)) translateY(-1px); }
.tool[aria-pressed="true"], .tool[aria-expanded="true"] { background: var(--racer); color: #10150c; }
.tool[aria-pressed="true"] svg { stroke: #10150c; }
.light-tool .live-badge {
  bottom: -8px; border: 1.5px solid var(--edge); border-radius: 2px; font: italic 700 7px/1.2 var(--display);
}
.light-menu {
  top: 72px; gap: 3px; padding: 4px; border: 2px solid var(--edge); border-radius: 5px;
  background: var(--panel); box-shadow: var(--drop-big); backdrop-filter: none; -webkit-backdrop-filter: none;
}
.settings { border: 2px solid var(--edge); border-radius: 5px; background: var(--panel); box-shadow: var(--drop-big); backdrop-filter: none; -webkit-backdrop-filter: none; }
.light-option { border-radius: 3px; transform: skewX(var(--slant)); }
.light-option > * { transform: skewX(calc(-1 * var(--slant))); }
.light-option[aria-pressed="true"] { background: var(--racer); color: #10150c; }
.app[data-phase="night"] .light-option[aria-pressed="true"] { color: #10150c; }
.live-pill { font: italic 700 10px/1 var(--display); }

/* Station sign: a hard edge, and a green "change" strip like the logo. */
.place { border: 4px solid var(--edge); box-shadow: var(--drop-big); } /* the logo plate's outline weight */
.place:hover, .place[aria-expanded="true"] { box-shadow: 5px 5px 0 rgb(16 21 12 / 0.32); }
.place-change {
  height: 18px; background: var(--racer); color: #10150c; border-top: 3px solid var(--edge);
  font: italic 700 10px/1 var(--display); letter-spacing: 0.02em;
}
.station-menu {
  border: 2px solid var(--edge); border-radius: 6px; background: var(--panel); box-shadow: var(--drop-big);
  backdrop-filter: none; -webkit-backdrop-filter: none;
}
.station-option { border-radius: 4px; }
.station-option-code { border: 1.5px solid var(--edge); background: var(--racer); color: #10150c; font: 700 11px/1 var(--display); }
.station-option-en { font-family: var(--display); font-weight: 600; }

/* Train popup and riding card. */
.train-popup {
  border: 2px solid var(--edge); border-radius: 6px; background: var(--panel); box-shadow: var(--drop-big);
  backdrop-filter: none; -webkit-backdrop-filter: none;
}
.train-popup::after { bottom: -8px; border-right: 2px solid var(--edge); border-bottom: 2px solid var(--edge); }
.popup-title { font: italic 700 14px/1.2 var(--display); }
.popup-detail { font-family: var(--display); }
.popup-ride {
  height: 36px; border: 2px solid var(--edge); border-radius: 4px; background: var(--racer); box-shadow: var(--drop);
  transform: skewX(var(--slant)); color: #fff; font: italic 700 14px var(--display); letter-spacing: 0.02em;
  text-shadow: -1px -1px 0 #10150c, 1px -1px 0 #10150c, -1px 1px 0 #10150c, 1px 1px 0 #10150c, 2px 2px 0 #10150c;
}
.popup-ride:hover { transform: skewX(var(--slant)) translateY(-1px); filter: brightness(1.05); }

/* Route display and small labels. */
.bottom {
  border: 2px solid var(--edge); border-radius: 6px; background: var(--panel); box-shadow: var(--drop-big);
}
.status { font-family: var(--display); font-weight: 600; font-style: italic; letter-spacing: 0.03em; }
#clock { font: 700 23px/1.05 var(--display); letter-spacing: 0.01em; }
.ride-hint {
  border: 2px solid var(--edge); border-radius: 4px; background: var(--panel); box-shadow: var(--drop);
  font-family: var(--display); backdrop-filter: none; -webkit-backdrop-filter: none;
}
.service-note button {
  border: 2px solid var(--edge); border-radius: 3px; background: var(--racer); color: #10150c;
  transform: skewX(var(--slant)); font: italic 700 11px var(--display);
}
.ride-stick { border: 2px solid var(--edge); background: var(--panel); box-shadow: var(--drop); backdrop-filter: none; -webkit-backdrop-filter: none; }
.ride-stick.is-pressed { border-color: #7cc92a; }

/* About panel. */
.info { border: 2px solid var(--edge); border-radius: 6px; background: var(--panel); box-shadow: var(--drop-big); }
.info h2 { font: italic 700 20px var(--display); }
kbd { border: 1.5px solid var(--edge); border-radius: 3px; font-family: var(--display); }

@media (max-width: 900px) {
  .title { top: 20px; left: 18px; }
  .place { width: min(190px, calc(100vw - 74px)); }
  .tools { top: 20px; right: 16px; flex-direction: column; }
  .bottom { left: 84px; right: 84px; bottom: 16px; padding: 7px 8px 7px 16px; }
  .line-step { width: 36px; height: 58px; }
  .ribbon { height: 72px; }
  .status { padding-right: 16px; }
  #clock { font-size: 19px; }
  .line-map { right: 14px; bottom: 16px; width: 58px; height: 58px; }
  .light-menu { top: auto; right: 62px; top: 20px; }
  .settings { top: 20px; right: 62px; }
  .ride-stick { left: 24px; bottom: 40px; }
  body.is-riding .ride-hint { bottom: 196px; max-width: calc(100vw - 32px); white-space: normal; }
}

@media (max-width: 600px) and (min-height: 440px) {
  .settings { top: 210px; }
}

@media (max-height: 500px) and (pointer: coarse) {
  body.is-riding .ride-hint { display: none; }
  .ride-stick { bottom: 16px; left: 28px; width: 116px; height: 116px; }
  .ride-actions { bottom: max(14px, env(safe-area-inset-bottom)); right: calc(max(16px, env(safe-area-inset-right)) + 46px); flex-direction: row-reverse; }
  .perspective { bottom: calc(max(14px, env(safe-area-inset-bottom)) + 5px); right: calc(max(16px, env(safe-area-inset-right)) + 120px); }
}

/* Phones: an almost HUD-free view. The logo and station sign shrink, Sound,
   Music, Settings, Hide and More show in the tool column (More reveals the
   rest), the route display spans the bottom, and first person drops the
   logo, hints and route display (all but its Map button), leaving the
   view to the sticks. */
#sound[aria-pressed="true"] .sound-off,
#music[aria-pressed="true"] .music-off { display: none; }
.more-tool { display: none; }
body.no-weather #weather { display: none !important; }
@media (max-width: 700px), (pointer: coarse) and (max-height: 500px) {
  .logo { width: 150px; }
  .title { top: 12px; left: 12px; }
  .place { width: 150px; min-height: 0; padding: 2px 6px 18px; margin-top: 4px; }
  .place-name-th { font-size: 19px; }
  .place-name-en { font-size: 14px; }
  .place-code { width: 24px; height: 24px; font-size: 11px; }
  .place-code.long { width: 26px; height: 26px; font-size: 9px; }
  .place-change { height: 15px; font-size: 8px; }
  .tools { top: 12px; right: 10px; gap: 5px; }
  .tool { width: 32px; height: 32px; }
  .more-tool { display: grid; }
  /* Sound, Music, Settings and Hide stay put; the chevron under them slides
     the rest (Light, Weather, Riders, About) out below it, one by one. */
  #more-tools { order: 1; }
  #light { order: 2; --i: 0; }
  #weather { order: 3; --i: 1; }
  #flight { order: 4; --i: 2; }
  #friends { order: 5; --i: 3; }
  #info-button { order: 6; --i: 4; }
  .more-tool svg { width: 18px; height: 18px; stroke-width: 2.2; transition: transform 0.25s ease; }
  body.tools-open .more-tool svg { transform: skewX(calc(-1 * var(--slant))) rotate(180deg); }
  .tools .tool:not(#sound):not(#music):not(#settings-button):not(#hide):not(#more-tools) {
    --delay: calc(var(--i) * 45ms);
    transition: height 0.22s ease var(--delay), margin 0.22s ease var(--delay), border-width 0.22s ease var(--delay),
      opacity 0.2s ease calc(var(--delay) + 50ms), transform 0.28s cubic-bezier(0.2, 0.8, 0.2, 1) var(--delay), background 0.2s;
  }
  body:not(.tools-open) .tools .tool:not(#sound):not(#music):not(#settings-button):not(#hide):not(#more-tools) {
    height: 0; margin-top: -5px; border-width: 0; box-shadow: none; opacity: 0; visibility: hidden; pointer-events: none;
    transform: skewX(var(--slant)) translateY(-14px);
    transition: height 0.18s ease, margin 0.18s ease, border-width 0.18s ease, opacity 0.12s ease, transform 0.18s ease, visibility 0s linear 0.18s;
  }
  @media (prefers-reduced-motion: reduce) {
    .tools .tool, .more-tool svg { transition: none !important; }
  }
  .settings, .light-menu { top: 12px; right: 52px; }
  .bottom {
    left: max(8px, env(safe-area-inset-left)); right: max(8px, env(safe-area-inset-right)); bottom: max(8px, env(safe-area-inset-bottom));
    gap: 4px; padding: 5px; border-width: 1.5px;
  }
  /* The phone shows the time itself; the stations get the room. */
  .status { display: none; }
  .ribbon { height: 66px; }
  .line-step { width: 34px; height: 56px; border-width: 1.5px; }
  /* The bar takes the full width; Map sits just above its right end, and
     drops into the corner in first person, when the bar goes. */
  .line-map {
    right: max(8px, env(safe-area-inset-right)); bottom: calc(max(8px, env(safe-area-inset-bottom)) + 88px);
    width: 50px; height: 50px; gap: 3px; border-width: 1.5px; box-shadow: var(--drop);
  }
  .line-map svg { width: 19px; height: 19px; }
  .line-map span { font-size: 9px; }
  /* First person: the route display goes; the Map button stays in its
     corner as the way back out to the map. */
  body.is-riding .bottom { display: none; }
  body.is-riding .line-map { bottom: max(8px, env(safe-area-inset-bottom)); }
  .ride-hint:not(.toast) { display: none; }
  .attribution { font-size: 8px; left: max(12px, env(safe-area-inset-left)); right: auto; bottom: calc(max(8px, env(safe-area-inset-bottom)) + 84px); opacity: 0.7; }
  body.is-riding .title h1, body.is-riding .attribution { display: none; }
  body.is-riding .title .place { opacity: 0.75; }
}

@media (prefers-reduced-motion: reduce) {
  .ui, .labels { transition: none; }
  .place.show { animation: none; opacity: 1; }
}

/* Ride together. */
.friends-tool { position: relative; }
.friends-count {
  position: absolute; top: -7px; right: -7px; min-width: 17px; height: 17px; padding: 0 4px; border: 2px solid var(--edge);
  border-radius: 3px; background: var(--racer); color: #10150c; font: italic 700 10px/13px var(--display); text-align: center;
}
.friends-count[hidden] { display: none; }
.social-status { font-family: var(--display); font-style: italic; }
.social-me { display: flex; gap: 12px; align-items: center; margin: 4px 0 6px; }
.social-me canvas { width: 116px; height: 150px; flex: none; border: 2px solid var(--edge); border-radius: 4px; background: var(--racer); }
.social-me > div { min-width: 0; }
.social-character { flex: 1 1 120px; }
.social-name { margin: 0 0 6px !important; font: italic 700 15px var(--display); color: var(--ink) !important; }
.social-row { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 8px; }
.social-chip {
  border: 2px solid var(--edge); border-radius: 3px; background: var(--panel); color: var(--ink); padding: 3px 8px;
  font: italic 600 11px var(--display); cursor: pointer;
}
.social-chip[aria-pressed="true"] { background: var(--racer); color: #10150c; }
.social-swatch { width: 22px; height: 22px; padding: 0; border: 2px solid var(--edge); border-radius: 3px; cursor: pointer; }
.social-swatch[aria-pressed="true"] { outline: 2px solid var(--ink); outline-offset: 2px; }
.social-emotes .social-chip { font-size: 18px; font-style: normal; padding: 2px 8px; }
.social-keys { font-family: var(--display); font-size: 10px; opacity: 0.7; }
.social-note { font-size: 11px; }
.toast { bottom: 150px; width: max-content; max-width: min(460px, calc(100vw - 32px)); white-space: normal; }
.mobile-social { display: flex; gap: 6px; position: absolute; right: 30px; bottom: 260px; z-index: 3; }
#emote-button { display: none; }
/* Chat and Emotes are round icon buttons, like the tools. */
.social-icon {
  display: grid; place-items: center; width: 36px; height: 36px; padding: 0; border: 2px solid var(--edge); border-radius: 50%;
  background: var(--panel); color: var(--ink); box-shadow: var(--drop); cursor: pointer; touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}
.social-icon svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.social-icon:active { transform: scale(0.94); }
.social-icon[aria-pressed="true"], .social-icon[aria-expanded="true"] { background: var(--racer); color: #10150c; }

/* Room chat: bottom left, in the app's panel style. Off by default; a
   Chat button brings it back. Messages fade after a while; while typing,
   the history becomes a scrollable panel above the input. */
.mc-chat {
  position: absolute; left: 24px; bottom: 148px; z-index: 5; width: min(400px, calc(100vw - 48px));
  display: flex; flex-direction: column; justify-content: flex-end;
  font: 500 13px/1.4 var(--sans); color: var(--ink); pointer-events: none;
}
.mc-bar { display: flex; align-items: center; gap: 8px; margin-top: 6px; pointer-events: auto; }
.mc-hint, .mc-send {
  height: 28px; padding: 0 10px; border: 2px solid var(--edge); border-radius: 4px;
  background: var(--panel); color: var(--ink); box-shadow: var(--drop);
  font: italic 600 12px/1 var(--display); letter-spacing: 0.02em; cursor: pointer; transition: transform 0.15s;
}
.mc-toggle:hover, .mc-hint:hover, .mc-send:hover:not(:disabled) { transform: translateY(-1px); }
.mc-toggle:active { transform: scale(0.94); }
.mc-hint { color: var(--ink-soft); }
.mc-hint kbd { font-style: normal; }
.mc-chat.chat-active .mc-bar { display: none; }
.mc-chat.chat-hidden .mc-messages,
.mc-chat.chat-hidden .mc-hint,
.mc-chat.chat-hidden .mc-status,
.mc-chat.chat-hidden .mc-form { display: none; }

.mc-messages {
  display: flex; flex-direction: column; align-items: flex-start; gap: 3px; max-height: 220px; overflow: hidden;
  scrollbar-width: thin;
}
.mc-msg {
  max-width: 100%; padding: 3px 8px; border-radius: 4px; background: var(--panel);
  box-shadow: 0 1px 4px rgb(16 21 12 / 0.12); overflow-wrap: anywhere; transition: opacity 1s ease-out;
}
.mc-msg.faded { opacity: 0; pointer-events: none; }
.mc-name { margin-right: 6px; font: italic 700 13px var(--display); color: var(--ink); }
.mc-name-me { color: #3d7a12; }
.app[data-phase="night"] .mc-name-me { color: #a6e05a; }
.mc-system { color: var(--ink-soft); font-style: italic; }
.mc-status { margin: 6px 0 0; font: italic 600 11px var(--display); color: var(--ink-soft); text-shadow: var(--halo); }
.mc-status[hidden] { display: none; }
.mc-chat.chat-active .mc-status { order: -1; margin: 0 0 6px; } /* above the history while typing */

/* Typing: one panel for history and input. */
.mc-chat.chat-active { pointer-events: auto; }
.mc-chat.chat-active .mc-messages {
  overflow-y: auto; padding: 8px 10px; gap: 2px;
  border: 2px solid var(--edge); border-bottom: 0; border-radius: 6px 6px 0 0; background: var(--panel);
}
.mc-chat.chat-active .mc-msg { opacity: 1; padding: 1px 0; background: none; box-shadow: none; }
.mc-chat.chat-active .mc-messages:empty { display: none; }
.mc-form {
  display: flex; align-items: center; gap: 8px; padding: 6px 6px 6px 10px;
  border: 2px solid var(--edge); border-radius: 0 0 6px 6px; background: var(--panel); box-shadow: var(--drop-big);
  pointer-events: auto;
}
.mc-chat.chat-active .mc-messages:empty ~ .mc-form { border-radius: 6px; }
.mc-form[hidden] { display: none; }
.mc-prompt { display: none; }
#chat-input {
  flex: 1; min-width: 0; height: 28px; padding: 0; border: 0; outline: none; background: transparent;
  color: var(--ink); font: 500 14px var(--sans); caret-color: currentColor;
}
#chat-input::placeholder { color: var(--ink-soft); }
.mc-send { flex: none; }
.mc-send:disabled { opacity: 0.45; cursor: default; box-shadow: none; }
.mc-toggle:focus-visible, .mc-hint:focus-visible, .mc-send:focus-visible { outline: 2px solid var(--green); outline-offset: 2px; }

@media (max-width: 900px) {
  .mobile-social { right: 14px; bottom: 150px; }
}

/* Phones: Chat and Emotes sit side by side at the top left, just under the
   station sign (and the compass on the map), clear of the walk stick, the
   Jump button and the route display. The chat opens downwards from there,
   above the on-screen keyboard. --title-bottom is the header's bottom edge
   (kept up to date in main.js). */
@media (max-width: 700px), (pointer: coarse) and (max-height: 500px) {
  .mc-chat {
    left: max(12px, env(safe-area-inset-left)); right: auto; top: calc(var(--title-bottom, 200px) + 10px); bottom: auto;
    width: min(360px, calc(100vw - 76px)); justify-content: flex-start; /* clear of the tool column */
  }
  .mc-chat .mc-bar { order: -1; margin: 0 0 6px; }
  .mc-chat .mc-hint { display: none; }
  #chat-input { font-size: 16px; } /* below 16px, iOS zooms the page in on focus */
  .mc-chat.chat-active { max-height: calc(100dvh - var(--title-bottom, 200px) - 20px); }
  /* Typing: the chat moves to the top of what's actually visible, over the
     station sign, so the keyboard (and Safari's bar above it) can't cover
     it. --vv-top and --vv-height follow window.visualViewport (main.js). */
  .mc-chat.chat-active {
    position: fixed; top: calc(var(--vv-top, 0px) + max(8px, env(safe-area-inset-top))); z-index: 20;
    width: calc(100vw - 24px); max-height: calc(var(--vv-height, 100dvh) - 16px);
  }
  .mc-chat.chat-active .mc-messages { min-height: 0; flex-shrink: 1; }
  .mc-chat.chat-active .mc-status { order: 0; margin: 0 0 6px; }
  .social-icon { width: 44px; height: 44px; }
  .social-icon svg { width: 22px; height: 22px; }
  .mobile-social {
    display: flex; position: absolute; left: calc(max(12px, env(safe-area-inset-left)) + 52px); right: auto;
    top: calc(var(--title-bottom, 200px) + 10px); bottom: auto; z-index: 6;
  }
  #emote-button { display: grid; }
  .mc-chat.chat-active ~ .mobile-social { visibility: hidden; }
  .mobile-emote-panel {
    position: absolute; left: -52px; top: calc(100% + 8px); width: 264px; max-width: calc(100vw - 24px);
    padding: 10px; border: 2px solid var(--edge); border-radius: 6px; background: var(--panel); box-shadow: var(--drop);
  }
  .mobile-emote-panel p { margin: 0 0 8px; }
  .mobile-emote-panel .social-keys { display: none; }
  .mobile-emote-panel .social-row { margin: 0; flex-wrap: nowrap; }
  .mobile-emote-panel .social-chip { min-width: 44px; min-height: 44px; flex: 1; padding: 2px; }
}

/* Birds-eye intro view. The route display stays: drag it to move along the line. */
body.in-intro .mc-chat,
body.in-intro .mobile-social,
body.in-intro .place,
body.in-intro #seat-prompt,
body.in-intro #ride-hint {
  opacity: 0 !important;
  pointer-events: none !important;
  transition: opacity 0.6s ease;
}

.intro-edges { position: absolute; inset: 0; z-index: 99; pointer-events: none; }
/* Rest the mouse near an edge: a soft, faintly green glow eases in on that side
   (opacity set per frame by src/intro-edge-pan.js) as the view glides there. */
.edge-glow { position: absolute; opacity: 0; will-change: opacity; }
[data-edge-glow="left"], [data-edge-glow="right"] { top: 0; bottom: 0; width: min(26vw, 280px); }
[data-edge-glow="up"], [data-edge-glow="down"] { left: 0; right: 0; height: min(26vh, 230px); }
[data-edge-glow="left"] { left: 0; background: radial-gradient(ellipse 100% 65% at 0 50%, rgb(226 255 214 / 0.95), rgb(200 245 180 / 0.38) 45%, transparent 78%); }
[data-edge-glow="right"] { right: 0; background: radial-gradient(ellipse 100% 65% at 100% 50%, rgb(226 255 214 / 0.95), rgb(200 245 180 / 0.38) 45%, transparent 78%); }
[data-edge-glow="up"] { top: 0; background: radial-gradient(ellipse 65% 100% at 50% 0, rgb(226 255 214 / 0.95), rgb(200 245 180 / 0.38) 45%, transparent 78%); }
[data-edge-glow="down"] { bottom: 0; background: radial-gradient(ellipse 65% 100% at 50% 100%, rgb(226 255 214 / 0.95), rgb(200 245 180 / 0.38) 45%, transparent 78%); }
body:not(.in-intro) .intro-edges { display: none; }
@media (hover: none), (pointer: coarse) { .intro-edges { display: none; } }
/* The map's (M) pin for where you were: a card on a short leader, like the
   station names, with a pulsing dot on the spot. */
.you-pin { position: absolute; left: 0; top: 0; display: flex; flex-direction: column; align-items: center; pointer-events: none; z-index: 1; }
.you-pin[hidden] { display: none; }
.you-pin-card {
  padding: 3px 9px 4px; border: 1.5px solid var(--edge); border-radius: 3px; background: var(--racer); color: #10150c;
  font: italic 700 13px/1.1 var(--display); box-shadow: var(--drop);
}
.you-pin-line { width: 2px; height: 64px; background: var(--edge); } /* clears the station name cards */
.you-pin-dot {
  width: 12px; height: 12px; margin-bottom: -6px; border: 2px solid var(--edge); border-radius: 50%; background: #fbfaf6;
  box-shadow: 0 0 0 0 rgb(120 190 32 / 0.7); animation: you-pulse 1.6s infinite;
}
@keyframes you-pulse { 70% { box-shadow: 0 0 0 12px rgb(120 190 32 / 0); } 100% { box-shadow: 0 0 0 0 rgb(120 190 32 / 0); } }
/* My location: the pin's dot alone, in maps-app blue, on your real spot.
.here-pin .you-pin-dot { background: #2f8cff; border-color: #fff; box-shadow: 0 0 0 0 rgb(47 140 255 / 0.7); animation-name: here-pulse; }
@keyframes here-pulse { 70% { box-shadow: 0 0 0 12px rgb(47 140 255 / 0); } 100% { box-shadow: 0 0 0 0 rgb(47 140 255 / 0); } }
*/
/* A compact station action at the top middle, over the sky rather than the scene. */
.enter-bar {
  position: absolute; left: 50%; top: max(30px, env(safe-area-inset-top)); z-index: 101; transform: translateX(-50%);
  transition: opacity 0.2s, transform 0.2s;
}
.enter-bar[hidden] { display: block; opacity: 0; pointer-events: none; transform: translate(-50%, -8px); }
.enter-card {
  display: flex; align-items: center; gap: 2px; padding: 3px; border: 2px solid var(--edge); border-radius: 999px;
  background: var(--panel); box-shadow: var(--drop);
}
.enter-go {
  min-height: 38px; padding: 0 14px 0 16px; border: 0; border-radius: 999px; background: transparent;
  color: var(--ink); font: 600 14px var(--display); cursor: pointer; transition: background 0.15s;
}
.enter-go:hover { background: color-mix(in srgb, var(--ink) 8%, transparent); }
.enter-go:active { transform: scale(0.97); }
.enter-go:focus-visible, .enter-close:focus-visible { outline: 2px solid var(--green); outline-offset: 3px; }
.enter-key { font-style: normal; margin-left: 5px; opacity: 0.6; }
.enter-close {
  width: 34px; height: 34px; padding: 0; border: 0; border-left: 1px solid color-mix(in srgb, var(--ink) 18%, transparent); border-radius: 0 999px 999px 0;
  background: transparent; color: var(--ink); font-size: 20px; line-height: 1; cursor: pointer; opacity: 0.6;
}
.enter-close:hover { opacity: 1; }
/* Narrower, the buttons stack down the right: sit just left of them, clear of the logo. */
@media (max-width: 900px) {
  .enter-bar { left: auto; right: 72px; top: 20px; transform: none; }
  .enter-bar[hidden] { transform: translateY(-8px); }
}
@media (max-width: 700px), (pointer: coarse) and (max-height: 500px) {
  .enter-bar { top: auto; right: auto; left: 50%; bottom: max(18px, env(safe-area-inset-bottom)); transform: translateX(-50%); }
  .enter-bar[hidden] { transform: translate(-50%, 8px); }
  .enter-key { display: none; }
  body.station-picked .bottom { opacity: 0; pointer-events: none; }
}

/* Keyboard guide: the keys that matter, shown on spawning in and the first
   time on the map (see coachKeys in main.js). Bottom left, above the chat
   button and clear of the compass; pressed keys light up. */
.key-guide {
  position: absolute; left: 30px; bottom: 198px; transform: translateX(-8px); z-index: 3;
  display: grid; gap: 6px; padding: 12px 14px 13px; border: 2px solid var(--edge); border-radius: 6px;
  background: var(--panel); color: var(--ink); box-shadow: var(--drop); font: italic 600 12px var(--display);
  opacity: 0; pointer-events: none; transition: opacity 0.45s ease, transform 0.45s ease;
}
.key-guide.is-visible { opacity: 1; transform: none; }
.key-guide[hidden] { display: none; }
.key-guide-title { margin: 0 0 2px; font: italic 700 12px var(--display); letter-spacing: 0.02em; color: var(--ink-soft); }
.key-guide-row { display: grid; grid-template-columns: 74px auto; align-items: center; gap: 10px; }
.key-guide-keys { display: flex; gap: 3px; }
.key-guide-wasd { display: grid; grid-template: '. w .' 'a s d' / 22px 22px 22px; gap: 3px; }
.key-guide-wasd kbd:nth-child(1) { grid-area: w; }
.key-guide-wasd kbd:nth-child(2) { grid-area: a; }
.key-guide-wasd kbd:nth-child(3) { grid-area: s; }
.key-guide-wasd kbd:nth-child(4) { grid-area: d; }
.key-guide kbd {
  display: grid; place-items: center; min-width: 22px; height: 22px; margin: 0; padding: 0 5px; box-sizing: border-box;
  border: 1.5px solid var(--edge); border-radius: 4px; border-bottom-width: 3px; background: var(--panel); color: var(--ink);
  font: normal 700 11px var(--display); transition: background 0.1s, transform 0.1s;
}
.key-guide kbd.wide { min-width: 52px; }
.key-guide kbd.is-down { background: var(--racer); color: #10150c; transform: translateY(1px); border-bottom-width: 2px; }
body.ui-hidden .key-guide { display: none; }
@media (max-height: 720px) { .key-guide { bottom: 192px; gap: 2px; padding: 8px 12px 9px; } .key-guide-title { display: none; } }
@media (pointer: coarse) { .key-guide { display: none; } }

/* Touch: settings and the pop-out menus at finger size. Sliders get a tall
   hit area and a big thumb, rows are at least 40px, and controls snap to
   where the finger lands rather than needing a precise grab. */
@media (pointer: coarse) {
  .settings { width: min(290px, calc(100vw - 68px)); padding: 12px 14px 14px; }
  .settings h2 { font-size: 15px; }
  .settings-label { min-height: 22px; margin-top: 10px; align-items: center; font-size: 14px; }
  .settings h2 + .settings-label { margin-top: 0; }
  .settings-label label { white-space: nowrap; }
  .settings p { font-size: 11.5px; }
  .settings input[type="range"] {
    -webkit-appearance: none; appearance: none; height: 40px; margin: 2px 0 6px; background: transparent; touch-action: pan-y;
  }
  .settings-advanced input[type="range"] { margin: 2px 0 6px; }
  /* Tracks in the ink colour, so they show on the dark night panel too. */
  .settings input[type="range"]::-webkit-slider-runnable-track { height: 8px; border-radius: 4px; background: color-mix(in srgb, var(--ink) 24%, transparent); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ink) 30%, transparent); }
  .settings input[type="range"]::-moz-range-track { height: 8px; border-radius: 4px; background: color-mix(in srgb, var(--ink) 24%, transparent); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ink) 30%, transparent); }
  .settings input[type="range"]::-moz-range-progress { height: 8px; border-radius: 4px; background: var(--green); }
  .settings input[type="range"]::-webkit-slider-thumb {
    -webkit-appearance: none; width: 28px; height: 28px; margin-top: -10px; border: 2px solid var(--edge); border-radius: 50%;
    background: var(--green); box-shadow: 0 2px 5px rgb(0 0 0 / 0.3);
  }
  .settings input[type="range"]::-moz-range-thumb {
    width: 24px; height: 24px; border: 2px solid var(--edge); border-radius: 50%; background: var(--green); box-shadow: 0 2px 5px rgb(0 0 0 / 0.3);
  }
  .settings select { min-height: 38px; min-width: 0; max-width: 62%; padding: 4px 8px; font-size: 16px; } /* 16px: iOS zooms into smaller fields */
  .settings-check { min-height: 42px; margin: 2px 0 0; gap: 10px; font-size: 14px; }
  .settings-check input { flex: none; width: 22px; height: 22px; margin: 0; }
  .settings-advanced summary { display: flex; align-items: center; min-height: 44px; font-size: 14px; }
  .settings-advanced[open] summary { margin-bottom: 0; }
  .light-menu { gap: 5px; padding: 5px; }
  .light-option { min-width: 44px; height: 44px; }
  .light-option svg { width: 21px; height: 21px; }
  .station-option { min-height: 46px; padding: 7px 9px; }
}

/* Phones: a pop-out is a solid sheet over everything it opens on (the logo,
   station sign, compass, labels, and the Chat and Emote buttons), clear of
   the tool column on the right. */
.app { --panel-solid: rgb(250 250 245); }
.app[data-phase="night"] { --panel-solid: rgb(22 27 46); }
@media (max-width: 700px), (pointer: coarse) and (max-height: 500px) {
  .settings, .light-menu, .station-menu, .info, .mobile-emote-panel,
  .mc-chat.chat-active .mc-messages, .mc-chat.chat-active .mc-form { background: var(--panel-solid); }
  .settings, .light-menu, .station-menu, .info { z-index: 12; }
  .settings, .info {
    top: max(12px, env(safe-area-inset-top)); left: max(12px, env(safe-area-inset-left));
    right: calc(max(10px, env(safe-area-inset-right)) + 50px); width: auto;
    max-height: calc(100% - max(12px, env(safe-area-inset-top)) - max(8px, env(safe-area-inset-bottom)) - 92px); /* above the route display */
    overflow-x: hidden;
  }
  .light-menu { right: calc(max(10px, env(safe-area-inset-right)) + 50px); }
  /* With Settings or About open, nothing else peeks out around the sheet:
     the station hint and Enter bar, station names, Map, credits. */
  body:has(#settings:not([hidden]), #info:not([hidden])) :is(.intro-hud, .enter-bar, .labels, .line-map, .attribution, .mobile-social, .mc-chat, .perspective) {
    visibility: hidden; pointer-events: none;
  }
}

/* ---------- Flight sim (experimental, flight-sim.js) ----------
   A layer over the 3D view, under the top-right tools: the figures up top,
   and on touch screens a stick (left thumb) and a throttle lever (right). */
.flight-sim { position: absolute; inset: 0; touch-action: none; user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; overflow: hidden; }
.flight-sim[hidden] { display: none; }
body.flight-sim-on :is(.title, .bottom, .line-map, .perspective, .ride-controls, .ride-actions, .seat-prompt, .ride-hint:not(.toast), .enter-bar, .intro-edges, .mobile-social, .mc-chat, .cine-card, .key-guide, .labels, .attribution, .vignette) { display: none !important; }

.flight-readout {
  position: absolute; top: max(16px, env(safe-area-inset-top)); left: max(16px, env(safe-area-inset-left));
  display: flex; flex-wrap: wrap; align-items: stretch; gap: 6px; max-width: max(240px, calc(100vw - 32px - 360px)); margin: 0;
}
.flight-readout p, .flight-exit, .flight-button {
  margin: 0; border: 2px solid var(--edge); border-radius: 4px; background: var(--panel); color: var(--ink);
  box-shadow: var(--drop); transform: skewX(var(--slant));
}
.flight-readout p { display: grid; grid-template-columns: auto auto; align-items: baseline; column-gap: 3px; padding: 3px 9px 4px; min-width: 66px; }
.flight-readout p > * { transform: skewX(calc(-1 * var(--slant))); }
.flight-readout span { grid-column: 1 / -1; font: 500 10px/1.2 var(--sans); color: var(--ink-soft); }
.flight-readout b { font: italic 700 19px/1.1 var(--display); font-variant-numeric: tabular-nums; }
.flight-readout i { font: 500 10px var(--sans); font-style: normal; color: var(--ink-soft); }
.flight-readout .flight-stall { display: none; align-items: center; background: #d8352a; color: #fff; font: italic 700 17px var(--display); }
.flight-stalling .flight-readout .flight-stall { display: flex; animation: flight-blink 0.5s steps(2) infinite; }
@keyframes flight-blink { 50% { opacity: 0.35; } }
.flight-exit { display: grid; place-items: center; width: 40px; padding: 0; cursor: pointer; }
.flight-exit svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: round; transform: skewX(calc(-1 * var(--slant))); }

.flight-help, .flight-portrait, .flight-message {
  position: absolute; left: 50%; top: 24%; transform: translateX(-50%); margin: 0; padding: 10px 16px;
  width: max-content; max-width: calc(100vw - 32px); border: 2px solid var(--edge); border-radius: 5px;
  background: var(--panel); color: var(--ink); box-shadow: var(--drop-big); font: 500 13px/1.7 var(--sans); text-align: center; pointer-events: none;
}
.flight-help p { margin: 0; }
.flight-help-touch, .flight-touch-on .flight-help-keys { display: none; }
.flight-touch-on .flight-help-touch { display: block; }
.flight-portrait { top: calc(24% + 92px); display: none; }
/* The minimap: under the top-right tools; beside them on a phone. */
.flight-minimap {
  position: absolute; right: max(30px, env(safe-area-inset-right)); top: 76px; width: 168px; height: 168px;
  border: 2px solid var(--edge); border-radius: 50%; background: #cdd1bc; box-shadow: var(--drop-big); pointer-events: none;
}
@media (pointer: coarse) and (orientation: landscape) and (max-height: 560px) {
  .flight-minimap { top: max(16px, env(safe-area-inset-top)); right: calc(max(20px, env(safe-area-inset-right)) + 64px); width: 118px; height: 118px; }
  .flight-readout { max-width: calc(100vw - 260px); }
}
@media (orientation: portrait) and (pointer: coarse) {
  .flight-minimap { left: max(16px, env(safe-area-inset-left)); right: auto; top: 160px; width: 120px; height: 120px; }
  .flight-help { top: 40%; }
  .flight-portrait { display: block; top: 62%; }
  .flight-readout p { min-width: 0; padding: 2px 7px 3px; }
  .flight-readout b { font-size: 16px; }
}
.flight-fade { animation: flight-fade 11s ease forwards; }
@keyframes flight-fade { 0%, 80% { opacity: 1; } 100% { opacity: 0; visibility: hidden; } }
.flight-message { top: 40%; font: italic 700 17px var(--display); }
.flight-crashed::after { content: ''; position: absolute; inset: 0; background: #d8352a; pointer-events: none; animation: flight-crash 1.2s ease-out forwards; }
@keyframes flight-crash { from { opacity: 0.55; } to { opacity: 0; } }

/* Touch: the stick waits bottom left, and comes to wherever the left thumb lands. */
.flight-stick, .flight-touch { display: none; }
.flight-touch-on .flight-stick, .flight-touch-on .flight-touch { display: block; }
.flight-stick {
  position: absolute; left: calc(max(24px, env(safe-area-inset-left)) + 62px); top: calc(100% - max(24px, env(safe-area-inset-bottom)) - 62px);
  width: 124px; height: 124px; margin: -62px 0 0 -62px; border: 2px solid rgb(255 255 255 / 0.55); border-radius: 50%;
  background: rgb(16 21 12 / 0.22); pointer-events: none; opacity: 0.6; transition: opacity 0.2s;
}
.flight-stick.active { opacity: 1; transition: none; }
.flight-knob {
  position: absolute; left: 50%; top: 50%; width: 52px; height: 52px; margin: -26px 0 0 -26px; border: 2px solid var(--edge);
  border-radius: 50%; background: var(--panel); box-shadow: var(--drop);
}
.flight-touch { position: absolute; right: max(20px, env(safe-area-inset-right)); bottom: max(20px, env(safe-area-inset-bottom)); }
.flight-throttle {
  position: absolute; right: 0; bottom: 0; width: 58px; height: min(230px, calc(100vh - 230px)); border: 2px solid var(--edge); border-radius: 6px;
  background: rgb(16 21 12 / 0.35); box-shadow: var(--drop); touch-action: none;
}
.flight-throttle-fill { position: absolute; left: 0; right: 0; bottom: 0; border-radius: 0 0 4px 4px; background: rgb(250 250 245 / 0.4); }
.flight-throttle-knob {
  position: absolute; left: -8px; right: -8px; height: 34px; margin-bottom: -17px; display: grid; place-items: center;
  border: 2px solid var(--edge); border-radius: 5px; background: var(--panel); color: var(--ink); box-shadow: var(--drop);
  font: italic 700 14px var(--display); font-variant-numeric: tabular-nums;
}
.flight-button {
  position: absolute; right: 78px; width: 84px; height: 44px; padding: 0; cursor: pointer;
  font: italic 700 14px var(--display); touch-action: none;
}
.flight-button[data-flight="brake"] { bottom: 0; }
.flight-button[data-flight="flaps"] { bottom: 54px; }
.flight-button.pressed { background: var(--racer); }
@media (max-height: 480px) {
  .flight-readout { gap: 4px; }
  .flight-readout p { padding: 2px 7px 3px; min-width: 56px; }
  .flight-readout b { font-size: 16px; }
  .flight-help, .flight-portrait { top: 22%; font-size: 12px; }
}

/* Desktop layout: the logo up in the corner with the station sign under
   it, lined up with the start of its lettering; the tools along the top
   right; and along the bottom, one row sitting on the same line: chat at
   the left, the route display in the middle, and the compass beside the
   Map button at the right. */
@media (min-width: 901px) and (pointer: fine) {
  .title { top: 14px; left: 16px; }
  .logo { width: 296px; }
  .place { margin: 6px 0 0 24px; }
  .station-menu { left: 24px; }
  .tools { top: 18px; right: 22px; }
  .tool { width: 40px; height: 34px; }
  .bottom {
    left: max(236px, calc(50% - 385px)); right: max(186px, calc(50% - 385px)); bottom: 14px;
    padding: 8px 8px 8px 20px;
  }
  .ribbon { height: 70px; }
  .line-step { height: 58px; }
  .line-map { right: 22px; bottom: 22px; }
  .compass { position: fixed; right: 120px; bottom: 32px; margin: 0; }
  .mc-chat { left: 18px; bottom: 22px; }
  .key-guide { left: 18px; bottom: 80px; }
  .attribution { right: 22px; bottom: 4px; }
}
