* { box-sizing: border-box; }
html, body, #app { height: 100%; margin: 0; }
body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;
  background: #f1f5f9; color: #1e293b; font-size: 14px;
}

/* ---------- 模板导入条（从往期计划导入） ---------- */
.tpl-bar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  background: #f1f5f9; border: 1px dashed #cbd5e1; border-radius: 8px; padding: 8px 12px; margin-bottom: 4px; }
.tpl-lb { font-size: 13px; font-weight: 600; color: #334155; }
.tpl-hint { font-size: 12px; color: #94a3b8; }

/* ---------- 登录 ---------- */
.login-wrap { height: 100%; display: flex; align-items: center; justify-content: center;
  background: linear-gradient(135deg, #1e3a8a 0%, #2563eb 55%, #38bdf8 100%); }
.login-box { width: 420px; background: #fff; border-radius: 12px; padding: 34px 34px 24px; box-shadow: 0 20px 50px rgba(15,23,42,.25); }
.login-brand { display: flex; gap: 14px; align-items: center; margin-bottom: 24px; }
.login-brand h1 { font-size: 21px; margin: 0 0 4px; color: #0f172a; }
.login-brand p { margin: 0; font-size: 12px; color: #64748b; }
/* Logo 图片（web/img/logo-hw.png）：按原始宽高比显示，不拉伸 */
.logo { height: 44px; width: auto; border-radius: 8px; display: block; flex: none; object-fit: contain;
  box-shadow: 0 2px 8px rgba(15,23,42,.18); }
.captcha-row { display: flex; gap: 10px; width: 100%; align-items: center; }
.captcha-row .el-input { flex: 1; }
.captcha-img { width: 118px; height: 44px; border: 1px solid #dcdfe6; border-radius: 4px; cursor: pointer; background: #f8fafc; flex: none; }
.captcha-img:hover { border-color: #2563eb; }
/* 多租户：登录域输入（原生 input + datalist，历史域由 localStorage tenant_history 提供） */
.login-tenant-input { width: 100%; height: 40px; padding: 0 11px; font-size: 14px; color: #1f2937;
  border: 1px solid #dcdfe6; border-radius: 4px; background: #fff; transition: border-color .2s; }
.login-tenant-input:focus { outline: none; border-color: #2563eb; }
.login-tenant-hint { font-size: 12px; color: #94a3b8; line-height: 1.6; margin-top: 2px; }
/* 登录页域区（20261024i）：域显示在密码框下方，灰色小字、不起眼；
   点击"登录域"文字才展开修改区（复选框 + 手动输入新域），页面不常驻勾选框 */
.login-tenant-foot { width: 100%; }
.login-tenant-label { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: #94a3b8;
  cursor: pointer; user-select: none; line-height: 1.6; }
.login-tenant-label:hover, .login-tenant-label.is-on { color: #64748b; }
.login-tenant-label.is-on .login-tenant-editcue { color: #2563eb; }
.login-tenant-editcue { color: #cbd5e1; font-size: 11px; }
.login-tenant-sub { color: #cbd5e1; }
.login-tenant-edit { margin-top: 8px; display: flex; flex-direction: column; gap: 6px; align-items: flex-start; }
.login-tenant-edit .login-tenant-input { width: 100%; }
.login-tenant-blank { opacity: .85; }
.boot-loading { height: 100%; display: flex; align-items: center; justify-content: center; color: #64748b; background: #f1f5f9; }

/* ---------- 布局 ---------- */
.layout { display: flex; height: 100%; }
.sidebar { width: 216px; background: #1d2939; flex: none; overflow-y: auto; }
.brand { display: flex; gap: 10px; align-items: center; padding: 16px 16px 14px; border-bottom: 1px solid rgba(255,255,255,.07); }
.brand-text b { color: #fff; font-size: 15px; display: block; }
.brand-text span { color: #64748b; font-size: 11px; }
.menu { border-right: none; }
.menu-group { padding: 14px 20px 6px; font-size: 11px; color: #64748b; letter-spacing: 1px; }
.el-menu-item { height: 42px; line-height: 42px; }
.mi { display: inline-block; width: 20px; margin-right: 8px; text-align: center; opacity: .85; }
.menu-badge { position: absolute; right: 14px; top: 10px; }

.main { flex: 1; display: flex; flex-direction: column; min-width: 0; }
.topbar { height: 56px; background: #fff; border-bottom: 1px solid #e2e8f0; display: flex; align-items: center;
  justify-content: space-between; padding: 0 20px; flex: none; }
.crumb { font-size: 16px; font-weight: 600; }
.topbar .right { display: flex; align-items: center; gap: 10px; }
.uname { color: #334155; }
.content { flex: 1; overflow: auto; padding: 16px 20px 30px; }

/* ---------- 通用 ---------- */
.page { min-height: 100%; }
.toolbar { display: flex; gap: 10px; align-items: center; margin-bottom: 14px; flex-wrap: wrap; }
/* 人员工作报表工具栏（t 批补）：此前无样式，周期按钮组与日期选择器按 inline 基线对齐不平齐；
   与 .toolbar 同款 flex 垂直居中，导出按钮仍靠 margin-left:auto 靠右 */
.sf-toolbar { display: flex; gap: 10px; align-items: center; margin-bottom: 14px; flex-wrap: wrap; }
.panel { margin-bottom: 14px; }
.pager { margin-top: 14px; display: flex; justify-content: flex-end; }

.stat-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 14px; margin-bottom: 14px; }
.stat-card { background: #fff; border-radius: 10px; padding: 16px 18px; border-left: 4px solid #2563eb;
  box-shadow: 0 1px 3px rgba(15,23,42,.06); }
.stat-label { font-size: 13px; color: #64748b; }
.stat-value { font-size: 26px; font-weight: 700; margin: 6px 0 4px; }
.stat-value .unit { font-size: 12px; font-weight: 400; margin-left: 4px; color: #94a3b8; }
.stat-sub { font-size: 12px; color: #94a3b8; }

.todo-item { display: flex; justify-content: space-between; align-items: center; padding: 9px 0; border-bottom: 1px dashed #eef2f7; }
.todo-item:last-child { border-bottom: none; }
.todo-title { font-weight: 500; }
.todo-sub { font-size: 12px; color: #94a3b8; margin-top: 2px; }
.quick { display: flex; flex-wrap: wrap; gap: 10px; }

.qr-box { width: 130px; height: 130px; border: 1px solid #e2e8f0; border-radius: 8px; display: flex; align-items: center; justify-content: center; }
.qr-code-text { font-size: 11px; color: #64748b; margin-top: 6px; word-break: break-all; max-width: 130px; }

.photo-list { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.photo-item { position: relative; width: 78px; height: 78px; border: 1px solid #e2e8f0; border-radius: 6px; overflow: hidden; }

/* 选择文件按钮：label 包裹原生 input，input 透明铺满 label，点击直接落在原生 input 上，
   Edge/夸克均稳定拉起文件框（不依赖 JS .click()，也不 display:none） */
.file-btn {
  display: inline-block;
  position: relative;
  overflow: hidden;
  cursor: pointer;
  padding: 6px 14px;
  border: 1px solid #409eff;
  border-radius: 4px;
  background: #ecf5ff;
  color: #409eff;
  font-size: 13px;
  line-height: 1;
  user-select: none;
  vertical-align: middle;
}
.file-btn:hover { background: #d9ecff; border-color: #79bbff; }
.file-btn:focus-within { outline: 2px solid #409eff44; }
.file-input { position: absolute; left: 0; top: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; font-size: 0; }

.photo-item img { width: 100%; height: 100%; object-fit: cover; }
.photo-item span { position: absolute; right: 2px; top: 0; cursor: pointer; color: #ef4444; font-size: 16px; font-weight: 700;
  background: rgba(255,255,255,.85); border-radius: 50%; width: 18px; height: 18px; line-height: 16px; text-align: center; }

/* 巡检记录跟进列表 */
.follow-list { margin-top: 6px; display: flex; flex-direction: column; gap: 10px; }
.follow-item { background: #f8fafc; border: 1px solid #eef2f7; border-radius: 6px; padding: 8px 12px; }
.follow-meta { display: flex; align-items: center; justify-content: space-between; color: #64748b; font-size: 12px; margin-bottom: 4px; }
.follow-content { color: #1e293b; font-size: 14px; line-height: 1.6; white-space: pre-wrap; word-break: break-word; }

/* 拍照按钮与上传控制栏（已废弃，保留空注释） */
/* .upload-controls / .pending-list 已移除：上传改为选中即自动上传 */


.doc-block { background: #f8fafc; border: 1px solid #eef2f7; border-radius: 6px; padding: 10px 12px; color: #334155; line-height: 1.7; }

/* ---------- 打印/输出文档 ---------- */
.print-body { font-family: "Microsoft YaHei", sans-serif; padding: 28px 34px; color: #111; }
.doc-title { text-align: center; font-size: 22px; font-weight: 700; margin-bottom: 6px; }
.doc-meta { width: 100%; margin: 10px 0 18px; font-size: 12px; color: #555; border-collapse: collapse; }
.doc-meta td { padding: 3px 8px; }
.doc-table { width: 100%; border-collapse: collapse; margin: 8px 0 16px; font-size: 13px; }
.doc-table th, .doc-table td { border: 1px solid #333; padding: 7px 10px; text-align: left; vertical-align: top; }
.doc-table th { background: #f1f5f9; font-weight: 600; width: 110px; }
.doc-table tr td:nth-child(3) { width: 110px; }
.doc-block-print { border: 1px solid #333; padding: 10px; min-height: 60px; margin-bottom: 14px; line-height: 1.8; }
.doc-photos { display: flex; flex-wrap: wrap; gap: 10px; }
.doc-photos img { width: 150px; height: 110px; object-fit: cover; border: 1px solid #999; }
.print-actions { position: fixed; right: 20px; top: 20px; display: flex; gap: 8px; }
@media print { .print-actions { display: none; } }

/* ---------- 卡片网格（专项检查） ---------- */
.card-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 12px; }
.check-card { border: 1px solid #e2e8f0; border-radius: 8px; padding: 14px 16px; background: #fff; cursor: pointer; transition: all .15s; }
.check-card:hover { border-color: #409eff; box-shadow: 0 2px 8px rgba(64,158,255,0.15); }
.check-card.active { border-color: #409eff; background: #ecf5ff; box-shadow: 0 2px 12px rgba(64,158,255,0.2); }
.cc-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; }
.cc-title { display: flex; align-items: center; gap: 6px; font-size: 15px; }
.cc-meta { display: flex; flex-wrap: wrap; gap: 12px; color: #64748b; font-size: 12px; margin-bottom: 10px; }
.cc-progress { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.cc-progress .el-progress { flex: 1; }
.cc-progress .prog-text { font-size: 12px; color: #475569; min-width: 40px; text-align: right; }
.cc-actions { display: flex; gap: 4px; justify-content: flex-end; border-top: 1px dashed #e2e8f0; padding-top: 6px; }
.dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; }
.dot-pending { background: #fbbf24; }
.dot-doing { background: #3b82f6; }
.dot-done { background: #22c55e; }

/* ---------- 大屏监控 v3（左3/4 巡视+维修，右1/4 专项检查） ---------- */
.bs-wrap { position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; z-index: 9000; display: flex; flex-direction: column; background: #050a15; color: #e2e8f0; overflow: hidden; }

/* 顶部标题栏 */
.bs-hdr { display: flex; align-items: center; padding: 0 20px; height: 52px; background: linear-gradient(90deg, #020617, #0f172a 30%, #0f172a 70%, #020617); border-bottom: 1px solid #1e3a5f; flex-shrink: 0; }
.bs-hdr-left { display: flex; flex-direction: column; min-width: 90px; }
.bs-date { font-size: 16px; font-weight: 700; color: #38bdf8; font-variant-numeric: tabular-nums; }
.bs-week { font-size: 11px; color: #475569; }
.bs-hdr-center { flex: 1; text-align: center; }
.bs-title-text { font-size: 22px; font-weight: 900; background: linear-gradient(90deg, #7dd3fc, #38bdf8, #60a5fa, #7dd3fc); -webkit-background-clip: text; -webkit-text-fill-color: transparent; letter-spacing: 4px; animation: shimmer 3s linear infinite; background-size: 200% 100%; }
@keyframes shimmer { 0%{background-position:200% 0} 100%{background-position:-200% 0} }
.bs-hdr-right { display: flex; align-items: center; gap: 8px; min-width: 170px; justify-content: flex-end; }
.bs-clock { font-size: 22px; font-weight: 700; color: #f1f5f0; font-variant-numeric: tabular-nums; letter-spacing: 2px; }
.bs-refresh-hint { font-size: 16px; color: #38bdf8; transition: transform .3s; display: inline-block; }
.bs-refresh-hint.spin { animation: spin 1s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
.bs-update { font-size: 11px; color: #334155; }

/* 主体：左 3/4 + 右 1/4 */
.bs-main { display: flex; flex: 1; gap: 10px; padding: 10px; overflow: hidden; min-height: 0; }
.bs-left { flex: 3; min-width: 0; display: flex; flex-direction: column; gap: 10px; }
/* 右侧「上=专项检查 / 下=手机端二维码与备案」，与左侧 巡视/维修 两行对齐 */
.bs-right { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 10px; }

/* 左侧两个区块 */
.bs-section { flex: 1; min-height: 0; display: flex; flex-direction: column; border-radius: 10px; border: 1px solid #1e3a5f; overflow: hidden; padding: 10px 12px; }
.bs-sec-insp { background: linear-gradient(180deg, #0a1a2e 0%, #0a1628 50%); }
.bs-sec-mnt { background: linear-gradient(180deg, #1a0e0a 0%, #0a1628 50%); }
.bs-sec-spc { background: linear-gradient(180deg, #0a1a0e 0%, #0a1628 30%); }

/* 大屏右下：手机端二维码 + 备案信息 */
.bs-qr-block {
  position: relative; flex-shrink: 0; overflow: hidden;
  display: flex; flex-direction: column; align-items: center; gap: 7px;
  padding: 12px 14px 13px;
  border-radius: 12px;
  border: 1px solid rgba(56, 189, 248, .28);
  background: linear-gradient(165deg, rgba(13, 38, 64, .96) 0%, rgba(10, 22, 40, .96) 55%, rgba(9, 30, 46, .96) 100%);
  box-shadow: 0 8px 22px rgba(0, 0, 0, .35), inset 0 0 24px rgba(56, 189, 248, .06);
}
/* 顶部一道高光，让卡片在深色大屏上立起来 */
.bs-qr-block::before {
  content: ''; position: absolute; inset: -1px -1px auto -1px; height: 2px;
  background: linear-gradient(90deg, transparent, #38bdf8, transparent); opacity: .75;
}
.bs-qr-frame {
  padding: 6px; border-radius: 10px; background: #fff;
  box-shadow: 0 0 14px rgba(56, 189, 248, .45), 0 2px 6px rgba(0, 0, 0, .3);
}
.bs-qr-img { width: 116px; height: 116px; display: block; border-radius: 6px; }
.bs-qr-label { font-size: 13px; font-weight: 600; color: #7dd3fc; letter-spacing: .5px; text-shadow: 0 0 10px rgba(56, 189, 248, .4); }
.bs-qr-sub { font-size: 11px; color: #64748b; letter-spacing: .5px; }
.bs-icp { font-size: 11px; color: #64748b; text-decoration: none; }
.bs-icp:hover { color: #94a3b8; }

/* 工作台首页底部：手机端二维码 + 备案信息 */
.home-foot {
  margin-top: 14px; display: flex; align-items: center; justify-content: center; gap: 16px;
  padding: 14px 20px; border-radius: 12px; border: 1px solid #e2e8f0;
  background: linear-gradient(120deg, #f8fafc 0%, #eff6ff 55%, #f8fafc 100%);
  box-shadow: 0 2px 12px rgba(37, 99, 235, .07);
}
.home-foot-qr { width: 72px; height: 72px; display: block; padding: 6px; background: #fff; border: 1px solid #e5e7eb; border-radius: 10px; box-shadow: 0 2px 8px rgba(15, 23, 42, .08); }
.home-foot-txt { display: flex; flex-direction: column; gap: 3px; }
.home-foot-tip { font-size: 14px; color: #1e293b; font-weight: 600; }
.home-foot-desc { font-size: 12px; color: #64748b; }
.home-foot-icp { font-size: 12px; color: #9ca3af; text-decoration: none; }
.home-foot-icp:hover { color: #6b7280; }

/* 区块标题 */
.sec-hdr { display: flex; align-items: center; gap: 10px; padding-bottom: 8px; border-bottom: 1px solid #1e3a5f; flex-shrink: 0; }
.sec-ico { font-size: 22px; }
.insp-ico { color: #38bdf8; text-shadow: 0 0 14px #38bdf8; }
.mnt-ico { color: #fb923c; text-shadow: 0 0 14px #fb923c; }
.spc-ico { color: #4ade80; text-shadow: 0 0 14px #4ade80; }
.sec-title { font-size: 18px; font-weight: 800; color: #f1f5f9; letter-spacing: 2px; }
.sec-sub { font-size: 10px; color: #334155; letter-spacing: 1px; }
.sec-sum { margin-left: auto; display: flex; gap: 14px; align-items: baseline; }
.sec-sum .ss { font-size: 12px; color: #64748b; }
.sec-sum .ss b { font-size: 22px; font-weight: 900; font-variant-numeric: tabular-nums; margin-right: 2px; }

/* 颜色 */
.green-v { color: #4ade80; text-shadow: 0 0 20px #16a34a88; }
.yellow-v { color: #fbbf24; text-shadow: 0 0 20px #d9770688; }
.red-v { color: #f87171; text-shadow: 0 0 20px #dc262688; }
.blue-v { color: #60a5fa; text-shadow: 0 0 20px #2563eb88; }
.purple-v { color: #a78bfa; text-shadow: 0 0 20px #7c3aed88; }
.insp-v { color: #38bdf8; text-shadow: 0 0 20px #0ea5e888; }

/* 三大类卡片网格 */
.cat-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; margin-top: 10px; flex-shrink: 0; }
.cat-card { background: #111d32; border-radius: 9px; border: 1px solid #1e3a5f; padding: 8px 10px; display: flex; flex-direction: column; }
.mnt-card { border-left: 3px solid #fb923c; }
.cat-hdr { display: flex; align-items: center; gap: 6px; margin-bottom: 8px; }
.cat-ico { font-size: 14px; color: #38bdf8; }
.cat-name { font-size: 14px; font-weight: 800; color: #f1f5f9; letter-spacing: 1px; }
.cat-total { margin-left: auto; font-size: 16px; font-weight: 900; color: #38bdf8; font-variant-numeric: tabular-nums; }
.cat-total i { font-size: 10px; color: #475569; font-style: normal; margin-left: 2px; }
.cat-urgent { margin-left: auto; font-size: 12px; font-weight: 800; color: #f87171; background: #7f1d1d33; border: 1px solid #7f1d1d66; border-radius: 10px; padding: 1px 8px; animation: blink 1.5s ease-in-out infinite; }

/* 卡片内 2x2 指标 */
.cat-stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px; }
.cs { text-align: center; background: #0d1b30; border-radius: 6px; padding: 6px 2px; }
.cs-v { display: block; font-size: 26px; font-weight: 900; line-height: 1.1; font-variant-numeric: tabular-nums; }
.cs-l { font-size: 11px; color: #64748b; margin-top: 2px; }

/* 列表区块（今日未完成巡检 / 待处理维修工单）——固定5行，多余滚动 */
.bs-list-block { display: flex; flex-direction: column; padding: 4px 12px 10px; flex: 1; min-height: 0; }
.lb-tit { font-size: 12px; color: #5b7aa8; font-weight: 700; margin: 4px 2px 6px; letter-spacing: 1px; display: flex; align-items: center; gap: 8px; }
.lb-count { background: #15233b; color: #6eb6ff; border-radius: 10px; padding: 0 8px; font-size: 11px; font-weight: 800; }
.lb-scroll { height: 180px; overflow-y: auto; display: flex; flex-direction: column; gap: 5px; }
.lb-scroll::-webkit-scrollbar { width: 4px; }
.lb-scroll::-webkit-scrollbar-track { background: transparent; }
.lb-scroll::-webkit-scrollbar-thumb { background: #1e3a5f; border-radius: 2px; }
.lb-row { display: flex; align-items: center; gap: 8px; padding: 6px 10px; border-radius: 6px; background: #101e33; border-left: 3px solid #1e3a5f; }
.lb-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; background: #475569; }
.lb-name { font-size: 14px; color: #dbe7f5; font-weight: 600; flex: 0 0 30%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lb-plan { flex: 1; font-size: 12px; color: #6b86ab; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lb-tag { font-size: 11px; font-weight: 700; padding: 1px 8px; border-radius: 3px; flex-shrink: 0; }
.lb-empty { color: #3a5a82; font-size: 13px; text-align: center; padding: 24px; }
.lb-tip { font-size: 11px; color: #4ade80; font-weight: 600; }

/* 三分内容框：登机桥 / 电梯 / 行李系统 */
.todo-split { display: flex; gap: 8px; flex: 1; min-height: 0; }
.todo-col { flex: 1; min-width: 0; display: flex; flex-direction: column; background: #0c1728; border: 1px solid #16273f; border-radius: 8px; overflow: hidden; }
.tc-hdr { display: flex; align-items: center; gap: 6px; padding: 5px 8px; background: linear-gradient(90deg, #14263f, #101d31); border-bottom: 1px solid #16273f; flex-shrink: 0; }
.tc-ico { font-size: 12px; color: #6eb6ff; flex-shrink: 0; }
.tc-name { flex: 1; font-size: 12px; font-weight: 800; color: #b9cde6; letter-spacing: 1px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tc-count { background: #1b2f4b; color: #6eb6ff; border-radius: 9px; padding: 0 7px; font-size: 11px; font-weight: 800; font-variant-numeric: tabular-nums; }
/* 每框固定显示 5 行，超出向上滚动 */
.tc-scroll { height: 176px; overflow-y: auto; padding: 5px 6px; display: flex; flex-direction: column; gap: 5px; }
.tc-scroll::-webkit-scrollbar { width: 4px; }
.tc-scroll::-webkit-scrollbar-track { background: transparent; }
.tc-scroll::-webkit-scrollbar-thumb { background: #1e3a5f; border-radius: 2px; }
.tc-scroll .lb-row { padding: 5px 7px; gap: 6px; }
.tc-scroll .lb-name { font-size: 13px; flex: 0 0 38%; }
.tc-scroll .lb-plan { font-size: 11px; }
.tc-scroll .lb-tag { font-size: 10px; padding: 1px 6px; }
.tc-scroll .lb-empty { padding: 30px 0; font-size: 12px; }

/* 状态点配色（巡检/维修工单状态） */
.st-pending { background: #f59e0b; box-shadow: 0 0 6px #f59e0b; }
.st-doing { background: #38bdf8; box-shadow: 0 0 6px #38bdf8; }
.st-overdue { background: #ef4444; box-shadow: 0 0 7px #ef4444; animation: blink 1.5s ease-in-out infinite; }
.st-done { background: #22c55e; }
.st-assigned { background: #a855f7; box-shadow: 0 0 6px #a855f7; }
/* 等级点配色（维修工单） */
.lv-urgent { background: #ef4444; box-shadow: 0 0 7px #ef4444; animation: blink 1.5s ease-in-out infinite; }
.lv-high { background: #f97316; box-shadow: 0 0 6px #f97316; }
.lv-mid { background: #fbbf24; }
.lv-low { background: #60a5fa; }
/* 状态标签配色 */
.tg-pending { background: #713f1233; color: #fbbf24; border: 1px solid #713f1255; }
.tg-doing { background: #0c4a6e33; color: #38bdf8; border: 1px solid #0c4a6e55; }
.tg-overdue { background: #7f1d1d33; color: #f87171; border: 1px solid #7f1d1d55; }
.tg-done { background: #14532d33; color: #4ade80; border: 1px solid #14532d55; }
.tg-assigned { background: #581c8733; color: #c084fc; border: 1px solid #581c8755; }
.tg-cancel { background: #1e293b; color: #64748b; border: 1px solid #33415555; }

/* 右侧专项检查计划列表 */
.plan-list { flex: 1; overflow-y: auto; padding: 8px 10px 12px; display: flex; flex-direction: column; gap: 9px; min-height: 0; }
.plan-list::-webkit-scrollbar { width: 3px; }
.plan-list::-webkit-scrollbar-thumb { background: #1e3a5f; border-radius: 2px; }
.plan-item { background: #0d1b30; border-radius: 8px; padding: 9px 11px; border: 1px solid #1e3a5f; }
.plan-top { display: flex; align-items: center; justify-content: space-between; margin-bottom: 6px; }
.plan-name { font-size: 14px; font-weight: 700; color: #e2e8f0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.plan-rate { font-size: 15px; font-weight: 900; font-variant-numeric: tabular-nums; }
.plan-bar { height: 8px; background: #1e293b; border-radius: 4px; overflow: hidden; }
.plan-bar-fill { height: 100%; border-radius: 4px; transition: width 1s ease; }
.plan-bar-fill.r-green, .plan-rate.r-green { background: #22c55e; color: #4ade80; }
.plan-bar-fill.r-yellow, .plan-rate.r-yellow { background: #f59e0b; color: #fbbf24; }
.plan-bar-fill.r-red, .plan-rate.r-red { background: #ef4444; color: #f87171; }
.plan-badges { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 7px; }
.pb { font-size: 11px; font-weight: 700; padding: 1px 7px; border-radius: 3px; }
.pb.green { background: #14532d33; color: #4ade80; border: 1px solid #14532d55; }
.pb.yellow { background: #713f1233; color: #fbbf24; border: 1px solid #713f1255; }
.pb.red { background: #7f1d1d33; color: #f87171; border: 1px solid #7f1d1d55; }
.pb.gray { background: #1e293b; color: #64748b; border: 1px solid #33415555; }

.srow-empty { color: #1e293b; font-size: 12px; text-align: center; padding: 14px; }
@keyframes blink { 0%,100%{opacity:1} 50%{opacity:.3} }

/* ---------- 借还：编号自动索引下拉 ---------- */
.borrow-bar { position: relative; display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  background: #f8fafc; border: 1px dashed #cbd5e1; border-radius: 8px; padding: 12px 14px; margin-bottom: 14px; }
.borrow-bar .code-search { position: relative; }
.borrow-bar .suggest { position: absolute; z-index: 50; top: 42px; left: 0; width: 320px; max-height: 280px; overflow-y: auto;
  background: #fff; border: 1px solid #cbd5e1; border-radius: 8px; box-shadow: 0 10px 30px rgba(15,23,42,.18); }
.suggest .sg-item { display: flex; align-items: center; gap: 8px; padding: 8px 12px; cursor: pointer; border-bottom: 1px solid #f1f5f9; }
.suggest .sg-item:last-child { border-bottom: none; }
.suggest .sg-item:hover { background: #eff6ff; }
.suggest .sg-code { font-weight: 700; color: #1d4ed8; font-family: Consolas, monospace; }
.suggest .sg-name { flex: 1; color: #334155; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.suggest .sg-empty { padding: 10px 12px; color: #94a3b8; font-size: 12px; }

/* 已索引工具卡片 */
.match-card { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; background: #ecfdf5; border: 1px solid #6ee7b7;
  border-radius: 8px; padding: 10px 14px; margin-bottom: 14px; font-size: 13px; }
.match-card .mc-label { color: #047857; font-weight: 600; }
.match-card .mc-name { color: #065f46; }
.match-card .mc-kit { color: #475569; }
.match-warn { background: #fef3c7; border: 1px solid #fcd34d; color: #92400e; border-radius: 8px; padding: 10px 14px; margin-bottom: 14px; font-size: 13px; }

/* ============ 强密码强度提示 ============ */
.pw-meter { margin-top: 6px; }
.pw-meter .el-progress { margin-bottom: 4px; }
.pw-hint { font-size: 12px; line-height: 1.5; color: #b45309; }

/* ==========================================================================
   大屏监控 v4（2026-10-17 改版）—— 全部新增规则，前缀 bs2-，只追加不修改上方既有规则
   布局：标题栏 / KPI条 / 告警条 / 未完成维修工单(告警区) / 左巡视·右维修 / 底部专项通栏
   ========================================================================== */

/* ---------- 布局骨架 ---------- */
.bs2-main { flex: 1 1 auto; }
/* 左栏1.15 : 右栏 1 —— 巡检要放「当期占比环」，维修要放「占比环+故障结构+人员工作量」 */
.bs2-left { flex: 1.15; }
.bs2-right { flex: 1; }
.bs2-bottom { display: flex; gap: 10px; padding: 0 10px 10px; flex-shrink: 0; height: 196px; }
.bs2-spc { flex: 1; min-width: 0; }
.bs-sec-spc.bs2-spc { background: linear-gradient(180deg, #0a1a0e 0%, #0a1628 40%); }
.bs-sec-mnt { overflow-y: auto; }
.bs-sec-mnt::-webkit-scrollbar { width: 4px; }
.bs-sec-mnt::-webkit-scrollbar-thumb { background: #1e3a5f; border-radius: 2px; }

/* ---------- ① 顶部 KPI 条 ---------- */
.bs2-kpi-strip { display: grid; grid-template-columns: repeat(8, 1fr); gap: 8px; padding: 10px 10px 6px; flex-shrink: 0; }
.bs2-kpi { background: #0d1b30; border: 1px solid #1e3a5f; border-radius: 8px; padding: 6px 10px; min-width: 0; }
.bs2-kpi-lb { font-size: 11px; color: #64748b; display: flex; align-items: center; gap: 4px; white-space: nowrap; }
.bs2-kpi-ico { font-size: 11px; }
.bs2-kpi-v { font-size: 26px; font-weight: 900; line-height: 1.15; font-variant-numeric: tabular-nums; }
.bs2-kpi-v i { font-size: 11px; font-style: normal; font-weight: 700; margin-left: 1px; }
.bs2-kpi-note { font-size: 10px; color: #475569; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* 语气分级：只有危险项用红，色彩克制 */
.bs2-kpi-danger { border-color: #7f1d1d66; }
.bs2-kpi-danger .bs2-kpi-v { color: #f87171; }
.bs2-kpi-warn .bs2-kpi-v { color: #fbbf24; }
.bs2-kpi-ok .bs2-kpi-v { color: #4ade80; }
.bs2-kpi-info .bs2-kpi-v { color: #7dd3fc; }

/* ---------- ② 统一告警条 ---------- */
.bs2-alert-strip { display: flex; gap: 8px; overflow-x: auto; white-space: nowrap;
  padding: 5px 12px; border-radius: 8px; margin: 0 10px 6px; flex-shrink: 0; align-items: center; }
.bs2-alert-strip::-webkit-scrollbar { height: 3px; }
.bs2-alert-strip::-webkit-scrollbar-thumb { background: #7f1d1d66; border-radius: 2px; }
.bs2-alert-strip:not(.is-clear) { background: #2a0f14; border: 1px solid #7f1d1d66; }
.bs2-alert-strip.is-clear { background: #0a2018; border: 1px solid #14532d55; }
.bs2-al { font-size: 12px; font-weight: 700; padding: 1px 9px; border-radius: 4px; flex-shrink: 0; }
.bs2-al-red { color: #fca5a5; background: #7f1d1d33; border: 1px solid #7f1d1d66; }
.bs2-al-ok { color: #4ade80; }

/* ---------- 未完成维修工单（放在告警区，通栏单列表） ---------- */
.bs2-open-mnt { margin: 0 10px 6px; padding: 4px 10px 6px; flex-shrink: 0;
  background: #1a0e0a; border: 1px solid #4c2a17; border-radius: 9px; max-height: 168px; display: flex; flex-direction: column; }
.bs2-mnt-scroll { overflow-y: auto; display: flex; flex-direction: column; gap: 4px; min-height: 0; }
.bs2-mnt-scroll::-webkit-scrollbar { width: 4px; }
.bs2-mnt-scroll::-webkit-scrollbar-thumb { background: #3f2a17; border-radius: 2px; }
.bs2-row { display: flex; align-items: center; gap: 8px; padding: 4px 9px; border-radius: 5px;
  background: #10161f; border-left: 3px solid #334155; font-size: 12px; }
.bs2-row-urgent { border-left-color: #ef4444; background: #1c1013; }
.bs2-row-high { border-left-color: #f97316; }
.bs2-dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; background: #475569; }
.bs2-r-name { color: #dbe7f5; font-weight: 700; flex: 0 0 20%; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bs2-r-plan { flex: 1 1 auto; min-width: 0; color: #6b86ab; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bs2-r-assignee { flex: 0 0 68px; color: #8fa8c4; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bs2-r-cat { flex: 0 0 62px; color: #475f7d; font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bs2-r-hours { flex: 0 0 42px; text-align: right; color: #64748b; font-size: 11px; font-variant-numeric: tabular-nums; }
.bs2-r-hours.is-hot { color: #f87171; font-weight: 800; }
.bs2-tag { flex-shrink: 0; font-size: 10px; font-weight: 700; padding: 1px 7px; border-radius: 3px; }
.bs2-tg-pending { background: #713f1233; color: #fbbf24; border: 1px solid #713f1255; }
.bs2-tg-doing { background: #0c4a6e33; color: #38bdf8; border: 1px solid #0c4a6e55; }
.bs2-tg-overdue { background: #7f1d1d33; color: #f87171; border: 1px solid #7f1d1d55; }
.bs2-tg-assigned { background: #581c8733; color: #c084fc; border: 1px solid #581c8755; }
.bs2-tg-processing { background: #0c4a6e33; color: #38bdf8; border: 1px solid #0c4a6e55; }
.bs2-tg-verified { background: #14532d33; color: #4ade80; border: 1px solid #14532d55; }
.bs2-st-pending { background: #f59e0b; box-shadow: 0 0 6px #f59e0b; }
.bs2-st-doing { background: #38bdf8; box-shadow: 0 0 6px #38bdf8; }
.bs2-st-overdue { background: #ef4444; box-shadow: 0 0 7px #ef4444; animation: blink 1.5s ease-in-out infinite; }
.bs2-lv-urgent { background: #ef4444; box-shadow: 0 0 7px #ef4444; animation: blink 1.5s ease-in-out infinite; }
.bs2-lv-high { background: #f97316; box-shadow: 0 0 6px #f97316; }
.bs2-lv-mid { background: #fbbf24; }
.bs2-lv-low { background: #60a5fa; }

/* ---------- 区块小标题 ---------- */
.bs2-block-tit { display: flex; align-items: center; gap: 8px; font-size: 12px; color: #5b7aa8;
  font-weight: 700; letter-spacing: 1px; margin: 10px 0 6px; flex-wrap: wrap; flex-shrink: 0; }
.bs2-count { background: #15233b; color: #6eb6ff; border-radius: 10px; padding: 0 8px; font-size: 11px; font-weight: 800; }
.bs2-tip { font-size: 10px; color: #3f5b7d; font-weight: 600; letter-spacing: 0; }
/* 列表被 LIMIT 截断时的提示（数据真实存在，只是没全展示） */
.bs2-trunc { font-size: 10px; font-weight: 700; letter-spacing: 0; color: #fbbf24;
  background: #713f1222; border: 1px solid #713f1255; border-radius: 3px; padding: 0 6px; }
.bs2-src-tag { font-size: 10px; font-weight: 700; padding: 0 6px; border-radius: 3px; letter-spacing: 0; }
.bs2-src-tag.mnt { color: #fb923c; background: #7c2d1222; border: 1px solid #7c2d1266; }
.bs2-empty { color: #1e293b; font-size: 12px; text-align: center; padding: 16px; grid-column: 1 / -1; }

/* ---------- 分类筛选 chip（横向滚动，分类再多也不换行撑破） ---------- */
.bs2-tab-row { display: flex; gap: 5px; overflow-x: auto; white-space: nowrap; margin-left: auto; padding-bottom: 1px; }
.bs2-tab-row::-webkit-scrollbar { height: 3px; }
.bs2-tab-row::-webkit-scrollbar-thumb { background: #1e3a5f; border-radius: 2px; }
.bs2-cat-tab { font-size: 11px; color: #7f9ab8; background: #0f1c2f; border: 1px solid #1e3a5f;
  border-radius: 10px; padding: 1px 9px; cursor: pointer; flex-shrink: 0; font-weight: 600; }
.bs2-cat-tab i { font-style: normal; color: #475f7d; margin-left: 3px; font-size: 10px; }
.bs2-cat-tab.is-on { color: #0a1628; background: #38bdf8; border-color: #38bdf8; font-weight: 800; }
.bs2-cat-tab.is-on i { color: #0a1628; }

/* ---------- 动态分类自适应网格（auto-fit + minmax，分类多了自动换行） ---------- */
.bs2-dyn-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(158px, 1fr));
  gap: 8px; flex-shrink: 0; max-height: 208px; overflow-y: auto; padding-right: 2px; }
.bs2-dyn-grid::-webkit-scrollbar { width: 3px; }
.bs2-dyn-grid::-webkit-scrollbar-thumb { background: #1e3a5f; border-radius: 2px; }
@media (min-width: 1600px) {
  .bs2-dyn-grid { grid-template-columns: repeat(auto-fit, minmax(196px, 1fr)); }
}
.bs2-dyn-card { background: #111d32; border: 1px solid #1e3a5f; border-radius: 9px;
  padding: 9px 10px; display: flex; align-items: center; gap: 10px; min-width: 0; }
.bs2-dyn-card.is-unknown { opacity: .72; border-style: dashed; }
.bs2-dyn-meta { min-width: 0; flex: 1; }
.bs2-dyn-name { font-size: 13px; font-weight: 800; color: #f1f5f9;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bs2-dyn-sub { font-size: 11px; color: #64748b; margin-top: 3px; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; }
.bs2-dyn-sub .grn { color: #4ade80; font-weight: 700; }
.bs2-dyn-sub .red { color: #f87171; font-weight: 700; }
.bs2-dyn-sub2 { font-size: 10px; color: #3f5b7d; margin-top: 2px; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; }
.bs2-dyn-sub2 .red { color: #f87171; font-weight: 700; }
/* 紧凑模式：>6 个分类时隐藏次要信息，保证不挤不溢出 */
.bs2-dyn-many .bs2-dyn-card { padding: 6px 8px; }
.bs2-dyn-many .bs2-dyn-sub2 { display: none; }
.bs2-dyn-many .bs2-dyn-name { font-size: 12px; }
.bs2-dyn-many .bs2-ring { width: 58px; height: 58px; }
.bs2-dyn-many .bs2-ring svg { width: 58px; height: 58px; }

/* ---------- 环形占比（纯 SVG，无图表库；零依赖零泄漏，v-for 友好） ---------- */
.bs2-ring { position: relative; display: inline-flex; align-items: center; justify-content: center;
  width: 72px; height: 72px; flex-shrink: 0; }
.bs2-ring svg { transform: rotate(-90deg); display: block; }
.bs2-ring-track { stroke: #1e293b; }
.bs2-ring-fill { transition: stroke-dasharray .8s ease; }
.bs2-ring-fill.bs2-r-green { stroke: #22c55e; }
.bs2-ring-fill.bs2-r-yellow { stroke: #f59e0b; }
.bs2-ring-fill.bs2-r-red { stroke: #ef4444; }
.bs2-ring-center { position: absolute; inset: 0; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 0; }
.bs2-ring-num { font-size: 18px; font-weight: 900; color: #e2e8f0; line-height: 1;
  font-variant-numeric: tabular-nums; }
.bs2-ring-num i { font-size: 9px; font-style: normal; font-weight: 700; }
.bs2-ring-lb { font-size: 9px; color: #64748b; margin-top: 1px; }
/* 空态：灰环 + 破折号。0% 红环会被误读成"全都没做"，故不显示 */
.bs2-ring.is-empty .bs2-ring-num { color: #475569; }
.bs2-ring.is-empty .bs2-ring-fill { stroke: transparent; }

/* ---------- 故障结构占比：堆叠条 + 图例 ---------- */
.bs2-fault { flex-shrink: 0; }
.bs2-stack-bar { display: flex; height: 14px; border-radius: 7px; overflow: hidden; background: #1e293b; }
.bs2-stack-seg { height: 100%; flex-shrink: 0; transition: width .8s ease; min-width: 2px; }
.bs2-seg-other { background: #334155; }
.bs2-stack-legend { display: flex; flex-wrap: wrap; gap: 5px 14px; margin-top: 8px; }
.bs2-sl-item { display: flex; align-items: baseline; gap: 5px; font-size: 11px; }
.bs2-sl-dot { width: 8px; height: 8px; border-radius: 2px; flex-shrink: 0; align-self: center; }
.bs2-sl-name { color: #94a3b8; max-width: 110px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bs2-sl-v { color: #e2e8f0; font-weight: 800; font-variant-numeric: tabular-nums; }
.bs2-sl-p { color: #64748b; font-size: 10px; }
.bs2-sl-rate { font-size: 10px; font-weight: 700; }
.bs2-sl-rate.bs2-r-green { color: #4ade80; }
.bs2-sl-rate.bs2-r-yellow { color: #fbbf24; }
.bs2-sl-rate.bs2-r-red { color: #f87171; }

/* ---------- 人员今日工作量（每人一条堆叠条：巡检/专项/维修 + 协同虚底色） ---------- */
.bs2-staff-list { display: flex; flex-direction: column; gap: 6px; overflow-y: auto;
  min-height: 0; max-height: 208px; padding-bottom: 2px; }
.bs2-staff-list::-webkit-scrollbar { width: 3px; }
.bs2-staff-list::-webkit-scrollbar-thumb { background: #1e3a5f; border-radius: 2px; }
.bs2-staff-row { display: grid; grid-template-columns: 58px 44px 1fr 26px 74px;
  align-items: center; gap: 7px; font-size: 11px; }
.bs2-stf-name { color: #e2e8f0; font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bs2-stf-dept { color: #475569; font-size: 10px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bs2-stf-bar { display: flex; height: 12px; background: #1e293b; border-radius: 6px; overflow: hidden; }
.bs2-stf-seg { height: 100%; flex-shrink: 0; transition: width .8s ease; }
.bs2-seg-insp { background: #38bdf8; }
.bs2-seg-spc { background: #a855f7; }
.bs2-seg-mnt { background: #22c55e; }
/* 协同：虚化底色区分主口径（大屏口径含协同，但视觉上必须能与主口径分开） */
.bs2-seg-assist { background: repeating-linear-gradient(45deg, #64748b, #64748b 3px, #475569 3px, #475569 6px); }
.bs2-stf-total { color: #f1f5f9; font-weight: 900; text-align: right; font-variant-numeric: tabular-nums; }
.bs2-stf-detail { color: #64748b; font-size: 10px; text-align: right; white-space: nowrap; }
.bs2-staff-legend { display: flex; flex-wrap: wrap; gap: 4px 12px; font-size: 10px; color: #64748b;
  padding-top: 6px; margin-top: 2px; border-top: 1px solid #16273f; }
.bs2-staff-legend span { display: inline-flex; align-items: center; gap: 4px; }
.bs2-dots { width: 8px; height: 8px; border-radius: 2px; display: inline-block; }
.bs2-staff-un { color: #fbbf24; }

/* ---------- 专项检查通栏：每计划一个当期占比环 ---------- */
.bs2-plan-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 8px; overflow-y: auto; min-height: 0; padding: 8px 2px 2px; }
.bs2-plan-grid::-webkit-scrollbar { width: 3px; }
.bs2-plan-grid::-webkit-scrollbar-thumb { background: #1e3a5f; border-radius: 2px; }
.bs2-plan-card { display: flex; align-items: center; gap: 9px; background: #0d1b30;
  border: 1px solid #1e3a5f; border-radius: 9px; padding: 7px 10px; min-width: 0; }
.bs2-plan-card .bs2-ring { width: 66px; height: 66px; }
.bs2-plan-card .bs2-ring svg { width: 66px; height: 66px; }
.bs2-plan-card .bs2-ring-num { font-size: 16px; }
.bs2-plan-meta { min-width: 0; flex: 1; }
.bs2-plan-name { font-size: 13px; font-weight: 700; color: #e2e8f0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bs2-plan-sub { font-size: 10px; color: #475f7d; margin-top: 2px; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; }
.bs2-plan-badges { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 4px; }
.bs2-pb { font-size: 10px; font-weight: 700; padding: 0 6px; border-radius: 3px; white-space: nowrap; }
.bs2-pb.green { background: #14532d33; color: #4ade80; border: 1px solid #14532d55; }
.bs2-pb.yellow { background: #713f1233; color: #fbbf24; border: 1px solid #713f1255; }
.bs2-pb.red { background: #7f1d1d33; color: #f87171; border: 1px solid #7f1d1d55; }
.bs2-pb.gray { background: #1e293b; color: #7f9ab8; border: 1px solid #33415555; }

/* ---------- 二维码 + 备案（缩为右下角小图，备案信息保留可点击） ---------- */
.bs2-qr { flex-shrink: 0; width: 232px; display: flex; align-items: center; gap: 10px;
  padding: 10px 12px; border-radius: 10px; border: 1px solid rgba(56, 189, 248, .28);
  background: linear-gradient(165deg, rgba(13, 38, 64, .96) 0%, rgba(10, 22, 40, .96) 100%); }
.bs2-qr-frame { padding: 4px; border-radius: 8px; background: #fff; flex-shrink: 0;
  box-shadow: 0 0 12px rgba(56, 189, 248, .4); }
.bs2-qr-img { width: 96px; height: 96px; display: block; border-radius: 5px; }
.bs2-qr-txt { min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.bs2-qr-label { font-size: 11px; font-weight: 600; color: #7dd3fc; line-height: 1.35; }
.bs2-qr-sub { font-size: 10px; color: #64748b; line-height: 1.35; }

/* ==========================================================================
   大屏监控 v5（2026-10-17 第二轮改版 · 按计划画图 + 四区重构）
   全部新增规则，前缀 bs2- / bs-sec-staff / staff-*，只追加不修改上方既有规则
   布局：标题栏(52) / 三栏区①②③(flex:1) / 区④人员管理通栏(固定 208px)
   ========================================================================== */

/* ---------- 四区骨架 ---------- */
/* 三栏并排：巡检(计划卡最多) : 专项(计划卡较少) : 维修(环+柱图+工单列表，内容最多)
   比例 1.05 : 0.95 : 1.2 —— 维修列内容纵向最多（设备类型环 + 故障柱图 + 未完成工单列表）给最大份额，
   专项列每卡信息量最小（含当期/截止期次）给最小份额 */
.bs2-row3 { flex: 1 1 auto; display: grid; grid-template-columns: 1.05fr 0.95fr 1.2fr; gap: 10px; padding: 10px 10px 0; min-height: 0; overflow: hidden; }
.bs2-area { min-width: 0; overflow: hidden; }
/* v4 的 .bs-sec-mnt 带overflow-y:auto 会让整列滚动，v5 三栏必须各自内部滚动，整页不滚 */
.bs2-area.bs-sec-mnt { overflow: hidden; }

/* ---------- 区④ 人员管理：横跨底部通栏 ---------- */
.bs-sec-staff { flex-shrink: 0; height: 208px; margin: 10px; padding: 8px 12px; position: relative; }
.bs-sec-staff { background: linear-gradient(180deg, #0a1a2e 0%, #0a1628 60%); }
.bs-sec-staff .staff-hdr { margin-bottom: 4px; }
.staff-ico { color: #38bdf8; }
.bs2-staff-area .bs2-qr { position: absolute; right: 12px; top: 8px; bottom: 8px; width: auto; padding: 6px 10px; }
.bs2-staff-area .bs2-qr-img { width: 72px; height: 72px; }
.bs2-staff-area .bs2-staff-legend { padding-right: 210px; }

/* ---------- 区块小标题（v5 统一用 bs2-sub-tit，与 v4 bs2-block-tit 同风格） ---------- */
.bs2-sub-tit { display: flex; align-items: center; gap: 8px; font-size: 12px; color: #5b7aa8;
  font-weight: 700; letter-spacing: 1px; margin: 9px 0 5px; flex-wrap: wrap; flex-shrink: 0; }

/* ---------- 卡片滚动容器（列内各自滚动，保证整页无纵向滚动条） ---------- */
.bs2-card-scroll, .bs2-mini-scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto;
  display: flex; flex-direction: column; gap: 7px; padding: 2px; }
.bs2-card-scroll::-webkit-scrollbar, .bs2-mini-scroll::-webkit-scrollbar { width: 4px; }
.bs2-card-scroll::-webkit-scrollbar-thumb, .bs2-mini-scroll::-webkit-scrollbar-thumb { background: #1e3a5f; border-radius: 2px; }
.bs2-flex1 { flex: 1 1 auto; min-height: 0; }

/* ---------- 巡检/专项：按计划一计划一卡 ---------- */
.bs2-plan-qty { font-size: 11px; color: #7f9ab8; margin-top: 2px; font-variant-numeric: tabular-nums; }
.bs2-plan-qty b { color: #4ade80; font-size: 13px; font-weight: 900; }
.bs2-pb.blue { background: #0c4a6e33; color: #38bdf8; border: 1px solid #0c4a6e55; }

/* ---------- 维修区：设备类型小环卡（只渲染 total>0 的类型） ---------- */
.bs2-mini-scroll { flex-direction: row; flex-wrap: wrap; align-content: flex-start; overflow-y: auto; }
.bs2-mini-card { display: flex; align-items: center; gap: 7px; background: #0d1b30;
  border: 1px solid #1e3a5f; border-radius: 8px; padding: 5px 9px; min-width: 0; flex: 1 1 150px; max-width: 100%; }
.bs2-ring-sm { width: 52px; height: 52px; flex-shrink: 0; }
.bs2-ring-sm svg { width: 52px; height: 52px; }
.bs2-ring-sm .bs2-ring-num { font-size: 14px; }
.bs2-mini-meta { min-width: 0; flex: 1; }
.bs2-mini-name { font-size: 12px; font-weight: 700; color: #e2e8f0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bs2-mini-qty { font-size: 11px; color: #7f9ab8; font-variant-numeric: tabular-nums; }
.bs2-mini-sub { font-size: 10px; margin-top: 1px; }
.bs2-mini-sub .red { color: #f87171; font-weight: 700; }

/* ---------- 故障结构：竖向柱状图（柱内按设备类型分段着色） ---------- */
.bs2-col-chart { flex-shrink: 0; height: 132px; display: flex; align-items: flex-end; gap: 6px;
  padding: 4px 2px 0; overflow-x: auto; overflow-y: hidden; }
.bs2-col-chart::-webkit-scrollbar { height: 3px; }
.bs2-col-chart::-webkit-scrollbar-thumb { background: #1e3a5f; border-radius: 2px; }
.bs2-col-item { flex: 0 0 46px; display: flex; flex-direction: column; align-items: center; height: 100%; min-width: 0; }
.bs2-col-val { font-size: 11px; font-weight: 800; color: #e2e8f0; line-height: 1.2;
  font-variant-numeric: tabular-nums; flex-shrink: 0; }
.bs2-col-track { flex: 1 1 auto; width: 26px; min-height: 0; display: flex; align-items: flex-end;
  background: linear-gradient(180deg, #0f1c2f, #0a1628); border-radius: 4px 4px 0 0; }
.bs2-col-stack { width: 100%; display: flex; flex-direction: column-reverse; justify-content: flex-start;
  border-radius: 4px 4px 0 0; overflow: hidden; }
.bs2-col-seg { display: block; width: 100%; min-height: 2px; }
.bs2-col-name { font-size: 10px; color: #7f9ab8; margin-top: 3px; line-height: 1.15; text-align: center;
  width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex-shrink: 0; }
.bs2-col-pct { font-size: 9px; color: #475f7d; font-variant-numeric: tabular-nums; flex-shrink: 0; }

/* ---------- 设备类型图例（柱内分段配色） ---------- */
.bs2-cat-legend { display: flex; flex-wrap: wrap; gap: 3px 10px; font-size: 10px; color: #64748b;
  margin-top: 5px; flex-shrink: 0; max-height: 26px; overflow: hidden; }
.bs2-cl-item { display: inline-flex; align-items: center; gap: 4px; white-space: nowrap; }

/* ---------- 区④ 人员管理：横向铺开的竖向柱状图 ---------- */
/* 人员名在柱下方横排：1920 宽下扣除二维码 210px + 左右 padding，可用约 1660px；
   minmax(54px,1fr) 可同屏排下约 28 人，超过则横向滚动，不再旋转（旋转在 1080p 下最难读） */
.bs2-staff-chart { display: grid; grid-template-columns: repeat(auto-fit, minmax(54px, 1fr));
  gap: 4px; align-items: end; height: 126px; overflow-x: auto; overflow-y: hidden; padding-right: 200px; }
.bs2-staff-chart::-webkit-scrollbar { height: 3px; }
.bs2-staff-chart::-webkit-scrollbar-thumb { background: #1e3a5f; border-radius: 2px; }
.bs2-scol { display: flex; flex-direction: column; align-items: center; height: 100%; min-width: 0; }
.bs2-scol-val { font-size: 11px; font-weight: 800; color: #e2e8f0; line-height: 1.2; flex-shrink: 0;
  font-variant-numeric: tabular-nums; }
.bs2-scol-track { flex: 1 1 auto; width: 22px; min-height: 0; display: flex; align-items: flex-end;
  background: linear-gradient(180deg, #0f1c2f, #0a1628); border-radius: 3px 3px 0 0; }
.bs2-scol-stack { width: 100%; display: flex; flex-direction: column-reverse; border-radius: 3px 3px 0 0; overflow: hidden; }
.bs2-scol-seg { display: block; width: 100%; min-height: 0; }
.bs2-scol-name { font-size: 10px; color: #a8c0da; margin-top: 3px; line-height: 1.15; width: 100%;
  text-align: center; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex-shrink: 0; }
.bs2-scol-dept { font-size: 9px; color: #3f5b7d; line-height: 1.1; width: 100%; text-align: center;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex-shrink: 0; }

/* ---------- v5 补充：列内高度分配（保证 1920x1080 整页不出现纵向滚动条） ---------- */
/* 维修列纵向元素最多：设备类型环卡区限高 132px，故障柱图固定 132px，剩余高度全给未完成工单列表 */
.bs2-area .bs2-mini-scroll { flex: 0 1 auto; max-height: 132px; }
.bs2-area .bs2-mnt-scroll { flex: 1 1 auto; }

/* ==========================================================================
   大屏监控 v6（2026-10-17 第三轮· 满屏重排）—— 只追加，前缀 bs6- / bs2- 覆盖
   目标：1920×1080 单屏满屏，无纵向滚动条、无横向滚动条、无重叠/截断
   行高全部用 fr + clamp()，不写死 px 高度，不为固定人数写死列数
   ========================================================================== */

/* ---------- ① 整页骨架：头clamp + 三栏 1fr + 人员通栏 clamp ---------- */
.bs6-wrap { display: grid; grid-template-rows: auto minmax(0, 1fr) auto; gap: clamp(6px, .7vh, 10px);
  padding: clamp(6px, .7vh, 10px); }
/* 头部在 grid 里占auto，继承既有 52px 高度 */
.bs6-hdr { height: clamp(46px, 5.2vh, 58px); }
/* 三栏：巡检 1.05 : 专项 .95 : 维修 1.2 —— 维修列纵向内容最多（环卡+柱图+工单列表）取最大份额；
   专项列每卡信息量最小取最小份额。fr 弹性，人数/计划数增减不改变列宽比例 */
.bs6-grid { display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr) minmax(0, 1.2fr);
  gap: clamp(8px, .8vw, 14px); padding: 0; min-height: 0; overflow: hidden; }
/* 人员通栏：高度随视口在 188~248px 之间自适应 */
.bs6-staff { height: clamp(188px, 21vh, 248px); margin: 0; min-height: 0; }

/* ---------- ② 区卡片通用：内部用 grid 行分配，任何区块都不撑破卡片 ---------- */
.bs6-card { display: grid; grid-template-rows: auto auto minmax(0, 1fr); gap: 0; min-width: 0; min-height: 0; overflow: hidden; }
/* 区头：图标 + 区名 + 英文 + 右侧汇总数字 */
.bs6-card-hd { display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding-bottom: clamp(4px, .5vh, 8px); border-bottom: 1px solid rgba(56, 189, 248, .16); }
.bs6-card-tit { font-size: clamp(15px, 1.15vw, 20px); font-weight: 800; color: #e8f1fb; letter-spacing: 2px; }
/* 区头汇总数字：关键数字层级，最大号 */
.bs6-sum { display: flex; gap: clamp(10px, 1vw, 20px); margin-left: auto; flex-wrap: wrap; }
.bs6-sum .ss { display: inline-flex; align-items: baseline; gap: 5px; }
.bs6-num-lg { font-size: clamp(17px, 1.35vw, 26px); font-weight: 900; line-height: 1;
  font-variant-numeric: tabular-nums; }
.bs6-unit { font-style: normal; font-size: clamp(10px, .72vw, 12px); color: #64748b; font-weight: 600; }

/* ---------- ③ 区块小标题（层级：区标题 > 区块标题 > 卡片名 > 说明） ---------- */
.bs6-sub { margin: clamp(6px, .8vh, 10px) 0 clamp(4px, .5vh, 7px); font-size: clamp(11px, .78vw, 13px); }
.bs6-em { font-style: normal; font-size: clamp(9px, .62vw, 11px); color: #3f5b7d; font-weight: 600;
  letter-spacing: 0; margin-left: 8px; }
.bs6-note { font-size: clamp(9px, .62vw, 11px); }

/* ---------- ④ 滚动容器：卡片区纵向自适应 + 内部滚动，整页不滚 ---------- */
.bs6-scroll { min-height: 0; padding: 2px 4px 2px 0; }

/* ---------- ⑤ 计划卡（巡检/ 专项共用，一个计划一张） ---------- */
.bs6-pcard { padding: clamp(6px, .7vh, 10px) clamp(8px, .7vw, 14px); gap: clamp(8px, .7vw, 14px);
  border-radius: 10px; }
.bs6-pcard .bs2-ring { width: clamp(52px, 3.6vw, 68px); height: clamp(52px, 3.6vw, 68px); }
.bs6-pcard .bs2-ring svg { width: 100%; height: 100%; }
.bs6-pname { font-size: clamp(13px, .92vw, 16px); }
.bs6-qty { font-size: clamp(11px, .78vw, 13px); }
.bs6-qty b { font-size: clamp(14px, 1vw, 18px); }
.bs6-badges { margin-top: clamp(3px, .35vh, 6px); }

/* ---------- ⑥ 维修区：内部四段（环卡 / 柱图 / 标题 / 工单列表）按fr 分配 ---------- */
/* 维修区 7 行：区头 / 环卡标题 / 环卡区 / 柱图标题 / 柱图区 / 工单标题 / 工单列表
   环卡区auto（卡片自撑，不写死高度），柱图区与工单列表各占一份 fr 吃剩余高度 */
.bs6-mnt { grid-template-rows: auto auto auto auto minmax(0, 1fr) auto minmax(0, 1fr); }
.bs6-mini { min-height: 0; max-height: none; flex: none; }
/* 设备类型小卡：flex 自适应换行，数量增减不占死位置 */
.bs6-mcard { flex: 1 1 clamp(140px, 9vw, 200px); padding: clamp(4px, .5vh, 7px) clamp(7px, .6vw, 12px); gap: 8px; }
.bs6-mname { font-size: clamp(11px, .78vw, 14px); }
.bs6-mqty { font-size: clamp(10px, .7vw, 12px); }
/* 故障柱图区：柱图 + 图例整体按fr 吃剩余高度 */
.bs6-fault { min-height: 0; display: grid; grid-template-rows: minmax(0, 1fr) auto; gap: 4px; }
.bs6-col { height: 100%; min-height: 0; gap: clamp(4px, .4vw, 8px); }
/* 柱宽弹性：1 1 + min-width，分类增减时列宽自适应收缩，避免出现横向滚动条 */
.bs6-colitem { flex: 1 1 clamp(34px, 2.5vw, 56px); max-width: clamp(34px, 2.5vw, 56px); }
.bs6-colval { font-size: clamp(11px, .75vw, 13px); }
.bs6-colname { font-size: clamp(9px, .62vw, 11px); }
.bs6-colpct { font-size: clamp(9px, .58vw, 10px); }
.bs6-legend { max-height: none; margin-top: 0; gap: 3px clamp(8px, .8vw, 14px);
  font-size: clamp(9px, .62vw, 11px); }
.bs6-mtodo { min-height: 0; }
/* 工单行：加大行高与字号，行数多时内部滚动 */
.bs6-mtodo .bs2-row { padding: clamp(4px, .45vh, 7px) 10px; }
.bs6-mtodo .bs2-r-name { font-size: clamp(11px, .75vw, 13px); }

/* ---------- ⑦ 区④ 人员：柱图横向铺开，列宽 minmax 自适应人数 ---------- */
.bs6-staff { display: grid; grid-template-rows: auto minmax(0, 1fr); position: relative; }
/* 区头右侧预留二维码宽度，图例与汇总数字不被压住 */
.bs6-staff .bs6-card-hd { flex-wrap: nowrap; padding-right: clamp(160px, 12vw, 240px); }
.bs6-staff .bs6-legend { margin-left: auto; }
.bs6-schart { display: grid; grid-template-columns: repeat(auto-fit, minmax(clamp(44px, 3.1vw, 64px), 1fr));
  gap: clamp(3px, .3vw, 6px); align-items: end; height: 100%; min-height: 0;
  overflow-x: auto; overflow-y: hidden; padding-right: clamp(170px, 12.5vw, 250px); }
.bs6-scolval { font-size: clamp(10px, .7vw, 13px); }
.bs6-scolname { font-size: clamp(9px, .62vw, 11px); margin-top: 3px; }
.bs6-scol .bs2-scol-track { width: clamp(16px, 1.2vw, 24px); }
.bs6-staff-empty { align-self: center; }
/* 二维码固定在人员区右下角，不参与柱图布局 */
.bs6-qr { position: absolute; right: clamp(10px, .8vw, 18px); top: 50%; transform: translateY(-50%);
  width: auto; padding: clamp(5px, .5vh, 9px) clamp(8px, .7vw, 14px); }
.bs6-qr .bs2-qr-img { width: clamp(54px, 4vw, 76px); height: auto; }

/* ---------- ⑧ 空态 ---------- */
.bs6-empty { font-size: clamp(11px, .75vw, 13px); padding: clamp(10px, 1.4vh, 20px); }

/* ==========================================================================
   大屏监控 v7（2026-10-17 第四轮 · 空白治理 + 语义色统一 + 细节打磨）
   只在本段追加/覆盖，不动上方任何既有规则（前 354 行完全未改）
   本轮解决三件事：
     1. 空白治理：三栏不再强制等分屏高，空态区按内容收缩，人员区不再为一句话占满通栏
     2. 语义色统一：红=异常 / 黄=待处理 / 绿=完成 / 蓝=进行中，全大屏一致
     3. 细节打磨：五级字号层级、数字等宽、滚动区淡出边界、环形/柱图边界态
   ========================================================================== */

/* ---------- 语义色变量（集中定义，便于深浅色覆写时只改这一处） ---------- */
.bs6-wrap {
  /* 语义色：含义固定，全大屏只允许这一套映射 */
  --bs-ok: #22c55e;/* 完成 / 正常 */
  --bs-warn: #f59e0b;      /* 待处理 / 待巡检 / 待派 */
  --bs-bad: #ef4444;/* 异常 / 紧急 */
  --bs-run: #38bdf8;      /* 进行中 / 分布 */
  --bs-ink: #e8f1fb;      /* 主文字 */
  --bs-ink-2: #a8c0da;    /* 次级文字 */
  --bs-ink-3: #6b86ab;    /* 标签 */
  --bs-line: rgba(56, 189, 248, .14);
  /* 五级字号层级：区标题 / 关键数字 / 小节标题 / 卡片名 / 标签说明 */
  --bs-t1: clamp(15px, 1.15vw, 20px);
  --bs-t2: clamp(17px, 1.32vw, 25px);
  --bs-t3: clamp(11px, .78vw, 13px);
  --bs-t4: clamp(13px, .92vw, 16px);
  --bs-t5: clamp(10px, .7vw, 12px);
}

/* ---------- ① 空白治理 ----------
   原 v6：grid-template-rows: auto minmax(0,1fr) auto + 人员区固定 clamp(188px,21vh,248px)。
   问题（用户截图实测）：人员区为「今日暂无人员完成记录」一行字占掉 227px 通栏；
   三栏被强制等分 767px，内容少的巡检/专项下半截全是死黑。

   v7 取舍（两种空白二选一，这里选「三栏等高填满 + 人员区按内容收缩」）：
   - 中间行保持 minmax(0,1fr)：三栏等高铺满，页面无「参差不齐的 ragged 底边」，
     空白留在面板内部（有边框、有底色，像面板而不是页面破洞）
   - 人员区改 auto + 下限：只有一行图/空态时不再占 200+px；
     空态用 flex 居中且自身高度收敛，不会被拉成巨型空带
   - 三栏内部滚动区吃剩余高度（1fr），配合底部淡出遮罩明确「下面还有内容」 */
.bs6-wrap { grid-template-rows: auto minmax(0, 1fr) auto; align-content: stretch; }
.bs6-grid { align-items: stretch; }
.bs6-card { max-height: 100%; }
.bs6-staff { height: auto; min-height: 0; max-height: clamp(220px, 30vh, 320px); }
.bs6-staff { grid-template-rows: auto minmax(0, auto); }
.bs6-schart { height: clamp(92px, 13vh, 168px); }
/* ---------- ② 区卡片通用：内部用 grid 行分配，任何区块都不撑破卡片 ----------
   v7 删掉了巡检/专项的说明性小标题，子元素从 3 个变成 2 个（区头 + 卡片滚动区），
   行定义同步改为两行，滚动区吃剩余高度。 */
.bs6-card {
  display: grid; grid-template-rows: auto minmax(0, 1fr); gap: 0;
  min-width: 0; min-height: 0; overflow: hidden; align-content: stretch;
}
/* 人员区吃掉整页剩余高度，柱图区随之变高 */
.bs6-staff { height: auto; min-height: clamp(112px, 14vh, 150px); max-height: none; }
.bs6-staff { grid-template-rows: auto minmax(0, 1fr); }
.bs6-schart { height: auto; min-height: clamp(88px, 12vh, 160px); }
/* 人员柱图区：高度由「有多少行柱」决定，用 clamp 给上下限，避免空态时被拉成大片空白 */
.bs6-schart { height: clamp(88px, 11.5vh, 150px); }

/* ---------- ② 空态：收敛成「一行小提示」+ 滚动区做成「内容井」 ----------
   三栏等高铺满（不留参差底边），内容少时空白落在滚动区内部。
   这里给滚动区一个极淡的内嵌底色 + 圆角，让空白读作「预留内容区」而不是页面破洞；
   空态本身高度收敛并垂直居中，不会被拉成巨型空带。 */
/* 「内容井」底色：比卡片底色略亮一点点 + 一道内嵌高光边，
   目的不是把空白做得更明显，而是让它读作「一块预留的数据画布」而不是页面破洞。
   亮度必须极低（.03 透明度级），高了反而会放大空旷感。 */
.bs6-scroll, .bs2-mini-scroll, .bs6-mtodo {
  background: rgba(56, 189, 248, .035);
  box-shadow: inset 0 0 0 1px rgba(56, 189, 248, .07);
  border-radius: 6px;
}
/* 内容不足一屏时把卡片组垂直居中：空白均分到上下，不再全部堆在底部。
   `safe` 关键字是关键 —— 内容超出时浏览器自动退回 flex-start，
   保证第一张卡永远可见、不会因居中而被顶出滚动区（实测已验证）。

   ⚠ 必须显式写 display:flex; flex-direction:column。
     下面第 ⑲ 段的 .bs6-scroll 继承链上，v6 段给 .bs-sec-insp 里的滚动容器
     设的是 display:block，导致本行的 justify-content 完全失效（实测
     computed display=block，卡片贴着顶部，下面空 680px）。block 容器上
     justify-content 不起作用，这是「文字看起来写了居中但没居中」的典型坑。 */
.bs6-scroll, .bs6-mtodo {
  display: flex; flex-direction: column;
  justify-content: safe center;
}
.bs2-mini-scroll { align-content: safe center; }
/* 空态在内容井里垂直居中：top/bottom auto margin 在 flex 列容器里生效 */
.bs6-scroll > .bs6-empty, .bs2-mini-scroll > .bs6-empty, .bs6-mtodo > .bs6-empty {
  margin: auto 0;
}
.bs6-empty {
  display: flex; align-items: center; justify-content: center; text-align: center;
  color: #3f5b7d; font-weight: 600; letter-spacing: .5px;
  padding: clamp(10px, 1.6vh, 22px) clamp(10px, 1vw, 20px);
  align-self: center; align-content: center;
  min-height: 0; height: fit-content;
}
/* 空态容器自身不撑高：把多余空间留白而不是拉出滚动条 */
.bs6-scroll > .bs6-empty, .bs2-mini-scroll > .bs6-empty { flex: 0 0 auto; }
/* 人员区空态：不再居中在 200px 高的大通栏里 */
.bs6-staff-empty { padding: clamp(8px, 1.2vh, 16px); }

/* ---------- ③ 层级：区标题中英拉开比例 ---------- */
.bs6-card-tit { font-size: var(--bs-t1); font-weight: 800; color: var(--bs-ink); letter-spacing: 2px; }
.bs6-card .sec-sub {
  font-size: clamp(9px, .62vw, 11px); letter-spacing: 1.5px; font-weight: 600;
  color: #3f5b7d; transform: translateY(1px);
}

/* ---------- ④ 区头数字：分母弱化，完成/异常突出 ---------- */
/* ss-base = 分母类（应巡 / 任务）：字号小一号、颜色灰，不与完成数抢视觉 */
.bs6-num-md { font-size: clamp(15px, 1.1vw, 21px); font-weight: 800; line-height: 1; color: var(--bs-ink-2); font-variant-numeric: tabular-nums; }
.bs6-sum .ss-base b { color: var(--bs-ink-2); }
.bs6-num-lg { font-size: var(--bs-t2); font-weight: 900; line-height: 1; font-variant-numeric: tabular-nums; }
/* 数字轻微过渡：30s 刷新时数值变化不突兀 */
.bs6-num-lg, .bs6-num-md { transition: color .45s ease; }
/* 区头分隔：数字区与标题之间加一条竖线，强化「标题区 / 数据区」两个域 */
.bs6-sum { padding-left: clamp(8px, .8vw, 16px); border-left: 1px solid var(--bs-line); }

/* ---------- ⑤ 小节标题：仅保留仍有信息增量的「未完成维修工单」 ---------- */
.bs6-sub { margin: clamp(5px, .7vh, 9px) 0 clamp(3px, .4vh, 6px); font-size: var(--bs-t3); }
.bs6-sub-row { display: flex; align-items: center; gap: 8px; flex-wrap: nowrap; flex-shrink: 0; }
.bs6-sub-t { color: #5b7aa8; font-weight: 700; letter-spacing: 1px; }

/* ---------- ⑤-2 维修区内部行定义（必须放在 v6 规则之后才能覆盖） ----------
   v7 删掉了两行说明性小标题，维修区子元素从 7 个变成 5 个：
     区头 / 设备类型环卡 / 故障柱图 / 工单标题 / 工单列表
   行数不匹配的代价：多出的 minmax(0,1fr) 空行会把柱图区压成 0 高（实测柱高仅 2px）。
   工单列表与柱图区各吃一份 fr：内容多时各自内部滚动，柱图不会被压扁。 */
.bs6-mnt {
  grid-template-rows: auto auto minmax(clamp(140px, 18vh, 190px), 1fr) auto minmax(0, 1fr);
  align-content: stretch;
}
/* 柱图区下限：分类只有 1 根柱时也不塌成一条线 */
.bs6-fault { min-height: clamp(140px, 18vh, 190px); }
.bs6-col { height: auto; min-height: 0; }
.bs6-colitem .bs2-col-track { min-height: clamp(64px, 9vh, 96px); }

/* ---------- ⑥ 计划卡：环形与右侧文字基线对齐 ---------- */
/* 原来「执行数量 0/16」「待巡检 16」两个标签左边缘不齐 → 统一为单一数量行 */
.bs6-pcard { align-items: center; }
.bs6-pname { font-size: var(--bs-t4); color: var(--bs-ink); line-height: 1.25; }
.bs6-qty {
  font-size: var(--bs-t5); color: var(--bs-ink-3); font-variant-numeric: tabular-nums;
  display: flex; align-items: baseline; gap: 1px; margin-top: 3px;
}
.bs6-qty b { font-size: clamp(15px, 1.05vw, 19px); font-weight: 900; color: var(--bs-ok); }
.bs6-qty-sep { color: #3f5b7d; margin: 0 1px; }
.bs6-badges { margin-top: clamp(3px, .35vh, 6px); }
/* 徽标统一圆角与字号，异常=红、待处理=黄、进行中=蓝 */
.bs6-pcard .bs2-pb { font-size: clamp(9px, .62vw, 11px); border-radius: 4px; padding: 1px 6px; font-variant-numeric: tabular-nums; }

/* ---------- ⑦ 环形图：线宽/圆角/起始角统一 ---------- */
/* 三种环（计划 68px / 设备类型 52px）都用同一 stroke-width，视觉重量一致 */
.bs6-pcard .bs2-ring svg, .bs6-mcard .bs2-ring svg { stroke-linecap: round; }
.bs2-ring-fill { transition: stroke-dasharray .7s ease; }
.bs6-mcard .bs2-ring-num { font-size: clamp(13px, .82vw, 15px); }

/* ---------- ⑧ 设备类型小卡 ---------- */
.bs6-mname { font-size: var(--bs-t4); font-weight: 700; color: var(--bs-ink); }
.bs6-mqty { font-size: var(--bs-t5); color: var(--bs-ink-3); font-variant-numeric: tabular-nums; }
.bs6-mqty b { color: var(--bs-ok); font-weight: 900; font-size: clamp(12px, .85vw, 15px); }

/* ---------- ⑨ 故障结构柱图：柱宽 / 最小高度 / 段间隙 / 数值标签统一 ---------- */
/* 单设备类型场景下分段会退化成单色，故给整柱加一层极淡描边，保证「这是一根柱」的轮廓仍在 */
.bs6-colval { font-size: clamp(11px, .72vw, 13px); font-weight: 800; color: var(--bs-ink); line-height: 1.15; font-variant-numeric: tabular-nums; }
.bs6-colitem .bs2-col-track {
  width: clamp(20px, 1.5vw, 30px); border-radius: 4px;
  box-shadow: inset 0 0 0 1px rgba(148, 178, 214, .10);
}
.bs6-col-seg { min-height: 3px; box-shadow: inset 0 1px 0 rgba(0, 0, 0, .22); }
.bs6-col-stack { box-shadow: 0 0 0 1px rgba(148, 178, 214, .12); }
/* 「其他」兜底桶：视觉弱化但保留过渡（斜纹底色，与主色柱区分但不突兀） */
.bs6-col-stack-other {
  background: repeating-linear-gradient(135deg, #3f4d63 0 4px, #35415433 4px 8px);
  opacity: .8;
}
.bs6-colitem-other .bs6-colval { color: var(--bs-ink-3); }
.bs6-colitem-other .bs6-colname, .bs6-colitem-other .bs6-colpct { color: #55688a; }
/* 柱名与柱宽一致（原来柱间距与标签间距节奏不一致） */
.bs6-colname { font-size: clamp(9px, .62vw, 11px); color: var(--bs-ink-3); line-height: 1.2; }
.bs6-colpct { font-size: clamp(9px, .58vw, 10px); color: #4f6a8c; font-variant-numeric: tabular-nums; }

/* ---------- ⑩ 工单行：时长与状态标签拉开距离 ---------- */
.bs6-mtodo .bs2-row { padding: clamp(4px, .45vh, 7px) 10px; gap: 10px; }
.bs6-mtodo .bs2-r-name { flex: 0 0 30%; font-size: clamp(11px, .75vw, 13px); }
.bs6-mtodo .bs2-r-plan { color: var(--bs-ink-3); }
.bs6-mtodo .bs2-r-hours { flex: 0 0 40px; margin-left: auto; }
.bs6-mtodo .bs2-tag { min-width: 50px; text-align: center; border-radius: 4px; }

/* ---------- ⑪ 滚动区：底部淡出，提示「下面还有内容」 ---------- */
/* 用 mask 做淡出：内容区底部 14px 渐隐，看得出还有内容被截断 */
.bs6-scroll, .bs2-mini-scroll, .bs6-mtodo {
  -webkit-mask-image: linear-gradient(180deg, #000 0, #000 calc(100% - 14px), transparent 100%);
  mask-image: linear-gradient(180deg, #000 0, #000 calc(100% - 14px), transparent 100%);
}
/* 内容不足一屏时不需要淡出（由 JS 按scrollHeight 打class，见 bigscreen.js scrollHint） */
.bs6-scroll.is-end, .bs2-mini-scroll.is-end, .bs6-mtodo.is-end {
  -webkit-mask-image: none; mask-image: none;
}
/* 横向柱图区（人员/故障）右侧淡出同理 */
.bs6-schart, .bs6-col {
  -webkit-mask-image: linear-gradient(90deg, #000 0, #000 calc(100% - 12px), transparent 100%);
  mask-image: linear-gradient(90deg, #000 0, #000 calc(100% - 12px), transparent 100%);
}
.bs6-schart.is-end, .bs6-col.is-end { -webkit-mask-image: none; mask-image: none; }

/* ---------- ⑫ 人员区：图例与二维码不打架 ---------- */
.bs6-staff .bs6-card-hd { flex-wrap: nowrap; }
.bs6-staff .bs6-legend { margin-left: auto; }
.bs6-scolval { font-size: clamp(10px, .68vw, 12px); font-weight: 800; color: var(--bs-ink); font-variant-numeric: tabular-nums; }
.bs6-scolname { font-size: clamp(9px, .6vw, 11px); color: var(--bs-ink-2); }
.bs6-scol .bs2-scol-track { box-shadow: inset 0 0 0 1px rgba(148, 178, 214, .10); }
/* 协同段斜纹：与纯色段区分开，且深浅背景下都可辨 */
.bs6-scol .bs2-seg-assist { background: repeating-linear-gradient(45deg, #64748b, #64748b 3px, #475569 3px, #475569 6px); }

/* ---------- ⑬ 暗色适配 ----------
   大屏是「深色底」专属场景（用户定稿），**不能**跟随系统 prefers-color-scheme 反转，
   否则浅色系统下会把文字翻成深色、深底上完全看不见（实测已发生）。
   这里只保留覆写钩子：需要浅色时给 .bs-wrap 加 .is-light，由变量统一接管。 */
.bs6-wrap.is-light {
  --bs-ink: #0f172a; --bs-ink-2: #334155; --bs-ink-3: #64748b;
  --bs-line: rgba(15, 23, 42, .12);
  background: #f1f5f9;
}
.bs6-wrap.is-light .bs6-card-tit,
.bs6-wrap.is-light .bs6-pname,
.bs6-wrap.is-light .bs6-mname { color: var(--bs-ink); }
.bs6-wrap.is-light .bs6-card .sec-sub { color: #94a3b8; }
.bs6-wrap.is-light .bs6-empty { color: #94a3b8; }

/* ---------- ⑭ 顶栏：时钟 + 数据新鲜度（原「更新 HH:mm」已删） ----------
   原来同一位置同时摆「16:31:31」和「更新 07:57」，两者都是当前时间，无信息增量。
   现在常驻只有时钟；⟳ 平时是静态符号（可悬停看精确取数时间），
   只有数据超过 90s 未更新（轮询失败/断网）时才亮出滞后秒数——那才是有用的告警。 */
.bs6-wrap .bs-refresh-hint {
  display: inline-flex; align-items: center;
  font-size: 11px;
  color: #4a6a8c; cursor: default; user-select: none;
}
.bs6-wrap .bs-refresh-hint.warn { color: var(--bs-warn); font-weight: 700; }
@keyframes bs6-spin { to { transform: rotate(360deg); } }
/* 加载中的旋转：只转⟳ 这个字符本身，滞后文字保持正立（不跟着一块转） */
.bs6-wrap .bs-refresh-hint .bs6-ref-ico { display: inline-block; font-style: normal; }
.bs6-wrap .bs-refresh-hint.spin .bs6-ref-ico { animation: bs6-spin 1.1s linear infinite; }
.bs6-wrap .bs-refresh-hint .bs6-ref-ico + em {
  font-style: normal; margin-left: 4px; font-size: 11px; color: var(--bs-warn); font-weight: 700;
}

/* ---------- ⑮ 二维码区块：规整成「图 + 右侧两行字」的固定块 ----------
   原来扫码图与备案号挤在一行、备案号还会被面板右边缘切掉。
   这里给固定宽度 + 让备案号自己占满剩余宽度并右对齐，绝不换行截断。 */
.bs6-qr {
  width: auto; max-width: 220px;
  display: flex; align-items: center; gap: 10px;
  /* 必须显式重置 top/bottom：v6 的 .bs2-staff-area .bs2-qr 同时设了 top:8px;bottom:8px，
     再叠加下面 top:50% 会算出「以面板中线为顶边」，整块二维码往上溢出人员面板、
     压到维修区（实测上移了 57px）。这里改成 top/bottom 对称夹住，垂直居中交给 flex。 */
  top: clamp(6px, .8vh, 12px); bottom: clamp(6px, .8vh, 12px);
  transform: none;
  height: auto;
}
.bs6-qr .bs2-qr-frame { padding: 3px; border-radius: 6px; box-shadow: 0 0 10px rgba(56, 189, 248, .28); }
.bs6-qr .bs2-qr-txt { flex: 1 1 auto; min-width: 0; gap: 4px; }
.bs6-qr .bs2-qr-label { font-size: 12px; font-weight: 700; letter-spacing: 1px; white-space: nowrap; }
.bs6-qr .bs-icp {
  font-size: 11px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  display: block; text-align: right;
}
/* 人员区图例与汇总数字为二维码让出净空，两侧都不被压住 */
.bs6-staff .bs6-card-hd { padding-right: 232px; }
.bs6-schart { padding-right: 232px; }

/* ---------- ⑯ 柱图标签：字号与对应关系 ----------
   柱下方名称原来 9~11px 且限高 2 行，容易读不出对应哪根柱。
   放大到 11~12px、放开行数（名称由 title 兜底全名），百分比弱化一档。 */
.bs6-colname { font-size: clamp(10px, .66vw, 12px); line-height: 1.25; }
.bs6-colpct { font-size: clamp(9px, .6vw, 11px); }
.bs6-colval { font-size: clamp(12px, .78vw, 14px); }
.bs6-scolname { font-size: clamp(10px, .66vw, 12px); }
.bs6-scolval { font-size: clamp(11px, .72vw, 13px); }

/* ---------- ⑰ 设备类型轮播（≥2 个类型有工单时启用） ----------
   为什么要轮播：mntCats 有8 个类型时并排会占 2~3 行，把下方故障结构柱图和工单列表挤扁。
   单卡只吃一行高度，且让看大屏的人有「逐个类型细看」的节奏。
   间隔 6s（JS 侧 CAR_MS）：读完「类型名 + 百分比 + 完成/总数」约需 4~5s，6s 留一点余量。 */

/* 舞台：固定单行高度。必须显式写出所有会被 .bs2-mini-card 继承的属性并重置，
   否则 v6 的 flex:1 1 clamp(140px,9vw,200px) / max-width 会把卡撑成整行宽度。 */
.bs6-car {
  position: relative;
  display: flex; align-items: stretch; gap: clamp(8px, .8vw, 14px);
  min-height: 0; height: clamp(58px, 7.6vh, 82px);
  padding: 0 clamp(2px, .3vw, 6px);
}
/* 卡本体：占满舞台剩余宽度，右侧让出指示器 */
.bs6-mcard-car {
  flex: 1 1 auto; min-width: 0;
  max-width: none;                /* 重置 .bs2-mini-card 的 max-width:100% + .bs6-mcard 的 flex-basis */
  margin: 0; padding: clamp(4px, .5vh, 7px) clamp(8px, .7vw, 14px);
  background: #0d1b30; border: 1px solid #1e3a5f; border-radius: 8px;
}
/* 卡内三段布局：环 / 名称+数量 / 进度条。
   v6 的 .bs2-mini-meta 只占内容宽度，环+文字全挤在左侧，右边空一大片。
   这里让 meta 吃掉中间全部剩余宽度、进度条贴右，中间用 space-between 把
   「类型名」和「完成/总数」上下对齐 —— 单卡独占整行时才不会显得稀疏。 */
.bs6-mcard-car .bs2-mini-meta {
  flex: 1 1 auto; min-width: 0;
  display: flex; flex-direction: column; justify-content: center; gap: 2px;
}
.bs6-mcard-car .bs2-mini-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* 进度条 + 剩余数：竖排贴在卡右侧，把单卡独占整行时的横向空间用起来 */
.bs6-car-side {
  flex: 0 0 clamp(96px, 12vw, 200px); align-self: center;
  display: flex; flex-direction: column; gap: 4px; min-width: 0;
}
.bs6-car-track {
  width: 100%; height: 5px; border-radius: 3px; overflow: hidden;
  background: #0b1728; box-shadow: inset 0 0 0 1px rgba(148, 178, 214, .10);
}
.bs6-car-left {
  font-size: clamp(10px, .66vw, 12px); color: var(--bs-ink-3);
  line-height: 1.2; white-space: nowrap; font-variant-numeric: tabular-nums;
}
/* 全完工时用语义绿，和进度条/环形同一个「完成」含义 */
.bs6-car-left.is-done { color: var(--bs-ok); font-weight: 700; }
.bs6-car-fill {
  display: block; height: 100%; width: 0;
  background: var(--bs-ok); border-radius: 2px;
  transition: width .7s ease, background-color .45s ease;
}
/* 完成率低时进度条跟着换语义色（与环形 rateClass 同一套映射） */
.bs6-car-fill.is-mid { background: var(--bs-warn); }
.bs6-car-fill.is-low { background: var(--bs-bad); }

/* 圆点指示器：竖排（卡是横的，圆点竖排更像"轮播胶片"，不与卡争横向空间） */
.bs6-car-dots {
  flex: 0 0 auto; display: flex; flex-direction: column; justify-content: center;
  gap: clamp(3px, .35vh, 5px); align-self: center; padding: 0 clamp(2px, .25vw, 4px);
}
.bs6-car-dot {
  width: 6px; height: 6px; border-radius: 50%; cursor: pointer;
  background: #24405e; box-shadow: inset 0 0 0 1px rgba(148, 178, 214, .16);
  transition: background-color .35s ease, box-shadow .35s ease, transform .35s ease;
}
.bs6-car-dot:hover { background: #3f6c9c; transform: scale(1.25); }
.bs6-car-dot.is-on {
  background: var(--bs-run); box-shadow: 0 0 6px rgba(56, 189, 248, .55);
}

/* 细进度条：走满一轮 = 一个间隔。悬停时用 animation-play-state:paused 真的冻住，
   不重置 animation（重置会让进度条跳回起点，比不暂停更糟） */
.bs6-car-bar {
  flex: 0 0 clamp(2px, .16vw, 3px); align-self: center;
  height: 60%; min-height: 22px; border-radius: 2px; overflow: hidden;
  background: #0b1728;
}
.bs6-car-bar-in {
  display: block; width: 100%; height: 100%; border-radius: 2px;
  background: linear-gradient(180deg, var(--bs-run), rgba(56, 189, 248, .35));
  animation-name: bs6-car-fill; animation-timing-function: linear;
  animation-iteration-count: infinite;
}
@keyframes bs6-car-fill { from { transform: scaleY(0); } to { transform: scaleY(1); } }
.bs6-car-bar-in.is-held { animation-play-state: paused; }

/* ---------- ⑲ 人员区拉高（150px → 210px） ----------
   用户反馈「人员管理区域拉高一点，太窄了不好看」。
   取 210px 的理由与空间账（1920×1080 实测）：
     - 原 150px 在1080p 下只够放区头(约 34px) + 一行空态(约 43px) + 上下留白，
       视觉上就是一条「扁带」，完全没有一个区该有的存在感；
     - 人员柱图区要真正可用，需要 ≥150px 的柱高（柱子 + 柱顶数值 + 柱下人名约需 110px），
       210px 减去区头 34px 余 176px，柱子可用高度从 v7 的约 100px 提到约 150px，实测能容纳
       25 人（auto-fit minmax 列宽下人均约 66px宽），柱子高度是原来的 1.5 倍；
     - 上限不能再高：人员区是 `auto` 行，1080p 下总高 = 头部 63 + 三栏 + 人员区 + 3 个 gap(约 8×3=24)
       + 上下 padding 约 16。三栏还要保住「4 张计划卡一屏可见 + 故障柱图 11~15 根 + 工单列表若干行」，
       人员区超过约 230px 三栏就会开始挤工单列表。
     - 写法：`height:clamp(190px, 19.5vh, 232px)`。19.5vh@1080=211px正好命中 210；
       下限 190 保证 1366×768 这类矮屏也不会把三栏挤没；上限 232 防止 4K 大屏上人员区独吞空间。
   拉高后空间从哪来：三栏等高，由中间行的 1fr 自动收缩让出（844px → 约 784px），
   也就是「人员区多占 60px，三栏每栏少占 60px」，不需要改三栏内部任何布局。 */
.bs6-staff {
  height: clamp(190px, 19.5vh, 232px);
  min-height: 0; max-height: none;
  /* 区头 auto + 柱图区吃掉剩余。必须显式写两行：v6/v7 里有多条 .bs6-staff
     的grid-template-rows 覆盖，这里是最后一道，必须自带完整定义。 */
  grid-template-rows: auto minmax(0, 1fr);
  align-content: stretch;
}
/* 柱图区：高度完全由剩余空间决定（不再有自己的 clamp 上限），
   这样人员区拉高多少，柱子就跟着长多少，不会出现「区变高、柱不变、底部空一条」。 */
.bs6-schart {
  height: auto; min-height: 0;
  align-self: stretch; align-content: end;
}
/* 空态在变高后的区域里真正垂直居中（v7 只做了 align-self:center，
   那是水平居中；这里补上纵向：容器是 1fr 行，空态自己 stretch + 内容居中） */
.bs6-staff .bs6-empty.bs6-staff-empty {
  align-self: stretch; align-content: center; justify-content: center;
  min-height: 0; height: auto;
}

/* ---------- ⑳ 计划卡轮巡（巡检区 + 专项区共用） ---------- */
.bs6-pcar {
  position: relative;
  display: flex; flex-direction: column; gap: clamp(5px, .6vh, 9px);
  min-height: 0; height: 100%;
  padding: 2px 4px 2px 0;
}
/* 视图区：吃掉除指示条外的全部高度。overflow:hidden 是必须的 ——
   out-in 切换时两帧会短暂共存，不裁剪就会看到上下两张叠在一起。 */
.bs6-pcar-view {
  flex: 1 1 auto; min-height: 0; overflow: hidden;
  display: flex; flex-direction: column; gap: 7px;
}
/* 一组卡：组内上下排布（与平铺时一致），竖向居中 */
.bs6-pcar-group {
  display: flex; flex-direction: column; gap: 7px;
  min-height: 0; justify-content: safe center;
}
/* 指示条：横排圆点 + 一条横向细进度条。
   这里用横排而维修区用竖排 —— 因为计划卡组是「上下换页」，
   横排圆点读作「页码」，和上下翻的直觉一致。 */
.bs6-pcar-bar {
  flex: 0 0 auto; display: flex; align-items: center; gap: clamp(5px, .5vw, 9px);
  padding: 0 clamp(2px, .25vw, 4px);
}
.bs6-pcar-dot {
  width: 6px; height: 6px; border-radius: 50%; cursor: pointer; flex: 0 0 auto;
  background: #24405e; box-shadow: inset 0 0 0 1px rgba(148, 178, 214, .16);
  transition: background-color .35s ease, box-shadow .35s ease, transform .35s ease;
}
.bs6-pcar-dot:hover { background: #3f6c9c; transform: scale(1.25); }
.bs6-pcar-dot.is-on { background: var(--bs-run); box-shadow: 0 0 6px rgba(56, 189, 248, .55); }
/* 横向进度条：走满一轮 = 一个间隔。悬停用 play-state:paused 冻住，不重置 animation */
.bs6-pcar-prog {
  flex: 1 1 auto; height: 3px; border-radius: 2px; overflow: hidden;
  background: #0b1728;
  transform-origin: left center;
}
.bs6-pcar-prog::before {
  content: ''; display: block; width: 100%; height: 100%; border-radius: 2px;
  background: linear-gradient(90deg, rgba(56,189,248,.35), var(--bs-run));
  animation-name: bs6-car-fillx; animation-timing-function: linear;
  animation-iteration-count: infinite;
}
@keyframes bs6-car-fillx { from { transform: scaleX(0); } to { transform: scaleX(1); } }
.bs6-pcar-prog.is-held::before { animation-play-state: paused; }

/* 切换过渡：淡入 + 8px 轻微纵向位移。克制 —— 不弹跳、不旋转、不横向飞入 */
.bs6-pcar-fade-enter-active { transition: opacity .36s ease, transform .36s ease; }
.bs6-pcar-fade-leave-active { transition: opacity .18s ease, transform .18s ease; }
.bs6-pcar-fade-enter-from { opacity: 0; transform: translateY(8px); }
.bs6-pcar-fade-leave-to { opacity: 0; transform: translateY(-8px); }
/* 切换瞬间（busy）用无过渡类，保证 out-in 衔接处没有空白帧 */
.bs6-pcar-none-enter-active, .bs6-pcar-none-leave-active { transition: none; }

/* 切换过渡：淡入 + 6px 轻微上移。克制 —— 不弹跳、不旋转、不横向飞入 */
.bs6-car-fade-enter-active { transition: opacity .36s ease, transform .36s ease; }
.bs6-car-fade-leave-active { transition: opacity .18s ease, transform .18s ease; }
.bs6-car-fade-enter-from { opacity: 0; transform: translateY(6px); }
.bs6-car-fade-leave-to { opacity: 0; transform: translateY(-6px); }
/* 切换瞬间（carBusy）用无过渡的类，保证 out-in 不出现中间空白帧 */
.bs6-car-none-enter-active, .bs6-car-none-leave-active { transition: none; }

/* ---------- ⑱ 腾出的高度给谁 ----------
   单卡轮播把「N 张卡并排占 2~3 行」压成 1 行，多类型场景下净省约 60~120px。
   给下方**故障结构柱图**，理由：
     - 柱图是维修区信息密度最高的元素（11~14 根柱 + 柱内设备类型分段），
       压矮会直接看不清哪根柱高、段怎么分；
     - 工单列表是纯文本行，自身已有独立滚动 + 底部淡出，少几行仍可读，
       而且「未完成 N 条」总数常驻标题行，压缩它不丢信息。
   做法：柱图行多分一份 fr，并把下限抬到 clamp(170px, 23vh, 260px)；
   工单列表仍保底 minmax(0,1fr)（内容多时内部滚动，绝不塌成0 高）。 */
.bs6-mnt {
  grid-template-rows:
    auto/* 区头 */
    auto              /* 设备类型：单卡轮播 */
    minmax(clamp(170px, 23vh, 260px), 1.45fr)   /* 故障结构柱图：多拿一份 */
    auto              /* 未完成工单标题 */
    minmax(0, 1fr);   /* 未完成工单列表 */
}
.bs6-fault { min-height: clamp(170px, 23vh, 260px); }
/* 柱图要真的把变高后的行填满。
   v6 的 .bs6-col 有 `height:100%`，但 v7 早期为了压平柱图设过 height:auto，
   行变高后柱子就吊在行顶、下面留一大片空（实测行389px、柱图只占 149px）。
   这里显式改回100%：柱图区是 grid 的 1fr 行（列高 = 行高一 图例），
   柱子在align-items:flex-end 下贴底，正好是柱状图该有的样子。 */
.bs6-fault .bs6-col { height: 100%; align-self: stretch; }
.bs6-fault { align-content: stretch; }

/* ---------- ㉑ 工单筛选标签行：修复撑破卡片 ----------
   症状（压力数据 15 个设备类型时）：标签行实测 1032px 宽，而它所在的
   维修区卡片只有 704px —— 标签从卡片右侧溢出，压到屏幕外。
   根因：.bs2-tab-row 在 .bs6-sub-row（flex-wrap:nowrap）里是个 flex item，
   默认 min-width:auto = 内容宽度。父级 nowrap 不允许换行，于是它不肯收缩，
   overflow-x:auto 也就永远不触发（要收缩必须先有 min-width:0）。
   修法：给 .bs2-tab-row 补 min-width:0 + flex:1 1 auto，让它能真正收缩，
        超出部分交给它自己的 overflow-x:auto 横滚（已有 3px 细滚动条提示）。 */
.bs6-sub-row > .bs2-tab-row { min-width: 0; flex: 1 1 auto; }

/* ---------- ㉒ 维修区网格列宽：修复子元素撑破卡片 ----------
   实测（压力数据 15 个设备类型）：.bs6-mnt 卡片 704px 宽，但它的 grid 列
   被解析成 1222.94px —— 比卡片还宽 519px，于是 .bs6-sub-row 的实际宽度
   1223px、左边缘 x=1222 直接跑到屏幕右侧外面（维修区右边界才是 1912）。
   根因：.bs6-mnt 只设了 grid-template-rows，从没设过 grid-template-columns。
   单列 grid 的列宽默认 auto = max-content，子元素（ nowrap 的筛选标签行）
   有多宽，列就有多宽，卡片 border-box 再也限制不住它。
   修法：显式给 minmax(0, 1fr)。min 的 0 允许列窄于内容，于是子元素走
        自己声明的 overflow-x:auto 横滚，卡片宽度重新成为唯一真值。 */
.bs6-mnt { grid-template-columns: minmax(0, 1fr); }
/* 同理给另外两区与外层三栏兜底，防止将来内容变多时再次撑破 */
.bs6-insp, .bs6-spc, .bs6-staff { grid-template-columns: minmax(0, 1fr); }
.bs6-grid > * { min-width: 0; }
/* sub-row 自己也不能被内容顶开（它是 grid item，默认 min-width:auto） */
.bs6-sub-row { min-width: 0; }

/* ---------- ㉓ 工单标题不换行、不被标签行挤扁 ----------
   实测（压力数据）：.bs6-sub-t 实测宽 47px、高 51px —— 「未完成维修工单」
   被压成两行。原因是它是 nowrap flex 行里的 flex item，默认 min-width:auto
   但 flex-shrink:1，标签行一变多它就被挤到换行。
   修法：标题与计数都不许收缩、不许换行（flex:0 0 auto + white-space:nowrap），
        空间全给标签行自己横滚。 */
.bs6-sub-row > .bs6-sub-t,
.bs6-sub-row > .bs2-count,
.bs6-sub-row > .bs2-trunc {
  flex: 0 0 auto; white-space: nowrap;
}

/* ---------- ㉔ 计划卡组在轮播舞台里垂直居中 ----------
   实测：舞台 .bs6-pcar-view 高约 700px，一组 4 张卡只占约 350px，
   .bs6-pcar-group 上的 justify-content:safe center 不生效 —— group 自己
   被 flex 拉伸成满高（默认 align-items:stretch），内容从顶部排下来。
   修法：让 view 用 safe center 居中这**一组**（组是唯一子元素，
   safe 保证卡片多于舞台时退回顶部、第一张永远可见），
   同时把 group 的 align 改回 flex-start，避免二次拉伸。 */
.bs6-pcar-view { justify-content: safe center; }
.bs6-pcar-group { align-self: center; width: 100%; }

/* ==========================================================================
   ㉕ v10 顶对齐（用户反馈：「计划任务条，未完成维修工单框都要顶对齐」）
   --------------------------------------------------------------------------
   v9 为了消灭「内容少时底部一大片空」给几个滚动容器加了
   `justify-content: safe center`，结果 2 张卡时整组飘到中间。
   用户要的是**从标题下方顶起排列**，不是居中。
   改法：safe center → flex-start。
   溢出保护怎么保留（这是safe center 原本唯一的价值，不能丢）：
     safe center 在内容超出时会自动退回 flex-start，
     而 flex-start 本来就是「内容超出时唯一正确的对齐方式」——
     超出部分由容器自身的 overflow-y:auto 纵向滚动，
     第一张卡永远在顶部可见。所以换成 flex-start 不损失任何保护，
     反而更简单、语义更准。无需再叠加任何 safe 关键字。
   为什么不用 safe flex-start：safe 只在「居中会导致首项被顶出可视区」
   时才有意义，而我们本来就要顶对齐，行为与 flex-start 完全一致，
   多写一个关键字只会让人误以为还有别的行为。
   ========================================================================== */

/* ㉕-1 巡检区 / 专项区计划卡区：顶对齐（覆盖 v9 ㉕③段加的 safe center） */
.bs6-scroll {
  justify-content: flex-start;
}
/* 轮播舞台内的计划卡组同样顶对齐 */
.bs6-pcar-view { justify-content: flex-start; }
.bs6-pcar-group { align-self: stretch; }

/* ㉕-2 空态块仍保持垂直居中。
   「无数据」和「有数据但少」是两回事：
     - 无数据 → 一行提示语，空荡荡，居中才好看（这正是 v7 的诉求，保留）
     - 有数据 2 张 → 用户明确要求顶起排列，不能居中
   所以空态用 margin:auto 0 单独居中，数据卡用 flex-start 顶起。 */
.bs6-scroll > .bs6-empty,
.bs2-mini-scroll > .bs6-empty,
.bs6-mtodo > .bs6-empty {
  margin: auto 0;          /* flex 列容器里 auto 上下外边距 = 垂直居中 */
  flex: 0 0 auto;
}

/* ㉕-3 未完成维修工单小节：顶对齐。
   症状（v9 真实数据）：维修区 783px 里，「未完成维修工单」标题下方
   只有 2 行工单（约 70px），工单列表区却拿了 minmax(0,1fr) 的全部剩余
   高度（��� 400px），2 行工单被safe center 推到中间，上下各空 170px，
   看起来像「框比内容大一倍」。
   改法：列表本身顶对齐（flex-start）。剩下的空白就落在列表下方，
   这是用户要的「内容从标题下方顶起排列，不要上下撑开」。
   注意：工单列表**必须保留纵向滚动**，因为 mnt.pendingList 可能几十条，
   flex-start + overflow-y:auto 才能让长列表滚起来而不顶破卡片。 */
.bs6-mtodo { justify-content: flex-start; }

/* ㉕-4 三区小节标题同一基线。
   巡检/专项区的区头（.bs6-card-hd）与维修区的「未完成维修工单」标题
   （.bs6-sub-row）分属两套组件，v9 之后高度不一致，肉眼看上去错开半行。
   做法：把两者的高度统一为 clamp(22px, 2.4vh, 28px)，行高统一 1，
   再用 align-items:center 让各自内部文字在同一条中线上。
   .bs6-card-hd 高度受 padding 影响，这里只锁 min-height 并归一内边距，
   避免影响区头里其他统计数字的位置。 */
.bs6-card-hd {
  min-height: clamp(22px, 2.4vh, 28px);
  box-sizing: border-box;
}
.bs6-sub-row {
  min-height: clamp(22px, 2.4vh, 28px);
  align-items: center;
  line-height: 1;
}
.bs6-sub-t { line-height: 1; }

/* ==========================================================================
   ㉖ 设备类型轮播 N/M 指示器（v10，替代 >5 个时的一列小圆点）
   ========================================================================== */
.bs6-car-nm {
  flex: 0 0 auto;
  display: flex; flex-direction: column; align-items: center;
  gap: clamp(4px, .5vh, 7px);
  justify-content: center;
  min-width: 0;
  padding: 0 2px;
}
/* N/M 数字：tabular-nums 让切换时数字不左右跳动 */
.bs6-car-num {
  font-size: clamp(13px, .95vw, 17px);
  font-weight: 800;
  color: var(--bs-ink);
  font-variant-numeric: tabular-nums;
  letter-spacing: .5px;
  line-height: 1;
  white-space: nowrap;
}
/* 左右箭头：点击直达上一个/下一个类型（对应圆点形态的「点圆点直达」） */
.bs6-car-arrow {
  font-size: clamp(15px, 1.1vw, 20px);
  line-height: 1;
  color: var(--bs-ink-2);
  cursor: pointer;
  padding: 2px 4px;
  border-radius: 4px;
  user-select: none;
  transition: color .18s ease, background-color .18s ease;
}
.bs6-car-arrow:hover { color: var(--bs-run); background: rgba(56, 189, 248, .12); }
.bs6-car-arrow.is-off { opacity: .3; cursor: default; }
.bs6-car-arrow.is-off:hover { color: var(--bs-ink-2); background: none; }

/* ==========================================================================
   ㉗ 工单筛选标签行（.bs2-tab-row）横向滚动提示
   --------------------------------------------------------------------------
   遗留项3：15 个设备类型时标签行要横滚，但 3px 细滚动条在暗底上不明显。
   做法：和其他滚动区一致，右侧加一条渐隐遮罩（mask），
   标签滚到尽头时由 JS 打 .is-end 关掉遮罩（复用 syncScrollHints 的判定）。
   ========================================================================== */
.bs2-tab-row {
  -webkit-mask-image: linear-gradient(90deg, #000 0, #000 calc(100% - 18px), transparent 100%);
  mask-image: linear-gradient(90deg, #000 0, #000 calc(100% - 18px), transparent 100%);
  padding-right: 14px;
}
.bs2-tab-row.is-end {
  -webkit-mask-image: none; mask-image: none;
  padding-right: 1px;
}

/* ==========================================================================
   ㉘ 人员区无数据时的处理（v10 需求 2.3）
   --------------------------------------------------------------------------
   结论：**不收缩人员区高度，改为让空态"占满并有设计感"**。理由三条：
     1) 用户 v9 明确要求「人员管理区域拉高一点，太窄了不好看」，
        若一到「今日暂无记录」就缩回 150px，等于让这个需求每天大部分时间
        失效 —— 大屏是 7×16 常驻的，凌晨到早上没数据是常态。
     2) 收缩会让整页布局在「有数据/无数据」之间**跳动**：三栏是1fr 等分，
        人员区一变矮，三栏就各多出一截，昨天看过的位置今天全错位。
        常驻大屏最忌讳布局抖动。
     3) 高度是 clamp()，本身已经能适配不同屏高；真要省空间应该压三栏，
        而不是压一个用户刚要求拉高的区。
   做法：给空态一个"内容井"外观（描边 + 弱底色 + 居中），
   让这 211px 读起来是一个"待填充的面板"而不是"坏掉的空白"。
   ========================================================================== */
.bs6-staff .bs6-staff-empty {
  align-self: stretch;
  margin: 0;
  height: auto;
  min-height: 0;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  gap: clamp(6px, .8vh, 12px);
  border: 1px dashed rgba(56, 189, 248, .16);
  border-radius: 8px;
  background: rgba(56, 189, 248, .035);
}
/* 空态文案 + 一条极细的装饰分隔线，给「面板待填充」一点设计感 */
.bs6-staff-empty .bs6-empty-txt { display: block; }
/* 旧结构里 .bs6-empty 自带 flex 居中，这里改成列向以便加副标题 */
.bs6-staff .bs6-staff-empty > * { margin: 0; }

/* 空态副标题样式（v10）：比主文案弱一档，字号更小、颜色更暗 */
.bs6-staff .bs6-empty-sub {
  font-size: clamp(10px, .72vw, 12px);
  font-weight: 600;
  letter-spacing: .3px;
  color: #34506f;
  white-space: nowrap;
}

/* ㉙ 专项区空态也顶对齐（v10 需求 1的延伸）
   v9 给 .bs6-scroll 统一加了 safe center，专项区 0 张计划时那行
   「暂无专项检查计划」被推到了面板正中（实测 y≈273，面板 71~854）。
   用户要求顶对齐，数据卡已经改完，这条把空态一起拉回顶部。
   注意：只对 .bs6-scroll 内的空态生效，.bs6-staff 的空态保持居中
   （㉘ 已单独给了人员区虚线井 + 居中，两者诉求不同）。 */
.bs6-scroll > .bs6-empty { margin: 0; align-self: flex-start; }
.bs2-mini-scroll > .bs6-empty { margin: 0; align-self: flex-start; }
.bs6-mtodo > .bs6-empty { margin: 0; align-self: flex-start; }

/* ============ P2 维修图纸 / 培训视频 ============ */
.drw-hint, .vid-hint { margin-top: 6px; color: #909399; font-size: 12px; }
/* 图纸预览：PDF 用 <embed>、图片用 <img>（不用 iframe —— WebKit 合成 wrapper 后内嵌 embed 渲染不出 PDF 插件查看器，会整片空白） */
.drw-preview { width: 100%; height: 72vh; border: 0; background: #f5f5f5; display: block; }
.drw-preview-img { display: block; max-width: 100%; max-height: 72vh; margin: 0 auto; object-fit: contain; background: #fff; }
.drw-preview-empty { padding: 80px 0; text-align: center; color: #909399; font-size: 14px; }
/* 视频封面缩略图 */
.vid-cover { width: 76px; height: 50px; object-fit: cover; border-radius: 4px; background: #eef; display: inline-block; }
.vid-cover-empty { display: inline-flex; align-items: center; justify-content: center; color: #bbb; font-size: 12px; border: 1px dashed #dcdfe6; }
.vid-cover-lg { width: 100%; max-height: 220px; object-fit: cover; border-radius: 6px; }
/* 视频播放器 */
.vid-player { width: 100%; max-height: 72vh; background: #000; border-radius: 6px; }
