/* Rover operator console. Phone portrait first (360–430 px), map left and
   panels right from 900 px. Colours are tokens so the canvas (app.js reads
   them with getComputedStyle) and the panels always agree, in both themes. */

:root {
  color-scheme: light dark;
  --bg: #f3f4f6;
  --card: #ffffff;
  --card-2: #f8f9fb;
  --line: #d7dbe2;
  --text: #15181d;
  --muted: #5d6573;
  --accent: #1f6feb;
  --accent-text: #ffffff;
  --ok: #188038;
  --warn: #b26a00;
  --bad: #c5221f;
  --info: #1a73e8;
  --violet: #7b3fc4;
  --teal: #00796b;

  --st-idle: #5d6573;
  --st-ready: #1a73e8;
  --st-aligning: #0b8ca8;
  --st-running: #188038;
  --st-paused: #b26a00;
  --st-manual: #7b3fc4;
  --st-done: #00796b;
  --st-fault: #c5221f;

  --fix-none: #8a8f98;
  --fix-gps: #c5221f;
  --fix-dgps: #d35400;
  --fix-float: #b8860b;
  --fix-fixed: #188038;

  --map-bg: #fbfbf8;
  --map-grid: rgba(20, 30, 50, 0.10);
  --map-grid-major: rgba(20, 30, 50, 0.22);
  --map-text: #3a4150;
  --route-paint: #1f4fd6;
  --route-transfer: #7d8796;
  --route-current: #e8710a;
  --route-selected: #d6336c;
  --route-draft: #d6336c;
  --paint-trail: rgba(255, 196, 0, 0.85);
  --paint-edge: rgba(120, 90, 0, 0.55);
  --track: #3b8f5a;
  --robot: #15181d;
  --robot-fill: rgba(31, 111, 235, 0.18);
  --sigma: rgba(31, 111, 235, 0.16);
  --nozzle: #e8710a;
  --lookahead: #d6336c;
  --ghost: #7b3fc4;
  --fix-dot: rgba(90, 96, 110, 0.55);
  --fix-dot-bad: #e53935;
  --mark: #e8710a;
  --antenna: #0b8ca8;
  --obstacle: #d93025;
  --fov: rgba(11, 140, 168, 0.08);

  --radius: 12px;
  --gap: 10px;
  --safety-h: 76px;
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Noto Sans", sans-serif;
}

/* Dark: guarded so a page that forces data-theme="light" stays light. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #0f1216;
    --card: #181c22;
    --card-2: #1f242c;
    --line: #2d343e;
    --text: #e8eaee;
    --muted: #9aa3b2;
    --accent: #4c8dff;
    --accent-text: #0b0d10;
    --ok: #3ccf6e;
    --warn: #f2b233;
    --bad: #ff5c58;
    --info: #6aa6ff;
    --violet: #b48bff;
    --teal: #3cc7b4;
    --st-idle: #9aa3b2;
    --st-ready: #6aa6ff;
    --st-aligning: #3cc3e0;
    --st-running: #3ccf6e;
    --st-paused: #f2b233;
    --st-manual: #b48bff;
    --st-done: #3cc7b4;
    --st-fault: #ff5c58;
    --fix-none: #8a8f98;
    --fix-gps: #ff5c58;
    --fix-dgps: #ff8f4a;
    --fix-float: #f2c94c;
    --fix-fixed: #3ccf6e;
    --map-bg: #12161b;
    --map-grid: rgba(220, 230, 255, 0.07);
    --map-grid-major: rgba(220, 230, 255, 0.17);
    --map-text: #b9c1cf;
    --route-paint: #6aa6ff;
    --route-transfer: #8995a8;
    --route-current: #ff9a3c;
    --route-selected: #ff6b9a;
    --route-draft: #ff6b9a;
    --paint-trail: rgba(255, 214, 64, 0.85);
    --paint-edge: rgba(255, 230, 140, 0.35);
    --track: #57c27e;
    --robot: #f2f4f8;
    --robot-fill: rgba(106, 166, 255, 0.22);
    --sigma: rgba(106, 166, 255, 0.20);
    --nozzle: #ff9a3c;
    --lookahead: #ff6b9a;
    --ghost: #b48bff;
    --fix-dot: rgba(200, 206, 220, 0.5);
    --fix-dot-bad: #ff5c58;
    --mark: #ff9a3c;
    --antenna: #3cc3e0;
    --obstacle: #ff6b5e;
    --fov: rgba(60, 195, 224, 0.10);
  }
}

:root[data-theme="dark"] {
  --bg: #0f1216; --card: #181c22; --card-2: #1f242c; --line: #2d343e; --text: #e8eaee;
  --muted: #9aa3b2; --accent: #4c8dff; --accent-text: #0b0d10; --ok: #3ccf6e; --warn: #f2b233;
  --bad: #ff5c58; --info: #6aa6ff; --violet: #b48bff; --teal: #3cc7b4;
  --st-idle: #9aa3b2; --st-ready: #6aa6ff; --st-aligning: #3cc3e0; --st-running: #3ccf6e;
  --st-paused: #f2b233; --st-manual: #b48bff; --st-done: #3cc7b4; --st-fault: #ff5c58;
  --fix-none: #8a8f98; --fix-gps: #ff5c58; --fix-dgps: #ff8f4a; --fix-float: #f2c94c; --fix-fixed: #3ccf6e;
  --map-bg: #12161b; --map-grid: rgba(220, 230, 255, 0.07); --map-grid-major: rgba(220, 230, 255, 0.17);
  --map-text: #b9c1cf; --route-paint: #6aa6ff; --route-transfer: #8995a8; --route-current: #ff9a3c;
  --route-selected: #ff6b9a; --route-draft: #ff6b9a; --paint-trail: rgba(255, 214, 64, 0.85);
  --paint-edge: rgba(255, 230, 140, 0.35); --track: #57c27e; --robot: #f2f4f8;
  --robot-fill: rgba(106, 166, 255, 0.22); --sigma: rgba(106, 166, 255, 0.20); --nozzle: #ff9a3c;
  --lookahead: #ff6b9a; --ghost: #b48bff; --fix-dot: rgba(200, 206, 220, 0.5); --fix-dot-bad: #ff5c58;
  --mark: #ff9a3c; --antenna: #3cc3e0; --obstacle: #ff6b5e; --fov: rgba(60, 195, 224, 0.10);
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  background: var(--bg);
  color: var(--text);
  font-size: 15px;
  line-height: 1.35;
  padding-bottom: calc(var(--safety-h) + env(safe-area-inset-bottom, 0px));
  -webkit-text-size-adjust: 100%;
  overflow-x: hidden;
}
button, input, select, textarea { font: inherit; color: inherit; }
[hidden] { display: none !important; }

/* ------------------------------------------------------------ header */
.top {
  position: sticky; top: 0; z-index: 20;
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  --top-py: 8px;
  padding: var(--top-py) 16px;
  background: var(--card);
  border-bottom: 1px solid var(--line);
}
.brand { font-weight: 700; letter-spacing: 0.02em; margin-right: 4px; }
.pill {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 10px; border-radius: 999px;
  background: var(--card-2); border: 1px solid var(--line);
  font-size: 13px; white-space: nowrap;
}
.pill .dot { width: 9px; height: 9px; border-radius: 50%; background: var(--muted); }
.pill.ok .dot { background: var(--ok); }
.pill.warn .dot { background: var(--warn); }
.pill.bad .dot { background: var(--bad); }
.pill.demo { background: var(--violet); color: #fff; border-color: transparent; font-weight: 600; }
/* Pitch demo controls (?mock=1&demo=pitch): pill-sized; mock mode moves them into the demo banner (.demobar). */
.democtl { display: inline-flex; align-items: center; gap: 6px; }
.democtl select, .democtl .mbtn {
  min-height: 28px; padding: 2px 10px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--card-2); color: var(--text);
  font-size: 13px; box-shadow: none;
}
.democtl select:disabled { opacity: 0.42; cursor: not-allowed; }
.spacer { flex: 1; }

/* --top-h: the header's height, set by app.js where the demo banner makes it grow. */
#staleBanner {
  position: sticky; top: var(--top-h, 42px); z-index: 19;
  background: var(--bad); color: #fff; text-align: center;
  font-weight: 700; padding: 6px 16px;
}
body.stale .panels .card:not(.mission) { opacity: 0.55; }
/* The mission card stays legible (it is what the operator looks at) but is
   hatched and faded, with its age written in it, so «Работа» on a frozen
   screen cannot pass for live. */
body.stale .card.mission > :not(.stale-tag) { opacity: 0.45; }
body.stale .card.mission {
  background-image: repeating-linear-gradient(135deg, transparent 0 10px, color-mix(in srgb, var(--bad) 12%, transparent) 10px 20px);
}
.stale-tag {
  margin: 2px 0 6px; padding: 4px 8px; border-radius: 8px;
  background: var(--bad); color: #fff; font-weight: 700; font-size: 14px;
}
.pill.stale { border-color: var(--bad); color: var(--bad); font-weight: 700; }

/* ------------------------------------------------------------ layout */
.layout { display: flex; flex-direction: column; gap: var(--gap); padding: var(--gap) 16px; }
.mapwrap {
  position: relative;
  height: 56vh; min-height: 300px;
  border-radius: var(--radius); overflow: hidden;
  border: 1px solid var(--line);
  background: var(--map-bg);
}
#map { display: block; width: 100%; height: 100%; touch-action: none; cursor: grab; }
#map.drawing { cursor: crosshair; }
.panels { display: flex; flex-direction: column; gap: var(--gap); min-width: 0; }

@media (min-width: 900px) {
  .layout {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 400px;
    align-items: start;
  }
  .mapwrap {
    position: sticky; top: calc(var(--top-h, 44px) + var(--gap));
    height: calc(100vh - var(--top-h, 44px) - var(--safety-h) - 3 * var(--gap));
  }
  .panels { max-height: none; }
}
@media (min-width: 1300px) {
  .layout { grid-template-columns: minmax(0, 1fr) 460px; }
}

/* ------------------------------------------------------------ map overlays */
.maptools {
  position: absolute; top: 8px; left: 8px; right: 8px;
  display: flex; flex-wrap: wrap; gap: 6px; pointer-events: none;
}
.maptools > * { pointer-events: auto; }
.mbtn {
  min-height: 36px; padding: 6px 10px; border-radius: 10px;
  border: 1px solid var(--line); background: var(--card); color: var(--text);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);
  font-size: 14px; cursor: pointer;
}
.mbtn.on { background: var(--accent); color: var(--accent-text); border-color: transparent; }
.seg-ctl { display: inline-flex; border-radius: 10px; overflow: hidden; border: 1px solid var(--line); box-shadow: 0 1px 3px rgba(0,0,0,.12); }
.seg-ctl .mbtn { border: none; border-radius: 0; box-shadow: none; }
.seg-ctl .mbtn + .mbtn { border-left: 1px solid var(--line); }
.drawbar {
  position: absolute; left: 8px; right: 8px; bottom: 8px;
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  padding: 8px; border-radius: 10px;
  background: var(--card); border: 1px solid var(--line);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.18);
}
.maphint {
  position: absolute; left: 8px; bottom: 8px; max-width: calc(100% - 16px);
  font-size: 12px; color: var(--map-text);
  background: color-mix(in srgb, var(--card) 80%, transparent);
  padding: 3px 8px; border-radius: 8px; pointer-events: none;
}

/* ------------------------------------------------------------ cards */
.card {
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 12px 14px; min-width: 0;
}
.card h2, details.card > summary {
  margin: 0 0 8px; font-size: 13px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted);
}
details.card > summary { cursor: pointer; margin: 0; list-style: none; display: flex; align-items: center; gap: 8px; }
details.card > summary::-webkit-details-marker { display: none; }
details.card > summary::before { content: "▸"; display: inline-block; transition: transform .15s; }
details.card[open] > summary::before { transform: rotate(90deg); }
details.card[open] > summary { margin-bottom: 10px; }
.sumnote { font-weight: 400; text-transform: none; letter-spacing: 0; color: var(--muted); margin-left: auto; font-size: 12px; }

.kv { display: grid; grid-template-columns: auto 1fr; gap: 3px 12px; font-size: 14px; }
.kv > dt { color: var(--muted); }
.kv > dd { margin: 0; text-align: right; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.kv.two { grid-template-columns: auto 1fr auto 1fr; }
.big { font-size: 28px; font-weight: 800; line-height: 1.1; letter-spacing: 0.01em; }
.mid { font-size: 20px; font-weight: 700; }
.sub { color: var(--muted); font-size: 13px; }
.reason { margin: 4px 0 8px; font-weight: 600; }
.reason:empty { display: none; }
.num { font-variant-numeric: tabular-nums; }
.chips { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 6px; }
.chip { font-size: 12px; padding: 1px 7px; border-radius: 999px; border: 1px solid var(--line); color: var(--muted); }
.chip.on { background: var(--accent); color: var(--accent-text); border-color: transparent; }
.chip.alarm { background: var(--bad); color: #fff; border-color: transparent; }
.warnline { color: var(--warn); font-weight: 600; font-size: 13px; margin-top: 6px; }
.badline { color: var(--bad); font-weight: 700; font-size: 13px; margin-top: 6px; }
.okline { color: var(--ok); font-weight: 600; font-size: 13px; margin-top: 6px; }
.warnline:empty, .badline:empty, .okline:empty { display: none; }

.c-ok { color: var(--ok); } .c-warn { color: var(--warn); } .c-bad { color: var(--bad); } .c-muted { color: var(--muted); }

.st-idle { color: var(--st-idle); } .st-ready { color: var(--st-ready); }
.st-aligning { color: var(--st-aligning); } .st-running { color: var(--st-running); }
.st-paused { color: var(--st-paused); } .st-manual { color: var(--st-manual); }
.st-done { color: var(--st-done); } .st-fault { color: var(--st-fault); }
.mission.st-border-fault { border-color: var(--st-fault); box-shadow: 0 0 0 2px color-mix(in srgb, var(--st-fault) 35%, transparent); }

.fix-none { color: var(--fix-none); } .fix-gps { color: var(--fix-gps); } .fix-dgps { color: var(--fix-dgps); }
.fix-rtk_float { color: var(--fix-float); } .fix-rtk_fixed { color: var(--fix-fixed); }

/* ------------------------------------------------------------ buttons */
.btn {
  min-height: 44px; padding: 8px 14px; border-radius: 10px;
  border: 1px solid var(--line); background: var(--card-2); color: var(--text);
  font-weight: 600; cursor: pointer; touch-action: manipulation;
}
.btn:disabled { opacity: 0.42; cursor: not-allowed; }
.btn.primary { background: var(--accent); color: var(--accent-text); border-color: transparent; }
.btn.go { background: var(--ok); color: #fff; border-color: transparent; }
.btn.amber { background: var(--warn); color: #fff; border-color: transparent; }
.btn.danger { background: var(--bad); color: #fff; border-color: transparent; }
.btn.small { min-height: 34px; padding: 4px 10px; font-size: 14px; font-weight: 500; }
.btn.on { outline: 3px solid var(--accent); outline-offset: 1px; }
.btnrow { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.btnrow > .btn { flex: 1 1 auto; }
/* minmax(0, …): a one-word label («ПРОДОЛЖИТЬ») must not set the column's
   minimum, or two columns of 142 px push the page sideways below ~310 px. */
.grid2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; margin-top: 8px; }
.grid2 > .btn { min-width: 0; padding-left: 8px; padding-right: 8px; overflow-wrap: break-word; hyphens: auto; }
/* Narrower than any phone (a split pane): one column, words whole. */
@media (max-width: 300px) { .grid2 { grid-template-columns: minmax(0, 1fr); } }
.ackline { margin-top: 8px; font-size: 13px; color: var(--muted); min-height: 1.2em; overflow-wrap: anywhere; }
.armwhy { font-size: 13px; color: var(--muted); margin-top: 6px; }

/* Safety bar: DISARM and STOP are always on screen and need no control lease.
   They act on the press (pointerdown), so nothing here may turn a press
   into a scroll, a zoom, a selection or a long-press menu. */
.safety {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 30;
  touch-action: none; user-select: none; -webkit-user-select: none; -webkit-touch-callout: none;
  display: grid; grid-template-columns: 1.3fr 1fr; gap: 0 10px;
  padding: 8px 16px calc(8px + env(safe-area-inset-bottom, 0px));
  background: var(--card); border-top: 1px solid var(--line);
  box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.12);
}
.safety .btn { min-height: 58px; font-size: 21px; font-weight: 800; letter-spacing: 0.04em; touch-action: none; }
.safety .btn.pressed { transform: scale(0.96); filter: brightness(1.35); box-shadow: 0 0 0 4px var(--accent); }
/* Status of the last STOP/DISARM, just above the bar (does not change its height). */
.safetymsg {
  position: absolute; left: 16px; right: 16px; bottom: calc(100% + 6px);
  padding: 6px 10px; border-radius: 8px; text-align: center;
  font-weight: 700; font-size: 15px; color: #fff; background: var(--muted);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2); pointer-events: none;
}
.safetymsg.ok { background: var(--ok); }
.safetymsg.bad { background: var(--bad); }
.btn.disarm { background: var(--bad); color: #fff; border: 3px solid color-mix(in srgb, var(--bad) 55%, #000); }
.btn.stop { background: #222; color: #fff; border: 3px solid var(--bad); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .btn.stop { background: #000; } }

/* ------------------------------------------------------------ follow bar */
.xtebar { position: relative; height: 16px; margin: 6px 0 4px; border-radius: 8px; background: var(--card-2); border: 1px solid var(--line); overflow: hidden; }
.xtebar .zero { position: absolute; left: 50%; top: 0; bottom: 0; width: 2px; margin-left: -1px; background: var(--muted); }
.xtebar .band { position: absolute; top: 0; bottom: 0; left: 40%; width: 20%; background: color-mix(in srgb, var(--ok) 20%, transparent); }
.xtebar .mark { position: absolute; top: 1px; bottom: 1px; width: 10px; margin-left: -5px; border-radius: 5px; background: var(--accent); transition: left .1s linear; }
.xtebar .mark.out { background: var(--bad); }
.xtelabels { display: flex; justify-content: space-between; font-size: 11px; color: var(--muted); }

/* ------------------------------------------------------------ joystick */
.joywrap { display: flex; gap: 14px; align-items: center; }
.joy {
  position: relative; flex: 0 0 auto;
  width: 180px; height: 180px; border-radius: 50%;
  background: radial-gradient(circle, var(--card-2) 0 62%, color-mix(in srgb, var(--line) 70%, transparent) 63% 100%);
  border: 2px solid var(--line);
  touch-action: none; user-select: none; -webkit-user-select: none;
}
.joy.disabled { opacity: 0.4; }
.joy.active { border-color: var(--accent); }
.joy .knob {
  position: absolute; left: 50%; top: 50%; width: 64px; height: 64px;
  margin: -32px 0 0 -32px; border-radius: 50%;
  background: var(--accent); box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
  pointer-events: none;
}
.joy .cross { position: absolute; inset: 0; pointer-events: none; }
.joy .cross::before, .joy .cross::after { content: ""; position: absolute; background: var(--line); }
.joy .cross::before { left: 50%; top: 10%; bottom: 10%; width: 1px; }
.joy .cross::after { top: 50%; left: 10%; right: 10%; height: 1px; }
.joyinfo { font-size: 14px; flex: 1; min-width: 0; }

/* ------------------------------------------------------------ editor */
.seglist { list-style: none; margin: 8px 0 0; padding: 0; max-height: 240px; overflow: auto; border: 1px solid var(--line); border-radius: 10px; }
.seglist li { display: grid; grid-template-columns: 2.4em 1fr auto auto; gap: 8px; align-items: center; padding: 7px 10px; border-bottom: 1px solid var(--line); cursor: pointer; font-size: 14px; }
.seglist li:last-child { border-bottom: none; }
.seglist li.sel { background: color-mix(in srgb, var(--route-selected) 14%, transparent); }
.seglist li.cur { font-weight: 700; }
.seglist .n { color: var(--muted); font-variant-numeric: tabular-nums; }
.seglist .tag { font-size: 12px; padding: 0 6px; border-radius: 6px; border: 1px solid var(--line); color: var(--muted); }
.seglist .tag.paint { color: var(--route-paint); border-color: var(--route-paint); }
.segedit { margin-top: 10px; padding: 10px; border-radius: 10px; background: var(--card-2); border: 1px solid var(--line); }
.row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 8px; }
.row label { display: inline-flex; align-items: center; gap: 6px; }
input[type="number"], input[type="text"] {
  min-height: 36px; padding: 4px 8px; border-radius: 8px; border: 1px solid var(--line);
  background: var(--card); width: 7em;
}
input[type="checkbox"] { width: 20px; height: 20px; accent-color: var(--accent); }
input[type="file"] { max-width: 100%; font-size: 13px; }
.filebtn { position: relative; overflow: hidden; display: inline-flex; align-items: center; }
.filebtn input { position: absolute; inset: 0; opacity: 0; cursor: pointer; }
.hr { height: 1px; background: var(--line); margin: 12px 0 4px; }

/* ------------------------------------------------------------ events */
.events { list-style: none; margin: 0; padding: 0; max-height: 320px; overflow: auto; font-size: 13px; }
.events li { display: grid; grid-template-columns: auto 1fr; gap: 2px 8px; padding: 5px 2px; border-bottom: 1px solid var(--line); }
.events time { color: var(--muted); font-variant-numeric: tabular-nums; }
.events .src { color: var(--muted); font-size: 12px; }
.events .lv-debug { color: var(--muted); }
.events .lv-info { color: var(--text); }
.events .lv-warn { color: var(--warn); font-weight: 600; }
.events .lv-error { color: var(--bad); font-weight: 700; }

/* ------------------------------------------------------------ settings */
pre.json {
  margin: 0; max-height: 300px; overflow: auto; font-size: 12px;
  background: var(--card-2); border: 1px solid var(--line); border-radius: 8px; padding: 8px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
textarea.patch {
  width: 100%; min-height: 110px; margin-top: 8px; padding: 8px;
  border-radius: 8px; border: 1px solid var(--line); background: var(--card);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 13px;
}
.cfgmsg { font-size: 13px; margin-top: 6px; overflow-wrap: anywhere; }

/* Geometry sub-card (inside Настройки): sketch, numbers, calibration help. */
.subcard {
  margin: 0 0 12px; padding: 10px 12px; border-radius: 10px;
  background: var(--card-2); border: 1px solid var(--line);
}
.subcard h3, .subhead {
  margin: 0 0 8px; font-size: 13px; font-weight: 700; color: var(--muted);
  display: flex; align-items: center; gap: 8px;
}
.subhead { margin-top: 4px; }
.geoprev { display: block; width: 100%; height: 230px; margin: 4px 0 2px; }
.geoprev .g-body { fill: var(--robot-fill); stroke: var(--robot); stroke-width: 1.5px; vector-effect: non-scaling-stroke; }
.geoprev .g-wd { fill: var(--robot); }
.geoprev .g-wp { fill: var(--card); stroke: var(--robot); stroke-width: 1.5px; vector-effect: non-scaling-stroke; }
.geoprev .g-axle { stroke: var(--muted); stroke-width: 1px; stroke-dasharray: 3 3; vector-effect: non-scaling-stroke; }
.geoprev .g-tc { stroke: var(--robot); stroke-width: 2px; fill: none; vector-effect: non-scaling-stroke; }
.geoprev .g-ant { fill: var(--antenna); stroke: var(--card-2); stroke-width: 1.5px; vector-effect: non-scaling-stroke; }
.geoprev .g-noz { fill: var(--nozzle); stroke: var(--card-2); stroke-width: 1.5px; vector-effect: non-scaling-stroke; }
.geoprev .g-fwd { stroke: var(--muted); stroke-width: 2px; fill: none; stroke-linecap: round; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.geoprev .g-txt { fill: var(--muted); font-family: inherit; }
.geolegend { display: flex; flex-wrap: wrap; gap: 4px 12px; font-size: 12px; color: var(--muted); margin-bottom: 6px; }
.geolegend span { display: inline-flex; align-items: center; gap: 5px; }
.geolegend .sw { display: inline-block; width: 12px; height: 12px; flex: 0 0 auto; }
.geolegend .sw.wd { width: 14px; height: 6px; background: var(--robot); }
.geolegend .sw.wp { width: 14px; height: 6px; border: 1.5px solid var(--robot); }
.geolegend .sw.tc { background: linear-gradient(var(--robot), var(--robot)) center / 100% 2px no-repeat, linear-gradient(var(--robot), var(--robot)) center / 2px 100% no-repeat; }
.geolegend .sw.ant { border-radius: 50%; background: var(--antenna); width: 9px; height: 9px; }
.geolegend .sw.noz { border-radius: 50%; background: var(--nozzle); width: 9px; height: 9px; }
.geonote { margin: 4px 0 8px; }
.geoform { display: flex; flex-direction: column; gap: 4px; }
.georow { display: grid; grid-template-columns: minmax(0, 1fr) 6.5em 2em; align-items: center; gap: 8px; font-size: 14px; }
.georow .geoname { min-width: 0; overflow-wrap: anywhere; }
.georow .geoname code { display: block; font-size: 11px; color: var(--muted); font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
.georow input[type="text"] { width: 100%; text-align: right; font-variant-numeric: tabular-nums; }
.georow input.dirty { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.georow input.bad { border-color: var(--bad); box-shadow: 0 0 0 1px var(--bad); }
.georow .geounit { color: var(--muted); font-size: 13px; }
.geogroup { margin-top: 6px; font-size: 12px; font-weight: 700; color: var(--muted); }
.geoderived { margin-top: 10px; font-size: 13px; }
.geohelp { margin-top: 10px; font-size: 13px; }
.geohelp > summary { cursor: pointer; font-weight: 600; color: var(--accent); }
.geohelp p { margin: 6px 0 0; line-height: 1.45; }
.geohelp code { font-size: 12px; }

/* ------------------------------------------------------------ toasts */
#toasts {
  position: fixed; left: 16px; right: 16px; z-index: 40;
  bottom: calc(var(--safety-h) + 10px + env(safe-area-inset-bottom, 0px));
  display: flex; flex-direction: column; align-items: center; gap: 6px; pointer-events: none;
}
.toast {
  max-width: 520px; width: 100%;
  padding: 10px 14px; border-radius: 10px;
  background: var(--card); color: var(--text); border: 1px solid var(--line);
  border-left: 6px solid var(--info);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.22);
  font-size: 14px; pointer-events: auto;
}
/* Stack the toasts above the stop-command status line while it shows. */
body.safety-msg #toasts { bottom: calc(var(--safety-h) + 54px + env(safe-area-inset-bottom, 0px)); }
.toast.error { border-left-color: var(--bad); }
.toast.warn { border-left-color: var(--warn); }
.toast.ok { border-left-color: var(--ok); }

@media (max-width: 380px) {
  .big { font-size: 24px; }
  .grid2 > .btn { font-size: 14px; }
  .joy { width: 150px; height: 150px; }
  .safety .btn { font-size: 18px; }
}

/* Football pitch dialog (route card) */
.pitchdlg { margin-top: 8px; }
.pitchform { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 6px 10px; }
.pitchform label { display: flex; flex-direction: column; gap: 2px; font-size: 13px; color: var(--muted); }
.pitchform label.chk { flex-direction: row; align-items: center; gap: 6px; grid-column: 1 / -1; }
.pitchform input[type=number], .pitchform select { width: 100%; min-width: 0; box-sizing: border-box; }
.pitchform input, .pitchform select { color: var(--text); }
.pitchform select { min-height: 36px; padding: 4px 8px; border: 1px solid var(--line); border-radius: 8px; background: var(--card-2, transparent); }
.pitchlist li { cursor: default; }

/* ------------------------------------------------------------ demo (mock mode only)
   The simulation says so everywhere (app.js showDisclaimers): a banner row
   in the header, a chip on every card, a caption on the stop bar, a note
   after the panels, a first-visit dialog; the map watermark is drawn on the
   canvas. body.demo is set only in mock mode. */
body.demo { --safety-h: calc(76px + var(--safety-cap-h, 20px)); }
.demobar {
  flex: 1 0 100%;
  margin: 0 -16px calc(-1 * var(--top-py));
  padding: 3px 16px 4px;
  background: color-mix(in srgb, var(--violet) 12%, var(--card));
  border-top: 1px solid color-mix(in srgb, var(--violet) 30%, var(--line));
  font-size: 12.5px; line-height: 1.3;
}
.demobar .long { display: none; }
@media (min-width: 900px) {
  .demobar .short { display: none; }
  .demobar .long { display: inline; }
}
.linkbtn {
  margin: 0 8px 0 6px; padding: 0; border: 0; background: none;
  color: var(--accent); font: inherit; font-weight: 600; text-decoration: underline; cursor: pointer;
}
/* The replay controls flow after the link (its right margin parts them) and wrap to the next line whole. */
.demobar .democtl { vertical-align: middle; white-space: nowrap; }
.demobar .democtl select, .demobar .democtl .mbtn { min-height: 24px; padding: 1px 8px; font-size: 12px; }
/* A narrow header: smaller pills, so it keeps to two rows down to 320 px, in Russian too. */
@media (max-width: 480px) {
  body.demo .top { --top-py: 6px; gap: 4px; }
  body.demo .top .pill { padding: 2px 7px; gap: 4px; font-size: 12px; }
  body.demo .brand { font-size: 14px; margin-right: 2px; }
}
.simchip {
  display: inline-block; margin-left: 6px; padding: 0 6px; border-radius: 999px;
  border: 1px solid currentColor; color: var(--violet);
  font-size: 10px; font-weight: 700; letter-spacing: 0.06em; line-height: 15px; vertical-align: 1px;
}
details.card > summary .simchip { margin-left: 0; }
/* Above the stop buttons, a row of the bar's grid; its height (--safety-cap-h) is measured by app.js. */
.safetycap {
  grid-column: 1 / -1; grid-row: 1;
  padding-bottom: 5px; text-align: center;
  font-size: 12px; line-height: 15px; font-weight: 600; color: var(--muted);
}
.demofoot { margin: 2px 4px 0; font-size: 12px; line-height: 1.45; color: var(--muted); }
.demodlg {
  position: fixed; inset: 0; z-index: 50;
  display: flex; align-items: center; justify-content: center;
  padding: 16px; background: rgba(8, 10, 14, 0.55);
}
.demodlg-box {
  width: 100%; max-width: 520px; max-height: 100%; overflow: auto;
  padding: 18px 18px 16px; border-radius: var(--radius);
  background: var(--card); color: var(--text); border: 1px solid var(--line);
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.35);
}
.demodlg-box h2 { margin: 0 0 10px; font-size: 18px; line-height: 1.25; }
.demodlg-box ul { margin: 0 0 16px; padding-left: 20px; font-size: 14px; line-height: 1.45; }
.demodlg-box li + li { margin-top: 6px; }
.demodlg-box .btn { width: 100%; }
