/* Smart Monitoring System — faithful to interface_styles.py palette */

:root {
  color-scheme: light;

  /* ── 淡色系（膠囊版）── */
  --bg:      #ffffff;   /* 純白底 */
  --panel:   #ffffff;   /* 卡片白底 */
  --panel-2: #f8f9fa;   /* 次要面板淺灰 */
  --border:  #e5e7eb;   /* 中性灰邊框 */
  --text:    #111827;   /* 近黑 */
  --muted:   #6b7280;   /* 中性灰 */
  --accent:  #2563eb;   /* 藍（物品搜尋 primary accent） */
  --accent-hover: #1d4ed8;
  --ok:      #16a34a;   /* 綠 */
  --warn:    #ea580c;   /* 橙 */
  --danger:  #dc2626;   /* 紅 */

  /* ── 模式色（文字 / 標題） ── */
  --mode-item:     #1d4ed8;   /* 藍 */
  --mode-leaving:  #0e7490;   /* 青 */
  --mode-cabinet:  #c2410c;   /* 橙 */
  --mode-security: #6d28d9;   /* 紫 */
  --mode-ia:       #be185d;   /* 洋紅（附錄 IB：原本與安全監控共用紫，撞色故改） */

  /* ── 模式主色（按鈕填充 / 邊框 / 高亮） ── */
  --mode-item-l:     #2563eb;   /* 藍 */
  --mode-leaving-l:  #0891b2;   /* 青 */
  --mode-cabinet-l:  #ea580c;   /* 橙 */
  --mode-security-l: #7c3aed;   /* 紫 */
  --mode-ia-l:       #db2777;   /* 洋紅（白字對比 4.59:1，過 WCAG AA） */

  --radius: 14px;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: "DM Sans", "Noto Sans TC", "PingFang TC", "Microsoft JhengHei",
               -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  line-height: 1.65;
}

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

h1, h2, h3, h4, h5 {
  color: var(--text);
  margin: 0 0 10px;
  font-weight: 600;
}
.muted { color: var(--muted); }
.small { font-size: 12px; }

/* ---------------- Buttons ---------------- */

button, .btn {
  background: var(--panel);
  color: var(--text);
  border: 1px solid var(--border);
  padding: 9px 16px;
  border-radius: 10px;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease, transform 0.08s ease, box-shadow 0.15s ease;
  box-shadow: 0 1px 4px rgba(0,0,0,.06);
}
button:hover, .btn:hover { border-color: var(--accent); box-shadow: 0 2px 10px rgba(0,0,0,.08); }

/* Press feedback: every button visibly "pushes in" on click so the user
   always knows the tap registered. */
button:active, .btn:active {
  transform: scale(0.95);
  box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.35);
}

/* Busy state for async actions (refresh buttons etc.). A spinner is shown
   before the label and the button is locked while its promise runs, so the
   user sees that something is happening. Toggled from JS via setButtonBusy(). */
button.is-busy, .btn.is-busy {
  pointer-events: none;
  opacity: 0.75;
}
button.is-busy::before, .btn.is-busy::before {
  content: "";
  display: inline-block;
  width: 0.85em;
  height: 0.85em;
  margin-right: 6px;
  vertical-align: -0.1em;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  animation: btn-spin 0.6s linear infinite;
}
@keyframes btn-spin { to { transform: rotate(360deg); } }

button.primary, .btn.primary {
  background: var(--accent);
  color: #fff;
  border-color: var(--accent);
}
button.primary:hover, .btn.primary:hover {
  background: var(--accent-hover);
  border-color: var(--accent-hover);
}

/* F5-3: Stop button uses Gradio's red "stop" variant. */
button.danger, .btn.danger {
  background: #e53935;
  color: #fff;
  border-color: #e53935;
}
button.danger:hover, .btn.danger:hover {
  background: #c62828;
  border-color: #c62828;
}

/* F5-2: Settings button highlighted blue while the settings pane is open. */
button.active, .btn.active {
  background: var(--accent);
  color: #fff;
  border-color: var(--accent);
}
button.active:hover, .btn.active:hover {
  background: var(--accent-hover);
  border-color: var(--accent-hover);
}

button.ghost {
  background: transparent;
  border: 1px solid var(--border);
}

button:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

button.small, .btn.small {
  padding: 5px 10px;
  font-size: 12px;
  font-weight: 500;
}

/* ---------------- Inputs ---------------- */

select, input[type="text"], input[type="number"], textarea {
  background: var(--bg);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 8px 10px;
  font-size: 14px;
  width: 100%;
  font-family: inherit;
}
select:focus, input[type="text"]:focus, input[type="number"]:focus, textarea:focus {
  border-color: var(--accent);
  outline: none;
}
textarea { resize: vertical; min-height: 60px; }
textarea[readonly], input[readonly] {
  background: var(--panel-2);
  color: var(--muted);
  cursor: default;
}
label.inline {
  display: inline-flex;
  align-items: center;
  font-weight: 600;
  margin-bottom: 0;
}
input[type="checkbox"] { accent-color: var(--accent); margin-right: 6px; }
input[type="range"] { accent-color: var(--accent); width: 100%; }

/* Localized file picker. The native <input type=file> button text ("Choose
   File" / "選擇檔案") is rendered by the BROWSER per its own locale and won't
   follow the app language (user: 臉部註冊選擇檔案沒跟著切換語言). So we visually
   hide the native control and drive it with a data-i18n <label> button (auto
   re-localized by applyI18n) + a JS-managed filename span. */
.file-ctrl { display: inline-flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.file-native {
  position: absolute !important; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0);
  white-space: nowrap; border: 0;
}
label.file-btn {
  display: inline-block; cursor: pointer; width: auto; margin: 0;
  background: var(--accent); color: #fff;
  border: 1px solid var(--accent); border-radius: 4px;
  padding: 6px 12px; font-size: 13px; font-weight: 600;
}
label.file-btn:hover { background: var(--accent-hover); border-color: var(--accent-hover); }
.file-name { font-size: 13px; color: var(--muted); word-break: break-all; }

label {
  display: block;
  font-weight: 600;
  color: var(--text);
  margin-bottom: 4px;
}

/* 附錄 HJ：hidden 屬性一定要真的把東西藏起來。
   瀏覽器內建的 [hidden]{display:none} 屬於 UA 樣式，任何作者樣式都贏過它 ——
   上面那條 `label{display:block}` 就是元凶：整個系統只要是 <label hidden> 都藏不
   住（dev 沒開放的「跌倒倒地不動」在別的帳號照樣出現，就是這樣來的）。之前是發現
   一個補一個（.status-banner[hidden]、.sh-right[hidden]…），治標不治本；這條放在
   最前面統一處理，之後任何元素設 hidden 都保證看不見。
   例外語法 hidden="until-found"（可被瀏覽器搜尋展開）本專案沒用到，一併蓋掉。 */
[hidden] { display: none !important; }

/* ---------------- Layout ---------------- */

.app {
  padding: 16px 20px 32px;
  max-width: 1600px;
  margin: 0 auto;
}

.header-row {
  /* Flex on ONE line (was a fixed 5-col grid that wrapped once the login
     feature added the logout button + username = 7 items). nowrap keeps every
     button parallel; the title shrinks/ellipsises first, and a very narrow
     window scrolls horizontally instead of wrapping. */
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  /* 附錄 GG（定案）：間隔固定 12px、按鈕維持「貼合文字」的自然寬度、整列靠左。
     多餘寬度就留在整列末端 —— 這是使用者在四種方案裡指定的那一種。
     走過的路：洞堆中間（原始，像壞掉）→ 留末端（GD）→ 攤到間隔（GE，間隔太寬）
     → 攤進按鈕（GF，按鈕太胖）→ 回到留末端。中文標籤比英文短約 300px（停止狀態
     再多約 150px），那塊空白一定要放在某處，末端是使用者選定的位置。 */
  gap: 12px;
  padding: 6px 0 14px;
  overflow-x: auto;
}
/* Title + 系統說明書 link share a left-aligned group so the manual link rides
   right next to the title instead of being flung to the button cluster.
   附錄 GH（定案）：`margin-right: auto` —— 標題群組靠左、控制列整組靠右、帳號名
   貼齊右緣，按鈕維持貼合文字的自然寬度、彼此 12px。這是使用者最終指定的長相。
   ⚠️ 已知取捨：這個 auto 會把整列的剩餘空間全部灌到標題群組與控制列之間。英文標籤
   比中文長約 300px（1500px 視窗：en 內容 1328px、zh 只有 1026px；停止狀態下運行中
   晶片隱藏再多約 150px），所以英文剩不多、看起來就是一整排，中文則會留下明顯的
   間隙。四種方案（洞留中間／留末端 GD／攤到間隔 GE／攤進按鈕 GF）都試過，
   「緊湊」與「滿版」在中文下無法同時成立，使用者選了這一種。
   （兩種語言在 1000/1280/1500px 下 scrollWidth 都等於 clientWidth，
   從來沒有東西被擠掉 —— 這自始至終是留白位置的問題，不是放不下。） */
.title-group {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 auto 0 0;
  min-width: 0;
  flex-shrink: 1;
}
.header-logo-img {
  width: 28px;
  height: 28px;
  border-radius: 6px;
  object-fit: cover;
  flex-shrink: 0;
}
.app-title {
  font-size: 22px;
  font-weight: 700;
  margin: 0;
  min-width: 0;         /* allow the title to shrink so buttons keep their row */
  flex-shrink: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Smaller-than-title pill link to the online manual. Subtle accent-tinted
   background, rounded, lifts slightly on hover. */
.manual-link {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
  color: var(--accent);
  padding: 5px 11px;
  border: 1px solid color-mix(in srgb, var(--accent) 45%, transparent);
  border-radius: 999px;
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  transition: background .15s ease, border-color .15s ease, color .15s ease, transform .15s ease;
}
.manual-link:hover {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
  transform: translateY(-1px);
}
/* Buttons + the account chip never shrink — they stay full-size, side by side.
   附錄 GG：按鈕**不**成長（GF 曾讓它們 flex-grow 去吃掉多餘寬度，結果按鈕過胖），
   維持貼合文字的自然寬度。 */
.header-row > .btn,
.header-row > button,
.header-row > .current-username { flex-shrink: 0; }

/* ── 附錄 GI：英文放不下整個標題的真正原因 ─────────────────────────────
   登入後這一列有 12 個元件（logo／標題／說明書＋引導兩顆藥丸／運行中晶片／
   計時器／5 顆按鈕／帳號名）。英文標籤合計比中文長約 300px，實測 vw < 1533px
   時 .app-title 就開始被 ellipsis 吃掉：1500px 差 32px、1280px 差 252px
   （「Smart Monitoring Sy…」）。GD–GH 五輪都沒抓到，是因為當時的預覽檔沒有
   帳號晶片、量測腳本也沒登入，剩餘寬度看起來永遠是正的 —— 使用者從第一則
   「以前英文版放得下全部，現在不行」講的就是這個溢出，不是留白位置。
   對策：分三段把寬度省回來；≥1600px 完全不動，維持使用者指定的原樣。 */
@media (max-width: 1600px) {
  .header-row { gap: 10px; }
  .header-row > .btn,
  .header-row > button { padding-left: 12px; padding-right: 12px; }
  .title-group { gap: 8px; }
  .manual-link,
  .guide-launch { padding-left: 9px; padding-right: 9px; }
}
/* 還是不夠：兩顆藥丸收成純 icon（title 屬性還在，滑過看得到全名）。 */
@media (max-width: 1470px) {
  #manual-link > span:not(.btn-ic),
  #guide-btn > .guide-btn-label { display: none; }
  .manual-link,
  .guide-launch { padding-left: 8px; padding-right: 8px; gap: 0; }
}
/* 再不夠就丟按鈕的 icon（文字比 icon 重要 —— 先犧牲圖示，字留著）。
   1300px 附近的英文卡在這一段：藥丸收完仍差 40–60px，拔掉 5 顆按鈕的 icon
   可省約 90px。 */
@media (max-width: 1350px) {
  .header-row > .btn > .btn-ic,
  #logout-btn > svg { display: none; }
  .header-row > .btn.has-ic { gap: 0; }
}
/* 最窄：反過來只留 icon，文字收掉（Start 例外，它是主要動作）。 */
@media (max-width: 1230px) {
  .header-row > .btn > .btn-ic { display: inline-flex; }
  #logout-btn > svg { display: inline; margin-right: 0 !important; }
  #ia-btn > span:not(.btn-ic),
  #phone-viewer-btn > span:not(.btn-ic),
  #settings-btn > span:not(.btn-ic),
  #logout-btn > span:not(.btn-ic) { display: none; }
}


.mode-row {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
  margin-bottom: 14px;
}
.mode-btn {
  padding: 14px;
  font-size: 15px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
}
.mode-title {
  margin: 0 0 14px;
  font-size: 18px;
}

.main-grid {
  display: grid;
  /* W-1: match the original Gradio column ratio (left scale=2 : right scale=8 ≈ 1:4). */
  grid-template-columns: 1fr 4fr;
  gap: 14px;
}
/* Intelligent-assistant mode: nudge the divider toward the social network so the
   assistant pane has a bit more room (left 1fr → 1.4fr). */
.main-grid.ia-mode { grid-template-columns: 1.4fr 4fr; }
@media (max-width: 1000px) {
  .main-grid, .main-grid.ia-mode { grid-template-columns: 1fr; }
  .mode-row { grid-template-columns: repeat(2, 1fr); }
}

/* ---------------- Panels ---------------- */

.panel {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px;
  color: var(--text);
  box-shadow: 0 2px 12px rgba(26,58,92,.07);
}
.panel + .panel { margin-top: 14px; }
.panel h3 {
  font-size: 15px;
  margin: 0 0 12px;
  color: var(--text);
}
.panel-inner {
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 12px;
  margin-top: 10px;
}

/* ── Collapsible mode-settings panels（四大模式設定收合，user request）──
   The section heading becomes a full-width .acc-head button; .acc-body uses
   the grid 0fr→1fr trick so it animates smoothly regardless of content
   height. Default = collapsed; .mode-panel.open expands. */
.mode-panel > .acc-head {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  background: transparent;
  border: none;
  padding: 6px 4px;
  margin: 0;
  font: inherit;
  font-size: 15px;
  font-weight: 700;
  color: var(--text);
  text-align: left;
  cursor: pointer;
  border-radius: 8px;
}
.mode-panel > .acc-head:hover { background: var(--panel-2); }
.mode-panel > .acc-head > svg { flex-shrink: 0; opacity: 0.65; }
.mode-panel > .acc-head .acc-chev {
  margin-left: auto;
  transition: transform 0.22s ease;
}
.mode-panel.open > .acc-head .acc-chev { transform: rotate(180deg); }
.acc-badge {
  flex: none;
  font-size: 11px;
  font-weight: 700;
  color: #fff;
  background: var(--accent);
  border-radius: 999px;
  padding: 1px 8px;
  min-width: 22px;
  text-align: center;
}
.acc-badge.zero { background: #9ca3af; }
/* Per-mode badge colours to match the mode-button palette. */
.mode-panel[data-panel="item_search"]      .acc-badge:not(.zero) { background: var(--mode-item-l); }
.mode-panel[data-panel="leaving_home"]     .acc-badge:not(.zero) { background: var(--mode-leaving-l); }
.mode-panel[data-panel="security_monitor"] .acc-badge:not(.zero) { background: var(--mode-security-l); }
.mode-panel > .acc-body {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.28s ease;
}
.mode-panel > .acc-body > .acc-inner {
  overflow: hidden;
  min-height: 0;
}
.mode-panel.open > .acc-body { grid-template-rows: 1fr; }
.mode-panel.open > .acc-body > .acc-inner { padding-top: 8px; }

.row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.row.tight { gap: 6px; }

.checklist-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 4px 12px;
  padding: 8px;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 4px;
  max-height: 220px;
  overflow-y: auto;
}
.settings-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}
@media (max-width: 900px) {
  .settings-grid { grid-template-columns: 1fr; }
}

/* #3: 方案3 — left-side category nav + right-side page (macOS Settings style). */
.settings-layout {
  display: block;
}
/* Category switcher sits on TOP as a horizontal bar (unified with the
   top-level Registration/Debug/System tabs). */
.settings-nav {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  gap: 6px;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 8px;
  margin-bottom: 16px;
}
.settings-cat {
  background: transparent;
  border: 0;
  color: var(--text);
  text-align: center;
  padding: 9px 14px;
  border-radius: 6px;
  cursor: pointer;
  font-weight: 600;
  font-size: 14px;
  white-space: nowrap;
}
.settings-cat:hover { background: var(--border); }
.settings-cat.active { background: var(--accent); color: #fff; }
.settings-pages { min-width: 0; }
.settings-page { display: none; }
.settings-page.active { display: block; }

/* Phone / narrow: keep the category bar as a horizontal scroller. */
@media (max-width: 760px) {
  .settings-nav {
    flex-wrap: nowrap;
    overflow-x: auto;
  }
}

.ia-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
}
@media (max-width: 900px) {
  .ia-grid { grid-template-columns: 1fr; }
}

/* 儀表板改版 Stage 5: Intelligent Assistant "at a glance" summary cards. */
.ia-summary-card {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin-top: 0;
}
.ia-summary-ic { font-size: 20px; line-height: 1.2; flex: none; }
.ia-summary-body { min-width: 0; }
.ia-summary-body > div:last-child {
  font-weight: 600;
  white-space: pre-line;
  word-break: break-word;
}

.network-wrap {
  background: #f0f4f8;
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 2px;            /* enlarge the graph: trim the empty border */
  margin-top: 6px;
}
.network-wrap svg {
  width: 100%;
  height: 460px;           /* bigger graph */
  display: block;
}

/* 附錄 FJ: 方案 C — 物品標籤 + 配對卡片 */
.ia-net-c { padding: 14px; }
.ia-c-h { font-size: 13px; font-weight: 700; color: var(--text); margin: 0 0 9px; }
.ia-net-c .ia-pc-list + .ia-c-h,
.ia-net-c .ia-chips + .ia-c-h { margin-top: 16px; }
.ia-chips { display: flex; flex-wrap: wrap; gap: 7px; }
.ia-chip {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--panel); border: 1px solid var(--border);
  border-radius: 999px; padding: 4px 11px; font-size: 12px; color: var(--text);
}
.ia-chip b { color: var(--accent-hover); font-weight: 700; }
.ia-chip-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--accent); flex: none; }
.ia-pc-list { display: flex; flex-direction: column; }
.ia-pc {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 0; border-bottom: 1px solid var(--border);
}
.ia-pc:last-child { border-bottom: none; }
.ia-pc-names { width: 128px; flex: none; font-size: 12px; font-weight: 600; color: var(--text); }
.ia-pc-meter { flex: 1; height: 8px; background: var(--panel); border: 1px solid var(--border); border-radius: 999px; overflow: hidden; }
.ia-pc-fill { height: 100%; background: linear-gradient(90deg, #93c5fd, var(--accent)); border-radius: 999px; }
.ia-pc-val { width: 30px; flex: none; text-align: right; font-weight: 700; color: var(--accent-hover); font-size: 12px; }
/* Caption box under the social-network graph: give it more vertical breathing
   room (top/bottom) so the hint text isn't cramped against the graph border. */
.network-wrap #ia-network-status {
  margin: 0;
  padding: 14px 10px;
  border-top: 1px solid var(--border);
  line-height: 1.6;
}
.network-wrap .node-circle { fill: #2563eb; stroke: #fff; stroke-width: 1.5; }
.network-wrap .node-label { fill: #111827; font-size: 12px; font-weight: 600; pointer-events: none; }
.network-wrap .edge { stroke: #93c5fd; stroke-opacity: 0.65; }
/* #9 hub-and-spoke: highlight the centre item and label each spoke's count. */
.network-wrap .node-center { fill: #ea580c; stroke: #fff; stroke-width: 2; }
.network-wrap .node-label-center { font-size: 14px; font-weight: 700; }
.network-wrap #ia-network-status { color: var(--muted); }
.network-wrap .edge-label {
  fill: #111827; font-size: 11px; font-weight: 700; pointer-events: none;
  paint-order: stroke; stroke: #f0f4f8; stroke-width: 3px; stroke-linejoin: round;
}

/* (User) judge-ready network: carry count INSIDE the node, co-occurrence count
   ON the line, plain-text legend above the graph. */
.net-legend {
  display: flex; flex-direction: column; gap: 5px;
  margin-top: 8px; padding: 9px 12px;
  background: var(--panel-2, #f5f7fa); border: 1px solid var(--border);
  border-radius: 8px; font-size: 12px; color: var(--muted); line-height: 1.5;
}
.net-legend-item { display: flex; align-items: center; gap: 7px; }
.net-legend-dot { border-radius: 50%; flex: none; }
.net-legend-dot.s { width: 8px;  height: 8px;  background: hsl(214,75%,66%); }
.net-legend-dot.l { width: 15px; height: 15px; background: hsl(214,75%,38%); margin-left: -3px; }
.net-legend-line {
  width: 26px; height: 0; flex: none;
  border-top: 4px solid #a8c8f0; border-radius: 2px; opacity: .9;
}
.network-wrap .node-count {
  fill: #fff; font-weight: 800; pointer-events: none;
  paint-order: stroke; stroke: rgba(0,0,0,.25); stroke-width: 2px; stroke-linejoin: round;
}
.network-wrap .edge-count-bg { fill: #f0f4f8; fill-opacity: .92; }
.network-wrap .edge-count {
  fill: #111827; font-size: 10px; font-weight: 700; pointer-events: none;
}

.thumb-row {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  margin-top: 8px;
}
.thumb-row img {
  width: 96px;
  height: 96px;
  object-fit: cover;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--panel-2);
}

.face-preview {
  display: block;
  width: 100%;
  max-width: 220px;
  max-height: 180px;
  margin-top: 8px;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--panel-2);
  object-fit: contain;
}
.face-preview:not([src]) { display: none; }

.checklist-grid label {
  font-weight: 500;
  margin: 0;
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 13px;
}

/* 附錄 GQ：勾選清單上「這一項有綁藍牙標籤、消失時會自動掃描」的小標。
   只有 emoji 沒有底色 —— 清單已經很密，再加一顆有色藥丸會讓人以為是狀態燈。 */
.checklist-grid label .ble-chip { font-size: 10.5px; line-height: 1; opacity: .8; cursor: help; }

/* 已綁定藍牙的物品一覽（物品註冊面板底下）。 */
.ble-table { width: 100%; border-collapse: collapse; margin-top: 10px; font-size: 12.5px; }
.ble-table th {
  text-align: left; font-size: 11px; font-weight: 600; color: var(--muted);
  padding: 4px 6px; border-bottom: 1px solid var(--border);
}
.ble-table td { padding: 5px 6px; border-bottom: 1px solid var(--border); vertical-align: middle; }
.ble-table td:last-child { text-align: right; }
.ble-table .ble-clear { padding: 2px 9px; font-size: 11.5px; border-radius: 7px; }

.field { margin-bottom: 12px; }
.field:last-child { margin-bottom: 0; }

/* Per-item detection confidence (Detection settings): one slider row per item.
   Scrollable so 27 items don't push the rest of the page off-screen. */
.item-conf-list {
  max-height: 420px;
  overflow-y: auto;
  margin: 10px 0;
  padding-right: 4px;
}
/* accordion wrapper */
.item-conf-accordion {
  border: 1px solid var(--border);
  border-radius: 6px;
  margin-bottom: 6px;
  overflow: hidden;
}
.item-conf-accordion:last-child { margin-bottom: 0; }
.item-conf-cat-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: 9px 12px;
  background: var(--border);
  border: none;
  cursor: pointer;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent, #3b82f6);
  text-align: left;
  user-select: none;
}
.item-conf-cat-header:hover { filter: brightness(0.94); }
.item-conf-cat-header::after {
  content: "▶";
  font-size: 9px;
  opacity: 0.55;
  flex-shrink: 0;
  transition: transform 0.18s;
}
.item-conf-cat-header.open::after { transform: rotate(90deg); }
.item-conf-cat-body { padding: 0 8px; }
.item-conf-cat-body[hidden] { display: none; }
.item-conf-row {
  display: grid;
  grid-template-columns: 1fr 130px 42px;
  align-items: center;
  gap: 10px;
  padding: 4px 0;
}
.item-conf-row + .item-conf-row { border-top: 1px solid var(--border); }
.item-conf-name { font-size: 14px; }
.item-conf-row input[type="range"] { width: 100%; }
.item-conf-val {
  font-variant-numeric: tabular-nums;
  text-align: right;
  color: var(--muted);
  font-size: 13px;
}

/* setloc (物品收納位置設定) */
.setloc-grid {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 10px;
  margin-bottom: 10px;
}
@media (max-width: 540px) { .setloc-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 360px) { .setloc-grid { grid-template-columns: 1fr; } }
.setloc-table { width: 100%; font-size: 13px; border-collapse: collapse; margin-top: 4px; }
.setloc-table td { padding: 4px 8px; border-bottom: 1px solid var(--border); }
.setloc-table tr:last-child td { border-bottom: none; }
.setloc-table td:first-child { font-weight: 500; min-width: 80px; }
.setloc-table td:last-child { color: var(--muted); }

/* Full-width block buttons (used in the Missing-Item Videos panel) */
.btn.block,
button.block { width: 100%; display: block; }

/* Missing-Item Videos panel mirrors Gradio's stacked layout:
   each control fills the full panel width, label above input. */
[data-panel="item_search"] .field > label {
  display: block;
  margin-bottom: 4px;
  font-size: 13px;
  color: var(--muted);
  font-weight: 600;
}
[data-panel="item_search"] .field > select,
[data-panel="item_search"] .field > video {
  width: 100%;
}

/* ---------------- Status indicator banner ---------------- */

.status-banner {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 12px;
  text-align: center;
  border-radius: 6px;
  font-weight: 700;
  font-size: 1.15em;
  margin-bottom: 12px;
  background: #9e9e9e;
  color: #fff;
}
.status-banner.ok     { background: #16a34a; color: #fff;    border: 1px solid #22c55e; }
.status-banner.warn   { background: #c2410c; color: #fff;    border: 1px solid #9a3412; }
.status-banner.danger { background: #b91c1c; color: #fff;    border: 1px solid #991b1b; }
.status-banner[hidden] { display: none !important; }

/* 方案 A — 警報 icon：白色半透明 squircle，danger 帶柔和 pulse 光暈 */
.status-banner .sb-ic {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: 9px;
  background: rgba(255, 255, 255, 0.2);
  border: 1.5px solid rgba(255, 255, 255, 0.45);
  flex-shrink: 0;
}
.status-banner .sb-ic svg { color: #fff; }
.status-banner .sb-text { line-height: 1.3; }
@keyframes sbPulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(255, 255, 255, 0); }
  50%      { box-shadow: 0 0 14px 2px rgba(255, 255, 255, 0.5); }
}
.status-banner.danger .sb-ic { animation: sbPulse 1.6s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) {
  .status-banner.danger .sb-ic { animation: none; }
}

#interaction-status {
  margin: -6px 0 10px;
  padding: 8px 12px;
  background: rgba(33,150,243,0.10);
  border-left: 3px solid var(--accent);
  border-radius: 4px;
  font-size: 13px;
  color: var(--text);
}
#interaction-status[hidden] { display: none !important; }

/* ---------------- Camera grid ---------------- */

.camera-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}
@media (max-width: 1100px) {
  .camera-grid { grid-template-columns: 1fr; }
}

.camera-card {
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 6px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
.camera-card .camera-label {
  padding: 8px 12px;
  font-size: 13px;
  color: #374151;
  border-bottom: 1px solid var(--border);
  background: rgba(0,0,0,0.04);
}
.camera-frame {
  position: relative;
  aspect-ratio: 16 / 9;
  background: #000;
}
.camera-frame video,
.camera-frame canvas,
.camera-frame img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}
.camera-frame video, .camera-frame img { object-fit: contain; }
.camera-frame canvas { pointer-events: none; }
.camera-placeholder {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--muted);
  font-size: 13px;
  text-align: center;
  padding: 12px;
}

/* ---------------- Cabinet capture / alert rows ---------------- */

.cabinet-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
  margin-top: 12px;
}
.cabinet-row[hidden] { display: none !important; }

/* Radar readout: large multi-line bearing/distance text under the canvas. */
.radar-readout {
  font-size: 16px !important;
  line-height: 1.55;
  color: var(--text);
  background: rgba(76,175,80,0.10);
  border-left: 4px solid var(--ok);
  padding: 10px 12px;
  margin: 10px 0 4px;
  white-space: normal;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-weight: 500;
}
.radar-readout strong {
  color: var(--ok);
  font-size: 17px;
  letter-spacing: 0.02em;
}
@media (max-width: 1100px) {
  .cabinet-row { grid-template-columns: 1fr; }
}
.cabinet-card {
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 6px;
  overflow: hidden;
  padding: 8px;
}
.cabinet-card .camera-label {
  margin: -8px -8px 6px;
  padding: 6px 10px;
  background: rgba(0,0,0,0.04);
  border-bottom: 1px solid var(--border);
  font-size: 13px;
  color: #374151;
}
.cabinet-frame {
  position: relative;
  aspect-ratio: 16 / 9;
  background: #000;
  border-radius: 4px;
  overflow: hidden;
}
.cabinet-frame canvas {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  display: block;
  cursor: crosshair;
}
.cabinet-card img {
  width: 100%;
  display: block;
  border-radius: 4px;
  background: #000;
  min-height: 120px;
  object-fit: contain;
}

/* ---------------- Pills / chips ---------------- */

.pill {
  display: inline-flex;
  align-items: center;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
}
.pill-idle    { background: #f3f4f6; color: #6b7280; }
.pill-running { background: #dcfce7; color: #15803d; }
.pill-error   { background: #fee2e2; color: #b91c1c; }

/* ---------------- Settings inline pane (replaces the old modal) ---------------- */

.settings-pane {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 18px 20px 24px;
  margin-top: 4px;
}
.settings-pane-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 12px;
}
.settings-pane-head h2 { margin: 0; font-size: 18px; }

/* ---------------- Tabs (used inside modal) ---------------- */

.tabs {
  display: flex;
  gap: 4px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 12px;
}
.tab {
  background: transparent;
  border: 0;
  color: var(--muted);
  padding: 8px 14px;
  border-bottom: 2px solid transparent;
  cursor: pointer;
  font-weight: 600;
}
.tab.active {
  background: var(--accent);
  color: #fff;                 /* white text on the blue active background */
  border-bottom-color: var(--accent);
  border-radius: 6px 6px 0 0;
}

.tab-content { display: none; }
.tab-content.active { display: block; }

/* ---------------- Hidden utility ---------------- */

.hidden { display: none !important; }

/* F5-4: Markdown-style output blocks (Gradio's gr.Markdown equivalent) used
   by the Intelligent Assistant panel — preserves newlines without the monospace
   <pre> look. */
.markdown-out {
  white-space: pre-wrap;
  background: var(--panel-2, #1a1a1a);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 8px 10px;
  min-height: 32px;
  font-size: 14px;
  line-height: 1.5;
  color: var(--text);
}

pre {
  background: #f3f4f6;
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 10px;
  font-size: 12px;
  color: #1f2937;
  max-height: 200px;
  overflow: auto;
  margin: 0;
}

/* ---------------- Debug panel (kept for /debug.html backwards compat) ---------------- */

.panel.legacy { max-width: 880px; margin: 24px auto; }
.panel.legacy h2 { color: var(--accent); }

/* ---------------- Alert feed (Phase E) ---------------- */

.alert-row {
  display: flex;
  gap: 8px;
  align-items: baseline;
  padding: 8px 10px;
  margin: 6px 0;
  background: var(--panel-2);
  border-left: 3px solid var(--accent);
  border-radius: 4px;
  font-size: 14px;
}
.alert-row.warn   { border-left-color: var(--warn);   }
.alert-row.danger { border-left-color: var(--danger); }
.alert-row.info   { border-left-color: var(--accent); }
.alert-row .alert-ts { color: var(--muted); font-size: 11px; margin-left: auto; }

/* ⑧ 警示日誌（inline）— phone web app alert-log 樣式：[時間][圓點][訊息] 一列列。
   資料來源與歷史中心相同（該帳號 localStorage），未點擊時就以日誌樣式呈現。 */
.sh-sub { font-size: 11px; font-weight: 400; margin-left: 2px; }
.alog { list-style: none; margin: 8px 0 0; padding: 0; max-height: 230px; overflow-y: auto; }
.alog li {
  display: flex; align-items: flex-start; gap: 8px;
  padding: 8px 4px; border-bottom: 1px solid var(--border);
  font-size: 13px; font-weight: 400;
}
.alog li:last-child { border-bottom: none; }
.alog-time {
  color: var(--muted); font-size: 11px; white-space: nowrap;
  padding-top: 2px; min-width: 64px; font-variant-numeric: tabular-nums;
}
.alog-dot { width: 8px; height: 8px; border-radius: 50%; margin-top: 5px; flex-shrink: 0; }
.alog-dot.danger { background: var(--danger); }
.alog-dot.warn   { background: var(--warn); }
.alog-dot.info   { background: var(--accent); }
.alog-dot.safe   { background: var(--ok); }
.alog-msg { flex: 1; line-height: 1.4; }
.alog-empty { padding: 18px 8px; color: var(--muted); font-size: 13px; text-align: center; border-bottom: none; justify-content: center; }

.pill-listening { background: #dcfce7; color: #15803d; }
.pill-warn      { background: #ffedd5; color: #9a3412; }

/* ---------------- Radar polar plot (Phase F) ---------------- */

.radar-wrap {
  background: #f0f4f8;
  border: 1px solid var(--border);
  border-radius: 6px;
  margin-top: 10px;
  aspect-ratio: 1 / 1;
  width: 100%;
  max-width: 360px;
  overflow: hidden;
  position: relative;
}
.radar-wrap canvas {
  width: 100%;
  height: 100%;
  display: block;
}


/* ---------------- D-19/D-20: debug-only UI ----------------
   Hide developer-facing widgets (fps counter, camera-info row,
   status-pill, alerts panel) unless the page is in debug mode.
   Enable debug mode by appending ?debug=1 to the URL or by
   setting localStorage.debugMode="1".                          */
body:not(.debug-mode) [data-debug="true"] {
  display: none !important;
}

/* ===== Phone viewer QR modal ===== */
.qr-modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.6);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  padding: 20px;
}
.qr-modal-overlay.hidden { display: none; }
.qr-modal {
  max-width: 360px;
  width: 100%;
}
.qr-modal #qr-target img,
.qr-modal #qr-target canvas { display: block; }

/* ---------------- Login gate (附錄 N.4) ---------------- */

.login-gate {
  position: fixed;
  inset: 0;
  z-index: 10000;
  display: flex;
  /* 附錄 KM：不能用 align-items:center。卡片比視窗高的時候（語言/地區那一步有三個
     下拉，約 673px，短視窗就會超過），置中的 flex 子項會往**兩邊**溢出，而上緣
     溢出的部分在 flex 容器裡是捲不到的 —— 標題和第一個下拉直接消失且無法觸及。
     改用 flex-start + 子項 margin:auto：塞得下時完全一樣是置中，塞不下時從頂端
     開始排並可以往下捲。gate 是 position:fixed，body 不會捲，所以捲軸必須在它身上。*/
  align-items: flex-start;
  justify-content: center;
  overflow-y: auto;
  padding: 20px;
  background: radial-gradient(1200px 600px at 50% -10%, #e8edf8, var(--bg));
}
.login-gate.hidden { display: none; }

.login-card {
  margin: auto;              /* 見上：塞得下＝置中，塞不下＝可捲 */
  width: 100%;
  max-width: 360px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 28px 26px 30px;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.14);
  text-align: center;
}
.login-logo { font-size: 42px; line-height: 1; }
.login-title { margin: 10px 0 16px; font-size: 22px; }
.login-checking { color: var(--muted); margin: 8px 0 0; }
.login-sub { color: var(--muted); margin: 0 0 14px; font-size: 13px; }

.login-input {
  width: 100%;
  padding: 11px 13px;
  margin-bottom: 12px;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text);
  font-size: 15px;
}
.login-input:focus { outline: none; border-color: var(--accent); }
.login-btn { width: 100%; padding: 12px; font-size: 15px; margin-top: 2px; }
.login-toggle { margin: 16px 0 0; font-size: 13px; color: var(--muted); }

.login-error {
  background: #fef2f2;
  color: #b91c1c;
  border-radius: 8px;
  padding: 9px 12px;
  margin-bottom: 12px;
  font-size: 13px;
  text-align: left;
}
.login-error.hidden { display: none; }

/* State machine: data-state toggles which pieces show. */
.login-gate[data-state="checking"] .login-form { display: none; }
.login-gate:not([data-state="checking"]) .login-checking { display: none; }
.login-gate[data-state="login"]    .login-when-register { display: none; }
.login-gate[data-state="register"] .login-when-login    { display: none; }

/* Folder-setup step (after sign-in): show only .login-folder, hide the form. */
.login-gate:not([data-state="folder"]) .login-folder { display: none; }
.login-gate[data-state="folder"] .login-form { display: none; }
.login-folder-skip { margin-top: 8px; background: transparent; }

/* Locale-setup step (附錄 KL) — first run of a brand-new account. Same state
   machine as the folder step: only .login-locale shows, and the card's generic
   title gives way to this step's "Welcome, <user>" heading. */
.login-gate:not([data-state="locale"]) .login-locale { display: none; }
.login-gate[data-state="locale"] .login-form { display: none; }
.login-gate[data-state="locale"] > .login-card > .login-title { display: none; }

/* Labelled select rows in the gate. .login-select deliberately mirrors
   .login-input above so the two never drift apart. */
.login-field { text-align: left; margin-bottom: 2px; }
.login-field > label {
  display: block;
  font-size: 12px;
  font-weight: 600;
  color: var(--muted);
  margin: 0 0 6px;
}
.login-select {
  width: 100%;
  padding: 11px 13px;
  margin-bottom: 12px;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text);
  font-size: 15px;
  font-family: inherit;
}
.login-select:focus { outline: none; border-color: var(--accent); }

.login-hint {
  display: flex;
  gap: 7px;
  align-items: flex-start;
  text-align: left;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 9px 11px;
  margin: 0 0 14px;
  font-size: 12px;
  color: var(--muted);
  line-height: 1.5;
}
.login-hint svg { flex: none; margin-top: 2px; }

/* ---------------- Header auth controls ---------------- */

.current-username {
  color: var(--muted);
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
}
.current-username:empty { display: none; }

/* ---------------- Role gating (附錄 N.4 / N.7b / BE / EU) ----------------
   Non-dev accounts never see the Debug tab or any [data-dev-only] block.
   Default (no role yet, i.e. pre-login behind the gate) also hides them, so
   nothing leaks on first paint.
   附錄 BE: the "contest" role (seeded sviif-contest judging account) ALSO gets
   the Debug tab, but inside it only [data-dev-only][data-contest-ok] blocks
   (account management, per-item confidence) — Developer Tools and the internal
   registration dump stay dev-only.
   附錄 EU: Telegram/Notifications settings 曾是 dev-only（合理，當時任何帳號按
   下「送測試訊息」都會廣播給全部訂閱者，暴露給一般帳號很危險）。附錄 EQ 做完
   帳號隔離後，一般帳號的廣播只會送到自己綁定的 chat——現在對一般帳號開放這頁
   才是必要的，否則「帳號名稱＋短代碼綁定」（附錄 ET）的入口本身就被 CSS 藏起來，
   一般使用者永遠找不到「綁定我的 Telegram」按鈕（先前巡檢重拍手冊截圖時發現）。
   附錄 GS：帳號管理搬到 設定 → System → 帳號 之後，Debug 分頁對 contest 帳號
   已經一格都不剩（剩下的全是 [data-dev-only] 且沒有 contest-ok），再讓它看得到
   就是一個點進去空白的分頁。所以 Debug 分頁改成純 dev。*/
body:not([data-role="dev"]) .tab[data-tab="debug"] { display: none !important; }
body:not([data-role="dev"]):not([data-role="contest"]) [data-dev-only] { display: none !important; }
body[data-role="contest"] [data-dev-only]:not([data-contest-ok]) { display: none !important; }

/* ---------------- Account management table (附錄 N.7b) ---------------- */

.users-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.users-table th, .users-table td {
  text-align: left;
  padding: 7px 8px;
  border-bottom: 1px solid var(--border);
}
.users-table th { color: var(--muted); font-weight: 600; }
.users-table .role-dev { color: var(--accent); font-weight: 600; }
.users-table .del-user-btn { padding: 4px 10px; font-size: 12px; }

/* ================================================================
   彩色主題系統 (v1.1.3 膠囊版)
   膠囊形模式按鈕 · 藍/青/橙/紫語義色 · 啟動綠暫停紅
   body[data-mode="…"] 由 switchMode() 設定。
   ================================================================ */

/* ── 0. SVG sprite icon 基底（<svg class="ic"><use href="#ic-…"/></svg>）── */
svg.ic {
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  flex-shrink: 0;
}
svg.ic-14 { width: 14px; height: 14px; }
svg.ic-16 { width: 16px; height: 16px; }
svg.ic-18 { width: 18px; height: 18px; }
svg.ic-20 { width: 20px; height: 20px; }

/* 按鈕內嵌 icon（header 按鈕 Start/助理/Viewer/設定、設定分頁）：
   icon 置於文字左側，顏色沿用 currentColor（啟用態白字 → icon 自動轉白）。 */
.btn.has-ic,
button.has-ic,
.settings-cat.has-ic {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
}
.btn-ic {
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
}

/* 帶 icon 的 section 標題（h2.sh、h3.sh）：icon 左置，顏色繼承 currentColor */
h2.sh,
h3.sh {
  display: flex;
  align-items: center;
  gap: 7px;
}
h2.sh > svg,
h3.sh > svg {
  flex-shrink: 0;
  opacity: 0.65;
}
/* Optional control docked to the right side of a .sh heading (e.g. the
   pose-skeleton overlay toggle in Live Monitoring). */
.sh-right {
  margin-left: auto;
  font-weight: 400;
  font-size: 13px;
  color: var(--muted);
  flex-shrink: 0;
}
/* label.inline sets display:inline-flex, which beats the [hidden] attribute's
   default display:none by specificity — without this override the toggle
   stays visible even when JS sets .hidden = true (user: 跌倒偵測關閉後右上角
   的按鈕要隱藏起來). Same pattern already fixed elsewhere in this file
   (.status-banner[hidden], .cabinet-row[hidden], etc). */
.sh-right[hidden] { display: none !important; }

/* ── 1. 模式按鈕：膠囊形 + 各自獨立啟用色 ── */
.mode-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  border-radius: 999px;
  border: 2px solid var(--border);
  background: #ffffff;
  color: #1f2937;
  box-shadow: none;
  transition: background 0.18s ease, border-color 0.18s ease, color 0.18s ease, transform 0.08s ease;
}
/* 未啟用 hover：邊框加深提示 */
.mode-btn:not(.primary):hover {
  border-color: #9ca3af;
  color: #111827;
  box-shadow: none;
}

/* ── 模式按鈕 icon 方塊（squircle）──
   未啟用：各模式語義色 tint 底 + 彩色 icon；啟用：白色半透明 + 白 icon。 */
.mode-btn .mb-ic {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: 6px;
  flex-shrink: 0;
}
.mode-btn[data-mode="item_search"]      .mb-ic { background: rgba(37, 99, 235, 0.12);  color: var(--mode-item-l); }
.mode-btn[data-mode="leaving_home"]     .mb-ic { background: rgba(8, 145, 178, 0.12);  color: var(--mode-leaving-l); }
.mode-btn[data-mode="cabinet_alert"]    .mb-ic { background: rgba(234, 88, 12, 0.12);  color: var(--mode-cabinet-l); }
.mode-btn[data-mode="security_monitor"] .mb-ic { background: rgba(124, 58, 237, 0.12); color: var(--mode-security-l); }
/* 啟用時 icon 方塊轉白透明、icon 轉白，疊在實心模式色上 */
.mode-btn.primary .mb-ic { background: rgba(255, 255, 255, 0.22); color: #fff; }

/* 啟用時各模式實心填色（覆蓋 button.primary 的通用藍色） */
.mode-btn[data-mode="item_search"].primary {
  background: #2563eb; border-color: #2563eb; color: #fff;
  box-shadow: 0 0 0 3px rgba(37,99,235,0.22);
}
.mode-btn[data-mode="leaving_home"].primary {
  background: #0891b2; border-color: #0891b2; color: #fff;
  box-shadow: 0 0 0 3px rgba(8,145,178,0.22);
}
.mode-btn[data-mode="cabinet_alert"].primary {
  background: #ea580c; border-color: #ea580c; color: #fff;
  box-shadow: 0 0 0 3px rgba(234,88,12,0.22);
}
.mode-btn[data-mode="security_monitor"].primary {
  background: #7c3aed; border-color: #7c3aed; color: #fff;
  box-shadow: 0 0 0 3px rgba(124,58,237,0.22);
}

/* 啟用 hover（稍深） */
.mode-btn[data-mode="item_search"].primary:hover     { background: #1d4ed8; border-color: #1d4ed8; }
.mode-btn[data-mode="leaving_home"].primary:hover    { background: #0e7490; border-color: #0e7490; }
.mode-btn[data-mode="cabinet_alert"].primary:hover   { background: #c2410c; border-color: #c2410c; }
.mode-btn[data-mode="security_monitor"].primary:hover{ background: #6d28d9; border-color: #6d28d9; }

/* ── 2. 模式列：透明底（膠囊直接浮在白頁面上） ── */
.mode-row {
  background: transparent;
  border: none;
  border-radius: 0;
  padding: 0 0 14px;
  margin-bottom: 0;
  gap: 10px;
}

/* ── 3. 模式標題顏色跟著切換 ── */
.mode-title { transition: color 0.25s ease; }
body[data-mode="item_search"]           .mode-title { color: var(--mode-item-l); }
body[data-mode="leaving_home"]          .mode-title { color: var(--mode-leaving-l); }
body[data-mode="cabinet_alert"]         .mode-title { color: var(--mode-cabinet-l); }
body[data-mode="security_monitor"]      .mode-title { color: var(--mode-security-l); }
body[data-mode="intelligent_assistant"] .mode-title { color: var(--mode-ia-l); }

/* ── 4. 左側設定面板頂邊：3px 彩條 ── */
.mode-panel[data-panel="item_search"]           { border-top: 3px solid var(--mode-item-l); }
.mode-panel[data-panel="leaving_home"]          { border-top: 3px solid var(--mode-leaving-l); }
.mode-panel[data-panel="cabinet_alert"]         { border-top: 3px solid var(--mode-cabinet-l); }
.mode-panel[data-panel="security_monitor"]      { border-top: 3px solid var(--mode-security-l); }
.mode-panel[data-panel="intelligent_assistant"] { border-top: 3px solid var(--mode-ia-l); }

/* ── 5. 標題列底線跟著模式切換（平滑過渡） ── */
.header-row {
  border-bottom: 2px solid var(--border);
  transition: border-bottom-color 0.3s ease;
  margin-bottom: 10px;
  padding-bottom: 10px;
}
body[data-mode="item_search"]           .header-row { border-bottom-color: color-mix(in srgb, var(--mode-item-l) 60%, var(--border)); }
body[data-mode="leaving_home"]          .header-row { border-bottom-color: color-mix(in srgb, var(--mode-leaving-l) 60%, var(--border)); }
body[data-mode="cabinet_alert"]         .header-row { border-bottom-color: color-mix(in srgb, var(--mode-cabinet-l) 60%, var(--border)); }
body[data-mode="security_monitor"]      .header-row { border-bottom-color: color-mix(in srgb, var(--mode-security-l) 60%, var(--border)); }
body[data-mode="intelligent_assistant"] .header-row { border-bottom-color: color-mix(in srgb, var(--mode-ia-l) 60%, var(--border)); }

/* ── 6. 相機卡左邊彩條 ── */
body[data-mode="item_search"]           .camera-card { border-left: 3px solid var(--mode-item-l); }
body[data-mode="leaving_home"]          .camera-card { border-left: 3px solid var(--mode-leaving-l); }
body[data-mode="cabinet_alert"]         .camera-card { border-left: 3px solid var(--mode-cabinet-l); }
body[data-mode="security_monitor"]      .camera-card { border-left: 3px solid var(--mode-security-l); }
body[data-mode="intelligent_assistant"] .camera-card { border-left: 3px solid var(--mode-ia-l); }

/* ── 7. 相機 label 背景微染色 ── */
body[data-mode="item_search"]           .camera-label { background: rgba(37,99,235,.08); }
body[data-mode="leaving_home"]          .camera-label { background: rgba(8,145,178,.08); }
body[data-mode="cabinet_alert"]         .camera-label { background: rgba(234,88,12,.08); }
body[data-mode="security_monitor"]      .camera-label { background: rgba(124,58,237,.08); }
body[data-mode="intelligent_assistant"] .camera-label { background: rgba(219,39,119,.08); }

/* ── 8. 主體面板 h3 標題：左色條 ── */
.panel > h3 {
  padding-left: 10px;
  border-left: 3px solid var(--accent);
  margin-bottom: 14px;
}
body[data-mode="item_search"]           .panel > h3 { border-left-color: var(--mode-item-l); }
body[data-mode="leaving_home"]          .panel > h3 { border-left-color: var(--mode-leaving-l); }
body[data-mode="cabinet_alert"]         .panel > h3 { border-left-color: var(--mode-cabinet-l); }
body[data-mode="security_monitor"]      .panel > h3 { border-left-color: var(--mode-security-l); }
body[data-mode="intelligent_assistant"] .panel > h3 { border-left-color: var(--mode-ia-l); }

/* ── 9. Start 按鈕：啟動=綠，暫停=紅 ── */
#start-btn:not([data-state="running"]) {
  background: #16a34a !important;
  border-color: #22c55e !important;
  color: #fff !important;
  box-shadow: 0 0 0 3px rgba(22,163,74,0.22) !important;
}
#start-btn:not([data-state="running"]):hover {
  background: #15803d !important;
  border-color: #16a34a !important;
  color: #fff !important;
}
#start-btn[data-state="running"] {
  background: #dc2626 !important;
  border-color: #ef4444 !important;
  color: #fff !important;
  box-shadow: 0 0 0 3px rgba(220,38,38,0.22) !important;
}
#start-btn[data-state="running"]:hover {
  background: #b91c1c !important;
  border-color: #dc2626 !important;
  color: #fff !important;
}

/* ── 10. 右上角按鈕激活色（各自獨立）— 選中實心，未選中無彩色框 ── */
/* 助理（ia-btn）→ 洋紅（附錄 IB） */
#ia-btn.primary {
  background: var(--mode-ia-l);
  border-color: var(--mode-ia-l);
  color: #fff;
  box-shadow: 0 0 0 3px rgba(219,39,119,0.22);
}
#ia-btn.primary:hover {
  background: var(--mode-ia);
  border-color: var(--mode-ia);
}
/* 手機（phone-viewer-btn）→ 藍 */
#phone-viewer-btn.active {
  background: #2563eb;
  border-color: #2563eb;
  color: #fff;
  box-shadow: 0 0 0 3px rgba(37,99,235,0.22);
}
#phone-viewer-btn.active:hover {
  background: #1d4ed8;
  border-color: #1d4ed8;
}
/* 設定（settings-btn）→ 橙 */
#settings-btn.active {
  background: #ea580c;
  border-color: #ea580c;
  color: #fff;
  box-shadow: 0 0 0 3px rgba(234,88,12,0.22);
}
#settings-btn.active:hover {
  background: #c2410c;
  border-color: #c2410c;
}

/* ── 11. 警報條（淡色系） ── */
.alert-row.danger { background: #fef2f2; border-left-color: var(--danger); }
.alert-row.warn   { background: #fff7ed; border-left-color: var(--warn); }

/* ── 12. 狀態 pill（淡色系，覆蓋上方定義） ── */
.pill-running { background: #dcfce7; color: #15803d; }
.pill-error   { background: #fee2e2; color: #b91c1c; }

/* ── 13. Header 即時狀態列（提案 4）── */
.header-status {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}
.header-status.hidden { display: none !important; }

.status-chip-running {
  display: flex;
  align-items: center;
  gap: 5px;
  background: #f0fdf4;
  border: 1px solid #86efac;
  border-radius: 20px;
  padding: 3px 10px;
  font-size: 12px;
  font-weight: 600;
  color: #15803d;
  white-space: nowrap;
}
.status-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #22c55e;
  flex-shrink: 0;
  animation: status-pulse 2s ease-in-out infinite;
}
@keyframes status-pulse { 0%,100%{opacity:1} 50%{opacity:.35} }

.header-runtime {
  font-size: 12px;
  font-weight: 600;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  letter-spacing: .03em;
  white-space: nowrap;
}

/* ── 登入頁 logo 圖片 ── */
.login-logo-img {
  width: 80px;
  height: 80px;
  border-radius: 16px;
  object-fit: cover;
}

/* ── Option B：右上角三顆功能按鈕 — 未選中淺灰底，選中實心色 ── */
#ia-btn:not(.primary),
#phone-viewer-btn:not(.active),
#settings-btn:not(.active) {
  background: #ffffff;
  border-color: #d1d5db;
}
#ia-btn:not(.primary):hover,
#phone-viewer-btn:not(.active):hover,
#settings-btn:not(.active):hover {
  background: #e5e7eb;
  border-color: #9ca3af;
}

/* ================================================================
   深色模式 (v1.2.1) — <html data-theme="dark">
   淺色為預設（上方規則完全不動）。深色重新定義中性色變數，讓所有
   走 var(--bg/panel/border/text/muted) 的元件自動轉深；再針對 v1.1.x
   硬寫的淺色面板逐一覆蓋。還原改版前 (v0.9.9) 的深色底色風格。
   模式語義色（藍/青/橙/紫/綠/紅）在深底上對比足夠，維持不變。
   ================================================================ */
html[data-theme="dark"] {
  color-scheme: dark;
  --bg:      #1a1a1a;
  --panel:   #2d2d2d;
  --panel-2: #242424;
  --border:  #444444;
  --text:    #e0e0e0;
  --muted:   #a0a0a0;
}

/* 模式按鈕未選中：深底淺字（覆蓋 v1.1.8 的白底黑字） */
[data-theme="dark"] .mode-btn {
  background: #2d2d2d;
  color: #e0e0e0;
}
[data-theme="dark"] .mode-btn:not(.primary):hover {
  border-color: #666;
  color: #ffffff;
}

/* 右上角三顆功能按鈕未選中：深灰底（覆蓋 Option B 的 #f3f4f6） */
[data-theme="dark"] #ia-btn:not(.primary),
[data-theme="dark"] #phone-viewer-btn:not(.active),
[data-theme="dark"] #settings-btn:not(.active) {
  background: #2d2d2d;
  border-color: #555;
}
[data-theme="dark"] #ia-btn:not(.primary):hover,
[data-theme="dark"] #phone-viewer-btn:not(.active):hover,
[data-theme="dark"] #settings-btn:not(.active):hover {
  background: #3a3a3a;
  border-color: #777;
}

/* 相機 label 文字：淺色（覆蓋 v1.1.9 的 #374151） */
[data-theme="dark"] .camera-card .camera-label,
[data-theme="dark"] .cabinet-card .camera-label {
  color: #d0d0d0;
  background: rgba(255,255,255,0.05);
}

/* pill-idle / pre 程式碼塊 */
[data-theme="dark"] .pill-idle { background: #3a3a3a; color: #a0a0a0; }
[data-theme="dark"] pre        { background: #242424; color: #d0d0d0; }

/* 社交網路圖 + 雷達圖底色（覆蓋 #f0f4f8） */
[data-theme="dark"] .network-wrap,
[data-theme="dark"] .radar-wrap { background: #202830; }
[data-theme="dark"] .network-wrap .node-label  { fill: #e0e0e0; }
[data-theme="dark"] .network-wrap .edge-label  { fill: #e0e0e0; stroke: #202830; }
[data-theme="dark"] .network-wrap .edge-count-bg { fill: #202830; }
[data-theme="dark"] .network-wrap .edge-count    { fill: #e0e0e0; }

/* Header「運行中」chip：深綠底 */
[data-theme="dark"] .status-chip-running {
  background: #0f2a18;
  border-color: #1f5132;
  color: #4ade80;
}

/* 警報條：深色染底（覆蓋淡粉/淡橙） */
[data-theme="dark"] .alert-row.danger { background: rgba(220,38,38,0.16); }
[data-theme="dark"] .alert-row.warn   { background: rgba(234,88,12,0.16); }

/* 狀態 pill：深色染底 */
[data-theme="dark"] .pill-running   { background: #0f2a18; color: #4ade80; }
[data-theme="dark"] .pill-error     { background: #3a1515; color: #f87171; }
[data-theme="dark"] .pill-listening { background: #0f2a18; color: #4ade80; }
[data-theme="dark"] .pill-warn      { background: #3a2410; color: #fdba74; }

/* 登入頁背景漸層（覆蓋淺藍 #e8edf8） */
[data-theme="dark"] .login-gate {
  background: radial-gradient(1200px 600px at 50% -10%, #20262e, var(--bg));
}
[data-theme="dark"] .login-error {
  background: #3a1515;
  color: #f87171;
}

/* 互動狀態提示框 */
[data-theme="dark"] #interaction-status { background: rgba(33,150,243,0.14); }


/* ===== Home Map (家中地圖) — visual zone/pin config, ported from approved preview ===== */
/* ---- Step 1: upload & name zones ---- */
  #home-map-panel .add-zone-row{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin-bottom:14px;
    background:var(--panel-2);border:1px dashed var(--border);border-radius:10px;padding:10px;}
  #home-map-panel .add-zone-row input[type="text"]{flex:1 1 140px;padding:8px 10px;border:1px solid var(--border);
    border-radius:8px;font-size:13px;font-family:inherit;}

  #home-map-panel .zone-gallery{display:grid;grid-template-columns:repeat(auto-fill,minmax(120px,1fr));gap:12px;}
  #home-map-panel .zone-card{border:1.5px solid var(--border);border-radius:12px;overflow:hidden;background:var(--panel);
    position:relative;transition:border-color .15s;}
  #home-map-panel .zone-card.active{border-color:var(--accent);box-shadow:0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent);}
  #home-map-panel .zone-card .thumb{width:100%;aspect-ratio:4/3;object-fit:cover;display:block;background:var(--panel-2);}
  #home-map-panel .zone-card .meta{padding:7px 8px;}
  #home-map-panel .zone-card .name{font-size:12.5px;font-weight:700;border:none;background:transparent;width:100%;
    padding:0;font-family:inherit;color:var(--text);}
  #home-map-panel .zone-card .name:focus{outline:1px solid var(--accent);border-radius:4px;}
  #home-map-panel .zone-card .placeholder-tag{position:absolute;top:6px;left:6px;background:rgba(0,0,0,.55);color:#fff;
    font-size:9.5px;padding:1px 6px;border-radius:999px;}
  #home-map-panel .zone-card .rm{position:absolute;top:6px;right:6px;width:20px;height:20px;border-radius:50%;
    background:rgba(220,38,38,.9);color:#fff;font-size:12px;line-height:20px;text-align:center;cursor:pointer;}
  #home-map-panel .zone-card .pick-btn{width:100%;border:none;border-top:1px solid var(--border);background:var(--panel-2);
    color:var(--accent);font-size:11.5px;font-weight:700;padding:5px 0;cursor:pointer;}
  #home-map-panel .zone-card.active .pick-btn{background:var(--accent);color:#fff;}

  /* ---- Step 2: pin canvas ---- */
  #home-map-panel .zone-tabs{display:flex;gap:8px;overflow-x:auto;padding-bottom:8px;margin-bottom:8px;}
  #home-map-panel .zone-tab{flex:0 0 auto;width:56px;height:42px;border-radius:8px;overflow:hidden;cursor:pointer;
    border:2px solid transparent;opacity:.6;}
  #home-map-panel .zone-tab img{width:100%;height:100%;object-fit:cover;display:block;}
  #home-map-panel .zone-tab.active{border-color:var(--accent);opacity:1;}

  #home-map-panel .photo-shell{position:relative;width:100%;aspect-ratio:16/7;border-radius:12px;overflow:hidden;
    border:1px solid var(--border);background:var(--panel-2);user-select:none;touch-action:none;}
  #home-map-panel .photo-shell img{width:100%;height:100%;object-fit:cover;display:block;pointer-events:none;}
  #home-map-panel .no-zone-hint{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
    color:var(--muted);font-size:13px;text-align:center;padding:0 30px;}

  #home-map-panel .pin-wrap{position:absolute;transform:translate(-50%,-50%);display:flex;flex-direction:column;
    align-items:center;gap:3px;touch-action:none;z-index:2;}
  #home-map-panel .pin-dot{position:relative;width:30px;height:30px;border-radius:50%;
    display:flex;align-items:center;justify-content:center;font-size:15px;cursor:grab;
    border:2px solid #fff;box-shadow:0 2px 6px rgba(0,0,0,.35);touch-action:none;}
  #home-map-panel .pin-dot:active{cursor:grabbing;}
  #home-map-panel .pin-dot.kind-camera{background:var(--accent);}
  #home-map-panel .pin-dot.kind-ble{background:#7c3aed;}
  #home-map-panel .pin-dot.kind-item{background:#fff;border-color:#0e7490;}
  #home-map-panel .pin-dot.kind-item.auto{border-style:dashed;border-color:var(--warn);}
  #home-map-panel .pin-tooltip{position:absolute;bottom:calc(100% + 4px);left:50%;transform:translateX(-50%);
    background:rgba(17,24,39,.92);color:#fff;font-size:10.5px;padding:2px 7px;border-radius:6px;
    white-space:nowrap;pointer-events:none;opacity:0;transition:opacity .1s;}
  #home-map-panel .pin-dot:hover .pin-tooltip{opacity:1;}
  #home-map-panel .pin-info{font-size:9.5px;font-weight:700;padding:2px 7px;border-radius:999px;
    white-space:nowrap;box-shadow:0 1px 3px rgba(0,0,0,.25);}
  #home-map-panel .pin-info.auto{background:#fffbeb;color:#92400e;border:1px solid #fde68a;}
  #home-map-panel .pin-info.manual{background:#ecfeff;color:#0e7490;border:1px solid #a5f3fc;}
  #home-map-panel .pin-dot img.custom-icon{width:76%;height:76%;object-fit:cover;border-radius:50%;pointer-events:none;}

  #home-map-panel .pin-editor{width:154px;background:var(--panel);border:1px solid var(--border);border-radius:10px;
    padding:9px;box-shadow:0 6px 18px rgba(0,0,0,.2);display:flex;flex-direction:column;gap:7px;
    font-size:11px;z-index:20;touch-action:auto;}
  #home-map-panel .pin-editor .row{display:flex;align-items:center;gap:6px;margin-bottom:0;}
  #home-map-panel .pin-editor .row > span.lab{flex:0 0 auto;color:var(--muted);width:30px;}
  #home-map-panel .pin-editor input[type="range"]{flex:1;accent-color:var(--accent);}
  #home-map-panel .pin-editor .mini-btn{flex:1;padding:4px 2px;border:1px solid var(--border);border-radius:6px;
    background:var(--panel-2);cursor:pointer;text-align:center;font-size:10.5px;position:relative;overflow:hidden;}
  #home-map-panel .pin-editor .mini-btn:hover{border-color:var(--accent);}
  #home-map-panel .pin-editor .mini-btn.danger{color:var(--danger);border-color:#fecaca;background:#fef2f2;}
  #home-map-panel .pin-editor .mini-btn input[type="file"]{position:absolute;inset:0;opacity:0;cursor:pointer;}

  #home-map-panel .palette-group{margin-top:12px;}
  #home-map-panel .palette-group-h{font-size:11.5px;font-weight:700;color:var(--muted);margin-bottom:4px;
    display:flex;align-items:center;gap:6px;}
  #home-map-panel .palette-group-h .sw{width:9px;height:9px;border-radius:50%;}
  #home-map-panel .palette{display:flex;gap:10px;overflow-x:auto;padding:2px 2px 8px;}
  #home-map-panel .chip{flex:0 0 auto;display:flex;flex-direction:column;align-items:center;gap:4px;
    width:64px;padding:7px 4px;border-radius:12px;border:1px solid var(--border);
    background:var(--panel);cursor:grab;touch-action:none;}
  #home-map-panel .chip:active{cursor:grabbing;}
  #home-map-panel .chip .ic{font-size:20px;}
  #home-map-panel .chip .lbl{font-size:10px;color:var(--text);text-align:center;line-height:1.15;}
  #home-map-panel .chip.dragging-source{opacity:.35;}

  .drag-ghost{position:fixed;pointer-events:none;z-index:999;width:34px;height:34px;border-radius:50%;
    display:flex;align-items:center;justify-content:center;font-size:16px;color:#fff;
    transform:translate(-50%,-50%);box-shadow:0 4px 14px rgba(0,0,0,.3);opacity:.9;}

  #home-map-panel .tag{font-size:10.5px;padding:1px 7px;border-radius:999px;font-weight:600;white-space:nowrap;}
  #home-map-panel .tag.cam{background:color-mix(in srgb, var(--accent) 15%, white);color:var(--accent);}
  #home-map-panel .tag.ble{background:color-mix(in srgb, #7c3aed 15%, white);color:#7c3aed;}
  #home-map-panel .tag.none{background:var(--panel-2);color:var(--muted);}
  #home-map-panel .empty-row{color:var(--muted);font-style:italic;padding:10px 2px;}

  #home-map-panel .callout{display:flex;gap:10px;background:#eef2ff;border:1px solid #c7d2fe;border-radius:10px;
    padding:10px 12px;font-size:12.5px;color:#3730a3;margin-top:10px;}
  #home-map-panel .callout .em{font-size:18px;}


/* Home Map jump-link highlight (triggered from the Intelligent Assistant panel) */
@keyframes hmFlashHighlight {
  0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 55%, transparent); }
  100% { box-shadow: 0 0 0 14px transparent; }
}
#home-map-panel.flash-highlight { animation: hmFlashHighlight 1.3s ease-out 2; border-radius: var(--radius); }

/* ================= 儀錶板改版（dashboard tools） ================= */
/* Per-mode segmented tool bar in the Live Monitoring panel. Buttons are
   hidden unless the active mode (body[data-mode]) matches their data-seg. */
.seg-tools {
  display: flex;
  border: 1px solid #cfe0ff;
  border-radius: 11px;
  overflow: hidden;
  margin-bottom: 12px;
}
.seg-btn {
  flex: 1;
  display: none;                       /* shown per mode below */
  align-items: center;
  justify-content: center;
  gap: 6px;
  border: none;
  border-right: 1px solid #e5eaf5;
  background: #fff;
  color: var(--accent);
  font: inherit;
  font-size: 13.5px;
  font-weight: 700;
  padding: 11px 6px;
  cursor: pointer;
}
.seg-btn:last-child { border-right: none; }
.seg-btn:hover { background: #eaf1ff; }
.seg-btn.active { background: linear-gradient(135deg, #1d4ed8, #2563eb); color: #fff; }
.seg-btn .seg-em { font-size: 16px; }
/* data-seg is a space-separated list of modes the button belongs to. */
body[data-mode="item_search"]      .seg-btn[data-seg~="item_search"],
body[data-mode="leaving_home"]     .seg-btn[data-seg~="leaving_home"],
body[data-mode="cabinet_alert"]    .seg-btn[data-seg~="cabinet_alert"],
body[data-mode="security_monitor"] .seg-btn[data-seg~="security_monitor"] { display: inline-flex; }
/* JS-hidden buttons (e.g. #seg-dz until the danger-zone feature is ticked)
   must beat the display rules above. */
.seg-btn[hidden] { display: none !important; }
/* 附錄 FK: JS 依「指定人臉」政策動態顯示臉部註冊按鈕（凌駕 data-seg 的每模式規則）。 */
.seg-btn.seg-force { display: inline-flex !important; }
.seg-btn.seg-force[hidden] { display: none !important; }

/* Per-mode dashboard extras (outing dropdown / security feature checkboxes). */
.dash-extra { display: none; align-items: center; gap: 10px; margin-bottom: 12px; flex-wrap: wrap; }
.dash-extra-lb { font-size: 13px; font-weight: 700; color: var(--muted); flex: none; }
.dash-extra select { flex: 1; min-width: 140px; }
body[data-mode="leaving_home"]     .dash-extra[data-dash-mode="leaving_home"],
body[data-mode="security_monitor"] .dash-extra[data-dash-mode="security_monitor"],
body[data-mode="item_search"]      .dash-extra[data-dash-mode="item_search"] { display: flex; }
/* 附錄 JZ：常用問句那一區是上下堆疊的（兩個下拉一列、輸入框一列、照著唸一列），
   不是 .dash-extra 預設的單列水平排。`.dash-extra select { flex: 1 }` 也必須
   還原，否則物品下拉會被拉成跟問句下拉一樣寬。 */
.dash-extra.dash-extra-col { flex-direction: column; align-items: stretch; gap: 0; }
.dash-extra.dash-extra-col select { flex: none; min-width: 0; }

/* ══ 附錄 KA：AI 狀態膠囊（方案 E 柔光浮起）═══════════════════════════════
   聆聽中＝洋紅 #db2777（智慧助理色）· 思考中＝主藍 #2563eb · 辨識中＝青綠 #0891b2
   三個色都在 DESIGN.md 現有色表內，沒有新增色。
   閒置時 .aistat-line 高度為 0 —— 膠囊 hidden 時不留空隙，工具條不會被往下推。 */
.aistat-line { display: flex; align-items: center; }
.aistat-line:has(.aistat[hidden]) { margin: 0; }
.aistat-line:not(:has(.aistat[hidden])) { margin-bottom: 10px; }
.aistat {
  display: inline-flex; align-items: center; gap: 8px;
  height: 30px; padding: 0 13px 0 11px; border-radius: 999px;
  font-size: 12.5px; font-weight: 600; letter-spacing: 0.01em;
  white-space: nowrap; user-select: none;
  /* 方案 E：淡色底 + 同色柔光陰影，比純淡色多一點「浮起來」的份量。 */
  background: color-mix(in srgb, var(--aic) 13%, var(--panel));
  border: 1px solid color-mix(in srgb, var(--aic) 22%, transparent);
  color: var(--aic-tx);
  box-shadow: 0 2px 10px color-mix(in srgb, var(--aic) 18%, transparent);
  animation: aistat-in 0.2s ease;
}
.aistat[hidden] { display: none; }
@keyframes aistat-in { from { opacity: 0; transform: translateY(-4px); } }
.aistat[data-state="listening"] { --aic: #db2777; --aic-tx: #be185d; }
.aistat[data-state="thinking"]  { --aic: #2563eb; --aic-tx: #1d4ed8; }
.aistat[data-state="scanning"]  { --aic: #0891b2; --aic-tx: #0e7490; }
.aistat[data-state="speaking"]  { --aic: #16a34a; --aic-tx: #15803d; }
/* 深色底上淡色文字讀不出來 —— 每個狀態各給一個亮階。 */
html[data-theme="dark"] .aistat[data-state="listening"] { --aic-tx: #f9a8d4; }
html[data-theme="dark"] .aistat[data-state="thinking"]  { --aic-tx: #93c5fd; }
html[data-theme="dark"] .aistat[data-state="scanning"]  { --aic-tx: #67e8f9; }
html[data-theme="dark"] .aistat[data-state="speaking"]  { --aic-tx: #86efac; }
/* 附錄 KE：膠囊移到 Live Monitoring 標題右側，靠右對齊。 */
.sh .aistat { margin-left: auto; }

/* 圖示一律用 currentColor 畫，跟著 --aic-tx 走，不必為深色模式再寫一套。 */
.aistat-ic {
  display: inline-flex; align-items: center; justify-content: center;
  width: 15px; height: 15px; flex: 0 0 auto; color: inherit;
}
/* 聆聽中 → 聲波條 */
.aistat-wave { display: inline-flex; align-items: center; gap: 2px; height: 14px; }
.aistat-wave i {
  width: 2.5px; height: 5px; border-radius: 999px; background: currentColor;
  animation: aistat-wv 0.9s ease-in-out infinite;
}
.aistat-wave i:nth-child(2) { animation-delay: 0.15s; }
.aistat-wave i:nth-child(3) { animation-delay: 0.3s; }
.aistat-wave i:nth-child(4) { animation-delay: 0.45s; }
@keyframes aistat-wv { 0%, 100% { height: 4px; } 50% { height: 13px; } }
/* 思考中 → 三點跳動 */
.aistat-dots { display: inline-flex; align-items: flex-end; gap: 3px; height: 14px; padding-bottom: 2px; }
.aistat-dots i {
  width: 4px; height: 4px; border-radius: 50%; background: currentColor;
  animation: aistat-bnc 1.05s ease-in-out infinite;
}
.aistat-dots i:nth-child(2) { animation-delay: 0.15s; }
.aistat-dots i:nth-child(3) { animation-delay: 0.3s; }
@keyframes aistat-bnc {
  0%, 80%, 100% { transform: translateY(0); opacity: 0.55; }
  40% { transform: translateY(-5px); opacity: 1; }
}
/* 辨識中 → 掃描框（掃描線上下掃） */
.aistat-scan {
  position: relative; width: 14px; height: 14px;
  border: 1.5px solid currentColor; border-radius: 3px; overflow: hidden;
}
.aistat-scan::after {
  content: ""; position: absolute; left: 0; right: 0; top: 1px;
  height: 1.5px; background: currentColor;
  animation: aistat-sw 1.35s ease-in-out infinite;
}
@keyframes aistat-sw { 0%, 100% { top: 1px; } 50% { top: calc(100% - 2.5px); } }
/* 附錄 KE：回應中 → 三格等化器（比聆聽的 4 格聲波高、色為綠，容易分辨）。 */
.aistat-talk { display: inline-flex; align-items: center; gap: 2.5px; height: 14px; }
.aistat-talk i {
  width: 2.5px; height: 6px; border-radius: 999px; background: currentColor;
  animation: aistat-tk 0.8s ease-in-out infinite;
}
.aistat-talk i:nth-child(2) { animation-delay: 0.12s; }
.aistat-talk i:nth-child(3) { animation-delay: 0.24s; }
@keyframes aistat-tk { 0%, 100% { height: 5px; } 50% { height: 14px; } }
@media (prefers-reduced-motion: reduce) {
  .aistat, .aistat-wave i, .aistat-dots i, .aistat-talk i, .aistat-scan::after { animation: none !important; }
  .aistat-wave i { height: 9px; }
  .aistat-talk i { height: 10px; }
  .aistat-dots i { opacity: 1; transform: none; }
}
/* 附錄 KE：AI 搜尋常用問句的收合 <details>。 */
.pq-details { border: 1px solid var(--line, #e5e7eb); border-radius: 10px; overflow: hidden; }
.pq-summary {
  display: flex; align-items: center; gap: 8px; cursor: pointer;
  padding: 8px 12px; font-weight: 600; font-size: 13px; list-style: none; user-select: none;
}
.pq-summary::-webkit-details-marker { display: none; }
.pq-summary .pq-chev { margin-left: auto; transition: transform 0.18s ease; }
.pq-details[open] .pq-summary .pq-chev { transform: rotate(180deg); }
.pq-details[open] .pq-summary { border-bottom: 1px solid var(--line, #e5e7eb); }

/* 附錄 KB：dev 外觀檢查用的並排樣本。用的是同一顆 .aistat，只是不受 hidden 管。 */
.aistat-samples { display: flex; gap: 9px; flex-wrap: wrap; align-items: center; }

/* ── 附錄 JZ：常用問句（二段式組句）──────────────────────────────────── */
.pq { display: block; }
.pq-selects { display: grid; grid-template-columns: 1.5fr 1fr; gap: 8px; align-items: start; }
.pq-col { min-width: 0; }
.pq-lb { display: block; font-size: 11.5px; font-weight: 700; color: var(--muted); margin-bottom: 4px; }
.pq select { width: 100%; }
.pq-hint { margin: 4px 0 0; font-size: 11px; color: var(--muted); }
.pq .ask-row { margin-top: 9px; }
.pq-say {
  display: flex; align-items: center; gap: 8px; margin-top: 9px;
  padding: 8px 11px; border-radius: 10px;
  /* 智慧助理的洋紅（DESIGN.md：v1.7.59 起不再借用安控的紫）。 */
  background: rgba(219, 39, 119, 0.09);
  border: 1px solid rgba(219, 39, 119, 0.26);
}
.pq-say-k { font-size: 10.5px; font-weight: 700; color: #be185d; white-space: nowrap; }
.pq-say-txt { flex: 1; min-width: 0; font-size: 13.5px; font-weight: 700; color: #be185d; }
/* 喚醒詞壓低一點：要唸，但重點是後面那句。 */
.pq-say-txt .pq-wake { opacity: 0.62; font-weight: 600; }
.pq-copy {
  flex: none; padding: 4px 9px; font-size: 11.5px; font-weight: 700; cursor: pointer;
  border-radius: 8px; border: 1px solid rgba(219, 39, 119, 0.3);
  background: var(--panel); color: #be185d;
}
html[data-theme="dark"] .pq-say-k,
html[data-theme="dark"] .pq-say-txt,
html[data-theme="dark"] .pq-copy { color: #f9a8d4; }
@media (max-width: 600px) {
  .pq-selects { grid-template-columns: 1fr; }
}

/* Face modal: show only the block for the active mode. */
#face-modal .face-block { display: none; }
body[data-mode="leaving_home"]     #face-modal .face-block[data-face-mode="leaving_home"],
body[data-mode="cabinet_alert"]    #face-modal .face-block[data-face-mode="cabinet_alert"],
body[data-mode="security_monitor"] #face-modal .face-block[data-face-mode="security_monitor"] { display: block; }

/* Region modal: cabinet vs danger-zone context (title/desc/capture button). */
#region-modal [data-rm] { display: none; }
body[data-mode="cabinet_alert"]    #region-modal [data-rm="cabinet_alert"],
body[data-mode="security_monitor"] #region-modal [data-rm="security_monitor"] { display: block; }
body[data-mode="cabinet_alert"]    #region-modal h3[data-rm="cabinet_alert"],
body[data-mode="security_monitor"] #region-modal h3[data-rm="security_monitor"] { flex: 1; }
body[data-mode="cabinet_alert"]    #region-modal .dm-em[data-rm="cabinet_alert"],
body[data-mode="security_monitor"] #region-modal .dm-em[data-rm="security_monitor"] { display: inline; }
body[data-mode="cabinet_alert"]    #region-modal button[data-rm="cabinet_alert"],
body[data-mode="security_monitor"] #region-modal button[data-rm="security_monitor"] { display: inline-block; }
/* Inside the modal the picker row always fits the modal width. */
#region-modal .cabinet-row { margin-top: 4px; }

/* Anchor container for the draggable radar overlay. */
.dash-rel { position: relative; }

/* 📡 Draggable BLE radar overlay (fixed size, A1 fade-in, drag by header). */
#radar-overlay {
  position: absolute;
  right: 12px;
  bottom: 12px;
  width: 250px;
  background: rgba(255, 255, 255, 0.97);
  backdrop-filter: blur(3px);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.24);
  z-index: 30;
  animation: radarFadeIn 0.3s ease both;
}
#radar-overlay[hidden] { display: none; animation: none; }
@keyframes radarFadeIn {
  from { opacity: 0; transform: scale(0.85); }
  to   { opacity: 1; transform: scale(1); }
}
.radar-ovl-hd {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 8px 10px;
  font-size: 12px;
  font-weight: 700;
  color: var(--text);
  border-bottom: 1px solid var(--border);
  cursor: move;
  user-select: none;
  touch-action: none;
}
.radar-ovl-hd .grab { color: var(--muted); font-size: 13px; }
.radar-ovl-x {
  margin-left: auto;
  font-size: 12px;
  color: var(--muted);
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 2px 8px;
  cursor: pointer;
}
.radar-ovl-bd { padding: 10px 12px 12px; }
.radar-target-row { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; }
.radar-target-row input { flex: 1 1 100%; min-width: 0; font-size: 12px; padding: 6px 8px; }
.radar-target-row button { font-size: 12px; padding: 6px 10px; white-space: nowrap; }
#radar-overlay .radar-wrap { max-width: none; margin-top: 0; }

/* Generic dashboard modal (map / AI / weather / face / region-select). */
.dash-modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(15, 23, 32, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  z-index: 220;
}
.dash-modal-overlay[hidden] { display: none; }
.dash-modal {
  background: var(--panel);
  border-radius: 16px;
  max-width: 560px;
  width: 100%;
  max-height: 88vh;
  overflow: auto;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.4);
  animation: radarFadeIn 0.28s ease both;
}
.dm-hd {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 14px 17px;
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  background: var(--panel);
  z-index: 1;
}
.dm-hd h3 { margin: 0; font-size: 15px; font-weight: 800; flex: 1; }
.dm-hd .dm-em { font-size: 17px; }
.dm-x {
  border: none;
  background: var(--panel-2);
  border-radius: 8px;
  width: 28px;
  height: 28px;
  font-size: 15px;
  cursor: pointer;
  color: var(--muted);
}
.dm-bd { padding: 15px 17px; font-size: 13px; }

/* 📍 Item-location map zones grid (read-only home-map view). */
.map-zones { display: grid; grid-template-columns: 1fr 1fr; gap: 11px; }
@media (max-width: 480px) { .map-zones { grid-template-columns: 1fr; } }
/* Inline card in the Live Monitoring panel — auto-visible in item_search mode
   (user: 尋找物品的物品位置地圖應該直接出現，不用再點按鈕/設定). */
/* v1.3.69: the map now sits ABOVE the camera grid — separator moved to the bottom edge. */
.map-inline { display: none; margin: 10px 0 14px; padding-bottom: 12px; border-bottom: 1px solid var(--border); }
/* v1.3.68: map is behind the #seg-map toolbar button — .open toggles it
   (auto-added when AI search / voice locate has a result to show). */
body[data-mode="item_search"] .map-inline.open { display: block; }
.map-inline-hd { display: flex; align-items: center; gap: 6px; margin: 0 0 8px; font-size: 13.5px; }
/* Wider host panel than the old modal → let cards flow instead of a fixed 2-col. */
.map-inline .map-zones { grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); }

/* 附錄 DV：物品距攝影機距離 — 左側面板常駐卡片（不用點開，尋找物品模式直接顯示）。
   卡片外框沿用 .panel/.sh，內文用 .dist-card-body。 */
.dist-card-body {
  font-size: 13px; line-height: 1.8; font-weight: 600; color: var(--text, #1f2937);
  white-space: pre-line;                 /* 多行「物品: 距離 m」保留換行 */
}
.map-zone { border: 1px solid var(--border); border-radius: 10px; overflow: hidden; }
.map-zone-photo {
  aspect-ratio: 4 / 3;
  position: relative;
  background: linear-gradient(135deg, #dfe7f0, #eef2f7);
  background-size: cover;
  background-position: center;
}
.map-zone-name {
  font-size: 11.5px;
  font-weight: 700;
  padding: 6px 9px;
  background: var(--panel-2);
  border-top: 1px solid var(--border);
}
.map-pin {
  position: absolute;
  transform: translate(-50%, -50%);
  /* 附錄 KO: 這個唯讀地圖的圖示原本只有 drop-shadow，放在深色物體上會看不見。
     改成裝在白色圓形底座裡（跟編輯器的 .pin-dot 一致），任何底色都看得清楚。 */
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 17px;
  background: #fff;
  border: 2px solid #fff;
  border-radius: 50%;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.45);
}
/* item emoji rendered as an SVG sprite on map pins (附錄 KD) */
.map-pin svg.ic { width: 18px; height: 18px; color: #0e7490; }
#home-map-panel .pin-dot svg.ic { width: 18px; height: 18px; }
#home-map-panel .pin-dot.kind-item svg.ic { color: #0e7490; }
#home-map-panel .pin-dot.kind-camera svg.ic,
#home-map-panel .pin-dot.kind-ble svg.ic { color: #fff; }
.map-pin-cap {
  position: absolute;
  top: calc(100% + 3px);   /* 附錄 KO: 圓形底座下方，不壓到圖示 */
  left: 50%;
  transform: translateX(-50%);
  font-size: 9px;
  font-style: normal;
  font-weight: 700;
  background: #111827;
  color: #fff;
  padding: 0 5px;
  border-radius: 5px;
  white-space: nowrap;
}

/* 🎯 AI locate-on-map（1A/2B/3A）: ✨AI 搜尋 / 語音「在哪」/ 管家歷史分析的
   答案直接標在物品地圖上 — 結果橫幅 + 命中區亮框 + 脈衝環 + 標籤。 */
.locate-banner {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  background: rgba(37, 99, 235, 0.08);
  border: 1px solid rgba(37, 99, 235, 0.35);
  border-radius: 9px; padding: 7px 12px; margin: 0 0 10px; font-size: 12.5px;
}
/* 附錄 GP：display:flex 會蓋掉 hidden 屬性的預設 display:none，少了這一行，
   還沒搜尋過的時候橫幅就一直空在那裡（只有一個 🔍 和「清除標記」，沒有文字），
   而且按「清除標記」也收不起來（clearLocateMarks 設的 hidden 同樣無效）。 */
.locate-banner[hidden] { display: none; }
.locate-banner.warn { background: rgba(217, 119, 6, 0.10); border-color: rgba(217, 119, 6, 0.45); }
.locate-clear {
  margin-left: auto; border: 1px solid var(--border); background: var(--panel);
  color: var(--muted); border-radius: 7px; font-size: 11.5px; padding: 3px 10px; cursor: pointer;
}
.cam-chip {
  font-size: 10px; font-weight: 700; padding: 1px 7px; border-radius: 20px;
  background: rgba(22, 163, 74, 0.14); color: #15803d; white-space: nowrap;
}
[data-theme="dark"] .cam-chip { color: #4ade80; }
.map-zone.hit {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px rgba(37, 99, 235, 0.32), 0 4px 14px rgba(37, 99, 235, 0.16);
}
.map-zone.hit .map-zone-name { color: var(--accent); }
.map-zones.dimmed .map-zone:not(.hit) { opacity: 0.38; filter: saturate(0.6); }
.locate-ring {
  position: absolute; transform: translate(-50%, -50%);
  width: 44px; height: 44px; border-radius: 50%;
  border: 2.5px solid var(--accent); pointer-events: none;
}
.locate-ring.area { width: 64px; height: 64px; }   /* 區域級命中（無精確圖釘）畫大圈 */
.locate-ring::before, .locate-ring::after {
  content: ""; position: absolute; inset: -2.5px; border-radius: 50%;
  border: 2.5px solid var(--accent);
  animation: locPulse 1.6s ease-out infinite;
}
.locate-ring::after { animation-delay: 0.8s; }
/* 附錄 IX：AI 這次推測的位置 —— 虛線 + 放大，和「平常位置」的實線圈區分開。
   虛線在這套介面本來就是「推測、未確認」的語彙（家中地圖的 AI 建議釘也是虛線），
   所以不引入新顏色，維持 accent 藍。 */
.locate-ring.ai { width: 62px; height: 62px; border-style: dashed; }
.locate-ring.ai.area { width: 78px; height: 78px; }
.locate-ring.ai::before, .locate-ring.ai::after { border-style: dashed; }
@keyframes locPulse {
  0%   { transform: scale(1);   opacity: 0.9; }
  100% { transform: scale(2.1); opacity: 0; }
}
.locate-tip {
  position: absolute; transform: translateX(-50%); z-index: 2;
  background: var(--accent); color: #fff;
  font-size: 10px; font-weight: 700; padding: 2.5px 8px; border-radius: 7px;
  white-space: nowrap; box-shadow: 0 2px 8px rgba(37, 99, 235, 0.4);
}
/* 1A: Gemini 影像分析摺疊列（原 ai-modal 內容搬到地圖下方） */
.gm-line { border: 1px solid var(--border); border-radius: 9px; margin-top: 10px; font-size: 12.5px; overflow: hidden; }
.gm-line summary {
  padding: 7px 11px; background: var(--panel-2); font-weight: 700; cursor: pointer;
  list-style: none; display: flex; align-items: center; gap: 6px;
}
.gm-line summary::-webkit-details-marker { display: none; }
.gm-line summary::after { content: "▾"; margin-left: auto; color: var(--muted); font-size: 10px; }
.gm-line[open] summary::after { content: "▴"; }
.gm-line-bd { padding: 9px 12px; color: var(--muted); line-height: 1.7; border-top: 1px solid var(--border); white-space: pre-wrap; }
/* 2B: 語音「在哪」浮動地圖小卡 — 不切模式，右下角浮出、8 秒自動關閉 */
.locate-float {
  position: fixed; right: 18px; bottom: 18px; z-index: 960;
  width: min(400px, calc(100vw - 36px));
  background: var(--panel); border: 1.5px solid var(--accent); border-radius: 12px;
  box-shadow: 0 12px 40px rgba(37, 99, 235, 0.32); overflow: hidden;
}
.lf-hd {
  display: flex; align-items: center; gap: 7px; padding: 8px 12px;
  font-size: 12px; font-weight: 800;
  background: rgba(37, 99, 235, 0.08); border-bottom: 1px solid rgba(37, 99, 235, 0.3);
}
.lf-x { margin-left: auto; border: none; background: none; color: var(--muted); font-size: 14px; cursor: pointer; }
.lf-bd { padding: 10px 12px; }
.lf-bd .map-zone-photo { aspect-ratio: 16 / 8; }
.lf-bar { height: 3px; background: rgba(37, 99, 235, 0.18); border-radius: 2px; overflow: hidden; margin-top: 8px; }
.lf-bar i { display: block; height: 100%; width: 100%; background: var(--accent); animation: lfShrink 8s linear forwards; }
@keyframes lfShrink { from { width: 100%; } to { width: 0; } }

[data-theme="dark"] #radar-overlay { background: rgba(32, 40, 48, 0.97); }

/* ============ 附錄 DN / DO：操作引導（新手導覽）— 淺色主題 ============ */
/* Header 啟動按鈕 — 淺藍色淺底（不用深藍實心），輕脈動吸引新使用者。 */
.guide-launch{
  flex-shrink:0; display:inline-flex; align-items:center; gap:6px;
  font-size:13px; font-weight:700; line-height:1; white-space:nowrap; cursor:pointer;
  color:#1d4ed8; padding:5px 12px; border:1px solid rgba(150,185,255,.55); border-radius:999px;
  background:rgba(238,244,255,.55); -webkit-backdrop-filter:blur(8px); backdrop-filter:blur(8px);
  transition:background .15s, border-color .15s, transform .15s, box-shadow .15s;
}
.guide-launch:hover{ transform:translateY(-1px); background:rgba(224,235,255,.72); box-shadow:0 0 0 3px rgba(96,165,250,.28); }
.guide-launch .btn-ic svg{ fill:currentColor; stroke:currentColor; stroke-width:1.4; }
@keyframes guidePulse{ 0%,100%{ box-shadow:0 0 0 0 rgba(96,165,250,.45); } 50%{ box-shadow:0 0 0 5px rgba(96,165,250,0); } }
.guide-launch{ animation:guidePulse 2.4s ease-out infinite; }

/* 導覽遮罩 / 聚光燈 / 工具提示卡（淺色卡片） */
.guide-back{ position:fixed; inset:0; z-index:9000; display:none; background:transparent; }
.guide-back.on{ display:block; }
.guide-hl{
  position:fixed; z-index:9001; display:none; border-radius:12px; pointer-events:none;
  box-shadow:0 0 0 3px #60a5fa, 0 0 0 9999px rgba(12,18,28,.60);
  transition:left .18s, top .18s, width .18s, height .18s;
}
.guide-tip{
  position:fixed; z-index:9002; display:none; width:320px; max-width:92vw;
  background:rgba(255,255,255,.72); -webkit-backdrop-filter:blur(16px) saturate(1.4);
  backdrop-filter:blur(16px) saturate(1.4); border:1px solid rgba(255,255,255,.5);
  border-radius:14px; padding:16px 16px 14px; box-shadow:0 18px 44px rgba(15,23,42,.35); color:#1f2937;
}
.guide-tip .guide-step{ font-size:11.5px; color:#2563eb; font-weight:700; letter-spacing:.6px; margin-bottom:6px; }
.guide-tip .guide-title{ margin:0 0 7px; font-size:15px; color:#111827; }
.guide-tip .guide-body{ margin:0 0 12px; font-size:13.3px; line-height:1.65; color:#4b5563; }
.guide-tip .guide-ctl{ display:flex; align-items:center; gap:8px; }
/* 附錄 IE：導覽步驟從 3～5 步加到 12～14 步。原本這排點點不換行，14 顆 ×12px
   會把「跳過／上一步／下一步」三顆鈕擠出卡片外。限寬 + 換行讓點點自己疊成兩排，
   按鈕位置不受影響；步驟數另有「步驟 3 / 14」文字，點點只是輔助指示。 */
.guide-tip .guide-dots{ display:flex; flex-wrap:wrap; gap:4px 5px; margin-right:auto; max-width:96px; }
.guide-tip .guide-dot{ width:7px; height:7px; border-radius:50%; background:#d2dae6; }
.guide-tip .guide-dot.on{ background:#2563eb; }
.guide-mini{ padding:7px 13px; border-radius:8px; font-size:13px; font-weight:600; cursor:pointer;
  border:1px solid rgba(217,226,240,.7); background:rgba(243,246,251,.5); color:#374151; }
.guide-mini:hover{ background:rgba(233,239,248,.8); }
.guide-mini.go{ background:rgba(59,130,246,.92); border-color:rgba(59,130,246,.92); color:#ffffff; }
.guide-mini.go:hover{ background:rgba(47,116,234,.96); }
.guide-mini.ghost{ background:rgba(243,246,251,.5); border-color:rgba(217,226,240,.7); color:#475569; }
.guide-mini.ghost:hover{ background:rgba(233,239,248,.8); color:#334155; }
.guide-tip .guide-arrow{ position:absolute; width:14px; height:14px; background:rgba(255,255,255,.72);
  -webkit-backdrop-filter:blur(16px); backdrop-filter:blur(16px);
  border-left:1px solid rgba(255,255,255,.5); border-top:1px solid rgba(255,255,255,.5); }
@media (max-width:640px){ .guide-tip{ width:88vw; } }

/* ── 攝影機設定：即時預覽 + 使用中徽章（附錄 EV） ───────────────────────── */
.cam-row{ display:grid; grid-template-columns:120px 1fr; gap:12px; align-items:start;
  background:var(--panel-2); border:1px solid var(--border); border-radius:10px;
  padding:10px; margin:12px 0; }
.cam-thumb{ width:120px; height:68px; border-radius:6px; position:relative; overflow:hidden;
  background:#000; border:1px solid var(--border); display:flex; align-items:center; justify-content:center; }
.cam-thumb video{ width:100%; height:100%; object-fit:cover; display:block; background:#000; }
.cam-thumb-empty{ position:absolute; inset:0; display:flex; align-items:center; justify-content:center;
  font-size:11px; color:var(--muted); background:var(--panel-2); }
.cam-thumb.has-stream .cam-thumb-empty{ display:none; }
.cam-live-tag{ position:absolute; top:5px; left:5px; background:rgba(0,0,0,.55); color:#fff;
  font-size:9px; font-weight:700; letter-spacing:.04em; padding:1px 6px 1px 14px; border-radius:999px; }
.cam-live-tag::before{ content:""; position:absolute; left:5px; top:50%; transform:translateY(-50%);
  width:6px; height:6px; border-radius:50%; background:#ff4d4d; box-shadow:0 0 0 2px rgba(255,77,77,.3); }
.cam-row-body{ min-width:0; }
.cam-row-body label{ display:block; font-size:13px; font-weight:600; margin-bottom:5px; }
.cam-row-body select{ width:100%; }
.cam-use-badge{ display:inline-flex; align-items:center; gap:5px; font-size:11px; font-weight:600;
  color:var(--ok); background:rgba(22,163,74,.14); padding:2px 9px; border-radius:999px; margin-top:8px; }
.cam-apply-hint{ margin-top:4px; }

/* ═══════════ ⑧ 警報歷史中心（附錄 EW） ═══════════ */
.hist-count { margin-left:auto; margin-right:10px; white-space:nowrap; }
.hist-filters { display:flex; gap:7px; flex-wrap:wrap; align-items:center; margin-bottom:12px; }
.hist-chip { font-size:12px; padding:4px 11px; border-radius:999px; border:1px solid var(--border);
  background:var(--panel-2); color:var(--muted); cursor:pointer; transition:all .15s; }
.hist-chip:hover { color:var(--text); }
.hist-chip.active { background:var(--accent); border-color:var(--accent); color:#fff; }
.hist-search-wrap { margin-left:auto; position:relative; display:inline-flex; align-items:center; }
.hist-search-ic { position:absolute; left:9px; top:50%; transform:translateY(-50%);
  color:var(--muted); pointer-events:none; width:14px; height:14px; }
/* input.hist-search：特異性需 ≥ 基礎 input[type="text"]，否則其 padding:8px 10px 會蓋掉
   下方左側 30px 讓位、導致文字壓到搜尋 icon。 */
input.hist-search { background:var(--panel-2); border:1px solid var(--border);
  border-radius:8px; padding:5px 10px 5px 32px; color:var(--text); font-size:12px;
  width:auto; min-width:130px; font-family:inherit; }
.hist-list { max-height:52vh; overflow-y:auto; }
.hist-day { font-size:12px; color:var(--muted); font-weight:700; letter-spacing:.03em; margin:12px 2px 7px; }
.hist-day:first-child { margin-top:0; }
.hist-item { display:grid; grid-template-columns:92px 1fr auto; gap:11px; align-items:center;
  background:var(--panel-2); border:1px solid var(--border); border-radius:10px; padding:8px; margin-bottom:8px; }
.hist-thumb { width:92px; height:54px; border-radius:6px; overflow:hidden; position:relative;
  display:flex; align-items:center; justify-content:center; background:#000; cursor:pointer; }
.hist-thumb img { width:100%; height:100%; object-fit:cover; display:block; }
.hist-thumb.noimg { font-size:20px; color:var(--muted); background:var(--panel); cursor:default; }
.hist-thumb .hist-cam { position:absolute; bottom:3px; left:4px; font-size:8px; font-weight:700;
  background:rgba(0,0,0,.6); color:#fff; padding:0 4px; border-radius:3px; letter-spacing:.03em; }
.hist-meta { min-width:0; }
.hist-title { font-size:13px; font-weight:600; color:var(--text); display:flex; align-items:center; gap:6px; flex-wrap:wrap; }
.hist-badge { font-size:10px; font-weight:700; padding:1px 7px; border-radius:999px; white-space:nowrap; }
/* 模式語意色（DESIGN.md）：危險區/保全紫、收納櫃橙、離家青、尋找藍。
   附錄 FS：先前只有深色版配色（淡色字＋低透明底），套在淺色主題的白底彈窗上幾乎看不見。
   基準改用 DESIGN.md 的淺色主題色（深字＋淡底，對白底 ≥5:1），深色主題再覆蓋回亮色字。 */
.hist-badge.danger_zone, .hist-badge.security_monitor { background:rgba(124,58,237,.12); color:#6d28d9; }
.hist-badge.cabinet_alert { background:rgba(234,88,12,.12); color:#c2410c; }
.hist-badge.leaving_home  { background:rgba(8,145,178,.12); color:#0e7490; }
.hist-badge.item_search   { background:rgba(37,99,235,.12); color:#1d4ed8; }
[data-theme="dark"] .hist-badge.danger_zone,
[data-theme="dark"] .hist-badge.security_monitor { background:rgba(124,58,237,.18); color:#a78bfa; }
[data-theme="dark"] .hist-badge.cabinet_alert { background:rgba(234,88,12,.18); color:#fb923c; }
[data-theme="dark"] .hist-badge.leaving_home  { background:rgba(8,145,178,.18); color:#38bdf8; }
[data-theme="dark"] .hist-badge.item_search   { background:rgba(37,99,235,.18); color:#93b4fb; }
.hist-desc { font-size:11px; color:var(--muted); margin-top:2px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.hist-right { text-align:right; white-space:nowrap; display:flex; flex-direction:column; align-items:flex-end; gap:5px; }
.hist-time { font-size:13px; font-weight:600; color:var(--text); }
.hist-del { font-size:11px; border:1px solid var(--border); background:transparent; color:var(--muted);
  border-radius:6px; padding:3px 8px; cursor:pointer; }
.hist-del:hover { color:var(--danger); border-color:var(--danger); }
.hist-empty { text-align:center; padding:22px 0; }
.hist-actions { margin-top:12px; justify-content:flex-end; gap:8px; }
.danger-text { color:var(--danger); }
/* lightbox */
.hist-lightbox { position:fixed; inset:0; background:rgba(0,0,0,.85); z-index:400;
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:12px; padding:24px; cursor:zoom-out; }
.hist-lightbox[hidden] { display:none; }
.hist-lightbox img { max-width:94vw; max-height:80vh; border-radius:10px; box-shadow:0 12px 40px rgba(0,0,0,.6); }
.hist-lightbox-cap { color:#e0e0e0; font-size:13px; text-align:center; }

/* ═══════════ 功能1：攝影機看門狗重連提示（附錄 EX） ═══════════ */
.cam-reconnect {
  position: absolute; inset: 0; z-index: 6;
  display: flex; align-items: center; justify-content: center; gap: 10px;
  background: rgba(20, 20, 20, 0.72); color: #fff; font-size: 13px; font-weight: 600;
  -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
}
.cam-reconnect[hidden] { display: none; }
.cam-reconnect-spin {
  width: 18px; height: 18px; border: 2px solid rgba(255,255,255,.3);
  border-top-color: var(--warn); border-radius: 50%; animation: camWdSpin .8s linear infinite;
}
@keyframes camWdSpin { to { transform: rotate(360deg); } }

/* ═══════════ 附錄 EY: Gemini 不可用 dev 紅字警示 ═══════════ */
.gemini-warn {
  margin: 8px 0 0; padding: 9px 12px; border-radius: 8px;
  background: rgba(220, 38, 38, 0.12); border: 1px solid var(--danger);
  color: var(--danger); font-size: 13px; font-weight: 700; line-height: 1.4;
}
.gemini-warn[hidden] { display: none; }

/* ═══════════ 附錄 FY：Pitch Tour（展場講稿提詞導覽，dev / sviif-contest 限定） ═══════════ */
/* 刻意「沒有」guide-tour 那層 9999px 暗幕：導覽開著時底下的系統必須全部可點，
   講者要能一邊看提詞一邊真的操作給評審看。高亮框只有彩色外框 + pointer-events:none。 */
body[data-role="dev"] .header-logo-img,
body[data-role="contest"] .header-logo-img{
  cursor:pointer;
  transition:transform .12s ease, box-shadow .12s ease;
}
body[data-role="dev"] .header-logo-img:hover,
body[data-role="contest"] .header-logo-img:hover{
  transform:scale(1.08); box-shadow:0 0 0 3px rgba(124,58,237,.35);
}
body.pt-open .header-logo-img{ box-shadow:0 0 0 3px rgba(124,58,237,.55); }

.pt-hl{
  position:fixed; z-index:9101; display:none; border-radius:12px; pointer-events:none;
  border:2.5px solid var(--mode-item-l); box-shadow:0 0 0 4px rgba(37,99,235,.18);
  transition:left .22s ease, top .22s ease, width .22s ease, height .22s ease;
}
.pt-card{
  position:fixed; z-index:9102; display:none; width:310px; max-width:92vw;
  background:var(--panel); border:1px solid var(--border); border-radius:var(--radius);
  box-shadow:0 18px 44px rgba(15,23,42,.22); padding:13px 15px 11px;
  border-top:4px solid var(--mode-item-l); color:var(--text);
  transition:left .22s ease, top .22s ease;
}
.pt-card .pt-arrow{
  position:absolute; width:13px; height:13px; background:var(--panel);
  border-left:1px solid var(--border); border-top:1px solid var(--border);
}
.pt-card .pt-meta{ display:flex; align-items:center; gap:8px; margin-bottom:7px; }
.pt-card .pt-badge{ font-size:10px; font-weight:700; padding:2px 9px; border-radius:999px; letter-spacing:.3px; }
.pt-card .pt-step{ font-size:10.5px; color:var(--muted); font-weight:600; margin-left:auto;
  font-family:ui-monospace,"SF Mono",Menlo,monospace; }
.pt-card .pt-title{ margin:0 0 6px; font-size:15.5px; font-weight:600; line-height:1.3; letter-spacing:-.2px; }
.pt-card .pt-body{ margin:0 0 10px; font-size:12.8px; line-height:1.55; color:#374151; font-weight:500; }
.pt-card .pt-switch{ display:none; font-size:12.5px; color:var(--muted); background:var(--panel-2);
  border:1px dashed var(--border); border-radius:8px; padding:6px 10px; margin-bottom:10px; }
/* 進度點自成一列、按鈕列靠右不換行。17 顆點跟按鈕擠同一行會被 overflow 切掉，
   走到後段時「目前這一顆」正好落在切線外，講者反而看不出自己在第幾步。 */
/* 附錄 GO：一次只畫目前模式的 4–6 顆點，換模式就重畫。點數變少了，間距從 4px
   放回 6px（22 顆時被壓到 4px 才塞得下一排），台上看得清楚一點。 */
.pt-card .pt-dots{ display:flex; align-items:center; gap:6px; flex-wrap:wrap;
  padding-top:10px; margin-bottom:9px; border-top:1px solid var(--border); }
.pt-card .pt-dot{ width:6px; height:6px; flex:0 0 auto; border-radius:50%; background:#d2dae6;
  transition:background .18s ease, width .18s ease; }
.pt-card .pt-dot.on{ width:16px; border-radius:999px; background:var(--mode-item-l); }
.pt-card .pt-ctl{ display:flex; align-items:center; justify-content:flex-end; gap:7px; flex-wrap:nowrap; }
.pt-card .pt-btn{ padding:6px 11px; border-radius:8px; font-size:11.8px; font-weight:600; cursor:pointer;
  flex:0 0 auto; white-space:nowrap; border:1px solid var(--border); background:var(--panel-2); color:#374151; }
.pt-card .pt-btn:active{ transform:scale(.95); }
.pt-card .pt-btn.go{ background:var(--mode-item-l); border-color:var(--mode-item-l); color:#fff; }
.pt-card .pt-btn.ghost{ color:var(--muted); }

/* 模式配色（1 藍 / 2 青 / 3 橙 / 4 紫）— 卡片上緣、Next 鈕、目前進度點、徽章、高亮框一起換。 */
/* 附錄 GK：0 = 不屬於任何模式的章節（開場／四大核心功能／四模式總覽／手機與結語）。
   走中性灰，沿用既有的 --muted 不新增色票，講者一眼分得出「這段不在任何模式裡」。 */
.pt-card[data-m="0"]{ border-top-color:var(--muted); }
.pt-card[data-m="0"] .pt-btn.go{ background:var(--muted); border-color:var(--muted); }
.pt-card[data-m="0"] .pt-dot.on{ background:var(--muted); }
.pt-card[data-m="0"] .pt-badge{ background:color-mix(in srgb, var(--muted) 14%, transparent); color:var(--muted); }
.pt-hl[data-m="0"]{ border-color:var(--muted); box-shadow:0 0 0 4px color-mix(in srgb, var(--muted) 18%, transparent); }
.pt-card[data-m="1"]{ border-top-color:var(--mode-item-l); }
.pt-card[data-m="1"] .pt-btn.go{ background:var(--mode-item-l); border-color:var(--mode-item-l); }
.pt-card[data-m="1"] .pt-dot.on{ background:var(--mode-item-l); }
.pt-card[data-m="1"] .pt-badge{ background:rgba(37,99,235,.12); color:var(--mode-item); }
.pt-card[data-m="2"]{ border-top-color:var(--mode-leaving-l); }
.pt-card[data-m="2"] .pt-btn.go{ background:var(--mode-leaving-l); border-color:var(--mode-leaving-l); }
.pt-card[data-m="2"] .pt-dot.on{ background:var(--mode-leaving-l); }
.pt-card[data-m="2"] .pt-badge{ background:rgba(8,145,178,.12); color:var(--mode-leaving); }
.pt-card[data-m="3"]{ border-top-color:var(--mode-cabinet-l); }
.pt-card[data-m="3"] .pt-btn.go{ background:var(--mode-cabinet-l); border-color:var(--mode-cabinet-l); }
.pt-card[data-m="3"] .pt-dot.on{ background:var(--mode-cabinet-l); }
.pt-card[data-m="3"] .pt-badge{ background:rgba(234,88,12,.12); color:var(--mode-cabinet); }
.pt-card[data-m="4"]{ border-top-color:var(--mode-security-l); }
.pt-card[data-m="4"] .pt-btn.go{ background:var(--mode-security-l); border-color:var(--mode-security-l); }
.pt-card[data-m="4"] .pt-dot.on{ background:var(--mode-security-l); }
.pt-card[data-m="4"] .pt-badge{ background:rgba(124,58,237,.12); color:var(--mode-security); }
.pt-hl[data-m="2"]{ border-color:var(--mode-leaving-l);  box-shadow:0 0 0 4px rgba(8,145,178,.18); }
.pt-hl[data-m="3"]{ border-color:var(--mode-cabinet-l);  box-shadow:0 0 0 4px rgba(234,88,12,.18); }
.pt-hl[data-m="4"]{ border-color:var(--mode-security-l); box-shadow:0 0 0 4px rgba(124,58,237,.18); }

/* ── 附錄 HK：智慧助理的打字發問列與答案區 ─────────────────────────────
   依 DESIGN.md 既有 token：緊湊間距（8/10px）、輸入 8px 圓角、按鈕 10px、
   顏色一律走變數。智慧助理模式的專屬色是洋紅（附錄 IB 起不再與安全監控共用
   紫色），所以答案區用它做左側標記，而不是通用的 accent 藍。 */
.ask-row { display: flex; gap: 8px; align-items: center; }
.ask-row input[type="text"] {
  flex: 1;
  min-width: 0;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--panel);
  color: var(--text);
  font-size: 13px;
}
.ask-row input[type="text"]:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(37, 99, 235, .15);
}
.ask-row button { border-radius: 10px; padding: 8px 14px; }
.ia-answer {
  margin-top: 10px;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-left: 3px solid var(--mode-ia-l);   /* 智慧助理專屬洋紅（DESIGN.md） */
  border-radius: 8px;
  background: var(--panel-2);
  color: var(--text);
  font-size: 13px;
  line-height: 1.55;
  white-space: pre-wrap;
}

/* 附錄 IK: 「這個模式現在不可能發出任何警報」的說明。用 --warn（提醒，不是錯誤）。
   [hidden] 要自己寫死 —— 本專案踩過 label{display:block} 蓋掉 UA 預設 [hidden]
   的坑，帶 class 的元素一律明確宣告，別依賴瀏覽器預設。 */
.arm-warn {
  margin: 6px 0 0;
  padding: 8px 10px;
  border: 1px solid var(--warn);
  border-left-width: 3px;
  border-radius: 6px;
  background: color-mix(in srgb, var(--warn) 8%, transparent);
  color: var(--text);
  font-size: 12px;
  line-height: 1.6;
}
.arm-warn[hidden] { display: none; }
