:root {
  --bg: #eef0f3;
  --panel: #ffffff;
  --text: #1c1f24;
  --muted: #6b7280;
  --line: #d9dde3;
  --accent: #2f6fdb;
  --rec: #3f8fd8;
  --motion: #e8833a;
  --ok: #3fa36b;
  --danger: #c8443a;
  --cursor: #e5484d;
  --video: #000;
  --win-line: #2a2e35;
}
@media (prefers-color-scheme: dark) {
  :root {
    --bg: #0f1114;
    --panel: #1a1d22;
    --text: #e6e8eb;
    --muted: #8b929c;
    --line: #2c3139;
    --accent: #5b93f0;
    --rec: #4b8fd6;
    --motion: #f0954f;
    --ok: #4cbf7f;
    --danger: #e0645a;
    --cursor: #ff6369;
  }
}
* { box-sizing: border-box; }
[hidden] { display: none !important; }
/* The viewer page: no admin parts. */
a.tab { text-decoration: none; color: var(--accent); font-size: 14px; }
label.check { display: flex; gap: 6px; align-items: center; }
label.check input { width: auto; }
/* (viewport-fit=cover: the page keeps clear of an iPhone's notch held sideways.) */
body { padding: 0 env(safe-area-inset-right) 0 env(safe-area-inset-left); }
body { margin: 0; background: var(--bg); color: var(--text); font: 14px/1.4 -apple-system, "PingFang SC", "Microsoft YaHei", sans-serif; }
h1 { font-size: 18px; margin: 0; letter-spacing: .05em; }
h3 { font-size: 13px; margin: 14px 0 6px; }
.spacer { flex: 1; }
.muted { color: var(--muted); font-weight: normal; }
.error { color: var(--danger); min-height: 1em; margin: 4px 0; }
button, select, input { font: inherit; color: inherit; background: var(--panel); border: 1px solid var(--line); border-radius: 6px; padding: 5px 10px; }
button { cursor: pointer; }
button:disabled, select:disabled { opacity: .45; cursor: default; }
button.primary { background: var(--accent); border-color: var(--accent); color: #fff; }
button.danger { color: var(--danger); }
button.on { border-color: var(--accent); color: var(--accent); }
.wide { width: 100%; margin-top: 10px; }

/* Login */
#login { position: fixed; inset: 0; display: grid; place-items: center; padding: 16px; }
#loginForm { display: grid; gap: 10px; width: min(340px, 100%); background: var(--panel); border: 1px solid var(--line); border-radius: 10px; padding: 24px; }
#loginForm label { display: grid; gap: 4px; }

/* Top bar */
header { display: flex; align-items: center; gap: 12px; padding: 8px 16px; border-bottom: 1px solid var(--line); background: var(--panel); flex-wrap: wrap; }
nav { display: flex; gap: 4px; }
.tab { border: 0; background: none; padding: 6px 14px; border-radius: 6px; }
.tab.on { background: var(--accent); color: #fff; }

/* The two views: cameras on the left, video on the right */
.view { display: flex; gap: 0; min-height: calc(100vh - 50px); }
aside { width: 230px; flex: none; padding: 4px 14px 14px; border-right: 1px solid var(--line); background: var(--panel); overflow-y: auto; }
section { flex: 1; min-width: 0; padding: 0 16px 16px; }
@media (max-width: 760px) {
  .view { flex-direction: column; }
  aside { width: auto; border-right: 0; border-bottom: 1px solid var(--line); }
}
.cams { list-style: none; margin: 0; padding: 0; }
.cams li { display: flex; align-items: center; gap: 8px; padding: 6px 8px; border-radius: 6px; cursor: pointer; user-select: none; }
.cams li:hover { background: var(--bg); }
.cams li.on { background: color-mix(in srgb, var(--accent) 14%, transparent); }
.cams li .name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cams input { margin: 0; padding: 0; }
.dot { width: 8px; height: 8px; border-radius: 50%; background: var(--muted); flex: none; }
.dot.recording, .dot.streaming { background: var(--ok); }
.dot.error { background: var(--danger); }
.dot.standby { background: #d6a537; }
.badge { font-size: 11px; padding: 0 5px; border-radius: 4px; background: var(--motion); color: #fff; }
.bar { display: flex; align-items: center; gap: 8px; padding: 10px 0; flex-wrap: wrap; }
.group { display: inline-flex; gap: 4px; align-items: center; }
.hint { font-size: 12px; margin: 6px 0 0; }
.legend { display: inline-block; width: 10px; height: 10px; border-radius: 2px; margin: 0 3px 0 10px; vertical-align: -1px; }
.legend.rec { background: var(--rec); }
.legend.motion { background: var(--motion); }

/* Video windows */
.wall { display: grid; gap: 2px; background: var(--win-line); padding: 2px; border-radius: 6px; max-width: calc((100vh - 170px) * 16 / 9); margin: 0 auto; }
.wall:fullscreen { max-width: none; border-radius: 0; height: 100vh; grid-auto-rows: 1fr; }
.wall:fullscreen .win { aspect-ratio: auto; }
/* (Pinches on a picture are its own - the page doesn't zoom - but a finger still scrolls the page, until it is zoomed in.) */
.win { position: relative; aspect-ratio: 16 / 9; background: var(--video); overflow: hidden; user-select: none; -webkit-user-select: none; touch-action: pan-x pan-y; }
.win.zoomed-in { touch-action: none; }
.win.focus { outline: 2px solid var(--accent); outline-offset: -2px; z-index: 1; }
.win video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; transform-origin: 0 0; }
.win .label { position: absolute; left: 0; right: 0; top: 0; display: flex; gap: 6px; align-items: center; padding: 4px 8px; color: #fff; font-size: 12px; background: linear-gradient(#0009, #0000); pointer-events: none; }
.win .msg { position: absolute; inset: 0; display: grid; place-items: center; color: #fffc; font-size: 13px; text-align: center; padding: 10px; pointer-events: none; }
/* (Icons, wrapping onto a second row in a small window rather than off its edge.) */
.win .tools { position: absolute; right: 6px; bottom: 6px; left: 6px; display: flex; flex-wrap: wrap-reverse; justify-content: flex-end; gap: 4px; opacity: 0; transition: opacity .15s; pointer-events: none; }
/* Shown on hover with a mouse; on touch screens a tap on the picture shows
   them and the next hides them (hover is left out there: iOS keeps it
   after a tap, and they could never be hidden). */
@media (hover: hover) {
  .win:hover .tools { opacity: 1; pointer-events: auto; }
}
.win.tools-on .tools { opacity: 1; pointer-events: auto; }
.win .tools button { background: #000a; color: #fff; border-color: #fff3; padding: 3px 8px; font-size: 13px; min-width: 32px; }
.win .zoomed { position: absolute; left: 6px; bottom: 6px; }

/* Full screen where the browser has none for page parts (iPhone): the part fills the window. */
.pseudo-full {
  position: fixed !important; inset: 0; z-index: 50; margin: 0 !important; max-width: none !important;
  width: 100vw; height: 100vh; height: 100dvh; border-radius: 0 !important; background: #000;
  padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
}
.wall.pseudo-full { grid-auto-rows: 1fr; }
.wall.pseudo-full .win, .win.pseudo-full { aspect-ratio: auto; }
body.pseudo { overflow: hidden; }
#exitFull {
  position: fixed; z-index: 60; top: calc(env(safe-area-inset-top) + 8px); right: calc(env(safe-area-inset-right) + 8px);
  background: #000a; color: #fff; border-color: #fff4; font-size: 18px; padding: 4px 12px;
}

/* Pan, tilt, zoom over a camera alone */
.ptz { position: absolute; left: 10px; bottom: 44px; display: grid; grid-template-columns: repeat(3, 34px); gap: 4px; }
.ptz button { background: #000a; color: #fff; border-color: #fff4; padding: 4px 0; touch-action: none; }
.ptz .zoom { grid-column: span 3; display: flex; gap: 4px; }
.ptz .zoom button { flex: 1; }

/* Motion zones: the camera's picture under a grid of cells */
#zoneEditor { position: relative; aspect-ratio: 16 / 9; background: #000; border-radius: 6px; overflow: hidden; touch-action: none; user-select: none; }
#zoneImg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
#zoneGrid { position: absolute; inset: 0; display: grid; grid-template-columns: repeat(16, 1fr); grid-template-rows: repeat(9, 1fr); }
#zoneGrid div { border: 1px solid #fff3; }
#zoneGrid div.out { background: #e5484d88; }
#ruleEditor { position: relative; aspect-ratio: 16 / 9; background: #000; border-radius: 6px; overflow: hidden; touch-action: none; user-select: none; cursor: crosshair; }
#ruleImg, #ruleSvg { position: absolute; inset: 0; width: 100%; height: 100%; }
#ruleImg { object-fit: cover; }
#ruleSvg polygon { fill: #f5a52440; stroke: #f5a524; stroke-width: 2px; vector-effect: non-scaling-stroke; }
#ruleSvg line { stroke: #f5a524; stroke-width: 3px; vector-effect: non-scaling-stroke; }
#ruleSvg circle { fill: #fff; stroke: #f5a524; stroke-width: 2px; vector-effect: non-scaling-stroke; }

/* Status */
.scroll { overflow-x: auto; }
#statusTable { border-collapse: collapse; width: 100%; font-size: 13px; background: var(--panel); }
#statusTable th, #statusTable td { text-align: left; padding: 6px 8px; border-bottom: 1px solid var(--line); white-space: nowrap; }
/* The disk: recordings, other files, free. */
.usebar { display: flex; height: 14px; border-radius: 7px; overflow: hidden; background: var(--line); margin: 4px 0 10px; }
.usebar span { height: 100%; }
.usebar .rec, .swatch.rec { background: var(--rec); }
.usebar .other, .swatch.other { background: var(--muted); opacity: .55; }
.swatch.free { background: var(--line); }
.kv, .list { border-collapse: collapse; font-size: 13px; margin-bottom: 10px; }
.kv th { text-align: left; font-weight: normal; color: var(--muted); padding: 3px 16px 3px 0; white-space: nowrap; vertical-align: top; }
.kv td { padding: 3px 0; }
.list { width: 100%; background: var(--panel); }
.list th, .list td { text-align: left; padding: 6px 8px; border-bottom: 1px solid var(--line); white-space: nowrap; vertical-align: top; }
.list td.addr { font-family: ui-monospace, monospace; font-size: 12px; white-space: pre; user-select: all; }
.share { display: inline-block; height: 8px; border-radius: 4px; background: var(--rec); vertical-align: middle; margin-right: 6px; }
.swatch { display: inline-block; width: 10px; height: 10px; border-radius: 2px; margin-right: 6px; vertical-align: -1px; }
#diskChart { width: 100%; height: 120px; background: var(--panel); border: 1px solid var(--line); border-radius: 8px; }
#logBox { background: var(--panel); border: 1px solid var(--line); border-radius: 8px; padding: 10px; font-size: 12px; max-height: 50vh; overflow: auto; white-space: pre-wrap; }
.events li img { width: 64px; height: 36px; object-fit: cover; border-radius: 3px; flex: none; background: #000; }
.events li { align-items: center; }

/* Phones held upright: the camera list across the top, the controls bigger */
@media (max-width: 760px) {
  aside { padding: 4px 12px 8px; }
  aside h3 { margin: 8px 0 4px; }
  .cams { display: flex; flex-wrap: nowrap; overflow-x: auto; gap: 4px; }
  .cams li { flex: none; border: 1px solid var(--line); }
  .wide { margin-top: 6px; }
  .events { max-height: 30vh; }
  section { padding: 0 8px 12px; }
  .controls button, .controls select { padding: 8px 12px; }
  .hint { display: none; }
  header { padding: 6px 12px; gap: 8px; }
  #disk, #whoami { display: none; }
}

/* Playback (room left under the video for the controls and timeline) */
#pwall { max-width: calc((100vh - 290px) * 16 / 9); margin-top: 12px; }
#pClock { font-variant-numeric: tabular-nums; font-size: 15px; margin-left: 6px; }
#timeline { display: block; width: 100%; background: var(--panel); border: 1px solid var(--line); border-radius: 8px; cursor: crosshair; touch-action: none; }
.day { display: flex; gap: 4px; }
.day input { flex: 1; min-width: 0; padding: 5px; }
.events { list-style: none; margin: 0; padding: 0; max-height: 45vh; overflow-y: auto; font-size: 13px; }
.events li { display: flex; gap: 8px; padding: 4px 6px; border-radius: 4px; cursor: pointer; font-variant-numeric: tabular-nums; }
.events li:hover { background: var(--bg); }
.events li .seen { min-width: 1.2em; }
.warn { color: var(--danger); font-weight: 600; }
/* The Events page: a picture per event. */
#eventsView section { flex: 1; min-width: 0; padding: 12px 16px; display: grid; gap: 12px; align-content: start; }
.evbar { flex-wrap: wrap; align-items: center; gap: 10px; }
.evbar .day { width: auto; }
.evgrid { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 12px; }
.evgrid li { background: var(--panel); border: 1px solid var(--line); border-radius: 8px; overflow: hidden; cursor: pointer; font-variant-numeric: tabular-nums; }
.evgrid li:hover, .evgrid li:focus-visible { border-color: var(--accent); }
.evgrid img { display: block; width: 100%; aspect-ratio: 16 / 9; object-fit: cover; background: var(--video); }
.evgrid img.none { visibility: hidden; }
.evgrid .evtext { display: flex; gap: 6px; align-items: baseline; padding: 6px 8px; font-size: 13px; }
.evgrid .evtext .who { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--muted); }
.evgrid li.evday { grid-column: 1 / -1; background: none; border: 0; cursor: default; padding: 8px 0 0; font-weight: 600; }
.enc { border: 1px solid var(--line); border-radius: 8px; padding: 8px; margin: 6px 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); gap: 6px 10px; align-items: end; }
.enc b { grid-column: 1 / -1; }
.scroll.audit { max-height: 360px; overflow-y: auto; }
.evbar .hours { display: inline-flex; align-items: center; gap: 4px; }
.evgrid li.empty { grid-column: 1 / -1; background: none; border: 0; cursor: default; padding: 24px 0; }
.events li .drop { padding: 0 6px; font-size: 12px; line-height: 1.4; }
.events li .who { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--muted); }

/* Dialogs */
dialog { background: var(--panel); color: var(--text); border: 1px solid var(--line); border-radius: 10px; width: min(520px, calc(100vw - 32px)); }
dialog::backdrop { background: #0006; }
dialog label { display: grid; gap: 4px; margin-bottom: 10px; }
dialog input, dialog select, dialog textarea { width: 100%; }
dialog textarea { font: inherit; color: inherit; background: var(--panel); border: 1px solid var(--line); border-radius: 6px; padding: 5px 10px; }
details { border: 1px solid var(--line); border-radius: 8px; padding: 8px 12px; margin-bottom: 12px; }
summary { cursor: pointer; color: var(--accent); }
.sched { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; padding: 6px 0; border-bottom: 1px solid var(--line); }
.sched label { display: inline-flex; gap: 2px; margin: 0; align-items: center; }
.sched input[type=checkbox] { width: auto; }
.sched input[type=time] { width: auto; }
.rtsp { font-family: ui-monospace, monospace; font-size: 12px; user-select: all; color: var(--muted); }
dialog input[type=range] { padding: 0; }
fieldset { border: 1px solid var(--line); border-radius: 8px; margin: 0 0 12px; padding: 10px 12px; }
legend { padding: 0 4px; color: var(--muted); }
.table { list-style: none; margin: 0 0 8px; padding: 0; }
.table li { display: flex; gap: 8px; align-items: center; padding: 5px 0; border-bottom: 1px solid var(--line); }
.table li .name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* A row: its name over one muted line of detail. */
.table li .name .title, .table li .name .muted { display: block; overflow: hidden; text-overflow: ellipsis; }
.table li .name .muted { font-size: 12px; }
.table li { padding: 8px 0; }
.table li .mode { font-size: 12px; color: var(--muted); white-space: nowrap; }
/* Settings: one subject at a time. */
#setDlg { width: min(620px, calc(100vw - 32px)); }
.settabs { display: flex; flex-wrap: wrap; gap: 4px; margin: 0 0 14px; border-bottom: 1px solid var(--line); padding-bottom: 8px; }
.settabs button { border: 0; background: none; padding: 5px 12px; border-radius: 6px; }
.settabs button.on { background: var(--accent); color: #fff; }
#setDlg fieldset { border: 0; padding: 0; margin: 0 0 16px; }
#setDlg legend { padding: 0; margin-bottom: 6px; font-weight: 600; color: var(--text); }
.buttons .left { margin-right: auto; }
/* An app, not a page: no double-tap zoom; on a phone, no zooming into a field either (iOS zooms below 16px). */
html { touch-action: manipulation; -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
@media (pointer: coarse) { input, select, textarea { font-size: 16px; } }
dialog .pair { display: grid; grid-template-columns: 2fr 1fr; gap: 0 10px; }
#brandBox, #onvifBox { margin-bottom: 10px; }
.nearby { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 10px; }
.nearby button { font-family: ui-monospace, monospace; font-size: 13px; }
.nearby button.added { opacity: .5; }
/* This device's alerts: from which cameras. */
.cam-checks { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 0 12px; margin: 4px 0 0; }
.cam-checks label { display: flex; gap: 6px; align-items: center; margin: 0; padding: 3px 0; }
.cam-checks input, #pushCamsBox .check input { width: auto; }
.buttons { display: flex; justify-content: flex-end; gap: 8px; margin-top: 8px; }
