:root {
  /* 主色 / 强调色 */
  --primary: #4f46e5;
  --primary-dark: #4338ca;
  --primary-light: #eef2ff;
  --primary-soft: #6366f1;
  /* 中性色 */
  --bg: #f1f5f9;
  --surface: #ffffff;
  --surface-2: #f8fafc;
  --border: #e2e8f0;
  --border-strong: #cbd5e1;
  --text: #0f172a;
  --muted: #64748b;
  --muted-2: #94a3b8;
  /* 语义色 */
  --online: #16a34a;
  --online-bg: #f0fdf4;
  --offline: #94a3b8;
  --offline-bg: #f1f5f9;
  --danger: #dc2626;
  --danger-bg: #fef2f2;
  --warn: #d97706;
  --warn-bg: #fffbeb;
  --info: #0284c7;
  --info-bg: #eff6ff;
  /* 侧边栏（深色） */
  --side-bg: #0f172a;
  --side-bg-2: #111c33;
  --side-text: #cbd5e1;
  --side-muted: #64748b;
  --side-active: #4f46e5;
  /* 阴影 / 圆角 */
  --shadow-sm: 0 1px 2px rgba(15,23,42,.06), 0 1px 3px rgba(15,23,42,.08);
  --shadow: 0 4px 12px rgba(15,23,42,.08), 0 2px 4px rgba(15,23,42,.04);
  --shadow-lg: 0 20px 40px rgba(15,23,42,.18);
  --radius: 12px;
  --radius-sm: 8px;
  --radius-lg: 16px;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;
  background: var(--bg);
  color: var(--text);
  font-size: 14px;
  -webkit-font-smoothing: antialiased;
}

.hidden { display: none !important; }
.muted { color: var(--muted); }

/* ============ 通用组件 ============ */
.primary-btn {
  padding: 10px 16px; border: none; border-radius: var(--radius-sm);
  background: var(--primary); color: #fff; font-size: 14px; font-weight: 600; cursor: pointer;
  transition: background .15s, transform .05s;
}
.primary-btn:hover { background: var(--primary-dark); }
.primary-btn:active { transform: translateY(1px); }
.primary-btn:disabled { opacity: .6; cursor: not-allowed; }

.ghost-btn {
  padding: 8px 14px; border: 1px solid var(--border); background: #fff;
  border-radius: var(--radius-sm); cursor: pointer; font-size: 13px; color: var(--text);
  transition: border-color .15s, color .15s, background .15s;
}
.ghost-btn:hover { border-color: var(--primary); color: var(--primary); }
.ghost-btn.danger:hover { border-color: var(--danger); color: var(--danger); }

.icon-btn {
  width: 38px; height: 38px; border: 1px solid var(--border); background: #fff;
  border-radius: var(--radius-sm); cursor: pointer; font-size: 18px; color: var(--muted);
}
.icon-btn:hover { border-color: var(--primary); color: var(--primary); }

.link-text { color: var(--primary); font-size: 13px; text-decoration: none; cursor: pointer; }
.link-text:hover { text-decoration: underline; }

.link-btn {
  padding: 3px 10px; border: 1px solid var(--border); background: #fff; border-radius: 6px;
  color: var(--danger); cursor: pointer; font-size: 12px;
}
.link-btn:hover { border-color: var(--danger); background: var(--danger-bg); }

.badge {
  background: var(--primary); color: #fff; border-radius: 999px;
  padding: 2px 9px; font-size: 12px; font-weight: 600;
}
.badge-online { font-size: 11px; padding: 2px 9px; border-radius: 999px; background: var(--online-bg); color: var(--online); border: 1px solid #bbf7d0; display: inline-block; white-space: nowrap; flex-shrink: 0; line-height: 1.4; }
.badge-offline { font-size: 11px; padding: 2px 9px; border-radius: 999px; background: var(--offline-bg); color: var(--offline); border: 1px solid var(--border); display: inline-block; white-space: nowrap; flex-shrink: 0; line-height: 1.4; }
.badge-mini { font-size: 11px; padding: 2px 9px; border-radius: 999px; border: 1px solid #bfdbfe; background: #eff6ff; color: #1d4ed8; display: inline-block; white-space: nowrap; flex-shrink: 0; line-height: 1.4; }
.badge-web { font-size: 11px; padding: 2px 9px; border-radius: 999px; border: 1px solid #c7d2fe; background: #eef2ff; color: #4338ca; display: inline-block; white-space: nowrap; flex-shrink: 0; line-height: 1.4; }
.badge-api { font-size: 11px; padding: 2px 9px; border-radius: 999px; border: 1px solid #fde68a; background: #fffbeb; color: #b45309; display: inline-block; white-space: nowrap; flex-shrink: 0; line-height: 1.4; }
.badge-ha-on { font-size: 11px; padding: 2px 9px; border-radius: 999px; background: var(--online-bg); color: var(--online); border: 1px solid #bbf7d0; display: inline-block; white-space: nowrap; flex-shrink: 0; line-height: 1.4; }
.badge-ha-off { font-size: 11px; padding: 2px 9px; border-radius: 999px; background: #fff7ed; color: #c2410c; border: 1px solid #fed7aa; display: inline-block; white-space: nowrap; flex-shrink: 0; line-height: 1.4; }

/* ============ 登录（分屏）============ */
.login-wrap {
  min-height: 100vh; display: flex; align-items: stretch; justify-content: center;
}
.login-brand {
  flex: 1 1 480px; max-width: 620px; padding: 64px 56px;
  background: linear-gradient(150deg, #4338ca 0%, #4f46e5 45%, #0ea5e9 120%);
  color: #fff; display: flex; flex-direction: column; justify-content: center;
}
.login-brand .brand-logo {
  width: 56px; height: 56px; border-radius: 14px; background: rgba(255,255,255,.16);
  display: flex; align-items: center; justify-content: center; font-weight: 800; font-size: 22px;
  letter-spacing: 1px; backdrop-filter: blur(4px); margin-bottom: 24px;
}
.login-brand h1 { margin: 0; font-size: 34px; letter-spacing: 1px; }
.brand-tag { margin: 8px 0 36px; opacity: .85; font-size: 14px; letter-spacing: .5px; }
.brand-points { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 16px; }
.brand-points li { display: flex; align-items: center; gap: 12px; font-size: 15px; opacity: .95; }
.brand-points .dot { width: 8px; height: 8px; border-radius: 50%; background: #7dd3fc; box-shadow: 0 0 0 4px rgba(125,211,252,.25); flex: none; }

.login-form-side {
  flex: 1 1 420px; max-width: 480px; display: flex; align-items: center; justify-content: center;
  padding: 40px 32px; background: var(--bg);
}
.login-card { width: 100%; max-width: 380px; background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-lg); box-shadow: var(--shadow); padding: 36px 32px; }
.login-head h2 { margin: 0 0 4px; font-size: 22px; }
.login-head .muted { margin: 0 0 22px; font-size: 13px; }

#login-form label, #register-form label, .env-block label { display: block; font-size: 13px; color: var(--muted); margin-bottom: 16px; }
#login-form input, #register-form input, .login-card select {
  width: 100%; margin-top: 6px; padding: 11px 13px;
  border: 1px solid var(--border); border-radius: var(--radius-sm); font-size: 14px;
  background: #fff; color: var(--text); transition: border-color .15s, box-shadow .15s;
}
#login-form input:focus, #register-form input:focus, .login-card select:focus,
.modal-box input:focus, .modal-box select:focus, .form-row input:focus, .form-row select:focus {
  outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px rgba(79,70,229,.15);
}
#login-btn, #register-btn { width: 100%; margin-top: 4px; }
.error-text { color: var(--danger); font-size: 13px; min-height: 18px; margin: 8px 0 0; }
.hint { color: var(--muted-2); font-size: 12px; text-align: center; margin-top: 18px; }
.link-text { display: block; text-align: center; margin-top: 14px; }

/* 登录方式 Tab */
.login-tabs { display: flex; gap: 6px; margin-bottom: 20px; background: var(--surface-2);
  border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 4px; }
.login-tab { flex: 1; padding: 9px 4px; border: none; background: transparent; color: var(--muted);
  font-size: 13px; border-radius: var(--radius-sm); cursor: pointer; transition: all .15s; }
.login-tab:hover { color: var(--text); }
.login-tab.active { background: var(--primary); color: #fff; font-weight: 600; }

/* 验证码输入行 */
.code-row { display: flex; gap: 8px; align-items: flex-start; }
.code-row input { flex: 1; margin-top: 6px; }
.code-row .ghost-btn { margin-top: 6px; white-space: nowrap; padding: 11px 12px; }

/* 登录底部链接 */
.login-foot-links { display: flex; justify-content: space-between; margin-top: 12px; }
.login-foot-links .link-text { margin-top: 0; }

/* 扫码登录框 */
.qr-box { text-align: center; margin: 8px 0 18px; }
.qr-image { width: 100%; min-height: 92px; display: flex; align-items: center; justify-content: center;
  padding: 12px; background: var(--surface-2); border: 1px dashed var(--border); border-radius: var(--radius-sm);
  font-size: 12px; color: var(--muted); word-break: break-all; }
.qr-status { font-size: 13px; color: var(--muted); margin-top: 10px; }
#qr-form .primary-btn { width: 100%; }
#qr-form .ghost-btn { width: 100%; margin-top: 8px; }

.env-block { margin-top: 8px; padding: 14px; background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--radius-sm); }
.env-block .env-label { margin-bottom: 8px; }
.env-block select { margin-top: 0; }

/* 环境引导提示 */
.env-hint { font-size: 12.5px; line-height: 1.5; margin: 2px 0 6px; padding: 8px 10px; border-radius: 8px; }
.env-hint code { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 12px; padding: 0 3px; border-radius: 4px; }
.env-hint.ok { color: #047857; background: #ecfdf5; border: 1px solid #a7f3d0; }
.env-hint.ok code { background: #d1fae5; }
.env-hint.warn { color: #b45309; background: #fffbeb; border: 1px solid #fde68a; }
.env-hint.warn code { background: #fef3c7; }
.env-hint.warn a { color: #b91c1c; font-weight: 600; text-decoration: underline; cursor: pointer; }
.env-hint.warn a:hover { color: #7f1d1d; }

/* ============ 主布局 ============ */
.app { display: grid; grid-template-columns: 250px 1fr; grid-template-rows: 100vh; }
.sidebar {
  grid-row: 1 / -1; background: var(--side-bg); color: var(--side-text);
  display: flex; flex-direction: column; padding: 16px 12px;
}
.sidebar-brand { display: flex; align-items: center; gap: 12px; padding: 8px 10px 18px; }
.sidebar-brand .brand-logo {
  width: 40px; height: 40px; border-radius: 10px; background: var(--primary); color: #fff;
  display: flex; align-items: center; justify-content: center; font-weight: 800; font-size: 16px; letter-spacing: 1px;
}
.sidebar-brand-text { display: flex; flex-direction: column; line-height: 1.25; }
.sidebar-brand-text strong { color: #fff; font-size: 15px; }
.sidebar-brand-text span { color: var(--side-muted); font-size: 11px; }

.nav { flex: 1; overflow-y: auto; display: flex; flex-direction: column; gap: 2px; }
.nav-group { color: var(--side-muted); font-size: 11px; font-weight: 600; letter-spacing: .08em;
  text-transform: uppercase; margin: 14px 12px 4px; }
.tab {
  display: flex; align-items: center; gap: 12px; width: 100%; text-align: left;
  border: none; background: none; padding: 10px 12px; cursor: pointer;
  font-size: 14px; color: var(--side-text); border-radius: 8px; transition: background .15s, color .15s;
}
.tab .ic { width: 19px; height: 19px; flex: none; stroke: currentColor; fill: none; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.tab:hover { background: var(--side-bg-2); color: #fff; }
.tab.active { background: rgba(79,70,229,.22); color: #fff; position: relative; }
.tab.active::before { content: ""; position: absolute; left: 0; top: 8px; bottom: 8px; width: 3px; border-radius: 0 3px 3px 0; background: var(--primary-soft); }

.sidebar-foot { padding: 12px 10px 4px; border-top: 1px solid rgba(255,255,255,.07); }

/* 右侧主区域 */
.main { display: grid; grid-template-columns: 1fr 320px; grid-template-rows: auto 1fr;
  grid-template-areas: "top top" "content realtime"; min-width: 0; }
.topbar {
  grid-area: top; display: flex; justify-content: space-between; align-items: center;
  padding: 14px 24px; background: var(--surface); border-bottom: 1px solid var(--border); position: sticky; top: 0; z-index: 20;
}
.topbar-left, .topbar-right { display: flex; align-items: center; gap: 12px; }
.crumb strong { font-size: 17px; }
.user-label { color: var(--muted); font-size: 13px; }
.user-avatar {
  width: 34px; height: 34px; border-radius: 50%; background: var(--primary-light); color: var(--primary-dark);
  display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: 14px;
}
#sidebar-toggle { display: none; }

.conn { font-size: 12px; padding: 4px 11px; border-radius: 999px; border: 1px solid var(--border); }
.conn.on { color: var(--online); border-color: #bbf7d0; background: var(--online-bg); }
.conn.off { color: var(--muted); }

.content { grid-area: content; padding: 22px 24px; overflow: auto; min-width: 0; }
.tab-panel { display: none; }
.tab-panel.active { display: block; animation: fade .2s ease; }
@keyframes fade { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }

.toolbar { display: flex; gap: 12px; align-items: flex-end; margin-bottom: 18px; flex-wrap: wrap; }
.toolbar label { font-size: 13px; color: var(--muted); margin-bottom: 0; }
.toolbar select { width: auto; min-width: 180px; margin-top: 0; padding: 9px 12px;
  border: 1px solid var(--border); border-radius: var(--radius-sm); font-size: 14px; background: #fff; }
.toolbar .primary-btn { margin-left: auto; }

/* ============ 卡片 / 表格 ============ */
.table-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow-sm); overflow: hidden; }
.data-table { width: 100%; border-collapse: collapse; background: transparent; }
.data-table th, .data-table td { text-align: left; padding: 12px 16px; border-bottom: 1px solid var(--border); font-size: 13px; }
.data-table th { background: var(--surface-2); color: var(--muted); font-weight: 600; white-space: nowrap; position: sticky; top: 0; }
.data-table tbody tr { transition: background .12s; }
.data-table tbody tr:hover { background: var(--primary-light); }
.data-table tbody tr:nth-child(even) { background: #fbfcfe; }
.data-table tbody tr:nth-child(even):hover { background: var(--primary-light); }
/* 离线网关行：置灰呈现，让用户直观看到「HA 离线 / 断网」导致的状态变化 */
.data-table tbody tr.row-offline { color: var(--muted); background: #f4f5f7; }
.data-table tbody tr.row-offline:hover { background: #eef0f3; }
.data-table tbody tr.row-offline .badge-offline { opacity: .85; }
.data-table tr:last-child td { border-bottom: none; }
.data-table td { word-break: break-word; }

/* ============ 设备卡片 · 小米家风格 ============ */
/* 设备页视觉重设计：
 * 1. 大卡片（圆角 16px、柔和阴影）作为容器
 * 2. 顶部：左侧类型彩色图标 + 右侧名称/副标签 + 右上角在线圆点
 * 3. 中部：关键读数（"状态 已开启 / 亮度 80%"），不用 JSON
 * 4. 底部：iOS 风格 toggle + 自定义滑块，即时控制
 * 5. 顶部 room-tabs 横向滚动条按网关聚合（仿米家"全部/客厅/卧室"）
 */
.device-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 18px;
}

/* HA 瞬时抖动（实时刷新检测到未连通）时整体置灰降级，而非清空网格造成闪烁 */
.device-grid.ha-offline { opacity: .55; filter: grayscale(.35); transition: opacity .3s ease; }

.device-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 16px;
  box-shadow: 0 1px 4px rgba(15, 23, 42, 0.04), 0 0 0 1px rgba(15, 23, 42, 0.02);
  padding: 18px 18px 16px;
  transition: box-shadow .25s ease, transform .2s ease;
  position: relative;
  overflow: hidden;
}
.device-card:hover {
  box-shadow: 0 6px 20px rgba(15, 23, 42, 0.08), 0 0 0 1px rgba(15, 23, 42, 0.04);
  transform: translateY(-2px);
}

/* 顶部布局：图标 + 名称区 + 在线圆点 */
.device-card-head {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 14px;
}
.device-icon {
  flex: none;
  width: 52px;
  height: 52px;
  border-radius: 14px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--surface-2);
  color: var(--muted);
  transition: background .25s, color .25s;
}
.device-icon svg { width: 28px; height: 28px; display: block; }
.device-icon.light       { background: #fff7ed; color: #f59e0b; }
.device-icon.switch      { background: #eff6ff; color: #3b82f6; }
.device-icon.input_boolean,
.device-icon.input_button { background: #eef2ff; color: #6366f1; }
.device-icon.cover       { background: #f5f3ff; color: #8b5cf6; }
.device-icon.sensor,
.device-icon.binary_sensor { background: #ecfeff; color: #06b6d4; }
.device-icon.climate     { background: #fef3c7; color: #f97316; }
.device-icon.fan         { background: #f0fdfa; color: #14b8a6; }
.device-icon.lock        { background: #fef2f2; color: #ef4444; }
.device-icon.media_player{ background: #f0fdf4; color: #22c55e; }
.device-icon.camera      { background: #f1f5f9; color: #475569; }
.device-icon.vacuum      { background: #fdf4ff; color: #c026d3; }
.device-icon.humidifier  { background: #ecfeff; color: #0891b2; }
.device-icon.number,
.device-icon.select      { background: #f8fafc; color: #64748b; }
.device-icon.update,
.device-icon.integration,
.device-icon.conversation,
.device-icon.alarm_control_panel,
.device-icon.default-ic { background: #f1f5f9; color: #475569; }

.device-card-meta {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.device-name {
  font-weight: 600;
  font-size: 15px;
  color: var(--text);
  line-height: 1.3;
  word-break: break-word;
  /* 中等截断 */
  display: -webkit-box;
  -webkit-line-clamp: 1;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.device-type-label {
  font-size: 11px;
  color: var(--muted);
  line-height: 1.2;
}
.device-online {
  flex: none;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: #cbd5e1;
  box-shadow: 0 0 0 3px rgba(203, 213, 225, 0.25);
}
.device-online.on {
  background: #10b981;
  box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.18);
  animation: pulse-dot 2s ease-in-out infinite;
}
@keyframes pulse-dot {
  0%, 100% { box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.18); }
  50%      { box-shadow: 0 0 0 6px rgba(16, 185, 129, 0.10); }
}

/* 中部：关键读数（按 type 渲染，如"状态 已开启"） */
.device-card-body {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 10px 0 14px;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  margin-bottom: 12px;
  min-height: 56px;
}
.device-state-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 13px;
  color: var(--muted);
}
.device-state-row .v {
  color: var(--text);
  font-weight: 600;
  font-size: 13px;
}
.device-state-row .v.on { color: var(--primary); }
.device-state-row .v.off { color: var(--muted); }

/* 底部：操作区 */
.device-card-actions {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.device-action-row {
  display: flex;
  align-items: center;
  gap: 10px;
}
.device-action-row .label {
  flex: none;
  min-width: 36px;
  font-size: 12px;
  color: var(--muted);
}
.device-action-row .v {
  flex: none;
  font-size: 12px;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}

/* iOS 风格 toggle */
.ios-toggle {
  flex: none;
  width: 48px;
  height: 28px;
  border-radius: 14px;
  background: #e2e8f0;
  position: relative;
  cursor: pointer;
  border: none;
  padding: 0;
  margin-left: auto;
  transition: background .22s ease;
}
.ios-toggle::after {
  content: '';
  position: absolute;
  top: 3px;
  left: 3px;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.18);
  transition: left .22s ease;
}
.ios-toggle.on { background: var(--primary); }
.ios-toggle.on::after { left: 23px; }
.ios-toggle:disabled { opacity: 0.45; cursor: not-allowed; }

/* 两个并排的开关（如 cover open/close）*/
.ios-toggle-row {
  display: flex;
  gap: 8px;
  margin-left: auto;
}

/* 自定义滑块（覆盖原生 input range） */
.ios-slider {
  flex: 1;
  appearance: none;
  -webkit-appearance: none;
  height: 6px;
  background: #e2e8f0;
  border-radius: 3px;
  outline: none;
  margin: 0;
  accent-color: var(--primary);
}
.ios-slider::-webkit-slider-thumb {
  appearance: none;
  -webkit-appearance: none;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--primary);
  cursor: pointer;
  border: 2px solid #fff;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.18);
}
.ios-slider::-moz-range-thumb {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--primary);
  cursor: pointer;
  border: 2px solid #fff;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.18);
}

.device-card.offline .device-icon { filter: grayscale(0.7); opacity: 0.55; }
.device-card.offline .device-card-actions { opacity: 0.55; }

/* 旧类保留兼容（少量遗留元素可能引用） */
.device-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; }
.device-type { font-size: 11px; color: var(--muted); background: var(--surface-2); padding: 2px 9px; border-radius: 999px; border: 1px solid var(--border); }
.props { font-size: 13px; color: var(--muted); margin: 6px 0 12px; }
.props b { color: var(--text); font-weight: 600; }
.toggle-btn { padding: 7px 14px; border-radius: var(--radius-sm); border: 1px solid var(--border); background: #fff; cursor: pointer; font-size: 13px; transition: background .15s, color .15s, border-color .15s; }
.toggle-btn:hover { border-color: var(--primary); }
.toggle-btn.on { background: var(--primary); color: #fff; border-color: var(--primary); }
.slider-row { display: flex; align-items: center; gap: 8px; margin-top: 10px; font-size: 12px; color: var(--muted); }
.slider-row input[type=range] { flex: 1; accent-color: var(--primary); }
.readonly-row { font-size: 13px; color: var(--muted); margin-top: 8px; }
.changed { animation: flash .6s ease; }
@keyframes flash { 0% { background: #fff7d6; } 100% { background: transparent; } }

/* ============ 房间分组 tabs（仿米家顶部） ============ */
.room-tabs {
  display: flex;
  gap: 8px;
  margin-bottom: 18px;
  overflow-x: auto;
  scrollbar-width: thin;
  padding: 2px 0 6px;
}
.room-tabs::-webkit-scrollbar { height: 4px; }
.room-tabs::-webkit-scrollbar-thumb { background: var(--border); border-radius: 2px; }
.room-tab {
  flex: none;
  padding: 8px 16px;
  border-radius: 999px;
  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--text);
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition: background .2s, color .2s, border-color .2s;
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.room-tab:hover { border-color: var(--primary); color: var(--primary); }
.room-tab.active {
  background: var(--primary);
  color: #fff;
  border-color: var(--primary);
  box-shadow: 0 2px 6px rgba(79, 70, 229, 0.25);
}
.room-tab .count {
  display: inline-block;
  min-width: 18px;
  text-align: center;
  padding: 0 6px;
  border-radius: 9px;
  background: rgba(255, 255, 255, 0.25);
  font-size: 11px;
  line-height: 16px;
}
.room-tab:not(.active) .count {
  background: var(--surface-2);
  color: var(--muted);
}

/* ============ 场景 ============ */
.scene-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 16px; }
.scene-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow-sm); padding: 16px; }
.scene-card h3 { margin: 0 0 6px; font-size: 16px; }
.scene-card .scene-desc { color: var(--muted); font-size: 12px; margin-bottom: 10px; }
.scene-actions-count { font-size: 12px; color: var(--muted); margin-bottom: 12px; }
.scene-card .control-row { justify-content: flex-end; }

/* ============ 模态框 ============ */
.modal { position: fixed; inset: 0; background: rgba(15,23,42,.5); backdrop-filter: blur(2px);
  display: flex; align-items: center; justify-content: center; z-index: 500; animation: fade .15s ease; }
.modal.hidden { display: none; }
.modal-box { width: 460px; max-width: 92vw; max-height: 88vh; overflow: auto; background: var(--surface);
  border-radius: var(--radius-lg); padding: 24px; box-shadow: var(--shadow-lg); }
.modal-box h3 { margin: 0 0 16px; font-size: 18px; }
.modal-box label { display: block; font-size: 13px; color: var(--muted); margin-bottom: 14px; }
.modal-box input, .modal-box select { width: 100%; margin-top: 6px; padding: 10px 12px;
  border: 1px solid var(--border); border-radius: var(--radius-sm); font-size: 14px; background: #fff; }
.modal-sub { font-size: 13px; color: var(--muted); margin: 4px 0 10px; }
.modal-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 8px; }
.modal-hr { border: none; border-top: 1px solid var(--border); margin: 18px 0; }
.scene-devices { display: flex; flex-direction: column; gap: 8px; margin-bottom: 16px; max-height: 260px; overflow: auto; }
.scene-dev-row { display: flex; align-items: center; gap: 8px; font-size: 13px; }
.scene-dev-row select { margin-left: auto; padding: 6px 8px; border: 1px solid var(--border); border-radius: 6px; font-size: 13px; background: #fff; }

/* ============ 版本信息 ============ */
.version-modal-box { width: 780px; }
.version-summary { display: flex; flex-wrap: wrap; gap: 14px 22px; margin-bottom: 16px; padding: 14px 16px;
  background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--radius); }
.version-summary .stat { font-size: 13px; color: var(--muted); }
.version-summary .stat b { font-size: 16px; color: var(--text); margin-left: 5px; }
.version-table th:nth-child(1), .version-table td:nth-child(1) { width: 14%; }
.version-table th:nth-child(2), .version-table td:nth-child(2) { width: 16%; }
.version-table th:nth-child(3), .version-table td:nth-child(3) { width: 12%; }
.version-table th:nth-child(4), .version-table td:nth-child(4) { width: 58%; }
.version-table td code { font-size: 12px; color: var(--muted); background: var(--surface-2); padding: 1px 6px; border-radius: 5px; }

.version-section { margin-top: 4px; }
.version-section-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.version-section-head strong { font-size: 15px; color: var(--text); }
.upgrade-filter { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; font-size: 13px; color: var(--muted); }
.upgrade-filter select { width: auto; padding: 6px 10px; border: 1px solid var(--border); border-radius: var(--radius-sm); font-size: 13px; background: #fff; }
.upgrade-wrap { max-height: 260px; overflow: auto; }
.upgrade-table th:nth-child(1), .upgrade-table td:nth-child(1) { width: 20%; }
.upgrade-table th:nth-child(2), .upgrade-table td:nth-child(2) { width: 18%; }
.upgrade-table th:nth-child(3), .upgrade-table td:nth-child(3) { width: 20%; }
.upgrade-table th:nth-child(4), .upgrade-table td:nth-child(4) { width: 12%; }
.upgrade-table th:nth-child(5), .upgrade-table td:nth-child(5) { width: 30%; }
.upgrade-table td code { font-size: 12px; color: var(--muted); background: var(--surface-2); padding: 1px 6px; border-radius: 5px; }

/* 记录升级表单 */
.form-row { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }
.form-row label { width: 110px; flex: none; font-size: 13px; color: var(--text); }
.form-row input, .form-row select { flex: 1; padding: 9px 12px; border: 1px solid var(--border); border-radius: var(--radius-sm); font-size: 14px; background: #fff; }
.req { color: var(--danger); }

/* ============ 智能洞察 / 通知 / 审计 ============ */
.panel-sub { margin: 18px 0 8px; font-size: 14px; color: var(--text); font-weight: 600; }
.panel-sub:first-child { margin-top: 0; }

.insight-summary { display: flex; flex-wrap: wrap; gap: 18px; margin-bottom: 16px; padding: 14px 16px;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow-sm); }
.insight-summary .stat { font-size: 13px; color: var(--muted); }
.insight-summary .stat b { font-size: 16px; color: var(--text); margin-left: 4px; }

/* ---- 习惯画像（行为模型链，P1） ---- */
.habit-block { margin-bottom: 22px; padding-bottom: 20px; border-bottom: 1px dashed var(--border-strong); }
.habit-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 12px; }
.habit-head h3 { margin: 0; font-size: 15px; font-weight: 600; color: var(--text); }
.habit-hint { font-size: 12px; color: var(--muted-2); }
.habit-head .ghost-btn { margin-left: auto; }
.habit-block .insight-summary { margin-bottom: 12px; }

/* 归属 / 信号徽标：让「这台设备的规律属于谁」一眼可辨 */
.habit-pill { display: inline-block; padding: 2px 9px; border-radius: 999px; font-size: 12px; white-space: nowrap;
  border: 1px solid var(--border); background: var(--surface-2); color: var(--muted); }
.habit-pill.scope-room { background: #f5f3ff; color: #6d28d9; border-color: #ddd6fe; }
.habit-pill.scope-user { background: #ecfeff; color: #0e7490; border-color: #a5f3fc; }
.habit-pill.scope-device { background: var(--surface-2); color: var(--muted); }
.habit-pill.sig-state { background: var(--info-bg); color: var(--info); border-color: #bae6fd; }
.habit-pill.sig-control { background: var(--warn-bg); color: var(--warn); border-color: #fde68a; }
/* 批量定时型（能耗聚合与预测 / 光伏预测）：与"逐条遥测"和"画像事件"都不同，
   它按定时任务跑，所以用在线态的中性绿表示"在运行"，避免被误读成响应式模型。
   用已定义的 --online / --online-bg（深色主题下会一并切换），不自己编变量名。 */
.habit-pill.sig-batch { background: var(--online-bg); color: var(--online); border-color: #a7f3d0; }

/* 24 小时时段分布迷你柱：峰值柱用主色，其余用浅灰，一眼看出规律集中在哪几小时 */
.habit-spark { display: block; }
.habit-spark rect { fill: var(--border-strong); }
.habit-spark rect.peak { fill: var(--primary); }
.habit-spark rect.empty { fill: var(--border); opacity: .5; }
.habit-spark text { font-size: 7px; fill: var(--muted-2); }
.habit-conf { display: inline-block; min-width: 34px; font-variant-numeric: tabular-nums; }

.badge-sev { font-size: 11px; padding: 2px 9px; border-radius: 999px; border: 1px solid var(--border); background: var(--surface-2); color: var(--muted); }
.sev-high { color: #b91c1c; background: var(--danger-bg); border-color: #fecaca; }
.sev-medium { color: #b45309; background: var(--warn-bg); border-color: #fde68a; }
.sev-low { color: #0369a1; background: var(--info-bg); border-color: #bae6fd; }
/* 习惯洞察固定 INFO 级：信息性结论，不是告警，用中性灰避免与「低」告警混淆 */
.sev-info { color: #4f46e5; background: var(--primary-light); border-color: #c7d2fe; }

.badge-read, .badge-unread, .badge-success, .badge-fail { font-size: 11px; padding: 2px 9px; border-radius: 999px; border: 1px solid var(--border); }
.badge-read { color: var(--muted); background: var(--surface-2); }
.badge-unread { color: var(--primary); background: var(--primary-light); border-color: #c7d2fe; }
.badge-success { color: var(--online); background: var(--online-bg); border-color: #bbf7d0; }
.badge-fail { color: #b91c1c; background: var(--danger-bg); border-color: #fecaca; }
#unread-badge { align-self: center; }

/* ============ 实时侧栏 ============ */
.realtime-panel { grid-area: realtime; border-left: 1px solid var(--border); background: var(--surface); padding: 16px; overflow: auto; }
/* 无网关时隐藏整块实时事件流面板（用户诉求：未接入网关不应出现实时事件流） */
.realtime-panel.rt-hidden { display: none !important; }
.gw-edit { color: var(--brand, #2563eb); font-size: 12px; margin-left: 6px; cursor: pointer; text-decoration: none; }
.gw-edit:hover { text-decoration: underline; }
.gw-remark-cell { line-height: 1.6; }
.realtime-head { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; flex-wrap: wrap; }
.realtime-head strong { margin-right: auto; }
.realtime-head .ghost-btn { padding: 4px 10px; font-size: 12px; }
.realtime-feed { list-style: none; margin: 0; padding: 0; font-size: 12px; }
.realtime-feed li { padding: 9px 11px; border: 1px solid var(--border); border-radius: 8px; margin-bottom: 8px; background: #fbfdff; border-left: 3px solid var(--brand, #2563eb); }
.realtime-feed li.lv-warn { border-left-color: #d97706; }
.realtime-feed li.lv-error { border-left-color: #dc2626; }
.realtime-feed li.lv-info { border-left-color: #2563eb; }
.realtime-feed .ts { color: var(--muted); font-size: 11px; display: flex; justify-content: space-between; gap: 8px; }
.realtime-feed .ts .kind { color: var(--brand, #2563eb); font-weight: 600; }
.realtime-feed .ev { color: var(--text); margin-top: 4px; line-height: 1.5; word-break: break-word; }

/* ============ 待导入设备区（米家 ghost 卡片） ============ */
.discovered-wrap { margin-top: 28px; padding-top: 20px; border-top: 1px dashed var(--border); }
.discovered-head {
  display: flex; align-items: baseline; gap: 10px; margin-bottom: 14px; flex-wrap: wrap;
}
.discovered-head strong { font-size: 15px; color: var(--text); }
.discovered-head .muted { font-size: 12px; }

/* 设备状态（只读提示项：HA 传感器等，不可操作） */
.sensor-section { margin-top: 28px; padding-top: 20px; border-top: 1px dashed var(--border); }
.section-subhead {
  display: flex; align-items: baseline; gap: 10px; margin-bottom: 14px; flex-wrap: wrap;
}
.section-subhead strong { font-size: 15px; color: var(--text); }
.section-subhead .muted { font-size: 12px; }
.inline-check { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; color: var(--muted); }
.inline-check input { width: auto; margin: 0; }

/* 待导入卡：虚线边框 + 半透明 + 偏暗视觉，区分于正式卡 */
.discovered-card {
  border: 1px dashed var(--border);
  background: repeating-linear-gradient(
    135deg,
    rgba(99, 102, 241, 0.025) 0,
    rgba(99, 102, 241, 0.025) 12px,
    transparent 12px,
    transparent 24px
  ), var(--surface);
  position: relative;
}
.discovered-card .device-card-head { margin-bottom: 10px; }
.discovered-card .device-card-body { display: none; }  /* 待导入设备不显示控制 */
.discovered-card .device-card-actions { display: none; }
.discovered-card .import-btn-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 12px;
  color: var(--muted);
  margin-top: 4px;
}
.import-btn {
  padding: 6px 14px;
  font-size: 12px;
  font-weight: 500;
  border-radius: 999px;
  border: 1px solid var(--primary);
  background: var(--primary);
  color: #fff;
  cursor: pointer;
  transition: filter .2s, transform .15s;
}
.import-btn:hover { filter: brightness(1.08); }
.import-btn:active { transform: scale(0.96); }
.import-btn:disabled { opacity: 0.55; cursor: not-allowed; }

/* ============ 历史事件弹窗 ============ */
.events-modal-box { width: 780px; }
.events-filter { display: flex; gap: 12px; align-items: flex-end; flex-wrap: wrap; margin-bottom: 14px; }
.events-filter label { margin-bottom: 0; flex: 1 1 150px; }
.events-filter select { margin-top: 4px; padding: 7px 10px; font-size: 13px; }
.events-wrap { max-height: 46vh; overflow: auto; border: 1px solid var(--border); border-radius: 8px; }
.events-table td { font-size: 12px; vertical-align: top; }
.events-table td:first-child { white-space: nowrap; color: var(--muted); }
.events-pager { display: flex; align-items: center; gap: 12px; margin-top: 12px; }
.events-pager .muted { font-size: 12px; }
.ev-level-badge { display: inline-block; padding: 1px 7px; border-radius: 999px; font-size: 11px; border: 1px solid; }
.ev-level-badge.info { color: #1d4ed8; background: #eff6ff; border-color: #bfdbfe; }
.ev-level-badge.warn { color: #b45309; background: #fffbeb; border-color: #fde68a; }
.ev-level-badge.error { color: #b91c1c; background: #fef2f2; border-color: #fecaca; }

/* ============ Toast ============ */
.toast {
  position: fixed; bottom: 24px; left: 50%; transform: translateX(-50%);
  background: #1f2733; color: #fff; padding: 11px 20px; border-radius: 10px; font-size: 13px;
  box-shadow: var(--shadow-lg); z-index: 999; max-width: 80vw;
}

/* ============ 加载遮罩 ============ */
.loading-overlay { position: fixed; inset: 0; background: rgba(255,255,255,.6); backdrop-filter: blur(2px);
  display: flex; align-items: center; justify-content: center; z-index: 800; }
.loading-overlay.hidden { display: none; }
.spinner { width: 42px; height: 42px; border: 4px solid var(--primary-light); border-top-color: var(--primary);
  border-radius: 50%; animation: spin .8s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

/* ============ 空状态 ============ */
.empty-state { text-align: center; padding: 48px 20px; color: var(--muted); }
.empty-state .em-icon { font-size: 40px; opacity: .35; margin-bottom: 10px; }

/* ============ 配置菜单：四类子标签 + 类别面板 ============ */
.subtabs { display: flex; gap: 8px; flex-wrap: wrap; margin: 4px 0 14px; }
.subtab { border: 1px solid var(--border, #e3e8ef); background: #fff; color: var(--text, #2b3445);
  padding: 8px 16px; border-radius: 999px; cursor: pointer; font-size: 13px; transition: all .15s; }
.subtab:hover { border-color: var(--primary, #4f46e5); color: var(--primary, #4f46e5); }
.subtab.active { background: var(--primary, #4f46e5); border-color: var(--primary, #4f46e5); color: #fff; }
.cat-panel { animation: fadeIn .18s ease; }
.cat-panel.hidden { display: none; }
@keyframes fadeIn { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
.empty-state .em-title { font-size: 15px; color: var(--text); font-weight: 600; margin-bottom: 4px; }
.empty-state .em-desc { font-size: 13px; }
.empty-hint { text-align: center; color: var(--muted); padding: 28px 12px; font-size: 13px; }

/* ============ 响应式 ============ */
@media (max-width: 1100px) {
  .app { grid-template-columns: 72px 1fr; }
  .sidebar { padding: 16px 8px; }
  .sidebar-brand-text, .nav-group, .tab span:not(.ic) { display: none; }
  .tab { justify-content: center; padding: 12px 0; }
  .tab .ic { width: 22px; height: 22px; }
  .sidebar-foot { display: none; }
}
@media (max-width: 860px) {
  .login-wrap { flex-direction: column; }
  .login-brand { display: none; }
  .login-form-side { max-width: none; }
  .app { grid-template-columns: 1fr; grid-template-rows: 100vh; }
  .sidebar { position: fixed; left: 0; top: 0; bottom: 0; width: 250px; z-index: 60; transform: translateX(-100%); transition: transform .2s; }
  .sidebar.open { transform: none; }
  .main { grid-template-columns: 1fr; grid-template-areas: "top" "content"; }
  .realtime-panel { display: none; }
  #sidebar-toggle { display: inline-flex; }
  body.nav-open .sidebar-backdrop { display: block; }
  body.nav-open { overflow: hidden; }
}

/* ============ 全局主题过渡 ============ */
body, .login-card, .topbar, .sidebar, .table-card, .device-card, .scene-card,
.modal-box, .version-summary, .insight-summary, .realtime-panel, .realtime-feed li,
.env-block, .login-form-side, .loading-overlay {
  transition: background-color .2s ease, border-color .2s ease, color .2s ease;
}

/* ============ 暗色主题 ============ */
[data-theme="dark"] {
  --bg: #0b1220;
  --surface: #111a2c;
  --surface-2: #0f172a;
  --border: #1e2a44;
  --border-strong: #2a3a5c;
  --text: #e2e8f0;
  --muted: #94a3b8;
  --muted-2: #64748b;
  --primary-light: #1e1b4b;
  --primary-soft: #818cf8;
  --online-bg: #052e1a;
  --online: #4ade80;
  --offline-bg: #1e293b;
  --danger-bg: #2a0f10;
  --danger: #f87171;
  --warn-bg: #2a1f08;
  --warn: #fbbf24;
  --info-bg: #0c2236;
  --info: #38bdf8;
  --side-bg: #060a14;
  --side-bg-2: #0a1020;
  --side-text: #cbd5e1;
  --shadow-sm: 0 1px 2px rgba(0,0,0,.4), 0 1px 3px rgba(0,0,0,.5);
  --shadow: 0 4px 12px rgba(0,0,0,.4), 0 2px 4px rgba(0,0,0,.3);
  --shadow-lg: 0 20px 40px rgba(0,0,0,.6);
}
[data-theme="dark"] .icon-btn, [data-theme="dark"] .ghost-btn, [data-theme="dark"] .toggle-btn,
[data-theme="dark"] .modal-box input, [data-theme="dark"] .modal-box select,
[data-theme="dark"] .form-row input, [data-theme="dark"] .form-row select,
[data-theme="dark"] .scene-dev-row select, [data-theme="dark"] .toolbar select,
[data-theme="dark"] #login-form input, [data-theme="dark"] #register-form input,
[data-theme="dark"] .login-card select, [data-theme="dark"] .upgrade-filter select,
[data-theme="dark"] .link-btn { background: var(--surface); color: var(--text); }
[data-theme="dark"] .data-table tbody tr:nth-child(even) { background: rgba(255,255,255,.025); }
[data-theme="dark"] .data-table tbody tr.row-offline { color: #8a93a3; background: rgba(255,255,255,.04); }
[data-theme="dark"] .data-table tbody tr.row-offline:hover { background: rgba(255,255,255,.07); }
[data-theme="dark"] .loading-overlay { background: rgba(0,0,0,.6); }
[data-theme="dark"] .badge-online { border-color: #14532d; }
[data-theme="dark"] .realtime-feed li { background: var(--surface); }

/* 设备卡 · 暗色主题适配 */
[data-theme="dark"] .device-card {
  background: var(--surface);
  border-color: rgba(255, 255, 255, 0.06);
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3), 0 0 0 1px rgba(255, 255, 255, 0.02);
}
[data-theme="dark"] .device-card:hover {
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(99, 102, 241, 0.18);
}
[data-theme="dark"] .device-card-body { border-color: rgba(255, 255, 255, 0.06); }
[data-theme="dark"] .device-icon.light       { background: rgba(245, 158, 11, 0.12); color: #fbbf24; }
[data-theme="dark"] .device-icon.switch      { background: rgba(59, 130, 246, 0.12); color: #60a5fa; }
[data-theme="dark"] .device-icon.input_boolean,
[data-theme="dark"] .device-icon.input_button { background: rgba(99, 102, 241, 0.12); color: #818cf8; }
[data-theme="dark"] .device-icon.cover       { background: rgba(139, 92, 246, 0.12); color: #a78bfa; }
[data-theme="dark"] .device-icon.sensor,
[data-theme="dark"] .device-icon.binary_sensor { background: rgba(6, 182, 212, 0.12); color: #22d3ee; }
[data-theme="dark"] .device-icon.climate     { background: rgba(249, 115, 22, 0.12); color: #fb923c; }
[data-theme="dark"] .device-icon.fan         { background: rgba(20, 184, 166, 0.12); color: #2dd4bf; }
[data-theme="dark"] .device-icon.lock        { background: rgba(239, 68, 68, 0.12); color: #f87171; }
[data-theme="dark"] .device-icon.media_player{ background: rgba(34, 197, 94, 0.12); color: #4ade80; }
[data-theme="dark"] .device-icon.camera,
[data-theme="dark"] .device-icon.update,
[data-theme="dark"] .device-icon.integration,
[data-theme="dark"] .device-icon.conversation,
[data-theme="dark"] .device-icon.alarm_control_panel,
[data-theme="dark"] .device-icon.default-ic { background: rgba(148, 163, 184, 0.12); color: #94a3b8; }
[data-theme="dark"] .device-icon.vacuum      { background: rgba(192, 38, 211, 0.12); color: #e879f9; }
[data-theme="dark"] .device-icon.humidifier  { background: rgba(8, 145, 178, 0.12); color: #22d3ee; }
[data-theme="dark"] .device-icon.number,
[data-theme="dark"] .device-icon.select      { background: rgba(148, 163, 184, 0.10); color: #94a3b8; }
[data-theme="dark"] .ios-toggle { background: rgba(255, 255, 255, 0.15); }
[data-theme="dark"] .ios-toggle.on { background: var(--primary); }
[data-theme="dark"] .ios-slider { background: rgba(255, 255, 255, 0.12); }
[data-theme="dark"] .room-tab:not(.active) {
  background: var(--surface);
  border-color: rgba(255, 255, 255, 0.06);
}
[data-theme="dark"] .room-tab:not(.active) .count { background: rgba(255, 255, 255, 0.06); }
[data-theme="dark"] .discovered-card {
  background:
    repeating-linear-gradient(135deg, rgba(129, 140, 248, 0.05) 0, rgba(129, 140, 248, 0.05) 12px, transparent 12px, transparent 24px),
    var(--surface);
  border-color: rgba(255, 255, 255, 0.08);
}

/* ============ 桌面侧栏折叠（用户手动）============ */
.app { transition: grid-template-columns .22s ease; }
.app.collapsed { grid-template-columns: 64px 1fr; }

/* —— 折叠态：仅图标，文字统一退场（用 visibility+opacity 双重隐藏，避免任何浏览器渲染残留文字） —— */
.app.collapsed .sidebar-brand-text,
.app.collapsed .nav-group,
.app.collapsed .tab .lbl,
.app.collapsed #conn-indicator,
.app.collapsed #sidebar-collapse .lbl-text,
.app.collapsed .sidebar-user-text,
.app.collapsed .sidebar-user .user-name,
.app.collapsed .sidebar-user .user-action {
  display: none !important;
  visibility: hidden !important;
  opacity: 0 !important;
  width: 0 !important; height: 0 !important;
  font-size: 0 !important; line-height: 0 !important;
  margin: 0 !important; padding: 0 !important;
  overflow: hidden !important;
}
/* 折叠态：连接状态条 = 纯圆点
   注意：必须用 text-indent 负值 + white-space:nowrap 把文字整体推出可视区，
   否则 "实时: 未连接" 会在 10px 宽的盒子里逐字换行，堆叠成乱码。 */
.app.collapsed #conn-indicator {
  width: 10px !important; height: 10px !important;
  min-width: 10px !important;
  padding: 0 !important; margin: 6px auto !important;
  border: none !important;
  border-radius: 50%;
  background: #f59e0b; box-shadow: 0 0 0 3px rgba(245, 158, 11, .18);
  display: block !important;
  visibility: visible !important; opacity: 1 !important;
  overflow: hidden !important;
  font-size: 0 !important; line-height: 0 !important;
  color: transparent !important;
  text-indent: -9999px !important;
  white-space: nowrap !important;
  flex: none !important;
  transition: background .2s, box-shadow .2s;
}
.app.collapsed #conn-indicator.on {
  background: #22c55e; box-shadow: 0 0 0 3px rgba(34, 197, 94, .22);
}

/* —— 折叠态：品牌区居中 —— */
.app.collapsed .sidebar-brand { justify-content: center; padding: 14px 0 18px; gap: 0; }
.app.collapsed .sidebar-brand .brand-logo {
  width: 40px; height: 40px; font-size: 16px;
  border-radius: 11px;
  box-shadow: 0 4px 14px rgba(79, 70, 229, .45);
}

/* —— 折叠态：图标按钮 —— */
.app.collapsed .tab { justify-content: center; padding: 11px 0; position: relative; }
.app.collapsed .tab .ic { width: 21px; height: 21px; }
.app.collapsed .sidebar { padding: 12px 8px; }

/* —— 折叠态 hover tooltip（设备/网关/...中文标签） —— */
.app.collapsed .tab[data-tab]:hover::after {
  content: attr(data-tip);
  position: absolute;
  left: calc(100% + 8px); top: 50%; transform: translateY(-50%);
  background: #0f172a; color: #f8fafc;
  font-size: 12px; padding: 6px 10px; border-radius: 6px;
  white-space: nowrap; pointer-events: none;
  box-shadow: 0 6px 18px rgba(0,0,0,.25);
  z-index: 50;
}
.app.collapsed .tab[data-tab]:hover::before {
  content: ""; position: absolute;
  left: calc(100% + 2px); top: 50%; transform: translateY(-50%);
  border: 6px solid transparent; border-right-color: #0f172a;
  pointer-events: none; z-index: 50;
}

/* —— 折叠态：nav 滚动条 —— */
.app.collapsed .nav {
  scrollbar-width: thin;
  scrollbar-color: rgba(203,213,225,.25) transparent;
  padding-bottom: 8px;
}
.app.collapsed .nav::-webkit-scrollbar { width: 4px; }
.app.collapsed .nav::-webkit-scrollbar-thumb { background: rgba(203,213,225,.18); border-radius: 4px; }
.app.collapsed .nav::-webkit-scrollbar-thumb:hover { background: rgba(203,213,225,.32); }
.app.collapsed .nav::-webkit-scrollbar-track { background: transparent; }

/* —— 折叠态：底部只保留 3 个图标（连接点 + 用户头像 + 折叠） —— */
.app.collapsed .sidebar-foot {
  display: flex; flex-direction: column;
  align-items: center; gap: 6px;
  padding: 8px 0 6px; border-top: 1px solid rgba(255,255,255,.06);
}
.app.collapsed #conn-indicator {
  /* 折叠态：仅显示 10px 橙色圆点（dot 规则已在上面 .app.collapsed #conn-indicator 处定义过） */
  visibility: visible;
  opacity: 1;
}
.app.collapsed #conn-indicator.on {
  background: #22c55e; box-shadow: 0 0 0 3px rgba(34, 197, 94, .22);
}
.app.collapsed .sidebar-user {
  width: 36px; height: 36px; border-radius: 50%;
  background: var(--primary-light);
  color: var(--primary-dark);
  display: flex; align-items: center; justify-content: center;
  font-weight: 700; font-size: 13px;
  border: 1px solid rgba(255,255,255,.08);
  cursor: pointer;
  margin: 0 !important;
  padding: 0 !important;
  text-align: center;
  overflow: hidden !important;
}
.app.collapsed .sidebar-user .user-avatar-sm { margin: 0 auto; }
.app.collapsed .sidebar-user:hover { background: var(--primary); color: #fff; }
/* 折叠态侧栏用户块：显示 tooltip 提示注销 */
.app.collapsed .sidebar-user::after {
  content: "注销账号";
  position: absolute;
  left: calc(100% + 8px); top: 50%; transform: translateY(-50%);
  background: #0f172a; color: #f8fafc;
  font-size: 12px; padding: 6px 10px; border-radius: 6px;
  white-space: nowrap; pointer-events: none;
  box-shadow: 0 6px 18px rgba(0,0,0,.25);
  opacity: 0; transition: opacity .15s;
  z-index: 50;
}
.app.collapsed .sidebar-user:hover::after { opacity: 1; }
.app.collapsed .sidebar-user { position: relative; }
.app.collapsed #sidebar-collapse {
  justify-content: center;
  width: 36px; height: 36px;
  padding: 0;
  border-radius: 50%;
  background: rgba(255,255,255,.05);
  border: 1px solid rgba(255,255,255,.08);
  transition: background .15s, transform .2s;
}
.app.collapsed #sidebar-collapse:hover { background: var(--primary); color: #fff; transform: translateY(-1px); border-color: var(--primary); }
.app.collapsed #sidebar-collapse svg { transform: rotate(180deg); width: 14px; height: 14px; }

/* —— 折叠态：分组标题退化为一条细分隔线，保留视觉分组感（避免所有图标糊成一坨）—— */
.app.collapsed .nav-group:not(:first-child) {
  display: block !important;
  visibility: visible !important;
  height: 1px !important;
  min-height: 1px !important;
  width: 28px !important;
  margin: 10px auto !important;
  padding: 0 !important;
  font-size: 0 !important;
  line-height: 0 !important;
  color: transparent !important;
  text-indent: -9999px !important;
  white-space: nowrap !important;
  overflow: hidden !important;
  background: rgba(255, 255, 255, .10) !important;
  border-radius: 1px;
}
.app.collapsed .nav-group:first-child {
  display: block !important;
  visibility: visible !important;
  height: 4px !important;
  min-height: 4px !important;
  margin: 0 0 6px !important;
  padding: 0 !important;
  font-size: 0 !important;
  line-height: 0 !important;
  color: transparent !important;
  overflow: hidden !important;
  background: transparent !important;
}

/* —— 折叠态：图标按钮 hover 圆角底，点击区域更明确 —— */
.app.collapsed .tab {
  border-radius: 10px;
  margin: 2px 0;
  transition: background .15s, color .15s;
}
.app.collapsed .tab:hover { background: rgba(255, 255, 255, .08); }
.app.collapsed .tab.active { background: var(--primary); color: #fff; }
.app.collapsed .tab.active::before,
.app.collapsed .tab.active::after { display: none; }

/* —— 折叠态：底部三件（连接点 / 头像 / 折叠）间距与呼吸感 —— */
.app.collapsed .sidebar-foot { gap: 10px; padding: 10px 0 12px; }
.app.collapsed .sidebar-user {
  width: 34px; height: 34px;
  border-radius: 50%;
  transition: background .15s, transform .15s, color .15s;
}
.app.collapsed .sidebar-user:hover { transform: translateY(-1px); }

/* ============ 侧栏底部用户区（折叠态居中头像，展开态完整信息+注销） ============ */
.sidebar-user {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px; margin: 4px 0 6px;
  border-radius: 8px;
  transition: background .15s;
  background: rgba(255,255,255,.04);
  border: 1px solid rgba(255,255,255,.06);
}
.sidebar-user:hover { background: rgba(255,255,255,.08); }
.sidebar-user .user-avatar-sm {
  width: 32px; height: 32px; border-radius: 50%;
  background: var(--primary-light); color: var(--primary-dark);
  display: flex; align-items: center; justify-content: center;
  font-weight: 700; font-size: 13px;
  flex: none;
}
.sidebar-user .sidebar-user-text {
  display: flex; flex-direction: column; line-height: 1.2; min-width: 0;
}
.sidebar-user .user-name {
  color: #fff; font-size: 13px; font-weight: 600;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  max-width: 130px;
}
.sidebar-user .user-role {
  color: var(--side-muted); font-size: 11px;
}
.sidebar-user .user-action {
  margin-left: auto; font-size: 11px;
  color: #fca5a5; border: none; background: none; cursor: pointer;
  padding: 4px 8px; border-radius: 6px;
  transition: background .15s, color .15s;
}
.sidebar-user .user-action:hover { background: rgba(239, 68, 68, .18); color: #fecaca; }

/* ===== 顶栏 #conn-indicator（与侧栏的 id 冲突，定义为内联 dot） ===== */
/* 注：顶栏 no conn-indicator，仅侧栏底部一个。用 sidebar 限定即可 */

/* 折叠按钮（展开态） */
#sidebar-collapse {
  background: none; border: none; color: var(--side-muted); cursor: pointer;
  width: 100%; padding: 8px 10px; display: flex; align-items: center; gap: 8px;
  border-radius: 8px; font-size: 13px; transition: background .15s, color .15s;
  margin-top: 2px;
}
#sidebar-collapse:hover { background: var(--side-bg-2); color: #fff; }
#sidebar-collapse svg { width: 16px; height: 16px; transition: transform .2s; flex: none; }
#theme-toggle { font-size: 16px; }

/* ============ 移动抽屉 backdrop（可点击关闭）============ */
.sidebar-backdrop { position: fixed; inset: 0; background: rgba(0,0,0,.4); z-index: 55; display: none; animation: fade .15s ease; }

/* ============ 骨架屏 ============ */
.skel {
  background: linear-gradient(90deg, var(--surface-2) 25%, var(--border) 37%, var(--surface-2) 63%);
  background-size: 400% 100%; animation: shimmer 1.4s ease infinite;
  border-radius: 6px; color: transparent;
}
.skel-line { height: 12px; margin-bottom: 8px; }
.skel-block { height: 80px; margin-bottom: 10px; border-radius: var(--radius); }
@keyframes shimmer { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }

/* ============ 登录品牌场景大图 ============ */
.login-brand {
  position: relative; overflow: hidden;
  background:
    linear-gradient(150deg, rgba(67,56,202,.78) 0%, rgba(14,165,233,.45) 100%),
    url('../img/login-hero.png') center/cover no-repeat;
}
.login-brand::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(ellipse at 28% 50%, rgba(15,23,42,.55) 0%, rgba(15,23,42,0) 65%);
}
.login-brand > * { position: relative; z-index: 1; }
[data-theme="dark"] .login-brand {
  background:
    linear-gradient(150deg, rgba(11,18,32,.7) 0%, rgba(14,165,233,.3) 100%),
    url('../img/login-hero.png') center/cover no-repeat;
}

/* ============ 侧栏用户菜单（点头像/展开态点击展开）============ */
.sidebar-user { position: relative; }
.sidebar-user-menu {
  position: absolute;
  left: calc(100% + 8px); bottom: 0;
  min-width: 180px;
  background: #ffffff;
  color: #1f2937;
  border: 1px solid #e5e7eb;
  border-radius: 10px;
  box-shadow: 0 10px 30px rgba(0,0,0,.18), 0 2px 6px rgba(0,0,0,.08);
  padding: 6px;
  z-index: 80;
  animation: popIn .14s ease-out;
}
@keyframes popIn { from { opacity: 0; transform: translateY(4px) scale(.97); } to { opacity: 1; transform: none; } }
.sidebar-user-menu .sum-item {
  display: flex; align-items: center; gap: 8px;
  width: 100%; padding: 8px 10px;
  border: none; background: transparent; cursor: pointer;
  border-radius: 6px;
  font-size: 13px; color: #1f2937;
  text-align: left;
  transition: background .12s, color .12s;
}
.sidebar-user-menu .sum-item:hover { background: #f1f5f9; }
.sidebar-user-menu .sum-item.danger { color: #b91c1c; }
.sidebar-user-menu .sum-item.danger:hover { background: #fef2f2; color: #991b1b; }
.sidebar-user-menu .sum-item[disabled] {
  color: #94a3b8; cursor: not-allowed; opacity: .65;
}
.sidebar-user-menu .sum-item[disabled]:hover { background: transparent; color: #94a3b8; }

/* 折叠态下：菜单从右侧弹出 */
.app.collapsed .sidebar-user-menu {
  left: calc(100% + 12px);
  bottom: 0;
}
[data-theme="dark"] .sidebar-user-menu {
  background: #1e293b; color: #e2e8f0; border-color: #334155;
  box-shadow: 0 10px 30px rgba(0,0,0,.45), 0 2px 6px rgba(0,0,0,.3);
}
[data-theme="dark"] .sidebar-user-menu .sum-item { color: #e2e8f0; }
[data-theme="dark"] .sidebar-user-menu .sum-item:hover { background: #334155; }
[data-theme="dark"] .sidebar-user-menu .sum-item.danger { color: #fca5a5; }
[data-theme="dark"] .sidebar-user-menu .sum-item.danger:hover { background: #450a0a; color: #fecaca; }

/* ===== 运营中心（admin） ===== */
.stat-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:12px;margin:8px 0 4px}
.stat-grid .stat{background:#fff;border:1px solid #eef0f4;border-radius:10px;padding:14px 16px}
.stat-grid .stat .num{font-size:26px;font-weight:700;color:#1f2d3d;line-height:1.1}
.stat-grid .stat .num.ok{color:#16a34a}
.stat-grid .stat .num.warn{color:#d97706}
.stat-grid .stat .lbl{font-size:12px;color:#8a94a6;margin-top:6px}
.admin-cols{display:grid;grid-template-columns:1fr 1fr;gap:16px}
.admin-cols h4.panel-sub{margin-top:6px}
@media(max-width:900px){.admin-cols{grid-template-columns:1fr}}

/* 监控告警：状态灯与级别徽标 */
.stat-grid .stat .light{width:14px;height:14px;border-radius:50%;display:inline-block;margin-bottom:8px;box-shadow:0 0 0 3px rgba(0,0,0,.04)}
.stat-grid .stat .light.ok{background:#16a34a}
.stat-grid .stat .light.warn{background:#d97706}
.stat-grid .stat .light.err{background:#dc2626}
.stat-grid .stat .sub{font-size:11px;color:#aab2c0;margin-top:4px}
.stat-grid .stat .num.err{color:#dc2626}
.badge.lvl-ok{background:#dcfce7;color:#15803d;border-color:#bbf7d0}
.badge.lvl-info{background:#e0f2fe;color:#0369a1;border-color:#bae6fd}
.badge.lvl-warn{background:#fef3c7;color:#b45309;border-color:#fde68a}
.badge.lvl-error{background:#fee2e2;color:#b91c1c;border-color:#fecaca}
.badge.lvl-ok,.badge.lvl-info,.badge.lvl-warn,.badge.lvl-error{display:inline-block;padding:2px 10px;border-radius:999px;font-size:12px;font-weight:600;border:1px solid transparent}

/* 运营中心：备份/恢复日志区 */
.backup-log{margin:0;padding:10px 12px;border-radius:8px;background:rgba(127,127,127,.08);
  font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12px;line-height:1.6;
  white-space:pre-wrap;word-break:break-all;max-height:320px;overflow:auto}
.data-table .btn-dry,.data-table .btn-restore{padding:2px 10px;font-size:12px;margin-right:6px}
.data-table .btn-restore{color:#b91c1c}

/* ============ 视图模式：平台管理员 vs 租户 ============
   admin（SUPER_ADMIN）登录后 body 会带上 .platform-mode：
     · 隐藏全部租户业务导航（设备 / 网关 / 场景 / 空间 / 租户 / 配置 / 操作记录 / 在线终端 / 智能洞察 / 通知）
       —— 这些已统一并入「平台运营 → 运营总览」或不再对管理员展示；
     · 只显示 data-scope="platform" 的平台运营导航（运营总览 / 软件与OTA / 监控告警 / 操作与联动记录 / 备份恢复）。
   普通租户默认隐藏 platform 项，因此租户侧界面与改造前完全一致。
   （无需 !important：折叠态样式本身带 !important，优先级更高，链路不受影响。） */
.nav > [data-scope="platform"] { display: none; }
body.platform-mode .nav > [data-scope="platform"] { display: flex; }
body.platform-mode .nav > p.nav-group[data-scope="platform"] { display: block; }
body.platform-mode .nav > [data-scope="tenant"] { display: none; }

/* 管理员视图下隐藏仅供租户使用的顶栏/侧栏入口 */
body.platform-mode .sidebar-user { cursor: default; }

/* ============ 智能提醒（P2） ============
   复用 .habit-block / .habit-head / .habit-summary 的骨架（两区块视觉上应是一组，
   因为它们讲的是同一件事的两半：学到的规律，和据此给出的提醒）。
   这里只补提醒特有的：规则徽标、设置面板、说明文字。 */
.reminder-block { border-bottom: none; margin-bottom: 26px; }

/* 规则徽标：把「该关未关」和「该开未开」两类在视觉上区分开 ——
   前者安全相关（WARNING 橙），后者是习惯偏差（INFO 蓝）。 */
.rule-badge { display: inline-block; padding: 2px 9px; border-radius: 999px; font-size: 12px;
  white-space: nowrap; border: 1px solid var(--border); background: var(--surface-2); color: var(--muted); }
.rule-badge.rule-still-on { color: var(--warn); background: var(--warn-bg); border-color: #fde68a; }
.rule-badge.rule-not-acted { color: var(--info); background: var(--info-bg); border-color: #bae6fd; }

/* 状态迁移提示：期望 vs 实际并排，矛盾关系一眼可见 */
.state-pill { display: inline-block; padding: 1px 8px; border-radius: 6px; font-size: 12px;
  border: 1px solid var(--border); background: var(--surface-2); color: var(--muted); }
.state-pill.state-on { color: var(--online); background: var(--online-bg); border-color: #bbf7d0; }
.state-pill.state-off { color: var(--muted); background: var(--offline-bg); }
.state-arrow { color: var(--muted-2); font-size: 12px; margin: 0 4px; }

/* 设置面板：默认折叠（常态无需改动），展开后单行网格，窄屏自动换行 */
.reminder-setting { margin: 0 0 12px; border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--surface-2); padding: 10px 14px; }
.reminder-setting > summary { cursor: pointer; font-size: 13px; color: var(--muted); font-weight: 600; }
.reminder-setting > summary:hover { color: var(--primary); }
.reminder-form { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 14px; margin-top: 12px; }
.rm-field { display: flex; flex-direction: column; gap: 5px; font-size: 12px; color: var(--muted); }
.rm-field input[type="number"], .rm-field select { padding: 6px 9px; border: 1px solid var(--border);
  border-radius: var(--radius-sm); font-size: 13px; background: #fff; color: var(--text); }
.rm-field input[type="number"] { width: 72px; }
.rm-field input[type="checkbox"] { width: 16px; height: 16px; accent-color: var(--primary); margin: 3px 0; }
.rm-msg { font-size: 12px; color: var(--online); }
.rm-msg.err { color: var(--danger); }
.rm-note { margin: 10px 0 0; font-size: 12px; color: var(--muted-2); line-height: 1.7; }

/* ---------------- AI 模型（P3 平台面） ---------------- */
/* 参数列表默认折叠：8 个模型 × 若干参数的展开会让目录表高到不可读，
   而运维多数时候只关心「有哪些模型、是否生效」，参数是排查时才看的细节。 */
.model-params > summary { cursor: pointer; font-size: 12px; color: var(--primary); white-space: nowrap; }
.model-params > summary:hover { text-decoration: underline; }
.model-params ul { margin: 8px 0 0; padding-left: 16px; font-size: 12px; line-height: 1.8; }
.model-params li { margin-bottom: 8px; color: var(--text); }
.model-params li b { font-weight: 600; }
.model-params li code { font-size: 11px; padding: 1px 5px; border-radius: 4px;
  background: var(--surface-2); border: 1px solid var(--border); }
.model-params li .muted { font-size: 11px; }

/* 模型参数设置输入框。宽度给足（180px）是因为阈值类参数可能是 2000 或 0.85 这样的
   多字符数值，窄输入框会让运维在核对当前值时看漏一位数字 —— 那是配置类界面最不该出的错。 */
.param-input {
  width: 180px; padding: 4px 8px; font-size: 13px;
  border: 1px solid var(--border-strong); border-radius: 6px;
  background: var(--surface); color: var(--text);
  font-variant-numeric: tabular-nums;
}
.param-input:focus { outline: none; border-color: var(--primary); }
#admin-model-param-tenant { max-width: 320px; }

/* ---------------- 联动建议 / 用电与发电（v1.2.0 智能模型优化） ---------------- */
/* 这两块复用 .habit-block 的骨架（同属「学到的规律 → 据此行动」这一组），
   只补一点视觉区分：建议块给一条左侧强调线，让人一眼看出"这里可以点采纳"。 */
.suggestion-block { border-left: 3px solid var(--primary); padding-left: 14px; }
.energy-block .panel-sub { margin: 16px 0 8px; }
#energy-forecast-note { margin-top: 8px; line-height: 1.7; }

/* ---------------- 设备格式对齐 / 设备码追踪 / 客户端发布（v1.4.0） ---------------- */

/* 共享输入控件样式。
   注意：`.inp` 与 `.ota-form` 此前只在 HTML 里用了类名、CSS 从未定义，
   导致 OTA 建包表单的输入框是裸的（无边框、不占宽）。这里补齐，
   顺序放在文件末尾是为了不改动上面既有规则 —— 新老元素一起受益。 */
.inp { width: 100%; padding: 9px 12px; border: 1px solid var(--border);
  border-radius: var(--radius-sm); font-size: 14px; background: var(--surface); color: var(--text);
  font-family: inherit; }
.inp:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px rgba(79,70,229,.12); }
textarea.inp { resize: vertical; line-height: 1.6; }
.ota-form, .rel-form { display: flex; flex-wrap: wrap; gap: 12px; align-items: flex-end;
  padding: 14px 16px; }
.ota-form .inp { flex: 1; min-width: 140px; }

/* 发布表单：字段多且宽度不齐，用网格对齐标签，避免"标签顶着输入框"的挤压感 */
.rel-form label { display: flex; flex-direction: column; gap: 6px; flex: 1 1 200px;
  font-size: 12px; color: var(--muted); }
.rel-form .rel-notes { flex: 1 1 100%; }
.rel-form .rel-actions { flex: 1 1 100%; display: flex; justify-content: flex-end; gap: 10px; }

/* 分段控件：两个入口（云端新建 / 导入已发现）在同一弹窗内切换 */
.seg-row { display: inline-flex; gap: 4px; padding: 4px; border-radius: 999px;
  background: var(--surface-2); border: 1px solid var(--border); margin: 2px 0 16px; }
.seg { border: none; background: transparent; color: var(--muted); font-size: 13px;
  padding: 7px 16px; border-radius: 999px; cursor: pointer; font-family: inherit; }
.seg:hover { color: var(--text); }
.seg.active { background: var(--surface); color: var(--primary); font-weight: 600;
  box-shadow: var(--shadow-sm); }

/* 对齐弹窗要放差异明细表，比常规弹窗宽；表格自带滚动，不撑破视口 */
.align-modal-box { width: 880px; }
.align-issues-wrap { max-height: 42vh; overflow: auto; border: 1px solid var(--border);
  border-radius: var(--radius-sm); margin-top: 12px; }
/* 差异类型徽标：可自动修复用主色（暗示"点一下就好"），需人工的用告警色 */
.kind-pill { display: inline-block; padding: 2px 9px; border-radius: 999px; font-size: 12px;
  white-space: nowrap; border: 1px solid var(--border); background: var(--surface-2); color: var(--muted); }
.kind-pill.auto { color: var(--primary); background: var(--primary-light); border-color: #ddd6fe; }
.kind-pill.manual { color: var(--warn); background: var(--warn-bg); border-color: #fde68a; }

/* 设备码：等宽字体 + 可选中，方便照着去 HA 后台搜 */
.dev-code { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12px; color: var(--muted); background: var(--surface-2);
  border: 1px solid var(--border); border-radius: 5px; padding: 1px 6px;
  word-break: break-all; user-select: all; }

/* 链路追踪：左侧标签定宽，右侧长文本可换行（entity_id 可能很长） */
.trace-modal-box { width: 620px; }
.trace-body { display: flex; flex-direction: column; gap: 1px; }
.trace-row { display: grid; grid-template-columns: 104px 1fr; gap: 12px; padding: 9px 0;
  border-bottom: 1px solid var(--border); font-size: 13px; align-items: start; }
.trace-row:last-child { border-bottom: none; }
.trace-row .k { color: var(--muted); font-size: 12px; padding-top: 1px; }
.trace-row .v { color: var(--text); word-break: break-all; }
.trace-hints { margin: 12px 0 0; padding: 12px 14px; border-radius: var(--radius-sm);
  background: var(--info-bg); border: 1px solid var(--border); }
.trace-hints.bad { background: var(--warn-bg); border-color: #fde68a; }
.trace-hints ul { margin: 8px 0 0; padding-left: 18px; line-height: 1.9; font-size: 13px; color: var(--text); }

/* 暗色主题：补齐新表单控件与徽标（.stat-grid 的旧硬编码白色也一并收敛到变量） */
[data-theme="dark"] .inp,
[data-theme="dark"] .ota-form .inp,
[data-theme="dark"] .rel-form .inp { background: var(--surface); color: var(--text); }
[data-theme="dark"] .seg.active { box-shadow: none; }
[data-theme="dark"] .kind-pill.auto { border-color: #312e81; }
[data-theme="dark"] .kind-pill.manual { border-color: #78350f; }
[data-theme="dark"] .trace-hints.bad { border-color: #78350f; }
[data-theme="dark"] .stat-grid .stat { background: var(--surface); border-color: var(--border); }
[data-theme="dark"] .stat-grid .stat .num { color: var(--text); }
[data-theme="dark"] .stat-grid .stat .lbl,
[data-theme="dark"] .stat-grid .stat .sub { color: var(--muted); }

/* ==========================================================================
   列表化的记录视图 + 运营总览美工（2026-09-18）
   设计原则：
     1) 只展示人能读懂的信息 —— 内部主键（tenant_id / target_id / request_id）一律不上屏；
        对象统一用「名称」，名称解析不到就退化为中文类型名，绝不退化成数字 id。
     2) 记录以「列表」而非宽表格呈现：一条记录 = 一行图标 + 标题 + 元信息 + 结果徽标，
        窄屏也能读；日期分组取代重复的时间戳列。
     3) 全部颜色走 CSS 变量，明暗主题自动一致。
   ========================================================================== */

/* ---------- 页头 ---------- */
.page-hero {
  display: flex; align-items: flex-start; gap: 16px; flex-wrap: wrap;
  margin-bottom: 16px;
}
.page-hero-main { flex: 1 1 320px; min-width: 0; }
.page-hero-main h3 { margin: 0 0 4px; font-size: 19px; font-weight: 700; color: var(--text); letter-spacing: .2px; }
.page-hero-main .muted { margin: 0; font-size: 13px; line-height: 1.6; }
.page-hero-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

/* ---------- 口径说明卡 ---------- */
.callout {
  background: var(--info-bg); border: 1px solid var(--border); border-radius: var(--radius);
  padding: 12px 16px; margin-bottom: 4px;
}
.callout strong { display: block; font-size: 13px; color: var(--info); margin-bottom: 6px; }
.callout ul { margin: 0; padding-left: 18px; }
.callout li { font-size: 12.5px; color: var(--text); line-height: 1.85; }

/* ---------- 筛选栏 ---------- */
.filter-bar {
  display: flex; align-items: flex-end; gap: 12px; flex-wrap: wrap;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow-sm); padding: 12px 16px; margin: 16px 0;
}
.filter-field { display: flex; flex-direction: column; gap: 5px; font-size: 12px; color: var(--muted); }
.filter-field select, .filter-field input {
  width: auto; min-width: 132px; margin: 0; padding: 8px 11px; font-size: 13px;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--surface); color: var(--text);
}
.filter-field.grow { flex: 1 1 220px; }
.filter-field.grow input { width: 100%; }
.filter-field select:focus, .filter-field input:focus {
  outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px rgba(79,70,229,.15);
}
.filter-bar .ghost-btn { padding: 8px 14px; font-size: 13px; }
.filter-count { margin-left: auto; align-self: center; font-size: 12.5px; color: var(--muted); white-space: nowrap; }

/* ---------- 记录列表 ---------- */
.log-list { display: flex; flex-direction: column; gap: 10px; }
.log-day {
  display: flex; align-items: center; gap: 10px; margin: 10px 0 2px;
  font-size: 12px; color: var(--muted); font-weight: 600; letter-spacing: .3px;
}
.log-day::after { content: ""; flex: 1; height: 1px; background: var(--border); }

.log-item {
  display: flex; align-items: flex-start; gap: 12px;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow-sm); padding: 12px 16px;
  border-left: 3px solid var(--border-strong);
  transition: border-color .15s, box-shadow .15s, transform .05s;
}
.log-item:hover { box-shadow: var(--shadow); transform: translateY(-1px); }
.log-item.ok    { border-left-color: var(--online); }
.log-item.info  { border-left-color: var(--primary-soft); }
.log-item.warn  { border-left-color: var(--warn); }
.log-item.error { border-left-color: var(--danger); }

.log-icon {
  flex: none; width: 34px; height: 34px; border-radius: 10px;
  display: flex; align-items: center; justify-content: center;
  font-size: 16px; background: var(--surface-2); border: 1px solid var(--border);
}
.log-main { flex: 1; min-width: 0; }
.log-title { font-size: 14px; color: var(--text); font-weight: 600; line-height: 1.5; word-break: break-word; }
.log-title .obj { font-weight: 500; color: var(--text); }
.log-meta {
  margin-top: 4px; font-size: 12px; color: var(--muted);
  display: flex; flex-wrap: wrap; gap: 6px; align-items: center;
}
.log-meta .sep { color: var(--border-strong); }
.log-note {
  margin-top: 6px; font-size: 12px; color: var(--muted); line-height: 1.6;
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: var(--radius-sm); padding: 6px 10px; word-break: break-word;
}
.log-right { flex: none; display: flex; flex-direction: column; align-items: flex-end; gap: 6px; }
.log-time { font-size: 12px; color: var(--muted-2); white-space: nowrap; font-variant-numeric: tabular-nums; }
.log-empty {
  background: var(--surface); border: 1px dashed var(--border-strong); border-radius: var(--radius);
  padding: 32px 20px; text-align: center; color: var(--muted); font-size: 13px;
}
.log-list.compact .log-item { padding: 10px 14px; }
.log-list.compact .log-icon { width: 28px; height: 28px; font-size: 14px; border-radius: 8px; }
.log-list.compact .log-title { font-size: 13px; }

/* 折叠的次要/技术明细区 */
.raw-block { margin-top: 22px; border-top: 1px dashed var(--border-strong); padding-top: 14px; }
.raw-block > summary {
  cursor: pointer; font-size: 13px; font-weight: 600; color: var(--muted); list-style: none;
  display: flex; align-items: center; gap: 8px;
}
.raw-block > summary::-webkit-details-marker { display: none; }
.raw-block > summary::before { content: "▸"; font-size: 12px; transition: transform .15s; }
.raw-block[open] > summary::before { transform: rotate(90deg); }
.raw-block > summary:hover { color: var(--primary); }
.raw-block > summary .muted { font-weight: 400; font-size: 12px; }

/* ---------- 租户健康卡（运营总览） ---------- */
.tenant-health { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 12px; }
.th-card {
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow-sm); padding: 14px 16px;
}
.th-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 12px; }
.th-name { font-size: 15px; font-weight: 700; color: var(--text); }
.th-no {
  font-size: 11.5px; font-weight: 600; color: var(--primary); background: var(--primary-light);
  border: 1px solid var(--border); border-radius: 999px; padding: 2px 9px;
  font-variant-numeric: tabular-nums;
}
.th-head .badge-online, .th-head .badge-offline { margin-left: auto; }
.th-metrics { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.th-metric { display: flex; flex-direction: column; gap: 3px; }
.th-metric .k { font-size: 11.5px; color: var(--muted); }
.th-metric .v { font-size: 15px; font-weight: 700; color: var(--text); font-variant-numeric: tabular-nums; }
.th-metric .v.zero { color: var(--muted-2); font-weight: 600; }
.th-bar { margin-top: 12px; height: 5px; border-radius: 999px; background: var(--surface-2); overflow: hidden; }
.th-bar i { display: block; height: 100%; border-radius: 999px; background: var(--online); transition: width .3s ease; }
.th-bar i.warn { background: var(--warn); }
.th-bar i.idle { background: var(--muted-2); }
.th-foot { margin-top: 8px; font-size: 11.5px; color: var(--muted-2); }

/* ---------- stat 卡片增强（运营总览 / 统计摘要共用） ---------- */
.stat-grid .stat { position: relative; overflow: hidden; transition: box-shadow .15s, transform .05s; }
.stat-grid .stat:hover { box-shadow: var(--shadow); transform: translateY(-1px); }
.stat-grid .stat::after {
  content: ""; position: absolute; left: 0; top: 0; width: 3px; height: 100%;
  background: var(--border-strong);
}
.stat-grid .stat.acc-ok::after { background: var(--online); }
.stat-grid .stat.acc-warn::after { background: var(--warn); }
.stat-grid .stat.acc-info::after { background: var(--info); }
.stat-grid .stat.acc-primary::after { background: var(--primary); }
.stat-grid .stat .num { font-variant-numeric: tabular-nums; }

/* ---------- 窄屏收敛 ---------- */
@media (max-width: 720px) {
  .filter-bar { padding: 12px; }
  .filter-field, .filter-field select, .filter-field input { width: 100%; min-width: 0; }
  .filter-field.grow { flex: 1 1 100%; }
  .filter-count { margin-left: 0; width: 100%; }
  .log-item { padding: 11px 12px; }
  .log-right { flex-direction: row; align-items: center; }
  .th-metrics { grid-template-columns: repeat(3, 1fr); }
}
