/* Fonts are self-hosted (Latin subset, SIL OFL — see fonts/LICENSE-*.txt) so the app
   makes no third-party requests and works on a LAN with no internet access. */
@font-face{ font-family:'Inter'; font-style:normal; font-weight:400; font-display:swap; src:url('/fonts/inter-latin-400-normal.woff2') format('woff2'); }
@font-face{ font-family:'Inter'; font-style:normal; font-weight:500; font-display:swap; src:url('/fonts/inter-latin-500-normal.woff2') format('woff2'); }
@font-face{ font-family:'Inter'; font-style:normal; font-weight:600; font-display:swap; src:url('/fonts/inter-latin-600-normal.woff2') format('woff2'); }
@font-face{ font-family:'Inter'; font-style:normal; font-weight:700; font-display:swap; src:url('/fonts/inter-latin-700-normal.woff2') format('woff2'); }
@font-face{ font-family:'JetBrains Mono'; font-style:normal; font-weight:400; font-display:swap; src:url('/fonts/jetbrains-mono-latin-400-normal.woff2') format('woff2'); }
@font-face{ font-family:'JetBrains Mono'; font-style:normal; font-weight:500; font-display:swap; src:url('/fonts/jetbrains-mono-latin-500-normal.woff2') format('woff2'); }

/* Tesla-language redesign, light theme — settled after iterating through
   several mockups against real Tesla screenshots. Near-monochrome, state
   shown by icon shape + a shared sliding-pill "strip" component used for
   gate control, alarm mode, and (read-only) sensor status. */

:root{
  --bg:#f5f5f7; --surface:#ffffff; --border:#e6e6e9;
  --text:#1d1d1f; --text-secondary:#6e6e73; --text-faint:#a3a3a8;
  --c-blue:#0071e3; --c-amber:#b8790a; --c-amber-bg:rgba(184,121,10,.12); --c-red:#d43a3a; --c-red-bg:rgba(212,58,58,.1); --c-green:#1a8a4a; --c-green-bg:rgba(26,138,74,.12); --c-gate-fail:#d9720a;
  --c-blue-dark:#0055b3; --c-blue-light:#bcdcff;
  --track:#eaeaed; --pill-bg:#ffffff; --hover:#ececef; --btn-idle:#dcdce0;
  --on-blue:#ffffff; --btn-neutral-bg:var(--btn-idle); --btn-neutral-text:var(--text);
  --font:'Inter','Helvetica Neue',Arial,sans-serif;
  --font-mono:'JetBrains Mono',monospace;
}
:root[data-theme="dark"]{
  --bg:#000000; --surface:#161618; --border:#2a2a2c;
  --text:#f5f5f5; --text-secondary:#9a9a9e; --text-faint:#5c5c60;
  --c-blue:#2d8cff; --c-amber:#e0a83e; --c-amber-bg:rgba(224,168,62,.16); --c-red:#ff6161; --c-red-bg:rgba(255,97,97,.14); --c-green:#3ecf6e; --c-green-bg:rgba(62,207,110,.16); --c-gate-fail:#ff8c1a;
  --c-blue-dark:#5aa6ff; --c-blue-light:#1e3a5c;
  --track:#232326; --pill-bg:#3a3a3d; --hover:#232326; --btn-idle:#3a3a3d;
  --on-blue:#ffffff; --btn-neutral-bg:var(--btn-idle); --btn-neutral-text:var(--text);
}
/* ---- Selectable palettes (Settings -> General, Owner). Each has a light block
   and a dark block; the unthemed block above is the original look, used only
   until the palette setting has loaded. Palette names must match src/palettes.js. ---- */
:root[data-palette="slate"]{
  --bg:#e9eef4; --surface:#ffffff; --border:#b9c5d3;
  --text:#111923; --text-secondary:#3d4b5c; --text-faint:#516074;
  --c-blue:#0a62c9; --c-blue-dark:#0a52a8; --c-blue-light:#c3d7ef;
  --c-amber:#8f5b00; --c-amber-bg:rgba(143,91,0,.12); --c-red:#c32f2f; --c-red-bg:rgba(195,47,47,.1); --c-green:#17703d; --c-green-bg:rgba(23,112,61,.12); --c-gate-fail:#a85200;
  --track:#d9e1ea; --pill-bg:#ffffff; --hover:#dde5ee; --btn-idle:#d9e1ea;
  --on-blue:#ffffff; --btn-neutral-bg:#dde3ea; --btn-neutral-text:#111923;
}
:root[data-palette="slate"][data-theme="dark"]{
  --bg:#10151c; --surface:#1a212b; --border:#3b4859;
  --text:#edf2f8; --text-secondary:#bac6d4; --text-faint:#94a3b6;
  --c-blue:#63b3ff; --c-blue-dark:#7cc0ff; --c-blue-light:#2c4764;
  --c-amber:#f0b84a; --c-amber-bg:rgba(240,184,74,.16); --c-red:#ff7b7b; --c-red-bg:rgba(255,123,123,.16); --c-green:#4fd68a; --c-green-bg:rgba(79,214,138,.16); --c-gate-fail:#ff9f45;
  --track:#273140; --pill-bg:#3f4d62; --hover:#232c39; --btn-idle:#3f4d62;
  --on-blue:#06121f; --btn-neutral-bg:#cfd8e3; --btn-neutral-text:#0f1620;
}
:root[data-palette="graphite"]{
  --bg:#eceded; --surface:#ffffff; --border:#b8bcc1;
  --text:#15171a; --text-secondary:#41454c; --text-faint:#585d65;
  --c-blue:#00758a; --c-blue-dark:#00606f; --c-blue-light:#bfe0e6;
  --c-amber:#8f5b00; --c-amber-bg:rgba(143,91,0,.12); --c-red:#c32f2f; --c-red-bg:rgba(195,47,47,.1); --c-green:#17703d; --c-green-bg:rgba(23,112,61,.12); --c-gate-fail:#a85200;
  --track:#dcdee0; --pill-bg:#ffffff; --hover:#e1e3e4; --btn-idle:#dcdee0;
  --on-blue:#ffffff; --btn-neutral-bg:#e0e2e4; --btn-neutral-text:#15171a;
}
:root[data-palette="graphite"][data-theme="dark"]{
  --bg:#17181b; --surface:#222428; --border:#464a52;
  --text:#f3f4f6; --text-secondary:#c3c6cd; --text-faint:#9a9ea8;
  --c-blue:#3cc8e0; --c-blue-dark:#52d3e8; --c-blue-light:#24454c;
  --c-amber:#f2b84b; --c-amber-bg:rgba(242,184,75,.16); --c-red:#ff7d78; --c-red-bg:rgba(255,125,120,.16); --c-green:#58d68d; --c-green-bg:rgba(88,214,141,.16); --c-gate-fail:#ff9f45;
  --track:#32353b; --pill-bg:#4a4e56; --hover:#2b2e33; --btn-idle:#4a4e56;
  --on-blue:#04161a; --btn-neutral-bg:#d3d6db; --btn-neutral-text:#14161a;
}
:root[data-palette="midnight"]{
  --bg:#eaecf7; --surface:#ffffff; --border:#b4bbdc;
  --text:#12163a; --text-secondary:#40466e; --text-faint:#555c8a;
  --c-blue:#3446c4; --c-blue-dark:#2a3aa8; --c-blue-light:#ccd3f5;
  --c-amber:#8f5b00; --c-amber-bg:rgba(143,91,0,.12); --c-red:#c32f2f; --c-red-bg:rgba(195,47,47,.1); --c-green:#17703d; --c-green-bg:rgba(23,112,61,.12); --c-gate-fail:#a85200;
  --track:#dadef0; --pill-bg:#ffffff; --hover:#dfe2f3; --btn-idle:#dadef0;
  --on-blue:#ffffff; --btn-neutral-bg:#dde0f2; --btn-neutral-text:#12163a;
}
:root[data-palette="midnight"][data-theme="dark"]{
  --bg:#0d1226; --surface:#171e3a; --border:#3a4575;
  --text:#eef0fb; --text-secondary:#bcc3e6; --text-faint:#9aa3d1;
  --c-blue:#8fa2ff; --c-blue-dark:#a3b3ff; --c-blue-light:#2c3a7a;
  --c-amber:#f3c15a; --c-amber-bg:rgba(243,193,90,.16); --c-red:#ff8a8a; --c-red-bg:rgba(255,138,138,.16); --c-green:#5adb95; --c-green-bg:rgba(90,219,149,.16); --c-gate-fail:#ffa24d;
  --track:#242d52; --pill-bg:#3d4a82; --hover:#1f2848; --btn-idle:#3d4a82;
  --on-blue:#0a0f2e; --btn-neutral-bg:#d2d7f2; --btn-neutral-text:#0e1230;
}
*{ box-sizing:border-box; }
button{ -webkit-tap-highlight-color:transparent; }
html,body{ margin:0; padding:0; height:100%; }
body{ background:var(--bg); color:var(--text); font-family:var(--font); -webkit-font-smoothing:antialiased; }
button, input, select{ font-family:inherit; }

.app{ display:flex; flex-direction:column; height:100vh; }

.statusbar{ display:flex; align-items:center; justify-content:space-between; padding:14px 22px; border-bottom:1px solid var(--border); font-size:11px; color:var(--text-secondary); flex-shrink:0; }
.statusbar__brand{ font-family:var(--font); font-weight:500; color:var(--text); font-size:13px; display:flex; align-items:center; gap:10px; cursor:pointer; }
.status-dot{ width:6px; height:6px; border-radius:50%; background:var(--c-blue); box-shadow:0 0 8px rgba(0,113,227,.4); flex-shrink:0; cursor:pointer; animation:reconnect-pulse 1.1s ease-in-out infinite; }
.status-dot.is-healthy{ background:var(--c-green); box-shadow:0 0 8px var(--c-green-bg); animation:none; }
.status-dot.is-warn{ background:var(--c-amber); box-shadow:0 0 8px rgba(184,121,10,.4); animation:reconnect-pulse 1.1s ease-in-out infinite; }
.status-dot.is-error{ background:var(--c-red); box-shadow:0 0 8px var(--c-red-bg); animation:none; }
#systemHealthModal .modal-box{ max-width:380px; }
.health-row{ display:flex; align-items:center; justify-content:space-between; gap:10px; padding:9px 0; border-bottom:1px solid var(--border); }
.health-row:last-of-type{ border-bottom:none; }
.health-row__label{ font-size:14px; color:var(--text); }
.health-row__value{ font-size:13px; font-weight:700; color:var(--c-green); flex-shrink:0; white-space:nowrap; }
.health-row__value.is-warn{ color:var(--c-amber); }
.health-row__value.is-error{ color:var(--c-red); }
@keyframes reconnect-pulse{ 0%,100%{ opacity:1; } 50%{ opacity:.35; } }
.reconnecting-label{ font-size:12px; font-weight:600; color:var(--c-amber); margin-left:2px; }
.statusbar__right{ display:flex; align-items:center; gap:6px; }
.icon-btn{ display:flex; align-items:center; justify-content:center; width:30px; height:30px; border-radius:8px; background:transparent; border:none; color:var(--text-secondary); cursor:pointer; }
.icon-btn svg{ width:17px; height:17px; }
.icon-btn:hover{ color:var(--text); background:var(--hover); }
.icon-btn.danger{ color:var(--c-red); }
.icon-btn.danger:hover{ color:var(--c-red); background:var(--c-red-bg); }
.icon-btn--lang{ font-size:11px; font-weight:700; letter-spacing:.02em; color:var(--text-secondary); }
.js-delete-user:hover{ color:var(--c-red); }
.icon-btn:disabled{ color:var(--text-faint); opacity:.4; cursor:not-allowed; pointer-events:none; }
.version-tag{ font-family:var(--font-mono); font-size:10px; color:var(--text-faint); }

.body-row{ flex:1; display:flex; min-height:0; }

.sidebar{ width:136px; flex-shrink:0; display:flex; flex-direction:column; gap:2px; padding:24px 10px; }
.side-item{ display:flex; flex-direction:column; align-items:center; gap:8px; padding:14px 6px; border-radius:12px; color:var(--text-faint); font-size:12px; font-weight:500; cursor:pointer; }
.side-item svg{ width:24px; height:24px; }
.side-item.is-active{ color:var(--text); font-weight:600; }

.main{ flex:1; padding:28px 30px; overflow:auto; min-width:0; }
.main h1{ font-weight:600; font-size:20px; margin:0; }
.view-header{ display:flex; align-items:center; justify-content:space-between; margin-bottom:20px; }
.js-refresh{ color:var(--text); position:relative; }
.js-refresh.is-just-pressed{ color:var(--c-blue); }
.js-refresh:disabled{ cursor:not-allowed; pointer-events:none; }

.js-refresh-icon.is-spinning{ animation:refresh-spin .9s linear infinite; color:var(--c-blue); }
@keyframes refresh-spin{ to{ transform:rotate(360deg); } }

.refresh-ring{ position:absolute; inset:0; width:30px; height:30px; pointer-events:none; }
.refresh-ring__track{ stroke:var(--border); }
.refresh-ring__progress{ stroke:var(--c-blue); stroke-linecap:round; transform-origin:50% 50%; transform:rotate(-90deg); transition:stroke-dashoffset 1s linear; }
.refresh-ring__progress.is-failed{ stroke:var(--c-red); }

.refresh-num{ position:absolute; inset:0; display:flex; align-items:center; justify-content:center; font-size:10.5px; font-weight:700; color:var(--c-blue); font-variant-numeric:tabular-nums; pointer-events:none; }
.refresh-num.is-failed{ color:var(--c-red); }

.refresh-result{ position:absolute; inset:0; display:flex; align-items:center; justify-content:center; pointer-events:none; }
.refresh-result svg{ width:15px; height:15px; }
.refresh-result.is-ok svg{ stroke:var(--c-blue); }
.refresh-result.is-failed svg{ stroke:var(--c-red); }

/* Error toast — a non-blocking, auto-dismissing banner (unlike alert()),
   for a brief, specific explanation with a code to reference and a copy
   button for pasting into a support request or a note to self. */
.error-toast{
  position:fixed; left:50%; bottom:24px; transform:translateX(-50%);
  display:flex; align-items:flex-start; gap:10px; max-width:min(92vw, 420px);
  background:var(--surface); color:var(--text); border:1px solid var(--border);
  border-radius:12px; padding:12px 12px 12px 14px; box-shadow:0 8px 28px rgba(0,0,0,.18);
  z-index:500;
}
.error-toast.hidden{ display:none; }
.error-toast__icon{ color:var(--c-red); flex-shrink:0; margin-top:1px; }
.error-toast__icon svg{ width:18px; height:18px; display:block; }
.error-toast__body{ display:flex; flex-direction:column; gap:2px; min-width:0; flex:1; }
.error-toast__message{ font-size:13px; font-weight:600; line-height:1.35; }
.error-toast__code{ font-size:11px; color:var(--text-faint); font-family:var(--font-mono); }
.error-toast__copy{ flex-shrink:0; border:none; background:transparent; color:var(--text-secondary); cursor:pointer; padding:4px; border-radius:6px; margin-top:1px; }
.error-toast__copy:hover{ background:var(--hover); color:var(--text); }
.error-toast__copy svg{ width:15px; height:15px; display:block; }
.error-toast__copy.is-copied{ color:var(--c-blue); }
.view-error{ background:rgba(212,58,58,.08); border:1px solid rgba(212,58,58,.25); color:var(--c-red); font-size:12px; padding:10px 14px; border-radius:10px; margin-top:14px; }

.update-banner{ display:flex; align-items:center; justify-content:center; gap:12px; background:var(--c-blue); color:var(--on-blue); font-size:12.5px; padding:8px; }
.update-banner button{ background:var(--on-blue); color:var(--c-blue); border:none; border-radius:8px; padding:4px 12px; font-size:12px; font-weight:600; cursor:pointer; }
.view{ display:none; }
.view.is-active{ display:block; }

.row{ display:flex; align-items:center; justify-content:center; gap:10px; margin-top:10px; }
.row__icon{ width:26px; height:26px; display:flex; align-items:center; justify-content:center; color:var(--text-secondary); flex-shrink:0; }
.row__icon svg{ width:24px; height:24px; }
.row__name{ font-size:18px; font-weight:700; }

/* Gates-specific title treatment: with gates now shown as circular
   buttons in columns rather than a left-aligned list, a small,
   left-aligned title no longer visually matches — centered and a
   little larger reads as the natural heading for a symmetric layout.
   Scoped to Gates only; Alarm/Cameras/Links keep the standard
   left-aligned header since their layouts don't share this shape. */
#view-gates .view-header{ display:grid; grid-template-columns:1fr auto 1fr; }
#view-gates .view-header h1{ grid-column:2; justify-self:center; font-size:24px; font-weight:700; }
#view-gates .view-header .js-refresh{ grid-column:3; justify-self:end; }

#gateList{ display:grid; grid-template-columns:1fr 1fr; gap:6px 16px; }

/* --- Shared sliding-pill strip: gates (action) + alarm (select) --- */
.pillstrip{ position:relative; display:flex; background:var(--track); border-radius:12px; padding:3px; }
.pillstrip__pill{ position:absolute; top:3px; bottom:3px; border-radius:9px; background:var(--pill-bg); box-shadow:0 1px 3px rgba(0,0,0,.14); transition:transform .28s cubic-bezier(.4,0,.2,1); }
.pillstrip__seg{ position:relative; z-index:1; flex:1; border:none; background:transparent; padding:13px 8px; font-size:14px; font-weight:600; color:var(--text-faint); text-align:center; cursor:pointer; white-space:nowrap; }
.pillstrip__seg.is-current{ color:var(--text); }
.pillstrip__seg:disabled{ cursor:not-allowed; }
.pillstrip__seg:disabled:not(.is-current){ color:var(--text-faint); }
.pillstrip__seg.is-status{ cursor:default; font-weight:500; }
.pillstrip__seg.is-status.is-final{ color:var(--c-blue); font-weight:700; }
.pillstrip__seg.is-status.is-motion{ color:var(--text); }
.pillstrip__seg.is-status.is-warn{ color:var(--c-amber); font-weight:700; }
.pillstrip__seg.is-status.is-stoppable{ cursor:pointer; text-decoration:underline; text-decoration-style:dotted; text-underline-offset:3px; }

/* --- Gates: single large tap-to-toggle circular button, ring shows how
   closed the gate is (full = closed, empty = open). Replaces the old
   slide-track + separate reset button. --- */
.gatebtn-wrap{ display:flex; justify-content:center; padding:6px 0; }
.gatebtn{ position:relative; width:170px; height:170px; border-radius:50%; border:none; background:none; cursor:pointer; padding:0; touch-action:none; }
.gatebtn:disabled{ cursor:default; }
.gatebtn > svg{ position:absolute; inset:0; width:100%; height:100%; }
.gatebtn__track{ stroke:var(--c-blue-light); }
.js-gatebtn-arc, .js-gatebtn-full{ stroke:var(--c-blue-dark); fill:none; transition:stroke .3s; }
.gatebtn.is-suspended .js-gatebtn-arc, .gatebtn.is-suspended .js-gatebtn-full{ stroke:var(--c-red); }
.gatebtn.is-failed .js-gatebtn-arc, .gatebtn.is-failed .js-gatebtn-full{ stroke:var(--c-gate-fail); }
.gatebtn.is-spinning .js-gatebtn-arc, .gatebtn.is-spinning .js-gatebtn-full{ stroke:var(--c-blue); transition:none; }
.gatebtn.is-spinning .gatebtn__ring{ animation:gatebtn-spin 1.1s linear infinite; transform-origin:50% 50%; }
@keyframes gatebtn-spin{ to{ transform:rotate(270deg); } }
.gatebtn__face{
  position:absolute; inset:21px; border-radius:50%; background:var(--surface);
  border:1px solid var(--border); box-sizing:border-box;
  box-shadow:0 1px 3px rgba(0,0,0,.1);
}
.gatebtn__status-row{ position:absolute; left:0; right:0; bottom:50%; padding-bottom:2px; display:flex; align-items:center; justify-content:center; gap:6px; }
.gatebtn__below{ position:absolute; left:0; right:0; top:50%; padding-top:2px; display:flex; flex-direction:column; align-items:center; gap:1px; }
.gatebtn__conf:empty{ display:none; }
.gatebtn__conf svg{ width:15px; height:15px; display:block; }
.gatebtn__status{ font-size:22px; font-weight:800; color:var(--text); letter-spacing:-.01em; }
.gatebtn__action{ font-size:13.5px; font-weight:600; color:var(--text-secondary); }
.gatebtn__countdown{ font-size:12.5px; font-weight:700; color:var(--c-blue-dark); font-variant-numeric:tabular-nums; }
.gatebtn.is-suspended .gatebtn__countdown{ color:var(--c-red); }
.gatebtn.is-failed .gatebtn__countdown{ color:var(--c-gate-fail); }
.gatebtn.is-failed .gatebtn__action{ font-size:11.5px; }

.is-reset-opt-disabled{ color:var(--text-faint); cursor:not-allowed; opacity:.6; }
.gate-meta{ font-family:var(--font-mono); font-size:10px; color:var(--text-faint); margin:6px 2px 0; text-align:center; }

/* --- Alarm --- */
.alarm-hero{ --mode:var(--text-faint); display:none; align-items:center; gap:14px; padding:16px 18px; border-radius:16px; background:var(--surface); border:1px solid var(--border); margin-bottom:18px; border-left:4px solid var(--mode); box-shadow:0 1px 3px rgba(0,0,0,.06); }
.alarm-hero[data-mode="triggered"]{ --mode:var(--c-red); display:flex; animation:pulse 1.2s ease-in-out infinite; }
@keyframes pulse{ 0%,100%{ opacity:1; } 50%{ opacity:.72; } }
.alarm-hero__badge{ color:var(--mode); }
.alarm-hero__badge svg{ width:24px; height:24px; }
.alarm-hero__label{ font-family:var(--font-mono); font-size:10px; letter-spacing:.1em; color:var(--text-faint); text-transform:uppercase; }
.alarm-hero__mode{ display:block; font-weight:700; font-size:16px; color:var(--mode); }

#modeStrip{ margin-bottom:28px; }
.group-label{ font-size:11px; font-weight:600; color:var(--text-faint); margin:22px 0 4px; text-transform:uppercase; letter-spacing:.04em; }
.group-label:first-of-type{ margin-top:0; }

/* --- Compact sensor row: icon + name + status, one line --- */
.sensor-row{ padding:9px 0; border-bottom:1px solid var(--border); }
.sensor-row:last-of-type{ border-bottom:none; }
.sensor-row__main{ display:flex; align-items:center; gap:10px; }
.sensor-row .row__icon{ width:22px; height:22px; }
.sensor-row .row__icon svg{ width:20px; height:20px; }
.sensor-row .row__name{ font-size:14px; flex:1; }
.sensor-row__ts{ display:block; font-size:10px; color:var(--text-faint); margin-top:4px; margin-left:32px; }
.mini-strip{ display:flex; background:var(--track); border-radius:8px; padding:2px; flex-shrink:0; }
.mini-strip__seg{ padding:5px 9px; font-size:10.5px; font-weight:600; color:var(--text-faint); border-radius:6px; }
.mini-strip__seg.is-current.is-known{ color:var(--on-blue); background:var(--c-blue); }
.row__icon.is-unknown{ color:var(--c-amber); }
.badge-unknown{ display:flex; align-items:center; gap:5px; background:var(--c-amber-bg); color:var(--c-amber); font-size:10.5px; font-weight:700; padding:5px 10px; border-radius:8px; flex-shrink:0; }
.badge-unknown svg{ width:12px; height:12px; flex-shrink:0; }

/* --- Settings --- */
.field-row{ display:flex; align-items:center; justify-content:space-between; gap:12px; padding:12px 0; border-bottom:1px solid var(--border); }
.field-row label{ display:flex; flex-direction:column; gap:2px; font-size:13px; }
.field-hint{ font-family:var(--font-mono); font-size:9.5px; color:var(--text-faint); }
.toggle-row{ display:flex; align-items:center; gap:10px; }

/* Real slider, styled Tesla-like: filled track up to the thumb, plain
   circular thumb. Range and readout come from the field itself. */
.slider-row{ display:flex; align-items:center; gap:12px; }
.slider-row input[type=range]{ flex:1; -webkit-appearance:none; appearance:none; height:5px; border-radius:3px; background:var(--border); outline:none; }
.slider-row input[type=range]::-webkit-slider-thumb{ -webkit-appearance:none; width:26px; height:26px; border-radius:50%; background:var(--c-blue); box-shadow:0 1px 3px rgba(0,0,0,.3); cursor:pointer; margin-top:-10.5px; }
.slider-row input[type=range]::-moz-range-thumb{ width:26px; height:26px; border-radius:50%; background:var(--c-blue); border:none; box-shadow:0 1px 3px rgba(0,0,0,.3); cursor:pointer; }
.slider-row input[type=range]::-webkit-slider-runnable-track{ height:5px; border-radius:3px; background:transparent; }
.tickrow{ position:relative; height:14px; margin-top:2px; }
.tickrow span{ position:absolute; transform:translateX(-50%); font-family:var(--font-mono); font-size:9px; color:var(--text-faint); }
.slider-readout{ font-family:var(--font-mono); font-size:13px; color:var(--text); width:34px; text-align:right; flex-shrink:0; }

/* Toggle switch — the checkbox stays for state/save-logic, just visually
   hidden; a label wraps both so a tap on the switch toggles the input. */
.switch{ position:relative; display:inline-block; width:46px; height:27px; flex-shrink:0; }
.switch input{ position:absolute; opacity:0; width:0; height:0; }
.switch__track{ position:absolute; inset:0; background:var(--track); border-radius:999px; transition:background .18s; box-shadow:inset 0 0 0 1px var(--border); }
.switch__track::after{ content:''; position:absolute; top:2.5px; left:2.5px; width:22px; height:22px; border-radius:50%; background:#fff; box-shadow:0 1px 3px rgba(0,0,0,.25); transition:transform .18s; }
.switch input:checked + .switch__track{ background:var(--c-blue); box-shadow:none; }
.switch input:checked + .switch__track::after{ transform:translateX(19px); }
.settings-note{ font-family:var(--font-mono); font-size:10px; color:var(--text-faint); margin-top:16px; line-height:1.5; }

#settingsTabStrip{ margin-bottom:20px; }
.settings-pane{ display:none; }
.settings-pane.is-active{ display:block; }

.user-row{ display:flex; align-items:center; gap:10px; padding:10px 0; border-bottom:1px solid var(--border); flex-wrap:wrap; }

.activity-row{ padding:10px 0; border-bottom:1px solid var(--border); }
.activity-row__top{ display:flex; justify-content:space-between; align-items:baseline; gap:8px; }
.activity-row__action{ font-family:var(--font-mono); font-size:11.5px; font-weight:600; color:var(--text); }
.activity-row__ts{ font-family:var(--font-mono); font-size:10px; color:var(--text-faint); white-space:nowrap; }
.activity-row__meta{ display:flex; gap:12px; font-size:11px; color:var(--text-secondary); margin-top:2px; }
.activity-row__detail{ font-size:12px; color:var(--text-secondary); margin-top:3px; }
.activity-row__ua{ font-family:var(--font-mono); font-size:9.5px; color:var(--text-faint); margin-top:3px; }
.user-avatar{ width:32px; height:32px; border-radius:50%; background:var(--hover); display:flex; align-items:center; justify-content:center; font-weight:600; font-size:12px; }
.user-info{ flex:1; display:flex; flex-direction:column; gap:1px; }
.user-role{ font-family:var(--font-mono); font-size:9.5px; color:var(--text-faint); }
.role-badge{ font-family:var(--font-mono); font-size:9.5px; padding:3px 8px; border-radius:20px; }
.role-badge.owner{ background:rgba(0,113,227,.12); color:var(--c-blue); }
.role-badge.guest{ background:var(--hover); color:var(--text-secondary); }
.user-row button{ background:none; border:none; color:var(--text-faint); cursor:pointer; font-size:11px; text-decoration:underline; }

.auth-field{ width:100%; background:var(--surface); border:1px solid var(--border); border-radius:10px; padding:11px 12px; color:var(--text); margin-bottom:10px; font-size:13px; }
.btn{ border:none; border-radius:12px; padding:11px 14px; background:var(--c-blue); color:var(--on-blue); font-weight:600; cursor:pointer; }
.btn.ghost{ background:transparent; border:1px dashed var(--border); color:var(--text-secondary); font-weight:400; width:100%; margin-top:10px; }
.btn.neutral{ background:var(--btn-neutral-bg); border:none; color:var(--btn-neutral-text); font-weight:600; width:100%; margin-top:10px; }
.btn.link{ background:none; color:var(--c-blue); text-decoration:none; font-weight:400; padding:4px; margin-top:6px; }
.btn.danger{ background:transparent; border:1px solid var(--c-red); color:var(--c-red); font-weight:600; }
.btn-flat{ flex:1; background:var(--btn-idle); color:var(--text); border:none; border-radius:10px; padding:10px 6px; font-size:12px; font-weight:600; cursor:pointer; display:flex; align-items:center; justify-content:center; gap:6px; text-align:center; }
.btn-flat svg{ width:14px; height:14px; flex-shrink:0; color:var(--c-amber); }
.logoff-actions{ display:flex; gap:8px; margin-bottom:16px; align-items:stretch; }
.logoff-actions .btn{ flex:1; width:auto; margin:0; }

.auth-overlay{ position:fixed; inset:0; background:var(--bg); display:none; flex-direction:column; align-items:center; justify-content:flex-start; padding:20px 28px 20px; text-align:center; z-index:50; }
.auth-overlay.is-locked{ display:flex; }
.auth-avatar{ width:40px; height:40px; border-radius:50%; background:var(--c-blue); color:var(--on-blue); display:flex; align-items:center; justify-content:center; font-weight:600; font-size:15px; margin-bottom:8px; }
.auth-box{ width:100%; max-width:260px; }
.auth-box > p:not(.error-text){ margin:0 0 16px; font-size:15px; font-weight:500; }
.pin-dots{ display:flex; gap:12px; justify-content:center; margin:8px 0 16px; }
.pin-dot{ width:11px; height:11px; border-radius:50%; border:1.5px solid var(--text-faint); }
.pin-dot.is-filled{ background:var(--c-blue); border-color:var(--c-blue); }
.pin-pad{ display:grid; grid-template-columns:repeat(3,1fr); gap:8px; }
.pin-key{ position:relative; aspect-ratio:1; border-radius:50%; border:none; background:transparent; color:var(--text); font-size:20px; font-weight:500; cursor:pointer; display:flex; align-items:center; justify-content:center; -webkit-tap-highlight-color:transparent; }
.pin-key svg{ width:20px; height:20px; }
.pin-key::before{ content:''; position:absolute; inset:6%; border-radius:50%; background:var(--track); opacity:0; transition:opacity .1s; }
.pin-key:active::before{ opacity:1; }
.pin-key--ghost{ visibility:hidden; }

.error-text{ color:var(--c-red); font-size:12px; margin:4px 0 10px; min-height:1em; }
.hidden{ display:none !important; }

.modal-backdrop{ position:fixed; inset:0; background:rgba(0,0,0,.4); display:flex; align-items:center; justify-content:center; z-index:60; padding:20px; }
.modal-box{ background:var(--surface); border:1px solid var(--border); border-radius:18px; padding:22px; width:100%; max-width:300px; box-shadow:0 8px 30px rgba(0,0,0,.25); }
.modal-title{ font-size:16px; font-weight:600; margin:0 0 8px; color:var(--text); }
.modal-body{ font-size:13px; color:var(--text-secondary); margin:0 0 20px; line-height:1.5; }
.modal-actions{ display:flex; gap:10px; }
.modal-actions .btn{ flex:1; margin:0; }
.modal-actions .btn.ghost{ margin:0; }

/* --- Mobile portrait (e.g. a phone, not Tesla's wide landscape screen) ---
   This app was designed exclusively for Tesla's ~2200px-wide screen and
   never adapted for a narrow phone — the fixed 136px text-label sidebar
   alone was eating over a third of a 390px-wide viewport, which is what
   was causing gate-row content to overflow and clip. Icon-only sidebar
   frees up real width; everything in the gate row shrinks to fit what's
   left rather than overflowing it. */
@media (max-width: 600px) {
  .sidebar{ width:58px; padding:16px 4px; gap:0; }
  .side-item{ padding:10px 2px; }
  .side-item span{ display:none; }
  .main{ padding:16px 12px; }
  .row__name{ font-size:13px; }
}
@media (max-width: 480px) {
  #gateList{ grid-template-columns:1fr; gap:18px 0; }
  .gatebtn{ width:150px; height:150px; }
  .gatebtn__status{ font-size:19px; }
  .gatebtn__action{ font-size:12.5px; }
}

/* --- Links --- */
.links-grid{ display:grid; grid-template-columns:repeat(auto-fill, minmax(300px, 1fr)); gap:10px; }
.link-card{ display:flex; align-items:center; gap:10px; background:var(--surface); border:1px solid var(--border); border-radius:12px; padding:10px 12px; }
.link-card__main{ display:flex; align-items:center; gap:10px; flex:1; min-width:0; text-decoration:none; color:inherit; }
.link-card__favicon{ width:24px; height:24px; flex-shrink:0; display:flex; align-items:center; justify-content:center; color:var(--text-faint); }
.link-card__favicon svg{ width:17px; height:17px; }
.link-card__text{ display:flex; flex-direction:column; min-width:0; overflow:hidden; }
.link-card__desc{ font-size:13px; font-weight:600; color:var(--text); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.link-card__url{ font-size:11px; color:var(--text-faint); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.link-card__actions{ display:flex; gap:2px; flex-shrink:0; }

/* --- Cameras --- */
.mode-label-row{ display:flex; flex-direction:column; gap:6px; margin:4px 0 18px; }
.mode-label-row__label{ font-size:13px; color:var(--text-secondary); font-weight:500; }

#cameraList[data-layout="list"]{ display:flex; flex-direction:column; }
#cameraList[data-layout="grid2"]{ display:grid; grid-template-columns:repeat(2, 1fr); gap:8px; }
#cameraList[data-layout="grid3"]{ display:grid; grid-template-columns:repeat(3, 1fr); gap:7px; }
#cameraList[data-layout="grid5"]{ display:grid; grid-template-columns:repeat(5, 1fr); gap:6px; }
#cameraList .group-label{ grid-column:1 / -1; }

.camera-row{ display:flex; align-items:center; gap:12px; padding:12px 0; border-bottom:1px solid var(--border); cursor:pointer; background:none; border-left:none; border-right:none; border-top:none; width:100%; text-align:left; }
.camera-row__name{ flex:1; min-width:0; font-size:16px; font-weight:700; letter-spacing:-.01em; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.camera-stat{ display:flex; align-items:center; gap:4px; font-size:12px; font-weight:600; flex-shrink:0; }
.camera-stat svg{ width:16px; height:16px; }
.camera-stat.is-normal{ color:var(--c-green); }
.camera-stat.is-warn{ color:var(--c-amber); }
.camera-stat.is-crit{ color:var(--c-red); }
.camera-sensor-icons{ display:flex; gap:9px; flex-shrink:0; }
.camera-sensor-icon{ position:relative; width:19px; height:19px; color:var(--text-faint); }
.camera-sensor-icon svg{ width:100%; height:100%; }
.camera-sensor-icon.is-active{ color:var(--c-blue); }
.camera-sensor-icon__dot{ position:absolute; top:-2px; right:-3px; width:6px; height:6px; border-radius:50%; background:var(--text-faint); }
.camera-sensor-icon.is-active .camera-sensor-icon__dot{ background:var(--c-blue); }
.camera-row__quick{ display:flex; gap:6px; flex-shrink:0; }
.camera-row__quick .icon-btn{ width:30px; height:30px; background:var(--btn-idle); }
.camera-row__quick .icon-btn svg{ width:17px; height:17px; }
.camera-row__chevron{ color:var(--text-faint); flex-shrink:0; }
.camera-row__chevron svg{ width:17px; height:17px; }

.camera-card{ background:var(--surface); border:1px solid var(--border); border-radius:12px; padding:12px; display:flex; flex-direction:column; gap:8px; cursor:pointer; text-align:left; }
.camera-card__thumb{ width:100%; aspect-ratio:1.3; background:var(--bg); border-radius:8px; overflow:hidden; position:relative; display:flex; align-items:center; justify-content:center; }
.camera-card__thumb img{ width:100%; height:100%; object-fit:cover; display:block; }
.camera-card__thumb svg{ width:26px; height:26px; color:var(--text-faint); }
.camera-card__ts{ position:absolute; bottom:3px; right:5px; font-size:8.5px; color:#fff; background:rgba(0,0,0,.55); padding:1px 4px; border-radius:4px; }
.camera-card__name{ font-size:15px; font-weight:700; letter-spacing:-.01em; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.camera-card__info-row{ display:flex; align-items:center; justify-content:space-between; gap:6px; }
.camera-card__stats-ts{ display:flex; flex-direction:column; gap:1px; font-size:10px; color:var(--text-faint); margin-top:4px; }
.camera-card__stats{ display:flex; gap:8px; flex-shrink:0; }
.camera-card .camera-stat{ font-size:11.5px; }
.camera-card .camera-stat svg{ width:14px; height:14px; }
.camera-card .camera-sensor-icons{ gap:7px; }
.camera-card .camera-sensor-icon{ width:16px; height:16px; }

.camera-detail-box{ max-width:380px; text-align:left; }
.camera-detail-header{ display:flex; align-items:center; gap:8px; margin-bottom:12px; }
.camera-detail-name{ font-size:16px; font-weight:700; }
.camera-detail-image{ background:var(--bg); border:1px dashed var(--border); border-radius:8px; height:170px; display:flex; align-items:center; justify-content:center; margin-bottom:10px; overflow:hidden; position:relative; }
.camera-detail-image img, .camera-detail-image video{ width:100%; height:100%; object-fit:cover; display:block; }
.camera-detail-image__placeholder{ font-size:12px; color:var(--text-faint); }
.camera-detail-image__ts{ position:absolute; bottom:4px; right:6px; font-size:10px; color:#fff; background:rgba(0,0,0,.55); padding:2px 6px; border-radius:4px; }
.camera-detail-image__loading-overlay{ position:absolute; top:50%; left:50%; transform:translate(-50%,-50%); font-size:12px; color:#fff; background:rgba(0,0,0,.6); padding:6px 12px; border-radius:6px; white-space:nowrap; }
.camera-detail-actions{ margin-bottom:8px; display:flex; flex-wrap:wrap; gap:8px; }
.camera-detail-controls{ display:flex; flex-wrap:wrap; gap:8px; margin:8px 0; }
.camera-action-btn{ flex:1 1 calc(50% - 4px); display:flex; flex-direction:row; align-items:center; justify-content:center; gap:8px; background:var(--btn-idle); border:none; border-radius:12px; padding:12px 8px; color:var(--text); font-size:12px; font-weight:700; cursor:pointer; }
.camera-action-btn svg{ width:22px; height:22px; }
.camera-action-btn.is-on{ background:var(--c-blue); border-color:var(--c-blue); color:var(--on-blue); }
.camera-action-btn:disabled{ opacity:.4; cursor:default; }
.camera-detail-sensors{ margin-top:6px; }
.camera-detail-stats-ts{ display:block; text-align:center; font-size:10px; color:var(--text-faint); margin-top:10px; }
.camera-detail-sensor-row{ display:flex; align-items:center; justify-content:space-between; padding:10px 2px; border-top:1px solid var(--border); border-left:none; border-right:none; border-bottom:none; background:none; width:100%; font-size:13px; cursor:pointer; text-align:left; }
.camera-detail-sensor-row__label{ display:flex; align-items:center; gap:6px; color:var(--text); }
.camera-detail-sensor-row__label svg{ width:15px; height:15px; color:var(--text-faint); }
.camera-detail-sensor-row.is-active .camera-detail-sensor-row__label svg{ color:var(--c-blue); }
.camera-detail-sensor-row__value{ color:var(--text-faint); font-size:12px; display:flex; align-items:center; gap:6px; }
.camera-detail-sensor-row__value svg{ width:13px; height:13px; color:var(--text-faint); }
.camera-detail-sensor-row.is-active .camera-detail-sensor-row__value{ color:var(--c-blue); }
.sensor-history-row{ padding:9px 2px; border-top:1px solid var(--border); font-size:13px; }
.sensor-history-row:first-child{ border-top:none; }

@media (max-width: 600px) {
  .links-grid{ grid-template-columns:1fr; }
  #cameraList[data-layout="grid3"], #cameraList[data-layout="grid5"]{ grid-template-columns:repeat(2, 1fr); }
}

/* --- Settings -> General: palette picker (custom buttons, no native select) --- */
.palette-picker{ display:flex; flex-wrap:wrap; gap:10px; margin:10px 0 4px; }
.palette-opt{ flex:1 1 84px; display:flex; flex-direction:column; align-items:center; gap:8px; padding:12px 8px; border-radius:12px; border:2px solid var(--border); background:var(--surface); color:var(--text-secondary); font-size:12px; font-weight:600; cursor:pointer; }
.palette-opt.is-current{ border-color:var(--c-blue); color:var(--text); }
.palette-opt__swatch{ display:flex; width:64px; height:28px; border-radius:8px; overflow:hidden; border:1px solid var(--border); }
.palette-opt__swatch span{ flex:1; }
