/* 自動產生，不要手改：python3 web/avtech-site/tools/sync_lan_css.py
   來源：firmware/nvr/ui/app.html 的樣式（雲端主控台和區網網頁同一套外觀） */
/* 調色盤取自 AVTECH 自己的識別：深藍 #0B2444 底、橘色 #E8640C 鏡頭光圈。
   中性色刻意往品牌藍偏一點 —— 純灰看起來像沒選過。
   橘色只留給「錄影中」：那是 logo 上的鏡頭顏色，也是畫面上最該被看見的事。

   字型只用系統堆疊。這個頁面由設備自己提供，而設備可能完全沒有對外網路
   （工廠、船舶、監控專網）—— 外部字型會靜靜地退回預設，那比一開始就不用更糟。 */
:root{
  --bg:#0b0e14; --panel:#141924; --panel2:#1b2231; --hover:#222a3a;
  --bd:#232b3a; --bd2:#2f3a4d;
  --tx:#e9edf4; --tx2:#9ba6b8; --tx3:#7d8899;
  --accent:#2c7be5; --accent2:#4a92f0; --accent-rgb:44,123,229;   /* 品牌客製會換掉這三個（applyBrand） */
  --brand:#e8640c;                 /* 鏡頭橘：只給錄影指示 */
  --ok:#27c07f; --warn:#e0a030; --err:#e5484d;
  --live:#e5484d;                  /* 即時：業界慣例的紅點，和錯誤同色但語意分開 */
  /* 深淺色主題（2026-10-12）：以下也跟著主題換。影像區（攝影機格子、播放器）不用這些，一律黑底淺字 */
  --field:#0d1119;                 /* 輸入框、下拉、時間軸、排程格的底 */
  --row-hover:rgba(255,255,255,.016);
  --shadow:0 12px 32px rgba(0,0,0,.55);
  --ok-bd:#1e4d38; --warn-bd:#4d3c1a; --err-bd:#4a2326; --sched-bd:#1f4577;
  --danger-tx:#e58e91; --danger-hover:#2a1416; --danger-bd2:#6b3034;
  --live-tx:#fff;                  /* 「即時」膠囊的字 */
  --tl-hair:rgba(233,237,244,.35); --tl-gap:rgba(var(--accent-rgb),.28);
  --vid-tx:#e9edf4; --vid-tx2:#aab4c6;   /* 影像上的字：不跟主題換 */
  color-scheme:dark;
  --m:ui-monospace,"SF Mono",Menlo,Consolas,monospace;
  --nav:206px; --r:7px;
  --top-h:56px;                    /* 頂端列與側欄品牌區同高，兩條底線才切齊（2026-10-12） */
}
/* 淺色：「跟著系統」時看作業系統；手動選了就看 data-theme（themeApply） */
@media (prefers-color-scheme: light){:root:not([data-theme="dark"]){
  --bg:#f3f5f8; --panel:#ffffff; --panel2:#eef1f5; --hover:#e6eaf0;
  --bd:#dfe3ea; --bd2:#c8cfda;
  --tx:#18202c; --tx2:#4a5566; --tx3:#6a7484;
  --accent2:#1f66c7;
  --ok:#17905a; --warn:#b17414; --err:#d33b40;
  --field:#ffffff; --row-hover:rgba(20,40,80,.035); --shadow:0 10px 28px rgba(20,30,50,.18);
  --ok-bd:#a9dcc3; --warn-bd:#e9cf98; --err-bd:#f1b9bb; --sched-bd:#a8c5ee;
  --danger-tx:#c2373c; --danger-hover:#fdecec; --danger-bd2:#e7a0a3;
  --live-tx:#c62f34; --tl-hair:rgba(24,32,44,.32); --tl-gap:rgba(var(--accent-rgb),.18);
  color-scheme:light}}
:root[data-theme="light"]{
  --bg:#f3f5f8; --panel:#ffffff; --panel2:#eef1f5; --hover:#e6eaf0;
  --bd:#dfe3ea; --bd2:#c8cfda;
  --tx:#18202c; --tx2:#4a5566; --tx3:#6a7484;
  --accent2:#1f66c7;
  --ok:#17905a; --warn:#b17414; --err:#d33b40;
  --field:#ffffff; --row-hover:rgba(20,40,80,.035); --shadow:0 10px 28px rgba(20,30,50,.18);
  --ok-bd:#a9dcc3; --warn-bd:#e9cf98; --err-bd:#f1b9bb; --sched-bd:#a8c5ee;
  --danger-tx:#c2373c; --danger-hover:#fdecec; --danger-bd2:#e7a0a3;
  --live-tx:#c62f34; --tl-hair:rgba(24,32,44,.32); --tl-gap:rgba(var(--accent-rgb),.18);
  color-scheme:light}
*{box-sizing:border-box}
html,body{height:100%}
body{margin:0;background:var(--bg);color:var(--tx);
 font:15px/1.5 -apple-system,BlinkMacSystemFont,"Segoe UI","Noto Sans TC",
      "PingFang TC","Microsoft JhengHei",sans-serif;
 -webkit-font-smoothing:antialiased;font-variant-numeric:tabular-nums;
 display:grid;grid-template-columns:var(--nav) 1fr}
a{color:inherit;text-decoration:none}
:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
@media(prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}

/* ---- 側欄 ---- */
nav{background:var(--panel);border-right:1px solid var(--bd);
 display:flex;flex-direction:column;min-height:100vh}
.brand{height:var(--top-h);padding:0 14px;border-bottom:1px solid var(--bd);display:flex;align-items:center;gap:10px;flex:none}
.brand img{width:28px;height:28px;flex:none;border-radius:6px;object-fit:contain}
.brand img[src$="/ui/mark.svg"]{border-radius:50%}
.brand .t{min-width:0}
.brand b{display:block;font-size:14.5px;font-weight:600;letter-spacing:-.01em;
 overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.brand span{display:block;font-size:13px;color:var(--tx3);font-family:var(--m);
 overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
nav ul{list-style:none;margin:0;padding:6px;flex:1}
nav li a{display:flex;align-items:center;gap:9px;padding:7px 9px;border-radius:5px;
 color:var(--tx2);font-size:14.5px;cursor:pointer;font-weight:500}
nav li a:hover{background:var(--hover);color:var(--tx)}
nav li a.on{background:var(--accent);color:#fff}
nav li a.on svg{opacity:1}
nav li a svg{width:15px;height:15px;flex:none;opacity:.72}
.navfoot{padding:10px 12px;border-top:1px solid var(--bd);
 display:flex;align-items:center;gap:8px;font-size:13.5px;color:var(--tx3)}
.navfoot .sp{flex:1}
.navfoot button{font:inherit;font-size:13.5px;padding:4px 9px;border-radius:4px;
 border:1px solid var(--bd2);background:transparent;color:var(--tx2);cursor:pointer}
.navfoot button:hover{color:var(--tx);border-color:var(--tx3)}
/* 右上角：深淺色、帳號（2026-10-14 比照 UniFi） */
/* 主題鈕和帳號鈕一樣是 30px 的實心圓（2026-10-14 使用者：透明底只看得到 16px 的圖示，像比較小的圓） */
.hdricon{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;border-radius:50%;
 border:0;padding:0;background:var(--panel2);color:var(--tx2);cursor:pointer;margin-left:6px}
.hdricon:hover{background:var(--bd2);color:var(--tx)}
.hdricon svg{width:16px;height:16px;display:block}
.acct{position:relative;margin-left:4px}
.avatar{width:30px;height:30px;border-radius:50%;border:0;background:var(--accent);color:#fff;font:600 13px/30px var(--sans, inherit);
 cursor:pointer;padding:0;text-align:center;text-transform:uppercase}
.avatar:hover{filter:brightness(1.1)}
.acctmenu{position:absolute;right:0;top:38px;z-index:50;min-width:200px;background:var(--panel, var(--card));border:1px solid var(--bd2);
 border-radius:8px;box-shadow:0 8px 24px rgba(0,0,0,.25);padding:10px}
.acctwho{display:flex;flex-direction:column;gap:2px;padding:2px 4px 10px;border-bottom:1px solid var(--bd);margin-bottom:8px}
.acctwho b{font-size:13.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.acctwho span{font-size:12px;color:var(--tx3)}
.acctmenu button{width:100%;text-align:left;font:inherit;font-size:13.5px;padding:7px 8px;border:0;border-radius:5px;
 background:transparent;color:var(--tx);cursor:pointer}
.acctmenu button:hover{background:var(--bd)}
/* 總覽左欄最上面的時間（原本在右上角） */
/* 和右邊「每列…全螢幕」那排一樣高（36px），下面的卡片才和影像頂端切齊（2026-10-14 使用者） */
.ovclock{display:flex;justify-content:space-between;align-items:center;height:36px;padding:0 4px;color:var(--tx2);font-size:13px}
.ovclock b{font-size:15px;color:var(--tx);font-variant-numeric:tabular-nums;font-weight:600}

/* ---- 主區 ---- */
main{min-width:0;display:flex;flex-direction:column;min-height:100vh}
/* 頂端列固定在畫面上方，捲動時不被捲走（2026-10-14 使用者）。要有底色才不會透出底下的內容 */
header{padding:0 18px;height:var(--top-h);border-bottom:1px solid var(--bd);
 display:flex;align-items:center;gap:10px;flex:none;position:sticky;top:0;z-index:40;background:var(--bg)}
/* 頁面標題不顯示（2026-10-14 使用者：左邊選單已經標了在哪一頁，沒必要）；元素留著給程式寫、給螢幕閱讀器 */
header h1{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
header .sp{flex:1}
/* 原始檔的文字標是 #00518e —— 深色底上看不見，內嵌後用 currentColor。 */
header .wordmark{display:none}   /* 2026-10-14 使用者：右上角的 AVTECH 字樣拿掉，改成左上角圓形的「AV」 */
header .brandlogo{height:22px;width:auto;max-width:180px;object-fit:contain;margin-right:2px}
header .brandname{font-size:13px;font-weight:600;color:var(--tx2);margin-right:2px}
/* 品牌設定頁：圖檔預覽放在深色底上（介面本來就是深色） */
.brimg{display:flex;align-items:center;gap:14px;flex-wrap:wrap;padding:10px 0;border-top:1px solid var(--bd)}
.brimg:first-child{border-top:0}
.brimg .pv{width:200px;height:56px;display:flex;align-items:center;justify-content:center;background:var(--bg);
 border:1px dashed var(--bd2);border-radius:var(--r);color:var(--tx3);font-size:12px}
.brimg .pv img{max-width:184px;max-height:44px;object-fit:contain}
.brimg .pv.sq{width:56px}
.brimg .pv.sq img{max-width:40px;max-height:40px}
#brcolor{width:44px;height:32px;padding:2px;border:1px solid var(--bd2);border-radius:5px;background:var(--panel2);cursor:pointer}
.content{padding:16px 18px 36px;flex:1;display:flex;flex-direction:column;gap:14px}
section{display:none;flex-direction:column;gap:14px}
section.on{display:flex}

/* 統計是資料，不是卡片 —— 不給邊框，靠底色與間距分組。
   邊框留給真正需要「這是一個獨立物件」的東西（表格、設定區塊）。 */
.grid{display:grid;gap:10px}
.g4{grid-template-columns:repeat(auto-fill,minmax(186px,1fr))}
.gcam{grid-template-columns:repeat(auto-fill,minmax(272px,1fr))}
.stat{background:var(--panel);border-radius:var(--r);padding:12px 14px}
.stat .k{font-size:13px;color:var(--tx3);text-transform:uppercase;
 letter-spacing:.07em;font-weight:600}
.stat .v{font-size:22px;margin-top:5px;font-weight:600;letter-spacing:-.025em}
.stat .s{font-size:13.5px;color:var(--tx2);margin-top:2px;font-family:var(--m)}

/* 面板：有邊框，因為它們是獨立的操作單位 */
.card{background:var(--panel);border:1px solid var(--bd);border-radius:var(--r);overflow:hidden}
.card>h2{font-size:13.5px;margin:0;padding:10px 14px;color:var(--tx2);font-weight:600;
 text-transform:uppercase;letter-spacing:.07em;border-bottom:1px solid var(--bd)}
.card>.body{padding:14px}
.card>.body.flush,.card>details>.body.flush{padding:0 14px 14px}   /* 收合區塊裡的也要（2026-10-14 儲存頁 SMART 表貼邊） */

/* ---- 攝影機：影像滿版，資訊疊在上面 ---- */
.cam{position:relative;aspect-ratio:16/9;background:#05070c;border-radius:var(--r);color:var(--vid-tx);
 overflow:hidden;border:1px solid var(--bd)}
.cam video{width:100%;height:100%;object-fit:cover;display:block}
.cam .empty{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
 color:var(--vid-tx2);font-size:13.5px;letter-spacing:.04em}
.cam .empty{flex-direction:column;gap:4px}
.cam .empty small{font:11.5px var(--m);opacity:.75}
.cam .ov{position:absolute;left:0;right:0;bottom:0;padding:22px 10px 8px;
 background:linear-gradient(transparent,rgba(5,7,12,.88));
 display:flex;align-items:baseline;gap:7px;cursor:default}
.cam .ov .nm{flex:1;font-size:14px;font-weight:500;min-width:0;
 overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cam .ov .res{font:12px var(--m);color:var(--vid-tx2)}
.cam .badge{position:absolute;top:8px;left:8px;display:flex;align-items:center;gap:5px;
 background:rgba(5,7,12,.6);padding:3px 7px;border-radius:4px;
 font:12px var(--m);letter-spacing:.05em;color:#d8dee9}
.dot{width:6px;height:6px;border-radius:50%;flex:none}
.dot.ok{background:var(--ok)}
.dot.no{background:var(--tx3)}
.dot.rec{background:var(--brand);animation:pulse 2.4s ease-in-out infinite}
@keyframes pulse{50%{opacity:.3}}

/* ---- 表格 ---- */
table{width:100%;border-collapse:collapse;font-size:14.5px}
th{text-align:left;font-size:13px;color:var(--tx3);text-transform:uppercase;
 letter-spacing:.07em;padding:9px 12px 7px 0;font-weight:600}
td{padding:7px 12px 7px 0;border-top:1px solid var(--bd);vertical-align:middle}
tbody tr:hover{background:var(--row-hover)}
td.mono{font-family:var(--m);font-size:13.5px;color:var(--tx2)}
td.lbl{width:34%;color:var(--tx2)}

/* ---- 表單 ---- */
input,select,button{font:inherit}
input[type=text],input[type=password],input[type=number],select{padding:6px 9px;border-radius:5px;
 border:1px solid var(--bd2);background:var(--field);color:var(--tx);font-size:14.5px}
input[type=number]{width:140px}
input:focus,select:focus{outline:none;border-color:var(--accent);
 box-shadow:0 0 0 3px rgba(var(--accent-rgb),.18)}
input[type=checkbox]{accent-color:var(--accent);width:15px;height:15px}
label.f{display:block;margin-bottom:11px;max-width:320px}
label.f .lb{display:block;font-size:13.5px;color:var(--tx2);margin-bottom:4px;font-weight:500}
label.f input{width:100%}
.btn{padding:6px 12px;border-radius:5px;border:1px solid var(--bd2);
 background:var(--panel2);color:var(--tx);cursor:pointer;font-size:14.5px;font-weight:500}
.btn:hover{background:var(--hover);border-color:var(--tx3)}
.btn.pri{background:var(--accent);border-color:var(--accent);color:#fff}
.btn.pri:hover{background:var(--accent2);border-color:var(--accent2)}
.btn.sm{padding:4px 9px;font-size:13.5px}
.btn.danger{border-color:var(--err-bd);color:var(--danger-tx);background:transparent}
/* 瀏覽器原生的「選擇檔案」按鈕套成 .btn（2026-10-14 使用者：韌體更新那顆沒套到樣式） */
input[type=file]{font:inherit;font-size:14px;color:var(--tx2);max-width:100%}
input[type=file]::file-selector-button{padding:6px 12px;margin-right:10px;border-radius:5px;border:1px solid var(--bd2);
 background:var(--panel2);color:var(--tx);cursor:pointer;font:inherit;font-size:14.5px;font-weight:500}
input[type=file]::file-selector-button:hover{background:var(--hover);border-color:var(--tx3)}
.btn.danger:hover{background:var(--danger-hover);border-color:var(--danger-bd2)}
.btn:disabled{opacity:.45;cursor:default}
.row{display:flex;gap:7px;align-items:center;flex-wrap:wrap}
.msg{font-size:13.5px;margin-top:9px;min-height:16px}
.msg.ok{color:var(--ok)} .msg.err{color:var(--err)} .msg.warn{color:var(--warn)}
.hint.warn{color:var(--warn)}
.pill{font:12px/1 var(--m);padding:4px 8px;border-radius:4px;
 border:1px solid var(--bd2);color:var(--tx2);letter-spacing:.04em}
.pill.ok{color:var(--ok);border-color:var(--ok-bd)}
.pill.warn{color:var(--warn);border-color:var(--warn-bd)}
.pill.err{color:var(--err);border-color:var(--err-bd)}
.adbar{height:6px;border-radius:3px;background:var(--field);border:1px solid var(--bd);overflow:hidden;margin-top:8px}
.adbar i{display:block;height:100%;width:0;background:var(--accent);transition:width .3s}
.hint{font-size:13.5px;color:var(--tx3);margin-top:8px;line-height:1.65;max-width:62ch}

/* ---- 設定：左右兩欄 ---- */
.two{display:grid;grid-template-columns:166px 1fr;gap:16px;align-items:start}
.subnav{list-style:none;margin:0;padding:0;position:sticky;top:calc(var(--top-h) + 16px);
 display:flex;flex-direction:column;gap:2px}
.subnav a{display:block;padding:6px 10px;border-radius:5px;color:var(--tx2);
 font-size:14.5px;cursor:pointer}
.subnav a:hover{background:var(--hover);color:var(--tx)}
.subnav a.on{background:var(--panel2);color:var(--tx);font-weight:500}
.pane{display:none;flex-direction:column;gap:12px}
.pane.on{display:flex}

[hidden]{display:none!important}

/* ---- 回放：左邊選攝影機，右邊播放器與時間軸（比照 UniFi Protect） ---- */
.pb{display:grid;grid-template-columns:224px 1fr;gap:14px;align-items:start}
/* 攝影機：最近事件 = 2：3，高度固定（2026-10-14 使用者：攝影機不要跟著內容一直變高變矮），內容多就各自捲。
   高度 = 視窗 − 上方標題列與 .content 上留白（72）− .content 下留白（36）：剛好不出卷軸 */
/* z-index：sticky 自成一層，裡面「⋯」選單的層級只在左欄裡比 —— 左欄整層要高過右邊的影片區，選單才不會被蓋住（2026-10-14） */
.pbside{position:sticky;z-index:20;top:calc(var(--top-h) + 16px);display:grid;grid-template-rows:minmax(0,2fr) minmax(0,3fr);gap:14px;min-width:0;
 height:calc(100vh - 108px);min-height:420px}
.pbside>.card{display:flex;flex-direction:column;min-height:0}
.pbcams ul{list-style:none;margin:0;padding:5px;flex:1;min-height:0;overflow:auto}
/* 左邊攝影機底下的最近事件（2026-10-14 使用者，比照 UniFi）：這一路最近幾筆，點了跳到那一刻 */
.pbev #pbev{flex:1;min-height:0;overflow:auto;padding:4px}
.pbevi{display:block;padding:6px;border-radius:6px;cursor:pointer}
.pbevi:hover{background:var(--hover)}
.pbevi.on{background:var(--panel2)}
/* 卡片：上方縮圖、事件名稱疊在縮圖左下角，下方時間（2026-10-14 使用者，比照 UniFi）。沒有截圖的（影像遺失等）是一條矮的色塊 */
.pbevimg{position:relative;aspect-ratio:16/9;border-radius:5px;overflow:hidden;background:var(--panel2)}
.pbevimg img{display:block;width:100%;height:100%;object-fit:cover}
.pbevimg.noimg{aspect-ratio:auto;height:32px}
.pbevtag{position:absolute;left:6px;bottom:6px;display:flex;align-items:center;gap:5px;max-width:calc(100% - 12px);
 background:rgba(5,7,12,.62);color:#fff;font-size:12px;font-weight:500;padding:3px 7px;border-radius:4px;
 white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.noimg .pbevtag{background:none;color:var(--tx);bottom:auto;top:50%;transform:translateY(-50%);left:8px;padding:0}
.pbevprot{all:unset;box-sizing:border-box;position:absolute;top:5px;right:5px;width:28px;height:28px;border-radius:50%;cursor:pointer;
 display:flex;align-items:center;justify-content:center;background:rgba(5,7,12,.6);color:#fff}
.pbevprot svg{width:15px;height:15px;fill:none;stroke:currentColor;stroke-width:2;stroke-linejoin:round}
.pbevprot:hover{background:rgba(5,7,12,.85)}
.pbevprot.on{background:var(--accent)}
.pbevprot.on svg{fill:currentColor}
.noimg .pbevprot{top:2px;width:28px;height:28px}
@media (hover:hover){.pbevi .pbevprot:not(.on){opacity:0}.pbevi:hover .pbevprot,.pbevprot:focus-visible{opacity:1}}
.pbevi time{display:block;margin:4px 2px 0;font:11.5px var(--m);color:var(--tx3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.pbevempty{padding:14px 8px;color:var(--tx3);font-size:13.5px}
.pbcams li a{display:flex;align-items:center;gap:8px;padding:6px 9px;border-radius:5px;
 color:var(--tx2);cursor:pointer;font-size:14.5px}
.pbcams li a:hover{background:var(--hover);color:var(--tx)}
.pbcams li a.on{background:var(--panel2);color:var(--tx);font-weight:500}
.pbcams .nm{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pbcams .id{font:12px var(--m);color:var(--tx3)}
/* 已移除（仍有錄影）的那一組（REMOVED_CAMERAS.md）；不在線的字變灰，不再畫綠點（2026-10-14 使用者） */
.pbcams li.pbrmh{padding:10px 9px 4px;font-size:12px;color:var(--tx3);letter-spacing:.04em}
.pbcams li.off .nm{color:var(--tx3)}
/* 「攝影機」標題右上角的「⋯」選單 */
.pbcams h2.pbh{display:flex;align-items:center;justify-content:space-between}
.pbmenu{position:relative;text-transform:none;letter-spacing:0}
.pbmenu>button{all:unset;cursor:pointer;width:26px;height:22px;border-radius:5px;text-align:center;font-size:16px;line-height:20px;color:var(--tx2)}
.pbmenu>button:hover,.pbmenu>button[aria-expanded="true"]{background:var(--hover);color:var(--tx)}
.pbmenul{position:fixed;z-index:60;min-width:220px;   /* fixed：卡片會把超出的部分切掉（2026-10-14 使用者），位置由 JS 照按鈕算 */background:var(--panel, var(--card));border:1px solid var(--bd2);
 border-radius:8px;padding:6px;box-shadow:0 8px 24px rgba(0,0,0,.35);display:grid;gap:2px}
.pbmenul label{display:flex;align-items:center;gap:8px;padding:7px 8px;border-radius:5px;font-size:13.5px;font-weight:400;color:var(--tx);cursor:pointer;white-space:nowrap}
.pbmenul label:hover{background:var(--hover)}
.pbcams li.pbrm small{display:block;font:11px var(--m);color:var(--tx3)}
.pbmain{min-width:0;display:flex;flex-direction:column;gap:10px}
/* 時間軸置底（2026-10-14 使用者）：右欄和左欄同高，影片區撐滿中間（比例不合時上下或左右留黑），
   控制列與時間軸貼在最下面、和左欄底部對齊。手機寬度照原本由上往下排 */
@media(min-width:821px){
  .pbmain{height:calc(100vh - 108px);min-height:420px}
  .pbmain>.stage{flex:1 1 0;min-height:0;display:flex;align-items:center;justify-content:center}
  .pbmain>.stage>video{height:100%;aspect-ratio:auto}
  .pbmain>.stage>.sgrid{flex:none;width:100%}
  .pbmain>#pbmsg:empty{display:none}
}
.stage{position:relative;background:#000;border:1px solid var(--bd);border-radius:var(--r);overflow:hidden;color:var(--vid-tx)}
.stage video{display:block;width:100%;aspect-ratio:16/9;background:#000;object-fit:contain}
.veil{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
 color:var(--vid-tx2);font-size:14px;letter-spacing:.03em;background:#000;
 transition:opacity .3s;pointer-events:none}
.veil.gone{opacity:0}
/* 雲台控制：浮在影片右側中間（下面是播放器自己的控制列，不擋）。圓形方向盤＋放大鏡＋書籤（2026-10-14，比照常見 VMS） */
.camside{position:absolute;right:12px;top:50%;transform:translateY(-50%);z-index:6;display:flex;flex-direction:column;align-items:flex-end;gap:10px;pointer-events:none}
.camside>*{pointer-events:auto}
.camaud{display:flex;gap:6px;padding:8px;border-radius:14px;background:rgba(5,7,12,.55);backdrop-filter:blur(6px)}
.camaud:not(:has(button:not([hidden]))){display:none}
.camaud button{all:unset;box-sizing:border-box;cursor:pointer;color:#fff;width:62px;padding:7px 0 5px;border-radius:10px;
 display:flex;flex-direction:column;align-items:center;gap:3px;font-size:12px;user-select:none;-webkit-user-select:none;touch-action:none}
.camaud button[hidden]{display:none}
.camaud button:hover{background:rgba(255,255,255,.14)}
.camaud button.on{background:var(--accent)}
.camaud svg{width:20px;height:20px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.camaud #pbspk:not(.on) .w{opacity:.35}
.ptz{position:relative;display:flex;flex-direction:column;align-items:center;gap:10px;
 padding:12px;border-radius:14px;background:rgba(5,7,12,.55);backdrop-filter:blur(6px);color:#fff;user-select:none;-webkit-user-select:none;touch-action:none}
.ptz button{all:unset;box-sizing:border-box;cursor:pointer;color:#fff;display:flex;align-items:center;justify-content:center}
.ptz svg{width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round}
.ptzring{position:relative;width:116px;height:116px;border-radius:50%;background:rgba(255,255,255,.08)}
.ptzring button{position:absolute;left:50%;top:50%;width:32px;height:32px;margin:-16px;border-radius:50%;
 transform:rotate(var(--a)) translateY(-40px)}
.ptzring button:hover{background:rgba(255,255,255,.16)}
.ptzring button.on{background:var(--accent)}
.ptzring .ptzc{transform:none;width:40px;height:40px;margin:-20px;background:rgba(255,255,255,.12)}
.ptzzoom{display:flex;gap:4px}
.ptzzoom button{width:52px;height:32px;border-radius:8px;background:rgba(255,255,255,.08)}
.ptzzoom button:hover{background:rgba(255,255,255,.16)}
.ptzzoom button.on{background:var(--accent)}
.ptz .ptzpre{gap:6px;width:108px;height:32px;border-radius:8px;font-size:12.5px;background:rgba(255,255,255,.08)}
.ptz .ptzpre:hover{background:rgba(255,255,255,.16)}
.ptz .ptzpre svg{width:15px;height:15px}
.ptzdrag{position:absolute;left:0;right:0;top:0;bottom:48px;z-index:5;cursor:grab;touch-action:none}
.ptzdrag.dragging{cursor:grabbing}
.ptzarrow{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;overflow:visible;display:none}
.ptzarrow line{stroke:rgba(255,255,255,.85);stroke-width:3;stroke-linecap:round}
.ptzarrow circle{fill:rgba(255,255,255,.85)}
.ptzdrag.dragging .ptzarrow{display:block}
.ptzlist{position:absolute;right:calc(100% + 8px);top:0;min-width:260px;max-height:300px;overflow:auto;background:var(--panel, var(--card));color:var(--tx);
 border:1px solid var(--bd2);border-radius:8px;padding:6px;box-shadow:0 8px 24px rgba(0,0,0,.4);font-size:13.5px}
/* 清單在 .ptz 裡面：.ptz button 的 all:unset／白字會蓋過來（2026-10-14 淺色模式下按鈕和字都看不到），按鈕一律在這裡自己寫 */
.ptzlist .pi{display:flex;align-items:center;gap:8px;padding:5px 6px 5px 8px;border-radius:5px;cursor:pointer}
.ptzlist .pi:hover{background:var(--hover)}
.ptzlist .pi .pn{min-width:28px;color:var(--tx3);font-variant-numeric:tabular-nums}
.ptzlist .pi .pnm{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ptz .ptzlist button{box-sizing:border-box;cursor:pointer;color:var(--tx2);font-size:12.5px;padding:3px 9px;border-radius:5px;
 border:1px solid var(--bd2);background:var(--card);white-space:nowrap}
.ptz .ptzlist button:hover{color:var(--tx);border-color:var(--tx3)}
.ptz .ptzlist button[data-rm]:hover{color:var(--err);border-color:var(--err)}
.ptz .ptzlist .pnew button{background:var(--accent);border-color:var(--accent);color:#fff}
.ptzlist .pnew{display:flex;gap:6px;padding:2px 4px 6px}
.ptzlist .pnew input{flex:1;min-width:0}
.ptzlist .phint{padding:0 4px 8px;color:var(--tx3);font-size:12px;line-height:1.5;border-bottom:1px solid var(--bd);margin-bottom:4px}
.ptzlist .pempty{padding:6px 8px;color:var(--tx3)}
.ptz .ptzlist svg.pico{width:14px;height:14px;vertical-align:-2px;stroke:currentColor;stroke-width:2.2;fill:none;stroke-linecap:round;stroke-linejoin:round}
.ptzlist .phome{cursor:default;border-bottom:1px solid var(--bd);border-radius:0;margin-bottom:4px;padding-bottom:7px}
.ptzlist .phome:hover{background:none}
.pbbar .sp{flex:1}
/* 多路同步回放：格子取代單一的 <video>；每格 16:9，格數決定欄數 */
.btn.tog.on{background:var(--accent);border-color:var(--accent);color:#fff}
.sgrid{display:grid;gap:2px;background:#000;margin:0 auto;color:var(--vid-tx)}
.sgrid[hidden],.dd[hidden]{display:none}
.stage.sync>video,.stage.sync>.veil{display:none}
.sgrid.c1{grid-template-columns:1fr}
.sgrid.c2{grid-template-columns:repeat(2,1fr)}
.sgrid.c3{grid-template-columns:repeat(3,1fr)}
.st{position:relative;aspect-ratio:16/9;background:#000;cursor:pointer;outline:2px solid transparent;outline-offset:-2px}
.st.focus{outline-color:var(--accent)}
.st video{width:100%;height:100%;display:block;object-fit:contain;aspect-ratio:auto;background:#000}
.st .stn{position:absolute;left:6px;top:5px;font-size:13px;color:#fff;background:rgba(0,0,0,.55);
 padding:2px 6px;border-radius:3px;max-width:calc(100% - 12px);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.st .stv{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;text-align:center;
 padding:0 12px;color:var(--vid-tx2);font-size:13.5px;line-height:1.6;white-space:pre-line;background:#000;pointer-events:none}
.st .stv[hidden]{display:none}
.pbcams ul.multi li a .ck{width:14px;height:14px;border:1px solid var(--tx3);border-radius:3px;flex:none;
 display:flex;align-items:center;justify-content:center;font-size:12px;line-height:1;color:#fff}
.pbcams ul.multi li a.sel .ck{background:var(--accent);border-color:var(--accent)}
.pbcams ul.multi li a.sel .ck::after{content:"✓"}
.pbcams ul:not(.multi) .ck{display:none}
.pbcams .pbhint{font-size:13px;color:var(--tx3);padding:2px 12px 8px;margin:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
a.btn{display:inline-block}
.tl{position:relative;height:calc(var(--tl-axis) * 2 + var(--tl-bar));margin:12px 14px;background:var(--field);
 border:1px solid var(--bd);border-radius:5px;overflow:hidden;cursor:crosshair;
 touch-action:pan-y;user-select:none;-webkit-user-select:none}
.tl.dragging{cursor:grabbing}
.tl{--tl-axis:38px;--tl-bar:8px}
/* 時間軸分層（2026-10-12 使用者：時間的字被錄影條蓋住；之後要放更多事件）：
   由上而下是 刻度字 → 刻度線與遺失／恢復記號 → 錄影帶 → 事件截圖（緊貼帶子下方）。
   藍帶上下兩塊一樣高（都是 --tl-axis），有沒有截圖都一樣高（2026-10-14 使用者：不要突然長高）。
   錄影帶比照 UniFi（2026-10-14 使用者）：一條粗的藍帶，有錄影深藍、沒錄影淺藍，不再畫橫的軸線。
   疊的順序：錄影條 1、遺失斜紋與動作與事件 2、刻度 3、播放位置 4、滑鼠所在時間 5 —— 字永遠在最上面 */
.tl .ticks{position:absolute;left:0;right:0;top:7px;height:17px;z-index:3;
 font:12px/17px var(--m);color:var(--tx3);pointer-events:none}
.tl .tick{position:absolute;transform:translateX(-50%);white-space:nowrap}
.tl .tick::after{content:"";position:absolute;left:50%;top:18px;width:1px;height:calc(var(--tl-axis) - 25px);background:var(--tx3);opacity:.8}
.tl .axis{position:absolute;left:0;right:0;top:var(--tl-axis);height:var(--tl-bar);border-radius:2px;
 background:var(--tl-gap);pointer-events:none}
.tl .span{position:absolute;top:var(--tl-axis);height:var(--tl-bar);background:var(--accent);z-index:1;
 opacity:.85;border-radius:2px}
.tl .span:hover{opacity:1}
/* 縮時區段（2026-10-12）：斜線條紋，和連續錄影分得出來；播到這裡會自動快轉。
   類別名不能叫 tl —— 會吃到時間軸容器 .tl 的樣式（高度、邊距），條紋就掉到線下面（使用者回報） */
.tl .span.tlapse{background:repeating-linear-gradient(135deg,var(--accent) 0 3px,transparent 3px 6px);
 box-shadow:inset 0 0 0 1px var(--accent);opacity:.9}
/* 播放位置的直桿和頂端的時間標籤同一個藍色（2026-10-14 使用者：原本黑／白色） */
/* 不加深色描邊：描邊會讓直線看起來比標籤深（使用者回報顏色不一樣） */
.tl .cursor{position:absolute;top:0;bottom:0;width:2px;margin-left:-1px;background:var(--accent);z-index:4;
 pointer-events:none;display:none}
/* 播錄影時直桿頂端掛播放時間（2026-10-14 使用者，比照 UniFi）；蓋在刻度字上面，靠兩端時往內縮（left 由 tlCursor 算） */
.tl .cursor span{position:absolute;top:4px;background:var(--accent);color:#fff;font:600 12px/1 var(--m);
 padding:4px 7px;border-radius:10px;white-space:nowrap;box-shadow:0 1px 3px rgba(0,0,0,.35)}
.tl .cursor span:empty{display:none}
.tl .hair{position:absolute;top:0;bottom:0;width:1px;background:var(--tl-hair);z-index:5;
 pointer-events:none;display:none}
.tl .hair span{position:absolute;bottom:3px;left:5px;font:12px/1 var(--m);color:var(--tx);
 background:rgba(5,7,12,.85);padding:3px 5px;border-radius:3px;white-space:nowrap;color:var(--vid-tx)}
.tlzoom{display:flex;align-items:center;gap:6px}
.pbright{margin-left:auto;display:flex;align-items:center;gap:8px;flex-wrap:wrap;justify-content:flex-end}
.tlzoom .btn{padding:2px 9px;font-size:14px;line-height:1.3}
.tlzoom #tlmid{min-width:56px;text-align:center;font:12.5px var(--m);color:var(--tx2)}
/* ---- 即時畫面的格子（總覽用） ---- */
/* 沒有訊息時不要佔高度 —— 回放頁要剛好塞進視窗 */
#pbmsg:empty{display:none}
/* 回放的提示浮在影片上方正中，不佔版面（2026-10-14 使用者：放在時間軸下面，出現時整個畫面會跳） */
.pbmain{position:relative}
.pbmain>#pbmsg{position:absolute;top:12px;left:50%;transform:translateX(-50%);z-index:15;margin:0;max-width:calc(100% - 40px);
 width:max-content;padding:8px 14px;border-radius:8px;background:var(--panel, var(--card));border:1px solid var(--bd2);
 box-shadow:0 6px 20px rgba(0,0,0,.35);font-size:13.5px;min-height:0}
.cam .lst{position:absolute;top:8px;right:8px;display:flex;align-items:center;gap:5px;
 background:rgba(5,7,12,.6);padding:3px 7px;border-radius:4px;
 font:12px var(--m);letter-spacing:.06em;color:#aab4c6}
.cam .lst.on{color:#fff}
/* 喇叭：有聲音的那幾路才有。一次只開一路（spkSet） */
.spk{flex:none;display:inline-flex;align-items:center;justify-content:center;width:26px;height:22px;padding:0;
 border:1px solid rgba(255,255,255,.18);border-radius:4px;background:rgba(5,7,12,.55);color:#aab4c6;cursor:pointer}
.spk:hover{color:#fff;border-color:rgba(255,255,255,.4)}
.spk.on{color:#fff;background:var(--accent);border-color:var(--accent)}
.spk svg{width:15px;height:15px;display:block}
.spk .w{display:none}
.spk.on .w{display:inline}
.spk.on .x{display:none}
.cam .lst.on::before{content:"";width:6px;height:6px;border-radius:50%;background:var(--live)}
.btn.live.on{background:var(--live);border-color:var(--live);color:#fff}
.pill.live{color:var(--live-tx);border-color:var(--live);background:rgba(229,72,77,.16)}
/* ---- 事件 ---- */
nav li a .cnt{margin-left:auto;font:12px/1 var(--m);background:var(--live);color:#fff;border-radius:8px;padding:2px 6px}
/* ---- 側欄收合：只剩圖示 ----
   只在寬螢幕生效；手機上側欄本來就是橫的一排、而且要看得到字。 */
#navtoggle{display:flex;align-items:center;justify-content:center;padding:4px 7px}
#navtoggle svg{width:14px;height:14px;transition:transform .18s ease}
@media(min-width:821px){
  /* 側欄固定在畫面上：右邊內容捲動時它不跟著走（2026-10-06，以前長頁面捲下去側欄會被帶走、底下一片空） */
  nav{position:sticky;top:0;height:100vh;align-self:start;overflow-y:auto}
  body{height:auto;min-height:100%}       /* body 固定一個畫面高的話，sticky 捲過一個畫面就跟著 body 走了 */
  body{transition:grid-template-columns .18s ease}
  body.navmini{--nav:58px}
  body.navmini .brand{justify-content:center;padding:0}
  body.navmini .brand .t{display:none}
  body.navmini nav li a{justify-content:center;padding:9px 0;position:relative}
  body.navmini nav li a .lbl{display:none}
  body.navmini nav li a svg{width:17px;height:17px}
  body.navmini nav li a .cnt{position:absolute;top:1px;right:3px;margin:0;padding:1px 4px;font-size:11px}
  body.navmini .navfoot{flex-direction:column;align-items:center;padding:10px 4px;gap:6px}
  body.navmini #navtoggle svg{transform:rotate(180deg)}
}
.dot.err{background:var(--err)}
.dot.warn{background:var(--warn)}
.dd-list.evtp{padding:10px;width:300px;max-height:calc(100vh - 24px)}   /* 比通用下拉清單的 300px 高：四組全部看得到 */
.evtp .seg{display:flex;margin-bottom:6px}
.evtp .seg button{flex:1;padding:5px 6px;font-size:13.5px}
.evtp .grp{display:flex;justify-content:space-between;align-items:center;margin:8px 6px 2px;font-size:12px;
 color:var(--tx3);letter-spacing:.04em;cursor:pointer;user-select:none}
.evtp .grp:hover{color:var(--tx2)}
.evtp .grp span{font-size:11.5px}
.evtp label{display:flex;align-items:center;gap:9px;padding:5px 6px;border-radius:5px;font-size:14px;
 color:var(--tx2);cursor:pointer;user-select:none}
.evtp label:hover{background:var(--hover);color:var(--tx)}
.evtp label .dot{width:7px;height:7px}
.evtp input{margin:0 0 0 auto}
.evp{display:grid;grid-template-columns:minmax(0,1fr) 320px;gap:14px;align-items:start}
.evday{font:12px var(--m);letter-spacing:.07em;color:var(--tx3);padding:10px 14px 5px;border-top:1px solid var(--bd)}
.evday:first-child{border-top:0}
.evi{display:grid;grid-template-columns:64px 180px minmax(0,1fr) auto;gap:10px;align-items:center;
 padding:8px 14px;border-top:1px solid var(--bd);cursor:pointer}
.evday+.evi{border-top:0}
.evi:hover{background:var(--hover)}
.evi.on{background:rgba(var(--accent-rgb),.1);box-shadow:inset 2px 0 0 var(--accent)}
.evt{min-width:0}
.evt b{display:block;font-weight:500;font-size:14.5px}
.evt span{font-size:13.5px;color:var(--tx2);display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.evi.new .evt b::after{content:"未讀";margin-left:7px;font:12px/1 var(--m);color:var(--accent2);letter-spacing:.04em}
.evd{font-size:13.5px;color:var(--tx2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.evd mark{background:none;color:var(--accent);font-weight:600}   /* 事件搜尋：標亮符合的詞 */
.evi time{font:12.5px var(--m);color:var(--tx2)}
/* 事件截圖（2026-10-14，evsnap.h）：清單一列一張小的，右邊詳細內容一張大的、點了跳到那一刻的回放 */
.evthumb{width:64px;height:36px;border-radius:4px;object-fit:cover;display:block;background:var(--panel2)}
/* 前面不再另外一欄點（2026-10-14 使用者：沒意義）；沒有截圖的在縮圖位置放類型顏色的點 */
.evi span.evthumb{display:flex;align-items:center;justify-content:center}
.evsnapbig{display:block;width:100%;aspect-ratio:16/9;object-fit:contain;background:#000;cursor:pointer}
/* AI 辨識的框（ai.h）：疊在截圖上，畫在影像上的顏色不跟主題換。人綠、汽車橘、機車紫 */
.evsnapwrap{position:relative;aspect-ratio:16/9;background:#000}
.evsnapwrap .evsnapbig{position:absolute;inset:0;height:100%;aspect-ratio:auto;object-fit:fill}
.aibox{position:absolute;border:2px solid #22c55e;border-radius:3px;pointer-events:none;box-shadow:0 0 0 1px rgba(0,0,0,.45)}
.aibox em{position:absolute;left:-2px;bottom:100%;font:600 12px/1 var(--m);font-style:normal;color:#06140b;background:#22c55e;padding:3px 5px;border-radius:3px 3px 0 0;white-space:nowrap}
.aibox.in em{bottom:auto;top:-2px;border-radius:0 0 3px 0}   /* 框貼著上緣：標籤放框裡 */
.aibox.car{border-color:#f59e0b}.aibox.car em{background:#f59e0b;color:#1a1003}
.aibox.moto{border-color:#a78bfa}.aibox.moto em{background:#a78bfa;color:#140b26}
.aibox.item{border-color:#22d3ee}.aibox.item em{background:#22d3ee;color:#04161a}   /* 遺留物：青色 */
.dot.obj{background:#22c55e}
.evmore{padding:10px 14px;border-top:1px solid var(--bd)}
.evpager{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.evpager .pg{font-size:14px;color:var(--tx2);font-variant-numeric:tabular-nums;margin:0 4px}
.evside{position:sticky;top:calc(var(--top-h) + 16px)}
.evempty{padding:32px 14px;color:var(--tx3);font-size:14px;text-align:center}
/* 方形（2026-10-14 使用者），裁中間 */
.tl .tlthumb{position:absolute;top:calc(var(--tl-axis) + var(--tl-bar) + 2px);width:32px;height:32px;
 border-radius:3px;background:var(--panel2);cursor:pointer;z-index:3;box-shadow:0 0 0 1px var(--bd);overflow:hidden}
.tl .tlthumb img{display:block;width:100%;height:100%;object-fit:cover}
.tl .tlthumb:hover{box-shadow:0 0 0 2px var(--accent)}
/* 疊在一起的合成一張（2026-10-20，和 HDMI 一樣）：右下角標還有幾筆 */
.tl .tlthumb .tlmore{position:absolute;right:1px;bottom:1px;padding:0 3px;border-radius:3px;background:var(--accent);
 color:#fff;font:600 10.5px/14px var(--m);pointer-events:none}
#tlpop{position:fixed;z-index:60;min-width:220px;max-width:min(320px,92vw);max-height:min(360px,60vh);overflow:auto;padding:6px;
 background:var(--panel);color:var(--tx);border:1px solid var(--bd2);border-radius:var(--r);box-shadow:0 8px 24px rgba(0,0,0,.35)}
#tlpop button{all:unset;box-sizing:border-box;display:flex;align-items:center;gap:10px;width:100%;padding:6px;border-radius:6px;cursor:pointer}
#tlpop button:hover,#tlpop button:focus-visible{background:var(--hover)}
#tlpop img{width:64px;height:36px;object-fit:cover;border-radius:3px;background:var(--panel2);flex:none}
#tlpop .t{font-size:13.5px}
#tlpop time{display:block;font:12px var(--m);color:var(--tx3)}
/* 小刻度（2026-10-14 使用者，比照 UniFi）：有時間字的大刻度之間再分幾格，短線 */
.tl .mtick{position:absolute;top:calc(var(--tl-axis) - 5px);height:5px;width:1px;background:var(--tx3);opacity:.55;pointer-events:none}
.tl .evm{position:absolute;top:calc(var(--tl-axis) - 11px);width:3px;height:9px;margin-left:-1px;border-radius:1px;z-index:2}
.tl .evm.video_loss,.tl .evm.rec_error{background:var(--err)}
.tl .evm.video_restore{background:var(--ok)}
.dot.mot{background:var(--warn)}
.mdmeter{position:relative;height:8px;max-width:420px;margin:12px 0 6px;border-radius:4px;
 background:var(--panel2);border:1px solid var(--bd)}
.mdmeter .lvl{position:absolute;left:0;top:0;bottom:0;width:0;border-radius:4px;background:var(--tx3);transition:width .2s}
.mdmeter .lvl.hit{background:var(--warn)}
.mdmeter .thr{position:absolute;top:-5px;bottom:-5px;width:2px;margin-left:-1px;background:var(--tx)}
.cloudcode{font:600 30px/1.2 var(--m);letter-spacing:.12em;margin:10px 0 4px;color:var(--tx)}
.cloudpair{display:flex;gap:20px;align-items:center;flex-wrap:wrap;margin-top:12px}
.bklist{display:grid;gap:6px;margin:10px 0}
.bkrow{display:flex;gap:10px;align-items:flex-start;padding:10px 12px;border:1px solid var(--bd);border-radius:6px;cursor:pointer}
.bkrow:has(input:checked){border-color:var(--accent);background:rgba(var(--accent-rgb),.08)}
.bkrow b{font-weight:500}
.bkrow .hint{margin:2px 0 0}
.cloudqr{width:164px;height:164px;flex:none;background:#fff;border-radius:6px;overflow:hidden}
.cloudqr svg{width:100%;height:100%;display:block}
.mdstate{font-size:14px;color:var(--tx2)} .mdstate.on{color:var(--warn);font-weight:600} .mdstate.off{color:var(--tx3)}
.tl .lossgap{position:absolute;top:var(--tl-axis);height:var(--tl-bar);pointer-events:none;z-index:2;
 background:repeating-linear-gradient(135deg,transparent 0 4px,rgba(229,72,77,.45) 4px 6px)}
@media(max-width:820px){
  .evp{grid-template-columns:1fr}
  .evi{grid-template-columns:64px minmax(0,1fr) auto}
  .evd{display:none}
  .evside{position:static}
}
/* ---- 下拉選單：取代內建 <select> 的外觀 ----
   Safari 會把 <select> 畫成灰色的系統按鈕，打開是系統選單，跟深色介面完全不搭。
   外觀比照這裡的輸入框；打開的清單用 fixed 定位掛在 body 上，不會被卡片的 overflow 裁掉。 */
.dd{position:relative;display:inline-flex;max-width:100%}
.dd-btn{font:inherit;font-size:14.5px;line-height:1.3;color:var(--tx);background:var(--field);
 border:1px solid var(--bd2);border-radius:5px;padding:6px 30px 6px 10px;cursor:pointer;
 text-align:left;white-space:nowrap;position:relative;max-width:100%;overflow:hidden;text-overflow:ellipsis}
.dd-btn::after{content:"";position:absolute;right:11px;top:50%;width:6px;height:6px;margin-top:-5px;
 border-right:1.5px solid var(--tx2);border-bottom:1.5px solid var(--tx2);transform:rotate(45deg);
 transition:transform .15s,margin-top .15s}
.dd-btn:hover{border-color:var(--tx3)}
.dd-btn:focus-visible,.dd-btn[aria-expanded="true"]{outline:none;border-color:var(--accent);
 box-shadow:0 0 0 3px rgba(var(--accent-rgb),.18)}
.dd-btn[aria-expanded="true"]::after{transform:rotate(225deg);margin-top:-1px}
.dd-list{position:fixed;z-index:1000;max-height:300px;overflow:auto;padding:4px;
 background:var(--panel2);border:1px solid var(--bd2);border-radius:7px;
 box-shadow:var(--shadow);outline:none}
.dd-opt{padding:7px 32px 7px 10px;border-radius:5px;font-size:14.5px;color:var(--tx2);
 cursor:pointer;white-space:nowrap;position:relative}
.dd-opt.act{background:var(--hover);color:var(--tx)}
.dd-opt.sel{color:var(--tx);font-weight:500}
.dd-opt.sel::after{content:"";position:absolute;right:12px;top:50%;width:4px;height:8px;margin-top:-6px;
 border-right:2px solid var(--accent2);border-bottom:2px solid var(--accent2);transform:rotate(45deg)}
/* ---- 裝置頁：攝影機清單與每路設定 ---- */
.camset{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.2fr);gap:14px;align-items:start}
.chlist tbody tr{cursor:pointer}
.chlist tbody tr.on{background:rgba(var(--accent-rgb),.1);box-shadow:inset 2px 0 0 var(--accent)}
/* 第一欄留內距：選中那列左邊的藍線不要黏著字（2026-10-14 使用者） */
.chlist th:first-child,.chlist td:first-child{padding-left:10px}
.seg{display:inline-flex;border:1px solid var(--bd2);border-radius:6px;overflow:hidden}
.seg button{font:inherit;font-size:14.5px;padding:6px 16px;background:transparent;color:var(--tx2);
 border:0;border-left:1px solid var(--bd2);cursor:pointer}
.seg button:first-child{border-left:0}
.seg button:hover{color:var(--tx)}
.seg button.on{background:var(--accent);color:#fff}
.seg button:disabled{cursor:default}
.seg button:disabled:not(.on){opacity:.5}
.fld{margin-bottom:14px}
.fld .lb{display:block;font-size:13.5px;color:var(--tx2);margin-bottom:5px;font-weight:500}
.week{display:grid;grid-template-columns:28px repeat(24,minmax(0,1fr));gap:2px;margin-top:8px;
 user-select:none;-webkit-user-select:none;touch-action:none}
.week span{font:12px/18px var(--m);color:var(--tx3);text-align:center}
.week i{height:20px;border-radius:2px;background:var(--field);border:1px solid var(--bd);cursor:crosshair}
.week i.on{background:var(--accent);border-color:var(--accent)}
.mpill{font:12px/1 var(--m);padding:3px 7px;border-radius:4px;border:1px solid var(--bd2);color:var(--tx);white-space:nowrap}
.mpill.schedule{color:var(--accent2);border-color:var(--sched-bd)}
.mpill.off{color:var(--err);border-color:var(--err-bd)}
.mpill.timelapse{border-style:dashed}
.copygrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:6px 14px;margin:8px 0 10px;font-size:14px}
.copygrid label{display:flex;gap:7px;align-items:center;cursor:pointer}
/* ---- 網路攝影機 ---- */
.chlist .src{font:11px/1 var(--m);color:var(--tx3);margin-left:6px}
/* 快照縮圖（src/snapshot.h）：清單每一列一張、編輯區上方一張大的。沒訊號的只留灰底 */
.thumb{width:64px;height:36px;object-fit:cover;border-radius:4px;background:var(--panel2);vertical-align:middle;margin-right:10px;flex:none}
.chlist .nmc{display:flex;align-items:center}
.iprm{margin-top:12px;padding:12px 14px;border:1px solid var(--err-bd, var(--bd2));border-radius:6px;display:grid;gap:6px;font-size:14px}
.iprm label{display:flex;gap:8px;align-items:center;cursor:pointer}
.iprmq{font-weight:500}
.ched-snap{width:100%;max-width:480px;aspect-ratio:16/9;object-fit:cover;border-radius:6px;background:var(--panel2);display:block;margin-bottom:14px}
.listbar{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:10px 0 8px;flex-wrap:wrap}
.listbar .hint{margin:0}
.ipsec{margin:20px 0 10px;padding-top:14px;border-top:1px solid var(--bd);font-size:13.5px;color:var(--tx2);font-weight:600}
#ipdlg,#encdlg{background:var(--panel);color:var(--tx);border:1px solid var(--bd2);border-radius:var(--r);
  padding:0;width:min(680px,94vw);max-height:88vh}
#encdlg{width:min(520px,94vw)}
#ipdlg::backdrop,#encdlg::backdrop{background:rgba(3,6,12,.62)}
/* 偵測區域（2026-10-20，HDMI 已有）：快照疊 16×9 格，亮的才偵測 */
#zonedlg{background:var(--panel);color:var(--tx);border:1px solid var(--bd2);border-radius:var(--r);
  padding:0;width:min(900px,96vw);max-height:92vh}
#zonedlg::backdrop{background:rgba(3,6,12,.62)}
#zonedlg .dlgbody{max-height:calc(92vh - 60px)}
.zonebox{position:relative;aspect-ratio:16/9;max-width:100%;background:#000;border-radius:6px;overflow:hidden;
  user-select:none;-webkit-user-select:none;touch-action:none}
.zonebox img{position:absolute;inset:0;width:100%;height:100%;object-fit:fill}
.zonegrid{position:absolute;inset:0;display:grid;grid-template-columns:repeat(16,1fr);grid-template-rows:repeat(9,1fr);cursor:crosshair}
.zonegrid i{border:1px solid rgba(255,255,255,.10);background:rgba(3,6,12,.6)}
.zonegrid i.on{background:rgba(var(--accent-rgb),.22);border-color:rgba(var(--accent-rgb),.7)}
/* AI 智慧分析（2026-10-20，ai_smart.h）：線與區域編輯、統計。畫在影像上的顏色不跟主題換 */
#aidlg,#statdlg{background:var(--panel);color:var(--tx);border:1px solid var(--bd2);border-radius:var(--r);
  padding:0;width:min(900px,96vw);max-height:92vh}
#aidlg::backdrop,#statdlg::backdrop{background:rgba(3,6,12,.62)}
#aidlg .dlgbody,#statdlg .dlgbody{max-height:calc(92vh - 60px)}
.aistage{position:relative;aspect-ratio:16/9;max-width:100%;background:#000;border-radius:6px;overflow:hidden;
  user-select:none;-webkit-user-select:none;touch-action:none}
.aistage img,.aistage svg{position:absolute;inset:0;width:100%;height:100%;object-fit:fill}
.aistage svg{cursor:crosshair}
.aistage .h{cursor:move}
.ailist{display:grid;gap:8px;margin-top:12px}
.ailist .it{display:flex;gap:8px;align-items:center;flex-wrap:wrap;padding:8px 10px;border:1px solid var(--bd);border-radius:6px}
.ailist .chip{width:12px;height:12px;border-radius:3px;flex:none}
.ailist input[type=text]{width:140px}
.ailist input[type=number]{width:80px}
.stattbl{width:100%;border-collapse:collapse;font-variant-numeric:tabular-nums;margin-bottom:14px}
.stattbl th,.stattbl td{padding:6px 8px;border-bottom:1px solid var(--bd);text-align:right;font-size:13.5px}
.stattbl th:first-child,.stattbl td:first-child{text-align:left}
.statbars{display:flex;align-items:flex-end;gap:2px;height:110px;margin:6px 0 2px;border-bottom:1px solid var(--bd)}
.statbars i{flex:1;background:var(--accent);border-radius:2px 2px 0 0;min-height:1px;opacity:.85}
.statax{display:flex;justify-content:space-between;font-size:12px;color:var(--tx3);margin-bottom:14px}
.ailive{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;z-index:2}
/* 動作熱區圖（2026-10-20，heatmap.h）：快照上疊 32×18 的顏色。畫在影像上，顏色不跟主題換 */
#heatdlg{background:var(--panel);color:var(--tx);border:1px solid var(--bd2);border-radius:var(--r);
  padding:0;width:min(900px,96vw);max-height:92vh}
#heatdlg::backdrop{background:rgba(3,6,12,.62)}
#heatdlg .dlgbody{max-height:calc(92vh - 60px)}
.heatbox{position:relative;aspect-ratio:16/9;max-width:100%;background:#000;border-radius:6px;overflow:hidden;margin-top:12px}
.heatbox img,.heatbox canvas{position:absolute;inset:0;width:100%;height:100%;object-fit:fill}
.heatbox canvas{image-rendering:auto;opacity:.78}
.heatlegend{display:flex;align-items:center;gap:8px;margin-top:10px;font-size:13px;color:var(--tx2)}
.heatlegend i{display:block;width:140px;height:8px;border-radius:4px;background:linear-gradient(90deg,#2563eb,#22c55e,#facc15,#ef4444)}
/* 縮時影片匯出（2026-10-13） */
#tlxdlg{background:var(--panel);color:var(--tx);border:1px solid var(--bd2);border-radius:var(--r);
  padding:0;width:min(560px,94vw);max-height:88vh}
#tlxdlg::backdrop{background:rgba(3,6,12,.62)}
#tlxdlg .tlxcustom{display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin-top:8px}
#tlxdlg progress{width:100%;height:8px;margin-top:6px;accent-color:var(--accent)}
.dlghead{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:12px 16px;border-bottom:1px solid var(--bd)}
.dlghead h2{margin:0;font-size:15px;font-weight:600}
.dlgbody{padding:16px;overflow:auto;max-height:calc(88vh - 108px)}
.dlgfoot{padding:10px 16px;border-top:1px solid var(--bd);display:flex;gap:8px;min-height:14px}
.foundlist{display:flex;flex-direction:column;gap:6px}
.found{display:grid;grid-template-columns:128px minmax(0,1fr) auto;gap:4px 12px;align-items:center;text-align:left;
  padding:9px 12px;border:1px solid var(--bd2);border-radius:5px;background:var(--panel2);color:var(--tx);cursor:pointer}
.found:hover:not(:disabled){border-color:var(--accent)}
.found:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
.found:disabled{opacity:.62;cursor:default}
.found .ip{font-family:var(--m);font-size:13.5px}
.found .hw{grid-column:2;color:var(--tx3);font-size:13px}
.tblwrap{overflow-x:auto}
.proftbl td:nth-child(n+4),.proftbl th:nth-child(n+4){text-align:center;width:64px}
.proftbl tr.dis td{color:var(--tx3)}
#ipdlg summary{cursor:pointer;font-size:13.5px;color:var(--tx2)}
@media(max-width:1100px){ .camset{grid-template-columns:1fr} }
/* ---- 總覽：左欄狀態 + 右側可編輯版面 ----
   比照 UniFi Protect 的儀表板。左欄是系統層級的即時數字，
   右邊是即時畫面的拼貼，可以拖曳換位、點角落換大小、存成版面。 */
.ovwrap{display:grid;grid-template-columns:268px minmax(0,1fr);gap:12px;align-items:start}
.ovrail{display:flex;flex-direction:column;gap:10px;position:sticky;top:calc(var(--top-h) + 16px)}
.ovrail .card>.body{padding:12px 13px}
.rw{display:flex;align-items:baseline;justify-content:space-between;gap:10px;
    font-size:14px;padding:5px 0}
.rw+.rw{border-top:1px solid var(--bd)}
.rw .k{color:var(--tx2);white-space:nowrap;flex:none}
/* 值靠右、不換行（2026-10-14 使用者：「最早的錄影」和時間都被擠成兩行）；放不下時縮小字，不折行 */
.rw .v{font-family:var(--m);color:var(--tx);font-size:13px;text-align:right;white-space:nowrap;min-width:0;overflow:hidden;text-overflow:ellipsis}
.big{font-size:26px;font-weight:600;letter-spacing:-.025em;line-height:1.15}
.sub{font-size:13px;color:var(--tx3);margin-top:3px}
/* 分段條：儲存用量與編碼預算共用 */
.bar{height:7px;border-radius:4px;background:var(--panel2);overflow:hidden;display:flex;margin:9px 0 0}
.bar i{display:block;height:100%}
/* 儲存頁：硬碟、保護的片段 */
/* 兩張卡一樣高（2026-10-14 使用者：錄影卷要和硬碟一樣高） */
.namerow{display:flex;gap:8px;align-items:center}
.namerow input{flex:1;min-width:0;max-width:280px}
.namerow+.msg:empty{display:none}
.stor2{display:grid;grid-template-columns:repeat(auto-fit,minmax(320px,1fr));gap:12px;align-items:stretch}
.dhead{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:10px}
.dhead .nm{font-weight:600;font-size:16px}
.dwhy{margin:0 0 12px;padding:9px 12px;border-radius:6px;font-size:14px;line-height:1.6}
.dwhy.warn{background:rgba(224,160,48,.1);color:var(--warn)}
.dwhy.err{background:rgba(229,72,77,.1);color:var(--err)}
.kvs{display:grid;grid-template-columns:repeat(auto-fill,minmax(128px,1fr));gap:10px 16px;margin:4px 0 12px}
.kvs .k{font-size:13px;color:var(--tx3)}
.kvs .v{font-size:16px;font-weight:600;margin-top:2px;font-variant-numeric:tabular-nums}
.plist .pi{display:flex;align-items:center;gap:8px;padding:9px 0;border-top:1px solid var(--bd);flex-wrap:wrap}
.plist .pi:first-child{border-top:0}
.plist .pt{flex:1;min-width:200px}
.plist .pt b{font-weight:600}
.plist .pt span{display:block;font-size:13.5px;color:var(--tx2);font-family:var(--m);margin-top:2px}
.smsum{padding:12px 16px;cursor:pointer;font-weight:600;font-size:15px}
#fmtdlg{background:var(--panel);color:var(--tx);border:1px solid var(--bd2);border-radius:var(--r);
  padding:0;width:min(680px,94vw);max-height:88vh}
#fmtdlg::backdrop{background:rgba(3,6,12,.62)}
#fmtdlg{max-width:min(460px,92vw)}
#setupdlg{background:var(--panel);color:var(--tx);border:1px solid var(--bd2);border-radius:var(--r);padding:0;width:min(620px,94vw)}
#setupdlg::backdrop{background:rgba(3,6,12,.62)}
.setupbody{padding:16px}
.steps{list-style:none;margin:0;padding:0;display:grid;gap:8px}
.steps li{display:grid;grid-template-columns:26px 1fr auto;gap:4px 12px;align-items:center;padding:10px 12px;border:1px solid var(--bd);border-radius:var(--r)}
.steps li .n{width:24px;height:24px;border-radius:50%;display:grid;place-items:center;font-size:13px;font-weight:600;background:var(--panel2);color:var(--tx2)}
.steps li.done .n{background:var(--ok);color:#06140d}
.steps li .t{font-weight:600}
.steps li .d{grid-column:2/-1;font-size:13.5px;color:var(--tx2)}
.steps li .x{grid-column:2/-1;display:flex;gap:8px;flex-wrap:wrap;align-items:center}
.steps li .x input,.steps li .x select{max-width:260px}
.setuppill{cursor:pointer;background:var(--accent);color:#fff;border:0}

.lgd{display:flex;flex-wrap:wrap;gap:5px;margin-top:8px}
.lgd span{font-size:12.5px;color:var(--tx2);display:inline-flex;align-items:center;gap:4px}
.lgd i{width:8px;height:8px;border-radius:2px;display:inline-block}
/* 編輯列 */
.ovbar{display:flex;align-items:center;gap:8px;margin-bottom:10px}
.ovbar .sp{flex:1}
.ovgrid{display:grid;gap:8px;grid-auto-rows:auto}
.ipbanner{display:flex;align-items:center;gap:12px;padding:10px 14px;margin:0 0 12px;border-radius:var(--r);
  background:var(--panel2);border:1px solid var(--warn);font-size:14.5px}
.ipbanner[hidden]{display:none}
.ipbanner span{flex:1;min-width:0;overflow-wrap:anywhere}
.ipbanner a{color:var(--tx);font-weight:600}
/* 監控全螢幕（2026-09-18 使用者要求，和本機 HDMI 同一件事）：分割畫面整塊放進螢幕，黑底。
   自訂的版面照用，格子縮到剛好放得下、置中（ovCells）。 */
.ovgrid:fullscreen{background:#000;padding:8px;width:100vw;height:100vh;box-sizing:border-box;
  overflow:auto;align-content:center}
.ovgrid:-webkit-full-screen{background:#000;padding:8px;width:100vw;height:100vh;box-sizing:border-box;
  overflow:auto;align-content:center}
.ovgrid .cam{cursor:pointer;transition:border-color .15s}
#ovcolseg{margin-right:4px}
.evcatn{margin-left:6px;background:var(--err);color:#fff;font:600 11px/1 var(--m);padding:2px 6px;border-radius:9px}
.ovcollbl{margin:0 2px 0 0;white-space:nowrap}
.ovbar .btn,#ovcolseg button{white-space:nowrap}
.ovgrid.noinfo .cam .badge,.ovgrid.noinfo .cam .lst,.ovgrid.noinfo .cam .ov{display:none}
@media(max-width:820px){.ovcollbl{display:none}.ovbar{flex-wrap:wrap;row-gap:8px}}
.ovgrid .cam:hover{border-color:var(--tx3)}
/* 跨格的磚不能留著 16:9，會被拉扁 —— 改成填滿自己的跨距。
   原本只寫了 2，拖到 3、4 格畫面上不會變（2026-10-12 使用者：「row 最多只有 2 嗎」）。
   列高由 ovRowH() 固定成「一格寬 × 9/16」：只有一格高的磚撐不起被高磚獨佔的那幾列，會被壓扁 */
.ovgrid .cam[data-h]:not([data-h="1"]){aspect-ratio:auto;height:100%}
.ovgrid .cam[data-w="2"]{grid-column:span 2}
.ovgrid .cam[data-w="3"]{grid-column:span 3}
.ovgrid .cam[data-w="4"]{grid-column:span 4}
.ovgrid .cam[data-h="2"]{grid-row:span 2}
.ovgrid .cam[data-h="3"]{grid-row:span 3}
.ovgrid .cam[data-h="4"]{grid-row:span 4}
/* 編輯中：外框、抓取游標、右下角的尺寸鈕 */
.ovgrid.edit .cam{border:1px dashed var(--bd2);cursor:grab;touch-action:none;user-select:none;-webkit-user-select:none}
.ovgrid.edit .cam.drag{cursor:grabbing}
.ovgrid.edit .cam.drag{opacity:.4}
.ovgrid.edit .cam.over{border-color:var(--accent);border-style:solid}
/* 右下角的拖曳控點。只在編輯模式出現。 */
.rsz{position:absolute;right:0;bottom:0;z-index:3;width:32px;height:32px;
     cursor:nwse-resize;touch-action:none;
     background:linear-gradient(135deg,transparent 50%,var(--accent) 50%);
     border-bottom-right-radius:var(--r)}
.rsz::after{content:"";position:absolute;right:5px;bottom:5px;width:7px;height:7px;
            border-right:2px solid #fff;border-bottom:2px solid #fff;opacity:.9}
.ovgrid:not(.edit) .rsz{display:none}
.ovgrid.edit .spk{display:none}   /* 編輯時喇叭剛好在尺寸鈕旁邊，藏起來免得按錯 */
/* 拖曳中：關掉過場動畫，否則每一格都會延遲追上，看起來像卡住 */
.ovgrid.sizing .cam{transition:none}
.szlbl{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);z-index:3;font:600 15px/1 var(--m);
       padding:8px 12px;border-radius:6px;background:rgba(8,11,18,.85);color:var(--vid-tx);display:none}
/* 尺寸（幾格寬 × 幾格高）只在拖右下角的那一格、拖的當下顯示。一直掛著會壓在右下角的解析度上，
   看起來像亂碼（2026-10-06 使用者：「有個非常奇怪的 1x2」） */
.ovgrid.edit .cam.rs .szlbl{display:block}
@media(max-width:980px){
  .ovwrap{grid-template-columns:1fr}
  .ovrail{position:static}
}
#chgrid .cam{cursor:pointer;transition:border-color .15s}
#chgrid .cam:hover{border-color:var(--tx3)}
#chgrid .empty-all{grid-column:1/-1;padding:40px 16px;text-align:center;color:var(--tx2)}
@media(max-width:820px){
  .pb{grid-template-columns:1fr}
  .pbside{position:static;display:block;height:auto;min-height:0}
  .pbcams ul{display:flex;overflow-x:auto;max-height:none}
  .pbev{display:none}
  .pbcams li a{white-space:nowrap}
}

@media(max-width:820px){
  /* 側欄要有自己的一列。原本沒指定列高，main 的 min-height:100vh 把整個視窗佔掉，
     側欄那一列被擠成 0px，選單置中在 0 高的列上、一半跑出畫面頂端 —— 手機上等於沒有導覽。 */
  body{grid-template-columns:1fr;grid-template-rows:auto 1fr}
  main{min-height:0}
  nav{min-height:auto;flex-direction:row;align-items:center;overflow-x:auto}
  .brand,.navfoot{display:none}
  nav ul{display:flex;padding:6px}
  .two{grid-template-columns:1fr}
  .subnav{position:static;flex-direction:row;overflow-x:auto;margin-bottom:2px}
}
