:root{--bg:#14171c;--panel:#1c2027;--panel2:#232831;--line:#2e343e;--text:#dce1e8;--mute:#8a94a3;--acc:#3fa9f5;--red:#ff4d4d;--amber:#ffb020;--green:#35d46a}
*{box-sizing:border-box}
body{margin:0;background:var(--bg);color:var(--text);font:13px/1.4 system-ui,-apple-system,"Segoe UI",Roboto,sans-serif}
header{padding:10px 16px;border-bottom:1px solid var(--line)}
header h1{font-size:16px;margin:0;font-weight:600}
main{padding:12px;display:grid;grid-template-columns:320px minmax(300px,1fr) minmax(360px,1.2fr);grid-template-areas:"side car right" "side bottom bottom";gap:12px;align-items:start}
aside{grid-area:side}
.car{grid-area:car}
.rightcol{grid-area:right;display:flex;flex-direction:column;gap:12px}
.rightcol>.panel{margin-bottom:0}
.bottom{grid-area:bottom}
@media(max-width:1150px){main{grid-template-columns:320px minmax(0,1fr);grid-template-areas:"side car" "side right" "bottom bottom"}}
@media(max-width:720px){main{grid-template-columns:1fr;grid-template-areas:"side" "car" "right" "bottom"}}
.panel{background:var(--panel);border:1px solid var(--line);border-radius:6px;padding:12px;margin-bottom:12px}
main>.panel{margin-bottom:0}
.panel h2{font-size:11px;text-transform:uppercase;letter-spacing:.07em;color:var(--mute);margin:0 0 10px;font-weight:600}
.mono{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}
select,button,input{font:inherit;color:var(--text)}
input[type=file]{max-width:100%}
select{background:var(--panel2);border:1px solid var(--line);border-radius:4px;padding:4px 6px;max-width:100%}
button{background:var(--panel2);border:1px solid var(--line);border-radius:4px;padding:5px 12px;cursor:pointer}
button:hover:not(:disabled){border-color:var(--acc)}
button:disabled,select:disabled,input:disabled{opacity:.45;cursor:default}
button.primary{background:#1f4f78;border-color:#2c6aa0}
.row{display:flex;align-items:center;justify-content:space-between;gap:8px;margin:6px 0}
.row label,.ctrl label{color:var(--mute)}
.row span{text-align:right;word-break:break-all}
#status{margin-top:10px;font-size:12px;color:var(--mute)}
#status.err{color:var(--red)}
input[type=range]{width:100%;accent-color:var(--acc)}
.ctrl{display:flex;gap:8px;align-items:center;flex-wrap:wrap}

/* car */
#carSvg{width:100%;max-height:640px;display:block}
.body{fill:#3b6ea5;stroke:#9bc0e6;stroke-width:1.5}
.hood{fill:none;stroke:#9bc0e6;stroke-opacity:.5}
.glass{fill:#1a2735;stroke:#9bc0e6;stroke-opacity:.6}
.roof{fill:#33618f;stroke:#9bc0e6;stroke-opacity:.5}
.mirror{stroke:#9bc0e6;stroke-width:4;stroke-linecap:round}
.tire{fill:#121417;stroke:#555c66}
.tread{stroke:#3a3f47;stroke-width:3}
.door{fill:#3b6ea5;stroke:#9bc0e6;stroke-width:1.2}
.door.open{fill:#ffb020;stroke:#ffd27a}
.lamp{stroke:#00000066}
.head{fill:#555}
.head.on{fill:#fffbe0;filter:url(#glow)}
.turn{fill:#5a4520}
.turn.on{fill:var(--amber);filter:url(#glow)}
.brake{fill:#5a1f1f}
.brake.on{fill:#ff2a2a;filter:url(#glow)}
.wlbl{fill:var(--mute);font:10px ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}

/* dashboard */
.gauges{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.gauges svg{width:100%;display:block}
.g-arc{fill:none;stroke:#2e343e;stroke-width:8;stroke-linecap:round}
.g-arc.red{stroke:#7a2323}
.g-tick{stroke:#8a94a3;stroke-width:1.5}
.g-tick.major{stroke:#dce1e8;stroke-width:2.5}
.g-num{fill:#dce1e8;font:11px system-ui,sans-serif;text-anchor:middle;dominant-baseline:middle}
.g-needle{stroke:#ff4d4d;stroke-width:3;stroke-linecap:round}
.g-hub{fill:#2e343e;stroke:#ff4d4d;stroke-width:2}
.g-val{fill:#dce1e8;font:600 22px ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;text-anchor:middle}
.g-unit{fill:#8a94a3;font:11px system-ui,sans-serif;text-anchor:middle}
.dashrow{display:grid;grid-template-columns:90px 1fr 1fr;gap:12px;align-items:center;margin-top:10px}
.lbl{color:var(--mute);font-size:11px}
.gearbox{text-align:center;border:1px solid var(--line);border-radius:6px;padding:8px}
#gear{font-size:38px;font-weight:700}
.wheelbox{text-align:center}
.steer{width:100px;height:100px}
.sw-rim{fill:none;stroke:#8a94a3;stroke-width:8}
.sw-hub{fill:#2e343e;stroke:#8a94a3;stroke-width:2}
.sw-spoke{stroke:#8a94a3;stroke-width:7;stroke-linecap:round}
.sw-mark{fill:var(--amber)}
.pedals{display:flex;gap:18px;justify-content:center}
.pedal{text-align:center}
.pbar{width:26px;height:96px;margin:0 auto 4px;background:var(--panel2);border:1px solid var(--line);border-radius:4px;position:relative;overflow:hidden}
.pbar>div{position:absolute;left:0;right:0;bottom:0;height:0;background:var(--green)}
.pbar.brk>div{background:var(--red)}
.pbar.clu>div{background:var(--amber)}
.pedal .v{font-size:11px}
.levels{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-top:14px}
.lrow{display:flex;justify-content:space-between;margin-bottom:4px}
.hbar{height:10px;background:var(--panel2);border:1px solid var(--line);border-radius:5px;overflow:hidden}
.hbar>div{height:100%;width:0;background:var(--acc)}

/* components */
.comp{fill:#26303c;stroke:#56606d;stroke-width:1.2;cursor:pointer}
.comp *{cursor:pointer}
.comp.ln,.comp.ln *{fill:none;stroke-width:5;stroke-linecap:round;stroke-linejoin:round}
.comp.ln.thin,.comp.ln.thin *{stroke-width:2.5}
.comp.ring{fill:none;stroke-width:3}
.comp.has{fill:#1f4a6e;stroke:#3fa9f5}
.comp.ln.has,.comp.ln.has *{stroke:#3fa9f5;fill:none}
.comp.act{fill:#2f86cc;stroke:#a8dcff}
.comp.ln.act,.comp.ln.act *{stroke:#a8dcff;fill:none}
.comp.sel{stroke:#ffb020;stroke-width:2.5}
.comp.ln.sel,.comp.ln.sel *{stroke:#ffb020}
.comp.ring.has{fill:none}
.spoke{stroke:#56606d;stroke-width:2;pointer-events:none}
.lamp,.door,.tire,.tpms{cursor:pointer}
.tpms{fill:#26303c;stroke:#56606d}
.tpms.has{fill:#1f4a6e;stroke:#3fa9f5}
.tpms.act{fill:#2f86cc;stroke:#a8dcff}
.tpms.sel,.tire.sel,.lamp.sel,.door.sel{stroke:#ffb020;stroke-width:2.5}
.body{fill-opacity:.35}
.chips{display:flex;flex-wrap:wrap;gap:6px;margin-top:10px}
.chip{font-size:11px;padding:3px 8px;border-radius:12px}
.chip.has{border-color:#2c6aa0}
.chip.sel{border-color:var(--amber);color:var(--amber)}
.scroll{overflow:auto;max-height:420px}
.scroll.short{max-height:260px}
.empty{color:var(--mute);padding:10px 6px}
.tabs{display:flex;gap:6px;margin-bottom:10px}
.tab.active{background:#1f4f78;border-color:#2c6aa0}
.detail td,.tabpane td{white-space:nowrap}
th{position:sticky;top:0;background:var(--panel)}

/* mapping */
table{width:100%;border-collapse:collapse}
th,td{text-align:left;padding:4px 6px;border-bottom:1px solid var(--line)}
th{color:var(--mute);font-weight:600;font-size:11px}
td select{width:100%}
td.val{white-space:nowrap;width:140px}
