* { box-sizing: border-box; margin: 0; padding: 0; }
:root {
  --bg: #f4f6f9;
  --panel: #ffffff;
  --ink: #1f2d3d;
  --muted: #6b7a8d;
  --line: #e3e8ef;
  --primary: #1f6feb;
  --primary-d: #1657c0;
  --green: #1a9e57;
  --amber: #c98a00;
  --orange: #f97316;
  --orange-d: #dd5f04;
  --red: #d23b3b;
  --head-bg: #eef2f7;
}
html, body { height: 100%; }
body {
  font-family: "Microsoft YaHei", "PingFang SC", "Segoe UI", system-ui, sans-serif;
  background: var(--bg);
  color: var(--ink);
  font-size: 14px;
}
.hidden { display: none !important; }
button { font-family: inherit; cursor: pointer; }

/* ---------- 登录 ---------- */
.login-wrap { position: fixed; inset: 0; display: flex; align-items: center; justify-content: center; background: linear-gradient(135deg,#1f6feb 0%, #2b8a6e 100%); }
.login-card { width: 360px; background: #fff; border-radius: 14px; padding: 36px 32px; box-shadow: 0 20px 60px rgba(0,0,0,.25); }
/* 登录页标题区：第 1 行品牌标居左，第 2/3 行居中
   第1 行「川嘉泵业」       —— 黑色、居左、字号较大
   第2 行「质量技术部工作台」—— 蓝色主标题，字号最大，居中
   第3 行「在线表格协作」     —— 副标题，居中
   2026-10-27：原第 4 行「T1 工作计划 · T2 三包件 · … · T6 理化」表单清单已按用户要求删除，
               对应样式 .login-tables 一并移除。 */
.login-head { text-align: center; margin-bottom: 26px; }
.login-logo { font-size: 20px; font-weight: 700; color: var(--ink); letter-spacing: 3px; text-align: left; }
.login-title { font-size: 26px; font-weight: 700; color: var(--primary); letter-spacing: 2px; line-height: 1.35; margin-top: 10px; }
.login-sub { color: var(--muted); font-size: 13px; margin-top: 8px; }
#login-form label { display: block; font-size: 13px; color: var(--muted); margin: 14px 0 6px; }
#login-form input { width: 100%; height: 42px; border: 1px solid var(--line); border-radius: 8px; padding: 0 12px; font-size: 14px; }
#login-form input:focus { outline: none; border-color: var(--primary); }
#login-btn { width: 100%; height: 44px; margin-top: 24px; background: var(--primary); color: #fff; border: none; border-radius: 8px; font-size: 15px; letter-spacing: 4px; }
#login-btn:hover { background: var(--primary-d); }
.login-msg { color: var(--red); font-size: 13px; margin-top: 12px; min-height: 18px; }
.login-hint { color: var(--muted); font-size: 12px; margin-top: 18px; line-height: 1.6; }
/* 页脚备案号（2026-11-12）：细线与上方提示隔开，灰字不抢视觉，链接到工信部备案查询 */
.login-beian { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--line); text-align: center; font-size: 12px; }
.login-beian a { color: var(--muted); text-decoration: none; }
.login-beian a:hover { color: var(--primary); text-decoration: underline; }

/* ---------- 左侧导航栏（2026-10-19 参照「教师首页」深色侧栏改版；色系沿用工作台蓝色系） ---------- */
/* 配色说明：底色取主色 #1f6feb 的深蓝阶（与看板表头 #2f5597 同族），文字冷白；
   活跃项 = 主色半透明块 + 左缘亮蓝竖条。**不采用参考图的紫调**，保持工作台原色系。 */
:root {
  /* 2026-11-13（用户指令「再加深」）：在 #14243d/#0d1829 基础上再调暗 ~20%，保持蓝调、文字对比不受影响 */
  --sb-bg1: #101e32;
  --sb-bg2: #0b1422;
  --sb-ink: #e9f0fb;
  --sb-muted: #8ea3c4;
  --sb-line: rgba(255,255,255,.09);
  --sb-hover: rgba(255,255,255,.07);
  --sb-active: rgba(31,111,235,.38);
  --sb-accent: #4d92ff;
}
.sidebar {
  /* 2026-11-13（用户指令「侧边菜单收窄」）：默认展开宽 260 → 212px；
     同时收紧品牌区/滚动区横向内边距（见下），整体更紧凑而不挤。 */
  flex: 0 0 auto; width: 212px; min-width: 0;
  display: flex; flex-direction: column; overflow: hidden;
  background: linear-gradient(180deg, var(--sb-bg1) 0%, var(--sb-bg2) 100%);
  color: var(--sb-ink);
  transition: width .18s ease;
}
.sb-brand { display: flex; align-items: center; gap: 10px; padding: 12px 12px; border-bottom: 1px solid var(--sb-line); }
/* 2026-10-21（用户指令）：侧栏品牌位 logo 改为「嘉陵江」图片（public/logo-jlj.png）。
   原为绿色渐变圆角方块 + 「川」字；现改为圆角容器承载图片，避免深色侧栏吃掉红色 logo。
   2026-11-12（用户指令）：先换「极浅蓝底红图-带R标」；16:35 又定稿为「同色版-带R标」（白底 + 图形文字全红 + ®）。
   容器底色随图统一为 #fff，与白底图片一致，避免在 34px 容器上下留白出现异色边框。 */
.sb-logo {
  width: 34px; height: 34px; flex: 0 0 auto; border-radius: 8px;
  background: #fff; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
}
.sb-logo img { width: 100%; height: 100%; object-fit: contain; display: block; }
.sb-brand-text { display: flex; flex-direction: column; min-width: 0; flex: 1; line-height: 1.35; }
/* 2026-10-21（用户指令「川嘉泵业和质量技术部工作台字体大小互换」）：
   原 b(川嘉泵业)=14px 主、i(质量技术部工作台)=11px 副 → 互换为 11px / 14px，
   即「质量技术部工作台」成为主标题、「川嘉泵业」退为副行。其余属性（字重、颜色、字距）保持原样。 */
.sb-brand-text b { font-size: 11px; font-weight: 600; letter-spacing: 1px; white-space: nowrap; }
.sb-brand-text i { font-style: normal; font-size: 14px; color: var(--sb-muted); white-space: nowrap; }
.sb-toggle {
  flex: 0 0 auto; width: 22px; height: 22px; padding: 0; line-height: 1;
  border: 1px solid var(--sb-line); border-radius: 6px;
  background: var(--sb-hover); color: var(--sb-muted); font-size: 13px;
  display: flex; align-items: center; justify-content: center;
}
.sb-toggle:hover { color: #fff; background: rgba(31,111,235,.4); border-color: var(--sb-accent); }
.sb-scroll { flex: 1; min-height: 0; overflow-y: auto; overflow-x: hidden; padding: 6px 8px 14px; }
.sb-scroll::-webkit-scrollbar { width: 8px; }
.sb-scroll::-webkit-scrollbar-thumb { background: rgba(255,255,255,.14); border-radius: 4px; }
.sb-group { padding: 10px 8px 6px; font-size: 11px; letter-spacing: 1px; color: var(--sb-muted); }

/* 导航列表：深色侧栏内取消原来的浅蓝卡片样式 */
.welcome-menu { display: flex; flex-direction: column; gap: 3px; background: none; border: 0; border-radius: 0; padding: 0; }
.menu-item {
  position: relative;
  display: flex; align-items: center; gap: 9px;
  padding: 8px 10px; border: 0; border-radius: 8px; min-height: 40px;
  background: transparent; color: var(--sb-ink);
  cursor: pointer; transition: background .15s, color .15s;
}
.menu-item:hover { background: var(--sb-hover); }
.menu-item.active { background: var(--sb-active); color: #fff; }
.menu-item.active::before {
  content: ''; position: absolute; left: -10px; top: 50%; transform: translateY(-50%);
  width: 3px; height: 20px; border-radius: 0 3px 3px 0; background: var(--sb-accent);
}
.menu-item .mi-ico { width: 19px; height: 19px; flex: 0 0 auto; opacity: .88; }
.menu-item.active .mi-ico { opacity: 1; }
.menu-item .mi-name { flex: 1; min-width: 0; font-size: 13px; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.menu-item .mi-arrow { flex: 0 0 auto; font-size: 15px; color: var(--sb-muted); }
.menu-item.active .mi-arrow { color: #cfe0ff; }
/* 二级菜单（2026-10-19：S1–S4 作为「S 基础设置」的折叠菜单）：
   父项点击展开/收起，箭头旋转 90° 作指示；子项缩进 + 小字号、无图标，
   左侧留一条淡竖线表示从属关系；折叠态（仅图标栏）整块隐藏。 */
.menu-item .mi-caret { transition: transform .16s ease; }
.menu-item.open .mi-caret { transform: rotate(90deg); color: #cfe0ff; }
.mi-sub-wrap { display: none; flex-direction: column; gap: 3px; margin-top: 2px; }
.mi-sub-wrap.open { display: flex; }
.menu-item.mi-sub { padding: 6px 10px 6px 40px; min-height: 32px; gap: 0; }
.menu-item.mi-sub::after {
  content: ''; position: absolute; left: 26px; top: 4px; bottom: 4px;
  width: 1px; background: var(--sb-line);
}
.menu-item.mi-sub .mi-name { font-size: 12.5px; font-weight: 400; color: var(--sb-muted); }
.menu-item.mi-sub:hover .mi-name { color: #fff; }
.sidebar.collapsed .mi-sub-wrap { display: none; }

/* 侧栏底部：当前用户 + 账号操作（原左下角浮动卡片，现内嵌侧栏） */
.sb-foot { border-top: 1px solid var(--sb-line); padding: 10px 8px; }
/* 侧栏底部备案号（2026-11-12）：位于退出登录下方，细线与上方按钮隔开，小号灰字 */
.sb-beian { margin-top: 9px; padding-top: 9px; border-top: 1px solid var(--sb-line); text-align: center; font-size: 11px; line-height: 1.6; }
.sb-beian a { color: var(--sb-muted); text-decoration: none; }
.sb-beian a:hover { color: #cfe0f0; text-decoration: underline; }
.corner-user {
  display: flex; flex-direction: column; align-items: stretch; gap: 8px;
  background: none; border: 0; box-shadow: none; padding: 0; width: auto; max-width: none;
}
.corner-user .user-info { color: var(--sb-muted); font-size: 12px; text-align: left; line-height: 1.5; padding: 0 2px; word-break: break-all; }
.corner-user .cu-btns { display: flex; gap: 6px; }
.corner-user .cu-btns .btn {
  flex: 1; padding: 7px 4px; text-align: center; font-size: 12px;
  background: var(--sb-hover); border: 1px solid var(--sb-line); color: var(--sb-ink);
}
.corner-user .cu-btns .btn:hover { background: rgba(31,111,235,.4); border-color: var(--sb-accent); color: #fff; }

/* 收起态：仅保留图标（72px 图标栏） */
.sidebar.collapsed { width: 72px; }
.sidebar.collapsed .sb-brand { padding: 14px 6px; gap: 6px; justify-content: center; }
.sidebar.collapsed .sb-brand-text,
.sidebar.collapsed .sb-group,
.sidebar.collapsed .mi-name,
.sidebar.collapsed .mi-arrow,
.sidebar.collapsed .sb-beian,
.sidebar.collapsed .user-info { display: none; }
.sidebar.collapsed .sb-scroll { padding: 6px 6px 14px; }
.sidebar.collapsed .menu-item { justify-content: center; padding: 9px 0; }
.sidebar.collapsed .menu-item.active::before { left: -6px; }
.sidebar.collapsed .cu-btns { flex-direction: column; }
.sidebar.collapsed .cu-btns .btn { font-size: 11px; padding: 6px 2px; }
.btn { border: 1px solid var(--line); background: #fff; color: var(--ink); border-radius: 7px; padding: 7px 14px; font-size: 13px; }
.btn:hover { border-color: var(--primary); color: var(--primary); }
.btn-primary { background: var(--primary); color: #fff; border-color: var(--primary); }
.btn-primary:hover { background: var(--primary-d); color: #fff; }
.btn-ghost { background: transparent; }
/* 打印按钮：醒目琥珀色实底（在弹窗页脚一片灰/白按钮中一眼可辨）。
   2026-10-11 用户要求「各表单的打印按钮用醒目颜色标记」——仅屏幕显示；
   #rf-foot 在 @media print 中整体隐藏，故打印件里不会出现该按钮。 */
.btn-print { background: var(--amber); border-color: var(--amber); color: #fff; font-weight: 600; letter-spacing: 1px; }
.btn-print:hover { background: #a87000; border-color: #a87000; color: #fff; }
/* 黄色（琥珀）实底按钮（2026-11-12 用户要求）：弹窗「仅保存」用它 ——
   与主操作（蓝色「保存并送审」）区分，一眼看出「只存草稿、不送审」这条次路径。 */
.btn-amber { background: var(--amber); border-color: var(--amber); color: #fff; font-weight: 600; }
.btn-amber:hover { background: #a87000; border-color: #a87000; color: #fff; }
.btn-danger { color: var(--red); border-color: #f0c0c0; }
.btn-danger:hover { background: #fdeaea; }
/* 橙色实底按钮（2026-10-14 用户要求）：用于 S11 明细表的「← 返回总成表」，
   便于从下钻态一眼看到返回入口。 */
.btn-orange { background: var(--orange); border-color: var(--orange); color: #fff; font-weight: 600; }
.btn-orange:hover { background: var(--orange-d); border-color: var(--orange-d); color: #fff; }

/* ---------- 布局 ---------- */
.app { display: flex; flex-direction: column; height: 100vh; }
.layout { display: flex; flex: 1; overflow: hidden; }
/* 工作台下拉选择器（现位于表格视图工具栏左侧） */
.tv-switch { flex-shrink: 0; width: 210px; max-width: 210px; padding: 6px 28px 6px 10px; font-size: 12px; }
/* 工作台下拉选择器（替代原 Tab 标签栏，节省页面空间） */
.table-select {
  max-width: 340px; width: 100%;
  padding: 7px 30px 7px 12px;
  font-size: 13px; font-family: inherit; color: var(--ink);
  background: #fff url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%23667' stroke-width='1.5' fill='none' stroke-linecap='round'/%3E%3C/svg%3E") no-repeat right 10px center;
  border: 1px solid var(--line); border-radius: 8px;
  appearance: none; -webkit-appearance: none; cursor: pointer;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.table-select:hover { border-color: var(--primary); }
.table-select:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 2px rgba(30, 100, 220, .12); }

/* ---------- 主区 ---------- */
/* 2026-11-13：主区改为纵向 flex —— 顶部选项卡固定 42px，其余高度给首页/表格视图。
   原先 main 是滚动容器 + 子视图 height:100%；加 tab 后会多出 42px 触发整区滚动，
   故改由子视图自身内部滚动（表格 .grid-wrap / 看板 .kanban-zone 已有滚动）。 */
.main { flex: 1; min-width: 0; overflow: hidden; padding: 20px 24px; display: flex; flex-direction: column; }
.main > #welcome, .main > #table-view { flex: 1; min-height: 0; height: auto; }

/* ---------- 顶部选项卡（2026-11-13） ----------
   2026-11-13h（用户指令）：「选项卡底色与菜单栏底色区分；选项卡之间用线条或其他明显区分」。
   撤销上一轮「与左侧主菜单同色系」的深蓝渐变 —— 那条深色带与侧栏连成一片、边界不清。
   现改为浅蓝灰页签带：左侧深蓝主菜单 / 顶部浅色页签一眼可分；
   每个页签右缘 1px 冷灰竖线分隔（选中态也保留），未选中半透明白底、选中纯白底 + 顶部主色条。
   z-index 200 保留：行表单仍是模态遮罩（z-index 50+），页签须高于遮罩才能点击切换。 */
.tab-bar {
  flex: 0 0 42px; position: relative; z-index: 200;
  display: flex; align-items: stretch; gap: 0;
  margin: -20px -24px 14px; padding: 0 16px 0 18px;
  /* 2026-11-13（用户指令「顶部颜色再加深」）：在 #dbe3ef/#c4d0e2 基础上再调暗 ~20%，仍浅于深色侧栏保持区分 */
  background: linear-gradient(180deg, #c3cee0 0%, #a7b6cf 100%);
  border-bottom: 1px solid #8ba3c0; box-sizing: border-box;
  box-shadow: 0 2px 5px rgba(23, 42, 72, .07);
}
.tab-list { display: flex; align-items: stretch; min-width: 0; overflow-x: auto; scrollbar-width: none; }
.tab-list::-webkit-scrollbar { height: 0; }
.wb-tab {
  position: relative;
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: 6px;
  height: 41px; padding: 0 12px; border: 0; border-bottom: 2px solid transparent;
  border-right: 1px solid #8ba3c0;               /* 页签之间的竖线分隔（加深档配套） */
  background: rgba(255, 255, 255, .32); color: #465b78; font-size: 13px; font-family: inherit;
  white-space: nowrap; cursor: pointer; user-select: none;
}
.wb-tab:hover { color: var(--primary-d); background: rgba(255, 255, 255, .78); }
.wb-tab.active {
  color: var(--primary-d); font-weight: 600; background: #fff;
  border-bottom-color: #fff;
  box-shadow: inset 0 3px 0 var(--primary);      /* 选中态顶部主色条 */
}
.wb-tab .wt-ico { font-size: 13px; opacity: .95; line-height: 1; }
.wb-tab .wt-txt { max-width: 170px; overflow: hidden; text-overflow: ellipsis; }
.wt-x {
  margin-left: 2px; width: 16px; height: 16px; line-height: 14px; padding: 0;
  border: 0; border-radius: 4px; background: transparent; color: #8a9bb2;
  font-size: 15px; cursor: pointer; text-align: center;
}
.wt-x:hover { background: #fde8e8; color: var(--red); }
.tab-home { padding-left: 6px; }
.tab-bar-fill { flex: 1 1 auto; min-width: 8px; }
.tab-all-close { align-self: center; margin-left: 6px; padding: 3px 9px; border: 1px solid #8ba3c0;
  border-radius: 6px; background: rgba(255, 255, 255, .7); color: #5b6c85; font-size: 11.5px; font-family: inherit; cursor: pointer; }
.tab-all-close:hover { color: var(--red); border-color: #e6b3b3; background: #fff2f2; }
/* 「＋」快速打开：白底下拉 + 明显描边，与浅色页签带拉开层次 */
.tab-picker {
  position: absolute; top: 44px; left: 18px; z-index: 30;
  min-width: 250px; max-width: 420px; max-height: 62vh; overflow: auto; padding: 6px;
  background: #fff; border: 1px solid #b6c6dc; border-radius: 8px;
  box-shadow: 0 10px 30px rgba(20, 40, 80, .18);
}
.tab-picker-item { display: block; width: 100%; text-align: left; padding: 7px 10px;
  border: 0; border-radius: 6px; background: transparent; color: var(--ink);
  font-size: 12.5px; font-family: inherit; cursor: pointer; white-space: nowrap; }
.tab-picker-item:hover { background: #eef5ff; color: var(--primary); }
.tab-picker-item.is-open { color: var(--primary); font-weight: 600; }
.tab-picker-empty { padding: 10px; color: var(--muted); font-size: 12px; }
/* 行表单页签（阶段二）与台账页签用同一外观，仅前缀图标不同；
   2026-11-13h：浅色页签带上改用深橙 / 深青绿，保证对比度足够 */
.wb-tab.tab-form .wt-ico { color: #c2681a; opacity: 1; }
/* 2026-11-13：B BOM清单 / S 基础设置 面板页签，⚙ 用青绿色与 ✎ 橙、▦ 冷灰区分 */
.wb-tab.tab-admin .wt-ico { color: #0f8a72; opacity: 1; }
.tab-picker-sep { padding: 8px 10px 4px; margin-top: 5px; border-top: 1px solid var(--line);
  color: var(--muted); font-size: 11px; letter-spacing: .5px; }

/* 首页：页头（标题 + 刷新）+ 看板区。原「左侧菜单区」已移入侧栏，故此处仅剩看板。 */
.welcome { height: 100%; box-sizing: border-box; display: flex; flex-direction: column; gap: 14px; }
.page-head { flex: none; display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.page-head h1 { font-size: 20px; font-weight: 700; color: var(--ink); letter-spacing: 1px; }
.page-head .ph-sub { font-size: 12px; color: var(--muted); margin-top: 4px; }
.page-head .btn { flex: none; }
.welcome-layout { flex: 1; min-height: 0; display: flex; gap: 20px; align-items: stretch; }
.kanban-zone {
  flex: 1; min-width: 0;
  background: var(--panel); border: 1px solid var(--line); border-radius: 10px;
  display: flex; flex-direction: column; overflow: hidden;
  /* 撑满主区高度：这样看板区才有确定高度，内部卡片才能「各占 1/2」。
     2026-10-09 用户指令：K0、K1 置于看板区左上角，高度各为看板区 1/2、内容滚动显示。 */
}
.kanban-head {
  padding: 12px 18px; font-size: 14px; font-weight: 600; color: var(--ink);
  border-bottom: 1px solid var(--line); background: #f7f9fc;
}
.kanban-placeholder {
  flex: 1; display: flex; align-items: center; justify-content: center;
  color: #b6bfd0; font-size: 13px; letter-spacing: 1px;
}
/* ---------- 看板卡片（参照用户截图：深蓝表头 + 紧凑表格） ---------- */
/* 看板卡片区：4 列网格、卡片按左上角对齐，行高固定为容器高度的 1/2。
   - grid-template-columns: repeat(4,1fr) → K0 占 1 列 = 区域宽的 1/4；K1 占 2 列 = 1/2
   - grid-template-rows: minmax(0,50%) → 两卡高度固定 = 看板区的 1/2（minmax 的 0 下限
     保证卡片可被压缩、不会被内容撑高；50% 是相对网格容器高度）
   - align-content / justify-content: start → 两张卡都贴左上角，右下留空
   - overflow: hidden → 内容超出时由卡片内部滚动，不把看板区撑高
   2026-10-09 用户指令：K0、K1 置于看板区左上角，高度各为看板区 1/2，宽 K0=1/4、K1=1/2。 */
.kanban-body { flex: 1; min-height: 0; overflow: hidden; padding: 14px 16px; display: grid; grid-template-columns: repeat(4, 1fr); grid-template-rows: minmax(0, 50%); grid-auto-rows: minmax(0, 50%); gap: 14px; align-content: start; justify-content: start; }
/* 卡片基础样式。 */
.kb-card { border: 1px solid var(--line); border-radius: 8px; overflow: hidden; background: #fff; box-shadow: 0 1px 4px rgba(16,24,40,.05); min-width: 0; }
/* K0 卡片：纵向 flex，标题固定、表格区滚动（内容超出卡片高度时在表内滚动，标题不随滚动消失）。 */
.kb-card:not(.wide2) { display: flex; flex-direction: column; overflow: hidden; }
/* K1 卡片：跨 2 列 = 看板区宽度的 1/2；纵向 flex，滚动区撑满卡片剩余高度。
   2026-10-09 用户指令：K1 宽为看板区的 1/2。 */
.kb-card.wide2 { grid-column: span 2; display: flex; flex-direction: column; }
.kb-card-title {
  padding: 8px 14px; font-size: 13px; font-weight: 600; color: #fff;
  background: #2f5597; letter-spacing: 1px;
}
.kb-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.kb-table th {
  background: #2f5597; color: #fff; font-weight: 600; text-align: center;
  padding: 7px 10px; border: 1px solid #4a6db5; white-space: nowrap;
}
.kb-table td { padding: 7px 10px; border: 1px solid #e3e8f0; text-align: center; }
.kb-table .kb-idx { width: 46px; color: var(--muted); }
.kb-table .kb-name { text-align: left; font-weight: 500; color: var(--ink); }
.kb-table .kb-num { width: 76px; }
.kb-table .kb-pend { width: 92px; }
.kb-row { cursor: pointer; transition: background .12s; }
.kb-row:hover { background: #eef4ff; }
/* K0 数据行奇偶底色交替（与 K1 同一规则）；hover 与奇偶同特异性且在其后，故可正常覆盖 */
.kb-table tbody tr.kb-row:nth-child(odd)  { background: #ffffff; }
.kb-table tbody tr.kb-row:nth-child(even) { background: #f2f6fc; }
.kb-table tbody tr.kb-row:hover { background: #eef4ff; }
.kb-row.kb-hot .kb-pend { color: #d92d20; font-weight: 700; }
.kb-row .kb-zero { color: #98a2b3; }
.kb-table tfoot td { background: #f7f9fc; font-weight: 600; text-align: center; }
.kb-table tfoot .kb-name { text-align: center; color: var(--muted); font-weight: 500; }
.kb-table tfoot .kb-pend { color: #d92d20; }
/* ---------- 看板滚动区（K0、K1 共用） ---------- */
/* 卡片内的纵向滚动容器（K0、K1 都用）。border-top 是标题条与表格之间的分隔线。
   注意：这条 1px 边框是 sticky 表头的定位参照起点（表头吸顶位置 = 容器 padding box 顶，
   即边框之下），因此表头 top:0 时顶端与容器内沿严丝合缝、不会留缝——它本身不是缺陷。
   flex:1 撑满卡片剩余高度；卡片高度由 .kanban-body 的 50% 行高固定，
   内容超出时在此容器内滚动，不会把卡片/看板区撑高。
   2026-10-09 用户指令：K0、K1 置于看板区左上角，高度各为看板区 1/2，超出滚动。
   2026-10-28：三块卡片仍占看板区高度的 1/2（同一行），只是左右次序按 DOM 排列，本样式无需改动。 */
.kb-scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto; overflow-x: auto; border-top: 1px solid var(--line); }
/* K0 表格与 K1 同样处理：滚动区里的表格用 separate + sticky 表头。
   原因同 K1：collapse 下折叠边框不随 sticky 单元格移动，表头吸顶后下沿会漏缝。
   相邻单元格边框在 separate 下会叠加成 2px，故统一「只画右、下」，左/顶由外框与表头承担。 */
.kb-scroll .kb-table { border-collapse: separate; border-spacing: 0; border-left: 1px solid #e3e8f0; }
.kb-scroll .kb-table th, .kb-scroll .kb-table td { border-top: 0; border-left: 0; }
.kb-scroll .kb-table thead th { border-top: 1px solid #4a6db5; position: sticky; top: 0; z-index: 3; background: #2f5597; box-shadow: 0 1px 0 0 #4a6db5; }
/* ---------- 看板③ K2「我的待办」（2026-10-10 新增） ---------- */
/* 与 K0/K1 同处 .kanban-body 的 4 列网格：K1 跨 2 列、K0 与 K2 各占 1 列（合计 4 列）。
   2026-10-28（用户指令「两个看板位置互换」）：DOM 次序改为 K2(1) + K1(2) + K0(1)，
   即「我的待办」在最左、K0 未审核表单在最右；两块都是 1 列窄卡，栅格宽度不变、无需在此加定位。
   卡片结构与 K0 一致：标题固定 + .kb-scroll 滚动（见 .kb-card:not(.wide2)）。 */
.kb-todo .todo-sum { display: flex; flex-wrap: wrap; gap: 6px; padding: 8px 10px; }
.kb-todo .todo-chip {
  font-size: 11.5px; line-height: 1.7; padding: 1px 8px; border-radius: 10px;
  border: 1px solid var(--line); background: #f7f9fc; color: var(--muted); white-space: nowrap;
}
.kb-todo .todo-chip b { color: var(--ink); font-size: 12.5px; margin-left: 4px; }
.kb-todo .todo-chip.hot { border-color: #e8c46a; background: #fff8e6; color: #8a6d00; }
.kb-todo .todo-chip.hot b { color: #b54708; }
.kb-todo .todo-list { list-style: none; margin: 0; padding: 0; }
.kb-todo .todo-item {
  display: flex; align-items: center; gap: 7px;
  padding: 7px 10px; border-bottom: 1px solid var(--line); cursor: pointer; transition: background .12s;
}
.kb-todo .todo-item:hover { background: #eef4ff; }
.kb-todo .todo-tag {
  flex: 0 0 auto; font-size: 11px; line-height: 1.6; padding: 0 6px; border-radius: 3px;
  color: #fff; white-space: nowrap;
}
.kb-todo .tag-review { background: #d98b1f; }
.kb-todo .tag-mine   { background: #3f7fb5; }
.kb-todo .tag-active { background: #3d8b52; }
.kb-todo .todo-main { display: flex; flex-direction: column; flex: 1 1 auto; min-width: 0; }
.kb-todo .todo-main > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kb-todo .todo-line1 { font-size: 12.5px; color: var(--ink); }
.kb-todo .todo-line2 { font-size: 11.5px; color: var(--muted); }
/* 定时提醒窄带（2026-11-02 新增）：R 定时任务不进 .todo-list，单独置顶一条。
   视觉上刻意与下方待办项区分：浅橙底 + 左侧色条，说明它是「按时间提醒」而不是「表里的流程待办」。 */
.kb-todo .todo-taskbar {
  display: flex; align-items: center; gap: 7px; margin: 8px 10px 0;
  padding: 7px 9px; border-radius: 5px; cursor: pointer;
  border: 1px solid #f0c987; border-left: 3px solid #e08a1e;
  background: #fff8e8; transition: background .12s;
}
.kb-todo .todo-taskbar:hover { background: #fff1d6; }
.kb-todo .todo-taskbar:focus-visible { outline: 2px solid #e08a1e; outline-offset: 1px; }
.kb-todo .todo-taskbar-ico { flex: 0 0 auto; font-size: 13px; line-height: 1; }
.kb-todo .todo-taskbar-main { display: flex; flex-direction: column; flex: 1 1 auto; min-width: 0; }
.kb-todo .todo-taskbar-main > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kb-todo .todo-taskbar-t { font-size: 12.5px; font-weight: 600; color: #8a4b00; }
.kb-todo .todo-taskbar-t em { font-style: normal; font-weight: 400; font-size: 11.5px; color: #a06a2a; margin-left: 6px; }
.kb-todo .todo-taskbar-s { font-size: 11.5px; color: #a06a2a; }
.kb-todo .todo-taskbar-go { flex: 0 0 auto; font-size: 11.5px; color: #b06a00; white-space: nowrap; }
.kb-active-table {
  width: 100%; table-layout: fixed;
  /* K1 表头用 separate（边框分离）模式而非 .kb-table 的collapse：
     collapse 下折叠边框由表格统一绘制在网格线上、不随 sticky 单元格移动，
     表头吸顶后其下边框留在原表格位置，下沿会漏缝、滚过的行内容从中透出。
     separate 下边框归属各自单元格，可随 sticky 正常移动。
     border-spacing:0 抵消 separate 默认的单元格间距，保持与 collapse 一致的紧凑排版。 */
  border-collapse: separate; border-spacing: 0;
  border-left: 1px solid #e3e8f0;
}
.kb-active-table th, .kb-active-table td {
  text-align: left; vertical-align: top;
  white-space: normal; word-break: break-word; line-height: 1.45;
}
/* separate 模式下相邻单元格边框不再折叠，会叠加成 2px。
   统一改为「只画右、下」，左侧与顶部由表格外框和表头各自承担，视觉仍是 1px 线。 */
.kb-active-table th, .kb-active-table td { border-top: 0; border-left: 0; }
.kb-active-table thead th { border-top: 1px solid #4a6db5; }  /* 表头顶线（原由 th 自身上边框承担） */
/* K1 表头完全参照 K0（.kb-table th）：深蓝底、白字、加粗、居中、单行不换行、上下居中。
   上面那条 th/td 通用规则会把 th 的 white-space 改成 normal、vertical-align 改成 top，
   故在此逐项还原为 K0 表头的取值。 */
.kb-active-table th {
  text-align: center; vertical-align: middle;
  white-space: nowrap; word-break: normal; line-height: normal;
}
/* K1 表头锁定：纵向滚动时固定在顶部。
   底色必须显式声明为不透明，才能完全遮住从下方滚过的行内容。
   box-shadow: 向下 1px 外扩投影，用于封住表头下沿与 tbody 首行之间的边界像素——
   th 的 border-bottom 只覆盖 th 盒内那 1px，其下方紧接首行、二者之间无遮挡，
   滚动时若某行文字正好落在边界像素上会漏出（2x 像素实测 scrollTop=150 时
   css 69.0 处出现 rgb(185,189,194) 等内容色，纯行底色应为 rgb(242,246,252)）。
   必须用外扩投影而非 inset 阴影：inset 只作用于盒内，盖不到盒外那 1px。
   （thead 内的 ::after 伪元素也实测无效，受表格层叠/裁剪影响。） */
.kb-active-table thead th {
  position: sticky; top: 0; z-index: 3;
  background: #2f5597;
  box-shadow: 0 1px 0 0 #4a6db5;
}
.kb-active-table .kb-idx { text-align: center; width: 6%; color: var(--muted); }
.kb-active-table th:nth-child(2), .kb-active-table td:nth-child(2) { width: 18%; } /* 子项目名称 */
.kb-active-table th:nth-child(3), .kb-active-table td:nth-child(3) { width: 12%; } /* 要求日期 */
.kb-active-table th:nth-child(4), .kb-active-table td:nth-child(4) { width: 24%; } /* 工作要求 */
.kb-active-table th:nth-child(5), .kb-active-table td:nth-child(5) { width: 22%; } /* 后续工作安排 */
.kb-active-table th:nth-child(6), .kb-active-table td:nth-child(6) { width: 18%; }  /* 负责/协助（加宽至刚好一行装下） */
.kb-active-table tr.kb-act-row { cursor: pointer; transition: background .12s; }
/* K1 数据行奇偶底色交替（白 / 浅蓝灰），便于横向对照阅读 */
.kb-active-table tbody tr.kb-act-row:nth-child(odd) { background: #ffffff; }
.kb-active-table tbody tr.kb-act-row:nth-child(even) { background: #f2f6fc; }
/* 悬停高亮：与上面同为 3 类级 + 2 元素级，特异性相同且位置在后，故能覆盖奇偶底色 */
.kb-active-table tbody tr.kb-act-row:hover { background: #eef4ff; }
/* K1 数据单元格：最多显示两行，超出部分以省略号收尾（-webkit-line-clamp 自带 …） */
.kb-active-table td.kb-cell .kb-clamp {
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  overflow: hidden; word-break: break-word; max-height: 2.9em;
}
.kb-active-table td.kb-cell .kb-zero { color: #98a2b3; }
/* 原首页「左侧菜单区 + 浅蓝菜单卡片」样式已废弃（2026-10-19 菜单移入深色侧栏），
   相关规则统一在文件上方「左侧导航栏」段内维护，此处不再重复定义。 */

/* 返回首页按钮：醒目底色（绿） */
#btn-home {
  background: #1e9e4a; border-color: #1e9e4a; color: #fff; font-weight: 600;
}
#btn-home:hover { background: #17823c; border-color: #17823c; box-shadow: 0 3px 10px rgba(30,158,74,.35); }

/* 「返回首页」居中于工具栏中部（2026-10-09 用户指令，T1~T5 通用）
   方案：.tv-tools 恢复 margin-left:auto 贴右，.tv-home 用绝对定位压在工具栏中线。
   为什么不加左右垫片：垫片本身占宽度，会把 .tv-info 挤成 0 宽（统计徽章消失），
   且两片同宽会令总宽超出容器而出现横向溢出——实测均不可取。
   窄屏兜底：空间不足以容纳「中线左侧信息 + 中线右侧按钮」时，
   由 JS 加 .tv-home-inline 类取消绝对定位，按钮回到右侧按钮组末尾，工具栏保持单行。 */
.tv-header { position: relative; }
.tv-home {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  z-index: 3;
  white-space: nowrap;
}
/* 窄屏回退：参与常规流，紧贴右侧按钮组末尾 */
.tv-home.tv-home-inline {
  position: static;
  transform: none;
  margin-left: 8px;
}
#btn-home { flex-shrink: 0; }

.table-view { background: var(--panel); border: 1px solid var(--line); border-radius: 10px; padding: 18px; display: flex; flex-direction: column; height: 100%; box-sizing: border-box; }
/* 表头：行数信息 + 统计徽章 + 工具条，**强制单行**。
   原先三处都写了 flex-wrap:wrap，宽度不够时「未选中行」等文本会折到第二行，
   把工具栏撑成两行（用户反馈）。现改为：
     · 容器 nowrap + 隐藏横向溢出
     · 各子项也 nowrap
     · 宽度紧张时用 clamp() 逐级缩小字体与间距（而非换行） */
.tv-header { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; flex-wrap: nowrap; white-space: nowrap; overflow: hidden; }
/* 页头工作台名称（2026-10-21 用户指令「将工作台名称放置在这里，原有元素右移」）：
   最左一席 = 编号徽标 + 名称；右侧一条细竖线作分隔，统计徽章/筛选/按钮组随之右移。
   名称可缩（min-width:0 + 省略号），编号徽标不缩，保证窄屏下按钮组不被挤掉。 */
.tv-name { display: flex; align-items: center; gap: 7px; flex-shrink: 0; min-width: 0;
  max-width: 34vw; padding-right: 10px; border-right: 1px solid var(--line); }
.tv-name.hidden { display: none; }
.tv-name-code { flex-shrink: 0; font-size: 11.5px; font-weight: 700; letter-spacing: .5px;
  color: #fff; background: var(--primary); border-radius: 6px; padding: 2px 7px; line-height: 1.5; }
.tv-name-txt { font-size: 15px; font-weight: 700; color: var(--ink); letter-spacing: .3px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tv-info { display: flex; align-items: center; gap: 8px; flex-wrap: nowrap; white-space: nowrap; min-width: 0; flex-shrink: 1; overflow: hidden; }
/* 右侧按钮组：保持 margin-left:auto 贴右。
   注意：本行是 .tv-tools 的唯一定义处，勿在别处再写 margin-left:0 ——
   同优先级下后定义会覆盖，导致工具组不贴右、「返回首页」居中判定误判为冲突。 */
.tv-tools { display: flex; align-items: center; gap: 8px; flex-wrap: nowrap; white-space: nowrap; margin-left: auto; flex-shrink: 0; }

.filter-input { height: 28px; border: 1px solid var(--line); border-radius: 7px; padding: 0 8px; width: clamp(120px, 18vw, 200px); font-size: 12px; }
.filter-input:focus { outline: none; border-color: var(--primary); }
/* 2026-11-06（用户指令）：筛选下拉（项目类别 / 状态），与关键字框同高同圆角 */
.filter-select { height: 28px; border: 1px solid var(--line); border-radius: 7px; padding: 0 4px; font-size: 12px; background: #fff; color: var(--ink); max-width: 150px; }
.filter-select:focus { outline: none; border-color: var(--primary); }
/* 行号/行提示文字：单行显示，过长由 JS 截断 */
.row-count { color: var(--muted); font-size: 11px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.toolbar-actions { display: flex; gap: 5px; flex-wrap: nowrap; align-items: center; white-space: nowrap; }
.tv-header .btn { padding: 5px 9px; font-size: 12px; border-radius: 6px; white-space: nowrap; flex-shrink: 0; }
/* 「未选中行」等行操作提示：单行显示，过长省略 */
.row-tip { color: var(--muted); font-size: 11px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 120px; flex-shrink: 0; }
/* 统计徽章：单行、不换行 */
.stats-bar { display: flex; flex-wrap: nowrap; gap: 5px; white-space: nowrap; overflow: hidden; }
.stats-bar .stat { font-size: 12px; padding: 3px 8px; border-radius: 14px; background: var(--head-bg); color: var(--ink); white-space: nowrap; }
.stats-bar .stat b { font-size: 13px; }
.stats-bar .stat-week { background: #e7f0ff; color: var(--primary); font-weight: 600; }

/* ---------- 在线提示：谁正在编辑哪一行 ----------
   用暖橙底色与他人的行高亮区分（暖色=有人在动，冷静不打扰阅读）；
   左边框给出"整行都是他"的语义，比只标一个格子更醒目。 */
.presence-bar { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 5px; }
.presence-bar:empty { display: none; }          /* 无人在线时不占位 */
.presence-chip {
  font-size: 12px; padding: 3px 9px; border-radius: 14px; white-space: nowrap;
  background: #fff4e5; color: #a35a12; border: 1px solid #ffd9ad;
}
.presence-chip b { font-size: 13px; }
.presence-chip .p-row { color: #d2691e; font-weight: 600; }
.presence-chip.p-viewing { background: #f2f4f7; color: #5b6472; border-color: #dfe3e8; }
.presence-chip.p-viewing .p-row { color: #5b6472; font-weight: 400; }

/* 有人正在编辑的行：整行淡橙底 + 左侧竖条提示 */
#data-table tr.row-editing > td { background: #fff8f0; }
#data-table tr.row-editing > td:first-child { box-shadow: inset 3px 0 0 #ff9f43; }
#data-table tr.row-editing > td.row-badge-editing { color: #a35a12; font-weight: 600; }
#data-table tr.row-editing:hover > td { background: #fff2e2; }

/* ---------- 窄屏 /低分辨率：逐级缩小，保证工具栏始终单行 ---------- */
@media (max-width: 1500px) {
  .tv-header { gap: 8px; }
  .tv-name { gap: 6px; padding-right: 8px; max-width: 30vw; }
  .tv-name-txt { font-size: 13.5px; }
  .tv-info { gap: 6px; }
  .tv-tools { gap: 6px; }
  .stats-bar .stat { font-size: 11px; padding: 2px 7px; }
  .stats-bar .stat b { font-size: 12px; }
  .tv-header .btn { font-size: 11px; padding: 4px 7px; }
  .row-count { font-size: 10px; }
  .filter-input { font-size: 11px; }
  .filter-select { font-size: 11px; max-width: 120px; }
}
@media (max-width: 1280px) {
  .tv-header { gap: 6px; }
  .tv-name { gap: 5px; padding-right: 6px; max-width: 26vw; }
  .tv-name-code { font-size: 10.5px; padding: 1.5px 6px; }
  .tv-name-txt { font-size: 12.5px; }
  .tv-info, .tv-tools { gap: 5px; }
  .stats-bar { gap: 4px; }
  .stats-bar .stat { font-size: 10px; padding: 2px 6px; border-radius: 12px; }
  .stats-bar .stat b { font-size: 11px; }
  .tv-header .btn { font-size: 10px; padding: 4px 6px; border-radius: 5px; }
  .toolbar-actions { gap: 4px; }
  .row-count { font-size: 10px; }
  .filter-input { height: 26px; font-size: 11px; }
  .filter-select { height: 26px; font-size: 11px; max-width: 100px; }
}

.grid-wrap { flex: 1; min-height: 0; overflow: auto; border: 1px solid var(--line); border-radius: 8px; }
/* 表头吸顶必须用 separate（边框分离）模式——与 K1 同一根因、同一解法：
   collapse 下折叠边框由表格统一绘制在网格线上、不随 sticky 单元格移动，
   表头吸顶后它自己的那 1px 下边框仍留在原表格位置（早已滚出视野），
   于是边界处只剩一行底色：表头与数据行直接贴在一起、状态列的彩色底纹顶到表头下沿，
   看起来就像顶部「漏光/开缝」。separate 下边框归属各自单元格，可随 sticky 正常移动。
   border-spacing:0 抵消 separate 默认的单元格间距，排版保持与 collapse 一致。 */
.data-table { border-collapse: separate; border-spacing: 0; width: 100%; font-size: 13px; }
/* separate 下相邻单元格边框不再折叠、会叠成 2px，故单元格只画「右、下」两向；
   表格左、上的外框由 .grid-wrap 自身的边框承担，视觉仍是 1px 线。 */
.data-table th, .data-table td { border: 0; border-right: 1px solid var(--line); border-bottom: 1px solid var(--line); padding: 6px 8px; text-align: left; vertical-align: top; min-width: 90px; max-width: 420px; }
/* 表头吸顶：下边线改由「向下 1px 外扩投影」承担而非 border-bottom。
   原因：th 的 border-bottom 只覆盖 th 盒内那 1px，紧接其下的首行无遮挡，
   缩放比非整数时（如 Windows 125%）表头高度会落到半个物理像素上、边界处仍会露出底下
   行的内容色；外扩投影画在盒外，可把这一像素一并封住。二者同色，视觉就是一条 1px 线。 */
.data-table thead th { background: var(--head-bg); position: sticky; top: 0; z-index: 5; font-weight: 600; white-space: nowrap; text-align: center; border-bottom: 0; box-shadow: 0 1px 0 0 var(--line); }
.data-table td.rownum { background: var(--head-bg); color: var(--muted); text-align: center; width: 36px; min-width: 36px; position: sticky; left: 0; z-index: 4; }
.data-table th.rownum { width: 36px; min-width: 36px; position: sticky; left: 0; z-index: 6; }
.data-table td.cell { white-space: pre-wrap; word-break: break-word; }
.data-table tbody tr.zebra-odd { background: #f4f7fb; }
.data-table tbody tr.zebra-even { background: #ffffff; }
.data-table td.editable { background: transparent; cursor: text; }
.data-table td.editable:focus { outline: 2px solid var(--primary); background: #fff; }
.data-table td.date-cell { white-space: nowrap; text-align: center; overflow-x: hidden; }
.data-table td.image-cell a { color: var(--primary); text-decoration: none; }
.data-table td.image-cell img { max-height: 60px; display: block; margin-top: 4px; border: 1px solid var(--line); border-radius: 4px; }
/* ---------- 附件单元格（方案 A+B：原文保留，附件另加图标；行高锁定不撑高表格） ---------- */
/* 附件单元格：徽标与文字同一行内排布，高度固定，不随内容增长 */
.data-table td.att-cell { max-height: none; overflow: visible; }
/* 文字与徽标同行（inline），让单元格高度恒定为一行 */
.att-inline { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.att-text { white-space: pre-wrap; word-break: break-word; font-size: 12px; line-height: 1.6; color: var(--ink); min-width: 0; }
.att-text.clamped { display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical; overflow: hidden; }
.att-bar { display: inline-flex; align-items: center; gap: 3px; flex-wrap: wrap; }
.att-chip { display: inline-flex; align-items: center; gap: 2px; height: 18px; padding: 0 4px; border: 1px solid var(--line); border-radius: 3px; background: #fff; color: var(--primary); font-size: 10px; cursor: pointer; white-space: nowrap; max-width: 100%; overflow: hidden; }
/* 固定列宽表的窄附件列：徽标压得更紧凑，只留图标 + 少量文件名 */
.data-table.colfixed td.att-cell .att-chip { max-width: 100%; padding: 0 3px; }
.data-table.colfixed td.att-cell .att-chip span,
.data-table.colfixed td.att-cell .att-chip { font-size: 9px; }
.att-chip:hover { border-color: var(--primary); background: #f2f7ff; }
.att-chip.att-broken { color: var(--red); border-color: #f0c0c0; cursor: default; }
.att-chip.att-broken:hover { background: #fff; border-color: #f0c0c0; }
.att-chip .att-ico { font-style: normal; font-weight: 700; font-size: 10px; }
.att-more { display: inline-flex; align-items: center; height: 20px; padding: 0 6px; border-radius: 4px; background: #eef2f7; color: var(--muted); font-size: 11px; cursor: pointer; }
.att-more:hover { background: #e2e8f0; }
.att-toggle { font-size: 10px; color: var(--primary); cursor: pointer; user-select: none; white-space: nowrap; }
/* ---------- 附件白名单列标记 ---------- */
/* 可添加附件的列：表头加 📎，列底色微黄，便于快速定位 */
.data-table th.th-attach { background: #fff8e6; color: #8a5a00; }
.data-table th.th-attach .th-att { font-size: 11px; margin-left: 3px; opacity: .85; }
.data-table td.col-attach { background: #fffdf5; }
/* 可附件列的空单元格：常驻提示，鼠标悬停才显形，避免视觉噪声 */
td.col-attach .att-add { opacity: .55; }
td.col-attach:hover .att-add { opacity: 1; }
.att-toggle:hover { text-decoration: underline; }
/* 「+ 附件」入口：平时隐去，悬停单元格才显示，避免视觉噪音与撑高表格 */
.att-add { display: inline-block; font-size: 10px; color: var(--primary); cursor: pointer; opacity: 0; transition: opacity .12s; user-select: none; white-space: nowrap; }
.att-cell:hover .att-add, td.cell:hover .att-add, .att-add:focus { opacity: 1; }
.att-add:hover { text-decoration: underline; }
/* 附件查看弹窗 */
.att-list { display: flex; flex-direction: column; gap: 14px; }
.att-item { border: 1px solid var(--line); border-radius: 8px; padding: 10px; }
.att-item .att-path { font-size: 12px; color: var(--muted); word-break: break-all; margin-bottom: 8px; }
.att-item img { max-width: 100%; max-height: 62vh; display: block; border-radius: 4px; border: 1px solid var(--line); }
.att-none { font-size: 13px; color: var(--muted); padding: 8px 0; }
.att-open { display: inline-block; font-size: 13px; color: var(--primary); text-decoration: none; }
.att-open:hover { text-decoration: underline; }
/* ---------- 插入附件弹窗 ---------- */
.ins-sec { margin-bottom: 18px; }
.ins-sec-title { font-size: 13px; font-weight: 500; color: var(--ink); margin-bottom: 8px; }
.ins-sec-tip { font-weight: 400; font-size: 12px; color: var(--muted); margin-left: 8px; }
.ins-sec-title code { background: var(--head-bg); padding: 1px 4px; border-radius: 3px; font-size: 12px; }
.ins-drop { border: 2px dashed var(--line); border-radius: 8px; background: #fafbfc; cursor: pointer; transition: border-color .15s, background .15s; }
.ins-drop:hover, .ins-drop.over { border-color: var(--primary); background: #f4f8ff; }
.ins-drop-inner { padding: 18px; text-align: center; }
.ins-drop-main { font-size: 14px; color: var(--primary); }
.ins-drop-tip { font-size: 12px; color: var(--muted); margin-top: 4px; line-height: 1.6; }
.ins-sel { margin-top: 8px; }
.ins-sel-item { display: flex; align-items: center; gap: 6px; padding: 5px 8px; border: 1px solid var(--line); border-radius: 5px; margin-bottom: 4px; font-size: 12px; background: #fff; }
.ins-sel-item .ins-sel-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ins-sel-item .ins-sel-size { color: var(--muted); white-space: nowrap; }
.ins-sel-item .ins-del { cursor: pointer; color: var(--muted); border: none; background: none; font-size: 15px; line-height: 1; padding: 0 2px; font-family: inherit; }
.ins-sel-item .ins-del:hover { color: var(--red); }
.ins-paste-box { border: 2px dashed var(--line); border-radius: 8px; background: #fafbfc; padding: 14px; text-align: center; cursor: text; transition: border-color .15s, background .15s; outline: none; }
.ins-paste-box:hover, .ins-paste-box:focus { border-color: var(--primary); background: #f4f8ff; }
.ins-paste-main { font-size: 13px; color: var(--primary); }
.ins-paste-tip { font-size: 12px; color: var(--muted); margin-top: 5px; line-height: 1.7; }
.ins-paste-tip b { color: var(--ink); font-weight: 500; }
kbd { display: inline-block; padding: 0 4px; border: 1px solid var(--line); border-bottom-width: 2px; border-radius: 3px; background: #fff; font-size: 11px; font-family: inherit; }
.ins-input { width: 100%; height: 34px; border: 1px solid var(--line); border-radius: 6px; padding: 0 10px; font-size: 13px; font-family: inherit; }
.ins-input:focus { outline: none; border-color: var(--primary); }
/* 文字说明输入框（可输入多行） */
.ins-textarea { width: 100%; border: 1px solid var(--line); border-radius: 6px; padding: 8px 10px; font-size: 13px; font-family: inherit; line-height: 1.6; resize: vertical; min-height: 56px; }
.ins-textarea:focus { outline: none; border-color: var(--primary); }
.ins-tip { font-size: 12px; color: var(--muted); margin-top: 5px; min-height: 17px; }
.ins-tip.err { color: var(--red); }
.ins-tip.ok { color: var(--green); }
.del-btn { color: var(--red); border: none; background: transparent; font-size: 13px; }
.del-btn:hover { text-decoration: underline; }

/* 固定列宽表（仅配置了 COL_WIDTHS 的表）：colgroup 的 width 才严格生效 */
.data-table.colfixed { table-layout: fixed; min-width: 100%; }
.data-table.colfixed th, .data-table.colfixed td { min-width: 0; max-width: none; }

/* ---------- 自适应收窄（.fitted，2026-10-15：让列多的表也尽量整屏显示）----------
   由 app.js 的 fitTableToWidth() 在「列宽合计 > 容器」时给表格加 .fitted 并等比收窄各列。
   此时列内空间变小，原本 nowrap 的表头/编码/日期文本会被压出格 → 这里统一放开换行。
   （<br> 两行表头不受影响，nowrap 下也照样折行。） */
.data-table.fitted thead th { white-space: normal; word-break: break-word; line-height: 1.25; }
.data-table.fitted th.col-code,
.data-table.fitted td.col-code { white-space: normal; overflow-wrap: anywhere; }
.data-table.fitted td.date-cell { white-space: normal; }
.data-table.fitted td.cell.num-cell { white-space: normal; }

/* ---------- t6（质检科理化工作台）：列多且含长文本，格内边距收紧给内容让宽 ----------
   2026-10-15 用户要求「尽量整屏显示」；4 项力学指标表头已由 HEADER_LABEL 改成两行，
   编号列允许按「-」折行（T6-YYYYMMDD-01 → 2 行）。 */
#data-table.tbl-t6 th, #data-table.tbl-t6 td { padding: 4px 5px; }
#data-table.tbl-t6 th.col-code,
#data-table.tbl-t6 td.col-code { white-space: normal; overflow-wrap: anywhere; }

/* 操作反馈：改为视口内浮层提示，确保任何滚动位置都看得见 */
.save-tip { position: fixed; left: 50%; top: 64px; transform: translateX(-50%) translateY(-6px); background: rgba(35,45,55,.94); color: #fff; font-size: 13px; line-height: 1.6; padding: 9px 20px; border-radius: 8px; z-index: 200; opacity: 0; pointer-events: none; transition: opacity .18s, transform .18s; max-width: 76vw; text-align: center; box-shadow: 0 4px 14px rgba(0,0,0,.2); }
.save-tip.show { opacity: 1; transform: translateX(-50%) translateY(0); }
.revcell { cursor: pointer; }

/* ---------- 统计看板 ----------
   样式已合并到文件上方的「表头强制单行」一节，此处不再重复定义 */

/* ---------- 下拉单元格 ---------- */
.data-table td.select-cell { padding: 2px 4px; }
/* 可输入 + 可选择的建议列（选项来自「下拉选项」工作表） */
.data-table td.opt-cell { padding: 2px 3px; }
.opt-input { width: 100%; min-width: 0; border: none; background: transparent; font: inherit; color: inherit; padding: 4px 5px; border-radius: 4px; }
.opt-input:hover { background: #f0f5fb; }
.opt-input:focus { outline: 2px solid var(--primary); background: #fff; }
.data-table td.select-cell select { width: 100%; border: none; background: transparent; font-family: inherit; font-size: 13px; padding: 4px 6px; border-radius: 6px; cursor: pointer; }
.data-table td.select-cell select:focus { outline: 1px solid var(--primary); }
/* ---------- 严格下拉（可换行呈现 + 弹层选择） ----------
原生 <select> 的选项文本无法换行，「外购换货（装配）」这类值会被截断；
改为「可换行文本单元格 + 点击弹浮层」，语义不变（仍只能从列表选）。 */
.data-table td.strict-cell { cursor: pointer; position: relative; white-space: pre-wrap; word-break: break-word; }
.data-table td.strict-cell .strict-text { display: inline; }
.data-table td.strict-cell .strict-caret { font-size: 9px; color: var(--muted); margin-left: 4px; opacity: 0; }
.data-table td.strict-cell:hover { background: #f0f5fb; }
.data-table td.strict-cell:hover .strict-caret { opacity: 1; }
.data-table td.strict-cell.strict-empty .strict-text { color: var(--muted); }
/* 浮层选项列表 */
.strict-pop { position: fixed; z-index: 60; min-width: 140px; max-width: 320px; max-height: 320px; overflow: auto; background: #fff; border: 1px solid var(--line); border-radius: 8px; box-shadow: 0 6px 20px rgba(0,0,0,.14); padding: 4px 0; }
.strict-pop-hd { font-size: 11px; color: var(--muted); padding: 4px 12px 6px; border-bottom: 1px solid var(--line); margin-bottom: 4px; }
.strict-opt { padding: 6px 12px; font-size: 13px; color: var(--ink); cursor: pointer; white-space: normal; }
.strict-opt:hover { background: #f0f5fb; }
.strict-opt.cur { color: var(--primary); font-weight: 500; }
.strict-blank { color: var(--muted); font-style: normal; }
/* 固定列宽表（t2）：窄列内容居中，避免数字贴边 */
.data-table.colfixed td.cell.num-cell { text-align: center; }

/* ---------- 手工录入格（下拉选「其他」后转为自由输入） ----------
   t3「接受部门」：下拉候选为「生产管理部 / 其他」；选「其他」后该格改手工录入。
   浅黄底 + 空值占位提示，提示此处可直接输入实际接受部门名称。 */
.data-table td.cell.free-cell { background: #fffbe6; }
.data-table td.cell.free-cell:empty::before { content: '填写部门名称'; color: #b9a24a; font-size: 12px; pointer-events: none; }
.data-table td.cell.free-cell:focus { outline: 2px solid #e5c74b; outline-offset: -2px; }

/* ---------- 长文本单元格内滚动（避免撑破行高） ---------- */
.data-table td.cell:not(.select-cell):not(.strict-cell):not(.opt-cell) { max-height: 130px; overflow: auto; }
/* ERP 编码等输入型单元格：宽度已按最长值设定，不要再叠内部滚动条（会遮住编码尾部） */
.data-table td.opt-cell { max-height: none; overflow: visible; }
/* ERP 编码：不换行、不裁切，保证完整可见（列宽 20ch > 实测最长 17 字符） */
.data-table td.opt-cell .code-input { min-width: 0; white-space: nowrap; }

/* ---------- 校验/审计表格 ---------- */
.val-summary { font-size: 14px; margin-bottom: 12px; }
.val-ok { color: var(--green); font-size: 14px; }
.val-table { border-collapse: collapse; width: 100%; font-size: 13px; }
.val-table th, .val-table td { border: 1px solid var(--line); padding: 7px 10px; text-align: left; }
.val-table thead th { background: var(--head-bg); }
.val-table tr.err td:first-child { color: var(--red); font-weight: 600; }
.val-table tr.warn td:first-child { color: var(--amber); font-weight: 600; }
.audit-detail { font-size: 12px; color: var(--muted); max-width: 360px; word-break: break-all; }

/* ---------- 窄屏适配 ---------- */
/* ---------- 侧栏 / 看板自适应 ---------- */
/* ≤1180px：侧栏自动收为图标栏（保留深色侧栏形态，把宽度让给表格/看板） */
@media (max-width: 1180px) {
  .sidebar { width: 72px; }
  .sidebar .sb-brand { padding: 14px 6px; gap: 6px; justify-content: center; }
  .sidebar :is(.sb-brand-text, .sb-group, .mi-name, .mi-arrow, .user-info) { display: none; }
  .sidebar .sb-scroll { padding: 6px 6px 14px; }
  .sidebar .menu-item { justify-content: center; padding: 9px 0; }
  .sidebar .menu-item.active::before { left: -6px; }
  .sidebar .cu-btns { flex-direction: column; }
  .sidebar .cu-btns .btn { font-size: 11px; padding: 6px 2px; }
  #sb-toggle { display: none; }
}
/* ≤900px：看板卡片改为单列（原 4 列网格在窄屏会把卡片挤成细条） */
@media (max-width: 900px) {
  .kanban-body {
    display: flex; flex-direction: column; gap: 12px;
    overflow-y: auto; overflow-x: hidden;
  }
  .kanban-body .kb-card { flex: none; max-height: 46vh; }
  .kanban-body .kb-card.wide2 { grid-column: auto; }
  .kanban-body .kb-card.wide4 { grid-column: auto; min-height: 220px; }
  /* K3 多栏在窄屏压缩：卡高受 46vh 限制，图矮一点才不会把脚注裁掉 */
  .kb-trend3 { gap: 8px; padding: 6px 10px 0; }
  .kb-shop-plot { height: 92px; }
  .kb-trend-n4 .kb-shop-plot { height: 76px; }
  .kb-shop-svg { height: 92px; }
  .kb-shop-val { font-size: 17px; }
  .kb-trend-x, .kb-trend3-note { padding-left: 10px; padding-right: 10px; }
}
@media (max-width: 768px) {
  .corner-user { padding: 0; gap: 6px; }
  .tv-switch { width: 150px; max-width: 150px; }
  .main { padding: 12px; }
  .table-view { padding: 12px; }
  .page-head h1 { font-size: 17px; }
}
@media (max-width: 640px) {
  .sidebar { width: 64px; }
  .sidebar .sb-logo { width: 26px; height: 26px; font-size: 13px; }
  .sidebar .sb-brand { padding: 12px 4px; }
  .sidebar .sb-scroll { padding: 6px 4px 12px; }
  .sidebar .sb-foot { padding: 8px 4px; }
  .sidebar .menu-item { min-height: 38px; padding: 8px 0; }
  .sidebar .mi-ico { width: 18px; height: 18px; }
  .sidebar .cu-btns .btn { font-size: 10px; padding: 5px 1px; }
  .main { padding: 10px; }
  .welcome { gap: 10px; }
  .page-head .ph-sub { display: none; }
}

/* ---------- 弹窗 ---------- */
.modal { position: fixed; inset: 0; background: rgba(20,30,45,.45); display: flex; align-items: center; justify-content: center; z-index: 50; }
.modal-box { width: 760px; max-width: 94vw; max-height: 88vh; background: #fff; border-radius: 12px; display: flex; flex-direction: column; }
.modal-head { display: flex; justify-content: space-between; align-items: center; padding: 16px 20px; border-bottom: 1px solid var(--line); font-weight: 700; font-size: 16px; }
.modal-close { border: none; background: transparent; font-size: 24px; line-height: 1; color: var(--muted); }
/* 行表单弹窗标题栏：只显示表名（表头）并居中；关闭按钮绝对定位，保证表名视觉居中。
   2026-10-10 用户要求：「表头」=表名，居中；原「第 N 行 ·」下移到状态条（见 app.js renderRowFormStatus）。 */
#row-form-modal .modal-head { justify-content: center; position: relative; }
#row-form-modal .modal-head #rf-title { flex: 1; text-align: center; }
#row-form-modal .modal-head .modal-close { position: absolute; right: 14px; top: 50%; transform: translateY(-50%); }
.modal-body { padding: 18px 20px; overflow: auto; }
/* 通用对话框 */
.modal-box-sm { width: 440px; }
.dlg-msg { font-size: 14px; line-height: 1.7; white-space: pre-wrap; word-break: break-word; }
.dlg-input { width: 100%; height: 36px; margin-top: 14px; border: 1px solid var(--line); border-radius: 7px; padding: 0 10px; font-family: inherit; font-size: 14px; }
.dlg-input:focus { outline: none; border-color: var(--primary); }
.dlg-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 20px; }
.btn-danger-solid { background: var(--red); border-color: var(--red); color: #fff; }
.btn-danger-solid:hover { filter: brightness(.94); }
/* 行操作选项菜单 */
.rowmenu-state { font-size: 13px; color: var(--muted); line-height: 1.7; margin-bottom: 14px; }
.rowmenu-list { display: flex; flex-direction: column; gap: 8px; }
.rowmenu-item { display: flex; align-items: center; gap: 10px; width: 100%; padding: 10px 12px; border: 1px solid var(--line); border-radius: 8px; background: #fff; cursor: pointer; text-align: left; font-family: inherit; font-size: 14px; color: var(--ink); transition: background .12s, border-color .12s; }
.rowmenu-item:hover { background: #f4f8ff; border-color: var(--primary); }
.rowmenu-item:disabled { opacity: .5; cursor: not-allowed; background: #f6f6f6; }
.rowmenu-item:disabled:hover { background: #f6f6f6; border-color: var(--line); }
.rowmenu-dot { width: 12px; height: 12px; border-radius: 50%; flex: 0 0 auto; box-shadow: inset 0 0 0 1px rgba(0,0,0,.15); }
.rowmenu-hint { margin-left: auto; font-size: 12px; color: var(--muted); white-space: nowrap; }
.modal-box-lg { width: 640px; }
.imp-hint { font-size: 13px; color: var(--muted); line-height: 1.7; margin-bottom: 12px; }   /* 通用提示条：基础设置各面板 / 插入附件弹窗共用（非导入专用） */
/* ---------- 提交 / 审核 ---------- */
.revcol, .revcell { width: 62px; min-width: 62px; text-align: center; padding: 4px 3px !important; }
.revcell { cursor: pointer; }
.revbadge { display: inline-block; font-size: 11px; padding: 3px 9px; border-radius: 5px; white-space: nowrap; line-height: 1.5; border: 1px solid rgba(0,0,0,.12); box-shadow: 0 1px 1px rgba(0,0,0,.06); }
tr.row-sel .revbadge { box-shadow: 0 0 0 2px #fff, 0 0 0 4px var(--primary); }
/* 处理中：置灰并禁止点击，防连点重复提交 */
.revbadge-busy { opacity: .55; cursor: progress !important; }
.revcell { cursor: pointer; }
.rev-note { display: block; font-size: 10px; color: var(--muted); margin-top: 2px; max-width: 56px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
tr.row-sel > td, tr.row-sel td.zebra-cell { background: #dce9fb !important; }
/* 从看板跳转定位：临时醒目高亮，约 2.8s 后褪去（行仍保留 row-sel 选中底色） */
tr.row-jump > td { background: #ffe08a !important; box-shadow: inset 0 2px 0 #e8a33d, inset 0 -2px 0 #e8a33d; }
tr.row-jump > td:first-child { box-shadow: inset 2px 0 0 #e8a33d, inset 0 2px 0 #e8a33d, inset 0 -2px 0 #e8a33d; }
tr.row-jump > td:last-child { box-shadow: inset -2px 0 0 #e8a33d, inset 0 2px 0 #e8a33d, inset 0 -2px 0 #e8a33d; }
tr.row-locked > td { background: #f6f7f9; }
tr.row-locked td.editable { cursor: default; }
/* .row-tip 的样式已合并到文件上方的「表头强制单行」一节 */
/* 打开方式错误提示横幅 */
.origin-warn { position: fixed; left: 0; right: 0; top: 0; z-index: 999; background: #fdeaea; color: #8a1f1f; border-bottom: 1px solid #f0c0c0; padding: 12px 18px; font-size: 14px; line-height: 1.7; }
.origin-warn code { background: #fff; border: 1px solid #f0c0c0; border-radius: 4px; padding: 1px 6px; font-family: Consolas, monospace; }
.admin-section { margin-bottom: 22px; }
.admin-section-title { font-size: 14px; font-weight: 600; margin-bottom: 12px; color: var(--primary); }
.add-user-form { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.add-user-form input[type=text], .add-user-form input:not([type=checkbox]) { height: 36px; border: 1px solid var(--line); border-radius: 7px; padding: 0 10px; }
.add-user-form .chk { font-size: 13px; color: var(--muted); display: flex; align-items: center; gap: 4px; }
.inline-msg { font-size: 13px; margin-top: 8px; min-height: 16px; }
.inline-msg.ok { color: var(--green); }
.inline-msg.err { color: var(--red); }

/* ---------- S5 抽样比例表（GB/T 2828.1-2012，2026-10-28 新增） ----------
   版式对齐纸质附表：细实线整框、表头浅灰底、全部居中；供货批量列等宽数字对齐。 */
.smp-wrap { overflow-x: auto; padding-top: 2px; }
.smp-table {
  width: 100%; max-width: 720px; border-collapse: collapse; table-layout: fixed;
  font-size: 13.5px; color: var(--ink);
}
.smp-table th, .smp-table td { border: 1px solid #8a97a8; padding: 6px 8px; text-align: center; }
.smp-table thead th { background: #eef2f7; font-weight: 600; }
.smp-table tbody td { background: #fff; }
.smp-table tbody tr:hover td { background: #f7fafd; }
.smp-table .smp-lot { font-variant-numeric: tabular-nums; letter-spacing: .2px; }
.smp-foot { margin-top: 8px; font-size: 12px; color: var(--muted); }
@media print {
  .smp-table th, .smp-table td { border: 1px solid #6b7785; }
  .smp-table thead th { background: #f2f2f2 !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
}

.perm-matrix { overflow: auto; border: 1px solid var(--line); border-radius: 8px; }
.perm-matrix table { border-collapse: collapse; width: 100%; font-size: 13px; }
.perm-matrix th, .perm-matrix td { border: 1px solid var(--line); padding: 8px 10px; text-align: center; }
.perm-matrix thead th { background: var(--head-bg); }
.perm-matrix td.uname { text-align: left; font-weight: 600; }
.perm-matrix select { padding: 4px 6px; border: 1px solid var(--line); border-radius: 6px; }
.mp-note { font-size: 11px; color: #6b7a8d; font-weight: 400; }

/* ---------- 基础设置弹窗 · 左侧菜单 + 右侧内容（2026-10-11）----------
   由「顶部页签」改为「左侧菜单」：「权限管理」「基础数据」「物料主数据」是同一个『基础设置』下的三个菜单项。
   ⚠ 弹窗本身已于同日改为**整屏铺满**，见文件末尾「基础设置弹窗 · 整屏铺满」一节
   （该节的 `#admin-modal .modal-box` 规则**覆盖**下面这条 1180px；此处保留作为非铺满时的回退宽度）。 */
#admin-modal .modal-box { width: 1180px; }
.admin-body { display: flex; flex: 1; min-height: 0; padding: 0; overflow: hidden; }
.admin-menu { width: 148px; flex: none; border-right: 1px solid var(--line); padding: 12px 8px; background: #f7f9fc; display: flex; flex-direction: column; gap: 4px; border-bottom-left-radius: 12px; }
.admin-mi { border: none; background: none; text-align: left; padding: 9px 12px; font-size: 14px; color: var(--ink); border-radius: 7px; cursor: pointer; font-family: inherit; }
.admin-mi:hover { background: #eaf1fb; color: var(--primary); }
.admin-mi.active { background: #e7f0ff; color: var(--primary); font-weight: 600; }
/* 基础设置 · 左侧菜单底部「返回首页」：沿用工具栏同款绿色（2026-10-12 用户指令） */
/* ⚠ 2026-11-13（用户指令「基础设置弹窗、定时任务弹窗里各还有一个『⌂ 返回首页』，去掉」）：
   #admin-home / #task-home 两个按钮已从 index.html 删除，下面这几段规则**成为无引用的死样式**，
   保留仅为按 index.html 注释留档一键恢复；删除按钮不影响 .modal-head 的 flex 布局（仅少一个子项）。 */
/* 基础设置弹窗「返回首页」：移至顶部栏并绝对居中（按 T1 等工具栏规则，2026-10-13） */
/* 尺寸与 T1~T7 工具栏「返回首页」(.tv-header .btn) 完全一致（含窄屏响应），2026-10-14 对齐 */
#admin-modal .modal-head { position: relative; }
#admin-home {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  border: 1px solid #1e9e4a; background: #1e9e4a; color: #fff; font-weight: 600;
  text-align: center; padding: 5px 9px; font-size: 12px; border-radius: 6px;
  cursor: pointer; font-family: inherit; z-index: 3; white-space: nowrap;
}
#admin-home:hover { background: #17823c; border-color: #17823c; box-shadow: 0 3px 10px rgba(30,158,74,.35); }
@media (max-width: 1280px) {
  #admin-home { font-size: 10px; padding: 4px 6px; border-radius: 5px; }
}
/* R 定时任务弹窗「返回首页」：与 G4 等台账页工具栏「返回首页」完全同款绿色实底按钮
   （2026-11-11 用户指令）。颜色/圆角/字号沿用 .btn + #btn-home 的口径：
   border-radius 7px、padding 7px 14px、font-size 13px、#1e9e4a 实底白字。
   不做绝对居中——页头右侧已有「＋ 新建任务」与关闭按钮，居中会重叠，故保持在右侧末尾。 */
#task-home {
  flex-shrink: 0; margin-left: 8px;
  background: #1e9e4a; border: 1px solid #1e9e4a; color: #fff;
  border-radius: 7px; padding: 7px 14px; font-size: 13px; font-weight: 600;
  font-family: inherit; cursor: pointer; white-space: nowrap;
}
#task-home:hover { background: #17823c; border-color: #17823c; color: #fff; box-shadow: 0 3px 10px rgba(30,158,74,.35); }
@media (max-width: 1280px) {
  #task-home { font-size: 12px; padding: 6px 10px; border-radius: 6px; }
}
.admin-content { flex: 1; min-width: 0; overflow: auto; padding: 18px 20px; }
.master-wrap { display: flex; gap: 16px; min-height: 380px; }
/* 2026-10-19（用户指令「参照首页格式设置；底色浅蓝色」）：
   字典分类栏整体改为**浅蓝底卡片**（不再是白底 + 右侧分隔线）——
   整栏 #eef4ff 浅蓝底 + 细蓝描边 + 圆角，条目平时透明、悬停略深、选中深一档（#d3e3fd）。
   2026-10-19 七次（用户指令「参照首页，底色布满左侧」）：取消 align-self:flex-start 与
   max-height 限制，改为**沿整列拉伸到底**（height 由 .master-wrap 撑满），浅蓝底铺满左侧；
   内容不足时底部留白同为浅蓝，内容多时栏内滚动。 */
.master-side {
  width: 200px; flex: none;
  background: #eef4ff;
  border: 1px solid #d8e4f7;
  border-radius: 8px;
  padding: 10px 10px 12px;
  align-self: stretch;
  max-height: none;
  overflow: auto;
}
.master-side-title { font-size: 12px; color: #6b82a4; margin-bottom: 6px; font-weight: 600; letter-spacing: .5px; }
.master-cats { display: flex; flex-direction: column; gap: 2px; }
.master-cats .mc-group { font-size: 12px; color: #8296b3; margin: 10px 0 2px; padding-left: 2px; }
.master-cats .mc-item { position: relative; padding: 6px 8px; min-height: 32px; box-sizing: border-box; border-radius: 7px; cursor: pointer; font-size: 13px; display: flex; justify-content: space-between; align-items: center; background: transparent; transition: background .12s, color .12s; }
.master-cats .mc-item:hover { background: #e3ecfd; }
.master-cats .mc-item.active { background: #d3e3fd; color: var(--primary); font-weight: 600; }
.master-cats .mc-item.active::before {
  content: ''; position: absolute; left: 0; top: 50%; transform: translateY(-50%);
  width: 3px; height: 18px; border-radius: 0 3px 3px 0; background: var(--primary);
}
.master-cats .mc-item .mc-n { font-size: 11px; color: var(--muted); }
.master-cats .mc-item.active .mc-n { color: var(--primary); }
/* 2026-10-19 三次：「全部字典」菜单已按用户要求撤除，相关 .mc-all 样式一并删除 */
/* 2026-10-14：字典项前加编号（S21/S22…）——标签左对齐、行数右对齐，编号用等宽数字避免抖动 */
.master-cats .mc-item .mc-main { flex: 1; min-width: 0; display: flex; align-items: center; gap: 8px; }
.master-cats .mc-item .mc-code { flex: none; font-size: 11px; font-weight: 600; color: var(--muted); font-variant-numeric: tabular-nums; letter-spacing: .3px; }
.master-cats .mc-item .mc-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.master-cats .mc-item.active .mc-code { color: var(--primary); }
/* ============ 2026-11-11（用户指令「三级菜单按二级菜单方式处理展示」）============
   词典分类原为「分组标题 + 全部条目平铺」的单列长列表（9 个分组 / 17 本字典，需长滚动、
   条目名被省略号截断）。现改为两级：栏内只列**分组父项**（名称 + 条目数 + 展开箭头），
   点父项后在**同一框线内**缩进展开该组字典条目（四级菜单同理按此规则，见 .mc-sub）。
   ⚠ 纯展示层改造：masterData.cur 仍是字典名（store.master 第 0 列匹配键），零数据改动。 */
.master-cats .mc-parent {
  position: relative; display: flex; align-items: center; gap: 5px;
  /* 左内边距收窄到 4px 给展开箭头让位；字号 12px：栏内可用宽约 178px */
  padding: 8px 8px 8px 4px; border-radius: 7px; cursor: pointer;
  font-size: 12px; line-height: 1.45; color: #33465f;
  transition: background .12s, color .12s;
}
.master-cats .mc-parent:hover { background: #e3ecfd; }
.master-cats .mc-parent.active { background: #d3e3fd; color: var(--primary); font-weight: 600; }
/* 展开态：底色比选中态浅一档，避免与「当前字典所在组」的 active 打架 */
.master-cats .mc-parent.open { background: #e2ecfd; color: var(--primary); font-weight: 600; }
/* 选中组左侧竖条：沿用原条目选中态（.mc-item.active::before）的视觉语言 */
.master-cats .mc-parent.active::before {
  content: ''; position: absolute; left: 0; top: 50%; transform: translateY(-50%);
  width: 3px; height: 18px; border-radius: 0 3px 3px 0; background: var(--primary);
}
/* 展开箭头：收起时 ›，展开时旋转 90°（变成 ⌄）——与 Windows/金蝶的树控件同一语言 */
.master-cats .mc-caret {
  flex: none; width: 12px; text-align: center; font-size: 13px; line-height: 1;
  color: #8296b3; transition: transform .14s, color .12s;
}
.master-cats .mc-parent.open .mc-caret { transform: rotate(90deg); color: var(--primary); }
.master-cats .mc-pname { flex: 1; min-width: 0; }
.master-cats .mc-pnum { flex: none; font-size: 11px; color: var(--muted); font-variant-numeric: tabular-nums; }
.master-cats .mc-parent.active .mc-pnum,
.master-cats .mc-parent.open .mc-pnum { color: var(--primary); }
/* 四级菜单：字典条目在父项下方缩进展开，左侧细线连回父项（树形缩进线），仍在浅蓝框线之内。
   高字典名改为折行、不再省略号截断 —— 这正是当初窄栏最难看的地方。 */
.master-cats .mc-sub { display: none; margin: 2px 0 2px 10px; padding-left: 8px; border-left: 1px solid #c8d8f2; }
.master-cats .mc-sub.open { display: block; }
/* 名称折行时（合并项 S31+ 的名字最长）编号、行数都与名称首行对齐，不跟着垂直居中悬空 */
.master-cats .mc-sub .mc-item { padding: 6px 7px; font-size: 12px; border-radius: 6px; align-items: flex-start; }
.master-cats .mc-sub .mc-item .mc-main { gap: 8px; align-items: flex-start; }
.master-cats .mc-sub .mc-item .mc-code { min-width: 26px; padding-top: 1px; }
.master-cats .mc-sub .mc-item .mc-n { padding-top: 1px; margin-left: 6px; }
.master-cats .mc-sub .mc-item .mc-name { white-space: normal; overflow: visible; text-overflow: clip; line-height: 1.4; }
.master-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.master-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 8px; }
.master-title { font-size: 15px; font-weight: 600; }
.master-info { font-size: 12px; color: var(--muted); }
/* 2026-10-13：标题行内的计数片（S11 总成数）。样式对齐 T1 顶部看板的「.stats-bar .stat」计数片
   （注：.stat 是 .stats-bar 作用域内的规则，标题行里直接用不生效，故单列一类）。 */
.head-stat { font-size: 12px; padding: 3px 8px; border-radius: 14px; background: var(--head-bg); color: var(--ink); white-space: nowrap; }
.head-stat b { font-size: 13px; }
.master-tools { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.master-tools .inline-msg { margin-top: 0; }
/* 2026-10-14：S11 工具行上移一行并入标题行；同日再改：搜索框＋新增总成在页面水平居中 */
.master-head.has-tools { align-items: center; flex-wrap: wrap; position: relative; }
.master-head .head-tools { position: absolute; left: 50%; transform: translateX(-50%); align-self: center; }
.master-table { overflow: auto; border: 1px solid var(--line); border-radius: 8px; max-height: 46vh; }
.master-table table { border-collapse: collapse; width: 100%; font-size: 13px; }
.master-table th, .master-table td { border: 1px solid var(--line); padding: 3px 5px; }
.master-table thead th { background: var(--head-bg); position: sticky; top: 0; z-index: 1; }
/* 最左「#」自动序号列（2026-10-14，替代原「编码」列）：常驻，不随横向滚动移出视野 */
.master-table th.md-i, .master-table td.md-i { position: sticky; left: 0; z-index: 2; text-align: center; color: var(--muted); font-family: Consolas, monospace; background: #fff; }
.master-table thead th.md-i { background: var(--head-bg); z-index: 3; }
.master-table tr.draft td.md-i { background: #fffbe9; }
.master-table input[type=text] { width: 100%; border: 1px solid transparent; background: transparent; padding: 4px 5px; font-size: 13px; border-radius: 4px; color: var(--ink); }
.master-table input[type=text]:hover { border-color: var(--line); }
.master-table input[type=text]:focus { outline: none; border-color: var(--primary); background: #fff; }
/* 2026-10-14：「合格标准」列改用**自适应多行文本框**（td.md-multi > textarea）。
   高度由 app.js 的 mdAutoSize() 按内容实时写入（渲染后 + 每次输入），故这里 overflow:hidden；
   同时给出手动兜底 resize:vertical。line-height/字体与单行输入框保持一致，视觉上仍是一张表。 */
.master-table td.md-multi { vertical-align: top; padding: 3px 5px; }
.master-table td.md-multi textarea {
  display: block; width: 100%; box-sizing: border-box;
  border: 1px solid transparent; background: transparent; border-radius: 4px;
  padding: 4px 5px; font: inherit; font-size: 13px; line-height: 1.5; color: var(--ink);
  resize: vertical; overflow: hidden; min-height: 28px;
  white-space: pre-wrap; word-break: break-word;
}
.master-table td.md-multi textarea:hover { border-color: var(--line); }
.master-table td.md-multi textarea:focus { outline: none; border-color: var(--primary); background: #fff; }
.master-table tr.off { opacity: .5; }
.master-table tr.draft td { background: #fffbe9; }
/* 2026-10-19（S21–S25 合并表）：「字典」列下拉——行内切换该行归属的字典 */
.master-table td.md-selwrap { padding: 3px 5px; }
.master-table .md-sel {
  width: 100%; box-sizing: border-box; padding: 4px 6px; font: inherit; font-size: 13px;
  color: var(--ink); background: #fff; border: 1px solid var(--line); border-radius: 5px; cursor: pointer;
}
.master-table .md-sel:hover { border-color: #c9d6e8; }
.master-table .md-sel:focus { outline: none; border-color: var(--primary); }
/* 2026-10-19 二次：「字典」列改为只读显示（不再允许改归属），淡底 + 常规字重，与可编辑列区分 */
.master-table td.md-ro { background: #f7f9fc; color: #48586e; font-size: 13px; white-space: nowrap; }
.master-table tr.off td.md-ro { background: #f7f9fc; }
/* 2026-10-19 三次（用户指令「S21-S25：接受部门等仅一行」）：同一字典的行用 rowspan 合并，
   组名竖向居中显示；组与组之间加一道略深的分隔线，便于一眼看出分块。 */
.master-table td.md-ro[rowspan] {
  vertical-align: middle; font-weight: 600; color: #33475b;
  border-top: 2px solid #d8e4f7; padding-left: 8px;
}
/* 2026-10-19 八次（用户指令「字典后面全部加上使用表单，如：接受部门T3」）：
   「字典」列名后跟一枚浅蓝小标签，标出使用表单（T3 / T4/T5 / S11 …）。 */
.master-table td.md-ro .md-dict-use {
  display: inline-block; margin-left: 6px; padding: 0 5px;
  font-size: 11px; font-weight: 600; line-height: 16px;
  color: #4b6c9c; background: #e3ecfd; border: 1px solid #cfdcf3; border-radius: 4px;
  font-variant-numeric: tabular-nums; letter-spacing: .2px;
}
.master-table .mt-op { white-space: nowrap; text-align: center; }
.master-table .mt-op span { color: var(--red); cursor: pointer; font-size: 12px; }
.master-table .mt-op span:hover { text-decoration: underline; }
.master-note { margin-top: 10px; margin-bottom: 0; }

/* ---------- 基础设置 · 物料主数据（P3A，2026-10-11）---------- */
.mat-tools { display: flex; align-items: center; gap: 8px; margin: 10px 0 8px; flex-wrap: wrap; }
.mat-search { width: 240px; padding: 6px 10px; border: 1px solid var(--line); border-radius: 6px; font-size: 13px; font-family: inherit; color: var(--ink); }
.mat-search:focus { outline: none; border-color: var(--primary); }
.mat-sel { padding: 6px 8px; border: 1px solid var(--line); border-radius: 6px; font-size: 13px; font-family: inherit; background: #fff; color: var(--ink); max-width: 190px; }
.mat-tools .inline-msg { margin-top: 0; }
.mat-count { font-size: 12px; color: var(--muted); margin-bottom: 6px; }
.mat-table { overflow: auto; border: 1px solid var(--line); border-radius: 8px; max-height: 54vh; }
.mat-table table { border-collapse: collapse; width: max-content; min-width: 100%; font-size: 12px; }
.mat-table th, .mat-table td { border: 1px solid var(--line); padding: 2px 4px; white-space: nowrap; }
.mat-table thead th { background: var(--head-bg); position: sticky; top: 0; z-index: 2; font-weight: 600; }
.mat-table th.mat-wide { min-width: 240px; }
.mat-table .mat-op-th { position: sticky; left: 44px; z-index: 3; }   /* 左距让位给最左侧 # 序号列 */
.mat-table td.mt-op { position: sticky; left: 44px; background: #fff; z-index: 1; }
.mat-table tr.draft td { background: #fffbe9; }
.mat-table tr.draft td.mt-op { background: #fffbe9; }
/* 最左侧 # 序号列（2026-10-13 用户要求：S11 总成主表 / S12 物料主数据 均加）——sticky 常驻，横向滚动不丢行号 */
.mat-table th.row-num { position: sticky; left: 0; z-index: 3; }
.mat-table td.row-num { position: sticky; left: 0; background: #fff; z-index: 1; text-align: center; color: var(--muted); font-variant-numeric: tabular-nums; }
.mat-table tr.draft td.row-num { background: #fffbe9; }
.mat-table tr.off td { opacity: .55; }
.mat-table input[type=text] { width: 100%; border: 1px solid transparent; background: transparent; padding: 3px 4px; font-size: 12px; border-radius: 4px; color: var(--ink); font-family: inherit; }
.mat-table input[type=text]:hover { border-color: var(--line); }
.mat-table input[type=text]:focus { outline: none; border-color: var(--primary); background: #fff; }
.mat-table select { border: 1px solid transparent; background: transparent; font-size: 12px; font-family: inherit; color: var(--ink); }
.mat-table select:focus { outline: none; border-color: var(--primary); }
.mat-table .mt-op { white-space: nowrap; text-align: center; }
.mat-table .mt-op span { color: var(--red); cursor: pointer; font-size: 12px; }
.mat-table .mt-op span:hover { text-decoration: underline; }
.mat-table .mat-used { color: #1a7f37; font-weight: 600; text-align: center; white-space: nowrap; }
.mat-table .mat-unused { color: #9aa5b1; text-align: center; white-space: nowrap; }
.mat-table td.mat-eff { font-family: Consolas, monospace; white-space: nowrap; font-weight: 600; color: var(--primary); }
.mat-table td.mat-eff.mat-eff-active { color: #0f6e56; background: #e6f7f1; }
.user-op { color: var(--red); font-size: 12px; margin-left: 8px; cursor: pointer; }
.user-op:hover { text-decoration: underline; }

/* ---------- 图片缩放查看（灯箱） ---------- */
#img-zoom { position: fixed; inset: 0; z-index: 9999; background: rgba(15,20,28,.88); display: flex; align-items: center; justify-content: center; }
#img-zoom.hidden { display: none; }
.iz-bar { position: absolute; top: 14px; left: 50%; transform: translateX(-50%); display: flex; align-items: center; gap: 8px; z-index: 2; background: rgba(0,0,0,.35); padding: 6px 10px; border-radius: 999px; }
.iz-btn { min-width: 30px; height: 30px; padding: 0 10px; border: 1px solid rgba(255,255,255,.35); background: rgba(255,255,255,.12); color: #fff; font-size: 15px; line-height: 1; border-radius: 999px; cursor: pointer; font-family: inherit; }
.iz-btn:hover { background: rgba(255,255,255,.28); }
.iz-scale { color: #fff; font-size: 13px; min-width: 46px; text-align: center; }
.iz-stage { width: 100%; height: 100%; overflow: hidden; display: flex; align-items: center; justify-content: center; cursor: grab; }
.iz-stage:active { cursor: grabbing; }
/* 2026-11-11：宽高由 JS 按「原图像素 × 缩放比」直接写入，故这里不能再限 max-width/max-height
   （max-* 会压掉内联 width，放大就失效）；也不再做 transition，否则每次缩放都在动画插值。 */
.iz-img { display: block; max-width: none; max-height: none; transform-origin: center center; image-rendering: auto; user-select: none; -webkit-user-drag: none; }
/* 「锐利」：nearest 采样，放大小字与线稿边缘硬朗（默认关闭，点按钮切换） */
.iz-btn.iz-on { background: rgba(255,255,255,.5); border-color: #fff; color: #10151c; font-weight: 700; }
.iz-title { position: absolute; bottom: 14px; left: 50%; transform: translateX(-50%); max-width: 90vw; color: #e8edf3; font-size: 12px; background: rgba(0,0,0,.4); padding: 4px 12px; border-radius: 999px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 图片列缩略图：限制行高、避免撑破表格，鼠标提示可放大 */
.data-table td.image-cell img.zoomable-img { max-height: 54px; max-width: 120px; width: auto; height: auto; border-radius: 4px; border: 1px solid var(--line); vertical-align: middle; }
.data-table td.image-cell img.zoomable-img:hover { border-color: var(--primary); }

/* ---------- 行表单弹窗（2026-10-10 弹窗表单改造） ----------
   表格改为只读展示，新增/编辑/查看统一走本弹窗；所有控件集中于此。
   宽度取 920px：t5 有 12 列，两列栅格下仍能一屏看全，较 .modal-box(760) 更从容。 */
.modal-box-xl { width: 920px; max-width: 94vw; max-height: 90vh; }
.modal-foot { display: flex; justify-content: flex-end; gap: 8px; padding: 14px 20px; border-top: 1px solid var(--line); flex-wrap: wrap; }
.rf-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px 18px; }
.rf-field { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.rf-field.rf-wide { grid-column: 1 / -1; }
.rf-label { font-size: 12px; color: var(--muted); }

/* ================= 通用弹窗版式：单据表格（2026-10-10） =================
   用户要求：T1–T4/T6/T7 的弹窗「全部以表格形式展示」。整张带框表格、左格写列名（浅灰底）、
   右格填值；每行 3 组「标签+值」（合计 6 个物理列），长文本 / 附件列独占一整行（跨满 6 列）。
   观感与 T5 的自定义 sheet 一致（T5 版式按要求本次不动）。
   结构由 app.js 的 rfSheetHtml() 生成；值格内仍包 .rf-field[data-field=ci]（联动重绘依赖它）。 */
.rf-sheet-fields { display: block; }   /* 覆盖 .rf-grid 的两列栅格，让整张单据表格占满宽度 */
.rf-sheet { width: 100%; border-collapse: collapse; table-layout: fixed; }
/* T3 底部签署区（2026-10-10 用户要求「最后两行字段水平均布」）：主表用非等宽栅格（数量格减半等），
   签署区改用**等宽**栅格，两者无法共用一张表 → 签署区另起一张同宽小表，靠相邻选择器拼成一张：
   上边距 -1px 抵消两条相邻边框（否则中间会出现 2px 双线）。 */
.rf-sheet + .rf-sheet { margin-top: -1px; }
.rf-sheet td { border: 1px solid #8a97a8; padding: 5px 8px; font-size: 13px; vertical-align: middle; }
/* 2026-10-19（用户「文字打印齐全」）：标签格不再用 ellipsis 吞字。
   旧：white-space:nowrap + overflow:hidden + text-overflow:ellipsis → A4 打印下
   「更改实施日期」等 6 字标签被截成「更改实施…」。改为**允许换行**（宁可两行，不可吞字），
   配合 app.js rfLabelWeight 系数上调（0.09→0.105），常见 6 字标签仍能单行放下。 */
.rf-sheet .rf-l { background: #eef2f7; color: var(--ink); font-weight: 600; text-align: center; white-space: normal; word-break: break-word; line-height: 1.25; overflow: visible; text-overflow: clip; }
.rf-sheet .rf-v { background: #fff; }
/* 空白签署格标签（2026-10-10，T3 审核后签署栏）：「质量技术部分管领导」「生产管理部分管领导」
   为 8 字标签，13% 标签列（≈114px）放不下时**允许换行**——绝不能走 .rf-l 默认的
   nowrap+ellipsis（会吞字）；字号略降以尽量单行放下。 */
.rf-sheet .rf-l.wr { white-space: normal; font-size: 12px; line-height: 1.25; word-break: break-all; }
/* 2026-10-28 用户指令（G8 工程变更工作台）：弹窗末尾「会签」整行（线下签署占位，不入库）。
   整行拉通全宽、行高 3 行（≈4.6em）；空值格无内容也保持高度，便于打印后手写会签。 */
.rf-sheet.rf-countersign .rf-v { height: 9.2em; min-height: 9.2em; }
/* 2026-10-28 G8：弹窗末尾「附件」整行（可上传，线对齐，保存后其余字段锁只读）
   2026-10-28 追加：附件只在「批准流程完成」后可录入 —— 批准前该格只读并给出提示。 */
.rf-sheet.rf-attach-row .rf-v { min-height: 4.6em; }
.rf-hint-lock { margin-top: 2px; font-size: 12px; color: #9aa7b6; }
/* 2026-10-28（用户指令）G8「发至」：字典「接受部门」多选勾选组（存「、」连接串）。
   行内可换行、自动撑高；打印时不换行控件被浏览器美化，勾选框仍可见。 */
.rf-chkgroup { display: flex; flex-wrap: wrap; gap: 2px 12px; padding: 2px 0; line-height: 1.6; }
.rf-chk { display: inline-flex; align-items: center; gap: 4px; font-size: 13px; cursor: pointer; white-space: nowrap; color: var(--ink); }
.rf-chk input[type=checkbox] { margin: 0; cursor: pointer; }
.rf-chkgroup .rf-chk-empty, .rf-chkgroup.rf-chk-empty { font-size: 12px; color: #9aa7b6; }
/* 弹窗编号行（2026-10-10 用户要求：位置与格式**完全参考 T5**）：
   表格**之外**、表格上方、右对齐、**无表格线**；样式与 .t5-code 合并定义（见下方 .t5-code, .rf-code）。 */
/* sheet 内控件去边框，随单元格走 */
.rf-sheet .rf-field { gap: 0; }
.rf-sheet .rf-input { border: none; border-radius: 0; background: transparent; padding: 2px 1px; }
.rf-sheet .rf-input:focus { border: none; box-shadow: none; background: #fbfdff; }
.rf-sheet .rf-input:disabled { background: transparent; color: var(--ink); }
.rf-sheet .rf-textarea { resize: vertical; }
/* 查看态（只读）：单元格内文字与附件图片的排版；图片限高，避免把表格行撑得过高（点击仍可放大） */
.rf-sheet .rf-static { min-height: 0; line-height: 1.35; word-break: break-word; }
/* 表格内的「编号」格（2026-10-20 S5：编号与「出厂编号」位置互换）：
   只读纯文本，无输入框、无底色 —— 与其它值格视觉一致，仅字重略加，便于一眼识别单据号。 */
.rf-sheet .rf-codeval { font-weight: 600; letter-spacing: 0.02em; }
/* 系统自动戳（「制表」「审核」，2026-10-10）：只读、灰底虚线框，用户不可编辑（弹窗与 T5 共用） */
.rf-stamp {
  display: block; min-height: 24px; padding: 3px 8px; line-height: 18px;
  border: 1px dashed #c3cfdf; border-radius: 4px; background: #f2f5fa;
  color: #4a5b70; font-size: 13px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.rf-stamp-empty { color: #9aa7b8; }
/* 手写签名图片（2026-10-27 用户指令）：弹窗内把系统戳值「刘翔 2026-10-21」里的姓名
   渲染为签名图（public/sign/liuxiang.png，透明底），日期仍以文字跟在后面。
   只在弹窗显示层替换，列表 / store.json / 导出 Excel 保持文字不变。 */
.sign-img {
  height: 24px; width: auto; max-width: 140px;
  vertical-align: -7px; margin: 0 6px 0 0;
  user-select: none; -webkit-user-drag: none;
}
.sign-date { color: #4a5b70; font-size: 12px; white-space: nowrap; }
/* 指定人签署栏（2026-10-27，G4「质量技术部主管」）：
   未签时显示「点击签署」按钮（仅签署人本人可见），已签后与系统戳同样只读显示签名图。
   琥珀色边框用于一眼区分"系统自动戳"与"需要人签的这一栏"。 */
.rf-leadsign { border-color: #d9b06a; background: #fdf8ee; }
.rf-sign-btn {
  display: block; width: 100%; min-height: 24px; padding: 3px 8px; line-height: 18px;
  border: 1px dashed #d18b28; border-radius: 4px; background: #fff8ec;
  color: #a35c00; font-size: 13px; font-family: inherit; cursor: pointer;
}
.rf-sign-btn:hover { background: #ffefd6; border-color: #b9741c; }
/* 打印：未签的签署栏留空白格（供线下手签），不把按钮样式打出来 */
@media print {
  .rf-sign-btn { display: block; border: none; background: transparent; color: transparent; padding: 0; min-height: 20px; }
}
/* 打印：签名保持可辨识尺寸（A4 纸面上约 6mm 高） */
@media print { .sign-img { height: 22px; vertical-align: -6px; } }
.rf-sheet .rf-static img.zoomable-img {
  display: inline-block; max-height: 48px; max-width: 100%;
  margin: 2px 6px 2px 0; vertical-align: middle;
}
.rf-input {
  width: 100%; height: 34px; border: 1px solid var(--line); border-radius: 7px;
  padding: 0 10px; font-family: inherit; font-size: 13px; background: #fff; color: var(--ink);
}
.rf-input:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 2px rgba(30,100,220,.12); }
/* 2026-10-19（用户：「两处滚动条取消，在弹窗和打印完全显示」）：
   field-sizing:content 让 textarea **原生按内容定高**——弹窗缩放、列宽变化、图片插入导致的
   换行变化都会自动跟随，且不会因为 1–2px 取整误差冒出滚动条；overflow-y:hidden 保证不出现滚动条。
   不支持的浏览器由 app.js 的 rfAutoGrow() 兜底（逐次补差直到装下）。 */
textarea.rf-input, .rf-textarea {
  height: auto; min-height: 56px; padding: 8px 10px; line-height: 1.6; resize: vertical;
  field-sizing: content; overflow-y: hidden;
}
/* T5「不合格处置单」= 241×140mm 固定纸张、行高精确配平，保持原固定高度，不参与内容自适应 */
.t5-fields textarea, .t5-fields .rf-textarea { field-sizing: fixed; overflow-y: auto; }
.rf-input:disabled { background: #f4f6f9; color: #69738a; cursor: not-allowed; }
.rf-free { display: flex; flex-direction: column; gap: 6px; }
.rf-att { display: flex; flex-direction: column; gap: 6px; }
.rf-chips { display: flex; flex-wrap: wrap; gap: 5px; }
.rf-chip {
  display: inline-flex; align-items: center; gap: 4px; font-size: 12px; padding: 2px 8px;
  border: 1px solid var(--line); border-radius: 12px; background: #f7f9fc; color: var(--ink); max-width: 100%;
}
.rf-chip .att-ico { font-style: normal; font-weight: 700; font-size: 10px; color: var(--primary); }
.rf-chip .rf-chip-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; cursor: pointer; }
.rf-chip .rf-chip-name:hover { color: var(--primary); text-decoration: underline; }
.rf-chip .rf-chip-x { cursor: pointer; color: var(--muted); }
.rf-chip .rf-chip-x:hover { color: var(--red); }
/* 2026-10-19（用户要求「更改内容能否将图片插入并显示在弹窗中」）：
   编辑态也直接显示图片缩略图——多图自动换行，点击放大，右上角 × 移除（不占位到保存才生效）。 */
.rf-att .rf-thumbs { display: flex; flex-wrap: wrap; gap: 8px; margin: 2px 0 0; }
.rf-att .rf-thumb {
  position: relative; width: 132px; height: 96px; border: 1px solid var(--line);
  border-radius: 6px; overflow: hidden; background: #f7f9fc;
}
.rf-att .rf-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; cursor: zoom-in; }
.rf-att .rf-thumb:hover { border-color: var(--primary); }
.rf-att .rf-thumb-x {
  position: absolute; top: 3px; right: 3px; width: 18px; height: 18px; line-height: 17px;
  text-align: center; border-radius: 50%; background: rgba(0, 0, 0, .55); color: #fff;
  font-size: 13px; cursor: pointer;
}
.rf-att .rf-thumb-x:hover { background: var(--red); }
/* 2026-10-19（用户要求「更改内容增加两列图片输入窗口：变更前 / 变更后，图片横向排满」）：
   两列等宽并排；**图片之间、图片与框线之间零间隙**（gap/padding/border-radius 全清零），
   图片宽 100% 铺满整列、按原比例纵向紧密相接。 */
/* 多组对比：一组 = 变更前 + 变更后两列；组内零间隙，组与组之间 8px 便于区分（2026-10-19） */
.rf-att .rf-imggroups { display: flex; flex-direction: column; gap: 8px; margin-top: 6px; }
.rf-att .rf-imgcols { display: flex; gap: 0; margin: 0; align-items: stretch; }
.rf-att .rf-imgcol {
  flex: 1 1 0; min-width: 0; display: flex; flex-direction: column;
  border: 1px solid var(--line); background: #fff; padding: 0; border-radius: 0;
}
.rf-att .rf-imgcol + .rf-imgcol { border-left: 0; }   /* 相邻两列共用一条框线，不出现双线 */
.rf-att .rf-imgcol-h {
  display: flex; align-items: center; justify-content: space-between; gap: 6px;
  font-size: 12.5px; font-weight: 600; color: #33475b;
  margin: 0; padding: 4px 7px; border-bottom: 1px solid var(--line); background: #f7f9fc;
}
/* 列头标题可换行但按钮不换行（避免「＋ 图 片」被挤成竖排） */
.rf-att .rf-imgcol-h > span { min-width: 0; white-space: nowrap; }
.rf-att .rf-imgcol-add { flex: 0 0 auto; white-space: nowrap; }
.rf-att .rf-imgcol-add {
  font-size: 12px; color: var(--primary); background: #fff; border: 1px dashed var(--line);
  border-radius: 6px; padding: 1px 8px; cursor: pointer; font-weight: 400;
}
.rf-att .rf-imgcol-add:hover { border-color: var(--primary); background: #f4f8ff; }
.rf-att .rf-imgcol-b { display: flex; flex-direction: column; gap: 0; flex: 1 1 auto; }
/* 列内图：宽度铺满该列、高度按原比例，四周不留边、图与图之间不留缝 */
.rf-att .rf-imgcol-b .rf-thumb { width: 100%; height: auto; border: 0; border-radius: 0; background: #fff; }
/* 列内图：**不拉伸小图**——原生像素显示最清晰（2026-11-11 用户：放大后清晰度低）。
   原为 width:100%，426px 的截图会被拉到列宽、257px 的竖图更被放大 1.5 倍发虚；
   现改为 width:auto + max-width:100%（大图仍等比缩到列宽），小图保持原尺寸居中。 */
.rf-att .rf-imgcol-b .rf-thumb img { width: auto; max-width: 100%; height: auto; max-height: none; object-fit: contain; background: #fff; display: block; margin: 0 auto; }
.rf-att .rf-imgcol-empty { font-size: 12px; color: #9aa7b6; text-align: center; padding: 16px 0; }
/* 未加图时两列不占版面，只留一条入口按钮（点它才展开「变更前/变更后」两列） */
.rf-att .rf-imgopenbar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 6px; }
.rf-att .rf-imgopen {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 14px; font-size: 13px; font-weight: 500; color: var(--primary);
  background: #f7fbff; border: 1px dashed var(--primary); border-radius: 7px; cursor: pointer;
}
.rf-att .rf-imgopen:hover { background: #eef6ff; border-style: solid; }
.rf-att .rf-imgopen-tip { font-size: 12px; color: #8a97a8; }
/* 已展开时底部的「＋ 再加一组对比图片」入口 */
.rf-att .rf-imgmore { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 6px; }
.rf-att .rf-imgmore-btn {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 12px; font-size: 12.5px; color: var(--primary);
  background: #fff; border: 1px dashed var(--primary); border-radius: 6px; cursor: pointer;
}
.rf-att .rf-imgmore-btn:hover { background: #eef6ff; border-style: solid; }
.rf-att .rf-imgmore-tip { font-size: 12px; color: #8a97a8; }
/* 每组 = 两列图片 + 该组下方的文字框（2026-10-19 用户：「控件前后均可添加文字」）：
   组后文字框紧贴图片下方（margin-top:0），空框高度压到 38px，避免多组时把表单拉得太长。 */
.rf-att .rf-imgblock { display: block; }
.rf-att .rf-gap-ta { margin-top: 0; min-height: 38px; }
/* 只读态的两列（与编辑态同版式：零间隙） */
.rf-static .rf-imggroups { display: flex; flex-direction: column; gap: 8px; margin: 6px 0; }
.rf-static .rf-imgblock { display: block; }
.rf-static .rf-ro-text-after { margin-top: 6px; }
.rf-static .rf-imgcols { display: flex; gap: 0; margin: 0; align-items: stretch; }
.rf-static .rf-imgcol {
  flex: 1 1 0; min-width: 0; display: flex; flex-direction: column;
  border: 1px solid var(--line); border-radius: 0; background: #fff; padding: 0;
}
.rf-static .rf-imgcol + .rf-imgcol { border-left: 0; }
.rf-static .rf-imgcol-h {
  font-size: 12.5px; font-weight: 600; color: #33475b;
  margin: 0; padding: 4px 7px; border-bottom: 1px solid var(--line); background: #f7f9fc;
}
.rf-static .rf-imgcol-b { display: flex; flex-direction: column; gap: 0; }
.rf-static .rf-imgcol-b .rf-thumb { width: 100%; height: auto; overflow: hidden; border-radius: 0; }
.rf-static .rf-imgcol-b .rf-thumb img { width: 100%; height: auto; max-height: none; object-fit: contain; background: #fff; display: block; }
.rf-static .rf-imgcol-empty { font-size: 12px; color: #9aa7b6; text-align: center; padding: 16px 0; }
/* 2026-11-12（用户截图：G3 已批准表单被一张图撑满）——
   对比图本来是「变更前 / 变更后」两列并排，各占半宽，高度自然受控；
   但很多记录只有一侧有图（常见：仅【变更后】），此时整列独占全宽，图片按原比例铺满，
   一张 A4 图纸就把弹窗顶到只剩图、其余字段全被推出屏外。
   故：**只有一列时**限制显示高度（宽度仍受 max-width:100% 约束、居中留白），
   看细节点图放灯箱到 1:1（app.js izUpscale），打印不受影响（@media print 里 max-height 仍为 none）。 */
.rf-att .rf-imgcol:only-child .rf-imgcol-b .rf-thumb img,
.rf-static .rf-imgcol:only-child .rf-imgcol-b .rf-thumb img {
  max-height: 360px; width: auto; max-width: 100%; margin: 0 auto;
}
.rf-addatt {
  align-self: flex-start; font-size: 12px; color: var(--primary); background: none;
  border: 1px dashed var(--line); border-radius: 7px; padding: 4px 10px; cursor: pointer;
}
.rf-addatt:hover { border-color: var(--primary); background: #f4f8ff; }
.rf-status {
  display: flex; flex-wrap: wrap; gap: 10px; align-items: center; font-size: 12.5px;
  background: #f7f9fc; border: 1px solid var(--line); border-radius: 8px; padding: 9px 12px; margin-bottom: 14px;
}
.rf-status .rf-st-item { color: var(--muted); }
.rf-status .rf-st-item b { color: var(--ink); }
/* 状态条最前的「第 N 行」（由标题栏下移而来，2026-10-10）：加深、加分隔线，与后续信息区分 */
.rf-status .rf-st-rowno { color: var(--ink); font-weight: 600; padding-right: 10px; border-right: 1px solid var(--line); }
/* 弹窗状态条右侧的「编号」（系统自动生成、只读）：右对齐、等宽数字、独立底色 */
.rf-st-code { margin-left: auto; padding: 3px 11px; border: 1px solid var(--line); border-radius: 6px; background: #fff; color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
.rf-st-code b { color: var(--primary); font-weight: 600; }
/* 列表中「编号」列：宽度贴合 T1-20261010-01（约13字符），不等宽拉伸 */
.col-code { min-width: 132px; white-space: nowrap; font-variant-numeric: tabular-nums; }
.rf-note-wrap { margin-top: 14px; display: flex; flex-direction: column; gap: 5px; }
@media (max-width: 760px) { .rf-grid { grid-template-columns: 1fr; } }

/* 弹窗页脚：左侧放破坏性/流转动作，右侧放取消与保存，避免误点 */
/* 弹窗页脚：左 = 破坏性/流转动作，中 = T1–T6 的「T0 计量确认/维修/变更记录」，右 = 取消与保存。
   2026-11-05（用户指令「把『记录』按钮放在弹窗底部中心」）：**仅含中间按钮时**（.has-c）三栏等分，
   左右各 flex:1 ⇒ 中间恒在正中；其它表页脚完全维持原样（L 自适应 + R 靠右），不受影响。
   ⚠ 元素上只有 id（#rf-foot）与 class="modal-foot"，没有 rf-foot 类 —— 选择器必须用 #rf-foot，
     写成 .rf-foot 会静默失效（中间按钮会被推左 87px）。 */
#rf-foot { justify-content: space-between; align-items: center; }
#rf-foot .rf-foot-l, #rf-foot .rf-foot-r { display: flex; gap: 8px; flex-wrap: wrap; }
#rf-foot .rf-foot-r { margin-left: auto; }
#rf-foot.has-c .rf-foot-l, #rf-foot.has-c .rf-foot-r { flex: 1 1 0; min-width: 0; }
#rf-foot.has-c .rf-foot-r { justify-content: flex-end; margin-left: 0; }
#rf-foot .rf-foot-c { display: flex; justify-content: center; gap: 8px; flex: 0 0 auto; padding: 0 10px; }
/* 页脚中心的「T0 计量确认/维修/变更记录」按钮：沿用页脚按钮尺寸，蓝字浅底以便与灰/白按钮区分 */
/* 2026-11-05（用户指令「按钮底色改为红色」）：红底白字，与页脚其它灰/白按钮区分开，一眼可见。
   悬停加深一档；禁用（未勾选计量类型）时降透明度但仍是红色，保持「这是主导操作」的视觉提示。 */
/* 2026-11-08 二次（用户指令「参照截图的位置、颜色，逻辑不变」）：G5 过程检验台账的
   「不合格工作台」按钮（.rf-g6foot）搬到同一位置、套同一套配色，故共用下列四条规则，
   仅各自靠 data 属性绑定各自的点击逻辑。 */
.rf-t0foot, .rf-g6foot {
  border: 1px solid #a83226; background: #d0392b; color: #fff; border-radius: 7px;
  padding: 7px 16px; font-size: 13px; cursor: pointer; white-space: nowrap;
}
.rf-t0foot:hover:not(:disabled), .rf-g6foot:hover:not(:disabled) { background: #b7301f; border-color: #8f2418; }
.rf-t0foot:active:not(:disabled), .rf-g6foot:active:not(:disabled) { background: #9c2618; }
.rf-t0foot:disabled, .rf-g6foot:disabled { opacity: .45; cursor: not-allowed; }
/* T5 打印提示：仅屏幕显示（#rf-foot 在 @media print 中整体 display:none，不会打印出来） */
.rf-print-hint { font-size: 12px; color: var(--muted); align-self: center; padding-left: 4px; line-height: 1.4; }
/* 打印表头（单据名称）：**仅打印时显示**，屏幕上 display:none 不占位。
   2026-10-10 用户要求：T3 打印表头 =「生产任务单（质量技术部）」（见 app.js 的 PRINT_TITLE）。 */
.rf-print-title { display: none; }

/* 只读查看模式：以静态文本呈现，保持与表格一致的阅读观感 */
.rf-static {
  font-size: 13px; line-height: 1.65; white-space: pre-wrap; word-break: break-word;
  background: #f7f9fc; border: 1px solid var(--line); border-radius: 7px;
  padding: 8px 10px; min-height: 36px;
}
.rf-static.rf-empty { color: var(--muted); }
.rf-static img.zoomable-img { max-width: 100%; max-height: 260px; border-radius: 6px; cursor: zoom-in; display: block; margin-top: 6px; }
.rf-ro-text { margin-bottom: 4px; }
.rf-hint { font-size: 11.5px; color: var(--muted); line-height: 1.5; }
/* ===== 有效期预警（2026-10-28）=====
   规则来自各表 config.expiry（哪一列、提前多少天），此处只管表现：
   已过期 = 红底加粗；临期 = 橙底；阈值由台账自己定，故不写死任何天数。 */
.cell.exp-cell { font-variant-numeric: tabular-nums; }
.cell.exp-expired { background: #fdeaea !important; color: #b3261e !important; font-weight: 600; }
.cell.exp-soon { background: #fff5da !important; color: #8a5a00 !important; }
.th-exp { margin-left: 3px; font-size: 11px; opacity: .8; cursor: help; }
.rf-exp-hint { margin-top: 4px; font-size: 11.5px; line-height: 1.5; color: var(--muted); }
.rf-exp-hint.exp-expired { color: #b3261e; font-weight: 600; }
.rf-exp-hint.exp-soon { color: #8a5a00; }

/* ---------- 2026-10-28：T1「校准/检定/年审」行的派生格与记录按钮 ----------
   时间格是从 T0 汇总出来的只读值（不落库）；2026-10-28 二次调整后按钮**常显常可点**
   （不再依赖"先勾选活动类型"）。打印件上按钮没有意义 → 隐藏按钮、改印一行「见 T0 记录表」。 */
.rf-t0last {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 6px;
  font-variant-numeric: tabular-nums;
  /* 值列仅 12%（≈89px）：压缩内边距，让「2019.12.25 + 1 条」尽量一行放下，放不下就折行 */
  padding: 2px 5px; border-color: #e3e9f2;
}
.rf-t0last .rf-t0cnt { font-size: 10.5px; color: var(--muted); }
.rf-t0btn {
  font-size: 12.5px; padding: 4px 8px; border: 1px solid #b9c4d2; background: #f4f7fb;
  color: #23527c; border-radius: 6px; cursor: pointer; white-space: nowrap;
}
.rf-t0btn:hover:not(:disabled) { background: #e8f0fa; border-color: #8fa9c6; }
.rf-t0btn:disabled, .rf-t0btn.is-off { opacity: .5; cursor: not-allowed; }
/* 打印替代文字：屏幕上不占位，打印时顶替按钮（否则该格空白） */
.rf-t0btn-print { display: none; font-size: 11.5px; color: #4a5b70; }
/* 未勾选「校准/检定/年审」时，周期格渲染成静态文本（仅显示、不可编辑）——淡色提示"待启用" */
.rf-sheet .rf-t0-locked { color: #9aa7b8; }
/* T1「校准/检定/年审」勾选组：值列宽约 20%（≈150px），三项横排略挤 → 字号与间距略收，
   仍允许折行（flex-wrap），不会撑破单元格。 */
.rf-chkgroup.rf-chkgroup-tight { gap: 0 8px; line-height: 1.5; }
.rf-chkgroup.rf-chkgroup-tight .rf-chk { font-size: 12.5px; gap: 3px; }
/* 2026-10-28（用户指令「只允许单选」）：单选勾选组 —— 外观仍是方块勾选（与多选一致，用户要的"打勾控件"），
   只是同组互斥，故不加额外装饰；仅在悬停时用手型提示"可点选/可取消"。 */
.rf-chkgroup.rf-chkgroup-single .rf-chk:hover .rf-chk-txt { color: #1c4e9c; }
/* 选「维修」时的周期格：在普通锁定（灰字）基础上加浅底，区分「维修不设周期」与「还没勾类型」两种情况。 */
.rf-sheet .rf-t0-locked.rf-t0-nocyc { color: #a8b3c2; background: #f7f8fa; }
/* 2026-11-04：计量块新增「下次计量确认日期」派生格（值取 T0 同名列）。
   与「上次日期」同款只读样式；已超期标红、临期标橙，和列表里的到期预警同口径。 */
.rf-t0last.rf-t0next-late { color: var(--red); font-weight: 600; }
.rf-t0last.rf-t0next-soon { color: #8a5a00; font-weight: 600; }

@media print {
  .rf-t0btn { display: none !important; }
  .rf-t0btn-print { display: inline; }
}
.rf-req { color: var(--red); }
.rf-other { margin-top: 6px; }
.rf-input.rf-invalid { border-color: var(--red); box-shadow: 0 0 0 2px rgba(190,60,60,.12); }
/* 2026-11-06（用户指令「G1 弹窗：设置状态为必选项」）：必填列标签后红星 + 未填时红框 */
.rf-req { color: var(--red); font-weight: 700; margin-left: 2px; font-size: 13px; line-height: 1; }
.rf-field.rf-req-miss .rf-input { border-color: var(--red); box-shadow: 0 0 0 2px rgba(190,60,60,.18); }
.rf-field.rf-req-miss .rf-input:focus { border-color: var(--red); }
@media print { .rf-req { color: #000; } }
.rf-lockbox { font-size: 13px; background: #eef1f5; color: #69738a; border: 1px solid var(--line); border-radius: 7px; padding: 8px 10px; }
/* 只读派生列（2026-10-14 用户要求，T6 弹窗「合格标准」）：
   值来自「S2 基础数据 → 材料」的对应材料，**只读、不可编辑**（无输入控件）。
   观感与查看态静态格一致，文字保留原换行、自动换行不截断。 */
.rf-ro-std {
  font-size: 13px; line-height: 1.6; white-space: pre-wrap; word-break: break-word;
  background: #f7f9fc; border: 1px solid var(--line); border-radius: 7px;
  padding: 8px 10px; color: var(--ink);
}
.chk-inline { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--muted); }

/* ---------- 弹窗层级（2026-10-10 弹窗表单改造）----------
   .modal 默认 z-index:50，同层级下按 DOM 顺序叠放。行表单弹窗在文档流靠后，
   会盖住通用对话框（提示/确认/输入）与附件弹窗 —— 表现为"点了按钮没反应"。
   这里显式定义叠放次序：行表单 < 附件 < 附件查看 < 行菜单 < 通用对话框。 */
#row-form-modal { z-index: 60; }
#ins-modal { z-index: 70; }
#att-modal { z-index: 80; }
#rowmenu { z-index: 90; }
#dlg { z-index: 100; }   /* 通用对话框永远在最上层（行表单内也会用到） */
#admin-modal, #validate-modal, #audit-modal { z-index: 55; }
/* S11 总成编辑弹窗 / 明细行编辑弹窗均由「基础设置」(55) 内点行唤起，必须叠在其上，
   否则保存/取消按钮被下层表格挡住 —— 现象同样是"点了没反应"（实测 elementFromPoint 命中下层 TD）。
   取 65：高于 55/60，低于附件 70。 */
#asm-edit-modal, #bom-edit-modal { z-index: 65; }

/* 两条顶部横幅同时出现时（打开方式不对 + 服务端未重启）不重叠 */
#origin-warn ~ #stale-warn { top: 84px; }

/* 「服务端未重启」提示：贴底显示，避免遮住顶部工具栏（否则会挡住「新增表单」等按钮） */
.stale-warn {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 999;
  background: #fdf3e2; color: #7a4a12; border-top: 1px solid #f0d9b0;
  padding: 12px 56px 12px 18px; font-size: 14px; line-height: 1.75;
  box-shadow: 0 -4px 14px rgba(0,0,0,.10);
}
.stale-warn code { background: rgba(0,0,0,.06); padding: 1px 5px; border-radius: 4px; }
.stale-warn .stale-x {
  position: absolute; right: 14px; top: 10px; border: none; background: transparent;
  font-size: 20px; line-height: 1; color: #a3763f; cursor: pointer;
}

/* 只读表格：整行可点（打开弹窗），但保留明确的可点语义 */
.data-table tbody tr[data-index] { cursor: pointer; }
.data-table tbody tr.row-locked { cursor: pointer; }

/* ================= T5「不合格处置单」弹窗版式（2026-10-10） =================
   严格照用户提供的图片排版：整张带框表格（标签列浅灰底、值列白底）、
   发现阶段/不合格原因/处置意见为勾选组，返工返修记录为小表，签署前为备注（原「质量问题图片」）。 */
.t5-fields { display: block; }   /* 覆盖 .rf-grid 的两列栅格，让整张 sheet 占满宽度 */
.t5-title { text-align: center; font-size: 18px; font-weight: 700; color: var(--ink); margin: 2px 0 14px; letter-spacing: 3px; }
/* 编号行：置于表格上方右侧、**无表格线**（2026-10-10）。
   `.t5-code` = T5 自定义 sheet；`.rf-code` = T1–T4/T6/T7 通用单据表格。
   两者**共用同一条规则**，确保全工作台编号位置与格式完全一致（用户要求）。 */
/* 2026-11-05（用户指令「T0 弹窗上部严格按 image 2 蓝色样式」）：编号行整体转蓝（标签+值均为 var(--primary)），
   与设备表顶部「记录编号：XXX」蓝字样式一致；值保留 600 字重做轻微强调。 */
.t5-code, .rf-code { text-align: right; font-size: 13px; color: var(--primary); margin: 0 0 2px; font-variant-numeric: tabular-nums; }
.t5-code b, .rf-code b { color: var(--primary); font-weight: 600; }
/* 2026-11-05（用户指令「T0 弹窗顶部左侧显示设备记录编号」）：T0 记录弹窗顶部行 = 左(设备记录编号) + 右(记录编号/校准编号) */
.rf-toprow { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; margin: 0 0 2px; }
.rf-devcode { text-align: left; font-size: 13px; color: var(--primary); font-variant-numeric: tabular-nums; }
.rf-devcode b { color: var(--primary); font-weight: 600; }
.t5-sheet { width: 100%; border-collapse: collapse; table-layout: fixed; }
.t5-sheet td { border: 1px solid #8a97a8; padding: 5px 8px; font-size: 13px; vertical-align: middle; }
.t5-sheet .t5-l { background: #eef2f7; color: var(--ink); font-weight: 600; text-align: center; white-space: nowrap; }
.t5-sheet .t5-v { background: #fff; }
.t5-sheet .t5-sec { background: #e6ebf2; font-weight: 700; text-align: center; color: var(--ink); }
.t5-sheet .t5-gridcell { padding: 0; }
/* sheet 内控件去边框，随单元格走 */
.t5-sheet .rf-field { gap: 0; }
.t5-sheet .rf-input { border: none; border-radius: 0; background: transparent; padding: 2px 1px; }
.t5-sheet .rf-input:focus { border: none; box-shadow: none; background: #fbfdff; }
.t5-sheet .rf-input:disabled { background: transparent; color: var(--ink); }

/* 勾选组（发现阶段 / 不合格原因 / 处置意见） */
.t5-chkgroup { display: flex; flex-direction: column; gap: 5px; }
.t5-chkrow { display: flex; flex-wrap: wrap; gap: 4px 18px; align-items: center; }
.t5-sub { font-size: 12.5px; font-weight: 600; color: var(--ink); margin-right: 2px; min-width: 44px; }
.t5-chk { display: inline-flex; align-items: center; gap: 4px; font-size: 13px; cursor: pointer; white-space: nowrap; color: var(--ink); }
.t5-chk input[type=checkbox] { margin: 0; cursor: pointer; }

/* 返工返修记录小表 */
.t5-gridwrap { width: 100%; }
.t5-grid { width: 100%; border-collapse: collapse; table-layout: fixed; }
.t5-grid th, .t5-grid td { border: 1px solid #8a97a8; padding: 3px 5px; font-size: 12.5px; text-align: center; }
.t5-grid th { background: #eef2f7; font-weight: 600; color: var(--ink); }
.t5-grid .t5-grid-in { border: none; border-radius: 0; background: transparent; padding: 3px 0; text-align: center; }
.t5-grid .t5-grid-in:focus { box-shadow: none; background: #fbfdff; }
.t5-sheet .t5-att-note { min-height: 38px; }
/* ---------- 「备注」行（原「质量问题图片」）：整行高度压到原来的约 1/3（2026-10-10 用户要求）----------
   原来该格是纵向堆叠：备注框（2 行，min-height 38px）+ 附件徽标 + 「添加图片/附件」按钮 ≈ 84px；
   现改为**单行横排**：备注框 1 行（24px）+ 附件徽标 + 紧凑按钮，整行 ≈ 28px（≈ 原来的 1/3）。
   附件入口保留（用户要求）；徽标多时在格内横向滚动，不撑高行。
   ⚠ 必须显式 min-height:0 —— 否则被上面的 .t5-sheet .t5-att-note{min-height:38px} 撑住。 */
.t5-sheet .t5-note-row > td { padding: 2px 8px; }
.t5-sheet .t5-note-row .rf-att { flex-direction: row; align-items: center; gap: 8px; }
.t5-sheet .t5-note-row .t5-att-note {
  flex: 1 1 auto; min-height: 0; height: 24px; padding: 2px 4px; line-height: 1.2; overflow: hidden;
}
.t5-sheet .t5-note-row .rf-chips { flex: 0 1 auto; flex-wrap: nowrap; overflow-x: auto; overflow-y: hidden; }
.t5-sheet .t5-note-row .rf-chip { flex: 0 0 auto; }
.t5-sheet .t5-note-row .rf-addatt { flex: 0 0 auto; align-self: center; padding: 1px 8px; font-size: 12px; white-space: nowrap; }
/* 查看态（只读）：附件图片在格内限高，保持该行仍是「一行」的高度；点击图片仍可放大查看 */
.t5-sheet .t5-note-row .rf-static { min-height: 0; padding: 3px 6px; line-height: 1.3; }
.t5-sheet .t5-note-row .rf-static img.zoomable-img { display: inline-block; max-height: 36px; margin: 0 0 0 6px; vertical-align: middle; }
/* ---------- 返工返修记录：条件显示 + 追加行（2026-10-10 用户要求） ----------
   整块（段题行 + 小表行）仅在「处置意见」勾选了「返工返修」时显示；
   隐藏用表级 .hide-rework 控制，两行**仍在 DOM 中占位**（打印 nth-child 序号不受影响）。 */
.t5-sheet.hide-rework .t5-rework-row { display: none; }
.t5-grid-add {
  margin: 3px 0 0; padding: 1px 8px; font-size: 12px; line-height: 1.6;
  border: 1px dashed #8a97a8; background: #f7fafd; color: #2f5597; border-radius: 3px; cursor: pointer;
}
.t5-grid-add:hover { background: #eef4fb; border-color: #2f5597; }

/* ---------- 打印：只输出行表单弹窗（用户要求 T5 弹窗可打印） ----------
   print 时给 body 挂 printing-form，仅显示 #row-form-modal，隐藏首页/表格等其余内容。 */
@media print {
  @page { size: A4 portrait; margin: 12mm; }
  /* 页码（2026-10-19 用户要求「每页设置页码，格式：页码/总页数」）：
     Chromium 131+ 支持 @page 页边距框 @bottom-center。单独写成一条无名 @page，
     即使某浏览器不支持该语法（整条被丢弃），也不会影响上面 A4/12mm 那条纸张设置。 */
  @page {
    @bottom-center {
      content: counter(page) "/" counter(pages);
      font-family: SimSun, "宋体", "Songti SC", serif;
      font-size: 9pt;
      color: #000;
      padding-top: 3mm;
      vertical-align: top;
    }
  }
  html, body { background: #fff !important; margin: 0 !important; padding: 0 !important; height: auto !important; overflow: visible !important; }
  body.printing-form > *:not(#row-form-modal) { display: none !important; }
  body.printing-form #row-form-modal {
    position: static !important; inset: auto !important; display: block !important;
    background: #fff !important; z-index: auto !important; padding: 0 !important; overflow: visible !important;
  }
  body.printing-form #row-form-modal .modal-box {
    width: 100% !important; max-width: none !important; max-height: none !important;
    border-radius: 0 !important; box-shadow: none !important; display: block !important; overflow: visible !important;
  }
  body.printing-form #row-form-modal .modal-body { overflow: visible !important; padding: 0 !important; }
  /* 交互性元素/界面外壳不打印：弹窗标题栏、关闭按钮、页脚动作按钮、加附件按钮、附件删除 ×、「＋追加一行」 */
  .modal-head, .modal-close, #rf-foot, .rf-addatt, .rf-imgcol-add, .rf-imgopenbar, .rf-imgmore, .rf-chip .rf-chip-x, .t5-grid-add { display: none !important; }
  /* 2026-10-10 用户要求：打印时不显示弹窗状态条（「第 N 行」「状态：未审核 草稿」）。
     T5 原先单独隐藏（见下方 body.print-t5 那条）；这里提到通用层，T1–T4/T6/T7 一并生效。 */
  #rf-status { display: none !important; }
  /* 2026-11-02 用户要求（G2 打印取消「审核 / 退回意见」）：
     该框是**审核人的系统操作区**（仅「待审核 + 当前用户是审核人」时出现），不属于纸质单据内容，
     打印时一并隐藏；通用层处理 ⇒ G/T 全部表打印都不再带出该框（此前各表都会印出来）。 */
  #rf-note-wrap { display: none !important; }
  /* 输入控件的 placeholder 提示（「YYYYMMDD，如…」「文字说明（可留空…）」等）不打印：
     Chromium 会把 placeholder 一并画进打印输出，故按打印媒体把颜色/填充置透明。 */
  .rf-input::placeholder, input::placeholder, textarea::placeholder {
    color: transparent !important; -webkit-text-fill-color: transparent !important; opacity: 0 !important;
  }
  /* 联动 / 字典等屏幕提示文字（.rf-hint）同属界面说明，不打印 */
  .rf-hint { display: none !important; }
  /* 2026-11-08（G11 反查）：被任务指令引用的反查条、以及「打开该记录」跳转入口都是界面导航，
     不属于纸质单据内容，打印时一并隐藏（否则会印在单据表头上方） */
  .rf-bk, .rf-bk-open { display: none !important; }
  /* 打印表头（单据名称）：屏幕隐藏，打印时居中置于表格上方（见 app.js 的 PRINT_TITLE） */
  .rf-print-title { display: block; text-align: center; font-size: 16pt; font-weight: 700; margin: 0 0 8px; letter-spacing: 1px; }
  /* 通用单据表格（T1–T4/T6/T7）打印：保留线框、压缩内边距、行不跨页断开 */
  .rf-sheet td { font-size: 9.5pt; padding: 3px 6px; }
  /* 2026-10-28 用户要求：打印时表格最外右边线必须落纸（会签行右缘曾整条缺失）。
     真因：本页全局是 box-sizing:border-box，表格 width:100% 时最外右框正好压在「页面可打印内容区的右边界」上，
        Chromium 打印栅格化按「向右/向下取整到页边」会把这条紧贴边界的 1px 外框舍去
        （左边框贴左边界却被保留——打印左右边缘的取舍不对称，是既有现象；屏幕预览看不出，只有实际打印/PDF 才丢）。
     ✅ 修复：打印时把表格宽度收窄 2px（width:calc(100% - 2px)），让最右竖线落进可打印区内部、不再压在边界上。
        所有 .rf-sheet 同宽收窄 ⇒ 各表竖线仍对齐；左侧不变、仅右侧内缩约 0.5mm，肉眼几乎无感。
       （此前误判为 content-box 溢出、加的 box-sizing:border-box 实为全局已有，无效，故保留但真正起作用的是 width 收窄。）
     ⚠ 特异性低于 .bpe-block .rf-sheet（零件属性区块），其 border:none 仍生效、不受此影响。
     ⚠ 打印对话框里「边距」请保持「默认」，不要再选「自定义边距」——那会叠加并可能把右边框重新挤出可打印区。 */
  .rf-sheet { border: 1px solid #8a97a8; box-sizing: border-box; width: calc(100% - 2px); }
  /* 2026-10-28（G8）：界面上「批准完成后方可添加附件」等提示属屏幕说明，不打印；
     「发至」的部门勾选组在纸上收紧间距与字号，避免把行撑高。 */
  .rf-hint-lock { display: none !important; }
  .rf-chkgroup { gap: 0 10px; line-height: 1.45; }
  .rf-chk { font-size: 9pt; }
  /* 签署格 8 字标签打印字号略降，配合 .wr 换行兜底，保证不截断 */
  .rf-sheet td.rf-l.wr { font-size: 8.5pt; }
  /* 编号行（表格上方右侧、无框）打印字号与表格正文一致 */
  .rf-code { font-size: 9.5pt; margin: 0 0 4px; }
  /* 2026-11-05（用户指令「T0 弹窗顶部左侧显示设备记录编号」）：打印时与右侧校准编号同字号 */
  .rf-toprow { display: flex; }
  .rf-devcode { font-size: 9.5pt; margin: 0 0 4px; }
  /* 系统自动戳在打印里去框去底，只留文字 */
  .rf-stamp { border: none; background: transparent; padding: 0; min-height: 0; }
  /* 2026-11-03（用户指令「打印时提示取消」）：「待岳婷签署 / 待刘翔签署」等**屏幕占位提示**
     属引导性文字，纸质单不应印出来（否则纸上多一行灰字、且不是手签）；打印时整块隐藏，
     单元格保留边框与高度（td 自身有高度），纸上即为空白格供线下手签。
     ⚠ 仅隐藏空占位（rf-stamp-empty）：已签的签名图（.rf-stamp 不带 empty）照常打印。 */
  .rf-stamp-empty { display: none !important; }
  /* 只读派生列「合格标准」（T6）：打印同样去框去底，只留文字，避免多色块影响单据观感 */
  .rf-ro-std { border: none; background: transparent; padding: 0; font-size: 9.5pt; line-height: 1.45; }
  .rf-sheet .rf-l { padding: 3px 4px; }
  /* T3 签署区（独立等宽小表 .rf-sign）：标签列宽 1/6，屏幕上装得下 9 字，但 A4 打印下
     「质量技术部分管领导」会被省略号吞字 → 打印字号降到 8.5pt（与签署格同档），
     并把标签左右内边距由 4px 压到 1px 换宽度（实测该格打印宽 ~110px，9 字 ×8.5pt≈102px），
     仍不行时允许换行兜底（宁可两行，不可吞字）。
     ⚠ 选择器必须用 `.rf-sheet.rf-sign td.rf-l`(0,3,1)：只写 `.rf-sign .rf-l`(0,2,0) 会被
       上面那条 `.rf-sheet .rf-l{padding:3px 4px}` 反超（同分时后写的赢）。 */
  .rf-sheet.rf-sign td.rf-l { font-size: 8pt; padding: 3px 1px; white-space: normal; line-height: 1.2; }
  .rf-sheet .rf-input { padding: 0 1px; }
  .rf-sheet .rf-field { gap: 0; }
  .rf-sheet tr { page-break-inside: avoid; break-inside: avoid; }
  /* 长行（含长文本 / 多张对比图）超过约半页高时允许跨页，避免「一行塞不下就整体溢出」；
     图片块自身仍 break-inside:avoid，不会把一张图切成两半。 */
  .rf-sheet tr.rf-breakable { page-break-inside: auto !important; break-inside: auto !important; }
  /* T5 的「不合格处置单」标题保留并作为打印标题 */
  .t5-title { font-size: 20px; margin: 0 0 12px; }
  /* ---------- T5 专用：打印纸张 241mm(宽) × 140mm(高) ----------
     2026-10-10：纸张改为「静态命名页」声明，不再依赖 printRowForm 动态注入的 <style>。
     命名页 @page t5page 的名称特异度高于无名 @page，故上面的 A4/12mm 不会作用到 T5 页；
     这样即使脚本时序/缓存问题导致动态注入失效，纸张与零边距依然成立（Ctrl+P 也生效）。
     140mm 高度有限 → 紧凑排版确保单页容纳；状态条不打印（编号已下移到表单顶部）。 */
  @page t5page { size: 241mm 140mm; margin: 0; }
  body.print-t5 .t5-fit { page: t5page; }
  body.print-t5 #rf-status { display: none !important; }
  /* @page margin:0 后纸张无边距，四边 10mm 留白改由内容内边距提供（用户要求 10mm）。
     ⚠ 不要在打印对话框里再选「自定义边距」——那会叠加成本页 10mm + 对话框值，看起来"过宽"。 */
  body.print-t5 .t5-fields { padding: 10mm; }
  /* 内容等比缩小（zoom）：仅仅压缩纵向（字号/行高/小表行高），表格宽度仍占满可用宽。
     2026-10-10 二次改版：第 2、3 行合并为一行后内容变矮，zoom 由 0.85 提到 0.90，
     使整单重新填满 241×140（下留白由 18mm 收回到 ~12mm，四边≈10~12mm）；实测 0.92 会翻第 2 页。
     ⚠ 不要用 width:calc(100%/zoom) 做宽度补偿——实测会把内容推到右侧贴纸边（右留白变 0）。 */
  body.print-t5 .t5-fit { zoom: 0.90; }
  /* ---------- 统一正文字号（2026-10-10）：T5 打印页除「表头/标题」外，所有文字一律 8pt ----------
     弹窗里 .t5-sheet td 与 .t5-grid td/th 本来就是同一字号（13px / 12.5px），只有字重不同；
     打印也必须如此——层级只用字重区分（标签 .t5-l、段题 .t5-sec、小表表头 th 加粗），
     不再出现 7.5pt / 9.5px / 12px 混排。 */
  body.print-t5 .t5-code { font-size: 8pt; margin: 0 0 1px; }
  body.print-t5 .t5-title { font-size: 14px; margin: 0 0 2px; letter-spacing: 1px; }
  body.print-t5 .t5-sheet td { font-size: 8pt; padding: 0 4px; line-height: 1.2; }
  body.print-t5 .t5-sheet .t5-l { padding: 0 2px; }
  body.print-t5 .t5-sheet .rf-input { padding: 0 1px; }
  body.print-t5 .t5-sheet textarea.rf-input { min-height: 0 !important; height: auto !important; line-height: 1.2; }
  /* ---------- 前 6 行行高按弹窗比例排布（2026-10-10，用户要求「行高在弹窗和打印相同」）----------
     2026-10-10 二次改版：原第 2、3 行已合并为一行（四对并排），故行索引整体 -1：
     现在 = 输入行 ①②③ : 勾选行 ④⑤ : 处置意见行 ⑥ = 45 : 28 : 50（弹窗 px，表宽 880）。
     打印页受 241×140mm 纸高所限，物理上不可能与弹窗等高，故按「这几行总高不变」把同一比例搬过来。
       · 输入行 ①②③：行高由输入框高度决定 → 34px 收到 30.5px（缩放前值）
       · 勾选行 ④⑤：显式行高 19.7px（缩放前值）
       · 处置意见行 ⑥：显式行高 35.2px（缩放前值）
     ⚠ 行号必须与 app.js t5FormHtml 的行结构一致，改版时同步改这里。
     ---------- 2026-10-10 四次调整：「备注」行压到 1/3 后的高度补偿 ----------
     「备注」行（原「质量问题图片」）由纵向堆叠改单行横排后，整表矮了约 34px（缩放前）≈ 8mm；
     纸张高度 140mm 不变 → 下留白会从 ~28.6mm 涨到 ~36.7mm（实测）。
     故把这段高度**按同一系数 1.205 分摊回 ①②③④⑤⑥ 行**（保持 45:28:50 的相互比例不变，
     也与 R5「打印与弹窗按比例一致」的口径一致），打印总高恢复到改前水平。
       · 输入行 ①②③：30.5 → 36.8px
       · 勾选行 ④⑤ ：19.7 → 23.7px
       · 处置意见行 ⑥：35.2 → 42.4px
     ⚠ 若将来再增删行，需按「打印内容总高 ≈ 100mm（= 140 − 上下各 10 − 余量）」重新配平。 */
  body.print-t5 .t5-sheet td.t5-v .rf-input { height: 36.8px; }
  body.print-t5 .t5-sheet > tbody > tr:nth-child(4),
  body.print-t5 .t5-sheet > tbody > tr:nth-child(5) { height: 23.7px; }
  body.print-t5 .t5-sheet > tbody > tr:nth-child(6) { height: 42.4px; }
  /* 返工返修小表：参照弹窗内布局 —— 表头行必须保留行高与内边距。
     旧写法 padding:0 把表头压成 ~2.6mm（与数据行 8mm 差太多，看着不像表头）。 */
  body.print-t5 .t5-grid th { font-size: 8pt; padding: 4px 3px; line-height: 1.2; }
  body.print-t5 .t5-grid td { font-size: 8pt; padding: 0 3px; }
  body.print-t5 .t5-grid .t5-grid-in { padding: 0; }
  body.print-t5 .t5-chkrow { gap: 0 10px; }
  body.print-t5 .t5-chk { font-size: 8pt; }
  body.print-t5 .t5-sub { font-size: 8pt; min-width: 30px; }
  body.print-t5 .rf-chip { font-size: 8pt; }
  body.print-t5 .t5-sheet .t5-att-note { min-height: 0; height: auto; }
  /* 「备注」行（原「质量问题图片」）打印跟随弹窗口径：同样是**单行横排**、不因附件区撑高。
     打印中该行本来就矮（按钮有边框已隐藏、textarea 高度被清零），这里只防止被弹窗的 24px 固定高反噬。 */
  body.print-t5 .t5-sheet .t5-note-row .t5-att-note { height: auto; min-height: 0; }
  body.print-t5 .t5-sheet .t5-note-row > td { padding: 0 4px; }
  body.print-t5 .t5-sheet .t5-note-row .rf-att { flex-direction: row; align-items: center; gap: 4px; }
  /* 输入控件打印成纯文本样式 */
  .rf-input, .rf-textarea, .t5-grid-in { border: none !important; background: transparent !important; box-shadow: none !important; resize: none !important; }
  textarea.rf-input, .rf-textarea { height: auto !important; overflow: visible !important; }
  /* 长文本打印（2026-10-19 用户要求「文字全部展开，不要折叠；一页不下可多页」）：
     打印前 textarea 已被等宽镜像 div 取代（见 app.js rfPreparePrintText），
     这里只负责：隐藏原控件、让镜像文字按原换行完整排版并允许跨页。 */
  .rf-hide-print { display: none !important; }
  .rf-print-text {
    white-space: pre-wrap; overflow-wrap: anywhere; word-break: break-word;
    font-size: 9.5pt; line-height: 1.45; padding: 0 1px; color: #000;
  }
  .rf-print-text.rf-print-empty { display: none !important; }
  .t5-sheet td, .t5-grid th, .t5-grid td { border-color: #333 !important; }
  /* 附件徽标只留文件名，去掉删除 ×（已在上方隐藏） */
  .rf-chip { border: none !important; padding: 0 4px 0 0 !important; }
  /* 2026-10-19（用户要求「打印时把图片打印出来」）：
     附件图片按**完整图像**打印（object-fit:contain 不裁切），单张 55×40mm、一行最多 3 张；
     图块不跨页断开，删除按钮 × 不打印。 */
  .rf-att .rf-thumb-x { display: none !important; }
  .rf-att .rf-thumbs { gap: 2mm; margin-top: 1.5mm; }
  .rf-att .rf-thumb, .rf-static .rf-imgcol-b .rf-thumb {
    border: 1px solid #666 !important; background: #fff !important;
    break-inside: avoid; page-break-inside: avoid;
  }
  /* 普通附件列（非分栏）：固定 55×40mm 缩略图 */
  .rf-att:not(.rf-split) .rf-thumb { width: 55mm; height: 40mm; max-width: 100%; }
  .rf-att .rf-thumb img { object-fit: contain !important; background: #fff !important; }
  /* T7 更改内容「变更前 / 变更后」两列：打印同样**零间隙**
     （图片紧贴列框线、图与图之间不留缝；列框线即单据表格线，不是图片自带的边框） */
  /* 多组对比打印：改成块级堆叠（flex 容器在分页上表现不可靠）；
     每组 = 图片 + 该组文字，组与组之间 3mm（组内文字紧贴图片下方，不加间距） */
  .rf-att .rf-imggroups, .rf-static .rf-imggroups { display: block !important; }
  .rf-att .rf-imgblock, .rf-static .rf-imgblock { display: block !important; }
  .rf-att .rf-imgblock + .rf-imgblock,
  .rf-static .rf-imgblock + .rf-imgblock { margin-top: 3mm; }
  .rf-att .rf-gap-ta { margin-top: 0 !important; min-height: 0 !important; }
  .rf-att .rf-imgcols, .rf-static .rf-imgcols { display: flex; gap: 0; align-items: stretch; }
  .rf-att .rf-imgcol, .rf-static .rf-imgcol {
    flex: 1 1 0; min-width: 0; border: 1px solid #666 !important; border-left: 0 !important;
    background: #fff !important; padding: 0 !important; border-radius: 0 !important;
    /* 列本身允许跨页（图多时继续往下排），单张图由 .rf-thumb 保证不切开 */
    break-inside: auto; page-break-inside: auto;
  }
  .rf-att .rf-imgcol:first-child, .rf-static .rf-imgcol:first-child { border-left: 1px solid #666 !important; }
  .rf-att .rf-imgcol-h, .rf-static .rf-imgcol-h { padding: 1mm 1.5mm !important; border-bottom: 1px solid #666 !important; background: #fff !important; }
  .rf-att .rf-imgcol-b, .rf-static .rf-imgcol-b { gap: 0 !important; }
  .rf-att .rf-imgcol-b .rf-thumb, .rf-static .rf-imgcol-b .rf-thumb {
    width: 100% !important; height: auto !important; border: 0 !important; border-radius: 0 !important;
    break-inside: avoid; page-break-inside: avoid;
  }
  .rf-att .rf-imgcol-b .rf-thumb img, .rf-static .rf-imgcol-b .rf-thumb img {
    width: 100% !important; height: auto !important; max-height: none !important;
    object-fit: contain !important; display: block;
  }
  .rf-imgcol-h { border-bottom: 1px dashed #999 !important; font-size: 9pt; }
  .rf-imgcol-empty { display: none !important; }
}

/* ---------- 基础设置弹窗 · 整屏铺满（2026-10-11）----------
   点击「基础设置」即整屏打开（100vw × 100vh、无圆角、无外边距）；
   三个菜单项（权限管理 / 基础数据 / 物料主数据）的内容区统一撑满可视高度，
   列表改为「内部滚动、填满剩余空间」，不再用固定 vh 限高。 */
#admin-modal .modal-box { width: 100vw; height: 100vh; max-width: none; max-height: none; border-radius: 0; }
#admin-modal .admin-menu { border-bottom-left-radius: 0; }
/* 内容区改纵向 flex：各 pane 撑满，滚动交给 pane 内部 */
#admin-modal .admin-content { display: flex; flex-direction: column; overflow: hidden; }
#admin-modal .admin-pane { flex: 1; min-height: 0; }
/* ① 权限管理：整段纵向滚动 */
#admin-modal #admin-pane-users { overflow: auto; }
/* ② 基础数据 / ③ 物料主数据：头 + 工具条固定，列表填满剩余高度 */
#admin-modal #admin-pane-master,
#admin-modal #admin-pane-materials,
#admin-modal #admin-pane-bom,
#admin-modal #admin-pane-procs { display: flex; flex-direction: column; min-height: 0; }
#admin-modal .master-wrap { flex: 1; min-height: 0; }
#admin-modal .master-side { overflow: auto; }
#admin-modal .master-main { min-height: 0; }
#admin-modal .master-table { flex: 1; min-height: 0; max-height: none; }
#admin-modal .mat-table { flex: 1; min-height: 0; max-height: none; }
#admin-modal .proc-table { flex: 1; min-height: 0; max-height: none; }
#admin-modal .bom-wrap { flex: 1; min-height: 0; }
#admin-modal .bom-main { min-height: 0; }
#admin-modal .bom-children { flex: 1; min-height: 0; }
/* 标题栏：整屏后「操作日志」不再被 space-between 挤到中间，改为标题左、操作右 */
#admin-modal .modal-head { justify-content: flex-start; gap: 10px; padding: 14px 20px; }
#admin-modal .modal-head #btn-audit { margin-left: auto; }

/* ---------- 基础设置 · BOM 关系（P3c，2026-10-11）----------
   左：成品列表（渠道筛选 + 搜索）　右：构成明细（自制 / 外购分组 + 工时定额）。只读浏览。 */
.bom-wrap { display: flex; gap: 16px; min-height: 380px; }
.bom-side { width: 264px; flex: none; border-right: 1px solid var(--line); padding-right: 10px;
  display: flex; flex-direction: column; overflow: hidden; }
.bom-side-title { font-size: 12px; color: var(--muted); margin-bottom: 8px; }
.bom-search { width: 100%; box-sizing: border-box; padding: 6px 10px; border: 1px solid var(--line);
  border-radius: 6px; font-size: 13px; font-family: inherit; color: var(--ink); margin-bottom: 6px; }
.bom-search:focus { outline: none; border-color: var(--primary); }
.bom-sel { width: 100%; box-sizing: border-box; padding: 6px 8px; border: 1px solid var(--line);
  border-radius: 6px; font-size: 13px; font-family: inherit; background: #fff; color: var(--ink); margin-bottom: 8px; }
.bom-list { flex: 1; min-height: 0; overflow: auto; display: flex; flex-direction: column; gap: 3px; }
.bom-item { border: 1px solid transparent; border-radius: 7px; padding: 6px 9px; cursor: pointer; }
.bom-item:hover { background: #f4f8ff; }
.bom-item.active { background: #e7f0ff; border-color: #bcd6ff; }
.bom-i-name { font-size: 13px; font-weight: 600; color: var(--ink); line-height: 1.35; }
.bom-i-sub { font-size: 11px; color: var(--muted); margin-top: 1px; font-family: Consolas, monospace; }
.bom-i-tags { margin-top: 3px; display: flex; gap: 8px; font-size: 11px; }
.bom-i-tags .t-self { color: #0f6e56; }
.bom-i-tags .t-buy { color: #854f0b; }
.bom-i-tags .t-all { color: var(--muted); }
.bom-main { flex: 1; min-width: 0; display: flex; flex-direction: column; min-height: 0; }
.bom-sum { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; }
.bom-chip { font-size: 12px; padding: 2px 9px; border-radius: 999px; background: #f1f3f6; color: var(--ink); }
.bom-chip.c-self { background: #e6f5ee; color: #0f6e56; }
.bom-chip.c-buy { background: #faf0da; color: #854f0b; }
.bom-chip.c-warn { background: #fcebeb; color: #a32d2d; }
.bom-chip.c-parent { background: #e6f1fb; color: #0c447c; }
.bom-chip.c-outs { background: #ece8f8; color: #5140a0; }   /* 其他属性（非自制件/外购件的兜底计数） */
.bom-chip.c-std  { background: #e6f2ff; color: #1a5fb4; }   /* 标准件（2026-11-09 零件属性新增） */
.bom-children { flex: 1; min-height: 0; overflow: auto; border: 1px solid var(--line); border-radius: 8px; }
.bom-table { border-collapse: collapse; width: 100%; font-size: 12px; }
/* 2026-10-15：左右内边距 6px→4px —— 14 列合计省出 28px 最小宽度，
   使明细表在 1280 视口也能完整显示（此前内容不可压缩、超出 19px）。 */
.bom-table th, .bom-table td { border: 1px solid var(--line); padding: 3px 4px; }
.bom-table thead th { background: var(--head-bg); position: sticky; top: 0; z-index: 2; font-weight: 600; white-space: nowrap; }
.bom-table td.bom-i { text-align: center; white-space: nowrap; }
.bom-table td.bom-code { font-family: Consolas, monospace; white-space: nowrap; }
.bom-table td.bom-spec { color: var(--muted); }
.bom-table tr.bom-grp td { background: #eef3fa; font-weight: 600; color: var(--primary); }
.bom-table tr.bom-nomat td { color: var(--muted); }
.bom-ok { color: #0f6e56; }
.bom-no { color: #a32d2d; }
.bom-empty { padding: 24px; text-align: center; color: var(--muted); font-size: 13px; }
/* ERP 编码停用 → 新编码生效（2026-10-11 方案A） */
.bom-table td.bom-code.bom-code-disabled { color: #9aa4b2; text-decoration: line-through; }
.bom-badge-off { display: inline-block; margin-left: 4px; padding: 0 4px; border-radius: 3px; font-size: 10px; line-height: 14px; color: #fff; background: #b4503f; vertical-align: middle; }
.bom-newcode-active { color: #0f6e56; font-weight: 600; background: #e7f4ee; }
.bom-badge-active { display: inline-block; margin-left: 4px; padding: 0 4px; border-radius: 3px; font-size: 10px; line-height: 14px; color: #fff; background: #0f6e56; vertical-align: middle; }
.bom-table td.bom-eff { font-family: Consolas, monospace; white-space: nowrap; font-weight: 600; color: var(--primary); }
.bom-table td.bom-eff.bom-eff-active { color: #0f6e56; }
.bom-table tr.bom-row-warn td { background: #fff6e0 !important; }

/* ---------- BOM 内嵌的金工工序定额（P3b，2026-10-11）----------
   自制件行尾「▸ N 道 · X min」可点击 → 展开一张工序子表（不落库、只做查阅）。 */
.bom-proc-toggle { cursor: pointer; color: var(--primary); font-size: 12px; white-space: nowrap; }
.bom-proc-toggle b { display: inline-block; transition: transform .12s; margin-right: 2px; }
.bom-proc-toggle.open b { transform: rotate(90deg); }
.bom-proc-toggle:hover { text-decoration: underline; }
.bom-proc-none { color: #c3c8cf; }
/* 设计生产BOM 明细行：2026-10-13 起行内不再放控件，改为「点行弹窗编辑」（参照 T1 单据表格）。
   外购/自制 与 版本号 在弹窗内改并写回 BOM；行上只做只读展示。 */
.bom-table tr.bom-row { cursor: pointer; }
.bom-table tr.bom-row:hover > td { background: #eef4fd; }
.bom-table tr.bom-row.bom-row-warn:hover > td { background: #ffeec9 !important; }
.bom-table td.bom-ver-ro { font-family: Consolas, monospace; }
/* S11 总成主表：点行弹窗编辑 —— 整行手型 + 悬停高亮（锁定列也要跟着亮） */
.mat-table tbody tr.asm-row { cursor: pointer; }
.mat-table tbody tr.asm-row:hover td, .mat-table tbody tr.asm-row:hover td.asm-lock { background: #eef4fd; }
.bom-wh { width: 64px; font-family: Consolas, monospace; font-size: 12px; padding: 2px 4px; border: 1px solid var(--line); border-radius: 4px; text-align: right; }
.bom-wh:focus { border-color: var(--primary); outline: none; }
.bom-wh-off { color: #c3c8cf; text-align: center; }
.bom-table tr.bom-proc-row > td { background: #fbfcfe; padding: 0; }
.bom-proc-box { padding: 6px 10px 8px; }
.bom-proc-hd { font-size: 12px; font-weight: 600; color: var(--primary); margin-bottom: 5px; }
.bom-proc-table { border-collapse: collapse; width: 100%; font-size: 11.5px; background: #fff; }
.bom-proc-table th, .bom-proc-table td { border: 1px solid var(--line); padding: 2px 6px; }
.bom-proc-table thead th { background: #eef3fa; font-weight: 600; white-space: nowrap; color: var(--ink); }
.bom-proc-table td.bom-i { text-align: center; white-space: nowrap; }
.how-ok { color: #0f6e56; font-size: 11px; }
.how-bad { color: #a32d2d; font-size: 11px; font-weight: 600; }

/* ---------- 基础设置 · 金工工序定额（P3b，2026-10-11）----------
   只读表格（19 列必然横向滚动）；「待确认」行整行标黄。 */
.proc-table { flex: 1; min-height: 0; overflow: auto; border: 1px solid var(--line); border-radius: 8px; }
.proc-table table { border-collapse: collapse; width: max-content; min-width: 100%; font-size: 12px; }
.proc-table th, .proc-table td { border: 1px solid var(--line); padding: 2px 5px; white-space: nowrap; }
.proc-table thead th { background: var(--head-bg); position: sticky; top: 0; z-index: 2; font-weight: 600; }
.proc-table tr.proc-pending td { background: #fffbe9; }
.proc-table td.proc-how { font-size: 11px; color: #0f6e56; }
.proc-table tr.proc-pending td.proc-how { color: #a32d2d; font-weight: 600; }

/* BOM 中心：单入口（原 物料/工序/BOM 三个平级菜单合并为 BOM 中心的三种子视图） */
#admin-modal #admin-pane-bom { display: flex; flex-direction: column; }
.bom-modebar { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; flex: none; }
.bom-mode { border: 1px solid var(--line); background: #fff; color: var(--ink); padding: 6px 14px; border-radius: 7px; font-size: 13px; cursor: pointer; font-family: inherit; }
.bom-mode:hover { border-color: var(--primary); color: var(--primary); }
.bom-mode.active { background: var(--primary); border-color: var(--primary); color: #fff; }
.bom-modetip { font-size: 12px; color: var(--muted); margin-left: 6px; }
.bom-subview { flex: 1; min-height: 0; }
/* S2 工时定额 · S21/S22 只读展示：modebar 固定，子视图填满剩余高度，表格在区域内上下+左右滚动 */
#admin-modal #admin-pane-show { display: flex; flex-direction: column; min-height: 0; overflow: hidden; }
#admin-modal #admin-pane-show > .bom-modebar { flex: 0 0 auto; }
#admin-modal #show-view-mat,
#admin-modal #show-view-proc { display: flex; flex-direction: column; flex: 1; min-height: 0; overflow: hidden; }
#admin-modal #admin-pane-show .mat-table,
#admin-modal #admin-pane-show .proc-table { flex: 1; min-height: 0; overflow: auto; max-height: none; }
#admin-modal .bom-subview.hidden { display: none; }
/* S11 总成主表（设计生产BOM 主视图，2026-10-13） */
#admin-modal #bom-view-tree.bom-wrap { display: flex; flex-direction: column; gap: 0; min-height: 0; }
#admin-modal .asm-wrap, #admin-modal .asm-detail { flex: 1; min-height: 0; display: flex; flex-direction: column; }
#admin-modal .asm-wrap .mat-table, #admin-modal .asm-detail .mat-table { flex: 1; min-height: 0; max-height: none; }
/* 2026-10-15：总成主表列宽硬约束（用户要求「页面在本机完全显示」）——
   .mat-table 原本全格 white-space:nowrap，长内容会无视 th 宽度提示撑开列（实测 1366 视口溢出 348px）。
   ⇒ 本表改 table-layout:fixed + 允许格内折行：th 宽度成为硬约束，
     多余宽度按比例填满视口、任何屏幕/缩放下都不再横向溢出。仅作用于总成主表，S21 等其它 .mat-table 不受影响。 */
#admin-modal .asm-wrap .mat-table table { width: 100%; table-layout: fixed; }
#admin-modal .asm-wrap .mat-table th,
#admin-modal .asm-wrap .mat-table td { white-space: normal; word-break: break-all; }
/* 编码类单元格保持单行，超长省略号截断（生效编码 / 明细按钮列） */
#admin-modal .asm-wrap .mat-table td.mat-eff { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#admin-modal .asm-wrap .mat-table td.row-num,
#admin-modal .asm-wrap .mat-table th.row-num { white-space: nowrap; }
/* 2026-10-14：明细标题上移，与「← 返回总成表」按钮同处一行（.detail-head），
   按钮不再独占一行 → 去掉 align-self / margin-bottom。 */
#asm-back { flex: 0 0 auto; }
/* 明细标题行：按钮 + 总成名称 + 编码·渠道 + 消息，居中对齐、可换行 */
#asm-detail-wrap .detail-head { flex: 0 0 auto; align-items: center; }
#asm-detail-wrap .detail-head .master-title { white-space: nowrap; }
/* 2026-10-14：「明细表：」固定前缀 + 总成名称 —— 两段同处一个 inline-flex 包裹层（不设 gap），
   避免被 .mat-tools 的 gap:8px 拆成两个词。前缀字号/字重/颜色与标题一致，读作「明细表：KV12S海水泵」。 */
#asm-detail-wrap .detail-name { display: inline-flex; align-items: baseline; }
#asm-detail-wrap .detail-tag { font-size: 15px; font-weight: 600; color: var(--ink); white-space: nowrap; }
/* 2026-10-14（用户指令）：chips 行（自制/外购/外协/合计/总成本身）**整行上移**，接在「编码 · 渠道」之后。
   它原为独占一行（.bom-sum 自带 margin-bottom:8px），并入标题行后须去掉该下边距；
   flex:0 1 auto 让它按内容占宽、空间不足时可整体换行（父级 .mat-tools 已 flex-wrap:wrap）。 */
#asm-detail-wrap .detail-head .bom-sum { margin-bottom: 0; flex: 0 1 auto; }
.mat-table td.asm-lock { background: #f4f6f8; color: var(--muted); font-family: Consolas, monospace; white-space: nowrap; }
.mat-table .asm-drill { border: 1px solid var(--line); background: #fff; border-radius: 4px; padding: 2px 9px; cursor: pointer; font-size: 12px; color: var(--primary); font-family: inherit; }
.mat-table .asm-drill:hover { background: var(--primary); color: #fff; }
.mat-table .asm-del { color: var(--red); cursor: pointer; font-size: 12px; }
.mat-table .asm-del:hover { text-decoration: underline; }
.bom-matcard { display: flex; flex-wrap: wrap; gap: 3px; max-width: 210px; }
.bm-tag { font-size: 10.5px; padding: 1px 6px; border-radius: 4px; background: #eef3fa; color: #2f6fb0; border: 1px solid #d3e2f3; white-space: nowrap; }
.bm-tag.bm-level { background: #eafaf0; color: #0f6e56; border-color: #bfe6cd; }

/* ================= 2026-10-15：S11 明细弹窗 · 自制件「铸造三字段」+「金工工序定额表」 =================
   两个区块 .bpe-block 追加在 .rf-sheet 表单之后；零件属性≠自制时整块 hidden（DOM 保留已填内容）。 */
.bpe-block { margin-top: 14px; border: 1px solid var(--line); border-radius: 6px; background: #fff; }
.bpe-block.hidden { display: none; }
.bpe-hd { display: flex; align-items: center; flex-wrap: wrap; gap: 10px;
  padding: 8px 12px; background: var(--head-bg); border-bottom: 1px solid var(--line);
  border-radius: 6px 6px 0 0; font-size: 13px; font-weight: 600; color: var(--ink); }
.bpe-hd-note { font-weight: 400; font-size: 12px; color: var(--muted); }
.bpe-warn { color: var(--red); }
.bpe-sum { margin-left: auto; font-weight: 400; font-size: 12.5px; color: #0f6e56; }
.bpe-add { border: 1px solid var(--orange); background: var(--orange); color: #fff; border-radius: 4px;
  padding: 3px 12px; font-size: 12.5px; font-family: inherit; cursor: pointer; white-space: nowrap; }
.bpe-add:hover { background: var(--orange-d); border-color: var(--orange-d); }
.bpe-block .rf-sheet { border: none; }
/* 自制件·铸造参数：单行 4 组「标签|值」——auto 布局 + 标签列 nowrap 不吃字，
   值列给最小宽度保证可输入（覆盖 .rf-sheet 的 table-layout:fixed 与 13% 定宽）。 */
.bpe-cast-table { table-layout: auto; }
.bpe-cast-table td.rf-l { width: 1px; white-space: nowrap; overflow: visible; text-overflow: clip; }
.bpe-cast-table td.rf-v { width: auto; min-width: 84px; }
.bpe-cast-table .rf-input { width: 100%; box-sizing: border-box; text-align: center; }
.bpe-scroll { overflow-x: auto; padding: 0 0 2px; }
.bpe-table { border-collapse: collapse; width: auto; table-layout: fixed; }
.bpe-table th, .bpe-table td { border: 1px solid var(--line); padding: 0; }
.bpe-table thead th { background: var(--head-bg); font-size: 12px; font-weight: 600; color: var(--ink);
  padding: 5px 6px; white-space: nowrap; text-align: center; }
.bpe-table thead th.bpe-th-ro { color: var(--muted); }
.bpe-in { width: 100%; box-sizing: border-box; border: none; background: transparent;
  font-family: inherit; font-size: 12.5px; color: var(--ink); padding: 5px 6px; text-align: center; }
.bpe-in:focus { outline: 2px solid #cfe0fb; outline-offset: -2px; background: #f7fbff; }
/* 只读派生格（单件工时min / 金工工时）：浅底 + 灰字，与可编辑格区分 */
.bpe-in.bpe-ro, .rf-input.bpe-ro { background: #f4f6f8; color: #4a5a6a; cursor: default; }
.bpe-opc { text-align: center; }
.bpe-del { border: none; background: transparent; color: var(--red); font-size: 15px; line-height: 1;
  cursor: pointer; padding: 4px 6px; font-family: inherit; }
.bpe-del:hover { background: #fdecec; border-radius: 3px; }
#bom-edit-fields .bpe-block + .imp-hint { margin-top: 12px; }



/* ================= G4「过程检验表」弹窗/打印版式（2026-10-21） =================
   用户指令：G4 更名为质检科检验工作台，弹窗与打印格式按
   过程检验表-20261020-V01.xlsx（横版 A4，左右 5mm / 上下 10mm，水平居中）。
   版式要素取自原表：表头区细边框(thin)、明细区粗边框(medium)、三级合并表头、
   表头浅灰底、数据居中、打印只输出表单本体（附件区 .rf-noprint 不打印）。 */
.t4-fields { display: block; }
.t4-title { text-align: center; font-size: 20px; font-weight: 700; letter-spacing: 6px;
  color: var(--ink); margin: 2px 0 4px; }
.t4-cap { display: flex; justify-content: flex-end; align-items: center;
  font-size: 12px; color: var(--muted); margin: 0 2px 6px; }
.t4-cap .t4-no { text-align: right; }
.t4-libnote { font-size: 12px; margin: 6px 2px 4px; line-height: 1.5; }
.t4-libnote .t4-ok { color: var(--green); }
.t4-libnote .t4-dim { color: var(--muted); }
.t4-libnote .t4-bad { color: var(--red); }

.t4-sheet { width: 100%; border-collapse: collapse; table-layout: fixed; }
.t4-sheet + .t4-sheet { margin-top: -1px; }
.t4-sheet td, .t4-sheet th { vertical-align: middle; word-break: break-word; }

/* ---- 表头信息区：细边框（对应原表 T:thin） ---- */
.t4-inf td { border: 1px solid #9aa7b6; padding: 3px 6px; font-size: 13px; height: 34px; }
.t4-inf td.t4-l { background: var(--head-bg); font-weight: 600; text-align: center; color: var(--ink); }
.t4-inf td.t4-v { background: #fff; }
.t4-inf td.t4-ro { color: #3d4b5c; text-align: center; }
/* 2026-10-21（用户：「弹窗输入时，表单均为可输入状态」）：
   图号/级别、版本号、检验日期、抽样方案、抽样数量 改为输入框，居中显示、与所在格同高 */
.t4-inf td.t4-in { padding: 2px 4px; }
.t4-inf td.t4-in .t4-inp { height: 30px; text-align: center; font-size: 13px; }

/* ---- 2026-11-08：G4 外采检验「抽检数」标签上的抽样水平标记 ----
   该列按 GB/T 2828.1-2012 特殊检验水平 S-2 自动取值（可手工改），标签后挂一枚小字标，
   让人一眼看出这个数是"按哪一档抽的"。inline 小标不改变格高，A4 打印版式不受影响。 */
.t4-inf td.t4-l .t16-smp {
  margin-left: 4px; padding: 0 4px; border-radius: 3px;
  background: #e7edf4; color: #4a5967; font-size: 10px; font-weight: 500;
  letter-spacing: 0; vertical-align: 1px;
}

/* ---- 2026-10-28：抽样方案下拉 + 抽样数量（引用 S5 表 GB/T 2828.1-2012） ----
   方案由手填改为下拉（S-2 / I / II / III）；数量为只读自动值：min(样本量, 批次数量)。 */
.t4-inf td.t4-in .t4-sel { width: 100%; padding: 0 2px; cursor: pointer; }
.t4-inf td.t4-qtycell { padding: 2px 4px; }
.t4-qtycell .t4-qn { font-size: 15px; font-weight: 700; color: var(--ink); letter-spacing: .5px; }
.t4-qtycell .t4-qt {
  margin-left: 4px; padding: 0 4px; border-radius: 4px; font-size: 11px; font-weight: 600;
  color: #b45309; background: #fdf3e3; border: 1px solid #f2ddb8;
}
.t4-qtycell .t4-qw { font-size: 12px; font-weight: 600; color: var(--red); }
.t4-qtycell .t4-qd { color: #9aa7b6; }

/* ---- 明细区：粗边框（对应原表 T:medium）+ 三级合并表头 ---- */
.t4-detail { border: 2px solid #4a5a6a; }
.t4-detail th, .t4-detail td { border: 2px solid #4a5a6a; padding: 4px 6px; font-size: 12.5px; }
.t4-detail thead th { background: var(--head-bg); font-weight: 600; text-align: center;
  color: var(--ink); line-height: 1.25; padding: 5px 4px; }
.t4-detail tbody td { height: 30px; text-align: center; background: #fff; }
/* 2026-11-08：规范格左右内边距 6px→2px。
   第一行默认值「外观（表面）缺陷检验」实测字宽 125px、格内可用 120px，差 5px 就会折成两行、
   把该行从 30px 撑到 42px（整行比其它行高一截）。缩窄内边距后可用 128px，单行放下。
   只调这一列：库里的尺寸项（φ50±0.1 之类）本来就短，居中显示不受影响；
   打印态的 padding 由后面 `body.print-t4 .t4-detail td` 规则覆盖，纸面不变。 */
.t4-detail tbody td.t4-spec { text-align: center; padding-left: 2px; padding-right: 2px; }
.t4-detail tbody td.t4-gauge { text-align: left; font-size: 12px; }
/* 测量结果 / 判定 / 备注：现场填写，留白且略降低饱和度以便手写辨识 */
.t4-detail tbody td.t4-m { background: #fff; }
.t4-detail tbody td.t4-judge { background: #fbfdfb; }

/* ---- 结论 + 签署行 ---- */
.t4-foot td { border: 1px solid #9aa7b6; padding: 4px 6px; font-size: 13px; height: 34px; }
.t4-foot td.t4-l { background: var(--head-bg); font-weight: 600; text-align: center; }
.t4-foot td.t4-v { background: #fff; }

/* ---- 2026-11-08 二次：结论行吸底规则已撤除 ----
   11:44 那次给结论行（.t4-footwrap）设 sticky bottom:0，目的是把埋在 15 行明细下方的
   「不合格工作台」按钮救到首屏。该按钮已于 2026-11-08 12:2x 搬到页脚正中常驻（.rf-g6foot），
   吸底失去意义，反而在滚动中途多压一条白条遮住明细 → 连同 app.js 的包裹层一并删除，
   结论行恢复普通文档流，打印版式不变。 */

/* ---- 检验结论右侧「不合格工作台」按钮（2026-10-28 建；2026-11-08 二次搬到页脚，改见 .rf-g6foot）----
   搬走后本行只剩结论值 + 两处签署，故 .t4-g6cell / .t4-g6btn 已废弃删除；
   按钮现由页脚中间栏渲染，外观与 T0 按钮同款（红底白字），规则见上文 .rf-t0foot 组选择器。 */

/* ---- 2026-10-28：G5→G6 转单来源提示条（仅屏幕，不打印） ---- */
.rf-src-banner {
  margin: 0 0 10px; padding: 8px 12px; border-radius: 8px; font-size: 12.5px;
  line-height: 1.6; color: #2b4a66; background: #eef6ff; border: 1px solid #cfe3f7;
}
.rf-src-banner b { color: #17456b; }
.rf-src-banner .rf-src-warn { color: #b3352f; display: block; margin-top: 4px; }

/* ---- 记录信息区（附件维护，不打印） ---- */
.t4-rec { margin-top: 12px; border: 1px dashed var(--line); border-radius: 8px; padding: 10px 12px; background: #fafcff; }
.t4-rec-h { font-size: 12px; font-weight: 600; color: var(--muted); margin-bottom: 8px; }

/* ---- 打印：横版 A4，只留表单本体 ---- */
@media print {
  body.print-t4 .rf-noprint { display: none !important; }
  /* G5→G6 来源提示条是屏幕信息，任何打印版式都不出（display 而非 visibility，避免留白影响 t5 单据高度） */
  .rf-src-banner { display: none !important; }
  body.print-t4 .t4-title { font-size: 15pt; letter-spacing: 6pt; margin: 0 0 1.5mm; }
  body.print-t4 .t4-cap { font-size: 8pt; margin: 0 0 1mm; }
  body.print-t4 .t4-libnote { display: none !important; }   /* 带出提示属屏幕信息，不上纸 */
  body.print-t4 .t4-inf td { font-size: 9pt; height: 6.5mm; padding: 0.8mm 1.5mm; }
  body.print-t4 .t4-detail th, body.print-t4 .t4-detail td { font-size: 8.5pt; padding: 0.8mm 1.5mm; }
  body.print-t4 .t4-detail thead th { line-height: 1.1; }
  body.print-t4 .t4-detail tbody td { height: 6mm; }
  body.print-t4 .t4-detail tbody td.t4-gauge { font-size: 8pt; }
  /* 2026-10-28（用户）：打印时「测量结果」5 列各加宽至原 4.5% 的 1.2×（→5.4%），合计多占 4.5%，
     由「备注」列（11.5%→7%）让出，保证打印表仍满 100%、不错列。仅作用于打印，弹窗不变。 */
  body.print-t4 .t4-detail col:nth-child(7),
  body.print-t4 .t4-detail col:nth-child(8),
  body.print-t4 .t4-detail col:nth-child(9),
  body.print-t4 .t4-detail col:nth-child(10),
  body.print-t4 .t4-detail col:nth-child(11) { width: 5.4% !important; }
  body.print-t4 .t4-detail col:nth-child(13) { width: 7% !important; }
  body.print-t4 .t4-foot td { font-size: 9pt; height: 7mm; padding: 0.8mm 1.5mm; }
  body.print-t4 .t4-sheet .rf-input { padding: 0 1px; }
  /* 2026-10-21（用户）：表头 5 项改为可输入格后，纸上仍按纯文本呈现——
     输入框去框去底、按内容高度收进单元格，既不打出一格控件框，也不会把行高撑开（横版单页保持）。 */
  body.print-t4 .t4-sheet input.rf-input {
    border: none !important; background: transparent !important;
    height: auto !important; min-height: 0; padding: 0 !important;
    font-size: inherit; line-height: 1.25; text-align: center;
  }
  /* 2026-10-21（用户）：「打印时，各下拉选项对应表格均为空」——
     下拉框在纸上由等值文字镜像替代（.rf-print-sel，见 app.js rfPreparePrintText），
     镜像文字继承所在格的字号/行高，避免 9.5pt 撑高行。 */
  body.print-t4 .t4-sheet .rf-print-text {
    font-size: inherit; line-height: 1.25; padding: 0; white-space: normal;
  }
  /* 打印时下拉箭头不上纸：取值控件在纸上按纯文本呈现（值本身照常打印） */
  body.print-t4 .t4-sheet select.rf-input {
    -webkit-appearance: none; appearance: none;
    background-image: none !important; padding-right: 0;
    text-align: left; text-align-last: left;
  }
  /* 明细行不允许跨页断开，整张表尽量落在同一页 */
  body.print-t4 .t4-detail tr { page-break-inside: avoid; break-inside: avoid; }
}

/* ================= G2「顾客抱怨处理单」弹窗/打印版式（2026-10-21） =================
   用户指令：G2 弹窗格式按纸质单 QR.05-09-03《顾客抱怨处理单》截图还原。
   三张细边框表拼接（基本信息 / 主体块 / 签署行），可填写格内仍是 .rf-field[data-field=ci]，
   保存、校验、附件、审核链路与其它表完全一致；打印为 A4 横向（与原单一致）。 */
.g2-fields { display: block; }
.g2-title { text-align: center; font-size: 20px; font-weight: 700; letter-spacing: 8px;
  color: var(--ink); margin: 2px 0 4px; }
.g2-cap { display: flex; justify-content: space-between; align-items: center; gap: 10px;
  font-size: 12px; color: var(--muted); margin: 0 2px 6px; }
.g2-cap .g2-stwrap { display: inline-flex; align-items: center; gap: 5px; }
.g2-cap .g2-state { height: 28px; font-size: 12.5px; min-width: 108px; }
.g2-cap .g2-no { text-align: right; }

.g2-sheet { width: 100%; border-collapse: collapse; table-layout: fixed; }
.g2-sheet + .g2-sheet { margin-top: -1px; }
.g2-sheet td { border: 1px solid #9aa7b6; padding: 3px 6px; font-size: 13px;
  vertical-align: middle; word-break: break-word; }
.g2-sheet td.g2-l { background: var(--head-bg); font-weight: 600; text-align: center; color: var(--ink); line-height: 1.3; }
.g2-sheet td.g2-v { background: #fff; }
/* 格内控件去框去底，与其它单据表（.rf-sheet）观感一致：纸面上一格一句话，不是一格一个控件 */
.g2-sheet .rf-input { border: none; border-radius: 0; background: transparent; padding: 2px 2px; height: 30px; }
.g2-sheet .rf-input:focus { border: none; box-shadow: none; background: #f6fafe; }
.g2-sheet .rf-input:disabled { background: transparent; color: var(--ink); }
.g2-sheet textarea.rf-input { min-height: 44px; padding: 2px; line-height: 1.6; resize: vertical; }
.g2-sheet .rf-static { min-height: 0; line-height: 1.45; word-break: break-word; }
.g2-sheet .rf-stamp { border: none; background: transparent; padding: 0; min-height: 0; }
.g2-sheet .g2-extra { text-align: left; }
.g2-inf td { height: 36px; }
.g2-blk td.g2-tall { height: auto; }
/* 2026-11-02（用户指令「弹窗三行行高各增加一倍」）：临时措施 / 原因调查 / 永久措施 三行。
   实测原行高 = 37px（格内是单行 input，高 30px + 上下内边距 6px + 1px 边框）⇒ 翻倍取 74px。
   td 的 height 只是**下限**：内容超高时行高继续跟随，不会被卡死；格内控件仍垂直居中。
   ⚠ 打印媒体另有一条把 g2-tall2 回落到 height:auto（见 @media print 的 body.print-g2 块），
     纸张实测 26px，与原版式一致。 */
.g2-blk td.g2-tall2 { height: 74px; }
/* 2026-11-03（用户「三行设置为多行文本框，可以输入多行文本」）：格内控件由单行 input 改为 textarea。
   ⚠ 必须显式 height:auto —— 上游 `.g2-sheet .rf-input { height: 30px }` 特异性(0,2,0) 高于
     `textarea.rf-input`(0,1,1)，会把多行框压回 30px（只剩一行高）；min-height 单独给。
   field-sizing:content（全局 textarea 规则）保底：内容换行后自动增高，不出内部滚动条。 */
.g2-blk td.g2-tall2 textarea.rf-input { height: auto; min-height: 62px; }
.g2-foot td { height: 36px; }
/* 签署行标签列只占栅格 13%~17%，放不下就折行、绝不溢出到值格里。
   2026-11-03（用户「质量技术分管领导上移」「生产管理分管领导左移」重排后）：8 字标签落在 13%~17% 列，
   13px 字号会折成两行 ⇒ 统一收到 12.5px + 内边距 2px，17% 列上的 8 字标签即可单行；
   仍放不下的（13% 列）照旧两行居中，不做省略。 */
.g2-foot td.g2-l { white-space: normal; line-height: 1.22; font-size: 12.5px; padding: 3px 2px; }
/* 2026-11-03 三次（用户「主管和分管领导位置互换」）：签署区第 1 行变成
   制表 | 质量技术部主管 | 质量技术分管领导，两栏都是「指定人签署」。
   主管栏落在**中组**：值格只有 13%（弹窗内约 114px）；分管领导栏 20%（约 176px）。
   签名图 24px 高 + 日期「2026-11-03」约 66px，一行放不下就会被 `.rf-stamp` 的
   nowrap + ellipsis 把日期裁掉 —— 故这两格改为 flex 换行：
   放得下就并排，放不下日期掉第二行；图再用 max-width:100% 兜底收缩，**绝不截断/省略**。
   （上一版曾为躲这个问题把主管栏硬放在第 3 组，现按用户要求换位，改用自适应解决。） */
.g2-foot td.g2-v.g2-signv .rf-stamp,
.g2-foot td.g2-v.g2-signv .rf-sign-btn {
  display: flex; flex-wrap: wrap; align-items: center; column-gap: 4px; row-gap: 1px;
  white-space: normal; overflow: visible; text-overflow: clip; min-height: 22px;
}
.g2-foot td.g2-v.g2-signv .sign-img { height: 22px; max-width: 100%; margin: 0; }
.g2-foot td.g2-v.g2-signv .sign-date { font-size: 11.5px; line-height: 1.15; }
/* 2026-11-03（用户「改进效果确认 在同一行展示」）：原为 改进效果<br>确认 两行，改为单行 6 字。
   标签列 13%（弹窗内约 84px），13px 字号放不下 ⇒ 12px + 左右内边距 2px + nowrap，实测单行不溢出。 */
.g2-blk td.g2-l.g2-l1 { white-space: nowrap; font-size: 12px; padding: 3px 2px; }
/* 顾客抱怨详情列挂了附件入口（2026-10-21 用户「顾客抱怨详情增加附件录入」）：
   附件区在格内铺满剩余宽度，缩略图略收小，避免撑破单据表格 */
.g2-sheet .rf-att { width: 100%; gap: 5px; }
.g2-sheet .rf-att .rf-thumbs { gap: 6px; }
/* 2026-11-03（用户「G2:图片显示缩略图或原图。请检查」）：
   原 104×78 + 通用 `object-fit: cover` 有两个毛病：① 照片边缘被裁掉（竖图两侧直接切掉），
   ② 尺寸太小看不清缺陷。改为**按原图比例自适应**：最长边 200×120，比例不变、内容完整，
   横图约 160×120、竖图约 90×120，都能看清；点击缩略图打开原图放大层（#img-zoom，
   支持 100% / 适应 / 复位 / 关闭）。
   打印不受影响：`@media print` 里 `.rf-att:not(.rf-split) .rf-thumb` 特异性更高，
   仍是 55×40mm + contain，纸张版式不变。 */
.g2-sheet .rf-att .rf-thumb { width: auto; height: auto; display: inline-block; line-height: 0; }
.g2-sheet .rf-att .rf-thumb img {
  width: auto; height: auto; max-width: 200px; max-height: 120px;
  object-fit: contain; background: #fff;
}
.g2-sheet .rf-addatt { width: 100%; justify-content: center; font-size: 12.5px; padding: 3px 8px; }
.g2-sheet .rf-chips { gap: 5px; }

/* 2026-11-03（用户指令「文字取消，增加附件：报怨单，在此可录入附件。打印时此附件不显示，只显示链接」）：
   「抱怨方式」格内追加的附件条 —— 与上方勾选组之间用一道虚线分开，读作「勾了书面抱怨就附上原件」。
   该列是「纯附件列」（app.js RF_ATT_PLAIN_COLS）：无文字说明框、无图片缩略图，
   屏幕上只列文件名徽标 + 添加按钮；打印时同样只留文件名（见下方 @media print 例外规则）。 */
.g2-attplain {
  display: flex; align-items: center; flex-wrap: wrap; gap: 3px 6px;
  width: 100%; margin-top: 5px; padding-top: 5px; border-top: 1px dashed var(--line);
}
.g2-attplain-l { font-size: 11.5px; color: #33475e; white-space: nowrap; font-weight: 600; }
.g2-attplain .rf-field { flex: 1 1 130px; min-width: 0; }
.rf-att.rf-att-plain { flex-direction: row; align-items: center; flex-wrap: wrap; gap: 4px 8px; width: 100%; }
.rf-att-plain .rf-chips { flex: 0 1 auto; min-width: 0; }
.rf-att-plain .rf-att-none { font-size: 12px; color: var(--muted); }
/* 这一列不截断文件名（屏幕上没有缩略图，名字是唯一线索）：给个较宽上限，超长再用省略号。
   上限收在 260px，好让「📎 添加」按钮仍能挤在同一行右侧（标签 + 徽标 + 按钮 ≈ 37% 格宽）。 */
.rf-att-plain .rf-chip { min-width: 0; }
.rf-att-plain .rf-chip-name { min-width: 0; max-width: 200px; }
.rf-att-plain .rf-chip { font-size: 11.5px; padding: 1px 6px; }
.g2-sheet .rf-att-plain .rf-addatt {
  width: auto; flex: 0 0 auto; font-size: 11.5px; padding: 1px 7px;
  white-space: nowrap; margin-left: auto;   /* 放不下换行时靠右，读作「操作按钮」而不是又一个内容 */
}

/* 勾选组：原生勾选框隐藏，用 ☐ / ☑ 字形呈现——屏幕上点得动，纸上与复印件都清晰 */
.g2-chkcell { padding: 4px 10px; }
.g2-chk { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 26px; }
.g2-chk-i { display: inline-flex; align-items: center; gap: 5px; cursor: pointer; user-select: none; }
.g2-chk-i input[type=checkbox] { position: absolute; width: 1px; height: 1px; opacity: 0; margin: 0; }
.g2-bx::before { content: '☐'; font-size: 15px; line-height: 1; }
.g2-chk-i input[type=checkbox]:checked ~ .g2-bx::before { content: '☑'; }
.g2-chk-i input[type=checkbox]:disabled ~ .g2-tx { color: var(--muted); }

/* 换货详情：四组「标签 + 值」等距排布（零件名称 / 零件号 / 数量 / 流水号） */
.g2-pairs { display: grid; grid-template-columns: auto 1.3fr auto 1.3fr auto .55fr auto .85fr;
  align-items: center; gap: 4px 6px; }
.g2-pairs .g2-pref, .g2-pairs .g2-pre { white-space: nowrap; font-weight: 600; color: var(--ink); }
.g2-pairs .rf-field { min-width: 0; }

/* 行内前缀（「验证确认小组：」等）：标签与控件同一行，占满剩余宽度 */
.g2-row { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.g2-row .g2-pre { white-space: nowrap; font-weight: 600; }
.g2-row .rf-field { flex: 1 1 160px; min-width: 0; }

/* ---- 打印：A4 横向，只留表单本体 ---- */
@media print {
  body.print-g2 .g2-title { font-size: 16pt; letter-spacing: 8pt; margin: 0 0 2mm; }
  body.print-g2 .g2-cap { font-size: 8pt; margin: 0 0 1mm; }
  body.print-g2 .g2-sheet td { font-size: 9pt; padding: 0.8mm 1.5mm; height: 7mm; }
  body.print-g2 .g2-blk td.g2-tall { height: auto; }
  /* 屏幕上加高的三行（临时措施 / 原因调查 / 永久措施）在纸上回落到内容高度，保持原紧凑版式 */
  body.print-g2 .g2-blk td.g2-tall2 { height: auto; }
  /* 输入控件在纸上按纯文本呈现（同 G4 做法）：去框去底、按内容高度收进单元格 */
  body.print-g2 .g2-sheet input.rf-input {
    border: none !important; background: transparent !important;
    height: auto !important; min-height: 0; padding: 0 !important;
    font-size: inherit; line-height: 1.3; text-align: left;
  }
  body.print-g2 .g2-sheet textarea.rf-input {
    border: none !important; background: transparent !important;
    min-height: 0 !important; padding: 0 !important; overflow: hidden;
    font-size: inherit; line-height: 1.35;
  }
  /* 下拉（状态）与长文本在纸上由等值文字镜像替代（.rf-print-text，见 app.js rfPreparePrintText） */
  body.print-g2 .g2-sheet .rf-print-text { font-size: inherit; line-height: 1.35; padding: 0; white-space: pre-wrap; }
  body.print-g2 .g2-sheet select.rf-input {
    -webkit-appearance: none; appearance: none; background-image: none !important;
    padding: 0; border: none !important; background: transparent !important;
    font-size: inherit; text-align: left;
  }
  /* 附件徽标/加附件按钮属屏幕维护入口，不上纸 */
  body.print-g2 .g2-sheet .rf-chips, body.print-g2 .g2-sheet .rf-addatt { display: none !important; }
  /* 例外：「抱怨单」是纯附件列（无缩略图），纸面上**只显示文件名链接**（用户 2026-11-03 指令
     「打印时此附件不显示，只显示链接」）—— 故徽标必须印出，按钮仍隐藏。
     特异性 (0,4,0) 高于上面那条 (0,3,0)，再带 !important 双保险。 */
  body.print-g2 .g2-sheet .rf-att-plain .rf-chips { display: flex !important; gap: 4px !important; }
  body.print-g2 .g2-sheet .rf-att-plain .rf-chip {
    border: none !important; background: transparent !important;
    padding: 0 6px 0 0 !important; font-size: inherit !important; color: #000 !important;
  }
  body.print-g2 .g2-sheet .g2-attplain { margin-top: 0; padding-top: 0.6mm; }
  body.print-g2 .g2-sheet .g2-attplain-l { font-size: 9pt; }
  /* 2026-11-03：屏幕态给 G2 缩略图放大了尺寸（最长边 200×120），打印要回到通用纸张规格 55×40mm，
     否则纸张版式被撑高。特异性 (0,3,1) 高于屏幕那条 (0,3,0)，且带 !important 防止再被覆盖。 */
  body.print-g2 .g2-sheet .rf-att .rf-thumb {
    width: 55mm !important; height: 40mm !important; max-width: 100%;
  }
  body.print-g2 .g2-sheet .rf-att .rf-thumb img {
    width: 100% !important; height: 100% !important;
    max-width: none !important; max-height: none !important;
    object-fit: contain !important; background: #fff !important;
  }
  body.print-g2 .g2-bx::before { font-size: 9.5pt; }
  body.print-g2 .g2-sheet tr { page-break-inside: avoid; break-inside: avoid; }
}

/* ===== S3 导入/导出数据（2026-10-21 新增） =====
   勾选清单：按 G/T/B 分组，每项显示「编号 + 名称 + 行数」；B 组标记为"仅导出"。 */
.io-groups { display: flex; flex-direction: column; gap: 12px; margin: 10px 0 14px; }
.io-group { border: 1px solid var(--line); border-radius: 8px; overflow: hidden; background: #fff; }
.io-group-hd { display: flex; align-items: center; gap: 8px; padding: 7px 10px; background: #eef3f9;
  border-bottom: 1px solid var(--line); font-size: 12.5px; font-weight: 700; color: var(--ink); }
.io-group-hd .io-gcount { font-weight: 400; color: var(--muted); font-size: 11.5px; }
.io-group-hd label { margin-left: auto; font-weight: 400; font-size: 12px; color: var(--muted);
  cursor: pointer; display: inline-flex; align-items: center; gap: 4px; }
.io-items { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 2px 14px; padding: 8px 10px; }
.io-item { display: flex; align-items: center; gap: 6px; font-size: 12.5px; padding: 3px 0; min-width: 0; cursor: pointer; }
.io-item input { flex: 0 0 auto; margin: 0; }
.io-item .io-code { flex: 0 0 auto; font-weight: 700; color: #3a5a86; background: #eef3f9;
  border-radius: 4px; padding: 0 4px; font-size: 11.5px; line-height: 17px; }
.io-item .io-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.io-item .io-rows { flex: 0 0 auto; color: var(--muted); font-size: 11.5px; }
.io-item.io-view .io-code { color: #6b4c9a; background: #f2eefa; }
.io-bar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; padding: 6px 0 2px; }
.io-allwrap { display: inline-flex; align-items: center; gap: 5px; font-size: 12.5px; cursor: pointer; }
.io-picked { font-size: 12.5px; color: var(--muted); }
.io-sp { flex: 1 1 auto; }
.io-result { margin-top: 12px; }
.io-result table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.io-result th, .io-result td { border: 1px solid var(--line); padding: 5px 8px; text-align: left; word-break: break-word; }
.io-result th { background: #eef3f9; font-weight: 700; }
.io-result .num { text-align: right; font-variant-numeric: tabular-nums; }
.io-loading { font-size: 12.5px; color: var(--muted); padding: 10px 2px; }
.io-warn { color: #a35b00; }

/* ---------- S4 操作日志（2026-10-23 新增，仅管理员）---------- */
/* 2026-11-08（用户指令「查询框上移两行；空行删除，表头上移至紧挨查询框」）：
   ① 面板内的标题与说明段已在 index.html 删除，故 log-bar 顶部内边距由 8px 归零，查询栏直接顶到面板上沿；
   ② 查询栏与表头之间原有两段空白：#log-msg 空态占 8px margin + 16px min-height，加 .log-wrap 的 8px margin-top，
      合计 32px —— 正是截图里那条空行。现让 #log-msg 空态不占位、.log-wrap 上边距归零，表头即紧接查询栏。 */
.log-bar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding: 0 0 6px; }
.log-f { display: inline-flex; align-items: center; gap: 5px; font-size: 12.5px; color: var(--muted); }
.log-bar input[type="date"], .log-bar select, .log-q {
  font-size: 12.5px; padding: 4px 7px; border: 1px solid var(--line);
  border-radius: 6px; background: #fff; color: #22303f;
}
.log-q { min-width: 210px; }
.log-bar select { max-width: 190px; }
/* 提示条（加载失败 / 查询结果条数等）只在有文字时出现，空态不占高度 */
#log-msg:empty { display: none; }
.log-wrap { margin-top: 0; max-height: 56vh; overflow: auto; border: 1px solid var(--line); border-radius: 8px; }
.log-table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.log-table thead th {
  position: sticky; top: 0; z-index: 1; background: #eef3f9; font-weight: 700;
  border-bottom: 1px solid var(--line); padding: 7px 9px; text-align: left; white-space: nowrap;
}
.log-table td { border-bottom: 1px solid #eef1f5; padding: 6px 9px; vertical-align: top; }
.log-table tr:hover td { background: #f7fafd; }
.log-time { white-space: nowrap; color: #4a5866; font-variant-numeric: tabular-nums; }
.log-user { white-space: nowrap; font-weight: 600; }
.log-tname { color: #3b4c5e; }
.log-detail { color: #33414f; word-break: break-word; }
/* 动作列：2026-11-08 用户指令「S4：红色标记全部删除」→「标记处全部删掉」，
   原来是彩色胶囊（.log-act，内联背景色）＋服务启停行淡绿底（.log-sys），均按指令删除，
   现只输出纯文字，颜色与「详情」列一致，页面上不再有任何彩色标记。 */
.log-act-td { color: #33414f; white-space: nowrap; }
.log-empty { text-align: center; color: var(--muted); padding: 18px 8px; }
.log-pager { display: flex; align-items: center; gap: 8px; padding: 10px 2px 2px; flex-wrap: wrap; }
.log-count { font-size: 12.5px; color: var(--muted); }
.log-page { font-size: 12.5px; color: #3b4c5e; font-variant-numeric: tabular-nums; }
.log-sp { flex: 1 1 auto; }
.log-pager .btn[disabled] { opacity: .5; cursor: not-allowed; }

/* ---- 2026-11-08（用户指令「S4：列表展示内容尽量多，下一页等内容与屏幕最下方尽量靠近」）----
   原状：.log-wrap 限定 max-height:56vh（900px 屏只有 504px，约 16 行），分页条紧跟表格，
   表格下方到屏幕底部还空着一大截，想看更多行只能翻页。
   现改为纵向弹性布局：
   · 面板 → 段落 → 表格 三层 min-height:0，表格 flex:1 1 auto，始终吃满剩余高度、超出部分内部滚动（表头 sticky 不受影响）；
   · 分页条 margin-top:auto —— 内容撑满时紧接表格，内容少时自动被推到面板最底部；
   · .admin-content 加 .ac-logs 标记（由 switchAdminTab 打上），底部内边距 18px → 6px，分页条更贴近屏幕下沿。
   2026-11-08 追加（用户指令「强行拉满」）：表格由 flex:0 1 auto 改为 flex:1 1 auto ——
   即使筛出两三行也把外框铺到分页条，页面不再出现"表格半截 + 大片裸白"的断层。
   注意只拉容器不拉 table 本身（table 设 height:100% 会把少数几行平分拉高，行高忽大忽小）。 */
#admin-modal #admin-pane-logs { display: flex; flex-direction: column; min-height: 0; }
#admin-modal #admin-pane-logs > .admin-section {
  display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; margin-bottom: 0;
}
#admin-pane-logs .log-bar { flex: 0 0 auto; }
#admin-pane-logs #log-msg { flex: 0 0 auto; }
#admin-pane-logs .log-wrap { flex: 1 1 auto; min-height: 0; max-height: none; }
#admin-pane-logs .log-pager { flex: 0 0 auto; margin-top: auto; padding: 8px 2px 0; }
#admin-modal .admin-content.ac-logs { padding-bottom: 6px; }

/* ---------- 2026-10-28：G5 抽样方案下拉的打印处理 ----------
   下拉箭头是屏幕控件，打印时去掉（只留格线与选中值文字，与其他手填项观感一致）；
   「全检」标记在纸上不需要底纹，改回细框。 */
@media print {
  .t4-inf td.t4-in .t4-sel { -webkit-appearance: none; appearance: none; }
  .t4-qtycell .t4-qt { background: transparent; border-color: #8a97a8; color: #333; }
}

/* ---------- 2026-10-28：有效期预警的打印处理 ----------
   预警是屏幕提示：打印件只保留原始日期文字（去底色/改色），提示行不打印，
   避免纸质记录表上出现与现场核定不一致的红色标记。 */
@media print {
  .cell.exp-expired, .cell.exp-soon { background: transparent !important; color: inherit !important; font-weight: normal !important; }
  .rf-exp-hint { display: none !important; }
}

/* ================= R 定时任务（2026-11-02 新增） =================
   三个弹窗：清单 / 新建编辑 / 到期提醒。配色一律走 :root 变量，与全站一致。 */
.task-box { width: 860px; }
.task-body { padding-top: 14px; }
.task-new-btn { padding: 5px 14px; font-size: 13px; }
/* 2026-11-11 用户指令「× 按操作系统一般习惯与返回首页位置互换；返回首页和新建任务放置在弹窗上部中间位置」：
   页头布局改为 —— 标题贴左、『＋新建任务 + ⌂返回首页』水平居中、关闭 × 贴最右（同 Windows 标题栏习惯）。
   做法：标题与 × 均绝对定位脱离文档流，不参与 flex 居中计算，
   故中间两个按钮的中线严格等于弹窗中线（若用等宽垫片会因标题宽度不等而偏斜，故不采用）。 */
#task-modal .modal-head { position: relative; justify-content: center; gap: 10px; }
#task-modal #task-title-h { position: absolute; left: 20px; top: 50%; transform: translateY(-50%); white-space: nowrap; }
#task-modal #task-close {
  position: absolute; right: 14px; top: 50%; transform: translateY(-50%);
  padding: 0 4px; border-radius: 6px;
}
#task-modal #task-close:hover { color: var(--ink); background: var(--head-bg); }
/* 中间组的两个按钮不参与 margin 推挤，间距统一由 .modal-head 的 gap 控制 */
#task-modal .task-new-btn { margin-left: 0; margin-right: 0; }
#task-modal #task-home { margin-left: 0; }
/* 窄屏兜底（<560px）：标题与 × 回归常规流，两个按钮靠右、× 仍在最末，避免三者叠压。
   断点取 560 而非 760：标题(约 85px) + 按钮组(约 204px) + ×(约 28px) + 左右内边距(40px)
   实际需约 380px，故 560~760 区间居中排版仍有充裕余量，无需过早回退。 */
@media (max-width: 560px) {
  #task-modal .modal-head { justify-content: flex-start; gap: 8px; }
  #task-modal #task-title-h, #task-modal #task-close { position: static; transform: none; }
  #task-modal .task-new-btn { margin-left: auto; }
}
.task-tip { font-size: 12.5px; color: var(--muted); line-height: 1.6; background: var(--head-bg);
  border-radius: 8px; padding: 9px 12px; margin-bottom: 14px; }
.task-tip b { color: var(--ink); }
.task-empty { text-align: center; color: var(--muted); font-size: 13.5px; padding: 48px 0; }
.task-grp { font-size: 12px; font-weight: 700; color: var(--muted); letter-spacing: .04em;
  margin: 16px 0 8px; }
.task-grp:first-child { margin-top: 0; }

.task-item { display: flex; align-items: flex-start; gap: 14px; border: 1px solid var(--line);
  border-radius: 10px; padding: 12px 14px; margin-bottom: 9px; background: #fff; }
.task-item.is-done { background: #fafbfc; opacity: .78; }
.task-item.is-overdue { border-color: #f0c4c4; background: #fffafa; }
.task-main { flex: 1; min-width: 0; }
.task-title-line { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.task-title { font-size: 14.5px; font-weight: 700; color: var(--ink); word-break: break-word; }
.task-item.is-done .task-title { text-decoration: line-through; color: var(--muted); }
.task-chip { font-size: 11px; font-weight: 600; color: var(--primary); background: rgba(31,111,235,.09);
  border-radius: 5px; padding: 2px 7px; white-space: nowrap; }
.task-chip.is-warn { color: var(--red); background: rgba(210,59,59,.1); }
.task-chip.is-mine { color: var(--green); background: rgba(26,158,87,.11); }
.task-meta { margin-top: 6px; font-size: 12.5px; color: var(--muted); display: flex;
  flex-wrap: wrap; gap: 4px 14px; line-height: 1.7; }
.task-detail { margin-top: 6px; font-size: 12.5px; color: #445; line-height: 1.65;
  white-space: pre-wrap; word-break: break-word; }
.task-acts { display: flex; flex-direction: column; gap: 6px; flex: 0 0 auto; }
.task-btn { font-size: 12px; padding: 4px 11px; white-space: nowrap; }
.task-btn.is-danger { color: var(--red); }

.task-edit-box { width: 640px; }
.task-form { display: flex; flex-direction: column; gap: 13px; }
.task-f { display: flex; flex-direction: column; gap: 5px; font-size: 12.5px; color: var(--muted);
  flex: 1; min-width: 0; }
.task-f input, .task-f textarea, .task-f select { font-family: inherit; font-size: 13.5px; color: var(--ink);
  border: 1px solid var(--line); border-radius: 7px; padding: 8px 10px; background: #fff; width: 100%; }
.task-f textarea { resize: vertical; line-height: 1.6; }
.task-f input:focus, .task-f textarea:focus, .task-f select:focus { outline: none; border-color: var(--primary); }
.task-frow { display: flex; gap: 13px; }
.task-adv { display: flex; gap: 7px; }
.task-adv input { width: 92px; }
.task-adv select { width: 92px; }
.task-notify { border: 1px solid var(--line); border-radius: 9px; padding: 11px 13px; }
.task-notify-h { font-size: 12.5px; font-weight: 700; color: var(--ink); margin-bottom: 9px; }
.task-notify-h span { font-weight: 400; color: var(--muted); margin-left: 8px; }
.task-notify-list { display: flex; flex-wrap: wrap; gap: 8px; }
.task-nm { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; color: var(--ink);
  border: 1px solid var(--line); border-radius: 7px; padding: 5px 11px; cursor: pointer; user-select: none; }
.task-nm.on { border-color: var(--primary); background: rgba(31,111,235,.07); color: var(--primary-d); font-weight: 600; }
.task-nm input { margin: 0; }
.task-nm em { font-style: normal; font-size: 11px; color: var(--muted); background: var(--head-bg);
  border-radius: 4px; padding: 1px 5px; }
.task-form-btns { display: flex; justify-content: flex-end; gap: 9px; margin-top: 4px; }

.task-alert-box { width: 500px; }
.task-alert-list { display: flex; flex-direction: column; gap: 10px; }
.ta-item { border-left: 3px solid var(--orange); background: #fffaf3; border-radius: 0 9px 9px 0; padding: 11px 14px; }
.ta-title { font-size: 14.5px; font-weight: 700; color: var(--ink); word-break: break-word; }
.ta-meta { margin-top: 5px; font-size: 12.5px; color: var(--muted); display: flex; flex-wrap: wrap; gap: 4px 10px; }
.ta-late { color: var(--red); font-weight: 600; }
.ta-soon { color: var(--orange-d); font-weight: 600; }
.ta-detail { margin-top: 6px; font-size: 12.5px; color: #445; line-height: 1.65;
  white-space: pre-wrap; word-break: break-word; }
.task-alert-btns { display: flex; justify-content: flex-end; margin-top: 18px; }

/* 2026-11-04（T0）派生只读格「下次计量确认日期」
   = 上次计量确认日期 + 计量确认周期，由服务端计算落库，弹窗里只能看不能改。
   浅灰底 + 斜体说明色，与旁边的可编辑输入框一眼区分；打印时背景自动被浏览器丢弃，不影响单据观感。 */
.rf-sheet .rf-ro-next {
  background: #edf1f7; border-radius: 4px; padding: 4px 8px; min-height: 26px;
  color: #1f2d3d; font-variant-numeric: tabular-nums; letter-spacing: .2px;
}
.rf-sheet .rf-ro-next.rf-ro-empty { color: #98a2b3; font-style: italic; font-size: 12.5px; }

/* 2026-11-08 二次（G14 联动）：合格率% 派生格 —— 数值按等宽加粗显示，未算出时右侧补一句操作提示。
   与 T0 的「下次计量确认日期」共用 .rf-ro-next 底色，视觉上同属"系统算出来的格"。 */
.rf-sheet .rf-ro-next.rf-ro-rate { font-weight: 700; font-variant-numeric: tabular-nums; }
.rf-sheet .rf-ro-hint { margin-left: 8px; font-size: 11.5px; font-weight: 400; font-style: normal; color: #98a2b3; }

/* =====================================================================================
   2026-11-08（用户指令「可以加上反查功能」）：G11 质量技术任务指令 ↔ 台账记录 的双向反查
   · .rf-bk      —— G2/G3/G10 弹窗顶部「本记录被哪些任务指令引用」提示条（屏幕专用，打印隐藏）
   · .rf-bk-open —— G11 弹窗「关联记录编号」格下方的「打开该记录 →」跳转入口
   配色沿用工作台蓝色系，与 .rf-hint 同族；点条目即跳转到 G11 的对应行（rfGotoRecord）。
   ===================================================================================== */
.rf-bk {
  margin: 6px 0 10px; padding: 8px 10px 9px;
  border: 1px solid #d7e5f8; border-left: 3px solid var(--primary);
  background: #f5f9ff; border-radius: 6px;
}
.rf-bk-hd { font-size: 12px; color: var(--muted); margin-bottom: 2px; }
.rf-bk-item {
  display: flex; align-items: center; gap: 8px; width: 100%; text-align: left;
  background: #fff; border: 1px solid var(--line); border-radius: 5px;
  padding: 4px 8px; margin-top: 5px; font-size: 12.5px; color: var(--ink); cursor: pointer;
}
.rf-bk-item:hover { border-color: var(--primary); background: #eef5ff; }
.rf-bk-code { flex: none; font-weight: 600; color: var(--primary); font-variant-numeric: tabular-nums; }
.rf-bk-tag { flex: none; background: #eef2f7; color: #4a5a6d; border-radius: 3px; padding: 0 6px; font-size: 11.5px; }
.rf-bk-sum { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rf-bk-due, .rf-bk-st { flex: none; color: var(--muted); font-size: 11.5px; }
.rf-bk-open {
  display: inline-block; margin-top: 4px; padding: 0; border: none; background: none;
  color: var(--primary); font-size: 12px; text-decoration: underline;
}
.rf-bk-open:hover { color: var(--primary-d); }

/* =====================================================================================
   2026-11-08（用户指令「想要在看板显示这些历年数据」）：看板 K3「历年合格率趋势」
   → 同日二次（用户指令「按铸造、金工、装配三个车间布置，显示近 2 年，总宽度按 K1」）：
     改为**三栏并排**，宽度由 wide4 收窄到 wide2（与 K1 同宽），一栏一个车间。
   · .kb-card.wide2 已在文件上方定义（grid-column: span 2）—— 与 K1 同宽，不再独占一行。
   · 三栏各带**独立纵轴**：铸造约 79–98%、金工约 89–100%，统一刻度会把金工压成直线。
     纵轴范围写在每栏 .kb-shop-ft 里，避免"看斜率比高低"的误读。
   · .kb-shop-svg 是内联 SVG，preserveAspectRatio="none" 让它填满栏宽；
     ⚠ SVG 内一个文字都不放（拉伸会把字压扁，上一版踩过这个坑），数值/刻度一律走 HTML。
   · 配色：铸造蓝 #2f6fd0、金工青绿 #0f9d8f、装配橙 #c9770f（三包件用淺橙 #e8a33d 区分）。
   ===================================================================================== */
.kb-card.wide4 { grid-column: span 4; display: flex; flex-direction: column; }
.kb-card.wide4 .kb-card-sub,
.kb-card.wide2 .kb-card-sub {
  margin-left: 8px; font-size: 11px; font-weight: 400; letter-spacing: 0;
  color: rgba(255, 255, 255, .72);
}
/* 不 flex-grow：三栏只占内容高度，x 轴刻度与脚注紧跟其后，多余高度集中在卡片底部。
   若让 trend3 撑满卡片，多出来的空白会落在"页脚"与"刻度"之间，看着像断了一截。 */
.kb-trend3 {
  flex: none; min-height: 0;
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px;
  padding: 8px 12px 0;
}
.kb-shop { min-width: 0; display: flex; flex-direction: column; }
.kb-shop-hd { display: flex; align-items: baseline; gap: 5px; min-width: 0; }
.kb-shop-hd b { font-size: 12.5px; font-weight: 600; color: var(--ink); white-space: nowrap; }
.kb-shop-tag {
  flex: none; font-size: 10px; color: #6b7a8d; background: #f1f4f8;
  border-radius: 3px; padding: 0 4px; line-height: 15px;
}
.kb-shop-val {
  font-size: 20px; font-weight: 600; line-height: 1.15; margin-top: 1px;
  font-variant-numeric: tabular-nums; letter-spacing: -.3px;
}
.kb-shop-val small { font-size: 11px; font-weight: 400; margin-left: 1px; letter-spacing: 0; }
/* 三栏主数字块高度统一（2026-11-09 用户指令「三处图表对齐」）。
   铸造栏是两料并排的 .kb-shop-val2（内部 16px 数字，行盒 18px），金工/装配是单值
   .kb-shop-val（20px 数字 + 1px 上边距，行盒 21px）。这 3px 的差会顺着 flex 列往下传，
   让铸造栏的图、x 轴、极值行整体比另两栏高 3px —— 图高固定 132px 时看不太出来，
   但三张图的顶边不在一条线上，横向比高低就失去了同一基准。统一 21px 下限抹平。 */
.kb-shop-val, .kb-shop-val2 { min-height: 21px; }
/* 2026-11-09（用户指令「铸造铸铁和铸铜合格率在同一个图表展示」）：
   一栏里放两条线 ⇒ 主数字也要成对出现。**横排**而不是两行：两行会把卡片撑高 ~20px，
   50% 卡高的 K3 已经贴着上限了（图 132px + 极值两行 + 脚注）。
   数字用各自的线色，前面一个同色小方块 + 「铸铁/铸铜」标签，与图内折线一一对应。 */
.kb-shop-val2 { display: flex; align-items: baseline; flex-wrap: wrap; gap: 2px 10px; }
.kb-shop-mv { display: inline-flex; align-items: baseline; gap: 3px; min-width: 0; }
.kb-shop-mv i {
  flex: none; width: 7px; height: 7px; border-radius: 2px;
  transform: translateY(-1px);
}
.kb-shop-mv em { font-style: normal; font-size: 10.5px; font-weight: 400; color: #6b7a8d; letter-spacing: 0; }
.kb-shop-mv b { font-size: 16px; font-weight: 600; font-variant-numeric: tabular-nums; letter-spacing: -.3px; }
.kb-shop-mv small { font-size: 10px; font-weight: 400; color: #8a95a5; margin-left: -1px; }
/* 期号行（2026-07　2026版）：2026-11-09 按用户指令从卡片上删除，样式保留以防回滚。
   原用途是标"最新一期 + 统计口径"，现同一信息挂在主数字的 title 上。 */
.kb-shop-when {
  font-size: 10.5px; color: #98a2b3; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}
/* 每栏图下方的两端横坐标（2026-11-09 用户指令「在图表下方将两端横坐标加上，最左 25-03、最右 26-07」）。
   用绝对定位 + 百分比左偏移，而不是 flex space-between —— 标签必须落在**折线的真实起止点**正下方：
   铸造/金工的线到 26-07 就录完了，右侧还留着 3 个月空白，把 26-07 贴到栏右边会让人
   误以为折线一直画到窗口末月（26-10）。右端标签用 -100% 位移把文字右边缘对齐到该月刻度。 */
.kb-shop-x {
  position: relative; flex: none; height: 11px; margin-top: 2px;
  font-size: 9.5px; line-height: 11px; color: #b0b9c6;
  font-variant-numeric: tabular-nums;
}
.kb-shop-x span { position: absolute; top: 0; white-space: nowrap; }
.kb-shop-x .kb-shop-x-r { transform: translateX(-100%); }
/* 图高**固定**而不用 flex 吃满剩余空间：容器多高、图就多高的话，纵向比例尺
   （每 1 个百分点折几像素）会随窗口大小漂移，同一张卡在 1366 屏和 4K 屏上"波动剧烈程度"完全不同，
   汇报时最容易吵的就是这个。固定 132px 让三栏的比例尺在任何屏幕上一致。 */
.kb-shop-svg {
  width: 100%; height: 132px; flex: none;
  display: block; margin-top: 4px;
}
/* 2026-11-09（用户指令「每月数据加上点标记」）：绘图区容器 + 每月圆点。
   点标记走 HTML 绝对定位而不是 SVG <circle> —— SVG 用 preserveAspectRatio="none" 填满栏宽，
   纵向 132/62≈2.1 倍、横向约 0.7 倍的拉伸会把圆拉成明显竖椭圆（旧版因此只敢标段末点）；
   放在 HTML 层按百分比定位，无论栏宽/屏幕都保持正圆。 */
.kb-shop-plot { position: relative; flex: none; height: 132px; margin-top: 4px; }
/* 4 栏（铸造拆成铸铁件/铸铜件后的常态）：每栏更窄，把图压矮 24px，
   保证「高/低 极值行（窄栏下会折成两行）+ 脚注」仍落在 50% 卡高之内，不被 .kb-card 的 overflow 裁掉。 */
.kb-trend-n4 .kb-shop-plot { height: 108px; }
.kb-shop-plot .kb-shop-svg { position: absolute; inset: 0; width: 100%; height: 100%; margin-top: 0; }
.kb-pt {
  position: absolute; width: 4.5px; height: 4.5px; box-sizing: border-box;
  border-radius: 50%; background: #fff; border: 1.3px solid currentColor;
  transform: translate(-50%, -50%);
}
/* 合并统计期的点（2026-11-09）：「2026.01 数据是 01-02 合并数据」——
   该点代表两个月合计，加一圈外环 + 底部跨度短横，和普通单月点区分开。 */
.kb-pt-span { width: 5.5px; height: 5.5px; box-shadow: 0 0 0 1.6px #fff, 0 0 0 2.6px currentColor; }
.kb-spanbar {
  position: absolute; bottom: 0; height: 0; box-sizing: border-box;
  border-top: 2px solid; border-radius: 1px; opacity: .55;
}
/* 均值行（2026-11-09 用户指令「再在下方增加 2025 年铸铁均值、2026 年铸铁均值等」）：
   位置在「当前值 + 期号」之下、折线图之上 —— 先读当前、再看历史中枢、最后看走势。
   每材料一行（铸铁 / 铸铜各一行），单材料栏（金工）只有一行且不重复材料名。
   均值本身由后端按「年份 + 统计口径」分开汇总（重量加权），与图上断点同一刀切。
   字号 10px：与极值行同量级但更淡，避免和"当前值"抢注意力。 */
/* 均值区槽位（2026-11-09 用户指令「三处图表对齐」）。
   三栏的均值行数本来不同：铸造 2 行（铸铁年均 / 铸铜年均）、金工 1 行、装配 0 行，
   直接顺排会让三张折线图的顶边各差一截，横向比高低时基准就不一致了。
   固定 29px（= 13px 行高 × 2 + 1px 行间距 + 2px 上边距，正好是铸造那两行的高度），
   行数少的栏用空白补齐；用 min-height 而非 height，是为了将来出现第 3 行时撑开而不是裁字。 */
.kb-shop-avgs { flex: none; min-height: 30px; }
.kb-shop-avg {
  flex: none; display: flex; flex-direction: column; gap: 1px; margin-top: 2px;
  font-size: 10px; line-height: 13px; color: #8a95a5;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.kb-shop-avg-r { display: flex; align-items: baseline; gap: 7px; min-width: 0; }
.kb-shop-avg-r i {
  flex: none; width: 6px; height: 6px; border-radius: 2px; transform: translateY(-1px);
}
.kb-shop-avg-r em { font-style: normal; font-size: 10px; color: #6b7a8d; }
.kb-shop-avg-y b { font-weight: 600; color: #4a586b; margin-left: 3px; }
.kb-shop-avg-y small { font-size: 9px; color: #a6b0be; margin-left: -1px; }
/* 图下「高/低」极值行（2026-11-08 三次指令「最大、最小数值显示到看板」）。
   两段平分栏宽：10px 字号下「高 95.90% 25-06」约 78px，栏宽 ~200px 刚好放得下两段。
   刻意不用红绿：三栏量纲不同（% 与 起），"高"对合格率是好、对起数是坏，红绿会误导。 */
.kb-shop-mm {
  flex: none; display: flex; align-items: center; justify-content: flex-start; flex-wrap: wrap;
  gap: 2px 9px; margin-top: 4px; font-size: 10px; line-height: 14px;
  color: #4a586b; font-variant-numeric: tabular-nums; white-space: nowrap;
}
.kb-shop-mm-i { display: inline-flex; align-items: baseline; gap: 3px; min-width: 0; }
/* 图下极值行里的「这条线是哪一条」色点（2026-11-09 铸造两线合并后新增） */
.kb-shop-mm-c {
  flex: none; width: 6px; height: 6px; border-radius: 2px; transform: translateY(-1px);
}
.kb-shop-mm-i b {
  flex: none; font-size: 9px; font-weight: 600; line-height: 13px; padding: 0 3px;
  border-radius: 2px;
}
.kb-shop-mm-i b.up { color: #2f6fd0; background: #eaf1fb; }
.kb-shop-mm-i b.dn { color: #6b7a8d; background: #f1f4f8; }
.kb-shop-mm-i small { font-size: 9px; font-weight: 400; color: #8a95a5; margin-left: -1px; }
.kb-shop-mm-i i { font-style: normal; font-size: 9.5px; color: #a6b0be; }
.kb-shop-ft {
  flex: none; font-size: 10px; color: #98a2b3; line-height: 14px; margin-top: 3px;
  border-top: 1px dashed #edf0f5; padding-top: 3px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.kb-shop-k {
  display: inline-block; width: 7px; height: 7px; border-radius: 2px;
  margin: 0 2px 0 5px; vertical-align: 0;
}
/* x 轴刻度：整卡一条，只标窗口首末两端（三栏时间轴相同，重复标反而不易读）。
   padding 与 .kb-trend3 同为 12px，两端正好落在第一栏起点与第三栏终点。 */
.kb-trend-x {
  flex: none; display: flex; justify-content: space-between;
  padding: 5px 12px 0; font-size: 10px; color: #b0b9c6;
  font-variant-numeric: tabular-nums;
}
.kb-trend3-note {
  flex: none; padding: 2px 12px 7px; font-size: 10.5px; line-height: 15px; color: #98a2b3;
}
@media (max-height: 800px) {
  .kb-shop-plot { height: 96px; }
  .kb-trend-n4 .kb-shop-plot { height: 76px; }
  .kb-shop-svg { max-height: 96px; }
  .kb-shop-val { font-size: 18px; }
}

/* ============ 飞出式子菜单（金蝶云星空风格：点击主菜单 → 右侧面板按分类分列）============ */
/* 2026-11-11（用户指令）：主菜单点击后，子菜单紧贴主菜单右侧弹出，按过程域/分类分列展示 */
#menu-flyout { position: fixed; z-index: 1200; display: none; }
#menu-flyout.show { display: block; animation: mfIn .14s ease; }
@keyframes mfIn { from { opacity: 0; transform: translateX(-6px); } to { opacity: 1; transform: none; } }
#menu-flyout .mf-panel {
  /* 2026-11-11（用户指令「二级菜单改为两行布置」）：由 flex 单排改为 grid 多行。
     列数由 JS 写入 --mf-per（= ceil(分组数 / 2)，G 组 6 个过程域 → 3 列 × 2 行）；
     兜底 1 列（T/B/S 组只有一列，与改造前视觉一致）。
     grid 而非 flex-wrap：同一列跨行共享宽度，竖线上下对齐，不会各行宽窄不齐。 */
  display: grid;
  grid-template-columns: repeat(var(--mf-per, 1), minmax(152px, max-content));
  grid-auto-flow: row;
  /* row-gap 保持 0：竖线才能连续穿过两行；行分隔改由第一行各列的 border-bottom 拼成一条整线
     （列宽跨行共享且列间无间隙，故各列的底边能严丝合缝连成一条），见下方 .mf-r1 / .mf-r2 */
  row-gap: 0; column-gap: 0;
  max-height: 80vh; overflow: auto;
  background: linear-gradient(180deg, var(--sb-bg1) 0%, var(--sb-bg2) 100%);
  border: 1px solid var(--sb-line); border-radius: 10px;
  box-shadow: 0 16px 40px rgba(0, 0, 0, .35); padding: 10px;
}
/* 分隔竖线改由 JS 逐列加 .mf-sep（行内非末列）——分行后 :last-child 只能管整体末列 */
#menu-flyout .mf-col { padding: 2px 14px; min-width: 152px; }
#menu-flyout .mf-col.mf-sep { border-right: 1px solid var(--sb-line); }
/* 两行布置时：第一行加下内边距 + 底边线（拼成整行横线），续行加等量上内边距。
   单列面板（T/B/S 组）不会带 mf-r1/mf-r2，内边距与改造前完全一致。 */
#menu-flyout .mf-col.mf-r1 { padding-bottom: 10px; border-bottom: 1px solid var(--sb-line); }
#menu-flyout .mf-col.mf-r2 { padding-top: 10px; }
#menu-flyout .mf-col:first-child { padding-left: 6px; }
#menu-flyout .mf-col:last-child { padding-right: 6px; }
#menu-flyout .mf-col-title {
  font-size: 11px; letter-spacing: .5px; color: var(--sb-accent); font-weight: 600;
  padding: 6px 8px 8px; white-space: nowrap;
}
#menu-flyout .mf-item {
  display: flex; align-items: center; padding: 7px 8px; border-radius: 6px; cursor: pointer;
  color: var(--sb-ink); font-size: 13px; white-space: nowrap;
}
#menu-flyout .mf-item:hover { background: var(--sb-hover); color: #fff; }
#menu-flyout .mf-txt { min-width: 0; }
.menu-item.mi-parent.mf-open { background: var(--sb-active); color: #fff; }
.menu-item.mi-parent.mf-open .mi-arrow,
.menu-item.mi-parent.mf-open .mi-caret { color: #cfe0ff; }

/* ============ 2026-11-11（用户指令）：G14 全流程实时预览框 + 锁定列样式 ============ */
.rf-g14-fp { margin: 10px 2px 2px; padding: 10px 14px; border: 1px dashed var(--sb-accent, #3a7afe); border-radius: 8px; background: rgba(58, 122, 254, .06); }
.rf-g14-fp-title { font-size: 12px; color: var(--sb-accent, #3a7afe); margin-bottom: 8px; }
.rf-g14-fp-row { display: flex; flex-wrap: wrap; gap: 18px; align-items: baseline; }
.rf-g14-fp-row span { font-size: 12px; color: #888; margin-right: 4px; }
.rf-g14-fp-row b { font-size: 15px; color: #222; margin-right: 8px; font-weight: 600; }
.rf-g14-fp-row b.ok { color: #1a9e4b; }
.rf-ro-lock { color: #c0392b !important; }

/* ============ 2026-11-11（用户指令）：G14 改为「每月 1 行 / 铸铁 + 铸铜两组」的弹窗版式 ============ */
/* 物料区表头带：一行一个物料，五列 = 周转 / 料废 / 铸造率 / 工废 / 金工率 */
.t20-sheet.t20-mat { margin-top: 12px; }
.t20-sheet .t20-hd td {
  background: #e2e9f4; color: #1f2c3d; font-weight: 600; text-align: center;
  white-space: normal; line-height: 1.25; padding: 6px 4px; font-size: 12.5px;
}
.t20-sheet .t20-hd .t20-hd-mat { width: 14%; background: #d5e0f0; }
.t20-sheet .t20-mat-name {
  background: #f4f7fc; font-weight: 600; text-align: center; color: #1f2c3d;
  font-size: 13px; letter-spacing: .5px;
}
.t20-sheet .rf-v { padding: 4px 6px; }
.t20-sheet .rf-v .rf-static.rf-ro-rate { font-weight: 600; color: #1a7f45; }

/* ============ 2026-11-13（用户指令）：B BOM清单 / S 基础设置 由整屏弹窗改为主区内嵌视图 ============
   #admin-modal 已移入 <main class="main">，成为 #welcome / #table-view 之外的第三个视图；
   与二者互斥显隐，侧栏 .sidebar 不再被全屏遮罩盖住，始终常驻可见可点。
   以下规则覆盖文件前部「.modal 遮罩 + 100vw×100vh 整屏」的旧定义；
   所有以 #admin-modal 为前缀的内部布局规则（pane 撑满、表格内部滚动等）继续原样生效。 */
#admin-modal {
  position: static; inset: auto; z-index: auto;
  background: transparent;                 /* 去掉 rgba(20,30,45,.45) 全屏遮罩 */
  display: flex; align-items: stretch; justify-content: stretch;
  flex: 1 1 auto; min-height: 0; height: auto; box-sizing: border-box;
}
#admin-modal .modal-box {
  width: 100%; height: 100%; max-width: none; max-height: none;
  flex: 1 1 auto; min-width: 0;
  border: 1px solid var(--line); border-radius: 10px; box-sizing: border-box;
  box-shadow: 0 2px 10px rgba(20, 40, 80, .05);
  overflow: hidden;                        /* 圆角裁切标题栏 */
}
#admin-modal .modal-head { background: #fff; flex: 0 0 auto; }
#admin-modal .admin-body { border-radius: 0 0 10px 10px; }
