:root{
  --bg:#f1f5f9; --card:#ffffff; --border:#e2e8f0; --text:#0f172a; --muted:#64748b;
  --primary:#2563eb; --primary-bg:#eff6ff; --ok:#16a34a; --ok-bg:#f0fdf4;
  --danger:#dc2626; --danger-bg:#fef2f2; --warn:#d97706; --warn-bg:#fffbeb;
  --side:#0f172a; --side-text:#94a3b8; --side-active:#e2e8f0;
  --chip:#f1f5f9; --hover:#f8fafc; --input-bg:#ffffff;
  --ask-l:#e6ecf3;   /* 问 DIoT 助手气泡底：--chip 与 --bg 同值，浅色下左气泡隐形 */
  --topbar-h:54px; --side-w:216px;
  --mono:ui-monospace,Consolas,'Courier New',monospace;
}
[data-theme="dark"]{
  --bg:#0b1220; --card:#0f172a; --border:#1e293b; --text:#e2e8f0; --muted:#94a3b8;
  --primary:#3b82f6; --primary-bg:#1e3a5f; --ok:#22c55e; --ok-bg:#052e16;
  --danger:#f87171; --danger-bg:#450a0a; --warn:#fbbf24; --warn-bg:#451a03;
  --side:#020617; --side-text:#94a3b8; --side-active:#e2e8f0;
  --chip:#1e293b; --hover:#132033; --input-bg:#0f172a;
  --ask-l:#1e2b42;   /* 比卡片/chip 更亮一档的蓝灰，深底下气泡可辨 */
}
*{margin:0;padding:0;box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
/* ---------- 细滚动条（PC Chrome/Edge 默认滚动条粗且突兀，全局统一替换；
   半透明石板色亮/暗主题通吃。Chrome 121+ 一旦设置 scrollbar-width 即改用
   标准细滚动条并忽略 ::-webkit-scrollbar 定制 → Firefox 专属包裹下发给
   标准属性，Chrome/Edge 走 6px webkit 定制） ---------- */
@-moz-document url-prefix(){
  *{scrollbar-width:thin;scrollbar-color:rgba(148,163,184,.45) transparent}
}
::-webkit-scrollbar{width:6px;height:6px}
::-webkit-scrollbar-thumb{background:rgba(148,163,184,.45);border-radius:3px}
::-webkit-scrollbar-thumb:hover{background:rgba(148,163,184,.7)}
::-webkit-scrollbar-track{background:transparent}
::-webkit-scrollbar-corner{background:transparent}
body{font-family:-apple-system,'Segoe UI','Microsoft YaHei',sans-serif;background:var(--bg);
     color:var(--text);font-size:14px;line-height:1.5;overflow-x:hidden}
/* iOS Safari 的 vh = 最大视口（工具栏收起态）；工具栏可见时可见高度更小，
   按 vh 定高的底部会被工具栏遮挡（iPad/iOS 实测"底部被遮挡"）。
   全站视口定高规则一律 vh 后补一行 dvh（动态可视视口，iOS 15.4+/现代浏览器
   由后者生效，老浏览器忽略不认识的 dvh 行回落 vh） */
#app{min-height:100vh;min-height:100dvh}

/* ---------- 侧边栏（PC：固定左侧、通高到顶） ---------- */
.sidebar{position:fixed;left:0;top:0;height:100vh;height:100dvh;width:var(--side-w);
  background:var(--side);color:var(--side-text);flex-shrink:0;
  display:flex;flex-direction:column;z-index:40}
/* 侧栏头：品牌字常驻 + 家庭切换器在其下；分隔线挂头容器——无家庭归属
   （切换器不渲染）时品牌字下仍有线。版本脚注见 .side-foot */
.side-head{border-bottom:1px solid #1e293b}
.logo{padding:16px 20px 10px}
.logo b{color:#fff;font-size:16px;letter-spacing:.5px}
/* 版本脚注：nav 之外 flex 尾部固定（nav 内滚不随动） */
.side-foot{padding:12px 20px;border-top:1px solid #1e293b;font-size:11px;color:#475569}
.nav{flex:1;padding:10px 0;overflow-y:auto}
.nav .group{font-size:11px;color:#475569;padding:14px 20px 4px;letter-spacing:1px}
.nav a{display:flex;align-items:center;gap:10px;padding:9px 20px;cursor:pointer;
       color:var(--side-text);text-decoration:none;font-size:13.5px;border-left:3px solid transparent}
.nav a:hover{color:#e2e8f0}
.nav a.active{color:var(--side-active);background:#1e293b;border-left-color:var(--primary)}
/* 侧边栏图标：内联 SVG 线性图标（描边随文字色，16px 网格统一线宽） */
.nav a .ico{width:16px;height:16px;flex-shrink:0;fill:none;stroke:currentColor;
            stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
/* 家庭切换器（侧栏头品牌字下方，原版本小字位）：自定义下拉（原生 select 系统弹层在
   深色侧边栏里外观割裂，也带不了图标/属主徽标/当前勾选）。头像=home.icon 图标库 svg
   （未配图标/未加载回落首字）铺 icon_color 底色；菜单相对切换器绝对定位，向下展开
   盖过下方导航项（z-index 保证在链接之上） */
.hswitch{position:relative;padding:2px 12px 12px}
.hs-btn{display:flex;align-items:center;gap:8px;width:100%;padding:7px 10px;
        background:#1e293b;border:1px solid #334155;border-radius:8px;cursor:pointer;
        color:var(--side-text);font:inherit;font-size:13px;text-align:left}
.hs-btn:hover{border-color:#475569;color:#e2e8f0}
.hs-ava{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;
        border-radius:6px;color:#fff;flex-shrink:0;font-size:12px;font-weight:600;line-height:1}
.hs-ava svg{width:15px;height:15px}
.hs-ava.sm{width:20px;height:20px;border-radius:5px;font-size:11px}
.hs-ava.sm svg{width:13px;height:13px}
.hs-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
         color:var(--side-active);font-weight:500}
.hs-item .hs-name{color:inherit;font-weight:400}
.hs-item.cur .hs-name{color:var(--side-active);font-weight:500}
.hs-role{flex-shrink:0;font-size:10px;line-height:1;padding:3px 5px;border-radius:4px;
         background:rgba(59,130,246,.18);color:#93c5fd}
.hs-chev,.hs-check{flex-shrink:0;fill:none;stroke-linecap:round;stroke-linejoin:round}
.hs-chev{width:12px;height:12px;stroke:currentColor;stroke-width:2;transition:transform .15s}
.hswitch.open > .hs-btn .hs-chev{transform:rotate(180deg)}
.hs-check{width:13px;height:13px;stroke:var(--primary);stroke-width:2.5}
.hs-menu{position:absolute;left:12px;right:12px;top:calc(100% - 4px);z-index:50;
         background:#1e293b;border:1px solid #334155;border-radius:8px;padding:4px;
         box-shadow:0 8px 24px rgba(0,0,0,.45)}
.hs-item{display:flex;align-items:center;gap:8px;padding:7px 8px;border-radius:6px;
         cursor:pointer;font-size:13px;color:var(--side-text)}
.hs-item:hover{background:#334155;color:#e2e8f0}
/* 系统分组折叠头（staff 专属区；默认展开、可收起） */
.nav .group.tog{cursor:pointer;user-select:none;display:flex;align-items:center;
                justify-content:space-between}
.nav .group.tog:hover{color:#64748b}
.nav .group .chev{width:11px;height:11px;fill:none;stroke:currentColor;stroke-width:2;
                  stroke-linecap:round;stroke-linejoin:round;transition:transform .15s}
.nav .group .chev.open{transform:rotate(90deg)}
.overlay{display:none;position:fixed;inset:0;background:rgba(0,0,0,.45);z-index:35}

/* ---------- 顶栏（PC：覆盖侧边栏之外的剩余宽度；随滚动吸顶） ---------- */
.topbar{background:var(--card);border-bottom:1px solid var(--border);height:var(--topbar-h);
        padding:0 24px;display:flex;align-items:center;gap:12px;
        position:sticky;top:0;z-index:30;margin-left:var(--side-w)}
.sp{flex:1}   /* 右推占位：顶栏 / 筛选行 / 映射与环境条行通用（仅写 .topbar .sp 时其余全是死的） */
.main{margin-left:var(--side-w);min-height:calc(100vh - var(--topbar-h));
      min-height:calc(100dvh - var(--topbar-h))}
.icon-btn{width:34px;height:34px;border-radius:8px;border:1px solid var(--border);
  background:var(--input-bg);cursor:pointer;font-size:15px;display:inline-flex;
  align-items:center;justify-content:center;color:var(--text);flex-shrink:0}
.user{font-size:13px;color:var(--muted);white-space:nowrap}
.content{padding:20px 24px;max-width:1280px}

/* ---------- 通用组件（垂直居中 / 不换行） ---------- */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:6px;height:34px;
     padding:0 14px;border-radius:8px;border:1px solid var(--border);background:var(--input-bg);
     cursor:pointer;font:inherit;font-size:13px;color:var(--text);white-space:nowrap;line-height:1}
.btn.primary{background:var(--primary);border-color:var(--primary);color:#fff}
/* 表格操作列等宽按钮：文案长短不一（停用/启用 vs 重置密码）导致各行列左缘漂移，
   统一定宽后跨行成列；配合操作列宽度 = 3×96 + 间隙（设为管理员实测 95px） */
.btn-op{min-width:96px}
/* 两步验证恢复码展示（twofa-design §7.1）：等宽两列、可整块选择，仅启用/重生成流程一次性可见 */
.twofa-codes{display:grid;grid-template-columns:1fr 1fr;gap:4px 22px;font-family:var(--mono);
  font-size:14px;letter-spacing:1px;background:var(--bg);border:1px dashed var(--border);
  border-radius:8px;padding:12px 16px;margin:10px 0;white-space:pre;user-select:all}
.btn:hover{filter:brightness(.97)}
.btn:disabled{opacity:.5;cursor:not-allowed}
.pill{display:inline-flex;align-items:center;gap:5px;height:28px;padding:0 12px;
      border-radius:99px;border:1px solid var(--border);background:var(--input-bg);
      cursor:pointer;font-size:12px;color:var(--muted);white-space:nowrap;line-height:1}
.pill.active{background:var(--primary-bg);color:var(--primary);border-color:var(--primary);font-weight:600}
.badge{display:inline-flex;align-items:center;height:20px;padding:0 8px;border-radius:99px;
       font-size:11px;font-weight:600;white-space:nowrap;line-height:1}
.b-on{background:var(--primary-bg);color:var(--primary)}
.b-off{background:var(--chip);color:var(--muted)}
.b-ok{background:var(--ok-bg);color:var(--ok)}
.b-err{background:var(--danger-bg);color:var(--danger)}
.b-warn{background:var(--warn-bg);color:var(--warn)}
.b-info{background:var(--primary-bg);color:var(--primary)}
input,select,textarea{font:inherit;color:var(--text)}
input.search,input.txt,select.sel{height:32px;padding:0 12px;border:1px solid var(--border);
  border-radius:8px;font-size:13px;background:var(--input-bg)}
input.search{width:220px}
input.txt{width:130px}
input.mini,select.mini{height:26px;font-size:12px;padding:0 8px;border:1px solid var(--border);
  border-radius:5px;background:var(--input-bg)}
input.mini{width:80px}
/* inline-block：表格 td 内 span.switch 行内元素不吃宽高（塌缩致与同行按钮重叠）；
   flex 容器内会被块化，原有布局不受影响 */
.switch{display:inline-block;vertical-align:middle;width:40px;height:22px;flex-shrink:0;cursor:pointer;border-radius:999px}
.switch .track{width:100%;height:100%;border-radius:inherit;background:#94a3b8;position:relative;transition:background .2s}
.switch .track::after{content:'';position:absolute;top:2px;left:2px;width:18px;height:18px;
  border-radius:50%;background:#fff;box-shadow:0 1px 2px rgba(0,0,0,.3);transition:transform .2s}
.switch.on .track{background:var(--ok)}
.switch.on .track::after{transform:translateX(18px)}
.dot{display:inline-block;width:8px;height:8px;border-radius:50%;margin-right:6px;vertical-align:1px}
.on{background:var(--ok)} .off{background:#64748b}
/* 智慧屏列表 HA 注册徽标：一眼看清已注册 broker，免点开抽屉（impl-plan §14 P1） */
.ha-chip{display:inline-block;font-size:10px;font-weight:600;line-height:1;padding:3px 7px;
  margin-left:8px;border-radius:9px;background:var(--primary-bg);color:var(--primary);
  border:1px solid var(--primary);vertical-align:2px}
.card{background:var(--card);border:1px solid var(--border);border-radius:10px;padding:16px 18px;margin-bottom:16px}
.card h3{font-size:13px;color:var(--muted);font-weight:600;margin-bottom:12px;letter-spacing:.5px}
.grid{display:grid;gap:16px;margin-bottom:16px}
/* grid 项卡片吃自己的 margin-bottom 会与 gap 叠成 32px（行间 32 vs 独立卡片 16 不齐） */
.grid>.card{margin-bottom:0;min-width:0}   /* min-width:0 防 spark 柱多时撑破 1fr 轨道 */
.g4{grid-template-columns:repeat(4,1fr)}
.g3{grid-template-columns:repeat(3,1fr)}
.g2{grid-template-columns:1.4fr 1fr}
/* nowrap+ellipsis：stat 卡文案在窄卡（手机两列）不落到第二行，超长省略 */
.stat .num{font-size:26px;font-weight:700;font-family:var(--mono);white-space:nowrap}
.stat .lbl{font-size:12px;color:var(--muted);margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* 环境来源小字（env-source-design §6.2）：概览环境卡第三行。容器 flex + 文本子元素
   自己省略——否则父级 nowrap/ellipsis 会把行尾的「去设置」链接一起吃掉 */
.stat .lbl.src{display:flex;align-items:center;gap:6px;font-size:11px;color:#64748b}
.stat .lbl.src>span{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.lnk{color:var(--primary);cursor:pointer;flex-shrink:0;text-decoration:none}
.lnk:hover{text-decoration:underline}
/* 仪表盘"现在"卡 .num 是中文文案：mono 栈无中文字形（Windows 回落宋体），回正文字体 */
.stat .num.txt{font-family:inherit}
/* 仪表盘：告警条 / 上报 sparkline / 待处理建议行（dashboard-optimize-20260904 A/B/D/E） */
/* 垂直居中：概览行里徽标/文字（20~24px）与按钮（34px）高度不一时整体居中
   （家庭概览「家里有人」行此前文字顶在按钮上沿）；告警条折行时时间戳居中反而更整 */
.dash-top{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:16px}
.alerts{display:flex;flex-wrap:wrap;gap:6px}
.spark{display:flex;align-items:flex-end;gap:2px;height:30px;margin-top:8px}
.spark i{flex:1;min-height:2px;background:var(--primary);opacity:.5;border-radius:1px}
.spark i.cur{opacity:1}
/* LLM 运行情况卡：近 14 天调用全失败日标红 */
.spark i.bad{background:var(--danger);opacity:.85}
/* LLM 运行情况卡「配置与策略」信息块：左标签定宽 muted + 值正文色——
   接入/参数/技能/配额原先是一整段 muted 长句平铺，无视觉分层难扫读 */
.llm-meta{display:flex;flex-direction:column;gap:5px;margin:2px 0 4px}
.llm-meta .lm{display:flex;gap:10px;font-size:12.5px;line-height:1.7;min-width:0}
.llm-meta .lm-k{flex-shrink:0;width:42px;color:var(--muted)}
.llm-meta .lm-v{min-width:0;color:var(--text)}
.llm-meta .lm-v .badge{vertical-align:-4px}   /* 行内徽标与文字基线对齐 */
.llm-meta .lm-v.muted{color:var(--muted)}
/* 链路健康卡：告警徽章点击后滚动定位的高亮脉冲 */
.card.flash{animation:card-flash 1.8s ease}
@keyframes card-flash{0%,45%{box-shadow:inset 0 0 0 2px var(--primary)}100%{box-shadow:none}}
.prow{display:flex;align-items:flex-start;gap:10px;padding:9px 0;border-bottom:1px solid var(--border)}
.prow:last-child{border-bottom:none}
.p-main{flex:1;min-width:0}
.p-act{display:flex;gap:6px;flex-shrink:0}
.stat .delta{font-size:11px;margin-top:6px}
.up{color:var(--ok)} .down{color:var(--danger)} .flat{color:var(--muted)}
.tscroll{overflow-x:auto}
table{width:100%;border-collapse:collapse;font-size:13px}
/* 列宽下限：列多时避免一字一行竖排（横向滚动优于不可读压缩） */
.tscroll table td{min-width:76px}
/* 状态指示灯列（实体/屏幕/自动化/场景首列 8px 圆点）不受列宽下限，
   th 已声明 width:34px——76px 下限让它白白占掉双倍横向空间（手机上尤其浪费） */
.tscroll table td.ind{min-width:34px}
th{font-size:11px;color:var(--muted);text-transform:uppercase;letter-spacing:.5px;
   text-align:left;padding:6px 10px;border-bottom:1px solid var(--border);white-space:nowrap}
td{padding:8px 10px;border-bottom:1px solid var(--border);white-space:nowrap}
tbody tr:hover td{background:var(--hover)}
.mono{font-family:var(--mono);font-size:12.5px}
.muted{color:var(--muted)}
.filters{display:flex;gap:8px;margin-bottom:12px;flex-wrap:wrap;align-items:center}
.funnel .frow{display:flex;align-items:center;gap:10px;margin:7px 0}
.funnel .flbl{width:88px;font-size:12px;color:var(--muted);text-align:right;flex-shrink:0}
.funnel .ftrack{flex:1;height:18px;border-radius:4px;background:var(--chip);overflow:hidden}
.funnel .fbar{height:100%;border-radius:4px;min-width:2px}
.funnel .fnum{font-family:var(--mono);font-size:12px;width:30px}
.legend{display:flex;gap:16px;font-size:12px;color:var(--muted);margin-bottom:8px;flex-wrap:wrap}
.legend i{display:inline-block;width:10px;height:3px;border-radius:2px;margin-right:5px;vertical-align:3px}
.steps{display:flex;margin-bottom:18px;overflow-x:auto}
.step{flex:1;text-align:center;position:relative;padding-top:34px;font-size:12px;
      color:var(--muted);cursor:pointer;min-width:86px;white-space:nowrap}
.step::before{content:attr(data-n);position:absolute;top:0;left:50%;transform:translateX(-50%);
  width:24px;height:24px;border-radius:50%;background:var(--chip);color:var(--muted);line-height:24px;
  font-size:12px;font-weight:600}
.step:not(:last-child)::after{content:'';position:absolute;top:12px;left:calc(50% + 16px);
  width:calc(100% - 32px);height:2px;background:var(--chip)}
.step.done::before{content:'✓';background:var(--ok);color:#fff}
.step.active::before{background:var(--primary);color:#fff}
.step.active{color:var(--text);font-weight:600}
.wiz2{display:grid;grid-template-columns:1fr 1.2fr;gap:16px}
/* 数据管理双栏：左表清单定宽、右表吃满剩余宽度。沿用 1fr/1.2fr 等分时左卡
   只有 210px，与表卡之间出现 ~320px 空档（表卡视觉居中漂浮），
   9 列的实体表在 633px 卡内还触发横向滚动 */
.wiz2.dview{grid-template-columns:210px minmax(0,1fr)}
/* 数据表列更密：单元格下限自全局 76px 降两档（单元格 white-space:normal
   可换行，不会一字一行）、水平内边距 10→8px，9 列的实体表在 1280 宽
   笔记本上也不再横向滚动 */
.wiz2.dview .tscroll table td{min-width:48px;padding-left:8px;padding-right:8px}
.wiz2.dview .tscroll table th{padding-left:8px;padding-right:8px}
/* ---------- 工作台满高（PC ≥881px）：列表页卡片吃满首屏、表格区内滚 + 表头吸顶 ----------
   数据管理双栏与各单卡列表页（实体/智慧屏/自动化/场景/日志/平台/账号）统一为
   "上筛选、中表格（内滚）、下分页/说明"的满高框架，页面下方不再大片留白；
   手机（≤880px）整块不生效，保持自然文档流。高度 = 视口 - 顶栏 - content 上下内边距 */
@media (min-width:881px){
  /* height 而非 min-height：min-height 只设下限，左栏 28 张表的内容高度仍会把
     网格行撑过视口；定高 + minmax(0,1fr) 行封顶（隐式 auto 行按内容取最大值，
     会在纵向上重新溢出）+ 内部 min-height:0 收缩，才能把滚动锁进表格区 */
  .wiz2.dview{height:calc(100vh - var(--topbar-h) - 40px);height:calc(100dvh - var(--topbar-h) - 40px);
    grid-template-rows:minmax(0,1fr)}
  .card.wb{height:calc(100vh - var(--topbar-h) - 40px);height:calc(100dvh - var(--topbar-h) - 40px)}
  /* 后代而非 > 子级：数据管理右卡外层还包着 grid 列 div，直接子选择器只命中左卡；
     该列 div 被网格拉伸为定高，卡片 height:100% 接力传递给内部 flex 收缩 */
  .wiz2.dview .card,.card.wb{display:flex;flex-direction:column;margin-bottom:0}
  .wiz2.dview .card{height:100%}
  .wiz2.dview > .card:first-child > div{flex:1;min-height:0}
  .wiz2.dview .tscroll,.card.wb .tscroll{flex:1;min-height:0;overflow:auto}
  .wiz2.dview .tscroll th,.card.wb .tscroll th{position:sticky;top:0;background:var(--card);z-index:1}
  /* collapse 下边框由表格统一绘制，行从吸顶表头的边缝透字；separate+0 间距视觉不变 */
  .wiz2.dview .tscroll table,.card.wb .tscroll table{border-collapse:separate;border-spacing:0}
}
textarea.payload{width:100%;height:132px;font-family:var(--mono);font-size:12.5px;padding:12px;
  border:1px solid var(--border);border-radius:8px;resize:vertical;background:var(--input-bg);color:var(--text)}
.mrow{border:1px solid var(--border);border-radius:9px;margin-bottom:10px;overflow:hidden}
.mrow .mhead{display:flex;align-items:center;gap:8px;padding:9px 12px;background:var(--hover);
  border-bottom:1px solid var(--border);flex-wrap:wrap}
.mrow .mbody{padding:10px 12px}
.opchips{display:flex;flex-wrap:wrap;gap:6px;align-items:center;margin:6px 0 8px}
.op{display:inline-flex;align-items:center;gap:4px;font-family:var(--mono);font-size:11.5px;
    background:var(--chip);border:1px solid var(--border);border-radius:6px;padding:3px 7px;line-height:1.4}
.op .arrow{color:var(--muted)}
.op input{width:86px;height:22px;font-size:11.5px;font-family:var(--mono);padding:0 6px;
  border:1px solid var(--border);border-radius:5px;background:var(--input-bg)}
.op.err{color:var(--danger);border-color:var(--danger)}
.op .del{cursor:pointer;color:var(--muted);padding:0 2px}
.op .del:hover{color:var(--danger)}
.tval{font-family:var(--mono);font-size:13px;font-weight:600}
.trow{display:flex;align-items:center;gap:8px;padding:3px 0;font-size:12px;flex-wrap:wrap}
/* 参数行 label+控件成对包裹：窄抽屉里换行只发生在对与对之间（此前「拉伸」标签行尾、
   输入框孤行头的拆对折行）；数字输入藏原生 spinner——48~64px 窄输入里上下箭头
   盖住数字（节奏级 10 只露出 1），键盘/粘贴改值，触屏本就无 spinner */
.trow .pair{display:inline-flex;align-items:center;gap:6px;white-space:nowrap}
.trow input[type=number]{-moz-appearance:textfield;appearance:textfield}
.trow input[type=number]::-webkit-outer-spin-button,
.trow input[type=number]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
.capcard{border:1px solid var(--border);border-radius:9px;padding:12px;margin-bottom:10px;background:var(--hover)}
.capgrid{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin-top:8px}
.capgrid label{font-size:12px;color:var(--muted)}
.skill{display:flex;align-items:flex-start;gap:12px;padding:12px 0;border-bottom:1px solid var(--border)}
.skill:last-child{border-bottom:none}
.sk-ico{width:38px;height:38px;border-radius:9px;background:var(--primary-bg);color:var(--primary);
        display:flex;align-items:center;justify-content:center;font-size:17px;flex-shrink:0}
.sk-body{flex:1;min-width:0}
.sk-name{font-weight:600;font-size:13.5px}
.sk-desc{font-size:12px;color:var(--muted)}
.sk-meta{font-size:11px;color:var(--muted);margin-top:3px}
.login-mask{position:fixed;inset:0;background:var(--bg);z-index:100;display:flex;
  align-items:center;justify-content:center}
.login-card{background:var(--card);border:1px solid var(--border);border-radius:12px;
  padding:28px;width:340px}
.login-card h2{font-size:17px;margin-bottom:16px}
.login-card input{width:100%;height:38px;margin-bottom:10px;padding:0 12px;
  border:1px solid var(--border);border-radius:8px;background:var(--input-bg);font-size:16px}
.login-err{color:var(--danger);font-size:12px;margin-bottom:10px;min-height:16px}
.hamburger{display:none}

/* ---------- 手机 / 窄屏适配（抽屉侧边栏 + 顶栏全宽 + 触控放大） ---------- */
@media (max-width:880px){
  :root{--topbar-h:60px}
  .topbar{margin-left:0;height:var(--topbar-h);padding:0 14px}
  .main{margin-left:0}
  .icon-btn{width:42px;height:42px;font-size:18px}
  .btn{height:40px;padding:0 16px;font-size:14px}
  .pill{height:34px;padding:0 14px;font-size:13px}
  .badge{height:24px;padding:0 10px;font-size:12px}
  input.search,input.txt,select.sel,textarea.payload,textarea.askta,input.mini,select.mini,.op input,
  .login-card input{font-size:16px}
  input.mini,select.mini{height:32px}
  .op input{width:120px;height:30px}
  .nav a{padding:13px 20px;font-size:15px}
  .content{padding:14px}
  .g4,.g3,.g2,.wiz2{grid-template-columns:1fr}
  .wiz2.dview{grid-template-columns:1fr}   /* 双栏布局仅 PC：手机塌单列（chip 条覆盖） */
  .funnel .flbl{width:70px}
  .user{display:none}
  /* 侧边栏变抽屉（顶栏下方滑出，顶栏汉堡可开合） */
  .sidebar{top:var(--topbar-h);height:calc(100vh - var(--topbar-h));
           height:calc(100dvh - var(--topbar-h));
           transform:translateX(-100%);transition:transform .25s}
  .sidebar.open{transform:translateX(0)}
  .overlay.show{display:block}
  .hamburger{display:inline-flex}
}

/* 品牌 logo：DIoT 中的 o 用主题蓝（bind 页/智慧屏同款） */
.logo-o{color:var(--primary)}

/* ---------- 技能参数快调弹窗 + 实体详情侧滑（console-design §7 P1） ---------- */
.modal-mask{position:fixed;inset:0;background:rgba(15,23,42,.45);z-index:70;display:flex;
  align-items:center;justify-content:center;padding:16px}
.modal-card{background:var(--card);border:1px solid var(--border);border-radius:12px;
  padding:20px;width:560px;max-width:100%;max-height:86vh;max-height:86dvh;overflow-y:auto}
.modal-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:14px}
.modal-head h3{margin:0;font-size:14px}
.pfield{margin-bottom:11px}
.plabel{display:block;font-size:12px;color:var(--muted);margin-bottom:3px}
.pctrl{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.pctrl input.txt{height:32px}
.phelp{font-size:11px;color:var(--muted);margin-top:3px}
.req{color:var(--danger)}
.chklist{display:flex;flex-wrap:wrap;gap:4px 14px}
.modal-foot{display:flex;gap:8px;align-items:center;margin-top:14px;
  border-top:1px solid var(--border);padding-top:12px}
.edim{display:none;position:fixed;inset:0;background:rgba(15,23,42,.35);z-index:60}
.edim.show{display:block}
.edrawer{position:fixed;top:0;right:-580px;width:540px;max-width:100vw;height:100vh;height:100dvh;
  background:var(--bg);z-index:61;border-left:1px solid var(--border);overflow-y:auto;
  transition:right .25s ease;padding:18px 20px 28px}
.edrawer.open{right:0}
/* 全局浮动 toast：原先渲染在 topbar 里，而 topbar 是 z-index:30 的 stacking
   context——抽屉（edim 60/edrawer 61）和弹窗（modal-mask 70）打开时 toast 整个
   被盖住，「确认创建」等失败只弹 toast 的路径在抽屉里看起来就是点了没反应。
   元素提到模板根层级 fixed 悬浮，z 90 压过全部浮层（登录掩码 100 之上无 toast
   场景）；覆盖 .badge 定高/nowrap，长报错可折行；pointer-events:none 不挡点击 */
.toast-float{position:fixed;top:calc(var(--topbar-h) + 12px);left:50%;transform:translateX(-50%);
  z-index:90;pointer-events:none;height:auto;min-height:26px;padding:5px 12px;
  line-height:1.5;white-space:normal;max-width:min(86vw,520px);
  box-shadow:0 6px 20px rgba(0,0,0,.18)}
.ed-head{display:flex;align-items:flex-start;justify-content:space-between;gap:8px;margin-bottom:6px}
.ed-meta{font-size:12px;color:var(--muted);margin-bottom:6px;display:flex;gap:4px 14px;flex-wrap:wrap}
.edrawer h3{font-size:13px;color:var(--muted);font-weight:600;margin:18px 0 8px;letter-spacing:.5px}
.capop{display:flex;align-items:center;gap:10px;padding:9px 12px;border:1px solid var(--border);
  border-radius:9px;margin-bottom:8px;background:var(--card);flex-wrap:wrap}
/* 能力模板编辑器（数据管理 → 设备类型/设备 capabilities；admin CapabilitiesEditorWidget 移植） */
.cap-card{border:1px solid var(--border);border-radius:9px;padding:10px 12px;margin:8px 0;
  background:var(--card)}
.cap-h{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:4px}
.cap-row{display:flex;align-items:center;gap:6px;margin:5px 0;flex-wrap:wrap}
.cap-lb{font-size:12px;color:var(--muted);white-space:nowrap}
.cap-sep{margin:8px 0;border-top:1px dashed var(--border)}
.cap-opt{display:inline-flex;align-items:center;gap:4px;margin:2px 4px 2px 0}
.cap-icur{display:inline-flex;width:22px;height:22px;flex-shrink:0}
.cap-icur svg{width:100%;height:100%}
.cap-igrid{position:absolute;z-index:30;top:30px;left:52px;background:var(--card);
  border:1px solid var(--border);border-radius:9px;padding:8px;width:300px;max-width:82vw;
  box-shadow:0 8px 24px rgba(0,0,0,.18)}
.cap-icells{display:flex;flex-wrap:wrap;gap:4px;margin-top:6px;max-height:220px;overflow-y:auto}
.cap-icell{display:inline-flex;width:36px;height:36px;padding:4px;border:1px solid transparent;
  border-radius:6px;cursor:pointer}
.cap-icell:hover{border-color:var(--primary);background:var(--bg)}
.cap-icell svg{width:100%;height:100%}
tr.clk{cursor:pointer}
tr.clk:hover td{background:var(--hover)}
.card.clk{cursor:pointer}
.histscroll{max-height:300px;overflow-y:auto}
@media (max-width:880px){
  .edrawer{width:100vw;right:-100vw;padding:14px}
  .modal-card{padding:16px}
  .pctrl input.txt,.pctrl select.sel{width:100% !important}
}

/* 自动化/场景编辑抽屉：比实体抽屉宽一档；内部两栏改单列（540/640px 装不下双栏） */
.edrawer.wide{width:640px}
/* 同优先级下文件序会压住 .edrawer.open，显式声明打开态（右滑入屏） */
.edrawer.wide.open{right:0}
.edrawer.wide:not(.open){right:-700px}
.edrawer .wiz2{grid-template-columns:1fr}
@media (max-width:880px){
  .edrawer.wide{width:100vw}
  .edrawer.wide.open{right:0}
  .edrawer.wide:not(.open){right:-100vw}
}

/* ---------- 手机端人体工学（可读性/触控/编辑页 sheet 化，console-design §4.2） ---------- */
@media (max-width:880px){
  /* 阅读字号：正文/标题/表格放大一档（12px 级文字是"看不清"的主因） */
  .content{font-size:15px}
  .card h3{font-size:14px}
  table{font-size:13.5px}
  table td,table th{padding:9px 10px}
  /* 表格不压缩：宁可横向滚动，不做竖排文字（min-width 下表格按内容展开） */
  .tscroll table{min-width:540px}
  .tscroll table td{word-break:break-word}
  /* 触屏滚动条是悬浮式（画在容器底边上、滚动态压住内容）：数据表操作按钮
     下缘与容器底只隔 td 的 9px padding，横向滚动时悬浮条正好蹭到按钮下缘
     （桌面经典滚动条占布局位不复现，手机实测被遮）——容器补 4px 底部
     内边距把末行按钮从滚动条区抬出来 */
  .tscroll{padding-bottom:4px}
  /* grid 项允许收缩到轨道宽（默认 min-width:auto 会被表格 min-width 顶开轨道，
     .tscroll 永远拿不到约束——仪表盘 g2 卡片横向撑爆页面即此因）；
     .wiz2 同理（数据管理模型 chip 条把卡片撑到 2000px+） */
  .grid>*{min-width:0}
  .wiz2>*{min-width:0}
  /* 触控目标：通用输入 40px、mini 38px、复选 18px（font 16 防 iOS 聚焦缩放） */
  input.search,input.txt,select.sel{height:40px}
  input.mini,select.mini{height:38px}
  .op input{height:36px;width:110px}
  input[type="checkbox"]{width:18px;height:18px;accent-color:var(--primary)}
  .login-card input{height:44px}
  /* 卡片/抽屉留白与安全区 */
  .card{padding:14px}
  .mrow .mbody{padding:12px}
  .edrawer{padding:16px 16px calc(28px + env(safe-area-inset-bottom))}
  .capop{padding:11px 12px}
  .capop .btn{height:36px !important;padding:0 14px !important}
  .pfield{margin-bottom:13px}
  /* 弹窗 → 底部动作面板（sheet）：全宽、拇指可达、上滑出现 */
  .modal-mask{padding:0;align-items:flex-end}
  .modal-card{width:100%;max-width:100%;max-height:92vh;max-height:92dvh;
    border-radius:14px 14px 0 0;
    padding:16px 16px calc(22px + env(safe-area-inset-bottom))}
  /* 数据管理：模型列表竖列（68vh 占满首屏）→ 横滑 chip 条 */
  .wiz2 > .card:first-child{max-width:100% !important}
  .wiz2 > .card:first-child h3{margin-bottom:8px}
  .wiz2 > .card:first-child > div{flex-direction:row !important;flex-wrap:nowrap !important;
    max-height:none !important;overflow-x:auto !important;overflow-y:hidden !important;gap:6px}
  .wiz2 > .card:first-child > div > a{flex:0 0 auto;white-space:nowrap;
    border:1px solid var(--border);padding:7px 12px !important;border-radius:8px}
  .wiz2 > .card:first-child > div > a .muted{display:none}   /* chip 上不显示"只读"角标 */
}

/* ---------- 手机端仪表盘密度（dashboard-optimize-20260904 反馈：薄内容卡片整行太浪费） ----------
   置于文件末尾以覆盖上方 ≤880px 的 g4 单列规则：现在卡与 KPI 两列，
   内容丰富的大卡（链路健康/漏斗/预测器）仍单列不挤压；卡片内边距与间距同步收紧 */
@media (max-width:880px){
  .grid{gap:10px;margin-bottom:10px}
  .card{padding:12px 14px;margin-bottom:10px}
  .dash-top{margin-bottom:10px}
  .g4{grid-template-columns:repeat(2,1fr)}
  .stat .num{font-size:20px}
  .spark{height:22px;margin-top:6px}
}

/* ---------- 手机端编辑抽屉/向导表单行规整（编辑页输入框、按钮排版凌乱反馈） ----------
   病灶：抽屉表单行 .trow 全靠 flex-wrap + inline 定宽（label width:70px、
   input width:220px/110px…），手机上换行位置随机、控件不吃满、右缘参差。
   思路与 PC 满高布局一致——媒体块内定点覆盖、模板零重排：标签保持定宽在左，
   控件 flex 吃满剩余宽度；flex-basis 兼作"放不下才换行"的临界宽度
   （flex 布局中 flex-basis 优先于 inline width 参与计算，无需逐个去掉模板定宽） */
@media (max-width:880px){
  /* 换行段之间留缝，wrap 后上下行不贴成一坨 */
  .edrawer .trow,.modal-card .trow,.card .trow,.capgrid,.cap-row{row-gap:8px}
  /* 标签放开 PC 定宽：长标签（如 Home Assistant）不被输入框盖住；
     控件反正 flex 吃满到右缘，行内观感不受标签宽度差影响 */
  .edrawer .trow span.muted,.card .trow span.muted{width:auto !important}
  /* 但行首标签恢复 70px 最小定宽（auto 只放开"上限"）：纯 auto 让短标签行
     （名称/类型 vs 用户名/密码）控件左缘随标签长短逐行漂移 12px 上下——
     定时/平台/数据管理/自动化左列全部中招；min-width 保短标签对齐成列，
     长标签仍自然变宽（只放开上限不下压下限）。仅行首（:first-child）——
     行中的 muted 片段（时段 ~ 分隔、行尾提示）不吃定宽 */
  .edrawer .trow > span.muted:first-child,
  .card .trow > span.muted:first-child{min-width:70px}
  /* 表单控件吃满剩余宽度（系统设置列表式：标签在左、控件向右铺满） */
  .edrawer .trow input.search,.edrawer .trow input.txt,.edrawer .trow select.sel,
  .edrawer .trow textarea.payload,
  .modal-card .trow input.txt,.modal-card .trow select.sel,
  .card .trow input.txt,.card .trow select.sel{flex:1 1 150px;width:auto;min-width:0}
  /* 触发器/条件/动作等一行多控件的 mini 控件用小一档临界值，尽量并排放下 */
  .edrawer .trow input.txt.mini,.edrawer .trow select.sel.mini,
  .card .trow input.txt.mini,.card .trow select.sel.mini{flex:1 1 110px}
  /* 能力编辑器 cap-row 小输入同理（key/名称、min/max 成对并排，枚举选项 chip 自适应换行） */
  .edrawer .cap-row input.txt,.edrawer .cap-row select.sel{flex:1 1 80px;min-width:0;width:auto}
  .edrawer .trow input[type="range"]{flex:1 1 140px;width:auto;min-width:0}
  /* 文本域独占整行（能力编辑器 JSON 框包在 inline flex:1 的包装 div 里，
     样式表 flex 压不住内联——!important 覆盖，让包装独占标签下一行再撑满） */
  .edrawer .trow textarea.payload{flex:1 1 100%;min-width:280px;width:100%}
  .edrawer .trow > div{flex:1 1 100% !important}
  /* 抽屉底部保存按钮行（.ed-foot）与弹窗按钮行：满宽等分，拇指可达且对齐 */
  .edrawer .ed-foot{display:flex;gap:8px;margin-top:14px}
  .edrawer .ed-foot .btn{flex:1}
  .modal-card .modal-foot .btn{flex:1}
}

/* ---------- 排查效率四件套 + 问 DIoT（2026-09-06，console-backlog-20260906 §1/§3） ---------- */
/* C StateRecord 历史迷你曲线：viewBox 100×40 拉伸绘制 + non-scaling-stroke 线宽恒定 */
.histcharts{display:flex;flex-direction:column;gap:8px;margin-bottom:10px}
.histchart{border:1px solid var(--border);border-radius:9px;padding:8px 10px;background:var(--card)}
.hc-svg{width:100%;height:56px;display:block}
/* F 自动化试跑结果 */
.drybox{margin-top:12px;border:1px solid var(--border);border-radius:9px;
  padding:10px 12px;background:var(--card)}
.drybox .trow{font-size:12px}
/* H 映射编辑器 map 算子键值对（设备值→系统值 行组） */
.mappairs{display:inline-flex;flex-direction:column;gap:3px;
  /* 左侧虚线缩进：键值对组在读感上从属于 map 算子 chip，与链上其余 chip 分层；
     行级 ✕（删单对）与算子级 ✕（删整个 map）不再混读成一串 */
  padding-left:8px;margin-left:2px;border-left:1px dashed var(--border)}
.mappair{display:inline-flex;align-items:center;gap:3px}
.mappair .arrow{color:var(--muted)}
.op input{min-width:0}
.op.err{border-color:var(--danger)}
/* 映射编辑器 cap-row 的「标签+控件」成对包裹：窄卡里换行只发生在对与对之间
   （此前 topic 标签行尾、输入框孤行头的拆对折行）；控件 flex 吃满对内剩余宽 */
.cap-row .pair{display:inline-flex;align-items:center;gap:6px;white-space:nowrap;flex:1;min-width:0}
/* G 问 DIoT 抽屉：自身整高 flex——日志区内滚 + 底部输入固定。
   底部内边距补 env(safe-area-inset-bottom)（≤880 全屏抽屉时 iPhone 底部
   指示条不压输入框；桌面 env()=0 无影响） */
.askdrawer{display:flex;flex-direction:column;overflow:hidden;
  padding:18px 20px calc(14px + env(safe-area-inset-bottom))}
.asklog{flex:1;min-height:0;overflow-y:auto;display:flex;flex-direction:column;
  gap:10px;padding:10px 2px 12px}
/* 三段式头部：.ed-head 全局 align-items:flex-start 供多行标题抽屉用，问 DIoT
   单行头（15px 标题 / 28px 清空 / 34px 关闭）改垂直居中同轴；底边描边与输入区
   顶边描边呼应，明确「头部 / 聊天区 / 输入区」分段。头部与输入行 flex-shrink:0
   锁死不压缩，抽屉高度变化全部由 asklog（flex:1）吸收 */
.askdrawer .ed-head{align-items:center;flex-shrink:0;margin-bottom:0;
  padding-bottom:10px;border-bottom:1px solid var(--border)}
.askdrawer .ed-head .btn{height:28px;padding:0 12px;font-size:12.5px}
@media (max-width:880px){
  .askdrawer .ed-head .btn{height:36px;font-size:13px}
  /* 手机端 16px 字号行高 24：输入框单行 40px（24 行高 + 14 padding + 2 描边），
     与发送按钮（stretch 拉齐）同高。媒体查询不加特异性——此规则此前放在文件
     前部的 ≤880 块里被同特异性的基础 .askta 37px 按源序反压，40px 从未生效
     （37px 盒装 24px 行高内容超 3px），加 .askdrawer 前缀提特异性后真生效 */
  .askdrawer .askta{height:40px;min-height:40px}
}
.askmsg{display:flex}
.askmsg.user{justify-content:flex-end}
.askmsg.user .askbody{align-items:flex-end}
.askmsg.user .askmeta{flex-direction:row-reverse}
.askbubble{padding:8px 12px;border-radius:12px;font-size:13.5px;
  line-height:1.65;white-space:pre-wrap;word-break:break-word;background:var(--ask-l)}
.askmsg.user .askbubble{background:var(--primary);color:#fff}
.askmsg.err .askbubble{background:var(--danger-bg);border:1px solid var(--danger);
  color:var(--danger)}
.askmeta{display:flex;align-items:center;gap:8px;min-height:14px;
  padding:0 4px;font-size:10.5px;color:var(--muted)}
.askop{border:none;background:none;padding:0;color:var(--muted);font-size:10.5px;
  cursor:pointer;opacity:0;transition:opacity .15s}
.askmsg:hover .askop{opacity:1}
.askop:hover{color:var(--primary);text-decoration:underline}
@media (hover:none){.askop{opacity:.75}}   /* 触屏无 hover：小字常显 */
/* 助手回答轻量 markdown 排版（mdLite 白名单产物；code 底用 --card 在 chip 底气泡上有对比） */
.askhtml p{margin:0}
.askhtml p + p{margin-top:6px}
.askhtml ul{margin:2px 0;padding-left:18px}
.askhtml li{margin:2px 0}
.askhtml code{font-family:var(--mono);font-size:12px;background:var(--card);
  border:1px solid var(--border);border-radius:4px;padding:0 4px}
.askhtml pre.askcode{font-family:var(--mono);font-size:11.5px;background:var(--card);
  border:1px solid var(--border);border-radius:6px;padding:7px 9px;margin:4px 0;
  overflow-x:auto;white-space:pre}
/* 「思考中」三点跳动 */
.typing{display:inline-flex;align-items:center;gap:4px;padding:12px 14px}
.typing span{width:6px;height:6px;border-radius:50%;background:var(--muted);
  animation:askdot 1.2s infinite ease-in-out}
.typing span:nth-child(2){animation-delay:.15s}
.typing span:nth-child(3){animation-delay:.3s}
@keyframes askdot{0%,80%,100%{opacity:.25;transform:translateY(0)}
  40%{opacity:1;transform:translateY(-3px)}}
/* 空态引导：标题 + 可点击示例 chips */
.askempty{margin:auto 0;padding:0 6px}
.askempty-h{font-size:15px;font-weight:700;margin-bottom:6px}
.askchips{display:flex;flex-wrap:wrap;gap:7px;margin-top:12px}
.askchip{border:1px solid var(--border);background:var(--card);color:var(--text);
  border-radius:14px;padding:5px 12px;font-size:12px;cursor:pointer}
.askchip:hover{border-color:var(--primary);color:var(--primary);background:var(--primary-bg)}
.askchip:disabled{opacity:.5;cursor:default}
.askinput{display:flex;gap:8px;padding-top:10px;border-top:1px solid var(--border);
  align-items:stretch;flex-shrink:0}
/* textarea 显式描边/底色/文字色：原先吃 UA 默认（底色恒白，夜间模式下
   color:var(--text) 浅色文字落在白底上看不清）。单行时上下对称 padding =
   文字垂直居中；高度 37px（行高 21 + 上下 7px padding + 描边 2px）与发送
   按钮等高（按钮 height:auto 靠 stretch 拉齐），多行增高时按钮同步撑开。
   askGrow 内联写 height（scrollHeight 不含描边，+2 补偿）；CSS 只兜底初始/上限 */
.askta{flex:1;min-width:0;resize:none;height:37px;min-height:37px;max-height:120px;
  line-height:1.5;padding:7px 11px;border:1px solid var(--border);border-radius:8px;
  background:var(--input-bg);color:var(--text);overflow-y:auto}
.askinput .btn{height:auto;min-height:37px}
/* 清空两段式确认态 */
.askclear-armed{color:var(--danger);border-color:var(--danger)}

/* 问 DIoT 二轮：草稿卡片 + 会话气泡组（2026-09-06）；类型色条三轮补 */
.askbody{display:flex;flex-direction:column;gap:4px;max-width:88%;min-width:0}
.askdraft{border:1px solid var(--border);border-radius:10px;background:var(--card);
  padding:9px 11px;font-size:12.5px;width:100%}
.askdraft.dk-auto{border-left:3px solid #3b82f6}
.askdraft.dk-scene{border-left:3px solid #8b5cf6}
.askdraft.dk-skill{border-left:3px solid #06b6d4}
.askdraft.dk-schedule{border-left:3px solid #f59e0b}
.askdraft.dk-cmd{border-left:3px solid #10b981}
.ad-h{display:flex;align-items:center;gap:6px;font-weight:600;margin-bottom:4px}
.ad-name{font-size:13px;font-weight:600;margin-bottom:4px}
.ad-row{font-family:var(--mono);font-size:11.5px;line-height:1.9;word-break:break-all}
.ad-k{display:inline-block;min-width:18px;color:var(--muted)}
.ad-err{color:var(--danger);font-size:12px;margin-top:4px}

/* 预测器参数弹窗：entity_list 行编辑（[{entity_id}]/[{event,value}] 行对象列表） */
.pelist{display:flex;flex-direction:column;gap:6px;width:100%}
.perow{display:flex;gap:6px;align-items:center;flex-wrap:wrap}

/* 智慧屏「管理」抽屉分区化排版（2026-09-07 重构）：五区各司其职——
   运行控制（即时命令）/ 屏保设置 / 环境条指标 / HA / 屏幕名；
   .svgrid 参数两列网格（.svf=label+控件自适应满宽，.wide 跨两列给 min–max 双输入），
   .sv-act 区尾保存行；取代旧平铺 trow（保存语义混杂、参数挤行的根源） */
.svsec{border:1px solid var(--border);border-radius:10px;padding:12px 14px;margin-bottom:12px}
.svsec>h3{display:flex;align-items:center;gap:8px;margin:0 0 10px;font-size:13px;
  font-weight:600;color:var(--text);letter-spacing:.5px}
.svsec>h3 .badge{flex-shrink:0}
.svsub{font-size:12px;color:var(--muted);font-weight:600;margin:12px 0 8px}
.svgrid{display:grid;grid-template-columns:1fr 1fr;gap:8px 16px}
.svf{display:flex;align-items:center;gap:8px;min-width:0}
.svf>span{font-size:12px;color:var(--muted);flex-shrink:0;white-space:nowrap;width:56px}
.svf input,.svf select{flex:1 1 0;min-width:0}
.svf i{font-style:normal;flex-shrink:0}
.svf.wide{grid-column:1/-1}
.sv-act{display:flex;align-items:center;gap:8px;margin-top:12px;flex-wrap:wrap}
@media (max-width:560px){
  .svgrid{grid-template-columns:1fr}
  /* 标签维持 56px 定宽（桌面同款）——此前窄屏改 auto 宽，每行控件左缘参差不齐 */
  /* 抽屉 .trow 里 inline 定宽 select 改弹性填满（width 需 !important 压内联样式）：
     运行控制双 select 平分一行，屏保形态 / HA 满宽，不再留参差空档 */
  .svsec .trow select.sel{flex:1 1 150px;width:auto !important;min-width:0}
  /* 分区头允许整体换行、去掉弹性空隙——防「运行控制」标题被挤成两行 */
  .svsec>h3{flex-wrap:wrap}
  .svsec>h3>.sp{display:none}
  /* 实体抽屉「快捷操作」行（.capop 不在 .trow 体系内，上轮 880 块罩不到）：
     数字框弹性吃满（flex-basis 优先于内联 width 参与主轴计算）——num 行第一行
     = 名称+滑杆+数字框满宽到右缘，「下发」换行到第二行；尾提示 inline
     margin-left:auto 会把它甩到行尾孤儿位（第二行=左「下发」右「提示」中段大段
     空白），!important 压内联改回紧跟前元素——与按钮聚成一组 */
  .capop input.txt.mini{flex:1 1 72px;width:auto !important;min-width:0}
  .capop span.muted{margin-left:0 !important}
}
