:root {
  --bg: #0e1116; --panel: #161b24; --panel-2: #1c2330; --line: #252d3b;
  --text: #e6eaf2; --muted: #8b95a8; --accent: #3ddc97; --accent-2: #5aa9ff;
  --warn: #ffb84d; --bad: #ff5d6c; --chip: #232b3a;
  --dot-idle: #475063; --zebra: rgba(255, 255, 255, .028); --line-hover: #3a4558;
  --overlay: rgba(14, 17, 22, .86); --field: #0b0e13;
  --radius: 12px; --font: system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, sans-serif;
}
/* light theme: html.light — sidebar toggle in the browser, ?theme=light on kiosk pages */
html.light {
  --bg: #eef1f6; --panel: #ffffff; --panel-2: #e7ebf2; --line: #d7dde7;
  --text: #17202e; --muted: #5d6a80; --accent: #12a86e; --accent-2: #2b74d4;
  --warn: #d98a1f; --bad: #d63b4d; --chip: #e7ecf3;
  --dot-idle: #b6c0cd; --zebra: rgba(24, 40, 70, .055); --line-hover: #aeb9c9;
  --overlay: rgba(240, 243, 248, .9); --field: #ffffff; --hot-row: rgba(217, 138, 31, .13);
}
html.light .chip.status-scaffold { color: #17202e; background: #c9d3e1; }
html.light .chip.status-archived { color: #5d6a80; background: #dde3ec; }
html.light .tman { --c-cpu: #2b74d4; --c-mem: #0f9a66; --c-dsk: #b8760e; --c-gpu: #7e52cc; --c-net: #0e8ba0;
  --c-ai: #c2377f; }
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body { background: var(--bg); color: var(--text); font: 15px/1.45 var(--font); min-height: 100vh; }
a { color: var(--accent-2); text-decoration: none; }
a:hover { text-decoration: underline; }
h1, h2, h3 { margin: 0 0 .5rem; font-weight: 650; letter-spacing: -.01em; }
h1 { font-size: 1.5rem; } h2 { font-size: 1.15rem; } h3 { font-size: 1rem; }
small, .muted { color: var(--muted); }
code, pre { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: .9em; }
pre { background: var(--field); border: 1px solid var(--line); border-radius: 8px; padding: .75rem; overflow: auto; }

/* ---- app shell: icon sidebar (Pass A redesign) */
.dot { width: 10px; height: 10px; border-radius: 50%; background: var(--accent); display: inline-block;
  box-shadow: 0 0 10px var(--accent); }
body.with-side { display: flex; min-height: 100vh; }
body.with-side > main { flex: 1; min-width: 0; }
.side { width: 210px; flex: none; background: var(--panel); border-right: 1px solid var(--line);
  display: flex; flex-direction: column; padding: .9rem .6rem; position: sticky; top: 0;
  height: 100vh; overflow-y: auto; }
.side .brand { display: flex; align-items: flex-start; gap: .55rem; color: var(--text); font-weight: 700;
  font-size: 1.02rem; padding: .2rem .55rem 1rem; line-height: 1.15; }
.side .brand .dot { margin-top: .3rem; }
.side .brand small { display: block; color: var(--muted); font-weight: 400; font-size: .7rem; }
.side .brand:hover { text-decoration: none; }
.side nav { display: flex; flex-direction: column; gap: 2px; }
.side nav a { display: flex; align-items: center; gap: .65rem; color: var(--muted); padding: .48rem .6rem;
  border-radius: 9px; font-size: .9rem; border-left: 2px solid transparent; }
.side nav a svg { width: 17px; height: 17px; flex: none; stroke: currentColor; fill: none;
  stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.side nav a.on { color: var(--text); background: var(--panel-2); border-left-color: var(--accent); }
.side nav a:hover { color: var(--text); background: var(--panel-2); text-decoration: none; }
.side .side-foot { margin-top: auto; padding: .6rem .55rem 0; display: flex; align-items: center; gap: .5rem; }
.side .side-foot .muted { font-size: .72rem; }
.side .side-foot form { margin-left: auto; }
.side .side-foot button { padding: .3rem .6rem; font-size: .82rem; }
@media (max-width: 820px) {
  .side { width: 58px; padding: .9rem .3rem; }
  .side .brand .bt, .side nav a span, .side .side-foot .muted { display: none; }
  .side nav a { justify-content: center; padding: .55rem 0; }
}

/* ---- layout */
.wrap { max-width: 1240px; margin: 0 auto; padding: 1.25rem; }
.grid { display: grid; gap: 1rem; }
.grid.tiles { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
.grid.cards { grid-template-columns: repeat(auto-fill, minmax(290px, 1fr)); }
.grid.two { grid-template-columns: 1fr 1fr; }
@media (max-width: 900px) { .grid.two { grid-template-columns: 1fr; } }
.section { margin-top: 1.5rem; }
.section-head { display: flex; align-items: baseline; gap: 1rem; margin-bottom: .6rem; }
.section-head .right { margin-left: auto; }

/* ---- panels */
.panel { background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); padding: 1rem; }
.tile { background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); padding: .85rem 1rem; }
.tile .k { color: var(--muted); font-size: .8rem; text-transform: uppercase; letter-spacing: .06em; }
.tile .v { font-size: 1.45rem; font-weight: 650; margin-top: .15rem; }
.tile .s { color: var(--muted); font-size: .8rem; }
.bar { height: 6px; background: var(--chip); border-radius: 4px; overflow: hidden; margin-top: .5rem; }
.bar > i { display: block; height: 100%; background: var(--accent); }
.bar > i.warn { background: var(--warn); } .bar > i.bad { background: var(--bad); }

/* ---- app cards */
.card { background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); padding: 1rem;
  display: flex; flex-direction: column; gap: .6rem; transition: border-color .15s, transform .15s; }
.card:hover { border-color: var(--line-hover); }
.card .state { width: 12px; height: 12px; }
.card .head { display: flex; align-items: center; gap: .6rem; }
.card .head h3 { margin: 0; }
.card .head h3 a { color: var(--text); }
.card .tagline { color: var(--muted); }
.chips { display: flex; flex-wrap: wrap; gap: .35rem; }
.chip { background: var(--chip); color: var(--muted); border-radius: 999px; padding: .12rem .6rem; font-size: .78rem; }
.chip.status-live { color: #0c1a14; background: var(--accent); }
.chip.status-dev { color: #1a1306; background: var(--warn); }
.chip.status-scaffold { color: var(--text); background: #3b4559; }
.chip.status-archived { color: var(--muted); background: #2a2f3a; }
.chip.runs-pi { color: #0b1a2b; background: var(--accent-2); }
.actions { display: flex; gap: .5rem; flex-wrap: wrap; margin-top: auto; }
.state { width: 10px; height: 10px; border-radius: 50%; background: var(--dot-idle); flex: none; }
.state.up { background: var(--accent); box-shadow: 0 0 8px var(--accent); }
.state.down { background: var(--bad); box-shadow: 0 0 8px var(--bad); }
.state.unknown { background: var(--warn); }

/* ---- buttons & forms */
button, .btn { font: inherit; border: 1px solid var(--line); background: var(--panel-2); color: var(--text);
  padding: .45rem .85rem; border-radius: 8px; cursor: pointer; }
button:hover, .btn:hover { border-color: var(--line-hover); text-decoration: none; }
button.primary, .btn.primary { background: var(--accent); color: #0c1a14; border-color: transparent; font-weight: 600; }
button.danger { background: transparent; color: var(--bad); border-color: var(--bad); }
button.ghost { background: transparent; color: var(--muted); }
button:disabled { opacity: .5; cursor: not-allowed; }
button.active-screen { outline: 2px solid var(--accent); }
input, textarea, select { font: inherit; background: var(--field); color: var(--text); border: 1px solid var(--line);
  border-radius: 8px; padding: .5rem .65rem; width: 100%; }
textarea { min-height: 320px; font-family: ui-monospace, Menlo, Consolas, monospace; font-size: .85rem; }
label { display: block; color: var(--muted); font-size: .85rem; margin: .6rem 0 .25rem; }
.form-row { display: flex; gap: .75rem; align-items: end; flex-wrap: wrap; }
.form-row > div { flex: 1; min-width: 200px; }
.error { color: var(--bad); margin: .5rem 0; }
.ok { color: var(--accent); }
.notice { border-left: 3px solid var(--warn); background: rgba(255,184,77,.08); padding: .6rem .8rem; border-radius: 6px; }

/* ---- tables */
table { width: 100%; border-collapse: collapse; }
th, td { text-align: left; padding: .45rem .5rem; border-bottom: 1px solid var(--line); vertical-align: top; }
th { color: var(--muted); font-weight: 500; font-size: .8rem; text-transform: uppercase; letter-spacing: .05em; }
tr:last-child td { border-bottom: 0; }

/* ---- auth pages */
.auth { max-width: 420px; margin: 10vh auto; }
.auth .panel { padding: 1.5rem; }

/* ---- remote desktop */
.vnc-frame { width: 100%; height: calc(100vh - 140px); border: 1px solid var(--line); border-radius: var(--radius);
  background: #000; }

/* ---- toast */
.toast { position: fixed; right: 1rem; bottom: 1rem; background: var(--panel-2); border: 1px solid var(--line);
  border-radius: 10px; padding: .6rem .9rem; opacity: 0; transform: translateY(10px); transition: .2s; pointer-events: none; }
.toast.show { opacity: 1; transform: none; }
.toast.bad { border-color: var(--bad); }

/* ---- dashboard ring gauges (Pass B) */
.gauges { display: grid; grid-template-columns: repeat(auto-fit, minmax(185px, 1fr)); gap: 1rem; }
.gauge { background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
  padding: .75rem .9rem; display: flex; align-items: center; gap: .85rem; }
.gauge .ring { position: relative; width: 74px; height: 74px; flex: none; }
.gauge .ring svg { position: absolute; inset: 0; transform: rotate(-90deg); }
.gauge .ring circle { fill: none; stroke-width: 7; }
.gauge .ring .track { stroke: var(--chip); }
.gauge .ring .val { transition: stroke-dashoffset .6s ease, stroke .3s; stroke-linecap: round; }
.gauge .ring .gv { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  font-size: .95rem; font-weight: 700; }
.gauge .gk { color: var(--muted); font-size: .72rem; text-transform: uppercase; letter-spacing: .07em; }
.gauge .gs { color: var(--muted); font-size: .76rem; margin-top: .15rem; }
.gauge.text { display: block; }
.gauge.text .gv2 { font-size: 1.2rem; font-weight: 700; margin: .2rem 0; }

/* ---- dashboard hero: screen switcher + live monitor preview (Pass A) */
.grid.hero { grid-template-columns: 1.6fr 1fr; }
@media (max-width: 1000px) { .grid.hero { grid-template-columns: 1fr; } }
.grid.hero .wide { grid-column: 1 / -1; }
.screen-chips { display: flex; flex-wrap: wrap; gap: .45rem; }
.screen-chips button { border-radius: 999px; padding: .4rem .95rem; font-size: .88rem; }
.screen-chips button.active-screen { outline: none; background: var(--accent); color: #0c1a14;
  border-color: transparent; font-weight: 600; }
.mon { margin: 0 auto; width: 270px; }
.mon .mon-screen { width: 268px; height: 156px; border: 6px solid #05070a; border-radius: 8px;
  background: #05070a; overflow: hidden; position: relative; box-shadow: 0 8px 28px rgba(0,0,0,.5); }
.mon .mon-screen iframe { width: 1024px; height: 600px; transform: scale(0.25); transform-origin: 0 0;
  border: 0; pointer-events: none; background: var(--bg); }
.mon .mon-stand { width: 74px; height: 11px; background: #10141b; margin: 0 auto; border-radius: 0 0 6px 6px; }
.mon .mon-base { width: 120px; height: 4px; background: #10141b; margin: 0 auto; border-radius: 4px; }
.mon .mon-cap { text-align: center; color: var(--muted); font-size: .76rem; margin-top: .45rem; }
/* ---- calendar (browser page) */
.setup { margin: .5rem 0 0 1.1rem; padding: 0; color: var(--muted); line-height: 1.7; }
.setup li { margin-bottom: .3rem; }
.setup b { color: var(--text); }
.ev-day { color: var(--muted); font-size: .76rem; text-transform: uppercase; letter-spacing: .07em;
  margin: .8rem 0 .25rem; border-bottom: 1px solid var(--line); padding-bottom: .2rem; }
.ev { display: flex; align-items: baseline; gap: .6rem; padding: .28rem 0; font-size: .92rem; }
.ev .ev-t { color: var(--muted); width: 74px; flex: none; font-variant-numeric: tabular-nums; }
.ev .ev-n { font-weight: 600; }
.ev .ev-cal { font-size: .78rem; }
.cdot { width: 9px; height: 9px; border-radius: 3px; display: inline-block; flex: none; }
.calpick { display: flex; align-items: center; gap: .45rem; margin: .15rem 0; color: var(--text);
  font-size: .88rem; }
.calpick input { width: auto; }
.cal-screen .cdot { width: 8px; height: 8px; border-radius: 2px; }
.cleg { display: inline-flex; align-items: center; gap: 4px; margin-right: 10px; }

/* ---- calendar (Pi screen) */
.cal-screen { display: flex; flex-direction: column; height: 100vh; padding: 12px 16px; gap: 10px; }
.cal-screen .cal-head { display: flex; align-items: flex-end; gap: 1rem; }
.cal-screen .cal-today { font-size: 34px; font-weight: 700; line-height: 1; }
.cal-screen .cal-date { font-size: 15px; margin-top: 3px; }
.cal-screen .cal-clock { font-size: 40px; font-weight: 700; letter-spacing: -.02em; }
/* summary tiles (mockup pass 3) */
.cal-screen .cal-kpis { display: flex; gap: 14px; margin-left: auto; margin-right: 18px; }
.cal-screen .kpi { text-align: right; line-height: 1.15; }
.cal-screen .kpi b { display: block; font-size: 19px; font-weight: 700; }
.cal-screen .kpi span { color: var(--muted); font-size: 10.5px; text-transform: uppercase; letter-spacing: .06em; }
.cal-screen .kpi span.nx { text-transform: none; letter-spacing: 0; max-width: 150px;
  display: inline-block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* all-day band above the timeline */
.cal-screen .allday { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 6px; }
.cal-screen .allday .ad { display: inline-flex; align-items: center; gap: 4px; font-size: 12px;
  background: var(--chip); border-radius: 5px; padding: 2px 7px; max-width: 100%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cal-screen .allday .ad.more { color: var(--muted); background: transparent; }
/* today as an hour grid with a live now-line (mockup pass 2) */
.cal-screen .tl { position: relative; flex: 1; min-height: 0; }
.cal-screen .tl-grid { position: relative; height: 100%; }
.cal-screen .tl-hour { position: absolute; left: 0; right: 0; border-top: 1px solid var(--line);
  height: 0; }
.cal-screen .tl-hour span { position: absolute; top: -7px; left: 0; font-size: 10px; color: var(--muted);
  background: var(--panel); padding-right: 4px; }
.cal-screen .tl-ev { position: absolute; left: 30px; right: 2px; background: var(--chip);
  border-left: 3px solid var(--accent-2); border-radius: 5px; padding: 2px 6px; font-size: 12.5px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cal-screen .tl-ev b { font-variant-numeric: tabular-nums; margin-right: 3px; }
.cal-screen .tl-ev.past { opacity: .5; }
.cal-screen .tl-now { position: absolute; left: 24px; right: 0; height: 0; border-top: 2px solid var(--bad);
  z-index: 3; }
.cal-screen .tl-now i { position: absolute; left: -5px; top: -4px; width: 7px; height: 7px;
  border-radius: 50%; background: var(--bad); }
.cal-screen .tl-empty { padding-top: 8px; }
.cal-screen .cal-body { grid-template-columns: 1.15fr 1fr 240px; }
/* Today has nothing timed in it: shrink that column and give the width to Next Up, whose
   titles were being clipped mid-word. */
.cal-screen.slim-today .cal-body { grid-template-columns: 265px 1fr 226px; }
.cal-screen.slim-today .tl { flex: none; min-height: 0; }
.cal-screen.slim-today .cal-col:first-child { justify-content: flex-start; }

/* ---- weather: the morning-brief half of the Today column */
.cal-screen .wx { border-bottom: 1px solid var(--line); padding-bottom: 7px; margin-bottom: 7px; }
.cal-screen .wx-top { display: flex; align-items: center; gap: 9px; }
.cal-screen .wx-icon { line-height: 0; color: var(--c-wx, var(--accent-2)); flex: none; }
.cal-screen .wx-icon svg { display: block; }
.cal-screen .wxh b svg { display: block; color: var(--muted); }
.cal-screen .wx-temp { font-size: 30px; font-weight: 700; letter-spacing: -.02em; }
.cal-screen .wx-meta { display: flex; flex-direction: column; line-height: 1.25; min-width: 0; }
.cal-screen .wx-meta b { font-size: 12.5px; }
.cal-screen .wx-meta span { font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cal-screen .wx-facts { display: flex; flex-wrap: wrap; gap: 4px 8px; margin-top: 5px; }
.cal-screen .wxf { font-size: 11px; color: var(--muted); white-space: nowrap; }
.cal-screen .wxf.rain { color: var(--accent-2); font-weight: 600; }
.cal-screen .wxf.uv { color: var(--warn); font-weight: 600; }
.cal-screen .wx-strip { display: grid; grid-template-columns: repeat(6, 1fr); gap: 2px; margin-top: 6px; }
.cal-screen .wxh { display: flex; flex-direction: column; align-items: center; line-height: 1.25; }
.cal-screen .wxh i { font-style: normal; font-size: 9.5px; color: var(--muted); }
.cal-screen .wxh b { font-size: 13px; font-weight: 400; }
.cal-screen .wxh u { text-decoration: none; font-size: 11.5px; font-weight: 600; }
.cal-screen .wxh s { text-decoration: none; font-size: 9px; color: var(--accent-2); min-height: 11px; }
.cal-screen .wx-err { font-size: 11px; }
/* week at a glance strip (mockup pass 3) - also stops the Today panel leaving a dead
   half-screen on days that have no timed events */
.cal-screen .weekstrip { display: grid; grid-template-columns: repeat(7, 1fr); gap: 6px;
  flex: none; height: 128px; }
.cal-screen .wday { background: var(--panel); border: 1px solid var(--line); border-radius: 8px;
  padding: 5px 6px; overflow: hidden; display: flex; flex-direction: column; gap: 2px; }
.cal-screen .wday.is-today { border-color: var(--accent); background: var(--chip); }
.cal-screen .wh { font-size: 10.5px; color: var(--muted); text-transform: uppercase;
  letter-spacing: .05em; margin-bottom: 1px; }
.cal-screen .wh b { color: var(--text); font-size: 13px; }
.cal-screen .wchip { display: flex; align-items: center; gap: 4px; font-size: 11px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cal-screen .wchip b { font-variant-numeric: tabular-nums; color: var(--muted); font-weight: 600; }
.cal-screen .wmore { font-size: 10px; color: var(--muted); }
.cal-screen .wempty { font-size: 11px; color: var(--muted); opacity: .6; }
.cal-screen .cal-body { display: grid; grid-template-columns: 1fr 1fr 260px; gap: 14px; flex: 1; min-height: 0; }
.cal-screen .cal-col { background: var(--panel); border: 1px solid var(--line); border-radius: 10px;
  padding: 10px 12px; overflow: hidden; display: flex; flex-direction: column; }
.cal-screen h2 { font-size: 12px; text-transform: uppercase; letter-spacing: .1em; color: var(--muted);
  margin: 0 0 8px; }
.cal-screen .cal-list { overflow: hidden; }
.cal-screen .cal-ev { display: flex; align-items: baseline; gap: 8px; padding: 5px 0;
  border-bottom: 1px solid var(--line); font-size: 15px; }
.cal-screen .cal-ev:last-child { border-bottom: 0; }
.cal-screen .cal-ev .t { color: var(--accent-2); font-weight: 650; width: 76px; flex: none;
  font-variant-numeric: tabular-nums; font-size: 14px; }
/* Wrap to a second line rather than clipping mid-word - these titles are long
   ("Classes begin for students in year two and...") and a cut-off title is unreadable. */
.cal-screen .cal-ev .n { font-weight: 600; white-space: normal; overflow-wrap: anywhere;
  line-height: 1.25; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; }
.cal-screen .cal-ev { align-items: flex-start; }
.cal-screen .cal-ev .t, .cal-screen .cal-ev .l { padding-top: 1px; }
.cal-screen .cal-ev .l { margin-left: auto; font-size: 12px; white-space: nowrap; }
.cal-screen .cal-ev.past { opacity: .45; }
.cal-screen .cal-ev.soon { background: rgba(61,220,151,.10); border-radius: 6px; padding-left: 6px; }
.cal-screen .cal-ev.soon .t { color: var(--accent); }
.cal-screen .mm-h, .cal-screen .mm { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.cal-screen .mm-h i { color: var(--muted); font-size: 10px; text-align: center; font-style: normal; }
.cal-screen .mm span { text-align: center; font-size: 12px; padding: 3px 0; border-radius: 5px; }
.cal-screen .mm span.has { background: var(--chip); font-weight: 650; }
.cal-screen .mm span.today { background: var(--accent); color: #0c1a14; font-weight: 700; }
.cal-screen .cal-foot { font-size: 12px; }

/* ---- n8n page: one card per workflow, dense but scannable */
.n8n-kpis { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
.wf-list { display: grid; gap: .8rem; }
.wf { background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
  padding: .9rem; border-left: 3px solid var(--accent); }
.wf.off { border-left-color: var(--line); opacity: .82; }
.wf .wf-head { display: flex; align-items: center; gap: .55rem; margin-bottom: .6rem; }
.wf .wf-head h3 { margin: 0; font-size: 1.05rem; }
.wf .wf-head h3 a { color: var(--text); }
.wf .wf-nodes { margin-left: auto; font-size: .8rem; }
.wf .wf-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: .55rem .9rem; margin-bottom: .5rem; }
.wf .wf-cell.wide { grid-column: span 2; }
@media (max-width: 700px) { .wf .wf-cell.wide { grid-column: span 1; } }
.wf .ck { color: var(--muted); font-size: .7rem; text-transform: uppercase; letter-spacing: .07em; }
.wf .cv { font-size: .9rem; margin-top: .12rem; display: flex; align-items: center;
  gap: .35rem; flex-wrap: wrap; }
.wf .cv.chips { gap: .3rem; }
.wf .bar { height: 5px; margin-top: .3rem; }
.wf .chip.trig { background: var(--accent-2); color: #0b1a2b; font-weight: 600; }
/* light theme darkens --accent-2, so the dark chip text would sit on a dark blue fill */
html.light .wf .chip.trig { color: #fff; }
.wf .hook { font-size: .78rem; background: var(--field); border: 1px solid var(--line);
  border-radius: 5px; padding: .1rem .4rem; }
.wf .wf-runs { display: flex; align-items: center; gap: .5rem; margin-top: .35rem; flex-wrap: wrap; }
.wf .rds { display: inline-flex; gap: 2px; }
.wf .rd { width: 9px; height: 14px; border-radius: 2px; background: var(--dot-idle); display: inline-block; }
.wf .wf-foot { font-size: .74rem; margin-top: .5rem; }
.dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; background: var(--dot-idle); flex: none; }
.dot.ok, .rd.ok { background: var(--accent); }
.dot.bad, .rd.bad { background: var(--bad); }
.dot.warn, .rd.warn { background: var(--warn); }

.n8n-strip { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; }
.n8n-strip .actions { margin-left: auto; margin-top: 0; }

/* ---- dashboard row 2: screen control + desktop panel + widget rail
   (pass A's screen centrepiece and side widgets, pass B's compact status stack) */
.dash { display: grid; grid-template-columns: 1.5fr 1fr 260px; gap: 1rem; align-items: start; }
.dash .rail { display: flex; flex-direction: column; gap: .6rem; }
/* narrow: the rail becomes a horizontal strip under the two panels. These overrides must
   come AFTER the base .dash .rail rule - same specificity, so source order decides. */
@media (max-width: 1180px) {
  .dash { grid-template-columns: 1fr 1fr; }
  .dash .rail { grid-column: 1 / -1; display: grid; gap: .6rem;
    grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); }
}
@media (max-width: 780px) { .dash { grid-template-columns: 1fr; } }
.wcard { background: var(--panel); border: 1px solid var(--line); border-radius: 10px; padding: .7rem;
  display: block; color: var(--text); border-left: 3px solid var(--line); }
.wcard:hover { text-decoration: none; border-color: var(--line-hover); border-left-color: var(--accent); }
.wcard .wk { color: var(--muted); font-size: .74rem; text-transform: uppercase; letter-spacing: .06em;
  display: flex; align-items: center; gap: .4rem; }
.wcard .wv { font-size: 1.25rem; font-weight: 700; margin-top: .1rem; font-variant-numeric: tabular-nums; }
.wcard .ws { color: var(--muted); font-size: .76rem; }
.wcard .bar { margin: .35rem 0 .2rem; height: 5px; }
button.sm, .btn.sm { padding: .3rem .7rem; font-size: .82rem; }
.kv { display: flex; align-items: center; gap: .5rem; font-size: .92rem; margin-bottom: .5rem; }
.kv.sm { font-size: .85rem; margin: .3rem 0 0; }
.kv .r { margin-left: auto; font-variant-numeric: tabular-nums; }
.mini-bars { display: flex; flex-direction: column; gap: .4rem; margin: .7rem 0 .2rem; }
.mini-bars .mb { display: flex; align-items: center; gap: .55rem; }
.mini-bars .mb .k { color: var(--muted); font-size: .78rem; width: 52px; flex: none; }
.mini-bars .mb .bar { flex: 1; margin: 0; height: 6px; }
.mini-bars .mb .v { width: 44px; text-align: right; font-size: .82rem; font-variant-numeric: tabular-nums; }

/* ---- kiosk (Pi's own 600x1024 portrait monitor) */
body.kiosk { overflow: hidden; cursor: none; }
body.kiosk main { padding: 0; max-width: none; }
#screen-frame { position: fixed; inset: 0; width: 100vw; height: 100vh; border: 0; background: var(--bg); }
.shub { padding: 22px 20px; display: flex; flex-direction: column; gap: 16px; min-height: 100vh; }
.shub .clock { font-size: 64px; font-weight: 700; letter-spacing: -.02em; line-height: 1; }
.shub .date { color: var(--muted); font-size: 20px; margin-top: 4px; }
.shub .tiles { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.shub .tile .v { font-size: 26px; }
.shub h2 { font-size: 15px; text-transform: uppercase; letter-spacing: .1em; color: var(--muted); margin: 6px 0 0; }
.shub .applist { display: flex; flex-direction: column; gap: 8px; }
.shub .app { display: flex; align-items: center; gap: 10px; background: var(--panel); border: 1px solid var(--line);
  border-radius: 10px; padding: 10px 12px; }
.shub .app .n { font-weight: 600; }
.shub .app .t { color: var(--muted); font-size: 13px; }
.shub .app .where { margin-left: auto; }
.shub .foot { margin-top: auto; color: var(--muted); font-size: 13px; display: flex; justify-content: space-between; }

/* ---- kiosk Obsidian vault graph (structure pushed by the desktop agent) */
.vgraph { --vg-link: rgba(160,180,210,.22); --vg-text: #e6eaf2; --vg-halo: rgba(14,17,22,.85);
  display: flex; flex-direction: column; height: 100vh; padding: 8px 10px; gap: 6px; }
html.light .vgraph { --vg-link: rgba(40,60,90,.20); --vg-text: #17202c; --vg-halo: rgba(255,255,255,.9); }
.vgraph .vg-head { display: flex; align-items: center; gap: 12px; font-size: 13px; flex: none; }
.vgraph .vg-title { font-weight: 700; font-size: 16px; white-space: nowrap; flex: none; }
.vgraph .vg-head > .muted { white-space: nowrap; flex: none; }
.vgraph .vg-legend { display: flex; gap: 10px; flex-wrap: wrap; margin-left: auto; }
.vgraph .vg-legend .lg { display: flex; align-items: center; gap: 4px; color: var(--muted); font-size: 11.5px; }
.vgraph .vg-legend .lg i { width: 8px; height: 8px; border-radius: 50%; display: inline-block; }
.vgraph .vg-clock { font-weight: 650; color: var(--text); }
.vgraph canvas { flex: 1; min-height: 0; width: 100%; display: block; }
.vgraph .vg-empty { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  text-align: center; }
.vgraph .vg-empty[hidden] { display: none; }

/* ---- kiosk PC task manager (stats pushed by the desktop taskman agent) */
/* One hue per metric, used for the tile, its sparkline/bar AND the matching table column,
   so a glance tells you which metric a cell belongs to. */
.tman { --c-cpu: #5aa9ff; --c-mem: #3ddc97; --c-dsk: #ffb84d; --c-gpu: #b98cff; --c-net: #35c8dc; --c-ai: #ff7ab8;
  display: flex; flex-direction: column; height: 100vh; padding: 10px 12px; gap: 8px; }
.tman .tm-head { display: flex; align-items: center; gap: 10px; font-size: 15px; }
.tman .tm-host { font-weight: 700; font-size: 18px; }
.tman .tm-cpuname { font-size: 13px; }
.tman .tm-head-right { margin-left: auto; display: flex; gap: 14px; align-items: center; font-size: 13px; }
.tman .tm-clock { color: var(--text); font-weight: 650; font-size: 16px; }
.tman .tm-body { display: grid; grid-template-columns: 370px 1fr; gap: 8px; flex: 1; min-height: 0; }
.tman .tm-left { display: flex; flex-direction: column; gap: 8px; min-height: 0; }
.tman .tm-tile { background: var(--panel); border: 1px solid var(--line); border-radius: 10px; padding: 8px 10px;
  border-left-width: 3px; }
.tman .k { color: var(--muted); font-size: 11px; text-transform: uppercase; letter-spacing: .07em; }
.tman .tile-cpu { border-left-color: var(--c-cpu); } .tman .tile-cpu .k { color: var(--c-cpu); }
.tman .tile-mem { border-left-color: var(--c-mem); } .tman .tile-mem .k { color: var(--c-mem); }
.tman .tile-gpu { border-left-color: var(--c-gpu); } .tman .tile-gpu .k { color: var(--c-gpu); }
.tman .tile-dsk { border-left-color: var(--c-dsk); } .tman .tile-dsk .k { color: var(--c-dsk); }
.tman .tile-net { border-left-color: var(--c-net); } .tman .tile-net .k { color: var(--c-net); }
/* the loaded LM Studio model, shown next to the VRAM it occupies; amber below the
   Hermes 64K floor, red when nothing is loaded (the wake-gateway would JIT-load small) */
.tman .gpu-sub { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tman .gpu-sub #tm-ai { color: var(--c-ai); font-weight: 600; }
.tman .gpu-sub #tm-ai.warn { color: var(--warn); }
.tman .gpu-sub #tm-ai.bad { color: var(--bad); }
.tman .tile-mem .bar > i { background: var(--c-mem); }
.tman .tile-gpu .bar > i { background: var(--c-gpu); }
.tman .tile-dsk .bar > i { background: var(--c-dsk); }
.tman .bar > i.warn { background: var(--warn); } .tman .bar > i.bad { background: var(--bad); }
.tman .tm-row { display: flex; align-items: center; gap: 8px; }
.tman .tm-row .k { width: 62px; flex: none; }
.tman .tm-row .v { font-size: 22px; font-weight: 700; min-width: 62px; }
.tman .tm-row .s { color: var(--muted); font-size: 12px; flex: 1; }
.tman .spark { margin-left: auto; flex: none; opacity: .9; }
.tman .tm-cores { display: grid; grid-template-columns: repeat(16, 1fr); gap: 3px; margin-top: 7px; }
.tman .tm-cores i { display: block; height: 9px; border-radius: 2px; background: var(--accent-2); opacity: .12; }
.tman .bar { margin-top: 6px; }
.tman .bar.thin { height: 4px; margin-top: 3px; }
.tman .tm-line { display: flex; align-items: baseline; gap: 8px; margin-top: 5px; font-size: 13px; }
.tman .tm-line .n { font-weight: 600; }
.tman .tm-line .r { margin-left: auto; color: var(--muted); font-variant-numeric: tabular-nums; }
.tman .tm-vols { margin-top: 6px; font-size: 12px; }
.tman .s.muted { font-size: 12px; margin-top: 4px; }
.tman .tm-procs { background: var(--panel); border: 1px solid var(--line); border-radius: 10px;
  padding: 4px 8px; overflow: hidden; min-height: 0; }
.tman .tm-procs table { font-size: 13px; }
.tman .tm-procs th, .tman .tm-procs td { padding: .24rem .45rem; }
.tman .tm-procs th { line-height: 1.2; padding-bottom: .3rem; }
.tman .tm-procs th .tot { display: block; font-size: 14.5px; font-weight: 700; letter-spacing: 0;
  text-transform: none; margin-top: 1px; }
.tman .tm-procs th.sortable { cursor: pointer; }
.tman .tm-procs th.num, .tman .tm-procs td.num { text-align: right; font-variant-numeric: tabular-nums;
  width: 86px; white-space: nowrap; }
.tman .tm-procs td.name { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  max-width: 0; }
/* row tracking: zebra stripes; idle rows dimmed so active ones pop */
.tman .tm-procs tbody tr:nth-child(odd) td { background: var(--zebra); }
.tman .tm-procs tr.idle td { opacity: .5; }
/* the top-impact processes get the loud treatment (importance score, not just sort order) */
.tman .tm-procs tbody tr.hot td { font-weight: 650; background: var(--hot-row, rgba(255,184,77,.10)); }
.tman .tm-procs tbody tr.hot td.name { border-left: 3px solid var(--warn); padding-left: .35rem; }
.tman .tm-procs td.num.em { font-weight: 700; }
.tman .pid { color: var(--muted); font-weight: 400; font-size: 11px; }
.tman .chip.new { background: var(--warn); color: #1a1306; font-size: 9.5px; font-weight: 700;
  text-transform: uppercase; padding: 0 6px; border-radius: 999px; letter-spacing: .04em; }
.tman .lg-bar { display: inline-block; width: 3px; height: 11px; background: var(--warn);
  margin-right: 5px; vertical-align: -2px; }
/* column identity: solid header band in the metric's hue (total inside), faint column wash below */
.tman { --th-text: #0c1116; }
html.light .tman { --th-text: #ffffff; }
.tman .tm-procs th.sortable { color: var(--th-text); opacity: .82; border-radius: 7px 7px 0 0; }
.tman .tm-procs th.sortable .tot { color: var(--th-text); }
.tman .tm-procs th.c-cpu { background: var(--c-cpu); } .tman .tm-procs td.c-cpu { box-shadow: inset 0 0 0 999px rgba(90,169,255,.05); --bc: var(--c-cpu); }
.tman .tm-procs th.c-mem { background: var(--c-mem); } .tman .tm-procs td.c-mem { box-shadow: inset 0 0 0 999px rgba(61,220,151,.05); --bc: var(--c-mem); }
.tman .tm-procs th.c-dsk { background: var(--c-dsk); } .tman .tm-procs td.c-dsk { box-shadow: inset 0 0 0 999px rgba(255,184,77,.05); --bc: var(--c-dsk); }
.tman .tm-procs th.c-gpu { background: var(--c-gpu); } .tman .tm-procs td.c-gpu { box-shadow: inset 0 0 0 999px rgba(185,140,255,.05); --bc: var(--c-gpu); }
.tman .tm-procs th.on { opacity: 1; box-shadow: inset 0 -3px 0 rgba(0,0,0,.42); }
/* in-cell magnitude bars: value length visible at a glance (mockup pass 1) */
.tman .tm-procs td.num { position: relative; }
.tman .tm-procs td.num::after { content: ''; position: absolute; left: 6px; bottom: 1px; height: 2.5px;
  width: var(--w, 0%); max-width: calc(100% - 12px); background: var(--bc, transparent);
  border-radius: 2px; opacity: .9; }
/* per-process activity dot: what is actually running */
.tman .pdot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 7px;
  background: var(--dot-idle); vertical-align: baseline; flex: none; }
.tman .pdot.act { background: var(--accent); box-shadow: 0 0 5px var(--accent); }
.tman .pdot.hot { background: var(--warn); box-shadow: 0 0 5px var(--warn); }
.tman .tm-legend { color: var(--muted); font-size: 11.5px; display: flex; gap: 12px; align-items: center;
  padding: 2px 6px 4px; }
.tman .tm-legend .pdot { margin-right: 4px; }
.tman .tm-offline { position: fixed; inset: 0; display: flex; align-items: center; justify-content: center;
  background: var(--overlay); backdrop-filter: blur(3px); text-align: center; z-index: 5; }
.tman .tm-offline[hidden] { display: none; }   /* author display:flex would otherwise beat the UA [hidden] rule */
.tman .tm-offline h2 { font-size: 26px; }

.cal-screen .cal-list { overflow: hidden; }

/* right card holds two months; the second is compact so both fit without scrolling */
.cal-screen .cal-col.months { overflow: hidden; }
.cal-screen h2.next-m { margin-top: 9px; }
.cal-screen .cal-col.months .mm span { padding: 2px 0; font-size: 11.5px; }
.cal-screen .cal-col.months .mm-h i { font-size: 9.5px; }
/* both month grids must fit exactly - a display screen cannot scroll to reveal the rest */
.cal-screen .cal-col.months h2 { margin-bottom: 4px; }
.cal-screen h2.next-m { margin-top: 5px; }
.cal-screen .cal-col.months .mm, .cal-screen .cal-col.months .mm-h { gap: 1px; }
.cal-screen .cal-col.months .mm span { padding: 1px 0; }

/* ---- balanced spacing: never let slack pool at the bottom of a card.
   Gaps above, between and below a card's content groups should read as equal. */
.cal-screen .cal-col.months { justify-content: space-evenly; }
.cal-screen .mblock { display: flex; flex-direction: column; }
.cal-screen .mblock h2 { margin-bottom: 5px; }
.cal-screen h2.next-m { margin-top: 0; }
/* the Next Up rows spread down the card instead of stacking at the top */
.cal-screen .cal-list { flex: 1; display: flex; flex-direction: column; justify-content: space-between; }
/* the timeline absorbs the Today card's slack rather than leaving a dead gap below it */
.cal-screen.slim-today .tl { flex: 1; display: flex; flex-direction: column; justify-content: center; }
.cal-screen.slim-today .tl-empty { padding-top: 0; text-align: center; }

/* Equal border spacing on ALL sides: rather than centring a short block and leaving fat
   gaps top and bottom, let the month grids GROW to fill the card. Every edge gap then
   equals the card padding, and the cells get bigger - easier to read from a distance too. */
.cal-screen .cal-col.months { justify-content: flex-start; gap: 10px; }
.cal-screen .mblock { flex: 1; min-height: 0; }
.cal-screen .mblock .cal-mini { flex: 1; display: flex; flex-direction: column; min-height: 0; }
.cal-screen .mblock .mm { flex: 1; grid-auto-rows: 1fr; }
.cal-screen .cal-col.months .mm span { padding: 0; display: flex; align-items: center;
  justify-content: center; }
/* uniform padding so the gap to every edge is identical, not 10 vertical / 12 horizontal */
.cal-screen .cal-col { padding: 11px; }

/* ---- Claude <-> Hermes delegation slider (dashboard rail) */
.wcard.deleg { border-left-color: var(--accent-2); }
.wcard.deleg:hover { border-left-color: var(--accent-2); }
.wcard.deleg .wv { font-size: 1.05rem; margin-bottom: .3rem; }
.wcard.deleg input[type=range] { width: 100%; padding: 0; margin: .1rem 0 .2rem; height: 20px;
  background: transparent; border: 0; cursor: ew-resize; -webkit-appearance: none; appearance: none; }
.wcard.deleg input[type=range]::-webkit-slider-runnable-track { height: 5px; border-radius: 3px;
  background: linear-gradient(90deg, var(--accent-2), var(--accent)); }
.wcard.deleg input[type=range]::-moz-range-track { height: 5px; border-radius: 3px;
  background: linear-gradient(90deg, var(--accent-2), var(--accent)); }
.wcard.deleg input[type=range]::-webkit-slider-thumb { -webkit-appearance: none; appearance: none;
  width: 15px; height: 15px; border-radius: 50%; background: var(--text);
  border: 2px solid var(--panel); margin-top: -5px; box-shadow: 0 1px 4px rgba(0,0,0,.4); }
.wcard.deleg input[type=range]::-moz-range-thumb { width: 15px; height: 15px; border-radius: 50%;
  background: var(--text); border: 2px solid var(--panel); box-shadow: 0 1px 4px rgba(0,0,0,.4); }
.wcard.deleg .dg-ends { display: flex; justify-content: space-between; align-items: baseline;
  color: var(--muted); font-size: .72rem; }
.wcard.deleg .dg-ends b { color: var(--text); font-size: .85rem; font-variant-numeric: tabular-nums; }
.wcard.deleg .ws { margin-top: .3rem; line-height: 1.35; white-space: normal; }

/* Display-only screens must never show a text selection. The kiosk hides the cursor but
   selection was still possible, so one stray drag (or a leftover from when the KVM existed)
   left text highlighted on the monitor permanently - nobody is there to click it away. */
body.kiosk, body.kiosk * { -webkit-user-select: none; user-select: none; }
body.kiosk ::selection { background: transparent; }
body.kiosk { -webkit-tap-highlight-color: transparent; }

/* ---- hub kiosk screen: rebuilt for the LANDSCAPE 1024x600 monitor. It was laid out for
   the old portrait orientation, so the app list ran 643px off the bottom of the screen -
   invisible on a display nobody can scroll. */
.shub { flex-direction: row; padding: 12px; gap: 12px; height: 100vh; min-height: 0; }
.shub .shub-left { display: flex; flex-direction: column; gap: 12px; width: 380px; flex: none; }
.shub .shub-right { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 8px;
  min-height: 0; }
.shub .clock { font-size: 54px; }
.shub .date { font-size: 17px; }
.shub .tiles { grid-template-columns: 1fr 1fr; gap: 8px; }
.shub .tile { padding: 8px 10px; }
.shub .tile .v { font-size: 22px; }
.shub h2 { margin: 0; }
/* app rows: compact, two columns, sized so every registered app fits without scrolling */
.shub .applist { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; align-content: start;
  flex: 1; min-height: 0; }
.shub .app { padding: 6px 9px; gap: 7px; border-radius: 8px; }
.shub .app .n { font-weight: 600; font-size: 13px; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; }
.shub .app .where { margin-left: auto; font-size: 11px; }
.shub .foot { margin-top: auto; font-size: 12px; flex-direction: column; gap: 2px;
  justify-content: flex-start; }
/* uniform padding so all four edge gaps match (ui-formatting rule) */
.tman .tm-tile { padding: 9px; }
.tman .tm-procs { padding: 6px 9px; }
/* trim back: 9px padding pushed the taskman rail 8px past the viewport */
.tman .tm-tile { padding: 7px 8px 7px 8px; }
.tman .tm-procs { padding: 7px 8px; }
/* equal on all four sides, and small enough that the rail still fits 600px */
.tman .tm-tile { padding: 7px; }
.tman .tm-procs { padding: 6px; }
/* Automation panel - fills what was ~300px of dead space under the app list.
   Rule 3 of the display-only note: empty space on a wall display is a bug. */
.shub .autolist { display: flex; flex-direction: column; gap: 6px; }
.shub .auto { display: flex; align-items: center; gap: 8px; padding: 7px;
  background: var(--panel); border: 1px solid var(--line); border-radius: 8px; font-size: 13px; }
.shub .auto .n { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.shub .auto .st { margin-left: auto; text-transform: uppercase; font-size: 11px;
  letter-spacing: .06em; color: var(--muted); }
.shub .auto.good .st { color: var(--ok); }
.shub .auto.bad .st { color: var(--bad); }
.shub .auto .tm { color: var(--muted); font-size: 11px; min-width: 58px; text-align: right; }
.shub .amt { color: var(--muted); font-size: 13px; padding: 7px; }
/* left rail: let the tiles use the height instead of stranding it at the bottom */
.shub .shub-left .tiles { flex: 1; grid-template-rows: 1fr 1fr; align-content: stretch; }
.shub .tile { display: flex; flex-direction: column; justify-content: center; }
/* Stretching the tiles to fill just made them hollow - keep them their natural size and
   put the recovered height into information (taglines, the automation list) instead. */
.shub .shub-left .tiles { flex: none; }
.shub .tile { display: block; }
.shub .app { align-items: center; }
.shub .app .ap { display: flex; flex-direction: column; min-width: 0; }
.shub .app .t { color: var(--muted); font-size: 11px; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
.shub .applist { gap: 7px; }
/* grid/flex items default to min-width:auto, so a long tagline forced the whole row wider
   than its column and pushed the page 590px sideways. */
.shub .app { min-width: 0; }
.shub .app .n { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.shub .auto { min-width: 0; }
/* Automation now lives in the left rail, where the empty band was. Rows wrap to two lines
   because the rail is narrow. */
.shub .shub-left .autolist { gap: 5px; }
.shub .shub-left .auto { flex-wrap: wrap; font-size: 12px; }
.shub .shub-left .auto .n { flex: 1 1 100%; }
.shub .shub-left .auto .st { margin-left: 0; }
.shub .shub-left .auto .tm { margin-left: auto; }


/* ------------------------------------------------------------------ voice HUD settings */
.vstat { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: .5rem 1.25rem;
  align-items: center; margin-bottom: 1rem; }
.vstat .vs-cell { display: flex; align-items: center; gap: .55rem; min-width: 0; }
.vstat .vs-cell + .vs-cell { border-left: 1px solid var(--line); padding-left: 1.25rem; }
.vstat b { display: block; font-size: .95rem; line-height: 1.25; overflow-wrap: anywhere; }
.vstat small { display: block; font-size: .74rem; letter-spacing: .02em; text-transform: uppercase; }
.vstat .rd { width: 10px; height: 10px; border-radius: 50%; background: var(--dot-idle); flex: none; }

.vgrid { align-items: start; }
.vgrid .panel { display: flex; flex-direction: column; }
.vgrid .panel > p.muted { margin-top: 0; }
.vgrid h3 { margin: 1.1rem 0 .4rem; }

.vrow { display: grid; grid-template-columns: 1fr minmax(120px, 200px); align-items: center;
  gap: .75rem; padding: .5rem 0; border-top: 1px solid var(--line); }
.vrow[hidden] { display: none; }          /* author display beats the UA's [hidden] rule */
.vrow label { margin: 0; color: var(--text); font-size: .9rem; }
.vrow > input, .vrow > select { width: 100%; margin: 0; }
.vrow > input[type=checkbox] { width: 18px; height: 18px; justify-self: end; accent-color: var(--accent); }
.vrow > input[type=range] { padding: 0; }

.vval { color: var(--accent-2); font-variant-numeric: tabular-nums; }
.vscale { display: flex; justify-content: space-between; color: var(--muted); font-size: .74rem; margin-top: .2rem; }
.vhint { font-size: .8rem; margin: .4rem 0 0; }
.vtest { margin-top: .25rem; flex-wrap: nowrap; }
.vtest input { flex: 1; min-width: 0; margin: 0; }
.vmods { display: flex; gap: 1rem; margin: .1rem 0 .2rem; }
.vchk { display: inline-flex; align-items: center; gap: .35rem; margin: 0; color: var(--text); font-size: .9rem; }
.vchk input { accent-color: var(--accent); width: 16px; height: 16px; }
.rst { background: var(--chip); color: var(--muted); border-radius: 999px; padding: .05rem .45rem;
  font-size: .7rem; text-transform: uppercase; letter-spacing: .04em; }

input[type=range] { -webkit-appearance: none; appearance: none; background: transparent; height: 20px; }
input[type=range]::-webkit-slider-runnable-track { height: 5px; border-radius: 3px; background: var(--chip); }
input[type=range]::-moz-range-track { height: 5px; border-radius: 3px; background: var(--chip); }
input[type=range]::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 15px; height: 15px;
  border-radius: 50%; background: var(--accent); margin-top: -5px; }
input[type=range]::-moz-range-thumb { width: 15px; height: 15px; border-radius: 50%; background: var(--accent);
  border: none; }

.vbar { position: sticky; bottom: 0; z-index: 5; display: flex; align-items: center; gap: .6rem;
  margin-top: 1rem; padding: .7rem 1rem; background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius); }
.vbar.on { border-color: var(--accent); }
.vbar .right { margin-left: auto; }
.warn-text { color: var(--warn); }

@media (max-width: 900px) {
  .vstat .vs-cell + .vs-cell { border-left: 0; padding-left: 0; }
  .vrow { grid-template-columns: 1fr; align-items: start; }
  .vrow > input[type=checkbox] { justify-self: start; }
}

/* ---- Daily brief (dashboard widget + /news) --------------------------------------- */
/* Prefix nb- to stay clear of the shared sheet; .news/.nb* were unused before this. */
.wcard.nb-card { border-left-color: var(--accent-2); }
.wcard.nb-card:hover { border-left-color: var(--accent-2); }
.nb-heads { list-style: none; margin: .45rem 0 0; padding: 0; display: flex;
            flex-direction: column; gap: .28rem; }
/* No line-clamp: clamping registers as clipped content and fails the UI audit. The
   dashboard JS truncates the string instead, so this can wrap freely. */
.nb-heads li { color: var(--muted); font-size: .74rem; line-height: 1.3;
               padding-left: .55rem; position: relative; }
.nb-heads li::before { content: ""; position: absolute; left: 0; top: .42em;
                       width: 3px; height: 3px; border-radius: 50%; background: var(--dot-idle); }

/* Five tiles must fit ONE row at 1024 px. The default .gauges track is minmax(185px),
   which wraps them and leaves a dead gap beside the orphan. The content column is only
   ~790 px once the sidebar is subtracted, so the track has to be 132 px, not 150. */
.nb-kpis { grid-template-columns: repeat(5, minmax(0, 1fr)); }
.nb-kpis .gauge { padding: 11px; }
.nb-kpis .gv2 { font-size: 1.05rem; }
.nb-kpis .gs { overflow-wrap: anywhere; }
@media (max-width: 900px) { .nb-kpis { grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); } }

.nb-date { background: var(--field); color: var(--text); border: 1px solid var(--line);
           border-radius: 8px; padding: .3rem .5rem; font: inherit; font-size: .82rem; }

.nb-layout { display: grid; grid-template-columns: 220px minmax(0, 1fr); gap: .8rem;
             align-items: start; }
@media (max-width: 820px) { .nb-layout { grid-template-columns: 1fr; } }

.nb-toc { padding: 14px; position: sticky; top: .8rem; }
.nb-toc .section-head { margin-bottom: .5rem; }
.nb-toc ul { list-style: none; margin: 0; padding: 0; display: flex;
             flex-direction: column; gap: .1rem; }
.nb-toc li { display: flex; align-items: baseline; gap: .5rem; }
.nb-toc a { flex: 1; min-width: 0; overflow-wrap: anywhere; color: var(--text); font-size: .84rem; padding: .26rem .4rem;
            border-radius: 6px; text-decoration: none; }
.nb-toc a:hover { background: var(--panel-2); text-decoration: none; }
.nb-toc .nb-wc { color: var(--muted); font-size: .72rem; font-variant-numeric: tabular-nums; }

/* Equal padding on all four sides - Cody's rule; do NOT split into "18px 22px". */
/* overflow-wrap is load-bearing: Google News citation URLs are ~250 unbroken characters
   and pushed the page into 1555 px of horizontal scroll before this was added. */
.nb-body { padding: 22px; line-height: 1.65; overflow-wrap: anywhere; min-width: 0; }
.nb-body a { overflow-wrap: anywhere; }
.nb-body .nb-sec + .nb-sec { margin-top: 1.6rem; padding-top: 1.2rem;
                             border-top: 1px solid var(--line); }
.nb-body h2 { font-size: 1.08rem; margin: 0 0 .5rem; }
.nb-body h3 { font-size: .94rem; margin: 1rem 0 .35rem; color: var(--muted); }
.nb-body p { margin: .55rem 0; }
.nb-body a { color: var(--accent-2); overflow-wrap: anywhere; }
.nb-body hr { border: none; border-top: 1px solid var(--line); margin: 1.2rem 0; }
.nb-body ul { margin: .5rem 0; padding-left: 1.2rem; }


/* --- MTG rules oracle (/rules) --------------------------------------------------- */
/* NOTE: .panel supplies the padding. Overriding one axis here is what failed the
   pc-audit even-padding check on the voice page -- do not repeat it. */
.mr-stat { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
           gap: .5rem 1.25rem; align-items: center; }
.mr-stat .mr-cell { display: flex; align-items: center; gap: .55rem; min-width: 0; }
.mr-stat .mr-cell + .mr-cell { border-left: 1px solid var(--line); padding-left: 1.25rem; }
.mr-stat b { display: block; font-size: .95rem; line-height: 1.25; overflow-wrap: anywhere; }
.mr-stat small { display: block; font-size: .74rem; letter-spacing: .02em; text-transform: uppercase; }
.mr-stat .rd { width: 10px; height: 10px; border-radius: 50%; background: var(--dot-idle); flex: none; }

.mr-askrow { display: flex; flex-direction: column; gap: .6rem; }
.mr-askrow textarea { width: 100%; box-sizing: border-box; resize: vertical;
  background: var(--field); color: var(--text); border: 1px solid var(--line);
  border-radius: 8px; padding: .6rem .7rem; font: inherit; font-size: 16px; }
.mr-btns { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; }
.mr-tts { display: inline-flex; align-items: center; gap: .35rem; color: var(--muted); font-size: .85rem; }
.mr-hint { font-size: .82rem; margin: .55rem 0 0; }
#mr-mic.rec { background: var(--bad); color: #fff; }

.mr-a-head { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; flex-wrap: wrap; }
.mr-a-head h2 { margin: 0; }
.mr-answer p { line-height: 1.55; overflow-wrap: anywhere; }
.mr-err { color: var(--bad); }
.mr-cites { display: flex; align-items: center; gap: .35rem; flex-wrap: wrap; margin-top: .5rem; }
.mr-cites .chip { font-variant-numeric: tabular-nums; }
.chip.warn { background: var(--warn); color: #1a1306; }
.mr-src { margin-top: .9rem; border-top: 1px solid var(--line); padding-top: .7rem; }
.mr-src summary { cursor: pointer; color: var(--muted); font-size: .86rem; }
.mr-src h3 { font-size: .85rem; text-transform: uppercase; letter-spacing: .03em;
             color: var(--muted); margin: .8rem 0 .35rem; }
.mr-src ul { margin: 0; padding-left: 1.1rem; }
.mr-src li { margin: .3rem 0; font-size: .88rem; line-height: 1.45; }

.mr-busy { display: flex; align-items: center; gap: .6rem; color: var(--muted); }
.spin { width: 14px; height: 14px; border-radius: 50%; flex: none;
        border: 2px solid var(--line); border-top-color: var(--accent);
        animation: mr-spin .8s linear infinite; }
@keyframes mr-spin { to { transform: rotate(360deg); } }

@media (max-width: 640px) {
  .mr-stat .mr-cell + .mr-cell { border-left: 0; padding-left: 0; }
  .mr-btns .btn { flex: 1 1 auto; }
}

/* away-from-home link strip on /rules (LAN only) */
.mr-remote { display: flex; align-items: center; gap: 1rem; justify-content: space-between; }
.mr-remote p { margin: .25rem 0 .5rem; font-size: .82rem; }
.mr-remote code { font-size: .82rem; word-break: break-all; color: var(--accent-2); }
.mr-remote .btn { flex: none; }
@media (max-width: 640px) { .mr-remote { flex-direction: column; align-items: stretch; } }

/* screen_hub: the automation list grows with the n8n workflow count, and at 8 workflows it
   was 638px tall inside a 576px rail - pushing the whole kiosk page 426px off a display
   nobody can scroll. Bound it to the leftover space; the JS trims rows to fit and says how
   many it dropped, because silently hiding rows on a wall display is its own bug. */
.shub .shub-left { min-height: 0; }
.shub .shub-left .autolist { flex: 1 1 auto; min-height: 0; overflow: hidden; }
.shub .automore { color: var(--muted); font-size: 11px; padding: 2px 7px; }
/* Two visible rows out of eight was thin. The wrapped layout gave each row ~78px, most of
   it padding, so tighten it and let 4-5 fit in the same band. */
.shub .shub-left .auto { padding: 4px 7px; line-height: 1.25; row-gap: 1px; }
.shub .shub-left .auto .n { margin-bottom: 1px; }

/* ---- main-pc remote desktop (/pc-desktop)
   The stage is a fixed window onto a much larger framebuffer: main-pc's two monitors form a
   4520x1920 bounding box, so "show me one monitor" is a crop, not a resize. .pcd-screen is
   POSITIONED, never transformed - noVNC maps clicks through the canvas's bounding rect and
   its own display.scale, and a CSS transform it does not know about would silently offset
   every click. See the layout() comment in pc_desktop.html. */
.pcd-badges { display: flex; gap: .4rem; align-items: center; }
.pill { border-radius: 999px; padding: .18rem .7rem; font-size: .78rem; font-weight: 600;
  background: var(--chip); color: var(--muted); white-space: nowrap; }
.pill.ok { background: var(--accent); color: #0c1a14; }
.pill.bad { background: var(--chip); color: var(--bad); box-shadow: inset 0 0 0 1px var(--bad); }
.row { display: flex; flex-wrap: wrap; gap: .55rem; align-items: center; }

.pcd-offline { max-width: 46rem; }
.pcd-offline h2 { margin: 0 0 .35rem; font-size: 1.05rem; }
.pcd-offline p { margin: 0 0 .9rem; }

.pcd-bar { display: flex; flex-wrap: wrap; gap: .6rem; align-items: center;
  margin: .2rem 0 .6rem; }
.pcd-views { display: flex; flex-wrap: wrap; gap: .45rem; }
.pcd-views button { border-radius: 999px; padding: .38rem .9rem; font-size: .86rem; }
.pcd-views button.on { background: var(--accent); color: #0c1a14; border-color: transparent;
  font-weight: 600; }
.pcd-tools { display: flex; flex-wrap: wrap; gap: .45rem; align-items: center; margin-left: auto; }
.pcd-sel { display: flex; align-items: center; gap: .4rem; color: var(--muted); font-size: .82rem; }
.pcd-sel select { width: auto; }

.pcd-stage { position: relative; overflow: hidden; background: #05070a;
  border: 1px solid var(--line); border-radius: var(--radius);
  height: calc(100vh - 232px); min-height: 380px; }
.pcd-stage:fullscreen { height: 100vh; border: 0; border-radius: 0; }
.pcd-screen { position: absolute; left: 0; top: 0; }
.pcd-screen canvas { display: block; }
.pcd-overlay { position: absolute; inset: 0; display: flex; align-items: center;
  justify-content: center; background: var(--overlay); color: var(--muted); font-size: .95rem; }
.pcd-overlay[hidden] { display: none; }
.pcd-foot { margin-top: .5rem; }

/* TOTP enrolment: the secret has to be readable character by character, so a mono face and
   room to breathe rather than a tidy truncation. */
.pcd-secret { background: var(--field); border: 1px solid var(--line); border-radius: 8px;
  padding: .5rem .7rem; font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: .92rem; letter-spacing: .04em; word-break: break-all; }
.pcd-uri { font-size: .78rem; letter-spacing: 0; flex: 1 1 22rem; }

/* ---- brief topics editor (/news/topics) */
/* Legend on its own full-width row rather than beside the numbers: at 1024px it wrapped to
   six lines in a half-width column and left the stats column standing in dead space. */
.nt-summary { display: flex; flex-direction: column; gap: .6rem; padding: 1rem; }
.nt-srow { display: flex; gap: 1rem; align-items: stretch; flex-wrap: wrap; }
/* Top-aligned so the numbers line up with the SHARE heading beside them; centring them
   pooled the card's slack above and below the column instead. */
.nt-stat { display: flex; flex-direction: column; justify-content: flex-start; min-width: 84px; }
.nt-stat-wide { flex: 1; min-width: 260px; }
.nt-sk { color: var(--muted); font-size: .78rem; text-transform: uppercase; letter-spacing: .05em; }
.nt-sv { font-size: 1.5rem; font-weight: 600; line-height: 1.2; }
/* The share bar IS the explanation of what weight does, so it fills the row rather than
   sitting as a thin rule under it. */
.nt-mix { display: flex; gap: 2px; margin-top: .35rem; height: 14px; border-radius: 7px; overflow: hidden; }
.nt-seg { min-width: 4px; background: var(--panel-2); }
.nt-legend { display: flex; flex-wrap: wrap; gap: .25rem .9rem; margin-top: .45rem; font-size: .78rem;
  color: var(--muted); }
.nt-key { display: inline-flex; align-items: center; gap: .3rem; white-space: nowrap; }
.nt-key b { color: var(--text); font-weight: 600; }
.nt-swatch { width: 9px; height: 9px; border-radius: 2px; flex: none; }
.nt-c0 { background: var(--accent); }
.nt-c1 { background: var(--accent-2); }
.nt-c2 { background: #b58cff; }
.nt-c3 { background: var(--warn); }

.nt-list { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fill, minmax(340px, 1fr)); }
.nt-card { display: flex; flex-direction: column; gap: .5rem; padding: 1rem; }
.nt-card.nt-off { opacity: .55; }
.nt-head { display: flex; flex-direction: column; gap: .4rem; }
.nt-head .nt-name { width: 100%; font-weight: 600; }
.nt-ctl { display: flex; gap: .4rem; align-items: center; }
.nt-ctl button { padding: .3rem .5rem; font-size: .8rem; }
.nt-ctl .nt-del { margin-left: auto; }
.nt-share { flex: none; min-width: 42px; text-align: center; }
.nt-grid { display: flex; gap: .75rem; align-items: end; flex-wrap: wrap; }
.nt-grid > div { flex: 1; min-width: 150px; }
.nt-wrap .nt-wv { color: var(--text); font-weight: 600; }
.nt-card label { margin: .35rem 0 .2rem; }
.nt-card textarea.nt-detail { min-height: 0; font-family: inherit; font-size: .9rem; }
.nt-fhead { display: flex; align-items: baseline; gap: .5rem; }
.nt-fhead label { margin: .35rem 0 .2rem; }
.nt-fhead button { margin-left: auto; padding: .25rem .5rem; font-size: .78rem; }
.nt-feeds { display: flex; flex-direction: column; gap: .35rem; }
.nt-feed { display: flex; gap: .35rem; }
.nt-feed .nt-fsrc { flex: 0 1 34%; min-width: 0; }
.nt-feed .nt-furl { flex: 1; min-width: 0; }
.nt-feed input { padding: .35rem .5rem; font-size: .85rem; }
.nt-feed .nt-fdel { flex: none; padding: .25rem .5rem; font-size: .78rem; }
.nt-nofeed { margin: 0; font-size: .82rem; }
/* Pushed to the bottom so every card ends on the same element even when the notes above
   are different lengths - otherwise the grid rows look ragged. */
.nt-extras { margin-top: auto; padding-top: .5rem; font-size: .78rem; }
.nt-extras:empty { display: none; }

@media (max-width: 700px) {
  .nt-list { grid-template-columns: 1fr; }
  .nt-feed { flex-wrap: wrap; }
  .nt-feed .nt-fsrc { flex: 1 1 100%; }
}

/* Kiosk-safe fallback when an external Pi-screen app is offline/erroring. */
.screen-wcard { width:100%; text-align:left; cursor:pointer; font:inherit; }
.screen-wcard:hover { border-color:var(--line-hover); }
.screen-fallback { min-height:100vh; display:grid; place-items:center; padding:2rem; background:radial-gradient(circle at 25% 10%, rgba(90,169,255,.18), transparent 35%), var(--bg); color:var(--text); }
.screen-fallback > div { max-width:760px; padding:2rem; border:1px solid var(--line); border-radius:24px; background:var(--panel); box-shadow:var(--shadow); text-align:center; }
.screen-fallback h1 { font-size:clamp(2rem,7vw,4.5rem); margin:.25rem 0 1rem; }
.screen-fallback p { font-size:clamp(1rem,2.2vw,1.35rem); line-height:1.45; }
.sf-kicker { color:var(--warn); text-transform:uppercase; letter-spacing:.12em; font-weight:800; font-size:.85rem; }

.project-features { display:grid; grid-template-columns:repeat(auto-fit,minmax(190px,1fr)); gap:.55rem; }
.feature-link { display:flex; flex-direction:column; gap:.15rem; padding:.65rem .75rem; border:1px solid var(--line); border-radius:10px; background:var(--panel-2); color:var(--text); }
.feature-link:hover { text-decoration:none; border-color:var(--line-hover); }
.feature-link span { font-size:.82rem; }
.project-card-features { display:flex; gap:.35rem; flex-wrap:wrap; }
.project-card-features a.chip:hover { text-decoration:none; color:var(--text); }
@media (max-width:820px){ .project-features{grid-template-columns:1fr} }
