/* Sync look: the shared design of every Sync platform (Sync HA, Sync NOC, Sync Design Desk shell).
   Sync Design black and white in the iOS 26 Liquid Glass manner: a drawing-paper ground (blueprint grid and a faint
   floor plan), clear glass that floats over it (a bright top edge, soft depth, the drawing softening through it),
   a floating glass sidebar for navigation, an action capsule at the top right, capsules everywhere, the primary
   action in ink (black in light, white in dark), colour only for real state.
   Canonical copy: claude-sync/docs/sync-look/sync-look.css. Each app carries a copy; change it here, copy it out,
   then screenshot every app in light and dark. Dark follows the device unless <html data-theme="light|dark">. */
:root {
  --bg: #dcdce1; --wash: #dcdce1; --grid-minor: rgba(0, 0, 0, .045); --grid-major: rgba(0, 0, 0, .09); --plan: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 980 680%22%3E%3Cg fill=%22none%22 stroke=%22rgba(0,0,0,0.34)%22 stroke-width=%227%22 stroke-linecap=%22square%22%3E%3Cpath d=%22M20 20H960V660H20Z%22/%3E%3Cpath d=%22M360 20V280M360 370V660M360 280H530M620 280H960M680 20V190M680 190H960M530 480H960M760 480V660M20 420H160M250 420H360%22/%3E%3C/g%3E%3Cg fill=%22none%22 stroke=%22rgba(0,0,0,0.2)%22 stroke-width=%222%22%3E%3Cpath d=%22M530 280A90 90 0 0 1 620 370M160 420A90 90 0 0 0 250 330M680 190A80 80 0 0 0 760 270%22/%3E%3Cpath d=%22M60 60H320M60 70H320M720 230H940M800 520V640M810 520V640%22/%3E%3Cpath d=%22M420 80h220v150H420zM400 520h110v110H400z%22 stroke-dasharray=%226 6%22/%3E%3C/g%3E%3Cg fill=%22none%22 stroke=%22rgba(0,0,0,0.2)%22 stroke-width=%221.5%22 stroke-dasharray=%223 7%22%3E%3Cpath d=%22M480 140L850 600M850 600L900 100M160 200L480 140M160 200L160 600M160 600L600 620%22/%3E%3C/g%3E%3Cg fill=%22rgba(0,0,0,0.55)%22%3E%3Ccircle cx=%22480%22 cy=%22140%22 r=%2210%22/%3E%3Ccircle cx=%22850%22 cy=%22600%22 r=%2210%22/%3E%3Ccircle cx=%22900%22 cy=%22100%22 r=%2210%22/%3E%3Ccircle cx=%22160%22 cy=%22200%22 r=%2210%22/%3E%3Ccircle cx=%22160%22 cy=%22600%22 r=%2210%22/%3E%3Ccircle cx=%22600%22 cy=%22620%22 r=%2210%22/%3E%3C/g%3E%3Cg fill=%22rgba(0,0,0,0.08)%22%3E%3Cpath d=%22M850 600l64-36v72z%22/%3E%3Cpath d=%22M480 140l80-28v56z%22/%3E%3C/g%3E%3Cg font-family=%22system-ui,sans-serif%22 font-size=%2214%22 font-weight=%22500%22 letter-spacing=%221%22 fill=%22rgba(0,0,0,0.34)%22%3E%3Ctext x=%22770%22 y=%2270%22%3EMASTER BEDROOM%3C/text%3E%3Ctext x=%22790%22 y=%22400%22%3ELIVING%3C/text%3E%3Ctext x=%22840%22 y=%22640%22%3EKITCHEN%3C/text%3E%3Ctext x=%22440%22 y=%22460%22%3EDINING%3C/text%3E%3Ctext x=%2260%22 y=%22480%22%3EGARAGE%3C/text%3E%3C/g%3E%3C/svg%3E");
  --ink: #000000; --ink2: #3c3c43; --label2: rgba(60, 60, 67, .7); --muted: rgba(60, 60, 67, .62); --line: rgba(0, 0, 0, .09); --inset: rgba(0, 0, 0, .055); --track: rgba(0, 0, 0, .08);
  --hue: #000000; --hue-soft: rgba(0, 0, 0, .06); --on-hue: #ffffff; --lens: rgba(0, 0, 0, .07); --sel: #ffffff; --sel-ring: 0 1px 2px rgba(0, 0, 0, .10), 0 4px 12px -4px rgba(0, 0, 0, .18);
  --glass: rgba(255, 255, 255, .72); --glass-strong: rgba(255, 255, 255, .96); --sheet: #f5f5f7; --glass-edge: transparent;
  --glass-spec: inset 0 1px 0 #ffffff, inset 0 0 0 1px rgba(255, 255, 255, .55), 0 0 0 1px rgba(0, 0, 0, .07);
  --shadow: 0 1px 2px rgba(0, 0, 0, .08), 0 10px 24px -10px rgba(0, 0, 0, .22), 0 36px 72px -32px rgba(0, 0, 0, .38);
  --up: #1f7a3a; --up-bg: rgba(52, 199, 89, .14); --warn: #8f5d00; --warn-bg: rgba(255, 159, 10, .14); --down: #b3261e; --down-bg: rgba(255, 59, 48, .10); --none: rgba(60, 60, 67, .42);
  --font: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI Variable Text", "Segoe UI", Inter, system-ui, sans-serif;
  --r: 24px; --r-in: 13px; --ease: cubic-bezier(.2, .7, .2, 1); --side: 288px; color-scheme: light;
}
:root[data-theme=dark] {
  --bg: #0b0b0c; --wash: #0b0b0c; --grid-minor: rgba(255, 255, 255, .025); --grid-major: rgba(255, 255, 255, .05); --plan: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 980 680%22%3E%3Cg fill=%22none%22 stroke=%22rgba(255,255,255,0.2)%22 stroke-width=%227%22 stroke-linecap=%22square%22%3E%3Cpath d=%22M20 20H960V660H20Z%22/%3E%3Cpath d=%22M360 20V280M360 370V660M360 280H530M620 280H960M680 20V190M680 190H960M530 480H960M760 480V660M20 420H160M250 420H360%22/%3E%3C/g%3E%3Cg fill=%22none%22 stroke=%22rgba(255,255,255,0.11)%22 stroke-width=%222%22%3E%3Cpath d=%22M530 280A90 90 0 0 1 620 370M160 420A90 90 0 0 0 250 330M680 190A80 80 0 0 0 760 270%22/%3E%3Cpath d=%22M60 60H320M60 70H320M720 230H940M800 520V640M810 520V640%22/%3E%3Cpath d=%22M420 80h220v150H420zM400 520h110v110H400z%22 stroke-dasharray=%226 6%22/%3E%3C/g%3E%3Cg fill=%22none%22 stroke=%22rgba(255,255,255,0.11)%22 stroke-width=%221.5%22 stroke-dasharray=%223 7%22%3E%3Cpath d=%22M480 140L850 600M850 600L900 100M160 200L480 140M160 200L160 600M160 600L600 620%22/%3E%3C/g%3E%3Cg fill=%22rgba(255,255,255,0.42)%22%3E%3Ccircle cx=%22480%22 cy=%22140%22 r=%2210%22/%3E%3Ccircle cx=%22850%22 cy=%22600%22 r=%2210%22/%3E%3Ccircle cx=%22900%22 cy=%22100%22 r=%2210%22/%3E%3Ccircle cx=%22160%22 cy=%22200%22 r=%2210%22/%3E%3Ccircle cx=%22160%22 cy=%22600%22 r=%2210%22/%3E%3Ccircle cx=%22600%22 cy=%22620%22 r=%2210%22/%3E%3C/g%3E%3Cg fill=%22rgba(255,255,255,0.06)%22%3E%3Cpath d=%22M850 600l64-36v72z%22/%3E%3Cpath d=%22M480 140l80-28v56z%22/%3E%3C/g%3E%3Cg font-family=%22system-ui,sans-serif%22 font-size=%2214%22 font-weight=%22500%22 letter-spacing=%221%22 fill=%22rgba(255,255,255,0.18)%22%3E%3Ctext x=%22770%22 y=%2270%22%3EMASTER BEDROOM%3C/text%3E%3Ctext x=%22790%22 y=%22400%22%3ELIVING%3C/text%3E%3Ctext x=%22840%22 y=%22640%22%3EKITCHEN%3C/text%3E%3Ctext x=%22440%22 y=%22460%22%3EDINING%3C/text%3E%3Ctext x=%2260%22 y=%22480%22%3EGARAGE%3C/text%3E%3C/g%3E%3C/svg%3E");
  --ink: #ffffff; --ink2: rgba(235, 235, 245, .86); --label2: rgba(235, 235, 245, .64); --muted: rgba(235, 235, 245, .6); --line: rgba(255, 255, 255, .1); --inset: rgba(255, 255, 255, .10); --track: rgba(255, 255, 255, .1);
  --hue: #ffffff; --hue-soft: rgba(255, 255, 255, .12); --on-hue: #000000; --lens: rgba(255, 255, 255, .14); --sel: rgba(255, 255, 255, .14); --sel-ring: inset 0 1px 0 rgba(255, 255, 255, .22);
  --glass: rgba(30, 30, 32, .42); --glass-strong: rgba(38, 38, 40, .92); --glass-edge: transparent; --sheet: #131314;
  --glass-spec: inset 0 1px 0 rgba(255, 255, 255, .30), inset 1px 0 0 rgba(255, 255, 255, .10), inset 0 0 0 1px rgba(255, 255, 255, .08);
  --shadow: 0 24px 60px -20px rgba(0, 0, 0, .85);
  --up: #30d158; --up-bg: rgba(48, 209, 88, .16); --warn: #ffd60a; --warn-bg: rgba(255, 214, 10, .14); --down: #ff6961; --down-bg: rgba(255, 69, 58, .16); --none: rgba(235, 235, 245, .3);
  color-scheme: dark;
}
@media (prefers-color-scheme: dark) { :root:not([data-theme=light]) {
  --bg: #0b0b0c; --wash: #0b0b0c; --grid-minor: rgba(255, 255, 255, .025); --grid-major: rgba(255, 255, 255, .05); --plan: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 980 680%22%3E%3Cg fill=%22none%22 stroke=%22rgba(255,255,255,0.2)%22 stroke-width=%227%22 stroke-linecap=%22square%22%3E%3Cpath d=%22M20 20H960V660H20Z%22/%3E%3Cpath d=%22M360 20V280M360 370V660M360 280H530M620 280H960M680 20V190M680 190H960M530 480H960M760 480V660M20 420H160M250 420H360%22/%3E%3C/g%3E%3Cg fill=%22none%22 stroke=%22rgba(255,255,255,0.11)%22 stroke-width=%222%22%3E%3Cpath d=%22M530 280A90 90 0 0 1 620 370M160 420A90 90 0 0 0 250 330M680 190A80 80 0 0 0 760 270%22/%3E%3Cpath d=%22M60 60H320M60 70H320M720 230H940M800 520V640M810 520V640%22/%3E%3Cpath d=%22M420 80h220v150H420zM400 520h110v110H400z%22 stroke-dasharray=%226 6%22/%3E%3C/g%3E%3Cg fill=%22none%22 stroke=%22rgba(255,255,255,0.11)%22 stroke-width=%221.5%22 stroke-dasharray=%223 7%22%3E%3Cpath d=%22M480 140L850 600M850 600L900 100M160 200L480 140M160 200L160 600M160 600L600 620%22/%3E%3C/g%3E%3Cg fill=%22rgba(255,255,255,0.42)%22%3E%3Ccircle cx=%22480%22 cy=%22140%22 r=%2210%22/%3E%3Ccircle cx=%22850%22 cy=%22600%22 r=%2210%22/%3E%3Ccircle cx=%22900%22 cy=%22100%22 r=%2210%22/%3E%3Ccircle cx=%22160%22 cy=%22200%22 r=%2210%22/%3E%3Ccircle cx=%22160%22 cy=%22600%22 r=%2210%22/%3E%3Ccircle cx=%22600%22 cy=%22620%22 r=%2210%22/%3E%3C/g%3E%3Cg fill=%22rgba(255,255,255,0.06)%22%3E%3Cpath d=%22M850 600l64-36v72z%22/%3E%3Cpath d=%22M480 140l80-28v56z%22/%3E%3C/g%3E%3Cg font-family=%22system-ui,sans-serif%22 font-size=%2214%22 font-weight=%22500%22 letter-spacing=%221%22 fill=%22rgba(255,255,255,0.18)%22%3E%3Ctext x=%22770%22 y=%2270%22%3EMASTER BEDROOM%3C/text%3E%3Ctext x=%22790%22 y=%22400%22%3ELIVING%3C/text%3E%3Ctext x=%22840%22 y=%22640%22%3EKITCHEN%3C/text%3E%3Ctext x=%22440%22 y=%22460%22%3EDINING%3C/text%3E%3Ctext x=%2260%22 y=%22480%22%3EGARAGE%3C/text%3E%3C/g%3E%3C/svg%3E");
  --ink: #ffffff; --ink2: rgba(235, 235, 245, .86); --label2: rgba(235, 235, 245, .64); --muted: rgba(235, 235, 245, .6); --line: rgba(255, 255, 255, .1); --inset: rgba(255, 255, 255, .10); --track: rgba(255, 255, 255, .1);
  --hue: #ffffff; --hue-soft: rgba(255, 255, 255, .12); --on-hue: #000000; --lens: rgba(255, 255, 255, .14); --sel: rgba(255, 255, 255, .14); --sel-ring: inset 0 1px 0 rgba(255, 255, 255, .22);
  --glass: rgba(30, 30, 32, .42); --glass-strong: rgba(38, 38, 40, .92); --glass-edge: transparent; --sheet: #131314;
  --glass-spec: inset 0 1px 0 rgba(255, 255, 255, .30), inset 1px 0 0 rgba(255, 255, 255, .10), inset 0 0 0 1px rgba(255, 255, 255, .08);
  --shadow: 0 24px 60px -20px rgba(0, 0, 0, .85);
  --up: #30d158; --up-bg: rgba(48, 209, 88, .16); --warn: #ffd60a; --warn-bg: rgba(255, 214, 10, .14); --down: #ff6961; --down-bg: rgba(255, 69, 58, .16); --none: rgba(235, 235, 245, .3);
  color-scheme: dark;
} }
* { box-sizing: border-box }
html, body { margin: 0; min-height: 100% }
body { font: 15px/1.47 var(--font); color: var(--ink); background-color: var(--bg); -webkit-font-smoothing: antialiased; letter-spacing: -.005em }
/* the drawing-paper grid is its own fixed layer (a fixed page background would be repainted on every scroll frame) */
body::after { content: ""; position: fixed; inset: 0; z-index: -2; pointer-events: none; background-image: linear-gradient(var(--grid-major) 1px, transparent 1px), linear-gradient(90deg, var(--grid-major) 1px, transparent 1px), linear-gradient(var(--grid-minor) 1px, transparent 1px), linear-gradient(90deg, var(--grid-minor) 1px, transparent 1px); background-size: 120px 120px, 120px 120px, 24px 24px, 24px 24px; contain: strict }
body::before { content: ""; position: fixed; right: 0; bottom: 0; width: min(1000px, 72vw); height: min(700px, 72vh); z-index: -1; pointer-events: none; background: var(--plan) right bottom / contain no-repeat; contain: strict }
a { color: inherit; text-decoration: none } a:hover { text-decoration: underline; text-underline-offset: 3px }
button, input, select, textarea { font: inherit; color: inherit }
:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; border-radius: 8px }
.num { font-variant-numeric: tabular-nums }
.muted { color: var(--muted) } .t2 { color: var(--ink2) }
.glass { background: var(--glass); border: 0; border-radius: var(--r); box-shadow: var(--glass-spec), var(--shadow); -webkit-backdrop-filter: blur(22px) saturate(160%); backdrop-filter: blur(22px) saturate(160%) }
@media (prefers-reduced-transparency: reduce) { .glass { background: var(--glass-strong); -webkit-backdrop-filter: none; backdrop-filter: none } }

/* shell: a floating glass bar on top, the page below */
.bar { position: sticky; top: 10px; z-index: 20; margin: 10px 14px 0; display: flex; align-items: center; gap: 14px; height: 56px; padding: 0 10px 0 14px }
.brand { display: flex; align-items: center; gap: 10px; font-weight: 650; font-size: 16px; color: var(--ink) } .brand img { width: 30px; height: 30px; border-radius: 8px } .brand:hover { text-decoration: none }
.tabs { display: flex; gap: 2px; padding: 3px; border-radius: 999px; background: var(--inset); margin-left: 8px }
.tabs a { padding: 6px 14px; border-radius: 999px; color: var(--ink2); font-size: 14px; font-weight: 500; white-space: nowrap } .tabs a:hover { text-decoration: none; color: var(--ink) }
.tabs a[aria-current] { background: var(--glass-strong); color: var(--ink); box-shadow: 0 1px 2px rgba(0, 0, 0, .08), 0 2px 8px rgba(0, 0, 0, .05) }
.tabs .n { margin-left: 6px; font-size: 12px; color: var(--down); font-weight: 600 }
.bar .end { margin-left: auto; display: flex; align-items: center; gap: 6px }
.fresh { font-size: 12px; color: var(--muted); display: flex; align-items: center; gap: 6px; margin-right: 6px } .fresh i { width: 7px; height: 7px; border-radius: 50%; background: var(--up) }
.icon { width: 38px; height: 38px; border-radius: 50%; border: 0; background: none; display: grid; place-items: center; cursor: pointer; color: var(--ink2) } .icon:hover { background: var(--inset) }
.icon svg { width: 19px; height: 19px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round }
.who { display: flex; align-items: center; gap: 8px; border: 0; background: none; cursor: pointer; padding: 4px 10px 4px 4px; border-radius: 999px; font-size: 14px } .who:hover { background: var(--inset) }
.who b { width: 30px; height: 30px; border-radius: 50%; background: var(--hue-soft); color: var(--hue); display: grid; place-items: center; font-size: 12px }
.menu { position: absolute; right: 10px; top: 60px; min-width: 210px; padding: 6px; border-radius: 13px; background: var(--glass-strong) }
.menu a, .menu button { display: block; width: 100%; text-align: left; padding: 9px 12px; border: 0; background: none; border-radius: 10px; color: var(--ink); cursor: pointer; font-size: 14px } .menu a:hover, .menu button:hover { background: var(--inset); text-decoration: none }
main { padding: 26px 24px 60px; max-width: 1640px; margin: 0 auto }
h1 { font-size: 30px; font-weight: 700; letter-spacing: -.02em; margin: 0 }
.head { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; flex-wrap: wrap; margin-bottom: 20px } .head p { margin: 4px 0 0; color: var(--ink2) }
.crumb { font-size: 14px; margin-bottom: 4px }

.sum { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 14px; margin-bottom: 22px }
.stat { padding: 16px 18px } .stat span { font-size: 13px; color: var(--muted); display: block } .stat b { font-size: 30px; font-weight: 650; letter-spacing: -.02em; font-variant-numeric: tabular-nums }
.stat.ok b { color: var(--up) } .stat.warn b { color: var(--warn) } .stat.crit b { color: var(--down) }

.pill { display: inline-flex; align-items: center; gap: 6px; padding: 3px 10px; border-radius: 999px; font-size: 12.5px; font-weight: 600; white-space: nowrap }
.pill i { width: 7px; height: 7px; border-radius: 50% } .pill.ok { background: var(--up-bg); color: var(--up) } .pill.ok i { background: var(--up) }
.pill.warn { background: var(--warn-bg); color: var(--warn) } .pill.warn i { background: var(--warn) } .pill.crit { background: var(--down-bg); color: var(--down) } .pill.crit i { background: var(--down) }
.pill.none { background: var(--inset); color: var(--muted) } .pill.none i { background: var(--none) }

.group { margin: 26px 0 10px; font-size: 13px; font-weight: 600; color: var(--muted); letter-spacing: .02em }

.cols { display: grid; grid-template-columns: minmax(0, 1.6fr) minmax(320px, 1fr); gap: 16px; align-items: start }
.stack { display: grid; gap: 16px; min-width: 0 }
.panel { padding: 18px 0 6px } .panel > h2 { margin: 0 18px 10px; font-size: 17px; font-weight: 650; display: flex; justify-content: space-between; align-items: baseline; gap: 10px } .panel > h2 small { font-size: 13px; font-weight: 400; color: var(--muted) }
.list { margin: 0 10px 8px } .row { display: flex; align-items: center; gap: 12px; padding: 10px 8px; border-top: 1px solid var(--line); min-width: 0 } .row:first-child { border-top: 0 }
.row .main { flex: 1; min-width: 0 } .row .main div { overflow: hidden; text-overflow: ellipsis; white-space: nowrap } .row .main small { color: var(--muted); font-size: 12.5px; display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
.row .val { font-variant-numeric: tabular-nums; color: var(--ink2); font-size: 14px; white-space: nowrap }
.empty { padding: 6px 18px 14px; color: var(--muted); font-size: 14px }

.kv { display: grid; grid-template-columns: auto 1fr; gap: 8px 16px; margin: 0 18px 14px; font-size: 14px } .kv dt { color: var(--muted) } .kv dd { margin: 0; text-align: right; font-variant-numeric: tabular-nums; overflow-wrap: anywhere }
.bars { margin: 0 18px 14px; display: grid; gap: 8px } .bars div { display: grid; grid-template-columns: 120px 1fr 40px; gap: 10px; align-items: center; font-size: 13px }
.bars i { height: 6px; border-radius: 3px; background: var(--track); position: relative; overflow: hidden } .bars i em { position: absolute; inset: 0 auto 0 0; background: var(--hue); border-radius: 3px }

/* controls */
.btn { display: inline-flex; align-items: center; gap: 8px; height: 36px; padding: 0 16px; border-radius: 999px; border: 0; background: var(--inset); color: var(--ink); cursor: pointer; font-weight: 550; font-size: 14px; white-space: nowrap } .btn:hover { background: var(--hue-soft); text-decoration: none }
.btn.primary { background: var(--hue); color: var(--on-hue) } .btn.primary:hover { filter: brightness(1.08) } .btn.sm { height: 30px; padding: 0 12px; font-size: 13px } .btn.danger { color: var(--down) }
.seg { display: inline-flex; gap: 2px; padding: 3px; border-radius: 999px; background: var(--inset) } .seg button { border: 0; background: none; padding: 5px 14px; border-radius: 999px; cursor: pointer; font-size: 13px; color: var(--ink2); font-weight: 500 }
.seg button[aria-pressed=true] { background: var(--glass-strong); color: var(--ink); box-shadow: 0 1px 2px rgba(0, 0, 0, .08) }
/* on/off switch: one tap toggles; ink when on, grey when off */
.tgl { display: inline-grid; place-items: center; min-width: 44px; min-height: 44px; padding: 0 2px; border: 0; background: none; cursor: pointer; vertical-align: middle }
.tgl i { position: relative; display: block; width: 46px; height: 28px; border-radius: 999px; background: var(--none); transition: background .2s var(--ease) }
.tgl i::after { content: ""; position: absolute; top: 3px; left: 3px; width: 22px; height: 22px; border-radius: 50%; background: var(--sheet); box-shadow: 0 1px 3px rgba(0, 0, 0, .25); transition: transform .2s var(--ease) }
.tgl[aria-checked=true] i { background: var(--hue) } .tgl[aria-checked=true] i::after { transform: translateX(18px) }
.tgl:disabled { cursor: default; opacity: .5 }
.form { display: grid; gap: 14px; padding: 0 18px 18px } .field { display: grid; gap: 6px; font-size: 13px; color: var(--ink2); font-weight: 500 } .field small { color: var(--muted); font-weight: 400 }
.field input, .field select, .field textarea { height: 40px; padding: 0 14px; border-radius: 12px; border: 1px solid var(--line); background: var(--glass-strong); font-size: 15px; color: var(--ink) }
.field input:focus, .field select:focus { outline: none; border-color: var(--hue); box-shadow: 0 0 0 4px var(--hue-soft) }
.two { display: grid; grid-template-columns: 1fr 1fr; gap: 12px }
.err { color: var(--down); font-size: 13px; min-height: 1em } .ok { color: var(--up); font-size: 13px }
table { width: 100%; border-collapse: collapse; font-size: 14px } th { text-align: left; font-weight: 500; color: var(--muted); font-size: 12.5px; padding: 8px 18px; border-bottom: 1px solid var(--line) } td { padding: 11px 18px; border-bottom: 1px solid var(--line); vertical-align: top }
tr:last-child td { border-bottom: 0 } tr.go { cursor: pointer } tr.go:hover td { background: var(--inset) } .r { text-align: right }
.signin { min-height: 100vh; display: grid; place-items: center; padding: 20px } .signin form { width: min(380px, 100%); padding: 28px; display: grid; gap: 14px } .signin h1 { font-size: 24px } .signin .brand { margin-bottom: 4px } .signin .btn { justify-content: center }
.skel { height: 120px; border-radius: var(--r); background: var(--inset); animation: pulse 1.4s ease-in-out infinite } @keyframes pulse { 50% { opacity: .5 } }
@media (prefers-reduced-motion: reduce) { * { transition: none !important; animation: none !important } }

.stack, .cols > * { grid-template-columns: minmax(0, 1fr); min-width: 0 } .panel { min-width: 0 } .row > .pill, .row > .btn { flex: none }
.row { color: inherit } a.row:hover { text-decoration: none; background: var(--inset); border-radius: 12px }
.panel > h2 a { font-size: 13px; font-weight: 500 }

.blocks { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); margin: 2px 0 16px }
.blk { display: grid; gap: 2px; padding: 4px 18px; color: inherit; min-width: 0; border-left: 1px solid var(--line) } .blk:first-child { border-left: 0 } .blk:hover { text-decoration: none } .blk:hover span { color: var(--ink) }
.blk b { font-size: 30px; font-weight: 600; font-variant-numeric: tabular-nums; line-height: 1.1; letter-spacing: -.02em; color: var(--ink) } .blk span { order: -1; font-size: 13px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis }
.blk.ok b { color: var(--up) } .blk.warn b { color: var(--warn) } .blk.crit b { color: var(--down) } .blk.info b { color: var(--hue) }
.blk.zero b { color: var(--muted); font-weight: 500 }

td.r.num { white-space: nowrap }

.icon.busy svg { animation: spin 1s linear infinite } @keyframes spin { to { transform: rotate(360deg) } } .icon:disabled { cursor: progress }

.field textarea { height: auto; min-height: 64px; padding: 10px 14px; resize: vertical; font: inherit; line-height: 1.4 }


/* phones: the bar keeps the brand mark, the tabs scroll, the page tightens */
@media (max-width: 700px) {
  .bar { margin: 8px 8px 0; gap: 8px; padding: 0 6px 0 10px; overflow: hidden } .brand span, .fresh span, .who span { display: none }
  .tabs { margin-left: 0; overflow-x: auto; scrollbar-width: none; flex: 1; min-width: 0 } .tabs::-webkit-scrollbar { display: none } .tabs a { padding: 6px 10px }
  .fresh { display: none } .who { padding: 4px } main { padding: 18px 12px 40px } .two { grid-template-columns: 1fr }
  .blocks { grid-auto-flow: row; grid-template-columns: repeat(3, minmax(0, 1fr)) }
}

/* ---------- the Liquid Glass shell: a floating glass sidebar, an action capsule, the page beside them ---------- */
body.has-side main { margin-left: calc(var(--side) + 32px); max-width: none; padding: 28px 40px 48px 32px }
.side { position: fixed; top: 16px; left: 16px; bottom: 16px; width: var(--side); z-index: 30; display: flex; flex-direction: column; gap: 2px; padding: 18px 12px 12px; border-radius: 26px; overflow-y: auto; scrollbar-width: none }
.side .brand { padding: 2px 8px 16px; font-size: 16px } .side .brand img, .side .brand svg { width: 32px; height: 32px; border-radius: 9px; flex: none }
.side .sec { font-size: 13px; font-weight: 600; color: var(--label2); padding: 14px 12px 4px }
.side .nav { display: flex; align-items: center; gap: 12px; padding: 10px 12px; border-radius: 13px; color: var(--ink); font-size: 15px; font-weight: 550; text-decoration: none; border: 0; background: none; width: 100%; text-align: left; cursor: pointer }
.side .nav:hover { background: var(--inset); text-decoration: none } .side .nav[aria-current] { background: var(--sel); box-shadow: var(--sel-ring) }
.side .nav svg { width: 20px; height: 20px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round }
.side .nav .n { margin-left: auto; font-size: 13px; font-weight: 500; color: var(--label2); font-variant-numeric: tabular-nums } .side .nav .n.bad { color: var(--down); font-weight: 650 }
.side .nav.quiet { color: var(--label2) }
.side .grow { flex: 1; min-height: 12px }
.side .search { display: flex; align-items: center; gap: 8px; height: 38px; padding: 0 12px; margin: 0 4px 10px; border-radius: 999px; background: var(--inset); color: var(--label2) }
.side .search input { border: 0; background: transparent; outline: none; font: inherit; color: var(--ink); width: 100%; height: 100% }
.side .me { display: flex; align-items: center; gap: 12px; padding: 8px 10px; border-radius: 13px; border: 0; background: none; cursor: pointer; width: 100%; text-align: left; color: var(--ink); font-size: 15px }
.side .me:hover, .side .me[aria-expanded="true"] { background: var(--inset) }
.side .me b { width: 32px; height: 32px; border-radius: 999px; display: grid; place-items: center; flex: none; font-size: 12px; font-weight: 650; color: var(--on-hue); background: var(--ink) }
.side .me small { display: block; font-size: 12.5px; color: var(--label2) }
.side .menu { position: static; margin: 4px 0 0; min-width: 0; padding: 4px; border-radius: 14px; background: var(--inset); box-shadow: none }
.topact { position: fixed; top: 22px; right: 32px; z-index: 25; display: flex; align-items: center; gap: 4px; padding: 5px; border-radius: 999px }
.topact .icon { width: 42px; height: 42px; color: var(--ink) } .topact .btn { height: 42px }
.topact .fresh { padding: 0 8px 0 10px; margin: 0 }
body.has-side .head { padding-right: calc(var(--topact-w, 280px) + 20px); min-height: 52px } /* room for the action capsule, measured by sync-look.js */
.btn { background: var(--lens); color: var(--ink) } .btn:hover { background: var(--hue-soft); filter: brightness(1.04) }
.btn.primary { background: var(--ink); color: var(--on-hue) } .btn.primary:hover { background: var(--ink); filter: none; opacity: .88 }
.btn.danger { color: var(--down) }
.seg button[aria-pressed=true], .tabs a[aria-current] { background: var(--sel); color: var(--ink); box-shadow: var(--sel-ring) }
.who b { background: var(--ink); color: var(--on-hue) }
.menu { box-shadow: var(--glass-spec), var(--shadow) }
.signin form { border-radius: 27px }
.field input, .field select, .field textarea { background: var(--inset); border-color: transparent }
.field input:focus, .field select:focus, .field textarea:focus { border-color: var(--ink); box-shadow: 0 0 0 4px var(--hue-soft) }
@media (prefers-reduced-transparency: reduce) { .glass, .side, .topact { background: var(--glass-strong); -webkit-backdrop-filter: none; backdrop-filter: none } }
/* phones and narrow windows: the sidebar becomes a glass bar on top, its links scroll sideways; actions sit below it */
@media (max-width: 900px) {
  body.has-side main { margin-left: 0; padding: 12px 14px 40px }
  .side { position: sticky; top: 8px; bottom: auto; left: auto; width: auto; margin: 8px 8px 0; flex-direction: row; align-items: center; padding: 6px 8px; border-radius: 999px; overflow-x: auto; overflow-y: hidden; background: var(--glass-strong); -webkit-backdrop-filter: none; backdrop-filter: none } /* no blur here: a blurred parent traps the fixed account menu */
  .side .brand { padding: 0 6px 0 2px } .side .brand span, .side .sec, .side .search, .side .grow, .side .me small, .side .me span { display: none }
  .side .nav { width: auto; flex: none; padding: 9px 14px; border-radius: 999px; font-size: 14px } .side .nav svg { display: none } .side .nav .n { margin-left: 6px }
  .side .me { width: auto; flex: none; padding: 4px } .side .menu { position: fixed; top: 64px; right: 10px; left: auto; width: 240px; background: var(--glass-strong); z-index: 40 }
  .topact { position: static; margin: 10px 14px 0; width: max-content; max-width: calc(100% - 28px); flex-wrap: wrap; border-radius: 21px }
  body.has-side .head { padding-right: 0 }
  body::before { width: 100vw; height: 50vh; opacity: .7 }
}
.field input, .field select, .field textarea { width: 100%; min-width: 0 } .two > * { min-width: 0 }

/* ---------- the wall display, the standard for critical dashboards (Sync HA overview, Sync NOC status) ----------
   counts on top (.ovtop with .blocks), then screen-sized pages that slide sideways (.deck > .track > .slide) driven by a
   .deckbar: tabs (#dtabs), previous / play-pause / next, time per page, a progress bar, full screen (body.kiosk hides the
   sidebar and the action capsule). The page script keeps the deck state outside the view so a data refresh keeps the page. */
main:has(.deck) { max-width: none; padding-bottom: 16px } main:has(.deck) .head { align-items: center; margin-bottom: 14px }
.ovtop { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr); gap: 16px; margin-bottom: 16px } .ovtop .panel { padding-bottom: 0 }
.deckbar { position: relative; display: flex; align-items: center; gap: 6px; padding: 5px 6px 5px 5px; border-radius: 999px }
.deckbar .seg { background: none } .deckbar .seg button[aria-selected=true] { background: var(--hue); color: var(--on-hue) }
.deckctl { display: flex; align-items: center; gap: 2px; padding-left: 6px; border-left: 1px solid var(--line) } .deckctl .icon { width: 34px; height: 34px }
.deckctl #dplay.on { background: var(--hue-soft); color: var(--hue) }
.deckctl select { height: 32px; padding: 0 10px; border-radius: 999px; border: 0; background: var(--inset); color: var(--ink); font: inherit; font-size: 13px }
.deckprog { position: absolute; left: 22px; right: 22px; bottom: 1px; height: 2px; border-radius: 2px; overflow: hidden }
.deckprog i { display: block; height: 100%; background: var(--hue); transform-origin: left; transform: scaleX(0); opacity: .7 } @keyframes deckprog { from { transform: scaleX(0) } to { transform: scaleX(1) } }
.deck { overflow: hidden; margin: -8px; padding: 8px 0 } .track { display: flex; transition: transform .6s var(--ease) }
.slide { flex: 0 0 100%; min-width: 0; padding: 0 8px; height: var(--slide-h, 640px); overflow: auto; scrollbar-width: thin }
.sl-map { display: grid; grid-template-columns: minmax(0, 1fr) minmax(280px, 340px); gap: 16px; height: 100% } .sl-map > .panel { min-height: 0; display: flex; flex-direction: column }
.sl-map .mapbox { flex: 1; min-height: 0 } .sl-map .fmap:not(.full) { height: 100% } .sl-map #o-list .list { overflow: auto }
.sl-sites { align-content: start } .sl-two { display: grid; grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr); gap: 16px; align-items: start }
.tscroll { overflow-x: auto } .sl-health td { white-space: nowrap } .sl-health td:first-child { white-space: normal } .tbad { color: var(--down); font-weight: 650 } .tmeh { color: var(--warn); font-weight: 600 }
body.kiosk .side, body.kiosk .topact { display: none } body.kiosk.has-side main { margin-left: 0; padding: 14px 18px 16px } body.kiosk .head { padding-right: 0 }
@media (max-width: 1100px) {
  .ovtop, .sl-map, .sl-two { grid-template-columns: minmax(0, 1fr) } .deckctl, .deckprog, .deckbar .seg { display: none } .deckbar { display: none }
  .deck { overflow: visible; margin: 0; padding: 0 } .track { display: grid; gap: 16px; transform: none !important } .slide { height: auto; overflow: visible; padding: 0 } .sl-map .fmap:not(.full) { height: 440px }
}

/* sidebar: each site with its state as a dot and its open problems (critical dashboards list every site) */
.side .nav.site { padding: 8px 12px; font-size: 14px; font-weight: 500 } .side .nav.site span:not(.n) { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0 }
.side .dot { width: 9px; height: 9px; border-radius: 50%; flex: none; margin: 0 5px; background: var(--none) } .side .dot.ok { background: var(--up) } .side .dot.warn { background: var(--warn) } .side .dot.crit { background: var(--down) } .side .dot.info { background: var(--ink); opacity: .55 }
@media (max-width: 900px) { .side .nav.site { display: none } }

/* ---------- the sidebar folds to an icon rail (body.side-min); the page takes the room. A button in the brand row toggles it,
   the choice is kept per browser. Folded: icons, site dots and the avatar stay; names live on as hover titles and for
   screen readers; a problem count becomes a small red dot on its icon. ---------- */
.side .brand { position: relative } .side .fold { margin-left: auto; width: 32px; height: 32px; border-radius: 10px; border: 0; background: none; color: var(--label2); display: grid; place-items: center; cursor: pointer; flex: none }
.side .fold:hover { background: var(--inset); color: var(--ink) } .side .fold svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; transition: transform .25s var(--ease) }
/* the fold is instant: animating the page width would lay the whole page out again on every frame */
/* the rail is a desktop state: a phone keeps its full top bar even if the sidebar was folded on a wider window */
@media (min-width: 901px) {
body.side-min { --side: 76px }
body.side-min .side { padding: 14px 10px 12px; align-items: stretch; overflow-x: hidden; overflow-y: auto; background: var(--glass-strong); -webkit-backdrop-filter: none; backdrop-filter: none } /* scrolls when long; no blur, so the fixed account menu is not trapped */
body.side-min .side .brand { flex-direction: column; gap: 10px; padding: 2px 0 12px; align-items: center }
body.side-min .side .fold { margin: 0 } body.side-min .side .fold svg { transform: rotate(180deg) }
body.side-min .side .brand span, body.side-min .side .nav > span:not(.n), body.side-min .side .me > span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap }
body.side-min .side .sec { font-size: 0; padding: 8px 0 4px; margin: 0 14px; border-top: 1px solid var(--line) }
body.side-min .side .search { width: 44px; margin: 0 auto 8px; padding: 0; justify-content: center } body.side-min .side .search input { position: absolute; width: 1px; opacity: 0; pointer-events: none }
body.side-min .side .nav { justify-content: center; padding: 9px 0; position: relative; gap: 0; flex: none } body.side-min .side .nav.site { padding: 9px 0 }
body.side-min .side .nav .n { display: none } body.side-min .side .nav .n.bad { display: block; position: absolute; top: 6px; right: 10px; width: 8px; height: 8px; padding: 0; border-radius: 50%; font-size: 0; background: var(--down) }
body.side-min .side .dot { margin: 0 } body.side-min .side .me { justify-content: center; padding: 8px 0 }
body.side-min .side .menu { position: fixed; left: 92px; bottom: 18px; top: auto; right: auto; width: 220px; background: var(--glass-strong); -webkit-backdrop-filter: blur(22px) saturate(160%); backdrop-filter: blur(22px) saturate(160%); box-shadow: var(--glass-spec), var(--shadow); z-index: 40 }
}
@media (max-width: 900px) { .side .fold { display: none } body.side-min { --side: 288px } }
.side .brand a { display: flex; align-items: center; gap: 10px; min-width: 0; color: var(--ink); text-decoration: none; font-weight: 650 } .side .brand a span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
@media (min-width: 901px) { body.side-min .side .nav.site .n { display: none } }

/* the Sync mark: the bare mark (no tile) in the theme's ink, black in light and white in dark; it follows the app's own
   light/dark switch because it is drawn as a mask filled with --ink (sync-mark.svg sits next to this file) */
.sync-mark { display: inline-block; flex: none; width: 28px; height: 28px; background: var(--ink); -webkit-mask: url(sync-mark.svg) center / contain no-repeat; mask: url(sync-mark.svg) center / contain no-repeat }
.side .brand .sync-mark { width: 28px; height: 28px; margin: 2px } .signin .brand .sync-mark, .card .brand .sync-mark { width: 30px; height: 30px }

/* every wall-display page is filled edge to edge: panels stretch to the page height, their lists and tables scroll inside,
   side-by-side panels share one height, an empty panel centres its one quiet line. No ragged ends, no dead space below. */
@media (min-width: 1101px) {
  .slide { display: flex; flex-direction: column } .slide > * { flex: 1 1 auto; min-height: 0 }
  .slide .panel { display: flex; flex-direction: column; min-height: 0 }
  .slide .panel > .scroll, .slide .panel > .tscroll, .slide .panel > .list, .slide .panel > table { flex: 1 1 auto; min-height: 0; overflow: auto }
  .slide .panel > .empty { flex: 1 1 auto; display: grid; place-items: center; text-align: center; font-size: 15px; padding: 18px }
  .sl-two, .probs { height: 100%; align-items: stretch !important; grid-template-rows: minmax(0, 1fr) }
  .sl-sites { height: 100%; grid-auto-rows: minmax(min-content, 1fr); align-content: stretch }
}

/* speed with the blur kept: glass is blurred at rest (computed once, then free). Only while something moves (scrolling,
   a deck page sliding) would the blur be recomputed every frame, so for that moment sync-look.js sets body.moving and the
   content sheets paint the exact colour their blur shows over the drawing paper (sampled: the 22px blur leaves the grid at
   1-2 levels of 255), returning to the real blur about 0.2 s after the motion stops. What floats keeps its blur always. */
body.moving .glass:not(.side):not(.topact):not(.deckbar):not(.menu):not(.bar):not([class*="fm-"]) { background: var(--sheet); -webkit-backdrop-filter: none; backdrop-filter: none }

/* charts (sync-charts.js): ink lines on the faint grid, the worst or second series dashed and grey, colour only past a limit */
.chart { position: relative; width: 100%; height: 220px } .chart.short { height: 170px }
.chart svg { display: block; width: 100%; height: 100% }
.chart .grid line { stroke: var(--line) } .chart .axis text { font: 11px var(--font); font-variant-numeric: tabular-nums; fill: var(--muted) }
.chart .base, .chart .cross { stroke: var(--track) } .chart .cross { stroke: var(--muted); stroke-dasharray: 2 3 }
.chart > .empty { height: 100%; display: grid; place-content: center; text-align: center; gap: 2px } .chart > .empty small { color: var(--muted) }
.tip { position: absolute; pointer-events: none; z-index: 5; padding: 8px 11px; border-radius: 12px; font-size: 12px; font-variant-numeric: tabular-nums; white-space: nowrap; color: var(--ink); background: var(--glass-strong); box-shadow: var(--glass-spec), var(--shadow); -webkit-backdrop-filter: blur(22px) saturate(160%); backdrop-filter: blur(22px) saturate(160%) }
.tip .tt { color: var(--muted); margin-bottom: 4px } .tip div { display: flex; gap: 14px; justify-content: space-between } .tip i { display: inline-block; width: 10px; height: 2px; margin-right: 6px; vertical-align: 3px }
.legend { display: flex; flex-wrap: wrap; gap: 4px 16px; font-size: 12px; color: var(--muted) } .legend i.line { display: inline-block; width: 14px; height: 2px; margin-right: 6px; vertical-align: 3px }
.gauge { margin: 0; display: grid; justify-items: center; min-width: 0 } .gauge svg { width: 100%; max-width: 150px; display: block }
.gauge path { fill: none; stroke-width: 9; stroke-linecap: round } .g-track { stroke: var(--track) } .g-val { stroke: var(--ink); transition: stroke-dasharray .6s var(--ease) }
.gauge.warn .g-val { stroke: var(--warn) } .gauge.crit .g-val { stroke: var(--down) } .gauge.none .g-val { stroke: none }
.g-fig { font-size: 25px; font-weight: 700; fill: var(--ink); letter-spacing: -.02em; font-variant-numeric: tabular-nums } .g-unit { font-size: 13px; font-weight: 500; fill: var(--muted) }
.gauge figcaption { margin-top: -10px; font-size: 13px; color: var(--muted); text-align: center }
.barlist { display: grid; gap: 9px } .bl-row { display: grid; grid-template-columns: minmax(90px, 46%) 1fr auto; gap: 12px; align-items: center; font-size: 13.5px }
.bl-row[data-href] { cursor: pointer } .bl-row[data-href]:hover .bl-l { text-decoration: underline }
.bl-l { overflow: hidden; text-overflow: ellipsis; white-space: nowrap } .bl-row i { height: 8px; border-radius: 99px; background: var(--track); overflow: hidden }
.bl-row em { display: block; height: 100%; border-radius: inherit; background: var(--ink); opacity: .82 } .bl-row.warn em { background: var(--warn); opacity: 1 } .bl-row.crit em { background: var(--down); opacity: 1 }
.bl-row b { font-variant-numeric: tabular-nums; font-weight: 600; min-width: 52px; text-align: right } .bl-row b small { color: var(--muted); font-weight: 500 }
.panel > .chart, .panel > .legend, .panel > .barlist { margin: 0 18px 12px; width: auto } .panel > .barlist { margin-bottom: 14px }
/* fingers: every tappable thing in the shell is at least 44 px on a touch screen */
@media (pointer: coarse) { .side .nav, .side .me, .topact .icon, .topact .btn, .seg button, .hctl select { min-height: 44px } .topact .icon { min-width: 44px } }

/* a select's open list: the browser paints it with the select's own background, which is see-through here, so the
   options get the solid sheet colour and the ink (white text on a white list in dark mode otherwise) */
select option, select optgroup { background-color: var(--sheet); color: var(--ink) }
