
  /* ===== 主题变量 =====
     承载主题的是 <html>（:root）而不是 <body> —— 因为 <head> 里有一段内联脚本要在
     首屏渲染**之前**就设好 data-theme，那时 body 还不存在。不这么做的话，
     夜晚模式会先闪一下白底再变暗（FOUC），对夜间使用体验很差。
     默认分支（:root，无 data-theme）用的是深色值，与原来一致。 */
  :root {
    --page-bg: radial-gradient(1200px 600px at 50% -10%, #16222D 0%, #0A1016 55%, #070B10 100%);
    --page-title: #EDF1F4;
    --page-sub: #8CA0AF;
    --app-bg: linear-gradient(180deg, #0D151D 0%, #0A1118 100%);
    --card-bg: rgba(255,255,255,0.03);
    --card-border: rgba(255,255,255,0.06);
    --text: #EDF1F4;
    --text-sec: #93A4B2;
    --text-soft: #8CA0AF;
    --text-dim: #566A77;
    --text-mute: #6E8290;
    --hr: #E8887A;
    --br: #5FC9C0;
    --ok: #5FBF7A;
    --ok-text: #7BD498;
    --warn-text: #E8C47E;
    --err: #F07B6B;
    --err-text: #F7A79C;
    --ok-bg: rgba(95,191,122,0.16);
    --mute-bg: rgba(255,255,255,0.06);
    --br-soft: rgba(95,201,192,0.16);
    --err-bg: rgba(240,123,107,0.14);
    --btn-bg: rgba(255,255,255,0.06);
    --btn-border: rgba(255,255,255,0.12);
    --btn-hover: rgba(255,255,255,0.10);
    --bar-bg: rgba(255,255,255,0.04);
    --bar-border: rgba(255,255,255,0.07);
    --mask: rgba(0, 0, 0, 0.55);
    --tabbar-bg: #0D151D;
    --drawer-bg: rgba(18, 28, 38, 0.97);
    /* v11.8 手机端 P0 令牌：选中态 / 卡片阴影 / 警示底 / 图标标签底色（变量化，值与原写死值一致） */
    --active-bg: rgba(255,255,255,0.12);
    --card-shadow: 0 0 0 1px rgba(255,255,255,0.05), 0 8px 24px rgba(0,0,0,0.35);
    --warn-bg: rgba(232,196,126,0.16);
    --ico-hr-bg: rgba(234,102,104,0.12);
    --ico-br-bg: rgba(95,201,192,0.16);
    --tag-err-bg: rgba(234,102,104,0.14);
    --tag-warn-bg: rgba(230,162,60,0.16);
    --gap-card: 12px;   /* 手机端卡片统一间距（v11.9），此前实测 14px/83px 混杂 */
  }
  :root[data-theme="light"] {
    --page-bg: radial-gradient(1200px 600px at 50% -10%, #F6FAFC 0%, #EAF1F5 55%, #E2EBF0 100%);
    --page-title: #16222D;
    --page-sub: #5B6B78;
    --app-bg: linear-gradient(180deg, #FFFFFF 0%, #F4F8FA 100%);
    --card-bg: rgba(0,0,0,0.025);
    --card-border: rgba(20,50,65,0.10);
    --text: #16222D;
    --text-sec: #4A5B68;
    --text-soft: #5B6B78;
    --text-dim: #8AA0AE;
    --text-mute: #7A8D9A;
    --hr: #D96B5A;
    --br: #2FA99E;
    --ok: #3BA75C;
    --ok-text: #2E9350;
    --warn-text: #B57F1F;
    --err: #E05B4D;
    --err-text: #C94A3D;
    --ok-bg: rgba(34,197,94,0.12);
    --mute-bg: rgba(0,0,0,0.05);
    --br-soft: rgba(47,169,158,0.14);
    --err-bg: rgba(224,91,77,0.10);
    --btn-bg: rgba(22,34,45,0.05);
    --btn-border: rgba(22,34,45,0.15);
    --btn-hover: rgba(22,34,45,0.10);
    --bar-bg: rgba(22,34,45,0.04);
    --bar-border: rgba(22,34,45,0.10);
    --mask: rgba(22, 34, 45, 0.42);
    --tabbar-bg: #ffffff;
    --drawer-bg: #FFFFFF;
    --active-bg: #FFFFFF;
    --card-shadow: 0 1px 2px rgba(16,42,58,0.04), 0 4px 16px rgba(16,42,58,0.08);
    --warn-bg: rgba(181,127,31,0.12);
  }

  /* ===== 字阶与字体（v14.0 文字统一）：标题/正文/注释各一级，同级全站同号同字体 ===== */
  :root {
    --font-sans: "PingFang SC", "Microsoft YaHei", "Noto Sans SC", -apple-system, system-ui, sans-serif;
    --font-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Consolas, monospace;
    --fs-page: 28px;      /* 页面主标题 */
    --fs-section: 18px;   /* 区块标题 */
    --fs-card: 14px;      /* 卡片 / 条目标题 */
    --fs-body: 13px;      /* 正文 */
    --fs-caption: 11px;   /* 注释 */
    --fs-micro: 10px;     /* 微标签 */
    --fs-num-lg: 32px;    /* 大数字 */
    --fs-num-sm: 20px;    /* 小数字 */

    /* ── 动效时长令牌（2026-09-27 起，仅先收口"JS/CSS 跨语言耦合"的两处）────────
       为什么只加这两个、不把 94 处时长一起令牌化：见 安护无微-网页端优化方案-v15.md
       的 P1「动效时长无令牌」节。结论是时长令牌化整体属 P1（维护成本，非当前缺陷），
       但那 94 处里有 2 处是**真的会漏**的跨语言耦合——JS 用 setTimeout 等一个写死的
       毫秒数，去配合 CSS 里另一个写死的秒数。两边都没有机制约束，改一边忘另一边
       就出静默缺陷（浏览器不报错、断言不红）。这里先只给这两处建令牌并让 JS 读它。
       余量约定：JS 的等待 = 动画时长 + 余量（下面两个 --dur-*-hold 已含余量）。
       余量存在的原因：transitionend 会漏触发（被打断 / 同值不触发），所以不退化为
       监听事件，而是保留"固定时长 + 小余量"的写法，只是把两个数收进同一个令牌。 */
    --dur-splash: 550ms;       /* 开屏淡出动画时长（.app-splash 的 transition） */
    --dur-splash-hold: 700ms;  /* 开屏 display:none 等待 = 550ms + 150ms 余量 */
    --dur-ev-leave: 300ms;     /* 告警行退场动画时长（.ev.ev-leave 的 transition） */
    --dur-ev-leave-hold: 320ms;/* 退场后重排等待 = 300ms + 20ms 余量 */

    /* 缓动曲线令牌（0927）：原先 84 处 transition 全用裸 `ease`，
       悬停/进入/退场三种相反的动作共用同一条曲线 ⇒ 手感"平"、缺层次。
       按**动作语义**分三条，各自取符合直觉的曲线： */
    --ease-hover: cubic-bezier(.4, 0, .2, 1);    /* 悬停/点击反馈：起步快、收尾慢，干脆利落 */
    --ease-enter: cubic-bezier(.2, .8, .25, 1);  /* 进入/切换：先快后缓，有"滑入"感（沿用开屏那条好曲线） */
    --ease-leave: cubic-bezier(.4, 0, 1, 1);     /* 退场/折叠：逐渐加速离开，符合"消失"直觉 */

    /* 按压反馈令牌（0927）：此前全站只有 13 处 :active 且全挂在具体类名上，
       没有任何一条覆盖"能点的东西"这一整体 ⇒ 同类操作有的按下有缩放、有的毫无反应
       （最刺眼：桌面报警条 .alarm-ack 无反馈，手机 .m-alarm-ack 有）。
       这里给出**统一按压契约**，由文件末尾的全局层注入，各处只需按需 opt-out。
       - 位移型（按钮/卡片）：--press-shift，轻微下沉，符合"按下去"的物理直觉
       - 缩放型（图标钮）：--press-scale，幅度略大，小目标上更可见
       - 时长刻意取短（80ms）：按压反馈必须"跟手"，过长会显得迟钝 */
    --press-shift: 1px;
    --press-scale: 0.96;
    --dur-press: 80ms;
  }
  * { box-sizing: border-box; }
  html, body { margin: 0; padding: 0; }
  body {
    min-height: 100vh;
    background: var(--page-bg);
    color: var(--text);
    font-family: var(--font-sans);
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 28px 16px 48px;
    transition: background 0.3s var(--ease-enter), color 0.3s var(--ease-enter);
  }

  /* ===== 页头（桌面控制台工具栏，手机上隐藏） ===== */
  .page-head {
    width: 100%; max-width: 1280px;
    display: flex; align-items: flex-end; justify-content: space-between; gap: 16px;
    flex-wrap: wrap;
    margin-bottom: 22px;
  }
  .page-head h1 { margin: 0 0 6px; font-size: var(--fs-page); font-weight: 600; letter-spacing: 0.02em; color: var(--page-title); }
  .page-head h1 .brand-mark { color: var(--br); }
  .page-head p { margin: 0; font-size: var(--fs-body); color: var(--page-sub); letter-spacing: 0.01em; }
  .head-actions { display: flex; gap: 8px; }
  .ctl-btn, .app-btn2 {
    height: 40px; min-width: 88px;
    display: inline-flex; align-items: center; justify-content: center; gap: 7px;
    padding: 0 14px;
    border-radius: 12px; border: 1px solid var(--btn-border);
    background: var(--btn-bg); color: var(--text);
    font-size: var(--fs-body); font-weight: 500; font-family: inherit; cursor: pointer;
    transition: background 0.15s var(--ease-hover), color 0.2s var(--ease-hover);
  }
  .ctl-btn:hover, .app-btn2:hover { background: var(--btn-hover); }
  .app-btn2.danger {
    background: color-mix(in srgb, var(--err) 12%, transparent);
    border-color: color-mix(in srgb, var(--err) 40%, transparent);
    color: var(--err-text);
  }
  .app-btn2.danger:hover { background: color-mix(in srgb, var(--err) 20%, transparent); }
  .app-btn2:disabled { opacity: 0.4; cursor: not-allowed; }
  .app-btn2 svg { display: block; }

  /* ===== App 主体 ===== */
  .app {
    width: 100%;
    max-width: 1280px;
    margin: 0 auto;
    padding: 22px 24px 28px;
    display: flex;
    flex-direction: column;
    gap: 14px;
    background: var(--app-bg);
    border: 1px solid var(--card-border);
    border-radius: 20px;
    font-family: var(--font-sans);
    transition: background 0.3s var(--ease-hover), border-color 0.3s var(--ease-hover);
  }

  /* ===== 顶栏（两行：第一行品牌+在线，第二行时间+主题按钮） ===== */
  .topbar {
    display: flex; flex-direction: column; gap: 10px;
    padding-top: 2px;
  }
  .top-row { display: flex; align-items: center; justify-content: space-between; }
  .sub-row { display: flex; align-items: center; justify-content: space-between; }
  .brand { display: flex; align-items: center; gap: 8px; font-size: 16px; font-weight: 600; }
  .brand svg { display: block; }
  .live { display: flex; align-items: center; gap: 5px; font-size: var(--fs-caption); color: var(--text-soft); }
  .live .dot {
    width: 8px; height: 8px; border-radius: 50%;
    background: var(--ok); box-shadow: 0 0 0 3px color-mix(in srgb, var(--ok) 15%, transparent);
    animation: breathe 2.4s ease-in-out infinite;
  }
  .live.off .dot {
    background: #8A949B; box-shadow: 0 0 0 3px rgba(138,148,155,0.15);
    animation: none;
  }
  @keyframes breathe { 0%,100% { opacity: 1; } 50% { opacity: 0.45; } }
  /* 顶栏时钟 .clock 已于 09-23 移除（与手机状态栏时间重复）；
     sub-row 只剩主题按钮，靠右对齐 */
  .sub-row { display: flex; align-items: center; justify-content: flex-end; }
  .theme-btn {
    width: 44px; height: 44px;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 50%;
    border: 1px solid var(--btn-border);
    background: var(--btn-bg);
    color: var(--text);
    cursor: pointer;
    transition: background 0.15s var(--ease-hover), color 0.2s var(--ease-hover), transform 0.15s var(--ease-hover);
  }
  .theme-btn:hover { background: var(--btn-hover); }
  .theme-btn:active { transform: scale(0.94); }
  .theme-btn svg { display: none; }
  .theme-btn svg.show { display: block; }

  /* ===== 仪表盘主布局 ===== */
  .dash {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 300px;
    grid-template-areas: "main side";
    gap: 16px;
  }
  .dash-main { display: flex; flex-direction: column; gap: 14px; min-width: 0; grid-area: main; }
  .dash-side { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
  /* 右列 = 侧栏卡片 + 事件流竖直等距排列；事件流 flex:1 撑满剩余高度，与左列底部齐平 */
  .dash-right {
    display: flex; flex-direction: column; gap: 16px;
    min-width: 0;
    grid-area: side;
  }

  /* 设备行 */
  .device-row {
    display: flex; align-items: center; justify-content: space-between;
    padding: 8px 12px;
    background: var(--bar-bg);
    border: 1px solid var(--bar-border);
    border-radius: 14px;
  }
  .device-name { font-size: var(--fs-body); color: var(--text-sec); }
  .device-name .room { color: var(--text); font-weight: 500; }
  .device-status {
    display: inline-flex; align-items: center; gap: 5px;
    font-size: var(--fs-caption); color: var(--ok);
  }
  .device-status svg { display: block; }

  /* 连接提示条 */
  .conn-bar {
    display: flex; align-items: center; gap: 8px;
    padding: 10px 12px;
    background: color-mix(in srgb, var(--warn-text) 10%, transparent);
    border: 1px solid color-mix(in srgb, var(--warn-text) 40%, transparent);
    border-radius: 14px;
    font-size: var(--fs-body); color: var(--warn-text);
  }
  .conn-bar.hidden { display: none; }
  .conn-bar svg { flex-shrink: 0; }

  /* 告警条 */
  /* ⚠️ 0927 真机实测（真机动画探针 + 最小复现矩阵）：
     原写法 `display:none` + `transition: max-height …` 的过渡**根本没播**。
     在 WebView(Chrome 138) 上实测：
       · `display:none → flex` + `transition: max-height/opacity/padding`  ⇒ **0 个动画，硬跳**
       · 加 `transition-behavior:allow-discrete` + `@starting-style`       ⇒ **仍然 0 个动画**
         （`@starting-style` 确实被解析成 CSSStartingStyleRule，但**不触发过渡**）
       · **去掉 `display:none`，改用 `max-height:0 + padding:0 + border-width:0 + overflow:hidden`**
         ⇒ **真的播**：实测 `getAnimations()` 抓到 8 个 running 过渡，h 从 0 滑到 38px。
     所以最终采用**最后一种**：既不依赖离散过渡（兼容性更好），又能真正动起来。
     关键点：收起态必须把 **border-width 也归零**——否则 1px 边框会留下 2px 高的一条
     （`max-height:0`+`overflow:hidden` 挡不住边框），这就是当初加 `display:none` 的原因。 */
  .alarm-bar {
    display: flex; align-items: center; gap: 9px;
    margin: 0;
    padding: 0 12px;
    max-height: 0; opacity: 0; overflow: hidden;
    border: 1px solid color-mix(in srgb, var(--err) 40%, transparent);
    border-width: 0;                     /* 收起态归零边框宽度 ⇒ 真 0 占位 */
    background: color-mix(in srgb, var(--err) 12%, transparent);
    border-radius: 14px;
    transition: max-height 0.35s var(--ease-leave), opacity 0.35s var(--ease-leave),
                padding 0.35s var(--ease-leave), border-width 0.35s var(--ease-leave);
  }
  .alarm-bar.show { max-height: 52px; opacity: 1; padding: 10px 12px; border-width: 1px; }
  .alarm-bar svg { flex-shrink: 0; }
  .alarm-bar .alarm-text { font-size: var(--fs-body); color: var(--err-text); font-weight: 500; }
  .alarm-bar .alarm-time { margin-left: auto; font-family: var(--font-mono); font-size: var(--fs-caption); color: var(--err-text); opacity: 0.8; }
  .alarm-bar .alarm-ack {
    flex-shrink: 0;
    padding: 4px 12px;
    border: 1px solid color-mix(in srgb, var(--err) 45%, transparent);
    border-radius: 999px;
    background: transparent;
    color: var(--err-text);
    font-size: var(--fs-body); font-family: inherit;
    cursor: pointer;
  }
  .alarm-bar .alarm-ack:hover { background: color-mix(in srgb, var(--err) 18%, transparent); }
  /* 已知悉后：收起红条但保留占位动画，下次告警重新展开（同收起态，含 border-width:0） */
  .alarm-bar.acked { max-height: 0; opacity: 0; padding: 0 12px; border-width: 0; }

  /* 图表卡片 */
  .chart-card {
    background: var(--card-bg);
    border: 1px solid var(--card-border);
    border-radius: 16px;
    padding: 14px 14px 10px;
    transition: background 0.3s var(--ease-hover), border-color 0.3s var(--ease-hover);
  }
  .chart-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
  .chart-title { display: inline-flex; align-items: center; gap: 7px; font-size: var(--fs-card); color: var(--text-sec); line-height: 1; }
  .chart-title svg { display: block; }
  .chart-legend {
    margin-left: 10px; padding: 2px 8px;
    border-radius: 999px;
    background: color-mix(in srgb, var(--ok) 10%, transparent);
    color: var(--ok-text);
    font-size: var(--fs-caption);
  }
  .chart-value {
    display: inline-flex; align-items: baseline;
    font-family: var(--font-mono);
    font-size: var(--fs-num-lg); font-weight: 600; color: var(--text); line-height: 1;
  }
  .chart-value .unit { font-size: var(--fs-caption); font-weight: 400; color: var(--text-soft); margin-left: 4px; }
  canvas.chart { display: block; width: 100%; height: 210px; }
  canvas#chartBr { height: 188px; }

  /* 底部统计（桌面 4 卡 / 手机 2 卡） */
  .stats-row { display: flex; gap: 12px; flex-wrap: wrap; }
  .stat-card {
    flex: 1 1 0; min-width: 0;
    background: var(--card-bg);
    border: 1px solid var(--card-border);
    border-radius: 16px;
    padding: 14px 14px 12px;
    transition: background 0.3s var(--ease-hover), border-color 0.3s var(--ease-hover);
  }
  .stat-label { display: flex; align-items: center; gap: 6px; font-size: var(--fs-caption); color: var(--text-sec); }
  .stat-label svg { display: block; }
  .stat-num {
    display: inline-flex; align-items: baseline;
    font-family: var(--font-mono);
    font-size: var(--fs-num-lg); font-weight: 600; color: var(--text); line-height: 1.15; margin-top: 4px;
    white-space: nowrap;
  }
  .stat-num .unit { font-size: var(--fs-caption); font-weight: 400; color: var(--text-soft); margin-left: 4px; }
  .stat-note { font-size: var(--fs-caption); color: var(--text-mute); margin-top: 3px; }
  .stat-status {
    display: inline-flex; align-items: center; gap: 5px;
    margin-top: 8px; padding: 3px 9px; border-radius: 999px;
    font-size: var(--fs-caption); font-weight: 500;
  }
  .stat-status.ok  { background: color-mix(in srgb, var(--ok) 14%, transparent); color: var(--ok-text); }
  .stat-status.warn{ background: color-mix(in srgb, var(--warn-text) 14%, transparent); color: var(--warn-text); }
  .stat-status.err { background: color-mix(in srgb, var(--err) 16%, transparent); color: var(--err-text); }
  .stat-status .dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }

  /* ===== 侧栏卡片 ===== */
  .side-card {
    background: var(--card-bg);
    border: 1px solid var(--card-border);
    border-radius: 16px;
    padding: 14px;
  }
  .side-title { font-size: var(--fs-section); color: var(--text-sec); letter-spacing: 0.03em; margin-bottom: 10px; }
  .side-vitals { display: flex; gap: 10px; }
  .side-vitals .sv {
    flex: 1 1 0; min-width: 0;
    background: var(--bar-bg);
    border: 1px solid var(--bar-border);
    border-radius: 12px;
    padding: 10px 12px;
  }
  .sv-label { display: block; font-size: var(--fs-caption); color: var(--text-mute); }
  .sv-num {
    display: inline-block; margin-top: 3px;
    font-family: var(--font-mono);
    font-size: var(--fs-num-lg); font-weight: 600; line-height: 1.1;
  }
  .sv-num.hr { color: var(--hr); }
  .sv-num.br { color: var(--br); }
  .sv-unit { font-size: var(--fs-caption); color: var(--text-soft); margin-left: 3px; }
  .side-status {
    display: inline-flex; align-items: center; gap: 6px;
    margin-top: 12px; padding: 4px 10px; border-radius: 999px;
    font-size: var(--fs-caption); font-weight: 500;
  }
  .side-status.ok   { background: color-mix(in srgb, var(--ok) 14%, transparent); color: var(--ok-text); }
  .side-status.warn { background: color-mix(in srgb, var(--warn-text) 14%, transparent); color: var(--warn-text); }
  .side-status.err  { background: color-mix(in srgb, var(--err) 16%, transparent); color: var(--err-text); }
  .side-status .dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }

  /* 设备列表（行容器 = 主按钮 + 管理按钮） */
  .dev-list { display: flex; flex-direction: column; gap: 6px; }
  .dev-empty {
    padding: 16px 10px;
    border: 1px dashed color-mix(in srgb, var(--text-mute) 40%, transparent);
    border-radius: 12px;
    font-size: var(--fs-body); line-height: 1.7;
    color: var(--text-mute);
    text-align: center;
  }
  .dev-empty span { display: block; font-size: var(--fs-card); font-weight: 600; color: var(--text-sec); }
  .dev-item {
    display: flex; align-items: center;
    border-radius: 12px;
    border: 1px solid transparent;
    background: transparent;
    transition: background 0.15s var(--ease-hover), border-color 0.15s var(--ease-hover);
  }
  .dev-item:hover { background: var(--btn-bg); }
  .dev-item.active {
    background: color-mix(in srgb, var(--br) 12%, transparent);
    border-color: color-mix(in srgb, var(--br) 40%, transparent);
  }
  .dev-main {
    flex: 1 1 auto; min-width: 0;
    display: flex; align-items: center; gap: 8px;
    padding: 9px 10px;
    border: none; background: transparent;
    color: var(--text-sec);
    font-size: var(--fs-body); font-family: inherit; cursor: pointer;
    text-align: left;
  }
  .dev-item.active .dev-main { color: var(--text); }
  .dev-main .dev-name-txt { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .dev-item .dev-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--ok); flex-shrink: 0; }
  .dev-item .dev-state { margin-left: auto; font-size: var(--fs-caption); color: var(--ok-text); flex-shrink: 0; }
  .dev-more {
    flex: 0 0 auto; width: 32px; height: 32px; margin-right: 4px;
    display: inline-flex; align-items: center; justify-content: center;
    border: 1px solid var(--card-border); border-radius: 9px;
    background: transparent; color: var(--text-mute);
    cursor: pointer; transition: background 0.15s var(--ease-hover), color 0.15s var(--ease-hover), border-color 0.15s var(--ease-hover);
  }
  /* 加边框是为了让它"看起来像个按钮"—— 纯图标时用户会当成装饰，
     反馈"好像没有设备解绑的选项"很可能就是没认出这个 ⋯。设备管理弹窗（含解绑）由它打开。 */
  .dev-more:hover { background: var(--btn-hover); color: var(--text); border-color: var(--text-dim); }

  /* 系统链路 */
  .sys-list { display: flex; flex-direction: column; gap: 8px; }
  .sys-item {
    display: flex; align-items: center; justify-content: space-between;
    font-size: var(--fs-body); color: var(--text-sec);
  }
  .sys-item .sys-state { display: inline-flex; align-items: center; gap: 5px; color: var(--ok-text); font-size: var(--fs-caption); }
  .sys-item .sys-state::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--ok); }
  .sys-item .sys-state.idle { color: var(--text-mute); }
  .sys-item .sys-state.idle::before { background: var(--text-mute); }
  .sys-item .sys-state.err { color: var(--err-text); }
  .sys-item .sys-state.err::before { background: var(--err); }
  .side-note { margin-top: 10px; font-size: var(--fs-caption); color: var(--text-mute); }

  /* ===== 告警事件流 ===== */
  .events {
    flex: 1 1 auto;
    min-height: 0;
    display: flex; flex-direction: column;
    background: var(--card-bg);
    border: 1px solid var(--card-border);
    border-radius: 16px;
    padding: 14px;
  }
  .events-head {
    display: flex; align-items: center; gap: 8px;
    font-size: var(--fs-section); color: var(--text-sec); font-weight: 500;
    margin-bottom: 10px;
  }
  .events-sub {
    font-size: var(--fs-micro); font-weight: 400; color: var(--text-mute);
    padding: 1px 8px; border-radius: 999px;
    background: var(--bar-bg); border: 1px solid var(--bar-border);
  }
  .events-list { flex: 1 1 auto; min-height: 120px; max-height: 60vh; display: flex; flex-direction: column; gap: 6px; overflow-y: auto; }
  .ev {
    display: flex; align-items: center; gap: 10px;
    padding: 8px 10px;
    border-radius: 10px;
    background: var(--bar-bg);
    border: 1px solid var(--bar-border);
    font-size: var(--fs-body);
  }
  .ev .ev-time { font-family: var(--font-mono); font-size: var(--fs-caption); color: var(--text-mute); flex-shrink: 0; }
  .ev .ev-tag {
    flex-shrink: 0;
    padding: 1px 7px; border-radius: 999px;
    font-size: var(--fs-micro); font-weight: 500;
  }
  .ev.err .ev-tag { background: color-mix(in srgb, var(--err) 16%, transparent); color: var(--err-text); }
  .ev.warn .ev-tag { background: color-mix(in srgb, var(--warn-text) 14%, transparent); color: var(--warn-text); }
  .ev.ok .ev-tag   { background: color-mix(in srgb, var(--ok) 14%, transparent); color: var(--ok-text); }
  .ev .ev-msg { color: var(--text-sec); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

  /* 异常管理（09-16）：筛选条 / 状态徽标 / 操作按钮 */
  .events-filter { display: flex; gap: 8px; margin-bottom: 10px; }
  .abn-filter {
    flex: 1 1 0; min-width: 0;
    font-size: var(--fs-body); color: var(--text);
    background: var(--bar-bg);
    border: 1px solid var(--bar-border);
    border-radius: 8px; padding: 6px 8px;
  }
  .ev.ev-manage { flex-wrap: wrap; }
  .ev.ev-manage .ev-status {
    flex-shrink: 0; font-size: var(--fs-micro); font-weight: 500;
    padding: 1px 7px; border-radius: 999px;
  }
  .ev.ev-manage.s-pending .ev-status { background: color-mix(in srgb, var(--warn-text) 14%, transparent); color: var(--warn-text); }
  .ev.ev-manage.s-ack .ev-status    { background: color-mix(in srgb, var(--ok) 14%, transparent); color: var(--ok-text); }
  .ev.ev-manage.s-ignored .ev-status { background: color-mix(in srgb, var(--text-mute) 20%, transparent); color: var(--text-sec); }
  .ev.ev-manage .ev-actions { display: flex; gap: 6px; margin-left: auto; flex-shrink: 0; }
  .ev-btn {
    font-size: var(--fs-body); line-height: 1; padding: 5px 9px; border-radius: 7px;
    border: 1px solid var(--bar-border); background: var(--bar-bg); color: var(--text-sec);
    cursor: pointer;
  }
  .ev-btn:hover { color: var(--text); border-color: var(--text-dim); }
  .ev-btn.ok { color: var(--ok-text); border-color: color-mix(in srgb, var(--ok) 45%, transparent); background: color-mix(in srgb, var(--ok) 8%, transparent); }
  .ev-btn.ok:hover { background: color-mix(in srgb, var(--ok) 16%, transparent); }
  .ev-btn.no { color: var(--err-text); border-color: color-mix(in srgb, var(--err) 45%, transparent); background: color-mix(in srgb, var(--err) 8%, transparent); }
  .ev-btn.no:hover { background: color-mix(in srgb, var(--err) 16%, transparent); }
  .ev.ev-manage .ev-note {
    flex-basis: 100%; font-size: var(--fs-caption); color: var(--text-mute);
    padding-left: 2px; white-space: normal; overflow: visible;
  }
  .ev.ev-empty { justify-content: center; color: var(--text-mute); font-size: var(--fs-body); gap: 8px; flex-wrap: wrap; }
  .ev.ev-leave { opacity: 0; transform: translateX(10px); transition: opacity var(--dur-ev-leave) var(--ease-leave), transform var(--dur-ev-leave) var(--ease-leave); }

  /* 手机端设备折叠卡 */
  .dev-fold { display: block; }
  .dev-fold-head {
    display: flex; align-items: center; justify-content: space-between; width: 100%;
    padding: 12px 14px;
    background: var(--card-bg); border: 1px solid var(--card-border); border-radius: 16px;
    font-size: var(--fs-card); color: var(--text); font-weight: 500;
    font-family: inherit; cursor: pointer;
  }
  .dev-fold-cur { display: inline-flex; align-items: center; gap: 8px; min-width: 0; }
  .dev-fold-cur .dev-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--ok); flex-shrink: 0; }
  .dev-fold-right { display: inline-flex; align-items: center; gap: 7px; flex-shrink: 0; }
  .dev-fold-state { font-size: var(--fs-caption); color: var(--ok-text); }
  .dev-fold-arrow { color: var(--text-soft); transition: transform 0.25s var(--ease-enter); }
  .dev-fold.open .dev-fold-arrow { transform: rotate(180deg); }
  .dev-fold-body {
    display: none; flex-direction: column; gap: 6px; margin-top: 8px;
    background: var(--card-bg); border: 1px solid var(--card-border); border-radius: 16px;
    padding: 6px;
  }
  .dev-fold.open .dev-fold-body { display: flex; }

  /* 手机端系统状态折叠卡 */
  .sys-fold { display: block; }
  .sys-fold-head {
    display: flex; align-items: center; justify-content: space-between; width: 100%;
    padding: 13px 14px;
    background: var(--card-bg); border: 1px solid var(--card-border); border-radius: 16px;
    font-size: var(--fs-card); color: var(--text); font-weight: 500;
    font-family: inherit; cursor: pointer;
  }
  .sys-fold-head .sys-fold-arrow { transition: transform 0.25s var(--ease-enter); color: var(--text-soft); }
  .sys-fold.open .sys-fold-arrow { transform: rotate(180deg); }
  .sys-fold-body {
    display: none; margin-top: 8px;
    background: var(--card-bg); border: 1px solid var(--card-border); border-radius: 16px;
    padding: 12px 14px;
  }
  .sys-fold.open .sys-fold-body { display: block; }
  .sys-fold-sec + .sys-fold-sec { margin-top: 10px; }
  .sys-fold-title { font-size: var(--fs-caption); color: var(--text-mute); margin-bottom: 6px; }
  .sys-fold-grid { display: flex; flex-wrap: wrap; gap: 6px; }
  .sys-fold-item {
    font-size: var(--fs-caption); padding: 4px 9px; border-radius: 999px;
    background: color-mix(in srgb, var(--ok) 12%, transparent); color: var(--ok-text);
  }
  .sys-fold-note { font-size: var(--fs-caption); color: var(--text-dim); margin-top: 10px; }

  /* 手机端演示控制 */
  .controls { display: flex; gap: 10px; align-items: center; padding-top: 2px; }
  .app-btn {
    flex: 1 1 0; min-width: 0;
    height: 46px;
    display: inline-flex; align-items: center; justify-content: center; gap: 7px;
    border-radius: 14px; border: 1px solid var(--btn-border);
    background: var(--btn-bg);
    color: var(--text); font-size: var(--fs-body); font-weight: 500;
    font-family: inherit; cursor: pointer;
    transition: background 0.15s var(--ease-hover), opacity 0.15s var(--ease-hover);
  }
  .app-btn:hover { background: var(--btn-hover); }
  .app-btn:disabled { opacity: 0.4; cursor: not-allowed; }
  .app-btn.primary {
    background: color-mix(in srgb, var(--br) 16%, transparent);
    border-color: color-mix(in srgb, var(--br) 45%, transparent);
    color: var(--br);
  }
  .app-btn.primary:hover { background: color-mix(in srgb, var(--br) 24%, transparent); }
  .app-btn.danger {
    background: color-mix(in srgb, var(--err) 12%, transparent);
    border-color: color-mix(in srgb, var(--err) 40%, transparent);
    color: var(--err-text);
  }
  .app-btn.danger:hover { background: color-mix(in srgb, var(--err) 20%, transparent); }
  .app-btn svg { display: block; }
  .foot-note { text-align: center; font-size: var(--fs-caption); color: var(--text-dim); margin-top: -2px; }

  /* ===== 新增：设备 SN 徽标 / 时段切换 / 离线条 / 起夜列表 / SN 查询 ===== */
  .device-sn {
    margin-left: 10px; padding: 2px 8px;
    border-radius: 999px;
    background: var(--bar-bg); border: 1px solid var(--bar-border);
    font-family: var(--font-mono);
    font-size: var(--fs-caption); color: var(--text-soft); letter-spacing: 0.04em;
  }
  .device-status.off { color: var(--warn-text); }
  .conn-bar.off {
    background: color-mix(in srgb, var(--text-sec) 8%, transparent);
    border-color: color-mix(in srgb, var(--text-sec) 30%, transparent);
    color: var(--text-sec);
  }
  .conn-bar.off.hidden { display: none; }

  /* 曲线时段切换 */
  .range-bar {
    display: flex; align-items: center; gap: 6px;
    padding: 4px;
    background: var(--bar-bg); border: 1px solid var(--bar-border);
    border-radius: 999px;
    width: max-content;
  }
  .range-btn {
    padding: 6px 14px; border-radius: 999px;
    border: none; background: transparent;
    color: var(--text-soft); font-size: var(--fs-body); font-weight: 500; font-family: inherit;
    cursor: pointer; transition: background 0.15s var(--ease-hover), color 0.15s var(--ease-hover);
  }
  .range-btn:hover { color: var(--text); }
  .range-btn.active {
    background: color-mix(in srgb, var(--br) 16%, transparent);
    color: var(--br);
  }

  /* SN 查询（桌面侧栏 / 手机折叠卡共用） */
  .sn-query {
    display: flex; gap: 6px; margin-top: 10px;
  }
  .sn-input {
    flex: 1; min-width: 0; height: 36px;
    padding: 0 10px;
    border-radius: 10px;
    border: 1px solid var(--bar-border); background: var(--bar-bg);
    color: var(--text); font-size: var(--fs-body); font-family: var(--font-mono);
    outline: none; transition: border-color 0.15s var(--ease-hover);
  }
  .sn-input::placeholder { color: var(--text-mute); font-family: var(--font-sans); }
  .sn-input:focus { border-color: color-mix(in srgb, var(--br) 55%, transparent); }
  .sn-btn-query {
    height: 36px; padding: 0 14px; border-radius: 10px;
    border: 1px solid color-mix(in srgb, var(--br) 50%, transparent);
    background: color-mix(in srgb, var(--br) 12%, transparent);
    color: var(--br); font-size: var(--fs-body); font-weight: 500; font-family: inherit;
    cursor: pointer;
  }
  .sn-btn-query:hover { background: color-mix(in srgb, var(--br) 20%, transparent); }
  .sn-btn-query:disabled { opacity: 0.5; cursor: not-allowed; }
  .sn-error {
    margin-top: 6px; padding: 8px 10px; border-radius: 10px;
    font-size: var(--fs-caption); line-height: 1.5;
    background: color-mix(in srgb, var(--err) 10%, transparent);
    border: 1px solid color-mix(in srgb, var(--err) 35%, transparent);
    color: var(--err-text);
  }
  .sn-error.ok {
    background: color-mix(in srgb, var(--ok) 10%, transparent);
    border-color: color-mix(in srgb, var(--ok) 35%, transparent);
    color: var(--ok-text);
  }
  .sn-error[hidden] { display: none; }
  .side-sn-query { margin-top: 10px; }

  /* 设备离线态 */
  .dev-item .dev-state.off { color: var(--warn-text); }
  .dev-item .dev-dot.off { background: var(--warn-text); }
  .dev-fold-state.off { color: var(--warn-text); }
  .dev-fold-cur .dev-dot.off { background: var(--warn-text); }

  /* 绑定模式切换（真实/模拟） */
  .bind-head { gap: 8px; }
  .bind-mode {
    display: flex; gap: 0;
    padding: 2px;
    border-radius: 999px;
    background: var(--bar-bg); border: 1px solid var(--bar-border);
    margin-right: auto;
  }
  .mode-btn {
    padding: 4px 10px; border: none; border-radius: 999px;
    background: transparent; color: var(--text-soft);
    font-size: var(--fs-body); font-family: inherit; cursor: pointer;
    white-space: nowrap;
    transition: background 0.15s var(--ease-hover), color 0.15s var(--ease-hover);
  }
  .mode-btn.active {
    background: color-mix(in srgb, var(--br) 16%, transparent);
    color: var(--br); font-weight: 500;
  }

  /* BLE 数据监视窗口 */
  .ble-mon {
    border-top: 1px solid var(--card-border);
    background: var(--bar-bg);
    display: flex; flex-direction: column;
    max-height: 190px;
  }
  .ble-mon[hidden] { display: none; }
  .ble-mon-head {
    display: flex; align-items: center; justify-content: space-between;
    padding: 8px 14px 6px;
  }
  .ble-mon-title {
    display: inline-flex; align-items: center; gap: 6px;
    font-size: var(--fs-card); font-weight: 600; color: var(--text);
  }
  .ble-mon-dot {
    width: 7px; height: 7px; border-radius: 50%;
    background: var(--text-mute);
  }
  .ble-mon-dot.on { background: var(--ok); animation: breathe 1.6s ease-in-out infinite; }
  .ble-mon-dot.err { background: var(--err); }
  .ble-mon-state {
    font-size: var(--fs-caption); font-weight: 400; color: var(--text-soft);
    padding: 1px 8px; border-radius: 999px;
    background: var(--card-bg); border: 1px solid var(--bar-border);
  }
  .ble-mon-clear {
    border: none; background: none;
    color: var(--text-mute); font-size: var(--fs-body); font-family: inherit;
    cursor: pointer; padding: 2px 6px; border-radius: 6px;
  }
  .ble-mon-clear:hover { color: var(--text); background: var(--btn-hover); }
  .ble-mon-list {
    flex: 1; overflow-y: auto;
    padding: 0 14px 10px;
    display: flex; flex-direction: column; gap: 2px;
    font-family: var(--font-mono);
    font-size: var(--fs-caption); line-height: 1.5;
  }
  .ble-frame {
    display: flex; gap: 8px; align-items: baseline;
    padding: 2px 6px; border-radius: 6px;
    word-break: break-all;
  }
  .ble-frame .bf-time { color: var(--text-mute); flex-shrink: 0; }
  .ble-frame .bf-dir { flex-shrink: 0; font-weight: 600; }
  .ble-frame.tx .bf-dir { color: var(--br); }
  .ble-frame.rx .bf-dir { color: var(--hr); }
  .ble-frame.sys .bf-dir { color: var(--text-mute); }
  .ble-frame.sys { color: var(--text-soft); font-style: italic; }
  .ble-frame .bf-data { color: var(--text-sec); }
  .ble-frame.hl { background: color-mix(in srgb, var(--ok) 10%, transparent); }
  .ble-frame.errf { background: color-mix(in srgb, var(--err) 10%, transparent); }

  /* 绑定表单 */
  .bind-pane label.bind-field { cursor: text; }
  .bind-field b.ok { color: var(--ok-text); }
  .bind-field b.warn { color: var(--warn-text); }
  .bind-field b.bad { color: var(--err-text); }

  /* ===== 桌面/手机专属区块（置于样式末尾，确保覆盖同名 display） ===== */
  .desktop-only { display: block; }
  .mobile-only { display: none; }

  /* ===== 中等宽度（≤980px）：仪表盘降为单列，侧栏卡片横向换行、事件流置底 ===== */
  @media (max-width: 980px) {
    .dash {
      grid-template-columns: 1fr;
      grid-template-areas: none;   /* 清掉桌面 "main side" 命名区域，否则窄屏仍是两列 */
    }
    .dash-main { grid-area: auto; }
    /* 右列容器打散，main → 侧栏 → 事件流按 DOM 顺序自动单列排列 */
    .dash-right { display: contents; }
    .dash-side {
      display: flex; flex-direction: row; flex-wrap: wrap;
    }
    .dash-side .side-card { flex: 1 1 260px; min-width: 0; }
    .stat-card { flex: 1 1 calc(50% - 6px); }
    .page-head { margin-bottom: 14px; }
  }

  /* ===== 手机端（≤480px）：保留原 App 布局，隐藏桌面模块 ===== */
  @media (max-width: 480px) {
    body { padding: 0; }
    .page-head { display: none; }
    .desktop-only { display: none !important; }
    .mobile-only { display: block; }
    .app {
      max-width: 100%;
      min-height: 100dvh;
      padding: calc(env(safe-area-inset-top, 12px) + 10px) 16px calc(env(safe-area-inset-bottom, 12px) + 10px);
      border: none; border-radius: 0;
    }
    .dash { display: block; }
    .dash-side { display: none; }
    .stat-num { font-size: 30px; }
    canvas.chart { height: 150px; }
    canvas#chartBr { height: 134px; }
    .stats-row { flex-wrap: wrap; }
    .stat-card { flex: 1 1 44%; min-width: 0; }
    .range-bar { align-self: center; }
    .sn-query { margin-top: 4px; }
    .controls { margin: 14px 0; }
  }
  @media (max-width: 520px) and (min-width: 481px) {
    body { padding: 18px 8px 32px; }
    .page-head h1 { font-size: 17px; }
    .page-head p { font-size: 12px; }
  }

  /* ===== 绑定抽屉（桌面右侧 / 手机底部） ===== */
  /* 通用居中小弹窗（设备管理等） */
  .dlg-mask {
    position: fixed; inset: 0; z-index: 1100;
    background: var(--mask);
    -webkit-backdrop-filter: blur(4px);
    backdrop-filter: blur(4px);
    display: flex; align-items: center; justify-content: center;
    padding: 16px;
  }
  .dlg-mask[hidden] { display: none; }
  .dlg-card {
    width: 340px; max-width: 100%;
    background: var(--drawer-bg); color: var(--text);
    border: 1px solid var(--card-border);
    border-radius: 18px;
    padding: 18px;
    display: flex; flex-direction: column; gap: 12px;
    box-shadow: 0 12px 36px rgba(0, 0, 0, 0.18);
    animation: dlgIn 0.2s var(--ease-enter);
  }
  @keyframes dlgIn { from { transform: scale(0.96); opacity: 0.4; } to { transform: none; opacity: 1; } }
  .dlg-title { font-size: var(--fs-section); font-weight: 600; }
  .dlg-danger {
    border: none; background: none;
    color: var(--err-text); font-size: var(--fs-body); font-family: inherit;
    cursor: pointer; padding: 9px; border-radius: 10px;
    transition: background 0.15s var(--ease-hover);
  }
  .dlg-danger:hover { text-decoration: underline; }
  .dlg-danger.arm { background: color-mix(in srgb, var(--err) 12%, transparent); text-decoration: none; font-weight: 500; }
  .dlg-warn {
    border: none; background: none;
    color: var(--warn-text); font-size: var(--fs-body); font-family: inherit;
    cursor: pointer; padding: 9px; border-radius: 10px;
    transition: background 0.15s var(--ease-hover);
  }
  .dlg-warn:hover { text-decoration: underline; }
  .dlg-warn.arm { background: color-mix(in srgb, var(--warn) 14%, transparent); text-decoration: none; font-weight: 500; }

  .dev-add {
    display: flex; align-items: center; justify-content: center; gap: 6px; width: 100%;
    margin-top: 2px; padding: 10px;
    border-radius: 12px;
    border: 1px dashed var(--text-sec);
    background: transparent; color: var(--text);
    font-size: var(--fs-body); font-family: inherit; cursor: pointer;
    transition: background 0.15s var(--ease-hover), color 0.15s var(--ease-hover);
  }
  .dev-add:hover { background: var(--btn-bg); color: var(--text); }
  .dev-add svg { display: block; }
  .bind-mask {
    position: fixed; inset: 0; z-index: 1000;
    background: var(--mask);
    -webkit-backdrop-filter: blur(4px);
    backdrop-filter: blur(4px);
    display: flex; justify-content: flex-end; align-items: stretch;
    opacity: 1; transition: opacity 0.2s var(--ease-enter);
  }
  .bind-mask[hidden] { display: none; }
  .bind-drawer {
    width: 380px; max-width: 92vw;
    background: var(--drawer-bg); color: var(--text);
    border-left: 1px solid var(--card-border);
    box-shadow: -12px 0 32px rgba(0, 0, 0, 0.12);
    display: flex; flex-direction: column;
    animation: bindIn 0.24s var(--ease-enter);
  }
  @keyframes bindIn { from { transform: translateX(24px); opacity: 0.4; } to { transform: none; opacity: 1; } }
  .bind-head {
    display: flex; align-items: center; justify-content: space-between;
    padding: 16px 18px 10px;
  }
  .bind-title { font-size: var(--fs-section); font-weight: 600; }
  .bind-close {
    display: inline-flex; align-items: center; justify-content: center;
    width: 32px; height: 32px; border-radius: 50%;
    border: none; background: var(--bar-bg); color: var(--text);
    cursor: pointer;
  }
  .bind-close:hover { color: var(--text); }
  .bind-steps { display: flex; align-items: center; gap: 8px; padding: 0 18px 12px; }
  .bind-step-dot {
    font-size: var(--fs-caption); color: var(--text-sec); padding: 3px 10px; border-radius: 999px;
    background: var(--bar-bg); white-space: nowrap;
  }
  .bind-step-dot.on { color: var(--ok-text); background: color-mix(in srgb, var(--ok) 16%, transparent); font-weight: 500; }
  .bind-step-line { flex: 1; height: 1px; background: var(--bar-border); }
  .bind-body { padding: 4px 18px 18px; display: flex; flex-direction: column; gap: 14px; overflow-y: auto; }
  .bind-pane { display: flex; flex-direction: column; gap: 14px; }
  .bind-pane.hidden { display: none; }
  .bind-guide {
    display: flex; align-items: center; gap: 14px;
    padding: 14px; border-radius: 14px;
    background: var(--bar-bg); border: 1px solid var(--bar-border);
    font-size: var(--fs-body); color: var(--text); line-height: 1.55;
  }
  .bind-guide svg { flex-shrink: 0; }
  .bind-guide b { color: var(--text); }
  .bind-primary { height: 46px; font-size: var(--fs-body); }
  .scan-status {
    display: flex; align-items: center; gap: 8px;
    font-size: var(--fs-body); color: var(--text);
  }
  .scan-spin {
    width: 14px; height: 14px; border-radius: 50%; flex-shrink: 0;
    border: 2px solid var(--bar-border); border-top-color: var(--br);
    animation: spin 0.9s linear infinite;
  }
  @keyframes spin { to { transform: rotate(360deg); } }
  .bind-list { display: flex; flex-direction: column; gap: 8px; max-height: 260px; overflow-y: auto; }
  .bind-item {
    display: flex; align-items: center; gap: 10px; width: 100%;
    padding: 11px 12px; border-radius: 12px;
    border: 1px solid var(--bar-border); background: var(--bar-bg);
    font-family: inherit; font-size: var(--fs-body); color: var(--text); text-align: left;
    cursor: pointer; transition: border-color 0.15s var(--ease-hover), background 0.15s var(--ease-hover);
  }
  .bind-item:hover { border-color: color-mix(in srgb, var(--br) 45%, transparent); }
  .bind-item.sel {
    border-color: color-mix(in srgb, var(--br) 65%, transparent);
    background: color-mix(in srgb, var(--br) 10%, transparent);
  }
  .bind-ico { width: 28px; height: 28px; border-radius: 50%; background: color-mix(in srgb, var(--br) 14%, transparent); color: var(--br); display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; }
  .bind-ico svg { display: block; }
  .bind-name { font-weight: 500; }
  .bind-name .bind-noise {
    font-style: normal;
    margin-left: 6px; padding: 1px 6px;
    border-radius: 999px;
    font-size: var(--fs-micro); font-weight: 400;
    color: var(--text-mute);
    border: 1px solid color-mix(in srgb, var(--text-mute) 40%, transparent);
  }
  .bind-rssi { margin-left: auto; font-size: var(--fs-caption); color: var(--text-sec); font-family: var(--font-mono); }
  .bind-note { font-size: var(--fs-caption); color: var(--text-sec); line-height: 1.5; }
  .bind-link { align-self: center; font-size: var(--fs-caption); color: var(--br); background: none; border: none; cursor: pointer; padding: 4px 8px; font-family: inherit; }
  .bind-link:hover { text-decoration: underline; }
  /* 真机蓝牙自检 */
  .bt-check {
    border: 1px solid var(--bar-border); border-radius: 14px;
    background: var(--bar-bg); padding: 12px 14px;
    display: flex; flex-direction: column; gap: 8px;
  }
  .bt-check-title { font-size: var(--fs-card); font-weight: 600; color: var(--text); }
  .bt-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; font-size: var(--fs-body); color: var(--text-sec); }
  .bt-row b { font-weight: 500; font-size: var(--fs-card); }
  .bt-row b.ok { color: var(--ok-text); }
  .bt-row b.bad { color: var(--err-text); }
  .bt-test-btn {
    height: 40px; border-radius: 10px; cursor: pointer;
    border: 1px solid color-mix(in srgb, var(--br) 50%, transparent);
    background: color-mix(in srgb, var(--br) 12%, transparent);
    color: var(--text); font-size: var(--fs-body); font-family: inherit;
  }
  .bt-test-btn:active { transform: scale(0.98); }
  .bt-test-btn:disabled { opacity: 0.5; cursor: not-allowed; }
  .bt-result { font-size: var(--fs-caption); color: var(--text-sec); line-height: 1.55; }
  .bt-result.ok { color: var(--ok-text); }
  .bt-result.bad { color: var(--err-text); }
  .bind-done-ico { display: flex; justify-content: center; margin: 6px 0 2px; }
  .bind-done-title { text-align: center; font-size: var(--fs-section); font-weight: 600; margin-bottom: 10px; }
  .bind-field {
    display: flex; align-items: center; gap: 10px;
    padding: 10px 12px; border-radius: 12px;
    background: var(--bar-bg); border: 1px solid var(--bar-border);
    font-size: var(--fs-body);
  }
  .bind-field > span { color: var(--text-sec); flex-shrink: 0; }
  .bind-field > b { font-weight: 500; }
  .bind-input {
    flex: 1; min-width: 0;
    background: transparent; border: none; outline: none;
    color: var(--text); font-size: var(--fs-body); font-family: inherit; text-align: right;
  }
  .bind-input::placeholder { color: var(--text-sec); }
  @media (max-width: 480px) {
    .bind-mask { align-items: flex-end; }
    .bind-drawer {
      width: 100%; max-width: 100%;
      border-left: none; border-top: 1px solid var(--card-border);
      border-radius: 20px 20px 0 0;
      max-height: 88vh;
      animation-name: bindUp;
    }
    @keyframes bindUp { from { transform: translateY(24px); opacity: 0.4; } to { transform: none; opacity: 1; } }
  }

/* ===== 手机端：小米健康式卡片首页（v0.12.0） ===== */
/* ⚠️ 这里是"手机页面容器"的大名单。**新增任何一个手机容器（class="m-xxx"）都必须
   同时登记到本行 + 下面 min-width:769px 的 !important 清单**，否则它在桌面端
   不会被隐藏。见 min-width:769px 处的详细说明。 */
.m-home, .m-detail, .m-me, .m-daily, .m-help, .m-tabbar { display: none; }

@media (max-width: 768px) {
  /* 手机端隐藏桌面布局；外观切换统一放在「我的」页。 */
  .app { padding: env(safe-area-inset-top) 0 80px; border-radius: 0; border: none; max-width: 100%; }
  .page-head, .dash-main, .dash-right, .sys-fold, .controls, .fold-wrap, .bind-wrap, .dev-section, .event-wrap, .foot-note { display: none !important; }
  .topbar { flex-direction: row; justify-content: space-between; align-items: center; padding: 12px 16px 4px; gap: 8px; }
  .sub-row { gap: 8px; }

  .m-home { display: block; padding: 8px 16px 100px; }
  /* 「我的」页（v11.5）：账号 / 设备概览 / 外观 / 关于。
     全部走主题变量，深浅色自动适配。 */
  .m-me { display: block; padding: 8px 16px 100px; }
  .m-me-acct { display: flex; align-items: center; gap: 14px; }
  .m-avatar {
    width: 52px; height: 52px; border-radius: 50%; flex: 0 0 auto;
    display: flex; align-items: center; justify-content: center;
    font-size: 22px; font-weight: 700; text-transform: uppercase;
    background: var(--br-soft); color: var(--br);
  }
  .m-me-acct-info { min-width: 0; }
  .m-me-email { font-size: 16px; font-weight: 600; color: var(--text); word-break: break-all; }
  .m-me-sub { font-size: 12px; color: var(--text-dim); margin-top: 3px; line-height: 1.5; }
  .m-me-hint { font-size: 12px; color: var(--text-dim); margin-top: 12px; line-height: 1.5; }
  .m-me-btn { display: block; width: 100%; min-height: 44px; margin-top: 12px; text-align: center; }
  .m-me-row { display: flex; justify-content: space-between; align-items: center; gap: 12px; font-size: 14px; color: var(--text-sec); margin-top: 12px; }
  .m-me-row b { color: var(--text); font-weight: 600; word-break: break-all; text-align: right; }
  .m-me-logout { display: block; width: 100%; min-height: 44px; margin-top: 16px; padding: 12px; border-radius: 12px; border: 1px solid transparent; background: var(--err-bg); color: var(--err); font-size: 15px; cursor: pointer; }
  .m-me-logout:active { border-color: var(--err); }
  /* 注销账号（2026-09-30）：必须与「退出登录」在视觉上**分级**——
     退出登录是常态操作（填充底色），注销是不可逆操作（描边+更弱的底色+说明文字），
     两者用同样的强视觉会让用户误以为"作用差不多"。 */
  .m-me-danger { display: block; width: 100%; min-height: 44px; margin-top: 10px; padding: 12px; border-radius: 12px; border: 1px solid var(--card-border); background: transparent; color: var(--text-sec); font-size: 14px; cursor: pointer; }
  .m-me-danger:active { border-color: var(--err); color: var(--err); }
  .m-me-danger[disabled] { opacity: .55; cursor: default; }
  .m-me-danger-hint { margin-top: 8px; font-size: 12px; line-height: 1.6; color: var(--text-soft); }
  /* 分段控件：当前选中项由 applyTheme() 统一维护，与顶栏按钮同一状态 */
  .m-seg { display: flex; background: var(--bar-bg); border-radius: 12px; padding: 4px; margin-top: 12px; }
  .m-seg button { flex: 1; min-height: 44px; padding: 10px 0; border: none; background: transparent; border-radius: 9px; font-size: 14px; color: var(--text-sec); cursor: pointer; }
  .m-seg button.active { background: var(--active-bg, var(--card-bg, #fff)); color: var(--text); font-weight: 600; box-shadow: 0 1px 3px rgba(0,0,0,0.15); }
  .m-hero { padding: 8px 4px 4px; }
  .m-hero-title { font-size: 26px; font-weight: 700; color: var(--text); }
  .m-hero-online { display: flex; align-items: center; gap: 6px; font-size: 13px; color: var(--ok); margin-top: 4px; }
  .m-hero-online .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--ok); }
  .m-hero-online.off { color: var(--warn-text); }
  .m-hero-online.off .dot { background: var(--warn-text); }
  /* 状态横幅（v11.9）：四态。颜色全走主题变量，深浅色自动适配。
     绿=一切正常 / 橙=离线或数据过期 / 红=告警或待处理 / 灰=状态获取中。
     类名与文案由 app.js mUpdateStatusBanner() 唯一写入。 */
  .m-status-banner { display: flex; align-items: center; gap: 8px; margin-top: 12px; padding: 11px 14px; border-radius: 14px; font-size: 13.5px; font-weight: 600; border: 1px solid transparent; }
  .m-status-banner .dot { width: 8px; height: 8px; border-radius: 50%; background: currentColor; flex: 0 0 auto; }
  .m-status-banner.s-ok { background: var(--ok-bg); color: var(--ok-text); }
  .m-status-banner.s-warn { background: var(--warn-bg); color: var(--warn-text); }
  .m-status-banner.s-alarm { background: var(--err-bg); color: var(--err-text); border-color: var(--err); }
  .m-status-banner.s-wait { background: var(--mute-bg); color: var(--text-sec); }

  .m-card { background: var(--card-bg, #fff); border: 1px solid var(--card-border); border-radius: 20px; padding: 18px 20px; margin-top: var(--gap-card, 14px); box-shadow: var(--card-shadow, 0 1px 4px rgba(0,0,0,0.04)); }
  /* 次级卡（今日概览/异常与告警，v11.9）：降一级——更小内边距/圆角/标题字号，
     让两张主卡（心率/呼吸）的视觉权重真正拉开，而不是只靠排序猜层级。 */
  .m-card-sub { padding: 14px 16px; border-radius: 16px; }
  .m-card-sub .m-summary-title { font-size: 13px; }
  .m-card-hr { cursor: pointer; }
  .m-card-br { cursor: pointer; }
  .m-card-head { display: flex; align-items: center; gap: 10px; }
  .m-card-ico { width: 36px; height: 36px; border-radius: 11px; display: flex; align-items: center; justify-content: center; font-size: 18px; }
  .m-card-ico svg { width: 20px; height: 20px; display: block; }
  .m-card-ico.hr { background: var(--ico-hr-bg); color: var(--err); }
  .m-card-ico.br { background: var(--ico-br-bg); color: var(--br); }
  .m-card-name { font-size: 15px; color: var(--text-sec); }
  .m-card-big { display: flex; align-items: baseline; gap: 8px; margin-top: 10px; }
  .m-big-num { font-size: 52px; font-weight: 700; color: var(--text); line-height: 1; letter-spacing: 2px; }
  .m-big-unit { font-size: 15px; color: var(--text-sec); }
  .m-card-time { font-size: 13px; color: var(--text-dim); margin-top: 4px; }
  .m-card-time.stale { color: var(--warn-text); }
  .m-mini-chart { width: 100%; height: 48px; margin-top: 12px; display: block; }

  .m-summary-title { font-size: 15px; font-weight: 600; color: var(--text); }
  .m-summary-row { display: flex; justify-content: space-between; margin-top: 12px; }
  .m-summary-item { text-align: center; flex: 1; }
  .m-summary-label { font-size: 12px; color: var(--text-dim); }
  .m-summary-val { font-size: 20px; font-weight: 600; color: var(--text); margin-top: 2px; }
  .m-summary-val .m-unit { font-size: 12px; color: var(--text-sec); font-weight: 400; }

  /* 手机端告警条（v11.6）。桌面 .alarm-bar 用 .show/.acked 两个类控制显隐，
     这里沿用**同一套类名语义**，让 app.js 的 setAlarmUI() 只需写一处逻辑。
     默认 display:none，靠 .show 出现；.acked 表示家属已确知悉（转灰、降低存在感，
     但**不隐藏** —— 呼吸暂停期间设备仍在监护，红条必须留痕）。 */
  /* ⚠️ 0927：与桌面 .alarm-bar 同款问题——`display:none ↔ flex` 会让过渡失效
     （真机实测：0 个动画、硬跳；连 `@starting-style` 也救不回来）。
     改用 `max-height:0 + padding:0 + border-width:0 + overflow:hidden` 做 0 占位，
     过渡即可真正播放。**勿把 display:none 加回来。** */
  .m-alarm-bar {
    display: flex;
    align-items: center; gap: 10px;
    margin-top: 0; padding: 0 16px;
    max-height: 0; opacity: 0; overflow: hidden;
    border-radius: 16px;
    background: var(--err-bg);
    border: 1px solid var(--err);
    border-width: 0;
    color: var(--err-text);
    transition: max-height 0.35s var(--ease-leave), opacity 0.35s var(--ease-leave),
                padding 0.35s var(--ease-leave), margin-top 0.35s var(--ease-leave),
                border-width 0.35s var(--ease-leave);
  }
  .m-alarm-bar.show { max-height: 200px; margin-top: 12px; padding: 14px 16px; opacity: 1; border-width: 1px; }
  .m-alarm-bar.acked { background: var(--mute-bg); border-color: var(--card-border); color: var(--text-dim); }
  .m-alarm-ico { display: flex; flex: 0 0 auto; }
  .m-alarm-text { flex: 1; min-width: 0; font-size: 15px; font-weight: 600; }
  .m-alarm-time { font-size: 12px; opacity: 0.75; flex: 0 0 auto; }
  .m-alarm-ack {
    flex: 0 0 auto; min-height: 48px;   /* 告警场景按钮取 48px 上限：紧张时刻最难点中的按钮最大 */
    padding: 10px 14px; border-radius: 10px;
    border: 1px solid currentColor; background: transparent;
    color: inherit; font-family: inherit; font-size: 13px; cursor: pointer;
  }
  .m-alarm-ack:active { background: var(--btn-hover); }
  .m-alarm-bar.acked .m-alarm-ack { display: none; }   /* 已确知悉就收起按钮，避免重复点 */

  /* 手机端「异常与告警」列表。着色沿用桌面 .ev 的 err/warn 约定，
     状态标签沿用 pending/ack/ignored 三态，避免两端理解不一致。 */
  .m-alarm-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
  .m-alarm-sub { font-size: 12px; color: var(--text-dim); flex: 0 0 auto; }
  .m-abn-list { margin-top: 6px; }
  .m-abn-row { display: flex; align-items: center; gap: 10px; padding: 12px 0; border-top: 1px solid var(--card-border); }
  .m-abn-row:first-child { border-top: none; }
  .m-abn-main { flex: 1; min-width: 0; }
  .m-abn-line { display: flex; align-items: center; gap: 8px; }
  .m-abn-tag { font-size: 12px; padding: 2px 8px; border-radius: 999px; flex: 0 0 auto; }
  .m-abn-tag.err { background: var(--tag-err-bg); color: var(--err-text); }
  .m-abn-tag.warn { background: var(--tag-warn-bg); color: var(--warn-text); }
  .m-abn-time { font-size: 12px; color: var(--text-dim); }
  .m-abn-note { font-size: 12px; color: var(--text-dim); margin-top: 4px; word-break: break-all; }
  .m-abn-status { font-size: 12px; flex: 0 0 auto; }
  .m-abn-status.s-pending { color: var(--err-text); }
  .m-abn-status.s-ack { color: var(--ok-text); }
  .m-abn-status.s-ignored { color: var(--text-mute); }
  .m-abn-acts { display: flex; gap: 6px; flex: 0 0 auto; }
  .m-abn-btn {
    min-height: 44px; padding: 9px 12px; border-radius: 10px;
    border: 1px solid var(--card-border); background: transparent;
    color: var(--text-sec); font-family: inherit; font-size: 13px; cursor: pointer;
  }
  .m-abn-btn.ok { border-color: var(--ok); color: var(--ok-text); }
  .m-abn-btn.no { border-color: transparent; background: var(--mute-bg); color: var(--text-dim); }
  .m-abn-btn:active { background: var(--btn-hover); }
  .m-abn-empty { font-size: 13px; color: var(--text-dim); padding: 10px 0 4px; }

  /* 详情页 */
  .m-detail:not([hidden]) { display: block; padding: 8px 16px 24px; }
  .m-detail-head { display: flex; align-items: center; gap: 10px; padding: 8px 4px; }
  .m-back { font-size: 28px; color: var(--text); background: none; border: none; cursor: pointer; padding: 0 10px; min-width: 44px; min-height: 44px; line-height: 1; }
  .m-detail-title { font-size: 18px; font-weight: 600; color: var(--text); }
  .m-tabs { display: flex; background: var(--bar-bg); border-radius: 12px; padding: 4px; margin: 12px 0; }
  .m-tab { flex: 1; min-height: 44px; text-align: center; padding: 10px 0; border: none; background: transparent; border-radius: 9px; font-size: 14px; color: var(--text-sec); cursor: pointer; }
  .m-tab.active { background: var(--active-bg, var(--card-bg, #fff)); color: var(--text); font-weight: 600; box-shadow: 0 1px 3px rgba(0,0,0,0.15); }
  .m-detail-big { display: flex; align-items: baseline; gap: 10px; padding: 12px 4px 4px; }
  .m-detail-big .m-big-num { font-size: 56px; font-weight: 700; color: var(--text); line-height: 1; }
  .m-detail-big .m-big-unit { font-size: 16px; color: var(--text-sec); }
  .m-detail-chart { width: 100%; height: 260px; margin-top: 12px; display: block; }
  /* v11.11: 参考带图例——说明曲线下方浅绿色带是正常范围（色块用与
     drawChart 参考带同源的 --ok-bg，两主题自动跟随）。 */
  .m-detail-legend { display: flex; align-items: center; justify-content: center; gap: 6px; font-size: 12px; color: var(--text-dim); margin-top: 10px; }
  .m-legend-swatch { display: inline-block; width: 14px; height: 8px; border-radius: 3px; background: var(--ok-bg); border: 1px solid var(--ok-text); opacity: 0.55; }
  /* v11.11: 卡片 mini 折线末端点。默认填充色走 HTML 标签上的 fill 属性
     （心率 --hr / 呼吸 --br），CSS 只负责"超范围变警示红"这一态——
     类选择器优先级恒高于展示属性，无需 !important。 */
  .m-mini-dot.bad { fill: var(--err); }
  .m-detail-note { font-size: 12px; color: var(--text-dim); text-align: center; margin-top: 12px; }

  /* 底部 Tab */
  .m-tabbar { display: flex; position: fixed; bottom: 0; left: 0; right: 0; background: var(--tabbar-bg, #ffffff); border-top: 1px solid var(--card-border); padding: 8px 0 calc(8px + env(safe-area-inset-bottom)); z-index: 100; box-shadow: 0 -2px 12px rgba(0,0,0,0.06); }
  .m-tabbar-item { flex: 1; min-height: 44px; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; background: none; border: none; color: var(--text-dim); cursor: pointer; }
  .m-tabbar-item.active { color: var(--br); }
  .m-tabbar-ico { display: block; }
  /* v11.11 tab 图标内联 SVG 两态：非选中描边、选中填充（同一 path 两种呈现）。
     替换原 Unicode 字符（⌂ ▣ ☻）——那些在 Android WebView / iOS 上字形差异大，
     也表达不了选中态。设备 tab 的心电线 .ico-d 选中时反色（实心屏上要看得见）。 */
  .m-tabbar-ico svg { width: 22px; height: 22px; display: block; }
  .m-tabbar-ico .ico-l { fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
  .m-tabbar-ico .ico-f { fill: currentColor; stroke: none; display: none; }
  .m-tabbar-ico .ico-d { fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
  .m-tabbar-item.active .ico-l { display: none; }
  .m-tabbar-item.active .ico-f { display: block; }
  .m-tabbar-item.active .ico-d { stroke: var(--tabbar-bg, #ffffff); }
  .m-tabbar-label { font-size: 12px; display: block; margin-top: 2px; }
}



.m-hero-row { display: flex; justify-content: space-between; align-items: center; }
.m-refresh-btn { background: none; border: none; font-size: 20px; color: var(--text-sec); cursor: pointer; padding: 10px 14px; min-width: 44px; min-height: 44px; border-radius: 10px; }
.m-refresh-btn:active { background: var(--btn-hover); }

.m-device-list { margin-top: 14px; }
.m-device-item { background: var(--card-bg); border: 1px solid var(--card-border); border-radius: 16px; padding: 14px 16px; margin-bottom: 10px; display: flex; justify-content: space-between; align-items: center; }
.m-device-info { flex: 1; }
.m-device-name { font-size: 16px; font-weight: 600; color: var(--text); }
.m-device-sn { font-size: 12px; color: var(--text-mute); margin-top: 2px; }
/* v11.11: 设备行"X 分钟前上报"——比 SN 大半号、用次级色，一眼可读；
   数据源 /api/devices 的 last_seen（app.js lastSeenMap）。 */
.m-device-lastseen { font-size: 12px; color: var(--text-sec); margin-top: 3px; }
.m-device-status { font-size: 12px; padding: 3px 10px; border-radius: 999px; border: 1px solid transparent; }
.m-device-status.online { background: var(--ok-bg); color: var(--ok-text); }
/* v11.8：离线是「最需要被看见」的状态，此前用 mute-bg 灰底灰字几乎不可见（用户已实际反馈）。
   升级为警示红系 + ⚠ 图标；unknown 才保留灰色语义。 */
/* 顺序注意：unknown 必须写在 offline **之前** —— 三类理论上互斥，但若真的同时存在，
   让更严重的 offline 赢（CSS 同优先级后者覆盖前者）。 */
.m-device-status.unknown { background: var(--mute-bg); color: var(--text-dim); }
.m-device-status.offline { background: var(--err-bg); color: var(--err-text); border-color: var(--err); }
.m-device-status.offline::before { content: "⚠ "; }
/* 设备行右侧：状态徽标 + 「管理」入口。
   管理入口复用桌面端的设备管理弹窗（改房间名 / 告警邮箱 / 解绑）——
   此前手机端设备行**没有任何操作入口**，用户根本找不到解绑。 */
.m-device-right { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
.m-device-more {
  border: 1px solid var(--card-border);
  background: transparent;
  color: var(--text-mute);
  font-family: inherit; font-size: 12px; line-height: 1;
  padding: 10px 14px; border-radius: 10px;
  min-height: 44px;                 /* 触控目标，别做成需要瞄准的小点 */
  cursor: pointer;
  transition: background 0.15s var(--ease-hover), color 0.15s var(--ease-hover), border-color 0.15s var(--ease-hover);
}
.m-device-more:hover, .m-device-more:active {
  background: var(--btn-hover); color: var(--text); border-color: var(--text-dim);
}

/* 系统链路（手机端设备页）：四项各自的接入状态。
   注意这里**只管样式**，状态值一律由 app.js 的 updateSysLink() 写入
   （与桌面端 sysXxx 共用同一份判定），避免两处各写一套判定而互相矛盾。 */
.m-sys-list { margin-top: 12px; }
.m-sys-item { display: flex; justify-content: space-between; align-items: center; padding: 11px 0; border-top: 1px solid var(--card-border); }
.m-sys-item:first-child { border-top: none; padding-top: 3px; }
.m-sys-name { font-size: 14px; color: var(--text-sec); }
/* 状态徽标：类名语义与桌面端 .sys-state **完全一致** ——
   裸类 = 正常(ok，绿)、.idle = 待接入(灰)、.err = 异常(红)。
   （app.js 的 sysStateClass() 就是按这个约定产出类名的，别改成 .ok，否则绿不上色。） */
.m-sys-state { font-size: 12px; padding: 3px 10px; border-radius: 999px; background: var(--ok-bg); color: var(--ok-text); border: 1px solid transparent; }
.m-sys-state::before { content: ""; display: inline-block; width: 6px; height: 6px; border-radius: 50%; background: currentColor; margin-right: 5px; vertical-align: middle; }
.m-sys-state.idle { background: var(--mute-bg); color: var(--text-sec); border-color: var(--card-border); }
.m-sys-state.idle::before { opacity: 0.5; }
.m-sys-state.err { background: var(--tag-err-bg); color: var(--err-text); border-color: transparent; }
.m-sys-note { font-size: 12px; color: var(--text-dim); margin-top: 10px; }

/* 登录页（v11.11 令牌化：此前整段写死浅色值，深色主题下仍是一片纯白。
   卡片底用 --drawer-bg（两主题都是实色），输入框用 --btn-bg/--btn-border，
   与应用内抽屉/按钮观感一致；提交按钮的青色即 --br 的品牌色。 */
/* 登录遮罩默认显示。已登录时首帧直接不画它 —— 显隐规则 `html[data-auth="in"] .login-page`
   内联在 index.html <head> 里（必须首帧前生效，写在这里会被旧缓存的样式表拖一帧）；
   运行期由 app.js 的 checkLogin() 统一写 display 与 data-auth。 */
.login-page { position: fixed; inset: 0; background: var(--app-bg); display: flex; align-items: center; justify-content: center; z-index: 99999; padding: 20px; }
.login-card { background: var(--drawer-bg); border-radius: 20px; padding: 32px 28px; width: 100%; max-width: 360px; box-shadow: var(--card-shadow); border: 1px solid var(--card-border); }
.login-logo { font-size: var(--fs-page); font-weight: 700; text-align: center; color: var(--text); }
.login-sub { font-size: var(--fs-caption); color: var(--text-sec); text-align: center; margin-top: 6px; margin-bottom: 28px; }
.login-form { display: flex; flex-direction: column; gap: 12px; }
.login-input { width: 100%; padding: 12px 14px; border: 1px solid var(--btn-border); border-radius: 12px; font-size: var(--fs-body); background: var(--btn-bg); color: var(--text); box-sizing: border-box; }
.login-code-row { display: flex; gap: 8px; }
.login-code-row .login-input { flex: 1; }
.login-code-btn { padding: 0 14px; border: 1px solid var(--btn-border); border-radius: 12px; background: var(--btn-bg); color: var(--text-sec); font-size: var(--fs-body); white-space: nowrap; cursor: pointer; }
.login-code-btn:disabled { opacity: 0.5; cursor: not-allowed; }
.login-submit { padding: 13px; border: none; border-radius: 12px; background: var(--br); color: #fff; font-size: var(--fs-body); font-weight: 600; cursor: pointer; }
.login-msg { font-size: var(--fs-caption); text-align: center; min-height: 20px; }
.login-msg.error { color: var(--err); }
.login-msg.success { color: var(--ok); }

/* ===== 视觉升级：清晰层级、轻量玻璃质感与更明确的操作反馈 ===== */
:root {
  --focus-ring: color-mix(in srgb, var(--br) 34%, transparent);
  --surface-strong: color-mix(in srgb, var(--card-bg) 88%, var(--text) 2%);
  --shadow-soft: 0 18px 45px rgba(9, 27, 38, 0.08);
}
:root[data-theme="dark"] {
  --shadow-soft: 0 18px 45px rgba(0, 0, 0, 0.24);
}

body {
  position: relative;
  isolation: isolate;
  background-image:
    radial-gradient(900px 520px at 8% -10%, color-mix(in srgb, var(--br) 11%, transparent), transparent 64%),
    radial-gradient(760px 460px at 96% 5%, color-mix(in srgb, var(--hr) 9%, transparent), transparent 62%),
    var(--page-bg);
}
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  opacity: .32;
  background-image: linear-gradient(color-mix(in srgb, var(--text) 5%, transparent) 1px, transparent 1px), linear-gradient(90deg, color-mix(in srgb, var(--text) 5%, transparent) 1px, transparent 1px);
  background-size: 44px 44px;
  mask-image: linear-gradient(to bottom, rgba(0,0,0,.6), transparent 75%);
}

button, input, select { -webkit-tap-highlight-color: transparent; }
button:focus-visible, input:focus-visible, select:focus-visible, [tabindex]:focus-visible {
  outline: 3px solid var(--focus-ring);
  outline-offset: 2px;
}
.page-head { margin-bottom: 26px; }
.page-head h1 { font-size: var(--fs-page); letter-spacing: -.01em; }
.page-head p { margin-top: 8px; font-size: var(--fs-body); color: var(--page-sub); }
.page-head .brand-mark { position: relative; }
.page-head .brand-mark::after { content: ""; display: inline-block; width: 6px; height: 6px; margin-left: 7px; vertical-align: 3px; border-radius: 50%; background: var(--br); box-shadow: 0 0 0 4px color-mix(in srgb, var(--br) 14%, transparent); }
.app {
  box-shadow: var(--shadow-soft);
  backdrop-filter: blur(18px);
}
.topbar { padding-bottom: 2px; }
.brand { letter-spacing: .01em; }
.brand svg { width: 26px; height: 26px; padding: 5px; border-radius: 9px; background: color-mix(in srgb, var(--br) 13%, transparent); }
.live { padding: 6px 10px; border: 1px solid color-mix(in srgb, var(--ok) 26%, transparent); border-radius: 999px; background: color-mix(in srgb, var(--ok) 8%, transparent); }
.live.off { border-color: var(--bar-border); background: var(--bar-bg); }
.theme-btn { box-shadow: 0 4px 12px color-mix(in srgb, var(--text) 8%, transparent); }
.device-row, .range-bar { box-shadow: 0 5px 16px color-mix(in srgb, var(--text) 4%, transparent); }
.chart-card, .stat-card, .side-card, .events {
  box-shadow: 0 8px 22px color-mix(in srgb, var(--text) 5%, transparent);
}
.chart-card { position: relative; overflow: hidden; }
.chart-card::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 2px;
  background: linear-gradient(90deg, var(--hr), transparent 72%);
  opacity: .75;
}
.chart-card-br::before { background: linear-gradient(90deg, var(--br), transparent 72%); }
.chart-value { letter-spacing: -.04em; }
.stat-card, .side-card, .events { transition: transform .2s var(--ease-hover), box-shadow .2s var(--ease-hover), border-color .2s var(--ease-hover); }
.stat-card:hover, .side-card:hover { transform: translateY(-2px); box-shadow: 0 12px 26px color-mix(in srgb, var(--text) 8%, transparent); border-color: color-mix(in srgb, var(--br) 22%, var(--card-border)); }
.stat-label svg { padding: 3px; width: 22px; height: 22px; border-radius: 7px; background: color-mix(in srgb, var(--br) 10%, transparent); }
.stat-card:first-child .stat-label svg { background: color-mix(in srgb, var(--hr) 10%, transparent); }
.range-bar { align-self: flex-start; }
.range-btn { min-height: 30px; }
.range-btn.active { box-shadow: 0 2px 8px color-mix(in srgb, var(--br) 16%, transparent); }
.conn-bar, .alarm-bar { box-shadow: 0 5px 16px color-mix(in srgb, var(--text) 5%, transparent); }
.ev { transition: border-color .15s var(--ease-hover), background .15s var(--ease-hover), transform .15s var(--ease-hover); }
.ev:hover { transform: translateX(2px); border-color: color-mix(in srgb, var(--br) 30%, var(--bar-border)); }
.dev-item.active { box-shadow: inset 3px 0 0 var(--br); }
.dev-add { min-height: 42px; }

/* 登录页改成“欢迎进入 + 登录操作”的聚焦场景，手机自动退化为单卡片。 */
.login-page {
  overflow: hidden;
  background:
    radial-gradient(800px 620px at 20% 40%, color-mix(in srgb, var(--br) 16%, transparent), transparent 66%),
    radial-gradient(680px 520px at 90% 30%, color-mix(in srgb, var(--hr) 10%, transparent), transparent 64%),
    var(--app-bg);
}
.login-page::before {
  content: "守护每一次呼吸\A让安心有迹可循";
  white-space: pre;
  position: absolute;
  left: max(7vw, 44px);
  top: 50%;
  transform: translateY(-56%);
  color: var(--text);
  font-size: clamp(30px, 4vw, 56px);
  font-weight: 700;
  line-height: 1.22;
  letter-spacing: -.04em;
  opacity: .92;
}
.login-page::after {
  content: "实时体征 · 异常提醒 · 安心相伴";
  position: absolute;
  left: max(7vw, 44px);
  top: calc(50% + 80px);
  color: var(--text-sec);
  font-size: 14px;
  letter-spacing: .1em;
}
.login-card {
  position: relative;
  z-index: 1;
  max-width: 408px;
  margin-left: min(42vw, 460px);
  padding: 34px 34px 26px;
  border-radius: 24px;
  box-shadow: 0 24px 70px color-mix(in srgb, var(--text) 16%, transparent);
  backdrop-filter: blur(18px);
}
.login-brand-row { display: flex; align-items: center; gap: 10px; color: var(--br); }
.login-brand-icon { display: inline-flex; width: 34px; height: 34px; align-items: center; justify-content: center; border-radius: 11px; background: color-mix(in srgb, var(--br) 15%, transparent); }
.login-brand-icon svg { display: block; }
.login-brand-label { font-size: 14px; font-weight: 600; letter-spacing: .04em; }
.login-kicker { margin-top: 30px; color: var(--br); font-size: var(--fs-micro); font-weight: 600; letter-spacing: .08em; }
.login-logo { margin-top: 8px; text-align: left; font-size: var(--fs-page); letter-spacing: -.04em; }
.login-sub { margin-top: 9px; margin-bottom: 26px; text-align: left; line-height: 1.6; }
.login-form { gap: 8px; }
.login-field-label { margin-top: 6px; color: var(--text-sec); font-size: var(--fs-caption); font-weight: 500; }
.login-input { min-height: 46px; padding: 12px 14px; border-radius: 13px; background: color-mix(in srgb, var(--btn-bg) 80%, transparent); transition: border-color .18s var(--ease-hover), box-shadow .18s var(--ease-hover), background .18s var(--ease-hover); }
.login-input:focus { border-color: color-mix(in srgb, var(--br) 65%, transparent); background: var(--drawer-bg); box-shadow: 0 0 0 4px color-mix(in srgb, var(--br) 12%, transparent); outline: none; }
.login-code-btn { min-height: 46px; padding: 0 15px; border-radius: 13px; font-weight: 500; transition: border-color .18s var(--ease-hover), color .18s var(--ease-hover), background .18s var(--ease-hover); }
.login-code-btn:hover { color: var(--br); border-color: color-mix(in srgb, var(--br) 48%, transparent); background: color-mix(in srgb, var(--br) 8%, transparent); }
.login-submit { min-height: 48px; margin-top: 10px; border-radius: 13px; background: linear-gradient(135deg, color-mix(in srgb, var(--br) 88%, white 12%), var(--br)); box-shadow: 0 10px 20px color-mix(in srgb, var(--br) 24%, transparent); transition: transform .15s var(--ease-hover), box-shadow .15s var(--ease-hover), filter .15s var(--ease-hover); }
.login-submit:hover { filter: brightness(1.04); box-shadow: 0 13px 25px color-mix(in srgb, var(--br) 30%, transparent); transform: translateY(-1px); }
.login-submit:active { transform: translateY(0); }
.login-submit.is-loading, .login-code-btn.is-loading { cursor: wait; }
.login-submit.is-loading::before, .login-code-btn.is-loading::before {
  content: "";
  display: inline-block;
  width: 14px; height: 14px;
  margin-right: 8px;
  vertical-align: -2px;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: spin .75s linear infinite;
}
.login-page.is-closing { animation: loginOut .22s var(--ease-leave) forwards; pointer-events: none; }
@keyframes loginOut { to { opacity: 0; transform: scale(1.015); } }
.login-footnote { display: flex; align-items: center; justify-content: center; gap: 7px; margin-top: 22px; color: var(--text-mute); font-size: var(--fs-caption); }
.login-foot-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--ok); box-shadow: 0 0 0 3px color-mix(in srgb, var(--ok) 14%, transparent); }

@media (max-width: 760px) {
  body::before { opacity: .18; }
  .login-page::before, .login-page::after { display: none; }
  .login-card { margin-left: 0; max-width: 408px; }
}

@media (max-width: 480px) {
  body { background-image: radial-gradient(420px 260px at 10% -5%, color-mix(in srgb, var(--br) 10%, transparent), transparent 65%), var(--page-bg); }
  .app { box-shadow: none; backdrop-filter: none; }
  .topbar { padding-top: max(12px, env(safe-area-inset-top)); }
  .brand { font-size: 15px; }
  .brand svg { width: 24px; height: 24px; }
  .theme-btn { width: 40px; height: 40px; }
  .m-hero-title { letter-spacing: -.04em; }
  .m-status-banner { box-shadow: 0 6px 18px color-mix(in srgb, var(--text) 5%, transparent); }
  .m-card { box-shadow: 0 7px 22px color-mix(in srgb, var(--text) 6%, transparent); }
  .m-card-big { margin-top: 12px; }
  .m-big-num { letter-spacing: -.04em; }
  .m-tabbar { backdrop-filter: blur(18px); background: color-mix(in srgb, var(--tabbar-bg) 88%, transparent); }
  .m-refresh-btn.is-loading { color:var(--br); pointer-events:none; }
  .login-page { padding: 18px; }
  .login-card { padding: 28px 22px 22px; border-radius: 22px; }
  .login-kicker { margin-top: 24px; }
  .login-logo { font-size: 26px; }
}

/* ===== v11.15 体验升级：温柔的监护工作台 ===== */
:root {
  --brand-ink: #102a36;
  --brand-soft: color-mix(in srgb, var(--br) 12%, transparent);
  --line-soft: color-mix(in srgb, var(--text) 10%, transparent);
  --surface-raised: color-mix(in srgb, var(--card-bg) 78%, var(--text) 2%);
}
:root[data-theme="dark"] { --brand-ink: #eef8f7; }
.page-eyebrow, .mobile-kicker, .overview-kicker, .story-eyebrow { font-family: var(--font-mono); font-size: 10px; letter-spacing: .14em; text-transform: uppercase; color: var(--br); font-weight: 600; }
.page-head h1 { letter-spacing: -.035em; font-size: var(--fs-page); line-height: 1.15; }
.page-head .page-eyebrow { margin-bottom: 10px; }
.page-head p { font-size: var(--fs-body); }
.page-head .head-actions { align-items: center; }
.head-actions .app-btn2 { min-width: auto; height: 38px; border-radius: 11px; }
.app-btn2 span[aria-hidden] { color: var(--br); font-size: 16px; }
.care-overview { display: flex; align-items: center; justify-content: space-between; gap: 22px; padding: 22px 24px; border: 1px solid color-mix(in srgb, var(--br) 22%, var(--card-border)); border-radius: 20px; background: linear-gradient(115deg, color-mix(in srgb, var(--br) 13%, var(--card-bg)), var(--card-bg) 62%); box-shadow: 0 12px 30px color-mix(in srgb, var(--br) 7%, transparent); overflow: hidden; position: relative; }
.care-overview::after { content: ""; position: absolute; width: 190px; height: 190px; right: 12%; top: -95px; border: 1px solid color-mix(in srgb, var(--br) 30%, transparent); border-radius: 50%; box-shadow: 0 0 0 22px color-mix(in srgb, var(--br) 4%, transparent), 0 0 0 44px color-mix(in srgb, var(--br) 3%, transparent); pointer-events: none; }
.overview-copy { min-width: 0; position: relative; z-index: 1; }
.overview-copy h2 { margin: 7px 0 5px; color: var(--brand-ink); font-size: var(--fs-section); letter-spacing: -.035em; }
.overview-copy p { margin: 0; color: var(--text-sec); font-size: var(--fs-body); }
.overview-status { display: inline-flex; align-items: center; gap: 7px; margin-top: 14px; padding: 6px 10px; border-radius: 999px; font-size: var(--fs-micro); font-weight: 600; }
.overview-status .dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; }
.overview-status.s-ok { color: var(--ok-text); background: color-mix(in srgb, var(--ok) 12%, transparent); }
.overview-status.s-warn { color: var(--warn-text); background: color-mix(in srgb, var(--warn-text) 12%, transparent); }
.overview-status.s-alarm { color: var(--err-text); background: color-mix(in srgb, var(--err) 12%, transparent); }
.overview-status.s-wait { color: var(--text-sec); background: var(--bar-bg); }
.overview-actions { display: flex; align-items: center; gap: 18px; position: relative; z-index: 1; }
.overview-icon { width: 58px; height: 58px; display: grid; place-items: center; border-radius: 18px; color: var(--br); background: color-mix(in srgb, var(--br) 14%, transparent); }
.overview-icon svg { width: 37px; height: 37px; }
.primary-action { min-height: 42px; padding: 0 16px; border: 0; border-radius: 12px; background: var(--br); color: #fff; font-weight: 600; font-size: var(--fs-body); font-family: var(--font-sans); cursor: pointer; box-shadow: 0 8px 18px color-mix(in srgb, var(--br) 24%, transparent); transition: transform .18s var(--ease-hover), filter .18s var(--ease-hover), box-shadow .18s var(--ease-hover); }
.primary-action:hover { transform: translateY(-1px); filter: brightness(1.04); box-shadow: 0 11px 22px color-mix(in srgb, var(--br) 30%, transparent); }
.primary-action:active { transform: translateY(0); }
a.primary-action { display: inline-flex; align-items: center; justify-content: center; text-decoration: none; }
#helpContactCard .primary-action { width: 100%; margin-top: 12px; }
.desk-kv a { color: var(--desk-link); overflow-wrap: anywhere; text-decoration: none; }
.desk-kv a:hover { text-decoration: underline; }
.text-action { border: 0; background: transparent; color: var(--br); font-weight: 500; font-size: var(--fs-body); font-family: var(--font-sans); padding: 7px 0; cursor: pointer; }
.pause-notice { display: flex; align-items: center; justify-content: space-between; padding: 10px 13px; border-radius: 12px; background: var(--warn-bg); color: var(--warn-text); font-size: var(--fs-body); }
.pause-notice[hidden] { display: none; }
.trend-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 16px; }
.trend-toolbar h2 { margin: 0 0 3px; font-size: var(--fs-section); letter-spacing: -.02em; }
.trend-toolbar > div:first-child span { font-size: var(--fs-caption); color: var(--text-mute); }
.trend-toolbar .range-bar { margin-left: auto; }
.events { overflow: hidden; }
.events-head { font-size: var(--fs-section); font-weight: 600; }
.events-sub { padding: 4px 8px; border-radius: 999px; background: color-mix(in srgb, var(--br) 11%, transparent); color: var(--br); font-size: var(--fs-micro); }
.ui-toast { position: fixed; left: 50%; bottom: 28px; z-index: 2000; max-width: min(420px, calc(100vw - 32px)); padding: 11px 16px; border: 1px solid var(--card-border); border-radius: 12px; background: var(--drawer-bg); color: var(--text); box-shadow: 0 12px 30px color-mix(in srgb, var(--text) 16%, transparent); font-size: var(--fs-body); opacity: 0; transform: translate(-50%, 12px); pointer-events: none; transition: opacity .2s var(--ease-enter), transform .2s var(--ease-enter); }
.ui-toast.show { opacity: 1; transform: translate(-50%, 0); }
.ui-toast.ok { border-color: color-mix(in srgb, var(--ok) 45%, var(--card-border)); }
.ui-toast.warn { border-color: color-mix(in srgb, var(--warn-text) 45%, var(--card-border)); }
.guide-card { width: min(520px, 100%); padding: 22px; }
.guide-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 14px; }
.guide-head h2 { margin: 6px 0 0; font-size: var(--fs-section); letter-spacing: -.04em; }
.guide-intro { margin: 14px 0 3px; color: var(--text-sec); font-size: var(--fs-body); }
.guide-steps { display: flex; flex-direction: column; gap: 2px; list-style: none; margin: 14px 0 10px; padding: 0; }
.guide-steps li { display: flex; align-items: flex-start; gap: 14px; padding: 14px 0; border-bottom: 1px solid var(--line-soft); }
.guide-steps li > span { color: var(--br); font-weight: 600; font-size: var(--fs-caption); font-family: var(--font-mono); padding-top: 2px; }
.guide-steps h3 { margin: 0 0 4px; font-size: var(--fs-card); }
.guide-steps p { margin: 0; color: var(--text-sec); font-size: var(--fs-body); line-height: 1.65; }
.guide-foot { padding: 10px 12px; border-radius: 10px; background: var(--bar-bg); color: var(--text-mute); font-size: var(--fs-caption); line-height: 1.5; }
.guide-card > .primary-action { width: 100%; margin-top: 14px; }
.current-device, .welcome-card, .care-tip, .alert-tabs { display: none; }
.mgClose { flex-shrink: 0; }
.m-hero-title { font-weight: 700; }
.section-note { float: right; margin-top: 3px; font-size: var(--fs-micro); font-weight: 400; color: var(--text-mute); }
.guide-row { display: flex; justify-content: space-between; width: 100%; min-height: 42px; margin-top: 12px; padding: 0; border: 0; border-top: 1px solid var(--card-border); background: transparent; color: var(--text); font-weight: 500; font-size: var(--fs-body); font-family: var(--font-sans); text-align: left; cursor: pointer; }
.guide-row span:last-child { color: var(--br); font-size: 18px; }
.login-story { position: absolute; left: max(7vw, 44px); top: 50%; width: min(43vw, 550px); transform: translateY(-50%); z-index: 1; }
.login-page::before, .login-page::after { display: none; }
.story-eyebrow { display: flex; align-items: center; gap: 8px; }
.story-eyebrow span { width: 7px; height: 7px; border-radius: 50%; background: var(--br); box-shadow: 0 0 0 5px color-mix(in srgb, var(--br) 14%, transparent); }
.login-story h2 { margin: 22px 0 15px; color: var(--brand-ink); font-size: clamp(36px, 4.3vw, 62px); line-height: 1.12; letter-spacing: -.065em; }
.login-story h2 em { color: var(--br); font-style: normal; }
.login-story > p { margin: 0; color: var(--text-sec); font-size: 15px; line-height: 1.8; }
.care-illustration { position: relative; width: 100%; height: 160px; margin-top: 27px; }
.care-house { position: absolute; left: 22%; top: 24px; display: grid; place-items: center; width: 100px; height: 100px; border-radius: 30px; color: var(--br); background: color-mix(in srgb, var(--br) 10%, transparent); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--br) 20%, transparent), 0 16px 34px color-mix(in srgb, var(--br) 12%, transparent); }
.care-house svg { width: 60px; height: 60px; }
.care-orbit { position: absolute; left: calc(22% - 34px); top: -9px; width: 168px; height: 168px; border: 1px solid color-mix(in srgb, var(--br) 26%, transparent); border-radius: 50%; transform: rotate(-24deg) scaleY(.48); }
.orbit-two { left: calc(22% - 58px); top: 12px; width: 215px; height: 160px; border-color: color-mix(in srgb, var(--hr) 17%, transparent); transform: rotate(26deg) scaleY(.45); }
.care-tag { position: absolute; display: inline-flex; align-items: center; gap: 7px; padding: 7px 10px; border: 1px solid var(--line-soft); border-radius: 999px; background: color-mix(in srgb, var(--drawer-bg) 70%, transparent); color: var(--text-sec); font-size: var(--fs-micro); box-shadow: 0 7px 17px color-mix(in srgb, var(--text) 5%, transparent); }
.care-tag i { width: 5px; height: 5px; border-radius: 50%; background: var(--br); }
.tag-top { left: 49%; top: 12px; }
.tag-bottom { left: 44%; top: 99px; }
.story-features { display: flex; gap: 24px; color: var(--text-mute); font: 10px var(--font-mono); }
.story-features b { margin-left: 4px; color: var(--text-sec); font-family: inherit; font-weight: 500; }
@media (max-width: 760px) {
  .page-head { align-items: flex-start; }
  .page-head .head-actions { width: 100%; }
  .care-overview { padding: 18px; }
  .overview-icon { display: none; }
  .login-story { display: none; }
}
@media (max-width: 768px) {
  .care-overview, .pause-notice, .trend-toolbar { display: none; }
  .ui-toast { bottom: calc(78px + env(safe-area-inset-bottom)); }
  .current-device { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin: 12px 0 4px; padding: 10px 12px; border: 1px solid var(--card-border); border-radius: 12px; background: var(--surface-raised); color: var(--text-mute); font-size: 11px; }
  .current-device select { flex: 1; min-width: 0; border: 0; background: transparent; color: var(--text); font: 600 12px inherit; outline: 0; text-align: right; }
  .welcome-card { display: none; padding: 20px 18px; margin-top: var(--gap-card); border: 1px solid color-mix(in srgb, var(--br) 24%, var(--card-border)); border-radius: 18px; background: linear-gradient(145deg, color-mix(in srgb, var(--br) 11%, var(--card-bg)), var(--card-bg)); text-align: center; }
  .welcome-card.show { display: block; }
  .welcome-symbol { display: inline-grid; place-items: center; width: 38px; height: 38px; border-radius: 12px; color: var(--br); background: var(--brand-soft); font-size: 25px; }
  .welcome-card h3 { margin: 12px 0 5px; font-size: 16px; }
  .welcome-card p { margin: 0 auto 14px; max-width: 290px; color: var(--text-sec); font-size: 12px; line-height: 1.65; }
  .welcome-card .primary-action { width: 100%; }
  .welcome-card .text-action { display: block; margin: 7px auto 0; }
  .mobile-kicker { margin-bottom: 5px; font-size: 9px; }
  .alert-tabs { display: flex; gap: 6px; margin: 11px 0 2px; }
  .alert-tabs button { padding: 6px 10px; border: 0; border-radius: 999px; background: var(--bar-bg); color: var(--text-mute); font: 500 11px inherit; cursor: pointer; }
  .alert-tabs button.active { background: color-mix(in srgb, var(--br) 15%, transparent); color: var(--br); }
  .care-tip { display: flex; align-items: center; gap: 8px; margin: 14px 3px 0; color: var(--text-mute); font-size: 11px; }
  .care-tip span:first-child { color: var(--br); font-size: 16px; }
  .care-tip button { margin-left: auto; border: 0; background: transparent; color: var(--br); font-size: 17px; cursor: pointer; }
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; scroll-behavior: auto !important; transition-duration: .01ms !important; }
}

/* ===== v12.0: 守护工作台 ===== */
:root {
  --desk-ink: var(--text); --desk-muted: var(--text-mute); --desk-line: var(--card-border);
  --desk-blue: #316a96; --desk-blue-deep: #24577d; --desk-link: #316a96; --desk-mint: #28ac94;
  --desk-surface: #152735; --desk-soft: #1c3140; --desk-page: #0d1c28;
}
:root[data-theme="light"] {
  --text: #193852; --text-sec: #547087; --text-soft: #6b8297; --text-mute: #71869b; --text-dim: #71869b;
  --card-border: #e4edf3; --card-bg: #fff; --bar-bg: #f2f7fa; --bar-border: #e3ebf2;
  --hr: #ee796e; --br: #16aa90; --ok-text: #07846e; --ok: #32b88c;
  --desk-ink: #153451; --desk-muted: #768da3; --desk-line: #e3edf3;
  --desk-surface: #fff; --desk-soft: #f3f7fa; --desk-page: #f0f6f9;
  --page-bg: #f0f6f9; --app-bg: #f0f6f9; --drawer-bg: #fff;
}
:root[data-theme="dark"] { --desk-blue: #376f99; --desk-blue-deep: #2e6289; --desk-link: #8dc4ed; --desk-mint: #58cbb2; }
.svg-library { position:absolute; width:0; height:0; overflow:hidden; }
.ui-icon { width:23px; height:23px; fill:none; stroke:currentColor; stroke-width:1.7; stroke-linecap:round; stroke-linejoin:round; flex:none; }
.brand .brand-mark { width:39px; height:43px; display:grid; place-items:center; color:white; border-radius:15px 15px 20px 20px; background:linear-gradient(140deg,#66d2ac,#28799e); transform:rotate(-8deg); }
.brand .brand-mark svg { width:28px; height:28px; background:none; padding:0; transform:rotate(8deg); }
.brand small { display:block; font-size:11px; font-weight:400; color:var(--text-soft); letter-spacing:.08em; margin-top:4px; }
.primary-action, .dev-add { background:var(--desk-blue); color:white; border:0; }
.login-page { overflow-y:auto; }
body.login-open { overflow:hidden; }
.dev-state.unknown, .device-status.unknown { color:var(--text-mute); }
.dev-dot.unknown { background:var(--text-mute) !important; }
/* ⚠️ 0927：这行 `.alarm-bar:not(.show), .alarm-bar.acked { display:none }` **已删除**。
   它是"收起态 0 占位"的实现手段，但代价是**杀死了 max-height 过渡**（display:none → flex
   是"新盒首次布局"，没有可插值的前值 ⇒ 实测 0 个动画、硬跳）。
   改为在 .alarm-bar / .alarm-bar.acked 里用 `max-height:0 + padding:0 + border-width:0
   + overflow:hidden` 实现**真 0 占位**（实测收起态 h=0.00、border-width=0px），
   同时过渡能真正播放（实测 8 个 running 过渡）。**勿再把 display:none 加回来。** */
#brStatus[hidden] { display:none !important; }
.dev-main { min-width:0; }
.dev-name-txt { min-width:0; overflow:hidden; text-overflow:ellipsis; }
.dev-name-txt b, .dev-name-txt small { display:block; }
.dev-name-txt b { font-size: var(--fs-card); font-weight:600; color:var(--text); }
.dev-name-txt small { font-size: var(--fs-caption); margin-top:5px; color:var(--text-mute); font-weight:400; }
.dev-state { font-size: var(--fs-caption); }
.device-row { box-shadow:none; }
.chart-card::before { display:none; }
.metric-icon { width:39px; height:39px; display:grid; place-items:center; border-radius:50%; flex:none; }
.metric-icon.hr { color:var(--hr); background:color-mix(in srgb,var(--hr) 12%,transparent); }
.metric-icon.hr .ui-icon { fill:currentColor; stroke-width:1.2; width:21px; }
.metric-icon.br { color:var(--br); background:color-mix(in srgb,var(--br) 12%,transparent); }
.chart-summary { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:8px; }
.chart-summary > div { background:var(--desk-soft); border-radius:12px; padding:12px 10px; }
.chart-summary span { display:block; font-size: var(--fs-caption); color:var(--text-mute); margin-bottom:7px; }
.chart-summary b { font-weight:500; font-size: var(--fs-num-sm); line-height:1.1; font-family: var(--font-mono); color:var(--text); }
.chart-summary > div:nth-child(2) b { color:var(--hr); }
.chart-card-br .chart-summary > div:nth-child(2) b { color:var(--br); }
/* 图例行（12.6）：桌面两张趋势卡的参考范围说明，与手机端 .m-detail-legend 同款观感。
   注意与上方 .chart-legend 胶囊徽章（旧版图表标题里的"正常 60–100"药丸，现无引用）同名，
   这里把胶囊的 padding/圆角/底色显式清掉，防止两套样式叠加出一个带底色的横条。 */
.chart-legend { display:flex; align-items:center; gap:6px; font-size: var(--fs-caption); color:var(--text-dim); margin:2px 2px 10px; padding:0; border-radius:0; background:none; }
.chart-legend-swatch { display:inline-block; width:14px; height:8px; border-radius:3px; background:var(--ok-bg); border:1px solid var(--ok-text); opacity:0.55; }
.trend-note { margin:0; color:var(--text-mute); font-size: var(--fs-caption); text-align:center; }
.events-list { overflow-y:auto; scrollbar-width:thin; }
.sidebar-logout { border:0; background:transparent; font-size: var(--fs-caption); font-family: var(--font-sans); color:var(--text-soft); cursor:pointer; padding:10px; }
/* 桌面端注销入口：与退出登录并列但更弱（文字按钮、hover 才转错误色），避免误触 */
.sidebar-danger { border:0; background:transparent; font-size: var(--fs-caption); font-family: var(--font-sans); color:var(--text-soft); cursor:pointer; padding:10px; }
.sidebar-danger:hover { color:var(--err); }
.sidebar-danger[disabled] { opacity:.55; cursor:default; }
.dev-empty { padding:21px 8px; font-size: var(--fs-body); line-height:1.8; }
.dev-empty span { color:var(--text-sec); }
[id="overviewSection"], #trendSection, #desktopEvents, #devicePanel { scroll-margin-top:24px; }

/* v12.3：紧凑总览 + 常驻四段设备链路。 */
.device-chain { display:none; }
@media (min-width:769px) {
  body { display:block; padding:0 32px 20px; background:var(--desk-page); overflow-x:clip; }
  body::before { display:none; }
  .app { width:100%; max-width:1600px; margin:0 auto; padding:0; display:flex; flex-direction:column; gap:18px; border:0; border-radius:0; background:none; box-shadow:none; backdrop-filter:none; }
  .topbar { position:relative; isolation:isolate; min-height:76px; width:100%; padding:15px 0; margin-bottom:6px; display:flex; flex-direction:row; align-items:center; gap:16px; background:var(--desk-surface); border:0; }
  .topbar::before { content:""; position:absolute; z-index:-1; inset:0 calc(50% - 50vw); background:var(--desk-surface); border-bottom:1px solid var(--desk-line); }
  .top-row { display:flex; align-items:center; flex-shrink:0; }
  .brand { display:flex; gap:10px; color:var(--desk-ink); font-size:23px; font-weight:700; letter-spacing:-.03em; }
  .brand small { font-size:10px; letter-spacing:.05em; }
  .topbar-right { display:none; }
  .head-actions { margin-left:auto; display:flex; align-items:center; gap:5px; }
  .head-actions .app-btn2 { min-width:0; height:40px; padding:0 10px; border:0; background:transparent; color:var(--text-soft); box-shadow:none; font-size: var(--fs-body); white-space:nowrap; }
  .head-actions .app-btn2:hover { background:var(--desk-soft); color:var(--desk-ink); }
  .account-chip { display:flex; align-items:center; gap:9px; margin-left:8px; padding-left:16px; border-left:1px solid var(--desk-line); }
  .account-avatar { width:35px; height:35px; display:grid; place-items:center; flex:none; border-radius:50%; color:#fff; background:linear-gradient(135deg,#6a9ba6,#275677); font-size:15px; font-weight:600; }
  .account-copy { min-width:0; }
  .account-copy b { display:block; max-width:160px; font-size: var(--fs-card); color:var(--text); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .account-copy small { display:none; }
  .sub-row { display:flex; align-items:center; gap:6px; }
  .theme-btn { width:36px; height:36px; border:0; box-shadow:none; background:var(--desk-soft); flex:none; }
  .sidebar-logout { white-space:nowrap; font-size: var(--fs-caption); }
  /* 🔴 桌面端必须隐藏**全部**手机页面容器，一个都不能漏。
     这些容器由 mSwitchPage() 写**内联** display 控制，所以只有这里的
     !important 能在桌面宽度压住它（内联样式赢过非 !important 的规则）。
     漏掉一个的后果（v0.6.0 日报页实测）：该容器保持显示；又因为它是
     main#app 的直接子级且没有 grid-area，会被自动放进 "side top / side body /
     side foot" 之外的**隐式网格行** ⇒ 落在 foot 行之后 ⇒ 表现为
     "每一页最底部都多出一块内容"。tools/static_assert.js 第 39 节做了
     集等价断言，漏登记会直接红。 */
  .m-home, .m-device, .m-detail, .m-me, .m-daily, .m-help, .m-tabbar, .mobile-vitals { display:none !important; }
  .care-overview { display:grid; grid-template-columns:1fr auto; gap:15px 20px; padding:0; border:0; border-radius:0; background:none; box-shadow:none; overflow:visible; }
  .care-overview::after { display:none; }
  .overview-heading h1 { margin:0 0 6px; color:var(--desk-ink); font-size: var(--fs-page); letter-spacing:.01em; }
  .overview-heading p { margin:0; font-size: var(--fs-body); color:var(--text-soft); }
  .overview-controls { display:flex; align-items:center; gap:18px; }
  .overview-controls select { max-width:270px; min-width:180px; height:43px; padding:0 36px 0 14px; border:1px solid var(--desk-line); border-radius:10px; background:var(--desk-surface); color:var(--text); font-family:inherit; font-weight:500; font-size: var(--fs-body); cursor:pointer; text-overflow:ellipsis; }
  .overview-controls .primary-action { min-height:43px; padding:0 18px; font-size: var(--fs-body); white-space:nowrap; }
  .device-status { margin:0; font-size: var(--fs-caption); gap:7px; color:var(--ok-text); white-space:nowrap; }
  .device-status.off { color:var(--warn-text); }
  .device-status.unknown { color:var(--text-mute); }
  .device-status .dot { width:8px; height:8px; border-radius:50%; background:currentColor; }
  .overview-status { grid-column:1/-1; display:flex; flex-wrap:wrap; align-items:center; gap:8px; min-height:42px; margin:0; padding:10px 14px; border:1px solid color-mix(in srgb,currentColor 18%,transparent); border-radius:10px; font-size: var(--fs-micro); font-weight:400; }
  .overview-status .ui-icon { width:17px; height:17px; flex:none; }
  .overview-status strong { font-weight:600; }
  .overview-status #overviewMeta:not(:empty)::before { content:"·"; margin-right:8px; }
  .overview-description { margin-left:auto; font-size: var(--fs-caption); }
  .device-chain { display:block; padding:16px 21px 14px; border:1px solid var(--desk-line); border-radius:15px; background:var(--desk-surface); box-shadow:0 4px 15px #20465b03; }
  .chain-heading { display:flex; align-items:center; gap:16px; }
  .chain-heading h2 { margin:0; font-size: var(--fs-section); color:var(--text); }
  .chain-heading p { margin:0; color:var(--text-mute); font-size: var(--fs-caption); }
  .chain-heading .text-action { margin-left:auto; font-size: var(--fs-body); min-height:30px; white-space:nowrap; }
  .chain-nodes { display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:40px; margin:15px 0 12px; padding:0; list-style:none; }
  .chain-node { min-width:0; position:relative; display:flex; align-items:center; gap:13px; }
  .chain-node:not(:last-child)::after { content:""; position:absolute; width:28px; right:-34px; top:50%; border-top:1px dashed var(--text-mute); opacity:.55; }
  .chain-icon { display:grid; place-items:center; flex:none; width:55px; height:59px; background:var(--desk-soft); border-radius:18px; color:var(--desk-link); }
  .chain-icon .ui-icon { width:30px; height:30px; stroke-width:1.6; }
  .chain-node h3 { margin:0 0 4px; font-size: var(--fs-card); font-weight:600; color:var(--text); }
  .chain-node p { margin:0 0 6px; font-size: var(--fs-caption); color:var(--text-soft); }
  .chain-node .sys-state { display:inline-flex; align-items:center; gap:6px; font-size: var(--fs-caption); color:var(--br); }
  .chain-node .sys-state::before { content:""; width:7px; height:7px; border-radius:50%; background:currentColor; }
  .chain-node .sys-state.idle { color:var(--text-mute); }
  .chain-node .sys-state.err { color:var(--warn-text); }
  .chain-note { margin:0; font-size: var(--fs-micro); color:var(--text-mute); }
  .dash { display:grid; grid-template-columns:minmax(0,1fr) minmax(300px,27%); grid-template-areas:"main side"; gap:18px; align-items:stretch; }
  .dashboard-primary { min-width:0; display:flex; flex-direction:column; gap:14px; grid-area:main; }
  .dash-right { display:flex; flex-direction:column; gap:16px; min-width:0; }
  .dash-side { display:block; min-width:0; }
  .dash-main { display:flex; flex-direction:column; flex:1; gap:13px; padding:18px; min-width:0; border:1px solid var(--desk-line); border-radius:15px; background:var(--desk-surface); }
  /* 两列共享行高；新增空间交给曲线，标题、统计和页脚保持自然高度。 */
  .trend-charts { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:14px; flex:1; min-width:0; }
  .trend-charts > .chart-card { display:flex; flex-direction:column; }
  .trend-charts .chart-head, .trend-charts .chart-summary { flex:none; }
  .chart-plot { position:relative; flex:1; min-height:198px; margin-bottom:8px; }
  .trend-charts .chart-plot canvas.chart, .trend-charts .chart-plot canvas#chartBr { position:absolute; inset:0; width:100%; height:100%; margin:0; }
  .trend-toolbar { padding:0; display:flex; align-items:center; gap:10px; }
  .trend-toolbar h2 { margin:0 0 4px; font-size: var(--fs-section); color:var(--desk-ink); }
  .trend-toolbar > div:first-child span { font-size: var(--fs-caption); }
  .range-bar { border-radius:9px; box-shadow:none; gap:2px; padding:3px; border:1px solid var(--desk-line); background:var(--desk-soft); align-self:center; }
  .range-btn { padding:6px 11px; font-size: var(--fs-body); border-radius:6px; white-space:nowrap; }
  .range-btn.active { background:var(--desk-blue); color:#fff; box-shadow:0 2px 4px #163d5e14; }
  .chart-card { min-width:0; padding:15px 14px 13px; border:1px solid var(--desk-line); border-radius:12px; box-shadow:none; background:var(--desk-surface); }
  .chart-head { display:flex; justify-content:flex-start; align-items:flex-start; gap:13px; margin-bottom:12px; }
  .chart-head h3 { margin:2px 0 5px; font-size: var(--fs-card); font-weight:600; color:var(--text); }
  .chart-head .metric-icon { width:45px; height:45px; margin-top:2px; }
  .chart-value { display:flex; align-items:baseline; gap:6px; font-size: var(--fs-num-lg); line-height:1.2; color:var(--text); white-space:nowrap; }
  .chart-value .unit { font-size: var(--fs-caption); margin-left:0; font-weight:400; letter-spacing:0; color:var(--text-mute); }
  .metric-freshness { margin:4px 0 0; color:var(--text-mute); font-size: var(--fs-caption); line-height:1.4; }
  canvas.chart, canvas#chartBr { width:100%; height:178px; margin-bottom:8px; }
  .chart-summary { border-top:1px solid var(--desk-line); gap:0; padding-top:12px; }
  .chart-summary > div { padding:0 12px; border-radius:0; background:none; border-right:1px solid var(--desk-line); text-align:center; }
  .chart-summary > div:last-child { border:0; }
  .chart-summary span { font-size: var(--fs-caption); margin-bottom:6px; }
  .chart-summary b { font-size: var(--fs-num-sm); color:var(--text); }
  .chart-summary > div:nth-child(2) b, .chart-card-br .chart-summary > div:nth-child(2) b { color:var(--text); }
  .trend-note { font-size: var(--fs-caption); }
  .side-card, .events { margin:0; padding:20px; background:var(--desk-surface); border:1px solid var(--desk-line); border-radius:15px; box-shadow:0 4px 15px #20465b03; }
  .side-card:hover { transform:none; box-shadow:none; }
  .side-title, .events-head { margin:0; font-size: var(--fs-section); font-weight:600; color:var(--desk-ink); }
  .panel-hint { color:var(--text-mute); font-size: var(--fs-caption); }
  .dev-list { gap:9px; max-height:280px; overflow-y:auto; }
  .dev-item { padding:9px; background:var(--desk-surface); border:1px solid var(--desk-line); border-radius:12px; min-width:0; }
  .dev-item.active { background:color-mix(in srgb,var(--br) 3%,var(--desk-surface)); border-color:color-mix(in srgb,var(--br) 20%,var(--desk-line)); box-shadow:none; }
  .dev-main { padding:5px 0; gap:10px; flex-wrap:wrap; align-items:center; }
  .dev-device-icon { width:31px; height:40px; flex:none; display:grid; place-items:center; border-radius:10px; background:var(--desk-soft); color:var(--text-soft); }
  .dev-device-icon .ui-icon { width:23px; }
  .dev-name-txt { flex:1; }
  .dev-name-txt b { font-size: var(--fs-card); }
  .dev-name-txt small { max-width:165px; overflow:hidden; text-overflow:ellipsis; }
  .dev-state { font-size: var(--fs-caption); margin-left:auto; }
  .dev-more { min-width:43px; height:43px; padding:0 5px; color:var(--desk-link); border:0; font-size: var(--fs-body); }
  .device-access { font-size: var(--fs-caption); display:block; margin:10px auto -3px; padding:5px; }
  .events { flex:1; min-height:0; min-width:0; overflow:hidden; }
  .events-head { display:flex; flex-wrap:wrap; gap:12px; align-items:center; justify-content:space-between; margin-bottom:10px; }
  .desktop-alert-tabs { display:flex; padding:3px; border:1px solid var(--desk-line); background:var(--desk-soft); border-radius:10px; }
  .desktop-alert-tabs button { display:flex; align-items:center; gap:5px; min-height:28px; padding:4px 7px; border:0; border-radius:7px; color:var(--text-sec); background:transparent; font-family:inherit; font-size: var(--fs-body); cursor:pointer; }
  .desktop-alert-tabs button[aria-pressed="true"] { color:#fff; background:var(--desk-blue); }
  .desktop-alert-tabs b { font-size: var(--fs-caption); font-weight:500; padding:1px 4px; border-radius:5px; background:color-mix(in srgb,currentColor 12%,transparent); }
  .events-advanced summary { cursor:pointer; width:fit-content; font-size: var(--fs-card); color:var(--text-mute); padding:4px 0; }
  .events-filter { gap:6px; margin:10px 0; }
  .abn-filter { min-width:0; flex:1; padding:7px; font-size: var(--fs-body); }
  .events-list { min-height:0; max-height:365px; }
  .events-foot { border-top:1px solid var(--desk-line); margin-top:auto; padding-top:10px; font-size: var(--fs-caption); color:var(--text-mute); }
  .ev, .ev.ev-manage { display:flex; flex-wrap:wrap; gap:7px; padding:14px 0; border:0; border-bottom:1px solid var(--desk-line); border-radius:0; background:none; }
  .ev-time { width:100%; color:var(--text-mute); font-size: var(--fs-caption); }
  .ev-tag { font-size: var(--fs-micro); font-weight:600; background:none; padding:0; }
  .ev-msg { width:100%; flex-basis:100%; font-size: var(--fs-body); line-height:1.8; white-space:normal; color:var(--text-soft); }
  .ev-status { margin-left:auto; font-size: var(--fs-micro); }
  .ev-actions { width:100%; margin:2px 0 0; gap:6px; }
  .ev-btn { min-height:29px; border-radius:7px; padding:4px 11px; }
  .ev.ev-empty { padding:23px 0 16px; display:flex; flex-direction:column; text-align:center; line-height:1.8; border:0; }
  .ev-empty-icon { display:grid; place-items:center; width:47px; height:47px; border:1.5px solid var(--text-mute); border-radius:50%; margin-bottom:6px; color:var(--text-mute); }
  .ev-empty-icon .ui-icon { width:25px; height:25px; }
  .ev-empty strong { font-size: var(--fs-card); font-weight:500; color:var(--text); }
  .ev-empty small { font-size: var(--fs-caption); color:var(--text-mute); }
  .foot-note { margin:0; padding:2px; font-size: var(--fs-caption); }
  .pause-notice { margin:0; transform:none; }
  #linkStatusMask { padding:0; align-items:stretch; justify-content:flex-end; }
  #linkStatusMask .connection-card { width:430px; max-height:100dvh; border-radius:20px 0 0 20px; padding:28px; animation:bindIn .22s var(--ease-enter); }
}
@media (min-width:769px) and (max-width:1150px) {
  body { padding:0 22px 20px; }
  .app { gap:15px; }
  .account-copy { display:none; }
  .topbar { gap:8px; }
  .overview-controls { gap:12px; }
  .overview-controls select { min-width:160px; max-width:210px; }
  .chain-nodes { gap:20px; }
  .chain-node { gap:8px; }
  .chain-node:not(:last-child)::after { width:12px; right:-16px; }
  .chain-icon { width:40px; height:48px; border-radius:14px; }
  .chain-icon .ui-icon { width:25px; height:25px; }
  .chain-node h3 { font-size:13px; }
  .dash { grid-template-columns:minmax(0,1fr) 285px; gap:15px; }
  .dash-main { padding:15px; }
  .trend-charts { grid-template-columns:1fr; }
  .trend-toolbar { flex-wrap:wrap; gap:10px; }
  .trend-toolbar .range-bar { margin-left:0; }
  .overview-description { flex-basis:100%; margin:0 0 0 25px; }
}
@media (max-width:768px) {
  body { padding:0; display:block; background:var(--desk-page); }
  body::before { display:none; }
  .topbar .head-actions, .sidebar-logout, .dash { display:none !important; }
  .app { display:flex; width:100%; max-width:600px; margin:0 auto; min-height:100dvh; padding:env(safe-area-inset-top) 0 0; gap:0; background:var(--desk-page); border:0; box-shadow:none; backdrop-filter:none; }
  .topbar { display:flex; flex-direction:row; justify-content:space-between; gap:12px; padding:18px 21px 0; }
  .topbar .top-row { width:auto; }
  .topbar .brand { font-size:19px; gap:9px; color:var(--text); }
  .brand .brand-mark { width:30px; height:33px; border-radius:10px; }
  .brand .brand-mark svg { width:22px; height:22px; }
  .brand small, .topbar-right { display:none; }
  .topbar .theme-btn { width:35px; height:35px; background:var(--desk-surface); box-shadow:none; border:1px solid var(--desk-line); }
  .topbar .sub-row { display:none; }
  .topbar { padding-bottom:2px; }
  .m-home, .m-me, .m-device { padding:20px 18px calc(96px + env(safe-area-inset-bottom)) !important; }
  .m-hero { padding:0 2px 12px; position:relative; }
  .m-hero::after { display:none; }
  .mobile-kicker { font-size:10px; letter-spacing:.13em; margin-bottom:7px; }
  .m-hero-title { font-size:29px; letter-spacing:-.02em; }
  .m-hero-online { font-size:11px; margin-top:8px; }
  .m-refresh-btn { display:inline-flex; align-items:center; justify-content:center; gap:6px; width:auto; min-height:44px; padding:0 13px; background:var(--desk-surface); border:1px solid var(--desk-line); border-radius:999px; font-family:inherit; font-size:12px; font-weight:500; color:var(--desk-blue); box-shadow:0 2px 6px #234c5f04; }
  .current-device { margin:0 0 14px; padding:11px 12px; border-radius:12px; background:var(--desk-surface); }
  .current-device select { font-family:inherit; font-size:11px; padding:4px 0; }
  .m-status-banner { display:flex; align-items:center; gap:14px; margin:0 0 15px; min-height:91px; padding:17px; border-radius:18px; border:1px solid var(--desk-line); background:var(--desk-surface); box-shadow:0 5px 17px #234c5f06; }
  .m-status-banner .mobile-shield { width:45px; height:45px; flex:none; display:grid; place-items:center; border-radius:50%; background:color-mix(in srgb,currentColor 9%,transparent); }
  .m-status-banner .mobile-shield .ui-icon { width:27px; height:27px; }
  .m-status-banner strong { display:block; font-size:17px; margin-bottom:5px; }
  #mStatusBannerText { display:block; font-size:11px; line-height:1.65; font-weight:400; }
  .m-status-banner.s-ok { background:linear-gradient(120deg,color-mix(in srgb,var(--br) 13%,var(--desk-surface)),color-mix(in srgb,var(--br) 4%,var(--desk-surface))); border-color:color-mix(in srgb,var(--br) 13%,transparent); }
  .m-status-banner.s-alarm { background:var(--err-bg); border-color:color-mix(in srgb,var(--err) 22%,transparent); }
  .mobile-vitals { display:grid; grid-template-columns:1fr 1fr; gap:12px; }
  .mobile-vitals .m-card { margin:0; padding:15px 13px 10px; min-width:0; border-radius:17px; min-height:177px; overflow:hidden; }
  .m-card { background:var(--desk-surface); border-color:var(--desk-line); box-shadow:0 5px 20px #234c5f05; }
  .m-card-head { gap:8px; }
  .m-card-ico { width:31px; height:31px; border-radius:50%; }
  .m-card-name { font-size:13px; color:var(--text); font-weight:600; }
  .m-card-big { margin-top:17px; gap:5px; }
  .m-card-big .m-big-num { font-size:35px; font-weight:600; }
  .m-big-unit { font-size:10px; color:var(--text-mute); }
  .m-card-time { font-size:10px; margin-top:5px; min-height:14px; }
  .m-mini-chart { height:38px; margin-top:10px; width:100%; }
  .m-card-sub { padding:17px 15px; border-radius:17px; margin-top:14px; }
  .m-summary-title, .m-card-sub .m-summary-title { font-size:14px; font-weight:600; }
  .section-note { font-size:9px; }
  .m-summary-row { gap:7px; margin-top:14px; }
  .m-summary-item { min-width:0; padding:0; }
  .m-summary-label { font-size:10px; }
  .m-summary-val { font-size:22px; }
  .m-unit { font-size:9px; }
  .m-alarm-sub { font-size:9px; }
  .alert-tabs { margin-top:12px; }
  .alert-tabs button { min-height:44px; font-family:inherit; }
  .m-abn-empty { font-size:11px; padding:22px 0 10px; }
  .m-abn-row { border-bottom:1px solid var(--desk-line); padding:13px 0; }
  .m-abn-btn { min-height:44px; }
  .m-tabbar { max-width:600px; margin:auto; border-radius:20px 20px 0 0; background:color-mix(in srgb,var(--desk-surface) 94%,transparent); box-shadow:0 -5px 24px #143d5210; }
  .m-tabbar-item.active { color:var(--desk-blue); }
  .m-tabbar-item.active .m-tabbar-ico { border-radius:11px; background:var(--br-soft); padding:3px 13px; margin:-3px 0; }
  .m-tabbar-label { font-size:11px; margin-top:7px; }
  .m-detail { padding:24px 14px 40px; }
  .m-detail-chart { margin-top:25px; }
  .m-detail-legend { font-size:11px; }
  .m-me .m-card, .m-device .m-card { border-radius:17px; }
  .login-story { display:none; }
  .login-card { margin-left:0; width:100%; max-width:410px; padding:29px 25px; }
  .welcome-card { margin:0 0 14px; }
  .care-tip { font-size:10px; }
}
@media (prefers-reduced-motion:reduce) { *,*::before,*::after { scroll-behavior:auto !important; animation-duration:.01ms !important; transition-duration:.01ms !important; } }

/* ===== v12.1：手机详情、设备绑定与辅助页的统一体验 ===== */
@media (max-width:768px) {
  /* 体征详情：把大数字、数据新鲜度和曲线放进连续的阅读路径。 */
  .m-detail:not([hidden]) { padding: 0 18px calc(28px + env(safe-area-inset-bottom)); }
  .m-detail-head { gap: 8px; padding: 16px 0 17px; }
  .m-back { width: 42px; min-width: 42px; height: 42px; min-height: 42px; padding: 0; border-radius: 13px; background: var(--desk-surface); border: 1px solid var(--desk-line); font-size: 30px; line-height: .8; color: var(--text); }
  .m-back:active { transform: scale(.96); background: var(--btn-hover); }
  .m-detail-heading { display:flex; align-items:center; gap:11px; min-width:0; }
  .m-detail-icon { width:42px; height:42px; flex:0 0 auto; display:grid; place-items:center; border-radius:14px; background:color-mix(in srgb,var(--hr) 12%,var(--desk-surface)); color:var(--hr); }
  .m-detail-icon.br { background:color-mix(in srgb,var(--br) 13%,var(--desk-surface)); color:var(--br); }
  .m-detail-icon svg { width:23px; height:23px; fill:none; stroke:currentColor; stroke-width:2; stroke-linecap:round; stroke-linejoin:round; }
  .m-detail-icon .detail-icon-br { display:none; }
  .m-detail-icon.br .detail-icon-hr { display:none; }
  .m-detail-icon.br .detail-icon-br { display:block; }
  .m-detail-kicker { display:block; color:var(--text-mute); font-size:10px; letter-spacing:.08em; line-height:1; margin-bottom:5px; }
  .m-detail-title { display:block; font-size:21px; line-height:1.1; letter-spacing:-.02em; }
  .m-detail-device { display:block; max-width:190px; margin-top:5px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; color:var(--text-dim); font-size:11px; }
  .m-detail-hero { margin:0 0 14px; padding:20px 18px 16px; border:1px solid var(--desk-line); border-radius:20px; background:linear-gradient(135deg,var(--desk-surface),color-mix(in srgb,var(--br) 7%,var(--desk-surface))); box-shadow:0 8px 22px #234c5f08; }
  .m-detail[data-metric="hr"] .m-detail-hero { background:linear-gradient(135deg,var(--desk-surface),color-mix(in srgb,var(--hr) 7%,var(--desk-surface))); }
  .m-detail-value { display:flex; align-items:baseline; gap:7px; }
  .m-detail-value .m-big-num { font-size:54px; line-height:.95; font-weight:700; letter-spacing:-.06em; color:var(--text); }
  .m-detail-value .m-big-unit { font-size:13px; color:var(--text-sec); }
  .m-detail-state { display:flex; align-items:center; gap:6px; margin-top:13px; color:var(--text-sec); font-size:12px; }
  .m-detail-state-dot { width:7px; height:7px; flex:0 0 auto; border-radius:50%; background:var(--text-mute); }
  .m-detail-state-dot.ok { background:var(--ok); box-shadow:0 0 0 4px var(--ok-bg); }
  .m-detail-state-dot.stale { background:var(--warn); box-shadow:0 0 0 4px var(--warn-bg); }
  .m-detail-state-dot.wait { background:var(--text-mute); }
  .m-detail-time { margin-left:auto; color:var(--text-mute); font-size:11px; }
  .m-tabs { margin:0 0 14px; padding:4px; border:1px solid var(--desk-line); border-radius:14px; background:var(--desk-surface); }
  .m-tab { min-height:42px; font-size:13px; border-radius:10px; }
  .m-tab.active { background:var(--br-soft); color:var(--br-text, var(--br)); box-shadow:none; }
  .m-detail-chart-card { padding:15px 13px 13px; border:1px solid var(--desk-line); border-radius:20px; background:var(--desk-surface); box-shadow:0 7px 20px #234c5f06; }
  .m-detail-chart-head { display:flex; align-items:center; justify-content:space-between; gap:8px; padding:0 3px; }
  .m-detail-chart-head strong { color:var(--text); font-size:14px; }
  .m-detail-chart-head span { color:var(--text-mute); font-size:10px; }
  .m-detail-chart { width:100%; height:272px; margin:13px 0 0; display:block; }
  .m-detail-legend { justify-content:flex-start; margin:10px 3px 0; font-size:10px; }
  .m-detail-note { display:flex; align-items:center; justify-content:center; gap:5px; margin:13px 0 0; font-size:10px; line-height:1.5; }
  .m-detail-note > span:first-child { color:var(--br); font-size:16px; }

  /* 绑定设备：底部抽屉有明确的拖拽感、步骤层级和触控尺寸。 */
  .bind-mask { align-items:flex-end; padding:0; }
  .bind-drawer { width:100%; max-width:100%; max-height:min(94dvh, 860px); border:0; border-top:1px solid var(--desk-line); border-radius:26px 26px 0 0; box-shadow:0 -14px 42px rgba(16,48,67,.18); animation-name:bindUp; }
  .bind-head { position:relative; padding:21px 20px 12px; }
  .bind-head::before { content:""; position:absolute; top:8px; left:50%; width:42px; height:4px; border-radius:99px; background:var(--text-mute); opacity:.45; transform:translateX(-50%); }
  .bind-title { font-size:20px; letter-spacing:-.03em; }
  .bind-close { width:38px; height:38px; background:var(--bar-bg); }
  .bind-steps { gap:5px; padding:0 20px 16px; }
  .bind-step-dot { flex:1; min-width:0; padding:8px 3px; text-align:center; font-size:11px; border:1px solid transparent; }
  .bind-step-dot.on { border-color:color-mix(in srgb,var(--ok) 22%,transparent); }
  .bind-step-line { min-width:7px; }
  .bind-body { padding:2px 18px calc(24px + env(safe-area-inset-bottom)); gap:12px; }
  .bind-pane { gap:12px; }
  .bind-guide { display:grid; grid-template-columns:39px minmax(0,1fr); align-items:start; gap:12px; padding:17px 15px; border-radius:18px; font-size:13px; line-height:1.75; }
  .bind-guide svg { width:34px; height:34px; margin-top:3px; }
  .bt-check { padding:15px; border-radius:18px; gap:10px; }
  .bt-check-title { font-size:14px; }
  .bt-row { font-size:12px; }
  .bt-row b { font-size:12px; }
  .bt-test-btn { height:48px; border-radius:13px; font-size:13px; }
  .bt-result { font-size:11px; line-height:1.65; }
  .bind-primary { min-height:50px; height:50px; border-radius:14px; font-size:15px; }
  .bind-note { font-size:11.5px; line-height:1.65; }
  .bind-list { max-height:30vh; }
  .bind-item { min-height:56px; border-radius:14px; padding:12px 13px; }
  .bind-field { min-height:53px; padding:0 14px; border-radius:14px; font-size:13px; }
  .bind-field > span { font-size:12px; }
  .bind-field > b, .bind-input { font-size:14px; }
  .bind-input { text-align:right; }
  .bind-link { min-height:40px; padding:8px 10px; font-size:12px; }
  .bind-done-ico { margin-top:12px; }
  .bind-done-title { font-size:20px; margin-bottom:5px; }
  .ble-mon { margin:0; border-radius:0; }

  /* 设备页与我的页：增加卡片标题、状态强调和可点区域反馈。 */
  .m-device .m-hero, .m-me .m-hero { padding-bottom:16px; }
  .m-device-list { margin-top:0; }
  .m-device-item { min-height:74px; margin-bottom:10px; padding:14px 15px; border-radius:18px; background:var(--desk-surface); border-color:var(--desk-line); box-shadow:0 5px 17px #234c5f06; }
  .m-device-item:active { transform:scale(.99); }
  .m-device-name { font-size:15px; }
  .m-device-sn { margin-top:4px; font-family:var(--font-mono); font-size:10px; letter-spacing:.02em; }
  .m-device-lastseen { margin-top:5px; font-size:10px; color:var(--text-mute); }
  .m-device-right { gap:9px; }
  .m-device-status { padding:5px 9px; font-size:10px; }
  .m-device-more { width:38px; height:38px; border-radius:12px; }
  .m-device .m-card { margin-top:14px; padding:17px 15px; }
  .m-sys-item { padding:13px 0; }
  .m-sys-name { font-size:12px; }
  .m-sys-state { font-size:10px; padding:4px 8px; }
  .m-sys-note { font-size:10px; line-height:1.55; }
  .m-me-acct { padding:17px 15px; border-radius:18px; }
  .m-me-email { font-size:15px; }
  .m-me-sub, .m-me-hint { font-size:11px; }
  .m-me .m-card { padding:17px 15px; }
  .m-me-btn { min-height:48px; border-radius:13px; }
  .m-me-row { font-size:12px; }
  .m-me-row b { font-size:12px; }
  .m-me-logout { min-height:48px; border-radius:13px; font-size:14px; }

  /* 使用指南和设备管理在手机上改为底部卡片，避免桌面窄弹窗挤压内容。 */
  .dlg-mask { align-items:flex-end; padding:0; }
  .dlg-card, .guide-card { width:100%; max-width:100%; max-height:92dvh; overflow-y:auto; border-radius:25px 25px 0 0; padding:21px 19px calc(22px + env(safe-area-inset-bottom)); }
  .guide-card .guide-head { position:sticky; top:-21px; z-index:1; padding-top:21px; background:var(--drawer-bg); }
  .guide-card h2 { font-size:21px; }
  .guide-steps li { gap:11px; padding:15px 0; }
  .guide-steps p { font-size:12px; line-height:1.7; }
  .dlg-card .bind-field { width:100%; }
  .dlg-card .bind-primary { width:100%; }
}

/* 所有弹窗复用稳定的按钮尺寸，避免 column flex 将主操作压扁。 */
body:has(.bind-mask:not([hidden])), body:has(.dlg-mask:not([hidden])) { overflow:hidden; }
.bind-primary { flex:0 0 auto; width:100%; min-height:48px; height:auto; padding:13px 18px; border:0; border-radius:13px; background:var(--desk-blue); color:#fff; font-weight:600; }
.bind-primary:hover { background:var(--desk-blue-deep); }
.bind-primary:disabled, .bind-link:disabled { cursor:not-allowed; opacity:.45; }
.bind-drawer { width:470px; max-width:100%; background:var(--desk-surface); min-height:0; overflow:hidden; }
.bind-head { flex:none; padding:24px 24px 18px; }
.bind-title { margin:5px 0 0; font-size: var(--fs-section); }
.bind-eyebrow { color:var(--br); font-size: var(--fs-micro); font-weight:600; font-family:var(--font-mono); letter-spacing:.14em; text-transform:uppercase; }
.bind-close { flex:none; min-width:44px; min-height:44px; }
.bind-steps { flex:none; padding:0 24px 20px; gap:6px; }
.bind-step-dot { display:flex; align-items:center; justify-content:center; gap:6px; padding:7px 8px; border-radius:10px; font-size: var(--fs-caption); }
.bind-step-dot b { font:inherit; font-weight:600; }
.bind-step-dot.done { color:var(--ok-text); background:var(--ok-bg); }
.bind-body { flex:1 1 auto; min-height:0; padding:0 24px 20px; overscroll-behavior:contain; scrollbar-width:thin; scrollbar-color:var(--desk-line) transparent; }
.bind-pane { gap:16px; }
.bind-guide { padding:20px; background:linear-gradient(125deg,var(--br-soft),var(--desk-soft)); border-color:var(--desk-line); }
.bind-guide h3, .bind-section-heading h3 { margin:0 0 7px; font-size: var(--fs-card); color:var(--text); }
.bind-guide p, .bind-section-heading p { margin:0; font-size: var(--fs-body); line-height:1.7; color:var(--text-sec); }
.bind-checklist { margin:0; padding:0; list-style:none; }
.bind-checklist li { display:flex; gap:13px; padding:14px 0; border-bottom:1px solid var(--desk-line); }
.bind-checklist li > span { display:grid; place-items:center; flex:none; width:32px; height:32px; border-radius:11px; color:var(--br); background:var(--br-soft); font-weight:500; font-size: var(--fs-caption); font-family: var(--font-mono); }
.bind-checklist b { font-size: var(--fs-card); font-weight:600; }
.bind-checklist p { margin:5px 0 0; color:var(--text-sec); font-size: var(--fs-caption); line-height:1.65; }
.bind-actions { position:static; background:var(--desk-surface); padding:12px 0 4px; display:flex; flex-direction:column; gap:8px; margin-top:2px; }
.bind-actions p { text-align:center; font-size: var(--fs-caption); color:var(--text-mute); margin:0; }

/* ===== 敏感个人信息单独同意（绑定前置） ===== */
.consent-body { margin:14px 0 4px; padding:14px 16px; background:var(--desk-soft); border:1px solid var(--desk-line); border-radius:14px; }
.consent-body p { margin:0 0 10px; font-size: var(--fs-body); line-height:1.75; color:var(--text-sec); }
.consent-body p:last-child { margin-bottom:0; }
/* 原先写 var(--text-pri, inherit)，而 --text-pri 全仓从未定义 => 实际回退 inherit，
   小标题与正文同色、只靠字重区分，没有视觉层级。改用已定义的 --text，
   并把标题做成块级（不动 DOM，四段仍是 p+b）。 */
.consent-body b { display: block; margin-bottom: 3px; color: var(--text); font-weight: 600; }
.consent-check { display:flex; align-items:flex-start; gap:10px; margin:14px 0 4px; padding:12px 14px; border:1px solid var(--desk-line); border-radius:14px; cursor:pointer; transition:border-color .15s var(--ease-hover), background .15s var(--ease-hover); }
.consent-check:hover { border-color:var(--br); background:var(--br-soft); }
.consent-check input { flex:none; width:20px; height:20px; margin:1px 0 0; accent-color:var(--br); cursor:pointer; }
.consent-check span { font-size: var(--fs-body); line-height:1.65; color:var(--text-sec); }
.bind-actions .bind-primary[disabled] { opacity:.5; cursor:not-allowed; }

/* 登录页协议勾选
   ⚠️ 容器与按钮的关系见 index.html 的注释：容器刻意用 div 而非 label，
      否则 label 会抢走按钮边缘的点击（表现为"条款点不动"）。
      这里把 cursor:pointer 只给到真正可点的三处：文字 label、复选框、条款按钮。 */
.login-consent { display:flex; align-items:flex-start; gap:9px; margin:12px 0 2px; }
.login-consent input { flex:none; width:16px; height:16px; margin:2px 0 0; accent-color:var(--br); cursor:pointer; }
.login-consent span { font-size: var(--fs-caption); line-height:1.7; color:var(--text-mute); text-align:left; }
.login-consent span > label { cursor:pointer; }
.login-consent-link { padding:0; border:none; background:none; color:var(--br); font-size:inherit; font-family:inherit; line-height:inherit; cursor:pointer; }
.login-consent-link:hover { text-decoration:underline; }
details.bt-check { display:block; background:var(--desk-soft); }
.bt-check summary, .ble-mon > summary { cursor:pointer; color:var(--text-sec); font-size: var(--fs-card); padding:3px 0; }
.bt-check summary span, .ble-mon > summary span { float:right; color:var(--text-mute); font-size: var(--fs-caption); }
.bt-check[open] > :not(summary) { margin-top:12px; }
.bt-test-btn { width:100%; }
.ble-mon { flex:none; display:block; max-height:190px; overflow:auto; overscroll-behavior:contain; }
.ble-mon > summary { padding:14px 24px; }
.ble-mon .ble-mon-list { max-height:110px; }
.bind-drawer label.bind-field, #devManageMask label.bind-field { display:grid; grid-template-columns:minmax(0,1fr); align-items:start; gap:7px; padding:13px 14px; }
.bind-drawer .bind-field > b { min-width:0; overflow-wrap:anywhere; margin-left:auto; }
.bind-drawer .bind-input, #devManageMask .bind-input { flex:none; min-width:0; width:100%; min-height:44px; height:44px; padding:9px 0; text-align:left; font-size: var(--fs-body); line-height:26px; border-radius:4px; }
.bind-field .password-entry { display:flex; align-items:center; gap:8px; width:100%; flex-shrink:1; }
.password-entry .bind-input { flex:1 1 0; width:0; }
.password-entry button { flex:none; min-height:36px; padding:4px 10px; border:0; border-radius:8px; color:var(--br); background:var(--br-soft); font-size: var(--fs-body); font-family: var(--font-sans); cursor:pointer; }
.scan-status { min-height:100px; padding:20px; border:1px solid var(--desk-line); border-radius:17px; background:var(--desk-soft); line-height:1.8; }
.scan-status { white-space:pre-line; overflow-wrap:anywhere; }
.scan-status[data-state="error"] { color:var(--warn-text); border-color:color-mix(in srgb,var(--warn-text) 25%,var(--desk-line)); background:color-mix(in srgb,var(--warn-text) 6%,var(--desk-surface)); }
#btnScanAgain[hidden], #btnScanAll[hidden] { display:none; }
.dlg-card { max-height:90dvh; overflow:auto; overscroll-behavior:contain; }
.dlg-card .dlg-warn, .dlg-card .dlg-danger { min-height:44px; flex:none; }
.m-detail-title { margin:0; }
@media (max-width:768px) {
  body.viewing-detail .topbar { display:none; }
  .m-detail:not([hidden]) { padding-top:8px; }
  .bind-drawer { width:100%; max-height:94dvh; }
  .bind-head { padding:22px 20px 16px; }
  .bind-title { font-size:21px; }
  .bind-steps { padding:0 20px 16px; }
  .bind-step-dot { padding:7px 5px; font-size:11px; }
  /* 原先这里是 padding:0 18px 16px，而更早那条写的 calc(24px + env(safe-area-inset-bottom))
     被本条盖掉 => 底部安全区其实一直失效（全面屏上最后一行贴着 home 指示条）。
     收口到本条，把 safe-area 加回来。 */
  .bind-body { padding:0 18px calc(16px + env(safe-area-inset-bottom)); }
  .bind-guide { padding:16px; }
  .bind-guide h3 { font-size:17px; }
  .bind-checklist li { padding:12px 0; }
  .ble-mon { padding-bottom:env(safe-area-inset-bottom); }
  .m-abn-row { flex-wrap:wrap; }
  .m-abn-main { min-width:min(210px,100%); }
  .m-abn-acts { margin-left:auto; }
  .m-abn-btn { min-height:44px; }
  .m-abn-line { flex-wrap:wrap; }
  .m-device-info { min-width:0; overflow-wrap:anywhere; }
  .m-device-more { width:auto; min-width:44px; min-height:44px; padding:0 9px; }
  .m-device-right { flex-wrap:wrap; justify-content:flex-end; max-width:44%; }
}

/* v12.2：键盘弹出时让表单滚动，不让 flex 压缩字段。 */
.dlg-card > *, .bind-pane, .bind-pane > *, .bind-field { flex-shrink:0; }
.dlg-card { scroll-padding-block:24px; }
.bind-body { scroll-padding-block:24px; }
.bind-field { min-width:0; }
.bind-field:focus-within { border-color:var(--br); box-shadow:0 0 0 3px var(--br-soft); }
.bind-field .bind-input:focus-visible { outline:none; }
.field-help { margin:-3px 2px 1px; color:var(--text-mute); font-size: var(--fs-caption); line-height:1.6; }
#devManageMask .dlg-card { width:440px; gap:16px; padding:24px; }
#devManageMask .dlg-title { font-size: var(--fs-section); }
#devManageMask .bind-field > b { min-width:0; margin-left:auto; overflow-wrap:anywhere; }
#devManageMask .bind-close { font-size:24px; }
.refresh-action .refresh-icon { flex:none; transform-origin:center; }
.refresh-action.is-loading .refresh-icon { animation:spin .8s linear infinite; }
.refresh-action.is-loading { cursor:wait; }
.device-panel-head { display:flex; align-items:center; justify-content:space-between; gap:8px; margin-bottom:14px; }
.device-panel-head .side-title { margin:0; }
.device-panel-head .text-action { min-height:44px; font-size: var(--fs-body); white-space:nowrap; }
.connection-card { width:460px; padding:26px; gap:16px; }
.connection-intro { margin:0; color:var(--text-sec); font-size: var(--fs-body); }
.connection-card .sys-list { border:1px solid var(--desk-line); border-radius:15px; padding:4px 16px; background:var(--desk-soft); }
.connection-card .sys-item { padding:17px 0; border-bottom:1px solid var(--desk-line); font-size: var(--fs-body); }
.connection-card .sys-item:last-child { border:0; }
.connection-card .side-note { margin:0; line-height:1.8; font-size: var(--fs-caption); }
@media (max-width:768px) {
  .dlg-mask, .bind-mask { top:var(--dialog-viewport-top,0px); bottom:auto; height:var(--dialog-viewport-height,100dvh); }
  .dlg-card, .guide-card, .bind-drawer { max-height:calc(var(--dialog-viewport-height,100dvh) - 12px); }
  #devManageMask .dlg-card, .connection-card { width:100%; padding:22px 20px calc(22px + env(safe-area-inset-bottom)); }
  .dlg-card { border-bottom:0; }
  .connection-card .sys-item { font-size:12px; }
}

/* 诊断抽屉只提供说明和现有操作，首页链路始终可见。 */
.diagnostic-current { padding:17px; border:1px solid var(--desk-line); background:var(--desk-soft); border-radius:13px; }
.diagnostic-current > span { display:block; font-size: var(--fs-caption); color:var(--text-mute); margin-bottom:7px; }
.diagnostic-current strong { font-size: var(--fs-card); overflow-wrap:anywhere; }
.diagnostic-current p { font-size: var(--fs-body); line-height:1.7; color:var(--text-soft); margin:7px 0 0; }
.diagnostic-steps { margin:0; padding-left:21px; color:var(--text-sec); }
.diagnostic-steps li { padding:12px 0; }
.diagnostic-steps b { color:var(--text); font-size: var(--fs-card); }
.diagnostic-steps p, .diagnostic-access p { margin:5px 0 0; font-size: var(--fs-body); line-height:1.75; color:var(--text-mute); }
.diagnostic-access { padding:17px; border:1px solid var(--desk-line); border-radius:13px; }
.diagnostic-access h3 { margin:0; font-size: var(--fs-card); }
.diagnostic-access .sn-query { margin-top:12px; }
.connection-card .primary-action { min-height:44px; }
.sn-access-card { width:460px; max-width:100%; padding:26px; gap:18px; }
.sn-access-intro,.sn-access-foot { margin:0; font-size: var(--fs-body); line-height:1.8; color:var(--text-sec); }
.sn-access-card .sn-query { display:flex; flex-direction:column; align-items:stretch; gap:12px; margin:0; }
.sn-access-card .bind-field { display:grid; grid-template-columns:minmax(0,1fr); align-items:start; gap:7px; padding:13px 14px; margin:0; }
.sn-access-card .sn-input { width:100%; min-width:0; min-height:44px; height:44px; padding:9px 0; text-align:left; font-size: var(--fs-body); line-height:26px; }
.sn-access-card .field-help { margin:0; }
.sn-access-card .sn-btn-query { width:100%; min-height:46px; background:var(--desk-blue); color:#fff; border:0; border-radius:13px; font-family:inherit; font-size: var(--fs-body); font-weight:600; }
.sn-access-card .sn-error { margin:14px 0 0; font-size: var(--fs-caption); line-height:1.8; overflow-wrap:anywhere; }
.sn-access-card .sn-error[hidden] { display:none; }
.sn-access-foot .text-action { min-height:44px; font-size: var(--fs-body); }
.sn-access-entry { display:flex; align-items:center; gap:12px; width:100%; margin:14px 0; padding:16px; border:1px solid var(--desk-line); border-radius:19px; background:var(--desk-surface); color:var(--text); text-align:left; cursor:pointer; }
.sn-entry-icon { display:grid; place-items:center; flex:none; width:44px; height:44px; border-radius:14px; color:var(--desk-link); background:var(--br-soft); font:600 15px 'IBM Plex Mono',monospace; }
.sn-access-entry > span:nth-child(2) { flex:1; min-width:0; }
.sn-access-entry strong { display:block; font-size: var(--fs-card); }
.sn-access-entry small { display:block; margin-top:5px; font-size: var(--fs-caption); line-height:1.6; color:var(--text-mute); }
.sn-access-entry > .ui-icon { width:17px; flex:none; color:var(--text-soft); }
@media (max-width:768px) { .sn-access-card { width:100%; padding:22px 20px calc(22px + env(safe-area-inset-bottom)); } }

/* v12.4：活动与告警共用时间线，起夜保持非告警语义。 */
.event-feed-note { margin:10px 0 0; color:var(--text-mute); font-size: var(--fs-caption); line-height:1.6; }
.event-night, .ev.event-night { display:flex; align-items:center; gap:10px; flex-wrap:nowrap; padding:14px 0; border-bottom:1px solid var(--desk-line); }
.event-night-icon { width:32px; height:32px; flex:none; display:grid; place-items:center; color:#9580bd; background:color-mix(in srgb,#9580bd 12%,transparent); border-radius:10px; }
.event-night-icon .ui-icon { width:19px; height:19px; }
.event-night-copy { flex:1; min-width:0; }
.event-night-copy > div { display:flex; align-items:center; justify-content:space-between; gap:8px; flex-wrap:wrap; }
.event-night-copy strong { font-size: var(--fs-card); font-weight:600; color:var(--text); }
.event-night-copy time { color:var(--text-mute); font-size: var(--fs-caption); }
.event-night-copy p { color:var(--text-sec); font-size: var(--fs-body); margin:5px 0 0; }
.event-night-label { color:var(--text-mute); font-size: var(--fs-micro); white-space:nowrap; }
.ev-feed-more { color:var(--text-mute); font-size: var(--fs-micro); text-align:center; padding:10px 0; }
@media (min-width:769px) { .desktop-alert-tabs { flex-basis:100%; width:100%; } .desktop-alert-tabs button { flex:1; justify-content:center; } }
@media (max-width:768px) { .event-night-label { display:none; } }

/* v12.5：统一品牌、页面及辅助流程；尺寸规则保留键盘视口适配。 */
:root[data-theme="light"] {
  --page-bg:#f5f7f4; --app-bg:#f5f7f4; --desk-page:#f5f7f4;
  --text:#16474d; --desk-ink:#123f46; --text-sec:#557076; --text-soft:#637c80;
  --text-mute:#708487; --text-dim:#708487; --desk-muted:#708487;
  --desk-blue:#155b65; --desk-blue-deep:#104a52; --desk-link:#156674;
  --desk-line:#e3ece9; --card-border:#e3ece9; --desk-soft:#f2f7f5;
  --desk-surface:#fff; --card-bg:#fff; --drawer-bg:#fff; --bar-bg:#f2f7f5; --bar-border:#e3ece9;
  --br:#1aa78f; --br-soft:#e2f4ee; --hr:#ee796b; --ok:#28ac79; --ok-text:#15825c;
  --card-shadow:0 5px 24px #1b4d4205; --tabbar-bg:#fff;
}
:root[data-theme="dark"] {
  --page-bg:#0e1d20; --app-bg:#0e1d20; --desk-page:#0e1d20;
  --desk-surface:#162b2e; --card-bg:#162b2e; --drawer-bg:#162b2e; --desk-soft:#1d3538;
  --text:#e5eeeb; --desk-ink:#e5eeeb; --text-sec:#b1c5c4; --text-soft:#a4bbba;
  --text-mute:#91aaa8; --text-dim:#91aaa8; --desk-line:#2a4143; --card-border:#2a4143;
  --bar-bg:#1d3538; --bar-border:#2a4143; --desk-blue:#287b7c; --desk-blue-deep:#22696a;
  --desk-link:#9ad9d0; --br:#69cbb6; --tabbar-bg:#162b2e; --card-shadow:0 5px 24px #00000010;
}
button,input,select { font-family:inherit; }
button { -webkit-tap-highlight-color:transparent; }
button:focus-visible, select:focus-visible, a:focus-visible, [role="button"]:focus-visible { outline:2px solid var(--br); outline-offset:3px; }
.brand .brand-mark,.login-brand-icon { width:46px; height:46px; border-radius:0; background:none; transform:none; padding:0; box-shadow:none; }
.brand .brand-mark .brand-svg,.login-brand-icon .brand-svg { width:100%; height:100%; padding:0; background:none; transform:none; stroke:none; }
.brand { gap:11px; }
.brand small { letter-spacing:.02em; }
.primary-action,.login-submit { background:var(--desk-blue); border-radius:12px; box-shadow:0 4px 12px #155b6512; }
.primary-action:hover,.login-submit:hover { background:var(--desk-blue-deep); }
.device-picker { display:flex; align-items:center; min-width:0; height:46px; gap:9px; padding-left:12px; background:var(--desk-surface); border:1px solid var(--desk-line); border-radius:12px; }
.device-picker .ui-icon { width:22px; color:var(--desk-link); }
.overview-art { position:absolute; right:0; top:0; height:100%; width:29%; object-fit:cover; object-position:right 62%; pointer-events:none; border-radius:0 22px 22px 0; mask-image:linear-gradient(to right,transparent,#000 22%); }
.overview-status { position:relative; }
.chain-icon { background:linear-gradient(145deg,var(--desk-soft),var(--br-soft)); }
.mobile-status-art,.mobile-chain-link,.metric-detail-link,.detail-statistics,.mobile-page-intro { display:none; }
.login-page { background:var(--desk-page); gap:50px; }
.login-story { max-width:590px; }
.login-story h2 { color:var(--text); font-size:46px; line-height:1.4; }
.login-story h2 em { color:var(--desk-link); }
.login-story > p { color:var(--text-sec); }
.care-illustration { position:relative; height:270px; margin-top:24px; overflow:hidden; border-radius:24px; }
.care-illustration img { width:100%; height:100%; object-fit:cover; }
.care-illustration > span { position:absolute; left:22px; top:25px; max-width:120px; font-size:17px; line-height:1.9; color:#426660; letter-spacing:.1em; }
.login-card { border:1px solid var(--desk-line); background:var(--desk-surface); border-radius:26px; box-shadow:0 15px 65px #244d4210; }
.login-brand-label { color:var(--text); }
.login-brand-row { gap:10px; }
.login-input { background:var(--desk-soft); border-color:var(--desk-line); border-radius:12px; color:var(--text); }
.login-code-btn { color:var(--desk-link); background:var(--br-soft); border-color:transparent; border-radius:12px; }
.login-input:focus { border-color:var(--br); box-shadow:0 0 0 3px var(--br-soft); }
.story-features { color:var(--text-mute); }
.story-features b { color:var(--text-sec); }
.dlg-card,.bind-drawer { border-color:var(--desk-line); box-shadow:0 16px 80px #123e4820; }
.dlg-card { background:var(--desk-surface); border-radius:24px; }
.bind-close { border:1px solid var(--desk-line); border-radius:50%; color:var(--text-sec); background:var(--desk-soft); }
.bind-guide { border-radius:18px; background:linear-gradient(125deg,var(--br-soft),var(--desk-soft)); }
.bind-checklist li > span { border-radius:50%; }
.bind-step-dot { border-radius:20px; color:var(--text-mute); }
.bind-step-dot.on { background:var(--desk-blue); color:#fff; border-color:transparent; }
.bind-connection-summary { padding:7px 16px; border:1px solid var(--desk-line); border-radius:16px; background:var(--desk-soft); }
.bind-connection-summary .bind-field { min-height:39px; padding:7px 0; border:0; border-radius:0; background:transparent; box-shadow:none; }
.bind-field { background:var(--desk-soft); border-color:var(--desk-line); }
.bind-field > span { color:var(--text-sec); }
.bind-field .bind-input { color:var(--text); }
.bind-input::placeholder { color:var(--text-mute); opacity:.85; }
.manage-identity { display:flex; align-items:center; gap:13px; padding:16px; background:var(--desk-soft); border:1px solid var(--desk-line); border-radius:16px; }
.manage-identity > div { min-width:0; }
.manage-identity > div > span { display:block; font-size: var(--fs-body); color:var(--text-mute); margin-bottom:6px; }
.manage-identity b { display:block; font-size: var(--fs-card); overflow-wrap:anywhere; }
.chain-link-icon { display:grid; place-items:center; flex:none; width:42px; height:46px; background:var(--br-soft); color:var(--desk-link); border-radius:14px; }
.manage-advanced { display:flex; flex-direction:column; gap:6px; border-top:1px solid var(--desk-line); padding-top:15px; }
.manage-advanced > span { font-size: var(--fs-caption); color:var(--text-mute); margin-bottom:2px; }
.manage-advanced button { text-align:left; font-size: var(--fs-body); border-radius:10px; padding:10px 12px; }
.manage-advanced .dlg-warn { background:var(--warn-bg); }
.manage-advanced .dlg-danger { background:var(--err-bg); }
.diagnostic-current { background:linear-gradient(120deg,var(--br-soft),var(--desk-soft)); border-radius:16px; }
.diagnostic-steps li::marker { color:var(--br); font-weight:600; }
.guide-steps li > span { border-radius:50%; background:var(--br-soft); color:var(--desk-link); }
.guide-foot { background:var(--desk-soft); border-color:var(--desk-line); }
.bind-done-ico { width:80px; height:80px; display:grid; place-items:center; margin:15px auto 0; border-radius:50%; background:var(--br-soft); }
/* 明暗双图：白天用阳光插画（img.art-day），夜晚模式换成夜景插画（img.art-night）。
   只隐藏当前主题不用的那张，显示与否仍由各插画位自身规则决定
   （如 .mobile-status-art 仅手机端显示），避免响应式布局被破坏。 */
:root[data-theme="dark"] img.art-day { display:none; }
:root[data-theme="light"] img.art-night,html:not([data-theme]) img.art-night { display:none; }
/* 09-26：插画已改用 <picture><source webp><img png 兜底>，WebP 只有 PNG 的 4% 体积。
   <picture> 只是 inline 包装层，layout 上对被包 img 透明（object-fit / flex item / 百分比宽
   都照旧生效，已实测）——但它是**匿名替换内容盒**，一旦被规则选中当成 flex/grid item 就会
   塌成 0 高。这里统一声明透传，后续给插画位加布局规则时不再被包装层绊住。 */
picture { display: contents; }
/* 夜景插画本身就是暗色调，不再套压暗滤镜；只需适配登录页插画上的文案颜色 */
:root[data-theme="dark"] .care-illustration > span { color:#cfe4df; }

@media (min-width:769px) {
  .app { max-width:1580px; gap:19px; }
  .topbar { background:transparent; margin-bottom:0; min-height:80px; }
  .topbar::before { background:transparent; border:0; }
  .brand { font-size:24px; }
  .brand small { font-size:11px; }
  .head-actions .app-btn2 { color:var(--text-sec); font-size: var(--fs-body); }
  .account-avatar { background:var(--br-soft); color:var(--desk-link); }
  .care-overview { position:relative; overflow:hidden; grid-template-columns:auto 1fr; align-items:center; gap:23px 18px; padding:28px 29% 23px 26px; border:1px solid var(--desk-line); border-radius:22px; background:var(--desk-surface); box-shadow:var(--card-shadow); }
  .overview-heading { position:relative; z-index:1; }
  .overview-heading h1 { font-size: var(--fs-page); letter-spacing:-.025em; }
  .overview-heading p { font-size: var(--fs-body); }
  .overview-controls { position:relative; z-index:1; justify-content:flex-end; gap:10px; min-width:0; }
  .overview-controls select { min-width:0; width:185px; max-width:100%; border:0; padding-left:0; background:transparent; font-size: var(--fs-body); }
  .overview-controls .primary-action { min-height:46px; padding:0 14px; }
  .overview-status { margin-right:0; font-size: var(--fs-micro); border:0; border-radius:11px; padding:12px 15px; z-index:1; }
  .overview-description { font-size: var(--fs-caption); line-height:1.6; }
  .device-status { padding:10px; border-radius:10px; background:var(--desk-soft); }
  .device-chain { display:grid; grid-template-columns:165px 1fr; gap:0 20px; padding:22px 26px 16px; border-radius:22px; box-shadow:var(--card-shadow); }
  .chain-heading { grid-row:1/3; display:flex; flex-direction:column; align-items:flex-start; justify-content:center; gap:8px; }
  .chain-heading h2 { font-size: var(--fs-section); }
  .chain-heading p { font-size: var(--fs-caption); max-width:145px; line-height:1.6; }
  .chain-heading .text-action { margin:0; min-height:24px; font-size: var(--fs-body); }
  .chain-nodes { margin:0; gap:32px; }
  .chain-icon { width:56px; height:63px; border-radius:20px; }
  .chain-node:not(:last-child)::after { width:20px; right:-25px; border-width:2px; opacity:.4; }
  .chain-note { grid-column:2; margin-top:12px; font-size: var(--fs-micro); }
  .dash { grid-template-columns:minmax(0,1fr) minmax(330px,32%); gap:19px; }
  .dash-main { padding:23px 20px 18px; gap:17px 14px; border-radius:22px; box-shadow:var(--card-shadow); }
  .trend-toolbar h2 { font-size: var(--fs-section); }
  .trend-toolbar > div:first-child span { font-size: var(--fs-caption); }
  .range-bar { border-radius:22px; padding:3px; border:0; }
  .range-btn { border-radius:20px; min-height:33px; font-size: var(--fs-body); }
  .chart-card { padding:20px 14px 17px; border-radius:16px; }
  .chart-head { gap:14px; margin-bottom:16px; }
  .chart-head .metric-icon { width:55px; height:55px; }
  .metric-icon .ui-icon { width:27px; height:27px; }
  .metric-icon.hr .ui-icon { width:26px; }
  .chart-head h3 { font-size: var(--fs-card); }
  .chart-value { font-size: var(--fs-num-lg); font-weight:600; letter-spacing:-.045em; }
  #hrNow { color:var(--hr); }
  .metric-freshness { font-size: var(--fs-caption); }
  canvas.chart,canvas#chartBr { height:198px; }
  .chart-summary { padding-top:18px; }
  .chart-summary b { font-size: var(--fs-num-sm); }
  .side-card,.events { border-radius:22px; padding:22px; box-shadow:var(--card-shadow); }
  .side-title,.events-head { font-size: var(--fs-section); }
  .desktop-alert-tabs { border-radius:20px; border:0; }
  .desktop-alert-tabs button { border-radius:17px; min-height:31px; font-size: var(--fs-body); }
  .ev-msg,.event-night-copy p { font-size: var(--fs-body); }
  .ev-time,.event-night-copy time { font-size: var(--fs-caption); }
  .event-feed-note { font-size: var(--fs-caption); }
  .ev-empty strong { font-size: var(--fs-card); }
  .event-night-icon { border-radius:50%; }
  .dev-item { border-radius:13px; }
  .foot-note { padding:0 0 8px; }
}
@media (min-width:769px) and (max-width:1350px) {
  .care-overview { padding-right:23%; grid-template-columns:1fr; gap:15px; }
  .overview-art { width:26%; }
  .overview-heading { display:flex; align-items:baseline; gap:15px; }
  .overview-heading h1 { margin:0; }
  .overview-controls { justify-content:flex-start; }
  .overview-controls select { width:210px; }
  .overview-description { margin-left:0; }
  .chain-icon { width:43px; height:50px; }
  .chain-nodes { gap:20px; }
  .chain-node { gap:9px; }
  .chain-node:not(:last-child)::after { width:10px; right:-14px; }
  .chain-node h3 { font-size:14px; }
  .chain-node p { font-size:11px; }
  .device-chain { grid-template-columns:140px 1fr; padding:20px; gap:0 12px; }
  .dash-main { padding:18px 15px; }
  .chart-head { gap:9px; }
  .chart-head .metric-icon { width:42px; height:42px; }
  .chart-value { font-size:29px; }
}
@media (min-width:769px) and (max-width:1100px) {
  .topbar { flex-wrap:wrap; gap:8px; }
  .top-row { margin-right:auto; }
  .head-actions { margin-left:0; }
  .head-actions .app-btn2 { padding:0 7px; font-size:11px; }
  .brand { font-size:20px; }
  .brand .brand-mark { width:39px; height:39px; }
  .dash { grid-template-columns:1fr; grid-template-areas:"main" "side"; }
  .dash-right { display:grid; grid-template-columns:1fr 1fr; align-items:start; }
  .device-chain { display:block; }
  .chain-heading { flex-direction:row; align-items:center; justify-content:flex-start; margin-bottom:15px; }
  .chain-heading p { max-width:none; }
  .chain-heading .text-action { margin-left:auto; }
  .chain-note { margin-top:13px; }
  .login-page { gap:25px; padding:25px; }
  .login-story h2 { font-size:35px; }
}
@media (max-width:768px) {
  body { background:var(--desk-page); }
  .app { background:var(--desk-page); }
  .topbar { padding:18px 20px 12px; }
  .brand { font-size:22px; gap:10px; }
  .brand .brand-mark { width:42px; height:42px; }
  .brand small { display:block; font-size:10px; letter-spacing:.05em; }
  .topbar .sub-row { display:none; }
  .m-home { padding:10px 18px 100px; }
  .m-hero { padding:9px 0 16px; }
  .m-hero-title { font-size:32px; letter-spacing:-.04em; }
  .m-hero-eyebrow { color:var(--desk-link); font-size:10px; letter-spacing:.08em; margin-bottom:6px; }
  .m-refresh-btn { display:flex; align-items:center; gap:6px; width:auto; min-width:44px; min-height:44px; height:auto; padding:8px 12px; border:1px solid var(--desk-line); border-radius:22px; background:var(--desk-surface); color:var(--desk-link); font-size:12px; box-shadow:none; }
  .m-hero-online { margin-top:8px; font-size:11px; }
  .current-device { gap:8px; padding:8px 12px; min-height:50px; border-radius:14px; margin-bottom:14px; }
  .current-device > .ui-icon { width:21px; color:var(--desk-link); }
  .current-device > span { flex:none; font-size:11px; }
  .current-device select { min-width:0; width:0; flex:1; font-size:12px; }
  .m-status-banner { position:relative; overflow:hidden; padding:20px 12px; min-height:107px; gap:9px; border-radius:20px; }
  .mobile-status-art { display:block; position:absolute; right:0; bottom:0; width:46%; height:100%; object-fit:cover; object-position:right 65%; opacity:.82; mask-image:linear-gradient(to right,transparent,#000 38%); pointer-events:none; }
  .m-status-banner .mobile-shield { width:34px; height:40px; flex:none; position:relative; }
  .m-status-banner > div { position:relative; max-width:calc(100% - 98px); }
  .m-status-banner strong { font-size:17px; line-height:1.5; }
  #mStatusBannerText { font-size:11px; line-height:1.6; }
  .mobile-vitals { gap:12px; }
  .mobile-vitals .m-card { padding:15px 13px 12px; border-radius:21px; box-shadow:var(--card-shadow); }
  .m-card-ico { width:31px; height:31px; }
  .m-card-name { font-size:14px; }
  .m-card-head { gap:7px; }
  .m-card-big { margin-top:16px; }
  .m-card-big .m-big-num { font-size:38px; }
  .m-card-big .m-big-unit { font-size:11px; }
  .m-card-time { font-size:10px; min-height:16px; }
  .m-mini-chart { height:37px; margin-top:14px; }
  .metric-detail-link { display:flex; align-items:center; justify-content:space-between; padding-top:10px; margin-top:3px; border-top:1px solid var(--desk-line); font-size:10px; color:var(--text-sec); }
  .m-card-alarm { padding:19px 16px; border-radius:21px; margin-top:15px; box-shadow:var(--card-shadow); }
  .m-summary-title { font-size:17px; }
  .m-alarm-sub { font-size:10px; }
  .alert-tabs { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); border-radius:22px; background:var(--desk-soft); padding:3px; gap:2px; }
  .alert-tabs button { display:flex; align-items:center; justify-content:center; min-width:0; padding:6px 4px; border-radius:20px; min-height:44px; font-size:11px; white-space:nowrap; }
  .alert-tabs button.active { background:var(--desk-blue); color:#fff; }
  .alert-tabs button b { margin-left:3px; font-size:10px; font-weight:500; }
  .m-abn-type,.event-night-copy strong { font-size:13px; }
  .event-night-copy p { font-size:12px; }
  .event-night-copy time { font-size:10px; }
  .m-abn-empty { padding:24px 0 18px; line-height:1.8; font-size:12px; }
  .event-feed-note { font-size:10px; }
  .mobile-chain-link { display:flex; align-items:center; gap:12px; width:100%; padding:15px; margin:14px 0 0; border:1px solid var(--desk-line); border-radius:19px; background:var(--desk-surface); color:var(--text); text-align:left; cursor:pointer; }
  .mobile-chain-link > span:nth-child(2) { flex:1; }
  .mobile-chain-link strong { display:block; font-size:14px; }
  .mobile-chain-link small { display:block; font-size:10px; color:var(--text-mute); margin-top:6px; }
  .mobile-chain-link > .ui-icon { width:17px; color:var(--text-soft); }
  .care-tip { line-height:1.8; margin:15px 3px; }
  .m-tabbar { border-radius:23px 23px 0 0; border-top:1px solid var(--desk-line); box-shadow:0 -6px 24px #183f3d08; }
  .m-tabbar-item.active { color:var(--desk-link); }
  .m-tabbar-label { font-size:11px; }
  .detail-statistics { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); margin-top:14px; padding:20px 12px 13px; border:1px solid var(--desk-line); border-radius:20px; background:var(--desk-surface); }
  .detail-statistics > div { text-align:center; border-right:1px solid var(--desk-line); }
  .detail-statistics > div:nth-child(3) { border:0; }
  .detail-statistics span { display:block; font-size:11px; color:var(--text-mute); }
  .detail-statistics b { display:block; font:500 24px/1.5 var(--font-mono); color:var(--text); margin-top:5px; }
  .detail-statistics p { grid-column:1/-1; text-align:center; font-size:10px; color:var(--text-mute); margin:14px 0 0; }
  .m-tab.active { background:var(--desk-blue); color:#fff; }
  .m-detail-state-dot.stale { background:var(--warn-text); }
  .m-detail-state { flex-wrap:wrap; }
  .m-device,.m-me { padding-inline:18px !important; }
  .m-device .m-hero,.m-me .m-hero { padding-bottom:6px; }
  .mobile-page-intro { display:block; font-size:12px; color:var(--text-mute); margin:0 0 20px; }
  .m-device-list { margin-top:16px; }
  .mobile-device-icon { display:grid; place-items:center; flex:none; width:42px; height:48px; border-radius:14px; background:var(--br-soft); color:var(--desk-link); }
  .m-device-item { gap:12px; padding:16px; border-radius:19px; box-shadow:var(--card-shadow); }
  .m-device-info { flex:1; }
  .m-device-right { max-width:31%; gap:4px; }
  .m-device-name { font-size:14px; }
  .m-device-sn { font-size:10px; }
  .m-device-more { border-color:var(--desk-line); color:var(--desk-link); background:var(--desk-soft); font-size:12px; }
  .mobile-chain-heading { display:flex; justify-content:space-between; align-items:center; gap:10px; }
  .mobile-chain-heading .text-action { font-size:11px; min-height:40px; }
  .m-sys-name { display:flex; align-items:center; gap:10px; font-size:12px; }
  .m-sys-name .ui-icon { width:22px; color:var(--desk-link); }
  .m-sys-state { flex:none; font-size:10px; }
  .m-me .m-card { border:1px solid var(--desk-line); border-radius:20px; box-shadow:var(--card-shadow); margin-top:15px; }
  .m-me-acct { background:linear-gradient(120deg,var(--br-soft),var(--desk-surface)); }
  .m-avatar { color:var(--desk-link); background:var(--desk-surface); border:1px solid var(--desk-line); box-shadow:none; }
  .m-me-email { overflow-wrap:anywhere; }
  .m-me-acct-info { min-width:0; }
  .m-me-btn { font-size:13px; }
  .m-seg { border-radius:14px; padding:4px; background:var(--desk-soft); }
  .m-seg button { border-radius:10px; min-height:44px; }
  .m-seg button.active { color:#fff; background:var(--desk-blue); }
  .login-page { padding:24px 20px; background:radial-gradient(ellipse at 85% 0%,var(--br-soft),transparent 60%),var(--desk-page); }
  .login-card { padding:30px 24px 22px; border-radius:26px; }
  .login-brand-icon { width:48px; height:48px; }
  .login-logo { font-size:28px; }
  .login-sub { font-size:12px; line-height:1.9; }
  .login-footnote { font-size:10px; }
  .dlg-card,.guide-card { border-radius:25px 25px 0 0; }
  .bind-steps { gap:3px; }
  .bind-step-dot { padding:7px 4px; }
  .bind-step-line { min-width:4px; }
  .bind-connection-summary .bind-field { font-size:12px; }
  .manage-advanced { gap:8px; }
}

/* =====================================================================
   v13.0 桌面端：左侧固定侧边栏 + 五页布局（首页/健康数据/设备管理/告警记录/帮助中心）
   移动端（≤768px）零改动：.desk-sidebar / .desk-content 整体隐藏，手机仍走底部三 tab。
   品牌色：象牙白 #FFFDF8 · 深海青 #134D63 · 薄荷绿 #59BDA6 · 暖珊瑚 #FF8F8A · 柔紫 #C8B4E9
   ===================================================================== */
:root {
  --brand-ivory: #FFFDF8;
  --brand-teal: #134D63;
  --brand-mint: #59BDA6;
  --brand-coral: #FF8F8A;
  --brand-lilac: #C8B4E9;
}
:root[data-theme="dark"] {
  --brand-ivory: #0E1D20;
  --brand-teal: #8FC7DA;
}

/* 非桌面宽度：整块侧边栏布局不参与渲染（手机端布局完全不受影响） */
@media (max-width: 768px) {
  .desk-sidebar, .desk-content { display: none !important; }
}

/* 桌面页面显隐（deskSwitchPage() 切 .active） */
.desk-page { display: none; }

@media (min-width: 769px) {
  body { padding: 0 26px 24px 0; font-size: var(--fs-body); }
  .app {
    max-width: 1680px;
    display: grid;
    grid-template-columns: 320px minmax(0, 1fr);
    grid-template-areas: "side top" "side body" "side foot";
    grid-template-rows: auto 1fr auto;
    align-items: start;
    gap: 0 28px;
  }
  .desk-sidebar { grid-area: side; }
  .topbar { grid-area: top; }
  .desk-content { grid-area: body; }
  .foot-note { grid-area: foot; }

  /* 顶栏归位到右列：品牌移到侧边栏，右侧放操作与账号 */
  .topbar { background: none; border: 0; padding: 18px 0 6px; min-height: 0; justify-content: flex-end; }
  .topbar::before { display: none; }
  .topbar .top-row .brand { display: none; }
  .topbar .head-actions { margin-left: auto; }

  /* ===== 侧边栏 ===== */
  .desk-sidebar {
    position: sticky; top: 0; align-self: start; height: 100vh;
    display: flex; flex-direction: column; gap: 16px;
    padding: 22px 14px 18px;
    border-right: 1px solid var(--desk-line);
  }
  .desk-side-head { display: flex; align-items: center; gap: 10px; padding: 2px 8px 8px; }
  .desk-brand-mark .brand-svg { width: 38px; height: 38px; display: block; }
  .desk-brand-text b { display: block; font-size: 19px; letter-spacing: -.02em; color: var(--brand-teal); }
  .desk-brand-text small { display: block; margin-top: 3px; font-size: 10.5px; color: var(--text-dim); }
  .desk-nav { display: flex; flex-direction: column; gap: 6px; }
  .desk-nav-item {
    display: flex; align-items: center; gap: 10px;
    padding: 11px 14px; border: 0; border-radius: 12px;
    background: transparent; color: var(--text-sec);
    font-weight: 600; font-size: var(--fs-card); font-family: var(--font-sans); cursor: pointer; text-align: left;
    transition: background .15s var(--ease-hover), color .15s var(--ease-hover);
  }
  .desk-nav-item:hover { background: color-mix(in srgb, var(--desk-ink) 5%, transparent); }
  .desk-nav-item .ui-icon { width: 18px; height: 18px; flex: none; }
  .desk-nav-item span { flex: 1; }
  .desk-nav-item.active { background: var(--brand-teal); color: var(--brand-ivory); }
  .desk-nav-badge {
    flex: none; min-width: 20px; padding: 1px 6px; border-radius: 999px;
    background: var(--brand-coral); color: #3A1614; font-size: var(--fs-micro); font-weight: 700; text-align: center;
  }
  /* 13.5.1 侧栏底部图文并排：文字在左、图在右（DOM 是图在前，用 row-reverse 调换）
     13.5.2 整块放大：侧栏加宽 238→320px，图 101→146px、正文 11→14px（「都有被守护的意义」8 字 112px，须放进文字栏 122px 内不再折行） */
  .desk-side-foot { margin: auto auto 0; padding: 12px 6px 0; width: 100%; max-width: 292px; text-align: center; display: flex; flex-direction: row-reverse; align-items: center; gap: 12px; }
  /* img 的 width/height 属性是表现提示：只盖 width 不盖 height 会被拉成属性高度 */
  .desk-side-foot img { width: 52%; height: auto; border-radius: 14px; display: block; flex: none; }
  .desk-side-foot p { flex: 1; min-width: 0; margin: 0; font-size: var(--fs-body); line-height: 1.75; color: var(--text-dim); }

  /* ===== 内容区与页面骨架 ===== */
  .desk-content { display: flex; flex-direction: column; gap: 15px; min-width: 0; }
  .desk-page.active { display: flex; flex-direction: column; gap: 15px; }
  .desk-page-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
  .desk-page-head h2 { font-size: var(--fs-page); letter-spacing: -.02em; color: var(--desk-ink); }
  .desk-page-head p { margin-top: 5px; font-size: var(--fs-body); color: var(--text-dim); }
  .desk-head-actions { display: flex; gap: 10px; }
  .desk-page .events-list { max-height: 620px; }
  /* 起夜行是横向单行布局，桌面 .ev-actions 的 width:100%（告警行按钮整行换行用）
     会把 flex 行全部吃掉、event-night-copy 被挤成 0 宽（文字逐字竖排）—— 起夜行里还原 auto */
  .ev.ev-night .ev-actions { width: auto; margin: 0 0 0 10px; flex: none; display: flex; gap: 6px; }
  .ev.ev-night .event-night-label { flex: none; }
  /* 设备列表去掉 v12.5 桌面的 280px 高度帽：设备管理页要完整列出所有设备 */
  .desk-page .dev-list { max-height: none; }
  /* 暗色下侧栏插画与既有插画同规格压暗（原 dark 规则未覆盖它） */
  /* 夜晚模式直接用夜景插画（img.art-night），不再对侧栏小图压暗 */

  /* ===== 指标卡（首页 4 张 / 告警 3 张） ===== */
  .desk-stat-row { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 14px; }
  .desk-stat-row.desk-stat-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .desk-stat-card {
    display: flex; align-items: center; gap: 12px;
    padding: 16px 18px; border: 1px solid var(--desk-line); border-radius: 15px; background: var(--desk-surface);
  }
  .desk-stat-ico { width: 40px; height: 40px; border-radius: 12px; display: grid; place-items: center; flex: none; }
  .desk-stat-ico .ui-icon { width: 20px; height: 20px; }
  .desk-stat-ico.hr { background: color-mix(in srgb, var(--hr) 14%, transparent); color: var(--hr); }
  .desk-stat-ico.br { background: color-mix(in srgb, var(--br) 14%, transparent); color: var(--br); }
  .desk-stat-ico.night { background: color-mix(in srgb, var(--brand-lilac) 30%, transparent); color: var(--brand-teal); }
  .desk-stat-ico.pend { background: color-mix(in srgb, var(--brand-coral) 24%, transparent); color: var(--err-text); }
  .desk-stat-ico.ok { background: var(--ok-bg); color: var(--ok-text); }
  .desk-stat-body { min-width: 0; }
  .desk-stat-body small { display: block; font-size: var(--fs-caption); color: var(--text-dim); }
  .desk-stat-body b { font-size: var(--fs-num-lg); letter-spacing: -.02em; color: var(--desk-ink); }
  .desk-stat-unit { margin-left: 4px; font-size: var(--fs-caption); color: var(--text-dim); }
  .desk-stat-body p { margin-top: 3px; font-size: var(--fs-caption); color: var(--text-mute); }

  /* ===== 体征摘要（首页迷你趋势，点击进健康数据） ===== */
  .desk-vitals { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
  .desk-vital-card {
    display: flex; flex-direction: column; gap: 10px; text-align: left;
    padding: 16px 18px; border: 1px solid var(--desk-line); border-radius: 15px;
    background: var(--desk-surface); cursor: pointer;
    transition: border-color .15s var(--ease-hover), transform .15s var(--ease-hover);
  }
  .desk-vital-card:hover { border-color: var(--brand-mint); transform: translateY(-1px); }
  .desk-vital-head { display: flex; align-items: center; gap: 10px; }
  .desk-vital-head .metric-icon { width: 34px; height: 34px; }
  .desk-vital-txt { flex: 1; min-width: 0; }
  .desk-vital-txt h3 { font-size: var(--fs-card); color: var(--desk-ink); }
  .desk-vital-txt p { margin-top: 2px; font-size: var(--fs-caption); color: var(--text-dim); }
  .desk-vital-val b { font-size: var(--fs-num-sm); letter-spacing: -.02em; color: var(--desk-ink); }
  .desk-vital-val small { margin-left: 4px; font-size: var(--fs-caption); color: var(--text-dim); }
  .desk-vital-card .m-mini-chart { width: 100%; height: 62px; margin-top: 0; display: block; }
  .desk-vital-card .m-mini-dot { fill: var(--br); }
  .desk-vital-card .m-mini-dot.bad { fill: var(--err); }
  .desk-vital-note { font-size: var(--fs-caption); color: var(--text-mute); }

  /* ===== 快速操作 ===== */
  .desk-quick h2 { font-size: var(--fs-section); color: var(--text-sec); margin-bottom: 10px; }
  .desk-quick-grid { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 12px; }
  .desk-quick-item {
    display: flex; align-items: center; gap: 10px; text-align: left;
    padding: 14px; border: 1px solid var(--desk-line); border-radius: 14px;
    background: var(--desk-surface); cursor: pointer;
    transition: border-color .15s var(--ease-hover);
  }
  .desk-quick-item:hover { border-color: var(--brand-mint); }
  .desk-quick-item .ui-icon { width: 18px; height: 18px; color: var(--brand-teal); flex: none; }
  .desk-quick-item b { display: block; font-size: var(--fs-card); color: var(--desk-ink); }
  .desk-quick-item small { display: block; margin-top: 3px; font-size: var(--fs-caption); color: var(--text-dim); }

  /* ===== 通用卡片 / 设备管理两列 ===== */
  .desk-card { border: 1px solid var(--desk-line); border-radius: 15px; background: var(--desk-surface); padding: 18px; }
  .desk-card-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: 12px; }
  .desk-card-head h2 { font-size: var(--fs-section); color: var(--desk-ink); }
  .desk-card-head p { margin-top: 3px; font-size: var(--fs-caption); color: var(--text-dim); }
  /* v13.4 设备管理「行式」布局：链路总览 / 设备诊断通栏，列表 + 详情居中两列。
     网格等高拉伸，设备台数少时空白收进卡片内部（操作按钮贴底），不再留大块裸背景 */
  .desk-grid-dev { display: grid; grid-template-columns: minmax(0, 1fr) 330px; gap: 20px; align-items: start; }
  .desk-grid-dev > .device-chain, .desk-grid-dev > .dev-grid-diag { grid-column: 1 / -1; }
  .desk-grid-dev > .dev-grid-list { grid-column: 1; }
  .desk-grid-dev > .dev-grid-detail { grid-column: 2; }
  /* 四张卡统一圆角 / 内边距 / 投影（side-card 与 desk-card 原本不一致，两列并排会露馅） */
  .desk-grid-dev > .device-chain, .desk-grid-dev > .dev-grid-list, .desk-grid-dev > .dev-grid-detail, .desk-grid-dev > .dev-grid-diag {
    border: 1px solid var(--desk-line); border-radius: 16px; background: var(--desk-surface);
    box-shadow: 0 4px 15px #20465b03; padding: 18px 20px;
  }
  /* 同行卡片白底等高；列表保持顶部排列，接入操作保持紧凑。单列由各自行高决定。 */
  .dev-grid-list, .dev-grid-detail { display: flex; flex-direction: column; min-width: 0; align-self: stretch; }
  .dev-grid-list .dev-list { flex: 1 1 auto; }
  .dev-grid-detail .desk-detail-actions { margin-top: auto; padding-top: 14px; }
  /* 序列号接入使用紧凑操作行。 */
  .dev-grid-list .dev-list-fill {
    flex: 0 0 auto; min-height: 60px; margin-top: 14px; padding: 10px 14px;
    display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px;
    border: 1px dashed color-mix(in srgb, var(--text-mute) 32%, transparent);
    border-radius: 12px; background: color-mix(in srgb, var(--desk-page) 65%, transparent);
  }
  .dev-grid-list .device-access { margin: 0; font-size: var(--fs-caption); }
  .dev-grid-list .dev-list-fill-hint { margin: 0; font-size: var(--fs-caption); color: var(--text-mute); }
  .desk-card-head .primary-action { flex: none; white-space: nowrap; }
  /* 链路总览通栏后仍可能在窄列（≤1279px 单列）：缩图标、禁折行，避免"毫米波雷/达"式断行 */
  .desk-grid-dev .chain-icon { width: 44px; height: 48px; border-radius: 14px; }
  .desk-grid-dev .chain-node { gap: 9px; }
  .desk-grid-dev .chain-node h3 { font-size: var(--fs-card); white-space: nowrap; }
  .desk-grid-dev .chain-node p { white-space: nowrap; }
  .desk-grid-dev .chain-node .sys-state { white-space: nowrap; }

  .desk-kv { display: flex; justify-content: space-between; gap: 14px; padding: 9px 0; border-bottom: 1px dashed color-mix(in srgb, var(--desk-line) 80%, transparent); font-size: var(--fs-body); }
  .desk-kv:last-of-type { border-bottom: 0; }
  .desk-kv span { color: var(--text-dim); flex: none; }
  /* 用 anywhere 而不是 break-all：SG2002 这类型号不被从中间拆断 */
  .desk-kv b { color: var(--desk-ink); font-weight: 600; text-align: right; word-break: normal; overflow-wrap: anywhere; }
  .desk-state.ok { color: var(--ok-text); }
  .desk-state.warn { color: var(--warn-text); }
  .desk-state.idle { color: var(--text-mute); }
  .desk-disclaimer { margin-top: 10px; font-size: var(--fs-caption); line-height: 1.8; color: var(--text-mute); }
  .desk-empty { padding: 16px 4px; font-size: var(--fs-body); line-height: 1.8; color: var(--text-dim); }
  .desk-detail-actions { margin-top: 14px; display: flex; gap: 10px; }

  /* 诊断清单：通栏后四项横向自适应排列（窄屏自动降列），说明行整行收尾 */
  .desk-diag-list { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 10px; }
  .desk-diag-list .desk-disclaimer { grid-column: 1 / -1; margin-top: 2px; }
  .desk-diag-row { display: flex; align-items: center; gap: 10px; padding: 10px 12px; border: 1px solid var(--desk-line); border-radius: 12px; }
  .desk-diag-row > div { flex: 1; min-width: 0; }
  .desk-diag-row b { display: block; font-size: var(--fs-card); color: var(--desk-ink); }
  .desk-diag-row small { display: block; margin-top: 2px; font-size: var(--fs-caption); color: var(--text-dim); }
  .desk-diag-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--text-mute); flex: none; }
  .desk-diag-dot.ok { background: var(--ok-text); }
  .desk-diag-dot.warn, .desk-diag-dot.err { background: var(--err); }
  .desk-diag-state { flex: none; font-size: var(--fs-caption); font-weight: 600; }
  .desk-diag-state.ok { color: var(--ok-text); }
  .desk-diag-state.warn { color: var(--warn-text); }
  .desk-diag-state.err { color: var(--err-text); }
  .desk-diag-state.idle { color: var(--text-mute); }

  /* 历史记录表 + 分页 */
  .desk-history-tools select { min-height: 36px; padding: 0 10px; border: 1px solid var(--desk-line); border-radius: 10px; background: var(--desk-page); color: var(--text-sec); font-size: var(--fs-body); }
  .desk-table-wrap { overflow-x: auto; }
  .desk-table { width: 100%; border-collapse: collapse; font-size: var(--fs-body); }
  .desk-table th { text-align: left; padding: 8px 10px; font-weight: 600; color: var(--text-dim); border-bottom: 1px solid var(--desk-line); white-space: nowrap; }
  .desk-table td { padding: 9px 10px; color: var(--text-sec); border-bottom: 1px dashed color-mix(in srgb, var(--desk-line) 70%, transparent); white-space: nowrap; }
  .desk-table-empty { text-align: center; color: var(--text-dim); padding: 22px 10px !important; white-space: normal; }
  .desk-table-state { display: inline-block; padding: 2px 9px; border-radius: 999px; font-size: var(--fs-caption); font-weight: 600; }
  .desk-table-state.ok { background: var(--ok-bg); color: var(--ok-text); }
  .desk-table-state.warn { background: color-mix(in srgb, var(--warn) 16%, transparent); color: var(--warn-text); }
  .desk-pager { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-top: 12px; }
  .desk-pager-btn { min-width: 30px; padding: 5px 10px; border: 1px solid var(--desk-line); border-radius: 8px; background: var(--desk-surface); color: var(--text-sec); font-size: var(--fs-body); cursor: pointer; }
  .desk-pager-btn:hover:not(:disabled) { border-color: var(--brand-mint); }
  .desk-pager-btn.active { background: var(--brand-teal); border-color: var(--brand-teal); color: var(--brand-ivory); }
  .desk-pager-btn:disabled { opacity: .45; cursor: default; }
  .desk-pager-info { font-size: var(--fs-caption); color: var(--text-dim); }

  /* 设备行新增按钮（详情 / 解绑，与 .dev-more 同高） */
  .dev-detail, .dev-unbind {
    flex: none; min-width: 43px; height: 43px; padding: 0 8px; margin-right: 4px;
    border: 1px solid var(--card-border); border-radius: 9px; background: transparent;
    color: var(--text-mute); font-weight: 600; font-size: var(--fs-body); font-family: var(--font-sans); cursor: pointer;
    transition: background .15s var(--ease-hover), color .15s var(--ease-hover), border-color .15s var(--ease-hover);
  }
  .dev-detail:hover { color: var(--text); border-color: var(--text-dim); }
  .dev-unbind:hover { color: var(--err-text); border-color: var(--err); }
  .dev-unbind.arm { background: var(--err); border-color: var(--err); color: #fff; }

  /* ===== 帮助中心 ===== */
  .help-search { display: flex; align-items: center; gap: 10px; }
  .help-search .ui-icon { width: 18px; height: 18px; color: var(--text-mute); flex: none; }
  .help-search input {
    flex: 1; min-width: 0; min-height: 44px; padding: 0 14px;
    border: 1px solid var(--desk-line); border-radius: 12px;
    background: var(--desk-page); color: var(--text); font-weight: 400; font-size: var(--fs-body); font-family: var(--font-sans);
  }
  .help-search input::placeholder { color: var(--text-mute); }
  .help-hot { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin-top: 12px; font-size: var(--fs-body); color: var(--text-dim); }
  .help-hot button { padding: 4px 12px; border: 1px solid var(--desk-line); border-radius: 999px; background: transparent; color: var(--text-sec); font-size: var(--fs-body); cursor: pointer; }
  .help-hot button:hover { border-color: var(--brand-mint); color: var(--brand-teal); }
  .help-search-result { margin-top: 10px; font-size: var(--fs-body); color: var(--brand-teal); }
  .desk-help-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 14px; }
  .help-entry { display: flex; flex-direction: column; gap: 7px; text-align: left; cursor: pointer; transition: border-color .15s var(--ease-hover); }
  .help-entry:hover { border-color: var(--brand-mint); }
  .help-entry-ico { width: 38px; height: 38px; border-radius: 11px; display: grid; place-items: center; background: color-mix(in srgb, var(--brand-mint) 20%, transparent); color: var(--brand-teal); }
  .help-entry-ico .ui-icon { width: 19px; height: 19px; }
  .help-entry h3 { font-size: var(--fs-card); color: var(--desk-ink); }
  .help-entry p { flex: 1; font-size: var(--fs-caption); line-height: 1.7; color: var(--text-dim); }
  .help-entry-link { font-size: var(--fs-body); font-weight: 600; color: var(--desk-link); }
  /* 帮助中心两栏等高（v14.2）：原先 align-items:start 让左列「常见问题」按内容高度收在顶部，
     右列（联系方式 + 关于）更高，左列底部就空出一块、卡片下沿也对不齐。
     改为 stretch 让两栏同高，左列列表 flex:1 把余量摊到条目间距里补满；
     右列末卡 flex:1 兜底，左列更高时右列下沿也仍是卡片边框。 */
  .desk-help-cols { display: grid; grid-template-columns: minmax(0, 1fr) 330px; gap: 15px; align-items: stretch; }
  .desk-help-side { display: flex; flex-direction: column; gap: 15px; }
  .desk-help-side > .desk-card:last-child { flex: 1 1 auto; }
  #helpFaqCard { display: flex; flex-direction: column; }
  #helpFaqCard .help-faq-list { flex: 1 1 auto; justify-content: space-between; }
  /* 筛选/搜索后条目变少时不能再靠拉开间距补满（3 条会被拉成上下各一条），
     间距还原为 8px；卡片仍然保持等高 —— 收缩会让底部又空出一大块、页面还会跳。
     :has([hidden]) 正是 helpApplyFilter() 写下的隐藏态 */
  #helpFaqCard:has(.help-faq-list > [hidden]) .help-faq-list { justify-content: flex-start; }
  .help-cats { display: flex; flex-wrap: wrap; gap: 6px; }
  .help-cats button { padding: 5px 12px; border: 1px solid var(--desk-line); border-radius: 999px; background: transparent; color: var(--text-sec); font-size: var(--fs-body); cursor: pointer; }
  .help-cats button.active { background: var(--brand-teal); border-color: var(--brand-teal); color: var(--brand-ivory); }
  .help-faq-list { display: flex; flex-direction: column; gap: 8px; }
  .help-faq-item { padding: 0 14px; border: 1px solid var(--desk-line); border-radius: 12px; background: var(--desk-page); }
  .help-faq-item summary {
    display: flex; justify-content: space-between; gap: 10px; align-items: center;
    padding: 12px 0; cursor: pointer; list-style: none;
    font-size: var(--fs-card); font-weight: 600; color: var(--desk-ink);
  }
  .help-faq-item summary::-webkit-details-marker { display: none; }
  .help-faq-item summary::after { content: "＋"; color: var(--text-mute); font-weight: 400; }
  .help-faq-item[open] summary::after { content: "－"; }
  .help-faq-item[open] summary { color: var(--brand-teal); }
  .help-faq-body { padding: 0 0 14px; font-size: var(--fs-body); line-height: 1.9; color: var(--text-sec); }
  .help-empty { padding: 16px 2px; font-size: var(--fs-body); color: var(--text-dim); }
  .help-todo { color: var(--warn-text); }
  .help-about { margin-bottom: 10px; font-size: var(--fs-body); line-height: 1.9; color: var(--text-sec); }
  .help-legal { display: flex; align-items: center; gap: 10px; margin-top: 10px; color: var(--text-mute); }

  /* ===== v13.0 新增弹窗 ===== */
  /* 🔴 登录页的条款弹窗必须比登录页本身更高。
     #loginPage 是 z-index:99999（.login-page），而通用 .dlg-mask 只有 1100 ——
     于是"在登录页上点《用户协议》/《隐私政策》"时，弹窗其实正常打开了
     （hidden=false、display=flex），却被登录页**整个盖住**，用户看到的就是"点了没反应"。
     症状极具迷惑性：鼠标是小手、按钮有按下反馈、无任何报错、桌面与手机端同时失效。
     只给 #legalMask 提升层级（不用改通用 .dlg-mask），避免波及告警详情/说明书/夜间设置等其他弹窗。 */
  #legalMask { z-index: 100000; }
  .alert-detail-card { width: min(500px, calc(100vw - 32px)); }
  .alert-detail-desc { margin: 12px 0; padding: 12px 14px; border-radius: 12px; background: var(--desk-page); font-size: var(--fs-body); line-height: 1.8; color: var(--text-sec); }
  .alert-detail-actions { display: flex; gap: 10px; margin-top: 14px; }
  .manual-card, .legal-card { width: min(560px, calc(100vw - 32px)); }
  .manual-sec { margin-top: 14px; }
  .manual-sec h3 { margin-bottom: 6px; font-size: var(--fs-card); color: var(--desk-ink); }
  .manual-list { margin: 0; padding-left: 18px; font-size: var(--fs-body); line-height: 2; color: var(--text-sec); }
  .legal-pane h3 { margin-bottom: 8px; font-size: var(--fs-card); color: var(--desk-ink); }
  .legal-pane p { margin-bottom: 8px; font-size: var(--fs-body); line-height: 1.9; color: var(--text-sec); }
  .legal-pane h4 { margin: 12px 0 6px; font-size: var(--fs-card); color: var(--desk-ink); }
  .legal-pane ul { margin: 0 0 8px; padding-left: 18px; }
  .legal-pane li { margin-bottom: 5px; font-size: var(--fs-body); line-height: 1.9; color: var(--text-sec); }
  .legal-pane .legal-meta { margin-bottom: 10px; font-size: var(--fs-caption); color: var(--text-dim); }
  .legal-pane a { color: var(--desk-link); text-decoration: underline; overflow-wrap: anywhere; }
  /* 保存期限/受托方清单表格：窄容器内可横向滚动，不撑破弹窗 */
  .legal-pane .legal-tbl-wrap { margin: 4px 0 12px; overflow-x: auto; border: 1px solid var(--desk-line); border-radius: 8px; }
  .legal-pane .legal-tbl { width: 100%; border-collapse: collapse; font-size: var(--fs-caption); }
  .legal-pane .legal-tbl th, .legal-pane .legal-tbl td { padding: 7px 9px; text-align: left; vertical-align: top; border-bottom: 1px solid var(--desk-line); color: var(--text-sec); line-height: 1.7; }
  .legal-pane .legal-tbl th { background: var(--desk-soft); color: var(--desk-ink); font-weight: 600; white-space: nowrap; }
  .legal-pane .legal-tbl tr:last-child td { border-bottom: none; }
  .legal-pane b { color: var(--desk-ink); font-weight: 600; }
}

/* 中等桌面（≤1279px）：指标卡两列、快速操作三列、帮助两列、设备管理单列 */
@media (min-width: 769px) and (max-width: 1279px) {
  .desk-stat-row, .desk-stat-row.desk-stat-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .desk-quick-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .desk-help-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .desk-grid-dev, .desk-help-cols { grid-template-columns: minmax(0, 1fr); }
  /* 单列回落：选择器必须和上面的列定位规则同权重（源序靠后才赢）。
     用 .desk-grid-dev > * 会输给 .dev-grid-detail 的 grid-column:2，撑出隐式第二列、把通栏卡挤成半宽 */
  .desk-grid-dev > .device-chain, .desk-grid-dev > .dev-grid-list, .desk-grid-dev > .dev-grid-detail, .desk-grid-dev > .dev-grid-diag { grid-column: 1 / -1; }
}

/* 窄桌面（≤1023px）：侧边栏收窄、体征摘要单列（13.5.2 侧栏 200→240px，保证底部图文文字栏 ≥96px 不折行） */
@media (min-width: 769px) and (max-width: 1023px) {
  .app { grid-template-columns: 240px minmax(0, 1fr); gap: 0 20px; }
  .desk-vitals { grid-template-columns: minmax(0, 1fr); }
  .desk-side-foot { padding: 10px 4px 0; gap: 10px; }
  .desk-side-foot img { width: 46%; border-radius: 12px; }
  .desk-side-foot p { font-size: 12px; line-height: 1.7; }
}

/* v13.4 设备链路通栏：大屏下图标与型号字号回到常规尺寸（窄屏沿用紧凑规格防断行） */
@media (min-width: 1440px) {
  .desk-grid-dev .chain-icon { width: 55px; height: 59px; border-radius: 18px; }
  .desk-grid-dev .chain-node { gap: 13px; }
  .desk-grid-dev .chain-node h3 { font-size: var(--fs-card); }
}

/* v13.0 首页当前设备操作：避免与左侧页面导航重复 */
@media (min-width: 769px) {
  .desk-quick-grid { grid-template-columns: repeat(3, minmax(0, 250px)); }
  .desk-quick-empty { display: grid; grid-template-columns: repeat(3, minmax(0, 250px)); gap: 12px; }
  .desk-quick-empty[hidden] { display: none; }
}

/* v13.1 快速操作美化：入口卡片层级、主题色与悬浮反馈 */
.desk-quick { margin-top: 2px; }
.desk-quick-head { display:flex; align-items:flex-end; justify-content:space-between; gap:16px; margin-bottom:12px; }
.desk-quick-head h2 { margin:0; font-size: var(--fs-section); letter-spacing:.01em; color:var(--desk-ink); }
.desk-quick-head p { margin:4px 0 0; font-size: var(--fs-caption); color:var(--text-dim); }
.desk-quick-kicker { padding:5px 9px; border-radius:999px; background:color-mix(in srgb, var(--brand-mint) 13%, transparent); color:var(--brand-teal); font-size: var(--fs-micro); font-weight:600; white-space:nowrap; }
.desk-quick-grid, .desk-quick-empty { gap:12px; }
.desk-quick-item { position:relative; min-height:78px; padding:13px 38px 13px 13px; border-color:color-mix(in srgb, var(--desk-line) 82%, var(--brand-mint)); border-radius:16px; box-shadow:0 3px 12px rgba(22,70,78,.035); overflow:hidden; transition:transform .18s var(--ease-hover), border-color .18s var(--ease-hover), box-shadow .18s var(--ease-hover), background .18s var(--ease-hover); }
.desk-quick-item::after { content:""; position:absolute; inset:auto -18px -28px auto; width:78px; height:78px; border-radius:50%; background:color-mix(in srgb, var(--desk-quick-accent, var(--brand-mint)) 9%, transparent); pointer-events:none; }
.desk-quick-item:hover, .desk-quick-item:focus-visible { transform:translateY(-2px); border-color:var(--desk-quick-accent, var(--brand-mint)); box-shadow:0 10px 22px rgba(22,70,78,.10); outline:none; }
.desk-quick-icon { display:grid; place-items:center; width:36px; height:36px; flex:none; border-radius:12px; color:var(--desk-quick-accent, var(--brand-teal)); background:color-mix(in srgb, var(--desk-quick-accent, var(--brand-mint)) 13%, transparent); transition:transform .18s var(--ease-hover), background .18s var(--ease-hover); }
.desk-quick-item:hover .desk-quick-icon, .desk-quick-item:focus-visible .desk-quick-icon { transform:scale(1.06); background:color-mix(in srgb, var(--desk-quick-accent, var(--brand-mint)) 18%, transparent); }
.desk-quick-icon .ui-icon { width:18px; height:18px; color:inherit; }
.desk-quick-item b { font-size: var(--fs-card); letter-spacing:.01em; }
.desk-quick-item small { line-height:1.45; }
.desk-quick-arrow { position:absolute; right:13px; bottom:12px; color:var(--desk-quick-accent, var(--text-mute)); font-size:18px; line-height:1; transition:transform .18s var(--ease-hover); z-index:1; }
.desk-quick-item:hover .desk-quick-arrow, .desk-quick-item:focus-visible .desk-quick-arrow { transform:translateX(3px); }
.desk-quick-item:nth-child(1) { --desk-quick-accent:var(--brand-teal); }
.desk-quick-item:nth-child(2) { --desk-quick-accent:#4D91B8; }
.desk-quick-item:nth-child(3) { --desk-quick-accent:#C28A32; }
.desk-quick-empty .desk-quick-item:nth-child(1) { --desk-quick-accent:var(--brand-teal); }
.desk-quick-empty .desk-quick-item:nth-child(2) { --desk-quick-accent:#4D91B8; }
.desk-quick-empty .desk-quick-item:nth-child(3) { --desk-quick-accent:#8B72B8; }
@media (max-width: 768px) {
  .desk-quick-head { align-items:flex-start; }
  .desk-quick-grid, .desk-quick-empty { grid-template-columns:repeat(2, minmax(0,1fr)); }
  .desk-quick-item { min-height:104px; align-items:flex-start; flex-direction:column; gap:9px; padding:12px 12px 30px; }
  .desk-quick-arrow { right:12px; bottom:10px; }
}

/* 首页设备工作区：四个入口 */
@media (min-width: 769px) {
  .desk-quick-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .desk-quick-item { min-height: 84px; }
}
.desk-quick-wide { min-width: 0; }

/* v13.1 设备连接与告警工作区：作用域限定桌面页面，复用浅/深色主题变量。 */
@media (min-width: 769px) {
  .desk-content { padding-top: 16px; }
  #deskPageAlerts, #deskPageDevices { gap: 20px; }
  #deskPageAlerts .desk-page-head, #deskPageDevices .desk-page-head { align-items: center; min-height: 72px; }
  #deskPageAlerts .desk-page-head h2, #deskPageDevices .desk-page-head h2 { font-size: var(--fs-page); }
  #deskPageAlerts .desk-page-head p, #deskPageDevices .desk-page-head p { font-size: var(--fs-body); }
  #deskPageAlerts :is(button, select):focus-visible,
  #deskPageDevices :is(button, summary):focus-visible { outline: 2px solid var(--desk-link); outline-offset: 3px; }
  .desk-grid-dev > .device-connection { display: flex; flex-direction: column; gap: 20px; padding: 22px 24px; }
  .connection-head { display: flex; align-items: center; justify-content: space-between; gap: 16px; }
  .connection-head h2 { margin: 0; font-size: var(--fs-section); color: var(--desk-ink); }
  .connection-head p { margin: 5px 0 0; font-size: var(--fs-caption); color: var(--text-sec); overflow-wrap: anywhere; }
  .connection-head .primary-action { flex: none; }
  .device-connection .chain-nodes { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 30px; margin: 0; }
  .device-connection .chain-node { min-width: 0; gap: 12px; }
  .desk-grid-dev .device-connection .chain-icon { width: 48px; height: 52px; border-radius: 15px; flex: none; }
  .device-connection .chain-node p { font-size: var(--fs-caption); margin-top: 4px; }
  .device-connection .sys-state { font-size: var(--fs-caption); margin-top: 6px; }
  .connection-summary { display: flex; align-items: flex-start; gap: 10px; padding: 13px 15px; border-radius: 10px; background: var(--desk-soft); color: var(--text-sec); }
  .connection-summary .ui-icon { width: 18px; height: 18px; margin-top: 2px; flex: none; color: var(--desk-link); }
  .connection-summary p { margin: 0; font-size: var(--fs-body); line-height: 1.7; }
  .connection-details { border-top: 1px solid var(--desk-line); padding-top: 13px; }
  .connection-details summary { cursor: pointer; color: var(--desk-link); font-size: var(--fs-card); }
  .connection-details summary span { margin-left: 16px; color: var(--text-sec); font-size: var(--fs-caption); }
  .connection-evidence { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; margin-top: 18px; }
  .connection-evidence h3 { font-size: var(--fs-card); margin: 0 0 8px; }
  .connection-evidence p { margin: 0; font-size: var(--fs-body); color: var(--text-sec); line-height: 1.8; }
  .connection-evidence .connection-scope { margin-top: 8px; font-size: var(--fs-caption); }
  .dev-grid-list .side-title { font-size: var(--fs-section); }
  .dev-grid-list .dev-list-fill-hint { font-size: var(--fs-caption); color: var(--text-sec); }

  #deskPageAlerts .desk-stat-row { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; }
  .alert-stat-card { position: relative; width: 100%; min-height: 114px; text-align: left; font-family: inherit; cursor: pointer; transition: border-color .15s, background .15s; }
  .alert-stat-card:hover, .alert-stat-card[aria-pressed="true"] { border-color: var(--desk-link); background: color-mix(in srgb, var(--desk-soft) 65%, var(--desk-surface)); }
  .alert-stat-card.has-pending { border-color: color-mix(in srgb, var(--err-text) 45%, var(--desk-line)); }
  .alert-stat-card.has-pending .desk-stat-body b { color: var(--err-text); }
  .alert-stat-card .desk-stat-body small { font-size: var(--fs-caption); color: var(--text-sec); }
  .alert-stat-card .desk-stat-body b { font-size: var(--fs-num-lg); font-variant-numeric: tabular-nums; }
  .alert-stat-card .desk-stat-unit { font-size: var(--fs-caption); }
  .alert-stat-hint { display: block; font-size: var(--fs-caption); line-height: 1.6; color: var(--text-sec); }
  .alert-stat-arrow { margin-left: auto; align-self: flex-start; color: var(--desk-link); font-size: 18px; }
  .alerts-workspace { display: grid; grid-template-columns: minmax(0, 1fr) 296px; gap: 20px; align-items: start; }
  /* 空记录时主卡跟随侧栏高度，内容区吸收余量，底部说明始终贴近卡片底部。 */
  #desktopEvents { display: flex; flex-direction: column; align-self: stretch; min-width: 0; padding: 24px; margin: 0; border-radius: 18px; }
  #desktopEvents .events-head { display: flex; flex-direction: column; align-items: stretch; gap: 18px; }
  .alert-list-heading { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
  .alert-list-heading h3 { margin: 0; font-size: var(--fs-section); color: var(--desk-ink); }
  .alert-list-heading span { font-size: var(--fs-caption); font-weight: 400; color: var(--text-sec); }
  #desktopEvents .desktop-alert-tabs { width: fit-content; max-width: 100%; flex-basis: auto; flex-wrap: wrap; gap: 3px; border-radius: 10px; padding: 4px; }
  #desktopEvents .desktop-alert-tabs button { flex: none; padding: 7px 11px; min-height: 36px; font-size: var(--fs-body); border-radius: 8px; }
  #desktopEvents .desktop-alert-tabs b { font-size: var(--fs-caption); }
  #desktopEvents .events-filter { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; padding: 16px 0; margin: 0; border-bottom: 1px solid var(--desk-line); }
  .alert-filter-label { color: var(--text-sec); font-size: var(--fs-caption); }
  #desktopEvents .abn-filter { flex: 0 1 180px; min-width: 0; min-height: 36px; font-size: var(--fs-body); }
  #desktopEvents .events-list { max-height: none; overflow: visible; }
  #desktopEvents .ev.ev-empty { flex: 1 0 auto; min-height: 280px; justify-content: center; align-items: center; gap: 10px; padding: 28px 20px; }
  #desktopEvents .ev-empty-icon { position: relative; width: 88px; height: 88px; border: 1px solid var(--desk-line); border-radius: 28px; color: var(--desk-link); background: var(--desk-soft); margin: 0 0 6px; box-shadow: 0 0 0 9px color-mix(in srgb, var(--desk-soft) 45%, transparent); }
  #desktopEvents .ev-empty-icon .ui-icon { width: 42px; height: 42px; }
  #desktopEvents .ev-empty[data-state="offline"] .ev-empty-icon,
  #desktopEvents .ev-empty[data-state="error"] .ev-empty-icon { color: var(--warn-text); background: var(--warn-bg); }
  #desktopEvents .ev-empty strong { font-size: var(--fs-card); font-weight: 600; line-height: 1.6; }
  #desktopEvents .ev-empty small { max-width: 390px; font-size: var(--fs-caption); color: var(--text-sec); line-height: 1.8; }
  #desktopEvents .empty-action { min-height: 38px; padding: 6px 16px; margin-top: 4px; font-size: var(--fs-body); color: var(--desk-link); background: var(--desk-soft); border-color: var(--desk-line); border-radius: 9px; }
  #desktopEvents .events-foot { margin-top: 12px; padding-top: 14px; font-size: var(--fs-caption); color: var(--text-sec); }
  #desktopEvents .ev-manage { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; grid-template-areas: "time tag status" "message message message" "actions actions actions" "note note note"; gap: 8px 12px; padding: 16px 0; align-items: center; }
  #desktopEvents .ev-manage .ev-time { grid-area: time; width: auto; }
  #desktopEvents .ev-manage .ev-tag { grid-area: tag; justify-self: start; font-size: var(--fs-micro); padding: 3px 8px; }
  #desktopEvents .ev-manage .ev-status { grid-area: status; margin: 0; font-size: var(--fs-micro); }
  #desktopEvents .ev-msg { grid-area: message; width: auto; font-size: var(--fs-body); line-height: 1.7; white-space: normal; }
  #desktopEvents .ev-manage .ev-actions { grid-area: actions; width: auto; margin: 0; justify-self: end; flex-wrap: wrap; }
  #desktopEvents .ev-manage .ev-note { grid-area: note; margin: 0; white-space: normal; overflow-wrap: anywhere; }
  #desktopEvents .ev-actions { flex-wrap: wrap; }
  #desktopEvents .ev-time, #desktopEvents .ev-btn { font-size: var(--fs-caption); }
  #desktopEvents .ev-btn { min-height: 34px; }
  #alertPager[hidden] { display: none; }
  .alerts-aside { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
  .alerts-aside .desk-card { padding: 20px; border-radius: 16px; background: color-mix(in srgb, var(--desk-soft) 40%, var(--desk-surface)); }
  .alert-aside-heading { display: flex; align-items: center; gap: 10px; }
  .alert-aside-heading .desk-stat-ico { width: 34px; height: 34px; border-radius: 10px; }
  .alert-aside-heading h3 { margin: 0; font-size: var(--fs-section); }
  .alert-source-name { margin: 16px 0 8px; font-size: var(--fs-card); font-weight: 600; overflow-wrap: anywhere; }
  .alert-source-facts { margin: 0; }
  .alert-source-facts > div { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; padding: 9px 0; border-bottom: 1px solid var(--desk-line); }
  .alert-source-facts dt { flex: none; font-size: var(--fs-caption); color: var(--text-sec); }
  .alert-source-facts dd { margin: 0; font-size: var(--fs-caption); text-align: right; overflow-wrap: anywhere; }
  .alert-source-facts [data-tone="ok"] { color: var(--ok-text); }
  .alert-source-facts [data-tone="muted"] { color: var(--text-sec); }
  .alert-source-note { margin: 14px 0 6px; color: var(--text-sec); font-size: var(--fs-caption); line-height: 1.8; }
  .alerts-aside .text-action { min-height: 36px; font-size: var(--fs-body); color: var(--desk-link); }
  .alert-guide summary { display: flex; align-items: center; justify-content: space-between; cursor: pointer; font-size: var(--fs-card); font-weight: 600; list-style: none; }
  .alert-guide summary::-webkit-details-marker { display: none; }
  .alert-guide[open] summary span { transform: rotate(180deg); }
  .alert-guide-body > div { margin-top: 12px; }
  .alert-guide-body b { font-size: var(--fs-card); }
  .alert-guide-body p { font-size: var(--fs-body); color: var(--text-sec); line-height: 1.8; margin: 4px 0 0; }
  .alert-guide-body > .text-action { margin-top: 10px; }
}
@media (min-width: 769px) and (max-width: 1199px) {
  .alerts-workspace { grid-template-columns: minmax(0, 1fr); }
  .alerts-aside { display: grid; grid-template-columns: 1fr 1fr; align-items: start; }
  .alert-stat-card { padding: 14px; gap: 10px; }
  .alert-stat-arrow { display: none; }
  .device-connection .chain-nodes { gap: 18px; }
}
@media (min-width: 769px) and (max-width: 1023px) {
  #deskPageAlerts .desk-stat-row { grid-template-columns: 1fr; gap: 10px; }
  .alert-stat-card { min-height: 88px; }
  .alert-stat-card .desk-stat-body { display: grid; grid-template-columns: auto auto 1fr; align-items: baseline; gap: 0 7px; width: 100%; }
  .alert-stat-card .desk-stat-body small { grid-column: 1 / -1; }
  .alert-stat-hint { grid-column: 3; }
  .alert-stat-card .desk-stat-unit { margin: 0; }
  .device-connection .chain-nodes { grid-template-columns: 1fr 1fr; gap: 22px; }
  .device-connection .chain-node::after { display: none; }
  .connection-evidence, .alerts-aside { grid-template-columns: 1fr; }
  .connection-details summary span { display: block; margin: 8px 0 0; }
}
/* v13.2 首页：两张完整比例的趋势卡与设备/事件侧栏。 */
@media (min-width: 769px) {
  #deskPageHome { gap: 20px; }
  .home-workspace { display: grid; grid-template-columns: minmax(0, 1fr) 296px; gap: 20px; align-items: stretch; }
  .home-trend-panel { padding: 22px; min-width: 0; display: flex; flex-direction: column; }
  .home-panel-heading { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 12px; }
  .home-panel-heading h2 { margin: 0; font-size: var(--fs-section); color: var(--desk-ink); }
  .home-panel-heading p { margin: 7px 0 0; font-size: var(--fs-caption); color: var(--text-sec); line-height: 1.7; }
  .home-panel-heading .range-bar { margin-left: auto; flex: none; }
  .home-panel-heading .range-btn { min-height: 36px; font-size: var(--fs-body); }
  /* 日报卡片头的范围分段：复用首页 range-bar 控件语言（分段外观来自 1651 块的
     .range-bar 桌面覆盖）。head 是 space-between，中段 margin-left:auto 把
     「分段 + 夜间入口」归拢到右侧；align-items:center 对齐 h2 与胶囊条。 */
  .daily-list-card .desk-card-head { align-items: center; flex-wrap: wrap; }
  .daily-list-card .range-bar { margin-left: auto; flex: none; }
  .daily-list-card .range-btn { min-height: 36px; }
  .home-metric-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; margin-top: 22px; flex: 1; }
  .home-metric-card { min-width: 0; padding: 18px 12px 16px; border: 1px solid var(--desk-line); border-radius: 14px; background: var(--desk-surface); display: flex; flex-direction: column; }
  .home-metric-heading { display: flex; align-items: center; gap: 10px; padding: 0 4px; }
  .home-metric-heading h3 { font-size: var(--fs-card); margin: 0; }
  .home-metric-heading .metric-icon { width: 36px; height: 36px; border-radius: 12px; flex: none; }
  .home-metric-kind { font-size: var(--fs-caption); color: var(--text-sec); margin-left: auto; }
  .home-metric-value { display: flex; align-items: baseline; gap: 5px; margin: 14px 4px 0; }
  .home-metric-value b { font-size: var(--fs-num-lg); line-height: 1.2; font-weight: 600; font-variant-numeric: tabular-nums; color: var(--desk-ink); }
  .home-metric-card:first-child .home-metric-value b { color: var(--hr); }
  .home-metric-value span { font-size: var(--fs-caption); color: var(--text-sec); }
  .home-metric-value small { margin-left: auto; font-size: var(--fs-caption); color: var(--text-sec); }
  .home-metric-fresh { margin: 8px 4px 22px; font-size: var(--fs-caption); color: var(--text-sec); }
  canvas.home-trend-canvas { display: block; width: 100%; height: 230px; flex: none; }
  .home-reference { margin: 8px 4px 16px; font-size: var(--fs-caption); color: var(--text-sec); display: flex; align-items: center; gap: 6px; }
  .home-reference > span { width: 12px; height: 7px; border: 1px solid var(--brand-mint); border-radius: 2px; background: color-mix(in srgb, var(--brand-mint) 13%, transparent); }
  .home-metric-stats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); padding-top: 14px; margin-top: auto; border-top: 1px solid var(--desk-line); }
  .home-metric-stats > div { text-align: center; border-right: 1px solid var(--desk-line); }
  .home-metric-stats > div:last-child { border: 0; }
  .home-metric-stats span { display: block; font-size: var(--fs-caption); color: var(--text-sec); }
  .home-metric-stats b { display: block; margin-top: 7px; font-size: var(--fs-num-sm); font-weight: 500; font-variant-numeric: tabular-nums; }
  .home-trend-footer { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; padding-top: 12px; font-size: var(--fs-caption); color: var(--text-sec); }
  .home-summary { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
  .home-summary .desk-card { padding: 20px; }
  .home-summary .home-panel-heading h2 { font-size: var(--fs-section); }
  .home-summary .text-action, .home-trend-footer .text-action { color: var(--desk-link); font-size: var(--fs-caption); }
  .home-device-row { display: flex; align-items: center; gap: 10px; padding: 14px 0; margin-top: 5px; }
  .home-device-row > div { flex: 1; min-width: 0; overflow-wrap: anywhere; }
  .home-device-row b { font-size: var(--fs-card); }
  .home-device-row small { display: block; margin-top: 5px; color: var(--text-sec); font-size: var(--fs-caption); }
  #homeDeviceState { font-size: var(--fs-caption); flex: none; color: var(--text-sec); }
  #homeDeviceState[data-tone="warn"] { color: var(--warn-text); }
  #homeDeviceState[data-tone="ok"] { color: var(--ok-text); }
  .home-device-seen { margin: 0 0 8px; color: var(--text-sec); font-size: var(--fs-caption); }
  .home-events-card { flex: 1; }
  .home-event-counts { display: flex; flex-wrap: wrap; gap: 10px; padding: 14px 0; border-bottom: 1px solid var(--desk-line); }
  .home-event-counts > span { border-radius: 8px; padding: 7px 9px; background: var(--desk-soft); font-size: var(--fs-caption); color: var(--text-sec); }
  .home-event-counts b { margin-left: 5px; color: var(--desk-ink); }
  .home-event-counts small { margin-left: 5px; font-size: var(--fs-micro); }
  .home-events-empty { text-align: center; display: flex; align-items: center; flex-direction: column; padding: 24px 0 12px; }
  .home-events-empty .ui-icon { width: 36px; height: 36px; color: var(--text-sec); margin-bottom: 14px; }
  .home-events-empty b { font-size: var(--fs-card); line-height: 1.7; font-weight: 500; }
  .home-events-empty p, .home-events-note { margin: 7px 0 0; font-size: var(--fs-caption); color: var(--text-sec); line-height: 1.8; }
  .home-event-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; width: 100%; text-align: left; padding: 14px 0; border: 0; border-bottom: 1px solid var(--desk-line); background: transparent; color: var(--text); cursor: pointer; }
  .home-event-row b { font-size: var(--fs-card); font-weight: 500; }
  .home-event-row small { display: block; margin-top: 5px; font-size: var(--fs-caption); color: var(--text-sec); }
  .home-event-row > span:last-child { font-size: var(--fs-caption); color: var(--desk-link); flex: none; }
  .home-care-note { display: flex; align-items: center; gap: 12px; padding: 12px 8px; color: var(--desk-link); }
  .home-care-note svg { width: 88px; height: 70px; flex: none; }
  .home-care-note b { font-size: var(--fs-card); font-weight: 500; }
  .home-care-note p { margin: 7px 0 0; font-size: var(--fs-caption); line-height: 1.8; color: var(--text-sec); }
  #deskPageHome #deskHomeActions { margin: 0; }
  #deskPageHome :is(button):focus-visible { outline: 2px solid var(--desk-link); outline-offset: 3px; }
}
@media (min-width: 769px) and (max-width: 1199px) {
  .home-workspace { grid-template-columns: minmax(0, 1fr); }
  .home-summary { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .home-care-note { grid-column: 1 / -1; justify-content: center; }
  #deskPageHome .desk-quick-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 769px) and (max-width: 959px) {
  .home-metric-grid, .home-summary { grid-template-columns: minmax(0, 1fr); }
  .home-trend-panel { padding: 18px; }
}
@media (max-width:768px) {
  #mobileAlertFilter { grid-template-columns:repeat(4,minmax(0,1fr)); }
  #mobileAlertFilter button { padding:6px 3px; font-size:11px; }
  .mobile-sync-note { font-size:12px; color:var(--text-sec); line-height:1.7; margin:12px 0; }
  .mobile-more-events { width:100%; min-height:44px; border:1px solid var(--desk-line); border-radius:10px; background:var(--desk-soft); color:var(--desk-link); margin-top:12px; }
  .mobile-more-events[hidden] { display:none; }
  .mobile-event-help, .mobile-diagnostic-details { margin-top:16px; border-top:1px solid var(--desk-line); padding-top:12px; font-size:13px; }
  .mobile-event-help summary, .mobile-diagnostic-details summary { min-height:36px; cursor:pointer; color:var(--desk-link); }
  .mobile-event-help p, .mobile-diagnostic-details p { line-height:1.8; font-size:12px; color:var(--text-sec); }
  .mobile-diagnostic-details h3 { font-size:14px; }
  .mobile-run-diag { width:100%; margin-top:12px; }
  .m-abn-empty strong { display:block; font-size:13px; font-weight:500; }
  .m-abn-empty p { margin:8px 0; font-size:12px; line-height:1.8; }
  .m-abn-row { flex-wrap:wrap; }
  .m-abn-btn { min-height:40px; }
  .alert-detail-card { width:calc(100vw - 32px); max-height:calc(var(--dialog-viewport-height,100dvh) - 32px); overflow:auto; }
  .alert-detail-actions { display:flex; flex-wrap:wrap; gap:10px; }
  .alert-detail-actions button { min-height:44px; }
  .alert-detail-card .desk-kv { display:flex; justify-content:space-between; gap:16px; padding:10px 0; border-bottom:1px solid var(--desk-line); font-size:13px; }
  .alert-detail-card .desk-kv b { overflow-wrap:anywhere; text-align:right; }
}
.alert-note-editor { display:block; flex-basis:100%; width:100%; font-size: var(--fs-body); }
.alert-note-editor textarea { display:block; width:100%; margin:8px 0; padding:12px; border:1px solid var(--desk-line); border-radius:10px; color:var(--text); background:var(--desk-surface); font:inherit; resize:vertical; }

/* Mobile device selection: original selects remain the business source of truth. */
.mobile-device-trigger, .mobile-device-empty[hidden], #mDeviceList[hidden] { display:none; }
.mobile-device-sheet:not([open]) { display:none; }
@media (max-width:768px) {
  .current-device .mobile-device-native { display:none; }
  .mobile-device-current { padding:0 16px 16px; margin:0 0 18px; border:1px solid var(--desk-line); border-radius:22px; background:var(--desk-surface); box-shadow:var(--card-shadow); overflow:hidden; }
  .mobile-device-current .current-device { margin:0; padding:10px 0; border:0; border-bottom:1px solid var(--desk-line); border-radius:0; min-height:66px; }
  .mobile-device-current .current-device > span { font-size:13px; color:var(--text); font-weight:600; }
  .mobile-device-current .m-device-list { margin:0; padding:8px 0; }
  .mobile-device-current .m-device-item { padding:14px 0; margin:0; border:0; border-bottom:1px solid var(--desk-line); border-radius:0; box-shadow:none; background:transparent; }
  .mobile-device-current .m-device-item:last-child { border-bottom:0; }
  .mobile-device-current .sn-access-entry { width:100%; margin:0; padding:14px 12px; gap:10px; border:1px solid var(--desk-line); border-radius:14px; background:var(--desk-soft); box-shadow:none; }
  .mobile-device-current .sn-entry-icon { width:36px; height:40px; border-radius:11px; }
  .mobile-device-current .sn-access-entry strong { font-size:13px; }
  .mobile-device-current .sn-access-entry small { font-size:11px; line-height:1.7; }
  .mobile-device-empty { display:flex; align-items:center; flex-direction:column; text-align:center; padding:26px 8px 22px; }
  .mobile-empty-icon { position:relative; display:grid; place-items:center; width:68px; height:68px; border:1px solid var(--desk-line); border-radius:23px; background:var(--br-soft); color:var(--desk-link); margin-bottom:16px; }
  .mobile-empty-icon > .ui-icon { width:34px; height:34px; }
  .mobile-empty-icon > .mobile-empty-shield { position:absolute; right:-8px; bottom:-5px; width:28px; height:28px; padding:5px; border-radius:10px; background:var(--desk-surface); box-shadow:0 2px 8px #123e4810; }
  .mobile-device-empty h3 { margin:0; font-size:16px; line-height:1.6; }
  .mobile-device-empty p { margin:8px 0 18px; color:var(--text-sec); font-size:12px; line-height:1.8; }
  .mobile-device-empty .primary-action { display:flex; align-items:center; justify-content:center; gap:8px; min-height:44px; padding:10px 20px; border-radius:12px; font-size:13px; }
  .mobile-device-trigger { display:flex; align-items:center; justify-content:flex-end; flex:1; gap:8px; min-width:0; min-height:44px; padding:6px 0 6px 6px; border:0; border-radius:8px; background:transparent; color:var(--text); text-align:right; cursor:pointer; font-family:inherit; font-size:13px; font-weight:500; line-height:1.6; }
  .mobile-device-trigger > span { min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .mobile-device-trigger > .ui-icon { flex:none; width:16px; height:16px; transform:rotate(90deg); color:var(--desk-link); }
  .mobile-device-trigger:disabled { color:var(--text-sec); cursor:default; }
  .mobile-device-trigger:disabled > .ui-icon { visibility:hidden; }
  .mobile-device-trigger:not(:disabled):active { background:var(--desk-soft); }

  .mobile-device-sheet { position:fixed; inset:auto 0 0; width:100%; max-width:560px; margin:0 auto; max-height:calc(var(--dialog-viewport-height,100dvh) - 16px); padding:0; border:1px solid var(--desk-line); border-bottom:0; border-radius:26px 26px 0 0; background:var(--desk-surface); color:var(--text); box-shadow:0 -12px 48px #00000024; overflow:hidden; }
  .mobile-device-sheet[open] { display:flex; flex-direction:column; animation:mobile-sheet-enter .18s ease-out; }
  .mobile-device-sheet::backdrop { background:var(--mask); backdrop-filter:blur(3px); }
  .mobile-sheet-handle { flex:none; width:34px; height:4px; border-radius:4px; background:var(--desk-line); margin:10px auto 8px; }
  .mobile-sheet-head { display:flex; align-items:center; gap:12px; padding:8px 20px 0; flex:none; }
  .mobile-sheet-icon, .mobile-option-icon { display:grid; place-items:center; flex:none; width:42px; height:46px; border-radius:14px; background:var(--br-soft); color:var(--desk-link); }
  .mobile-sheet-head > div { min-width:0; flex:1; }
  .mobile-sheet-head h2 { font-size:19px; line-height:1.5; margin:0; }
  .mobile-sheet-head p { margin:3px 0 0; color:var(--text-sec); font-size:12px; }
  .mobile-sheet-head .bind-close { flex:none; margin:0; min-width:44px; min-height:44px; border:1px solid var(--desk-line); border-radius:50%; background:var(--desk-soft); color:var(--text-sec); font-size:25px; }
  #mobileDeviceSheetHint { flex:none; margin:14px 20px; color:var(--text-sec); font-size:12px; line-height:1.8; }
  .mobile-device-options { min-height:0; overflow-y:auto; overscroll-behavior:contain; padding:3px 20px 12px; scroll-padding-block:8px; }
  .mobile-device-option { display:flex; align-items:center; gap:12px; padding:14px 12px; margin-bottom:10px; min-height:92px; border:1px solid var(--desk-line); border-radius:16px; background:var(--desk-surface); cursor:pointer; }
  .mobile-device-option:last-child { margin-bottom:0; }
  .mobile-device-option[aria-selected="true"] { border-color:var(--br); background:var(--br-soft); }
  .mobile-device-option:focus-visible { outline:2px solid var(--desk-link); outline-offset:1px; }
  .mobile-device-option[aria-disabled="true"] { opacity:.55; cursor:not-allowed; }
  .mobile-option-copy { min-width:0; flex:1; overflow-wrap:anywhere; }
  .mobile-option-copy strong { display:block; font-size:14px; font-weight:600; line-height:1.6; }
  .mobile-option-sn { display:block; color:var(--text-sec); font-size:11px; line-height:1.8; }
  .mobile-option-meta { display:flex; flex-wrap:wrap; align-items:center; gap:3px 10px; margin-top:5px; font-size:11px; line-height:1.6; }
  .mobile-option-state { color:var(--text-sec); }
  .mobile-option-state::before { content:""; display:inline-block; vertical-align:middle; width:6px; height:6px; border-radius:50%; background:currentColor; margin-right:5px; }
  .mobile-option-state[data-tone="online"] { color:var(--ok-text); }
  .mobile-option-state[data-tone="offline"] { color:var(--warn-text); }
  .mobile-option-seen { color:var(--text-sec); font-size:11px; }
  .mobile-option-check { display:grid; place-items:center; flex:none; width:23px; height:23px; border:1px solid var(--desk-line); border-radius:50%; color:transparent; background:var(--desk-surface); }
  .mobile-option-check .ui-icon { width:16px; height:16px; }
  [aria-selected="true"] > .mobile-option-check { color:var(--desk-surface); background:var(--desk-link); border-color:var(--desk-link); }
  .mobile-sheet-footer { flex:none; padding:12px 20px calc(16px + env(safe-area-inset-bottom)); border-top:1px solid var(--desk-line); background:var(--desk-surface); }
  .mobile-sheet-footer button { display:flex; align-items:center; justify-content:center; gap:9px; width:100%; min-height:46px; border:1px solid var(--desk-line); border-radius:13px; background:var(--desk-soft); color:var(--desk-link); font-size:13px; font-weight:600; }
  .mobile-sheet-footer button .ui-icon:last-child { width:16px; }

  /* Keep existing shared mobile dialogs visually consistent without changing their workflows. */
  .dlg-card { overscroll-behavior:contain; }
  .dlg-card .guide-head { gap:12px; align-items:flex-start; }
  .dlg-card .guide-head > div { min-width:0; }
  .dlg-card .guide-head h2, .dlg-card .dlg-title { font-size:20px; line-height:1.5; overflow-wrap:anywhere; }
  .dlg-card .bind-close { flex:none; min-width:44px; min-height:44px; border-radius:50%; }
  .dlg-card :is(.bind-input, .sn-input, textarea) { font-size:16px; }
  .dlg-card .guide-head + p { line-height:1.8; }
  .alert-detail-card { width:100%; }
}
@media (max-width:360px) {
  .mobile-device-current { padding-inline:12px; }
  .mobile-device-current .current-device { gap:6px; }
  .mobile-device-current .current-device > span { font-size:12px; }
  .mobile-device-trigger { font-size:12px; }
  .mobile-sheet-head { gap:9px; padding-inline:16px; }
  .mobile-sheet-head h2 { font-size:18px; }
  .mobile-device-options { padding-inline:16px; }
  .mobile-device-option { gap:9px; padding:12px 10px; }
  .mobile-option-icon { width:34px; height:40px; }
  .mobile-sheet-footer { padding-inline:16px; }
}
@keyframes mobile-sheet-enter { from { opacity:0; transform:translateY(16px); } to { opacity:1; transform:translateY(0); } }
@media (prefers-reduced-motion:reduce) { .mobile-device-sheet[open] { animation:none; } }

/* BLE communication is distinct from cloud diagnostics; keep raw errors readable. */
.ble-mon { max-height:none; overflow:visible; }
.ble-mon > summary { min-height:44px; padding:13px 22px; font-size: var(--fs-card); font-weight:600; }
.ble-mon > summary span { font-size: var(--fs-caption); font-weight:400; }
.ble-mon-note { margin:0; padding:0 22px 4px; font-size: var(--fs-body); line-height:1.75; color:var(--text-sec); }
.ble-mon-head { padding:4px 22px; gap:10px; }
.ble-mon-title { flex-wrap:wrap; font-size: var(--fs-card); }
.ble-mon-clear { min-height:36px; padding:6px 8px; font-size: var(--fs-body); flex:none; }
.ble-mon .ble-mon-list { max-height:clamp(100px,23dvh,240px); min-height:0; padding:0 16px 12px; gap:7px; overscroll-behavior:contain; font-size: var(--fs-caption); line-height:1.7; }
.ble-mon .ble-frame { display:grid; grid-template-columns:max-content minmax(0,1fr); align-items:start; gap:4px 12px; flex:none; padding:10px 12px; border:1px solid var(--desk-line); border-radius:10px; background:var(--desk-surface); font-style:normal; word-break:normal; }
.ble-mon .ble-frame.errf { background:color-mix(in srgb, var(--err) 9%, var(--desk-surface)); }
.ble-mon .ble-frame.hl { background:color-mix(in srgb, var(--ok) 8%, var(--desk-surface)); }
.ble-mon .bf-time { grid-column:1; font-size: var(--fs-caption); font-variant-numeric:tabular-nums; color:var(--text-sec); }
.ble-mon .bf-dir { grid-column:2; font-size: var(--fs-caption); }
.ble-mon .bf-data { grid-column:1 / -1; min-width:0; white-space:pre-wrap; overflow-wrap:anywhere; color:var(--text); }
@media (max-width:768px) {
  .ble-mon > summary { padding-inline:18px; }
  .ble-mon-note { padding-inline:18px; }
  .ble-mon-head { padding-inline:18px; }
  .ble-mon .ble-mon-list { max-height:clamp(90px,19dvh,170px); padding-inline:12px; padding-bottom:calc(12px + env(safe-area-inset-bottom)); }
}
/* 13.5 Mobile help reuses the desktop content node and all business handlers. */
.m-help { display:none; }
.mobile-help-entry { display:none; }
@media (min-width:769px) { #mHelp { display:none !important; } }
@media (max-width:768px) {
  .mobile-help-entry { width:100%; display:flex; align-items:center; gap:13px; text-align:left; font-family:inherit; color:var(--text); cursor:pointer; }
  .mobile-help-entry > span:nth-child(2) { flex:1; min-width:0; }
  .mobile-help-entry strong { display:block; font-size:15px; }
  .mobile-help-entry small { display:block; margin-top:6px; font-size:12px; color:var(--text-sec); line-height:1.6; }
  .mobile-help-entry > .ui-icon { width:18px; height:18px; color:var(--desk-link); flex:none; }
  .mobile-help-entry .help-entry-ico { display:grid; place-items:center; width:44px; height:48px; border-radius:14px; background:var(--br-soft); color:var(--desk-link); flex:none; }
  .mobile-help-entry .help-entry-ico .ui-icon { width:24px; height:24px; }
  #mHelp { padding:8px 18px calc(104px + env(safe-area-inset-bottom)); }
  .m-help-head { padding:0 0 22px; }
  .m-help-back { display:flex; align-items:center; gap:8px; min-height:44px; padding:8px 0; margin-bottom:14px; border:0; background:transparent; color:var(--desk-link); font:inherit; font-size:14px; cursor:pointer; }
  .m-help-back .ui-icon { width:18px; height:18px; transform:rotate(180deg); }
  #mHelpTitle { margin:5px 0 0; font-size:28px; line-height:1.4; color:var(--desk-ink); }
  #mHelpTitle:focus { outline:none; }
  #mHelp #deskPageHelp { display:flex; flex-direction:column; gap:16px; }
  #mHelp .desk-page-head { display:none; }
  #mHelp .desk-card { min-width:0; margin:0; border:1px solid var(--desk-line); border-radius:19px; background:var(--desk-surface); padding:18px; box-shadow:var(--card-shadow); }
  #mHelp .desk-card-head { display:flex; flex-direction:column; gap:12px; margin-bottom:16px; }
  #mHelp .desk-card-head h2 { margin:0; font-size:18px; color:var(--desk-ink); }
  #mHelp .help-search { display:flex; gap:8px; align-items:center; }
  #mHelp .help-search > .ui-icon { display:none; }
  #mHelp .help-search input { flex:1; width:100%; min-width:0; min-height:46px; padding:10px; border:1px solid var(--desk-line); border-radius:12px; background:var(--desk-soft); color:var(--text); font:inherit; font-size:16px; }
  #mHelp .help-search input::placeholder { color:var(--text-sec); }
  #mHelp .help-search .primary-action { min-height:46px; padding:0 12px; flex:none; }
  #mHelp .help-hot { display:flex; align-items:center; flex-wrap:wrap; gap:6px; margin-top:12px; font-size:12px; color:var(--text-sec); }
  #mHelp .help-hot > span { width:100%; }
  #mHelp .help-hot button, #mHelp .help-cats button { min-height:40px; padding:8px 11px; border:1px solid var(--desk-line); border-radius:10px; color:var(--text-sec); background:var(--desk-soft); font:inherit; font-size:12px; cursor:pointer; }
  #mHelp .help-search-result { font-size:12px; color:var(--desk-link); line-height:1.8; margin:12px 0 0; overflow-wrap:anywhere; }
  /* 13.5.1 手机端四入口卡提到搜索栏上面（FAQ 反馈不被推到屏幕外） */
  #mHelp .desk-help-grid { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:12px; order:-1; }
  #mHelp .help-entry { display:flex; flex-direction:column; gap:8px; padding:16px; text-align:left; font:inherit; cursor:pointer; }
  #mHelp .help-entry-ico { width:36px; height:40px; display:grid; place-items:center; border-radius:12px; color:var(--desk-link); background:var(--br-soft); }
  #mHelp .help-entry-ico .ui-icon { width:20px; height:20px; }
  #mHelp .help-entry h3 { margin:2px 0 0; color:var(--desk-ink); font-size:15px; }
  #mHelp .help-entry p { flex:1; margin:0; color:var(--text-sec); font-size:12px; line-height:1.8; }
  #mHelp .help-entry-link { color:var(--desk-link); font-size:12px; }
  #mHelp .desk-help-cols, #mHelp .desk-help-side { display:flex; flex-direction:column; gap:16px; }
  #mHelp .help-cats { display:flex; flex-wrap:wrap; gap:7px; }
  #mHelp .help-cats button.active { color:var(--desk-surface); background:var(--desk-link); border-color:var(--desk-link); }
  #mHelp .help-faq-list { display:flex; flex-direction:column; gap:10px; }
  #mHelp .help-faq-item { min-width:0; border:1px solid var(--desk-line); border-radius:12px; padding:0 13px; background:var(--desk-soft); }
  #mHelp .help-faq-item[hidden], #mHelp [hidden] { display:none !important; }
  #mHelp .help-faq-item summary { display:flex; align-items:center; justify-content:space-between; gap:12px; min-height:52px; padding:12px 0; list-style:none; font-size:14px; font-weight:600; line-height:1.6; color:var(--text); cursor:pointer; }
  #mHelp .help-faq-item summary::-webkit-details-marker { display:none; }
  #mHelp .help-faq-item summary::after { content:"＋"; color:var(--desk-link); flex:none; font-size:18px; font-weight:400; }
  #mHelp .help-faq-item[open] summary::after { content:"－"; }
  #mHelp .help-faq-body { font-size:13px; line-height:1.9; color:var(--text-sec); padding:0 0 12px; overflow-wrap:anywhere; }
  #mHelp .help-faq-body p { margin:0; }
  #mHelp .help-empty { font-size:13px; line-height:1.8; color:var(--text-sec); }
  #mHelp .help-empty p { margin:0 0 8px; }
  #mHelp .desk-kv { display:flex; justify-content:space-between; gap:12px; border-bottom:1px solid var(--desk-line); padding:12px 0; font-size:13px; color:var(--text-sec); }
  #mHelp .desk-kv b { text-align:right; overflow-wrap:anywhere; }
  #mHelp .help-todo { color:var(--warn-text); }
  #mHelp .desk-disclaimer, #mHelp .help-about { margin:12px 0; font-size:12px; line-height:1.9; color:var(--text-sec); }
  #mHelp .help-legal { display:flex; align-items:center; gap:10px; flex-wrap:wrap; color:var(--text-sec); }
  #mHelp .text-action { min-height:44px; font-size:13px; color:var(--desk-link); }
  #mHelp :is(button,input,summary):focus-visible, .mobile-help-entry:focus-visible { outline:2px solid var(--desk-link); outline-offset:3px; }
  .manual-card .manual-sec h3, .legal-pane h3 { font-size:16px; margin:16px 0 8px; }
  .manual-card .manual-list { margin:0; padding-left:20px; font-size:13px; line-height:1.9; color:var(--text-sec); }
  .manual-card .desk-disclaimer, .legal-pane p { font-size:13px; line-height:1.9; color:var(--text-sec); }
  .legal-pane h4 { font-size:14px; margin:14px 0 6px; }
  .legal-pane ul { margin:0 0 10px; padding-left:20px; }
  .legal-pane li { font-size:13px; line-height:1.9; color:var(--text-sec); margin-bottom:6px; }
  .legal-pane .legal-meta { font-size:12px; color:var(--text-mute); }
  .legal-pane a { color:var(--desk-link); text-decoration:underline; overflow-wrap:anywhere; }
  .legal-pane .help-todo, .manual-card .help-todo { color:var(--warn-text); }
}
@media (max-width:360px) {
  #mHelp { padding-inline:12px; }
  #mHelp .desk-card { padding:14px; }
  #mHelp .desk-help-grid { gap:10px; }
  #mHelp .help-entry { padding:14px; }
}

/* ============================================================
   应用内开屏覆盖层（系统闪屏之后的完整品牌稿；明暗随 data-theme）
   Logo 复用 #i-brand 标准标识；加载动画为纯CSS三点跳动。
   ============================================================ */
.app-splash {
  position: fixed; inset: 0; z-index: 9999;
  display: flex; align-items: center; justify-content: center;
  background: linear-gradient(180deg, #E7F3EE 0%, #F6FAF7 55%, #FFFDF8 100%);
  padding-top: env(safe-area-inset-top);
  padding-bottom: env(safe-area-inset-bottom);
  opacity: 1; visibility: visible; transition: opacity var(--dur-splash) var(--ease-enter), visibility var(--dur-splash) var(--ease-enter);
  -webkit-user-select: none; user-select: none;
}
:root[data-theme="dark"] .app-splash {
  background: linear-gradient(180deg, #103F45 0%, #0B2E34 55%, #061E23 100%);
}
.app-splash.is-hidden { opacity: 0; visibility: hidden; }

.app-splash-inner {
  display: flex; flex-direction: column; align-items: center;
  width: 100%; max-width: 420px; padding: 0 24px; margin-top: -7vh;
}

/* Logo 底托：浅色透明（标识直接显示），深色为象牙白圆角卡，避免深色半心融入背景 */
.app-splash-badge {
  display: grid; place-items: center;
  width: 132px; height: 132px; border-radius: 34px; background: transparent;
}
:root[data-theme="dark"] .app-splash-badge {
  width: 150px; height: 150px; background: #FFFDF8;
  box-shadow: 0 18px 42px rgba(0, 0, 0, .38);
}
.app-splash-logo {
  width: 100%; height: 100%; stroke: none;
  animation: splashPop .8s cubic-bezier(.2, .8, .25, 1) both;
}
:root[data-theme="dark"] .app-splash-logo { width: 122px; height: 122px; }
@keyframes splashPop {
  from { opacity: 0; transform: scale(.86); }
  to { opacity: 1; transform: scale(1); }
}

.app-splash-name {
  margin-top: 30px; color: #134D53;
  font-family: "Microsoft YaHei", "PingFang SC", "Noto Sans SC", sans-serif;
  font-size: 38px; font-weight: 700; letter-spacing: 6px;
}
:root[data-theme="dark"] .app-splash-name { color: #FFFFFF; }
.app-splash-slogan {
  margin-top: 12px; color: #6E8D89; font-size: 15px; letter-spacing: 3px;
}
:root[data-theme="dark"] .app-splash-slogan { color: #7FCBB8; }

/* 加载动画：三点依次跳动（柔和，替代静态图里的加载圈） */
.app-splash-loader {
  margin-top: 44px; display: flex; align-items: center; gap: 10px; height: 14px;
}
.app-splash-loader span {
  width: 9px; height: 9px; border-radius: 50%; background: #59BDA6;
  animation: splashBounce 1.1s ease-in-out infinite;
}
.app-splash-loader span:nth-child(2) { animation-delay: .15s; }
.app-splash-loader span:nth-child(3) { animation-delay: .3s; }
:root[data-theme="dark"] .app-splash-loader span { background: #7FCBB8; }
@keyframes splashBounce {
  0%, 100% { transform: translateY(0); opacity: .5; }
  50% { transform: translateY(-7px); opacity: 1; }
}

/* 装饰叶片：极淡椭圆 + 模糊，柔和散落在标识周围，不抢主体 */
.app-splash-deco { position: absolute; inset: 0; overflow: hidden; pointer-events: none; }
.splash-leaf {
  position: absolute; background: #59BDA6; opacity: .12; filter: blur(7px);
  border-radius: 72% 28% 55% 45% / 55% 45% 55% 45%;
}
:root[data-theme="dark"] .splash-leaf { opacity: .10; }
.splash-leaf.l1 { left: 15%; top: 25%; width: 64px; height: 96px; transform: rotate(26deg); }
.splash-leaf.l2 { right: 14%; top: 24%; width: 64px; height: 96px; transform: rotate(-28deg) scaleX(-1); }
.splash-leaf.l3 { left: 21%; top: 41%; width: 46px; height: 70px; transform: rotate(12deg); opacity: .08; }
.splash-leaf.l4 { right: 21%; top: 42%; width: 46px; height: 70px; transform: rotate(-12deg) scaleX(-1); opacity: .08; }

@media (prefers-reduced-motion: reduce) {
  .app-splash-logo, .app-splash-loader span { animation: none; }
}
/* ==========================================================================
   全站统一按压反馈层（0927）
   --------------------------------------------------------------------------
   背景：此前全站 `:active` 仅 13 处，且**全部挂在具体类名上**，没有任何一条
   覆盖"能点的东西"这一整体。后果是同类操作反馈不一致——最刺眼的对照是
   桌面报警条 `.alarm-ack`（无按压）vs 手机 `.m-alarm-ack`（有变色）。

   做法：在文件末尾追加一层**全局按压契约**，用低特异性选择器兜底，
   各组件原有的 `:active` 规则（特异性更高）继续生效、互不冲突。

   三条纪律：
   1. **只加"按下瞬间"的反馈，不改任何既有结果态**（`.active` / `.is-loading`
      / `[disabled]` 等一律不碰），避免回归。
   2. **禁改布局尺寸**：只用 transform/opacity/background 这类不触发 reflow 的属性，
      且 transform 不写 scale 以外的东西，防止网格错位。
   3. **允许 opt-out**：给任意元素加 `data-no-press` 即退出全局契约
      （例如内部已有一套完整动效、再加会打架的组件）。

   特异性的坑（已实测）：`.m-tabbar-item` 自带 `transition: none`（style.css 旧规则），
   它和本层 `transition: transform …` 是**同一特异性**，谁在后面谁赢 ——
   所以本层必须放在文件**最末尾**，并且对这类"自带 transition 的组件"显式补 transition。
   ========================================================================== */

/* —— 1) 通用可点元素：按下轻微下沉 ——
   `button:active` 覆盖面最广；再把本项目的"看起来能点但不是 button"的元素补上。
   注意排除：已禁用的、以及自带完整按压动效的（那些由各自规则处理，特异性更高）。 */
button:not([disabled]):active,
input[type="button"]:not([disabled]):active,
input[type="submit"]:not([disabled]):active,
[role="button"]:not([aria-disabled="true"]):active,
[data-press]:not([data-no-press]):active {
  transform: translateY(var(--press-shift));
}

/* —— 2) 图标型小按钮：按下缩放（位移在小目标上几乎看不见）——
   只挑本项目里明确是"图标钮"的那几个类；不做全局 scale，
   否则大卡片/整行条目会缩得很怪。 */
.theme-btn:not([data-no-press]):active,
.m-back:not([data-no-press]):active,
.bind-close:not([data-no-press]):active,
.dlg-close:not([data-no-press]):active,
.m-help-back:not([data-no-press]):active,
.m-device-more:not([data-no-press]):active {
  transform: scale(var(--press-scale));
}

/* —— 3) 补过渡：按压必须"跟手"，不能"啪"地跳 ——
   ⚠️ 这里**不能用"枚举手写类名清单"**（第一版就是那样，实测立刻漏了 .m-alarm-ack，
      因为它藏在 @media(max-width:768px) 里、桌面视口下根本查不到）。
      改为**按元素类型族**兜底，避免"清单永远补不全"：
      · 所有 button / input 按钮 / role=button / [data-press]
      · 本项目"看起来能点但不是 button"的元素（整行条目、导航项、卡片、链接型入口）
   这些选择器特异性均为 0-1-0 级别，各级组件自身的 transition（特异性更高）依旧优先。 */
button,
input[type="button"],
input[type="submit"],
[role="button"],
[data-press],
.desk-nav-item,
.dev-more,
.dev-add,
.sn-btn-query,
.alarm-ack,
.m-alarm-ack,
.login-code-btn,
.sidebar-logout,
.desktop-logout,
.m-more-events,
.m-card-hr,
.m-card-br,
.sn-btn,
.app-btn,
.app-btn2,
.primary-action,
.dlg-danger,
.dlg-warn,
.bind-primary,
.bind-close,
.dlg-close,
.range-btn,
.desk-quick-item,
.m-refresh-btn,
.m-tab,
.m-tabbar-item,
.m-device-more,
.m-device-item,
.m-back,
.sn-access-entry,
.mobile-chain-link,
.guide-row,
.text-action,
.m-help-back,
.theme-btn,
.m-me-logout,
.m-me-danger,
.sidebar-danger {
  transition: transform var(--dur-press) var(--ease-hover),
              background var(--dur-press) var(--ease-hover),
              color var(--dur-press) var(--ease-hover),
              border-color var(--dur-press) var(--ease-hover),
              opacity var(--dur-press) var(--ease-hover);
}

/* —— 4) 按压时的底色变化：给"没有自身 :active 背景"的组件一个统一反馈 ——
   统一用 --btn-hover（与手机端 `.m-alarm-ack:active` 同一变量），保证手感一致。 */
.desk-nav-item:not([data-no-press]):active,
.dev-more:not([data-no-press]):active,
.dev-add:not([data-no-press]):active,
.sn-btn-query:not([data-no-press]):active,
.alarm-ack:not([data-no-press]):active,
.login-code-btn:not([data-no-press]):active,
.sn-access-entry:not([data-no-press]):active,
.mobile-chain-link:not([data-no-press]):active,
.guide-row:not([data-no-press]):active,
.m-tab:not([data-no-press]):active,
.m-more-events:not([data-no-press]):active,
.desktop-logout:not([data-no-press]):active,
.sidebar-logout:not([data-no-press]):active,
.m-me-danger:not([data-no-press]):active,
.sidebar-danger:not([data-no-press]):active,
.m-help-back:not([data-no-press]):active,
.text-action:not([data-no-press]):active,
.range-btn:not([data-no-press]):active {
  background: var(--btn-hover);
}

/* —— 5) 整行/整卡型可点条目：按下轻微缩放（位移在满宽元素上像"抖动"）—— */
.m-device-item:not([data-no-press]):active,
.desk-quick-item:not([data-no-press]):active,
.m-card-hr:not([data-no-press]):active,
.m-card-br:not([data-no-press]):active,
.sn-access-entry:not([data-no-press]):active {
  transform: scale(.995);
}

/* —— 6) 底部 tab：自身 `transition:none` 会吃掉本层过渡，单独显式声明 ——
   （放在最后，确保覆盖住早前那条 `transition: none`） */
.m-tabbar-item:not([data-no-press]):active {
  transform: translateY(var(--press-shift));
  transition: transform var(--dur-press) var(--ease-hover),
              color var(--dur-press) var(--ease-hover);
}

/* —— 7) 尊重系统"减少动态效果"：关掉按压位移，只保留底色反馈 —— */
@media (prefers-reduced-motion: reduce) {
  button:active, [role="button"]:active, [data-press]:active,
  .theme-btn:active, .m-back:active, .bind-close:active,
  .m-tabbar-item:active, .m-device-item:active,
  .m-card-hr:active, .m-card-br:active, .desk-quick-item:active,
  .sn-access-entry:active {
    transform: none;
  }
}

/* ---- 「有待处理」卡可点提示（2026-10-02）----
   只在真有待处理时（JS 挂上 data-jump-pending）出现。箭头**用纯 CSS 画**
   （border 旋转 45°，不新增 DOM、不用 Unicode 图标 —— 本仓图标一律内联 SVG 或纯 CSS）。
   按压反馈不用另写：role="button" 已落入全站通用 :active 契约。 */
.m-status-banner[data-jump-pending],
.overview-status[data-jump-pending] { cursor: pointer; }
.m-status-banner[data-jump-pending]::after,
.overview-status[data-jump-pending]::after {
  content: ""; flex: 0 0 auto; width: 6px; height: 6px; margin-left: 2px;
  border-right: 1.6px solid currentColor; border-bottom: 1.6px solid currentColor;
  transform: rotate(-45deg); opacity: 0.7;
}

/* ---- 自绘蓝牙设备列表（2026-10-02）----
   为什么要自绘：手机壳里 requestDevice 必然弹**插件原生 AlertDialog**（白底 + 全大写
   CANCEL + 英文），它不在 WebView 的 DOM 内 ⇒ 样式改不了。改用插件无弹窗的扫描通道
   （requestLEScan）自己画列表，才谈得上"美化"。
   行本身复用既有的 .bind-list/.bind-item（原本是孤儿 CSS，正好用上）；这里只补
   "作为按钮用"需要的复位与右侧信号标签。 */
button.bind-item { width: 100%; font: inherit; color: inherit; text-align: left; }
.bind-item .bind-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bind-item .bind-sig { flex: 0 0 auto; font-size: var(--fs-caption); color: var(--text-sec); }
.bind-list:not([hidden]) { margin-top: 10px; }

/* ==========================================================================
   App 内更新提示条（0927）
   --------------------------------------------------------------------------
   仅在"远端 version > 本地 version"时出现，由 app-update.js 驱动。
   ⚠️ 收起态**不用 display:none**（同告警条的教训：display:none 会让 transition
   无起始值直接硬跳）。改用 max-height + padding + border-width 归零，
   保证展开/收起都能真正插值。默认隐藏，加 .show 才展开。
   ========================================================================== */
.app-update-bar {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  max-height: 0; padding: 0 14px; border-width: 0; overflow: hidden;
  margin-bottom: 0;
  border-style: solid; border-radius: 12px;
  background: var(--ok-bg); color: var(--text);
  transition: max-height 0.28s var(--ease-enter), padding 0.28s var(--ease-enter),
              border-width 0.28s var(--ease-enter), margin-bottom 0.28s var(--ease-enter),
              opacity 0.28s var(--ease-enter);
  opacity: 0;
  /* 0947 修复：本元素是 main#app 的直接子级（**不在** .desk-content 内，
     否则 ≤768px 被 display:none!important 连带隐藏 ⇒ 手机永远看不到）。
     用 position:relative 保证它参与正常文档流，不遮挡下方内容。 */
  position: relative;
  z-index: 1;
}
/* 🔴 max-height 是**为动画存在**的，不是内容上限 —— 一旦内容超过它，
   `overflow:hidden` 会把超出的部分（**包括「立即更新/稍后」整排按钮**）一起裁掉。
   0.6.2 事故：notes 变长到 212px 而这里只有 140px，实测按钮被裁到可视区外 62px
   ⇒ 用户看得见"发现新版本"，却没有任何可点的入口（真机反馈"没法更新"）。
   真正的保险是下面 .app-update-text **自己限高可滚**，这里的值只是兜底：
   必须同时容下 文本上限 + 动作行 + 提示行。 */
.app-update-bar.show {
  max-height: 160px; padding: 11px 14px; border-width: 1px;
  margin-bottom: 10px; opacity: 1;
}
.app-update-bar > svg { flex: 0 0 auto; color: var(--ok-text); }
.app-update-bar .app-update-text {
  flex: 1; min-width: 0; font-size: var(--fs-body); line-height: 1.5;
  /* 🔴 文本区必须**自己**限高 + 可滚动。此前这里是 `overflow: visible`：
     超长说明既不换行撑开（被父级裁掉），又没有任何滚动条
     ⇒ 用户反馈"文字也没办法滑动（即便未显示所有内容）"就是这个。
     4.5em = 3 行（line-height 1.5）。 */
  max-height: 4.5em; overflow-y: auto;
  -webkit-overflow-scrolling: touch; overscroll-behavior: contain;
}
/* 点过「立即更新」之后就地给的后续步骤说明（手机端没有下载进度可看，
   这一步是让用户知道"更新正在进行、接下来该做什么"） */
.app-update-bar .app-update-hint {
  flex: 1 1 100%; font-size: var(--fs-caption); line-height: 1.6; color: var(--text-sec);
}
.app-update-bar .app-update-hint[hidden] { display: none; }
.app-update-bar .app-update-go {
  flex: 0 0 auto; padding: 7px 13px; border-radius: 9px;
  background: var(--br); color: #fff; font-size: var(--fs-label);
  font-weight: 600; text-decoration: none; cursor: pointer;
}
.app-update-bar .app-update-go:active { transform: translateY(var(--press-shift)); }
.app-update-bar .app-update-later {
  flex: 0 0 auto; padding: 7px 11px; border: 0; border-radius: 9px;
  background: transparent; color: var(--text-soft);
  font-family: inherit; font-size: var(--fs-label); cursor: pointer;
}
.app-update-bar .app-update-later:active { background: var(--btn-hover); }

/* 手机端：说明文字独占一行、按钮换行排布，避免文案被挤成一行。
   main#app 在 ≤768px 的 padding 左右为 0，故这里补 16px 水平内缩对齐 .m-home。
   上限 = 文本 6em(4 行) + 动作行 35 + 提示行 + 内边距，留足余量 ⇒ 动作行永不被裁。 */
@media (max-width: 768px) {
  .app-update-bar { margin-left: 16px; margin-right: 16px; }
  .app-update-bar.show { max-height: 260px; }
  .app-update-bar .app-update-text { flex: 1 1 100%; max-height: 6em; }
}

/* ===== 手动检查更新（2026-09-27）=========================================
   入口在「关于」区：桌面 = 帮助中心关于卡的 desk-kv 行；手机 = 我的页关于卡。
   两条入口各带一个 .update-check-hint（app-update.js 就地写入结果文字），
   故这里只需描述"提示长什么样"，不含任何定位假设。
   ------------------------------------------------------------------------ */
.update-check-btn { padding: 2px 0; }
.update-check-btn:disabled { color: var(--text-soft); cursor: default; }

/* 提示紧跟按钮之后，同一行内右对齐；过长自动换行不撑破容器 */
.update-check-hint {
  display: block; margin-top: 2px;
  font-size: var(--fs-label); font-weight: 500; line-height: 1.5;
  color: var(--text-soft); text-align: right;
  overflow-wrap: anywhere;
}
/* 状态色（tone 由 JS 整串赋类给出，见 setManualHint） */
.update-check-hint.ok { color: var(--ok-text); }
.update-check-hint.err { color: var(--err-text); }

/* 该行改为纵向排布：标签在左，按钮+提示在右且可上下堆叠 */
.desk-kv.update-check-row > b,
.m-me-row.update-check-row > b { display: flex; flex-direction: column; align-items: flex-end; }

/* 手机端「关于」行字号随既有 12px 档（与 .m-me-row 的窄屏规则一致） */
@media (max-width: 400px) {
  .m-me-row.update-check-row .update-check-hint { font-size: 11px; }
}

/* ============================================================
   v0.6.0 每日日报（列表页 + 单日详情）
   ------------------------------------------------------------
   颜色一律走语义令牌（--desk-ink / --hr / --br / --ok / --err /
   --warn-text），深色与浅色主题自动跟随，不写死色值。
   日报是"结算产物"，任何数值为空时 JS 一律渲染 "—"，不补 0。
   ============================================================ */

/* 日报页只在桌面宽度 `display:flex`（同 .desk-page.active），这里只补内部布局 */
@media (min-width: 769px) {
  /* 页面级纵向节奏对齐兄弟页：#deskPageHome / #deskPageAlerts / #deskPageDevices
     都显式写了 20px，日报页此前落回 .desk-page.active 的默认 15px ⇒ 卡片偏挤。 */
  #deskPageDaily { gap: 20px; }
  /* 单日详情此前**没有任何布局规则**：‹返回 / 概览卡 / 两栏网格 / 免责声明
     四个子元素零间距贴成一整条，看着就是"糊住的长条"。这里把卡片间距补回来
     （16px 与帮助页 #mHelp #deskPageHelp 同档）。
     ⚠️ 必须写成 :not([hidden])：直接写 .daily-detail{display:flex} 会盖掉
     hidden 属性的 display:none，导致详情视图**永远显示**。 */
  .daily-detail:not([hidden]) { display: flex; flex-direction: column; gap: 16px; }
  /* 间距改由上面的 gap 统一给，去掉返回按钮自带的 margin-bottom，否则首屏多 10px */
  .daily-detail:not([hidden]) .daily-back { margin-bottom: 0; }
  .desk-card.daily-list-card { padding: 18px; }
  /* 返回按钮：.daily-detail 是 flex 列，默认 align-items:stretch 会把按钮拉满整行，
     文字于是浮在页面正中、与下面的卡片对不上齐。收回收自身宽度、贴左。 */
  .daily-detail:not([hidden]) .daily-back { align-self: flex-start; }
  /* 两栏等高。此前是 align-items:start ⇒ 左卡四行、右卡只有一句空态，
     两张卡各按内容算高度，看着就是参差。stretch（grid 默认值）配下面的
     flex 列，让多出来的空白收进卡片内部，而不是露在卡片之间。 */
  .desk-grid-daily { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr); gap: 20px; }
  .desk-grid-daily > .desk-card { display: flex; flex-direction: column; }
  /* 说明贴卡底：等高后左卡多出的空白集中到数据行与说明之间，
     而不是把说明顶在数据行下面、底下留一大片裸背景。 */
  .desk-grid-daily > .desk-card > .daily-note { margin-top: auto; padding-top: 12px; }
  /* 事件多条时限高滚动。右卡若不封顶，几十条异常就能把它撑成整页高、
     连带把左卡一起拉伸，等高立刻又破功——这一条就是"有数据之后不乱"的保证。
     只滚不截断：监护产品不能把异常事件悄悄藏掉。 */
  .desk-grid-daily .daily-events { flex: 1 1 auto; min-height: 0; max-height: 340px; overflow-y: auto; scrollbar-gutter: stable; }
  /* 空态在整块高度里居中（flex 列内 margin:auto 两轴都吃满剩余空间），
     不再塌成一行贴在卡顶。 */
  .desk-grid-daily .daily-events .daily-empty { margin: auto; }
}

/* ---- 近 7 天列表 ---- */
.daily-list { display: flex; flex-direction: column; }
.daily-row {
  width: 100%; display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, .9fr) minmax(0, .9fr) auto;
  align-items: center; gap: 12px; padding: 13px 10px; border: 0; border-top: 1px solid var(--desk-line);
  background: none; text-align: left; font: inherit; color: inherit; cursor: pointer;
  border-radius: 10px; transition: background-color .18s var(--ease-hover);
}
.daily-row:first-of-type { border-top: 0; }
.daily-row:hover { background: var(--desk-soft); }
.daily-row:focus-visible { outline: 2px solid var(--desk-blue); outline-offset: -2px; }
.daily-row-day { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.daily-row-day b { font-size: var(--fs-body); font-weight: 600; color: var(--desk-ink); font-variant-numeric: tabular-nums; }
.daily-row-day small { font-size: var(--fs-caption); color: var(--text-sec); }
.daily-row-metric { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.daily-row-metric span { font-size: var(--fs-caption); color: var(--text-sec); }
.daily-row-metric b { font-size: var(--fs-num-sm); font-weight: 500; font-variant-numeric: tabular-nums; color: var(--desk-ink); }
.daily-row-metric.hr b { color: var(--hr); }
.daily-row-metric.br b { color: var(--br); }
.daily-row-flag { display: inline-flex; align-items: center; justify-content: center; min-width: 46px; padding: 4px 9px; border-radius: 999px; font-size: var(--fs-caption); font-weight: 600; white-space: nowrap; }
/* 状态一律整串赋值（row.className="daily-row-flag ..."），禁 classList.add */
.daily-row-flag.ok { color: var(--ok-text); background: var(--ok-bg); }
.daily-row-flag.warn { color: var(--warn-text); background: var(--warn-bg); }
.daily-row-flag.err { color: var(--err-text); background: var(--err-bg); }
.daily-row-flag.idle { color: var(--text-sec); background: var(--mute-bg); }
.daily-row.is-today { background: color-mix(in srgb, var(--desk-soft) 60%, transparent); }
.daily-empty { padding: 20px 4px; font-size: var(--fs-body); color: var(--text-sec); text-align: center; }

/* ---- 当日曲线（2026-10-01）----
   数据来自日报接口的 series：仍在 24h 明细窗内 = 原始采样点；更早的日 = 结算时存下的
   5 分钟桶均值。两种分辨率共用 drawChart（同一套光晕+主线+端点画法），所以这里只管
   画布盒模型与间距，**不引入第二种曲线样式**。
   ⚠️ 高度必须写 CSS（不是靠内容撑）：renderDailyCurve() 用 clientHeight 算像素尺寸，
       height 为 0 时画布会退化成 0×0 而静默什么都不显示。 */
.daily-curve { position: relative; margin-top: 4px; }
.daily-curve-canvas { display: block; width: 100%; height: 118px; }
.daily-curve-canvas + .daily-curve-canvas { margin-top: 6px; }
.daily-curve-note:empty { display: none; }
/* 曲线空态占位（0.6.9 后补）：无数据时盖在两块清空的画布上，替代 240px 纯白。
   绝对定位覆盖而非替换画布 —— 画布循环照旧清空，卡片高度不跳动。
   说明性文字一律 --text-sec（不用 --text-dim，项目硬规则）。 */
.daily-curve-empty { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; text-align: center; padding: 0 12px; }
.daily-curve-empty[hidden] { display: none; }
.daily-curve-empty::before { content: "◌"; font-size: 22px; line-height: 1; color: var(--text-sec); opacity: .55; }
.daily-curve-empty b { font-size: var(--fs-body); font-weight: 600; color: var(--text-sec); }
.daily-curve-empty small { font-size: var(--fs-caption); line-height: 1.5; color: var(--text-sec); }

/* ---- 单日详情 ---- */
.daily-back { margin-bottom: 10px; }
/* 结算状态标签：形式对齐诊断页 .m-sys-state 胶囊（圆点+胶囊底），文字内容不变。
   类名语义遵守全局约定：裸类 = ok（绿，"已结算"）、.idle = 待定（灰，"尚未结算/暂无记录"）。 */
.daily-settle-tag { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; font-weight: 400; padding: 3px 10px; border-radius: 999px; background: var(--ok-bg); color: var(--ok-text); border: 1px solid transparent; white-space: nowrap; }
.daily-settle-tag::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.daily-settle-tag.idle { background: var(--mute-bg); color: var(--text-sec); border-color: var(--card-border); }
.daily-settle-tag.idle::before { opacity: 0.5; }
.daily-metric-stats { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.daily-metric-stats small { display: block; margin-top: 3px; font-size: var(--fs-caption); color: var(--text-sec); }
.daily-diff { margin-top: 13px; font-size: var(--fs-caption); line-height: 1.6; color: var(--text-sec); }
.daily-range-hint { font-size: var(--fs-caption); color: var(--text-sec); }

.daily-kv { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 11px 18px; }
.daily-kv > div { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; padding: 10px 0; border-top: 1px solid var(--desk-line); }
.daily-kv > div span { font-size: var(--fs-caption); color: var(--text-sec); }
.daily-kv > div b { font-size: var(--fs-num-sm); font-weight: 500; font-variant-numeric: tabular-nums; color: var(--desk-ink); }
.daily-kv > div:nth-child(1), .daily-kv > div:nth-child(2) { border-top: 0; }
/* 数值空位短条（0.6.9 后补）：详情页取不到值的数值位显示一个"待填的槽"，
   替代孤零零的 — 破折号。条高用 em 随字号缩放（kv 行小字 / 摘要大数字通用）；
   ::before 画条不改元素的 display，b（行内）与 .m-summary-val（块级）都安全。
   数据口径不变：依旧不补 0、不编数据 —— 只是视觉形态从字符换成短条。 */
.kv-blank::before { content: ""; display: inline-block; width: 34px; height: .55em; border-radius: 999px; background: color-mix(in srgb, var(--text) 10%, transparent); }
.daily-note { margin-top: 12px; font-size: var(--fs-caption); line-height: 1.6; color: var(--text-sec); }

/* ---- 全天时间轴 ----
   桌面与手机由 renderDailyTimeline() 同源写入同一串 DOM，所以这里不放在任何
   媒体查询里：两边共用一套规则，改一处不会让另一处错位。
   颜色一律走变量 + color-mix，浅色/深色/薄荷三套主题不用各写一遍。 */
.daily-tl { margin-top: 12px; }
.daily-tl-track {
  position: relative; height: 34px; border-radius: 9px; overflow: hidden;
  background-color: var(--desk-soft);
  /* 每 25% = 6 小时一条刻度线，让"事件落在几点"能目测，而不是只看个大概方位 */
  background-image: linear-gradient(to right, var(--desk-line) 0 1px, transparent 1px);
  background-size: 25% 100%;
}
.daily-tl-seg { position: absolute; top: 0; bottom: 0; }
/* 实色 = 本日报自己的夜间段（计入「夜间 N 条」） */
.daily-tl-seg.night { background: color-mix(in srgb, var(--desk-ink) 14%, transparent); }
/* 斜纹 = 前一日日报的夜间段尾巴：不涂实，否则轴上数出来的条数会和「夜间 N 条」打架 */
.daily-tl-seg.prev {
  background-image: repeating-linear-gradient(135deg,
    color-mix(in srgb, var(--desk-ink) 15%, transparent) 0 4px, transparent 4px 9px);
}
.daily-tl-cover {
  position: absolute; top: 50%; height: 8px; margin-top: -4px; border-radius: 999px;
  background: color-mix(in srgb, var(--desk-muted) 55%, transparent);
}
.daily-tl-tick { position: absolute; top: 5px; bottom: 5px; width: 2px; margin-left: -1px; border-radius: 2px; }
/* 2px 宽的刻度点不到 title，用伪元素撑出一块透明命中区（命中仍算在父元素上） */
.daily-tl-tick::before { content: ""; position: absolute; top: -5px; bottom: -5px; left: -4px; right: -4px; }
.daily-tl-tick.hr { background: var(--hr); }
.daily-tl-tick.br { background: var(--br); }
.daily-tl-tick.bed { background: var(--warn-text); }
.daily-tl-axis {
  display: flex; justify-content: space-between; margin-top: 6px;
  font-family: var(--font-mono); font-size: var(--fs-caption);
  font-variant-numeric: tabular-nums; color: var(--text-dim);
}
.daily-tl-note { margin-top: 10px; font-size: var(--fs-caption); line-height: 1.6; color: var(--text-sec); }
.daily-tl-legend { display: inline-flex; align-items: center; flex-wrap: wrap; gap: 5px; font-size: var(--fs-caption); font-weight: 400; color: var(--text-sec); }
.daily-tl-legend .k { display: inline-block; width: 3px; height: 11px; border-radius: 2px; }
.daily-tl-legend .k.cover { width: 11px; height: 3px; border-radius: 2px; background: color-mix(in srgb, var(--desk-muted) 55%, transparent); }
.daily-tl-legend .k.hr { background: var(--hr); }
.daily-tl-legend .k.br { background: var(--br); }
.daily-tl-legend .k.bed { background: var(--warn-text); }
/* 手机卡的标题原本是纯块级，图例塞进去会紧贴标题文字；只在带图例的那一行开 flex。 */
.m-summary-title:has(.daily-tl-legend) { display: flex; align-items: center; justify-content: space-between; gap: 8px 12px; }

/* ---- 事件清单 ---- */
.daily-events { display: flex; flex-direction: column; }
.daily-evt { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 12px; padding: 12px 4px; border-top: 1px solid var(--desk-line); }
.daily-evt:first-of-type { border-top: 0; }
.daily-evt-ico { width: 34px; height: 34px; border-radius: 11px; display: grid; place-items: center; }
.daily-evt-ico .ui-icon { width: 19px; height: 19px; }
.daily-evt-ico.hr { color: var(--hr); background: var(--err-bg); }
.daily-evt-ico.br { color: var(--br); background: var(--br-soft); }
.daily-evt-ico.bed { color: var(--warn-text); background: var(--warn-bg); }
.daily-evt-body { min-width: 0; }
.daily-evt-body b { display: block; font-size: var(--fs-body); font-weight: 600; color: var(--desk-ink); }
.daily-evt-body small { display: block; margin-top: 3px; font-size: var(--fs-caption); color: var(--text-sec); }
.daily-evt-right { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; }
.daily-evt-val { font-size: var(--fs-num-sm); font-weight: 500; font-variant-numeric: tabular-nums; color: var(--desk-ink); }
.daily-evt-val .daily-evt-derived { margin-left: 4px; font-size: var(--fs-caption); font-weight: 400; color: var(--text-sec); }
.daily-evt-status { font-size: var(--fs-caption); font-weight: 600; }
.daily-evt-status.ok { color: var(--ok-text); }
.daily-evt-status.warn { color: var(--warn-text); }
.daily-evt-status.idle { color: var(--text-sec); }

/* ---- 短标签统一成设备链路状态那套视觉语言（2026-10-02）----
   类名一字不改：daily-row-flag / daily-evt-status 的整串字面量被 static_assert
   第 38 节 H 锁死，改名直接红 ⇒ 统一只能靠**样式分组**。
   圆点用 ::before + currentColor 画，与 .m-sys-state 同一手法（不新增 DOM、不用图标）。
   刻意**不动** .m-sys-state 与桌面 .chain-node .sys-state：那两处 err 的红/黄是**有意
   分开**的语义，强行收敛会换掉红黄，并与「warn 用 warn 令牌 / err 用 err 令牌」的既有
   断言打架。这里只让日报自己与它们**视觉同源**。 */
.daily-row-flag::before,
.daily-evt-status::before {
  content: ""; flex: 0 0 auto; width: 6px; height: 6px; border-radius: 50%;
  background: currentColor; margin-right: 5px;
}
/* 事件行状态原本只是「纯文字变色」（无底无线），与列表行胶囊是两套画法 ⇒ 补盒模型 */
.daily-evt-status { display: inline-flex; align-items: center; padding: 3px 9px; border-radius: 999px; }
.daily-evt-status.ok { background: var(--ok-bg); }
.daily-evt-status.warn { background: var(--warn-bg); }
.daily-evt-status.idle { background: var(--mute-bg); }
/* idle 圆点弱化半档，与 .m-sys-state.idle::before 保持一致 */
.daily-row-flag.idle::before,
.daily-evt-status.idle::before { opacity: 0.5; }

/* ---- 手机端（≤768px）----
   桌面那套 .desk-page 在窄屏整体隐藏；这里只给手机容器自己的窄屏微调。
   注意：显隐由 mSwitchPage() 内联 display 控制，此处**不写 display**。 */
@media (max-width: 768px) {
  /* 设备选择行与首页同款。首页是**裸的** .current-device 圆角行；
     日报此前又把它包进 .m-card ⇒ 卡里套卡，与首页风格不统一。
     这里只剥掉外层卡片外观，内层 .current-device 继续用首页那套样式
     （margin-top 由 .m-card 的 --gap-card 保留，不动）。 */
  .m-card.daily-device-row { padding: 0; border: 0; border-radius: 0; background: none; box-shadow: none; }
  .daily-row { grid-template-columns: minmax(0, 1.2fr) minmax(0, .8fr) minmax(0, .8fr) auto; gap: 8px; padding: 12px 6px; }
  .daily-row-flag { min-width: 40px; padding: 3px 7px; }
  .daily-metric-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .daily-metric-stats > div:nth-child(2) { border-right: 0; }
  .daily-kv { grid-template-columns: minmax(0, 1fr); }
  .daily-kv > div:nth-child(2) { border-top: 1px solid var(--desk-line); }
  .m-daily .m-card { margin-bottom: var(--gap-card); }
  .m-daily-disclaimer { margin: 12px 4px 0; font-size: var(--fs-caption); line-height: 1.6; color: var(--text-sec); }
}

/* ===== 日报「夜间时段」入口 + 设置抽屉（视觉收口）=====
   两个真机截图上暴露的实际缺陷（不是风格偏好）：
   ① 手机端入口 #mDailyNightBtn 复用了通用的 .text-action（透明底、无边框、无图标），
      与旁边的正文同质感 ⇒ 用户看不出这是一个可点的控件。
      做法：描边胶囊 + 尾部 chevron。选择器限定在 .m-daily 内 ⇒
      桌面端 #dailyNightBtn 完全不受影响（它在 .desk-card-head 里、旁边就是 h2，空间充足）。
   ② 抽屉里的 .daily-night-* 此前**一条 CSS 规则都没有**：输入行退回浏览器默认的
      inline 布局，窄屏下"结束"标签与第二个时间控件被挤成两行；同时
      .desk-detail-actions 的 flex 只写在 min-width:769px 那个块里 ⇒ 手机端两个按钮
      退回 inline 排布、紧贴底边。
      做法：补齐输入行与动作行；窄屏改为纵向堆叠，时间控件独占右侧、不与标签争行宽。 */

/* ① 入口：'近 7 天' 居左、入口居右；入口自身是胶囊 chip */
.m-daily #mDailyListCard > .m-summary-title { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.m-daily .text-action[data-daily-night] {
  display: inline-flex; align-items: center; gap: 5px; flex: none;
  min-height: 30px; padding: 0 11px;
  border: 1px solid color-mix(in srgb, var(--br) 34%, transparent);
  border-radius: 999px;
  background: color-mix(in srgb, var(--br) 10%, transparent);
  color: var(--desk-ink); font-size: 12px; font-weight: 600;
}
/* 尾部 chevron 用边框旋转画（不引字符/图标：本页没有可复用的 symbol）。
   文字色刻意用 --desk-ink 而非 --br —— 12px 品牌青绿对白底仅 ≈3:1，低于 WCAG AA 4.5:1；
   "可点击"由胶囊形状 + 描边 + chevron 表达，文字保持可读。 */
.m-daily .text-action[data-daily-night]::after {
  content: ""; width: 5px; height: 5px; margin-top: -2px; flex: none;
  border-right: 1.6px solid currentColor; border-bottom: 1.6px solid currentColor;
  transform: rotate(45deg);
}
/* 通用 .text-action:active 会把底色刷成 --btn-hover 灰，在淡青底上很脏 ⇒ 单独给按压色 */
.m-daily .text-action[data-daily-night]:active { background: color-mix(in srgb, var(--br) 22%, transparent); }

/* ② 抽屉：说明段 / 输入行 / 错误行 / 动作行 */
.daily-night-card .daily-night-intro { margin: 2px 0 4px; color: var(--text-sec); font-size: var(--fs-body); line-height: 1.8; }
.daily-night-card .daily-night-intro b { color: var(--text); font-weight: 600; }

.daily-night-inputs { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); align-items: end; gap: 12px; }
.daily-night-inputs > label { display: flex; flex-direction: column; gap: 7px; min-width: 0; font-size: var(--fs-caption); font-weight: 500; color: var(--text-sec); }
.daily-night-inputs > span { align-self: end; display: flex; align-items: center; justify-content: center; min-height: 46px; color: var(--text-mute); font-size: var(--fs-body); }
.daily-night-inputs input[type="time"] {
  width: 100%; min-width: 0; box-sizing: border-box;
  min-height: 46px; padding: 0 12px;
  border: 1px solid var(--desk-line); border-radius: 12px;
  background: var(--desk-soft); color: var(--desk-ink);
  font-family: var(--font-sans); font-size: 16px; font-weight: 600; letter-spacing: .02em;
}
.daily-night-inputs input[type="time"]:focus-visible { outline: 2px solid var(--br); outline-offset: 1px; border-color: var(--br); }

.daily-night-err { margin: 2px 0 0; padding: 9px 12px; border-radius: 10px; background: var(--err-bg); color: var(--err-text); font-size: var(--fs-caption); line-height: 1.6; }
.daily-night-err[hidden] { display: none; }

.daily-night-card .desk-detail-actions { margin-top: 6px; display: flex; align-items: center; gap: 12px; }
.daily-night-card .desk-detail-actions .primary-action { flex: 1; min-height: 46px; }
.daily-night-card .desk-detail-actions .text-action { flex: none; min-height: 46px; padding: 0 6px; color: var(--text-sec); }

/* 窄屏：输入行纵向堆叠 —— 这是截图里"排版凌乱"的直接原因（标签与时间控件争同一行） */
@media (max-width: 768px) {
  .daily-night-inputs { grid-template-columns: minmax(0, 1fr); gap: 14px; }
  .daily-night-inputs > span { display: none; }
  .daily-night-inputs > label { flex-direction: row; align-items: center; justify-content: space-between; gap: 14px; font-size: var(--fs-body); }
  .daily-night-inputs > label input[type="time"] { width: auto; flex: 0 0 auto; min-width: 132px; }
}
