/* ESPsoup UI (layout "four areas": Scan · Spectrum · Tools · Device). One theme for the whole app (light / dark / auto,
   theme.js sets <html data-theme>), plot colours per look (body[data-ui], read by app.js applyUi()).
   Base components, decoder cards, onboarding, firmware page and fullscreen video kept from the former style.css. */
:root {
  --bg: #f3f5f8; --panel: #ffffff; --panel2: #eef1f5; --panel3: #e4e9ef; --line: #dbe2ea; --text: #15202b; --muted: #5b6977; --faint: #8794a1;
  --accent: #2563eb; --accent-ink: #ffffff; --accent-soft: #2563eb1a; --accent2: #0e9f8e; --danger: #d6336c; --ok: #22914a; --warn-c: #d9480f;
  --shadow: 0 1px 2px #0000000d, 0 4px 16px #0000000f; --radius: 14px;
  --font: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif; --mono: ui-monospace, "Cascadia Mono", "Roboto Mono", Consolas, monospace;
  --top-h: calc(54px + env(safe-area-inset-top)); --bar-h: calc(62px + env(safe-area-inset-bottom)); --rail-w: 0px;
  --cal-bg: #ebfbee; --cal-line: #b2f2bb; --cal-text: #2b6b39;
  color-scheme: light;
}
:root[data-theme=dark] {
  --bg: #0d1318; --panel: #141c23; --panel2: #1b252e; --panel3: #233039; --line: #26323d; --text: #e5ecf1; --muted: #8d9ca8; --faint: #66757f;
  --accent: #5b8cff; --accent-ink: #06142e; --accent-soft: #5b8cff22; --accent2: #2dd4bf; --danger: #ff5c8a; --ok: #40c06a; --warn-c: #ff8a3d;
  --shadow: 0 1px 2px #0006, 0 4px 18px #0005; --cal-bg: #12291a; --cal-line: #24542f; --cal-text: #8ce99a; color-scheme: dark;
}
@media (min-width: 900px) { :root { --bar-h: 0px; --rail-w: 86px; } }
@media (orientation: landscape) and (max-height: 560px) { :root { --bar-h: 0px; --rail-w: calc(72px + env(safe-area-inset-left)); --top-h: 46px; } }

/* ---- plot looks (only the instrument colours change; 'auto' follows the theme) ---- */
body { --plot-bg: #ffffff; --grid: #e7ecf1; --axis: #6b7886; --trace: #2563eb; --hold: #e8590c; --avg: #0ca678; --marker: #d6336c; --wf-bg: #eef1f5; --overlay-text: #8793a0; }
:root[data-theme=dark] body { --plot-bg: #0f171d; --grid: #1e2a33; --axis: #8193a0; --trace: #37c964; --hold: #e6b969; --avg: #5fb8ff; --marker: #ff5c8a; --wf-bg: #0a1014; --overlay-text: #7f96a3; }
body[data-ui=slate] { --plot-bg: #111a1f; --grid: #223038; --axis: #8fa0a8; --trace: #37c964; --hold: #e6b969; --marker: #ff5c8a; --wf-bg: #0b1114; --overlay-text: #7f96a3; }
body[data-ui=studio] { --plot-bg: #000; --grid: #1c232c; --axis: #7c8b9a; --trace: #ffe14d; --hold: #ff6b3d; --marker: #36c5f4; --wf-bg: #000; --overlay-text: #5f7385; }
body[data-ui=pocket] { --plot-bg: #fff; --grid: #e6ebf0; --axis: #6b7886; --trace: #3b5bdb; --hold: #e8590c; --marker: #d6336c; --wf-bg: #f3f5f8; --overlay-text: #8793a0; }
body[data-ui=phosphor] { --plot-bg: #010502; --grid: #0d2a16; --axis: #2f8a4c; --trace: #39ff7a; --hold: #c6ff3d; --marker: #ffd23d; --wf-bg: #000; --overlay-text: #2f7a45; }
body[data-ui=phosphor] .chart canvas { filter: drop-shadow(0 0 2px #39ff7a55); }

* { box-sizing: border-box; }
[hidden] { display: none !important; }
html, body { margin: 0; height: 100%; background: var(--bg); color: var(--text); font: 14.5px/1.4 var(--font); -webkit-tap-highlight-color: transparent; overflow: hidden; }
a { color: var(--accent); }
svg { fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.muted { color: var(--muted); }
.grow { flex: 1 1 auto; min-width: 0; }
.row { display: flex; align-items: center; gap: 8px; }

/* ---- base components ---- */
.mono { font-family: var(--mono); font-size: 12px; }
.chip { background: var(--panel2); border: 1px solid var(--line); border-radius: 12px; padding: 2px 10px; font-size: 12px; color: var(--muted); white-space: nowrap; }
details { border-bottom: 1px solid var(--line); padding: 4px 0 8px; }
summary { cursor: pointer; padding: 10px 0 4px; font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: .08em; color: var(--muted); list-style: none; }
summary::-webkit-details-marker { display: none; }
summary::after { content: '▾'; float: right; transition: transform .15s; }
details:not([open]) summary::after { transform: rotate(-90deg); }
label { display: block; margin: 7px 0; color: var(--muted); font-size: 12px; }
label output { float: right; color: var(--text); }
.unit { float: right; }
input, select, button { font: inherit; color: var(--text); background: var(--panel2); border: 1px solid var(--line); border-radius: 10px; }
button { background: var(--panel); }
input[type=number], input[type=text], input[type=password], input[type=search], select { width: 100%; padding: 7px 10px; margin-top: 3px; min-height: 42px; }
input[type=range] { width: 100%; accent-color: var(--accent); background: none; border: 0; min-height: 28px; }
input[type=checkbox] { accent-color: var(--accent); width: 18px; height: 18px; }
button { padding: 7px 12px; cursor: pointer; min-height: 42px; }
button:hover:not(:disabled) { border-color: var(--accent); }
button:disabled, input:disabled, select:disabled { opacity: .45; cursor: default; }
button.primary { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); font-weight: 650; }
button.ghost { background: transparent; }
button.danger { color: var(--danger); }
.tune { display: flex; gap: 3px; margin-top: 3px; }
.tune input { text-align: center; font-size: 18px; font-weight: 600; margin: 0; }
.tune button { padding: 4px 9px; min-width: 40px; }
.pair { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.pair label { margin: 4px 0; }
.check { display: flex; align-items: center; gap: 8px; color: var(--text); font-size: 13px; min-height: 36px; }
.actions { display: flex; gap: 6px; margin: 8px 0; flex-wrap: wrap; }
.actions button { flex: 1; }
.note { color: var(--muted); font-size: 12px; margin: 4px 0; }
.note.support span { display: block; margin-bottom: 6px; }
.note.support .tip { display: inline-block; margin: 0 6px 4px 0; padding: 6px 12px; border-radius: 999px; color: #fff; font-weight: 600; text-decoration: none; }
.note.support .kofi { background: #ff5e5b; } .note.support .paypal { background: #00457c; }
.badge { display: inline-block; font-size: 11px; padding: 0 6px; border-radius: var(--radius); margin-left: 4px; }
.badge.ok { background: #d3f9d8; color: #1f5f36; } .badge.exp { background: #6b4c1c; color: #ffe8c2; } .badge.no { background: #5c1f22; color: #ffd8da; }
.peaks { width: 100%; border-collapse: collapse; font-size: 12px; font-variant-numeric: tabular-nums; }
.peaks th { text-align: right; color: var(--muted); font-weight: 500; padding: 3px 4px; }
.peaks td { text-align: right; padding: 6px 4px; border-top: 1px solid var(--line); cursor: pointer; }
.peaks tr:hover td { background: var(--panel2); }
.peaks:has(tbody:empty) thead { display: none; }
.peaks tr.pad td { border-top-color: transparent; cursor: default; }
.peaks tr.pad:hover td { background: none; }
.modal { position: fixed; inset: 0; background: #000a; display: flex; align-items: center; justify-content: center; z-index: 30; }
#picker { z-index: 45; }   /* above the firmware page (.fl-page 41), which may use the same chooser */
.modal .sheet-box { background: var(--panel); border: 1px solid var(--line); border-radius: 14px; padding: 14px; width: min(92vw, 380px); display: flex; flex-direction: column; gap: 8px; }
.modal .sheet-box h3 { margin: 0 0 4px; font-size: 16px; }
.modal .sheet-box button { text-align: left; }
.icon-btn { width: 34px; min-width: 34px; height: 34px; min-height: 34px; padding: 0; border-radius: 50%; font-weight: 700; line-height: 1; display: inline-flex; align-items: center; justify-content: center; }


/* ================= app frame: top bar, tab bar / rail, views ================= */
.top { position: fixed; top: 0; left: 0; right: 0; height: var(--top-h); z-index: 20; display: flex; align-items: center; gap: 10px; padding: env(safe-area-inset-top) 12px 0 calc(12px + env(safe-area-inset-left));
  background: var(--panel); border-bottom: 1px solid var(--line); }
.brand { display: flex; align-items: center; gap: 7px; flex: none; }
.brand img { width: 28px; height: 28px; }
.brand b { font-size: 15px; letter-spacing: -.2px; }
.brand b span { color: #e8772e; }
.ttl { margin: 0; flex: 1; min-width: 0; font-size: 17px; font-weight: 700; padding-left: 10px; border-left: 1px solid var(--line); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pill { flex: 0 1 auto; min-width: 0; max-width: 54vw; display: inline-flex; align-items: center; gap: 7px; min-height: 38px; padding: 4px 12px; border-radius: 19px; background: var(--panel2); border: 1px solid var(--line); font-size: 12.5px; color: var(--text); }
.pill > span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.pill .chip { background: none; border: 0; padding: 0 0 0 7px; border-left: 1px solid var(--line); border-radius: 0; color: var(--muted); }
#light { flex: none; width: 9px; height: 9px; border-radius: 50%; background: var(--faint); }
#light.on { background: var(--ok); box-shadow: 0 0 0 3px color-mix(in srgb, var(--ok) 25%, transparent); }
body.disconnected .pill { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); font-weight: 650; }
body.disconnected #light { background: var(--accent-ink); }
@media (max-width: 420px) { .pill .chip { display: none; } .brand b { display: none; } }

#tabbar { position: fixed; left: 0; right: 0; bottom: 0; z-index: 20; height: var(--bar-h); display: flex; padding: 0 env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
  background: var(--panel); border-top: 1px solid var(--line); }
#tabbar button { flex: 1; min-height: 0; border: 0; border-radius: 0; background: none; color: var(--muted); display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px; font-size: 12px; font-weight: 600; padding: 4px 0; }
#tabbar button svg { width: 58px; height: 30px; padding: 3px 17px; border-radius: 15px; transition: background .15s; }
#tabbar button[aria-selected=true] { color: var(--accent); }
#tabbar button[aria-selected=true] svg { background: var(--accent-soft); }
@media (min-width: 900px), (orientation: landscape) and (max-height: 560px) {
  #tabbar { top: var(--top-h); bottom: 0; right: auto; width: var(--rail-w); height: auto; flex-direction: column; justify-content: flex-start; gap: 6px; padding-top: 14px; border-top: 0; border-right: 1px solid var(--line); }
  #tabbar button { flex: none; min-height: 66px; }
}
#main { position: fixed; top: var(--top-h); bottom: var(--bar-h); left: var(--rail-w); right: 0; }
.view { position: absolute; inset: 0; overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; }
body:not([data-tab=scan]) #view-scan, body:not([data-tab=spectrum]) #view-spectrum, body:not([data-tab=tools]) #view-tools, body:not([data-tab=device]) #view-device { display: none; }
.wrap { max-width: 1280px; margin: 0 auto; padding: 12px 14px 28px; }
#error { position: fixed; z-index: 30; top: calc(var(--top-h) + 6px); left: calc(var(--rail-w) + 10px); right: 10px; margin: 0 auto; max-width: 720px; padding: 9px 14px; border-radius: 12px;
  background: color-mix(in srgb, var(--danger) 14%, var(--panel)); border: 1px solid var(--danger); color: var(--text); font-size: 13.5px; box-shadow: var(--shadow); }
.note { color: var(--muted); font-size: 12.5px; margin: 4px 0; }
.note.bad, .fc-msg.bad { color: var(--danger); }
.sec { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; margin: 16px 2px 8px; }
.sec h2, .sec h3 { margin: 0; font-size: 12.5px; text-transform: uppercase; letter-spacing: .07em; color: var(--muted); font-weight: 700; }
.sec > span { color: var(--muted); font-size: 12px; }
.sec .act { min-height: 34px; padding: 4px 8px; border: 0; background: none; color: var(--accent); font-weight: 650; display: inline-flex; align-items: center; gap: 5px; font-size: 13px; }
.sec .act svg { width: 17px; height: 17px; }
.chips { display: flex; gap: 8px; overflow-x: auto; scrollbar-width: none; padding: 2px 0; flex: none; }
.chips::-webkit-scrollbar { display: none; }
.chip { flex: none; display: inline-flex; align-items: center; gap: 6px; min-height: 36px; padding: 5px 12px; border-radius: 18px; border: 1px solid var(--line); background: var(--panel); font-size: 13px; white-space: nowrap; color: var(--text); }
.chip .n { color: var(--muted); font-size: 12px; }
.chip.on { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); font-weight: 600; }
.chip.on .n { color: inherit; }
.chip .lg { width: 10px; height: 10px; border-radius: 3px; display: inline-block; }
.lg-live { background: var(--trace); } .lg-max { background: var(--hold); } .lg-avg { background: var(--avg); }
.list { display: flex; flex-direction: column; gap: 8px; }
.card { background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); padding: 12px 14px; box-shadow: var(--shadow); }
.card h2, .card h3 { margin: 0 0 6px; font-size: 15px; }
.seg { display: flex; background: var(--panel2); border-radius: 12px; padding: 3px; gap: 2px; margin: 6px 0; }
.seg button { flex: 1; border: 0; background: transparent; min-height: 38px; border-radius: 9px; font-weight: 600; color: var(--muted); padding: 4px 8px; }
.seg button.on { background: var(--panel); color: var(--text); box-shadow: 0 1px 3px #0002; }
.setrow { display: flex; align-items: center; gap: 12px; padding: 12px 14px; border-radius: var(--radius); background: var(--panel); border: 1px solid var(--line); width: 100%; text-align: left; min-height: 64px; box-shadow: var(--shadow); color: var(--text); }
.setrow .ic { width: 40px; height: 40px; border-radius: 11px; background: var(--accent-soft); color: var(--accent); display: flex; align-items: center; justify-content: center; flex: none; }
.setrow .ic svg { width: 22px; height: 22px; }
.setrow .st { flex: 1; min-width: 0; } .setrow b { display: block; font-size: 15px; } .setrow small { display: block; color: var(--muted); font-size: 12.5px; }
.setrow .go { color: var(--faint); font-size: 22px; }
.iconbtn { min-width: 44px; width: 44px; height: 44px; min-height: 44px; padding: 0; display: inline-flex; align-items: center; justify-content: center; border-radius: 50%; background: transparent; border-color: transparent; color: var(--text); }
.iconbtn svg { width: 22px; height: 22px; }

/* ================= Scan ================= */
#view-scan .wrap { padding-bottom: 140px; }
.searchbox { display: flex; align-items: center; gap: 8px; padding: 0 6px 0 14px; min-height: 50px; border-radius: 25px; background: var(--panel); border: 1.5px solid var(--line); box-shadow: var(--shadow); margin: 0; color: var(--muted); }
.searchbox:focus-within { border-color: var(--accent); }
.searchbox svg { width: 20px; height: 20px; flex: none; }
.searchbox input { flex: 1; border: 0; background: transparent; min-height: 46px; padding: 0; margin: 0; outline: none; font-size: 15px; color: var(--text); width: auto; }
.searchbox .x { min-width: 38px; width: 38px; height: 38px; min-height: 38px; padding: 0; border-radius: 50%; border: 0; background: transparent; color: var(--muted); }
.qres { display: flex; flex-direction: column; gap: 10px; margin-top: 12px; }
.qres h4 { margin: 6px 2px 0; font-size: 12px; text-transform: uppercase; letter-spacing: .07em; color: var(--muted); }
.ing-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 7px; }
.ing { position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px; padding: 9px 4px 8px; min-height: 76px; border-radius: var(--radius); background: var(--panel);
  border: 1.5px solid var(--line); text-align: center; box-shadow: var(--shadow); color: var(--text); }
.ing .e { font-size: 22px; line-height: 1; }
.ing b { font-size: 12px; font-weight: 650; line-height: 1.2; hyphens: auto; overflow-wrap: anywhere; }
.ing small { display: none; color: var(--muted); font-size: 11.5px; line-height: 1.25; }
.ing .cnt { position: absolute; right: 6px; top: 4px; font-size: 11.5px; font-weight: 750; color: var(--accent); }
.ing.sel { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 9%, var(--panel)); }
.ing.sel::after { content: '✓'; position: absolute; left: 5px; top: 5px; width: 18px; height: 18px; border-radius: 50%; background: var(--accent); color: var(--accent-ink); font-size: 11px; font-weight: 800; display: flex; align-items: center; justify-content: center; }
.ing.busy { animation: ingBusy 1.4s ease-in-out infinite; }
@keyframes ingBusy { 50% { border-color: color-mix(in srgb, var(--accent2) 70%, var(--line)); } }
.ing.off { opacity: .5; box-shadow: none; }
.ing .why { display: block; font-size: 10.5px; color: var(--muted); line-height: 1.15; }
@media (prefers-reduced-motion: reduce) { .ing.busy { animation: none; border-color: var(--accent2); } }
.res { display: flex; align-items: center; gap: 10px; padding: 8px 8px 8px 10px; border-radius: var(--radius); background: var(--panel); border: 1px solid var(--line); box-shadow: var(--shadow); min-height: 62px; cursor: pointer; }
.res .ic { width: 40px; height: 40px; border-radius: 11px; display: flex; align-items: center; justify-content: center; font-size: 20px; background: var(--panel2); flex: none; }
.res .tx { flex: 1 1 auto; min-width: 0; }
.res .tx b { display: block; font-size: 14.5px; font-weight: 650; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.res .tx span { display: block; color: var(--muted); font-size: 12.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.res .meta { text-align: right; font-size: 11.5px; color: var(--muted); flex: none; }
.res .meta b { display: block; color: var(--text); font-size: 12.5px; }
.res .acts { display: flex; gap: 4px; flex: none; }
.res .acts button, .res .find { min-width: 44px; width: 44px; height: 44px; min-height: 44px; padding: 0; border-radius: 11px; display: inline-flex; align-items: center; justify-content: center; background: var(--panel2); border: 0; color: var(--accent); }
.res .acts button svg, .res .find svg { width: 20px; height: 20px; }
.res .acts button:disabled { color: var(--faint); }
.res.alert { border-color: color-mix(in srgb, var(--danger) 55%, var(--line)); }
.res.fresh { animation: resIn .45s ease-out; }
.live { display: inline-block; width: 7px; height: 7px; border-radius: 50%; background: var(--ok); margin-right: 6px; vertical-align: 2px; }
.nb, .res .tx span.nb { display: inline-block; margin: 0 6px 0 0; color: #fff; line-height: 1.4; font-size: 10px; font-weight: 800; color: #fff; background: var(--ok); border-radius: 6px; padding: 1px 5px; vertical-align: 2px; }
@keyframes resIn { from { opacity: 0; transform: translateY(5px); } }
.h-empty, .empty { text-align: center; color: var(--muted); padding: 22px 12px; border: 1px dashed var(--line); border-radius: var(--radius); font-size: 13.5px; }
.res-more { display: flex; justify-content: center; margin-top: 8px; }
.res-more button { min-height: 40px; border-radius: 12px; }
.sig { padding: 12px 14px; border-radius: var(--radius); background: var(--panel); border: 1px solid var(--line); box-shadow: var(--shadow); display: flex; flex-direction: column; gap: 6px; }
.sig .t { display: flex; align-items: center; gap: 10px; }
.sig .t .e { width: 38px; height: 38px; border-radius: 10px; background: var(--panel2); display: flex; align-items: center; justify-content: center; font-size: 19px; flex: none; }
.sig .t b { display: block; font-size: 15px; } .sig .t small { display: block; color: var(--muted); font-size: 12px; }
.sig .fr { font-family: var(--mono); font-size: 12.5px; }
.sig .acts { display: flex; gap: 8px; flex-wrap: wrap; }
.sig .acts button { min-height: 40px; padding: 5px 12px; font-size: 13.5px; }
.sig.no { opacity: .85; border-style: dashed; box-shadow: none; }
.sig .why { color: var(--danger); font-size: 12.5px; }
.actbar { position: fixed; left: var(--rail-w); right: 0; bottom: var(--bar-h); z-index: 15; padding: 8px 12px 6px; background: color-mix(in srgb, var(--panel) 94%, transparent); backdrop-filter: blur(8px); border-top: 1px solid var(--line); }
body:not([data-tab=scan]) .actbar { display: none; }
.ab-row { display: flex; gap: 8px; align-items: stretch; }
.ab-go { flex: 1; min-width: 0; min-height: 50px; font-size: 15.5px; font-weight: 700; border-radius: 14px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ab-go.stop { background: var(--danger); border-color: var(--danger); color: #fff; }
.ab-x { flex: none; width: 50px; padding: 0; font-size: 18px; color: var(--muted); background: var(--panel2); border: 0; border-radius: 14px; }
.ab-opt { flex: none; min-height: 50px; border-radius: 14px; display: inline-flex; align-items: center; gap: 6px; }
.ab-opt svg { width: 19px; height: 19px; }
@media (max-width: 420px) { .ab-opt span { display: none; } .ab-opt { width: 50px; justify-content: center; padding: 0; } }
.ab-st { margin: 4px 2px 0; font-size: 12px; text-align: center; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-height: 16px; }
.ab-st.err { color: var(--danger); }
.ab-prog { position: absolute; left: 0; right: 0; top: 0; height: 3px; }
.ab-prog i { display: block; height: 100%; width: 0; background: var(--accent2); transition: width .35s; }
@media (min-width: 600px) { .ing small { display: block; } .ing { min-height: 92px; } .ing-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (min-width: 900px) {
  .scan-cols { display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr); gap: 22px; align-items: start; }
  .col-r .sec:first-child { margin-top: 2px; }
  .actbar { right: auto; width: calc((100vw - var(--rail-w)) * .51); max-width: 680px; }
}

/* ================= Spectrum ================= */
#view-spectrum { overflow: hidden; }
.spec-wrap { position: absolute; inset: 0; display: flex; }
.spec-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 5px; padding: 6px 12px 6px; min-height: 0; }
.spec-main > * { flex: none; }
.charts-home { flex: 1 1 auto; min-height: 0; display: flex; }
.charts { flex: 1; min-height: 0; display: flex; flex-direction: column; gap: 6px; }
.chart { position: relative; background: var(--plot-bg); border: 1px solid var(--line); border-radius: 12px; flex: 1 1 42%; display: flex; min-height: 80px; overflow: hidden; }
.chart.water { flex: 1 1 58%; background: var(--wf-bg); }
.chart canvas { flex: 1; width: 100%; min-height: 0; display: block; cursor: crosshair; touch-action: none; }
#empty { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; color: var(--muted); pointer-events: none; text-align: center; padding: 12px; }
#empty .big { font-size: 40px; color: var(--accent); } #empty h2 { margin: 6px 0; color: var(--text); font-size: 16px; } #empty p { margin: 0; font-size: 12.5px; }
#warn { padding: 6px 6px 6px 10px; border-radius: 10px; font-size: 12.5px; background: color-mix(in srgb, var(--warn-c) 13%, var(--panel)); border: 1px solid color-mix(in srgb, var(--warn-c) 45%, var(--line)); }
#warn:not([hidden]) { display: flex; align-items: center; gap: 6px; } #warn > span { flex: 1; min-width: 0; }
#warn .warn-x { flex: none; width: 32px; height: 32px; min-height: 32px; padding: 0; border: 0; background: none; font-size: 20px; }
.bandrow { display: flex; gap: 8px; align-items: center; min-width: 0; }
.bandrow .bandchips { flex: 1 1 auto; min-width: 0; }
.bandrow select { flex: 0 0 auto; width: 46px; min-height: 34px; margin: 0; padding: 2px 4px; border-radius: 17px; color: transparent; background: var(--panel) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238794a1' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M4 7h16M4 12h16M4 17h10'/%3E%3C/svg%3E") center/20px no-repeat; }
.bandrow select option, .bandrow select optgroup { color: var(--text); }
.bandchips .chip { min-height: 34px; }
.bandchips select { flex: none; width: auto; min-height: 34px; margin: 0; padding: 3px 8px; border-radius: 17px; font-size: 13px; }
.band-info:empty { display: none; }
#pause .i-play, #pause.paused .i-pause { display: none; } #pause.paused .i-play { display: block; }
.toolrow { display: flex; align-items: center; gap: 4px; min-height: 38px; }
.rxinfo { flex: 1; min-width: 0; color: var(--muted); font-size: 12.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#cursor, #zoomInfo { color: var(--muted); font-size: 11.5px; white-space: nowrap; }
#cursor:empty, #zoomInfo:empty { display: none; }
.readout { display: flex; align-items: center; gap: 6px; padding: 5px 6px 5px 12px; border-radius: 12px; background: var(--panel); border: 1px solid var(--line); min-height: 52px; }
.readout .tx { flex: 1; min-width: 0; font-size: 12px; line-height: 1.3; }
.readout .tx > * { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.readout .tx .sep { display: none; }
.readout .tx b { font-family: var(--mono); font-size: 13.5px; }
.readout .tx #roB { color: var(--text); }
.readout button { flex: none; min-height: 44px; min-width: 62px; padding: 3px 6px; font-size: 11px; font-weight: 650; border-radius: 10px; display: inline-flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px; color: var(--accent); }
.readout button svg { width: 19px; height: 19px; }
.statline { display: flex; gap: 12px; color: var(--muted); font-size: 11.5px; white-space: nowrap; overflow: hidden; padding: 0 2px; }
.statline b { color: var(--text); font-variant-numeric: tabular-nums; }
.statline > div { flex: none; } .statline > div:has(#marker), .statline > div:has(#peak), #crc { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
@media (max-width: 520px) { #crc { display: none; } .statline > div:has(#marker) { display: none; } }
.spec-side { display: none; width: 340px; flex: none; border-left: 1px solid var(--line); background: var(--panel); overflow-y: auto; padding: 4px 16px 20px; }
.rx-panel h3 { font-size: 12.5px; text-transform: uppercase; letter-spacing: .07em; color: var(--muted); margin: 16px 0 2px; }
.rx-panel h3:first-child { margin-top: 8px; }
@media (min-width: 900px) { .spec-side { display: block; } #setBtn { display: none; } }
@media (orientation: landscape) and (max-height: 560px) { .bandchips, .band-info, .statline { display: none; } .spec-main { gap: 4px; padding-top: 4px; } }

/* ---- VFO (freqctl.js) ---- */
.fc { display: flex; align-items: center; gap: 4px; }
.fc .pm { flex: none; min-width: 40px; width: 40px; height: 40px; min-height: 40px; padding: 0; border-radius: 50%; font-size: 22px; line-height: 1; display: inline-flex; align-items: center; justify-content: center; background: var(--panel2); border: 0; color: var(--text); }
.fc-disp { position: relative; display: flex; align-items: baseline; padding: 0 6px; border-radius: 10px; cursor: text; touch-action: none; user-select: none; -webkit-user-select: none; outline: none; }
.fc-disp:focus-visible { box-shadow: 0 0 0 2px var(--accent); }
.fc-disp .d { font: 700 34px/1.12 var(--mono); letter-spacing: -1px; padding: 0 .5px; border-radius: 4px; font-variant-numeric: tabular-nums; }
.fc-disp .d.lo { font-size: 23px; color: var(--muted); }
.fc-disp .d.z { color: var(--faint); opacity: .55; }
.fc-disp .d.hot { background: var(--accent-soft); color: var(--accent); }
.fc-disp .sep { font: 700 28px/1 var(--mono); color: var(--muted); }
.fc-disp .sp { width: 5px; }
.fc-disp.bad .d:not(.z) { color: var(--danger); }
.fc-disp.bad { background: repeating-linear-gradient(135deg, transparent 0 7px, color-mix(in srgb, var(--danger) 12%, transparent) 7px 14px); }
.fc-unit { color: var(--muted); font-size: 13px; margin-right: 2px; }
.fc-edit { display: flex; gap: 6px; align-items: center; margin-top: 2px; }
.fc-edit input { font: 700 21px var(--mono); min-height: 46px; margin: 0; flex: 1; min-width: 0; }
.fc-edit button { min-height: 46px; }
.fc-line { display: flex; align-items: center; gap: 8px; min-height: 30px; }
.fc-msg { flex: 1; min-width: 0; font-size: 12.5px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin: 0; }
.fc-line { flex-wrap: wrap; }
.fc-line.bad .fc-msg { flex-basis: 100%; white-space: normal; }
.fc-line.bad .fc-near { margin-left: 0; }
.fc-line .fc-step { margin-left: auto; }
.fc-wrap.editing .fc-msg { white-space: normal; }
.fc-msg.ok::before { content: '✓ '; color: var(--ok); font-weight: 800; }
.fc-near { display: inline-flex; align-items: center; min-height: 28px; padding: 1px 10px; font-size: 12.5px; border-radius: 14px; border-color: var(--danger); color: var(--danger); background: transparent; margin-left: 4px; }
.fc-step { flex: none; width: auto; min-height: 32px; margin: 0; padding: 2px 6px; font-size: 12.5px; border-radius: 10px; }
.fc-wrap.editing .fc-step { display: none; }
@media (max-width: 360px) { .fc-disp .d { font-size: 30px; } .fc-disp .d.lo { font-size: 20px; } }

/* ================= Tools ================= */
.tool-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.tool { display: flex; flex-direction: column; align-items: flex-start; gap: 5px; padding: 13px; min-height: 124px; border-radius: var(--radius); background: var(--panel); border: 1px solid var(--line); box-shadow: var(--shadow); text-align: left; color: var(--text); }
.tool .ic { width: 44px; height: 44px; border-radius: 12px; background: var(--accent-soft); color: var(--accent); display: flex; align-items: center; justify-content: center; }
.tool .ic svg { width: 24px; height: 24px; }
.tool b { font-size: 15px; } .tool small { color: var(--muted); font-size: 12.5px; line-height: 1.3; }
.tool .st { font-size: 11.5px; font-weight: 750; color: var(--ok); } .tool .st:empty { display: none; }
.tool.off { opacity: .55; } .tool.off .st { color: var(--muted); }
.tools-note { margin-top: 14px; }
@media (min-width: 900px) { .tool-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

/* full-screen tool page (shell.js openPage) */
.page { position: fixed; top: 0; bottom: 0; left: var(--rail-w); right: 0; z-index: 35; background: var(--bg); display: flex; flex-direction: column; }
.page .pg-h { flex: none; display: flex; align-items: center; gap: 6px; padding: calc(6px + env(safe-area-inset-top)) 10px 6px; background: var(--panel); border-bottom: 1px solid var(--line); min-height: var(--top-h); }
.page .pg-h h2 { margin: 0; font-size: 18px; flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.page .pg-h h2 small { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden; font-size: 12px; color: var(--muted); font-weight: 500; white-space: normal; line-height: 1.3; }
.page .pg-b { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: 12px 14px 28px; }
.page .pg-b > .tp { max-width: 980px; margin: 0 auto; display: flex; flex-direction: column; gap: 8px; }
.page .pg-b.fill { display: flex; flex-direction: column; }
.page .pg-b.fill > .tp { flex: 1; min-height: 0; width: 100%; }
.tp-h { font-size: 12.5px; text-transform: uppercase; letter-spacing: .07em; color: var(--muted); margin: 18px 0 2px; }
.chart-slot { display: flex; min-height: 0; }
.chart-slot .charts { min-height: 320px; }
.page .pg-b.fill .chart-slot { flex: 1 1 auto; }
.chart-slot.small .charts { min-height: 180px; max-height: 240px; }
.pano-ctl { display: flex; gap: 8px; align-items: flex-end; flex-wrap: wrap; }
.pano-ctl label.inl { margin: 0; flex: 1 1 180px; }
.pano-ctl #panoRun { min-height: 44px; min-width: 120px; }
.pano-range { display: flex; align-items: flex-end; gap: 8px; }
.pano-range label { flex: 1; margin: 0; } .pano-range .dash, .pano-range .unit { padding-bottom: 12px; color: var(--muted); }
.pano-range input.bad, input.bad { border-color: var(--danger); }
details.opts { border: 1px solid var(--line); border-radius: 12px; padding: 0 12px; background: var(--panel); }
details.opts summary { padding: 10px 0; color: var(--muted); font-size: 13px; cursor: pointer; }
.find-vfo { margin-bottom: 4px; }
#tp-find .fx-row label:first-child { display: none; }   /* the VFO above sets the frequency */
.fmh-st { margin: 4px 0; font-size: 13px; color: var(--muted); }
.fmh-map { position: relative; height: min(52vh, 420px); min-height: 260px; border-radius: 14px; overflow: hidden; background: var(--panel2); border: 1px solid var(--line); }
.fmh-leaflet { position: absolute; inset: 0; }
.fmh-acts { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 8px; }
.fmh-est { font-size: 22px; line-height: 26px; text-align: center; background: none; border: 0; text-shadow: 0 0 3px #fff; }
.board-card .row { margin-bottom: 8px; } .board-card b { display: block; } .board-card small { display: block; color: var(--muted); font-size: 12.5px; }
.s-dot { width: 10px; height: 10px; border-radius: 50%; background: var(--faint); flex: none; } .s-dot.on { background: var(--ok); }

/* ================= Device ================= */
.dev-grid { display: flex; flex-direction: column; gap: 12px; max-width: 760px; }
.dev-grid .card h2 { font-size: 16px; }
@media (min-width: 1100px) { .dev-grid { max-width: 1180px; display: grid; grid-template-columns: 1fr 1fr; align-items: start; } }

/* ================= sheets (bottom on phones, floating on desktop) ================= */
.scrim { position: fixed; inset: 0; z-index: 50; background: #0007; }
.sheet { position: fixed; left: 0; right: 0; bottom: 0; max-height: 84vh; z-index: 51; background: var(--panel); border-radius: 20px 20px 0 0; box-shadow: 0 -8px 30px #0004; display: flex; flex-direction: column; padding-bottom: env(safe-area-inset-bottom); }
.sheet .sh-grab { width: 42px; height: 5px; border-radius: 3px; background: var(--line); margin: 7px auto 0; }
.sheet .sh-h { display: flex; align-items: center; gap: 8px; padding: 4px 8px 6px 18px; border-bottom: 1px solid var(--line); }
.sheet .sh-h h3 { margin: 0; font-size: 17px; flex: 1; }
.sheet .sh-b { overflow-y: auto; overscroll-behavior: contain; padding: 8px 16px 18px; }
@media (min-width: 900px) { .sheet { left: auto; right: 18px; bottom: 18px; width: 440px; border-radius: 18px; } }
.kv { display: grid; grid-template-columns: auto 1fr; gap: 5px 12px; font-size: 13.5px; margin-bottom: 10px; } .kv > span:nth-child(odd) { color: var(--muted); } .kv .mono { font-family: var(--mono); }
.exp-acts { display: flex; gap: 8px; flex-wrap: wrap; }
.exp-acts button { flex: 1 1 auto; }

/* airplane-mode hint (radiohint.js) */
.rh-modal { position: fixed; inset: 0; z-index: 60; background: #0008; display: flex; align-items: flex-end; justify-content: center; padding: 12px; }
.rh-box { width: min(100%, 460px); background: var(--panel); border-radius: 20px; padding: 18px 18px 12px; box-shadow: 0 10px 40px #0006; margin-bottom: env(safe-area-inset-bottom); }
.rh-box .rh-ic { font-size: 30px; } .rh-box h3 { margin: 6px 0; font-size: 18px; } .rh-box p { margin: 6px 0; font-size: 14px; } .rh-box .rh-note { color: var(--muted); font-size: 12.5px; }
.rh-acts { display: flex; gap: 8px; flex-wrap: wrap; margin: 12px 0 6px; } .rh-acts button { flex: 1 1 auto; min-height: 46px; }
.rh-off { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--muted); min-height: 40px; }
@media (min-width: 700px) { .rh-modal { align-items: center; } }

/* finds: Find / Watch buttons in decoder cards and map lists */
#decTable .dec-find .find { flex: none; display: inline-flex; align-items: center; justify-content: center; gap: 5px; min-height: 36px; padding: 4px 12px; border-radius: 12px; border: 0; background: var(--accent); color: #fff; font-weight: 650; font-size: 13px; }
#decTable .dec-find .find svg { width: 16px; height: 16px; }
#decTable td.dec-find { order: 1; flex: none; align-self: center; }
.burners { display: flex; flex-direction: column; gap: 8px; margin: 6px 0 10px; }
.burner { display: flex; align-items: center; gap: 12px; padding: 10px 12px; border-radius: 14px; background: var(--panel2); }
.burner > div { flex: 1; min-width: 0; } .burner b { display: block; font-size: 14px; } .burner span:not(.s-dot) { display: block; color: var(--muted); font-size: 12px; }
#langSel { width: 100%; }
.pwa-update { position: fixed; left: 50%; transform: translateX(-50%); bottom: calc(var(--bar-h) + 80px); z-index: 50; border-radius: 14px; }
.m-map { height: min(52vh, 460px); min-height: 280px; }
.m-map .fm-map { height: 100%; }
.m-map .fm-btn { background: var(--panel); color: var(--text); border-color: var(--line); box-shadow: var(--shadow); }
.m-map .fm-stage { border-radius: 16px; }
.fx-src { font-size: 12.5px; font-weight: 650; color: var(--accent2); }
.fx-src[hidden] { display: none; }
.fx-row[hidden], .fx-actions button[hidden] { display: none; }
.fx-recwf { width: 100%; height: 220px; border-radius: 12px; background: #0b1114; }
.fx-recwf[hidden] { display: none; }
.fx-rec-i { flex: none; width: 34px; height: 34px; border-radius: 10px; display: flex; align-items: center; justify-content: center; font-size: 18px; background: var(--panel2); }
.fx-rec-n { margin-left: auto; flex: none; font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }
.tp .fx > .fx-head b { display: none; }   /* the page header already shows the title */
.cal { background: var(--cal-bg); border-color: var(--cal-line); }

/* ---- decoder cards (Identify page) ---- */
/* Decoder panel + results as live cards (mockup A, screen 2) */
#decodeSide summary { font-size: 13px; color: var(--text); padding-top: 14px; }
#decodeSide details { border: 0; }
.dec-row { display: grid; grid-template-columns: 1fr auto; gap: 10px; align-items: end; }
.dec-row .check { margin: 7px 0; min-height: 38px; }
#fpvFrame { display: block; width: 100%; aspect-ratio: 4 / 3; image-rendering: pixelated; border-radius: 12px; background: #000; margin-top: 6px; }
#fpvFrame[hidden] { display: none; }
#decTable { border-collapse: separate; border-spacing: 0; margin-top: 6px; }
#decTable thead { display: none; }
#decTable tbody { display: flex; flex-direction: column; gap: 9px; }
#decTable tr { position: relative; display: flex; flex-wrap: wrap; align-items: baseline; column-gap: 6px; row-gap: 3px; background: var(--panel2); border: 1px solid var(--line); border-radius: 16px; padding: 11px 12px 11px 66px; min-height: 66px; animation: decIn .35s ease-out; }
#decTable tr::before { content: var(--dec-ic, '📡'); position: absolute; left: 12px; top: 50%; transform: translateY(-50%); width: 42px; height: 42px; border-radius: 12px; background: var(--dec-bg, #1d2f45); display: flex; align-items: center; justify-content: center; font-size: 21px; }
#decTable td { border: 0; padding: 0; text-align: left; cursor: default; background: none !important; }
#decTable td:empty { display: none; }
#decTable td:nth-child(1) { order: 0; flex: 1 1 0; min-width: 0; font-size: 15px; font-weight: 700; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#decTable td:nth-child(5) { order: 1; flex: none; color: var(--accent); font-size: 12px; font-weight: 600; background: color-mix(in srgb, var(--accent) 14%, transparent) !important; border-radius: 8px; padding: 1px 7px; }
#decTable:not([data-kind=lte]) td:nth-child(5)::before { content: '×'; opacity: .7; }
/* LTE: "Operator · cell PCI" as the card title */
#decTable[data-kind=lte] td:nth-child(3) { order: -1; flex: none; font-size: 15px; font-weight: 700; color: var(--text); }
#decTable[data-kind=lte] td:nth-child(3)::before { content: none; }
#decTable[data-kind=lte] td:nth-child(1)::before { content: '· cell '; font-weight: 600; color: var(--muted); }
#decTable[data-kind=lte] td:nth-child(4)::before { content: none; }
#decTable[data-kind=lte] td:nth-child(2)::after { content: ' ·'; opacity: .7; }
#decTable td:nth-child(2), #decTable td:nth-child(3), #decTable td:nth-child(4) { order: 2; color: var(--muted); font-size: 12.5px; }
#decTable td:nth-child(3)::before, #decTable td:nth-child(4)::before { content: '· '; opacity: .7; }
#decTable tr::after { content: ''; order: 1; flex-basis: 100%; height: 0; }
#decTable[data-kind=ble] { --dec-ic: '🔵'; --dec-bg: #16303a; }
#decTable[data-kind=zigbee] { --dec-ic: '🏠'; --dec-bg: #1e3326; }
#decTable[data-kind=nrf24] { --dec-ic: '⚡'; --dec-bg: #3a3217; }
#decTable[data-kind=fpv] { --dec-ic: '🎥'; --dec-bg: #3a1c2c; }
#decTable[data-kind=classify] { --dec-ic: '🎮'; --dec-bg: #2c1f3d; }
#decTable[data-kind=lte] { --dec-ic: '📶'; --dec-bg: #1d2f45; }
#decTable[data-kind=rid] { --dec-ic: '🛸'; --dec-bg: #16352c; }
#decTable[data-kind=mw] { --dec-ic: '🍲'; --dec-bg: #3a2a14; }
#decTable[data-kind=cam] { --dec-ic: '📹'; --dec-bg: #2a2140; }
#decTable[data-kind=wifib] { --dec-ic: '📡'; --dec-bg: #1a2d45; }
#decTable[data-kind=ant] { --dec-ic: '❤'; --dec-bg: #3a1a1e; }
body[data-ui=pocket] #decTable tr::before { filter: saturate(.8) brightness(1.6); }
.dec-empty { color: var(--muted); font-size: 13px; text-align: center; padding: 22px 12px; border: 1px dashed var(--line); border-radius: 16px; margin: 10px 0; }
@keyframes decIn { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }

/* ---- Onboarding overlay + Flasher modal (additive) ---- */
.ob-modal { position: fixed; inset: 0; z-index: 40; background: #000b; display: flex; align-items: center; justify-content: center; padding: 12px; }
.ob-sheet { background: var(--panel); color: var(--text); border: 1px solid var(--line); border-radius: 14px; width: min(100%, 560px); max-height: 92vh; max-height: 92svh; display: flex; flex-direction: column; overflow: hidden; box-shadow: 0 10px 40px #0007; }

/* Onboarding */
.ob-dots { display: flex; gap: 8px; justify-content: center; padding: 16px 0 4px; }
.ob-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--line); }
.ob-dot.on { background: var(--accent); }
.ob-scroll { overflow-y: auto; padding: 8px 18px 4px; -webkit-overflow-scrolling: touch; }
.ob-content { display: flex; flex-direction: column; gap: 10px; }
.ob-badge { align-self: center; font-size: 30px; line-height: 1; background: var(--panel2); border: 1px solid var(--line); border-radius: 14px; padding: 10px 16px; }
.ob-badge img { display: block; width: 44px; height: 44px; margin: -4px -6px; }
.ob-title { margin: 4px 0 0; text-align: center; font-size: 20px; color: var(--text); }
.ob-lead { margin: 0 0 4px; text-align: center; color: var(--muted); font-size: 14px; }
.ob-card { background: var(--panel2); border: 1px solid var(--line); border-radius: 12px; padding: 10px 14px; }
.ob-card h4 { margin: 0 0 6px; font-size: 13px; color: var(--text); }
.ob-list { margin: 0; padding-left: 18px; color: var(--muted); font-size: 13px; }
.ob-list li { margin: 4px 0; }
.ob-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 4px 0; }
.ob-actions .primary, .ob-flash { flex: 0 0 auto; }
.ob-fwwhere { color: var(--muted); font-size: 13px; margin: 10px 0 0; }
.ob-credit { color: var(--muted); font-size: 12px; margin: 6px 0 0; overflow-wrap: anywhere; }
.ob-credit a { color: var(--accent); text-decoration: underline; }
.ob-foot { border-top: 1px solid var(--line); padding: 12px 18px calc(12px + env(safe-area-inset-bottom)); display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.ob-dontshow { display: flex; align-items: center; gap: 8px; color: var(--muted); font-size: 12px; margin: 0; }
.ob-dontshow input { width: 18px; height: 18px; accent-color: var(--accent); }
.ob-nav { display: flex; gap: 8px; margin-left: auto; }
.ob-nav button, .ob-skip, .ob-back, .ob-next { min-height: 42px; padding: 8px 16px; }
.ob-skip, .ob-back { background: transparent; }

@media (max-width: 480px) {
  .ob-modal { padding: 0; }
  .ob-sheet { width: 100%; height: 100%; max-height: 100%; border: 0; border-radius: 0; padding-top: env(safe-area-inset-top); }
  .ob-scroll { flex: 1 1 auto; min-height: 0; }   /* full-screen sheet: footer stays at the bottom */
  .ob-nav { width: 100%; }
  .ob-nav .ob-next { margin-left: auto; }
}

/* Firmware page (flash.js): full-screen page with a back button; on wide screens next to the navigation rail.
   Header · cards (board, firmware, options, verification) · log panel (≥ 35 % of the screen, always visible) · sticky dock. */
.fl-page { position: fixed; top: 0; bottom: 0; left: var(--rail-w); right: 0; z-index: 41; display: flex; flex-direction: column;
  background: var(--bg); color: var(--text); padding: env(safe-area-inset-top) env(safe-area-inset-right) 0 0; }
.fl-top { flex: none; display: flex; align-items: center; gap: 10px; padding: 8px 14px; background: var(--panel); border-bottom: 1px solid var(--line); }
.fl-back { width: 42px; height: 42px; min-height: 42px; padding: 0 0 3px; border-radius: 50%; border: 0; font-size: 28px; line-height: 1; flex: none;
  background: color-mix(in srgb, var(--accent) 12%, var(--panel)); color: var(--accent); }
.fl-top-t { min-width: 0; }
.fl-top h2 { margin: 0; font-size: 20px; letter-spacing: -.3px; }
.fl-attrib { display: block; color: var(--muted); font-size: 12px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fl-body { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.fl-scroll { flex: 1 1 auto; min-height: 80px; overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; padding: 10px 14px; display: flex; flex-direction: column; gap: 10px; }
.fl-cards { display: flex; flex-direction: column; gap: 10px; }
.fl-intro { margin: 0; }
.fl-card { background: var(--panel); border: 1px solid var(--line); border-radius: 14px; padding: 10px 12px; display: flex; flex-direction: column; gap: 8px; box-shadow: var(--shadow, none); }
.fl-card h3 { margin: 0; font-size: 12px; text-transform: uppercase; letter-spacing: .07em; color: var(--muted); font-weight: 650; }
.fl-card-h { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.fl-mini { min-height: 30px; padding: 3px 10px; font-size: 12px; border-radius: 8px; }
.fl-field { display: flex; flex-direction: column; gap: 6px; }
.fl-lbl { color: var(--muted); font-size: 12px; text-transform: uppercase; letter-spacing: .06em; }
.fl-radio { display: flex; align-items: center; gap: 8px; color: var(--text); font-size: 13px; margin: 2px 0; }
.fl-radio input { width: 18px; height: 18px; accent-color: var(--accent); flex: none; }
.fl-license { color: var(--muted, #8a8f98); font-weight: 500; }   /* bundled ESPsoup firmware: licence note */
.fl-filerow { display: flex; flex-direction: column; gap: 4px; color: var(--muted); font-size: 12px; }
.fl-device { color: var(--text); font-size: 12.5px; margin: 0; }
.fl-boards { display: flex; flex-direction: column; gap: 6px; }
.fl-board { display: flex; align-items: flex-start; gap: 10px; margin: 0; padding: 8px 10px; border: 1px solid var(--line); border-radius: 12px; background: var(--panel2); color: var(--text); cursor: pointer; }
.fl-board.sel { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 8%, var(--panel)); }
.fl-board input { width: 18px; height: 18px; margin: 2px 0 0; accent-color: var(--accent); flex: none; }
.fl-board-t { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.fl-board-t b { font-size: 14px; }
.fl-board-t small { color: var(--muted); font-size: 11.5px; overflow-wrap: anywhere; }
.fl-board-t .fl-board-fw { color: var(--ok, #2f9e44); font-weight: 600; }
.fl-board-t .fl-board-fw.unk { color: var(--muted); font-weight: 400; font-style: italic; }
.fl-tag { font-style: normal; font-size: 10.5px; font-weight: 650; margin-left: 6px; padding: 1px 6px; border-radius: 6px; vertical-align: 1px;
  background: color-mix(in srgb, var(--accent2, #3b5bdb) 15%, transparent); color: var(--accent2, #3b5bdb); }
.fl-credit { margin: 8px 0 0; font-size: 12px; overflow-wrap: anywhere; }
.fl-credit a { color: var(--accent); text-decoration: underline; }
.fl-board-t .fl-board-upd { color: var(--warn-c, #d9480f); font-weight: 650; }
/* Device page: update hint for boards with the original ESP-SDR or an older ESPsoup (shell_pantry.js) */
.fw-upd { margin: 0; padding: 10px 12px; border-radius: var(--radius); background: color-mix(in srgb, var(--warn-c) 12%, var(--panel)); border: 1px solid color-mix(in srgb, var(--warn-c) 50%, var(--line)); }
.fw-upd b { display: block; color: var(--warn-c); font-size: 14.5px; }
.fw-upd p { margin: 4px 0 8px; font-size: 12.5px; color: var(--text); }
.fw-upd button { width: auto; }
.fl-steps { margin: 0; padding-left: 18px; color: var(--muted); font-size: 13px; }
.fl-steps li { margin: 4px 0; }
/* log: terminal colours in both themes */
.fl-logcard { flex: 0 0 auto; height: 35vh; height: 35svh; min-height: 150px; display: flex; flex-direction: column; margin: 0 14px 8px;
  border: 1px solid var(--line); border-radius: 12px; overflow: hidden; background: #0f171c; }
.fl-log-h { flex: none; display: flex; align-items: center; justify-content: space-between; gap: 6px; padding: 4px 6px 4px 10px; background: #18232a; }
.fl-log-h .fl-lbl { color: #9fb2bd; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fl-log-acts { display: flex; gap: 4px; flex: none; }
.fl-log-h .fl-mini { background: #22303a; color: #dbe6ec; border-color: #33434e; min-height: 28px; padding: 2px 8px; }
.fl-log { flex: 1 1 auto; min-height: 0; overflow: auto; margin: 0; padding: 6px 8px; color: #d3dfe6; background: none; border: 0;
  font-family: var(--mono); font-size: 11px; line-height: 1.45; white-space: pre-wrap; word-break: break-word; overscroll-behavior: contain; }
.fl-log .ll b { color: #6f8794; font-weight: 400; }
.fl-log .ll-ok { color: #8ce99a; }
.fl-log .ll-err { color: #ff8787; }
.fl-log .ll-part { color: #9fb2bd; }
.fl-page.logfull .fl-scroll { display: none; }
.fl-page.logfull .fl-logcard { flex: 1 1 auto; height: auto; margin-top: 8px; }
/* sticky dock: steps, progress, status, error, buttons */
.fl-dock { flex: none; padding: 8px 14px calc(8px + env(safe-area-inset-bottom)); background: var(--panel); border-top: 1px solid var(--line); display: flex; flex-direction: column; gap: 5px; }
.fl-dock .actions { margin: 2px 0 0; }
.fl-dock .actions button { min-height: 42px; }
.fl-stepbar { display: flex; gap: 3px; margin: 0; padding: 0; list-style: none; }
.fl-stepbar li { flex: 1 1 0; min-width: 0; display: flex; align-items: center; justify-content: center; gap: 3px; padding: 3px 2px; border-radius: 8px;
  background: var(--panel2); color: var(--muted); font-size: 10.5px; white-space: nowrap; overflow: hidden; }
.fl-stepbar li span { overflow: hidden; text-overflow: ellipsis; }
.fl-stepbar li i { font-style: normal; font-weight: 700; font-size: 10px; flex: none; }
.fl-stepbar li[data-st=active] { background: color-mix(in srgb, var(--accent) 18%, var(--panel)); color: var(--accent); font-weight: 650; }
.fl-stepbar li[data-st=done] { background: color-mix(in srgb, var(--ok, #2f9e44) 16%, var(--panel)); color: var(--ok, #2f9e44); }
.fl-stepbar li[data-st=done] i { font-size: 0; }
.fl-stepbar li[data-st=done] i::before { content: '✓'; font-size: 10px; }
.fl-stepbar li[data-st=fail] { background: color-mix(in srgb, var(--danger) 18%, var(--panel)); color: var(--danger); font-weight: 650; }
.fl-stepbar li[data-st=fail] i { font-size: 0; }
.fl-stepbar li[data-st=fail] i::before { content: '✗'; font-size: 10px; }
.fl-stepbar li[data-st=skip] { opacity: .45; text-decoration: line-through; }
@media (max-width: 420px) { .fl-stepbar li:not([data-st=done]):not([data-st=fail]) i { display: none; } .fl-stepbar li { font-size: 10px; letter-spacing: -.15px; } }   /* six steps on a 360 dp phone */
.fl-progrow { display: flex; align-items: center; gap: 8px; }
.fl-progress { flex: 1; width: 100%; height: 12px; accent-color: var(--accent); }
.fl-pct { flex: none; min-width: 3.2em; text-align: right; font-size: 12px; font-variant-numeric: tabular-nums; color: var(--muted); }
.fl-status { min-height: 18px; margin: 0; font-size: 13px; color: var(--text); font-weight: 550; }
.fl-status[data-error=true] { color: var(--danger); }
.fl-status[data-ok=true] { color: var(--ok, #2f9e44); }
.fl-error { max-height: 28vh; overflow: auto; border: 1px solid var(--danger, #e5484d); background: color-mix(in srgb, var(--danger, #e5484d) 12%, var(--panel)); color: var(--text); border-radius: 10px; padding: 8px 12px; font-size: 13px; line-height: 1.4; overflow-wrap: anywhere; }
.fl-error b { color: var(--danger, #e5484d); }
.fl-error small { display: block; margin-top: 4px; color: var(--muted); font-size: 11.5px; }
.fl-error button { display: block; width: 100%; margin-top: 8px; }
/* verification card */
.fl-result { border-width: 2px; }
.fl-badge { border-radius: 10px; padding: 8px 10px; font-weight: 700; font-size: 14px; }
.fl-badge.ok { background: color-mix(in srgb, var(--ok, #2f9e44) 15%, var(--panel)); color: var(--ok, #2f9e44); }
.fl-badge.bad { background: color-mix(in srgb, var(--danger) 14%, var(--panel)); color: var(--danger); }
.fl-badge.run { background: var(--panel2); color: var(--muted); font-weight: 600; }
.fl-badge small { display: block; margin-top: 4px; color: var(--text); font-weight: 400; font-size: 12px; overflow-wrap: anywhere; }
.fl-r-fw { margin: 0; font-size: 12.5px; color: var(--muted); }
.fl-img { border-top: 1px solid var(--line); padding-top: 6px; display: flex; flex-direction: column; gap: 2px; }
.fl-img > b { font-size: 13px; }
.fl-img.ok > b { color: var(--ok, #2f9e44); }
.fl-img.bad > b { color: var(--danger); }
.fl-kv { display: grid; grid-template-columns: 76px 1fr; gap: 6px; font-size: 11.5px; }
.fl-kv span { color: var(--muted); }
.fl-kv code { font-family: var(--mono); font-size: 11px; overflow-wrap: anywhere; word-break: break-all; }
.fl-kv.bad code { color: var(--danger); font-weight: 700; }
.fl-running { border-radius: 10px; padding: 8px 10px; background: color-mix(in srgb, var(--accent2, #3b5bdb) 12%, var(--panel)); font-weight: 650; font-size: 13.5px; }
.fl-running.bad { background: color-mix(in srgb, var(--danger) 10%, var(--panel)); font-weight: 500; }
.fl-running small { display: block; color: var(--muted); font-weight: 400; font-size: 11.5px; margin-top: 3px; overflow-wrap: anywhere; }
.fl-running button { margin-top: 8px; width: 100%; }
@media (min-width: 900px) {
  .fl-body { flex-direction: row; }
  .fl-scroll { flex: 1 1 50%; max-width: 640px; padding: 14px 18px; }
  .fl-logcard { flex: 1 1 50%; height: auto; margin: 14px 18px 14px 0; }
  .fl-page.logfull .fl-logcard { margin-left: 18px; }
  .fl-dock { padding-left: 18px; padding-right: 18px; }
  .fl-dock .actions { max-width: 640px; }
}
@media (orientation: landscape) and (max-height: 560px) {
  .fl-logcard { height: 40vh; min-height: 120px; }
}
/* Fullscreen analog video (fpvview.js): 4:3 picture on black, info top left, close top right */
.fpvfs { position: fixed; inset: 0; z-index: 1000; background: #000; display: flex; align-items: center; justify-content: center; user-select: none; -webkit-user-select: none; cursor: zoom-out; }
.fpvfs[hidden] { display: none; }
.fpvfs canvas { flex: none; display: block; width: auto; background: #000; cursor: inherit; }   /* not the instrument canvas rule (flex: 1) */
.fpvfs-info { position: absolute; left: max(14px, env(safe-area-inset-left)); top: max(10px, env(safe-area-inset-top)); max-width: calc(100% - 90px); color: #fff; font: 600 15px/1.35 system-ui, sans-serif; text-shadow: 0 1px 3px #000, 0 0 10px #000; pointer-events: none; }
.fpvfs-info b { display: block; font-size: 18px; }
.fpvfs-info span { display: block; font-weight: 500; font-size: 13px; opacity: .92; }
.fpvfs-note { position: absolute; left: 50%; bottom: max(14px, env(safe-area-inset-bottom)); transform: translateX(-50%); width: max-content; max-width: min(680px, calc(100% - 32px)); background: rgba(0, 0, 0, .66); color: #fff; font: 13px/1.4 system-ui, sans-serif; padding: 8px 12px; border-radius: 10px; text-align: center; pointer-events: none; }
.fpvfs-note:empty { display: none; }
.fpvfs-x { position: absolute; right: max(10px, env(safe-area-inset-right)); top: max(8px, env(safe-area-inset-top)); width: 44px; height: 44px; padding: 0; border-radius: 22px; border: 0; background: rgba(0, 0, 0, .55); color: #fff; font-size: 22px; line-height: 44px; cursor: pointer; }
body.fpvfs-on { overflow: hidden; }
#fpvFrame { cursor: zoom-in; }
.fpvfs-open { margin-top: 6px; width: 100%; }
.fpvfs-open[hidden], #decTable .fpvfs-card[hidden] { display: none; }
#decTable .fpvfs-card { order: 3; margin-top: 5px; padding: 4px 11px; font-size: 12.5px; border-radius: 9px; }

#panoRangeMsg { white-space: normal; overflow: visible; }
#panoRangeMsg.skip { color: var(--warn, #c98a00); }

/* ---- TV (tv.js): analog video receiver ---- */
.tv .tv-screens { display: grid; grid-template-columns: minmax(0, 1fr); gap: 10px; }
.tv.dual .tv-screens { grid-template-columns: minmax(0, 1fr); }
@media (min-width: 700px), (orientation: landscape) and (min-width: 560px) { .tv.dual .tv-screens { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
/* three to eight pictures ("many"). Phone upright: the selected picture big on top, the others small below (two per row,
   three per row from five pictures); landscape / tablet / desktop: a grid — 3 side by side, 4 as 2 × 2 (4 in a row from
   1100 px), 5–6 as 3 per row, 7–8 as 4 per row */
.tv.dual.many .tv-screens { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
.tv.dual.n5 .tv-screens, .tv.dual.n6 .tv-screens, .tv.dual.n7 .tv-screens, .tv.dual.n8 .tv-screens { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; }
.tv.dual.many .tv-scr.sel { grid-column: 1 / -1; order: -1; }
.tv.dual.many .tv-scr:not(.sel) .tv-name { font-size: 12.5px; }
.tv.dual.many .tv-scr:not(.sel) .tv-bot { font-size: 10px; padding: 5px 7px; }
.tv.dual.many .tv-scr:not(.sel) .tv-top { padding: 5px 7px; gap: 5px; }
.tv.dual.many .tv-scr:not(.sel) .tv-badge { font-size: 9.5px; padding: 3px 5px; }
.tv.dual.many .tv-scr:not(.sel) .tv-nm-f, .tv.dual.many .tv-scr:not(.sel) .tv-bars { display: none; }
@media (min-width: 700px), (orientation: landscape) and (min-width: 560px) {
  .tv.dual.n3 .tv-screens, .tv.dual.n5 .tv-screens, .tv.dual.n6 .tv-screens { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .tv.dual.n4 .tv-screens { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .tv.dual.n7 .tv-screens, .tv.dual.n8 .tv-screens { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .tv.dual.many .tv-scr.sel { grid-column: auto; order: 0; }
  .tv.dual.n3 .tv-scr:not(.sel) .tv-nm-f, .tv.dual.n4 .tv-scr:not(.sel) .tv-nm-f, .tv.dual.n3 .tv-scr:not(.sel) .tv-bars, .tv.dual.n4 .tv-scr:not(.sel) .tv-bars { display: revert; }
  .tv.dual.n3 .tv-scr:not(.sel) .tv-bars, .tv.dual.n4 .tv-scr:not(.sel) .tv-bars { display: inline-flex; }
  .tv.dual.n3 .tv-scr:not(.sel) .tv-name, .tv.dual.n4 .tv-scr:not(.sel) .tv-name { font-size: 14px; }
  .tv.dual.n3 .tv-scr:not(.sel) .tv-bot, .tv.dual.n4 .tv-scr:not(.sel) .tv-bot { font-size: 11px; }
}
@media (min-width: 1100px) { .tv.dual.n4 .tv-screens { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
/* one board: hint that more boards give more pictures (dismissable) */
.tv-more { display: flex; align-items: center; gap: 8px; margin: 0; padding: 7px 8px 7px 12px; border: 1px dashed var(--line); border-radius: 10px; color: var(--muted); font-size: 12.5px; }
.tv-more[hidden] { display: none; }
.tv-more span { flex: 1; min-width: 0; } .tv-more a { color: var(--accent); font-weight: 650; white-space: nowrap; }
.tv-more button { flex: none; min-height: 0; width: 28px; height: 28px; padding: 0; border-radius: 50%; border: 0; background: transparent; color: var(--muted); font-size: 15px; }
@media (min-width: 900px) { .tv > .tv-more { grid-column: 1; } }
.tv-scr { position: relative; background: #000; border-radius: 12px; overflow: hidden; aspect-ratio: 4 / 3; cursor: zoom-in; user-select: none; -webkit-user-select: none; box-shadow: var(--shadow); max-height: 62vh; margin: 0 auto; width: 100%; }
@media (min-width: 700px) { .tv:not(.dual) .tv-scr { max-width: calc(62vh * 4 / 3); } }
.tv-scr.sel { outline: 3px solid var(--accent); outline-offset: 2px; }
.tv-cv { display: block; width: 100%; height: 100%; background: #000; }
.tv-top, .tv-bot { position: absolute; left: 0; right: 0; display: flex; align-items: center; gap: 8px; padding: 7px 10px; color: #fff; text-shadow: 0 1px 2px #000, 0 0 8px #000; pointer-events: none; }
.tv-top { top: 0; background: linear-gradient(#0009, #0000); }
.tv-bot { bottom: 0; font: 600 11.5px/1.3 var(--mono); background: linear-gradient(#0000, #000a); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: block; }
.tv-name { font: 750 15px/1.2 var(--font); flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tv-badge { font: 800 11px/1 var(--font); letter-spacing: .06em; padding: 4px 7px; border-radius: 6px; background: #0008; }
.tv-badge.on { background: #1f9d4a; } .tv-badge.mid { background: #b7791f; } .tv-badge.off { background: #a61e4d; }
.tv-bars { display: inline-flex; align-items: flex-end; gap: 2px; height: 14px; }
.tv-bars i { width: 4px; background: #fff4; border-radius: 1px; } .tv-bars i:nth-child(1) { height: 4px; } .tv-bars i:nth-child(2) { height: 6.5px; } .tv-bars i:nth-child(3) { height: 9px; } .tv-bars i:nth-child(4) { height: 11.5px; } .tv-bars i:nth-child(5) { height: 14px; }
.tv-bars i.on { background: #4ade80; }
.tv-fsx, .tv-fsp, .tv-fsn { display: none; }
.tv-scr.fs { position: fixed; inset: 0; z-index: 1000; border-radius: 0; aspect-ratio: auto; max-height: none; max-width: none !important; margin: 0; display: flex; align-items: center; justify-content: center; cursor: default; box-shadow: none; outline: 0; }
.tv-scr.fs .tv-cv { width: min(100vw, calc(100vh * 4 / 3)); height: auto; aspect-ratio: 4 / 3; }
.tv-scr.fs .tv-top { padding: max(10px, env(safe-area-inset-top)) 64px 10px max(14px, env(safe-area-inset-left)); }
.tv-scr.fs .tv-name { font-size: 19px; } .tv-scr.fs .tv-bot { font-size: 13px; padding: 10px max(14px, env(safe-area-inset-left)) max(10px, env(safe-area-inset-bottom)); }
.tv-scr.fs .tv-fsx, .tv-scr.fs .tv-fsp, .tv-scr.fs .tv-fsn { display: flex; align-items: center; justify-content: center; position: absolute; border: 0; color: #fff; background: #0006; border-radius: 50%; font-size: 22px; min-height: 0; padding: 0; }
.tv-scr.fs .tv-fsx { top: max(8px, env(safe-area-inset-top)); right: max(8px, env(safe-area-inset-right)); width: 48px; height: 48px; }
.tv-scr.fs .tv-fsp, .tv-scr.fs .tv-fsn { top: 50%; transform: translateY(-50%); width: 64px; height: 64px; }
.tv-scr.fs .tv-fsp { left: max(10px, env(safe-area-inset-left)); } .tv-scr.fs .tv-fsn { right: max(10px, env(safe-area-inset-right)); }
body.tv-fs-on #tabbar, body.tv-fs-on .top { visibility: hidden; }
.tv-tuner { display: flex; flex-direction: column; gap: 8px; padding: 10px; }
.tv-pick { margin: 0; }
.tv-chrow { display: grid; grid-template-columns: 64px minmax(0, 1fr) 64px; gap: 8px; align-items: stretch; }
.tv-big { font-size: 22px; min-height: 58px; border-radius: 14px; }
.tv-chname { display: flex; flex-direction: column; align-items: center; justify-content: center; background: var(--panel2); border-radius: 14px; padding: 4px 8px; min-width: 0; }
.tv-chname b { font: 800 26px/1.1 var(--font); letter-spacing: .02em; } .tv-chname span { font: 600 14px/1.2 var(--mono); color: var(--muted); }
.tv-bandrow { display: grid; grid-template-columns: 48px minmax(0, 1fr) 48px; gap: 8px; align-items: center; }
.tv-bandrow button { font-size: 20px; min-height: 42px; }
.tv-bandname { text-align: center; font-weight: 650; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tv-acts { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.tv-recbtn.on { background: #c81e1e; border-color: #c81e1e; color: #fff; font-variant-numeric: tabular-nums; }
.tv-recbtn.on::first-letter { animation: tvRecBlink 1s steps(2, start) infinite; }
.tv-replay[hidden] { display: none; }
.tv-recmark { font: 800 11px/1 var(--font); letter-spacing: .06em; padding: 4px 7px; border-radius: 6px; background: #c81e1e; color: #fff; animation: tvRecBlink 1s steps(2, start) infinite; }
.tv-recmark.paused { animation: none; background: #0008; }
.tv-recmark[hidden] { display: none; }
@keyframes tvRecBlink { to { opacity: .35; } }
.tv-fsrec { display: none; }
.tv-scr.fs .tv-fsrec { display: flex; align-items: center; justify-content: center; position: absolute; border: 0; background: #0006; color: #ff4d4d; border-radius: 50%; font-size: 26px; min-height: 0; padding: 0;
  bottom: max(44px, calc(env(safe-area-inset-bottom) + 40px)); right: max(12px, env(safe-area-inset-right)); width: 56px; height: 56px; }
.tv-scr.fs .tv-fsrec.on { background: #c81e1e; color: #fff; }
.tv-recbox { display: flex; flex-direction: column; gap: 6px; }
.tv-recbox .check[hidden] { display: none; }
:root[data-theme=red] .tv-recbtn.on, :root[data-theme=red] .tv-recmark, :root[data-theme=red] .tv-scr.fs .tv-fsrec.on { background: #3d0603; color: #ff2a1a; box-shadow: inset 0 0 0 1.5px #ff2a1a; }
:root[data-theme=red] .tv-scr.fs .tv-fsrec { color: #ff2a1a; }
.tv-seek.on, .tv-cycbtn.on { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); font-weight: 650; }
.tv-cyc { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; border-top: 1px solid var(--line); padding-top: 8px; }
.tv-cyc .tv-lbl { flex-basis: 100%; }
.tv-cycbtn { min-width: 110px; }
.tv-every { display: inline-flex; align-items: center; gap: 6px; }
.tv-every input { width: 72px; }
.tv-cyc select { max-width: 100%; }
.tv-cycinfo { flex-basis: 100%; margin: 0; font-family: var(--mono); font-size: 12.5px; }
.tv-cycinfo:empty { display: none; }
.tv-msg:empty, .tv-fwnote:empty, .tv-viewnote:empty { display: none; }
.tv-lbl { font-size: 12px; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: .05em; }
.tv-list { display: flex; flex-direction: column; gap: 8px; }
.tv-band { display: flex; flex-direction: column; gap: 4px; }
.tv-bl { font-size: 12.5px; font-weight: 650; color: var(--muted); }
.tv-chips { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px; }
@media (min-width: 520px) { .tv-chips { grid-template-columns: repeat(8, minmax(0, 1fr)); } }
.tv-ch { position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px; min-height: 46px; padding: 4px 2px; border-radius: 10px; }
.tv-ch b { font-size: 14px; } .tv-ch small { font: 500 11px/1.1 var(--mono); color: var(--muted); }
.tv-ch.on { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); } .tv-ch.on small { color: inherit; opacity: .85; }
.tv-ch.no, .tv-ch:disabled { opacity: .38; } .tv-ch.no small { text-decoration: line-through; }
.tv-ch.fav::after { content: '★'; position: absolute; top: 1px; right: 4px; font-size: 11px; color: #f59f00; }
.tv-opts { display: flex; flex-direction: column; gap: 8px; padding: 10px; }
.tv-opts .seg { margin: 0; }
.tv-gain { display: grid; grid-template-columns: auto auto minmax(0, 1fr) 2.5em; align-items: center; gap: 8px; }
.tv-sl { display: grid; grid-template-columns: 7.5em minmax(0, 1fr); align-items: center; gap: 8px; }
.tv-viewbox { display: flex; flex-direction: column; gap: 6px; border-top: 1px solid var(--line); padding-top: 8px; }
@media (min-width: 900px) {
  .tv { display: grid !important; grid-template-columns: minmax(0, 1fr) 340px; align-items: start; }
  .tv > .tv-screens, .tv > .tv-fwnote { grid-column: 1; }
  .tv > .tv-tuner { grid-column: 2; grid-row: 1 / span 3; }
  .tv > .tv-listbox, .tv > .tv-free, .tv > .tv-opts, .tv > p.note:last-child { grid-column: 1 / -1; }
  /* several (smaller) pictures: the channel list fills the space under them next to the tall tuner column */
  .tv.dual > .tv-listbox { grid-column: 1; }
}
.page .pg-b > .tp.tv { max-width: 1280px; }

/* ---- theme shortcut (header): the same setting as Device → Appearance, as a small menu ---- */
.thbtn { flex: none; width: 38px; height: 38px; min-height: 38px; padding: 0; border-radius: 19px; display: inline-flex; align-items: center; justify-content: center; background: var(--panel2); border: 1px solid var(--line); color: var(--muted); }
.thbtn .ti { width: 19px; height: 19px; display: none; }
html:not([data-pref]) .thbtn .ti-auto, html[data-pref=auto] .thbtn .ti-auto, html[data-pref=light] .thbtn .ti-light, html[data-pref=dark] .thbtn .ti-dark, html[data-pref=red] .thbtn .ti-red { display: block; }
.thmenu { position: fixed; z-index: 45; top: calc(var(--top-h) - 2px); right: 12px; display: flex; flex-direction: column; gap: 2px; padding: 5px; min-width: 150px; background: var(--panel); border: 1px solid var(--line); border-radius: 14px; box-shadow: 0 8px 28px #0004; }
.thmenu[hidden] { display: none; }
.thmenu button { display: flex; align-items: center; gap: 10px; border: 0; background: transparent; min-height: 40px; border-radius: 10px; text-align: left; font-weight: 600; color: var(--muted); }
.thmenu button svg { width: 18px; height: 18px; flex: none; }
.thmenu button.on { background: var(--accent-soft); color: var(--text); }
@media (max-width: 360px) { .thbtn { width: 34px; height: 34px; min-height: 34px; } }

/* ==== red night mode (theme.js 'red'; palette "red light classic" like espsoup.com): pure red on black, nothing white, no
   blue / green / yellow. Status colours become brightness + symbols; pictures go through #espRedImg (index.html). ==== */
/* @red */
:root[data-theme=red] {
  --bg: #000; --panel: #080000; --panel2: #0d0101; --panel3: #1f0302; --line: #4a0c08; --text: #ff2a1a; --muted: #c41f14; --faint: #7a120b;
  --accent: #ff2a1a; --accent-ink: #000; --accent-soft: #1f0302; --accent2: #c41f14; --danger: #ff2a1a; --ok: #ff2a1a; --warn-c: #c41f14; --warn: #c41f14;
  --shadow: none; --cal-bg: #1f0302; --cal-line: #4a0c08; --cal-text: #ff2a1a; --btn-bg: #3d0603; --btn-ink: #ff2a1a; --btn-line: #7a120b;
  --red-img: url(#espRedImg); --red-inv: url(#espRedInv); --red-txt: url(#espRedTxt); color-scheme: dark; scrollbar-color: #4a0c08 #000;
}
:root[data-theme=red] body, :root[data-theme=red] body[data-ui] { --plot-bg: #000; --grid: #2a0604; --axis: #c41f14; --trace: #ff2a1a; --hold: #b81c12; --avg: #7a120b; --marker: #ff2a1a; --wf-bg: #000; --overlay-text: #7a120b; }
:root[data-theme=red] body[data-ui=phosphor] .chart canvas { filter: none; }
:root[data-theme=red] ::selection { background: #3d0603; color: #ff2a1a; }
:root[data-theme=red] ::placeholder { color: #7a120b; }
/* form controls: no white check marks / grey tracks (the browser picks white on an accent fill) */
:root[data-theme=red] input:is([type=checkbox], [type=radio]) { -webkit-appearance: none; appearance: none; width: 18px; height: 18px; flex: none; border: 2px solid #c41f14; border-radius: 4px; background: transparent; vertical-align: middle; }
:root[data-theme=red] input[type=radio] { border-radius: 50%; }
:root[data-theme=red] input:is([type=checkbox], [type=radio]):checked { background: #ff2a1a; box-shadow: inset 0 0 0 3px #000; border-color: #ff2a1a; }
:root[data-theme=red] input:is([type=checkbox], [type=radio]):disabled { border-style: dashed; border-color: #4a0c08; }
:root[data-theme=red] input[type=range] { -webkit-appearance: none; appearance: none; background: transparent; }
:root[data-theme=red] input[type=range]::-webkit-slider-runnable-track { height: 4px; border-radius: 2px; background: #4a0c08; }
:root[data-theme=red] input[type=range]::-webkit-slider-thumb { -webkit-appearance: none; width: 18px; height: 18px; margin-top: -7px; border: 0; border-radius: 50%; background: #ff2a1a; }
:root[data-theme=red] input[type=range]::-moz-range-track { height: 4px; border-radius: 2px; background: #4a0c08; }
:root[data-theme=red] input[type=range]::-moz-range-thumb { width: 18px; height: 18px; border: 0; border-radius: 50%; background: #ff2a1a; }
:root[data-theme=red] select option { background: #080000; color: #ff2a1a; }
:root[data-theme=red] progress { accent-color: #ff2a1a; background: #1f0302; }
/* filled buttons, toggles, badges: dark red with red text and a red rim */
:root[data-theme=red] :is(button.primary, .ab-go, .ab-go.stop, #decTable .dec-find .find, .fm-btn[aria-pressed=true], .nb, .res .tx span.nb, .badge, .badge.ok, .badge.exp, .badge.no, .note.support .tip, .fl-badge, .fl-badge.ok, .ing.sel::after) {
  background: var(--btn-bg); color: var(--btn-ink); border-color: var(--btn-line); box-shadow: inset 0 0 0 1px var(--btn-line); }
:root[data-theme=red] body.disconnected .pill { background: var(--btn-bg); border-color: var(--btn-line); color: var(--btn-ink); }
:root[data-theme=red] body.disconnected #light { background: transparent; box-shadow: inset 0 0 0 2px var(--btn-ink); }
:root[data-theme=red] .seg button.on, :root[data-theme=red] .fx-seg button.on { background: var(--btn-bg); color: var(--btn-ink); box-shadow: inset 0 0 0 1px var(--btn-line); }
:root[data-theme=red] .brand b span { color: #c41f14; }
:root[data-theme=red] :is(.modal, .scrim, .rh-modal, .ob-modal) { background: #000c; }
/* status: live = full dot, otherwise a hollow ring (brightness + shape instead of green / grey) */
:root[data-theme=red] #light, :root[data-theme=red] .s-dot { background: transparent; box-shadow: inset 0 0 0 2px #7a120b; }
:root[data-theme=red] #light.on, :root[data-theme=red] .s-dot.on { background: #ff2a1a; box-shadow: 0 0 0 3px #3d0603; }
/* pictures, emoji and icons: red luminance */
:root[data-theme=red] :where(img, video, .ing .e, .res .ic, .fmh-est) { filter: var(--red-img); }
:root[data-theme=red] #decTable tr::before { filter: var(--red-img); background: #1f0302; }
:root[data-theme=red] :is(#fpvFrame, .fpvfs canvas) { filter: var(--red-img); }
:root[data-theme=red] :is(.fx-toggle, .fmh-st, .leaflet-control-attribution) { filter: var(--red-txt); }
/* map tiles: inverted luminance (white land → black, roads / labels → dim red) */
:root[data-theme=red] img.leaflet-tile { filter: var(--red-inv); }
:root[data-theme=red] .leaflet-container { background: #000; }
:root[data-theme=red] :is(.leaflet-bar a, .leaflet-control-attribution, .leaflet-control-attribution a, .leaflet-tooltip, .leaflet-popup-content-wrapper, .leaflet-popup-tip) { background: #080000; color: #c41f14; border-color: #4a0c08; box-shadow: none; }
:root[data-theme=red] .leaflet-tooltip::before { border-color: transparent; }
:root[data-theme=red] path.fm-op { stroke: #ff2a1a; fill: #7a120b; }
:root[data-theme=red] path.fm-line { stroke: #ff2a1a; }
:root[data-theme=red] path.fm-self { stroke: #ff2a1a; fill: #3d0603; }
:root[data-theme=red] path.fm-acc { stroke: #7a120b; fill: #7a120b; }
:root[data-theme=red] .fm-drone { color: #ff2a1a; text-shadow: none; }
/* finder gauge + legends + kitchen toasts */
:root[data-theme=red] .fx { --fx-hot: #ff2a1a; --fx-warm: #b81c12; --fx-cold: #4a0c08; }
:root[data-theme=red] .fx-gauge-svg stop:nth-child(1) { stop-color: #3d0603; }
:root[data-theme=red] .fx-gauge-svg stop:nth-child(2) { stop-color: #96100a; }
:root[data-theme=red] .fx-gauge-svg stop:nth-child(3) { stop-color: #ff2a1a; }
:root[data-theme=red] .fx-legend i { background: linear-gradient(90deg, #000, #340402 30%, #96100a 65%, #ff2a1a); box-shadow: inset 0 0 0 1px #4a0c08; }
:root[data-theme=red] .fx-pick-card { background: #1f0302; color: #ff2a1a; box-shadow: inset 0 0 0 1px #7a120b; }
:root[data-theme=red] .fx-toast { background: #0d0101; color: #ff2a1a; border-left-color: #ff2a1a; box-shadow: inset 0 0 0 1px #4a0c08; }
/* recordings / firmware log */
:root[data-theme=red] .fx-recwf { background: #000; }
:root[data-theme=red] :is(.fl-logcard, .fl-log-h, .fl-log-h .fl-mini) { background: #080000; color: #c41f14; border-color: #4a0c08; }
:root[data-theme=red] :is(.fl-log, .fl-log .ll b, .fl-log .ll-part, .fl-log-h .fl-lbl) { color: #c41f14; }
:root[data-theme=red] .fl-log .ll-ok { color: #ff2a1a; }
:root[data-theme=red] .fl-log .ll-ok::before { content: '\2713  '; }
:root[data-theme=red] .fl-log .ll-err { color: #ff2a1a; font-weight: 700; }
:root[data-theme=red] .fl-log .ll-err::before { content: '\2715  '; }
/* fullscreen video + TV overlays: red text, no white */
:root[data-theme=red] :is(.fpvfs-info, .fpvfs-note, .fpvfs-x, .tv-top, .tv-bot, .tv-scr.fs .tv-fsx, .tv-scr.fs .tv-fsp, .tv-scr.fs .tv-fsn) { color: #ff2a1a; text-shadow: 0 1px 2px #000; }
:root[data-theme=red] .tv-badge { background: transparent; color: #c41f14; box-shadow: inset 0 0 0 1.5px #7a120b; }
:root[data-theme=red] .tv-badge.on { background: #3d0603; color: #ff2a1a; box-shadow: inset 0 0 0 1.5px #ff2a1a; }
:root[data-theme=red] .tv-badge.on::before { content: '\25CF  '; }
:root[data-theme=red] .tv-badge.mid { background: repeating-linear-gradient(135deg, #3d0603 0 4px, transparent 4px 8px); color: #ff2a1a; }
:root[data-theme=red] .tv-badge.mid::before { content: '\25D0  '; }
:root[data-theme=red] .tv-badge.off { color: #c41f14; box-shadow: inset 0 0 0 1.5px #4a0c08; }
:root[data-theme=red] .tv-badge.off::before { content: '\2715  '; }
:root[data-theme=red] .tv-bars i { background: #3d0603; }
:root[data-theme=red] .tv-bars i.on { background: #ff2a1a; }
:root[data-theme=red] .tv-ch.fav::after { color: #ff2a1a; }
/* @red-end */
