/* ===== v319（2026-09-22）：线平衡改善页「+ 新建数据」修复（数据不在 app.js 的 state 里，以前点了完全没效果；本模块用捕获阶段接管 + 丢弃前确认 + 清旧草稿）。**本文件未新增任何选择器**。历史 v299：配置表主键修复 / 三站新增「配制技术员」/ VIP 改为逐页可配；v295：登录状态分档 + CPK 口径统一；v294：切页摄像头提示噪音修正；v289~v293：SSO 免登入口 / IDB 连接自愈 / 登录门整洁层；v288：登录门整洁层；v287：待同步队列自动收敛；v286：云端同步状态显示修复；v285：第 4/5/7/8 项。 */
/* ===== v236（2026-09-11）：IE Plus 扩展 P3 三项——⑨轻量 VSM 增值比 ⑩标准作业组合票（人-机-时间甘特） ⑪半成品暂存效期（GMP 时限预警）。零侵入：仍由 ieplus.js 独立承载，复用既有 card/field/metric/table 样式，无新增选择器 ===== */
/* ===== v235（2026-09-12）：新增独立页「IE 增强工具（IE Plus）」—— 集中承载 P1/P2 新增 IE 工具：①宽放率分解 ②西屋法评比 ③SPC 控制图(X̄-R) ④不良帕累托 ⑤动作经济原则检查 ⑥SMED 换型与 CIP 清洁 ⑦瓶颈漂移与工时偏差 ⑧批号与效期。零侵入：独立文件 ieplus.js + 独立 section，只读复用现有数据，可整体删除 ===== */
/* IE Plus：图表横向滚动容器（窄屏可横向查看控制图/帕累托图） */
.chart-scroll { width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; }
/* ===== v234（2026-09-12）：优化空间收敛 —— 开发脚本 shot.js/shot2.js/probe.js（Playwright 自动化，无任何引用）移出部署目录至 ../devtools/，减小包体、避免源码外泄；云函数/前端不再包含开发工具 ===== */
/* ===== v233（2026-09-12）：按开发 MD 补齐两项要求 —— ① 公式引擎单元测试 9 项（括号/IF/除零/非法字符/空表达式/深度限制/变量求值/未声明变量/eval 禁用），MD 第七节明确要求；② 操作日志检索（类型/操作人/起止时间，显式提交遵循 v209），MD 第五节明确要求 ===== */
/* ===== v232（2026-09-12）：守卫批次3 —— ArchiveStore 全部 103 处调用加安全降级守卫（列表→[]、读写→Promise.resolve(null)、开关→undefined，保持表达式与 await 语义不变）；整体隐患核查后修复备份解密路径对损坏文件的容错（给中文提示，不抛技术错误）；R1/R3/R4 扫描确认无隐患 ===== */
/* ===== v231（2026-09-12）：按开发 MD 复核后的加固 —— ① 守卫批次1：CloudSync.isEnabled() 33 处裸用统一安全降级（未加载=未启用）；② 守卫批次2：app.js 启动期依赖自检（模块缺失即时提示+落日志）；③ 补齐 MD 三·（一）·4 冲突告警：cloud-sync 拉取冲突留痕，不再静默覆盖 ===== */
/* ===== v230（2026-09-12）：稳定性整体核查 —— ① 静默 catch 全量日志化（336 处，异常不再无声消失）；② index.html 加版本探针 version.json（穿透旧 SW，自动注销旧缓存并刷新）；③ 系统加固「一键核验」新增线上版本探针 / SW 状态 / 本地存储可写性；④ 回归测试扩至 195 条覆盖本周全部异常 ===== */
/* ===== v229（2026-09-11）：登录网关改绝对地址 https://cosmeticnote.cn/ie-mod-login —— cosmeticnote.cn 下同域零回归，默认域名 tcloudbaseapp.com 下跨域（网关已支持 CORS）也能登录，为用户提供一个「无旧 SW 缓存」的备用入口 ===== */
/* ===== v228（2026-09-11）：数据大屏响应式重构 —— 手机端「块级排列 + 每卡固定 320px + 容器纵向滚动 + 100dvh」，平板端「2 列 + 固定行高 280px」，杜绝原 grid-auto-rows:minmax(160px,1fr)+align-content:stretch 把行高均分压缩导致图表被压扁/底部内容被截断；桌面端保持一屏均分不变 ===== */
/* ===== v227（2026-09-11）：彻底脱离旧 SW —— ① error-trap.js showLog 兜底：即使弹窗失败也用 prompt 显示原始日志（可复制），不再只弹「打开失败」；② index.html 加 ?unregister-sw 一键注销全部 SW 并重定向，摆脱旧 SW 缓存死循环；③ sw.js/index.html 版本戳对齐 ===== */
/* ===== v220（2026-09-10）：#559 P1/P2 落地 —— ① IE 线平衡决策三卡（理论最少工位数 N_min=⌈ΣCT/节拍⌉、现有工位数·人力、工位富余/缺口）；② Takt 反算计算器（点数=可用时间×稼动率÷需求产量，不点不影响手填）；③ 评比系数 state.line.rating 默认 1.00（=1 时所有既有数字零变化），标准工时三要素显式化 + std-vs-actual「标准时间(含宽放)」列；④ 线平衡页新增「历史对比」卡：改善前后叠加山积图（对档案库快照）+ 全线/逐工位差异趋势收敛曲线；⑤ 全线差异分析表一键导出 Excel（含判定·主因·对策 + 指标摘要）。全线侧同步给 3 个线平衡决策指标 ===== */
/* ===== v219（2026-09-10）：#559 全线/逐工位差异分析落地 —— ① CT 口径标签化（净观测/含宽放并列，计算不变）；② 全线 balanceRate 补 suspect 保护 + 映射/低样本计数告警；③ 岗位映射支持 state.video.lineMap 手动绑定（默认仍按下标，零回归）；④ 差异对比表升级（Δ全线−AI/Δ全线−产能法、标样参考、循环数/归集方式/有效作业比、判定、R1~R8 主因·对策）+ 修正 AI·CT 列口径 ===== */
/* ===== v218（2026-09-10）：#553 视频人工辅助（IE自动分析）① 保存时检测同日同产品代码已存在弹窗三选一（覆盖/另存/取消），避免反复保存产生多条同日同 code 记录；② 汇总页"同一产品合并" key 从 (name+code+isNewProduct) 升级为 (name+code+isNewProduct+date)，实现"同一产品同一日期合并"并标注存档数；③ 视频分析页 📝 暂存按钮（stageVideoBtn→stageIEModule 写 DraftStore）之前已就绪，本版本继续保留 ===== */
/* ===== v204（2026-09-09）：#544 云端 1MB 墙积压档案自动 offload 重试（29 条未同步自愈）；#545 按工位/全线双输出互不覆盖 + 新增「💾 保存」按钮；#546 全线验证复用标样标准循环模板校准 CT；#547 无效程序复盘（熔断骨架已移除、shot.js/probe.js 为外部 Playwright 工具不随应用加载） ===== */
:root {
  --bg: #f5f6f8;
  --card: #ffffff;
  --ink: #1f2329;
  --muted: #6b7280;
  --line: #e3e6ea;
  --brand: #185fa5;
  --brand2: #0f6e56;
  --ok: #3b6d11;
  --warn: #ba7517;
  --bad: #a32d2d;
  --idle: #5f5e5a;
}

* { box-sizing: border-box; }

/* 轻量提示 toast（保存数据后反馈） */
#pageToast {
  position: fixed; left: 50%; bottom: 30px; transform: translateX(-50%) translateY(16px);
  background: var(--brand); color: #fff; padding: 10px 18px; border-radius: 10px;
  font-size: 14px; box-shadow: 0 8px 28px rgba(0,0,0,.22);
  opacity: 0; pointer-events: none; transition: opacity .25s, transform .25s; z-index: 999;
  max-width: 90vw; text-align: center;
}
#pageToast.show { opacity: 1; transform: translateX(-50%) translateY(0); }

body {
  margin: 0;
  font-family: -apple-system, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;
  background: var(--bg);
  color: var(--ink);
  font-size: 14px;
  line-height: 1.55;
}

header {
  background: var(--brand);
  color: #fff;
  padding: 14px 22px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}
header h1 { margin: 0; font-size: 17px; font-weight: 600; }
header p { margin: 4px 0 0; font-size: 12px; opacity: .85; }

nav {
  display: flex;
  gap: 4px;
  padding: 0 16px;
  background: #fff;
  border-bottom: 1px solid var(--line);
  position: sticky;
  top: 0;
  z-index: 10;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
nav::-webkit-scrollbar { display: none; }
nav button {
  border: none;
  background: none;
  padding: 12px 18px;
  font-size: 14px;
  color: var(--muted);
  cursor: pointer;
  border-bottom: 2px solid transparent;
  flex: 0 0 auto;
}
nav button.active { color: var(--brand); border-bottom-color: var(--brand); font-weight: 600; }

.nav-wrap { display: flex; align-items: stretch; position: sticky; top: 0; z-index: 10; background: #fff; border-bottom: 1px solid var(--line); }
.nav-wrap > nav { flex: 1 1 auto; border-bottom: none; display: flex; align-items: stretch; overflow-x: auto; overflow-y: visible; -webkit-overflow-scrolling: touch; scroll-behavior: smooth; }
.nav-group { position: relative; display: flex; align-items: stretch; flex: 0 0 auto; }
.nav-title {
  border: none; background: none; padding: 12px 14px; font-size: 14px; color: var(--muted);
  cursor: pointer; border-bottom: 2px solid transparent; display: inline-flex; align-items: center; gap: 4px; white-space: nowrap;
}
.nav-title::after { content: '\25BE'; font-size: 10px; opacity: .7; }
.nav-title:hover { color: var(--brand); }
.nav-group.active .nav-title, .nav-title.active { color: var(--brand); border-bottom-color: var(--brand); font-weight: 600; }
.nav-dropdown {
  position: fixed; top: auto; left: auto; min-width: 250px; z-index: 9999; display: none;
  background: #fff; border: 1px solid var(--line); border-top: 2px solid var(--brand);
  border-radius: 0 0 10px 10px; box-shadow: 0 12px 28px rgba(0,0,0,.12); padding: 6px; flex-direction: column;
}
.nav-group.open .nav-dropdown { display: flex; }
.nav-dropdown button {
  border: none; background: none; text-align: left; padding: 10px 12px; font-size: 14px;
  color: var(--text); cursor: pointer; border-radius: 6px; white-space: nowrap; border-bottom: none;
}
.nav-dropdown button:hover { background: #f2f6fa; }
.nav-dropdown button.active { color: var(--brand); background: #eaf2fb; font-weight: 600; }
.nav-arrow { flex: 0 0 auto; border: none; background: #fff; color: var(--brand); font-size: 24px; line-height: 1; width: 36px; cursor: pointer; padding: 0 6px; }
.nav-arrow:hover { background: var(--line); }
.nav-arrow:active { transform: scale(0.92); }
.nav-jump { flex: 0 0 auto; margin: 0 10px; height: 36px; align-self: center; border: 1px solid var(--line); border-radius: 6px; padding: 0 8px; font-size: 13px; color: var(--muted); background: #fff; max-width: 140px; }
@media (max-width: 720px) { .nav-arrow, .nav-jump { display: none; } }

main { padding: 20px 22px 60px; max-width: 1080px; margin: 0 auto; }

.panel { display: none; }
.panel.active { display: block; }

.card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 18px 20px;
  margin-bottom: 18px;
  box-shadow: 0 1px 2px rgba(0,0,0,.03);
}
.card h2 { margin: 0 0 14px; font-size: 15px; }
.card h3 { margin: 0 0 10px; font-size: 14px; color: var(--brand); }

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 12px;
}
/* v246 修复「手机端整页横向溢出」：
   grid/flex 子项默认 min-width:auto = min-content 尺寸 ⇒ 一旦里面有宽内容（例如 26 列表格、
   888px 的表头），轨道会被撑到内容宽度，父级 grid 也随之超宽，最终 documentElement 出现横向滚动
   （实测 390px 视口下「线平衡改善」页 docScrollWidth 达 936px）。
   给网格子项加 min-width:0 后，子项可收缩到轨道宽，内部的 .table-wrap{overflow-x:auto} 才会真正生效。 */
.grid > *, .metrics > * { min-width: 0; }
.field label { display: block; font-size: 12px; color: var(--muted); margin-bottom: 4px; }
.field input, .field select {
  width: 100%;
  padding: 8px 10px;
  border: 1px solid var(--line);
  border-radius: 7px;
  font-size: 14px;
  background: #fff;
  color: var(--ink);
}
.field input:focus, .field select:focus { outline: none; border-color: var(--brand); }

.row { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.btn {
  border: 1px solid var(--brand);
  background: var(--brand);
  color: #fff;
  padding: 8px 14px;
  border-radius: 7px;
  cursor: pointer;
  font-size: 13px;
}
.btn:hover { opacity: .92; }
.btn.ghost { background: #fff; color: var(--brand); }
.btn.sm { padding: 4px 9px; font-size: 12px; }
.btn.danger { border-color: var(--bad); background: #fff; color: var(--bad); }
.btn.danger:hover { background: var(--bad); color: #fff; }
.btn.info { border-color: var(--brand); background: #fff; color: var(--brand); }
.btn.info:hover { background: var(--brand); color: #fff; }

/* 操作按钮组：汇总表动作列，横向排列并自动换行（Action button group for summary tables） */
.ops-cell { display: flex; flex-wrap: wrap; gap: 5px; align-items: center; min-width: 140px; }
.ops-cell .btn { flex: 0 0 auto; white-space: nowrap; }

/* 传报流程时间轴（Report flow timeline） */
.rf-flow { display: flex; flex-direction: column; gap: 2px; }
.rf-node { display: flex; align-items: flex-start; gap: 10px; padding: 4px 0; }
.rf-dot { width: 12px; height: 12px; border-radius: 50%; margin-top: 3px; background: #cfd8e3; border: 2px solid #cfd8e3; flex: 0 0 auto; }
.rf-node.done .rf-dot { background: var(--good, #2E8B57); border-color: var(--good, #2E8B57); }
.rf-body { font-size: 13px; line-height: 1.5; }
.rf-actions { margin-top: 6px; display: flex; gap: 8px; flex-wrap: wrap; }
.btn.recording { background: var(--bad); border-color: var(--bad); color: #fff; animation: recpulse 1s infinite; }
@keyframes recpulse { 0%,100% { opacity: 1; } 50% { opacity: .65; } }
#cameraPreview { margin-top: 8px; }

table { width: 100%; border-collapse: collapse; font-size: 13px; }
th, td { border: 1px solid var(--line); padding: 7px 9px; text-align: left; }
th { background: #f0f3f6; font-weight: 600; color: var(--muted); }
td input, td select { width: 100%; border: 1px solid var(--line); border-radius: 6px; padding: 5px 7px; font-size: 13px; background:#fff; color: var(--ink); }
td.num { text-align: right; font-variant-numeric: tabular-nums; }

.proc { border: 1px solid var(--line); border-radius: 10px; padding: 14px 16px; margin-bottom: 14px; background:#fff; }
.proc-head { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; margin-bottom: 10px; }
.proc-head .field { flex: 1; min-width: 130px; }

.metrics { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px,1fr)); gap: 12px; }
.metric { background: #f7f9fb; border: 1px solid var(--line); border-radius: 9px; padding: 12px 14px; }
.metric .k { font-size: 12px; color: var(--muted); }
.metric .v { font-size: 20px; font-weight: 600; margin-top: 4px; }
.metric .v small { font-size: 12px; color: var(--muted); font-weight: 400; }

.cpk-grades { display: flex; flex-wrap: wrap; gap: 8px; margin: 14px 0 4px; }

.badge { display: inline-block; padding: 2px 9px; border-radius: 999px; font-size: 12px; font-weight: 600; }
.badge.ok { background: #eaf3de; color: var(--ok); }
.badge.warn { background: #faefda; color: var(--warn); }
.badge.bad { background: #fcebeb; color: var(--bad); }
.badge.idle { background: #f1efee; color: var(--idle); }
.badge.super { background: linear-gradient(135deg,#f59e0b,#d97706); color: #fff; box-shadow: 0 1px 3px rgba(217,119,6,.4); }
.badge.danger { background: #fcebeb; color: var(--bad); }
.badge.blue { background: #e6f0fa; color: #185fa5; }
.badge.red { background: #fcebeb; color: #c0392b; }
.badge.cpk { background: #eadcff; color: #6b21a8; }
.badge.ecrs { padding: 1px 6px; font-size: 11px; border-radius: 4px; margin-right: 4px; text-transform: uppercase; }
.badge.ecrs-E { background: #fcebeb; color: var(--bad); }
.badge.ecrs-C { background: #faefda; color: #b45309; }
.badge.ecrs-R { background: #e6f0fb; color: var(--brand); }
.badge.ecrs-S { background: #e9f5ec; color: var(--brand2); }

/* 各岗位详细测试表 */
.bar-cell { min-width: 130px; }
.mini-bar { height: 12px; background: #eee; border-radius: 6px; overflow: hidden; border: 1px solid var(--line); }
.mini-bar span { display: block; height: 100%; }
.bar-cell small { display: block; font-variant-numeric: tabular-nums; color: var(--muted); margin-top: 2px; }
.sugg-cell { font-size: 12px; line-height: 1.5; color: #374151; min-width: 220px; }

#chart { width: 100%; height: 340px; }
#balanceGauge { width: 100%; height: 280px; }
#balanceBar { width: 100%; height: 280px; }
.charts2 { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 16px; margin-top: 14px; }
.hint-inline { font-size: 12px; color: var(--muted); font-weight: 400; }

.hint { font-size: 12px; color: var(--muted); margin-top: 8px; }
.toolbar { display: flex; gap: 10px; margin-bottom: 14px; flex-wrap: wrap; }

/* 视频叠加注释层 */
.video-overlay-wrap { margin: 12px 0 4px; }
.video-current { font-size: 13px; font-weight: 600; margin-bottom: 6px; color: var(--brand); min-height: 18px; }
.action-timeline { position: relative; height: 38px; background: #f0f3f6; border: 1px solid var(--line); border-radius: 6px; overflow: hidden; }
.action-seg { position: absolute; top: 0; bottom: 0; font-size: 10px; color: #fff; display: flex; align-items: center; justify-content: center; overflow: hidden; white-space: nowrap; opacity: .92; }
.action-seg.active { outline: 2px solid #ff4d4f; outline-offset: -2px; opacity: 1; }
.action-playhead { position: absolute; top: 0; bottom: 0; width: 2px; background: #ff4d4f; z-index: 5; }
.video-balance-mini { margin-top: 12px; }
.check { display: inline-flex; align-items: center; gap: 6px; font-size: 14px; font-weight: 600; }
.check input { width: auto; }
#stationAssignTable .excluded { opacity: .45; }
#stationAssignTable .excluded td:not(:last-child) { text-decoration: line-through; }
.help-link { color: var(--accent); text-decoration: none; font-weight: 600; }
.help-link:hover { text-decoration: underline; }
.balance-conclusion { margin-top: 16px; border-top: 1px solid var(--line); padding-top: 12px; }
.balance-conclusion h3 { margin: 12px 0 8px; font-size: 14px; color: var(--brand); }
.balance-conclusion h3:first-child { margin-top: 0; }
.balance-conclusion p { margin: 0; line-height: 1.7; }
.balance-conclusion ul.sugg { margin: 6px 0 0; padding-left: 20px; }
.balance-conclusion ul.sugg li { margin: 6px 0; line-height: 1.6; }
.ecrs-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 12px; margin: 12px 0; }
.ecrs-block { border: 1px solid var(--line); border-radius: 8px; padding: 12px 14px; background: #fafbfc; }
.ecrs-block h4 { margin: 0 0 8px; font-size: 13px; font-weight: 600; }
.ecrs-E h4 { color: var(--bad); }
.ecrs-C h4 { color: var(--warn); }
.ecrs-R h4 { color: var(--brand); }
.ecrs-S h4 { color: var(--brand2); }
.ecrs-block ul { margin: 0; padding-left: 16px; }
.ecrs-block li { margin: 5px 0; font-size: 12px; line-height: 1.55; }

/* 视频产能标定 */
.takt-measure-row { padding: 8px; border: 1px dashed var(--line); border-radius: 8px; background: #fafbfc; }
.takt-measure-row .field { margin-bottom: 0; }
.takt-measure-row .field label { font-size: 11px; }
.takt-measure-row .num { font-weight: 600; color: var(--brand); }
.balance-mini-bar { height: 14px; background: #eee; border-radius: 7px; overflow: hidden; border: 1px solid var(--line); margin-top: 6px; }
.balance-mini-fill { height: 100%; background: linear-gradient(90deg, #3b6d11, #0f6e56); transition: width .25s; }

@media print {
  nav, .toolbar, .no-print { display: none !important; }
  body { background:#fff; }
  .card { box-shadow:none; }
}

/* 档案库 */
.arc-search { flex: 1; min-width: 180px; padding: 8px 10px; border: 1px solid var(--line); border-radius: 7px; font-size: 13px; background:#fff; color: var(--ink); }
.arc-search:focus { outline: none; border-color: var(--brand); }

/* 录入校验护栏：工序提示条 + 明细表 ⚠ 标记 */
.proc-warn { border: 1px solid #f0c36d; background: #fff8e6; border-radius: 6px; padding: 8px 10px; margin: 6px 0 10px; font-size: 13px; }
.proc-warn .proc-warn-item { line-height: 1.6; }
.proc-warn .proc-warn-item + .proc-warn-item { margin-top: 4px; }
.proc-warn .proc-warn-item.error { color: #a32d2d; }
.proc-warn .proc-warn-item.warn { color: #8a5a00; }
.proc-warn .proc-warn-item.info { color: #185fa5; }
.warn-mark { color: #a32d2d; font-size: 13px; margin-left: 4px; cursor: help; }

/* 视频产能法双指标读数 */
.vreadout { display:flex; flex-wrap:wrap; align-items:center; gap:8px; margin:8px 0 2px; padding:6px 8px; background:#f3f8fb; border:1px solid #d6e6f2; border-radius:6px; font-size:13px; }
.vreadout .tag { display:inline-block; padding:2px 8px; border-radius:12px; font-size:12px; font-weight:600; }
.vreadout .tag.ok { background:#e3f6ec; color:#1d7a45; border:1px solid #b6e3c9; }
.vreadout .tag.info { background:#e7f0fb; color:#185fa5; border:1px solid #bcd6f2; }
.vreadout .hint { color:#6b7785; font-size:12px; }

/* 视频动作计数按钮 */
.ac-chip { background:#e3f6ec; border:1px solid #b6e3c9; color:#1d7a45; margin:2px 0; }
.ac-chip:hover { background:#d2efe0; }

/* 新品前三批：质量图片上传与预览 */
.bq-thumb-wrap { min-width: 70px; min-height: 52px; display: flex; align-items: center; justify-content: center; background: var(--bg2); border: 1px dashed var(--border); border-radius: 6px; }
.bq-thumb { max-width: 80px; max-height: 60px; border-radius: 6px; cursor: zoom-in; object-fit: cover; box-shadow: 0 2px 6px rgba(0,0,0,.1); }
.bq-thumb:hover { box-shadow: 0 4px 10px rgba(0,0,0,.18); }
.bq-photo-cell { min-width: 110px; }
.bq-photo-cell label.btn { display: inline-block; margin: 0; }
.bq-photo-cell .btn + .btn { margin-left: 4px; }

/* 灯箱放大图片 */
#batchPhotoBox .modal { background: rgba(0,0,0,.85) !important; border: none !important; }
#batchPhotoBox img { background: #fff; }


/* ===== 总览主页（快速导航） ===== */
.home-group { margin: 18px 0 6px; }
.home-group > h3 { font-size: 15px; color: var(--ink); margin: 0 0 10px; padding-left: 10px; border-left: 4px solid var(--brand, #185fa5); }
.home-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 14px; }
.home-card {
  display: flex; flex-direction: column; gap: 6px; text-align: left;
  background: #fff; border: 1px solid var(--line, #e3e8ee); border-radius: 12px;
  padding: 16px 16px; cursor: pointer; transition: transform .12s ease, box-shadow .12s ease, border-color .12s ease;
  box-shadow: 0 1px 2px rgba(20,40,70,.04);
}
.home-card:hover { transform: translateY(-2px); box-shadow: 0 6px 18px rgba(20,40,70,.12); border-color: var(--brand, #185fa5); }
.home-card .hc-name { font-size: 15px; font-weight: 600; color: var(--ink, #1f2d3d); }
.home-card .hc-desc { font-size: 12.5px; color: #6b7785; line-height: 1.5; }
@media (max-width: 600px) { .home-grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); } }

.table-wrap { overflow-x: auto; margin-top: 12px; }
.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; max-width: 100%; margin-top: 12px; }
.table-scroll table { width: auto; min-width: 100%; }
#taktSummaryTable, #balSummaryTable { width: 100%; border-collapse: collapse; font-size: 13px; }
#taktSummaryTable th, #balSummaryTable th,
#taktSummaryTable td, #balSummaryTable td { padding: 7px 10px; border-bottom: 1px solid var(--line); white-space: nowrap; text-align: left; }
#taktSummaryTable th, #balSummaryTable th { background: #f0f4f8; position: sticky; top: 0; }
#taktSummaryTable tbody tr:hover, #balSummaryTable tbody tr:hover { background: #f7fafc; cursor: pointer; }
#taktSummaryTable .num, #balSummaryTable .num { text-align: right; font-variant-numeric: tabular-nums; }
.summary-empty { padding: 28px 12px; text-align: center; color: var(--muted); }
#arcList { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 12px; margin-top: 14px; }
.arc-card { border: 1px solid var(--line); border-radius: 10px; padding: 14px 16px; background: #fff; display: flex; flex-direction: column; gap: 8px; }
.arc-head { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; }
.arc-head strong { font-size: 14px; color: var(--ink); word-break: break-all; }
.arc-time { font-size: 11px; color: var(--muted); white-space: nowrap; }
.arc-meta { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.arc-meta .badge { background: #eef3f8; color: var(--brand); border: 1px solid #dce7f0; }
.arc-meta .badge.ghost { background: #f4f5f7; color: var(--muted); border: 1px solid var(--line); }
.arc-note { font-size: 12px; color: #374151; background: #f9fafb; border-left: 3px solid var(--line); padding: 6px 9px; border-radius: 4px; }
.arc-actions { display: flex; flex-wrap: wrap; gap: 6px 8px; margin-top: 2px; }
.arc-actions .btn { flex: 0 0 auto; }

/* 保存对话框 */
.modal-mask { position: fixed; inset: 0; background: rgba(15,23,42,.45); display: flex; align-items: center; justify-content: center; z-index: 100; padding: 16px; }
.modal-mask[hidden] { display: none !important; }
.modal { background: #fff; border-radius: 12px; padding: 22px 24px; width: 100%; max-width: 440px; box-shadow: 0 12px 40px rgba(0,0,0,.2); max-height: calc(100vh - 32px); overflow-y: auto; }
.modal h3 { margin: 0 0 16px; font-size: 16px; }
.modal .field { margin-bottom: 12px; }
.modal textarea { width: 100%; border: 1px solid var(--line); border-radius: 7px; padding: 8px 10px; font-size: 14px; font-family: inherit; resize: vertical; background:#fff; color: var(--ink); }
.modal textarea:focus, .modal .field input:focus { outline: none; border-color: var(--brand); }
.modal-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 6px; }

/* 一键保存按钮与提示 toast */
.btn.primary { background: var(--brand); color: #fff; border-color: var(--brand); }
.btn.primary:hover { filter: brightness(1.05); }
#pageToast { position: fixed; left: 50%; bottom: 32px; transform: translateX(-50%) translateY(16px); background: var(--brand); color: #fff; padding: 10px 18px; border-radius: 10px; font-size: 14px; box-shadow: 0 6px 24px rgba(0,0,0,.22); opacity: 0; pointer-events: none; transition: opacity .25s, transform .25s; z-index: 999; max-width: 90vw; text-align: center; }
#pageToast.show { opacity: 1; transform: translateX(-50%) translateY(0); }

/* ---------- 登录门 / 用户栏 / 用户管理 ---------- */
.login-overlay {
  position: fixed; inset: 0; z-index: 200;
  background: rgba(15,23,42,.55);
  display: none; align-items: center; justify-content: center;
  padding: 16px;
}
.login-card {
  background: #fff; border-radius: 14px; padding: 26px 28px;
  width: 100%; max-width: 380px; box-shadow: 0 16px 48px rgba(0,0,0,.28);
}
.login-card h2 { margin: 0 0 6px; font-size: 18px; color: var(--brand); }
.login-card .field { margin-bottom: 12px; }
.login-card input {
  width: 100%; border: 1px solid var(--line); border-radius: 8px;
  padding: 10px 12px; font-size: 14px; background:#fff; color: var(--ink);
}
.login-card input:focus { outline: none; border-color: var(--brand); }
.login-error { color: var(--bad); font-size: 13px; min-height: 18px; margin: 2px 0 8px; }
.btn.block { width: 100%; justify-content: center; }
.user-bar { display: flex; align-items: center; gap: 8px; }
.user-chip {
  display: inline-flex; align-items: center; gap: 6px;
  background: rgba(255,255,255,.16); color: #fff;
  padding: 5px 12px; border-radius: 999px; font-size: 13px; font-weight: 600;
}
/* v273：身份未解析提示（有会话但读不到角色）—— 把「编辑入口集体消失」这种静默失效变成可见、可重试 */
.auth-warn { margin-left:8px; background:#3a2a12; border:1px solid #6b4a1c; color:#f0c37a; border-radius:999px;
  padding:3px 10px; font-size:12px; cursor:pointer; font-family:inherit; }
.auth-warn:hover { border-color:#c99a4e; color:#ffdda6; }

.admin-tag {
  font-style: normal; font-size: 11px; font-weight: 600;
  background: #ffd76e; color: #7a5200; border-radius: 999px; padding: 1px 8px;
}
.admin-tag.super {
  background: linear-gradient(135deg,#f59e0b,#d97706); color: #fff;
  box-shadow: 0 1px 3px rgba(217,119,1,.45);
}
.lock-note { color: var(--bad); font-size: 13px; }
.protected-hint {
  background: #fff7ed; border: 1px solid #fed7aa; color: #9a3412;
  border-radius: 8px; padding: 8px 10px; margin: 0 0 10px;
}
#usersWrap .ops .btn:disabled { opacity: .4; cursor: not-allowed; }
.mono { font-family: Consolas, Menlo, monospace; font-size: 12px; color: var(--muted); }
.user-create { align-items: end; }
#usersWrap table td, #usersWrap table th { padding: 8px 10px; border-bottom: 1px solid var(--line); text-align: left; }
#usersWrap .ops { white-space: nowrap; }
#usersWrap .ops .btn { margin-right: 4px; }
#usersWrap .role-select {
  padding: 6px 8px; border: 1px solid var(--line); border-radius: 8px;
  background: #fff; color: var(--ink); font-size: 13px; min-width: 150px; max-width: 190px;
}

/* ---------- PPT 报告页 ---------- */
.ppt-preview { display: flex; flex-direction: column; gap: 18px; padding: 6px 0 40px; }
.ppt-slide {
  background: #fff; border: 1px solid var(--line); border-radius: 10px;
  box-shadow: 0 6px 22px rgba(20,60,110,.10); overflow: hidden;
  aspect-ratio: 16 / 9; min-height: 360px; padding: 22px 26px;
  display: flex; flex-direction: column;
}
.ppt-slide-title { font-size: 20px; font-weight: 700; color: var(--brand); border-left: 5px solid var(--brand); padding-left: 12px; margin-bottom: 14px; }
.ppt-kpis { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; }
.ppt-kpi { background: #F2F6FB; border: 1px solid #D5E2F0; border-radius: 10px; padding: 16px 10px; text-align: center; }
.ppt-kpi .v { font-size: 26px; font-weight: 800; color: var(--brand); line-height: 1.1; }
.ppt-kpi .k { font-size: 12px; color: #555; margin-top: 6px; }
.ppt-note { margin-top: 18px; font-size: 14px; color: #444; font-style: italic; line-height: 1.6; }
.ppt-charts { display: flex; gap: 14px; flex: 1; min-height: 0; }
.ppt-chart-box { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.ppt-chart-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 4px; }
.ppt-chart-title { font-size: 12px; font-weight: 600; color: var(--brand); }
.ppt-chartsel { background: #fff; color: #33415c; border: 1px solid var(--line); border-radius: 6px; padding: 3px 6px; font-size: 11px; cursor: pointer; }
.ppt-chart { flex: 1; min-height: 320px; }
.ppt-bullets { margin: 10px 0 0; padding-left: 22px; color: #333; font-size: 13px; line-height: 1.7; }
.ppt-bullets-lg { font-size: 15px; line-height: 1.9; margin: 4px 0; }
.ppt-table { font-size: 12px; }
.ppt-table th { background: var(--brand); color: #fff; }
.ppt-table td, .ppt-table th { padding: 7px 8px; border-bottom: 1px solid #D5E2F0; text-align: center; }
.ppt-cover { align-items: center; justify-content: center; background: linear-gradient(160deg, #EAF1F8 0%, #ffffff 60%); }
.ppt-cover-inner { text-align: center; }
.ppt-cover-tag { display: inline-block; font-size: 14px; color: var(--brand); border: 1px solid var(--brand); border-radius: 999px; padding: 4px 16px; margin-bottom: 18px; }
.ppt-cover-title { font-size: 44px; font-weight: 800; color: var(--brand); margin: 0 0 10px; }
.ppt-cover-sub { font-size: 16px; color: #667; margin-bottom: 30px; }
.ppt-cover-meta { display: inline-grid; grid-template-columns: auto auto; gap: 8px 18px; text-align: left; font-size: 14px; color: #444; }
.ppt-cover-meta div { display: flex; gap: 8px; }
.ppt-cover-meta span { color: var(--muted); min-width: 64px; }
@media (max-width: 760px) { .ppt-kpis { grid-template-columns: repeat(2, 1fr); } .ppt-charts { flex-direction: column; } .ppt-chart { min-height: 240px; } }

/* 产线分组对比表：组行底色 + 子行缩进 */
.ppt-table td.lbl { text-align: left; font-weight: 600; color: var(--brand); }
.ppt-table td.num { text-align: center; }

/* ===== 导出 PDF（打印引擎）：只打印预览区，每张幻灯片一页 A4 横向 ===== */
@media print {
  @page { size: A4 landscape; margin: 10mm; }
  body { background: #fff !important; }
  .no-print,
  header, nav, main > .panel:not(#ppt),
  .toolbar, .user-bar, .login-overlay, .modal, .modal-mask,
  #pptStatus { display: none !important; }
  #ppt { display: block !important; padding: 0 !important; }
  #pptPreview { padding: 0 !important; }
  #pptPreview .ppt-slide {
    display: block !important;
    page-break-after: always;
    break-after: page;
    border: 1px solid #d8e0ea;
    border-radius: 6px;
    box-shadow: none;
    margin: 0 0 6mm;
    padding: 10mm;
  }
  #pptPreview .ppt-slide:last-child { page-break-after: auto; break-after: auto; }
  #pptPreview .ppt-chart { min-height: 300px; }
  #pptPreview .ppt-table { font-size: 10px; }
  #pptPreview .ppt-bullets { font-size: 12px; }
}


/* ===== 录入校验护栏：工序提示条 + 明细表 ⚠ 标记 ===== */
.proc-warn { border: 1px solid #f0c36d; background: #fff8e6; border-radius: 6px; padding: 8px 10px; margin: 6px 0 10px; font-size: 13px; }
.proc-warn .proc-warn-item { line-height: 1.6; }
.proc-warn .proc-warn-item + .proc-warn-item { margin-top: 4px; }
.proc-warn .proc-warn-item.error { color: #a32d2d; }
.proc-warn .proc-warn-item.warn { color: #8a5a00; }
.proc-warn .proc-warn-item.info { color: #185fa5; }
.warn-mark { color: #a32d2d; font-size: 13px; margin-left: 4px; cursor: help; }

/* ===== 视频产能法双指标读数 ===== */
.vreadout { display:flex; flex-wrap:wrap; align-items:center; gap:8px; margin:8px 0 2px; padding:6px 8px; background:#f3f8fb; border:1px solid #d6e6f2; border-radius:6px; font-size:13px; }
.vreadout .tag { display:inline-block; padding:2px 8px; border-radius:12px; font-size:12px; font-weight:600; }
.vreadout .tag.ok { background:#e3f6ec; color:#1d7a45; border:1px solid #b6e3c9; }
.vreadout .tag.info { background:#e7f0fb; color:#185fa5; border:1px solid #bcd6f2; }
.vreadout .hint { color:#6b7785; font-size:12px; }

/* ===== 视频动作计数按钮 ===== */
.ac-chip { background:#e3f6ec; border:1px solid #b6e3c9; color:#1d7a45; margin:2px 0; }
.ac-chip:hover { background:#d2efe0; }

/* ===== 档案库新模块徽章 + 工位图布局 ===== */
.badge.batch { background: #fde9d9; color: #b45309; }
.badge.station { background: #e0e7ff; color: #3730a3; }
.badge.oee { background: #d1fae5; color: #047857; }

.st-flow { display: flex; flex-wrap: wrap; align-items: stretch; }
.st-box { min-width: 120px; flex: 1 1 120px; border: 2px solid #cbd5e1; border-radius: 10px; padding: 10px 12px; text-align: center; box-shadow: 0 1px 2px rgba(0,0,0,.04); }
.st-box-name { font-weight: 600; font-size: 14px; color: #1f2a37; }
.st-box-meta { display: flex; justify-content: center; gap: 8px; font-size: 12px; color: #6b7785; margin-top: 6px; flex-wrap: wrap; }
.st-box-bn { font-size: 12px; font-weight: 700; margin-top: 6px; }
.st-arrow { align-self: center; color: #9aa6b2; font-size: 20px; padding: 0 4px; }

/* ===== 视频观测 ===== */
#voVideo { background:#000; }
#voElapsed, #voPieces, #voCT { font-weight:700; }
.row { display:flex; align-items:center; }

/* ===== 数据大屏（暗色） ===== */
/* 大屏作为 flex 容器占满可视区域；在 main 内时突破 max-width 限制 */
.panel.active.screen-panel {
  display: flex;
  flex-direction: column;
  position: fixed;
  top: 0; left: 0; right: 0; bottom: 0;
  z-index: 5;
  width: 100vw;
  height: 100vh;
  margin: 0;
  max-width: 100vw;
  background: linear-gradient(160deg,#0c1322 0%,#0f1a2e 100%);
  color: #cdd6e3;
}
/* 大屏沉浸式：body.screen-mode 时隐藏顶部导航栏（.nav-wrap），防止挡住 KPI 卡片 */
body.screen-mode .nav-wrap { display: none !important; }
body.screen-mode .user-bar { display: none !important; }
.screen-panel:fullscreen,
.screen-panel:-webkit-full-screen,
.screen-panel:-moz-full-screen {
  display: flex;
  flex-direction: column;
  width: 100vw;
  height: 100vh;
  min-height: 100vh;
  padding: 0;
}
.screen-panel {
  background:linear-gradient(160deg,#0c1322 0%,#0f1a2e 100%);
  color:#cdd6e3;
  min-height: calc(100vh - 104px); /* header ~56 + nav ~48 */
  height: calc(100vh - 104px);
  overflow: hidden;
}
.screen-panel .card { background:transparent; box-shadow:none; border:none; }
.screen-bar {
  display:flex; align-items:center; gap:10px; padding:10px 18px;
  flex: 0 0 auto;
  /* v245：工具条固定**单排**。原先 flex-wrap:wrap，标题+说明+5 个按钮+更新时间+恢复顺序
     在 1600px 下总宽刚好超一行 → 「全屏」被挤到第二排。
     现在改为 nowrap：说明文字用省略号自适应收缩，按钮永不换行；极窄屏可横向滚动兜底。 */
  flex-wrap: nowrap;
  overflow-x: auto;
  overflow-y: hidden;
  background:rgba(10,18,32,.85); backdrop-filter:blur(6px);
  border-bottom:1px solid #1d2a40;
}
.screen-bar.hidden { display: none !important; }
.screen-bar strong { font-size:15px; color:#fff; }
.screen-bar .hint { color:#7e90ab; font-size:12px; }
.screen-bar .btn { padding: 7px 12px; font-size: 13px; }
/* 单排布局：标题/按钮/状态 保持自然宽度不收缩；仅「说明文字」可收缩并用省略号收尾 */
.screen-bar > strong { flex: 0 0 auto; white-space: nowrap; }
.screen-bar > .btn { flex: 0 0 auto; white-space: nowrap; }
.screen-bar > .hint { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.screen-bar > #screenUpdated,
.screen-bar > #pdScreenState,
.screen-bar > .kpi-reset-wrap { flex: 0 0 auto; white-space: nowrap; }
/* 滚动条在深色工具条上默认太显眼，弱化处理（滚动兜底时才出现） */
.screen-bar::-webkit-scrollbar { height: 0; }

/* v246：全屏大屏为 position:fixed 四边贴边 + 独立 App 模式（apple-mobile-web-app-capable）下，
   iOS 刘海/圆角/底部 Home 指示条会盖住内容。三道安全区处理：
   ① 工具条（顶部）加 padding-top/left/right；② 可滚动主体（底部）加 padding-bottom；③ 横屏左右。 */
.screen-panel { padding-left: env(safe-area-inset-left); padding-right: env(safe-area-inset-right); }
.screen-bar {
  padding-top: calc(10px + env(safe-area-inset-top));
  padding-left: calc(18px + env(safe-area-inset-left));
  padding-right: calc(18px + env(safe-area-inset-right));
}
.screen-grid { padding-bottom: calc(28px + env(safe-area-inset-bottom)) !important; }
@media (max-width: 760px) {
  .screen-bar { padding-top: calc(8px + env(safe-area-inset-top)); }
}

/* v246 触控体验：大屏上的数字/文字长按会被选中并弹出复制菜单（参观屏很干扰）；
   按钮一律 touch-action:manipulation 消除移动端双击缩放等待与误缩放。 */
.screen-panel, .screen-panel .kpi, .screen-panel .scr-card, .screen-panel .pd-board,
.kpi-v, .pd-bk-val, .pd-judge-value { user-select: none; -webkit-user-select: none; }
.screen-panel button, .screen-panel .btn, .toolbar button, .toolbar .btn { touch-action: manipulation; }
.screen-kpi {
  /* v271：KPI 条**自动填满整排并居中**（用户诉求）——
     原为 `flex: 0 0 calc((100% - 7*10px)/8)`（每项固定 1/8 宽）+ flex-start ⇒
     1278px 下 5 个 KPI 只占 62%、右侧空 470px（左留白 0），既不满也不居中。 */
  display:flex; flex-wrap:wrap; justify-content:center; gap:10px;
  padding:10px 18px 6px;
  flex: 0 0 auto;
}
.kpi { background:#13203a; border:1px solid #21314f; border-radius:12px; padding:12px 10px; text-align:center; cursor: grab; transition: transform .1s, box-shadow .1s; /* v271：改为「可伸缩」—— 个数少时自动放大铺满整排；达到上限（360px）后以居中方式留白；
     个数多时换行，最后一行同样居中。手机/平板断点另有固定列宽规则（后定义 ⇒ 覆盖此处）。 */
  flex: 1 1 150px; max-width: 360px; min-width: 0; }
.kpi:active { cursor: grabbing; }
.kpi.dragging { opacity: .6; transform: scale(1.02); box-shadow: 0 6px 16px rgba(0,0,0,.35); border-color: #5AA9FF; }
.kpi-v { font-size:22px; font-weight:800; color:#5AA9FF; }
.kpi-k { font-size:11px; color:#8fa3bf; margin-top:4px; }
.kpi-reset { font-size: 12px; color: #8fa3bf; cursor: pointer; text-decoration: underline; }
.kpi-reset:hover { color: #5AA9FF; }
.kpi-reset-wrap { margin-left: auto; }
.screen-grid {
  display:grid;
  /* v270：桌面列数改回**自适应**（auto-fit），并把「单卡最小可用宽度」定在 290px ——
     v268 写死 6 列时，1280~1500px 宽的窗口上每张卡只有 ~200px：卡片头（标题 + 两个下拉）
     就把整张卡占满，图表区被压成 0（用户报的「有数据但看不到图」与「布局很难看」）。
     行仍用 auto-rows + align-content:stretch：**行数按卡片数自动决定并拉伸填满一屏**（保持原有观感）。
     卡片用 --sp-w/--sp-h 跨格（跨格在 auto-fit 下同样成立：span 的是「列轨道」）。 */
  grid-template-columns:repeat(auto-fit,minmax(290px,1fr));
  grid-auto-rows: minmax(190px, 1fr);
  gap:12px;
  padding:10px 18px 18px;
  flex: 1 1 0;
  min-height: 0;
  overflow-y: auto;
  align-content: stretch;
  box-sizing: border-box;
}
/* v268：三块大屏的页签（自动分析 / 过程分析 / 问题与改善） */
.scr-boards { display:flex; flex-wrap:wrap; gap:8px; padding:0 18px 4px; flex:0 0 auto; }
.scr-board-tab {
  background:#13203a; border:1px solid #21314f; color:#cfe0f5; border-radius:999px;
  padding:6px 14px; font-size:13px; font-weight:600; cursor:pointer; display:flex; align-items:center; gap:6px;
}
.scr-board-tab:hover { border-color:#5AA9FF; }
.scr-board-tab.on { background:#185FA5; border-color:#185FA5; color:#fff; }
.scr-board-tab .scr-board-n {
  font-size:11px; font-weight:700; background:rgba(255,255,255,.16); border-radius:999px; padding:0 6px; min-width:18px; text-align:center;
}
.scr-card-sub { padding:0 18px 6px; font-size:12px; color:#7f93b0; flex:0 0 auto; }
/* v271：被设为「不显示」的图表 —— 恢复入口（隐藏必须可逆） */
.scr-hidden-bar { display:flex; align-items:center; gap:10px; padding:0 18px 4px; flex:0 0 auto; flex-wrap:wrap; }
.scr-restore {
  background:#13203a; border:1px dashed #3a4a63; color:#9fb0c9; border-radius:999px;
  padding:4px 12px; font-size:12px; cursor:pointer;
}
.scr-restore:hover { border-color:#5AA9FF; color:#cfe0f5; }
.scr-restore-tip { font-size:11px; color:#62748f; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
/* v269：卡片头「单独全屏查看」按钮 + 全屏浮层（把真实卡片搬进浮层，两个下拉仍可用） */
.scr-card-t { flex:1 1 auto; min-width:0; }
.scr-zoom { flex:0 0 auto; background:#0f1a2e; border:1px solid #21314f; color:#5AA9FF; border-radius:6px; padding:2px 7px; font-size:12px; line-height:1.3; cursor:pointer; }
.scr-zoom:hover { border-color:#5AA9FF; background:#152740; }
body.card-full { overflow:hidden; }
.scr-full { position:fixed; inset:0; z-index:9500; background:#070e1c; display:flex; flex-direction:column; padding:10px 12px 12px; box-sizing:border-box; }
.scr-full-bar { display:flex; align-items:center; justify-content:space-between; gap:10px; padding:0 2px 8px; flex:0 0 auto; }
.scr-full-hint { font-size:12px; color:#7f93b0; }
/* v269：全屏浮层里给图表一个**确定尺寸**。
   坑 1：链式百分比高度（.scr-card 高度 auto ⇒ 子项 height:100% 解析成 auto）会让 ECharts 量到 0 高。
   坑 2：ECharts 初始化时会往容器写**内联** `position:relative`，普通 CSS 规则压不过内联 ⇒ 必须 !important。 */
.scr-full .scr-card { flex:1 1 auto; min-height:0; height:auto; grid-column:auto !important; grid-row:auto !important; }
.scr-full .scr-card-b { flex:1 1 auto; min-height:0; height:auto; position:relative; }
.scr-full .scr-chart { position:absolute !important; inset:6px 8px 8px; height:auto; }
.scr-full .scr-empty { flex:1 1 auto; min-height:0; height:100%; }
/* v271：全屏里表格放大一档（窄卡里的 11px 在大屏上偏小） */
.scr-full .scr-tbl { font-size:13px; }
.scr-full .scr-tbl th, .scr-full .scr-tbl td { padding:8px 12px; }
.scr-full .scr-tbl th.scr-tbl-k, .scr-full .scr-tbl td.scr-tbl-k { max-width:280px; }
.scr-full .scr-tbl-cap { font-size:11px; }
.scr-card { background:#101b30; border:1px solid #21314f; border-radius:14px; overflow:hidden; display:flex; flex-direction:column; min-height: 160px; height: 100%;
  /* v268：尺寸档位（跨列 × 跨行）——由 JS 写 --sp-w/--sp-h（桌面 1~3 列、平板最多 2 列、手机忽略） */
  grid-column: span var(--sp-w, 1); grid-row: span var(--sp-h, 1); min-width: 0; }
/* 强制 echarts canvas 背景透明，避免「大屏白底」 */
.scr-chart > div, .scr-chart canvas { background: transparent !important; }
/* 大屏 grid 内部滚动条样式（暗色主题） */
.screen-grid::-webkit-scrollbar { width: 8px; height: 8px; }
.screen-grid::-webkit-scrollbar-track { background: rgba(20,32,52,.5); }
.screen-grid::-webkit-scrollbar-thumb { background: rgba(95,142,180,.5); border-radius: 4px; }
.screen-grid::-webkit-scrollbar-thumb:hover { background: rgba(95,142,180,.8); }
/* v270：卡片头固定「两行」结构 —— 第 1 行标题（横向、单行、超长省略），第 2 行两个下拉 + 全屏键。
   改前是「标题 + 两个下拉挤在同一行」：窄卡里标题被压到只剩几十像素 ⇒ 逐字换行成竖条，
   而两个下拉因为 align-items:center 会随标题高度上下浮动（看起来像「有的卡没有筛选键」）。
   两行结构同时保证：标题永远横向、两个键永远在同一位置、卡片头高度恒定（不再吃掉图表区）。 */
.scr-card-h { padding:6px 10px 7px; font-size:12px; font-weight:600; color:#cfe0f5; border-bottom:1px solid #1d2a40; background:#13203a; flex: 0 0 auto; display:flex; flex-direction:column; align-items:stretch; gap:5px; }
.scr-card-t { min-width:0; line-height:1.35; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.scr-card-ctrls { display:flex; align-items:center; gap:6px; z-index: 5; min-width:0; }
/* 两个下拉「等比分配」控件行宽度（窄卡里也不会把 ⛶ 挤出去）；⛶ 固定尺寸不参与伸缩 */
.scr-card-ctrls .scr-viewsel, .scr-card-ctrls .scr-chartsel { flex:1 1 auto; min-width:0; }
.scr-card-ctrls .scr-zoom { flex:0 0 auto; }
.scr-viewsel, .scr-chartsel, .ppt-chartsel {
  appearance: none; -webkit-appearance: none; -moz-appearance: none;
  background: rgba(16,27,48,.95);
  color: #cfe0f5;
  border: 1px solid #21314f;
  border-radius: 6px;
  padding: 3px 22px 3px 8px;
  font-size: 11px;
  cursor: pointer;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'><path fill='%23cfe0f5' d='M0 0l5 6 5-6z'/></svg>");
  background-repeat: no-repeat;
  background-position: right 7px center;
  background-size: 9px 6px;
}
.scr-viewsel:hover, .scr-chartsel:hover, .ppt-chartsel:hover { border-color: #3a5a8a; }
.scr-viewsel:focus, .scr-chartsel:focus, .ppt-chartsel:focus { outline: 1px solid #5AA9FF; }
.scr-viewsel option, .scr-chartsel option, .ppt-chartsel option { background:#13203a; color:#cfe0f5; }
.scr-card[draggable="true"] { cursor:move; }
.scr-card.dragging { opacity:.55; border:1px dashed #5AA9FF; box-shadow:0 0 12px rgba(90,169,255,.35); }
.scr-card-b { padding:6px 8px 8px; flex:1; min-height:0; position:relative; height: 100%; overflow: visible; }
.scr-chart { width:100%; height:100%; min-height:120px; }
.scr-empty { width:100%; height:100%; min-height:120px; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:6px; color:#62748f; font-size:13px; text-align:center; padding:8px 20px; }
/* v270：空卡占位不再只说「暂无数据」—— 写明**数据来源**并给「去录入」按钮（用户不用猜去哪录） */
.scr-empty-t { color:#9fb0c9; font-size:13px; }
.scr-empty-hint { color:#6f83a0; font-size:11px; line-height:1.45; max-width:100%; }
.scr-empty-go { padding:4px 12px; font-size:12px; background:#1a2c4a; color:#cfe0f5; border:1px solid #21314f; border-radius:8px; cursor:pointer; }
.scr-empty-go:hover { border-color:#5AA9FF; color:#fff; }
/* v270：「数据表」视图（图表类型的最后一项）—— 与图形同一份数据，窄卡里比图更可读 */
.scr-tbl-wrap { position:absolute; inset:0; overflow:auto; padding:4px 8px 2px; box-sizing:border-box; -webkit-overflow-scrolling:touch; }
.scr-tbl { width:100%; border-collapse:collapse; font-size:11px; }
.scr-tbl th, .scr-tbl td { padding:4px 6px; border-bottom:1px solid rgba(95,142,180,.16); white-space:nowrap; }
.scr-tbl thead th { position:sticky; top:0; background:#16233c; color:#9fb0c9; font-weight:600; text-align:right; z-index:1; }
.scr-tbl th.scr-tbl-k, .scr-tbl td.scr-tbl-k { text-align:left; max-width:140px; overflow:hidden; text-overflow:ellipsis; color:#cdd6e3; position:sticky; left:0; background:#101b30; }
.scr-tbl thead th.scr-tbl-k { background:#16233c; z-index:2; }
.scr-tbl td.scr-tbl-v { text-align:right; color:#dfe9f7; font-variant-numeric:tabular-nums; }
.scr-tbl tbody tr:nth-child(even) td { background:rgba(255,255,255,.025); }
.scr-tbl-cap { font-size:10px; color:#62748f; padding:4px 2px 2px; }
/* v270：切换大屏时的即时反馈（渲染是异步的，没有它用户会以为「点了没反应」） */
.screen-grid.board-switching { opacity:.45; }
.screen-grid.board-switching::before { content:'切换中…（Switching）'; position:absolute; left:50%; top:8px; transform:translateX(-50%); font-size:12px; color:#9fb0c9; }
.screen-grid { position:relative; }

/* 总览内嵌浅色图表 */
.home-charts { display:grid; grid-template-columns:repeat(auto-fit,minmax(300px,1fr)); gap:14px; margin-top:16px; }
.home-charts-hint { color:#6b7785; font-size:13px; background:#f3f7fb; border:1px dashed #cbd5e1; border-radius:10px; padding:14px; }
.scr-card.light { background:#fff; border:1px solid #e3e9f1; }
.scr-card.light .scr-card-h { background:#f3f7fb; color:#33415c; border-bottom:1px solid #e3e9f1; }
.scr-card.light .scr-chart { height:240px; }

/* ===== 移动端适配（手机 / 窄屏自动适应） ===== */
@media (max-width: 760px) {
  header { padding: 10px 14px; }
  header h1 { font-size: 15px; }
  header p { font-size: 11px; }

  main { padding: 14px 12px 64px; }

  .card { padding: 14px 14px; }
  .card h2 { font-size: 14px; }
  .card h3 { font-size: 13px; }

  /* 表单与输入：放大触摸目标、字号≥16px 防止 iOS 自动放大 */
  .field { min-width: 0; }
  .field input, .field select,
  .login-card input,
  .modal input, .modal textarea,
  .arc-search,
  td input, td select,
  textarea {
    font-size: 16px;
    padding: 10px 10px;
  }

  /* 工序录入：字段纵向堆叠、装满宽度 */
  .proc-head { flex-direction: column; align-items: stretch; }
  .proc-head .field { min-width: 0; }

  .grid, .metrics { grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); }
  .metrics .metric .v { font-size: 18px; }

  /* 工具栏按钮：自动换行并拉满，便于单手点按 */
  .toolbar { gap: 8px; }
  .toolbar .btn { flex: 1 1 auto; text-align: center; padding: 11px 12px; font-size: 14px; }
  .btn { padding: 10px 14px; font-size: 14px; }
  .btn.sm { padding: 8px 10px; font-size: 13px; }

  /* 工位图：竖向堆叠便于手机浏览 */
  .st-flow { flex-direction: column; }
  .st-box { flex: 1 1 auto; }
  .st-arrow { transform: rotate(90deg); align-self: center; padding: 2px 0; }

  /* 图表：移动端降低高度，避免过长 */
  #chart, #balanceGauge, #balanceBar { height: 280px; }
  .charts2 { grid-template-columns: 1fr; }
  .ecrs-grid { grid-template-columns: 1fr; }

  /* 总览内嵌图表：单列 */
  .home-charts { grid-template-columns: 1fr; }

  /* ===== 数据大屏（暗色参观屏）手机端重构 v228 =====
     原问题：.screen-grid 用 grid-auto-rows:minmax(160px,1fr)+align-content:stretch，
     会把每行沿视口高度「均分压缩」→ 手机单列时图表被压扁、底部内容被截断。
     方案：改为「块级顺序排列 + 每卡固定高度 + 容器纵向滚动」，信息完整可见、滚动流畅、触摸目标加大。 */
  .panel.active.screen-panel {
    position: fixed;
    top: 0; left: 0; right: 0; bottom: 0;
    width: 100vw;
    height: 100vh;
    height: 100dvh;                 /* 移动端动态视口，地址栏伸缩不再遮挡底部内容 */
    max-width: 100vw;
    min-height: 0;
    margin: 0;
    overflow: hidden;
    display: flex;
    flex-direction: column;
  }
  .screen-bar { flex: 0 0 auto; gap: 8px; padding: 8px 12px; row-gap: 8px; flex-wrap: wrap; overflow-x: visible; }
  .screen-bar strong { font-size: 14px; }
  .screen-bar .hint { display: none; }
  .screen-bar .btn { padding: 9px 12px; font-size: 13px; min-height: 40px; }
  .screen-kpi { flex: 0 0 auto; gap: 8px; padding: 10px 12px 6px; }
  .kpi { padding: 10px 8px; flex: 0 0 calc((100% - 3 * 8px) / 4); }
  .kpi-v { font-size: 18px; }
  .kpi-k { font-size: 10px; }
  .screen-grid {
    display: block;                 /* 关键：取消 grid 均分，杜绝行高被压扁 */
    flex: 1 1 auto;
    min-height: 0;
    height: auto;
    overflow-y: auto;
    overflow-x: hidden;
    -webkit-overflow-scrolling: touch;   /* iOS 惯性滚动更跟手 */
    overscroll-behavior: contain;        /* 滚动不穿透到底层页面 */
    padding: 10px 12px 28px;             /* 底部留白，最后一张卡不被遮挡 */
    box-sizing: border-box;
    align-content: initial;
  }
  .screen-panel .scr-card {
    height: 320px;                  /* 每卡固定高度：图表获得充足空间，不再被压扁 */
    min-height: 320px;
    margin: 0 0 12px;
  }
  .screen-panel .scr-card:last-child { margin-bottom: 4px; }
  .screen-panel .scr-card.light .scr-chart { height: 100%; }
  .screen-panel .scr-chart { height: 100%; min-height: 0; }
  .screen-panel .scr-empty { height: 100%; min-height: 0; }
}

@media (max-width: 1100px) and (min-width: 761px) {
  /* 中等宽度桌面 / 平板：大屏顶部栏隐藏描述，避免换行 */
  .screen-bar .hint { display: none; }
  /* 数据大屏平板端 v228：2 列 + 固定行高（280px），避免均分压缩导致图表过矮；溢出时容器内滚动 */
  .screen-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-auto-rows: 280px;
    align-content: start;
    gap: 12px;
  }
  .screen-panel .scr-card { min-height: 280px; height: 280px; }
  .screen-panel .scr-chart { min-height: 0; }
  .screen-panel .scr-empty { min-height: 0; }
}

@media (max-width: 420px) {
  main { padding: 12px 10px 64px; }
  .card { padding: 12px 12px; }
  .screen-kpi { gap: 8px; }
  .kpi { padding: 10px 6px; flex: 0 0 calc((100% - 1 * 8px) / 2); }
  .kpi .kpi-v { font-size: 18px; }
  .toolbar .btn { flex: 1 1 100%; }
}

/* 超级管理员数据维护区 */
.danger-zone { border: 1px solid #f0b8b8; background: #fff6f6; }

/* 线平衡改善：5 组测量输入框紧凑显示 */
#lbimp .table-wrap { overflow-x: auto; }
#lbimp table { min-width: 820px; }
#lbimp .lbimp-measure { width: 62px; min-width: 52px; padding: 6px 4px; text-align: center; }
#lbimp .lbimp-takt-disp { font-weight: 600; color: var(--brand); min-width: 80px; }
#lbimp td .lbimp-name { min-width: 90px; }
#lbimp td .lbimp-man { width: 56px; text-align: center; }
.danger-zone h2 { color: #c0392b; }
.confirm-input { width: 100%; padding: 10px 12px; margin-top: 8px; font-size: 16px; border: 1px solid #d9e0ea; border-radius: 8px; box-sizing: border-box; }

/* 自定义公式 / 聚合统计（批 2） */
.formula-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 10px; margin-top: 10px; }
.formula-card { border: 1px solid #e3e8f0; border-radius: 10px; padding: 10px 12px; background: #fbfcfe; }
.formula-card .fc-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 6px; }
.formula-card .fc-expr { background: #f1f4f9; border-radius: 6px; padding: 6px 8px; font-size: 13px; word-break: break-all; color: #334; }
.formula-card .fc-ops { display: flex; gap: 6px; margin-top: 8px; }
.chk-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 4px 10px; max-height: 180px; overflow: auto; padding: 4px 0; }
.agg-row { display: flex; gap: 6px; align-items: center; margin-bottom: 6px; }
.agg-row select, .agg-row input { flex: 1 1 auto; min-width: 0; }
.agg-row .btn.xs { flex: 0 0 auto; }
.func-bar { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin: 6px 0; }
.var-bar { display: flex; flex-wrap: wrap; gap: 6px; max-height: 120px; overflow: auto; padding: 4px; background: #f7f9fc; border-radius: 6px; }
.modal.wide { max-width: 720px; width: 92vw; }
.mono { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }


/* ---- 资料库（Knowledge Base）---- */
.kb-analyzer-head { display:flex; align-items:flex-start; justify-content:space-between; gap:12px; flex-wrap:wrap; margin-bottom:10px; }
.kb-chips { display:flex; gap:6px; flex-wrap:wrap; }
.kb-list { display:grid; grid-template-columns:repeat(auto-fill,minmax(320px,1fr)); gap:12px; }
.kb-card { border:1px solid var(--line); border-radius:12px; padding:12px 14px; background:#fff; }
.kb-head { display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
.kb-head b { font-size:14px; color:#2b3a55; flex:1; }
.kb-ops { display:flex; gap:6px; }
.kb-summary { margin:8px 0 4px; font-size:13px; color:#5b6b85; line-height:1.6; }
.kb-content { margin:8px 0; font-size:13px; color:#3d4c66; line-height:1.8; white-space:pre-line; background:#f7f9fc; border-left:3px solid var(--brand); padding:8px 10px; border-radius:0 8px 8px 0; }
.kb-imps { margin-top:8px; }
.kb-imp { border:1px solid #e4eaf3; border-radius:10px; padding:8px 10px; margin-bottom:8px; background:#fbfcfe; }
.kb-imp > b { font-size:12px; color:var(--brand); }
.kb-imp-row { font-size:12.5px; color:#3d4c66; margin-top:4px; line-height:1.6; }
.kb-tag { display:inline-block; min-width:36px; background:#eef3fa; color:#185FA5; border-radius:4px; font-size:11px; padding:1px 5px; margin-right:6px; text-align:center; }
.kb-tag.act { background:#e8f5ef; color:#2E8B57; }
.kb-tag.mth { background:#fdf3e3; color:#b0791a; }
.kb-tag.eff { background:#fbe9e8; color:#c24438; }
.kb-foot { margin-top:8px; }
/* 数据分析助手 */
.an-concl { font-size:13px; color:#33415c; line-height:1.7; margin:4px 0; }
.an-tips-title { font-size:13px; font-weight:700; color:var(--brand); margin:12px 0 6px; }
.an-tip { font-size:13px; color:#2E8B57; line-height:1.7; margin:4px 0; padding-left:4px; }
.an-in { width:100%; }

/* ---- 改善输出（Improvement / PDCA）---- */
.imp-board { display:grid; grid-template-columns:repeat(auto-fit,minmax(240px,1fr)); gap:12px; margin-top:12px; }
.imp-col { background:#f7f9fc; border-radius:12px; padding:10px; min-height:120px; }
.imp-col-h { font-size:13px; font-weight:700; border-bottom:2px solid; padding-bottom:6px; margin-bottom:8px; display:flex; justify-content:space-between; }
.imp-card { background:#fff; border:1px solid var(--line); border-radius:10px; padding:10px; margin-bottom:8px; }
.imp-card-od { border-color:#E2574C; box-shadow:0 0 0 1px rgba(226,87,76,.25); }
.imp-card-t { font-size:13px; font-weight:700; color:#2b3a55; border-left:3px solid; padding-left:6px; }
.imp-card-m { font-size:12px; color:#5b6b85; margin-top:6px; line-height:1.5; }
.imp-card-f { margin-top:8px; display:flex; gap:6px; flex-wrap:wrap; }
.imp-table { width:100%; border-collapse:collapse; font-size:13px; }
.imp-table th { background:#eef3fa; color:#33415c; padding:8px 6px; text-align:left; }
.imp-table td { padding:8px 6px; border-bottom:1px solid #eef1f6; }
.imp-overdue { background:#fdf3f2; }
.imp-od { color:#E2574C; font-size:11px; font-weight:700; margin-top:2px; }
.imp-badge { display:inline-block; color:#fff; border-radius:10px; padding:1px 8px; font-size:11px; }
.imp-pdca { margin-top:12px; }
.imp-sec { border:1px solid #e4eaf3; border-radius:10px; padding:10px; margin-bottom:10px; background:#fbfcfe; }
.imp-sec.p { border-left:4px solid #185FA5; } .imp-sec.d { border-left:4px solid #2E8B57; }
.imp-sec.c { border-left:4px solid #7B5EA7; } .imp-sec.a { border-left:4px solid #E2574C; }
.imp-pdca-tag { display:inline-block; font-weight:800; color:#fff; border-radius:6px; padding:2px 10px; font-size:12px; margin-bottom:8px; background:#185FA5; }
.imp-sec.d .imp-pdca-tag { background:#2E8B57; } .imp-sec.c .imp-pdca-tag { background:#7B5EA7; } .imp-sec.a .imp-pdca-tag { background:#E2574C; }
.imp-img { position:relative; width:110px; height:82px; border:1px solid #d5dde8; border-radius:8px; overflow:hidden; cursor:pointer; }
.imp-img img { width:100%; height:100%; object-fit:cover; }
.imp-img:hover { border-color:#185FA5; }
.imp-img-x { position:absolute; top:2px; right:2px; background:rgba(0,0,0,.6); color:#fff; border-radius:50%; width:18px; height:18px; line-height:16px; text-align:center; cursor:pointer; font-size:12px; z-index:2; }
.imp-lightbox { position:fixed; inset:0; background:rgba(0,0,0,.92); z-index:10000; display:flex; align-items:center; justify-content:center; }
.imp-lightbox img { max-width:96vw; max-height:96vh; object-fit:contain; }
.imp-audit-comment { background:#fdf3e3; border:1px solid #f0d9a8; border-radius:8px; padding:8px 10px; font-size:12.5px; color:#8a6a2a; margin-top:10px; }
.imp-kpi { background:#f5f8fc; border:1px solid var(--line); border-radius:10px; padding:10px; text-align:center; }
.imp-kpi-v { font-size:22px; font-weight:800; color:#185FA5; }
.imp-kpi-k { font-size:11px; color:#5b6b85; margin-top:2px; }

/* ---- 改善输出：分段附件与状态条 ---- */
.imp-seg-files { margin-top:6px; }
.seg-files-list { display:flex; flex-wrap:wrap; gap:8px; margin-top:4px; }
.imp-file { display:inline-flex; align-items:center; gap:6px; background:#f3f6fa; border:1px solid #d5dde8; border-radius:8px; padding:4px 8px; font-size:12px; max-width:220px; }
.imp-file a { color:#185FA5; text-decoration:none; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.imp-file a:hover { text-decoration:underline; }
.imp-stbar { display:inline-block; color:#fff; border-radius:10px; padding:2px 12px; font-size:12px; font-weight:700; }
.imp-seg-files .seg-file { font-size:12px; }

/* ---- 改善输出 v2：流程指示条 ---- */
.imp-flowbar { display:flex; align-items:center; gap:6px; margin:8px 0; font-size:12px; color:#8896A6; flex-wrap:wrap; }
.imp-flow { display:inline-flex; align-items:center; justify-content:center; width:26px; height:26px; border-radius:50%; background:#eef3fa; color:#185FA5; font-weight:800; border:2px solid #d5dde8; }
.imp-flow.on { background:#185FA5; color:#fff; border-color:#185FA5; box-shadow:0 0 0 3px rgba(24,95,165,.18); }
.imp-tab { margin-right: 4px; }

/* ---- 问题提报（Issue Report） ---- */
.iss-badge { display:inline-block; color:#fff; border-radius:10px; padding:2px 10px; font-size:11.5px; font-weight:600; }
.iss-overdue { background:#fff6f6; }
.iss-od { display:inline-block; background:#E2574C; color:#fff; border-radius:8px; padding:0 6px; font-size:11px; }
.iss-tab { margin-right: 4px; }
.iss-ops { white-space: nowrap; }
.iss-ops .btn { margin-right: 4px; }
.iss-meta { display:flex; flex-wrap:wrap; gap:10px; margin:10px 0; }
.iss-meta > div { flex:1 1 120px; background:#f5f8fc; border:1px solid var(--line); border-radius:10px; padding:8px 10px; }
.iss-meta span { display:block; font-size:11px; color:#5b6b85; }
.iss-meta b { font-size:14px; color:#33415c; }
.iss-desc { background:#f7f9fc; border:1px solid #e4eaf3; border-radius:8px; padding:10px 12px; font-size:13.5px; white-space:pre-wrap; min-height:40px; }
.iss-imgs { display:flex; flex-wrap:wrap; gap:8px; margin-top:4px; }
.iss-imgs img { width:110px; height:82px; object-fit:cover; border:1px solid #d5dde8; border-radius:8px; cursor:pointer; }
.iss-imgs img:hover { border-color:#185FA5; }
.iss-pdca { background:#f5f8fc; border:1px solid var(--line); border-radius:10px; padding:10px 12px; }
.iss-pdca-seg { background:#fff; border:1px solid #e4eaf3; border-radius:8px; padding:10px 12px; margin:8px 0; }
.iss-pdca-seg-title { font-weight:600; font-size:13.5px; margin-bottom:6px; }
.iss-pdca-item { margin:6px 0; }
.iss-pdca-item b { display:block; font-size:12px; color:#5b6b85; margin-bottom:2px; }
.iss-pdca .iss-imgs { margin-top:6px; }
.iss-prog { height:10px; background:#e8eef6; border-radius:6px; overflow:hidden; margin:8px 0 4px; }
.iss-prog-bar { height:100%; background:linear-gradient(90deg,#185FA5,#5AA9FF); border-radius:6px; transition:width .3s; }
.iss-pdca-header { display:flex; align-items:center; gap:12px; flex-wrap:wrap; margin-bottom:6px; }
.iss-pdca-seg.active { background:#f8fbff; border-color:#b8d4f0; box-shadow:0 1px 4px rgba(24,95,165,.08); }
.iss-pdca-actions { display:flex; align-items:flex-end; gap:8px; flex-wrap:wrap; margin-top:10px; padding-top:8px; border-top:1px dashed #dce4ef; }
.iss-pdca-actions .field { flex:1 1 100%; margin:0 0 6px; }
.iss-pdca-actions .field label { font-size:12px; }
.iss-pdca-actions .btn { white-space:nowrap; }
.iss-pdca-actions select { padding:6px 8px; border:1px solid var(--line); border-radius:6px; min-width:140px; }
.iss-pdca-ta, .iss-pdca-comment { width:100%; resize:vertical; }
.iss-pdca-auditbox { background:#fffbf5; border:1px dashed #f0d6a8; border-radius:8px; padding:10px; }
.iss-pdca-files { margin-top:6px; }
.iss-pdca-files-list { display:flex; flex-wrap:wrap; gap:8px; margin-top:6px; }
.iss-submit-box { background:#f7f9fc; border:1px solid #e4eaf3; border-radius:8px; padding:10px 12px; font-size:13px; }
.iss-submit-box > div { margin:4px 0; }
.iss-seg-files { margin-top:6px; }
.is-files-list, .sb-files-list { display:flex; flex-wrap:wrap; gap:8px; margin-top:4px; }

/* 问题与改善：流转记录留痕 */
.iss-trace { background:#fafbfe; border:1px solid #e6eaf2; border-radius:8px; padding:8px 10px; font-size:12.5px; }
.iss-trace-row { display:flex; flex-wrap:wrap; align-items:center; gap:6px 10px; padding:5px 0; border-bottom:1px dashed #eef1f6; }
.iss-trace-row:last-child { border-bottom:none; }
.iss-trace-act { font-weight:600; color:#1a64b5; }
.iss-trace-by { color:#3a4a63; }
.iss-trace-at { color:#9aa4b5; margin-left:auto; font-size:11.5px; }
.iss-trace-desc { flex:1 1 100%; color:#5b6b85; background:#fff; border-left:3px solid #cdd7e6; padding:4px 8px; border-radius:4px; margin-top:2px; }

/* 问题与改善：合并页子 tab */
.lean-tabs { margin-bottom:10px; }
.lean-tabs .btn { margin-right:6px; }
.lean-sub { display:none; }
.lean-sub.active { display:block; }

/* ---------- 打印：仅输出指定弹窗/面板 ---------- */
@media print {
  @page { margin: 8mm; }
  .print-hide { display: none !important; }
  .print-ancestor { display: block !important; visibility: visible !important; }
  .print-target { position: absolute; left: 0; top: 0; width: 100%; background: #fff !important; color: #000 !important; overflow: visible !important; z-index: 99999; }
  .print-target, .print-target * { visibility: visible !important; }
  .print-target .modal { width: 100% !important; max-width: 100% !important; max-height: none !important; border: none !important; box-shadow: none !important; background: #fff !important; color: #000 !important; overflow: visible !important; }
  .print-target .modal-actions, .print-target .toolbar.no-print, .print-target .no-print { display: none !important; }
  .print-target h2, .print-target h3, .print-target h4 { color: #000 !important; page-break-after: avoid; }
  .print-target p.hint, .print-target .hint { color: #444 !important; }
  .print-target table { width: 100%; border-collapse: collapse; font-size: 11px; color: #000; }
  .print-target th, .print-target td { border: 1px solid #999; padding: 4px 5px; color: #000; }
  .print-target th { background: #e9edf2 !important; }
  .print-target img { max-width: 100%; height: auto; }
  .print-target .table-wrap, .print-target .metric, .print-target .ecrs-block, .print-target .card { page-break-inside: avoid; }
  .print-target .badge { border: 1px solid #999; }
}

/* ================= 待办（My Tasks）聚合页 ================= */
.tasks-filters { display:flex; flex-wrap:wrap; gap:8px; align-items:center; margin:10px 0 14px; }
.tasks-filters button { padding:6px 14px; border-radius:18px; border:1px solid var(--border, #d6dde6); background:#fff; color:#33415c; cursor:pointer; font-size:13px; }
.tasks-filters button.active { background:#185FA5; border-color:#185FA5; color:#fff; }
.tasks-count { margin-left:auto; color:#6b7888; font-size:13px; }

.tasks-groups { display:flex; flex-direction:column; gap:18px; }
.task-group { background:#f7f9fb; border:1px solid #e6ebf1; border-radius:12px; padding:12px 14px; }
.task-group > h3 { margin:0 0 10px; font-size:15px; color:#1f2d3d; display:flex; align-items:center; gap:8px; }
.task-gcount { background:#185FA5; color:#fff; border-radius:10px; font-size:12px; padding:1px 8px; }
.task-att-block { margin-top:8px; }
.task-att-title { font-size:13px; font-weight:600; color:#48586e; margin:6px 0 6px; padding-left:8px; border-left:3px solid #c2cdd9; }
.task-att-count { color:#8a96a6; font-weight:400; margin-left:4px; }
.task-att-list { display:grid; grid-template-columns:repeat(auto-fill, minmax(280px, 1fr)); gap:10px; }

.task-card { background:#fff; border:1px solid #e3e9f0; border-radius:10px; padding:10px 12px; cursor:pointer; transition:box-shadow .15s, transform .15s; }
.task-card:hover { box-shadow:0 4px 14px rgba(24,95,165,.16); transform:translateY(-1px); }
.task-card.is-mine { border-color:#E2574C; box-shadow:0 0 0 2px rgba(226,87,76,.12); }
.task-head { display:flex; align-items:center; gap:6px; flex-wrap:wrap; margin-bottom:6px; }
.task-att-badge { font-size:11px; padding:1px 8px; border-radius:10px; font-weight:600; }
.task-att-badge.att-initiated { background:#e7f0fb; color:#185FA5; }
.task-att-badge.att-received { background:#fdf2e0; color:#C77C12; }
.task-status { font-size:11px; padding:1px 8px; border-radius:10px; color:#fff; margin-left:auto; }
.task-title { font-size:14px; font-weight:600; color:#1f2d3d; line-height:1.35; }
.task-sub { font-size:12px; color:#6b7888; margin-top:2px; }
.task-progress { height:6px; background:#eef2f6; border-radius:4px; overflow:hidden; margin:8px 0 6px; }
.task-bar { height:100%; border-radius:4px; transition:width .3s; }
.task-foot { display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
.task-next { font-size:12px; color:#33415c; }
.task-mine { background:#E2574C; color:#fff; font-size:11px; padding:1px 8px; border-radius:10px; font-weight:600; }
.task-meta { font-size:12px; color:#6b7888; margin-top:5px; }
.task-time { font-size:11px; color:#9aa6b4; margin-top:2px; }
.task-empty { padding:24px; text-align:center; color:#6b7888; background:#f7f9fb; border-radius:10px; }
.task-err { background:#fdecea; border:1px solid #f3b7b1; color:#b23b32; border-radius:8px; padding:8px 10px; margin:8px 0; font-size:13px; }

/* ---- 全局监管模式（超级管理员） ---- */
.tasks-filters .tf-row { display:flex; flex-wrap:wrap; gap:8px; align-items:center; margin-bottom:8px; }
.tasks-filters .tf-label { font-size:13px; color:#48586e; }
.tasks-filters select#tasksAcc { padding:5px 8px; border-radius:8px; border:1px solid #d6dde6; background:#fff; color:#33415c; font-size:13px; max-width:220px; }
.tasks-filters .tf-check { font-size:13px; color:#48586e; display:inline-flex; align-items:center; gap:4px; cursor:pointer; }
.task-owner-badge { font-size:11px; padding:1px 8px; border-radius:10px; font-weight:600; background:#eef1f5; color:#3a4a5e; }
.task-type-tag { font-size:11px; padding:1px 8px; border-radius:10px; font-weight:600; background:#eaf3ec; color:#2E8B57; }
.task-type-tag.tg-batch { background:#e7f0fb; color:#185FA5; }
.task-type-tag.tg-issue { background:#fdecea; color:#C0392B; }
.task-type-tag.tg-imp   { background:#f3ecf9; color:#7B5EA7; }
.task-legend { font-size:12px; color:#5b6b85; margin:8px 0 2px; display:flex; align-items:center; gap:6px; flex-wrap:wrap; }
.tg-legend { font-size:11px; padding:1px 8px; border-radius:10px; font-weight:600; }
.tg-legend.tg-batch { background:#e7f0fb; color:#185FA5; }
.tg-legend.tg-issue { background:#fdecea; color:#C0392B; }
.tg-legend.tg-imp   { background:#f3ecf9; color:#7B5EA7; }
.task-next-actor { font-size:12px; color:#C77C12; background:#fdf2e0; padding:1px 8px; border-radius:10px; font-weight:600; }
.task-done-tag { font-size:11px; color:#2E8B57; background:#e7f3ec; padding:1px 7px; border-radius:10px; }
.task-card.att-global { border-left:3px solid #6b7888; }
.task-card.is-done { opacity:.72; }
.task-acc-block { background:#f7f9fb; border:1px solid #e6ebf1; border-radius:12px; padding:12px 14px; }
.task-acc-title { font-size:15px; color:#1f2d3d; display:flex; align-items:center; gap:8px; margin-bottom:10px; font-weight:600; }
.task-acc-count { background:#5b6b85; color:#fff; border-radius:10px; font-size:12px; padding:1px 8px; font-weight:400; }
.task-acc-open { font-size:12px; color:#C77C12; background:#fdf2e0; padding:1px 8px; border-radius:10px; }
.task-acc-done { font-size:12px; color:#2E8B57; }
.task-acc-list { display:grid; grid-template-columns:repeat(auto-fill, minmax(280px, 1fr)); gap:10px; }

/* ===== IE自动分析·小白引导步骤条与合规状态（v103 新增，仅新增类，不动既有样式） ===== */
.cap-step { display:inline-block; padding:3px 10px; border-radius:999px; font-size:12px; background:#f1f1f1; color:#888; border:1px solid #ddd; transition:all .15s; }
.cap-step.active { background:#185FA5; color:#fff; border-color:#185FA5; }
.cap-step.done { background:#e6f1fb; color:#185FA5; border-color:#85b7eb; }
.cap-step.warn { background:#fdeaea; color:#a32d2d; border-color:#f09595; }
#captureCompliance.ok { color:#2E8B57; }
#captureCompliance.bad { color:#a32d2d; }

/* ===== IE自动分析·傻瓜模式结果页（v107） ===== */
.res-grid { display:flex; flex-wrap:wrap; gap:12px; margin:10px 0; }
.res-block { flex:1; min-width:150px; border:1px solid var(--border); border-radius:10px; padding:10px 12px; background:#fafbfc; }
.res-label { font-size:12px; color:#666; }
.res-val { font-size:24px; font-weight:700; color:#185FA5; margin:2px 0; }
.res-sub2 { font-size:12px; color:#888; }
.res-sub { font-weight:600; margin:12px 0 4px; color:#1f2d3d; }
.res-list { margin:0 0 8px 18px; padding:0; }
.res-list li { margin:3px 0; line-height:1.5; }
.res-tbl { border-collapse:collapse; width:100%; margin:8px 0; font-size:13px; }
.res-tbl th, .res-tbl td { border:1px solid var(--border); padding:5px 8px; text-align:left; }
.res-bn { background:#fdeaea; }
.res-ctx { font-size:13px; color:#1f2d3d; margin:2px 0 10px; font-weight:600; }
#smartBar .row { margin:6px 0; }
/* 汇总表操作列吸右：横向滚动时查看/删除始终可见 */
.table-wrap table td.ops-col, .table-wrap table th.ops-col { position: sticky; right: 0; background: #fff; box-shadow: -2px 0 4px rgba(0,0,0,.08); z-index: 1; }
/* 总体结论一行一条，类 Excel */
.conclusion-list p { margin: 4px 0; line-height: 1.6; font-size: 14px; }


/* ---------- 工位图打印模板样式 ---------- */
.station-print-wrap { background: #fff; border: 1px solid var(--line); padding: 18px; margin-top: 14px; }
.station-print-view { color: #000; font-size: 12px; line-height: 1.5; }
.station-print-view .sp-title { text-align: center; font-size: 20px; font-weight: bold; margin-bottom: 10px; }
.station-print-view table { width: 100%; border-collapse: collapse; margin: 6px 0; font-size: 11px; }
.station-print-view th, .station-print-view td { border: 1px solid #999; padding: 4px 6px; text-align: center; vertical-align: middle; }
.station-print-view th { background: #e9edf2; }
.station-print-view .sp-subhead { text-align: left; }
.station-print-view .sp-flow-wrap { margin: 14px 0; overflow-x: auto; }
.station-print-view .sp-flow { display: flex; align-items: center; gap: 6px; min-width: max-content; }
.station-print-view .sp-step { text-align: center; min-width: 90px; border: 1px solid #666; border-radius: 6px; padding: 6px; background: #fff; }
.station-print-view .sp-step-id { width: 28px; height: 28px; line-height: 26px; border: 1px solid #333; border-radius: 50%; margin: 0 auto 4px; font-weight: bold; }
.station-print-view .sp-step-name { font-weight: bold; margin-bottom: 3px; }
.station-print-view .sp-step-tag { font-size: 10px; padding: 2px 4px; border: 1px solid #999; border-radius: 3px; }
.station-print-view .sp-step-bn { color: #c0392b; font-weight: bold; margin-top: 3px; }
.station-print-view .sp-arrow { font-size: 18px; color: #333; }
.station-print-view .sp-desc-title { text-align: center; font-size: 16px; font-weight: bold; margin: 14px 0 8px; }
.station-print-view .sp-desc-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.station-print-view .sp-desc-item { border: 1px solid #999; padding: 8px; }
.station-print-view .sp-desc-idx { font-weight: bold; margin-bottom: 4px; }
.station-print-view .sp-desc-name { font-weight: bold; margin-bottom: 4px; }
.station-print-view .sp-desc-text { color: #333; }
.station-print-view .sp-bottom { margin-top: 12px; }
.station-print-view .sp-log { margin-top: 10px; }
.station-print-view .sp-note { border: 1px solid #999; padding: 6px; margin-top: 10px; white-space: pre-wrap; }
.station-print-view .sp-footer { display: flex; justify-content: space-between; margin-top: 16px; }
.station-print-view .sp-footer span { width: 30%; border-top: 1px solid #333; padding-top: 4px; text-align: center; }
@media print {
  .station-print-view { font-size: 10.5pt; }
  .station-print-view .sp-desc-grid { grid-template-columns: 1fr 1fr; }
}

/* ===== 草稿箱（Drafts / 待办）· v146 ===== */
.draft-table { width: 100%; border-collapse: collapse; }
.draft-table th, .draft-table td { padding: 10px 12px; border-bottom: 1px solid #e8ecf2; text-align: left; vertical-align: middle; }
.draft-table th { background: #f4f7fb; font-size: 13px; color: #5a6678; }
.draft-table tbody tr:hover { background: #fafcff; }
.draft-badge { display: inline-block; padding: 2px 10px; border-radius: 999px; font-size: 12px; font-weight: 600; }
.draft-st-unsaved { background: #fff4e5; color: #b26a00; }
.draft-st-saved { background: #e7f6ec; color: #1f8a4c; }
.draft-st-modified { background: #eaf1ff; color: #185FA5; }
.draft-table .ops-cell { white-space: nowrap; }
.draft-table .ops-cell .btn { margin-right: 6px; }

/* ===== 人工辅助分步引导（v146）· Phase A/B/C/D ===== */
.phase-steps { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; margin: 8px 0 14px; }
.phase-step { display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px; border-radius: 999px; font-size: 13px; background: #f1f5fa; color: #5a6678; border: 1px solid #e1e8f0; }
.phase-step b { display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; border-radius: 50%; background: #cdd9e6; color: #2b3b4e; font-size: 12px; }
.phase-step.active { background: #185FA5; color: #fff; border-color: #185FA5; }
.phase-step.active b { background: #fff; color: #185FA5; }
.phase-step.done { background: #e7f6ec; color: #1f8a4c; border-color: #bfe6cc; }
.phase-step.done b { background: #1f8a4c; color: #fff; }
.phase-arrow { color: #9aa7b6; font-weight: 700; }
.phase-block { margin-top: 6px; }
.phase-block h3 { margin: 6px 0 8px; font-size: 15px; color: #243244; }
#stationListTable { width: 100%; border-collapse: collapse; }
#stationListTable th, #stationListTable td { padding: 8px 10px; border-bottom: 1px solid #e8ecf2; text-align: left; font-size: 13px; }
#stationListTable th { background: #f4f7fb; color: #5a6678; }
#stationListTable .num { text-align: center; }
#stationListTable tbody tr.row-active { background: #eaf1ff; }
#stationListTable tbody tr.row-active td { font-weight: 600; }
.analyze-target-bar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; padding: 10px 12px; background: #f7fafe; border: 1px dashed #b9d3ec; border-radius: 8px; }
.analyze-target-bar .at-label { color: #5a6678; font-size: 13px; }
.analyze-target-bar b { color: #185FA5; }

/* ===== v146 分步引导·拍摄/导入/产能法集中入口 ===== */
.station-actions { display: flex; gap: 6px; flex-wrap: wrap; }
.station-actions .btn { font-size: 12px; padding: 4px 8px; }
#stationListTable tbody tr.capacity-row td { padding: 0; border-bottom: none; }
#stationListTable tbody tr.capacity-row .row { padding: 8px 12px; }
.mini-cam-bar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding: 10px 12px; background: #f4f7fb; border: 1px solid #e1e8f0; border-radius: 8px; }
#miniCaptureSteps .cap-step { display: inline-flex; align-items: center; padding: 4px 10px; border-radius: 999px; font-size: 12px; background: #f1f5fa; color: #5a6678; }
#miniCaptureSteps .cap-step.done { background: #e7f6ec; color: #1f8a4c; }
#miniCaptureSteps .cap-step.active { background: #185FA5; color: #fff; }
.badge { display: inline-block; padding: 1px 6px; border-radius: 4px; font-size: 11px; font-weight: 600; margin-left: 4px; }
.badge.ai { background: #e7f0ff; color: #185FA5; }
.badge.cap { background: #fff4e0; color: #b76e00; }
#runAi { min-width: 220px; }

/* ===== v167 修复操作人显示、档案详情分岗位/全线数据展示、删除后防拉回；v166 云同步写入改走 ieModSync 云函数代理，绕过 PG RLS；v165 节拍/线平衡页移除新建/暂存/保存按钮 ===== */
.line-info-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
  gap: 10px 16px;
  background: #f8fafc;
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 14px 16px;
  margin: 10px 0 16px;
}
.line-info-grid .li-item { display: flex; flex-direction: column; gap: 2px; }
.line-info-grid .li-label { font-size: 11px; color: var(--muted); font-weight: 500; }
.line-info-grid .li-value { font-size: 13px; color: var(--ink); font-weight: 600; word-break: break-all; }

.arc-line-info {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
  gap: 6px 12px;
  background: #f8fafc;
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 10px 12px;
  margin: 8px 0;
  font-size: 12px;
}
.arc-line-info .li-item { display: flex; flex-direction: column; gap: 1px; }
.arc-line-info .li-label { font-size: 10px; color: var(--muted); }
.arc-line-info .li-value { font-size: 12px; color: var(--ink); font-weight: 600; word-break: break-all; }

.arc-footer-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 4px;
  font-size: 12px;
  color: var(--muted);
}

.line-param-badges {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 8px;
  margin-top: 4px;
}
.line-param-badges .param-badge {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  background: #f1f5f9;
  border: 1px solid #e2e8f0;
  color: #475569;
  border-radius: 4px;
  padding: 1px 6px;
  font-size: 11px;
}
.line-param-badges .param-badge .k { color: #94a3b8; }
.line-param-badges .param-badge .v { color: #334155; font-weight: 600; }

/* ===== v203（媒体→COS 主链路接线 + LB 图表接入查看链路：lbimp.js showLbimpDetail 只读弹窗（lbimpSummary 汇总页「查看」调用）三场景（SOP/现场测算/改善后）下加 山积图+瀑布图+ECRS（id 前缀 Det 避免与编辑面板冲突，弹窗插入后即渲染）；archive-ui.js 档案库 LB 卡片「查看（View）」由 showArchiveDetail（IE 结构弹窗，LB 档案会空白）改走 showLbimpDetail（含图表）；全量数据控制台 LB「打开」= openLbimpById 编辑态已含图不变。v201 渲染函数参数化（sceneKey+lbimpData+idPrefix）以复用） + v201（LB 模块现场测算/改善后加图+ECRSLB 模块「现场测算/改善后」两项下加 图表+ECRS：山积图（柱状+瓶颈红+平均横线）+ 瀑布图（ECharts 堆叠区间显示 CT 累加）+ 按 ECRS 结构化改善建议（Eliminate/Combine/Rearrange/Simplify 四项+平衡率等级标注），与 renderMetrics 同步重算自动刷新） + v200（SW 状态修复SW 状态修复 + PWA 接管：error-trap checkSW 旧版 navigator.serviceWorker.register(r.scope) 是无效调用（r.scope 是 URL 字符串不能当脚本注册），改为 r.update() 触发已注册 SW 拉最新 sw.js 立即 install+activate；加固面板加「🔄 重新加载（激活 SW）」按钮（data-act=reloadForSW → location.reload()）—— v199 部署后 sw.js 变化已 install+activate，但当前已打开的标签页 controller 仍为 null（未受新 SW 控制），强刷一次让新 SW 接管，状态从「未激活」变「已激活」） + v199（档2 云存储地基+自检档2 云存储（pgstore）地基+自检：① 云端创建 pgstore bucket iemod-media（storage.buckets 直插 rowCount=1）；② 新增 media-store.js——MediaStore.selfTest() 真机自检「上传→读回→删除」一条探针 JSON（探测 SDK 三路径：uploadFile(fileContent)/uploadFile(filePath/File)/app.storage），结果入 localStorage.ie_storage_selftest + console；通过后用于把 drafts 明细等媒体大对象分离上 COS、PG 行只存统计+引用，从架构上根治体积型不同步；③ 加固面板加「☁ 云存储自检」按钮（data-act=storageTest）；④ sw.js SHELL 加入 media-store.js。主链路（cloud-sync toRow/loadRecord 媒体分离）待自检通过后接入） + v198（云端上云根治闭环：cloudSafeData 第二层强剥保险 + pendingAdd 防挤爆云端上云根治闭环：① cloudSafeData 第二层强剥保险——900KB 预算仍超（9/8 前旧结构巨型视频档案）时删 video.drafts/stationResults[].drafts/lineVerify.byStation[].drafts 段级明细并只保留统计核心（medianCycleCT/validWorkRatio/cycles/ct/balanceRate/bottleneck/name），summary.js 弹窗仅依赖统计值不受影响，本地 IndexedDB 始终保留完整草稿；② pendingAdd 防 200 条上限被「永久失败/已删」旧 id 占满挤掉新记录（先剔墓碑残留再截断保留最新）——根治新记录推送失败静默丢上传） + v197（云端 1MB 硬墙真因 + v196-b 视频优先云端 1MB 硬墙真因 + v196-b 视频优先：v184 误判 CloudBase executePGSql 硬上限为 10MB，实际是 1MB（1048576B）——712 个 upsert 失败几乎全部是同一错误「request size 1130524B exceeds 1048576B」。v197 把前端 cloudSafeData 终极预算 7MB→900KB（留 100KB 给 SQL 包装）、FIELD_CAP 2MB→128KB、更激进剥离 video.drafts[]._raw/_poses/_landmarks 等大字段；云函数 _MAX_DATA 9MB→900KB 兜底 too_large 守卫（用户已可丢弃待传队列 1 条以停止风暴）。v196-b：lineMetrics 优先用 stationResults（视频数据），不再被用户在动作录入里手录的 4 个空壳工序（actions=[]/CT=0）覆盖真实的 7 个视频分岗位数据；与 summary.js 弹窗渲染策略保持一致） + v196（IE 模块结果分析页数据贯通IE 模块结果分析页数据贯通：根因是 lineMetrics() 派生节拍/线平衡仅依赖 state.processes——视频分析档案 state.processes 为空时，节拍分析/线平衡分析/工位图页均显示空（即使 state.video.stationResults/lineVerify 有完整数据）。修复：lineMetrics() 在 state.processes 为空但 stationResults 有 done 数据时，自动派生"伪工序"（每个 done 项=p.calcMode=video，CT 来自视频），并返回 fromVideo/videoLine 标记+数据；renderAnalysis/renderBalance 检测 fromVideo 时附加"全线视频验证（Phase D）"指标+瓶颈岗位+各岗位 CT 表（与 summary.js 弹窗保持一致），让视频分析档案加载到工作区后三个结果分析页（视频分析+节拍分析+线平衡分析）都能直接看到分岗位+全线数据） + v195（修归属人/操作人混淆修归属人/操作人混淆：console.js 列表"归属人"列原代码 r.operator || ownerName(r.ownerId) 优先显示 operator 字段——这是 v167 把"操作人"误当"归属人"显示的设计混淆，导致查询/筛选按归属人过滤时找不到数据（云端 owner_id=赵静 0 条 records，但 operator=赵静 实际归属但坤林/余文龙的多条数据列表显示"赵静"）。改为永远以 ownerId 解析为主显示归属人，操作人降级为副信息（小字"操作：xxx"），归属/操作一目了然不影响"选归属人=0 条"的合理结果。崩溃页与本修复独立，告知复现路径后另行排查） + v194（归属人下拉补全+可搜索归属人下拉补全+可搜索：之前 console.js 下拉只从「当前 _records 中实际出现的 ownerId 集合」派生（与数据强耦合）——如果某账号在云端 user_roles 表里但当前页没数据，下拉就找不到该账号。改为下拉始终包含 user_roles 全部账号（与数据无关），并新增「🔍 筛选归属人」输入框，输入「赵/赵静/UID 前 8 位」实时过滤下拉选项，1 秒定位目标账号。云函数 opListUsers 不需改） + v193（删除复活终极修复删除复活终极修复：v190/v191 漏掉的「ensureAuth 假阴导致删除复活」路径——之前 cloud-sync.js remove() 在 ensureAuth 失败时直接 return false（未写本地墓碑、未入 pendingDelete 队列），导致云端 opDelete 未发出但本机 ArchiveStore 已 del → 心跳 doSync 60s 拉回云端记录时本地无墓碑 → put 回本地 → 用户看到「删除后又出现」。现在 remove(id) 改造为先无条件 tombstoneAdd(本地)+pendingDel（无论鉴权/网络如何，本地墓碑永远生效），再 try _doDelete，失败入 pendingDelAdd 由 doSync 周期(内置 refreshAuth 续期) 重试。心跳拉回时 tombstoneHas=true 必跳过并 rdb 直删云端（兜底云端墓碑未写的极端情况），从根上杜绝复活） + v192（跨设备同步根治跨设备同步根治：① cloud-sync.js 60s 周期定时器从「仅上传补传」升级为「多设备双向同步心跳」——60s 周期 + 页面回到前台(visible) + 网络恢复(online) + 加载 5s 首轮，自动执行 doSync（拉取云端新数据 + 拉云端墓碑清理本机已删残留副本 + 上传待传 + 重试待删队列）。根治两症状：A) 手机保存 → 电脑不手动刷新看不到；B) 手机/全量数据删除 → 电脑本地残留不自动清（表现为「删了又出现」）。任一端 ≤60s（常规切端 ≤5s）自动收敛。② 草稿（暂存）上云：新增独立云表 ie_mod_drafts（云函数 draftPull/draftUpsert/draftDelete + 懒建表，与正式档案 ie_mod_records 物理隔离绝不污染档案/汇总/全量数据）；cloud-sync.js 暴露 draftPush/draftPullAll/draftRemove；draft.js 集成——stageDraft 后静默推云、delDraft 同步删云、进入草稿箱先云端合并、60s 周期/visible/online 静默双向合并（同 id 取 updatedAt 新者胜）。实现「手机端暂存 → 电脑端草稿箱可见并可继续编辑」+ v191（删除收口 + 全量数据权限收紧删除收口 + 全量数据权限收紧：用户确认「删除只保留在全量数据控制台，其余汇总/档案页不提供删除开关；全量数据仅超级管理员和显式授权人员可查看操作」。① auth.js PAGES 增 alldata 授权页 + canSeeAllData()/canAllDataOp(op)/canDeleteRecord()——super 恒真，其余账号需管理员在权限弹层勾选 alldata.v/e/d；console.js 渲染门槛 + app.js 导航/首页 alldata 显隐全部改走 canSeeAllData（默认拒绝，不再 admin 全开）。② archive-ui 档案库卡片、summary.js 节拍/线平衡汇总表、cpk/oee/station/lbimp/batch 汇总表：删除按钮移除，只留查看/打开/导出——删除统一到「全量数据控制台」。③ 各模块工作区「删除当前记录」（registerOpButton d 位）与 doDelete/deleteArchive 守卫统一绑定 canDeleteRecord()——普通账号（含未授权 alldata 的 admin）无法删除任何档案记录，彻底杜绝误删与复活入口。④ 全量数据控制台内行内改/批量改按 alldata e、行删/批量删按 alldata d 显隐+守卫）+ v190（根治 admin console「已删除多次又复活」架构漏洞：remove() 改用 _doDelete()（refreshAuth+withRetry）失败入 pendingDelete 队列由 doSync 自动重试；doSync 拉回云端记录前同时用云端墓碑表+本地墓碑过滤（防复活）；console 删按钮 await 并 toast 真实结果）+ v189（修复 v188 部署后「数据 0 条」：pullAll/queryAll 在 rdb 调用前 refreshAuth() 强制续期 access token）+ v188（恢复「安静流畅、不弹异常」：① 云函数 ieModSync 每次 upsert/delete/tombstones 自动写 ie_sync_logs 调用日志，任何同步失败管理员一条 SQL 即可远程看到真因；② 移除 L1 熔断骨架，周期补传 5min→60s，push 登录态暂失也入队自动重试；③ error-trap.js 全面静默化：风暴红横幅默认关闭(recoverOn=false)、js/promise/net 异常与 Safe.run 只记日志不再弹 toast；④ saveSnapshot 保存后同步失败不再显示红字）+ v187（flushPending 取消 `else break` 9 条全试 + 失败追踪 listPendingDetails/discardPending + 「丢弃未同步」入口 + ErrLog 令牌桶限速 30/min + Watchdog 排除 net/sync/isolated + HUD 待同步可点）+ v186（stageIEModule 暂存剥离视频 + 7MB 兜底白名单）+ v185（视频用完即删绝不存档）+ v184（云端同步 10MB 请求上限修复 + ieModSync 9MB 护栏）+ v183 二期（主工作区迁 IndexedDB，5–10MB 配额墙消失，HUD 用 origin 级真实配额百分比）+ v182 常驻存储监测 HUD（本地/云端占用实时显示+软上限自动修剪+联动一键清理）+ v181 修复 #508 + v180 止血包 + v179 持久化兜底 + v178 分段续录 + v176 性能优化 ===== */
.svs-wrap { margin-top: 14px; }
.svs-chart { width: 100%; height: 320px; margin: 8px 0 4px; }
.svs-tbl { margin-top: 6px; }
.svs-tbl td .hint { display: block; }
.svs-summary { display: flex; flex-wrap: wrap; gap: 10px; margin: 10px 0 4px; }
.svs-kpi { flex: 1 1 150px; min-width: 130px; background: #f5f8fb; border: 1px solid #e2e9f0; border-radius: 8px; padding: 8px 10px; display: flex; flex-direction: column; gap: 2px; }
.svs-kpi .k { font-size: 12px; color: #5f5e5a; }
.svs-kpi .v { font-size: 16px; font-weight: 700; color: #185fa5; }

/* ===== v219（2026-09-10）：#559 全线/逐工位差异对比表 —— 异常告警条 + 映射下拉 + 宽表滚动 ===== */
.svs-warn { margin: 10px 0; padding: 10px 12px; border-radius: 8px; border: 1px solid #f0dcae; background: #fdf6e7; color: #8a5a00; font-size: 13px; line-height: 1.75; }
.svs-warn > div + div { margin-top: 4px; }
.lm-map { max-width: 176px; padding: 3px 6px; border: 1px solid #cfdae6; border-radius: 6px; background: #fff; color: #1b2430; font-size: 12.5px; }
.res-tbl.diff-tbl { min-width: 1180px; }
.res-tbl.diff-tbl th, .res-tbl.diff-tbl td { white-space: nowrap; }
.res-tbl.diff-tbl td.diag { white-space: normal; min-width: 200px; max-width: 280px; }

/* ===== v168 三端自适应全屏（仅增量增强，不改动既有业务样式/流程）=====
   设计红线：桌面（>1024）保持现状；平板（640–1024）舒适布局；手机（<640）紧凑全屏。
   触摸命中区 ≥40px、表格横向滚动兜底、100dvh 全屏适配。 */
html, body { min-height: 100vh; min-height: 100dvh; }
body { overflow-x: hidden; }
main { min-height: calc(100vh - 120px); min-height: calc(100dvh - 120px); }
.table-wrap { width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* 触摸命中区：平板/手机统一加大可点区域，防误触 */
@media (max-width: 1024px) {
  button.btn, .nav-arrow, .nav-title, nav button[data-tab], select { min-height: 40px; }
}

/* 平板（640–1024）：导航可横向滚动，表格横滚，卡片舒适 */
@media (min-width: 640px) and (max-width: 1024px) {
  .card { padding: 14px 16px; }
  nav { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .panel table { display: block; width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; }
}

/* 手机（<640）：全屏紧凑、导航横向滚动、表格横滚、弹窗近乎全屏 */
@media (max-width: 639px) {
  .card { padding: 12px; margin-bottom: 12px; border-radius: 10px; }
  nav { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  nav button[data-tab], .nav-title { font-size: 13px; padding: 9px 10px; }
  main { padding: 8px; }
  .panel table { display: block; width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; font-size: 12px; }
  .modal { width: 94vw; max-height: 88vh; overflow: auto; }
  h2 { font-size: 18px; }
  h3 { font-size: 16px; }
  button.btn, .nav-arrow { min-height: 40px; }
  .analyze-target-bar, .mini-cam-bar, .station-actions { gap: 6px; }
}

/* 超窄屏（<380）：导航进一步紧凑 */
@media (max-width: 379px) {
  nav button[data-tab], .nav-title { font-size: 12px; padding: 7px 8px; }
}

/* 桌面（≥1025）：保持现状，仅给表格加横滚兜底 */
@media (min-width: 1025px) {
  .panel table { max-width: 100%; }
}

/* ===========================================================================
   v239：生产分析统一引擎（ProdAnalytics）共用样式
   用于 —— CPK 能力判定卡 / OEE 判定卡 / 线平衡率判定卡 / 汇总统计卡 /
            汇总输出区 / 大屏生产分析看板。全站判定卡外观与颜色语义一致。
   颜色语义：绿 ok ≥门槛 ｜ 黄 warn ｜ 红 bad ｜ 灰 idle 无数据
   =========================================================================== */

/* ---- 判定卡 ---- */
.pd-cap-wrap { margin-top: 12px; }
.pd-judge {
  border: 1px solid var(--line, #e3e6ea);
  border-left: 5px solid #6b7280;
  border-radius: 10px;
  padding: 12px 14px;
  background: #fbfcfd;
}
.pd-judge[data-level="ok"]   { background: #f2fbf9; }
.pd-judge[data-level="warn"] { background: #fffaf2; }
.pd-judge[data-level="bad"]  { background: #fdf4f4; }
.pd-judge-title { font-size: 13px; font-weight: 600; color: var(--muted, #5b6470); margin-bottom: 4px; }
.pd-judge-value { display: flex; align-items: center; gap: 8px; font-size: 26px; font-weight: 700; letter-spacing: -.5px; line-height: 1.25; }
.pd-judge-light { display: inline-block; width: 10px; height: 10px; border-radius: 50%; flex: 0 0 auto; }
.pd-judge-label { font-size: 14px; font-weight: 600; }
.pd-judge-extra { display: flex; flex-wrap: wrap; gap: 6px 18px; margin-top: 8px; }
.pd-jc-k { font-size: 13px; color: var(--muted, #5b6470); }
.pd-jc-k b { color: var(--ink, #1f2328); margin-left: 5px; }
.pd-judge-range { margin-top: 6px; font-size: 12px; color: var(--muted, #5b6470); }
.pd-judge-hint {
  margin-top: 8px; padding: 8px 10px; border-radius: 8px;
  background: #fff4e5; border: 1px solid #f3d9ae; color: #8a5300; font-size: 13px; line-height: 1.65;
}
.pd-judge-hint b { color: #b45309; }

/* ---- 汇总统计卡条 ---- */
.pd-kpi-strip { margin: 10px 0 4px; }

/* ---- 图表空态占位（禁止留白） ---- */
.pd-chart-empty {
  display: flex; align-items: center; justify-content: center;
  height: 100%; min-height: 120px; padding: 16px; text-align: center;
  color: #64748b; font-size: 12px; line-height: 1.7;
}

/* ---- 生产分析汇总输出区（IE 手动录入分析页底部） ---- */
.pd-out-block { margin-top: 18px; padding-top: 14px; border-top: 2px dashed var(--line, #e3e6ea); }
.pd-out-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 12px; margin: 12px 0; }
.pd-out-thumbs { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 12px; }
.pd-thumb {
  border: 1px solid var(--line, #e3e6ea); border-radius: 10px; background: #fff;
  padding: 8px; cursor: pointer; transition: box-shadow .18s, transform .18s;
}
.pd-thumb:hover { box-shadow: 0 4px 14px rgba(16,24,40,.10); transform: translateY(-2px); }
.pd-thumb-h { font-size: 12.5px; font-weight: 600; color: var(--muted, #5b6470); padding: 2px 4px 6px; display: flex; justify-content: space-between; align-items: center; }
.pd-thumb-jump { font-size: 11.5px; color: var(--brand, #1d4ed8); font-weight: 500; }
.pd-thumb-chart { width: 100%; height: 190px; }
.pd-advice {
  border-left: 5px solid #b45309; background: #fffaf2; border-radius: 10px;
  padding: 16px 20px; font-size: 14px; line-height: 1.85;
}
.pd-advice h4 { margin: 0 0 8px; font-size: 14.5px; color: #b45309; }
.pd-advice .pd-advice-head { font-weight: 700; color: #8a5300; margin-bottom: 10px; }

/* v244：改善建议逐条排版（长段落不再挤成一团）
   —— 每条独立一行，①②③ 用固定宽度的序号栏 + 悬挂缩进 ⇒ 换行后与首行文字对齐。 */
.pd-advice-list { display: grid; gap: 9px; }
.pd-advice-item { display: grid; grid-template-columns: 22px minmax(0, 1fr); align-items: start; }
.pd-advice-no { font-weight: 700; line-height: 1.85; }
.pd-advice-tx { min-width: 0; }
.pd-advice .pd-advice-no { color: #b45309; }

/* ===========================================================================
   数据大屏 · 生产分析看板（深色）
   =========================================================================== */
.pd-board-head {
  display: flex; align-items: baseline; justify-content: space-between; flex-wrap: wrap; gap: 10px;
  padding: 10px 16px 12px; margin-bottom: 4px;
  border-bottom: 1px solid rgba(148,163,184,.20);
}
.pd-board-title { font-size: 22px; font-weight: 800; color: #e6eefc; letter-spacing: .5px; }
.pd-board-sub { font-size: 13px; color: #94a3b8; }
.pd-board-clock { font-size: 15px; color: #cbd5e1; font-variant-numeric: tabular-nums; }
.pd-board-live { font-size: 12px; color: #64748b; margin-left: 8px; }
.pd-card-dark { background: rgba(15,26,46,.72); border: 1px solid rgba(148,163,184,.18); border-radius: 12px; padding: 12px 14px; }
.pd-big-kpi { display: flex; flex-direction: column; gap: 2px; height: 100%; }
.pd-big-kpi .pd-bk-top { display: flex; align-items: center; gap: 8px; }
.pd-big-kpi .pd-bk-name { font-size: 13px; color: #94a3b8; font-weight: 600; }
.pd-big-kpi .pd-bk-light { width: 12px; height: 12px; border-radius: 50%; box-shadow: 0 0 10px currentColor; }
.pd-big-kpi .pd-bk-val { font-size: 40px; font-weight: 800; line-height: 1.05; letter-spacing: -1px; font-variant-numeric: tabular-nums; }
.pd-big-kpi .pd-bk-label { font-size: 13px; font-weight: 600; }
.pd-big-kpi .pd-bk-sub { font-size: 11.5px; color: #64748b; }
.pd-big-kpi .pd-bk-trend { flex: 1; min-height: 54px; margin-top: 4px; }
.pd-advice-dark {
  border-left: 5px solid #b45309; background: rgba(180,83,9,.12); border-radius: 10px;
  padding: 16px 20px; color: #fde3c0; font-size: 14px; line-height: 1.85;
}
.pd-advice-dark h4 { margin: 0 0 8px; font-size: 14.5px; color: #fbbf24; }
.pd-advice-dark .pd-advice-head { color: #fcd34d; font-weight: 700; margin-bottom: 10px; }
.pd-advice-dark .pd-advice-no { color: #fbbf24; }
.pd-advice-dark .pd-advice-tx { color: #fde3c0; }

@media (max-width: 760px) {
  .pd-judge-value { font-size: 22px; }
  .pd-big-kpi .pd-bk-val { font-size: 32px; }
  .pd-board-title { font-size: 18px; }
}

/* ===========================================================================
   v241：数据大屏 · 生产分析看板（深色）
   =========================================================================== */
/* v241（拆分后）：生产分析大屏为**独立页**（#pdscreen），.pd-board 即该页的可滚动主体。
   关键：作为 .screen-panel（fixed 100vh + overflow:hidden，flex column）的子项，
   必须 flex:1 + min-height:0 + 自身 overflow-y:auto，否则内容会被父级裁掉。 */
.pd-board {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  /* v246：底部叠加 iOS 安全区（Home 指示条），避免最后一张卡片被遮挡 */
  padding: 4px 18px calc(28px + env(safe-area-inset-bottom));
  box-sizing: border-box;
}
.pd-board-kpis {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px; margin: 12px 0;
}
.pd-board-charts {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px; margin-bottom: 12px;
}
.pd-board-chart-h { font-size: 13px; font-weight: 600; color: #94a3b8; margin-bottom: 4px; }
.pd-board-chart { width: 100%; height: clamp(220px, 26vh, 320px); }
.pd-board-foot { display: block; }               /* v244：建议区平铺整排（原先靠右只占 720px，左侧大片留白） */
.pd-board-advice-wrap { width: 100%; }
/* 宽屏下把正文行宽限制在易读区间，避免超宽行长反而难读 */
.pd-board-advice-wrap .pd-advice-list { max-width: 1560px; }
.pd-board .pd-chart-empty { color: #64748b; }

/* 生产分析大屏：工具条按钮与状态 */
#pdScreenBar { position: relative; z-index: 2; }
#pdScreenState { color: #64748b; font-size: 12px; margin-left: auto; }
@media (max-width: 1100px) {
  .pd-board { padding: 4px 12px 28px; }
  .pd-board-chart { height: 260px; }
}

/* 手机/平板：看板改为单列堆叠，避免大字号与图表被压扁 */
@media (max-width: 1100px) {
  .pd-board-kpis, .pd-board-charts { grid-template-columns: 1fr; }
  .pd-board-foot { display: block; }
  .pd-board-advice-wrap { width: 100%; }
  .pd-advice, .pd-advice-dark { padding: 14px 15px; font-size: 13.5px; line-height: 1.8; }
  .pd-advice-item { grid-template-columns: 20px minmax(0, 1fr); }
}
