:root {
  /* 颜色体系（清新 Air 风格 + 蓝色主色；单一主色 + 语义色，禁止混用杂色） */
  --c-bg: #f7f9fc;
  --c-bg-2: #f1f5f9;
  --c-surface: #ffffff;
  --c-border: #e3e8f0;
  --c-text: #1e293b;
  --c-text-2: #475569;
  --c-muted: #64748b;
  --c-primary: #2f80ed;
  --c-primary-d: #1a66c4;
  --c-primary-bg: #e8f1fd;
  --c-danger: #e5484d;
  --c-danger-bg: #fcebeb;
  --c-success: #2f7d32;
  --c-success-bg: #e8f5e9;
  --c-warn: #a05a00;
  --c-warn-bg: #fdf3e3;
  /* 警示档描边**分两档**（2026-10-07 批 3 · Lead 裁定："并的是字面量，不是外观"）：
     按钮描边用一个值、小标签/小旗描边用另一个值 —— 各自保持原值 ⇒ 视觉位移 Δ=0 */
  --c-warn-bd: #e0b36a;      /* 按钮档（.btn.clear 原本就是这个值） */
  --c-warn-bd-2: #ffd9a0;    /* 小标签/小旗档（.tag.warn / .cat-flag.report / NOT SUBMITTED 徽标原本就是这个值） */
  --c-warn-bd-3: #f0c96b;    /* 草稿横幅档（原 draft-banner 规则用的就是它；该规则 2026-10-08 批 2b 已删） */
  --c-warn-bg-2: #f7e7c8;    /* .btn.clear:hover 原本就是这个值 */
  --c-warn-bg-3: #f0dcb0;    /* .btn.clear:active 原本就是这个值 */
  --c-warn-soft: #8a6d1f;    /* ⚠ A1 的**软提醒**色（`.field-msg.soft` ＝"可以不管"那一级）：值**不变**，
                                只是上了令牌 ⇒ 别把它和上面的警示档混用（语义不同） */
  --c-primary-bd: #bcd6f7;   /* 主色描边（按钮 `.btn-back` / `.btn.soft` 原本就是这个值） */
  --c-primary-bd-2: #8fbcff; /* 主色悬停描边（`.btn-back:hover` 原本就是这个值） */
  /* ⚠ 教训（2026-10-07 批 3，同类坑踩了两次）：**批量把字面量换成令牌时，必须跳过 `--token:` 定义行**，
     否则会把令牌自己的值也换成 `var(自己)`（`--c-warn-soft` / `--c-primary-soft` 都中过招）。 */
  --c-primary-soft: rgba(47, 128, 237, .08);   /* 主色 8% 淡底（`.btn-add` ＋ 照片位同色覆盖；Lead 裁定 1） */
  /* A4 严口径（2026-10-07 批 4 · C2）：透明度变体不再散在文件里，按用途归族 ——
     **alpha 写法统一用简写**（`.22`，不写 `0.22`）；同族原本两个 alpha 的各留一枚（并值 ≠ 改样）。 */
  --c-primary-a22: rgba(47, 128, 237, .22);   /* 文本选区 ::selection */
  --c-primary-a18: rgba(47, 128, 237, .18);   /* 聚焦环（原 photo-prev:hover 等用的就是它） */
  --c-primary-a16: rgba(47, 128, 237, .16);   /* 淡底叠加（.btn-add:hover · .photo-field.on） */
  --c-primary-a12: rgba(47, 128, 237, .12);   /* 日期轮高亮带 */
  --c-danger-a18: rgba(229, 72, 77, .18);     /* 危险色聚焦环 */
  --c-danger-a12: rgba(229, 72, 77, .12);     /* 危险色淡底 */
  --c-scrim-a40: rgba(15, 23, 42, .4);        /* 遮罩·浅 */
  --c-scrim-a45: rgba(15, 23, 42, .45);       /* 遮罩·中（弹窗/抽屉/日期轮） */
  --c-scrim-a82: rgba(15, 23, 42, .82);       /* 遮罩·深（图片查看） */
  --shadow-a2: rgba(0, 0, 0, .2);             /* 黑阴影·浅 */
  --shadow-a25: rgba(0, 0, 0, .25);           /* 黑阴影·中 */
  --shadow-a4: rgba(0, 0, 0, .4);             /* 黑阴影·深 */
  --shadow-a5: rgba(0, 0, 0, .5);             /* 黑阴影·最深 */
  --shadow-a04: rgba(15, 23, 42, .04);        /* 深蓝阴影·极浅（卡片投影） */
  --shadow-inset: rgba(16, 24, 40, .05);      /* 内阴影（搜索框凹陷感） */
  --c-info: #6a3fbf;         /* 紫 ＝ 有语义的第三方色（「需填板上位号」徽标）· Lead 2026-10-07 定论 */
  --c-info-bg: #efe9fd;
  --c-info-bd: #d9ccf5;
  --c-success-bd: #b6e6c6;   /* 成功档描边（`.tag.ok` 原本就是这个值） */
  --c-success-bd-2: #9ed3ac; /* 成功档描边·另一档（`.photo-field.on` 原本就是这个值） */
  --c-border-2: #c7d0da;     /* 中性灰·深一档（照片虚线框 / 顶栏分隔符原本就是这个值） */
  --c-scroll: #cdd5df;       /* 滚动条拇指（⑫ 的那套"滚动时才上色"靠它；并进 --c-border 会变浅看不出来） */
  --c-scroll-hover: #b6c0cd;
  /* 圆角体系：控件 10 / 卡片 14 / 弹窗大容器 18（Air 风更圆润） */
  --radius-sm: 10px;
  --radius: 14px;
  --radius-lg: 18px;
  /* 阴影：轻盈柔和 + 偏移，不用纯黑 */
  --shadow: 0 1px 2px rgba(30, 41, 59, .04), 0 2px 6px rgba(30, 41, 59, .06);
  --shadow-lg: 0 12px 32px rgba(30, 41, 59, .14);
  /* 聚焦环 */
  --ring: 0 0 0 3px rgba(47, 128, 237, .18);
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;
  background: var(--c-bg);
  color: var(--c-text);
  font-size: 14px;
  line-height: 1.5;
  -webkit-tap-highlight-color: transparent; /* 手机点按去掉默认灰块 */
}

.hidden { display: none !important; }

/* 浏览器表面主题化（最便宜的"认真做过"信号）：选区 / 光标 / 键盘聚焦 / 滚动条 */
::selection { background: var(--c-primary-a22); }
input, textarea { caret-color: var(--c-primary); }
:focus-visible { outline: 2px solid var(--c-primary); outline-offset: 2px; }
@media (min-width: 768px) {
  ::-webkit-scrollbar { width: 10px; height: 10px; }
  ::-webkit-scrollbar-track { background: transparent; }
  ::-webkit-scrollbar-thumb { background: var(--c-scroll); border-radius: 5px; border: 2px solid var(--c-bg); }
  ::-webkit-scrollbar-thumb:hover { background: var(--c-scroll-hover); }
}
/* 触觉反馈：可点元素按下轻微收缩 */
.btn:active, .nav-item:active, .ps-item:active, .cat-sub-row:active,
.chk:active, .emp-loc-card:active { transform: scale(0.98); }

/* ---------- 登录屏 ---------- */
.login-screen {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(135deg, var(--c-primary-bg) 0%, var(--c-bg) 100%);
}
.login-card {
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  width: 380px;
  padding: 32px 28px;
}
.login-logo {
  font-size: 22px;
  font-weight: 600;
  color: var(--c-primary-d);
  margin-bottom: 4px;
}
.login-sub {
  color: var(--c-muted);
  font-size: 13px;
  margin-bottom: 22px;
}
.field { margin-bottom: 14px; }
.field label {
  display: block;
  font-size: 12px;
  color: var(--c-muted);
  margin-bottom: 6px;
}
.field input, .field select {
  width: 100%;
  padding: 9px 11px;
  border: 1px solid var(--c-border);
  border-radius: var(--radius-sm);   /* G2（2026-10-07 批 1）：8 → 10，与列表筛选 / .date-wheel / .modal select 同值 */
  font-size: 14px;
  background: var(--c-surface);
  color: var(--c-text);
}
/* 占位符统一：输入框与下拉框的 "-----Please select-----" 显示完全一致（字体/字号/颜色） */
input::placeholder, textarea::placeholder { color: var(--t-3); }
select option { color: var(--c-text); }
select:has(option[data-ph="1"]:checked) { color: var(--t-3); }
.field input:focus, .field select:focus {
  outline: none;
  border-color: var(--c-primary);
  box-shadow: var(--ring);
}
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 9px 16px;
  border: 1px solid transparent;
  border-radius: 8px;
  font-size: 14px;
  cursor: pointer;
  background: var(--c-primary);
  color: var(--c-surface);
}
.btn:hover { background: var(--c-primary-d); }
.btn.block { width: 100%; }
.btn.ghost { background: var(--c-surface); color: var(--c-text); border-color: var(--c-border); }
.btn.ghost:hover { background: var(--c-bg); }
.btn.ghost.on { background: var(--c-primary); color: var(--c-surface); border-color: var(--c-primary); }
/* 清空筛选按钮：琥珀橙描边，与普通 ghost 区分 */
.btn.clear { background: var(--c-warn-bg); color: var(--c-warn); border-color: var(--c-warn-bd); }
.btn.clear:hover { background: var(--c-warn-bg-2); }
.btn.clear:active { background: var(--c-warn-bg-3); }
.btn.danger { background: var(--c-danger); }
.login-hint {
  margin-top: 16px;
  font-size: 12px;
  color: var(--c-muted);
  background: var(--c-bg);
  border-radius: 8px;
  padding: 10px 12px;
}
.login-hint b { color: var(--c-text); }

/* ---------- 主框架 ---------- */
.app { display: flex; min-height: 100vh; }
.sidebar {
  width: 220px;
  background: var(--c-surface);
  border-right: 1px solid var(--c-border);
  color: var(--c-text-2);
  flex-shrink: 0;
  padding: 18px 12px;
  display: flex;
  flex-direction: column;
}
.sidebar .brand {
  font-size: 15px;
  font-weight: 700;
  color: var(--c-primary-d);
  padding: 4px 10px 18px;
}
.nav-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  color: var(--c-text-2);
  font-size: 14px;
  margin-bottom: 6px;
  /* 2026-10-07 用户：「左侧的列表里，不同的版块的按键，你做一个边框的效果」⇒
     每个版块 ＝ 一枚带边框的按键（浅描边 ＋ 白底；悬停描边转主色，沿用全站 `.ps-item:hover` 那套语言）。
     ⚠ 全站唯一样式：只改这一处，侧栏每一项都跟着变（`.nav-item` 同时用在菜单项与 Log out 上）。 */
  border: 1px solid var(--c-border);
  background: var(--c-surface);
}
.nav-item:hover { background: var(--c-bg-2); color: var(--c-text); border-color: var(--c-primary); }
/* 当前页：主色实底 ⇒ 描边同色，不留一圈浅灰 */
.nav-item.active { background: var(--c-primary); color: var(--c-surface); border-color: var(--c-primary); }
.nav-foot { margin-top: auto; font-size: 12px; color: var(--c-muted); padding: 8px 10px; }

/* 2026-10-07 用户：「左侧的列表需要做一个可以上下滑动的设计」（板块多了会展示不全）⇒
   侧栏拆三段：**品牌固定 · 菜单可滚 · 底部固定**（手机抽屉共用同一套）。
   滚动条不另造：沿用全站那套 `::-webkit-scrollbar`（10px · var(--c-scroll) 拇指）。 */
.sidebar .brand { flex: 0 0 auto; }
.nav-foot { flex: 0 0 auto; }
/* A7（2026-10-07 批 1）：侧栏「重置演示数据」原来写死 inline `padding:3px 8px;font-size:11px` ⇒ 全站唯一的 **24px** 档 ✗
   ⇒ 改走**主档 44px / 13px**（与页面内 `.btn` 同值）。
   ⚠ 为什么不走"小号档"：`.perm-tool .btn{height:30px}` 被 `#page button.btn{min-height:var(--ctl-h)!important}` 压着，
     权限页那种紧凑按钮**实测就是 44px** ⇒ 站内**实际只有一档**（44）；A7 判据也按"与实测基准一致"来判。
     （要把 30px 档真正复活属批 3 的一致性收口，本轮不动权限页外观。） */
.nav-foot .btn { height: var(--ctl-h); min-height: var(--ctl-h); padding: 0 10px; font-size: 13px; margin-top: 6px; }
.nav-list {
  flex: 1 1 auto;
  min-height: 0;                 /* flex 子项默认 min-height:auto ⇒ 不加这条不会出现滚动条 */
  overflow-y: auto;
  overscroll-behavior: contain;  /* 滚到底不把整页带着一起滚 */
}
/* 侧栏滚动条「只在滚动时出现」（2026-10-07 用户：「当我上下滚动时它才出现，我不滚动时不要出现」）——
   自绘滚动条（`::-webkit-scrollbar`）在 Chrome 里**会常显**（不滚动也挂着一条），所以拇指默认**透明**、
   只在 `.is-scrolling`（由 `navScrollbarAutoHide()` 在滚动时加）时上色；轨道透明 ⇒ 位置不发散、**开关时不跳布局**。
   ⚠ **放在媒体查询之外**：抽屉是手机端（≤768px）才有的形态，而全站那套 `::-webkit-scrollbar` 只在 ≥768px 生效
   ⇒ 不写在这里，手机抽屉里就是浏览器默认的常显滚动条（用户看到的就是这条）。 */
.nav-list::-webkit-scrollbar { width: 10px; }
.nav-list::-webkit-scrollbar-track { background: transparent; }
.nav-list::-webkit-scrollbar-thumb { background: transparent; border-radius: 5px; border: 2px solid transparent; }
.nav-list.is-scrolling::-webkit-scrollbar-thumb { background: var(--c-scroll); border: 2px solid var(--c-bg); }
/* 桌面端（≥769px）**把侧栏钉在视口高度** —— 不钉的话 `.app{min-height:100vh}` 的 `align-items:stretch`
   会让侧栏**跟着内容一起长**（实测长到 1981px）⇒ 菜单区永远不出现滚动条、底部还会被顶出屏幕。
   钉住之后：品牌固定 · 菜单可滚 · 底部固定。手机端另有 `position:fixed` 抽屉规则，不受影响。 */
@media (min-width: 769px) {
  .sidebar { position: sticky; top: 0; height: 100vh; align-self: flex-start; }
}

.content { flex: 1; display: flex; flex-direction: column; min-width: 0; }
.topbar {
  height: 56px;
  background: var(--c-surface);
  border-bottom: 1px solid var(--c-border);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 22px;
  /* 吸顶固定：长页面滚动时顶栏（含 ☰ 菜单按钮）始终可见 */
  position: -webkit-sticky;
  position: sticky;
  top: 0;
  z-index: 40;
}
.topbar .title { font-size: 16px; font-weight: 600; cursor: pointer; }
.topbar .title:hover { color: var(--c-primary); }
.topbar .user { font-size: 13px; color: var(--c-muted); display: flex; align-items: center; gap: 10px; }
.role-tag {
  display: inline-block;
  padding: 2px 8px;
  border-radius: var(--radius-sm);   /* G3（批 3）：6 → 10，与 .tag / .cat-flag 同档 */
  font-size: 12px;                   /* G3：11 → 12（判据要求三处同值） */
  background: var(--c-primary);
  color: var(--c-surface);
}
.page { padding: 22px; flex: 1; overflow: auto; }

/* ---------- 卡片 / 表格 ---------- */
.card {
  /* 2026-10-06 用户：「**外层容器的底色这个，我要改的就是这个**」＋「**改为浅灰**」＋「**如果跟其它的部分通用，就一起改**」
     ⇒ **`.card` ＝ 每个页面的外层容器（那张"大白纸"）**，是**全站通用类** ⇒ **一条规则、全站外层容器一起改浅灰**（`--c-bg-2``）。
     ⚠ 连带效果（正是用户要的）：容器变浅灰后，里面的**白卡**（`.vitem` / `.field` / 各种子卡）**自然浮出来**；
       —— 因为**间距本身是透明的**，"卡与卡之间看到的颜色"就是**这层容器的底色**。 */
  background: var(--c-bg-2);
  border: 1px solid var(--c-border);
  border-radius: var(--radius);
  padding: 18px;
  margin-bottom: 18px;
  box-shadow: var(--shadow);
  overflow-x: hidden;
}
.card h3 { margin: 0 0 14px; font-size: 14px; }   /* G7-2（2026-10-07 批 4）：卡片标题统一 14px ——
   报表页「近期流水（最新 N 条）」原来 15px、与其它卡片标题不同档（`.card h3` 是全站唯一规则 ⇒ 改一处全站一致）。 */
.grid { display: grid; gap: 14px; }
.grid-2 { grid-template-columns: 1fr 1fr; }
.grid-3 { grid-template-columns: repeat(3, 1fr); }
.grid-4 { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 900px) { .grid-2,.grid-3,.grid-4 { grid-template-columns: 1fr; } }

.stat {
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: var(--radius);
  padding: 16px;
  box-shadow: var(--shadow);
}
.stat .num { font-size: 26px; font-weight: 600; }
.stat .lbl { font-size: 12px; color: var(--c-muted); margin-top: 4px; }

table { width: 100%; border-collapse: collapse; font-size: 13px; table-layout: fixed; }
th, td { text-align: left; padding: 10px 12px; border-bottom: 1px solid var(--c-border);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
th { color: var(--c-muted); font-weight: 500; background: var(--c-bg-2); }
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; }
tr:hover td { background: var(--c-bg-2); }

.toolbar { display: flex; gap: 10px; align-items: center; margin-bottom: 14px; flex-wrap: wrap; }
.toolbar .spacer { flex: 1; }
/* 工具栏分区：操作按钮组（第一行，靠右）+ 筛选行（第二行，均匀分布） */
.tb-actions { display: inline-flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.tb-filters { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin-bottom: 14px; }
.tb-filters select { flex: 1 1 130px; min-width: 0; }
.tb-filters .search { flex: 2 1 200px; min-width: 0; }
.tb-filters .date-wheel { flex: 1 1 130px; min-width: 0; min-height: var(--ctl-h); }   /* A2②（2026-10-07 批 1）：44px 原来只在媒体查询里 ⇒ 桌面 40px */
/* 页面说明文字：提示条式（浅灰底圆角小字），避免干扰主体内容观感 */
.card > p.muted { font-size: 12px; line-height: 1.55; color: var(--c-muted); background: var(--c-bg-2); border-radius: var(--radius-sm); padding: 8px 12px; margin: 0 0 14px; }
/* 搜索框：胶囊形 + 放大镜图标，与筛选下拉明显区分 */
.search {
  /* A2①（2026-10-07 批 1）：原来 44px 只写在移动端媒体查询里 ⇒ 桌面 33px。提到全站（胶囊圆角 999 不动）。 */
  min-height: var(--ctl-h);
  padding: 8px 14px 8px 36px;
  border: 1px solid var(--c-border);
  border-radius: 999px;
  background: var(--c-surface) url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 14 14'%3E%3Ccircle cx='6' cy='6' r='4.5' stroke='%2394a3b8' stroke-width='1.6' fill='none'/%3E%3Cpath d='M9.5 9.5L13 13' stroke='%2394a3b8' stroke-width='1.6' stroke-linecap='round'/%3E%3C/svg%3E") no-repeat 13px center;
  box-shadow: inset 0 1px 2px var(--shadow-inset);
  font-size: 13px;
  min-width: 200px;
}
.search:focus { outline: none; border-color: var(--c-primary); box-shadow: var(--ring); }
/* C1（2026-10-07 批 4）：**表单控件的文字色**统一 —— `.search`（胶囊搜索框）与 `input[type=checkbox]`
   从来没设过 `color` ⇒ 落到**浏览器表单默认黑**（搜索框里打的字是纯黑，而设计口径是 `--t-1 #1e293b`）。
   test-eng 批 3 实测 **8 个采样控件**命中该默认黑（4 个 `.search` ＋ 4 个 checkbox）
   ⇒ 按 Lead 裁定写在**更广的基线**上一处覆盖两类；placeholder 走 `--t-3`（更具体，不受影响）；
   禁用态 `select:disabled` 也仍走 `--t-3`。 */
input, select, textarea { color: var(--t-1); }

.row-form { display: grid; grid-template-columns: repeat(2, 1fr); gap: 14px; }
.row-form .full { grid-column: 1 / -1; }

.badge {
  display: inline-block;
  padding: 2px 8px;
  /* G7-1（2026-10-07 批 4）：状态徽标家族第 4 套（6px/11px）并到 10px/12px ——
     与 `.tag` / `.cat-flag` / `.role-tag` 同档（同类东西一个值）。 */
  border-radius: var(--radius-sm);
  font-size: 12px;
}
.badge.low { background: var(--c-warn-bg); color: var(--c-warn); }
.badge.ok { background: var(--c-success-bg); color: var(--c-success); }
.badge.out { background: var(--c-danger-bg); color: var(--c-danger); }

/* ---------- 提示条 ---------- */
.toast {
  position: fixed;
  bottom: 24px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--c-text);
  color: var(--c-surface);
  padding: 11px 18px;
  border-radius: 8px;
  font-size: 13px;
  box-shadow: 0 4px 14px var(--shadow-a2);
  z-index: 99;
}
.toast.err { background: var(--c-danger); }
.toast.ok { background: var(--c-success); }

.empty { color: var(--c-muted); text-align: center; padding: 40px; }
.muted { color: var(--c-muted); }
/* 工单内统一 "+ Add" 按钮：虚线主色描边，区别于普通按钮 */
.btn-add {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  padding: 8px 16px; border-radius: 8px;
  border: 1px dashed var(--c-primary);
  background: var(--c-primary-soft);
  color: var(--c-primary);
  font-size: 13px; font-weight: 600; cursor: pointer;
}
.btn-add:hover { background: var(--c-primary-a16); }
/* Repair Times 可点击（查看历史维修） */
.pill.clickable { cursor: pointer; color: var(--c-primary); text-decoration: underline; text-underline-offset: 2px; }
/* 历史维修弹窗卡片 */
.wo-hist-sec b { font-size: 13px; color: var(--c-muted); display: block; margin: 10px 0 6px; }
.wo-hist-sec:first-child b { margin-top: 0; }
.wo-hist-card { border: 1px solid var(--c-border); border-radius: 10px; padding: 10px 12px; margin-bottom: 8px; background: var(--c-surface); }
.wo-hist-card.brief { border-style: dashed; background: var(--c-bg-2); }
.wo-hist-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 6px; gap: 8px; }
.wo-hist-head b { font-size: 13px; color: var(--c-text); }
.wo-hist-row { display: flex; gap: 8px; font-size: 12px; padding: 2px 0; }
.wo-hist-row .k { color: var(--c-muted); min-width: 56px; flex-shrink: 0; }
.wo-hist-row .v { color: var(--c-text-2); }
.pill { font-size: 12px; color: var(--c-muted); border-radius: var(--radius-sm); }   /* G7-3（批 4）：
   只读值胶囊原来**没有任何圆角**（0px）⇒ 提为 10px。⚠ 这是**统一**（站内同类胶囊控件都是 10px），不是回退。 */

/* ---------- 移动端适配（海外员工主要用手机，PRD PWA） ---------- */
.menu-btn {
  display: none;
  background: none;
  border: 0;
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  color: var(--c-text);
  padding: 4px 8px;
}
.mask {
  position: fixed;
  inset: 0;
  background: var(--c-scrim-a40);
  z-index: 40;
}
@media (max-width: 768px) {
  .menu-btn { display: inline-flex; }
  .sidebar {
    position: fixed;
    left: 0;
    top: 0;
    bottom: 0;
    z-index: 50;
    width: 240px;
    transform: translateX(-100%);
    transition: transform 0.2s ease;
  }
  .sidebar.open { transform: none; }
  .login-card { width: calc(100vw - 40px); }
  .page { padding: 14px; }
  .card { padding: 14px; overflow-x: hidden; }
  .grid-2, .grid-3, .grid-4 { grid-template-columns: 1fr; }
  .toolbar .search { min-width: 0; flex: 1; }
  .stat .num { font-size: 22px; }
  .row-form { grid-template-columns: 1fr; }
  /* 移动端触控目标（≥44px，手指友好）与可读性 */
  body { font-size: 13px; }   /* 批 7：正文档 13px（原 15） */
  .btn { min-height: var(--ctl-h); }   /* 批 7：主按钮档（44）走令牌 */
  .nav-item { min-height: 46px; }
  .field input, .field select { padding: 12px 11px; }
  select { min-height: 44px; padding: 10px 32px 10px 12px; }
  /* 筛选行手机端：下拉两列、搜索占整行 */
  .tb-filters select { flex: 1 1 46%; }
  .tb-filters .search { flex: 1 1 100%; }
  .tb-filters .date-wheel { flex: 1 1 46%; }
  /* 盘点行手机端：右侧换行到第二行，横排靠右，不再挤压三行文字 */
  .cnt-side { width: 100%; margin-left: 0; flex-direction: row; align-items: center; justify-content: flex-end; gap: 8px; }
  /* iOS 安全区（底部刘海 / 手势条） */
  .page { padding-bottom: calc(14px + env(safe-area-inset-bottom)); }
  .toast { bottom: calc(24px + env(safe-area-inset-bottom)); }
}

/* ---------- 详情弹窗（点击行查看完整内容） ---------- */
.modal-mask {
  position: fixed; inset: 0;
  background: var(--c-scrim-a45);
  z-index: 60;
  display: flex; align-items: center; justify-content: center;
  padding: 16px;
}
.modal {
  background: var(--c-surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  width: 460px; max-width: 100%;
  max-height: 86vh; overflow: auto;
  padding: 18px 20px;
}
.modal h3 {
  /* 弹窗标题行吸顶：内容滚动时标题与 × 始终可见（详情类长弹窗通用） */
  position: -webkit-sticky;
  position: sticky;
  top: 0;
  z-index: 5;
  background: var(--c-surface);
  padding: 14px 0 10px;
  margin: 0 0 12px;
  border-bottom: 1px solid var(--c-border);
  font-size: 16px;
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.modal .x { cursor: pointer; color: var(--c-muted); font-size: 22px; line-height: 1; padding: 0 4px; }
/* ---------- 新建工单独立浮层（与详情弹窗分离：z-index 低于 modal-mask，嵌套的「选择使用备件/确认备件」弹窗可叠加在上面，不会被 closeModal 误关） ---------- */
/* 工单表单标题栏吸顶：长页面滚动时标题与 × 关闭按钮始终可见（移动端方便随时关闭） */
.detail-row { display: flex; gap: 10px; padding: 7px 0; border-bottom: 1px dashed var(--c-border); font-size: 13px; }
.detail-row:last-child { border-bottom: 0; }
.detail-k { width: 110px; color: var(--c-muted); flex-shrink: 0; }
.detail-v { flex: 1; word-break: break-word; min-width: 0; }
.detail-v a { color: var(--c-primary); }

/* ---------- 图片点击放大（lightbox） ---------- */
.img-zoom-mask {
  position: fixed; inset: 0;
  background: var(--c-scrim-a82);
  z-index: 90;
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
  cursor: zoom-out;
}
.img-zoom-box { position: relative; max-width: 94vw; max-height: 94vh; }
.img-zoom-img {
  display: block;
  min-width: 88vw;        /* 手机端小图也放大到占满屏宽（不再显示原尺寸小图） */
  max-width: 94vw;        /* 最大不超过视口宽 */
  max-height: 92vh;       /* 最大不超过视口高 */
  width: auto;            /* 宽度按比例自适应，保持原图比例不拉伸 */
  height: auto;
  object-fit: contain;    /* 触发 max 限制时仍按原比例完整显示，绝不拉伸 */
  border-radius: 10px;
  box-shadow: 0 12px 40px var(--shadow-a5);
  background: var(--c-surface);
}
/* 电脑端（≥768px）：大图再放大约 3 倍（接近满屏），比例不变；手机端维持现状 */
@media (min-width: 768px) {
  .img-zoom-img {
    min-width: 60vw;      /* 小图也放大到约视口 60% 宽 */
    max-width: 94vw;
    max-height: 94vh;
  }
}
.img-zoom-x {
  position: absolute; top: -14px; right: -14px;
  width: 36px; height: 36px; border-radius: 50%;
  background: var(--c-surface); color: var(--c-text); font-size: 24px; line-height: 34px;
  text-align: center; cursor: pointer;
  box-shadow: 0 2px 10px var(--shadow-a4); font-weight: bold;
}

/* ---------- 滚轮日期选择器（禁止手填；样式与 select 统一：白底/同高/同圆角/箭头） ---------- */
/* 批 7 §三-c（2026-10-09）：日期框**字号一律 13px**（原 14）；圆角 10（--radius-sm）与配色不变；
   筛选栏内仍 44px（A2 不动）· 表单内 38px（见 `#page .field .date-wheel` 那组）。 */
.date-wheel {
  cursor: pointer;
  min-height: 40px;
  line-height: 1.4;
  padding: 8px 32px 8px 12px;
  border: 1px solid var(--c-border);
  border-radius: var(--radius-sm);
  background-color: var(--c-surface);
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'><path d='M1 1l5 5 5-5' stroke='%235b6572' stroke-width='1.6' fill='none' stroke-linecap='round'/></svg>");
  background-repeat: no-repeat;
  background-position: right 12px center;
  font-size: 13px;   /* 批 7 §三-c：日期框字号一律 13px（原 14） */
  color: var(--c-text);
  max-width: 100%;
}
.date-wheel:focus { outline: none; border-color: var(--c-primary); }
.wheel-sheet-mask { position: fixed; inset: 0; background: var(--c-scrim-a45); z-index: 70; display: flex; align-items: flex-end; }
.wheel-sheet { background: var(--c-surface); width: 100%; max-width: 480px; margin: 0 auto; border-radius: 14px 14px 0 0; padding: 8px 0 14px; box-shadow: 0 -6px 24px var(--shadow-a2); }
.wheel-head { display: flex; justify-content: space-between; align-items: center; padding: 8px 16px 10px; font-size: 13px; }   /* 批 7 §三-c：日期轮内部并入统一（15→13）*/
.wheel-clear { text-align: right; padding: 0 16px 6px; }
.wheel-cols { position: relative; display: flex; height: 180px; padding: 0 12px; }
.wheel-col { flex: 1; overflow-y: auto; scroll-snap-type: y mandatory; -webkit-overflow-scrolling: touch; padding: 72px 0; text-align: center; position: relative; z-index: 1; }
.wheel-col .wi { height: 36px; line-height: 36px; scroll-snap-align: center; color: var(--c-muted); font-size: 16px; position: relative; }
.wheel-col .wi.sel { color: var(--c-text); font-weight: 600; font-size: 19px; }
.wheel-highlight { position: absolute; top: 72px; left: 12px; right: 12px; height: 36px; background: var(--c-primary-a12); border-top: 1px solid var(--c-primary); border-bottom: 1px solid var(--c-primary); border-radius: 6px; pointer-events: none; }

/* ---------- 工单分区 ---------- */
.wo-section {
  /* 与采购/调拨/盘点新建页统一：无边框无底色，仅用留白分区（背景=卡片白底） */
  margin: 0 0 16px;
}
.wo-section > b { display: block; margin-bottom: 10px; color: var(--c-text); font-size: var(--fs-sec); font-weight: 600; }   /* 批 7：17 → --fs-sec(15) */
/* ⚠ 2026-10-06 起 **界面不再显示段标题**（用户：把 A 后面的 work order info 也去掉）⇒ 本节两条 `.wo-section > b` 规则
   **已无匹配元素**，保留作历史（另一条在 ~L1341，记录「标题被照片瓦片压住」的 z-index 修复）。留白改由 `.wo-section { margin }` 承担。 */
.wo-part-row { border-bottom: 1px dashed var(--c-border); padding-bottom: 8px; margin-bottom: 8px; }
.wo-part-row:last-child { border-bottom: 0; }
.req { color: var(--c-danger); margin-left: 2px; }
.wo-dyn { grid-column: 1 / -1; display: grid; grid-template-columns: repeat(2, 1fr); gap: 14px; }
/* 审批块改中性样式（2026-10-05 用户：“这个底色，不好看，你改一下颜色和样式”）：
   原来用 --c-warn/--c-warn-bg（琥珀）⇒ 看起来像“警告”；改为**中性浅灰分组块 ＋ 左侧细色条**，更像“审批信息分组”。 */
.wo-bigblock {
  grid-column: 1 / -1;
  /* 与 .card **同一套设计变量**（2026-10-05 用户：“这个可以去掉，感觉不是很统一风格。你有没有更好的方案”）：
     白底 · 同色细边 · 同圆角 · 同投影 —— 不再用任何色条/底色，风格与全站卡片一致。 */
  /* 2026-10-05 用户：“审批块已改为中性样式，这个你再改一下，加个底色”
     ⇒ 底色改用系统已有的浅灰变量 --c-bg-2，与全站一致，仍**不用警告色**；内部输入框保持白底以形成层次。 */
  background: var(--c-bg-2); border: 1px solid var(--c-border);
  border-radius: var(--radius); box-shadow: var(--shadow);
  padding: 14px 16px;
  display: grid; grid-template-columns: repeat(2, 1fr); gap: 14px; margin-top: 6px;}
.wo-bigblock .field.full { grid-column: 1 / -1; }
@media (max-width: 768px) { .wo-dyn, .wo-bigblock { grid-template-columns: 1fr; } }

/* 更换项编号 + 行头 */
.btn.sm { height: var(--ctl-h-row); min-height: var(--ctl-h-row); padding: 0 10px; font-size: 13px; border-radius: 8px; }   /* 批 7 §三-b：行内小档 32px · **唯一内边距 0 10px**（页面级覆盖已删）*/

/* 备件搜索弹窗 */
.ps-toolbar { margin-bottom: 8px; }
.ps-item { padding: 9px 12px; border: 1px solid var(--c-border); border-radius: 8px; margin-bottom: 6px; cursor: pointer; }
.ps-item:hover { border-color: var(--c-primary); background: var(--c-bg); }
.ps-item.whole { border-color: var(--c-primary); background: var(--c-primary-bg); }
.ps-item .muted { font-size: 12px; margin-top: 2px; }
/* 二级分类（备件分类页）：一行一个，缩进展示 + 右侧改/删按钮 */
.cat-sub-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 3px 0 3px 14px; font-size: 12px; color: var(--c-text); border-left: 2px solid var(--c-border); margin: 2px 0 2px 4px; }
.cat-sub-row .sub-right { display: inline-flex; align-items: center; gap: 6px; flex-shrink: 0; }
.cat-sub-row .sub-acts { display: inline-flex; gap: 4px; flex-shrink: 0; }
/* 分类权限图标（二级分类行）：需汇报（橙）/ 需板上位号（紫） */
.cat-flag { display: inline-flex; align-items: center; padding: 0 7px; height: 18px; border-radius: var(--radius-sm); font-size: 12px; line-height: 1; flex-shrink: 0; }
.cat-flag.report { background: var(--c-warn-bg); color: var(--c-warn); border: 1px solid var(--c-warn-bd-2); }
.cat-flag.loc { background: var(--c-info-bg); color: var(--c-info); border: 1px solid var(--c-info-bd); }
/* 批 1（2026-10-08）· ⑱ 分类页「一级分类数」：**窄屏退化为 `4 个`**（用户要求：写不下就退化，
   不许换行 / 撑破工具栏）；`.cat-top-count` 本身不换行。两条都不涉控件尺寸 ⇒ A2 不受影响。 */
.cat-top-count { white-space: nowrap; }
@media (max-width: 768px) { .cat-top-noun { display: none; } }
/* 分类权限开关（新增/编辑分类弹窗） */
.cat-perms { display: flex; flex-direction: column; gap: 8px; margin-top: 12px; }
/* 备件选择（采购/调拨共用）：每项左侧图片缩略图 + 右侧信息右移 */
.pp-thumb { width: 44px; height: 44px; flex-shrink: 0; object-fit: contain; border-radius: 8px; border: 1px solid var(--c-border); background: var(--c-surface); cursor: pointer; }
/* 「简略产品表达」三行式：左图 + 第一行名称/第二行编码/第三行规格 + 右侧可选信息
   窄屏防挤压：容器允许换行；三行文字最小可读宽 140px；右侧信息/按钮换行后自动靠右 */
.brief-lines { flex: 1 1 140px; min-width: 0; }
.bl-code { font-size: 13px; color: var(--c-text); word-break: break-all; }
.bl-name { font-size: 13px; font-weight: 700; color: var(--c-text); margin-top: 2px; }
.bl-spec { font-size: 12px; color: var(--c-muted); margin-top: 2px; }
.brief-right { flex-shrink: 0; font-size: 12px; font-weight: 600; color: var(--c-text); text-align: right; margin-left: auto; }
/* 「简略产品表达」模板（用户定名）：左图 + 三行文字 + 右侧信息/按钮；窄屏自动换行不挤压 */
.brief-part { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.brief-part .btn { flex-shrink: 0; }
/* 核对收货：行尾的实收数量输入 */
.rec-qty { flex-shrink: 0; display: flex; align-items: center; gap: 6px; }
.rec-qty .muted { font-size: 11px; }
.rec-qty input { width: 76px; padding: 7px 6px; border: 1px solid var(--c-border); border-radius: 8px; font-size: 13px; text-align: center; }
.rec-qty input:focus { outline: none; border-color: var(--c-primary); }
/* ---------- 数量步进器（方案 A：− / + 左右按钮，长按连加减；电脑鼠标 / 手机触控均可用） ---------- */
.qty-step { display: inline-flex; align-items: center; gap: 6px; vertical-align: middle; }   /* ㊽（2026-10-10 批 8）：间距 4 → **6px**（用户图）*/
  .qty-step .qs-btn {
    width: 30px; height: 30px; min-width: 30px; padding: 0; font-size: 13px; line-height: 1; border-radius: 50%; cursor: pointer;
  }   /* (66)：± **30×30**（原 34）*/   /* ㊽：± **34×34 圆**（radius 50%）· 号 13px */
  /* ㊽ 配色（用户「用我们现有的蓝」）：减号＝描边圆（白底 ＋ 1.5px 主色边 ＋ 主色号）*/ 
  .qty-step .qs-btn:first-child { background: var(--c-surface); color: var(--c-primary); border: 1px solid var(--c-primary); }   /* ㊽：减号＝**描边圆**（1px 主色描边 —— Chrome 对 border-width **按整像素取整**，写 1.5px 计算值仍是 1px ⇒ 规格取可实现值 1px，见《字体与控件标准》2026-10-10 裁决）*/   /* ㊽：减号＝**描边圆**（1.5px 主色边；`!important` 因为别处有 1px 边框规则把它压成 1px）*/
  .qty-step .qs-btn:first-child:hover { background: var(--c-primary-bg); }
  /* 加号＝实底圆（主色底 ＋ 白号、无边框）*/
  .qty-step .qs-btn:last-child { background: var(--c-primary); color: #fff; border: 0; }
  .qty-step .qs-btn:last-child:hover { background: var(--c-primary-d); }   /* 批 7 §三-d（唯一模板）：± 30×34 · 13px · 圆角 8 */
.qty-step .qs-btn:active { background: var(--c-primary-bg); border-color: var(--c-primary); }
  .qty-step input[type="number"] {
    width: 40px; height: 30px; text-align: center; padding: 0; border: 0;
    border-radius: 4px; font-size: 13px; font-weight: 600;
    background: var(--c-primary-bg); color: var(--c-text);
  }   /* (66)：数字块 **40×30**（原 46×34）*/   /* ㊽：数字块 **46×34 · 圆角 4 · 主色浅底(--c-primary-bg) · 无边框 · 13px/600**（与 ± 等高）*/
/* batch 7 (Lead approved): the shared class owns the height -- exclusion only stops the form-field rule (38);
   the template must declare its own 34px, otherwise whatever rule applies at that spot wins (tf-rec measured 44). */
#page .qs-num, .modal .qs-num, body .qs-num { height: 30px !important; min-height: 30px !important; }   /* 批 7 §三-d：**唯一数量模板的高度由共享类自己定**（特指度 (1,1,0) —— 只需压过弹窗里那条 44px 规则；
      `:not(.qs-num)` 的排除只负责"不再给表单字段的 38px"）。`.qs-num` 只出现在数量模板里 ⇒ 不碰筛选栏 44px。 */   /* batch 7: unique qty template height (40x34 / +/- 30x34) */   /* 批 7 §三-d（唯一模板）：数字框 40×34 · 13px · 圆角 9（与 ± 等高）*/
.qty-step input[type="number"]::-webkit-outer-spin-button,
.qty-step input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.qty-step input[type="number"]:focus { outline: none; border-color: var(--c-primary); }
/* ---------- 下拉选择（方案 C：原生 select + 样式美化；手机上点开仍弹系统原生选择器） ---------- */
select {
  appearance: none; -webkit-appearance: none; -moz-appearance: none;
  touch-action: manipulation; /* 消除双击缩放延迟：点按快速触发 click，滚动不误触 */
  min-height: 40px; line-height: 1.4; /* 上下留白，中英文都不裁剪 */
  padding: 8px 32px 8px 12px;
  border: 1px solid var(--c-border); border-radius: var(--radius-sm);
  background: var(--c-surface) url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%235b6572' stroke-width='1.6' fill='none' stroke-linecap='round'/%3E%3C/svg%3E") no-repeat right 12px center;
  font-size: 14px; color: var(--c-text);
  cursor: pointer; max-width: 100%;
}
/* 校验失败：下拉/输入框红框（源=目标网点、必填图片未上传等） */
select.row-error, input.row-error { border-color: var(--c-danger); background: var(--c-danger-bg); }
select:focus { outline: none; border-color: var(--c-primary); }
select:disabled { background-color: var(--c-bg-2); color: var(--t-3); cursor: not-allowed; }
/* 盘点差异（三行式模板行内）：固定宽度右对齐，步进后实时更新 */
.cnt-diff { font-size: 12px; font-weight: 600; min-width: 42px; text-align: right; }
/* 盘点产品行（三行式模板 + 右侧实盘区）：flex 容器 */
.cnt-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
/* 盘点右侧竖排：系统数（上）+ 实盘步进器与差异（下）；窄屏换行到第二行靠右 */
.cnt-side { flex-shrink: 0; margin-left: auto; display: flex; flex-direction: column; align-items: flex-end; gap: 5px; }
.ps-confirm { display: block; }
.ps-card { border: 1px solid var(--c-border); border-radius: 8px; padding: 10px 12px; margin-bottom: 12px; background: var(--c-bg); }

/* 文本截断规则：名称 / 物料编码 / 规格 最多两行；其余字段单行省略号 */
.clamp-2 { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; word-break: break-word; line-height: 1.35; }
.clamp-1 { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sp-table { table-layout: fixed; }
.sp-card-row .val { display: inline-block; max-width: calc(100% - 72px); vertical-align: top; }

/* 备件图片：列表缩略图 / 详情画廊 / 表单预览 */
.sp-thumb { width: 44px; height: 44px; object-fit: contain; border-radius: var(--radius-sm); border: 1px solid var(--c-border); background: var(--c-surface); vertical-align: middle; }
.sp-img { width: 120px; height: 120px; object-fit: contain; border-radius: var(--radius-sm); border: 1px solid var(--c-border); background: var(--c-surface); }
.sp-preview { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 4px; }
.sp-preview .sp-img { width: 76px; height: 76px; }

/* 通用纵向卡片列表（替代横向表格，适配手机；信息从上到下逐行展示，无左右滑动） */
.vlist { display: flex; flex-direction: column; gap: 10px; margin-top: 4px; }
.vitem {
  border: 1px solid var(--c-border);
  border-radius: 10px;
  padding: 12px 14px;
  /* 2026-10-06 **浅蓝底色尝试已撤回**（用户：「改的不对，退回到之前的版本」）—— 底色回到纯白（原状）。
     撤回前的写法（留档）：`background: var(--c-primary-bg)`（`var(--c-primary-bg)`）· 见 log 与需求文档 §10 的撤回行。 */
  background: var(--c-surface);
  box-shadow: var(--shadow);
}
.vitem .vhead {
  font-weight: 600; font-size: 13px; margin-bottom: 6px;   /* 批 7：15→13 */
  display: flex; justify-content: space-between; align-items: center; gap: 10px;
}
.vrow {
  display: flex; justify-content: space-between; gap: 12px;
  font-size: 13px; padding: 4px 0; border-top: 1px dashed var(--c-border);
}
.vrow:first-of-type { border-top: 0; }
.vrow .k { color: var(--c-muted); flex-shrink: 0; }
.vrow .v { text-align: right; word-break: break-word; min-width: 0; }
/* 批 2（2026-10-08）· ㉕：**只给 Alerts 块**值列左对齐（全站 .vrow .v 仍右对齐 —— 2026-10-06 既定口径不动）。
   justify-content: flex-start 让值列不再被 space-between 推到最右；标签在前、值紧随其后。 */
.alerts-rows .vrow { justify-content: flex-start; }
.alerts-rows .vrow .v { text-align: left; }
/* 避让右下角固定的回顶按钮 .to-top（实测两档：桌面 42×42 · right 18 · bottom 84；
   ≤768px 46×46 · right 14 · bottom 72+safe ⇒ 按钮顶边距视口底 126 / 118px）。
   实测（改前 · 滚到页底）卡片底边距视口底仅 8px ⇒ 需 margin ≥ 122px；取 126px ⇒
   1280 档 gap = 8+126−126 = 8px、390 档 gap = 8+126−118 = 16px（都 ≥4px，矩形不相交）。 */
.alerts-rows { padding-right: 60px; }
  /* ⚠ 必须压过站内既有的 `#page > .card:last-child { margin-bottom: 0 !important; }`（L1261，
     Alerts 卡正是 `#page` 的最后一个 .card）⇒ 选择器提到 (1,2,1) 并同样 !important。 */
  #page > .card.alerts-card:last-child { margin-bottom: 126px !important; }
.vacts { margin-top: 10px; display: flex; gap: 8px; flex-wrap: wrap; }
/* (68)（2026-10-10 批 B）：**产品卡片**复用「卡片右上角动作区」版式（与员工管理/维修中心同款：距顶 23 · 距右 15 · 宽≈78）
   ⇒ 不给产品页单独造版式；卡片需 `position: relative`（见下）。类型标签移到名称右侧并允许换行（`.vhead`）*/ 
.prodcard { position: relative; }
.prodcard > .vacts { position: absolute; top: 23px; right: 15px; margin-top: 0; flex-wrap: nowrap; }
.prodcard .vhead { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; padding-right: 88px; }

.vsub { margin-top: 6px; }
.vsub .tag { margin: 2px 4px 2px 0; }
.tag { display:inline-block; padding:2px 10px; border-radius:10px; font-size:12px; line-height:1.5; font-weight:500; border:1px solid transparent; }
.tag.muted { background:var(--c-bg-2); color:var(--c-muted); border-color:var(--c-border); }
.tag.warn { background:var(--c-warn-bg); color:var(--c-warn); border-color:var(--c-warn-bd-2); }
.tag.ok { background:var(--c-success-bg); color:var(--c-success); border-color:var(--c-success-bd); }
.tag.info { background: var(--c-primary-bg); color: var(--c-primary-d); border-color: var(--c-primary-bd); }
.itr-link { cursor:pointer; text-decoration:underline dotted; text-underline-offset:2px; }
.itr-link:hover { filter:brightness(0.95); }
/* 明细备件：序号标题 + 横线分隔（多备件界限清晰，不再用外框） */
.item-line { border-bottom: 1px solid var(--c-border); padding: 10px 0; margin-bottom: 10px; }
.item-line:last-child { border-bottom: 0; margin-bottom: 0; }
.item-head { display: flex; align-items: center; gap: 6px; margin-bottom: 6px; }
.item-no {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 20px; height: 20px; padding: 0 6px;
  border-radius: 10px; background: var(--c-primary); color: var(--c-surface);
  font-size: 12px; font-weight: 600;
}
/* 员工所属维修点：方案 B 两列网格（小卡片；选中=蓝边框+浅蓝底，无勾） */
.emp-locs-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
.emp-loc-card {
  display: flex; align-items: center; justify-content: center;
  padding: 8px 6px; border: 0.5px solid var(--c-border); border-radius: 8px;
  font-size: 12px; cursor: pointer; background: var(--c-surface); text-align: center;
  transition: border-color .15s, background .15s;
}
.emp-loc-card:hover { border-color: var(--c-primary); }
.emp-loc-card.on { border-color: var(--c-primary); background: var(--c-primary-bg); }
.emp-loc-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.emp-loc-card input { display: none; }
/* 添加明细按钮更醒目 */
.add-row-btn { display: inline-flex; align-items: center; gap: 4px; padding: 7px 14px; border-radius: 8px; border: 1px dashed var(--c-primary); color: var(--c-primary-d); background: var(--c-primary-bg); cursor: pointer; font-size: 13px; font-weight: 600; }
.add-row-btn:hover { background: var(--c-primary-bg); }
/* 备件明细行：紧凑一行式（序号 + 编码名称选择 + 数量 + 删除键），采购/调拨共用 */
.part-row { display: flex; align-items: center; gap: 8px; padding: 8px 0; border-bottom: 1px dashed var(--c-border); flex-wrap: wrap; }
.part-row:last-child { border-bottom: 0; }
.part-row .item-no { flex-shrink: 0; }
.part-row .pick-btn {
  flex: 1 1 160px; min-width: 0; text-align: left; padding: 8px 10px;
  border: 1px solid var(--c-border); border-radius: 8px; background: var(--c-surface); cursor: pointer;
  font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--c-text);
}
.part-row .pick-btn:hover { border-color: var(--c-primary); }
/* 调拨/采购明细行（三行式）：数量标签 */
.qty-label { font-size: 12px; color: var(--c-muted); flex-shrink: 0; }
.part-row-brief { align-items: flex-start; }
/* 上传控件英文化：隐藏原生 file input（避免浏览器语言显示"选择文件"），用英文虚线按钮替代，点击整块触发选择 */
/* 校验失败的行：红框 + 浅红底，便于定位（调拨/采购/工单备件行通用） */
.part-row.row-error, .wo-part-row.row-error { border: 1.5px solid var(--c-danger); border-radius: 10px; background: var(--c-danger-bg); padding: 8px 10px; margin: 4px 0; }
.part-stock { font-size: 11px; color: var(--c-muted); padding: 0 2px 8px; }

/* 备件卡片：详情弹窗 / 核对收货 / 手机端列表 共用（全局生效，桌面端也能用）；「手机端列表容器」仍仅移动端显示 */
.sp-card {
  display: flex; gap: 12px;
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: 12px;
  padding: 12px 14px;
  margin-bottom: 12px;
  box-shadow: var(--shadow);
  cursor: pointer;
  align-items: flex-start;
}
.sp-card-thumb {
  width: 72px; height: 72px; flex-shrink: 0;
  object-fit: cover; border-radius: 10px;
  border: 1px solid var(--c-border); background: var(--c-surface);
}
.sp-card-body { flex: 1; min-width: 0; position: relative; }
.sp-card-name {
  font-size: 13px; font-weight: 600; color: var(--c-text);   /* 批 7：15→13 */
  margin-bottom: 4px; line-height: 1.35;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; word-break: break-word;
}
.sp-card-row {
  font-size: 12px; color: var(--c-muted);
  line-height: 1.65;
}
.sp-card-row span {
  display: inline-block; min-width: 64px;
  color: var(--c-muted); margin-right: 4px;
}
.sp-card-actions {
  position: absolute; right: 0; bottom: 0;
  display: flex; gap: 6px;
}
/* 批 7 §三-b：页面级按钮覆盖已删（同类只允许一个内边距）*/
.sp-cards { display: none; }
@media (max-width: 768px) {
  .sp-table { display: none; }
  .sp-cards { display: block; }
}

/* 授权矩阵勾选 */
.chk { display: inline-flex; align-items: center; gap: 5px; font-size: 13px; }
/* ㊹（2026-10-10 批 8）：勾选标签在 `.field` 内被 `.field label { display: block }`（(0,1,1)）压成 block ⇒ `align-items:center`/`gap` 失效，
   圆圈只能靠 `vertical-align:middle` 对首行（实测单行 −2.25px · 两行 +9.38px）。修法：更高特异性恢复 inline-flex ＋ 对齐**首行**；
   圆圈用 margin-top 做首行居中 —— 行高 22.5px ⇒ (22.5 − 13)/2 ≈ 4.75 ⇒ 取 5px。 */
.field label.chk, .wo-part-row label.chk { display: inline-flex !important; align-items: flex-start !important; gap: 5px !important; }
.field label.chk input[type="checkbox"], .wo-part-row label.chk input[type="checkbox"] { margin-top: 2.5px !important; flex: none !important; }   /* ㊹：**实测行高 18px**（不是 22.5）⇒ (18 − 13)/2 = 2.5px 才能让圆圈中心对齐**首行**文字中心 */

/* 维修网点授权：竖向单选，适配手机（无左右滑动） */


/* ㊳（2026-10-08 · task-24）：**全站勾选框改圆形** —— 未选＝圆环＋白心（不透明）；选中＝蓝底（`--c-primary`）＋白勾。
   ⚠ 对勾**必须**用 `background-image` 的 SVG data URI：`input` 是**替换元素**，`::before/::after` 在 Chrome 里不渲染（实测无效）；
   ⚠ `.emp-loc-cb`（员工表单网点卡里的勾选框）**保持隐藏** —— 选中态由整张卡片表达，见 `.emp-loc-card input{display:none}`；
   ⚠ 尺寸沿用各载体现有尺寸（13px / 16px / 22px），只改形状与配色；`:focus-visible` 用现有令牌（不新增色值）；
   ⚠ **DOM/JS 一行未动** ⇒ `checked` / `onchange` / `permSyncCounts` 行为不变（`.perm-cb2` 仍是 120 个）。 */
input[type="checkbox"] {
  appearance: none; -webkit-appearance: none;
  /* ⚠ 必须显式给默认档尺寸：`appearance:none` 会**抹掉浏览器原生勾选框的固有尺寸**（13×13），
     不给就塌成 2×2（2026-10-08 回归，visual-ux 抓到：登录页与分类弹窗三处勾选框变 2×2）。
     16px 档（`.chk-void input`）与 22px 档（`.perm-row input` / `.perm-cb2`）各自覆盖，不受这里影响。 */
  width: 13px; height: 13px;
  /* ㊶（2026-10-08 · task-27）：勾选框**不该被 flex 压扁** —— 弹窗里实测被压掉 0.81px（`#cat-report` 12.19×13、
     登录页 11.98×13）⇒ 加 `flex: none` 根除；`width/height` 已显式给（见上，`appearance:none` 会抹掉固有尺寸）。 */
  flex: none;
  border: 1.5px solid var(--c-border); border-radius: 50%;
  background-color: var(--c-surface);
  background-image: none; background-repeat: no-repeat; background-position: center; background-size: 74% 74%;
  box-sizing: border-box; cursor: pointer; vertical-align: middle;
}
input[type="checkbox"]:checked {
  background-color: var(--c-primary); border-color: var(--c-primary);
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3.4 8.6l3 3 6.2-6.8' fill='none' stroke='%23fff' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
input[type="checkbox"]:focus-visible { outline: none; border-color: var(--c-primary); box-shadow: 0 0 0 2px var(--c-primary-a18); }
input[type="checkbox"]:disabled { opacity: 0.5; cursor: not-allowed; }
/* ㊸（批 7 · 与《字体与控件标准》同属一份控件标准）：**更高特异性兜底** —— 勾选框放进 `.field` / `.wo-part-row` 后，
   被表单输入规则（`.field input{width:100%;padding:12px 11px}`（0,1,1）＋ `.wo-part-row input{padding-top/bottom !important}`）
   压/撑成**椭圆**（备件行 A/B 实测 24×14）⇒ 这里用 (1,1,1) / (0,2,1) 级别把它们拉回 **13×13 正圆**。
   只覆盖 `input[type="checkbox"]` ⇒ 其余载体（`.chk` 13 · `.chk-void` 16 · `.perm-cb2` 22 · `.perm-loc` 13 · `.emp-loc-cb` 隐藏）不受影响。 */
.field input[type="checkbox"], .wo-part-row input[type="checkbox"], .wo-flags input[type="checkbox"] {
  width: 13px !important; height: 13px !important; min-width: 13px !important;
  padding: 0 !important; flex: none !important; box-sizing: border-box !important;
  border-radius: 50% !important;
}

/* ---------- 长文本域 ---------- */
textarea {
  width: 100%;
  padding: 9px 11px;
  border: 1px solid var(--c-border);
  border-radius: 8px;
  font-size: 14px;
  font-family: inherit;
  resize: vertical;
  color: var(--c-text);
  background: var(--c-surface);
}
.field textarea:focus {
  outline: none; border-color: var(--c-primary);
  box-shadow: var(--ring);
}

@media (max-width: 768px) {
  .modal { width: 100%; }
}

/* #20 回到顶部：右下角悬浮箭头（所有列表页通用） */
.to-top {
  position: fixed;
  right: 18px;
  bottom: 84px;
  width: 42px; height: 42px;
  border-radius: 50%;
  border: 1px solid var(--c-border);
  background: var(--c-surface);
  color: var(--c-primary);
  font-size: 20px; line-height: 1;
  box-shadow: var(--shadow);
  cursor: pointer;
  z-index: 45;
  display: flex; align-items: center; justify-content: center;
}
.to-top:active { transform: scale(0.94); }
@media (max-width: 768px) {
  .to-top { right: 14px; bottom: calc(72px + env(safe-area-inset-bottom, 0px)); width: 46px; height: 46px; }
}

/* 卡片标题（System Notes 等）：普通标题，不吸顶不遮挡内容 */

/* 新建表单页标题栏：与采购新建页一致的普通工具栏（Back 左 + 标题右），不吸顶不遮挡 */
.form-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 14px;
}
.form-bar .spacer { flex: 1; }

/* 滚动防误触：页面滚动进行时禁用下拉/日期等点选控件（停止 200ms 后恢复） */
body.scrolling select,
body.scrolling .date-wheel { pointer-events: none; }

/* #27 SN 多行：每行 照片URL + SN + 生产日期 + 删除 */
.wo-sn-row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-bottom: 8px; }
.wo-sn-row .wo-sn-ph { flex: 1 1 180px; min-width: 0; padding: 9px 11px; border: 1px solid var(--c-border); border-radius: 10px; font-size: 13px; }
.wo-sn-row .wo-sn-val { flex: 1 1 140px; min-width: 0; padding: 9px 11px; border: 1px solid var(--c-border); border-radius: 10px; font-size: 13px; }
.wo-sn-row .wo-sn-date { flex: 1 1 130px; font-size: 12px; color: var(--c-muted); }

/* #33 repair photos 多行输入（复用 .wo-sn-row 布局） */
.wo-rpr-val { flex: 1 1 240px; min-width: 0; padding: 9px 11px; border: 1px solid var(--c-border); border-radius: 10px; font-size: 13px; }

/* #25/#26 void：作废标识 + Include voided 复选框 */
.voided-banner { display: inline-block; background: var(--c-danger-bg); color: var(--c-danger); border: 1px solid var(--c-danger); border-radius: var(--radius-sm); font-size: 11px; font-weight: 700; padding: 2px 8px; margin-bottom: 6px; letter-spacing: 0.5px; }
.chk-void { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; color: var(--c-muted); white-space: nowrap; cursor: pointer; }
.chk-void input { width: 16px; height: 16px; }   /* ㊳：原来的 accent-color 在 appearance:none 下已失效，删掉（形状/配色统一由全站规则给） */

/* #25/#26 void：作废标识 + Include voided 复选框 */
.voided-banner { display: inline-block; background: var(--c-danger-bg); color: var(--c-danger); border: 1px solid var(--c-danger); border-radius: var(--radius-sm); font-size: 11px; font-weight: 700; padding: 2px 8px; margin-bottom: 6px; letter-spacing: 0.5px; }
.chk-void { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; color: var(--c-muted); white-space: nowrap; cursor: pointer; }
.chk-void input { width: 16px; height: 16px; }   /* ㊳：原来的 accent-color 在 appearance:none 下已失效，删掉（形状/配色统一由全站规则给） */

/* 批 2（2026-10-08）· task-19：es 族 CSS（19 个选择器 / 19 个规则块 / 77 条声明 / 19 行）已删除 ——
   它随批 1（㉚）删掉「工程师统计」整族 JS 后成为孤儿（app.js 与 index.html 里 0 引用）。
   原族名（此处不写成选择器形态，便于 grep 归零）：es-grid / es-card / es-name / es-row（含 b 子项）/ es-sec /
   es-sub / es-week-head / es-wk-nav（含 .btn 与 :disabled）/ es-wk-label / es-engs / es-engs-lbl /
   es-engs-acts / es-time / es-time-row / es-time-tag / es-time-range —— 需要时按 git 历史还原。 */
/* #4 分段控件（Monthly/Weekly 切换） */
/* 版本标记（2026-10-04）：顶栏常显，用来确认"现在看的是哪一版"（V2.1） */

/* =============================================================================
 * 工单照片位「选择文件」＋ 草稿徽标（2026-10-04）
 * 照片位：保留原输入框当值容器（hidden），旁边给按钮/文件名/缩略图；
 * 报错时 JS 会给 hidden 输入加 .row-error ⇒ 用 :has() 把红框画在外层，保证看得见。
 * ========================================================================== */
/* ⚠ 必须写成 `.field .photo-file`（0,2,0）—— 只写 `.photo-file`（0,1,0）**斗不过 `.field input { width: 100% }`（0,1,1）**，
   结果隐藏的选文件控件被撑成整行宽（实测 511px）＋绝对定位 ⇒ 右边缘溢出到 x=830 ⇒ **整个表单页能左右拖**
   （2026-10-04 真机测量所得；同款错误当日在 V2 里也犯过一次，教训：**隐藏控件要写足优先级 ＋ 钉住位置 ＋ clip**） */
#page .photo-file, .field .photo-file, .photo-field .photo-file, .wo-sn-row .photo-file {   /* #page 前缀保证压过 .field input{width:100%}，并覆盖不在 .field 里的行 */
  position: absolute; left: 0; top: 0; width: 1px; height: 1px; padding: 0; margin: 0; border: 0;
  opacity: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%);
}
/* 照片选择框：**与输入框同一套外观**（实线 1px ＋ 圆角 10 ＋ 13px 字 ＋ 同高）——
   2026-10-04 用户：「添加图片和添加SN码，形式完全不一个，要调整成一样的」：
   原来这里是**虚线框 ＋ 里再套一个白底按钮**（盒中盒），而 SN 是实线输入框 ⇒ 看着像两种控件。
   现在：一个实线框里放「蓝色文字按钮 ＋ 文件名 ＋ 缩略图」，形状与输入框一致；
   已传时只把边框与底色淡淡变绿（形状不变，仍然是"一个框"）。 */
.photo-field {
  position: relative; overflow: hidden;              /* 定位祖先 ＋ 裁掉隐藏控件可能带出的溢出 */
  flex: 1 1 180px; min-width: 0;
  display: flex; align-items: center; gap: 8px;
  padding: 0 8px 0 10px; min-height: 40px;
  border: 1px solid var(--c-border); border-radius: 10px; background: var(--c-surface);   /* 和 .wo-sn-val 完全一致 */
}
.photo-field.on { border-color: var(--c-success-bd-2); background: var(--c-success-bg); }
.photo-field:has(input.row-error) { border-color: var(--c-danger); background: var(--c-danger-bg); }
/* 框内的"选择照片"做成**扁平蓝字按钮**（不再是一个白底小方块，避免盒中盒） */
.photo-field .btn, .photo-field .btn.ghost, .photo-field .btn.soft {
  border: 0; background: transparent; color: var(--c-primary-d);
  padding: 0; min-height: auto; font-size: 13px; font-weight: 600;
}
.photo-field .btn:hover { text-decoration: underline; }
.photo-name { font-size: 13px; color: var(--c-muted); max-width: 220px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.photo-field:not(.on) .photo-name { color: var(--t-3); }   /* 未选时像占位符 */

/* SN 行：让「输入框」与「照片框」在同一行里尺寸观感一致 */
.wo-sn-row .wo-sn-val, .wo-sn-row .photo-field { flex: 1 1 180px; min-height: 40px; font-size: 13px; }
.wo-sn-row .wo-sn-val { border-radius: 10px; }
.wo-sn-row .wo-sn-val { padding: 9px 11px; }

/* =============================================================================
 * 按钮统一（2026-10-04 用户：「back to list 这种按键，统一改一个颜色和位置，这样可以明显的显示这是一个按键」）
 * ① .btn-back：返回类按钮 —— **浅蓝底 ＋ 蓝边 ＋ 蓝字 ＋ 箭头**，一眼看出是可点的按钮，且各页一致；
 * ② .form-actions：底部操作区 —— 统一间距与对齐（桌面右对齐一行；手机竖排、主操作在最前）；
 * ③ .btn.soft：次级动作（如 Save (draft)）—— 浅蓝底，与主操作（实心蓝）/取消（描边）三档可分。
 * ========================================================================== */
.btn-back {
  background: var(--c-primary-bg); color: var(--c-primary-d); border: 1px solid var(--c-primary-bd); border-radius: 10px;
  padding: 8px 14px; font-size: 13px; font-weight: 600; min-height: 38px;
}
.btn-back:hover { background: var(--c-primary-bg); border-color: var(--c-primary-bd-2); }
.btn.soft { background: var(--c-primary-bg); color: var(--c-primary-d); border: 1px solid var(--c-primary-bd); }
.btn.soft:hover { background: var(--c-primary-bg); }
.form-actions {
  display: flex; flex-wrap: wrap; gap: 10px; align-items: center;
  justify-content: flex-end; margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--c-border);
}
.form-actions .btn { min-height: 44px; white-space: nowrap; }
@media (max-width: 640px) {
  .form-actions { flex-direction: column; align-items: stretch; }
  .form-actions .btn { width: 100%; }
}

/* SN 行里的两个控件必须"长得像双胞胎"（2026-10-04 第二轮微调）：
   ① 显式 box-sizing（保证 padding/border 不把高度撑出去）② 同一高度 40px ③ 同一起始宽度（flex: 1 1 0）
   ④ 框内的「Choose photo」不换行（第一版被挤成两行 ⇒ 照片框比输入框高）⑤ 文件名省略号截断 */
.wo-sn-row .wo-sn-val, .wo-sn-row .photo-field {
  box-sizing: border-box;
  flex: 1 1 0; min-width: 0; height: 40px; min-height: 40px;
  font-size: 13px; border-radius: 10px; border: 1px solid var(--c-border);
}
.wo-sn-row .wo-sn-val { padding: 0 11px; line-height: 38px; }
.wo-sn-row .photo-field { padding: 0 8px 0 10px; }
.wo-sn-row .photo-field .btn { flex: 0 0 auto; white-space: nowrap; }
.wo-sn-row .photo-name { flex: 0 1 auto; min-width: 0; }   /* 空间不够时先压文件名（省略号） */
.wo-rpr-val.photo-field, .wo-sn-row .wo-rpr-val { height: 40px; }

/* 窄屏：SN 行里两个控件各自占满一行（仍然同高同形，但照片框有位置放缩略图）
   —— 2026-10-04 第三轮：等宽并排时缩略图会被挤掉，宁可换行也要让"已传照片"看得见 */
@media (max-width: 560px) {
  .wo-sn-row .photo-field, .wo-sn-row .wo-sn-val { flex: 1 1 100%; }
  .wo-sn-row .photo-name { display: none; }   /* 窄屏只留「Choose photo ＋ 缩略图」 */
}

/* 缩略图钉在照片框右侧（绝对定位）—— flex 排布下会被挤到看不见，改为不参与挤压（2026-10-04 第三轮） */
.photo-field { padding-right: 44px; }

/* ⚠ 优先级：`.wo-sn-row .photo-field`（0,2,0）会压过裸 `.photo-field`（0,1,0）——
   所以给缩略图留位这一条必须也带 `.wo-sn-row` 前缀（今天第三次栽在优先级上） */
.wo-sn-row .photo-field { padding-right: 44px; }
.wo-rpr-val.photo-field { padding-right: 44px; }

/* =============================================================================
 * 2026-10-04 用户截图要求：
 * ① 底部三个键 → `Submit` / `Save` / `Cancel`，**并排一行**（不再竖排堆叠）；
 * ② 照片框 → 按 `+ Add SN`（.btn-add）的格式来：**虚线蓝框 ＋ 浅蓝底 ＋ 蓝字 ＋ 圆角 8**。
 * ========================================================================== */
.form-actions { flex-wrap: nowrap; }
.form-actions .btn { flex: 1 1 auto; min-width: 0; }
@media (max-width: 640px) {
  /* 覆盖前面那条"手机竖排"的规则：三个短标签一行放得下，保持一行 */
  .form-actions { flex-direction: row; align-items: center; }
  .form-actions .btn { width: auto; flex: 1 1 0; padding: 9px 8px; font-size: 13px; }
}

/* 照片框：与 .btn-add 同款（虚线蓝、浅蓝底、蓝字、圆角 8、同高） */
.wo-sn-row .photo-field, .field .photo-field, .photo-field {
  border: 1px dashed var(--c-primary);
  background: var(--c-primary-soft);
  color: var(--c-primary);
  border-radius: 8px;
  height: 38px; min-height: 38px;
  font-size: 13px; font-weight: 600;
}
.photo-field.on { border-style: dashed; border-color: var(--c-primary); background: var(--c-primary-a16); }
.photo-field .btn, .photo-field .btn.ghost, .photo-field .btn.soft {
  color: var(--c-primary); font-weight: 600; font-size: 13px;
}
.photo-field:not(.on) .photo-name { color: var(--c-primary); opacity: .75; }

/* 桌面端：三个键按内容宽度、右对齐；手机端才撑满一行（2026-10-04 微调） */
@media (min-width: 641px) {
  .form-actions .btn { flex: 0 0 auto; min-width: 104px; }
}

/* 钉死：照片框**必须**按内容宽度（与 `+ Add SN` 同宽同形）—— 前面有几条 flex 规则先后覆盖过，
   这里用 !important 一次定死，不再来回（2026-10-04 第三轮；教训：同一属性被多处覆盖时，与其猜顺序不如钉死） */
.wo-sn-row .photo-field, .photo-field { flex: 0 0 auto !important; width: auto !important; max-width: 100% !important; }
.wo-sn-row .wo-sn-val { flex: 1 1 100% !important; }

/* SN 行排版（2026-10-04 修"加一行后错位"）：
   原因：我给 SN 输入框加了 flex:1 1 100% ⇒ 它独占一行，把日期与 × 挤到第三行、× 被 margin 甩到最右。
   现在：① 照片框按内容宽 ② SN 输入框 flex:1 1 160px（够宽就与照片框同一行，不够才换行）
        ③ 日期自适应 ④ 删除键固定 38×38 且**跟在同一行末尾**（不再孤立甩到最右、也不再被压成小方块）。 */
.wo-sn-row { align-items: center; }
.wo-sn-row .wo-sn-val { flex: 1 1 160px !important; min-width: 120px; }
.wo-sn-row .wo-sn-date { flex: 1 1 auto; min-width: 0; }
.wo-sn-row .btn.ghost.sm {
  flex: 0 0 auto; margin-left: 0; width: 38px; min-width: 38px; height: 38px; min-height: 38px;
  padding: 0; font-size: 16px; line-height: 1; border-radius: 10px;
}
.wo-sn-row .photo-field { margin-right: 2px; }

/* SN 行：窄屏改用**两列网格**（不再靠 flex 挤 —— 挤的结果是照片框被压窄、文字被裁）
   第一行：照片框 ＋ 删除键   第二行：SN 输入框（占满）   第三行：生产日期（占满）
   2026-10-04 第四轮；教训：多个控件同排又要换行时，**网格比 flex 可预测**。 */
@media (max-width: 560px) {
  .wo-sn-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 8px; align-items: center; }
  .wo-sn-row .photo-field { grid-column: 1; width: 100% !important; max-width: 100% !important; }
  .wo-sn-row .btn.ghost.sm { grid-column: 2; }
  .wo-sn-row .wo-sn-val { grid-column: 1 / -1; width: 100%; }
  .wo-sn-row .wo-sn-date { grid-column: 1 / -1; }
}

/* SN 行最终修法（2026-10-04 第五轮）：
   根因 = 框内按钮是 `justify-content:center`，**文字比容器宽时两侧对称溢出**，再被 `.photo-field{overflow:hidden}` 两头裁掉
        ⇒ 屏幕上看成 "oose photo"（左右各缺一点）。
   三条一起解决：① 照片框**不再 overflow:hidden**（隐藏的文件输入本身已有 clip，不需要外层再裁）
                ② 框内按钮**不许收缩**（min-width: max-content）且左对齐
                ③ SN 行里**不显示文件名**（窄屏本来就没有它的位置，缩略图已足够表意） */
.photo-field { overflow: visible; }
.wo-sn-row .photo-field { justify-content: flex-start; }
.wo-sn-row .photo-field .btn { flex: 0 0 auto !important; min-width: max-content; justify-content: flex-start; }
.wo-sn-row .photo-name { display: none !important; }

/* SN 行（窄屏）最终版：**显式**网格定位（自动流曾把 × 甩到单独一行）
   第 1 行：＋ Choose photo（整行）
   第 2 行：[ SN 输入框 ] [ × ]     ← 用户要求：叉与输入框同一行
   第 3 行：生产日期（整行） */
@media (max-width: 560px) {
  .wo-sn-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 8px; align-items: center; }
  .wo-sn-row .photo-field { grid-row: 1; grid-column: 1 / -1; width: 100% !important; max-width: 100% !important; }
  .wo-sn-row .wo-sn-val { grid-row: 2; grid-column: 1; width: 100%; }
  .wo-sn-row .btn.ghost.sm { grid-row: 2; grid-column: 2; }
  .wo-sn-row .wo-sn-date { grid-row: 3; grid-column: 1 / -1; }
}

/* SN 行（窄屏）**最终定稿**：用 flex ＋ 显式 order 强制排布（网格与自动流都试过，压不住前面的规则）
   第 1 行：＋ Choose photo（整行）  第 2 行：[ SN 输入框 ][ × ]   第 3 行：生产日期（整行） */
@media (max-width: 560px) {
  .wo-sn-row { display: flex !important; flex-wrap: wrap; gap: 8px; align-items: center; }
  .wo-sn-row .photo-field { order: 1; flex: 1 1 100% !important; width: 100% !important; max-width: 100% !important; }
  .wo-sn-row .wo-sn-val { order: 2; flex: 1 1 0 !important; min-width: 120px !important; }
  .wo-sn-row .btn.ghost.sm { order: 3; flex: 0 0 auto !important; width: 38px !important; min-width: 38px !important; height: 38px; min-height: 38px; padding: 0; }
  .wo-sn-row .wo-sn-date { order: 4; flex: 1 1 100%; }
}

/* （原「SN 照片位按 V1.0 样子」的一块已按用户要求撤销：恢复到虚线蓝 + Choose photo） */

/* =============================================================================
 * 2026-10-04（用户第三轮）：① `＋ Choose photo` 与 `＋ Add SN` **颜色必须完全一致**
 *    —— 两者都用 .btn-add 的底色 `--c-primary-soft`（主色 8% 淡底）；**"已传照片"状态也不再加深底色**（原来 .on 用了 .16 ⇒ 看着深一档）
 *  ② 去掉 `Choose photo` 文字下面的**横线**（我之前加了 hover 下划线，截图里看着像常驻下划线）
 * ========================================================================== */
.photo-field, .photo-field.on,
.wo-sn-row .photo-field, .wo-sn-row .photo-field.on, .field .photo-field, .field .photo-field.on {
  background: var(--c-primary-soft) !important;
  border: 1px dashed var(--c-primary) !important;
  color: var(--c-primary) !important;
}
.photo-field .btn, .photo-field .btn:hover, .photo-field .btn:focus,
.photo-field .btn.ghost, .photo-field .btn.ghost:hover, .photo-field .btn.soft {
  text-decoration: none !important;
  color: var(--c-primary) !important;
  font-weight: 600 !important;
  background: transparent !important;
  border: 0 !important;
}
/* 与 .btn-add 保持同高 */
.photo-field { height: 36px !important; min-height: 36px !important; }

/* 2026-10-04 用户：`＋ Choose photo` 与 `＋ Add SN` **字号也要一致**（此前照片框内按钮沿用了 .btn.sm 的 12px） */
.photo-field .btn, .photo-field .btn.ghost, .photo-field .btn.soft,
.wo-sn-row .photo-field .btn {
  font-size: 13px !important;
  font-weight: 600 !important;
  line-height: 1.2 !important;
}

/* =============================================================================
 * SN 行：**两种宽度都明确排布**（2026-10-04 桌面截图发现照片框与输入框重叠）
 * 桌面（>560px）：一行 —— [＋ Choose photo] [ SN 输入框(自适应) ] [日期] [×]
 * 手机（≤560px）：两行 —— 第一行照片框（整行）；第二行 [ SN 输入框 ][ × ]；日期整行
 * ⚠ 前面十几条规则互相覆盖过，这里用 !important 一次定死（并保留注释说明来龙去脉）
 * ========================================================================== */
.wo-sn-row { display: flex !important; flex-wrap: nowrap !important; gap: 8px !important; align-items: center !important; }
.wo-sn-row .photo-field { flex: 0 0 auto !important; width: auto !important; min-width: 0 !important; }
.wo-sn-row .wo-sn-val { flex: 1 1 auto !important; min-width: 0 !important; }
.wo-sn-row .wo-sn-date { flex: 0 0 auto !important; }
.wo-sn-row .btn.ghost.sm { flex: 0 0 auto !important; }
@media (max-width: 560px) {
  .wo-sn-row { flex-wrap: wrap !important; }
  .wo-sn-row .photo-field { flex: 1 1 100% !important; width: 100% !important; }
  .wo-sn-row .wo-sn-val { order: 2; flex: 1 1 0 !important; }
  .wo-sn-row .btn.ghost.sm { order: 3; }
  .wo-sn-row .wo-sn-date { order: 4; flex: 1 1 100% !important; }
}

/* 缩略图可点（2026-10-04）：鼠标手型 ＋ 悬停描边，明确"能点开看大图" */

/* （原「卡片下内边距压到 6px」的一条已按用户要求撤回：用户指的是卡片**外**到页面底的空白） */

/* =============================================================================
 * 卡片**外**到页面底的空白（2026-10-04 用户第三次说，终于量准了）：
 * 实测 = 卡片下边距 18px ＋ `#page` 下内边距 14px = **32px**。
 * 处理：表单页最后一张卡片下边距归零 ＋ `#page` 下内边距 14 → 8px ⇒ 合计 **8px**。
 * ⚠ 只影响"最后一张卡片"，中间的卡片间距（18px）保持不变。
 * ========================================================================== */
#page > .card:last-child { margin-bottom: 0 !important; }
#page { padding-bottom: 8px !important; }

/* =============================================================================
 * 2026-10-04 用户截图：「这几个蓝色的宽度，不一样，改成一样的」
 * 指的是 `+ Add spare part` ／ `+ Choose photo`（维修照片区）／ `+ Add photo` 三个虚线蓝控件。
 * 统一规则：**全部按内容宽度**（与 `+ Add SN` 同款），不再有"撑满一行"的例外。
 * 注：SN 行里的照片位同理按内容宽（它旁边就是 SN 输入框，本来就该窄）。
 * ========================================================================== */
.photo-field {
  flex: 0 0 auto !important;
  width: auto !important;
  max-width: 100% !important;
  align-self: flex-start;
  justify-self: start;
}

/* 2026-10-04 用户：「这几个蓝色的宽度，不一样，改成一样的」⇒ 给"虚线蓝控件"统一**最小宽度**，
   使 `+ Add spare part` / `+ Choose photo` / `+ Add photo` / `+ Add SN` 看起来**一样宽**（内容短也保持同宽）。 */
.btn-add, .photo-field { min-width: 152px !important; }
.photo-field { justify-content: center !important; }

/* 根因收尾：`.photo-field` 是 `<span>` 但设了 `display: flex` ⇒ **在块级父元素（.field）里会撑满整行**，
   这就是"F 段 Choose photo 特别宽"的原因。改成 `inline-flex` ⇒ 按内容收缩，与 `.btn-add` 同宽（152px 起）。 */
.photo-field { display: inline-flex !important; width: auto !important; min-width: 152px !important; }

/* =============================================================================
 * 照片上传改成"方形瓦片"式（2026-10-04 用户给的参考图）：
 *   空：**方形虚线框 ＋ 中间大「＋」**（灰虚线、浅底）
 *   已传：**同尺寸方形缩略图**（点开看大图）＋ **右上角圆形「×」**（删除）；「＋」留在右侧（换图/再加）
 * 覆盖全部照片位（SN 照片 / 维修照片 / 凭证 / 纸质单 / 付款截图 —— 共用同一组件）。
 * ========================================================================== */
.photo-field {
  display: inline-flex !important; align-items: center; gap: 10px;
  background: none !important; border: 0 !important; padding: 0 !important;
  min-width: 0 !important; width: auto !important; height: auto !important; min-height: 0 !important;
  justify-content: flex-start !important;
}
.photo-add {
  width: 88px; height: 88px; flex: 0 0 auto;
  border: 2px dashed var(--c-border-2); border-radius: 10px; background: var(--c-bg-2);
  color: var(--t-3); font-size: 34px; font-weight: 400; line-height: 1;
  display: flex; align-items: center; justify-content: center; cursor: pointer;
}
.photo-add:hover { border-color: var(--c-primary); color: var(--c-primary); background: var(--c-primary-bg); }
.photo-thumbwrap { position: relative; flex: 0 0 auto; display: none; }
.photo-field.on .photo-thumbwrap { display: inline-block; }
.photo-del {
  position: absolute; right: -8px; top: -8px; width: 24px; height: 24px;
  border-radius: 50%; border: 2px solid var(--c-surface); background: var(--c-muted); color: var(--c-surface);
  font-size: 14px; line-height: 1; display: flex; align-items: center; justify-content: center;
  cursor: pointer; padding: 0;
}
.photo-del:hover { background: var(--c-danger); }
.photo-name { display: none !important; }   /* 参考图里没有文件名；文件名放 title 提示 */

/* SN 行：瓦片与输入框并排 —— 行高改为自动，避免瓦片被压 */
@media (max-width: 560px) {
  .wo-sn-row .photo-field { flex: 0 0 auto !important; width: auto !important; }
}

/* =============================================================================
 * 照片位**最终规则**（2026-10-04 用户：传完一张就错位 + "一格只能一张图，要多张点按键加一格"）
 * 根因：容器的"虚线蓝框"是前几轮的遗留样式（现在框里是瓦片，容器必须**透明无框、按内容宽**），
 *       且已传状态下不该再显示「＋」（**一格一张**；要多张由各段的 `+ Add photo` / `+ Add SN` 加格）。
 * 这条是**权威块**：把容器的边框/底色/内边距/最小宽度全部清掉，并锁死两个瓦片的尺寸。
 * ========================================================================== */
.photo-field {
  display: inline-flex !important; align-items: center !important; gap: 8px !important;
  background: none !important; border: 0 !important; border-radius: 0 !important;
  padding: 0 !important; margin: 0 !important;
  min-width: 0 !important; width: auto !important; height: auto !important; min-height: 0 !important;
  flex: 0 0 auto !important; justify-content: flex-start !important;
}
.photo-field .photo-thumbwrap, .photo-field .photo-add {
  flex: 0 0 auto !important; width: 88px !important; height: 88px !important;
}
.photo-field.on .photo-add { display: none !important; }   /* ★ 一格只放一张图 */

/* ⚠ 优先级修正（本轮第二次栽在同一件事上）：裸 `.photo-field`（0,1,0）**斗不过**
   `.wo-rpr-val.photo-field` / `.wo-sn-row .photo-field`（0,2,0）这类"类＋类"选择器 ⇒
   上面那条权威块被压住了。这里改用 **`#page` 前缀（1,1,0）** 重写一遍，一次压住全部旧规则。 */
#page .photo-field {
  display: inline-flex !important; align-items: center !important; gap: 8px !important;
  background: none !important; border: 0 !important; border-radius: 0 !important;
  padding: 0 !important; margin: 0 !important;
  min-width: 0 !important; width: auto !important; height: auto !important; min-height: 0 !important;
  flex: 0 0 auto !important; justify-content: flex-start !important;
}
#page .photo-field .photo-thumbwrap,
#page .photo-field .photo-add {
  flex: 0 0 auto !important; width: 88px !important; min-width: 88px !important;
  height: 88px !important; min-height: 88px !important;
}
#page .photo-field .photo-add {
  border: 2px dashed var(--c-border-2) !important; border-radius: 10px !important; background: var(--c-bg-2) !important;
  color: var(--t-3) !important; font-size: 34px !important; display: flex !important;
  align-items: center !important; justify-content: center !important;
}
#page .photo-field.on .photo-add { display: none !important; }   /* ★ 一格只放一张图 */
#page .photo-field .photo-del {
  position: absolute !important; right: -8px !important; top: -8px !important;
  width: 22px !important; height: 22px !important; border-radius: 50% !important;
  border: 2px solid var(--c-surface) !important; background: var(--c-muted) !important; color: var(--c-surface) !important;
  font-size: 13px !important; line-height: 1 !important; padding: 0 !important;
  display: flex !important; align-items: center !important; justify-content: center !important;
}
#page .photo-field .photo-thumbwrap { position: relative !important; display: none !important; }
#page .photo-field.on .photo-thumbwrap { display: inline-block !important; }

/* 🔴 2026-10-04 用户截图：**上传后 Serial No. (SN) 标签被盖住** —— 真因是**缩略图被撑高**（实测 ~165px）
   盖掉了上面那一行标签。这里用"最高优先级 + 裁切"把缩略图与它的容器钉死在 88×88。 */
#page .photo-field .photo-thumbwrap,
#page .field .photo-field .photo-thumbwrap,
#page .wo-sn-row .photo-field .photo-thumbwrap,
#page .photo-field .photo-thumbwrap { position: relative !important; display: none !important; }
#page .photo-field.on .photo-thumbwrap { display: block !important; }

/* =============================================================================
 * 缩略图**最终形态**（2026-10-04 用户：「上传之后图片显示不全、位置也不对」）：
 *   改用**背景图**渲染（`background-size: cover`）—— **不依赖 `<img>` 的原始尺寸**，
 *   所以永远不会像 `<img>` 那样被图片比例拉成非正方形。方块本体就是 `.photo-thumbwrap`。
 * ========================================================================== */
#page .photo-field .photo-thumbwrap {
  position: relative !important; display: none !important;
  width: 88px !important; min-width: 88px !important; max-width: 88px !important;
  height: 88px !important; min-height: 88px !important; max-height: 88px !important;
  border: 1px solid var(--c-border) !important; border-radius: 10px !important; background-color: var(--c-surface) !important;
  cursor: zoom-in !important; overflow: visible !important;
}
#page .photo-field.on .photo-thumbwrap { display: block !important; }

/* 2026-10-04 用户：删除键「×」太小 ⇒ 22×22 放大到 28×28、字号 13→17、外移一点更醒目（带轻微阴影） */
#page .photo-field .photo-del {
  width: 28px !important; min-width: 28px !important; height: 28px !important; min-height: 28px !important;
  right: -10px !important; top: -10px !important;
  font-size: 15px !important; font-weight: 600 !important; line-height: 1 !important;   /* 批 7：17→15 */
  border: 2px solid var(--c-surface) !important; background: var(--c-muted) !important; color: var(--c-surface) !important;
  border-radius: 50% !important; padding: 0 !important;
  display: flex !important; align-items: center !important; justify-content: center !important;
  box-shadow: 0 1px 3px var(--shadow-a2) !important; cursor: pointer !important;
}
#page .photo-field .photo-del:hover { background: var(--c-danger) !important; }

/* 2026-10-04 用户：删除键改 24×24，并**往内挪**（左移＋下移，贴在缩略图内右上角） */
#page .photo-field .photo-del {
  width: 24px !important; min-width: 24px !important; height: 24px !important; min-height: 24px !important;
  right: 2px !important; top: 2px !important;
  font-size: 13px !important; font-weight: 600 !important; line-height: 1 !important;   /* 批 7：15→13 */
  border: 2px solid var(--c-surface) !important; background: var(--c-muted) !important; color: var(--c-surface) !important;
  border-radius: 50% !important; padding: 0 !important;
  display: flex !important; align-items: center !important; justify-content: center !important;
  box-shadow: 0 1px 3px var(--shadow-a2) !important; cursor: pointer !important;
}

/* 选图来源弹窗（2026-10-04）：**去掉说明文字** ＋ **按钮文字不许溢出**
   —— 三个键放不下就换行；每个键至少占 45% 宽、文字不折行被裁。 */

/* =============================================================================
 * 2026-10-04 两处修补：
 * ① **F 段（及各段）标题被照片瓦片压住** —— `.wo-section > b` 原来是**行内元素**，
 *    照片瓦片是块级盒子、且带负向视觉（阴影/圆角）⇒ 标题左侧被盖。改为**块级 ＋ 层级在上 ＋ 下留间距**，
 *    这样"标题一行、内容从下一行开始"变成结构性的，不再依赖巧合。
 * ② **报错标红** —— 提交校验失败的字段/所在行加 `.row-error`（红框 ＋ 淡红底），配合 `woErr()` 的滚动与聚焦。
 * ========================================================================== */
.wo-section > b { display: block; margin-bottom: 8px; position: relative; z-index: 2; }
.wo-section > div { position: relative; z-index: 1; }
.row-error, .row-error.photo-field, .row-error .photo-add {
  border-color: var(--c-danger) !important;
  box-shadow: 0 0 0 2px var(--c-danger-a18) !important;
  background: var(--c-danger-bg) !important;
}
.field.row-error > label, .row-error > label { color: var(--c-danger) !important; font-weight: 600; }
.wo-sn-row.row-error { border-radius: 10px; }

/* 选图弹窗只剩两个键（2026-10-04 用户：右上角已有 ×，不需要 Cancel）⇒ 两个键平分一行 */

/* 表单页眉（2026-10-04 用户：把「← Back to list」与标题放到固定的页眉里） */
.topbar-sep { color: var(--c-border-2); margin: 0 4px; }
.topbar-formtitle { font-size: 14px; font-weight: 600; color: var(--c-text); white-space: nowrap; }
.btn-back.sm { padding: 4px 10px; font-size: 12px; }

/* 表单态页眉：不许换行、不许挤压（2026-10-04 用户截图：文字挤成两行/三行） */
.topbar { flex-wrap: nowrap; }
.topbar .menu-btn, .topbar .btn-back.sm, .topbar .topbar-formtitle { flex: 0 0 auto; white-space: nowrap; }
.topbar .topbar-formtitle { overflow: hidden; text-overflow: ellipsis; }
.topbar .title { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* 表单页眉排布（2026-10-05 用户：标题居中 · 返回键靠右 · 字号加大）
   用**三列网格**（1fr auto 1fr）⇒ 标题在页面正中间，与左右两侧宽度无关。 */
.topbar-form {
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center;
  gap: 10px; width: 100%; min-width: 0;
}
.topbar-form .menu-btn { justify-self: start; }
.topbar-form .topbar-formtitle {
  justify-self: center; white-space: nowrap;
  font-size: 15px; font-weight: 700; color: var(--c-text); letter-spacing: .2px;   /* 批 7：17→15 */
}
.topbar-form .btn-back { justify-self: end; white-space: nowrap; font-size: 14px; padding: 7px 14px; }

/* ⚠ 修正：`.topbar` 本身是 flex 容器 ⇒ 网格子元素会被"按内容宽"排布（实测标题偏左 197px、返回键离右 283px）。
   加 `flex: 1 1 100%` 让它**占满整行**，三列网格才成立。 */
.topbar-form { flex: 1 1 100%; }

/* =============================================================================
 * 表单页眉排布 —— **最终做法：绝对定位**（2026-10-05）
 * 前面用"三列网格 + flex/width"两次都没生效（实测标题中心仍偏左 197px、返回键离右 283px）——
 * 不再猜父层 flex/grid 的行为：直接**绝对定位**钉在页眉内 —— 标题水平居中、返回键贴右、菜单键贴左。
 * 绝对定位相对父容器计算，不受 flex 分配、内容宽度、兄弟元素影响 ⇒ 结构性保证。
 * ========================================================================== */
.topbar-form { position: relative !important; width: 100% !important; height: 100% !important; display: block !important; }
.topbar-form .topbar-formtitle {
  position: absolute !important; left: 50%; top: 50%;
  transform: translate(-50%, -50%) !important;
  font-size: 15px !important; font-weight: 700 !important; white-space: nowrap !important;   /* 批 7：17→15 */
}
.topbar-form .btn-back {
  position: absolute !important; right: 0; top: 50%; transform: translateY(-50%) !important;
  font-size: 14px !important; padding: 7px 14px !important; white-space: nowrap !important;
}
.topbar-form .menu-btn { position: absolute !important; left: 0; top: 50%; transform: translateY(-50%) !important; }

/* 页眉退出键：由「← Back to list」文字键改为 **圆形 ×**（2026-10-05 用户要求）
   位置不变（仍是页眉最右），动作不变（关闭表单回到列表）；标题仍绝对居中。 */
.topbar-form .topbar-x {
  position: absolute !important; right: 0; top: 50%; transform: translateY(-50%) !important;
  width: 36px !important; height: 36px !important; border-radius: 50% !important;
  border: 1px solid var(--c-border) !important; background: var(--c-surface) !important;
  color: var(--c-text) !important; font-size: 22px !important; line-height: 1 !important;
  display: flex !important; align-items: center !important; justify-content: center !important;
  cursor: pointer !important; padding: 0 0 3px 0 !important;
}
.topbar-form .topbar-x:hover { background: var(--c-danger-bg) !important; border-color: var(--c-danger) !important; color: var(--c-danger) !important; }

/* 草稿标记改为紧凑胶囊（2026-10-05 用户："未提交版式不好看"）：
   原来是一条占满整行的大黄块 ＋ 大按钮 ⇒ 现在是一条小胶囊，一行放完，不再挤压卡片信息。 */
.voided-banner { margin-bottom: 6px; }

/* 未提交标识（2026-10-05 用户：放到单号右边＝原客诉日期位置；并去掉 Continue 按钮） */
.badge.draft {
  margin-left: auto; background: var(--c-warn-bg) !important; border: 1px solid var(--c-warn-bd-2) !important;
  color: var(--c-warn) !important; font-weight: 600;
  border-radius: var(--radius-sm) !important;   /* G7-1（批 4）：原 999px 胶囊 ⇒ 与 .badge 家族同档 10px */
  padding: 1px 10px !important;
}

/* 滚轮标题（问题那行）：正常字号、允许换行；与两侧按钮留出间距，不与它们重叠 */
.wheel-head { align-items: center; gap: 10px; }
.wheel-head .wheel-title { white-space: normal; line-height: 1.28; font-size: 13px; text-align: center; flex: 1 1 auto; min-width: 0; }
.wheel-head .btn { flex: 0 0 auto; }

/* 字段级即时错误提示（2026-10-05）：离开字段时就地给出原因，不必等提交 */
.field-msg { color: var(--c-danger); font-size: 12px; line-height: 1.35; margin-top: 4px; }
.field .row-error, .field.row-error input, .field.row-error select { border-color: var(--c-danger) !important; }

/* "Not submitted" 与 "VOIDED" **同位置同大小**（2026-10-05 用户："都改为同一个位置，改到与 void 同样的位置、大小"）：
   逐项照抄 .voided-banner 的几何与字号，仅替换配色为琥珀。 */
.notsubmitted-banner {
  display: inline-block;
  background: var(--c-warn-bg); color: var(--c-warn); border: 1px solid var(--c-warn-bd-2);
  /* 与 .voided-banner **逐项一致**：字体族/字号/字重/字距/大小写/行高/内边距/圆角（2026-10-05 用户：“文字的字体、大小写、大小都要一样”） */
  font-family: inherit; font-size: 11px; font-weight: 700; font-style: normal;
  letter-spacing: 0.5px; text-transform: uppercase; line-height: inherit;
  /* G7-1（批 4）：横幅**保留自有尺寸**（用户 2026-10-05 要求两条横幅同位置同大小、字体字号一致），
     只把圆角提到三档之一 —— 取 10px，与 `.voided-banner` 保持一致。 */
  padding: 2px 8px; margin-bottom: 6px; border-radius: var(--radius-sm);
}

/* 审批块小标题（说明这是"审批分组"，不加任何颜色） */
.wo-bigblock-title { grid-column: 1 / -1; font-size: 12px; font-weight: 700; color: var(--c-muted); letter-spacing: .3px; text-transform: uppercase; margin-bottom: -4px; }

/* =============================================================================
 * 备件行紧凑化（2026-10-05 用户：“这个格式，你调整一下，感觉不够紧凑”）
 *   只调**尺寸与间距**，不动结构：
 *   · 缩略图 88 → 64px（行高随之下降）· 按钮改小 · 字段/标签外边距收紧 · 步进器变小
 * ========================================================================== */
.wo-part-row { padding-bottom: 6px !important; margin-bottom: 6px !important; }
.wo-part-row .field { margin-bottom: 5px !important; }
.wo-part-row .field label { font-size: 12px !important; margin-bottom: 2px !important; }
.wo-part-row .photo-thumbwrap,
.wo-part-row .photo-add,
.wo-part-row .photo-field .photo-thumbwrap { width: 64px !important; height: 64px !important; }
/* ② 批 B：旧尺寸覆盖已删（统一由 `.x-del` 给 30×30）*/
.wo-part-row .btn { height: var(--ctl-h-row) !important; min-height: var(--ctl-h-row) !important; padding: 0 10px !important; font-size: 13px !important; }   /* 批 7 §三-b：行内小档 32 · 唯一内边距 */
.wo-part-row input, .wo-part-row select { padding-top: 6px !important; padding-bottom: 6px !important; }


/* 备件行右侧操作区（2026-10-05 用户："数字框放到 delete 的位置，delete 去掉换成叉"）：
   数量步进器与 × 同处备件信息右侧；× 为圆形小按钮。 */
.wo-part-row .brief-part { display: flex; align-items: center; gap: 10px; }
.wo-part-row .wo-part-actions { margin-left: auto; display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
.wo-part-row .wo-part-x {
  width: 26px; height: 26px; border-radius: 50%; border: 1px solid var(--c-border);
  background: var(--c-surface); color: var(--c-danger); font-size: 16px; line-height: 1;
  display: inline-flex; align-items: center; justify-content: center; cursor: pointer; padding: 0;
}
.wo-part-row .wo-part-x:hover { background: var(--c-danger-bg); border-color: var(--c-danger); }

/* 每个备件一个"框"，并把 × 放到右上角、数量在右侧居中
   （2026-10-05 用户："我希望改成这样的布局，同时，在一个备件的外面，加一个框，把这些框在一起"） */
.wo-part-row .field.full {
  border: 1px solid var(--c-border); border-radius: 10px; background: var(--c-surface);
  padding: 10px 12px; margin-bottom: 6px;
}
.wo-part-row .brief-part { align-items: center; }
.wo-part-row .wo-part-actions {
  flex-direction: column; align-items: flex-end; justify-content: space-between;
  align-self: stretch; gap: 12px;
}
.wo-part-row .wo-part-x { order: -1; }                 /* × 排到最上（右上角） */
.wo-part-row .wo-pqty { margin-top: auto; }   /* 数量在右侧竖向居中偏下 */

/* ㊶（2026-10-08 · task-27 · 技术债）：这一组原来**三处并存** —— 本条旧口径 `nowrap` ＋ `> *:first-child{min-width:0}`（把
   缩略图/文字块压成 6px/13px 的**根因**）＋ 下方批 4 的覆盖组，靠"同特异性＋靠后＋`!important`"互相压 ⇒ **能用但脆弱**。
   现收敛成**一处定义**：本条直接给最终口径（放不下时才换行；`row-gap` 并进本条），下游只留"下限宽/不让位"（见本文件下方
   `.brief-part > .pp-thumb / > .brief-lines / > .brief-right / > .wo-part-actions` 四条）。 */
/* 修正：备件行**放得下就不换行**（2026-10-05 用户截图：× 与数量被挤到文字下方、框变高 ⇒ 不允许出现那种形态）；
   窄屏放不下时**允许换行**（2026-10-08 批 4/㉟ 的结论，此处并入本条，不再靠"靠后写覆盖"）。 */
.wo-part-row .brief-part { flex-wrap: wrap !important; row-gap: 6px !important; column-gap: 8px !important; align-items: center !important; }   /* (66)：文本左缘＝图片右缘＋8 */
/* ㊶：**已删除** `.wo-part-row .brief-part > *:first-child { min-width: 0 !important; flex: 1 1 auto !important; }`
   —— 它把缩略图与文字块都变成"可无限收缩项"，是 390 窄屏被压成 6px / 13px（一行一个词）的根因；
   下限宽由下面 `.brief-part > .pp-thumb`（64px）与 `.brief-part > .brief-lines`（140px）负责。 */
.wo-part-row .wo-part-actions { flex: 0 0 auto !important; align-self: center !important; justify-content: center !important; gap: 10px !important; }
.wo-part-row .field.full { padding: 10px 12px 10px 2px !important; }   /* (66)：左 12→2「整体靠左」；右 12 保持（保右缘 335）*/

/* 备件行右侧操作区**整体缩小**（2026-10-05 用户："现在的按键，数量框，都缩小一点，太大了"） */
  .wo-part-row .wo-part-actions button:not(.wo-part-x) {
    width: 30px; height: 30px; min-width: 30px; padding: 0; font-size: 13px; line-height: 1; border-radius: 50%;
  }   /* (66)：30×30 */   /* ㊽：与唯一模板同（34×34 圆）—— 具体配色/形状由 `.qty-step .qs-btn:*` 那两条给 */   /* 批 7 §三-d：工单备件行 ± 与模板同（30×34 · 圆角 8）*/
  .wo-part-row .wo-part-actions input {
    width: 40px; height: 30px; min-height: 30px; font-size: 13px; font-weight: 600; text-align: center;
    padding: 0; border: 0; border-radius: 4px; background: var(--c-primary-bg); color: var(--c-text);
  }   /* (66)：40×30 */   /* ㊽：工单备件行数字块（46×34 · 圆角 4 · 浅蓝底）*/
/* 批 7 §三-d 修正（自测：数量框被 `.field input{min-height:var(--ctl-h-sub)!important}` 顶到 38 ⇒ **三者不等高**）：
   用 (0,2,1)+!important 把模板内数字框钉在 **34px**（与 ± 同高；`.field` 那条是 (0,1,1)）。 */
#page .field .qty-step input[type="number"], #page .wo-part-row .qty-step input[type="number"],
#page .wo-part-row .wo-part-actions input, #page .field .wo-part-row .wo-part-actions input {
  height: 30px !important; min-height: 30px !important; max-height: 30px !important;
}   /* 批 7 §三-d：工单备件行数量框（40×34 · 13px · 圆角 9）*/
/* ② 批 B：旧尺寸覆盖已删（统一由 `.x-del` 给 30×30）*/


/* (66) · 裁定(丙)（2026-10-10）：**底部横带** —— 左边 `Current stock: N pcs`、右边 stepper；
   × 仍留在右上（`.wo-part-actions` 纵向、order:-1），三者右缘均对齐卡片内容右缘。 */

/* (66) 追加（批 B）：把“叉”从文档流里拿出来（右上角绝对定位）
   ⇒ 文本块能拉到卡片内容右缘，与叉/数量右缘三者相等（≤1px）。 */
.wo-part-row .brief-part { position: relative; }
.wo-part-row .wo-part-actions { position: absolute !important; top: 0 !important; right: 0 !important; margin-left: 0 !important; }
.wo-part-row .brief-part > .brief-lines { padding-right: 38px; }
/* ② 提高 `.x-del` 特异性：既有 `#page .photo-field .photo-del` 等带 !important 的规则会压过单类选择器 */
#page .x-del, .modal .x-del, body .x-del {
  width: 30px !important; height: 30px !important; min-width: 30px !important; padding: 0 !important;
  border-radius: 50% !important; background: #fff !important; border: 1px solid var(--c-danger) !important;
  color: var(--c-danger) !important; font-size: 14px !important; line-height: 1 !important;
  display: inline-flex !important; align-items: center !important; justify-content: center !important;
  box-shadow: 0 1px 3px rgba(15, 23, 42, .18) !important; position: relative;
}
#page .x-del:hover, .modal .x-del:hover, body .x-del:hover { background: var(--c-danger-bg) !important; }
/* (66) 补：空的 `.brief-right`（库存已搬到底部横带）不再占位，否则 `.brief-lines` 右缘差 8px（column-gap）*/
.wo-part-row .brief-part > .brief-right:empty { display: none; }
/* ② 再提一级：旧 `#page .photo-field .photo-del`（(1,2,0)+important）会压过 `#page .x-del`（(1,1,0)）⇒ 加到 (1,3,0) */
#page .photo-field .photo-del.x-del, .photo-field .photo-del.x-del {
  width: 30px !important; height: 30px !important; min-width: 30px !important; padding: 0 !important;
  border-radius: 50% !important; background: #fff !important; border: 1px solid var(--c-danger) !important;
  color: var(--c-danger) !important; font-size: 14px !important; line-height: 1 !important;
  display: inline-flex !important; align-items: center !important; justify-content: center !important;
  box-shadow: 0 1px 3px rgba(15, 23, 42, .18) !important; position: relative;
}
/* ②补（批 B 复验）：SN 行/维修照片行的 × 带 `.btn.ghost` 会被通用按钮高度（44）接管
   ⇒ 只在 `.x-del` 作用域内压到 30（**不改全站 `.btn`**）。 */
.btn.x-del, button.x-del, .btn.ghost.x-del, .btn.ghost.sm.x-del, .modal .btn.x-del,
#page .btn.x-del, #page button.x-del, #page .btn.ghost.x-del, body .btn.x-del {
  width: 30px !important; height: 30px !important; min-height: 30px !important; max-height: 30px !important;
  padding: 0 !important; border-radius: 50% !important;
}
/* ②复验：再加一级（(1,2,1)）—— `#page button.btn`（(1,1,1)）等规则会把「叉」拉到 44；只作用于 `.x-del` */
#page button.btn.x-del, #page button.x-del.btn, #page .wo-sn-row button.x-del, #page .wo-part-row button.x-del,
#page .wo-rpr-row button.x-del, .modal button.btn.x-del, body button.btn.x-del {
  width: 30px !important; height: 30px !important; min-height: 30px !important; max-height: 30px !important;
  padding: 0 !important; border-radius: 50% !important;
}
.wo-stock-band { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-top: 6px; }
.wo-stock-band .wo-pcur { font-size: 12px; color: var(--c-muted); }
/* 修正：`.brief-part` 的"第一个子元素可收缩"规则**不要作用在按钮上**
   （2026-10-05：它把 `Select spare part` 拉成了整行宽） */
.wo-part-row .brief-part > button:first-child { flex: 0 0 auto !important; }

/* "Select spare part" 加底色（2026-10-05 用户："加一个底色，要不然看不出来是一个按键"）
   —— 用系统主色的浅底（与 + Add spare part 同色系），一眼可辨为按钮。 */
.wo-part-row .brief-part > button:first-child {
  background: var(--c-primary-bg) !important;
  border-color: var(--c-primary) !important;
  color: var(--c-primary-d) !important;
  font-weight: 600 !important;
}
.wo-part-row .brief-part > button:first-child:hover { background: var(--c-primary) !important; color: var(--c-surface) !important; }

/* "Select spare part" 改为**输入框样式**（2026-10-05 用户："改为输入框，跟这个一样，加上 please select 的这个字样"）：
   与系统其它下拉/日期框一致 —— 白底、圆角、灰字占位符；点击后弹出备件选择。 */
.wo-part-row .brief-part input.wo-part-pick {
  flex: 1 1 auto !important; min-width: 0 !important; width: auto !important;
  background: var(--c-surface) !important; border: 1px solid var(--c-border) !important;
  border-radius: 10px !important; color: var(--c-text) !important;
  padding: 0 12px !important; font-size: var(--fs-body) !important; cursor: pointer !important;   /* 批 7：表单内 38px 档 · 字号 13 */
}
.wo-part-row .brief-part input.wo-part-pick::placeholder { color: var(--c-muted) !important; }
/* task-14（2026-10-12）：**清空「×」与占位文字不再重叠** —— 根因：「×」是**绝对定位**在 `.brief-part` 右上
   （见上面 `.wo-part-row .wo-part-actions{position:absolute;top:0;right:0}`），而预留 38px 的规则只作用在
   `.brief-lines`；新加的占位输入框 `.wo-part-pick` 是 `.brief-part` 的**直接子元素**、没有右内边距 ⇒ 文字压到 × 上。
   修法：给它同值的右内边距（38px，与 `.brief-lines` 同口径），不新造控件与档位。 */
.wo-part-row .brief-part > input.wo-part-pick { padding-right: 38px !important; }

/* ㉟（2026-10-08 · task-24）：**窄屏备件行被压成一列竖排**（用户 390 截图：备件信息一行一个词、压到下方字段）。
   改前实测（390）：`.pp-thumb` 被压到 **6px**、`.brief-lines` 被压到 **13px** ⇒ 信息块高 **333px**；
   根因：`.wo-part-row .brief-part > *:first-child{min-width:0; flex:1 1 auto}` 那一版规则把**图片与文字块都变成
   可无限收缩项**（㊶ 已删除），而右侧库存/操作区是 `flex: 0 0 auto` 不让位 ⇒ 文字块只能挤到 13px。
   修法（不改任何 JS/DOM）：① 给缩略图与文字块**下限宽度**（不再被压成竖排）；
   ② 放不下时允许 `.brief-part` **换行**（信息块一行、库存＋操作区落到次行）；放得下时仍是单行 ——
      **不破 2026-10-05 的结论**（那条针对"× 与数量被挤到文字下方"，本规则只在真的放不下时才换行）。
   ⚠ 选择器全部限定在 `.wo-part-row` 内 ⇒ 弹窗里的 `.brief-part`（选件列表/确认页）不受影响。 */
/* ㊶：原来这里还有一条 `.wo-part-row .brief-part { flex-wrap: wrap !important; row-gap: 6px !important; }`
   —— 与上面改写过后的基础规则完全重复（那是"靠后写覆盖"的产物）⇒ **已删除**；渲染等价见交付报告的量测对照。 */
.wo-part-row .brief-part > .pp-thumb { flex: 0 0 auto !important; width: 64px !important; height: 64px !important; object-fit: cover !important; }   /* (66)：正方形 64、cover、不参与伸缩 */
.wo-part-row .brief-part > .brief-lines { flex: 1 1 160px !important; min-width: 140px !important; overflow-wrap: anywhere; }
.wo-part-row .brief-part > .brief-right { flex: 0 0 auto !important; }
.wo-part-row .brief-part > .wo-part-actions { flex: 0 0 auto !important; margin-left: auto !important; }

/* SN 软提醒（2026-10-05）：琥珀色提示，**不标红、不拦提交** */
.field-msg.soft { color: var(--c-warn-soft); }   /* ⚠ A1 软提醒色（#8a6d1f · "可以不管"那一级）—— 与警示档 --c-warn 语义不同，别混用 */

/* "Confirm part" 的紧凑信息表（2026-10-05） */

/* F 段：大件审批卡（2026-10-05） */
#wo-parts .wo-bigblock { display: none !important; }        /* 原有审批字段块隐藏，只作数据载体 */
#wo-bigsec { margin-top: 14px; }
.wo-bigcard { border: 1px solid var(--c-border); border-radius: 10px; background: var(--c-surface); padding: 12px 14px; margin-bottom: 12px; }
/* 2026-10-06 用户：「**bms的名称和details，上下居中对齐，不是左右居中**」
   ⚠ 更正：我先前的理解错了（做成了左右居中 `text-align: center`）—— **已撤**。
   正解 ＝ 标题行改 flex ＋ `align-items: center` ⇒ **备件名与 Details 按钮垂直居中对齐**；水平仍保持左对齐。 */
.wo-bigcard-title { font-weight: 700; font-size: 14px; margin-bottom: 8px; display: flex; align-items: center; flex-wrap: wrap; }

/* F 段必填缺项：红星同款标红（2026-10-05） */
#wo-bigcards .big-err, #wo-bigcards input.big-err, #wo-bigcards select.big-err { border-color: var(--c-danger) !important; box-shadow: 0 0 0 3px var(--c-danger-a12) !important; }
#wo-bigcards .photo-field.big-err .photo-add { border-color: var(--c-danger) !important; color: var(--c-danger) !important; box-shadow: 0 0 0 3px var(--c-danger-a12) !important; }

/* =============================================================================
 * P1/P2 界面系统性优化（2026-10-05，依据《界面评审-工单页》P1＋P2）
 *   P1 控件高度归一 44px ＋ 字号收敛为 12/13/15（消除 4 种控件高度、7 档字号）
 *   P2 点按热区 ≥40px —— **视觉尺寸一律不变**，只用伪元素扩大可点区域
 * ========================================================================== */
:root { --ctl-h: 44px; --ctl-h-sub: 38px; --ctl-h-row: 32px; --fs-label: 12px; --fs-hint: 12px; --fs-body: 13px; --fs-title: 14px; --fs-sec: 15px; }   /* 批 7（2026-10-09 ·《字体与控件标准》定稿 v1）：T2 标签 12 · T3 正文 13 · T4 小标题 14 · T5 区段 15；新增 --ctl-h-sub(表单 38) / --ctl-h-row(行内 32) */

/* ---- P1-1 表单控件统一高度（下拉 / 输入 / 文本域 / 日期滚轮 / 备件选择） ---- */
#page .field input:not([type="hidden"]):not([type="checkbox"]):not([type="radio"]):not(.qs-num),
#page .field select,
#page .field textarea,
#page .field .date-wheel,
#page .field .wo-part-pick { min-height: var(--ctl-h-sub) !important; }   /* 批 7：表单内字段 44 → 38（筛选栏/按钮仍 44）*/

/* ---- P1-1b 筛选栏（.tb-filters）不在 .field 内 ⇒ P1-1 覆盖不到它 ----
 * 2026-10-05 补：列表页两个筛选下拉实测只有 40px。真因＝覆盖率缺口 ＋ 覆盖顺序：
 *   基础规则 `select { min-height: 40px }`（本文件更靠后）与移动端 `@media select { min-height: 44px }`（更靠前）
 *   特异性相同（0,0,1）⇒ **靠后者胜** ⇒ 那条 44px 从未生效。
 * 修法＝按 P1 同一口径把筛选栏下拉纳入 --ctl-h（(1,1,1) + !important，稳压基础 select）· 不分断点（与 P1-1 一致）。 */
#page .tb-filters select, #page .toolbar select { min-height: var(--ctl-h) !important; }   /* A2③（2026-10-07 批 1）：stock 页 3 个下拉在 `.toolbar` 里（不在 .tb-filters）⇒ 一并纳入 */

/* 批 2b（2026-10-08）：孤儿 CSS 第二波已删除（32 个类 · 清单见文末注释）—— 原位留痕。 */
/* ---- P1-2 常规按钮统一高度（**不含**小图标按钮与小步进器） ---- */
#page button.btn:not(.sm):not(.xs),
#page .btn-add,
#page .btn-back { min-height: var(--ctl-h) !important; }

/* ---- P1-3 字号收敛为 12 / 13 / 15 ---- */
#page label, #page .field > label { font-size: var(--fs-label) !important; }
#page .field input, #page .field select, #page .field textarea,
#page .wo-bigcard-title { font-size: var(--fs-title) !important; }   /* 批 7：卡片小标题走 T4(14) */
#page .muted, #page .field-msg, #page .wo-sn-date,
#page .bl-spec, #page .bl-code, #page .hint { font-size: var(--fs-hint) !important; }
#page .wo-section > b { font-size: var(--fs-sec) !important; }

/* ---- P2 点按热区 ≥40px（**不改视觉尺寸**） ---- */

/* ②（2026-10-10 批 B · 用户定稿）：**删除标识（唯一）** —— 圆形 · 白底 · 1px `--c-danger` 描边 · 红叉 · 浅阴影 · **30×30**；
   热区用 `::after inset -5px` 扩到 40×40（**不改视觉尺寸**）。全站删除 × 一律挂 `.x-del`（防再分叉）。 */
.x-del {
  width: 30px !important; height: 30px !important; min-width: 30px !important; padding: 0 !important;
  border-radius: 50% !important; background: #fff !important; border: 1px solid var(--c-danger) !important;
  color: var(--c-danger) !important; font-size: 14px !important; line-height: 1 !important;
  display: inline-flex !important; align-items: center !important; justify-content: center !important;
  box-shadow: 0 1px 3px rgba(15, 23, 42, .18); cursor: pointer; position: relative;
}
.x-del::after { content: ""; position: absolute; inset: -5px; }
.x-del:hover { background: var(--c-danger-bg) !important; }
/* ② 关闭类（≠删除）：无底、无圆、纯灰 ×（弹窗 × 与页眉条 ×）；页眉热区保持 ≈36 用透明内边距 */
.modal .x { background: transparent !important; border: 0 !important; border-radius: 0 !important; color: var(--c-muted) !important; }
.topbar-form .topbar-x { background: transparent !important; border: 0 !important; border-radius: 0 !important; color: var(--c-muted) !important; padding: 10px !important; }
.topbar-form .topbar-x:hover { background: transparent !important; border: 0 !important; color: var(--c-text) !important; }
.wo-part-x { position: relative; }
.wo-part-x::after { content: ""; position: absolute; inset: -5px -9px; }               /* 22×22 → 40×32 热区 */
.wo-part-row .wo-part-actions button:not(.wo-part-x) { position: relative; }
.wo-part-row .wo-part-actions button:not(.wo-part-x)::after { content: ""; position: absolute; inset: -5px -4px; }  /* 30 → 40 */
.photo-del { position: relative; }
.photo-del::after { content: ""; position: absolute; inset: -8px; }

/* =============================================================================
 * P3 / P4 / P5（2026-10-05，依据《界面评审-工单页》）
 *   P3 信息密度：标签 13 · 正文 15 · 说明 12（三档到底，不再有 12 满屏）
 *   P4 文字色收敛：**三档灰 + 主色 + 语义红/琥珀**（原来的杂灰全部并入 --t-3）
 *   P5 长表单导航：**段内跳转条** ＋ **跳到未填项**
 * ========================================================================== */
:root {
  --t-1: #1e293b;   /* 主文 */
  --t-2: #64748b;   /* 次文 */
  --t-3: #94a3b8;   /* 提示/占位 */
}
/* P4：正文与说明的用色统一到三档（语义色保持不变） */
#page { color: var(--t-1); }
/* ⚠ 2026-10-07 批 1 · A1：这一条原来是 `.muted` 与 `.field-msg` **同一档灰 ＋ !important** ⇒
   把 `.field-msg`（硬错红 `var(--c-danger)`）与 `.field-msg.soft`（软提醒琥珀 `var(--c-warn)`）**一起压平**，
   界面上"必须改"与"可以不管"长得一样。**做法 ＝ 把 `.field-msg` 从这条里让位**（不是再加一条红字覆盖 ——
   那样软提醒仍是灰）：颜色回到各自定义 ⇒ 硬错红 / 软提醒琥珀。字号仍由 P1-3 那条统一（12px）。 */
#page .muted, #page .hint, #page .wo-sn-date,
#page .bl-code, #page .bl-spec,
#page .wo-part-actions label, #page .ey-parts-label label { color: var(--t-2) !important; }
#page label, #page .field > label { color: var(--t-2) !important; }
/* ⚠ 2026-10-06 修：原来这一条把 `.date-wheel` 与占位符并在一起并带 !important ⇒ **控件本体被永久染成占位灰**，
   日期滚轮**选了值仍是灰的**（基础规则里的 `color: var(--c-text)` 被压掉）。现按本文件既有约定拆开：
   **空＝提示灰 / 已填＝主文色**（与其它字段值同色 · 见 `#page { color: var(--t-1) }`）。 */
#page input::placeholder, #page textarea::placeholder { color: var(--t-3) !important; }
#page .date-wheel { color: var(--t-3) !important; }
#page .date-wheel:not(:placeholder-shown) { color: var(--t-1) !important; }
#page .wo-section > b { color: var(--t-1) !important; }


/* P4 收尾（2026-10-05）：**必填红星与语义红统一** · **照片 ＋ 归到提示灰** */
.req { color: var(--c-danger) !important; }
#page .wo-part-x { color: var(--c-danger) !important; }
.photo-add { color: var(--t-3) !important; }

/* =============================================================================
 * A 一致性收尾（2026-10-05）：控件高度统一 44 · 字号只剩 12/13/15
 *   实测问题：按钮 44px 而输入框 47px（含边框）；字号残 13.3333px（浏览器默认按钮字号）等
 * ========================================================================== */
#page .field input:not([type="hidden"]):not([type="checkbox"]):not([type="radio"]):not(.qs-num),
#page .field select,
#page .field .date-wheel { height: var(--ctl-h-sub) !important; min-height: var(--ctl-h-sub) !important;
  padding-top: 0 !important; padding-bottom: 0 !important; box-sizing: border-box !important; }
/* 浏览器未设字号的按钮/输入默认 13.3333px ⇒ 统一到 13px */
#page button, #page input, #page select, #page textarea { font-size: 13px !important; }
#page .field input, #page .field select, #page .field textarea { font-size: var(--fs-body) !important; }   /* 批 7：表单正文 15 → 13 */


/* ==========================================================================
 * 工单表单「一题一卡」（2026-10-06 · 用户要求，参照 Google Forms 的样子）
 *   用户原话：「**改成像这样，每个问题，是一个卡片，然后有一个背景色，卡片卡片之间有一个间隔**」
 *   ① 表单外层换**浅灰底**（`--c-bg-2`）⇒ 白卡才有对比，否则白卡压在白底上看不出是卡
 *   ② 每个问题（`.field`）＝**白卡**：圆角 ＋ 描边 ＋ 极淡阴影
 *   ③ **卡与卡的间隔**由既有的 `.row-form { gap: 14px }` 给 ⇒ 卡自身 `margin-bottom` 归零（不叠加两道间距）
 *   范围：**仅工单表单 `.wo-form`**；选择器走 `.wo-section > .row-form > .field` 的**直接子级链**，
 *         正好避开 `#wo-parts` 里更深的备件行字段与 `#wo-bigcards` 的大件审批卡。
 * ========================================================================== */
.wo-form { background: var(--c-bg-2); }
.wo-form .wo-section > .row-form > .field,
.wo-form .wo-section > .field {          /* 2026-10-06 补：直接挂在段下的字段（Repair Times (auto) 与两个组标签）也要卡 */
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: var(--radius-sm);
  padding: 10px 12px 12px;
  box-shadow: 0 1px 2px var(--shadow-a04);
  margin-bottom: 0;
}
/* 报错时红框画在**卡片**上（卡片化之后，一眼看出是哪张卡出错；控件自身的红框规则仍保留） */
.wo-form .wo-section > .row-form > .field.row-error,
.wo-form .wo-section > .field.row-error {
  border-color: var(--c-danger) !important;
  background: var(--c-danger-bg);
}

/* ---- 组卡：把「组标签 ＋ 明细行 ＋ 加号按钮」收进**同一张卡**（2026-10-06 用户：「这3个，放在同一个卡片里面」）----
 * 与题面卡同款外观；组卡内的 `.field` 不再是 `.wo-section` 的直接子级 ⇒ **自动退回普通标签**（不再自己成卡）。
 * 当前两处：备件组（Spare Parts Replaced ＋ 备件行 ＋ + Add spare part）· 维修照片组（Repair Photos ＋ 槽位 ＋ + Add repair photo）。 */
.wo-form .group-card {
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: var(--radius-sm);
  padding: 10px 12px 12px;
  box-shadow: 0 1px 2px var(--shadow-a04);
  /* A5（2026-10-07 批 1）：14 → 10 —— 组卡是所在 `.wo-section` 的 **last-child** ⇒ 上面那条
     `:not(:last-child){ margin-bottom: 10px }` 选不中它 ⇒ 间距只剩这里写死的 14（同表单两种间距）。 */
  margin-bottom: 10px;
}
.wo-form .group-card > .field { margin-bottom: 8px; }   /* 组卡内的标签：普通间距，不做卡 */

/* ---- 段内间距：**按根因修**（2026-10-06 第二次修 · 先诊断后动手）----
 * 【根因】卡片规则给每张卡写了 `margin-bottom: 0`，把间隔责任推给 `.row-form { gap: 14px }`；
 *   但 **`gap` 只作用于同一个网格内部、不跨容器** ⇒ 凡是"间隔发生在容器边界"的地方就**没有间隔来源**：
 *     ① `Serial Number` 卡（网格内）→ `Repair Times` 卡（网格**之后**的直接子级）：实测 **gap 0**；
 *     ② 第 1 个 `.row-form` → 第 2 个 `.row-form`（第二个带内联 `margin-top:8px`）：实测 **gap 8**（只剩那个写死的 8）。
 * 【修法】**段内每个"非最后一个"子元素自带 14px 下边距** ⇒ 所有容器边界（网格→字段 / 网格→网格 / 卡→组卡 …）都恢复间隔；
 *   **相邻块级外边距会合并**（14 与内联 8 ⇒ 取 14）⇒ 不会叠成 22；段与段之间仍由 `.wo-section { margin: 0 0 16px }` 负责。
 *   比"把段改成 flex"风险低：**不动 display、不动网格**。
 * 【判据】**上下相邻两张卡的间距必须 ≥ 12px**（驱动 `cardGaps.violationCount` 已内置断言；改前为 2）。 */
/* 【间距口径 · 2026-10-06 用户「改成跟工单列表里的一样」】表单卡片间距**统一 10px** ＝ 列表的 `.vlist { gap: 10px }`；
   下面三条（网格 gap / 段内下边距 / 段与段）**必须同值**，否则同一张表单里会出现两种间距。 */
.wo-form .row-form { gap: 10px; }                          /* ① 网格内的卡 */
.wo-form .wo-section > *:not(:last-child) { margin-bottom: 10px; }   /* ② 段内跨容器的卡（网格→字段 / 网格→网格） */
/* ②b（2026-10-07 批 1 · A5）：**最后一个子元素同样 10** —— `.wo-section` 的 padding-bottom / border-bottom
   实测都是 0 ⇒ 子元素的 margin-bottom 会与段自身那条 `margin-bottom: 10px` **合并**（取大者）⇒ 视觉零变化；
   但 A5 判据量"每个 `.wo-section > *` 的 margin-bottom 都＝10"，`:not(:last-child)` 会让每段最后一个留 0。
   ⚠ 特异性与上面卡片规则（`… > .field { margin-bottom: 0 }`，同为 0,3,0）打平 ⇒ **靠位置更后**取胜。 */
.wo-form .wo-section > *:last-child { margin-bottom: 10px; }
.wo-form .wo-section { margin-bottom: 10px; }              /* ③ 段与段 */

/* ---- 统一卡片格式：**工单详情 ↔ 工单列表**（2026-10-06 用户：「工单详情里的卡片的格式，改成跟工单列表里的一样。然后这2个改为统一格式」）----
 * 详情（`.modal.modal-vitem`）与列表卡片（`.vitem`）**用同一套值**：圆角 10px · 1px 描边 · 同一阴影 · 内边距 12px 14px；
 * 行也同 `--` 与 `.vrow` 同值：13px · 虚线分隔 · 上下 4px · **值右对齐**。
 * ⚠ 范围**仅工单详情**（`modal-vitem`）—— 其它弹窗（备件/采购/调拨/盘点详情）**仍用原来的 `.detail-row`**，不受影响。 */
.modal.modal-vitem { border: 1px solid var(--c-border); border-radius: 10px; box-shadow: var(--shadow); padding: 12px 14px; }
.modal.modal-vitem .detail-row { padding: 4px 0; border-bottom: 1px dashed var(--c-border); }
.modal.modal-vitem .detail-k { width: auto; min-width: 104px; }
.modal.modal-vitem .detail-v { text-align: right; }

/* ---- 备件选择弹窗（`Select spare part`）与列表 / 详情统一（2026-10-06 用户：「**这里的，也改一下样式，包括格式、间隔和颜色等等，跟工单详情和工单列表里的一样**」）----
 * 外壳：复用 `.modal-vitem`（与工单详情同一个类）⇒ 圆角 10 · 1px 描边 · 同一阴影 · 内边距 12/14（自动生效，无需重复写）。
 * 下面把**列表项 / 标签 / 下拉 / 行间距**对齐到参照值（参照 ＝ 列表卡片 `.vitem` 与列表/详情行）。
 * ⚠ 作用域仅 `.modal-vitem`（＝ 工单详情 ＋ 备件选择）—— **其它弹窗不受影响**。
 * 搜索框保持胶囊（全站搜索框都是胶囊，列表页也一样 ⇒ 属应用惯例，不是不一致）。 */
.modal-vitem .ps-item { background: var(--c-surface); border-radius: 10px; box-shadow: var(--shadow); padding: 12px 14px; margin-bottom: 10px; }
.modal-vitem .ps-item:last-child { margin-bottom: 0; }
.modal-vitem .ps-item:hover { background: var(--c-bg); }
.modal-vitem .ps-item.whole { background: var(--c-primary-bg); }
.modal-vitem .row-form { gap: 10px; }                     /* 与全站卡片间距口径一致 */
/* 弹窗内下拉统一到「工单列表筛选区」的实测标准：圆角 10px（--radius-sm）· 高 44px（--ctl-h）· 字号 13px
   （2026-10-06 用户：「备件选择那里…跟工单列表里的选项一样的格式」＋「两个已知差异一起收」；
     改前弹窗下拉实测 45.6px / 14px ⇒ 现全站弹窗下拉统一；这条同时覆盖 .modal-vitem，故原先那条已删） */
.modal select { border-radius: var(--radius-sm); height: var(--ctl-h-sub); font-size: 13px; }   /* 批 7：弹窗=表单态 ⇒ 38 */
/* ---- G1/G6（2026-10-07 批 1）：**弹窗**里的按钮/输入与页面内同类同值 ----
 *   根因：上面 P1-2（按钮高度 · `#page button.btn`）与 P1-3（字号 · `#page button,input,select,textarea`）
 *         两组都只写了 `#page` 作用域，而弹窗挂在 body 下 ⇒ 拿不到（实测弹窗按钮 36px/14px vs 页面 44px/13px）。
 *   （弹窗下拉当初已单独补过 —— 见上一行 `.modal select`；这里补按钮与输入类。）
 *   小号档 `.btn.sm` / `.btn.xs` **不受高度约束**（保留站内小号档的存在）。 */
.modal .btn:not(.sm):not(.xs) { min-height: var(--ctl-h) !important; }
.modal button, .modal input:not([type="hidden"]):not([type="checkbox"]):not([type="radio"]),
.modal select, .modal textarea { font-size: 13px !important; }
.modal input:not([type="hidden"]):not([type="checkbox"]):not([type="radio"]):not([type="file"]):not(.qs-num) {   /* 批 7 §三-d：**语义排除** —— 数量模板的数字框（`.qs-num`）自带 34px 高度，不属于"弹窗字段 44px"这条；
      本条特指度 (0,5,1)+!important，是弹窗内数量框被顶到 44px 的真凶 ⇒ 加 :not(.qs-num) 一处排除覆盖全部弹窗场景。 */
  min-height: var(--ctl-h) !important; box-sizing: border-box !important; }

/* ---- 权限页：**每个角色一张卡**（2026-10-06 用户：「这个页面…很多信息都是不全的，看不到」）----
 * 原实现是 5 列表格 ＋ 列头塞按钮 ＋ `width:100%` ⇒ 列被硬挤、菜单名被裁成 `Dash...` ✗
 * 现在**不用表格** ⇒ 没有固定列宽、**没有可截断的地方**；窄屏一列、宽屏两列。 */
.perm-grid { display: flex; flex-direction: column; gap: 14px; }
@media (min-width: 760px) { .perm-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); } }
/* 批 I-a（2026-10-11）：**权限页工具栏跨满两列** —— `.perm-grid` 在 ≥760px 是两列网格，而它的第一个子元素正是
   `.toolbar`、第二个是超管固定卡 ⇒ 两者同处第 1 行，网格项默认 `align-self:stretch` ⇒ 工具栏被拉伸到同排卡片高度
   （实测 106.7px）且只占左半列宽。加上跨列后工具栏高度回到 ≈44px、宽度＝卡片内容宽。
   ⚠ <760px 走上面的 flex 单列分支，本来就正常 ⇒ 这条规则只在网格分支生效（媒体查询外声明即等价）。 */
.perm-grid > .toolbar { grid-column: 1 / -1; }

/* task-17（2026-10-12）：评分卡**四列**（项目名 / 合格线 / 权重 / 得分）。
   新增类仅两处、理由逐条：① `.score-table` —— 既有 `.row-form` 是**两列**网格、`.perm-row` 是权限矩阵专用
   （列宽固定 40px），都不适合"1 名称列 ＋ 2 输入列 ＋ 1 数值列"，故用一个 scoped grid；
   ② `.score-cell/.score-head/.score-name/.score-val` —— 仅做对齐与标题色，取既有令牌（`--fs-hint`/`--c-muted`）。
   输入框仍走既有 `.field input`（44px 档）⇒ 控件档位不变；`.field` 的 14px 下边距在网格内清零。 */
/* task-19（2026-10-12 批 B）：设置页 12 行里每行两个"第 N 日"数字框 ⇒ 需要窄档宽度。
   新增类仅此一个（`.mw-day`）· 只给宽度，**字号/内边距/高度全走既有 `input` 档位**（不新造控件风格）。 */
.mw-day { width: 68px; }

.score-table { display: grid; grid-template-columns: minmax(0, 1fr) 92px 92px 72px; gap: 8px 12px; align-items: center; }
.score-table .field { margin-bottom: 0; }
.score-cell { font-size: 13px; min-width: 0; overflow-wrap: anywhere; }
.score-head { font-size: var(--fs-hint, 12px); color: var(--c-muted); }   /* 表头与 .field label 同档（12px 弱色） */
.score-val { text-align: right; font-variant-numeric: tabular-nums; color: var(--c-text); }   /* ＝ .vrow .v 的数值样式（右对齐＋等宽数字） */
@media (max-width: 480px) { .score-table { grid-template-columns: minmax(0, 1fr) 76px 76px 56px; } }
.perm-role { border: 1px solid var(--c-border); border-radius: 10px; background: var(--c-surface); overflow: hidden; }
/* ㊲（2026-10-08 · task-24 · 方案 A）：标题行原为 `--c-bg-2`（与页面容器 `.card` 同色 ⇒ 层次糊在一起）。
   改为**白**（`--c-surface`）＋ 靠 `--c-border` 底边线分层；固定卡的标题行仍是 transparent（见下方 .perm-fixed）。 */
.perm-head { display: flex; align-items: center; gap: 8px; padding: 10px 12px; background: var(--c-surface); border-bottom: 1px solid var(--c-border); }
.perm-head b { font-size: 14px; }
.perm-count { font-size: 12px; color: var(--c-muted); }
/* 权限管理页（2026-10-06）：每权限一行 × 查看/修改/批准 三列（无固定列宽 ⇒ 不会截断） */
/* ㊲：表头行同理由 `--c-bg-2` → 白；与标题行/数据行之间只靠边线区分（数据行本来也是白 + 虚线上边线）。 */
.perm-row.perm-head-row { background: var(--c-surface); border-radius: var(--radius-sm); font-size: 12px; }
.perm-col { flex: 0 0 40px; width: 40px; display: flex; align-items: center; justify-content: center; }
/* 权限管理页版式（2026-10-07 重做 · **照 app 既有版块**：card ＋ toolbar ＋ 小 ghost 按钮 ＋ --ctl-h 控件） */
.perm-head-edit { display: block; }
.perm-tool { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; min-width: 0; }
/* 第二行（范围 ＋ 改名/停用/删除）：按钮更紧凑；**放不下就换行，绝不被裁掉** */
/* 批 7 §三-b：页面级按钮覆盖已删 */
/* 第 2 行：**标签（可查看地区）＋ 下拉**单独一行（2026-10-07 用户） */
.perm-tool-2 { flex-wrap: nowrap; }
/* 第 3 行：**框占满剩余宽度**（2026-10-07 用户："框可以左右宽度宽一些"） */
/* 「指定网点（可多选）」⇒ 卡上多出一排网点勾选（角色级 `locIds`） */
.perm-loc { display: inline-flex; align-items: center; gap: 4px; font-size: 12px; color: var(--c-text); }
/* task-15/22/22b/22c/22d（2026-10-12）· 看板类别行：**按视口显式分方案**（用户原话两个选项："要么都在同一行，要么每个一行"）
   ── 实测依据（Lead 跑的 `_p922c` · 逐视口 **子元素右边界 − 行内容盒右界** 与 行级 `scrollW − clientW`）：
      360 = 无溢出（走 B）· **1280 = 无溢出 ⇒ A 可行** · 1040 = worstOver **51.9** · 760 = **72.4** · 390 = **91.9**
      （390 原始量：rowContentW 291 vs 四子项 103.9 ＋ 3×81 ＋ 3×12 ≈ 383 ⇒ 缺 ~92px）
   ⇒ **断点**：A 只在 **≥1280px** 生效；**<1280 一律走 B（每个勾各占一行）** —— 断点落在实测的 1041–1280 之间，取 1280。
   ⇒ 曾用"缩名「维修工单」"来在窄档强行同行；窄档改走 B 后**该手段用途消失** ⇒ 文案已恢复原名（1280 用原名也放得下：自然宽 −24）。
   ── B（默认，<1280）：标签独占一行（满行）＋ 每个勾各占一行 ⇒ 每项一个 top、严格递增，且**任何项都不被压扁** */
.perm-row.perm-cat-row { flex-wrap: wrap; align-items: flex-start; }
.perm-cat-row .perm-name { flex: 0 0 100%; min-width: 0; }
.perm-cat-row .perm-loc.perm-cat { flex: 1 1 100%; }
/* ── A（≥1280）：标签 ＋ 三个勾**同一行**（`rowLineGroups == 1`）——
   ① 顶端对齐（`.perm-row` 基础规则是 `align-items:center`，且**文件里更靠后** ⇒ 必须用 0,2,0 的选择器压过它，
      否则 2 行的标签与 22px 的勾顶端差 ~7px、视觉侧按 top 聚类会判 M ✗）
   ② 勾**不收缩**（被压缩时勾内文字换行 ⇒ 各勾高度不同 ⇒ 顶端不再同一水平线）
   ③ 标签给**可读下限** `max-content`（防 task-22 那次的"压成 3px 竖排"回归） */
@media (min-width: 1280px) {
  .perm-row.perm-cat-row { flex-wrap: nowrap; align-items: flex-start; }
  .perm-cat-row .perm-name { flex: 0 1 auto; min-width: max-content; }
  .perm-cat-row .perm-loc.perm-cat { flex: 0 0 auto; }
}
.perm-tool + .perm-tool { margin-top: 8px; }
.perm-tool strong { font-size: 14px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 批 7 §三-b：页面级按钮覆盖已删（原 padding 0 7px / 30px 散装值）*/
.perm-count { flex: 0 0 auto; white-space: nowrap; font-size: 12px; color: var(--c-muted); }
.perm-badge { flex: 0 0 auto; white-space: nowrap; font-size: 12px; padding: 2px 6px; border-radius: var(--radius-sm);
  background: var(--c-bg-2); color: var(--c-muted); border: 1px solid var(--c-border); }
/* 数据范围选择器：**紧凑**（占前半行即可，不再拉满整行 ✗） */
.perm-scope-sel { flex: 0 1 auto; max-width: 40%; height: var(--ctl-h); border: 1px solid var(--c-border);
  border-radius: var(--radius-sm); font-size: 13px; background: var(--c-surface); }

.perm-row { display: flex; align-items: center; gap: 12px; padding: 10px 12px; cursor: pointer; border-top: 1px dashed var(--c-border); }
.perm-row:first-of-type { border-top: 0; }
.perm-row:active { background: var(--c-bg); }
.perm-name { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; font-size: 13px; line-height: 1.35; word-break: break-word; }
.perm-name em { font-style: normal; font-size: 12px; color: var(--c-muted); }   /* G5（批 3）：11 → 12，与 .muted 同档 */
.perm-row input { flex: 0 0 auto; width: 22px; height: 22px; }
/* 超管"固定"卡（2026-10-06：超管不给开关 —— 口径 #43「超管自身不可改」）⇒ 视觉上不可交互 */
/* ㊲：固定卡（不可编辑）原与页面容器同为 `--c-bg-2` ⇒ 撞色 ⇒ 曾改用 `--c-bg`（#f7f9fc，比容器浅一档）。
   (56)（2026-10-11 批 H）：那个浅灰与**其它角色卡**（`.perm-role` ＝ `--c-surface` #fff，见上文 1861）不一致 ⇒
   底色**改白**（`--c-surface`），四张卡观感统一；页面容器此时是 `--c-bg-2`（#f1f5f9）⇒ **仍不撞色**。
   标题行保持 transparent（白对白 ⇒ 等效白底），"浅色＝不可编辑"的旧语义不再由底色承担
   （固定卡的只读性由"无勾选框 ＋ `perm-fixed` 分支不渲染操作按钮"表达）。 */
.perm-role.perm-fixed { background: var(--c-surface); }
.perm-role.perm-fixed .perm-head { background: transparent; border-bottom: 0; }
.perm-role.perm-fixed .perm-count { color: var(--c-primary-d, var(--c-muted)); }

/* 大件审批卡标题里的 Details 入口（2026-10-06 用户：标题只留名称、后面加"详细信息"）——
   小号文字按钮：不抢标题视觉，但可点（触控热区靠 padding 撑到约 32px 高）。 */
.wo-bigcard-title .big-info {
  margin-left: 8px; padding: 4px 8px;
  font-size: 12px; font-weight: 500; font-family: inherit;
  color: var(--c-primary-d); background: var(--c-primary-bg);
  border: 1px solid var(--c-primary); border-radius: 999px;
  cursor: pointer; vertical-align: middle;
}

/* =============================================================================
 * 2026-10-08 · 批 2b（task-21）· 孤儿 CSS 第二波删除清单（32 个类选择器 / 59 条规则）
 *   定档依据：这些类在 app.js ＋ index.html 里**类名字面命中 = 0**（含 `classList.*("名")` 与
 *   拼接构造检查），多数随批 1 删除「工程师统计卡」与更早的界面改版成为孤儿；
 *   组规则里与活选择器同行的，只摘掉孤儿那一条（如 `.wo-rpr-val.photo-field, .wo-sn-row .photo-rpr`
 *   只丢后者）；与规则相邻的历史注释**一律保留**（未经核实不删注释）。
 *   —— 需要时按 git 历史还原；本批只删 CSS，未动任何在用的样式（验收口径：全页视觉 Δ=0）。
 *   · 浮层/表单壳：wo-overlay · wo-panel · wo-panel h3 · wo-panel .x · wo-row-head · wo-idx
 *   · 备件选择弹窗：ps-chips · ps-meta · ps-row（含 > span / > b）· ps-title · pp-item · pp-info · sp-gallery
 *   · 老版备件行：part-row .qty-in（含 :focus）· part-row .del-btn（含 :hover）· qty-stepper
 *   · 上传控件（英文化前的旧版）：file-wrap（含内部 input 规则）· file-btn
 *   · 旧权限/授权矩阵：chk-row · auth-opts · auth-opt（含 input）· perm-lab · perm-locs · perm-tool-3（含后代）
 *   · 工程师统计卡残留（批 1 已删 JS）：seg（4 条）· chip（含 .on 与 group 成员）
 *   · 旧照片组件（app.js 已不再生成 photo-prev）：photo-prev（含 8 条 group 成员与 hover）· photo-rpr · photo-src
 *   · 其它：big-photo-note（含 2 处 group 成员）· btn-ghost · draft-banner（含 .btn）· ver-tag · wo-sn-unknown-wrap
 * ========================================================================== */

/* (67)（2026-10-10 批 C）：工单表单底部动作区 —— **只作用于 `.wo-actions`**（不动全站 `.btn` / `.form-actions` ✗）：
   动作区靠右 · 左右内边距 12 · 高度仍 44 · 390 宽不换行不溢出。 */
.form-actions.wo-actions { justify-content: flex-end !important; flex-direction: row !important; flex-wrap: nowrap !important; align-items: center !important; }
.form-actions.wo-actions .btn { flex: 0 0 auto !important; width: auto !important; min-width: 0 !important; padding: 9px 12px !important; min-height: 44px !important; }

/* =============================================================================
 * (53)（2026-10-11 批 H）：**工单字段标题**与**工单详情行键** → 深色 ＋ 加粗
 *   参照物＝"详情标题 `REP-…`"（`.modal h3`，见 480）：它没有自己的色/字重 ⇒ 继承 `body` 的
 *   `--c-text`（#1e293b）＋ h3 的 UA 默认粗体 ⇒ 计算值 **#1e293b / 700**。
 *   现状（改前）：字段标题被 `#page label, #page .field > label`（1732）压成 `--t-2`（#64748b）· 400；
 *               详情行键 `.detail-k`（500）是 `--c-muted`（同一个 #64748b）· 400。
 *   作用域（Lead 2026-10-11 已拍：**只做工单，不放开全站**）：`.wo-form`（工单表单）＋
 *   `.modal.modal-vitem`（工单详情弹窗；备件/采购/调拨/盘点四类详情弹窗与其它页面**一律不动**）。
 *   · 特异性 `#page .wo-form .field > label:not(.chk)` ＝ (1,3,1) ⇒ **稳压** 1732 的 (1,0,1)
 *     与 1731 `.ey-parts-label label` 的 (1,1,1)，不依赖书写先后。
 *   · `:not(.chk)`：`.wo-flags` 里两个勾选标签（from damaged board / not recorded）是**选项文字**、
 *     不是字段标题，不跟着变（本文件 838 早有 `.field label.chk` 单列一档的惯例）。
 *   · 必填红星不受影响：`.req { color: var(--c-danger) }`（1743）作用在**子 span 自身**。
 *   · 第 3 条给 (50) 用：详情里被标 `.row-error` 的行，键也变红（与 `.row-error > label` 1383 同口径）。
 * ========================================================================== */
#page .wo-form .field > label:not(.chk) { color: var(--t-1) !important; font-weight: 700 !important; }
.modal.modal-vitem .detail-k { color: var(--c-text) !important; font-weight: 700 !important; }
.modal.modal-vitem .detail-row.row-error .detail-k { color: var(--c-danger) !important; }

/* =============================================================================
 * V2.2 · 登录 / 恢复中动画（2026-11-01）：转圈 + 等待提示
 * ========================================================================== */
.login-spinner {
  width: 30px; height: 30px; margin: 6px auto 12px;
  border-radius: 50%;
  border: 3px solid rgba(124, 199, 255, .22);
  border-top-color: #7cc7ff;
  animation: loginSpin .9s linear infinite;
}
@keyframes loginSpin { to { transform: rotate(360deg); } }
.login-wait-hint {
  margin-top: 8px; font-size: 12.5px; line-height: 1.5; text-align: center;
  color: var(--t-3, #8b98a5);
}
