/* ============ 圣华运输磅单管理系统 · 设计系统 ============ */
:root {
  --primary: #f97316;
  --primary-dark: #ea580c;
  --primary-light: #fff7ed;
  --primary-darker: #c2410c;
  --primary-100: #ffedd5;
  --primary-200: #fed7aa;

  --bg: #f4f5f7;
  --surface: #ffffff;
  --surface-2: #f8fafc;
  --border: #e5e7eb;
  --border-2: #eef0f3;

  --text: #1f2937;
  --text-2: #6b7280;
  --text-3: #6b7280; /* R406:占位符/次要文字对比度 #9ca3af(2.55)→#6b7280(4.83),达 WCAG AA */

  --green: #16a34a;
  --green-bg: #dcfce7;
  --yellow: #d97706;
  --yellow-bg: #fef3c7;
  --red: #dc2626;
  --red-bg: #fee2e2;
  --blue: #2563eb;
  --btn-h: 44px; /* R407-C3:移动端主/次按钮统一高度令牌,替代 40/42/44 混用 */
  --blue-bg: #dbeafe;

  --radius: 12px;
  --radius-sm: 8px;
  --shadow: 0 1px 3px rgba(16,24,40,.06), 0 1px 2px rgba(16,24,40,.04);
  --shadow-md: 0 4px 16px rgba(16,24,40,.08);
  --shadow-lg: 0 12px 40px rgba(16,24,40,.16);
  --sidebar-w: 232px;

  /* 字体层级令牌（集中管理，消除 magic number） */
  --fs-micro: 11px; --fs-caption: 12px; --fs-sm: 13px; --fs-base: 14px;
  --fs-md: 16px; --fs-lg: 17px; --fs-xl: 20px;
  --fs-2xl: 22px; --fs-3xl: 24px; --fs-4xl: 27px;
  /* 语义强调色（此前未定义导致 var(--orange) 失效，已修复） */
  --orange: var(--primary);
  /* KPI 多色卡片强调色令牌（集中管理 dashboard 散落 hex，便于统一调整） */
  --purple: #7c3aed; --purple-bg: #f3e8ff;
  --cyan: #0891b2; --cyan-bg: #cffafe;
  --amber-deep: #854F0B;

  /* R431：移动端语义色令牌（收敛 mobile.js 散落 hex，值沿用原硬编码色，视觉零变化） */
  --on-primary: #ffffff;
  --purple-100: #ede9fe;
  --red-deep: #b91c1c;
  --red-100: #fecaca;
  --red-50: #fef2f2;
  --prio-high: #A32D2D;
  --prio-warn: #BA7517;
  --prio-normal: #185FA5;

  /* R441：移动端体验令牌（统一触控区/防缩放/破坏型语义色） */
  --tap-min: 44px;          /* 最小触控区高度 */
  --fs-input-m: 16px;       /* iOS 输入框防缩放字号 */
  --danger: var(--red);     /* 破坏型操作语义色 */

  /* ============ R532k：CSS 变量体检补定义 ============
     背景：全项目扫描 53 文件 / 103 个已定义变量 / 109 个被引用变量，
     查出 32 个未定义引用。其中 23 个属 vendor/vg-print 第三方（均带兜底，无害）；
     以下 6 个属我方代码，缺失时 CSS `var()` 无兜底 → 整条声明静默失效、回退浏览器默认值，
     不报错、不告警（与 js/utils.js 的 icon() 静默吐空串同类坑）。 */

  /* --text-1：全项目只定义了 --text/--text-2/--text-3，但 CSS+JS 共 9 处引用 --text-1：
     style.css 的 .gear-btn(仪表栏齿轮按钮)、.gear-menu button(齿轮菜单四项：仪表设置/
     通讯调试/置零/诊断)、.mp-chip(手机端筛选芯片)、.mp-backtop(手机端回顶)、
     .mpn-label / .mp-chips-label / .mpn-quota > span(消息中心)；
     pages-bill.js:1080、pages-core.js:4735 两处内联。缺失致文字色回退继承。
     设为 --text 别名而非独立色值，保证暗色模式/高对比模式自动跟随。 */
  --text-1: var(--text);
  /* --orange-bg：pages-settlement.js:709「应付合计」图标底色引用，缺失致 background 整条失效。 */
  --orange-bg: var(--primary-100);

  /* 以下 4 个此前靠调用点兜底值(var(--x,#hex))侥幸生效，集中补定义以消除隐患：
     若未来有人移除兜底值即变为静默失效，属定时炸弹。补定义后兜底值仍可保留作双保险。 */
  --line: var(--border);
  --bg-2: var(--surface-2);
  --primary-bg: var(--primary-light);
  --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;

  /* R532k：通讯调试终端面板配色（三模式各自覆盖，见 html.dark / body.hc 区块） */
  --term-bg: #0b1020;        /* 浅色模式下仍保留深底终端观感（对照度友好） */
  --term-fg: #7dd3fc;
  --term-border: #1e293b;
}

* { box-sizing: border-box; margin: 0; padding: 0; }
/* R1056：禁 iOS「双击页面放大」（老板 2026-10-17 报障）。
   manipulation = 允许滚动与双指捏合，只去掉【双击缩放】（并顺带消除 300ms 点击延迟）。
   与 index.html 的 viewport（maximum-scale=1.0 / user-scalable=no）成对：
     iOS 10+ 的 Safari 忽略 viewport 缩放限制，小程序 web-view 的 WKWebView 遵守；两道一起上才两头都管住。
   子元素自理：车牌键盘 / 悬浮铃铛 已单独设 touch-action:none（供按住拖动），本行不影响它们。
   双指捏合仍允许（未做 gesturestart 锁死那一档）。 */
html, body { height: 100%; touch-action: manipulation; }
body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", "Helvetica Neue", Arial, sans-serif;
  background: var(--bg);
  color: var(--text);
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}
button { font-family: inherit; cursor: pointer; border: none; background: none; }
input, select, textarea { font-family: inherit; font-size: 14px; }
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-thumb { background: #d1d5db; border-radius: 4px; }
::-webkit-scrollbar-track { background: transparent; }

/* ============ 登录页 ============ */
.login-wrap {
  min-height: 100vh; min-height: 100dvh; display: flex; align-items: center; justify-content: center;
  background: linear-gradient(135deg, #fb923c 0%, #f97316 45%, #ea580c 100%);
  padding: 24px;
}
.login-card {
  background: #fff; border-radius: 20px; box-shadow: var(--shadow-lg);
  width: 100%; max-width: 400px; padding: 40px 32px; animation: pop .35s ease;
}
/* ============ R532L：ICP 备案号悬挂（管局硬性要求）============
   管局原文：「悬挂 ICP 备案号并链接至工信部备案官网首页，否则将被管局责令更改」。
   四处：登录页 / PC 侧边栏(深底) / 手机端「我的」/ 扫码公开页 bill.html(独立样式)。
   规范要点：字号低于正文、颜色不可过于醒目但**必须清晰可读**（不能被判定为刻意隐藏），链接指向工信部。 */
.icp-foot { text-align: center; font-size: 11px; line-height: 1.6; margin-top: 16px; color: var(--text-3); }
/* R735：备案号由 1 个变 2 个后，PC 侧边栏那种窄容器（内容宽仅 208px）里两个号约 330px
   ⇒ 必然折行，且实测断在词中间（"兵公 / 网安备66080002000207号"）。加 nowrap 让**每个备案号
   整体不拆**，折行只发生在中间的「｜」处 ⇒ 两种宽度下都整齐（最长的那个号约 163px < 208px，不会溢出）。 */
.icp-foot a { color: inherit; text-decoration: none; white-space: nowrap; }
.icp-foot a:hover { color: var(--primary); text-decoration: underline; }
/* 深底变体：PC 侧边栏背景为固定深色 #1f2430（不随主题变），故此处色值不能用 --text-3，
   否则暗色模式下深字压深底会看不见。取 #94a3b8 对齐侧边栏既有次要文字色（对比度约 7:1）。 */
.icp-foot.icp-dark {
  margin: 0; padding: 12px 14px; border-top: 1px solid rgba(255,255,255,.06);
  color: #94a3b8; font-size: 11px;
}
.icp-foot.icp-dark a:hover { color: #fff; }
@keyframes pop { from { opacity: 0; transform: translateY(12px) scale(.98);} to {opacity:1;transform:none;} }
.login-logo { width: 60px; height: 60px; border-radius: 16px; background: linear-gradient(135deg,#fb923c,#ea580c);
  display: flex; align-items: center; justify-content: center; margin: 0 auto 16px; box-shadow: 0 8px 20px rgba(249,115,22,.35); }
.login-logo svg { width: 32px; height: 32px; }
.login-title { text-align: center; font-size: var(--fs-xl); font-weight: 700; }
.login-sub { text-align: center; color: var(--text-2); margin: 6px 0 26px; font-size: 13px; }
.field { margin-bottom: 16px; }
.field label { display: block; font-size: 13px; color: var(--text-2); margin-bottom: 6px; font-weight: 500; }
.input {
  width: 100%; height: 40px; border: 1.5px solid var(--border); border-radius: var(--radius-sm);
  padding: 0 14px; background: var(--surface-2); transition: .15s; outline: none;
}
.input:focus { border-color: var(--primary); background: #fff; box-shadow: 0 0 0 3px rgba(249,115,22,.12); }
.input.invalid, select.input.invalid { border-color: var(--red) !important; box-shadow: 0 0 0 2px rgba(220,38,29,.18); }
.field-err { color: var(--red); font-size: 12px; margin-top: 3px; line-height: 1.4; }
.input::placeholder { color: var(--text-3); }

/* R409-F2：登录页窄屏适配（手机端卡片收窄、输入框更高更易点） */
@media (max-width: 820px) {
  .login-wrap { padding: 16px; }
  .login-card { width: 92vw; max-width: 420px; padding: 26px 20px; }
  .login-card .input, .login-card .btn-primary { height: 48px; font-size: 16px; }
}
.input:disabled { background: var(--surface-2); color: var(--text-3); cursor: not-allowed; }
.mp-input:disabled { background: var(--surface-2); color: var(--text-3); cursor: not-allowed; }
textarea.input { height: auto; padding: 10px 14px; resize: vertical; min-height: 72px; }
select.input { cursor: pointer; }
.btn-primary {
  width: 100%; height: 40px; border-radius: var(--radius-sm); background: var(--primary); color: #fff;
  font-weight: 600; font-size: 15px; transition: .15s;
}
.btn-primary:hover { background: var(--primary-dark); }
.btn-primary:active { transform: translateY(1px); }
.login-tabs { display: flex; background: var(--surface-2); border-radius: var(--radius-sm); padding: 4px; margin-bottom: 22px; }
.login-tabs button { flex: 1; height: 36px; border-radius: 6px; color: var(--text-2); font-weight: 500; transition: .15s; }
.login-tabs button.active { background: #fff; color: var(--primary); box-shadow: var(--shadow); }
/* R511 · .test-accounts/.ta-* 样式已随"点击账号快速登录"功能一并移除 */

/* ============ App 布局 ============ */
.app { display: none; }
.app.active { display: block; }
.layout { display: flex; min-height: 100vh; min-height: 100dvh; }
.sidebar {
  width: var(--sidebar-w); background: #1f2430; color: #cbd5e1; flex-shrink: 0;
  display: flex; flex-direction: column; position: fixed; top: 0; bottom: 0; left: 0; z-index: 40;
}
.sb-brand { padding: 20px 18px; display: flex; align-items: center; gap: 10px; border-bottom: 1px solid rgba(255,255,255,.06); }
.sb-logo { width: 34px; height: 34px; border-radius: 9px; background: linear-gradient(135deg,#fb923c,#ea580c);
  display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.sb-logo svg { width: 19px; height: 19px; }
.sb-brand .t { font-size: 15px; font-weight: 700; color: #fff; line-height: 1.2; }
.sb-brand .s { font-size: 11px; color: #94a3b8; }
.sb-nav { flex: 1; overflow-y: auto; padding: 10px 10px 20px; }
.sb-group-title { font-size: 11px; color: #64748b; padding: 14px 10px 6px; letter-spacing: .5px; }
.nav-item { display: flex; align-items: center; gap: 11px; padding: 10px 12px; border-radius: 9px; color: #cbd5e1;
  font-size: 14px; cursor: pointer; transition: .12s; margin-bottom: 2px; position: relative; }
.nav-item:hover { background: rgba(255,255,255,.06); color: #fff; }
.nav-item.active { background: var(--primary); color: #fff; font-weight: 600; box-shadow: 0 4px 12px rgba(249,115,22,.35); }
.nav-item svg { width: 18px; height: 18px; flex-shrink: 0; }
.nav-badge { margin-left: auto; background: #ef4444; color: #fff; font-size: 11px; font-weight: 600; min-width: 20px; height: 20px;
  border-radius: 10px; display: inline-flex; align-items: center; justify-content: center; gap: 3px; padding: 0 6px;
  line-height: 1; flex-shrink: 0; /* R532j:补 line-height/flex-shrink/gap——原缺 line-height 致数字基线偏心,两位数时更明显 */ }
.nav-badge svg { width: 11px; height: 11px; } /* R532j:徽章内图标尺寸(此前无约束,会按替换元素默认渲染) */
.nav-item.active .nav-badge { background: #fff; color: var(--primary); }

.main { flex: 1; margin-left: var(--sidebar-w); display: flex; flex-direction: column; min-width: 0; }
.topbar { height: 60px; background: #fff; border-bottom: 1px solid var(--border); display: flex; align-items: center;
  padding: 0 24px; position: sticky; top: 0; z-index: 30; gap: 16px; }
.topbar .page-title { font-size: var(--fs-lg); font-weight: 700; }
.topbar .spacer { flex: 1; }
.topbar-btn { width: 38px; height: 38px; border-radius: 9px; display: flex; align-items: center; justify-content: center;
  color: var(--text-2); transition: .12s; position: relative; }
.topbar-btn:hover { background: var(--surface-2); color: var(--text); }
.topbar-btn svg { width: 20px; height: 20px; }
.user-chip { display: flex; align-items: center; gap: 10px; padding: 5px 10px 5px 5px; border-radius: 30px;
  border: 1px solid var(--border); transition: .12s; }
.user-chip:hover { background: var(--surface-2); }
.avatar { width: 32px; height: 32px; border-radius: 50%; background: linear-gradient(135deg,#fb923c,#ea580c);
  color: #fff; display: flex; align-items: center; justify-content: center; font-weight: 600; font-size: 13px; flex-shrink: 0; }
.user-chip .un { font-weight: 600; font-size: 13px; }
.user-chip .ur { font-size: 11px; color: var(--text-2); }
/* R532j:PC 顶栏「超级管理员」标签此前无样式——.role-tag 全项目只在 .mp-header(手机端)作用域有定义,
   导致 PC 端该 span 退化为裸行内文本,紧贴姓名造成视觉挤压重叠。此处限定 .user-chip 作用域补齐,
   不影响移动端既有 .mp-header .role-tag 两条规则。 */
.user-chip .role-tag { display: inline-block; margin-left: 5px; padding: 1px 7px; border-radius: 9px;
  font-size: 10px; font-weight: 600; line-height: 1.5; vertical-align: 1px; white-space: nowrap; }
.content { padding: 24px; flex: 1; animation: fade .2s ease; }

/* ============ 通用组件 ============ */
.card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow); }
.card-pad { padding: var(--sp-5); }
.section-bar { display: flex; align-items: center; margin-bottom: 18px; gap: 12px; flex-wrap: wrap; }
.section-bar h2 { font-size: var(--fs-md); font-weight: 700; }
.section-bar .spacer { flex: 1; }

/* ============ 看板分段导航 + 可折叠区块（R191 #341） ============ */
html { scroll-behavior: smooth; }
.dash-nav { position: sticky; top: 0; z-index: 30; display: flex; gap: 6px; flex-wrap: wrap;
  align-items: center; padding: 10px 0; margin-bottom: 14px; background: var(--bg);
  border-bottom: 1px solid var(--border); }
.dash-nav a { font-size: 13px; color: var(--text-2); text-decoration: none; padding: 6px 12px;
  border-radius: 999px; border: 1px solid var(--border); background: var(--surface); transition: .15s; white-space: nowrap; }
.dash-nav a:hover { color: var(--primary); border-color: var(--primary-200); }
.dash-nav a.active { color: #fff; background: var(--primary); border-color: var(--primary); }
details.card-pad > summary { display: flex; align-items: center; cursor: pointer; list-style: none; }
details.card-pad > summary::-webkit-details-marker { display: none; }
details.card-pad > summary .section-bar { flex: 1; margin-bottom: 0; }
details.card-pad > summary::after { content: '▾'; margin-left: 8px; color: var(--text-2); font-size: 12px; }
details.card-pad:not([open]) > summary::after { content: '▸'; }

/* R206 方案1：看板次级数据区块默认收起，单一开关控制（不影响 echarts 图表渲染） */
.dash-root.dash-collapsed .dash-secondary { display: none; }
.dash-root.dash-collapsed #dashToggleBtn { box-shadow: 0 0 0 2px var(--primary-200); }

/* R893 · 按钮内容「真正居中」—— 修两个独立缺陷：
   ① align-items 只管交叉轴，缺 justify-content 时主轴默认 flex-start（靠左）⇒ 一旦按钮被 min-width 撑宽
      （.modal-foot 88px / .modal:has(.fm) 112px / .modal--drawer 112px），文字就贴左（实测「关闭」偏 42px）。
   ② flex-direction: row 用于切断【页面布局类 .main】对 class="btn main" 的污染 —— .main（第 199 行）带
      flex-direction: column，命中按钮后会让内容竖排（图标与文字上下分家、纯文字按钮贴顶，实测差 20px）。
   .main 与 .btn 特异性相同、靠源码顺序决胜；.btn 在后 ⇒ 本条稳定生效。 */
.btn { height: 40px; padding: 0 16px; border-radius: var(--radius-sm); font-weight: 600; font-size: 14px;
  display: inline-flex; align-items: center; justify-content: center; flex-direction: row; gap: 6px; transition: .12s; white-space: nowrap; }
.btn svg { width: 16px; height: 16px; }
.btn:active { transform: translateY(1px); }
.btn:disabled, .btn.is-disabled { opacity: .55; cursor: not-allowed; pointer-events: none; box-shadow: none; }
/* R963 · 按钮可读性与主次层级（老板 2026-10-07 采纳方案 1 + 进一步优化）
   动因：主按钮原为 #f97316 底 + 白字 = 对比度 2.80:1，连 WCAG 大字档(3:1)都没到，
         户外强光下糊成一片；且「批量提取」与「创建订单」同为橙实底 ⇒ 主次不分。
   处置：① 主按钮底色改用 --primary-dark(#ea580c，3.56:1)，悬停/按下用 --primary-darker(#c2410c，5.18:1)
         ② 非小型主按钮放大到 15px/700（走大字档，3.56:1 站得更稳）
         ③ 补齐四态（.btn 基础已含 active 下沉与 disabled 透明度，这里补主按钮专属的禁用灰）
         ④ 次按钮 .btn-soft 字色加深到 #9a3412（6.88:1），用【内描边】而非外边框 ⇒ 不影响布局且一眼看出能点
   注：.btn-sm 的 12px 在样式表后面，会覆盖 ② ⇒ 小按钮尺寸不受影响。 */
.btn-o { background: var(--primary-dark); color: #fff; }
.btn-o:hover { background: var(--primary-darker); }
.btn-o:not(.btn-sm) { font-size: 15px; font-weight: 700; }
.btn-o:disabled, .btn-o.is-disabled { background: #e2e8f0; color: #94a3b8; }
.btn-ghost { background: #fff; color: var(--text); border: 1px solid var(--border); }
.btn-ghost:hover { background: var(--surface-2); border-color: var(--text-3); }
.btn-soft { background: var(--primary-light); color: #9a3412; box-shadow: inset 0 0 0 1px var(--primary-200); }
.btn-soft:hover { background: var(--primary-100); color: var(--primary-darker); }
.btn-danger { background: var(--red-bg); color: var(--red); }
.btn-danger:hover { background: #fecaca; }
/* R438:破坏型确认弹窗权重反转——操作按钮白底红字(低权重但明确危险),取消按钮(由 confirmBox 注入 btn-o)转橙色主按钮高亮 */
.btn-danger-text { background: #fff; color: var(--red); border: 1px solid var(--red); }
.btn-danger-text:hover { background: var(--red-bg); }

/* R701 · 破坏型确认的「动作单」形态（老板 2026-09-19 16:32 选定方案 B）。
   危险项红字独立一行在上、取消灰底独立一块在下 —— 主次分明（旧 R438 是反的：
   取消穿品牌橙，看着像"推荐点它"）。只作用于 `danger=true` 的确认框，非危险路径一字未改。
   用 var(--surface) 而非 #fff，高对比模式下自动跟随。 */
/* ===== R887 · 确认框「三态分流」（甲案，取代 R701 的竖排动作单）=====
   危险＝红实心按钮 + 红色三角图标；确认＝品牌橙主按钮 + 橙色圆图标；提示＝单按钮「知道了」+ 蓝色圆图标。
   三态共用 confirmBox / alertBox 一个实现 ⇒ 全站 50+ 调用点一起变，不会出现两套确认框。 */
.modal--confirm .modal-foot { flex-direction: row; gap: 10px; }
.modal--confirm .modal-foot .btn { flex: 1 1 0; min-width: 0; height: 44px; border-radius: 9px;
  font-size: 14.5px; font-weight: 500; justify-content: center; margin: 0; }
.modal--confirm .cb-cancel { background: var(--surface); color: var(--text); border: 1px solid var(--border); }
.modal--confirm .cb-cancel:hover { background: var(--surface-2); border-color: var(--text-3); }
.modal--confirm .cb-ok { background: var(--primary); color: #fff; border: 1px solid var(--primary); }
.modal--confirm .cb-ok:hover { background: var(--primary-dark); border-color: var(--primary-dark); }
.modal--confirm .cb-danger { background: #DC2626; color: #fff; border: 1px solid #DC2626; }
.modal--confirm .cb-danger:hover { background: #B91C1C; border-color: #B91C1C; }
/* 标题左侧真 SVG 图标（data URI 画在伪元素上，无需改 openOverlay 的页头结构） */
.modal--confirm .modal-head h3::before { content: ''; display: inline-block; width: 18px; height: 18px;
  margin-right: 7px; vertical-align: -3px; background-repeat: no-repeat; background-position: center; background-size: contain; }
.modal--confirm .modal-head h3::before { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23F97316' stroke-width='1.9' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M9.6 9.3a2.5 2.5 0 1 1 3.4 2.3c-.7.3-1 .9-1 1.6v.3'/%3E%3Cpath d='M12 16.6h.01'/%3E%3C/svg%3E"); }
.modal--danger .modal-head h3::before { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23DC2626' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0Z'/%3E%3Cpath d='M12 9.5v3.5'/%3E%3Cpath d='M12 16.8h.01'/%3E%3C/svg%3E"); }
.modal--alert .modal-head h3::before { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23378ADD' stroke-width='1.9' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M12 11v5'/%3E%3Cpath d='M12 7.6h.01'/%3E%3C/svg%3E"); }
/* 提示型：只有一个「知道了」，用中性样式（不抢眼），全宽 */
.modal--alert .modal-foot .btn { background: var(--surface); color: var(--text); border: 1px solid var(--border); }
.modal--alert .modal-foot .btn:hover { background: var(--surface-2); border-color: var(--text-3); }
/* 手机端：两按钮仍横排各占一半（比竖排更好点，且危险项在右） */
@media (max-width: 480px) {
  .modal--confirm .modal-foot { flex-direction: row; }
  .modal--confirm .modal-foot .btn { width: auto; flex: 1 1 0; }
}
/* R438:确认弹窗紧凑化——覆盖 .modal-body 全局 80px 底部留白(那是给带 sticky footer 的大表单留的) */
.modal--confirm .modal-body { padding: 18px 22px 6px; }

/* R439:底部 sheet 选择器(替代移动端原生 select,对齐微信/支付宝列表选择范式) */
.picker-field {
  width: 100%; min-height: 40px; border: 1.5px solid var(--border); border-radius: var(--radius-sm);
  padding: 0 36px 0 14px; background: var(--surface-2); display: flex; align-items: center;
  color: var(--text-2); font-size: 14px; cursor: pointer; position: relative; box-sizing: border-box;
}
.picker-field:after { content: '▾'; position: absolute; right: 14px; color: var(--text-3); font-size: 13px; }
.picker-field.has-value { color: var(--text); }
/* R903 · 归属锁定只读：由订单带出的合同/订单不可改（老板 2026-10-04 拍板）。
   两个信号一起给：右侧 ▾ 换成锁 + 底色转深一档（--border-2 = #eef0f3，比默认 --surface-2 深一点）。
   放在 .has-value 之后，靠源码顺序覆盖它的 color（两者特异性相同，顺序在后即生效）。 */
.picker-field.locked { cursor: not-allowed; color: var(--text-2); background: var(--border-2); }
.picker-field.locked:after { content: '🔒'; font-size: 12px; color: var(--text-2); }
.modal--sheet { top: auto; bottom: 0; left: 0; right: 0; transform: none; width: 100%; max-height: 72vh; border-radius: 16px 16px 0 0; margin: 0; padding-bottom: env(safe-area-inset-bottom); }
.modal--sheet .modal-body { padding: 8px 0 0; max-height: calc(72vh - 56px); }
.picker-search { padding: 4px 16px 10px; }
.picker-search .input { height: 40px; }
.picker-list { max-height: calc(72vh - 132px); overflow-y: auto; overscroll-behavior: contain; }
.picker-row { padding: 14px 18px; font-size: 15px; color: var(--text); display: flex; align-items: center; justify-content: space-between; border-bottom: 1px solid var(--border); }
.picker-row:active { background: var(--surface-2); }
.picker-row.sel { color: var(--primary); font-weight: 500; }
.picker-check { color: var(--primary); font-size: 18px; line-height: 1; }
.picker-empty { padding: 24px 18px; text-align: center; color: var(--text-3); font-size: 14px; }
.picker-cancel { width: calc(100% - 32px); margin: 12px 16px 16px; height: 46px; }
/* R488:PC 锚定下拉面板(方案C+,对齐 AntD Select)——仅 >680px 由 JS 启用;手机端底部 sheet 不变 */
.pc-picker { position: fixed; z-index: 300; background: var(--surface, #fff); border: 1px solid var(--border); border-radius: 10px; box-shadow: 0 8px 24px rgba(17,24,39,.14); overflow: hidden; animation: pcPickerIn .12s ease; }
@keyframes pcPickerIn { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
.pc-picker .picker-search { padding: 6px; border-bottom: 1px solid var(--border); }
.pc-picker .picker-list { max-height: 256px; overflow-y: auto; overscroll-behavior: contain; }
.pc-picker .picker-row-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pc-picker .picker-row:hover, .pc-picker .picker-row.hov { background: var(--surface-2); }
.pc-kbd-hint { padding: 5px 12px; font-size: 11px; color: var(--text-3); border-top: 1px solid var(--border); background: var(--surface-2); }
.modal--pcpick { top: 12vh; bottom: auto; border-radius: 12px; }
.modal--pcpick .modal-body { max-height: calc(60vh - 56px); }
/* R496:C审核抽屉——右侧滑出面板,聚焦单订单审核(v6.1 表格+抽屉布局) */
.modal--drawer { top: 0; right: 0; bottom: 0; left: auto; transform: none; width: min(760px, 94vw); height: 100%; max-height: none; border-radius: 0; animation: drawerIn .22s ease; }
.modal--drawer .modal-body { max-height: calc(100vh - 124px); }
@keyframes drawerIn { from { transform: translateX(48px); opacity: .3; } to { transform: none; opacity: 1; } }
.picker-field.picker-open { border-color: var(--primary); box-shadow: 0 0 0 3px rgba(255,136,0,.13); }
.confirm-msg { font-size: 14px; line-height: 1.5; color: var(--text); margin: 0; white-space: pre-line; }
.btn-sm { height: 28px; padding: 0 11px; font-size: 12px; border-radius: 7px; }
.btn-green { background: var(--green); color:#fff; }
.btn-green:hover { filter: brightness(.95); }
.btn-warn { background: var(--yellow-bg); color: var(--yellow); }
.btn-warn:hover { background: #fde68a; }

/* R54 操作列下拉菜单 */
.action-menu { min-width: 156px; background: var(--surface); border: 1px solid var(--border); border-radius: 12px; box-shadow: 0 12px 32px rgba(0,0,0,.18); padding: 6px; text-align: left; }
.action-menu.float { position: fixed; z-index: 9999; display: none; }
.action-menu.float.open { display: block; }
.am-item { display: flex; align-items: center; gap: 8px; width: 100%; text-align: left; background: transparent; border: none; padding: 9px 11px; border-radius: 8px; font-size: 13px; font-weight: 500; color: var(--text); cursor: pointer; white-space: nowrap; }
.am-item:hover { background: var(--surface-2); }
.am-item.danger { color: var(--red); }
.am-item.danger:hover { background: var(--red-bg); }
.am-item.primary { color: var(--primary); }
.am-item.primary:hover { background: var(--primary-100); }
.am-item svg { width: 16px; height: 16px; flex: none; }
.kebab { font-size: 18px; line-height: 1; padding: 0 11px; font-weight: 700; }

/* R58 往来账明细列选择器 */
.ledger-coltoggle { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 14px; padding: 8px 12px; margin-bottom: 12px; background: var(--surface-2); border: 1px solid var(--border); border-radius: 10px; font-size: 13px; color: var(--text-2); }
.ledger-colopt { display: inline-flex; align-items: center; gap: 5px; cursor: pointer; user-select: none; }
.ledger-colopt input { accent-color: var(--primary); }

/* R54 客户明细：上方统计卡即下钻 Tab */
.cd-stat { transition: .12s; border: 1px solid var(--border); }
.cd-stat:hover { border-color: var(--primary); }
.cd-stat.active { border-color: var(--primary); box-shadow: 0 0 0 2px var(--primary-light); }

/* 统一焦点可见性(键盘可达性 / 跨组件一致) */
.btn:focus-visible, .input:focus-visible, .nav-item:focus-visible, .topbar-btn:focus-visible,
.login-tabs button:focus-visible, .tabs button:focus-visible {
  outline: 2px solid var(--primary); outline-offset: 2px;
}
img, video, embed { max-width: 100%; }

.stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 16px; margin-bottom: 22px; }
.stat-grid-3 { grid-template-columns: repeat(3, 1fr); }
@media (max-width: 1100px) { .stat-grid-3 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 680px) { .stat-grid-3 { grid-template-columns: 1fr; } .form-grid { grid-template-columns: 1fr; } .form-grid.cols3 { grid-template-columns: 1fr; } }

/* 近30天趋势条形图 */
.trend-bars { display: flex; align-items: flex-end; gap: 4px; height: 160px; padding-top: 8px; overflow-x: auto; }
.trend-bars .tcol { flex: 1; min-width: 14px; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; height: 100%; }
.trend-bars .tbar { width: 70%; max-width: 22px; background: linear-gradient(180deg,#fb923c,#f97316); border-radius: 4px 4px 0 0; transition: height .5s ease; min-height: 2px; }
.trend-bars .tlbl { font-size: 10px; color: var(--text-2); margin-top: 4px; transform: rotate(0deg); white-space: nowrap; }
.stat { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 18px 20px; box-shadow: var(--shadow);
  position: relative; overflow: hidden; }
.stat .ic { width: 42px; height: 42px; border-radius: 11px; display: flex; align-items: center; justify-content: center; margin-bottom: 12px; }
.stat .ic svg { width: 22px; height: 22px; }
.stat .v { font-size: var(--fs-4xl); font-weight: 800; letter-spacing: -.5px; }
.stat .l { color: var(--text-2); font-size: 13px; margin-top: 2px; }
.stat .trend { font-size: 12px; margin-top: 8px; display: inline-flex; align-items: center; gap: 3px; }

table.tbl { width: 100%; border-collapse: collapse; }
.tbl th { text-align: left; font-size: 12px; color: var(--text-2); font-weight: 600; padding: 12px 14px;
  background: var(--surface-2); border-bottom: 1px solid var(--border); white-space: nowrap; }
.tbl td { padding: 13px 14px; border-bottom: 1px solid var(--border-2); font-size: 13px; vertical-align: middle; overflow-wrap: break-word; }
.tbl td.text-right { white-space: nowrap; }
/* R843 · 表格全表居中（老板 2026-10-01 拍板）—— 表头与内容都在各自单元格内水平居中。
   病因：`.tbl th{text-align:left}`（权重 0,1,1）压过 `.text-right`（0,1,0）⇒ 数字列"表头靠左、内容靠右"，
   同一列上下错开一整列（结算净重 / 货款 / 运费 / 合计 / 操作 都中招，全站 9 个页面）。
   本组选择器权重 ≥ 0,2,1，明确覆盖两者，把 text-right / text-center 一并归一为居中。 */
.tbl th, .tbl td,
.tbl th.text-right, .tbl td.text-right,
.tbl th.text-center, .tbl td.text-center { text-align: center; }
/* R843 · 紧凑表（预约单 / 厂内提货 / 采购收货）—— 表头与单元格改用同一套内边距。
   病因：这三个表的 td 被内联成 `padding:8px 6px`，而 th 仍走全局 `12px 14px`
   ⇒ 每列表头比内容多缩进 8px，整表轻微错位（"车牌偏右 / 供货单位偏左"的来源）。 */
.tbl.tbl-compact th, .tbl.tbl-compact td { padding: 8px 6px; }
/* R562：表格内操作列多按钮——拉开 8px 间距，防两个同色按钮紧贴糊成一团（订单详情"打印磅单/补回单照片"压字根因） */
.row-actions-inline { display: inline-flex; align-items: center; gap: 8px; flex-wrap: nowrap; justify-content: flex-end; }
.tbl tbody tr { transition: background .12s ease; }
.tbl tbody tr:hover { background: var(--primary-light); }
.tbl tr:last-child td { border-bottom: none; }
.table-wrap { overflow-x: auto; }
/* R936 · 发货单列表「货物」列：一车多货时【格内逐行列出每一种】，不新增表格行。
   字号 11px（比 .text-sm 的 12px 再小 1px）、行距锁 18px ⇒ 2~3 行也能紧凑排在同一格内。
   仅作用于本列（.dlv-goods-cell），不动任何其它列 / 其它表格。
   ★ 单行（1 种货）时后端不加 .dlv-goods-line，观感与改前完全一致（逐字节退化）。 */
.tbl td.dlv-goods-cell { line-height: 1.4; }
.tbl td.dlv-goods-cell .dlv-goods-line { font-size: 11px; line-height: 18px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* R937 · 逐项多行里的两种特殊行（沿用 R936 的 .dlv-goods-line 骨架）：
   · .dlv-sum-line —— 末行「共 X 托 / 共 Y 块」合计，用上边框与逐项行分开，并稍暗以区别明细
   · .dlv-line-empty —— 某一项该字段为空时的占位「—」（保持行数对齐，不让人误以为漏了一行） */
.tbl td.dlv-goods-cell .dlv-goods-line.dlv-sum-line { border-top: 1px dashed var(--border-2); margin-top: 2px; padding-top: 2px; color: var(--text-2); font-weight: 600; }
.tbl td.dlv-goods-cell .dlv-goods-line .dlv-line-empty { color: var(--text-2); }
.mono { font-variant-numeric: tabular-nums; }
/* A11y/排版：卡片内吨数·金额等数字等宽对齐，避免数字抖动（P2-1） */
.mp-order, .mp-card, .mp-drill, .mp-menu-item { font-variant-numeric: tabular-nums; }
.strong { font-weight: 600; }
/* R215 · 操作日志「对象」列可读化样式 */
.audit-tbl { display: inline-block; font-size: 10px; line-height: 1; padding: 2px 6px; border-radius: 4px; background: #eef2f7; color: #64748b; margin-right: 6px; font-family: var(--mono, monospace); vertical-align: middle; }
.audit-obj { color: var(--text, #1f2937); font-weight: 500; }
.audit-raw { color: #94a3b8; font-size: 11px; }

.badge { display: inline-flex; align-items: center; gap: 4px; padding: 3px 9px; border-radius: 20px; font-size: 12px; font-weight: 600; white-space: nowrap; }
.badge .dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
/* R407-C2:状态徽章文字色加深,对比度达 WCAG AA(4.5);原 #16a34a/#d97706/#dc2626 仅 3.0~4.0 户外/强光下偏淡 */
.b-green { background: var(--green-bg); color: #0f7a35; }
.b-yellow { background: var(--yellow-bg); color: #b45309; }
.b-red { background: var(--red-bg); color: #b3160f; }
.b-blue { background: var(--blue-bg); color: #1d4ed8; }
.b-gray { background: #f1f5f9; color: #475569; }
.b-orange { background: var(--primary-100); color: var(--primary-dark); }
.b-purple { background: #f3e8ff; color: #6d28d9; }

.tabs { display: inline-flex; background: var(--surface-2); border: 1px solid var(--border); border-radius: 10px; padding: 4px; gap: 2px; }
.tabs button { padding: 7px 15px; border-radius: 7px; font-size: 13px; color: var(--text-2); font-weight: 500; transition: .12s; }
.tabs button.active { background: #fff; color: var(--primary); box-shadow: var(--shadow); font-weight: 600; }
/* R908 · 「待审核」时业务线整排锁住（该状态是跨业务线汇总，不读业务线选择集）——灰显 + 不可点 + 说明。
   行业依据：筛选维度互不兼容时应「保留控件 + 禁用 + 说明原因」，而不是让它点了没反应（或偷偷改勾选）。 */
.tabs.is-locked button { opacity: .45; cursor: not-allowed; }
.tabs.is-locked button.active { opacity: .55; }
.tabs-lock-note { font-size: 12px; color: var(--text-3); margin-left: 6px; white-space: nowrap; }
.mp-chips.is-locked .mp-chip { opacity: .45; }
.mp-chips.is-locked .mp-chip.active { opacity: .55; }
/* R441:记账主体切换器——比模式页签更紧凑,与模式页签视觉区分 */
.entity-tabs { margin-left: 0; }
.entity-tabs button { padding: 5px 11px; font-size: 12.5px; }

.search-box { position: relative; }
.search-box svg { position: absolute; left: 11px; top: 50%; transform: translateY(-50%); width: 16px; height: 16px; color: var(--text-3); }
.search-box input { height: 38px; padding: 0 12px 0 34px; border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: #fff; width: 240px; max-width: 100%; outline: none; transition: .12s; }
.search-box input:focus { border-color: var(--primary); box-shadow: 0 0 0 3px rgba(249,115,22,.1); }

.empty { text-align: center; padding: 60px 20px; color: var(--text-2); font-weight: 600; }
.empty svg { width: 56px; height: 56px; margin-bottom: 14px; opacity: .5; }
.empty p { font-size: 14px; }

/* R188-G: 数据透视懒加载骨架屏(shimmer),仅在 WebDataRocks 异步就绪前展示 */
.sk-pivot { height: 100%; min-height: 540px; display: flex; flex-direction: column; gap: 10px; padding: 14px; box-sizing: border-box; }
.sk { background: linear-gradient(90deg, #eef1f5 25%, #f6f8fa 37%, #eef1f5 63%); background-size: 400% 100%; animation: sk-shimmer 1.3s ease-in-out infinite; border-radius: 6px; }
.sk-toolbar { height: 38px; flex: 0 0 auto; }
.sk-row { height: 46px; flex: 1 1 0; }
.sk-tip { height: auto; flex: 0 0 auto; background: none; animation: none; color: var(--text-3); font-size: 13px; text-align: center; padding: 4px 0; }
@keyframes sk-shimmer { 0% { background-position: 100% 0; } 100% { background-position: 0 0; } }
@media (prefers-reduced-motion: reduce) { .sk { animation: none; } }

.progress { height: 7px; background: var(--border); border-radius: 4px; overflow: hidden; }
.progress .bar { height: 100%; background: linear-gradient(90deg,#fb923c,#f97316); border-radius: 4px; transition: width .4s; }

/* ============ 弹窗 ============ */
.modal-mask { position: fixed; inset: 0; background: rgba(17,24,39,.5); backdrop-filter: blur(2px); z-index: 100;
  display: flex; align-items: center; justify-content: center; padding: 20px; animation: fade .18s; }
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }
.modal { background: #fff; border-radius: 16px; width: min(520px, calc(100vw - 40px)); position: fixed; top: 5vh; left: 50%; transform: translateX(-50%); max-height: 90vh; overflow: hidden; /* R362:完全重建——fixed 相对视口 + translateX 水平居中 + max-height/overflow 兜底，不依赖 flex/grid/absolute，footer 用 block 文档流自然贴底 */
  box-shadow: var(--shadow-lg); animation: pop .22s ease; }
.modal.wide { width: min(720px, calc(100vw - 40px)); }
/* R972 · 大面板档（预约单 / 厂内提货）—— 自动适应的第一级：把弹窗本身放宽。
   520px 时「每行 4 个」每格只剩 110px、长公司名被压成竖排；放宽后由算法决定列数与跨度。 */
.modal.modal--xl { width: min(1400px, 94vw); }
.modal.modal--drawer { top: 0; right: 0; bottom: 0; left: auto; transform: none; border-radius: 0; height: 100%; max-height: none; width: min(760px, 94vw); animation: drawerIn .22s ease; } /* R504:双类特异性锁死抽屉定位(防 .modal 基础规则源序在后覆盖)。R847:补 width——R504 只锁了定位漏了宽度，导致 .modal 的 520px 压过 .modal--drawer 的 760px（预约单明细/厂内提货明细实测 520px）。宽档 .modal--drawer.wide 源序在本行之后，仍照常覆盖 */
/* R504:弹窗/抽屉三层框架——抽屉管查看、弹窗管填写确认；档位 S420/M520默认/L720/XL920 */
.modal--s { width: min(420px, calc(100vw - 40px)); }
.modal--l { width: min(720px, calc(100vw - 40px)); }
.modal--xl { width: min(920px, calc(100vw - 40px)); }
/* R819e:表单弹窗新增两档（老板 2026-09-29 拍板）——原「>=9 才 720、其余 520」只有两档，
   5 字段的厂内提货被塞 520 窄框。新增 N480（字段 1~4 单列窄）/ M600（字段 5~8 两列中），
   并把 L 档表单态放宽到 800（表单类后缀 .modal--form，避免影响纯展示的 720 弹窗）。
   统一 max-width 兜底：窄屏时自动贴边，不再溢出。 */
.modal--n { width: min(480px, calc(100vw - 32px)); }
.modal--m { width: min(600px, calc(100vw - 32px)); }
.modal--l.modal--form { width: min(800px, calc(100vw - 32px)); }
.modal--drawer.wide { width: min(92vw, clamp(1080px, 78vw, 1600px)); } /* R845:固定 1080 档 → 视口自适应。下限 1080(保笔记本不缩)、中段 78vw、上限 1600(再宽遮罩点不到且扫读过长)、92vw 兜底防溢出。订单详情 16 列宽表在 2560 屏不再横滚 */
/* ===== R902 · 采购收货「多车会话」抽屉（主从两栏 + 车队卡 + 磅单照片缩略图）=====
   共享视觉类一律用新名（rc-sess- / rc-car / rc-photo），绝不改既有规则本体。 */
.modal--drawer-rc { width: min(1040px, 94vw); }   /* 比通用抽屉宽，容得下两栏；最小宽由 data-min-w=860 控制 */
.modal--drawer-rc .modal-body { padding: 0; }      /* 两栏各自管内边距 */
.rc-sess { display: flex; align-items: stretch; min-height: 360px; }
.rc-sess-l { flex: 0 0 300px; border-right: 1px solid var(--border, #e3e8ef); background: var(--surface-2, #f3f5f8); padding: 12px; display: flex; flex-direction: column; gap: 8px; }
.rc-sess-r { flex: 1; min-width: 0; display: flex; }
/* .fm 默认靠 margin:-22px 铺满 .modal-body 边缘；这里容器换了（.rc-sess-r）⇒ 必须显式归零并吃下内边距，
   否则灰底会溢出两栏、盖住左栏车队（仅作用于本抽屉内的 .fm，其它弹窗一字不动）。 */
.rc-sess-r .fm { flex: 1; margin: 0; padding: 16px 18px 80px; border-radius: 0; }
.rc-sess-cnt { font-size: 12px; color: var(--text-2, #6b7280); background: var(--surface, #fff); border: 1px solid var(--border, #e3e8ef); border-radius: 14px; padding: 3px 10px; align-self: flex-start; }
.rc-sess-cnt b { color: var(--primary, #f97316); }
.rc-sess-list { overflow-y: auto; max-height: 46vh; display: flex; flex-direction: column; gap: 8px; }
.rc-car { border: 1px solid var(--border, #e3e8ef); border-radius: 9px; background: var(--surface, #fff); padding: 6px 10px 7px; cursor: pointer; }
/* R1106 · 选中态改用「换色 + 外圈阴影」，**边框宽度始终 1px**。
   原来 border 1px→2px 会让卡片宽 2px、文字被推右 1px（老板 2026-10-21 实测：
   看着像外面又套了一圈框、第二行字偏右）。box-shadow 不占布局，视觉高亮更强且零位移。 */
.rc-car.sel { border-color: var(--primary, #f97316); background: var(--primary-100, #fff7ed); box-shadow: 0 0 0 1.5px var(--primary, #f97316); }
/* R904 · 两行紧凑式（老板 2026-10-04 拍板）：第一行 车牌 + 状态 + 右上角入场时间 + 低调小 ×；第二行 毛·皮·净。
   实测单卡 97px → 59px（−39%）；原「标记离场」大按钮独占一行已退役。 */
.rc-car .p { display: flex; align-items: center; gap: 6px; }
.rc-car .p .plate { font-size: 13.5px; font-weight: 700; letter-spacing: .2px; }
.rc-car .p .t { margin-left: auto; font-style: normal; font-size: 11px; color: var(--text-3, #9ca3af); }
.rc-car .p .rm { flex: none; width: 18px; height: 18px; margin-left: 4px; border-radius: 5px;
  display: flex; align-items: center; justify-content: center; font-size: 13px; line-height: 1; color: #cbd5e1; cursor: pointer; }
.rc-car .p .rm:hover { background: #fee2e2; color: #ef4444; }
.rc-car .m { font-size: 11px; color: var(--text-2, #6b7280); margin-top: 2px; line-height: 1.6; }
/* R904 · 原 .rc-car .a（「标记离场」按钮行）随该按钮一并退役 —— 出口改为右上角 .p .rm 的 18x18 小 ×。 */
.rc-sess-empty { font-size: 12px; color: var(--text-3, #9ca3af); padding: 10px 2px; line-height: 1.7; }
.rc-sess-add { border: 1px dashed var(--border, #cbd5e1); border-radius: 9px; padding: 8px; text-align: center; font-size: 12px; color: var(--text-2, #475569); background: var(--surface, #fff); cursor: pointer; }
.rc-sess-add:hover { border-color: var(--primary, #f97316); color: var(--primary, #f97316); }
/* 磅单照片：三态【等高 96px】 ⇒ 未上传 / 已上传 / 已清除，弹窗高度全程不变 */
.rc-photo { position: relative; width: 100%; height: 96px; border: 2px dashed var(--border, #cbd5e1); border-radius: 10px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; color: var(--text-3, #94a3b8); background: var(--surface-2, #f8fafc); cursor: pointer; overflow: hidden; }
.rc-photo:hover { border-color: var(--primary, #f97316); color: var(--primary, #f97316); }
.rc-photo img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
.rc-photo.has { border-style: solid; border-width: 1px; }
.rc-photo.dis { border-style: solid; background: var(--surface-3, #f1f3f5); color: var(--text-3, #9ca3af); cursor: not-allowed; }
.rc-photo-x { position: absolute; right: 6px; top: 6px; width: 20px; height: 20px; border-radius: 50%; background: rgba(15,23,42,.62); color: #fff; font-size: 12px; line-height: 20px; text-align: center; z-index: 2; }
.rc-photo-tag { position: absolute; left: 6px; top: 6px; font-size: 10px; background: #15803d; color: #fff; border-radius: 5px; padding: 1px 6px; z-index: 2; }
.rc-photo-zoom { position: absolute; left: 6px; bottom: 6px; font-size: 10px; background: rgba(15,23,42,.62); color: #fff; border-radius: 5px; padding: 1px 6px; z-index: 2; }
.rc-photo-hint { font-size: 10px; color: var(--text-3, #9ca3af); margin-top: 4px; }
@media (max-width: 820px) {
  .modal--drawer-rc { width: 100%; }
  .rc-sess { flex-direction: column; min-height: 0; }
  .rc-sess-l { flex: 0 0 auto; border-right: 0; border-bottom: 1px solid var(--border, #e3e8ef); max-height: 32vh; }
  .rc-sess-list { max-height: 24vh; }
  .rc-sess-r .fm { padding: 12px 14px 92px; }
  .rc-photo { height: 84px; }
}
.modal--drawer .modal-body table { width: auto; min-width: 100%; } /* R505:表格按内容自然伸展不压缩(修 width:100% 强制挤压致单元格换行);窄内容铺满抽屉 */
.modal--drawer .modal-body th, .modal--drawer .modal-body td { white-space: nowrap; } /* R505:明细列不折行,真正超宽由 .table-wrap 横向滚动 */
.modal-head { padding: 18px 22px; border-bottom: 1px solid var(--border); display: flex; align-items: center; }
.modal-head h3 { font-size: var(--fs-md); font-weight: 700; }
.modal-head .mh-back { flex: none; margin-right: 12px; padding: 6px 13px 6px 9px; border: 1px solid #b5d4f4; background: #e8f1fb; border-radius: 8px; font-size: 13px; font-weight: 600; line-height: 1.2; color: #0c447c; font-family: inherit; cursor: pointer; white-space: nowrap; display: inline-flex; align-items: center; } /* R946 · 弹窗「‹ 返回」——左上角逐级回退（蓝底高对比，一眼可见） */
.modal-head .mh-back:hover { background: #d5e8f8; }
.modal-head .x { margin-left: auto; width: 32px; height: 32px; border-radius: 8px; display: flex; align-items: center; justify-content: center; color: var(--text-2); }
.modal-head .x:hover { background: var(--surface-2); }
.modal-body { padding: 22px; overflow-y: auto; overflow-x: auto; max-height: calc(90vh - 130px); box-sizing: border-box; overscroll-behavior: contain; /* R364 底部留白改由 .modal.has-foot 控制——仅带 footer 的表单弹窗保留 80px(R442),纯展示弹窗不再浪费。R406:overflow-x 改 auto。A11y:overscroll-behavior 防弹窗内滚带动背景页(R411 P2-2) */ }
.modal.has-foot .modal-body { padding-bottom: 80px; }
.modal-foot { padding: 16px 22px; border-top: 1px solid var(--border); display: flex; gap: 10px; justify-content: flex-end; flex-wrap: wrap; background: #fff; position: sticky; bottom: 0; /* R364:sticky footer 贴在 body 滚动容器底部，body 的底部 padding 保证不遮内容 */ z-index: 2; }
.modal-foot .btn { min-width: 88px; }
.modal-body .pa-preview-wrap { overflow: hidden; max-width: 100%; }
.modal-body .pa-preview-wrap > #paPreview { transform-origin: top left; }
/* R272-R：hiprint 输出的 absolute 元素需要最近的 positioned 祖先，否则定位跑出容器 */
.modal-body .pa-preview-wrap { position: relative; }
.modal-body .hp-print,
.modal-body .hiprint-printTemplate,
.modal-body .hiprint-printPanel,
.modal-body .hiprint-printPaper { position: relative; }
/* R272-V：hiprint 输出 printPaper 默认 flex 容器，导致 printElements 的 position:absolute 失效（堆叠居中）。
   用更通用的类名前缀匹配（兼容不同 hiprint 版本）。强制 printPaper 及其 content 是 block 布局，让 printElements 的 absolute 定位生效。 */
.modal-body [class*="hiprint-printPaper"] { display: block !important; }
.modal-body [class*="hiprint-printPaper-content"] { display: block !important; }
/* 缩放后 .hiprint-printPaper 子元素 absolute 仍然按原坐标定位，但容器需要 relative 作为参考 */
.modal.resizable { resize: both; overflow: hidden; max-width: 96vw; max-height: 96vh; }
.modal.resizable .modal-body { overflow: auto; }
/* R846 抽屉宽度可拖拽 —— 左边缘手柄。
   为什么不用上面的 .modal.resizable（CSS 原生 resize:both）：它的手柄在【右下角】、改宽要往右拖，
   而 .modal--drawer 是 right:0 贴死屏幕右边 ⇒ 往右拖直接出视口，根本拖不宽；且原生 resize 不记忆。
   命中区 10px（远大于 2px 视觉线）—— 4px 的线肉眼与鼠标都难抓。 */
.modal-resizer { position: absolute; left: 0; top: 0; bottom: 0; width: 10px; z-index: 4;
  cursor: col-resize; touch-action: none; background: transparent; }
.modal-resizer::after { content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 2px;
  background: transparent; transition: background .15s; }
.modal-resizer:hover::after, .modal-resizer:focus::after, .modal-resizer.dragging::after { background: var(--primary); }
.modal-resizer:focus { outline: none; }
/* 拖动中：全局锁指针并禁选中，否则快速拖动会拖出文字选区 */
body.is-col-resizing { cursor: col-resize; user-select: none; -webkit-user-select: none; }
body.is-col-resizing * { user-select: none !important; -webkit-user-select: none !important; }
#teCanvasArea { touch-action: none; }
#teCanvas .te-el { touch-action: none; }
#teRulerTop, #teRulerLeft { user-select: none; }
/* R70：模板编辑器 UI 优化（工具条分组 / 三栏加宽 / 空态 / 按钮反馈） */
.te-toolbar { display: flex; flex-wrap: wrap; gap: 10px 14px; margin-bottom: 10px; }
.te-tb-group { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; padding: 7px 10px; background: var(--surface-2, #f3f5f8); border: 1px solid var(--border, #e3e8ef); border-radius: 10px; }
.te-tb-label { font-size: 12px; font-weight: 700; color: var(--text-2, #6b7280); margin-right: 2px; letter-spacing: .5px; }
.te-tb-group .btn { padding: 5px 11px; }
.te-tb-group .btn:hover { background: var(--primary-100); border-color: var(--primary); }
.te-tb-group .btn-o { background: var(--primary); color: #fff; border-color: var(--primary); }
#teLayers, #tePanel { background: var(--surface, #fff); border: 1px solid var(--border, #e3e8ef); border-radius: 10px; padding: 8px; box-shadow: 0 1px 3px rgba(0,0,0,.04); }
#teLayers { font-size: 12px; }
#teCanvasWrap { box-shadow: inset 0 0 0 1px rgba(0,0,0,.06); }
@media (max-width: 480px) { .modal-foot { flex-direction: column-reverse; } .modal-foot .btn { width: 100%; min-width: 0; } }

/* R64①：图片放大独立灯箱层（z 高于 modal-mask，关闭只移除自身，不波及下方弹窗） */
.img-lightbox { position: fixed; inset: 0; z-index: 1000; display: flex; align-items: center; justify-content: center; }
.img-lightbox-mask { position: absolute; inset: 0; background: rgba(0,0,0,.8); }
.img-lightbox-body { position: relative; z-index: 1; max-width: 92vw; max-height: 88vh; }
.img-lightbox-body img { max-width: 100%; max-height: 82vh; border-radius: 10px; box-shadow: 0 12px 40px rgba(0,0,0,.5); display: block; }
/* R409-G5：图片预览点击放大（放大后可滑动查看大图细节） */
.img-lightbox-body.zoomed { max-width: 92vw; max-height: 88vh; overflow: auto; -webkit-overflow-scrolling: touch; }
.img-lightbox-body.zoomed img { max-width: none; max-height: none; width: 220%; height: auto; border-radius: 10px; cursor: zoom-out; }
.img-zoom-btn { position: absolute; bottom: -14px; left: -10px; width: 34px; height: 34px; border-radius: 50%; border: none; background: #fff; color: #333; font-size: 12px; font-weight: 700; cursor: pointer; box-shadow: 0 2px 8px rgba(0,0,0,.3); z-index: 2; }

/* R71：hiprint 可视化设计器容器（替代自有编辑器） */
.hp-wrap { display: flex; flex-direction: column; gap: 8px; }
.hp-toolbar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.hp-hint { color: var(--text-2, #6b7280); font-size: 12px; }
.hp-body { display: flex; gap: 8px; align-items: stretch; min-height: 64vh; }
.hp-left { width: 170px; flex-shrink: 0; background: #f6f8fa; border: 1px solid var(--border, #e3e8ef); border-radius: 8px; padding: 10px 8px; display: flex; flex-direction: column; gap: 8px; }
.hp-left .hp-group-title { font-size: 12px; font-weight: 600; color: var(--text-2, #6b7280); padding: 0 4px; }
.hp-left .hp-scroll { display: flex; flex-direction: column; gap: 4px; overflow: auto; max-height: 28vh; }
.hp-left .hp-item { display: flex; align-items: center; gap: 8px; padding: 7px 8px; border-radius: 6px; background: #fff; border: 1px solid var(--border, #e3e8ef); cursor: move; font-size: 13px; color: var(--text, #111827); user-select: none; }
.hp-left .hp-item:hover { border-color: var(--primary); color: var(--primary); }
.hp-left .hp-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--primary); }
.hp-left .hp-tag { min-width: 22px; text-align: center; font-size: 10px; padding: 2px 4px; border-radius: 4px; background: #e5e7eb; color: #374151; }
/* R184c②：分类折叠（默认折叠字段分类，仅展开基础元素） */
.hp-left .hp-group-title { cursor: pointer; display: flex; align-items: center; justify-content: space-between; }
.hp-left .hp-group-title::after { content: '▾'; font-size: 10px; color: var(--text-2, #6b7280); }
.hp-left .hp-group.collapsed .hp-group-title::after { content: '▸'; }
.hp-left .hp-group.collapsed .hp-scroll { display: none; }
/* R184c②：收藏/常用置顶区 + 星标 */
.hp-left .hp-fav { display: flex; flex-direction: column; gap: 4px; border: 1px dashed #c7d2fe; background: #eef2ff; border-radius: 6px; padding: 6px 6px; }
.hp-left .hp-fav-title { font-size: 12px; font-weight: 600; color: #4338ca; padding: 0 2px; }
.hp-left .hp-fav-list { display: flex; flex-direction: column; gap: 4px; max-height: 22vh; overflow: auto; }
.hp-left .hp-fav-item { background: #fff; }
.hp-left .hp-star { margin-left: auto; cursor: pointer; color: #f59e0b; font-size: 14px; line-height: 1; padding: 0 2px; flex-shrink: 0; user-select: none; }
.hp-left .hp-star.on { color: #f59e0b; }
.hp-left .hp-star:hover { transform: scale(1.15); }
.hp-center { flex: 1; background: #aeb6c2; border-radius: 8px; overflow: hidden; padding: 8px; position: relative; }
.hp-design { background: #fff; position: absolute; top: 0; left: 0; }
.hp-design .hiprint-printPaper { outline: 1px dashed #9ca3af; }
/* R183d: 让选中元素的调整手柄清晰可见，resize-panel 不遮挡内容 */
.hp-design .hiprint-printElement .resize-panel { background-color: rgba(59,130,246,.08) !important; border: 1px dashed rgba(59,130,246,.55); box-sizing: border-box; cursor: move; }
.hp-design .hiprint-printElement .resize-panel .resizebtn { width: 10px !important; height: 10px !important; background: #fff !important; border: 2px solid var(--primary) !important; border-radius: 50%; box-shadow: 0 1px 3px rgba(0,0,0,.25); z-index: 10; }
.hp-design .hiprint-printElement .resize-panel .resizebtn:hover { background: var(--primary) !important; border-color: var(--primary) !important; }
.hp-design .hiprint-printElement .resize-panel .resizebtn.r { width: 14px !important; height: 14px !important; border-radius: 3px; }
.hp-design .hiprint-printElement .resize-panel .del-btn { display: none !important; }
.hp-design .size-box { display: none !important; }
.hp-ruler-top { position: absolute; top: 8px; left: 30px; right: 8px; height: 22px; overflow: hidden; background: #eef1f5; border-bottom: 1px solid #c7cdd6; z-index: 4; }
.hp-ruler-left { position: absolute; top: 30px; left: 8px; bottom: 8px; width: 22px; overflow: hidden; background: #eef1f5; border-right: 1px solid #c7cdd6; z-index: 4; }
.hp-stage { position: absolute; top: 30px; left: 30px; }
.hp-scale { position: absolute; top: 0; left: 0; transform-origin: top left; }
.hp-toolbar2 { margin-top: 6px; gap: 10px 12px; }
.hp-size-label { font-size: 12px; font-weight: 600; color: var(--text, #111827); background: #eef1f5; padding: 3px 8px; border-radius: 6px; flex-shrink: 0; }
.hp-zoom { display: inline-flex; align-items: center; gap: 4px; }
.hp-zoom .text-2 { min-width: 46px; text-align: center; }
/* R183e: 工具栏分组卡片 */
.hp-tb-group { display: inline-flex; align-items: center; flex-wrap: wrap; gap: 4px; padding: 5px 8px; background: var(--surface-2, #f3f5f8); border: 1px solid var(--border, #e3e8ef); border-radius: 10px; }
.hp-tb-group .hp-tb-label { font-size: 11px; font-weight: 700; color: var(--text-2, #6b7280); margin-right: 4px; letter-spacing: .3px; white-space: nowrap; }
.hp-tb-group .btn { padding: 5px 10px; font-size: 12px; }
.hp-tb-group .btn:hover { background: var(--primary-100); border-color: var(--primary); color: var(--primary); }
/* R183e/f: 标尺三级刻度 */
.hp-ruler-tick { position: absolute; pointer-events: none; }
.hp-ruler-top .hp-ruler-tick { top: 0; width: 1px; }
.hp-ruler-left .hp-ruler-tick { left: 0; height: 1px; }
.hp-ruler-tick.ruler-maj { background: #1f2937; }
.hp-ruler-tick.ruler-mid { background: #4b5563; }
.hp-ruler-tick.ruler-min { background: #6b7280; opacity: .9; }
.hp-ruler-num { position: absolute; font: 9px/11px sans-serif; color: #1f2937; pointer-events: none; }
.hp-ruler-top .hp-ruler-num { top: 1px; }
.hp-ruler-left .hp-ruler-num { left: 2px; }

/* R183i:实时真数据预览浮层(独立非破坏性,不毁设计器) */
.hp-preview-mask { position: fixed; inset: 0; background: rgba(17,24,39,.55); z-index: 200; display: flex; align-items: center; justify-content: center; padding: 24px; }
.hp-preview-box { background: #fff; border-radius: 14px; width: min(960px, 96vw); height: min(92vh, 1100px); display: flex; flex-direction: column; overflow: hidden; box-shadow: 0 20px 60px rgba(0,0,0,.35); }
.hp-preview-bar { display: flex; align-items: center; gap: 14px; padding: 12px 16px; border-bottom: 1px solid var(--border); flex-shrink: 0; }
.hp-preview-title { font-weight: 700; font-size: 14px; }
.hp-preview-src { font-size: 12px; color: var(--text-2); }
.hp-preview-close { margin-left: auto; }
.hp-preview-scroll { flex: 1; min-height: 0; overflow: auto; background: #eef1f5; padding: 20px; display: flex; justify-content: center; align-items: flex-start; }
.hp-preview-sheet { background: #fff; box-shadow: 0 4px 16px rgba(0,0,0,.18); transform-origin: top center; }
.hp-margin-box { position: absolute; border: 1px dashed #f59e0b; pointer-events: none; z-index: 5; }
.hp-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; z-index: 6; }
.hp-guide { position: absolute; background: var(--primary); opacity: .7; pointer-events: none; }
/* R183k: 持久标尺辅助线（存于 #hpGuides，与元素同坐标空间，随缩放自动缩放） */
.hp-guides { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; z-index: 7; }
.hp-guide-v { position: absolute; top: 0; width: 0; border-left: 1px solid var(--primary); height: 100%; pointer-events: none; }
.hp-guide-h { position: absolute; left: 0; height: 0; border-top: 1px solid var(--primary); width: 100%; pointer-events: none; }
.hp-guide-drag { border-color: #dc2626; }
.hp-guide-grip { position: absolute; top: -5px; left: -5px; width: 9px; height: 9px; background: var(--primary); border: 1px solid #fff; border-radius: 2px; cursor: grab; pointer-events: auto; box-shadow: 0 0 0 1px color-mix(in srgb, var(--primary) 40%, transparent); }
.hp-guide-grip:hover { background: var(--primary-dark); transform: scale(1.15); }
.hp-guide-grip:active { cursor: grabbing; }
.hp-drag-tip { position: absolute; z-index: 20; background: rgba(17,24,39,.92); color: #fff; font: 11px/14px monospace; padding: 4px 6px; border-radius: 5px; pointer-events: none; white-space: nowrap; }
.hiprint-printElement.hp-overflow { outline: 2px solid #dc2626; }
.hp-right { width: 260px; flex-shrink: 0; background: #f6f8fa; border: 1px solid var(--border, #e3e8ef); border-radius: 8px; padding: 8px; overflow: auto; }
.hp-foot { min-height: 30px; }
.hp-print { background: #fff; padding: 0; }
@media (max-width: 720px) { .hp-body { flex-direction: column; } .hp-left, .hp-right, .hp-right-wrap { width: auto; } }

/* ===== R181 P0 外套：全屏 / 网格 / 搜索 / 状态栏 ===== */
.modal.hp-fullscreen { position: fixed; inset: 0; width: 100% !important; height: 100% !important; max-width: none; max-height: none !important; margin: 0; border-radius: 0; display: flex; flex-direction: column; }
.modal.hp-fullscreen .modal-head { flex-shrink: 0; }
.modal.hp-fullscreen .modal-body { flex: 1; min-height: 0; overflow: hidden; display: flex; padding: 10px; }
.modal.hp-fullscreen .hp-wrap { width: 100%; height: 100%; }
.modal.hp-fullscreen .hp-body { flex: 1; min-height: 0; }
.modal-mask.hp-fs { padding: 0; background: #fff; backdrop-filter: none; }
.hp-left .hp-search { width: 100%; box-sizing: border-box; padding: 6px 8px; border: 1px solid var(--border, #e3e8ef); border-radius: 6px; font-size: 13px; margin-bottom: 6px; outline: none; }
.hp-left .hp-search:focus { border-color: var(--primary); }
.hp-left .hp-group { display: flex; flex-direction: column; gap: 4px; }
.hp-left .hp-group + .hp-group { margin-top: 4px; }
/* R183g: 图层管理面板 */
.hp-layers { display: flex; flex-direction: column; gap: 4px; border-top: 1px dashed var(--border, #e3e8ef); padding-top: 6px; margin-top: 4px; }
.hp-layers-title { font-size: 12px; font-weight: 600; color: var(--text-2, #6b7280); padding: 0 4px; display: flex; align-items: center; gap: 6px; }
.hp-layer-count { display: inline-flex; align-items: center; justify-content: center; min-width: 16px; height: 16px; padding: 0 4px; border-radius: 8px; background: var(--primary); color: #fff; font-size: 11px; }
.hp-layers-list { display: flex; flex-direction: column; gap: 3px; overflow: auto; max-height: 26vh; }
.hp-layer { display: flex; align-items: center; justify-content: space-between; gap: 6px; padding: 5px 6px; border-radius: 6px; background: #fff; border: 1px solid var(--border, #e3e8ef); font-size: 12px; }
.hp-layer:hover { border-color: var(--primary); }
.hp-layer-name { cursor: pointer; color: var(--text, #111827); flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hp-layer-hidden .hp-layer-name { color: #9ca3af; text-decoration: line-through; }
.hp-layer-locked .hp-layer-name { color: #b45309; }
.hp-layer-acts { display: flex; gap: 2px; }
.hp-layer-btn { border: 1px solid var(--border, #e3e8ef); background: #f9fafb; border-radius: 4px; padding: 1px 5px; font-size: 11px; cursor: pointer; color: #374151; line-height: 1.6; }
.hp-layer-btn:hover { background: var(--primary); color: #fff; border-color: var(--primary); }
.hp-locked { outline: 2px solid #b45309; outline-offset: 1px; }
.hp-grid { position: absolute; inset: 0; z-index: 7; pointer-events: none; background-image: radial-gradient(circle, color-mix(in srgb, var(--primary) 30%, transparent) 1px, transparent 1.4px); background-position: 0 0; }
.hp-statusbar { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; font-size: 12px; color: var(--text-2, #6b7280); padding: 5px 10px; background: #eef1f5; border-radius: 0 0 8px 8px; }
.hp-statusbar span { white-space: nowrap; }
.hp-st-hint { margin-left: auto; color: #9aa3af; font-size: 11px; }
.hp-pagination { min-height: 16px; }

/* R183·多选对齐 + 浮动微调条 */
.hp-sep { display: inline-block; width: 1px; height: 20px; background: var(--border, #e3e8ef); margin: 0 4px; vertical-align: middle; }
.hp-finetune { position: absolute; right: 10px; bottom: 10px; z-index: 30; width: 172px; background: #fff; border: 1px solid var(--border, #e3e8ef); border-radius: 10px; box-shadow: 0 8px 24px rgba(0,0,0,.16); padding: 10px; font-size: 12px; }
.hp-finetune .hp-ft-head { font-weight: 600; color: var(--text, #111827); margin-bottom: 8px; font-size: 12px; }
.hp-finetune .hp-ft-pad { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; margin-bottom: 8px; }
.hp-finetune .hp-ft-pad span { display: block; }
.hp-finetune .hp-ft-btn { border: 1px solid var(--border, #e3e8ef); background: #f6f8fa; border-radius: 6px; padding: 6px 0; font-size: 13px; cursor: pointer; color: var(--text, #111827); }
.hp-finetune .hp-ft-btn:hover { border-color: var(--primary); color: var(--primary); }
.hp-finetune .hp-ft-row { display: flex; align-items: center; gap: 6px; margin-top: 6px; flex-wrap: wrap; }
.hp-finetune .hp-ft-step { padding: 3px 4px; border: 1px solid var(--border, #e3e8ef); border-radius: 6px; font-size: 12px; }
.hp-qrbind { position: absolute; right: 10px; bottom: 170px; z-index: 30; width: 220px; background: #fff; border: 1px solid var(--border, #e3e8ef); border-radius: 10px; box-shadow: 0 8px 24px rgba(0,0,0,.16); padding: 10px; font-size: 12px; }
.hp-qrbind .hp-qr-head { font-weight: 600; color: var(--text, #111827); margin-bottom: 8px; font-size: 12px; }
.hp-qrbind .hp-qr-row { margin-bottom: 8px; }
.hp-qrbind .hp-qr-field, .hp-qrbind .hp-qr-input { width: 100%; padding: 5px 6px; border: 1px solid var(--border, #e3e8ef); border-radius: 6px; font-size: 12px; box-sizing: border-box; }
.hp-qrbind .hp-qr-tip { color: var(--text-2, #6b7280); font-size: 11px; line-height: 1.4; }
.hp-tabletip { position: absolute; right: 10px; bottom: 175px; z-index: 29; width: 240px; background: #fff; border: 1px solid var(--border, #e3e8ef); border-radius: 10px; box-shadow: 0 8px 24px rgba(0,0,0,.16); padding: 10px 12px; font-size: 12px; color: var(--text, #111827); line-height: 1.7; }
.hp-tabletip b { display: block; margin-bottom: 4px; font-size: 12px; }
.hp-tabletip .hp-tt-item { display: inline-block; margin-right: 6px; padding: 1px 6px; background: var(--primary-light); color: var(--primary); border-radius: 5px; font-size: 11px; }
.hp-qrbind .hp-qr-compose { max-height: 180px; overflow-y: auto; display: grid; grid-template-columns: 1fr 1fr; gap: 4px; margin-top: 4px; }
.hp-qrbind .hp-qr-check { display: flex; align-items: center; gap: 4px; font-size: 11px; color: var(--text, #111827); cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hp-qrbind .hp-qr-check input { margin: 0; }
/* R245-B3/B4：条码面板与二维码容错级别行的标签 + 紧凑下拉 */
.hp-qrbind .hp-qr-lb { display: block; color: var(--text-2, #6b7280); font-size: 11px; margin-bottom: 3px; }
.hp-qrbind .hp-qr-sm { padding: 4px 5px; font-size: 11px; }
/* R245-B5：表格单元格合并面板（挂在表格提示条下方） */
.hp-tabletip .hp-tt-merge { display: flex; align-items: center; gap: 8px; margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--border, #e3e8ef); }
.hp-tabletip .hp-tt-btn { border: 1px solid var(--border, #e3e8ef); background: #f6f8fa; border-radius: 6px; padding: 4px 8px; font-size: 11px; cursor: pointer; color: var(--text, #111827); }
.hp-tabletip .hp-tt-btn:hover { border-color: var(--primary); color: var(--primary); }
.hp-tabletip .hp-tt-btn.hp-tt-primary { background: var(--primary); border-color: var(--primary); color: #fff; }
.hp-tabletip .hp-tt-state { font-size: 11px; color: var(--text-2, #6b7280); }
.hp-tabletip .hp-tt-state.on { color: var(--green, #16a34a); font-weight: 600; }
.hp-tabletip .hp-tt-box { margin-top: 8px; }
.hp-tabletip .hp-tt-cols { max-height: 150px; overflow-y: auto; display: grid; grid-template-columns: 1fr 1fr; gap: 4px; margin-top: 4px; }
.hp-tabletip .hp-tt-act { display: flex; gap: 6px; margin-top: 8px; }
.hp-tabletip .hp-qr-tip { color: var(--text-2, #6b7280); font-size: 11px; line-height: 1.4; }
.hp-tabletip .hp-qr-check { display: flex; align-items: center; gap: 4px; font-size: 11px; color: var(--text, #111827); cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hp-tabletip .hp-qr-check input { margin: 0; }

/* ===================== R245 Batch C · 设计器交互优化配套样式 ===================== */
/* C-1 工具栏图标按钮：对齐组 8 个按钮改纯图标后需要固定为等宽方块，否则箭头字形宽度不一会参差 */
.hp-tb-group .btn.hp-tb-ico { width: 30px; padding: 5px 0; text-align: center; font-size: 14px; line-height: 1.2; }
/* C-10 快捷键触发时的按钮高亮（Ctrl+Z/C/V/A 命中即闪一下，建立键↔按钮的对应关系） */
@keyframes hpFlash { 0% { background: var(--primary); color: #fff; transform: scale(1.08); } 100% { background: transparent; color: inherit; transform: scale(1); } }
.hp-tb-group .btn.hp-flash { animation: hpFlash .48s ease-out; border-color: var(--primary); }
@media (prefers-reduced-motion: reduce) { .hp-tb-group .btn.hp-flash { animation: none; outline: 2px solid var(--primary); } }

/* C-3/C-4 右侧属性面板外包：标题条常驻在 #hpSetting 外面（hiprint 每次选中都会清空 #hpSetting） */
.hp-right-wrap { width: 260px; flex-shrink: 0; display: flex; flex-direction: column; gap: 6px; min-height: 0; }
.hp-right-wrap > .hp-right { width: auto; flex: 1; min-height: 0; }
.hp-right-head { display: flex; align-items: center; gap: 8px; padding: 6px 9px; background: var(--surface-2, #f3f5f8); border: 1px solid var(--border, #e3e8ef); border-radius: 8px; }
.hp-right-head .hp-rh-t { font-size: 12px; font-weight: 700; color: var(--text, #111827); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hp-right-head .hp-rh-btn { margin-left: auto; flex-shrink: 0; border: 1px solid var(--border, #e3e8ef); background: #fff; border-radius: 6px; padding: 3px 8px; font-size: 11px; cursor: pointer; color: var(--text-2, #6b7280); }
.hp-right-head .hp-rh-btn:hover { border-color: var(--primary); color: var(--primary); }
.hp-right-head .hp-rh-btn.on { background: var(--primary); border-color: var(--primary); color: #fff; }

/* R258 批量操作条：多选 ≥2 时显示，提供统一等比缩放 */
.hp-batch-bar { display: flex; align-items: center; gap: 6px; padding: 7px 9px; background: #eff6ff; border: 1px solid #bfdbfe; border-radius: 8px; flex-wrap: wrap; }
.hp-batch-bar .hp-bb-label { font-size: 11px; font-weight: 700; color: #1d4ed8; white-space: nowrap; }
.hp-batch-bar .hp-bb-group { display: inline-flex; align-items: center; gap: 4px; }
.hp-batch-bar .hp-bb-group label { font-size: 11px; color: #374151; white-space: nowrap; }
.hp-batch-bar .hp-bb-input { width: 52px; height: 24px; border: 1px solid #93c5fd; border-radius: 4px; text-align: center; font-size: 12px; font-weight: 600; color: #1d4ed8; background: #fff; outline: none; }
.hp-batch-bar .hp-bb-input:focus { border-color: var(--primary); box-shadow: 0 0 0 2px rgba(249,115,22,.18); }
.hp-batch-bar .hp-bb-group span:last-of-type { font-size: 11px; color: #6b7280; }
.hp-batch-bar .hp-bb-btn { height: 24px; padding: 0 10px; font-size: 11px; font-weight: 600; }
.hp-batch-bar .hp-bb-presets { display: inline-flex; align-items: center; gap: 2px; margin-left: auto; }
.hp-batch-bar .hp-bb-pb { height: 22px; min-width: 32px; padding: 0 4px; font-size: 10px; line-height: 1; }

/* R258 增强 C：包围盒四角拖拽手柄 */
.hp-bbox-handle:hover { background: var(--primary) !important; border-color: #1d4ed8 !important; transform: scale(1.2); }
/* C-3 分组标题条：默认（页签模式）隐藏，仅在「展开全部」模式下出现并可点击折叠 */
.hp-prop-gt { display: none; }
.hp-right.hp-prop-all .prop-tab-items { display: none; }
.hp-right.hp-prop-all .hiprint-option-items { display: block !important; margin-bottom: 8px; border: 1px solid var(--border, #e3e8ef); border-radius: 8px; background: #fff; overflow: hidden; }
.hp-right.hp-prop-all .hp-prop-gt { display: flex; align-items: center; justify-content: space-between; padding: 6px 9px; background: var(--surface-2, #f3f5f8); border-bottom: 1px solid var(--border, #e3e8ef); font-size: 12px; font-weight: 600; color: var(--text, #111827); cursor: pointer; user-select: none; }
.hp-right.hp-prop-all .hp-prop-gt::after { content: '▾'; font-size: 10px; color: var(--text-2, #6b7280); }
.hp-right.hp-prop-all .hiprint-option-items.hp-gt-collapsed .hp-prop-gt::after { content: '▸'; }
.hp-right.hp-prop-all .hiprint-option-items.hp-gt-collapsed > *:not(.hp-prop-gt) { display: none !important; }

/* C-9 微调面板：⌃ 角标 + 快捷键说明行 */
.hp-finetune .hp-ft-btn { position: relative; }
.hp-finetune .hp-ft-kb::after { content: attr(data-kb); position: absolute; top: 1px; right: 3px; font-size: 9px; line-height: 1; color: var(--text-2, #9ca3af); pointer-events: none; }
.hp-finetune .hp-ft-tip { margin-top: 8px; padding-top: 7px; border-top: 1px dashed var(--border, #e3e8ef); font-size: 10px; line-height: 1.6; color: var(--text-2, #6b7280); }
.hp-finetune .hp-ft-tip b { color: var(--text, #111827); }
.hp-finetune .hp-ft-tip a { color: var(--primary); text-decoration: none; }
.hp-finetune kbd, .hp-help-box kbd { display: inline-block; padding: 0 4px; border: 1px solid var(--border, #d1d5db); border-bottom-width: 2px; border-radius: 4px; background: #fff; font: 500 10px/16px ui-monospace, Menlo, Consolas, monospace; color: var(--text, #111827); }

/* C-1 帮助浮层（F1）——独立于 modal，避免顶掉正在编辑的设计器 DOM */
.hp-help-mask { position: fixed; inset: 0; background: rgba(17,24,39,.55); z-index: 210; display: flex; align-items: center; justify-content: center; padding: 24px; }
.hp-help-box { background: #fff; border-radius: 14px; width: min(680px, 94vw); max-height: 88vh; display: flex; flex-direction: column; overflow: hidden; box-shadow: 0 20px 60px rgba(0,0,0,.35); }
.hp-help-bar { display: flex; align-items: center; gap: 12px; padding: 12px 16px; border-bottom: 1px solid var(--border, #e3e8ef); flex-shrink: 0; }
.hp-help-bar .hp-help-title { font-weight: 700; font-size: 14px; }
.hp-help-bar .btn { margin-left: auto; }
.hp-help-body { flex: 1; min-height: 0; overflow: auto; padding: 14px 16px 18px; }
.hp-help-sec + .hp-help-sec { margin-top: 14px; }
.hp-help-st { font-size: 12px; font-weight: 700; color: var(--primary); margin-bottom: 6px; }
.hp-help-tb { width: 100%; border-collapse: collapse; }
.hp-help-tb td { padding: 4px 6px; font-size: 12px; vertical-align: top; border-bottom: 1px solid var(--surface-2, #f3f5f8); }
.hp-help-tb .hp-help-k { width: 190px; white-space: nowrap; }
.hp-help-tb .hp-help-d { color: var(--text-2, #6b7280); }

.img-lightbox-body .x { position: absolute; top: -12px; right: -12px; width: 34px; height: 34px; border-radius: 50%; border: none; background: #fff; color: #333; font-size: 18px; cursor: pointer; box-shadow: 0 2px 8px rgba(0,0,0,.3); }
.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.form-grid .full { grid-column: 1 / -1; }

/* ===== R885 · 桌面端表单弹窗【分组卡片】（老板 2026-10-03 从三版方案里圈定甲案）=====
   页面灰底 + 每组一块白卡；组标题＝橙左竖条 + 12.5px/600（与 R884 手机端详情页同一套语言）。
   ⚠️ 只作用于「用 Pages.fmGroup() 包过」的弹窗（.modal-body > .fm），
      .form-grid / .input / .dl / .modal-body 等公共本体一律不动 ⇒ 未改造的弹窗零影响。 */
.fm { background: #E7EAEF; margin: -22px; padding: 14px; }
/* 带 footer 的弹窗：.modal-body 底部预留 80px（历史遗留的 footer 留位）⇒ 灰底要一并吃下，否则底部露白条 */
.modal.has-foot .modal-body > .fm { margin-bottom: -80px; }
.fm-sec { background: var(--surface); border-radius: 12px; margin-bottom: 9px; }
.fm-sec:last-child { margin-bottom: 0; }
.fm-bar { display: flex; align-items: center; gap: 7px; padding: 11px 14px 3px;
  font-size: 12.5px; font-weight: 600; color: #374151; letter-spacing: .01em; }
.fm-bar::before { content: ''; flex: none; width: 3px; height: 11px; border-radius: 2px; background: var(--primary); }
.fm-body { padding: 5px 14px 13px; }
/* R886 · 手机端真抽屉（Mobile.sheet）内的分组外壳：其滚动区内边距是 18px（.modal-body 是 22px），
   负边距必须按 18px 重算，否则左右各溢出 4px（新建订单在手机上走这条路）。 */
.mp-sheet-scroll > .fm { margin: -18px; padding: 18px; }
/* R885 · 表单弹窗底部按钮「居中 + 等宽」—— 用 :has(.fm) 限定「含分组卡片的表单弹窗」，
   不动 .modal-foot 公共本体（确认框 / 详情弹窗 / 打印预览一律不受影响）。
   浏览器不支持 :has() 时整条规则被忽略 ⇒ 退回原「靠右」形态，不会坏。 */
.modal:has(.fm) .modal-foot { justify-content: center; gap: 10px; }
.modal:has(.fm) .modal-foot .btn { min-width: 112px; padding: 0 20px; }

/* ============ R890 · 手机端表单「设置列表式」（老板 2026-10-04 圈定戊案）============
   背景：手机端三个表单窗口（新建客户 / 新建合同 / 新增车辆）走 .modal 全宽贴底弹窗，
         字段由 R885 的分组卡片呈现（标签在上、输入框整行）⇒ 合同那种 21 字段要滚很久。
   方案：≤820px 时把 .fm 表单覆盖为「设置列表式」—— 每段一块白卡，一行一字段
         （标签左 / 值右 / 行分隔线 / 行高 50px），组标题退成灰字小标。
   依据：R888/R889 调研 —— iOS 设置页 / 微信 / 支付宝 的行式做法（本轮老板从 8 版方案中圈定）。
   ⚠️ 只作用于 ≤820px 且仅限 .fm 容器内 ⇒ 电脑端、.form-grid / .picker-field / .photo-box 本体一字不动。
   ⚠️ 负边距按【手机端 .modal-body 的 16px】重算（原来照电脑端 22px 写 ⇒ 实测左右各溢出 6px、内容区横向可滚）。
   ⚠️ 度量与 R820「手机端新建订单扁平行」对齐（标签列 / 24px 高输入 / 右对齐 / .picker-field 同款），
      避免同一个人在手机上看到两套行式。
   ⚠️ 全程不使用 :has()（老板 2026-10-04 选「稳做法」）—— 照片字段改用 R890 加的 .fm-photo 语义类标记。 */
@media (max-width: 820px) {
  /* 1) 外框：负边距改按手机端 16px（修 R889 实测的「左右各溢出 6px」） */
  .fm { margin: -16px; }
  /* 手机端 .modal.has-foot .modal-body 的底部内边距是 92px（电脑端 80px），灰底要一并吃下 */
  .modal.has-foot .modal-body > .fm { margin-bottom: -92px; }

  /* 2) 组标题 → 灰字小标；组自身不再是一张卡（白卡改由字段区承担） */
  .fm .fm-sec { background: transparent; border-radius: 0; margin-bottom: 16px; }
  .fm .fm-bar { padding: 0 2px 7px; font-size: 12px; font-weight: 600; color: #8A9099; }
  .fm .fm-bar::before { display: none; }
  .fm .fm-body { padding: 0; }

  /* 3) 字段区 → 一块白卡；一行一字段 */
  .fm .form-grid,
  .fm .form-grid.cols3 { display: block; background: var(--surface); border-radius: 11px; overflow: hidden; }
  .fm .form-grid > div { display: flex; flex-wrap: wrap; align-items: center; gap: 0 10px;
    min-height: 50px; padding: 3px 14px; border-bottom: 1px solid var(--border-2); }
  .fm .form-grid > div:last-child { border-bottom: 0; }

  /* 标签：自然宽、不折行（长标签靠换行把值挤到第二行，不用省略号截断 —— 截断会让人读不出字段名） */
  .fm .form-grid > div > label { flex: none; margin: 0; font-size: 13.5px; color: var(--text-2); white-space: nowrap; }

  /* 值：右对齐、无框、透明底（与 R820 扁平行同款度量） */
  .fm .form-grid > div > .input,
  .fm .form-grid > div > .picker-field { flex: 1 1 56px; min-width: 0; width: auto; margin-left: auto;
    text-align: right; border: 0; background: transparent; box-shadow: none;
    height: 42px; line-height: 42px; padding: 0 0 0 10px; font-size: 14.5px; color: var(--text); }
  .fm .form-grid > div > .input:focus { outline: none; }
  .fm .form-grid > div > .input[readonly] { background: transparent !important; }
  .fm .form-grid > div > .input::placeholder { color: #B9BEC6; }
  /* R911 · 日期行右侧加「日历」图标 —— 纯 CSS 背景，不动 DOM、不动取值。
     依据：手机端行式里日期框与普通文本框长得一样，看不出「点它能弹日历」。
     data-datepick 是 R827 起所有自绘日期框的统一标记 ⇒ 一处覆盖合同/车辆/提货计划/外部车/订单。
     放在 ≤820px 媒体块内 ⇒ 电脑端（走原生日期控件）不在此范围，零影响。
     ⚠️ 背景三个属性必须带 !important：同区块 887 行的
     .fm .form-grid > div > .input[readonly] { background: transparent !important } 是简写 + important，
     会把 background-image 一并重置成 none（日期框都是 readonly），不加就等于没写。 */
  .fm .form-grid > div > .input[data-datepick] {
    padding-right: 22px;
    background-repeat: no-repeat !important; background-position: right center !important;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='15' height='15' viewBox='0 0 16 16' fill='none'><rect x='1.6' y='3' width='12.8' height='11.4' rx='2' stroke='%239ca3af' stroke-width='1.3'/><path d='M1.6 6.4h12.8M5.4 1.6v3M10.6 1.6v3' stroke='%239ca3af' stroke-width='1.3' stroke-linecap='round'/></svg>") !important;
  }
  .fm .form-grid > div > select.input { text-align: right; }
  .fm .form-grid > div > .picker-field { min-height: 42px; padding: 0 20px 0 10px;
    justify-content: flex-end; color: #B9BEC6; }
  .fm .form-grid > div > .picker-field:after { right: 0; }
  .fm .form-grid > div > .picker-field.has-value { color: var(--text); }

  /* 4) 块级子内容（复选组 / 说明文字 / 备注 span）：自己占一整行，不跟标签挤一行 */
  .fm .form-grid > div > :not(label):not(.input):not(.picker-field):not(.photo-box) { flex-basis: 100%; }
  .fm .form-grid > div > .text-2.text-xs { line-height: 1.6; }

  /* 5) R890 · 照片字段（老板 2026-10-04 从五种处理方式里选「戊-A」）：跳出行式、保持整宽大框。
     依据：飞书《上传》规范「在表单中使用上传组件时，建议附件宽度与表单内容等宽」；
           Oracle 移动端 Attachment 模式把小缩略图定位为 Document Icon（只指示「有没有」）。
           车辆表单的行驶证 / 保险单是【要核对内容】的（年审到期日、保险到期日）⇒ 不缩成小缩略图。 */
  .fm .form-grid > .fm-photo { display: block; padding: 11px 14px 14px; }
  .fm .form-grid > .fm-photo > label { display: block; margin: 0 0 8px; font-size: 13.5px; color: var(--text-2); white-space: normal; }
  .fm .form-grid > .fm-photo .photo-box { width: 100%; flex: none; }
  .fm .form-grid > .fm-photo .picker-field { margin-left: 0; text-align: left; }
  /* R890 · 手机端磅单详情「电商订单风」（老板 2026-10-04 从 8 版方案里圈定己案）——
     顶部状态条 + 横向四步。合计金额同受 App.canSeeBillMoney() 管辖（磅房与司机不渲染）。 */
  .mp-so-head { display: flex; align-items: center; gap: 10px; background: var(--surface); border-radius: 12px; padding: 12px 13px; margin-bottom: 9px; }
  .mp-so-net { font-size: 16px; font-weight: 600; color: var(--text); }
  .mp-so-head-r { margin-left: auto; text-align: right; }
  .mp-so-head-r span { display: block; font-size: 11px; color: var(--text-2); }
  .mp-so-head-r b { font-size: 16px; font-weight: 600; color: var(--primary-dark); }
  .mp-so-steps { display: flex; align-items: center; background: var(--surface); border-radius: 12px; padding: 11px 8px; margin-bottom: 9px; }
  .mp-so-step { flex: 1 1 0; display: flex; flex-direction: column; align-items: center; gap: 5px; position: relative; }
  .mp-so-step i { position: relative; z-index: 1; width: 11px; height: 11px; border-radius: 50%; background: #E5E7EB; box-sizing: border-box; }
  .mp-so-step.on i { background: var(--primary); }
  .mp-so-step span { font-size: 11px; color: var(--text-3); white-space: nowrap; }
  .mp-so-step.on span { color: var(--text); font-weight: 500; }
  .mp-so-step:not(:last-child)::after { content: ''; position: absolute; top: 5px; left: 50%; width: 100%; height: 1px; background: #E5E7EB; z-index: 0; }
  .mp-so-step.on:not(:last-child)::after { background: var(--primary-200); }
  /* 吸底操作条内的按钮等宽（审核栏自身写了 flex:1 / flex:2 的内联值，优先级更高、不受影响） */
  .mp-flat .mp-sheet-foot .mp-btn { flex: 1 1 0; }
}

/* R484:三列局部类,仅新建订单表单使用(甲方→乙方→货品 / 预估载重|有效期起|止一行3);全局 2 列与其他页面不受影响 */
.form-grid.cols3 { grid-template-columns: 1fr 1fr 1fr; }
.form-grid.cols3 .full { grid-column: 1 / -1; }
/* R839:采购收货弹窗「毛重|皮重|净重」三列一行(.full 容器内嵌局部三列);680px 以下(手机)塌成单列防挤压 */
.rc-w3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 12px; }
/* R1113 · 老板 2026-10-25：来厂过磅「货物类型（只读）」与「送货司机」必须等高对齐。
   两者本来就是同一个 .input，但只读态在部分环境下会缩高 ⇒ 这里显式锁定同一高度/盒模型。 */
#rc_goods, #rc_driver { height: 40px !important; box-sizing: border-box; line-height: 22px; }
@media (max-width: 680px) { .rc-w3 { grid-template-columns: 1fr; } }
/* R828 · 合同表单「适用业务模式」复选框组 —— 修 UI 变形（4 项被挤成竖排拆字）。
   根因：原实现用 .flex(gap-8) + inline height:44px，flex 默认 nowrap ⇒ 4 项 + 长文案
        「采购收货（进厂）」超出 L800 弹窗内容宽 ⇒ 每项被压到极窄 ⇒ 中文逐字换行。
   修法：独立类 —— 允许换行(flex-wrap:wrap)、每项文字不拆(nowrap)、高度自适应(min-height)。
   为什么用独立类而非改 .flex：.flex 全站 200+ 处在用，动它会波及无关页面。 */
.cn-mode-group { display: flex; flex-wrap: wrap; gap: 8px 14px; align-items: center; min-height: 44px; }
.cn-mode-group > label { display: flex; align-items: center; gap: 4px; white-space: nowrap; flex: 0 0 auto; cursor: pointer; }
/* R409-G6：移动端新建/编辑长表单分段卡片；R409-G1：列表搜索框 */
.mp-form-sec { background: var(--surface); border: 1px solid var(--border); border-radius: 12px; padding: 12px 12px 14px; margin-bottom: 12px; }
.mp-form-sec-t { font-size: 13px; font-weight: 700; color: var(--text); margin-bottom: 10px; }
.mp-form-sec .form-grid { gap: 12px; }
.mp-search-wrap { margin: 10px 0 2px; }
.mp-search-wrap .mp-input { height: 42px; }
.req::after { content: " *"; color: var(--red); }
/* R365:临时磅单弹窗字段区两列紧凑（参照新增磅单 form-grid，解决内容超高 footer 漂出）
   R366:纯白底 + 细边框（替代灰底圆角），更干净 */
.tf-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.tf-grid .tf-row[data-span="2"] { grid-column: span 2; }
.tf-grid .tf-row { display: flex; align-items: center; gap: 8px; min-width: 0; background: #fff; border: 1px solid var(--border, #e2e8f0); border-radius: 8px; padding: 5px 10px; }
.tf-grid .tf-row .tf-lbl { width: 64px; flex: none; color: var(--text-2, #64748b); font-size: 13px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.tf-grid .tf-row .tf-del { flex: none; padding: 2px 8px; }

/* R819e:表单弹窗布局优化（老板 2026-09-29 拍板，依据 B 端表单行业标准）
   ① 单列修饰类：字段少的表单（如厂内提货默认 5 项）走单列，输入框拉满不再留白
   ② 标签统一 88px：原 64px(半行) / 84px(整行) 两套导致左边缘不齐（行业标准值 88px）
   ③ 删除按钮 PC 端悬停才显形，降低视觉噪音；触屏端保持常显（无悬停能力，否则无法删字段） */

.tf-grid .tf-row .tf-lbl { width: 88px; }

@media (hover: hover) and (pointer: fine) {
  .tf-grid .tf-row .tf-del { opacity: 0; transition: opacity .12s; }
  .tf-grid .tf-row:hover .tf-del, .tf-grid .tf-row:focus-within .tf-del { opacity: 1; }
}

/* 详情行 */
.dl { display: grid; grid-template-columns: 120px 1fr; gap: 12px 16px; }
.dl dt { color: var(--text-2); font-size: 13px; }
.dl dd { font-size: 14px; font-weight: 500; }
/* R63④：明细分区标题 / 汇总条 / 驳回框（与移动端 .mp-reject-hint 视觉一致） */
.detail-h { display: flex; align-items: center; font-size: 14px; font-weight: 700; margin: 18px 0 12px; padding-left: 10px; border-left: 3px solid var(--primary); }
.detail-h:first-child { margin-top: 0; }
.detail-sum { background: var(--surface-2); border-radius: 10px; padding: 12px 14px; font-size: 13px; color: var(--text); margin-bottom: 14px; }
.detail-sum b { font-weight: 700; }
.reject-box { display: flex; align-items: center; gap: 8px; background: var(--red-bg); color: var(--red); border-radius: 10px; padding: 10px 12px; font-size: 13px; font-weight: 600; margin-top: 10px; }
.reject-box svg { width: 16px; height: 16px; flex-shrink: 0; }

/* Toast */
.toast-wrap { position: fixed; top: 20px; left: 50%; transform: translateX(-50%); z-index: 200; display: flex; flex-direction: column; gap: 8px; align-items: center; }
.toast { background: #1f2937; color: #fff; padding: 11px 20px; border-radius: 10px; font-size: 14px; box-shadow: var(--shadow-lg);
  display: flex; align-items: center; gap: 8px; animation: toastIn .25s; }
.toast.ok { background: #16a34a; } .toast.err { background: #dc2626; } .toast.warn { background: #d97706; }
.toast svg { width: 18px; height: 18px; }
@keyframes toastIn { from { opacity: 0; transform: translateY(-12px); } to { opacity: 1; } }

/* 关联卡片组(模式C双磅单) */
.dual-group { background: linear-gradient(135deg,#eff6ff,#dbeafe); border: 1px solid #bfdbfe; border-radius: 14px; padding: 14px; margin-bottom: 14px; }
.dual-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.dual-head .on { font-weight: 700; font-size: 13px; }
.dual-head .sum { font-size: 13px; color: var(--blue); font-weight: 600; }
.dual-bills { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.dual-bill { background: #fff; border-radius: 11px; padding: 13px; }
.dual-bill.placeholder { border: 2px dashed #cbd5e1; background: rgba(255,255,255,.4); display: flex; flex-direction: column;
  align-items: center; justify-content: center; color: var(--text-3); min-height: 110px; }
.dual-bill .type { display: flex; align-items: center; gap: 6px; font-weight: 600; font-size: 13px; margin-bottom: 8px; }
.dual-bill .type .cd { width: 8px; height: 8px; border-radius: 50%; }

/* 照片占位 */
.photo-box { width: 100%; aspect-ratio: 4/3; border: 2px dashed var(--border); border-radius: 10px; display: flex; flex-direction: column;
  align-items: center; justify-content: center; color: var(--text-3); background: var(--surface-2); cursor: pointer; transition: .12s; }
.photo-box:hover { border-color: var(--primary); color: var(--primary); }
.photo-thumb { width: 100%; aspect-ratio: 4/3; border-radius: 10px; object-fit: cover; background: #e5e7eb;
  display:flex; align-items:center; justify-content:center; }

/* ============ 移动端 / 小程序 ============ */
.mobile-only { display: none; }
.phone-preview-bar { display: none; }

/* 手机预览框(桌面端展示小程序) */
.phone-sim-mask { position: fixed; inset: 0; background: rgba(17,24,39,.6); backdrop-filter: blur(3px); z-index: 150;
  display: none; align-items: center; justify-content: center; }
.phone-sim-mask.active { display: flex; }
.phone-frame { width: 390px; height: 800px; max-height: 92vh; background: #000; border-radius: 44px; padding: 10px;
  box-shadow: 0 30px 80px rgba(0,0,0,.5); position: relative; }
.phone-notch { position: absolute; top: 10px; left: 50%; transform: translateX(-50%); width: 140px; height: 26px; background: #000;
  border-radius: 0 0 16px 16px; z-index: 5; }
.phone-screen { width: 100%; height: 100%; background: var(--bg); border-radius: 36px; overflow: hidden; position: relative; display: flex; flex-direction: column; }
.phone-close { position: absolute; top: -44px; right: 0; color: #fff; display: flex; align-items: center; gap: 6px; font-size: 14px; }
.phone-hint { position: absolute; top: -44px; left: 0; color: rgba(255,255,255,.7); font-size: 13px; }

/* 小程序界面 */
.mp-wrap { display: flex; flex-direction: column; height: 100%; }
.mp { display: flex; flex-direction: column; height: 100%; background: var(--bg); min-height: 0; position: relative; }
/* 列表过滤条吸顶:长列表滚动时标题+分段筛选不丢失 */
.mp-sticky { position: sticky; top: 0; z-index: 4; background: var(--surface); border-bottom: 1px solid var(--border); padding: 14px 14px 10px; padding-top: calc(14px + env(safe-area-inset-top)); margin: 0 -14px 0; }
/* R861 · 吸顶条「控制区」与「内容区」分离（老板 2026-10-01 指出：控制区与灰底内容同色，看着像浮在半空）。
   NN/g 对吸附头部的要求原文：必须是不透明背景、且与主内容区背景不同 —— 半透明都会"让内容难以阅读、
   经常惹恼用户"，同色等于完全没区分。故：白底 + 1px 分割线，控制区成为一根"工具条"，内容区保持 --bg 灰底。
   作用域是整个 .mp-sticky（含 13 个下钻页的 .mp-subbar.mp-sticky）—— 全站统一，不留两套头部样式。
   注意：首页/我的收入用的是 .mp-header（橙色渐变头），与本类不同源，不受影响。 */
.mp-body-scrolled .mp-sticky { box-shadow: 0 2px 8px rgba(15, 23, 42, .06); }
/* R865 · 吸顶控制区的两行统一最小高度 —— 视图搬家后，四个视图（订单/发货单/预约单/厂内提货）
   共用同一块顶部位置，但内容多少不一：业务线槽 38px、标题+按钮 32px、只有标题 23px
   ⇒ 实测四者总高 101 / 95 / 95 / 80px，切视图时整页会跳一下（老板真机反馈"没对齐"就是这个）。
   统一 38px 后四者一致；只约束高度，不改任何行为（发货单本来就没有状态，仍然不显示槽）。 */
.mp-sticky .mp-head-row { min-height: 38px; }
/* R861 · 空状态三件套（标题 / 说明 / 出口）—— 由 Mobile._emptyBlock 唯一出口生成。
   行业铁律：筛选无结果与真无数据必须长得不一样，且每一种都要给出口（不让用户走进死胡同）。
   类名带 mp-empty- 前缀：避开既有 .empty p 规则，也避免通用短名撞车。 */
.mp-empty-t { font-size: 15px; font-weight: 600; color: var(--text-1); margin: 0 0 6px; }
.mp-empty-s { font-size: 12px; font-weight: 400; color: var(--text-2); margin: 0 0 16px; line-height: 1.6; }
.mp-empty-a { display: inline-flex; align-items: center; height: 36px; padding: 0 20px; border-radius: 999px; border: 1px solid var(--border); background: var(--surface); color: var(--text-1); font-size: 13px; font-weight: 600; }
.mp-empty-a:active { background: var(--surface-2); }
.mp-body > .mp-sticky + .mp-card, .mp-body > .mp-sticky + .mp-order { margin-top: 2px; }
/* R63③：移动端列表筛选条默认收起，不遮盖列表 */
.mp-filter-toggle { width: 100%; height: 44px; border-radius: 10px; border: 1px solid var(--border); background: var(--surface); color: var(--text-2); font-size: 13px; font-weight: 500; display: flex; align-items: center; justify-content: center; gap: 6px; margin-top: 10px; cursor: pointer; -webkit-tap-highlight-color: transparent; transition: background .15s ease; }
.mp-filter-toggle:active { background: var(--surface-2); }
.mp-filter { display: none; margin-top: 10px; }
.mp-filter.open { display: block; }
/* 键盘可达性:可见 focus 环(不影响鼠标点击) */
.mp-tab:focus-visible, .mp-back:focus-visible, .mp-menu-item:focus-visible, .mp-drill:focus-visible,
.mp-quick .q:focus-visible, .mp-seg button:focus-visible, .mp-dual button:focus-visible, .mp-btn:focus-visible, .mp-input:focus-visible,
.mp-sheet-scroll select:focus-visible, .photo-box:focus-visible {
  outline: 2px solid var(--primary); outline-offset: 2px; border-radius: 10px;
}
  .mp-header { background: linear-gradient(135deg,#fb923c,#ea580c); color: #fff; padding: calc(env(safe-area-inset-top) + 12px) 18px 16px; flex-shrink: 0; margin-top: calc(-1 * env(safe-area-inset-top)); }
  .mp-header.sm { padding: calc(env(safe-area-inset-top) + 12px) 18px 14px; margin-top: calc(-1 * env(safe-area-inset-top)); }
.mp-header .greet { font-size: 13px; opacity: .9; }
.mp-header .name { font-size: 20px; font-weight: 700; margin-top: 2px; }
.mp-header .role-tag { display: inline-block; background: rgba(255,255,255,.22); padding: 2px 10px; border-radius: 20px; font-size: 12px; margin-top: 8px; }
/* R783：手机端「实时已连」常驻状态点 —— 老板 2026-09-25 要求：手机端也要有类似电脑端右上角的状态指示。
   原先手机端只有 #syncBannerM 横幅，ok 态 3 秒后淡出 ⇒ 同步正常时顶部什么都看不见。
   用法：首页挂在问候行右侧（深橙底 ⇒ 半透明白胶囊 + 白字），「我的」页挂在状态卡里（浅底 ⇒ 透明底 + 深字）。
   颜色由 JS 按状态实时给（绿/橙/红/灰），这里只定形状与排版，不写死颜色。 */
.mp-sync-chip { display: inline-flex; align-items: center; gap: 5px; padding: 2px 9px; border-radius: 20px; background: rgba(255,255,255,.22); font-size: 12px; line-height: 1.6; white-space: nowrap; -webkit-tap-highlight-color: transparent; }
.mp-sync-chip .mp-sync-dot { width: 8px; height: 8px; border-radius: 50%; flex: none; display: inline-block; }
.mp-sync-chip .mp-sync-txt { color: #fff; }
/* 「我的」页状态卡内是浅色卡面 ⇒ 换回正文字色，避免白字看不见 */
.mp-card .mp-sync-chip { background: var(--surface-2); }
.mp-card .mp-sync-chip .mp-sync-txt { color: var(--text-2); }
.mp-title { font-size: var(--fs-lg); font-weight: 700; }
.mp-body { flex: 1; min-height: 0; overflow-y: auto; padding: calc(14px + env(safe-area-inset-top)) 14px 14px; -webkit-overflow-scrolling: touch; overscroll-behavior: contain; }
.mp-body::-webkit-scrollbar { display: none; }
.mp-tabbar { display: flex; background: var(--surface); border-top: 1px solid var(--border); flex-shrink: 0; padding-bottom: max(8px, env(safe-area-inset-bottom)); }
.mp-tab { flex: 1; padding: 10px 0 8px; min-height: 44px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px; color: var(--text-2); font-size: 12px; cursor: pointer; -webkit-tap-highlight-color: transparent; transition: color .2s ease; user-select: none; position: relative; }
.mp-tab svg { width: 24px; height: 24px; }
/* R409-G2：底部 Tab 红点（待办数量提示，如待审核磅单） */
.mp-tab-ico { position: relative; display: inline-flex; }
/* R579【真因修复】：底部红点"几乎看不见"的根因 —— 文件后段有一条 `.mp-tab span { overflow: hidden; text-overflow: ellipsis }`
   （本意是给页签**文字**做省略号），但红点容器 `.mp-tab-ico` 也是 <span>，被连带命中 →
   红点超出图标范围的部分**全部被裁掉**，只剩压在图标上的几个像素可见（R578 往外挪反而越挪越看不见）。
   此处显式放开：`.mp-tab .mp-tab-ico` 特异性 (0,2,0) > `.mp-tab span` (0,1,1)，稳定胜出。
   ⚠️ 排查提示：`getBoundingClientRect()` 只报布局位置、**不反映被祖先 overflow 裁掉的部分** ——
   当时实测显示"露在图外 11×10px"却肉眼看不到，就是被这个盲区骗了。 */
.mp-tab .mp-tab-ico { overflow: visible; }
/* R579：位置回到"贴着图标、但完整可见" —— 不再需要靠"往外挪"来绕开裁切（裁切已被上面那条修复）。
   相对 22px 图标：右超出 9px、上超出 8px → 红点压在图标右上角，露出的部分也不会再被裁。
   白边 2px：红点压在**橙色**（激活态图标色）上时用于分离辨识。尺寸 14px 不变。 */
.mp-tab-dot { position: absolute; top: -8px; right: -9px; min-width: 14px; height: 14px; padding: 0 4px; border-radius: 7px; background: var(--red); color: #fff; font-size: 10px; line-height: 14px; text-align: center; font-style: normal; font-weight: 700; box-shadow: 0 0 0 2px var(--surface); pointer-events: none; }
.mp-tab-dot.dot-sm { right: -6px; }
/* R410-2：顶部「磅单」切换器红点（与底部 Tab 红点同源样式，锚定在 seg 按钮内） */
.mp-seg button { position: relative; }
.mp-seg-dot { position: absolute; top: -6px; right: -8px; min-width: 15px; height: 15px; padding: 0 4px; border-radius: 8px; background: var(--red); color: #fff; font-size: 10px; line-height: 15px; text-align: center; font-style: normal; font-weight: 700; box-shadow: 0 0 0 2px var(--surface); pointer-events: none; z-index: 2; }
.mp-seg-dot.dot-sm { right: -5px; }
/* R410-3：移动端卡片本体可点（详情），按钮区仍独立可点 */
.mp-order { cursor: pointer; }
.mp-tab.active { color: var(--primary); }
.mp-tab:active { background: var(--surface-2); border-radius: 10px; transition: background .12s ease; }
.mp-card { background: var(--surface); border-radius: 13px; padding: 14px; margin-bottom: 12px; box-shadow: var(--shadow); transition: box-shadow .2s ease, transform .15s ease; }

/* ============ R1012 · 手机端发货单卡片（方案 B¹，与预览方案逐行一致）============
   三行：① 单号 + 日期 + 状态 + ⋯ ② 车号 · 货物 规格 ③ 购货单位 · 项目 · 数量
   操作收进「⋯」菜单（R1011 曾做成两个直达按钮 ⇒ 与老板看过的预览方案不一致，本次回归）。
   拉运行不再展示司机（司机默认不填写）。全部规则限定在 .mp-dlv 内 —— 电脑端零影响。
   放在 .mp-card 之后：.mp-dlv 与 .mp-card 特异性相同，靠"谁在后谁赢"覆盖 padding。 */
.mp-dlv{position:relative;padding:12px 13px}
.mp-dlv-r1{display:flex;align-items:center;gap:8px}
.mp-dlv-no{font-size:13.5px;font-weight:700;letter-spacing:-.2px;
  min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mp-dlv-r1 .dt{font-size:11.5px;color:var(--text-2);margin-left:auto;flex:none}
.mp-dlv-r1>span{flex:none}
.mp-dlv-more{border:1px solid var(--border);background:#fff;color:#475569;font-size:14px;font-weight:700;
  width:30px;height:28px;border-radius:8px;cursor:pointer;line-height:1;flex:none;padding:0;
  -webkit-tap-highlight-color:transparent}
.mp-dlv-menu{position:absolute;right:13px;top:38px;z-index:30;background:#fff;border-radius:11px;
  padding:5px;box-shadow:0 10px 30px rgba(15,23,42,.22);min-width:136px}
.mp-dlv-menu button{display:block;width:100%;text-align:left;border:none;background:transparent;
  font-size:13px;font-family:inherit;color:var(--text);padding:10px 11px;border-radius:8px;cursor:pointer;
  -webkit-tap-highlight-color:transparent}
.mp-dlv-menu button.cancel{color:#6b7280;border-top:1px solid var(--border-2);border-radius:0;
  margin-top:4px;padding-top:11px}
.mp-dlv-r2{display:flex;align-items:center;gap:5px;margin-top:6px;font-size:12.5px;color:#334155;
  overflow:hidden;white-space:nowrap}
.mp-dlv-r2 .pl{font-weight:700;flex:none}
.mp-dlv-r2 .gd{overflow:hidden;text-overflow:ellipsis;min-width:0}
.mp-dlv-r2 i{font-style:normal;color:#cbd5e1;flex:none}
.mp-dlv-r3{margin-top:4px;font-size:11.5px;color:var(--text-2);overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
.mp-dlv-r3 i{font-style:normal;color:#cbd5e1}
.mp-dlv-r3 .b{color:#0f172a;font-weight:600}
.mp-dlv-r3 .qt{color:var(--primary-dark);font-weight:700}
.mp-dlv-r3 .wd{color:#c2410c;font-weight:700}
.mp-quick { display: grid; grid-template-columns: repeat(4,1fr); gap: 6px; }
.mp-quick.q5 { grid-template-columns: repeat(5,1fr); }
.mp-quick .q { display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 8px 0; min-height: 64px; cursor: pointer; -webkit-tap-highlight-color: transparent; transition: transform .15s ease, opacity .2s ease; border-radius: 10px; }
.mp-quick .q:active { transform: scale(.95); opacity: .7; }
.mp-quick .qi { width: 46px; height: 46px; border-radius: 14px; display: flex; align-items: center; justify-content: center; }
.mp-quick .qi svg { width: 22px; height: 22px; }
.mp-quick .ql { font-size: 12px; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
.mp-text-link { display: inline-flex; align-items: center; gap: 4px; margin-top: 10px; min-height: 44px; padding: 12px 2px; background: none; border: none; color: var(--primary); font-size: 13px; font-weight: 600; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.mp-text-link svg { width: 16px; height: 16px; }
.mp-text-link:active { opacity: .7; }
.mp-stat-row { display: grid; grid-template-columns: repeat(3,1fr); gap: 10px; }
.mp-stat { background: rgba(255,255,255,.18); border-radius: 12px; padding: 12px 8px; text-align: center; color: #fff; min-width: 0; overflow: hidden; }
.mp-stat .v { font-size: clamp(16px, 4.6vw, 21px); font-weight: 800; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; line-height: 1.2; }
.mp-stat .l { font-size: 11px; opacity: .9; margin-top: 2px; }
.mp-reject-hint { display: flex; align-items: center; gap: 8px; background: var(--red-bg); color: var(--red); border-radius: 10px; padding: 9px 12px; font-size: 13px; font-weight: 600; margin-bottom: 10px; }
.mp-reject-hint svg { width: 16px; height: 16px; flex-shrink: 0; }
.mp-order { background: var(--surface); border-radius: 13px; padding: 14px; margin-bottom: 12px; box-shadow: var(--shadow); transition: box-shadow .2s ease, transform .15s ease; }
.mp-order .oh { display: flex; justify-content: space-between; align-items: flex-start; gap: 10px; margin-bottom: 10px; }
.mp-order .oh > div:first-child { min-width: 0; }
.mp-order .on { font-weight: 700; font-size: 14px; }
.mp-order .meta { font-size: 12px; color: var(--text-2); margin-top: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mp-order .row { display: flex; justify-content: space-between; gap: 12px; font-size: 13px; padding: 4px 0; }
.mp-order .row .k { color: var(--text-2); flex-shrink: 0; }
.mp-order .row > span:last-child { min-width: 0; overflow-wrap: anywhere; text-align: right; }
.mp-btn { width: 100%; height: 44px; border-radius: 11px; background: var(--primary); color: #fff; font-weight: 600; font-size: 15px; margin-top: 10px; cursor: pointer; -webkit-tap-highlight-color: transparent; transition: opacity .2s ease, transform .15s ease; border: none; }
.mp-btn:active { transform: scale(.98); opacity: .9; }
.mp-btn.ghost { background: var(--primary-light); color: var(--primary-dark); }
.mp-btn.gray { background: var(--surface-2); color: var(--text-2); }
.mp-btn:disabled { opacity: .55; pointer-events: none; }
.mp-card:active, .mp-order:active { transform: scale(.99); }
.mp-field { margin-bottom: 14px; }
.mp-field label { display: block; font-size: 13px; color: var(--text-2); margin-bottom: 6px; }
.mp-input { width: 100%; height: 46px; border: 1.5px solid var(--border); border-radius: 11px; padding: 0 14px; background: var(--surface); outline: none; font-size: 16px; /* R406:移动端 ≥16px,防 iOS 聚焦整页缩放 */ }
.mp-input:focus { border-color: var(--primary); }
/* R66 车号搜索下拉(替代胶囊：车辆多时不臃肿，默认带出上次车) */
.veh-combo { position: relative; }
.veh-combo .mp-input[readonly] { background: var(--surface); cursor: pointer; }
.veh-combo .veh-pop { position: absolute; left: 0; right: 0; top: calc(100% + 4px); z-index: 60; background: var(--surface); border: 1.5px solid var(--border); border-radius: 12px; box-shadow: 0 8px 24px rgba(0,0,0,.12); padding: 8px; max-height: 264px; display: flex; flex-direction: column; overflow: hidden; }
.veh-combo .veh-pop-search { height: 40px; margin-bottom: 6px; }
.veh-combo .veh-pop-list { overflow-y: auto; -webkit-overflow-scrolling: touch; flex: 1; }
.veh-combo .veh-pop-item { padding: 11px 12px; border-radius: 9px; font-weight: 600; cursor: pointer; }
.veh-combo .veh-pop-item:hover, .veh-combo .veh-pop-item:active { background: var(--surface-2); }
.veh-combo .veh-pop-item.active { background: var(--primary); color: #fff; }
.veh-combo .veh-pop-item.pinned { color: var(--primary-dark); }
.veh-combo .veh-pop-item .veh-pop-mine { margin-left: 8px; padding: 1px 6px; border-radius: 6px; font-size: 11px; font-weight: 600; background: var(--surface-2); color: var(--primary-dark); }
.veh-combo .veh-pop-item.active .veh-pop-mine { background: rgba(255,255,255,.22); color: #fff; }
.veh-combo .veh-pop-empty { padding: 14px 12px; color: var(--text-3); font-size: 13px; text-align: center; }
.veh-combo .veh-pop-manual { margin-top: 6px; }
.veh-combo .veh-pop-other { margin-top: 6px; width: 100%; padding: 10px; border: none; background: transparent; color: var(--primary); font-weight: 600; cursor: pointer; border-top: 1px solid var(--border); }
.mp-seg { display: flex; gap: 8px; }
.mp-seg button { flex: 1; height: var(--btn-h, 44px); border-radius: 11px; border: 1.5px solid var(--border); background: var(--surface); color: var(--text-2); font-weight: 500; font-size: 13px; }
.mp-seg button.active { border-color: var(--primary); background: var(--primary-light); color: var(--primary-dark); font-weight: 600; }
.mp-seg button:disabled { opacity: .45; }
/* R407-E2:待审核态下业务模式筛选失效 → 置灰禁用,避免"选了模式却显示全部模式待审"的隐性不一致 */
.mp-seg.disabled { opacity: .5; pointer-events: none; }
.mp-dual { display:flex; gap:10px; margin-bottom: 12px; }
.mp-dual button { flex:1; padding: 14px 8px; border-radius: 12px; border: 1.5px solid var(--border); background: var(--surface); position: relative; }
.mp-dual button .ico { width: 38px; height: 38px; border-radius: 11px; margin: 0 auto 6px; display:flex; align-items:center; justify-content:center; }
.mp-dual button.active { border-color: var(--primary); background: var(--primary-light); }
.mp-dual button:disabled { opacity: .5; }
.mp-dual .lbl { font-size: 13px; font-weight: 600; }
.mp-dual .st { font-size: 11px; margin-top: 4px; }
.mp-me-head { display: flex; align-items: center; gap: 14px; }
.mp-me-head .av { width: 56px; height: 56px; border-radius: 50%; background: rgba(255,255,255,.25); display:flex; align-items:center; justify-content:center; font-size:22px; font-weight:700; color:#fff; }
.mp-menu-item { display: flex; align-items: center; gap: 12px; padding: 15px 14px; border-bottom: 1px solid var(--border-2); font-size: 14px; cursor: pointer; -webkit-tap-highlight-color: transparent; transition: background .2s ease; }
.mp-menu-item:active { background: var(--surface-2); }
.mp-menu-item:last-child { border-bottom: none; }
.mp-menu-item svg { width: 20px; height: 20px; color: var(--primary); }
.mp-menu-item .arrow { margin-left: auto; color: var(--text-3); }

/* R701 · 手机端「我的」页改「图标宫格」（老板 2026-09-19 16:32 选定方案 C）。
   取代 R700 的分组折叠 —— 老板真机反馈「折叠之后只有一个圆点，只有几个字，一点都不直观也不太好看」；
   宫格把每个功能连同图标一起摆出来，**不折叠、一次都不用点**，且天然好看（彩色圆角图标块）。
   tile 实际高约 63px（38 图标 + 5 间距 + 两行 11px 文字），远超 44px 最小可点尺寸。 */
/* R702 · 方案 A「iOS 卡片风」（老板 2026-09-19 16:55 选定）—— 三处改动，都针对老板本轮原话：
   ① **一行放四个**（原 3 列）：UI 惯例 —— 390pt 屏 3 列每格约 110pt，低于 100pt 就该换布局；
      最长项名 6 字 ≈66px < 4 列单格 ≈83px ⇒ 装得下，且 21 项由 **8 行压到 7 行**。
   ② **浅灰底 + 白卡片**：老板「他们的背景是纯白色，是不是要加一点那种浅色能看出来区别」——
      页面底 `.mp` 本就是 `--bg`(#f4f5f7) 浅灰，加白卡后**卡片自带边界**（微信「我」页 `#f0eff5`+白卡、
      iOS「设置」同款）。卡片之间靠底色差 + `--shadow` 分层，就是"能看出区别"的来源。
   ③ **标题与卡片左边缘对齐**（去掉原 `margin-left: 2px`）：老板「看着很别扭」＝格式塔邻近性原则 ——
      原组标题距图标 8px、图标距文字 5px，两个距离太近 ⇒ 标题被读成"另一个图标的说明文字"，
      像在别人家箱子上贴了个标签；且标题左对齐、图标居中 ⇒ 全页**没有任何对齐线**。
      现在标题贴在卡片左上、与卡边同一条竖线，卡片又把同组内容"框"在一起 ⇒ 归属不再有歧义。
   tile 的 :active 由 `--surface-2`(#f8fafc) 改 `--bg`(#f4f5f7)：前者在白卡片上按下去几乎看不见反馈。 */
.mp-me-gt { font-size: 12px; font-weight: 700; color: var(--text-2); margin: 16px 0 7px; }
.mp-me-card { background: var(--surface); border-radius: 14px; padding: 10px 6px; box-shadow: var(--shadow); }
.mp-me-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px 2px; }
.mp-me-tile { display: flex; flex-direction: column; align-items: center; gap: 5px; padding: 4px 2px; border-radius: 10px; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.mp-me-tile:active { background: var(--bg); }
.mp-me-tile-ic { width: 38px; height: 38px; border-radius: 12px; display: flex; align-items: center; justify-content: center; flex: none; }
.mp-me-tile-ic svg { width: 19px; height: 19px; }
.mp-me-tile-lb { font-size: 11px; line-height: 1.25; text-align: center; color: var(--text); }

/* 移动端内容密集型页面(统计/往来账/司机工资/磅单):卡片化,无横向表格 */
.mp-tab span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
.mp-subbar { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }
/* R574：返回重设计 —— 去掉灰底药丸，改为【纯箭头】（微信 / 支付宝 / 美团设置页同形态）。
   原灰底块是"按钮"语义，与同排的页面标题抢视线，且左边缘被 padding 顶开、标题起点偏右。
   点击区仍保证 40×40（触控标准），只把视觉"退后"，让标题成为唯一焦点。
   改这一条，全项目 11 个下钻页自动统一（含 contracts 的单行头部）。 */
.mp-back { min-height: 40px; min-width: 40px; padding: 0 6px; margin: 0 0 0 -6px; background: none; border: none; color: var(--text); border-radius: 10px; font-size: 13px; font-weight: 600; display: inline-flex; align-items: center; justify-content: center; gap: 4px; cursor: pointer; -webkit-tap-highlight-color: transparent; transition: opacity .12s ease, background .12s ease; flex-shrink: 0; }

.mp-back:active { opacity: .5; background: none; }

.mp-back svg { width: 22px; height: 22px; }

.mp-dash-kpis { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.mp-dash-kpi { background: var(--surface-2); border-radius: 10px; padding: 10px 6px; text-align: center; min-width: 0; }
.mp-dash-kpi .v { font-size: clamp(13px, 3.6vw, 16px); font-weight: 800; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; line-height: 1.2; }
.mp-dash-kpi .l { font-size: 11px; color: var(--text-2); margin-top: 2px; }
.mp-prog-row { margin-bottom: 12px; }
.mp-prog-row:last-child { margin-bottom: 0; }
.mp-kv { display: flex; justify-content: space-between; gap: 12px; font-size: 13px; padding: 4px 0; }
.mp-kv .k { color: var(--text-2); flex-shrink: 0; }
.mp-kv > span:last-child { min-width: 0; overflow-wrap: anywhere; text-align: right; }
.mp-card-warn { border-color: var(--red); background: var(--red-bg); }
.mp-card-orange { border-color: var(--orange); background: var(--primary-100); }
.mp-drill-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.mp-drill { display: flex; align-items: center; gap: 10px; background: var(--surface-2); border-radius: 11px; padding: 12px; cursor: pointer; -webkit-tap-highlight-color: transparent; transition: transform .15s ease, opacity .2s ease; }
.mp-drill:active { transform: scale(.97); opacity: .8; }
.mp-drill .di { width: 40px; height: 40px; border-radius: 11px; display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.mp-drill .di svg { width: 20px; height: 20px; }
.mp-drill > div:last-child { min-width: 0; }
@media (max-width: 360px) {
  .mp-dash-kpis { grid-template-columns: repeat(2, 1fr); }
}

/* 响应式:真实移动端
   R422：补 (max-height:520px) 条件。仅按宽度判定时，手机横屏 CSS 宽常达 780~900px（>820），
   会被误判为桌面 → 掉进「请用手机」引导页。横屏时按高度兜底，仍走移动端壳。
   两条规则必须同步加条件（且互斥）：移动壳 = 窄屏 OR 矮屏；桌面 = 宽屏 AND 高屏。 */
@media (max-width: 820px), (max-height: 520px) {
  .desktop-only { display: none !important; }
  .mobile-only { display: block; }
  #appDesktop { display: none !important; }
  #appMobile.active { display: block; height: 100vh; height: 100dvh; }
}
@media (min-width: 821px) and (min-height: 521px) {
  #appMobile { display: none !important; }
}

/* 工具类 */
.flex { display: flex; } .items-center { align-items: center; } .items-end { align-items: flex-end; } .gap-4 { gap: 4px; } .gap-8 { gap: 8px; } .gap-12 { gap: 12px; }
.mt-4 { margin-top: 4px; } .mt-6 { margin-top: 6px; } .mt-8 { margin-top: 8px; } .mt-10 { margin-top: 10px; } .mt-12 { margin-top: var(--sp-3); } .mt-16 { margin-top: 16px; }
.mb-8 { margin-bottom: 8px; } .mb-10 { margin-bottom: 10px; } .mb-12 { margin-bottom: var(--sp-3); } .mb-16 { margin-bottom: 16px; }
.text-2 { color: var(--text-2); } .text-sm { font-size: 12px; } .text-right { text-align: right; }
.hidden { display: none !important; }
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.tpl-thumb { width: 200px; height: 140px; flex-shrink: 0; overflow: hidden; border: 1px solid var(--border, #e2e8f0); border-radius: 8px; background: #fff; position: relative; }
@media (max-width: 680px) { .tpl-thumb { width: 130px; height: 96px; } }
/* R356:回退 R352 缩略图比例自适应改造。R352→R356 五版迭代未解决（mm 单位 + Windows DPI + zoom + transform 组合 bug），
   退回 R347 等效（固定 200×140 框 + scale(0.16)）。缩略图与各模板真实比例不再按真实比例显示，
   但保证显示完整不报错。R342 修复（列表尺寸从 panel 取值）保留生效。 */
/* R245-P1 缩略图懒渲染占位 */
.tpl-thumb-ph { width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; font-size: 12px; color: var(--text-3, #94a3b8); background: repeating-linear-gradient(45deg, #fafafa, #fafafa 8px, #f2f4f7 8px, #f2f4f7 16px); }
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
@media (max-width: 900px) { .grid-3 { grid-template-columns: 1fr; } }
.link { color: var(--primary); font-weight: 600; cursor: pointer; }
.link:hover { text-decoration: underline; }

/* ============ UI 精修补充：工具类 / 间距令牌（4px 基准） ============ */
:root {
  --sp-1: 4px;  --sp-2: 8px;  --sp-3: 12px; --sp-4: 16px;
  --sp-5: 20px; --sp-6: 24px; --sp-8: 32px; --sp-10: 40px; --sp-12: 48px;
}
.text-center { text-align: center; }
.text-purple { color: #7c3aed; }
.text-nowrap { white-space: nowrap; }
.muted-3 { color: var(--text-3); }
/* 报表预览表格（去内联硬编码，统一令牌） */
.rpt-tbl { border-collapse: collapse; width: 100%; }
.rpt-tbl th, .rpt-tbl td { border: 1px solid var(--border); padding: 6px 10px; }
.rpt-tbl th { background: var(--surface-2); font-weight: 600; text-align: left; }
.rpt-tbl .num { text-align: right; font-variant-numeric: tabular-nums; }
.rpt-tbl .total-row td { background: var(--surface-2); font-weight: 700; }
.rpt-note { margin-top: 14px; color: var(--text-2); font-size: 12px; line-height: 1.6; }

/* ============ 移动端弹层滚动回弹 ============ */
.mp-sheet { overscroll-behavior: contain; }
.mp-sheet-panel { overscroll-behavior: contain; }
.mp-sheet-scroll { overscroll-behavior: contain; -webkit-overflow-scrolling: touch; }

/* ============ R65 磅单管理：整行/卡片点击可开详情（鼠标手型 + 悬停高亮） ============ */
.tbl tbody tr.bill-row { cursor: pointer; }
.tbl tbody tr.bill-row:hover { background: var(--surface-2); }
.dual-bill.click-card { cursor: pointer; }
.dual-bill.click-card:hover { background: var(--surface-2); }

/* ============ 动效偏好（尊重 prefers-reduced-motion） ============ */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; scroll-behavior: auto !important; }
}

/* ============ 暗色模式(系统级,仅 prefers-color-scheme: dark 生效,不影响 PC 浅色默认) ============ */
@media (prefers-color-scheme: dark) {
  :root {
    --bg: #0f172a;
    --surface: #1e293b;
    --surface-2: #334155;
    --border: #334155;
    --border-2: #2a3a4d;
    --text: #e2e8f0;
    --text-2: #aeb8c7;
    --text-3: #8a96a8;
    --primary-light: #2a1c0e;
    --primary-100: #3a2410;
    --primary-200: #4a3015;
    --shadow: 0 1px 3px rgba(0,0,0,.4), 0 1px 2px rgba(0,0,0,.3);
    --shadow-md: 0 4px 16px rgba(0,0,0,.5);
    --shadow-lg: 0 12px 40px rgba(0,0,0,.6);
    /* R532k：暗色下终端面板加深，与模态背景形成层次（浅色模式的 #0b1020 在暗色下几乎糊在一起） */
    --term-bg: #060b17;
    --term-fg: #93c5fd;
    --term-border: #1e293b;
  }
  /* 暗色下强化卡片分隔,避免与背景糊在一起 */
  .card, .stat, .mp-card, .mp-order { border-color: var(--border); }
  .mp-btn.ghost { background: var(--surface-2); }
  .modal, .modal-head, .modal-body { background: var(--surface); color: var(--text); }
  .modal-head { border-color: var(--border); }
  .tbl th { background: var(--surface-2); }
  .toast { background: #0f172a; border: 1px solid var(--border); }
  .mp-card-warn, .mp-reject-hint { background: rgba(220,38,38,0.15); border-color: var(--red); }
  .mp-card-warn .mp-kv .k, .mp-reject-hint { color: var(--red); }
  /* 双磅单组：暗色下改用深色表面，避免浅蓝卡片漂浮 */
  .dual-group { background: linear-gradient(135deg, #1e293b, #0f172a); border-color: var(--border); }
  .dual-bill { background: var(--surface); }
  .dual-bill.placeholder { border-color: var(--border-2); background: var(--surface-2); color: var(--text-3); }
  .photo-thumb { background: var(--surface-2); }
}

/* R91#6:桌面列表分页控件 */
.pager { display:flex; align-items:center; gap:8px; flex-wrap:wrap; margin-top:12px; padding-top:10px; border-top:1px solid var(--border); font-size:13px; color:var(--text-2); }
.pg-info { margin-right:auto; }
.pg-btn { min-width:32px; height:32px; padding:0 8px; border-radius:8px; border:1px solid var(--border); background:var(--surface); color:var(--text); cursor:pointer; font-size:13px; transition:background .15s,border-color .15s; }
.pg-btn:hover:not(:disabled) { border-color:var(--primary); color:var(--primary); }
.pg-btn.active { background:var(--primary); border-color:var(--primary); color:#fff; }
.pg-btn:disabled { opacity:.4; cursor:not-allowed; }
.pg-ell { color:var(--text-3); padding:0 2px; }

/* R100#U3:长操作加载遮罩 */
.busy-overlay{position:fixed;inset:0;background:rgba(0,0,0,.45);display:flex;flex-direction:column;align-items:center;justify-content:center;z-index:9999;color:#fff}
.busy-spin{width:42px;height:42px;border:4px solid rgba(255,255,255,.3);border-top-color:#fff;border-radius:50%;animation:busyspin .8s linear infinite}
.busy-text{margin-top:14px;font-size:14px}
@keyframes busyspin{to{transform:rotate(360deg)}}

/* ============ R110① 全局搜索 ============ */
.gs-wrap{position:relative;display:flex;align-items:center}
.topbar-search{height:34px;border:1px solid var(--border);border-radius:8px;padding:0 12px;font-size:13px;width:240px;max-width:38vw;background:var(--surface);color:var(--text);outline:none}
.topbar-search:focus{border-color:var(--primary);box-shadow:0 0 0 3px rgba(37,99,235,.15)}
.gs-results{position:absolute;top:42px;left:0;min-width:360px;max-width:90vw;max-height:62vh;overflow:auto;background:var(--surface);border:1px solid var(--border);border-radius:10px;box-shadow:0 8px 24px rgba(0,0,0,.14);z-index:60;padding:6px}
.gs-results .gs-cat{font-size:11px;color:var(--text-2);padding:8px 10px 2px}
.gs-results .gs-item{display:flex;justify-content:space-between;gap:10px;padding:8px 10px;border-radius:8px;cursor:pointer}
.gs-results .gs-item:hover{background:var(--surface-2)}
.gs-results .gs-label{font-size:13px;color:var(--text);font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.gs-results .gs-sub{font-size:12px;color:var(--text-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:50%}
.gs-results .gs-empty{padding:14px;text-align:center;color:var(--text-2);font-size:13px}

/* ============ R110② 批量操作 ============ */
.batch-bar{display:flex;gap:8px;align-items:center;flex-wrap:wrap;padding:8px 10px;background:var(--surface-2);border-radius:8px;margin-bottom:10px}
.batch-bar .text-sm{color:var(--text-2)}
.bill-sel{position:absolute;top:8px;right:8px;z-index:2}
.bill-sel input{width:16px;height:16px;cursor:pointer}

/* ============ R161 称重仪表状态栏 ============ */
/* ============ R338 称重仪表栏 v7：单行紧凑三段式（徽章 + 数字块 + 齿轮菜单） ============ */
.scale-bar{display:flex;align-items:center;gap:8px;padding:0 16px;margin-bottom:12px;height:64px;box-sizing:border-box;background:var(--surface);border:1px solid var(--border);border-radius:12px;font-size:13px}
.scale-bar .scale-body{display:flex;align-items:center;flex:1;min-width:0;gap:24px}
.scale-bar.collapsed .scale-body{display:none}
/* 左段：连接状态胶囊徽章 */
.scale-badge{display:inline-flex;align-items:center;gap:8px;padding:5px 14px;border-radius:999px;flex:0 0 auto;font-weight:600;font-size:13px;line-height:1}
.scale-badge.badge-green{background:#dcfce7;color:#15803d}
.scale-badge.badge-yellow{background:#fef9c3;color:#a16207}
.scale-badge.badge-red{background:#fee2e2;color:#b91c1c}
.scale-badge.badge-alarm{background:#fee2e2;color:#dc2626}
.scale-dot{display:inline-block;width:8px;height:8px;border-radius:50%;background:#ef4444;flex:0 0 auto}
/* 中段：数字块（等宽 tabular-nums，数字变宽只增宽不变形；flex:0 0 auto 防收缩） */
.scale-mid{display:inline-flex;align-items:center;gap:10px;flex:1 1 auto;min-width:0;white-space:nowrap}
.scale-mid-label{color:var(--text-2);font-size:12px;flex:0 0 auto}
.scale-mid b{font-family:ui-monospace,Menlo,Consolas,monospace;font-variant-numeric:tabular-nums;font-size:34px;font-weight:800;line-height:1;flex:0 0 auto;transition:color .15s}
.scale-mid .s-weight-green{color:#16a34a}
.scale-mid .s-weight-orange{color:#f59e0b}
.scale-mid .s-weight-red{color:#ef4444}
.scale-mid .s-weight-idle{color:var(--text-2);opacity:.35}
.scale-unit{color:#64748b;font-size:14px;flex:0 0 auto}
.scale-state{flex:0 1 auto;min-width:0;font-size:12px;font-weight:600;white-space:nowrap}
.scale-state.st-stable{color:#16a34a}
.scale-state.st-moving{color:#f59e0b}
.scale-state.st-idle{color:var(--text-2);opacity:.5}
/* 右段：操作区（断开/连接 + 齿轮菜单） */
.scale-actions{display:inline-flex;align-items:center;gap:8px;flex:0 0 auto;margin-left:auto}
.gear-wrap{position:relative;flex:0 0 auto}
.gear-btn{width:36px;height:36px;border-radius:6px;border:1px solid var(--border);background:var(--surface);color:var(--text-1);cursor:pointer;font-size:15px;display:inline-flex;align-items:center;justify-content:center;padding:0}
.gear-btn:hover{background:var(--surface-2)}
.gear-menu{position:absolute;right:0;top:calc(100% + 6px);min-width:150px;background:var(--surface);border:1px solid var(--border);border-radius:8px;box-shadow:0 4px 12px rgba(0,0,0,.12);padding:6px;z-index:60;display:flex;flex-direction:column}
.gear-menu button{border:none;background:none;text-align:left;padding:8px 12px;border-radius:6px;cursor:pointer;font-size:13px;color:var(--text-1);display:block;width:100%}
.gear-menu button:hover{background:var(--surface-2)}
.gear-debug{margin-top:6px;padding:6px 8px 2px;border-top:1px solid var(--border);font-size:11px;color:var(--text-2);line-height:1.6}
.scale-alarm-btn{flex:0 0 auto}
.scale-bar .btn{margin:0}
.scale-badge .blink{animation:scaleBlink .8s steps(1,end) infinite}
.scale-toggle{background:none;border:none;cursor:pointer;color:var(--text-2);font-size:13px;padding:2px 8px;display:inline-flex;align-items:center;gap:4px;border-radius:6px;flex:0 0 auto}
.scale-toggle:hover{color:var(--primary);background:rgba(0,0,0,.05)}
.scale-toggle-label{font-weight:600}

/* ============ R532k 仪表设置弹窗：四段折叠分组 ============
   背景：原弹窗 22 个字段平铺 ≈988px，磅房 1366×768 屏下 .modal-body 可视仅 ~561px，
   超出 76% 必须滚动且无分组。本样式提供「段落头 + 可折叠体」两件套。 */
.sc-note {
  background: var(--primary-light); border: 1px solid var(--primary-100);
  border-left: 3px solid var(--primary); border-radius: 8px;
  padding: 10px 12px; font-size: 12.5px; color: var(--text); line-height: 1.7; margin-bottom: 12px;
}
.sc-cloud {
  display: flex; align-items: center; gap: 8px; cursor: pointer;
  padding: 9px 12px; margin-bottom: 12px; border: 1px solid var(--border);
  border-radius: 8px; background: var(--surface-2); font-size: 13px; color: var(--text);
  -webkit-tap-highlight-color: transparent;
}
.sc-cloud input { width: 16px; height: 16px; flex: 0 0 auto; accent-color: var(--primary); cursor: pointer; }
.sc-sec { border: 1px solid var(--border); border-radius: 8px; margin-bottom: 10px; overflow: hidden; background: var(--surface); }
.sc-sec-hd {
  display: flex; align-items: center; gap: 8px; width: 100%; text-align: left;
  padding: 10px 12px; background: var(--surface-2); border: none; cursor: pointer;
  font-size: 13px; font-family: inherit; color: var(--text);
}
.sc-sec-hd:hover { background: var(--primary-light); }
.sc-sec.open .sc-sec-hd { border-bottom: 1px solid var(--border); }
.sc-sec-arw { flex: 0 0 auto; color: var(--text-2); font-size: 11px; width: 12px; }
.sc-sec-tt { flex: 0 0 auto; font-weight: 600; }
.sc-sec-hint { flex: 1 1 auto; text-align: right; font-size: 11.5px; color: var(--text-2); font-weight: 400; }
.sc-sec-bd { padding: 12px; }
/* 折叠体内层 form-grid 去掉重复边距，避免两层 padding 叠加 */
.sc-sec-bd .form-grid { margin: 0; }
@media (max-width: 560px) {
  .sc-sec-hint { display: none; }
  .sc-note { font-size: 12px; }
}
/* R532k 通讯调试：终端面板。
   原实现把 background:#0b1020;color:#7dd3fc 硬编码在 HTML 内联 style 上——
   全项目唯一一处硬编码深色底，导致体统暗色模式(html.dark)下更黑、
   高对比模式(body.hc)下深底浅字对比崩坏。现抽为变量，三模式各自适配。 */
.sd-term {
  background: var(--term-bg); color: var(--term-fg);
  border: 1px solid var(--term-border);
  padding: 10px; border-radius: 8px;
  white-space: pre-wrap; word-break: break-all;
  max-height: 180px; overflow: auto; font-size: 12px; line-height: 1.6;
}
.sd-out {
  background: var(--surface-2); color: var(--text);
  border: 1px solid var(--border);
  padding: 10px; border-radius: 8px;
  white-space: pre-wrap; word-break: break-all;
  max-height: 200px; overflow: auto;
}
/* R201 称重仪表文字状态化：折叠时通过文字颜色/闪烁直接识别仪表状态 */
.scale-toggle-label.s-label-red{color:#ef4444;animation:scaleBlink 1s steps(1,end) infinite}
.scale-toggle-label.s-label-green{color:#22c55e}
.scale-toggle-label.s-label-yellow{color:#eab308;animation:scaleBlink 1s steps(1,end) infinite}
@keyframes scaleBlink{0%,100%{opacity:1}50%{opacity:.2}}
/* R223: 非"实时已连"状态整体强闪（分色：致命红/过渡黄；覆盖 ERROR/未连接/称重异常/连接中） */
@keyframes sbAlarmRed{0%,100%{background:var(--surface);box-shadow:0 0 0 0 rgba(239,68,68,0)}50%{background:#fee2e2;box-shadow:0 0 0 3px rgba(239,68,68,.65)}}
@keyframes sbAlarmYellow{0%,100%{background:var(--surface);box-shadow:0 0 0 0 rgba(234,179,8,0)}50%{background:#fef9c3;box-shadow:0 0 0 3px rgba(234,179,8,.6)}}
@keyframes sbDotBlink{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.35;transform:scale(.6)}}
.scale-bar.alarm-red{animation:sbAlarmRed .8s ease-in-out infinite;border-color:#ef4444}
.scale-bar.alarm-yellow{animation:sbAlarmYellow .8s ease-in-out infinite;border-color:#eab308}
.scale-bar.alarm-red-static{background:#fee2e2;border-color:#ef4444} /* R224:非磅房角色只标红不闪 */
.scale-bar.alarm-yellow-static{background:#fef9c3;border-color:#eab308}
.scale-dot.blink{animation:sbDotBlink .8s ease-in-out infinite}
.scale-status.blink{animation:scaleBlink .8s steps(1,end) infinite}

/* ============ R202 同步状态横幅（方案A：顶部状态条，PC/手机通用） ============ */
/* 同步中/异常时在页面顶部显示一条状态条，正常态隐藏；原右上角小圆点保留为常驻静默态 */
/* R532j:改 position:fixed 真吸顶——原 sticky 只贴在 .main 容器内,用户滚到页面中段横幅会跟着滚走,
   导致"断线提示不够明显、用户继续在坏连接上录数据"。fixed 后全视口常驻。
   注:仅异常档(error/local)使用 fixed 常驻;ok/syncing 档仍走 sticky 以免遮挡内容。 */
.sync-banner{display:none;position:sticky;top:0;z-index:40;align-items:center;justify-content:center;gap:8px;
  font-size:13px;font-weight:600;color:#fff;padding:7px 14px;text-align:center;cursor:pointer;
  box-shadow:0 1px 4px rgba(0,0,0,.12)}
.sync-banner.show{display:flex}
.sync-banner.syncing,.sync-banner.warning{background:#f59e0b}
.sync-banner.error{background:var(--red)}
.sync-banner.ok{background:var(--green)}
.sync-banner .sync-spin{width:12px;height:12px;border:2px solid rgba(255,255,255,.45);border-top-color:#fff;border-radius:50%;animation:syncSpin .7s linear infinite;flex:0 0 auto}
@keyframes syncSpin{to{transform:rotate(360deg)}}
/* R532j:第2档(中)+第3档(重)强化——异常横幅改真吸顶常驻,图标放大,不被滚动带走 */
.sync-banner.tier2,.sync-banner.tier3{position:fixed;top:0;left:0;right:0;z-index:60;
  font-size:14px;font-weight:700;letter-spacing:.2px}
.sync-banner.tier2{padding:10px 14px;box-shadow:0 3px 14px rgba(0,0,0,.28)}
.sync-banner.tier3{padding:11px 14px;box-shadow:0 4px 18px rgba(0,0,0,.34)}
.sync-banner.tier2 .sb-ico,.sync-banner.tier3 .sb-ico{font-size:19px}
.sync-banner.tier3 .sb-main{font-size:15px}
/* 真吸顶后需给正文让出顶部空间——由 JS 在 .app 上挂 has-sync-fixed 类控制 */
.app.has-sync-fixed .topbar{padding-top:0}
.app.has-sync-fixed .content{padding-top:calc(24px + var(--sync-fixed-h, 0px))}
/* ============ R533：SSL 证书到期横幅 ============
   仅管理员、剩余 ≤30 天显示。四档配色：30 天琥珀 / 15 天橙 / 7 天与过期红。
   与 .sync-banner 并列在内容区顶部；不采用 fixed 档位，避免与同步横幅互相遮挡。 */
.cert-banner{display:none;align-items:center;justify-content:center;gap:8px;
  font-size:13px;font-weight:500;color:#fff;padding:8px 14px;line-height:1.5;text-align:center}
.cert-banner.show{display:flex}
.cert-banner.lv-warn{background:#BA7517}
.cert-banner.lv-urgent{background:#C2410C}
.cert-banner.lv-critical,.cert-banner.lv-expired{background:#A32D2D}
.cert-banner .cb-ico{display:inline-flex;align-items:center;flex:0 0 auto}
.cert-banner .cb-ico svg{width:15px;height:15px}
.cert-banner .cb-main{min-width:0}
.cert-banner .cb-btn{flex:0 0 auto;background:rgba(255,255,255,.18);color:#fff;border:1px solid rgba(255,255,255,.5);
  border-radius:6px;padding:4px 12px;font-size:12px;font-weight:600;cursor:pointer;min-height:28px}
.cert-banner .cb-btn:active{background:rgba(255,255,255,.32)}
@media (max-width:767px){
  .cert-banner{font-size:12px;padding:7px 10px;gap:6px;align-items:flex-start}
  .cert-banner .cb-main{text-align:left;line-height:1.45}
  .cert-banner .cb-btn{min-height:32px;padding:6px 10px}
}

/* ============ R213 同步状态分级：失败态醒目化 + 离线灰档 ============ */
/* 严格口径：watch 断开(warning)并入红色失败态；local 独立"离线"档——R222 由灰底小字升级为橙色醒目横幅(纵向+按钮),明确告知数据仅存本机、需重新登录 */
.sync-banner.local{background:#f59e0b;flex-direction:column;gap:3px;padding:9px 14px}
/* 失败态：两行 + 自救按钮；脉冲仅播放 8 次(约 9 秒)后自动转静态红条——既醒目又不会长期闪烁致烦 */
.sync-banner.error{background:var(--red);flex-direction:column;gap:3px;padding:9px 14px;animation:syncPulse 1.15s ease-in-out 8}
@keyframes syncPulse{0%,100%{filter:brightness(1)}50%{filter:brightness(1.45)}}
.sync-banner .sb-main{display:flex;align-items:center;justify-content:center;gap:6px;font-size:13.5px;font-weight:700;line-height:1.35}
.sync-banner .sb-ico{font-size:15px;line-height:1;flex:0 0 auto}
.sync-banner .sb-sub{font-size:11.5px;font-weight:500;opacity:.92;line-height:1.35}
.sync-banner .sb-acts{display:flex;gap:8px;margin-top:3px}
.sync-banner .sb-btn{border:1px solid rgba(255,255,255,.72);background:rgba(255,255,255,.16);color:#fff;font-size:12.5px;font-weight:600;padding:6px 14px;border-radius:9px;cursor:pointer;line-height:1.5;min-height:32px;font-family:inherit;touch-action:manipulation}
.sync-banner .sb-btn-ghost{background:transparent;font-weight:700}
.sync-banner .sb-btn:hover{background:rgba(255,255,255,.32)}
.sync-banner .sb-btn:active{transform:translateY(1px)}
@media (prefers-reduced-motion:reduce){.sync-banner.error{animation:none}.scale-bar.alarm-red,.scale-bar.alarm-yellow,.scale-dot.blink,.scale-status.blink,.scale-badge .blink{animation:none}} /* 无障碍:系统开启"减少动态效果"时不闪烁 */
.scale-bar .scale-body{display:flex;align-items:center;flex:1;min-width:0;gap:24px} /* R338:三段式布局（左徽章/中数字块/右操作） */
.scale-bar.collapsed .scale-body{display:none}

/* R186#5:模式C 主从列表+预览(替代低密度的卡片组) */
.c-md{display:flex;gap:14px;align-items:flex-start}
.c-list{flex:0 0 320px;max-height:64vh;overflow:auto;border:1px solid var(--border);border-radius:12px;background:var(--surface)}
.c-row{padding:10px 12px;border-bottom:1px solid var(--border);cursor:pointer;transition:background .12s}
.c-row:last-child{border-bottom:none}
.c-row:hover{background:var(--surface-2)}
.c-row.active{background:var(--primary-light);border-left:3px solid var(--primary)}
.c-row-top{display:flex;justify-content:space-between;align-items:center;gap:8px}
.c-row-meta{margin-top:3px;color:var(--text-2);font-size:12px;line-height:1.5}
.c-preview{flex:1;min-width:0}
@media (max-width:720px){.c-md{flex-direction:column}.c-list{flex:1 1 auto;width:100%;max-height:none}}

/* ============ U4 高对比模式（磅房强光环境）============
   开关：顶栏「高对比」按钮 → body.hc，偏好存 localStorage(sh_hc)。
   实现方式：仅覆盖设计令牌 + 少量描边/字重，不改任何布局尺寸，可随时关闭回到默认皮肤。 */
body.hc {
  --text: #000000;
  --text-2: #263238;
  --text-3: #37474f;
  --border: #94a3b8;
  --border-2: #94a3b8;
  --bg: #ffffff;
  --surface: #ffffff;
  --surface-2: #eef2f7;
  --green: #0f7a35;
  --green-bg: #c8f2d6;
  --yellow: #8a4b00;
  --yellow-bg: #ffe6b3;
  --red: #b3160f;
  --red-bg: #ffd6d3;
  --blue: #123fbe;
  --blue-bg: #cfe0ff;
  --primary-dark: #b4430a;
  --shadow: 0 0 0 1px #94a3b8;
  --shadow-md: 0 0 0 1px #94a3b8;
}
body.hc .card,
body.hc .tbl th,
body.hc .tbl td { border-color: #94a3b8; }
body.hc .tbl th { background: #e2e8f0; color: #000; font-weight: 800; }
body.hc .text-2, body.hc .text-3 { font-weight: 600; }
body.hc .btn { border-width: 2px; font-weight: 700; }
body.hc .badge, body.hc .tag { font-weight: 700; border: 1px solid currentColor; }
body.hc .scale-mid .s-weight-green { color: #0f7a35; }
body.hc .scale-mid .s-weight-orange { color: #8a4b00; }
body.hc .scale-mid .s-weight-red { color: #b3160f; }
body.hc .scale-mid .s-weight-idle { color: #263238; font-weight: 700; }
body.hc .topbar-btn.hc-on { background: #000; color: #fff; }
/* R532k：高对比模式终端面板——强光环境下深底浅字对比不足，改纯白底黑字加粗描边 */
body.hc { --term-bg: #ffffff; --term-fg: #000000; --term-border: #000000; }
body.hc .sd-term { font-weight: 700; border-width: 2px; }

/* R318:打印预览灰底画布——白纸在浅灰背景上自然呈现纸张尺寸（参照 Word/Excel 打印预览），替代原黑色参考框。
   仅作用于打印预览弹窗（含 .pa-preview-wrap 的 modal）；模板缩略图/其他弹窗不受影响。 */
.modal-body:has(.pa-preview-wrap) { background: #e2e8f0; }
.modal-body:has(.pa-preview-wrap) .hp-print { background: transparent; border: none; }
.modal-body:has(.pa-preview-wrap) [class*="hiprint-printPaper"] { border: 1px solid #e5e7eb; background: #fff; }
/* 设计器轻量预览纸张参考框统一浅灰（源头 border 已改，此处兜底保证屏幕可见） */
.hp-print-lite { background: #fff; }


/* R335:打印预览放大弹窗——接近全屏，三联纸(241×140mm≈911×531px)在大屏下接近/达到 100% 真实尺寸；
   内容区允许滚动（custom/100% 时查看超出部分），fit 自适应兜底（窗口不足时自动缩小不截断）。 */
.modal.pp-xl { max-width: min(96vw, 1600px); max-height: 92vh; }
.pp-body { overflow: auto; }
/* R335:预览缩放控件（[−] 百分比 [+] [适应] [100%]）——信息栏右侧紧凑一行 */
.pp-scale-bar { display: inline-flex; align-items: center; gap: 6px; margin-left: auto; flex: none; font-size: 12px; color: var(--text-2); white-space: nowrap; }
.pp-scale-bar .btn { padding: 2px 8px; font-size: 12px; }
.pp-scale-pct { min-width: 46px; text-align: center; font-family: ui-monospace, Menlo, Consolas, monospace; }

/* R374: 撤销 R372 的单行截断(nowrap)——长文本改为换行并撑高行。
   配合 R374 二维码锚定机制：上方行因长文本换行撑高时，锚定的二维码随单元格下移，不再漂移。
   作用域仍限定 .hp-print，不误伤页面 .tbl/.rpt-tbl 列表表格。 */
.hp-print table.hiprint-static-grid-table td {
  white-space: normal;
  word-break: break-all;
  overflow: visible;
}

/* R373: 打印清晰度增分——全局字体覆盖（宋体 → 黑体优先）。
   作用域同时覆盖自研渲染器(.hp-print，热敏 sgt 模板)与 hiprint 原生渲染(.hiprint-printPaper，196mm 大票)，
   !important 压过 template-hiprint.js/print-lock.css 内联 SimSun，两条路径一起生效。
   SimHei 笔画均匀粗实，203dpi 热敏比衬线宋体扛虚；同字号更清晰，间接缓解字号放大导致的排版拥挤。 */
.hp-print, .hp-print *,
.hiprint-printPaper, .hiprint-printPaper *,
.hiprint-printElement-text, .hiprint-printElement-longText, .hiprint-printElement-table {
  font-family: 'SimHei', 'Microsoft YaHei', 'SimSun', sans-serif !important;
}
/* R374: 静态网格表也纳入黑体覆盖（与预览/画布表格字体一致，消除字体差异导致的行高/位置偏差） */
.hiprint-static-grid-table, .hiprint-static-grid-table * {
  font-family: 'SimHei', 'Microsoft YaHei', 'SimSun', sans-serif !important;
}
/* R374: 二维码锚定状态角标（画布/预览一眼区分 自由/锚定，消除歧义） */
.qr-anchor-badge {
  position: absolute; top: -3px; left: -3px; z-index: 60;
  background: var(--primary); color: #fff; font-size: 9px; line-height: 1.2;
  padding: 2px 4px; border-radius: 3px; pointer-events: none;
  font-family: system-ui, -apple-system, sans-serif; white-space: nowrap;
  box-shadow: 0 1px 2px rgba(0,0,0,.3);
}

/* ============ R402 手机端打磨（B/C 批）：仅 @media(max-width:820px) 与 .mp-*/#appMobile 作用域，桌面端 #appDesktop 与 .modal 桌面表现不变 ============ */
@keyframes sheetUp { from { transform: translateY(100%); } to { transform: translateY(0); } }

/* B5 首页留白压缩：姓名与角色标签同行、统计区上间距收紧 */
.mp-header .mp-idrow { display: flex; align-items: center; gap: 8px; }
.mp-header .name { font-size: 16px; font-weight: 700; margin-top: 0; }
.mp-header .role-tag { margin-top: 0; display: inline-flex; align-items: center; }

/* C6 订单页「新建订单」紧凑按钮（替代 12px 文本链，真实点击区≥32px） */
.mp-mini-btn { border: none; background: var(--primary); color: #fff; font-size: 13px; font-weight: 600; height: var(--btn-h, 44px); padding: 0 12px; border-radius: 8px; cursor: pointer; -webkit-tap-highlight-color: transparent; transition: opacity .15s ease, transform .12s ease; }
.mp-mini-btn:active { transform: scale(.96); opacity: .9; }
.mp-mini-btn.ghost { background: #fff; color: var(--primary); border: 1px solid var(--border, #e5e7eb); }

/* B2 次级文字（原 11px）→ 提到 12-13px */
.mp-tab { font-size: 12px; }
.mp-stat .l { font-size: 12px; }
.mp-dash-kpi .l { font-size: 12px; }
.mp-quick .ql { font-size: 13px; }

/* B3 极窄屏（≤360）：底部 tab 缩字号、图标略缩，防 6 个 tab 溢出 */
@media (max-width: 360px) {
  .mp-tab { font-size: 12px; gap: 2px; padding: 8px 0 6px; }
  .mp-tab svg { width: 22px; height: 22px; }
  .mp-quick .qi svg { width: 20px; height: 20px; }
  .mp-quick .ql { font-size: 12px; }
  .mp-dash-kpis { grid-template-columns: repeat(2, 1fr); }
}

/* B6 列表名字截断防护：订单副信息允许换行（重要信息不被裁切） */
.mp-order .meta { white-space: normal; overflow: visible; text-overflow: clip; }

/* B4 过磅仪表栏窄屏重排（≤680：数字缩、可换行、齿轮点击区放大） */
@media (max-width: 680px) {
  .scale-bar { height: auto; flex-wrap: wrap; gap: 10px; padding: 12px 14px; }
  .scale-bar .scale-body { gap: 12px; flex-wrap: wrap; }
  .scale-mid b { font-size: 26px; }
  .scale-mid-label, .scale-state { font-size: 12px; }
  .gear-btn { width: 40px; height: 40px; }
  .scale-badge { font-size: 12px; padding: 5px 12px; }
}

/* C7 + A4 桌面弹窗在手机上变底部抽屉（仅 ≤820，桌面不变）：全宽贴底、栅格单列、标签块级、输入≥46 */
@media (max-width: 820px) {
  .modal-mask { align-items: flex-end; padding: 0; }
  .modal { top: auto; bottom: 0; left: 0; transform: none; width: 100%; max-width: 100%; max-height: 92vh; max-height: 92dvh; border-radius: 16px 16px 0 0; margin: 0; animation: sheetUp .24s ease; }
  .modal-body { padding: 16px; max-height: calc(92vh - 138px); max-height: calc(92dvh - 138px); }
  .modal.has-foot .modal-body { padding-bottom: 92px; }
  .modal-foot { padding: 12px 16px calc(12px + env(safe-area-inset-bottom)); }
  .modal-foot .btn { height: 46px; font-size: 15px; min-width: 0; flex: 1 1 auto; }
  .form-grid { grid-template-columns: 1fr; gap: 14px; }
  .form-grid.cols3 { grid-template-columns: 1fr; }
  .form-grid .full { grid-column: auto; }
  /* R404-3：桌面 .modal.wide/.pp-xl 未在本媒体查询覆盖→手机上右留 40px 不贴底；此处补全宽贴底（特异度相同、源序在后，仅 ≤820px 生效，不泄漏桌面） */
  .modal.wide { width: 100%; max-width: 100%; }
  .modal.pp-xl { max-width: 100%; max-height: 92vh; max-height: 92dvh; }
  .field { display: block; margin-bottom: 14px; }
  .field label, label.text-sm { display: block; font-size: 14px; color: var(--text); margin-bottom: 6px; font-weight: 500; }
  .input, select.input { height: 46px; font-size: 16px; }
  /* R441:移动端 .btn-sm 触控区提到 44px(原 30px 偏小,磅房过磅录入等按钮易误触) */
  .btn-sm { height: 44px; font-size: 14px; padding: 0 14px; }
  /* R441:移动端选择器字号 16px,规避 iOS 聚焦缩放 */
  .picker-field { font-size: 16px; }
  /* R404-4：弹窗体内按钮(如添加明细行)触控区≥44px */
  .modal-body .btn { height: 44px; font-size: 15px; }
  /* R913 · 问题③：价格档改回「一个档 = 一行」（R404-4 原文 flex:1 1 100% ⇒ 每框独占整行，1 档占 4 行）。
     ⚠️ 源码 pages-core.js 里价格档本来就是一行（.price-row flex + 各字段固定宽 90/140/140/120）；
        这条只在 ≤820px 媒体块内 ⇒ 电脑端一直是一行，只有手机竖排（实测 260px/档）。
     改后按手机可用宽约 314px 重分配：模式 58 + 日期 2×约 76 + 单价 56 + 删除 28 + 间距 16。
     ⚠️ 日期框用 flex:1 1 74px（可压缩）⇒ 更窄的机型会等比收窄，而不是横向溢出。 */
  .price-row { flex-wrap: nowrap; gap: 4px; }
  .price-row .input { flex: 0 0 auto; width: auto; font-size: 12px; padding: 0 4px; }
  .price-row > .picker-field,
  .price-row > select.input { flex: 0 0 58px; font-size: 11.5px; padding: 0 14px 0 5px; min-height: 33px; }
  .price-row > .input[data-datepick] { flex: 1 1 74px; min-width: 0; font-size: 12px; }
  .price-row > .input[type="number"] { flex: 0 1 56px; min-width: 0; }
  .price-row > .btn-sm { flex: 0 0 28px; height: 33px; padding: 0; }
  /* ⚠️ 必须有这条：价格档改成 nowrap 后，其【内容最小宽】约 474px（各控件固定宽之和），
     而 #cn_prices 是 .fm .form-grid > div 这个 flex 容器的子项 ⇒ min-width:auto 会把它
     撑到 474px（父仅 311px）⇒ 横向溢出 163px（实测，比改前更糟）。
     加 min-width:0 + width:100% 让它回到父宽，再由 flex 自行分配各控件宽度。 */
  #cn_price_wrap > #cn_prices { min-width: 0; width: 100%; }
  .tf-grid { grid-template-columns: 1fr; }
  /* R410-4：新建订单「车牌 + 次数」合并单行（窄屏不再各占一行）；车牌占剩余、次数缩窄 */
  .of-row { flex-wrap: nowrap !important; align-items: center; }
  .of-row select.input, .of-row input.input { flex: 0 1 auto !important; width: auto; min-width: 0; }
  .of-row input[data-k="plate"], .of-row select[data-k="driver"] { flex: 1 1 auto !important; min-width: 0; }
  .of-row input[data-k="cnt"] { flex: 0 0 64px !important; width: 64px !important; }
  .of-row .btn-ghost.btn-sm { flex: 0 0 auto !important; }
  /* R404-2：刘海机 Toast 被状态栏吃掉 → 手机端改底部避让安全区（不影响桌面 top:20px） */
  .toast-wrap { top: auto; bottom: calc(20px + env(safe-area-inset-bottom)); }
  /* R404-6 自定义车牌键盘(仅在手机端 order 表单挂载) */
  .mp-plate-kb { position: fixed; left: 0; right: 0; bottom: 0; z-index: 150; background: #f2f3f5; padding: calc(8px + env(safe-area-inset-bottom)) 8px 8px; box-shadow: 0 -4px 16px rgba(0,0,0,.18); transform: translateY(100%); transition: transform .22s ease; max-height: 60vh; overflow-y: auto; }
  .mp-plate-kb.show { transform: translateY(0); }
  .pk-bar { display: flex; align-items: center; gap: 10px; margin-bottom: 6px; }
  .pk-display { flex: 1; min-width: 0; height: 44px; background: #fff; border-radius: 8px; padding: 0 12px; font-size: 18px; font-weight: 700; letter-spacing: 2px; color: var(--text); display: flex; align-items: center; justify-content: space-between; overflow: hidden; }
  .pk-ph { color: var(--text-3); font-weight: 400; letter-spacing: 0; font-size: 14px; }
  .pk-count { flex: 0 0 auto; margin-left: 8px; font-size: 12px; font-weight: 400; letter-spacing: 0; color: var(--text-3); }
  .pk-count-err { color: #dc2626; }
  .pk-cancel { height: 44px; padding: 0 14px; border: none; background: transparent; color: var(--primary); font-weight: 600; font-size: 14px; }
  /* R560：校验提示行（非法时红字；正常时保留高度避免键盘抖动） */
  .pk-tiprow { min-height: 16px; padding: 0 2px 4px; font-size: 12px; color: #92400e; }
  .pk-tiprow-err { color: #dc2626; }
  /* R560：候选车牌（该客户历史优先 + 全局兜底，前缀匹配；点一下整段填入） */
  .pk-cands { display: flex; gap: 6px; overflow-x: auto; padding: 0 0 8px; -webkit-overflow-scrolling: touch; }
  .pk-cand { flex: 0 0 auto; height: 34px; padding: 0 12px; border: 1px solid var(--primary); border-radius: 17px; background: #fff; color: var(--primary); font-size: 14px; font-weight: 600; letter-spacing: 1px; }
  .pk-cand:active { background: var(--primary-light, #e8f0fe); }
  .pk-keys { display: flex; flex-direction: column; gap: 6px; }
  /* R560：8 列网格 —— 省份 31+删除=8×4、字母 24=8×3 均正好排满，按键等宽且不再参差 */
  .pk-row { display: grid; grid-template-columns: repeat(8, 1fr); gap: 6px; }
  .pk-key { width: 100%; min-width: 0; height: 46px; padding: 0; border: none; border-radius: 8px; background: #fff; font-size: 16px; font-weight: 600; color: var(--text); box-shadow: 0 1px 0 rgba(0,0,0,.08); touch-action: manipulation; }
  .pk-key:active { background: #e5e7eb; }
  /* R560：当前位不允许的键置灰禁用（智能校验） */
  .pk-key.pk-dis { background: #e9eaec; color: #b8bcc2; box-shadow: none; pointer-events: none; }
  .pk-del { background: #e5e7eb; color: var(--text); }
  .pk-ok { grid-column: span 2; background: var(--primary); color: #fff; }
  .pk-sp { background: #fff7ed; color: #ea580c; }
}

/* C4 防双击误缩放（保留双指缩放）：交互元素禁用双击缩放 */
.mp-btn, .mp-tab, .mp-quick .q, .mp-seg button, .mp-back, .mp-menu-item, .mp-mini-btn, .modal-foot .btn, .q { touch-action: manipulation; }

/* R426:小程序内「开启派单微信提醒」入口横条(仅司机+from=mp 显示,可关闭) */
/* R451：.mp-notify-bar/.mpn-* 随横条移除而删除（订阅入口统一走小程序铃铛） */

/* ===== R466：chips 化头部 + H5 内嵌消息中心 ===== */
/* 计数 chips 行（吸顶，参考美团商家版待办 tab 范式）：单点即切，数字徽标与消息中心待办互相印证 */
.mp-chips { display: flex; align-items: center; gap: 8px; overflow-x: auto; padding: 6px 2px; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
.mp-chips::-webkit-scrollbar { display: none; }
.mp-chip { flex: none; display: inline-flex; align-items: center; justify-content: center; gap: 5px; padding: 7px 14px; border-radius: 999px; border: 1px solid var(--border); background: var(--bg, #fff); color: var(--text-1); font-size: 13px; line-height: 1; touch-action: manipulation; }
.mp-chip.active { background: var(--primary); border-color: var(--primary); color: #fff; }
.mp-chip i { font-style: normal; font-size: 11px; background: var(--red-100, #fee2e2); color: var(--red-deep, #b91c1c); border-radius: 999px; padding: 1px 6px; }
.mp-chip.active i { background: rgba(255,255,255,.25); color: #fff; }
.mp-chip-sep { flex: none; width: 1px; height: 16px; background: var(--border); margin: 0 2px; }
/* 回顶浮钮：滚动超一屏浮现 */
.mp-backtop { position: fixed; right: 14px; bottom: 110px; width: 40px; height: 40px; border-radius: 50%; background: rgba(255,255,255,.92); border: 1px solid var(--border); box-shadow: 0 2px 10px rgba(0,0,0,.10); display: flex; align-items: center; justify-content: center; font-size: 18px; color: var(--text-1); z-index: 60; touch-action: manipulation; }
/* H5 内嵌铃铛浮钮（位置沿用原生铃铛习惯位：右下、tabbar 上方） */
/* R728：① 默认位置补上 iPhone 底部**安全区**（旧写法 bottom:64px 没算 Home 条 ⇒
      「导航 50px + 安全区 34px」正好把它压住，老板截图里挡住了「我的」）；
   ② touch-action 由 manipulation 改 none、并禁选中 ⇒ 供「按住拖动」使用
      （拖动与点击由 JS 区分：位移 < 8px 仍算点击，照旧打开消息中心）。 */
.mp-bell { position: fixed; right: 14px; bottom: calc(64px + env(safe-area-inset-bottom, 0px)); width: 46px; height: 46px; border-radius: 50%; background: var(--primary); color: #fff; border: none; box-shadow: 0 4px 14px rgba(0,0,0,.18); display: flex; align-items: center; justify-content: center; z-index: 61; touch-action: none; -webkit-user-select: none; user-select: none; }
.mp-bell svg { width: 22px; height: 22px; }
.mp-bell-badge { position: absolute; top: -5px; right: -5px; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 10px; background: var(--red-deep, #e11d48); color: #fff; font-size: 12px; line-height: 20px; text-align: center; font-style: normal; }
/* 消息中心面板（普通 HTML 层，无 cover-view 限制） */
.mp-notify { position: fixed; inset: 0; z-index: 70; }
.mpn-mask { position: absolute; inset: 0; background: rgba(15,23,42,.45); }
.mpn-card { position: absolute; left: 50%; top: 50%; transform: translate(-50%,-50%); width: min(92vw, 400px); max-height: 78vh; display: flex; flex-direction: column; background: var(--bg, #fff); border-radius: 18px; box-shadow: 0 10px 40px rgba(0,0,0,.22); overflow: hidden; }
.mpn-head { display: flex; align-items: center; gap: 10px; padding: 14px 16px; border-bottom: 1px solid var(--border); }
.mpn-head b { font-size: 16px; }
.mpn-head span { flex: 1; }
.mpn-done { border: none; background: var(--red-50, #fef2f2); color: var(--text-2, #666); border-radius: 10px; padding: 7px 14px; font-size: 13px; touch-action: manipulation; }
.mpn-body { overflow-y: auto; padding: 10px 12px 16px; -webkit-overflow-scrolling: touch; }
.mpn-sec { font-size: 12px; color: var(--text-2); margin: 10px 4px 8px; }
.mpn-row { display: flex; align-items: center; padding: 12px 10px; border-radius: 12px; border: 1px solid var(--border); margin-bottom: 8px; background: var(--bg, #fff); }
.mpn-row.p-high { border-left: 3px solid var(--red); }
.mpn-row.p-warn { border-left: 3px solid var(--yellow, #f59e0b); }
.mpn-main { flex: 1; min-width: 0; }
.mpn-label { font-size: 14px; font-weight: 600; color: var(--text-1); }
.mpn-sub { font-size: 12px; color: var(--text-2); margin-top: 2px; }
/* R509 · 消息中心待办明细行 */
.mpn-items { margin-top: 6px; display: flex; flex-direction: column; gap: 3px; }
.mpn-item { font-size: 11px; color: var(--text-3, #888); background: var(--bg-2, #f5f5f5); border-radius: 6px; padding: 3px 8px; }
.mpn-count { flex: none; min-width: 22px; height: 22px; border-radius: 11px; background: var(--red-deep, #e11d48); color: #fff; font-size: 12px; line-height: 22px; text-align: center; padding: 0 6px; margin: 0 8px; }
.mpn-chev { flex: none; color: #c4c9d4; font-size: 18px; }
.mpn-empty { padding: 22px 0; text-align: center; color: var(--text-2); font-size: 13px; }
.mpn-sub-btn { width: 100%; height: 44px; border: none; border-radius: 12px; background: var(--blue-bg, #eff6ff); color: var(--blue, #2563eb); font-size: 14px; touch-action: manipulation; }

/* ===== R467：铃铛/面板 X5 兼容修复 + 标题行统一规格 ===== */
/* 修「铃铛点一次就失灵」：① inset 简写 X5(老Chromium)不识别→遮罩宽高为0、卡片定位跑偏，改四边显式；
   ② hidden 属性对 position:fixed 元素在 X5 上不可靠→关闭后疑似残留透明层挡住铃铛，改 class 切换
   （默认 display:none，加 .open 才显示——弹层最保险写法）。 */
.mp-notify { position: fixed; left: 0; right: 0; top: 0; bottom: 0; z-index: 70; display: none; }
.mp-notify.open { display: block; }
.mpn-mask { position: absolute; left: 0; right: 0; top: 0; bottom: 0; background: rgba(15,23,42,.45); }
/* 回顶按钮同款显隐方案（hidden 属性 → class） */
.mp-backtop { display: none; }
.mp-backtop.show { display: flex; }
/* 标题行统一规格（合同管理/订单/磅单 三页同一套）：标题 17px 加粗，按钮统一 32px 高/13px 字号/8px 圆角 */
.mp-head-row { align-items: center; }
.mp-head-row /* R574：原来这条把 .mp-back 一并压到 32px（R571 为对齐页头行按钮定的）。返回键已重设计为
   40×40 触控区，故把 .mp-back 从本规则摘出，只保留页头行内按钮的 32px。 */
.mp-head-row .mp-mini-btn { height: 32px; min-height: 32px; padding: 0 12px; font-size: 13px; border-radius: 8px; }
.mp-head-row .mp-title { font-size: 17px; }
/* R467：chips 行首分组小标签 */
.mp-chips-label { flex: none; font-size: 11px; color: var(--text-2); padding-right: 2px; }
/* R468：chips 行首标签增强（老板反馈灰字太小不直观；又不臃肿——只升半档：12px 加粗主文字色） */
.mp-chips-label { font-size: 12px; font-weight: 600; color: var(--text-1); }
/* 标题行删除刷新后的说明：列表刷新统一走下拉刷新（#mpBody touchmove 已有，微信/美团/淘宝同款惯例） */
/* R469：订阅额度卡（驾驶员面板内：剩余额度 + 订阅+1 按钮，点后 auto=1 授权→+1→自动返回） */
.mpn-quota { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 10px 12px; border: 1px solid var(--border); border-radius: 12px; background: var(--blue-bg, #eff6ff); }
.mpn-quota > span { font-size: 13px; color: var(--text-1); }

/* ===== R470：列表页紧凑化（老板 9-04 复验：顶部留白多 / 主按钮与选中chips撞脸 / chips 松散） ===== */
/* ① 顶部双层内边距(容器14+卡片14≈40px)压成一层：容器 8 + 卡内 10，顶部空隙 ~14px */
.mp-body { padding-top: calc(8px + env(safe-area-inset-top)); }
.mp-sticky { padding: 10px 14px 8px; padding-top: calc(10px + env(safe-area-inset-top)); margin: 0 -14px 0; }
.mp-search-wrap { margin: 8px 0 2px; }
/* ② 标题行主操作按钮：橙色实心方块 → 白底橙边描边胶囊（iOS/微信范式：实心=当前态(chips选中)，描边=可执行动作）
   ——只作用于标题行内(.mp-head-row 作用域)，不影响他处按钮 */
/* R571：高度 30→32px —— 与 .mp-back（L1476 声明 32px）及下方 chips 齐平；此前本行把 L1476 的 32px 覆盖成 30px，导致"同一声明写两遍、后者胜" */
.mp-head-row .mp-mini-btn { height: 32px; padding: 0 14px; border-radius: 999px; box-sizing: border-box; background: #fff; color: var(--primary); border: 1px solid var(--primary); }
.mp-head-row .mp-mini-btn:active { background: var(--red-50, #fff7ed); }
.mp-head-row .mp-mini-btn.ghost { border-color: var(--border); color: var(--text-2); }
/* ③ chips 紧凑化（参考美团/淘宝筛选密度）：行内间距 8→6，按钮 7×14→5×12，字号 13→12 */
.mp-chips { gap: 6px; }
/* R571：chips 改定高 32px —— 原 padding 5px 12px + line-height:1 实测仅约 24px，
   与页头按钮（32px）同屏高低不齐；定高后两者齐平，触控区也更友好。 */
.mp-chip { height: 32px; padding: 0 13px; font-size: 12px; box-sizing: border-box; }
.mp-chip i { font-size: 10px; padding: 1px 5px; }

/* ===== R474:PC 工具栏两行制（维度行+筛选动作行）· 按钮四级分级 ===== */
.sb-row { display: flex; align-items: center; gap: 10px; flex: 1; min-width: 0; }
.sb-row + .sb-row { margin-top: 10px; }
.sb-row .spacer { flex: 1; }
/* L3 低频设置/回收站：图标小圆钮（悬停 title 提示） */
.icon-btn { width: 32px; min-width: 32px; height: 32px; padding: 0; display: inline-flex; align-items: center; justify-content: center; border-radius: 8px; }
.icon-btn.icon-btn-active { background: var(--primary); color: #fff; border-color: var(--primary); }
.icon-btn.icon-btn-active svg { color: #fff; }
/* L1 分裂按钮：主按＋▾ 紧贴一体 */
.split-btn { display: inline-flex; }
.split-btn .btn { border-radius: 0; margin: 0; }
/* R574：改【直接子选择器】。原写法 `.split-btn .btn:first-child`（后代 + :first-child，特异性 0,3,0）
   会误伤箭头按钮 —— 它被包在 <span class="pm-wrap"> 里、正好是该 span 的第一个子元素，
   于是右圆角被这条规则压成直角，整个按钮变成"左圆右直"，与主按钮方向相反。
   收窄为 `>` 直接子元素后箭头不再被误伤，恢复「主按钮左圆右直 / 箭头区左直右圆」。 */
.split-btn > .btn:first-child { border-radius: 8px 0 0 8px; }

/* R573：参照参照图模式 —— 同色系两块 + 极细淡线 + 整体连续圆角。
   R570 曾把分隔线由 .35 提到 .45，反而加重了"两个按钮硬拼"的观感，此处回调 .22；
   右区改同色系亮一档 #fb923c（主色 #f97316 的下一档），靠色差做出"一个按钮的两半"。
   全项目仅此一处分裂按钮（磅单管理「＋新增磅单」）。 */
.split-btn .btn.split-caret { background: #fb923c; }
.split-btn .split-caret { border-radius: 0 8px 8px 0; padding: 0 10px; min-width: 34px; justify-content: center; border-left: 1px solid rgba(255,255,255,.22); }
/* 状态 chips 计数徽章（tabs 分段内） */
.tabs button .chip-n, .tabs button i.chip-n { font-style: normal; font-size: 11px; margin-left: 4px; padding: 0 5px; border-radius: 999px; background: var(--red-100, #fee2e2); color: var(--red-deep, #b91c1c); }
.tabs button.active .chip-n { background: rgba(255,255,255,.25); color: #fff; }

/* ===== R478：徽章计数双色规则 ===== */
/* 红=要动手的桶（chip-n 原样式）；灰=看分布的桶（chip-n-muted） */
.tabs button i.chip-n-muted { background: #eef0f3; color: #666; }
.tabs button.active i.chip-n-muted { background: rgba(255,255,255,.3); color: #fff; }
.mp-chip i.mute { background: #eef0f3; color: #666; }
.mp-chip.active i.mute { background: rgba(255,255,255,.3); color: #fff; }

/* ===== R479：按钮四态语义配色（B-22，沿用 R470"实心=主动作/描边=次要"体系） ===== */
.mp-btn.ok { background: #3B6D11; }
.mp-btn.gray { background: #fff; color: #666; border: 1px solid #D3D1C7; font-weight: 500; }
/* R564：图标+文字成组居中（订单详情「代录磅单」等图文混排按钮）。
   基类 .mp-btn 无 flex，图标(20×20 SVG)与文字按文本流左对齐 → 内容偏左显歪。
   gap 替代原先的字面空格。 */
.mp-btn.center { display: flex; align-items: center; justify-content: center; gap: 6px; }
.mp-btn.center > svg { flex: none; width: 18px; height: 18px; }
/* ============ R568 · 筛选区维度标签 + 描边主色按钮 ============ */
/* 筛选维度的文字标签（业务线 / 状态）。动因：两组 tabs 样式完全相同、无法区分维度，
   行业规范（Helios/海信盘古）要求筛选分层级并明示维度。 */
.f-label { font-size: 12px; color: var(--text-2); white-space: nowrap; flex: none; }
/* 描边式主色按钮（磅单页「视图 ▾」下拉用）：比实心主按钮低一档，不与「新增磅单」抢视觉焦点。 */
.btn-o-line { background: #fff; color: var(--primary); border: 1px solid var(--primary); font-weight: 500; }
.btn-o-line:hover { background: var(--primary-light, #fff7ed); }

/* ===== R569：工具栏通用下拉浮层（把「菜单式居中弹窗」改为「贴按钮下拉」） =====
   动因：视图切换 / 更多设置 / 新增 三类低频菜单此前走 openOverlay（整屏遮罩 + 居中弹窗），
   与主流后台「贴按钮下拉」观感不符（视线要跑到屏幕中间，还多一个"取消"按钮）。
   用法：<span class="pm-wrap"><button ... onclick="popToggle('xxMenu', event)">…</button>
        <span class="pm-menu" id="xxMenu" style="display:none">…</span></span>
   靠页面右侧的按钮加 .pm-right 右对齐，防止下拉溢出视口。 */
.pm-wrap { position: relative; display: inline-flex; flex: none; }
.pm-menu { position: absolute; top: calc(100% + 6px); left: 0; min-width: 148px;
  background: var(--surface); border: 1px solid var(--border); border-radius: 8px;
  box-shadow: 0 6px 18px rgba(0, 0, 0, .12); padding: 5px; z-index: 80;
  display: flex; flex-direction: column; gap: 2px; }
.pm-menu.pm-right { left: auto; right: 0; }
.pm-item { display: flex; align-items: center; gap: 6px; width: 100%; height: 32px; border: none;
  background: none; text-align: left; padding: 0 10px; border-radius: 6px; box-sizing: border-box;
  font-size: 13px; color: var(--text); cursor: pointer; white-space: nowrap; }
.pm-item:hover { background: var(--surface-2); }
.pm-item.on { background: var(--primary-light); color: var(--primary-dark); font-weight: 500; }
.pm-item > svg { width: 13px; height: 13px; flex: none; }
.pm-item > svg.pm-tick { opacity: 0; }
.pm-item.on > svg.pm-tick { opacity: 1; }

/* ===== R570：工具栏控件尺寸统一（紧凑档 · 32px / 13px） =====
   动因：工具栏内混用了 .btn(38) / .btn-sm(30) / .icon-btn(32) / .input(46) 四种高度，视觉高低不齐。
   业界规范（站酷 B 端后台规范 / new-api design.md / 管理平台 UI 规范）统一为常规 32px（8 的倍数档 24/32/40）。
   做法：作用域限定 .section-bar，不动全局 .btn/.input 基类 —— 于是全站收敛为「工具栏 32 / 表单·弹窗 40」两档。
   注意：移动端 ≤820px 走 #appMobile 的 .mp-* 体系，本段不影响；下方仍补一条保险覆盖。 */
.section-bar .btn { height: 32px; padding: 0 13px; font-size: 13px; }
.section-bar .icon-btn { width: 32px; min-width: 32px; padding: 0; }
.section-bar .input, .section-bar select.input { height: 32px; font-size: 13px; padding: 0 12px; border-width: 1px; }
.section-bar .picker-field { min-height: 32px; font-size: 13px; padding: 0 28px 0 12px; }
.section-bar .tabs { padding: 3px; }
.section-bar .tabs button { height: 24px; line-height: 24px; padding: 0 13px; font-size: 13px; }
/* R570 窄屏触控保险：必须放在主规则【之后】—— 媒体查询不提升特异性，同特异性按源序取胜；
   放在前面会被上面的 32px 主规则覆盖（首版即踩此坑，800px 视口实测仍为 32px）。
   ≤820px 实际走 #appMobile 的 .mp-* 体系，本段仅作"万一仍渲染 PC 工具栏"的兜底。 */
@media (max-width: 820px) {
  .section-bar .btn { height: 44px; font-size: 14px; padding: 0 14px; }
  .section-bar .input, .section-bar select.input { height: 46px; font-size: 16px; }
  .section-bar .picker-field { min-height: 46px; font-size: 16px; }
  .section-bar .tabs button { height: 36px; line-height: 36px; }
}

/* ===== R575：吸顶条「悬空」修复（全项目 13 个页面统一受益）=====
   根因：安全间距留在了滚动容器 .mp-body 的 padding-top 上，而 sticky 元素受包含块限制
   （最多只能贴到父 content box 顶部），于是吸顶条上方永远留一条缝。
   缝隙高度 = 容器 padding-top + sticky 的 top（实测：safe=0 → 8px；safe=28 → 64px）。
   真机上这条缝里会滚出下层卡片内容，视觉上像"悬空"。
   修法：① 容器顶距归零（本类）② 安全间距改由吸顶条自身 padding-top 承担 ③ top / margin-top 归零。
   本类由 Mobile.renderBody 的 finally 自动加到含 .mp-sticky 的页面上，新页面无需逐页处理。
   !important 是必需的：.mp-body 的窄屏覆盖（文件后段）与之同特异性，靠源序不可靠。 */
.mp-body-sticky { padding-top: 0 !important; }

/* ===== R595：打印模板分组列表（按单据类型分组 + 圆圈单选） =====
   .tpl-radio 用真实 button 元素（可聚焦、可键盘操作、有 title 提示）；圆圈 = "一组只能选一个"的天然语义，
   点一下即切换默认、立即生效，无需弹窗与二次保存。
   当前生效行整体加浅绿底与绿边，与实心绿圈呼应；kind=temp 的存量模板用灰圈表示不可选。 */
.tpl-group { margin-top: 14px; }
.tpl-group-head { display: flex; align-items: baseline; gap: 8px; padding-bottom: 6px; border-bottom: 1px solid var(--border-2); }
.tpl-group-name { font-weight: 600; font-size: 13px; }
.tpl-row { display: flex; align-items: center; gap: 10px; padding: 9px 11px; border: 1px solid var(--border); border-radius: 10px; margin-top: 8px; }
.tpl-row.on { border-color: var(--green); background: #f7fdf9; }
.tpl-radio { flex: none; width: 16px; height: 16px; padding: 0; border-radius: 50%; border: 2px solid #c7c3bc; background: #fff; cursor: pointer; }
.tpl-radio:hover { border-color: var(--primary); }
.tpl-radio.on { border-color: var(--green); background: var(--green); box-shadow: inset 0 0 0 3px #fff; }
.tpl-radio.dis { border-color: #e5e7eb; background: #f8fafc; cursor: not-allowed; }


/* R712 · ① 取景屏单栏：提示行改为叠在画面底部（绝对定位）。文案为空时（启动屏/异常屏）
   不能留一条空黑条 ⇒ 用 :empty 自动隐藏。零 JS 改动。 */
#shCamHint:empty { display: none; }

/* ═══ R719 · 取景「真全屏」（手机端单栏取景态；JS 只切一个 class 触发） ═══════════════════
   背景（老板 2026-09-20 14:20）：「光做 A 不够，做完 A 还要把画面弄到全屏。」
   做法：#shCamBox 铺满整屏、stage/video 撑到 100vw×100vh；标题行与按钮行改成
        半透明浮层压在画面上（R712 老板已确认「字可以压在画面上」）。
   ⚠️ 一律 !important：JS 侧**只切一个 class**，完全不去改 _setStage() 的三态内联样式
      ⇒ 电脑端 / 核对屏 / 异常屏 / 双栏 逐字节原样不变，随时可回退（去掉 class 即恢复）。
   ⚠️ video 用视口单位而不是 100%：绿框画在跟随 video 的 canvas 上，若 video 落进
      letterbox 留黑边，则「元素尺寸 ≠ 画面尺寸」⇒ 绿框会整体偏移。max 约束下
      video 保持自身宽高比 ⇒ 元素尺寸＝画面尺寸。
   ⚠️ 老内核兜底：不用 inset 简写；safe-area 先给普通值再覆盖 calc。 */
#shCamMask.sh-fs #shCamBox { position: absolute !important; left: 0 !important; top: 0 !important; right: 0 !important; bottom: 0 !important; }
#shCamMask.sh-fs #shCamStage {
  max-width: 100vw !important; max-height: 100vh !important;
  width: 100vw !important; height: 100vh !important;
  border-radius: 0 !important; box-shadow: none !important;
}
#shCamMask.sh-fs #shCamStage video {
  max-width: 100vw !important; max-height: 100vh !important;
  border-radius: 0 !important; box-shadow: none !important;

  /* R1135：原来只给 max 上限 ⇒ video 按自身比例缩在中间，上下一片黑（像没全屏）。
     现在撑满 + cover ⇒ 真正铺满整屏；裁掉的那部分由 JS 的坐标换算补回来。 */
  /* R1135：**只在横屏**铺满。竖屏铺满会把纸的左右裁出屏幕（实测纸占宽 60% 时四角跑到 -143/533，
     屏幕只有 390）⇒ 只能靠退后拍全 ⇒ 纸更小、更糊。竖屏保持「宽度顶满 + 上下模糊填充」，清晰度最优。 */
  
}
/* R1136：R1135 那条「横屏 cover」已撤 —— 黑边方案要求画面完整显示（contain），
   两套填充方式并存会让「画面矩形」和「绿框映射」对不上。 */
#shCamMask.sh-fs #shCamTitle {
  position: absolute !important; left: 0; right: 0; top: 0; z-index: 6;
  /* R730：左内边距 14px ⇒ 76px（那颗按钮原来压着标题文字）。
     R732（取景屏方案 A）：按钮文字由"摄像头"变成**当前摄像头名**，宽度增加 ⇒ 让位加到 112px；
     并**钉死一行**（nowrap + 省略号）—— 标题一旦折行就会掉到右上角两个胶囊上，
     正是老板截图里「后置三镜头（后（后置）关闭）」那种叠字。 */
  padding: 12px 56px 30px 112px; box-sizing: border-box; pointer-events: none;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  background: linear-gradient(rgba(0,0,0,.66), rgba(0,0,0,0));
}
/* R721：提示行在全屏态**强制**叠在画面底部 —— 光有 bottom 不够：
   「分辨率不足被拦」那条早退路径会把 hint 改成内联 static（文档流），
   于是它掉到按钮行下面、画面也跟着矮一条（台架截图实测）。position 也钉死就没这问题。 */
#shCamMask.sh-fs #shCamHint {
  position: absolute !important; left: 0 !important; right: 0 !important;
  bottom: 100px !important; border-radius: 0 !important;
  /* ⚠️ 下面这几条也都是"早退路径不复原"的补丁：被拦一次之后，hint 的内联样式会停在
     static / transparent / max-width:86vw（画面里就变成"没有黑底、贴左边、看不清"）。
     全屏态下统统钉死，取景屏的提示行就永远长一个样。 */
  max-width: none !important; background: rgba(0,0,0,.55) !important; color: #fff !important;
  padding: 7px 10px !important; text-align: center !important;
}
#shCamMask.sh-fs #shCamOps {
  position: absolute !important; left: 0; right: 0; bottom: 0; z-index: 6;
  padding: 16px 14px 16px; box-sizing: border-box;
  background: linear-gradient(rgba(0,0,0,0), rgba(0,0,0,.66));
}
#shCamMask.sh-fs #shCamOps { padding-bottom: calc(16px + env(safe-area-inset-bottom)); }

/* ═══ R722 · 取景「背景模糊填充」+ 遮罩纯黑 + ✕ 让位（老板 2026-09-20 14:56）══════════════
   背景：手机给的是竖版≈3:4 画面，而屏幕细长≈9:19 ⇒ 画面按原比例完整显示时上下**必然**各留一条。
   ⚠️ 先讲清一个事实：**留空不影响清晰度** —— 磅单是横着放的，决定清楚的只有「画面宽度」，
      而宽度已经顶满整屏 ⇒ 纸分到的像素已经是最大。留空浪费的是屏幕高度，不是像素。
   做法：JS 再挂一路**同一 MediaStream** 的 video 当背景（object-fit:cover + blur）铺满留空区；
        这里只负责三件事：全屏态下让背景层出现、遮罩改纯黑（不再透出下层页面）、✕ 让开右上角胶囊。
   ⚠️ 主画面（＝算法看到的那一张）一个字不动：既不裁切、也不缩放。 */
#shCamMask.sh-fs { background: #000 !important; }
/* R1134：背景填充层提亮（老板 2026-10-29：取景器看着没全屏）。
   R722 早就用「同一路流的低分辨率画布放大」填满了上下留空 —— 技术上已铺满，
   但那层颜色偏暗，视觉上仍像留了两条黑边。这里只提亮背景层，**主画面一个字不改**
   （主画面是算法看到的那张，裁一点都会让绿框飘）。filter 不生效的机型等于没改，零副作用。 */
#shCamMask.sh-fs #shCamBg {
  display: block !important;
  filter: brightness(1.5) saturate(0.9) !important;
}
#shCamMask.sh-fs #shCamX { top: 46px !important; right: 14px !important; }

/* ═══ R1136 · 取景器「黑边装 UI」（老板 2026-10-30 11:05）════════════════════════════
   口径：**画面区尽可能干净 —— 只留实时识别的绿框**；所有提示与按钮搬进上下黑边，
        按原相机 / 扫描全能王的方式排布。
   实现：JS 只算「画面真实渲染矩形」并写进 CSS 变量（--shPicW / --shPicH / --shBand），
        这里只按它摆位。换机型、换方向都不会把按钮压到画面上。
   ⚠️ 主画面仍按原比例**完整显示**（contain），一个像素不裁；
      R722 那层「模糊填充」在这里关掉 —— 黑边回归纯黑，画面边界才干净。
   ⚠️ 黑边 < 120px（矮屏 / 横屏）时挂 .sh-bandless，回退成"叠在画面上"的老样式。 */
#shCamMask.sh-fs #shCamBox {
  position: absolute !important; left: 50% !important;
  margin-left: calc(var(--shPicW, 100vw) / -2) !important;
  top: var(--shBand, 0px) !important;
  width: var(--shPicW, 100vw) !important;
  height: var(--shPicH, calc(100vw * 4 / 3)) !important;
  transform: none !important; gap: 0 !important;
}
#shCamMask.sh-fs #shCamStage {
  width: 100% !important; height: 100% !important;
  max-width: none !important; max-height: none !important;
  border-radius: 0 !important; box-shadow: none !important; background: #000 !important;
}
#shCamMask.sh-fs #shCamStage video {
  width: 100% !important; height: 100% !important; object-fit: contain !important;
  max-width: none !important; max-height: none !important;
  border-radius: 0 !important; box-shadow: none !important;
}
/* 黑边纯黑：不再用「同一路画面的模糊放大版」去填（那层让边界发糊，正是"不像原相机"的根源） */
#shCamMask.sh-fs #shCamBg { display: none !important; }
/* 顶栏 = 上黑边：标题居中，避开右上角的 ✕ */
#shCamMask.sh-fs #shCamTitle {
  position: absolute !important; left: 0 !important; right: 0 !important; top: 0 !important;
  height: var(--shBand, 0px) !important;
  display: flex !important; align-items: center; justify-content: center;
  padding: 0 104px !important; background: none !important;
}
/* 提示 = 紧贴画面下沿，落在下黑边里；不再压一条半透明黑条在画面上 */
#shCamMask.sh-fs #shCamHint {
  position: absolute !important; left: 0 !important; right: 0 !important;
  top: calc(100% + 8px) !important; bottom: auto !important;
  background: none !important; max-width: none !important; border-radius: 0 !important;
  padding: 0 12px !important; color: #fff !important; text-align: center !important;
}
/* 按钮行 = 下黑边，垂直居中不贴底（留出安全区） */
#shCamMask.sh-fs #shCamOps {
  position: absolute !important; left: 0 !important; right: 0 !important; bottom: 0 !important;
  /* 下黑边要一分为二：上 30px 留给提示行，剩下的才是按钮区。
     不分开的话，band 一窄提示就压在按钮上了（台架实测过）。 */
  height: calc(var(--shBand, 0px) - 30px) !important;
  display: flex !important; align-items: center !important; justify-content: center !important;
  background: none !important;
  padding: 0 16px calc(6px + env(safe-area-inset-bottom, 0px)) !important;
}
/* ✕ 放到上黑边中部，与标题同一行 */
#shCamMask.sh-fs #shCamX { top: calc(var(--shBand, 0px) / 2 - 20px) !important; right: 14px !important; }

/* ── 上黑边固定两行（R1137）──────────────────────────────────────────────
   以前标题是「整条黑边高度 + 垂直居中」，两个胶囊按 band 变量算负偏移 ⇒ band 一变就撞行
   （老板截图里「把整张磅单放进框里」和「自动拍：开」叠在一行）。
   现在不跟比例走，直接钉死两行：第 1 行 11px（镜头名 / 自动拍），第 2 行 46px（标题 / ✕）。 */
#shCamMask.sh-fs:not(.sh-bandless) #shCamPick {
  top: max(6px, calc((var(--shBand, 0px) - 84px) / 2 + 4px)) !important; left: 12px !important;
  max-width: 46% !important; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}
#shCamMask.sh-fs:not(.sh-bandless) #shAuto { top: max(6px, calc((var(--shBand, 0px) - 84px) / 2 + 4px)) !important; right: 12px !important; }
#shCamMask.sh-fs:not(.sh-bandless) #shCamTitle {
  top: max(40px, calc((var(--shBand, 0px) - 84px) / 2 + 39px)) !important; height: 38px !important;
  padding: 0 96px !important; justify-content: center !important;
}
#shCamMask.sh-fs:not(.sh-bandless) #shCamX { top: max(40px, calc((var(--shBand, 0px) - 84px) / 2 + 39px)) !important; right: 12px !important; }

/* ── 底部按钮照原型（R1137）──────────────────────────────────────────────
   原来三个都是文字胶囊、宽度各自不同 ⇒ 看着「大小不一」。
   现在：相册 / 闪光灯 = 52px 圆钮（图标），拍摄 = 70px 白色大圆环，三等分等距。 */
#shCamMask.sh-fs #shCamOps {
  justify-content: space-between !important;
  padding-left: 34px !important; padding-right: 34px !important;
}
#shCamMask.sh-fs #shBtnAlb,
#shCamMask.sh-fs #shBtnTorch {
  width: 52px !important; height: 52px !important; min-width: 0 !important; padding: 0 !important;
  border-radius: 50% !important; border: 1px solid rgba(255, 255, 255, .34) !important;
  background: rgba(255, 255, 255, .10) !important;
  color: transparent !important; font-size: 0 !important; position: relative;
}
#shCamMask.sh-fs #shBtnAlb::before,
#shCamMask.sh-fs #shBtnTorch::before {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  font-size: 19px; color: #fff; line-height: 1;
}
#shCamMask.sh-fs #shBtnAlb::before { content: '▤'; }
#shCamMask.sh-fs #shBtnTorch::before { content: '☀'; }
#shCamMask.sh-fs #shBtnTorch.on { background: #facc15 !important; border-color: #facc15 !important; }
#shCamMask.sh-fs #shBtnTorch.on::before { color: #111; }
#shCamMask.sh-fs #shBtnShot {
  width: 70px !important; height: 70px !important; min-width: 0 !important; padding: 0 !important;
  border-radius: 50% !important; border: 0 !important; background: #fff !important;
  box-shadow: 0 0 0 3px rgba(255, 255, 255, .38), inset 0 0 0 3px #d9dee6;
  color: transparent !important; font-size: 0 !important;
}
/* 底部三个按钮排成一行：相册 · 拍摄 · 闪光灯（原来会折行，拍摄独占一行） */
#shCamMask.sh-fs #shCamOps { flex-wrap: nowrap !important; gap: 10px !important; }
#shCamMask.sh-fs #shCamOps button { min-width: 0 !important; padding: 10px 14px !important; }
#shCamMask.sh-fs #shCamOps > span { display: none !important; }   /* 中间那根竖线在新排布里多余 */

/* ── R1138 · V2 定稿（老板 2026-10-30 拍板：选 V2 不选 V3）────────────────
   布局一个字不动（上下黑边平分、画面居中、四角直角），只改三处尺寸细节：
   ① 快门 70 → 76，白环加厚 —— 按下去更有"咔"的手感（参考原生相机）
   ② 左右圆钮 52 → 54，并补「图标下方小字」—— 只放图标像装饰，加字才知道能点
      （小字做法借扫描全能王，骨架仍是原生相机）
   ③ 按钮区底边留 10px + 安全区 —— 小字不贴屏幕边 */
#shCamMask.sh-fs #shBtnShot {
  width: 76px !important; height: 76px !important;
  box-shadow: 0 0 0 4px rgba(255, 255, 255, .30), inset 0 0 0 3px #dfe4ec !important;
}
#shCamMask.sh-fs #shBtnAlb,
#shCamMask.sh-fs #shBtnTorch { width: 54px !important; height: 54px !important; }
#shCamMask.sh-fs #shBtnAlb::after,
#shCamMask.sh-fs #shBtnTorch::after {
  position: absolute; left: 50%; transform: translateX(-50%); bottom: -18px;
  font-size: 10.5px; line-height: 1; color: #9fb0c6; white-space: nowrap; letter-spacing: .3px;
}
#shCamMask.sh-fs #shBtnAlb::after { content: '相册'; }
#shCamMask.sh-fs #shBtnTorch::after { content: '闪光灯'; }
#shCamMask.sh-fs #shCamOps { padding-bottom: calc(10px + env(safe-area-inset-bottom, 0px)) !important; }

/* 「画面四周那一圈黑」的真凶：§shCamStage 自带内联 padding:12px（原本是给
   "正在启动摄像头…"那句文字留的），全屏态下把视频四周各缩进 12px ⇒ 看着像
   画面里还套了一圈黑。这里清零（!important 声明优先级高于内联的非 !important）。
   只在非回退态清 —— .sh-bandless 下那句启动文字还要靠它留白。 */
#shCamMask.sh-fs:not(.sh-bandless) #shCamStage { padding: 0 !important; }

/* —— 黑边不够用时的回退（矮屏 / 横屏）：一律按改造前的样子走 —— */
#shCamMask.sh-fs.sh-bandless #shCamBox {
  top: 0 !important; height: 100% !important; width: 100vw !important; margin-left: -50vw !important;
}
#shCamMask.sh-fs.sh-bandless #shCamTitle { height: auto !important; padding: 12px 104px 30px !important; }
#shCamMask.sh-fs.sh-bandless #shCamHint {
  top: auto !important; bottom: 100px !important; background: rgba(0, 0, 0, .55) !important;
}
#shCamMask.sh-fs.sh-bandless #shCamOps {
  height: auto !important; padding: 16px 14px calc(16px + env(safe-area-inset-bottom, 0px)) !important;
}
#shCamMask.sh-fs.sh-bandless #shCamX { top: 46px !important; }

/* ============ R813 · 手机端「新建临时磅单」抽屉：字段改列表式（标签左 / 值右 / 无外框 / 无删除按钮） ============
   结构仍用 #tempFieldsList + .tf-row[data-key]（保存逻辑 Pages.saveTempBill 按此取字段键），
   只在这里把「两列网格小盒子」覆盖成「列表行」——不动 HTML 结构，两端共用同一套保存。 */
.tf-grid.mb-list { grid-template-columns: 1fr; gap: 0; }
.tf-grid.mb-list .tf-row { border: none; border-bottom: 1px solid var(--border, #e2e8f0); border-radius: 0; padding: 11px 2px; gap: 10px; background: transparent; }
.tf-grid.mb-list .tf-row:last-child { border-bottom: none; }
.tf-grid.mb-list .tf-row .tf-lbl { width: 60px; font-size: 13px; color: var(--text-2); }
.tf-grid.mb-list .tf-row .mb-tf-in { flex: 1; min-width: 0; border: none; background: transparent; font-size: 14px; color: var(--text); padding: 0; height: 24px; line-height: 24px; }
.tf-grid.mb-list .tf-row .mb-tf-in:focus { outline: none; }
.tf-grid.mb-list .tf-row .mb-tf-in::placeholder { color: var(--text-3); }
.tf-grid.mb-list .tf-row .mb-tf-val { flex: 1; min-width: 0; font-size: 14px; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* R821b:原 `.mb-tf-val.empty` 改名 `.is-empty` —— 避免误命中全局 `.empty`（padding:60px 20px）
   导致【空值时该行被撑到 166px】。详见 _patch/20260929/patch_r821b_empty.js 头部说明。 */
.tf-grid.mb-list .tf-row .mb-tf-val.is-empty { color: var(--text-3); }
.tf-grid.mb-list .tf-row .mb-tf-arrow { flex: none; color: var(--text-3); font-size: 17px; line-height: 1; }
/* R814：临时磅单抽屉「更多信息」折叠条（默认收起，点一下展开） */
.mb-tf-fold { display: flex; align-items: center; gap: 8px; padding: 11px 2px; cursor: pointer; border-bottom: 1px solid var(--border, #e2e8f0); }
.mb-tf-fold-t { flex: none; font-size: 13px; color: var(--text); font-weight: 600; }
.mb-tf-fold-s { flex: 1; min-width: 0; font-size: 12px; color: var(--text-3); text-align: right; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mb-tf-fold-a { flex: none; color: var(--text-3); font-size: 11px; line-height: 1; }

/* ============ R819b · 厂内提货「车号」自绘建议卡片 ============
   背景：R819 首版车号用 <datalist>（浏览器原生控件），实测弹出方向/尺寸不可控，
         会向上溢出盖住弹窗标题、并把 .tf-row(flex) 撑高（老板 2026-09-28 截图反馈）。
   现方案：改用自绘胶囊卡片（复用 R815 plateSuggest 引擎），绝对定位不占布局。
   注意：本段只新增规则，不改动 .tf-row / .tf-grid 既有定义。 */
.tf-grid .tf-row .pk-plate-wrap { position: relative; flex: 1; min-width: 0; display: block; }
.tf-grid .tf-row .pk-plate-wrap > input { width: 100%; }
/* 建议卡片容器：绝对定位在输入框下方，父级 .tf-row 已是 flex ⇒ 不参与高度计算 */
.tf-grid .tf-row [data-pk-plate-sug] { position: absolute; left: 0; right: 0; top: calc(100% + 4px); z-index: 60; }
/* 同行两列等高：保险起见显式声明（grid 默认 stretch，此处防输入框被拉伸） */
.tf-grid .tf-row { align-self: stretch; }
.tf-grid .tf-row > .input, .tf-grid .tf-row > textarea, .tf-grid .tf-row > select { align-self: center; }

/* ============ R819d · 车号下拉行（统一外观，替换原彩色胶囊） ============
   老板 2026-09-28 拍板：「车号下拉框只保留一种——聪明逻辑不变，改显示方式为下拉」。
   本节仅供 R819d 新增的 .plate-sug-row 使用；订单/正式磅单/厂内提货三处同款。
   纯新增规则，不动任何既有选择器。 */
.plate-sug-row + .plate-sug-row { border-top: 0.5px solid var(--border, #e2e8f0); }
.plate-sug-row:hover, .plate-sug-row:active { background: var(--surface-2, #f8fafc); }
/* R819d:订单/磅单侧车号下拉包装壳（相对定位父级，供候选面板 absolute 定位） */
[data-plate-sugwrap] { position: relative; display: block; width: 100%; }

/* ============ R820 · 厂内提货手机端皮肤（对齐预约单）+ 收货单位选择弹层 ============
   背景：厂内提货的字段行由 Pages._pickupFieldRowHtml 生成，被「手机端抽屉」与
         「电脑端弹窗」共用。若直接改行内 input 类名，电脑端会跟着变形。
   方案：入口开关 window.__pkMobileSkin —— 手机端入口置 true，行生成器据此输出
         .mb-tf-row 扁平行；电脑端默认 false，输出原 .input 带框皮肤（物理隔离）。
   本节只新增两类规则：① 扁平行内 input/val 的补充约束 ② 收货单位选择弹层。
   既有 .tf-grid.mb-list 规则【一字不动】。 */

/* 扁平行内的裸 input（.mb-tf-in 已在 mb-list 块内定义，此处补「非 mb-list 容器」的兜底） */
.tf-row.mb-tf-row { position: relative; }
/* 车号专属壳在扁平行下：占满整行，供候选面板 absolute 定位 */
.tf-row.mb-tf-row .pk-plate-wrap { position: relative; flex: 1; min-width: 0; display: block; }

/* 收货单位选择弹层（R820：手机端扁平行不能放 <select>，改点击弹层） */
.pk-unit-pick { margin: 0 2px 10px; background: var(--surface, #fff); border: 1px solid var(--border, #e2e8f0); border-radius: 10px; overflow: hidden; box-shadow: 0 6px 18px rgba(15,23,42,.08); }
.pk-unit-pick-h { padding: 9px 12px; font-size: 12px; color: var(--text-3, #94a3b8); background: var(--surface-2, #f8fafc); border-bottom: 1px solid var(--border, #e2e8f0); }
.pk-unit-pick-l { max-height: 240px; overflow-y: auto; -webkit-overflow-scrolling: touch; }
.pk-unit-pick-i { padding: 11px 12px; font-size: 14px; color: var(--text, #0f172a); cursor: pointer; border-bottom: 0.5px solid var(--border, #e2e8f0); }
.pk-unit-pick-i:last-child { border-bottom: none; }
.pk-unit-pick-i:active { background: var(--surface-2, #f8fafc); }
.pk-unit-pick-i.on { color: var(--primary, #f97316); font-weight: 600; }

/* ============ R820 · 手机端「新建订单」抽屉：字段区改「预约单同款扁平行」 ============
   背景：手机端原本直接调电脑端 Pages.orderForm()，弹窗被 @media(820px) 强行贴底成
         「伪抽屉」，皮肤仍是 .input 白底带框 + form-grid 三列被压成一列。
   方案：新建订单在手机上改走 Mobile.sheet（真抽屉），字段区沿用 Pages.orderForm()
         原样产出的 .form-grid.cols3 结构，由本段 CSS 覆盖为单列扁平行。
   作用域严格限定在 #mpSheet 内 => 电脑端弹窗 / 其他 22 处 Mobile.sheet 一律不受影响。
         既有 .form-grid / .mp-form-sec / .picker-field 定义【一字不动】。 */

/* 抽屉底部操作栏（取消 / 创建订单）—— sheet 无 foot 区，故由 .of-sheet-foot 承担 */
/* R911 · 抽屉底部按钮「吸底常驻」—— 原来 .of-sheet-foot 只在内容末尾，
   合同 21 字段要滚到底才见「保存」；改成 sticky 后与弹窗 .modal-foot 的位置完全一致，用户无感。
   写法照抄项目既有的 .mp-sheet-foot（本文件同区域），负边距吃掉 .mp-sheet-scroll 的 18px 内边距。 */
#mpSheet .of-sheet-foot { display: flex; gap: 10px; position: sticky; bottom: -18px;
  margin: 16px -18px -18px; padding: 10px 18px calc(10px + env(safe-area-inset-bottom));
  background: var(--surface); border-top: 1px solid var(--border); }
#mpSheet .of-sheet-foot .btn { flex: 1; height: 46px; border-radius: 10px; font-size: 15px; }

/* 字段区：三列/两列 -> 单列扁平行（标签左 / 值右 / 无外框） */
#mpSheet .mp-form-sec { background: transparent; border: none; border-radius: 0; padding: 0; margin-bottom: 6px; }
#mpSheet .mp-form-sec-t { font-size: 13px; font-weight: 700; color: var(--text); margin: 14px 2px 2px; }
#mpSheet .mp-form-sec .form-grid,
#mpSheet .mp-form-sec .form-grid.cols3 { grid-template-columns: 1fr; gap: 0; }
#mpSheet .mp-form-sec .form-grid > div { border-bottom: 1px solid var(--border, #e2e8f0); padding: 11px 2px; display: flex; align-items: center; gap: 10px; min-height: 46px; }
#mpSheet .mp-form-sec .form-grid > div:last-child { border-bottom: none; }
#mpSheet .mp-form-sec .form-grid > div > label { width: 96px; flex: none; margin: 0; font-size: 13px; color: var(--text-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#mpSheet .mp-form-sec .form-grid > div > .input { flex: 1; min-width: 0; border: none; background: transparent; padding: 0; height: 24px; line-height: 24px; font-size: 14px; color: var(--text); text-align: right; }
#mpSheet .mp-form-sec .form-grid > div > .input:focus { outline: none; }
#mpSheet .mp-form-sec .form-grid > div > .input[readonly] { background: transparent !important; }
#mpSheet .mp-form-sec .form-grid > div > .input::placeholder { color: var(--text-3); }
#mpSheet .mp-form-sec .form-grid > div > select.input { text-align: right; }
/* picker-field（合同选择入口）：同款扁平行外观 */
#mpSheet .mp-form-sec .form-grid > div > .picker-field { flex: 1; min-width: 0; border: none; background: transparent; padding: 0 20px 0 0; min-height: 24px; text-align: right; justify-content: flex-end; font-size: 14px; color: var(--text-3); }
#mpSheet .mp-form-sec .form-grid > div > .picker-field:after { right: 2px; }
#mpSheet .mp-form-sec .form-grid > div > .picker-field.has-value { color: var(--text); }
/* 日期型右对齐，与预约单观感一致 */
#mpSheet .mp-form-sec .form-grid > div > .input[type="date"] { text-align: right; }
/* 车牌清单行（of-row）在抽屉内同样扁平行化 */
#mpSheet #ofRows .of-row { display: flex; align-items: center; gap: 8px; border-bottom: 1px solid var(--border, #e2e8f0); padding: 10px 2px; }
#mpSheet #ofRows .of-row .input { flex: 1; min-width: 0; border: none; background: transparent; padding: 0; height: 24px; text-align: right; font-size: 14px; }
/* R911 · 车牌框「看得出能点」—— 精确到车牌那一格（input[data-k="plate"]）。
   为什么需要它：抽屉里所有行式输入都是「无框 + 透明底 + 右对齐」（R820 定的扁平行风格），
   而车牌框是其中唯一「点它会弹车牌键盘」的 ⇒ 缺的不是边框，是「可点击」的暗示。
   因此只让这一格长出输入框样子，同排的「次」与其它行式输入一律不碰。
   ⚠️ 落点说明：外部方案给的是 .fm .form-grid > div > .input[readonly]，那条选择器
   匹配不到车牌框（车牌在 #ofRows > .of-row 下，不经 .form-grid > div）⇒ 照它改等于没改。
   用 #mpSheet 前缀 ⇒ 作用域锁死在订单抽屉内，电脑端与其它页面零影响。 */
/* R912 · 车牌可见框「看得出能点」—— 指针改为【可见的那个框】。
   ⚠️ R911 的教训（浏览器计算样式实测确证）：手机端 addOrderRow 把 data-k="plate" 挂在
   【type="hidden" 的隐藏框】上，可见框只有 id="of_plate_N"、没有 data-k
   ⇒ 按 input[data-k="plate"] 找框，命中的必然是那个看不见的隐藏框（实测它的 border 变成了 1.5px，
     而可见框仍是 0px none）—— 这就是「改完跟没改一样」的原因。
   ⚠️ 且【绝不能给可见框补 data-k】：取值代码是 row.querySelector('[data-k="plate"]').value，
   手机端的值写在隐藏框里，两个框同带该属性会让取值拿到空的可见框 ⇒ 把建单数据改坏。
   故按 id 前缀 + .of-plate 类精确指认可见框。 */
/* R963：车牌框改为「.of-plate-box 包裹 + 可编辑输入框」（与电脑端同构）——
   选择器由【直接子代】改为【后代】：plateEnhance 的候选面板还会再包一层 relative 壳
   （_renderPlateSug 的 data-plate-sugwrap），用 > 会匹配不到 ⇒ 手机端样式整片失效。 */
#mpSheet #ofRows .of-row .of-plate-box { flex: 1 1 auto; min-width: 0; }
#mpSheet #ofRows .of-row input.of-plate {
  border: 1px solid var(--border, #e5e7eb) !important;
  background-color: var(--surface, #fff) !important;
  border-radius: 9px; height: 44px; line-height: 42px; width: 100%;
  padding: 0 12px 0 38px; text-align: left; color: var(--text); font-size: 15px;
  background-repeat: no-repeat !important; background-position: 12px center !important;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='17' height='17' viewBox='0 0 16 16' fill='none'><rect x='1.2' y='3.6' width='13.6' height='8.8' rx='2' stroke='%2394a3b8' stroke-width='1.3'/><path d='M4 6.4v3.2M6.4 6.4v3.2M8.8 6.4v3.2M11.2 6.4v3.2' stroke='%2394a3b8' stroke-width='1.1'/></svg>") !important;
}
#mpSheet #ofRows .of-row input.of-plate::placeholder { color: #94a3b8; }
#mpSheet #ofRows .of-row input.of-plate:focus {
  border-color: #F97316 !important; box-shadow: 0 0 0 3px rgba(249,115,22,.12); outline: none;
}

/* ============ R912 · 手机端订单表单「分层排版」 ============
   病根（浏览器实测）：R820 的「扁平行」（label 固定 96px + 省略号 / 值右对齐 / 无框透明）
   把三类性质完全不同的内容压成了同一个长相 —— ① 只读带出值（短）② 可填输入框 ③ 长说明文字。
   实测：标签「甲方（合同带出）」容器 96px、需 104px（截断 8px）；「预估载重(吨·选填)」需 136px（截断 40px）；
   预估载重的说明文字塞在 placeholder 里、需 278px 而框只有 229px（截断 49px）；可填与只读也分不清。
   修法：按「这行是拿来读的、还是拿来填的」分两种形态。
   全部带 #mpSheet 前缀 ⇒ 电脑端与其它页面零影响。 */

/* ① 展示行（只读带出 / 日期）：保持「标签左 / 值右」，但 label 自适应、不再截断 */
#mpSheet .mp-form-sec .form-grid > div > label {
  width: auto; min-width: 72px; max-width: 48%; flex: 0 0 auto;
  white-space: nowrap; overflow: visible; text-overflow: clip; font-size: 13.5px; }
#mpSheet .mp-form-sec .form-grid > div { padding: 0 2px; min-height: 48px; }
#mpSheet .mp-form-sec .form-grid > div > .input { height: 26px; line-height: 26px; font-size: 14.5px; }

/* ② 填写行（div.is-fill）：标签在上 + 输入框整行、白底圆角带框、文字左对齐 */
#mpSheet .mp-form-sec .form-grid > div.is-fill { display: block; padding: 12px 2px 14px; }
#mpSheet .mp-form-sec .form-grid > div.is-fill > label {
  display: block; width: auto; max-width: none; margin: 0 0 7px; font-size: 13.5px; }
#mpSheet .mp-form-sec .form-grid > div.is-fill > .input {
  width: 100%; height: 42px; line-height: 40px; text-align: left; padding: 0 12px;
  /* !important 必须带：上面那条同族规则（同为 #mpSheet 前缀）把 border 抹成 none、背景抹成透明，
     实测不加时改后 border 仍读到 0px（只剩圆角看不出框）。与本文件既有的 background:transparent!important 同一套做法。 */
  border: 1px solid var(--border, #e5e7eb) !important;
  border-radius: 9px; background-color: var(--surface, #fff) !important;
  font-size: 14.5px; color: var(--text); }
#mpSheet .mp-form-sec .form-grid > div.is-fill > .input:focus {
  border-color: #F97316 !important; box-shadow: 0 0 0 3px rgba(249,115,22,.12); outline: none; }
#mpSheet .mp-form-sec .form-grid > div.is-fill > .field-hint {
  margin-top: 7px; font-size: 12px; line-height: 1.65; color: var(--text-3); }
/* 说明小字：电脑端也会用到（同一份模板）⇒ 全局定义，两端都不裸奔 */
.field-hint { font-size: 12px; line-height: 1.6; color: var(--text-3); margin-top: 5px; }

/* ③ 日期行：补回「日历」图标 —— R911 那条是 .fm .form-grid 前缀（无 #mpSheet），
   优先级低于本区同族规则（ID 选择器 + 简写 background 会把 background-image 一起重置），
   实测订单页日期框没有图标、而合同/车辆页有。这里用同款规则 + #mpSheet 前缀补回。 */
#mpSheet .mp-form-sec .form-grid > div > .input[data-datepick] {
  padding-right: 24px;
  background-repeat: no-repeat !important; background-position: right 2px center !important;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='15' height='15' viewBox='0 0 16 16' fill='none'><rect x='1.6' y='3' width='12.8' height='11.4' rx='2' stroke='%239ca3af' stroke-width='1.3'/><path d='M1.6 6.4h12.8M5.4 1.6v3M10.6 1.6v3' stroke='%239ca3af' stroke-width='1.3' stroke-linecap='round'/></svg>") !important; }

/* ④ 分组小标题与清单说明行：把标题和说明拆成上下两行，不再挤在一行里 */
#mpSheet .mp-form-sec-t { margin: 18px 2px 4px; }
#mpSheet .mp-list-head { margin: 18px 2px 8px; }
#mpSheet .mp-list-head > b { display: block; font-size: 13.5px; margin-bottom: 3px; }
#mpSheet .mp-list-head > span { display: block; font-size: 12px; color: var(--text-3); line-height: 1.6; }

/* R913 · 问题①：展示行的值改「紧跟标签」（原来值一律贴右边缘）。
   实测病根（浏览器计算样式）：style.css:2119 的值 text-align:right ＋ 2170 的 label{width:auto}
   ⇒ 每行成了「左边一个词 + 右边一个词」，标签右缘到值的空隙占该行 50%~82%
     （甲方 271px/82%、客户 242px/73%、货品 257px/77%、有效期起止各 165px/50%）。
   改后：值一律左对齐紧跟标签 ⇒ 空隙统一 10px（3%）；配合 label 的 min-width:72px，
   各行的值起始位置还竖直对齐（实测落在同一个 x）。 */
#mpSheet .mp-form-sec .form-grid > div > .input[readonly] { text-align: left; }
#mpSheet .mp-form-sec .form-grid > div > .picker-field { justify-content: flex-start; text-align: left; }
#mpSheet .mp-form-sec .form-grid > div > select.input { text-align: left; }

/* ⑤ R913 · 车牌行合并回「一行」（R912 曾拆成两行，实测每车 113px ⇒ 太占高）。
   ⚠️ 依据：本文件 1718-1723 的 R410-4 设计原本就是一行（nowrap + 车牌 flex:1 + 次数 64px）；
      R912 为解「车牌框只剩 106px、提示被截」把它拆成两行 —— 那是治错了地方：
      正解是【在一行内重新分配宽度】—— 删除按钮由「✕ 删除」缩成图标、次数框收窄，
      车牌框仍有 177px ⇒ 提示「车牌号，如 京A12345」（需 144px）完整显示。
   实测：每车 113px → 60px（两车 227px → 121px）。 */
#mpSheet #ofRows .of-row { display: flex; align-items: center; gap: 8px; padding: 11px 2px; border-bottom: none; }
#mpSheet #ofRows .of-row + .of-row { border-top: 1px solid var(--border, #e2e8f0); }
#mpSheet #ofRows .of-row > .of-lb { flex: none; font-size: 13px; color: var(--text-2); }
#mpSheet #ofRows .of-row > input[data-k="cnt"] {
  /* 宽度不在这里声明 —— 由本文件 1731 行（R410-4，flex/width 均带 !important）决定 = 64px。
     原先这里写过 flex:0 0 52px / width:52px，实测被那条 !important 压过、从未生效，
     留着只会误导后人，故移除；此处只补视觉（白底圆角带框 + 居中）。 */
  height: 36px; text-align: center; font-size: 14px;
  border: 1px solid var(--border, #e5e7eb) !important; border-radius: 8px;
  background-color: var(--surface, #fff) !important; }
#mpSheet #ofRows .of-row > .of-del {
  flex: none; width: 34px; height: 36px; padding: 0; border-radius: 8px;
  color: #e11d48; background: var(--red-bg, #fff1f2); border: none; font-size: 15px; }

/* ⑥ 底部按钮栏：它是 sticky 常驻（R911 为「不滚到底也能看见保存」而改），
   浮起时会盖住它上方的内容 ⇒ 加一条渐变遮罩，让「下面还有内容」一眼可见。
   （实测：滚到底时按钮回到文档流末尾、最后一行内容完整可见，不存在被永久遮挡的内容。）*/
#mpSheet .of-sheet-foot::before {
  content: ''; position: absolute; left: 0; right: 0; top: -16px; height: 16px;
  background: linear-gradient(to bottom, rgba(255,255,255,0), var(--surface));
  pointer-events: none; }



/* ============ R821 · 图2 修复：厂内提货/预约单「扁平行」高度塌陷 ============
   老板 2026-09-29 截图反馈「新建提货计划这个布局不合理啊，收货单位为什么这么大？」

   ★ 先认账（取证结论，如实汇报）：
     收货单位那一行**本身没有缺陷**。真正的问题是我在 R820 引入的两个缺陷，
     把它的上下几行"压扁"了，它就显得特别大 —— 一排人站着，旁边两个人蹲下了，
     中间那个就显得特别高。

     缺陷① 空字段行塌陷：R820 给 .tf-row.mb-tf-row 只加了 position:relative，
            没有定义最小高度 ⇒ 没有内容的行（如"备注""电话"）被压到 22px 左右。
     缺陷② 白底带框残留：.tf-grid.mb-list .tf-row 的 padding:11px 2px 是**靠父容器后代
            选择器**生效的；R820 新类 .tf-row.mb-tf-row 加在**行本身**上，
            若该行不在 .tf-grid.mb-list 容器内，就落回 .tf-row 原始定义
            （padding:5px 10px + background:#fff + border）⇒ 露出白底和边框。

   修法（3 条 CSS，与设计稿一致）：
     ① 给扁平行定最小高度 46px —— 与订单抽屉 .mp-form-sec 的 min-height:46px 对齐，
        也和 Apple HIG / Material 的 44px 触控底线一致；
     ② 把"扁平行"样式从"依赖父容器"改为"挂在行自己的类上"，不再依赖 .mb-list 容器；
     ③ 空值行也保持同样高度（align-items:center 已由 .tf-row 提供）。

   ⚠️ 只新增/覆写与 .mb-tf-row 相关的规则；.tf-grid.mb-list 既有规则【一字不动】，
      避免误伤预约单原本正常的行。 */

/* ① 统一最小高度 + 高度对齐（空字段不再塌陷） */
.tf-row.mb-tf-row { position: relative; min-height: 46px; align-items: center; }

/* ② 扁平行自带"扁平列表"皮肤（不再依赖 .tf-grid.mb-list 父容器） */
.tf-row.mb-tf-row {
  border: none;
  border-bottom: 1px solid var(--border, #e2e8f0);
  border-radius: 0;
  padding: 11px 2px;
  gap: 10px;
  background: transparent;
}
.tf-row.mb-tf-row:last-child { border-bottom: none; }

/* ③ 标签与值：与预约单同款（标签 60px、字号 13px、灰字） */
.tf-row.mb-tf-row .tf-lbl { width: 60px; font-size: 13px; color: var(--text-2, #6b7280); flex: none; }
.tf-row.mb-tf-row .mb-tf-in {
  flex: 1; min-width: 0; border: none; background: transparent;
  font-size: 14px; color: var(--text, #1f2937); padding: 0;
  height: 24px; line-height: 24px;
}
.tf-row.mb-tf-row .mb-tf-in:focus { outline: none; }
.tf-row.mb-tf-row .mb-tf-in::placeholder { color: var(--text-3, #6b7280); }
.tf-row.mb-tf-row .mb-tf-val {
  flex: 1; min-width: 0; font-size: 14px; color: var(--text, #1f2937);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  /* R821:统一内容高度到 24px（与 .mb-tf-in 的 height:24px 对齐）。
     实测依据：不改这条时，输入型行 47px、文本型行（如"收货单位"）44px，
     差 3px —— 这正是"行高忽高忽低 / 收货单位看着不齐"的实测根因。
     改后 5 行统一 47px（Edge 无头实测，见 _patch/20260929/report_r821_matrix.js）。 */
  line-height: 24px;
}
.tf-row.mb-tf-row .mb-tf-val.is-empty { color: var(--text-3, #6b7280); }
/* R821b 防御：万一还有旧代码/旧缓存 HTML 拼出 `.mb-tf-val.empty`，
   这里显式复位被全局 `.empty` 污染的三个属性，杜绝「空值行变 166px」复发。 */
.tf-row.mb-tf-row .mb-tf-val.empty { color: var(--text-3, #6b7280); padding: 0; text-align: left; font-weight: 400; }
.tf-row.mb-tf-row .mb-tf-arrow { flex: none; color: var(--text-3, #6b7280); font-size: 17px; line-height: 1; }
/* 扁平行里的日期输入：右对齐淡色箭头提示"可点" */
.tf-row.mb-tf-row .mb-tf-in[data-datepick] { cursor: pointer; }

/* ============ R821 · 自绘日期选择面板（Mobile.dateSheet）============
   老板 2026-09-29 拍板方案 B：微信 X5 原生 <input type="date"> 由 shadow DOM 绘制，
   CSS 够不着（改配色/缩字号/换绿头都做不到），且占屏约 62%、头上一大块绿色、三个大按钮。
   改自绘底部面板：占屏约 36%，高度砍四成以上。

   设计对标：Material Design v3（底部面板 / 触控目标 ≥32dp / 必须支持键盘手输）
            + Accor Design System（mobile 一律 bottom sheet）
            + Apple HIG（触控底线 44px）
   配色沿用系统 CSS 变量（--primary 橙），与全站一致，不再有大绿头。 */

/* 遮罩与面板容器 */
#mpDateSheet { -webkit-tap-highlight-color: transparent; }
#mpDateSheet .ds-panel {
  background: var(--surface, #fff);
  border-radius: 14px 14px 0 0;
  display: flex; flex-direction: column;
  padding-bottom: env(safe-area-inset-bottom);
  animation: sheetUp .22s ease;
  max-height: 70dvh;
}

/* ① 顶部窄条：约 38px */
#mpDateSheet .ds-head {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 14px;
  border-bottom: 1px solid var(--border, #e2e8f0);
  flex: none;
}
#mpDateSheet .ds-title { font-size: 14px; font-weight: 600; color: var(--text, #1f2937); flex: none; }
#mpDateSheet .ds-tabs {
  display: flex; gap: 2px; margin-left: auto;
  background: var(--surface-2, #f1f5f9); border-radius: 8px; padding: 2px;
}
#mpDateSheet .ds-tab {
  font-size: 12px; padding: 4px 12px; border-radius: 6px;
  color: var(--text-2, #6b7280); cursor: pointer; line-height: 1.4;
}
#mpDateSheet .ds-tab.is-on { background: var(--surface, #fff); color: var(--primary, #f97316); font-weight: 600; box-shadow: 0 1px 2px rgba(15,23,42,.08); }
#mpDateSheet .ds-x {
  flex: none; width: 30px; height: 30px; display: flex; align-items: center; justify-content: center;
  color: var(--text-2, #6b7280); cursor: pointer; border-radius: 8px;
}
#mpDateSheet .ds-x:active { background: var(--surface-2, #f1f5f9); }
#mpDateSheet .ds-x svg { width: 17px; height: 17px; }

/* ② 快捷胶囊：约 34px */
#mpDateSheet .ds-quick {
  display: flex; gap: 8px; padding: 9px 14px 6px;
  flex: none; overflow-x: auto; -webkit-overflow-scrolling: touch;
}
#mpDateSheet .ds-quick::-webkit-scrollbar { display: none; }
#mpDateSheet .ds-chip {
  flex: none; font-size: 12.5px; padding: 5px 13px; border-radius: 999px;
  background: var(--surface-2, #f1f5f9); color: var(--text-2, #6b7280);
  cursor: pointer; line-height: 1.5; white-space: nowrap;
  border: 1px solid transparent;
}
#mpDateSheet .ds-chip:active { background: var(--primary-100, #ffedd5); color: var(--primary, #f97316); border-color: var(--primary-200, #fed7aa); }

/* ③ 主体 */
#mpDateSheet .ds-body { flex: 1; min-height: 0; overflow-y: auto; padding: 0 14px 4px; }

/* 日历条：‹ 2026 年 9 月 › */
#mpDateSheet .ds-cbar { display: flex; align-items: center; justify-content: space-between; padding: 4px 2px 6px; }
#mpDateSheet .ds-ym {
  font-size: 14px; font-weight: 600; color: var(--text, #1f2937); cursor: pointer;
  padding: 3px 10px; border-radius: 8px;
}
#mpDateSheet .ds-ym:active { background: var(--surface-2, #f1f5f9); }
#mpDateSheet .ds-nav {
  width: 32px; height: 32px; display: flex; align-items: center; justify-content: center;
  font-size: 20px; color: var(--text-2, #6b7280); cursor: pointer; border-radius: 8px; line-height: 1;
}
#mpDateSheet .ds-nav:active { background: var(--surface-2, #f1f5f9); }

/* 星期表头 */
#mpDateSheet .ds-wd { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; padding: 0 0 2px; }
#mpDateSheet .ds-wd span { text-align: center; font-size: 11px; color: var(--text-3, #94a3b8); padding: 2px 0; }

/* 日期格：7 列 */
#mpDateSheet .ds-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; padding-bottom: 6px; }
#mpDateSheet .ds-d {
  aspect-ratio: 1 / 1; display: flex; align-items: center; justify-content: center;
  font-size: 13.5px; color: var(--text, #1f2937); border-radius: 8px; cursor: pointer;
  max-height: 38px; min-height: 32px;
}
#mpDateSheet .ds-d:active { background: var(--surface-2, #f1f5f9); }
#mpDateSheet .ds-d.is-blank { cursor: default; }
#mpDateSheet .ds-d.is-today { color: var(--primary, #f97316); font-weight: 700; box-shadow: inset 0 0 0 1px var(--primary-200, #fed7aa); }
#mpDateSheet .ds-d.is-sel { background: var(--primary, #f97316); color: #fff; font-weight: 700; box-shadow: none; }

/* 手输区 */
#mpDateSheet .ds-text { padding: 14px 2px 4px; }
#mpDateSheet .ds-input {
  width: 100%; box-sizing: border-box; font-size: 17px; letter-spacing: .5px;
  padding: 12px 14px; border: 1px solid var(--border, #e2e8f0); border-radius: 10px;
  background: var(--surface-2, #f8fafc); color: var(--text, #1f2937); text-align: center;
  font-variant-numeric: tabular-nums;
}
#mpDateSheet .ds-input:focus { outline: none; border-color: var(--primary, #f97316); background: var(--surface, #fff); }
#mpDateSheet .ds-hint { font-size: 12px; color: var(--text-3, #94a3b8); text-align: center; margin-top: 8px; }

/* ④ 底部按钮：触控目标 ≥44px（Apple HIG / Material 底线） */
#mpDateSheet .ds-foot { display: flex; gap: 10px; padding: 10px 14px 14px; flex: none; }
#mpDateSheet .ds-btn {
  flex: 1; height: 44px; border-radius: 10px; font-size: 15px; font-weight: 600;
  cursor: pointer; border: 1px solid transparent;
}
#mpDateSheet .ds-btn-o { background: var(--surface, #fff); color: var(--text-2, #6b7280); border-color: var(--border, #e2e8f0); }
#mpDateSheet .ds-btn-o:active { background: var(--surface-2, #f1f5f9); }
#mpDateSheet .ds-btn-p { background: var(--primary, #f97316); color: #fff; }
#mpDateSheet .ds-btn-p:active { background: var(--primary-dark, #ea580c); }

/* 大屏（平板/桌面）下不需要摊满：限宽居中，观感更像"浮层"而非"抽屉" */
@media (min-width: 560px) {
  #mpDateSheet .ds-panel { max-width: 420px; margin: 0 auto 0; border-radius: 14px 14px 0 0; }
}

/* ===== R862 · 控制区分段槽 + 业务线图标（老板 2026-10-01 拍板 A1）=====
   问题：白底吸顶工具条上放浅灰胶囊（#f4f5f7 底 + #e5e7eb 边，与纯白只差 4% 亮度）⇒「灰上加灰」，
   形状全靠那圈边撑着；放大镜按钮更是白底白框。
   改法：一组胶囊装进浅灰「槽」，选中项变白块浮起来（iOS 分段控件形态）；业务线每格配图标
   （磅房=秤 / 自营=卡车 / 购销=箱子 / 采购=收货单，与弹抽屉的 iconOf 同一套），靠图标认线不只靠颜色。
   ★ 宽度策略（A1）：格子【不强制等分】（flex:0 0 auto 自然宽），槽本身 overflow-x:auto
      ⇒ 宽屏一屏放下、窄屏自动可横滑，避免「硬压到刚好、换个手机就挤爆」。
      实测（无头 Edge / 真 CSS）：@440 屏内容 412 = 容器 412（刚好放下）；@375 屏内容 405 > 347（滑一下）。
   注意：类名用专属的 .mp-chips-well —— 项目里已有一个 .mp-seg（弹窗里的分段按钮组），
   复用它会语义混淆、且将来有人给 .mp-seg 加更重的规则会误伤这里。本规则只作用于 .mp-sticky 内的 .mp-chips —— 下钻页与弹窗里的 mp-chips 不受影响。 */
.mp-sticky .mp-chips.mp-chips-well { background: #f1f3f5; border-radius: 13px; padding: 3px; gap: 3px; }
.mp-sticky .mp-chips.mp-chips-well .mp-chip { flex: 0 0 auto; background: transparent; border: 0; color: #4b5563; border-radius: 10px; height: 32px; padding: 0 8px; gap: 5px; font-size: 12px; font-weight: 400; }
/* R867 · 业务线升级为【多选】⇒ 选中态加一圈内描边（inset 阴影而非 border：不占宽度、不引起布局位移），
   让"可以同时选多个"这件事在视觉上成立 —— 否则多个白块并排会像是"高亮坏了"。 */
.mp-sticky .mp-chips.mp-chips-well .mp-chip.active { background: #fff; color: var(--primary); font-weight: 500; box-shadow: inset 0 0 0 1px var(--primary), 0 1px 2px rgba(15, 23, 42, .10); }
.mp-sticky .mp-chips.mp-chips-well .mp-chip svg { width: 15px; height: 15px; flex: 0 0 auto; }
.mp-sticky .mp-chips.mp-chips-well .mp-chip.active i { background: #fff7ed; color: #ea580c; }
/* 窄屏兜底：图标与内距各降一档，尽量一屏放下（实测 360px 屏可用约 332px） */
@media (max-width: 400px) {
  .mp-sticky .mp-chips.mp-chips-well .mp-chip { padding: 0 5px; gap: 4px; font-size: 11px; }
  .mp-sticky .mp-chips.mp-chips-well .mp-chip svg { width: 14px; height: 14px; }
}
/* ===== R870 · 紧凑表单与吸底操作栏 ===== */
/* label 内联：把"标签独占一行"压成一行 —— 用于车辆选择与过磅时间（省 22px/项） */
.mp-field.inline { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
.mp-field.inline > label { margin-bottom: 0; flex: 0 0 auto; }
.mp-field.inline > .mp-input, .mp-field.inline > .veh-combo { flex: 1 1 auto; min-width: 0; }
/* 毛/皮/净三格一行（375px 屏每格约 110px，文本可用约 82px；input 字号保持 16px 不变，防 iOS 聚焦缩放） */
.mp-grid3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 8px; margin-bottom: 12px; }
.mp-mini-lb { display: block; font-size: 12px; color: var(--text-2); margin-bottom: 5px; }
/* 详情/表单的吸底操作栏：sticky + 负 margin 抵消滚动区 18px 内边距，不改 sheet() 公共组件 */
.mp-sheet-foot { position: sticky; bottom: -18px; margin: 16px -18px -18px; padding: 10px 18px calc(10px + env(safe-area-inset-bottom)); background: var(--surface); border-top: 1px solid var(--border); display: flex; gap: 10px; }

/* ===== R871 · 手机端上传表单统一为「线条式」（甲案）=====
   老板 2026-10-03 拍板：甲案为统一标准，只改手机端、电脑端一行不动。
   为什么不去改 .photo-box / .photo-thumb 本身：它们被电脑端 9 处共用（pages-bill / pages-core /
   pages-invoice 的磅单照片、回单照片、行驶证、保险单、发票附件…），动类本身会把电脑端一起改掉。
   ⇒ 一律用「双类 / 后代选择器」把样式限定在手机端表单内，电脑端零影响。
   圆角收敛：本段把手机端表单内的圆角级别压到 3 级（外框 16 / 缩略块与下拉 9 / 下拉项 6），
   原先同屏混用 6 种（mp-input 11 · photo-box 10 · photo-thumb 10 · veh-pop 12 · veh-pop-item 9 · veh-pop-mine 6）。 */
.mp-ln { display: flex; align-items: center; gap: 10px; margin: 0 -18px; padding: 0 18px; min-height: 48px; border-top: 1px solid var(--border); }
.mp-ln > .mp-k { flex: 0 0 42px; font-size: 12px; color: var(--text-2); }
.mp-ln > .mp-v { flex: 1 1 auto; min-width: 0; }
.mp-ln > .mp-a { flex: 0 0 auto; font-size: 12px; color: var(--primary); cursor: pointer; padding: 4px 0 4px 6px; }
.mp-ln .mp-input { height: auto; min-height: 26px; border: none; border-radius: 0; padding: 0; background: transparent; font-weight: 500; }
.mp-ln .mp-input:focus { border-color: transparent; }
.mp-3col { display: flex; margin: 0 -18px; padding: 10px 18px 12px; border-top: 1px solid var(--border); }
.mp-3col > div { flex: 1 1 0; min-width: 0; }
.mp-3col > div + div { border-left: 1px solid var(--border); padding-left: 11px; }
.mp-3col .k { font-size: 12px; color: var(--text-2); margin-bottom: 3px; }
.mp-3col .mp-input { height: auto; min-height: 26px; border: none; border-radius: 0; padding: 0; background: transparent; font-size: 16px; font-weight: 500; }
.mp-3col .mp-input[readonly] { background: transparent; }
.photo-box.mp-shot { width: 56px; height: 56px; aspect-ratio: auto; border-radius: 9px; border-width: 1px; flex: 0 0 auto; display: flex; align-items: center; justify-content: center; }
.photo-box.mp-shot .photo-thumb { width: 100%; height: 100%; aspect-ratio: auto; border-radius: 9px; cursor: zoom-in; }
.mp-shot-tip { font-size: 12px; color: var(--text-2); }
/* R1127 · 磅单上传抽屉的照片位改整行（老板 2026-10-29：手机上 56×56 看不清单子上的字）。
   只给这一处加 .mp-shot-wide，**不动 .mp-shot 本体** —— 它被磅单/C双磅单/自提/发货单 4 处共用，
   全局改会把别人的布局一起顶乱。object-fit:contain ⇒ 按原比例显示、不裁切（原型 v7 要求）。 */
.photo-box.mp-shot.mp-shot-wide { width: 100%; height: auto; min-height: 132px; aspect-ratio: auto; flex: 1 1 auto; }
.photo-box.mp-shot.mp-shot-wide .photo-thumb { width: 100%; height: auto; max-height: 42vh; aspect-ratio: auto; object-fit: contain; background: #f3f4f6; }
/* R1128 · 磅单上传的「毛重/皮重/净重」三格（照原型 v7 落地）
   为什么不用 .mp-3col：① 数字左对齐 ⇒ 104.50 比 25.12 宽，三列重心不齐；
   ② 竖线从标签贯穿到底像压在字上；③ 数字贴竖线没呼吸感；④ 净重只读却长得能改。
   改法：浅底圆角格 + 数字居中 + 等宽数字(tabular-nums) + 净重绿底标「自动算」。
   ⚠️ .mp-3col 被 4 处共用（uploadBill/_dualBody/ticketSheet/wbRecord），这里只新增 .w3，不碰它。 */
.w3 { display: flex; gap: 8px; margin: 12px 0 4px; }
.w3 .cell { flex: 1 1 0; min-width: 0; background: var(--surface-2); border-radius: 10px;
  padding: 9px 6px 8px; text-align: center; border: 1px solid transparent; transition: .12s; }
.w3 .cell:focus-within { border-color: var(--primary); background: var(--surface); }
.w3 .k { font-size: 11.5px; color: var(--text-2); margin-bottom: 4px; white-space: nowrap;
  display: flex; align-items: center; justify-content: center; gap: 3px; }
.w3 .v { display: block; }
.w3 input { width: 100%; min-width: 0; border: none; background: transparent; outline: none;
  text-align: center; font-size: 17px; font-weight: 600; color: var(--text); padding: 0;
  box-sizing: border-box; font-variant-numeric: tabular-nums; font-feature-settings: "tnum"; }
.w3 input::placeholder { font-weight: 400; color: #c3c8d2; }
.w3 .u { font-size: 9.5px; color: var(--text-3); opacity: .8; }
.w3 .cell.auto { background: #f0fdf4; border-color: #d1fae5; }
.w3 .cell.auto input { color: #15803d; cursor: default; }
.w3 .tag { font-size: 9.5px; font-weight: 700; color: #15803d; background: #dcfce7;
  border-radius: 3px; padding: 0 3px; line-height: 1.6; }
.w3 .cell.bad { border-color: #fecaca; background: #fef2f2; }
.w3 .cell.bad input { color: #b91c1c; }
.w3 .tag.tbad { color: #b91c1c; background: #fee2e2; }

/* ══ R1129 · 磅单上传「拍照识别」这条路的专属件（照原型 v7 原文）══ */
/* 识别中：转圈状态条 */
.ocr-bar { margin: 10px 0 0; padding: 10px 12px; border-radius: 10px; background: var(--surface-2);
  border: 1px solid var(--border); font-size: 12px; color: var(--text-2); display: flex; align-items: center; gap: 9px; }
.ocr-spin { width: 14px; height: 14px; border: 2px solid var(--border); border-top-color: var(--primary);
  border-radius: 50%; animation: co-sp .7s linear infinite; flex: 0 0 auto; }
@keyframes co-sp { to { transform: rotate(360deg); } }
/* 顶部大拍照区（未拍） */
.shot-big { width: 100%; aspect-ratio: 16/10; border-radius: 12px; border: 2px dashed var(--primary);
  background: var(--surface-2); display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 7px; color: var(--text-3); cursor: pointer; position: relative; overflow: hidden; transition: .15s; margin-bottom: 10px; }
.shot-big .t1 { font-size: 14px; font-weight: 600; }
.shot-big .t2 { font-size: 11.5px; opacity: .85; }
.shot-big svg { width: 30px; height: 30px; }
/* 拍照区里的两个入口 */
.sh-acts { display: flex; gap: 8px; margin-top: 12px; width: 100%; }
.sh-a { flex: 1; height: 38px; border-radius: 9px; border: 1px solid var(--border); background: var(--surface);
  color: var(--text); font-size: 12.5px; font-weight: 600; cursor: pointer;
  display: flex; align-items: center; justify-content: center; gap: 5px; }
.sh-a:active { background: var(--surface-2); }
.sh-a svg { width: 15px; height: 15px; }
/* 已拍大图：按原比例、不裁 */
.pb-wide { width: 100%; height: auto; aspect-ratio: auto; border: 1px solid var(--green); border-radius: 9px;
  overflow: hidden; background: #E8ECF3; padding: 0; display: block; cursor: zoom-in; line-height: 0; }
.pb-wide img { display: block; width: 100%; height: auto; }
/* 识别成功提示 */
.hint-line { font-size: 11.5px; color: #b45309; margin-top: 5px; display: flex; gap: 5px; align-items: flex-start; line-height: 1.55; }
.hint-line .dot { flex: 0 0 auto; margin-top: 1px; }
/* 识别失败卡 */
.pb-fail { background: #fef2f2; border: 1px solid #fecaca; border-radius: 10px; padding: 10px 12px; margin: -4px 0 12px; }
.pb-fail .t { font-size: 12.5px; color: #b91c1c; font-weight: 700; }
.pb-fail .d { font-size: 11.5px; color: #7f1d1d; margin-top: 4px; line-height: 1.65; }
.pb-fail .acts { display: flex; gap: 8px; margin-top: 9px; }
.pb-fail .acts button { flex: 1; height: 34px; border-radius: 8px; font-size: 12.5px; font-weight: 600; cursor: pointer; border: 1px solid; }
.pb-fail .acts .r { background: #fff; border-color: #fecaca; color: #b91c1c; }
.pb-fail .acts .m { background: var(--primary); border-color: var(--primary); color: #fff; }
/* 与订单核对区（只提示） */
.chl { margin: 10px 0 2px; border-radius: 9px; padding: 9px 11px; font-size: 11.5px; line-height: 1.6; }
.chl.ok { background: #f0fdf4; border: 1px solid #d1fae5; color: #15803d; display: flex; align-items: center; gap: 6px; }
.chl.ok i { flex: 0 0 auto; width: 13px; height: 13px; border-radius: 50%; background: #16a34a; color: #fff;
  font-style: normal; font-size: 9.5px; font-weight: 800; display: flex; align-items: center; justify-content: center; line-height: 1; }
.chl.warn { background: #fffbeb; border: 1px solid #fde68a; }
.chl.warn .r { display: flex; align-items: center; gap: 6px; padding: 3px 0; color: #78350f; }
.chl.warn .r i { flex: 0 0 auto; width: 13px; height: 13px; border-radius: 50%; background: #f59e0b; color: #fff;
  font-style: normal; font-size: 9.5px; font-weight: 800; display: flex; align-items: center; justify-content: center; line-height: 1; }
.chl.warn .lb { flex: 0 0 52px; color: #92400e; white-space: nowrap; }
.chl.warn .vv { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }
.chl.warn .st { flex: 0 0 auto; font-size: 10px; color: #b45309; max-width: 44%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chl.warn .note { font-size: 10px; color: #a16207; margin-top: 5px; padding-top: 5px; border-top: 1px dashed #fde68a; }
.veh-combo .veh-pop { border-radius: 9px; }
.veh-combo .veh-pop-item { border-radius: 6px; }

/* ===== R875 · 审核台趟条 / 详情关键数字条 ===== */
.dual-tripno { font-size: 11px; padding: 1px 7px; border-radius: 8px; background: var(--primary-light); color: var(--primary-dark); font-weight: 600; white-space: nowrap; }
.dual-trip { border-radius: 10px; }
/* 详情骨架自适应列：宽屏两列、窄屏（手机 375px）自动单列 —— 避免电脑端 grid-2 在手机上横向溢出 */
.bill-skel { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 10px 18px; align-items: start; }
.bill-skel > * { min-width: 0; }
.bill-skel dd { word-break: break-word; }

/* ===== R876 · 详情页重排（消除留白）+ 手机端紧凑键值 =====
   电脑端：.bill-top 让「徽标 + 键值」与照片同行；.bill-kv2 每行两对、.bill-kv3 每行三对。
   手机端：.mp-kv2 每行两对、.mp-kv3 每行三格（均双类限定，绝不动 .mp-kv 本体）。 */
.bill-top { display: flex; align-items: flex-start; gap: 16px; }
.bill-top-main { flex: 1 1 auto; min-width: 0; }
.bill-top-photo { flex: 0 0 200px; width: 200px; min-width: 0; }
.bill-kv2, .bill-kv3 { display: grid; margin: 0; gap: 6px 14px; }
.bill-kv2 { grid-template-columns: auto minmax(0, 1fr) auto minmax(0, 1fr); }
.bill-kv3 { grid-template-columns: auto minmax(0, 1fr) auto minmax(0, 1fr) auto minmax(0, 1fr); }
.bill-kv2 dt, .bill-kv3 dt { color: var(--text-2); font-size: 13px; }
.bill-kv2 dd, .bill-kv3 dd { margin: 0; font-size: 14px; font-weight: 500; min-width: 0; word-break: break-word; }
.mp-kv2 { display: grid; grid-template-columns: 1fr 1fr; column-gap: 10px; }
.mp-kv2 .mp-kv { padding: 3px 0; min-width: 0; align-items: flex-start; }
/* 值允许折行 —— 不截断（合同号 / 金额算式都是核对要素，截断等于丢信息，老板反复强调过） */
.mp-kv2 .mp-kv > span:last-child { overflow-wrap: anywhere; }
.mp-kv3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0 8px; }
.mp-kv3 .mp-kv { display: block; padding: 3px 0; min-width: 0; text-align: center; }
.mp-kv3 .mp-kv .k { display: block; margin-bottom: 2px; }
.mp-kv3 .mp-kv > span:last-child { display: block; text-align: center; }

/* ===== R882 · 手机端详情：分组标题 + 整行键值 + 关键数值强调（老板 2026-10-03 截图反馈）=====
   三个问题一起收：
     ① 「布局不合理」—— 值较长的键值（关联合同 / 运费结算给）挤在半格 ⇒ 折行错位；
     ② 「键值中间空一片」—— .mp-kv 是 space-between，标签贴左值贴右，短值中间全空；
     ③ 「没有对比色」—— 分组标题与关键数值都是灰字，整页无重点。
   三条规则全部【新类限定】，不动 .mp-kv / .mp-kv2 / .mp-kv3 本体（手机端其它页面零影响）。 */

/* ① R884 · 【分段卡】：页面中灰底 + 每段一块白卡（老板从四版方案里圈定「丙案 · 丙二档」）
   —— 段标题＝橙左竖条 + 标题字重，「条」与「内容」同属一块白卡；零边框零分隔线，
      分区只靠「底色差 + 一条橙竖条」。替换 R882 的 .mp-sec（那条是"裸标题"，无卡无内容归属）。
   ⚠️ 全部只作用于 .mp-flat 内部（手机端磅单详情专属），不动 sheet() 公共组件与其它页面。 */
.mp-flat { background: #E7EAEF; margin: -18px -18px calc(-18px - env(safe-area-inset-bottom)) -18px; padding: 14px 14px 18px; }
.mp-fbadges { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; padding: 0 2px 10px; }
.mp-fsec { background: var(--surface); border-radius: 12px; margin-bottom: 9px; }
.mp-fbar { display: flex; align-items: center; gap: 7px; padding: 11px 13px 3px;
  font-size: 12.5px; font-weight: 600; color: #374151; letter-spacing: .01em; }
.mp-fbar::before { content: ''; flex: none; width: 3px; height: 11px; border-radius: 2px; background: var(--primary); }
.mp-fbar .rt { margin-left: auto; font-size: 11.5px; font-weight: 400; color: var(--text-2);
  max-width: 62%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mp-fbody { padding: 4px 13px 12px; }
.mp-fphoto { display: flex; align-items: center; gap: 12px; }
/* 吸底操作栏：本页外层多了 .mp-flat（14px 左右内边距 + 18px 底内边距）⇒ 负 margin 必须按新基准重算，
   否则按钮组会顶出 sheet 面板边界。（公共 .mp-sheet-foot 是给"无 .mp-flat 包裹"的页面用的，本体不动。） */
.mp-flat .mp-sheet-foot { position: sticky; bottom: 0; margin: 14px -14px -18px;
  padding: 10px 14px calc(10px + env(safe-area-inset-bottom)); }

/* ② 整行键值：标签固定列 + 值【左对齐】—— 值有整行宽度不折行，且不再中间空一片 */
.mp-kv.mp-kv-row { display: flex; align-items: flex-start; gap: 0; }
.mp-kv.mp-kv-row > .k { flex: 0 0 74px; width: 74px; }
.mp-kv.mp-kv-row > span:last-child { flex: 1 1 auto; min-width: 0; text-align: left; }

/* ③ 关键数值强调色（净重 / 货物价值 / 运费） */
.mp-num { color: var(--primary-dark); }
@media (max-width: 620px) {
  .bill-top { flex-direction: column; }
  .bill-top-photo { flex: 0 0 auto; width: 100%; }
  .bill-kv2, .bill-kv3 { grid-template-columns: auto minmax(0, 1fr); }
}

/* ===== R880 · 抽屉/弹窗体系规范（现代简约） ===== */
/* 页头右侧工具区（配合 openModal 第 10 参数 headExtra；不传时结构完全同旧版） */
.modal-head .mh-right { margin-left: auto; display: flex; align-items: center; gap: 2px; }
.modal-head .mh-right .x { margin-left: 0; }
.mh-tool { width: 30px; height: 30px; border: 0; border-radius: 8px; background: transparent; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; color: #9CA3AF; }
.mh-tool:hover { background: #F3F4F6; color: #4B5563; }
.mh-more { position: relative; display: inline-block; }
.mh-menu { display: none; position: absolute; right: 0; top: 34px; z-index: 9; min-width: 156px; padding: 5px;
  background: #fff; border: 1px solid #EEF0F3; border-radius: 10px; box-shadow: 0 8px 24px rgba(16,24,40,.10); }
.mh-more.open .mh-menu { display: block; }
.mh-menu button { display: block; width: 100%; padding: 8px 10px; border: 0; border-radius: 7px; background: transparent;
  font-family: inherit; font-size: 13px; text-align: left; color: #374151; cursor: pointer; }
.mh-menu button:hover { background: #F9FAFB; }
.mh-menu button.is-danger { color: #DC2626; }
.mh-menu .sep { height: 1px; margin: 4px 6px; background: #F1F3F5; }

/* 状态进度条 */
.dlg-steps { display: flex; align-items: center; gap: 9px; margin: 0 0 16px; font-size: 12.5px; color: #9CA3AF; }
.dlg-steps .st { display: flex; align-items: center; gap: 6px; white-space: nowrap; }
.dlg-steps .st::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: #D8DBE0; }
.dlg-steps .st.is-done { color: #059669; }
.dlg-steps .st.is-done::before { background: #059669; }
.dlg-steps .st.is-on { color: #C2410C; font-weight: 500; }
.dlg-steps .st.is-on::before { background: #F97316; box-shadow: 0 0 0 3px rgba(249,115,22,.13); }
.dlg-steps i { flex: 0 0 auto; width: 26px; height: 1px; background: #F1F3F5; }

/* 后果说明（审批类必给 —— 让用户知道"点下去会发生什么"） */
.dlg-hint { display: flex; gap: 8px; align-items: flex-start; margin: 0 0 14px; padding: 11px 13px;
  background: #F9FAFB; border-radius: 9px; font-size: 12.5px; line-height: 1.6; color: #4B5563; }
.dlg-hint svg { flex: none; margin-top: 1.5px; color: #9CA3AF; }
.dlg-hint b { font-weight: 500; color: #111827; }

/* 条件选项（替代原来平级的「跳过运费」按钮） */
.dlg-opt { display: flex; align-items: center; gap: 9px; margin: 0 0 14px; font-size: 13.5px; color: #374151; cursor: pointer; }
.dlg-opt input { flex: none; width: 16px; height: 16px; margin: 0; accent-color: #F97316; }

/* 操作区：左＝次要（破坏性最左），右＝主要（≤2） */
.act-foot { display: flex; flex: 1 1 auto; align-items: center; justify-content: space-between; gap: 12px; }
.act-foot .L, .act-foot .R { display: flex; align-items: center; gap: 10px; min-width: 0; }
.act-foot .btn { height: 40px; padding: 0 18px; border: 1px solid #E5E7EB; border-radius: 9px; background: #fff;
  font-size: 14px; font-weight: 500; color: #4B5563; box-shadow: none; }
.act-foot .btn:hover { background: #F9FAFB; border-color: #D1D5DB; }
.act-foot .btn.danger { color: #DC2626; }
.act-foot .btn.main { background: #F97316; border-color: #F97316; color: #fff; padding: 0 24px;
  box-shadow: 0 1px 2px rgba(249,115,22,.22); }
.act-foot .btn.main:hover { background: #EA580C; border-color: #EA580C; }
@media (max-width: 820px) {
  .act-foot .L, .act-foot .R { flex: 1 1 0; }
  .act-foot .L .btn, .act-foot .R .btn { flex: 1 1 0; min-width: 0; padding: 0 10px; }
  .act-foot .L .btn:only-child, .act-foot .R .btn:only-child { flex: 0 1 auto; padding: 0 20px; }
}
@media (max-width: 480px) {
  .act-foot { flex-direction: row; flex-wrap: wrap; gap: 8px; }
  .act-foot .L, .act-foot .R { flex: 1 1 100%; gap: 8px; }
  .act-foot .L .btn, .act-foot .R .btn { flex: 1 1 0; min-width: 0; padding: 0 8px; }
  .act-foot .L .btn:only-child, .act-foot .R .btn:only-child { flex: 1 1 100%; padding: 0 12px; }
}
/* ===== R881 · 抽屉操作区统一（决策成组靠右 · 按钮加大分层）+ R879 规范补课 =====
   背景：R880 第一批把「磅单详情 · 审核」做成「左次要 / 右主要」左右分区。
   真机/实测判定：760px 抽屉里两个按钮各贴一边、中间空 490px，「位置大小都不合理」。
   ⇒ R881 改为【成组靠右】：破坏性在主操作左侧、两者相邻（间距 20px），并统一加大按钮。
   安全：全部限定在 .modal--drawer 之下；不传 headExtra 的老调用页头逐字节不变；
        .modal--drawer 以外的弹窗（表单/确认框）本轮一律不动。 */

/* ① 抽屉标题：15px / 500 字重（R879 规范：不再用 700） */
.modal--drawer .modal-head h3 { font-size: 15px; font-weight: 500; letter-spacing: -.01em; }

/* ② 键值：标签右对齐 + 值左对齐（专业业务软件做法，形成整齐列） */
.modal--drawer .modal-body .dl dt { text-align: right; }

/* ③ 徽标：6px 方角（R879 规范禁胶囊），字重 500 */
.modal--drawer .modal-body .badge { border-radius: 6px; font-weight: 500; }

/* ④ 底部操作区：决策【居中】+ 两个按钮【等宽】（次要与主操作同尺寸 112×40，主次靠颜色区分）
   R882 · 老板 2026-10-03 截图反馈：①「没有居中」②「大小不至于 2（挡）」。
   旧值：.modal-foot 靠右(flex-end)、次要 min-width 96 / 主操作 min-width 128 ⇒ 两个按钮既贴右又不等宽。
   ⚠️ 两条链都要改：磅单详情·审核走 .act-foot（左 .L / 右 .R 两个分组），
      其余抽屉的按钮是 .modal-foot 直挂 —— 只改一条另一半不生效。 */
.modal--drawer .modal-foot { justify-content: center; gap: 10px; }
.modal--drawer .act-foot { display: flex; flex-direction: row; flex: 0 0 auto; align-items: center; justify-content: center; gap: 10px; }
.modal--drawer .act-foot .L, .modal--drawer .act-foot .R { display: flex; flex: 0 0 auto; align-items: center; gap: 10px; min-width: 0; }
.modal--drawer .act-foot .L:empty { display: none; }
.modal--drawer .modal-foot .btn { flex: 0 0 auto; margin: 0; height: 40px; min-width: 112px; padding: 0 20px;
  border: 1px solid #E5E7EB; border-radius: 9px; background: #fff; font-size: 14px; font-weight: 500;
  color: #4B5563; box-shadow: none; }
.modal--drawer .modal-foot .btn:hover { background: #F9FAFB; border-color: #D1D5DB; }
.modal--drawer .modal-foot .btn.danger { color: #DC2626; }
/* R882 · 主操作与次要【同尺寸】—— 主次靠【橙底】区分，不靠尺寸（老板：「大小不至于 2」） */
.modal--drawer .modal-foot .btn.main { min-width: 112px; padding: 0 20px; background: #F97316;
  border-color: #F97316; color: #fff; box-shadow: 0 1px 2px rgba(249,115,22,.22); }
.modal--drawer .modal-foot .btn.main:hover { background: #EA580C; border-color: #EA580C; }

@media (max-width: 480px) {
  /* ⑤ 状态进度条：窄屏不截断（R880 遗留缺陷 —— 375px 实测溢出 37px，修后 0px） */
  .dlg-steps { flex-wrap: wrap; gap: 6px 8px; font-size: 11.5px; }
  .dlg-steps .st { gap: 5px; }
  .dlg-steps i { flex: 1 1 8px; width: auto; min-width: 8px; max-width: 22px; }

  /* ⑥ 手机端底部：两按钮【全宽上下堆叠】（次要在上、主操作在下靠近拇指）
     —— 沿用平台既有行为（公共规则本就为这个形态准备），不跟 flex/grid 较劲 */
  .modal--drawer .modal-foot { display: block; }
  .modal--drawer .act-foot { display: block; }
  .modal--drawer .act-foot .L, .modal--drawer .act-foot .R { display: block; }
  .modal--drawer .act-foot .L { margin-bottom: 8px; }
  .modal--drawer .act-foot .R .btn { margin-bottom: 0; }
  .modal--drawer .modal-foot .btn { width: 100%; min-width: 0; padding: 0 12px; }
  .modal--drawer .modal-foot > .btn { margin: 0 0 8px; }
  .modal--drawer .modal-foot > .btn:last-child { margin-bottom: 0; }

  /* ⑦ 窄屏下抽屉正文里「写死两列」退回一列（真实渲染实测：订单详情 375px 两列被横向裁掉） */
  .modal--drawer .modal-body [style*="grid-template-columns:1fr 1fr"],
  .modal--drawer .modal-body [style*="grid-template-columns: 1fr 1fr"] { grid-template-columns: 1fr !important; }
}

/* ==================================================================
   R914 · 手机端新建表单「乙案 · 填充块风」视觉重构（纯样式覆盖，零 JS 改动）
   ------------------------------------------------------------------
   作用范围：仅 #mpSheet（手机端底部抽屉）内的表单。电脑端与其它弹窗零影响
            （#mpSheet 只在移动壳里存在）。
   做法：不碰任何 DOM 结构与 JS —— 只覆盖 R827 / R911 / R912 / R913 建立的
        「单列扁平行（标签左 96px→72px + 值贴右/贴标签 + 无框透明底）」为
        「卡片白 + 标签在上 + 灰填充块（可填/只读一眼可分）」。
   ⚠️ 本块生效后，R913 的「标签等宽 72px + 值紧跟标签」扁平行被整体替换；
      原规则仍留在文件中（约 2120-2255 行区间），仅不再产生视觉效果，便于回退。
   对比关系（机器实测，核算脚本见 _核算/对比度核算.js，非目测）：
      卡片白 #FFFFFF  ↔  填充块 #E8ECF3  =  1.185 : 1
        （旧方案 #F2F4F7 仅 1.102 —— 这正是"对比不明显"的量化来源）
      填充块描边 #DDE3EC  vs  白卡      =  1.290 : 1（底色差 + 描边，双重界定）
      主文字 #0F172A on 填充块 = 15.5 : 1 ｜ 字段标签 #6B7280 = 4.4 : 1（均达 WCAG AA）
   ================================================================== */

/* ① 抽屉底与内容区（这两个元素带内联样式，必须加 !important 才盖得住） */
#mpSheet .mp-sheet-panel { background: #F4F5F8 !important; }
#mpSheet .mp-sheet-scroll { padding: 12px !important; padding-bottom: calc(12px + env(safe-area-inset-bottom)) !important; }

/* ② 订单页族（.mp-form-sec）卡片化 */
#mpSheet .mp-form-sec { background: #fff; border: none; border-radius: 18px; padding: 13px 13px 4px; margin-bottom: 11px; box-shadow: 0 1px 3px rgba(16, 24, 40, .06); }
#mpSheet .mp-form-sec-t { display: flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 700; color: #0F172A; margin: 0 0 11px; }
#mpSheet .mp-form-sec-t::before { content: ''; flex: none; width: 6px; height: 6px; border-radius: 2px; background: var(--primary, #f97316); }

/* ③ 三表单族（.fm）卡片化 */
#mpSheet .fm { background: transparent; margin: 0; padding: 0; }
#mpSheet .fm .fm-sec { background: #fff; border-radius: 18px; padding: 13px 13px 4px; margin-bottom: 11px; box-shadow: 0 1px 3px rgba(16, 24, 40, .06); }
#mpSheet .fm .fm-bar { padding: 0 0 11px; font-size: 12.5px; font-weight: 700; color: #0F172A; }
#mpSheet .fm .fm-bar::before { display: inline-block; width: 6px; height: 6px; border-radius: 2px; background: var(--primary, #f97316); }
#mpSheet .fm .fm-body { padding: 0; }

/* ④ 字段栅格改成单列 + 行改「标签在上」的块（覆盖扁平行） */
#mpSheet .mp-form-sec .form-grid,
#mpSheet .mp-form-sec .form-grid.cols3,
#mpSheet .fm .form-grid,
#mpSheet .fm .form-grid.cols3 { display: grid; grid-template-columns: 1fr; gap: 0; background: transparent; border-radius: 0; overflow: visible; }
#mpSheet .mp-form-sec .form-grid > div,
#mpSheet .mp-form-sec .form-grid > div.is-fill,
#mpSheet .fm .form-grid > div,
#mpSheet .fm .form-grid > div.is-fill { display: block; border: 0; padding: 0; margin: 0 0 10px; min-height: 0; flex-wrap: nowrap; }
#mpSheet .mp-form-sec .form-grid > div > label,
#mpSheet .mp-form-sec .form-grid > div.is-fill > label,
#mpSheet .fm .form-grid > div > label,
#mpSheet .fm .form-grid > div.is-fill > label { display: block; width: auto; flex: none; font-size: 11.5px; line-height: 1.4; color: #6B7280; margin: 0 0 5px 3px; white-space: normal; overflow: visible; text-overflow: clip; }

/* ⑤ 填充块 · 可填（input / select）—— 底色差 + 1px 描边 = 1.185 / 1.290 双重界定 */
#mpSheet .mp-form-sec .form-grid > div > .input,
#mpSheet .mp-form-sec .form-grid > div.is-fill > .input,
#mpSheet .fm .form-grid > div > .input { display: block; width: 100%; max-width: none; flex: none; height: 45px; min-height: 45px; margin: 0; box-sizing: border-box; background: #E8ECF3 !important; border: 1px solid #DDE3EC !important; border-radius: 12px; padding: 0 13px; font-size: 14.5px; color: var(--text, #1f2937) !important; text-align: left; }
#mpSheet .mp-form-sec .form-grid > div > select.input,
#mpSheet .fm .form-grid > div > select.input { text-align: left; }

/* ⑤b 填充块 · 可点选择器（.picker-field 是 div，需 flex 垂直居中） */
#mpSheet .mp-form-sec .form-grid > div > .picker-field,
#mpSheet .fm .form-grid > div > .picker-field { display: flex; align-items: center; justify-content: flex-start; width: 100%; height: 45px; min-height: 45px; flex: none; margin: 0; box-sizing: border-box; background: #E8ECF3; border: 1px solid #DDE3EC; border-radius: 12px; padding: 0 26px 0 13px; font-size: 14.5px; color: var(--text-3, #6b7280); text-align: left; }
#mpSheet .mp-form-sec .form-grid > div > .picker-field::after,
#mpSheet .fm .form-grid > div > .picker-field::after { right: 13px; color: #98A2B3; }

/* ⑥ 只读（合同带出 / 日期）：去掉描边 + 灰字 —— 与"可填"一眼分开 */
#mpSheet .mp-form-sec .form-grid > div > .input[readonly],
#mpSheet .mp-form-sec .form-grid > div > .input[disabled],
#mpSheet .fm .form-grid > div > .input[readonly],
#mpSheet .fm .form-grid > div > .input[disabled] { background: #E8ECF3 !important; border-color: transparent !important; color: #7A8494 !important; }

/* ⑦ 聚焦态：橙底 + 橙边 + 橙光晕 */
#mpSheet .mp-form-sec .form-grid > div > .input:focus,
#mpSheet .mp-form-sec .form-grid > div.is-fill > .input:focus,
#mpSheet .fm .form-grid > div > .input:focus { background: #FFF7ED !important; border-color: var(--primary, #f97316) !important; box-shadow: 0 0 0 3px rgba(249, 115, 22, .13); color: #DE5A0B !important; }
#mpSheet .mp-form-sec .form-grid > div > .input::placeholder,
#mpSheet .fm .form-grid > div > .input::placeholder { color: #8A94A6; }

/* ⑧ 三格一行：合同信息（甲方 / 客户 / 货品）、拉运安排（预估吨位 / 有效期起 / 有效期止）
      —— 375px 下每格 96px、可用 74px：日期字号须 ≤13px（13.5px 实测被截掉末位） */
#mpSheet .mp-form-sec .form-grid.cols3 { grid-template-columns: repeat(3, 1fr); gap: 8px; }
#mpSheet .mp-form-sec .form-grid.cols3 > div { margin-bottom: 10px; }
#mpSheet .mp-form-sec .form-grid.cols3 > div > label { margin-left: 2px; font-size: 11px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#mpSheet .mp-form-sec .form-grid.cols3 > div > .input,
#mpSheet .mp-form-sec .form-grid.cols3 > div > .picker-field { height: 45px; min-height: 45px; padding-left: 10px; padding-right: 10px; font-size: 12.5px; }
#mpSheet .mp-form-sec .form-grid.cols3 > div > .picker-field { padding-right: 22px; }
#mpSheet .mp-form-sec .form-grid.cols3 > div > .picker-field::after { right: 8px; }
#mpSheet .mp-form-sec .form-grid.cols3 .field-hint { font-size: 10px; line-height: 1.45; margin-top: 4px; }
/* ================= R978 · 订单抽屉字段区：长值整行 / 短值两格 =================
   改前实测（390px 宽、真 CSS 渲染、无头 Edge）：
     「合同信息」grid-template-columns = 108px 108px 108px；
     甲方控件可用 106px 而内容需要 170px、客户需要 183px ⇒ 公司全名被截掉约 5~6 个字。
   同源病：R970 给「预约单」诊断出的"字段被压"（R972 已修），订单抽屉未修 —— 姊妹面未对齐。
   做法：长值字段（甲方/客户/货品、供货方/收货方）⇒ 整行。
   ⚠️ 只动「合同信息 / 订单信息」这一组：改前实测「拉运安排」三格（108px）本身不截断
      （日期值 106px ≤ 可用 106px）⇒ R979 撤掉了 R978 多改的两格覆盖（会留半行豁口）。
   ⚠️ 只作用于 #mpSheet（手机端抽屉）；电脑端 .form-grid.cols3 三列一字不动。 */
@media (max-width: 820px) {
  #mpSheet .mp-form-sec .form-grid.cols3.of-grid-long { grid-template-columns: 1fr; }
  #mpSheet .mp-form-sec .form-grid.cols3.of-grid-long > div > label { white-space: normal; overflow: visible; text-overflow: clip; }
}

/* ==================================================================
   R981 · 手机端「新建订单」抽屉：字段区改「标签左 / 值右」行式卡片
   ------------------------------------------------------------------
   老板 2026-10-08 拍板：与「可交互原型 V5」布局一致（选②常驻可填）。
   改前实测（390px 真 CSS 渲染）：每字段 = 标签独占一行 + 45px 灰底填充块 = 65px。
   改后 = 44px/字段、值右对齐、无外框 ⇒ 整列 740 → 632px（矮 108px），
        且长公司名不再被截断（R978 只修了「合同信息」，本轮统一到全部区块）。
   ⚠️ 作用域严格限定 #mpSheet（手机端抽屉）：电脑端 .form-grid.cols3 一字不动。
   ⚠️ 必须带 !important —— 本区既有规则（2763 填充块 / 2769 picker / 2822 车牌）本身带
      !important，同级特异性下不带则盖不住。 */

/* ① 区块 = 白卡（圆角 + 细边 + 微阴影） */
#mpSheet .mp-form-sec { background:#fff !important; border:1px solid #e9eef5 !important; border-radius:14px !important; padding:0 0 4px !important; margin:0 0 10px !important; box-shadow:0 1px 3px rgba(16,24,40,.06) !important; overflow:hidden; }
/* ② 区块头：标题 + 完成度徽标同一行 */
#mpSheet .mp-form-sec-t { display:flex !important; align-items:center !important; gap:7px !important; padding:12px 13px 9px !important; margin:0 !important; font-size:13px !important; font-weight:700 !important; color:#0f172a !important; }
#mpSheet .of-badge { flex:none; font-size:10.5px; font-weight:600; border-radius:999px; padding:1px 7px; }
#mpSheet .of-badge.ok { background:#dcfce7; color:#15803d; }
#mpSheet .of-badge.pd { background:#f1f5f9; color:#64748b; }
/* ③ 字段行：标签左 / 值右（覆盖「标签在上 + 灰底填充块」）
   ⚠️ 必须先让父容器 .form-grid 从「grid 三列」回到块级 —— 只改子项 display:flex 不够：
      子项仍被栅格摆在 3 列里 ⇒ 三个字段会挤在同一行（R981 真渲染实测）。
      既有 2154（单列）与 2788（repeat(3,1fr)）两条都设了 display:grid，故此处必须显式 block。 */
#mpSheet .mp-form-sec .form-grid,
#mpSheet .mp-form-sec .form-grid.cols3 { display:block !important; }
#mpSheet .mp-form-sec .form-grid > div,
#mpSheet .mp-form-sec .form-grid > div.is-fill { display:flex; flex-wrap:wrap !important; align-items:center !important; gap:10px !important; min-height:44px !important; padding:0 13px !important; margin:0 !important; border:0 !important; border-bottom:1px solid #f1f5f9 !important; }
/* R993 · 非控件子元素独占整行 —— 与「.fm 版」同源（本文件 L935 早有这条，#mpSheet 版一直漏）。
   漏掉的后果（老板真机截图 + 390px 真 CSS 实测复现）：D 模式「是否关联外部运输」那一行里，
   .mp-seg 按钮组 与 .text-2 说明文字都没有规则 ⇒ 与 label / 控件抢宽度，而 flex 默认 nowrap
   ⇒ 两者被压到「一字宽」、中文逐字竖排（实测 .mp-seg 整块只剩 51px、说明文字只剩 135px）。
   加后实测：.mp-seg 302px、两按钮各 147px、说明文字 302px ⇒ 恢复正常。 */
#mpSheet .mp-form-sec .form-grid > div > :not(label):not(.input):not(.picker-field) { flex-basis:100% !important; }
#mpSheet .mp-form-sec .form-grid > div:last-child { border-bottom:0 !important; }
#mpSheet .mp-form-sec .form-grid > div > label { display:block !important; width:96px !important; flex:none !important; margin:0 !important; font-size:13px !important; line-height:1.3 !important; color:#475569 !important; white-space:nowrap !important; overflow:hidden !important; text-overflow:ellipsis !important; }
#mpSheet .mp-form-sec .form-grid > div > .input,
#mpSheet .mp-form-sec .form-grid > div.is-fill > .input { display:block !important; flex:1 !important; min-width:0 !important; width:auto !important; height:auto !important; min-height:0 !important; margin:0 !important; padding:0 !important; border:0 !important; border-radius:0 !important; background:transparent !important; box-shadow:none !important; font-size:13.5px !important; color:#0f172a !important; text-align:right !important; }
/* 只读 / 禁用（合同带出、日期）：只改排版，字色沿用既有灰 ⇒ 保住"只读 vs 可填"一眼可辨。
   ⚠️ 必须补 [readonly] 变体 —— 既有 2777 行 `… > div > .input[readonly]` 是 (1,4,1)，
      比本段 `.input` 的 (1,3,1) 高一级；不补这条则灰底盖不掉（R981 真渲染实测抓到）。 */
#mpSheet .mp-form-sec .form-grid > div > .input[readonly],
#mpSheet .mp-form-sec .form-grid > div > .input[disabled] { display:block !important; flex:1 !important; min-width:0 !important; width:auto !important; height:auto !important; min-height:0 !important; margin:0 !important; padding:0 !important; border:0 !important; border-radius:0 !important; background:transparent !important; box-shadow:none !important; font-size:13.5px !important; text-align:right !important; }
#mpSheet .mp-form-sec .form-grid > div > .input:focus,
#mpSheet .mp-form-sec .form-grid > div.is-fill > .input:focus { background:transparent !important; border:0 !important; box-shadow:none !important; color:#c2410c !important; }
#mpSheet .mp-form-sec .form-grid > div > .picker-field { flex:1 !important; min-width:0 !important; width:auto !important; height:auto !important; min-height:0 !important; margin:0 !important; background:transparent !important; border:0 !important; border-radius:0 !important; padding:0 18px 0 0 !important; font-size:13.5px !important; color:#0f172a !important; justify-content:flex-end !important; }
/* ④ 车牌 / 驾驶员清单：并入同款白卡（#mpSheet 作用域 ⇒ 全站只有订单抽屉用 mp-list-head） */
#mpSheet .mp-list-head { display:flex !important; align-items:center !important; gap:8px !important; flex-wrap:nowrap !important; background:#fff !important; border:1px solid #e9eef5 !important; border-bottom:0 !important; border-radius:14px 14px 0 0 !important; padding:12px 13px 8px !important; margin:0 !important; }
#mpSheet .mp-list-head > b { display:block !important; flex:none !important; font-size:12.5px !important; font-weight:700 !important; color:#0f172a !important; margin:0 !important; }
#mpSheet .mp-list-head > span { display:block !important; font-size:10.5px !important; line-height:1.5 !important; color:#98a2b3 !important; }
/* ⚠️ 必须 nowrap + 说明行省略号 —— 用 flex-wrap:wrap 时那句长说明会折成两行，
      清单头由 82px 涨到 116px（R981 真渲染实测）。
      第 2 个 span 是撑开占位（HTML 里 style="flex:1"）⇒ 必须收成 0，否则吃掉说明的空间。 */
#mpSheet .mp-list-head > span:nth-of-type(1) { flex:1 1 0 !important; min-width:0 !important; white-space:nowrap !important; overflow:hidden !important; text-overflow:ellipsis !important; }
#mpSheet .mp-list-head > span:nth-of-type(2) { flex:0 0 0 !important; }
#mpSheet #ofRows { background:#fff !important; border:1px solid #e9eef5 !important; border-top:0 !important; border-radius:0 0 14px 14px !important; padding:2px 13px 10px !important; margin:0 0 10px !important; }
#mpSheet #ofRows:empty { border-top:1px solid #e9eef5 !important; border-radius:14px !important; padding:0 !important; }
/* ⑤ 底栏：左「还差 N 项」+ 右「创建订单（共 N 张）」 */
#mpSheet .of-sheet-foot { flex-wrap:nowrap !important; gap:9px !important; align-items:center !important; }
#mpSheet .of-sheet-foot .of-rest { flex:none; font-size:11.5px; color:#94a3b8; }
#mpSheet .of-sheet-foot .of-rest.warn { color:#c2410c; font-weight:600; }
#mpSheet .of-sheet-foot .btn-o { flex:1.55 1 0 !important; font-size:13.5px !important; white-space:nowrap !important; }
#mpSheet .of-sheet-foot .btn:not(.btn-o) { flex:1 1 0 !important; }


/* ⑨ 字段说明小字 */
#mpSheet .field-hint,
#mpSheet .mp-form-sec .form-grid > div.is-fill > .field-hint { font-size: 10.5px; line-height: 1.55; color: #98A2B3; margin-top: 4px; }

/* ⑩ 车牌清单行（车牌 + 次数 + 删除 一行）
   ⚠️ R912 在 2162-2168 给 .of-plate 写了【带 !important 的】border / background-color(#fff) /
      background-image（车牌小图标）/ background-position ⇒ 本段必须同样带 !important 才盖得住。
      实证（L3 真渲染）：不加 !important 时该框背景仍是白色 rgb(255,255,255)。
   左侧留 40px 是给 R912 那张车牌小图标让位（图标 background-position 12px center）。 */
#mpSheet #ofRows .of-row { display: flex; align-items: center; gap: 8px; border: 0; padding: 0; margin: 0 0 10px; min-height: 0; }
#mpSheet #ofRows .of-row + .of-row { border-top: 0; }
#mpSheet #ofRows .of-row input.of-plate { flex: 1 1 auto !important; min-width: 0 !important; width: 100% !important; height: 45px !important; box-sizing: border-box !important; background-color: #E8ECF3 !important; border: 1px solid #DDE3EC !important; border-radius: 12px !important; padding: 0 13px 0 40px !important; background-position: 13px center !important; font-size: 13.5px !important; color: var(--text, #1f2937) !important; text-align: left !important; }
#mpSheet #ofRows .of-row input.of-plate::placeholder { color: #8A94A6 !important; }
#mpSheet #ofRows .of-row input.of-plate:focus { background-color: #FFF7ED !important; border-color: var(--primary, #f97316) !important; box-shadow: 0 0 0 3px rgba(249, 115, 22, .13) !important; }
#mpSheet #ofRows .of-row > .of-lb { flex: none !important; font-size: 11.5px !important; color: #6B7280 !important; }
#mpSheet #ofRows .of-row > input[data-k="cnt"] { flex: none !important; width: 46px !important; height: 45px !important; box-sizing: border-box !important; background: #E8ECF3 !important; border: 1px solid #DDE3EC !important; border-radius: 12px !important; padding: 0 4px !important; text-align: center !important; font-size: 14px !important; color: var(--text, #1f2937) !important; }
#mpSheet #ofRows .of-row > .of-del { flex: none !important; width: 30px !important; height: 45px !important; border-radius: 10px !important; background: transparent !important; border: 0 !important; color: #B4BDCA !important; font-size: 14px !important; }

/* ⑪ 清单小标题（车牌清单 / 驾驶员清单） */
#mpSheet .mp-list-head { margin: 4px 2px 10px; }
#mpSheet .mp-list-head > b { display: block; font-size: 12.5px; font-weight: 700; color: #0F172A; margin-bottom: 3px; }
#mpSheet .mp-list-head > span { display: block; font-size: 10.5px; line-height: 1.55; color: #98A2B3; }

/* ⑫ 「＋ 添加车牌 / 添加驾驶员」等小按钮 */
#mpSheet .btn.btn-ghost.btn-sm { display: flex; align-items: center; justify-content: center; width: 100%; height: 42px; box-sizing: border-box; border-radius: 12px; background: #fff; border: 1px solid #DDE3EC; color: #3F4A5A; font-size: 13.5px; font-weight: 600; margin: 0 0 6px; }

/* ⑬ 照片框（行驶证 / 保险单）：虚线框表达"这里可以传东西" */
#mpSheet .photo-box { background: #E8ECF3; border: 1.5px dashed #C6D0DE; border-radius: 12px; }

/* ⑭ 抽屉内提示条（蓝色业务说明 / 橙底注意 / 灰底信息） */
#mpSheet .card-pad { border-radius: 11px; font-size: 11px; line-height: 1.6; }

/* ⑮ 底部按钮区（R911 的 sticky 保持不变，仅统一观感） */
#mpSheet .of-sheet-foot { background: #F4F5F8; }
#mpSheet .of-sheet-foot .btn { height: 50px; border-radius: 14px; font-size: 16px; font-weight: 600; }
#mpSheet .of-sheet-foot .btn.btn-o { box-shadow: 0 8px 20px rgba(249, 115, 22, .30); }

/* ⑯ 老板 2026-10-05 拍板：【删除】「预估载重」格的说明小字
      （原文："可留空。用于磅差校验：本车净重与它偏差超过 10% 会标记待审"）
      为什么要删：它在三格里排成 4 行，把该格撑高 ⇒ 三格不等高、整张卡片被顶长。
      删法：仅在手机端抽屉内隐藏。电脑端框宽（两列）该说明只占一行、不影响版面 ⇒ 保留。
      ⚠️ 若将来要连电脑端一起删，应改 pages-order.js 的 qtyBlock 模板（A/B/C/D 四模式共用）。 */
#mpSheet .mp-form-sec .form-grid.cols3 > div > .field-hint { display: none; }

/* ==================================================================
   R996 · 手机端抽屉「三表单族（.fm）」统一为「标签左 / 值右」行式卡片
   ------------------------------------------------------------------
   老板 2026-10-08 真机反馈：手机端「新建发货单」的输入框仍是【灰底填充块】，
   与已改造过的「新建订单 / 新建合同」不一致，要求统一成同一种交互模式。
   根因（读源码 + 行号实证）：
     · R970 段（本文件 2747~2784）曾把 .mp-form-sec 与 .fm **一起**改成"标签在上 + 灰底块"；
     · R981 段只把 .mp-form-sec **改回**扁平行（"标签左 / 值右 / 无外框"），**漏了 .fm**；
     · 凡走 Pages.fmGroup 的抽屉（新建/编辑发货单、编辑合同、编辑客户、磅单录入…）
       因此全部停留在旧样式 —— 又一次"姊妹面未对齐"（同族老坑）。
   做法：把 R981 那一整套规则在 .fm 作用域下【逐条镜像】一遍，数值完全一致。
   ⚠️ 作用域严格限定 #mpSheet（手机端抽屉）⇒ 电脑端弹窗的 .fm 一字不动。
   ⚠️ 必须带 !important —— R970 段的 .fm 规则本身带 !important，
      同特异性下不带则盖不住（R981 血泪：同特异性看谁在后，但带 !important 的必须也带）。
   ================================================================== */

/* ① 区块白卡：内边距交给字段行（避免与扁平行自带的 0 13px 叠成双份） */
#mpSheet .fm .fm-sec { padding:0 0 4px !important; border:1px solid #e9eef5 !important; border-radius:14px !important; box-shadow:0 1px 3px rgba(16,24,40,.06) !important; }
/* ② 区块头：与 .mp-form-sec-t 同款（橙点 + 12.5px/700 + 12px 13px 9px） */
#mpSheet .fm .fm-bar { display:flex !important; align-items:center !important; gap:7px !important; padding:12px 13px 9px !important; margin:0 !important; }
#mpSheet .fm .fm-bar::before { display:inline-block !important; flex:none !important; }
#mpSheet .fm .fm-body { padding:0 !important; }

/* ③ 字段行：标签左 / 值右（镜像 R981 主体） */
#mpSheet .fm .form-grid,
#mpSheet .fm .form-grid.cols3 { display:block !important; }
#mpSheet .fm .form-grid > div,
#mpSheet .fm .form-grid > div.is-fill { display:flex !important; flex-wrap:wrap !important; align-items:center !important; gap:10px !important; min-height:44px !important; padding:0 13px !important; margin:0 !important; border:0 !important; border-bottom:1px solid #f1f5f9 !important; }
/* 非控件子元素（按钮组 / 说明文字 / 照片框…）独占整行 —— 与 R993 的 .mp-form-sec 版同源。
   不加这条：.mp-seg 之类会与标签、输入框抢宽度，中文被压成逐字竖排。 */
#mpSheet .fm .form-grid > div > :not(label):not(.input):not(.picker-field) { flex-basis:100% !important; }
#mpSheet .fm .form-grid > div:last-child { border-bottom:0 !important; }
#mpSheet .fm .form-grid > div > label,
#mpSheet .fm .form-grid > div.is-fill > label { display:block !important; width:96px !important; flex:none !important; margin:0 !important; font-size:13px !important; line-height:1.3 !important; color:#475569 !important; white-space:nowrap !important; overflow:hidden !important; text-overflow:ellipsis !important; }
#mpSheet .fm .form-grid > div > .input,
#mpSheet .fm .form-grid > div.is-fill > .input { display:block !important; flex:1 !important; min-width:0 !important; width:auto !important; height:auto !important; min-height:0 !important; margin:0 !important; padding:0 !important; border:0 !important; border-radius:0 !important; background:transparent !important; box-shadow:none !important; font-size:13.5px !important; color:#0f172a !important; text-align:right !important; }
/* select 保持左对齐 —— 下拉文字右对齐会"看着跑偏"（与 .mp-form-sec 版一致的处理） */
#mpSheet .fm .form-grid > div > select.input { text-align:left !important; }
/* 只读 / 禁用：只改排版，字色沿用既有灰 ⇒ 保住「只读 vs 可填」一眼可辨。
   ⚠️ 必须补 [readonly] 变体 —— 2777 行那条是 (1,4,1)，比本段 .input 的 (1,3,1) 高一级。 */
#mpSheet .fm .form-grid > div > .input[readonly],
#mpSheet .fm .form-grid > div > .input[disabled] { display:block !important; flex:1 !important; min-width:0 !important; width:auto !important; height:auto !important; min-height:0 !important; margin:0 !important; padding:0 !important; border:0 !important; border-radius:0 !important; background:transparent !important; box-shadow:none !important; font-size:13.5px !important; text-align:right !important; }
#mpSheet .fm .form-grid > div > .input:focus,
#mpSheet .fm .form-grid > div.is-fill > .input:focus { background:transparent !important; border:0 !important; box-shadow:none !important; color:#c2410c !important; }
#mpSheet .fm .form-grid > div > .picker-field { flex:1 !important; min-width:0 !important; width:auto !important; height:auto !important; min-height:0 !important; margin:0 !important; background:transparent !important; border:0 !important; border-radius:0 !important; padding:0 18px 0 0 !important; font-size:13.5px !important; color:#0f172a !important; justify-content:flex-end !important; }
#mpSheet .fm .form-grid > div > .picker-field::after { right:0 !important; }
/* ④ 字段说明小字：跟在值下面、不撑高整行 */
#mpSheet .fm .form-grid > div > .field-hint { flex-basis:100% !important; font-size:10.5px !important; line-height:1.55 !important; color:#98a2b3 !important; margin:2px 0 0 !important; }

/* ==================================================================
   R914b · 合同页 5 处调整（业务模式一行 / 价格档两行 / 填充块统一 / 不许被撑宽）
   ------------------------------------------------------------------
   配套 JS 改动（pages-core.js）：①「采购收货（进厂）」→「采购收货」
     ② 删除「购销运输（C）…」整句说明  ③ 合同名称从「期限与总量」移到「合同基本信息」
   根因（真渲染实测）：价格档 5 个控件行内写死宽共 556px，而可用仅 324px；
     其外层 #cn_price_wrap 是 grid 子项、未设 min-width:0 ⇒ 被内容撑宽 ⇒ 溢出屏幕 219px。
   ================================================================== */

/* ① 业务模式四选项 → 一行四格 */
#mpSheet .cn-mode-group { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; }
#mpSheet .cn-mode-group > label { white-space: nowrap; font-size: 12.5px; justify-content: flex-start; gap: 4px; }

/* ② 价格档外层不许被内容撑宽 */
#mpSheet #cn_price_wrap { min-width: 0; }
#mpSheet #cn_prices { min-width: 0; width: 100%; }

/* ③ 价格档一行五格：模式 ｜ 生效起 ｜ 生效止 ｜ 单价 ｜ 删除
      R917：改用 flex + 显式宽度 + margin 间距（弃 grid / gap / minmax / justify-self）
      —— R916 的 grid 写法在老板真机（微信 X5 内核）上与桌面不一致：「自提」把旁边的日期挤掉
         （实测间隙 4.5px，而别处 25px）。不再赌语法兼容：flex 是源码本身就带（class="flex"）
         的路线、真机早已在用。宽度（375px 下可用 325px）：58 + 5 + D + 5 + D + 5 + 58 + 5 + 26 = 325
         ⇒ D = 81.5px，与 R916 设计值一致。
      ⚠️ 必须显式 gap: 0 —— 外层 @media 里旧的 .price-row { gap: 4px } 会与 margin 叠加。 */
#mpSheet .price-row { display: flex !important; flex-wrap: nowrap !important; align-items: center !important; gap: 0 !important; margin-bottom: 12px !important; }
#mpSheet .price-row > * { flex: 0 0 auto !important; margin: 0 5px 0 0 !important; min-width: 0 !important; box-sizing: border-box !important; }
#mpSheet .price-row > *:last-child { margin-right: 0 !important; }

/* ④ 每格宽度全部写死（不靠 stretch、不靠 flex-grow 争抢）
      R917：两个日期框用 flex:1 1 0px 等分 ⇒ 无论容器多宽，两框必然等宽 */
/* ⚠️ R919 修正：价格档「模式」的真实可见元素是**升级后的壳** .picker-field（div），
   原生 select 被 Pages.upgradeSelects 置 display:none（pages-core.js:6877）
   —— R916 / R917 / R918 三轮的样式**全打在了看不见的 select 上**（与 R912 车牌框同族，第三次）。
   ✅ 好消息：壳是 div ⇒ `width: auto` 在 flex 容器里会【按内容收缩】（select 做不到这件事）⇒
      不需要变量、也不需要再改 JS：「自提」≈45px、「采购收货」≈68px，自动跟随内容。
   ⚠️ 已锁定的下拉（.locked）保留锁形图标语义（R903 设计），只统一底色与字号。 */
#mpSheet .price-row > .picker-field {
  flex: 0 0 auto !important;
  width: auto !important;
  min-width: 0 !important;
  max-width: 90px !important;
  height: 45px !important; min-height: 45px !important;
  box-sizing: border-box !important;
  padding: 0 14px 0 8px !important;
  background: #E8ECF3 !important;
  border: 1px solid #DDE3EC !important;
  border-radius: 12px !important;
  font-size: 11.5px !important;
  color: var(--text) !important;
  display: flex !important; align-items: center !important; justify-content: flex-start !important;
  overflow: hidden !important; white-space: nowrap !important; text-align: left !important;
  position: relative !important; cursor: pointer !important;
}
#mpSheet .price-row > .picker-field::after { content: '▾' !important; position: absolute !important; right: 5px !important; font-size: 10px !important; color: #6B7280 !important; }
#mpSheet .price-row > .picker-field.locked { background: #E8ECF3 !important; color: var(--text) !important; cursor: default !important; }
#mpSheet .price-row > .picker-field.locked::after { content: '🔒' !important; right: 3px !important; font-size: 10px !important; }
#mpSheet .price-row > input[data-f="from"],
#mpSheet .price-row > input[data-f="to"] { flex: 1 1 0px !important; width: auto !important; max-width: none !important; }
#mpSheet .price-row > input[data-f="price"] { flex: 0 0 58px !important; width: 58px !important; max-width: 58px !important; }

/* ⑤ 填充块外观（灰底 + 描边 + 圆角；日期框保持"可点"观感、不去描边） */
#mpSheet .price-row .input { height: 45px !important; min-height: 45px !important; box-sizing: border-box !important; background: #E8ECF3 !important; border: 1px solid #DDE3EC !important; border-radius: 12px !important; padding: 0 6px !important; font-size: 11.5px !important; color: var(--text) !important; text-align: center !important; }
#mpSheet .price-row > select.input { font-size: 11.5px !important; }   /* padding 归 ④-b 管（同特异性下后者会覆盖） */

/* ⑥ 删除按钮：26×32 小件，最右一格 */
#mpSheet .price-row > button, #mpSheet .price-row > button.btn-danger { flex: 0 0 26px !important; width: 26px !important; max-width: 26px !important; height: 32px !important; border-radius: 9px !important; background: #F1F3F7 !important; border: 0 !important; color: #98A2B3 !important; font-size: 12px !important; padding: 0 !important; }

/* ========================= R931 · 手机端「新建订单 · 驾驶员清单」行（模式 B/C）=========================
   老板 2026-10-05 反馈：模式 B 新建订单里，驾驶员那一行被撑变形 —— 下拉被挤成极窄一条、
   名字「测试司机甲」逐字换行成竖排，整行被撑高。

   ★ 根因（实测，非推测）：
     style.css:2792  #mpSheet .btn.btn-ghost.btn-sm { width: 100%; height: 42px; ... }
     这条是给「➕ 添加驾驶员」「取消 / 创建订单」这类【整宽 ghost 按钮】加的，
     却【误伤了本行右侧的删除按钮】—— 它只是普通的 .btn.btn-ghost.btn-sm，没有 .of-del 类，
     因而享受不到 2784 行 `#mpSheet #ofRows .of-row > .of-del { width: 30px }` 的豁免。
     再叠加 1737 行 `.of-row .btn-ghost.btn-sm { flex: 0 0 auto !important }`
     ⇒ flex-basis 回退到 width（=100%）、且 flex-shrink=0（不许收缩）
     ⇒ 删除按钮恒定霸占整行宽度，驾驶员下拉只能拿到 min-content（中文=1 个字）⇒ 逐字换行、行被撑高。
     （同族第四次：R912 车牌框打在 type=hidden 上 / R918 价格档下拉打在 display:none 的 select 上 /
       R913 探针漏 .fm / 本次 —— 都是"改的元素不是用户看到的那个"或"误伤无关元素"。）

   ★ 修法（三锁 + 从根上杜绝换行）：
     ① 删除按钮固定 34px、四重限宽，并用 :not(.of-del) 精确排除 A 模式车牌行（不动它的 30px）；
     ② 驾驶员下拉的【壳】占满剩余宽 + white-space:nowrap/ellipsis —— 即使宽度再紧也只截字、绝不竖排；
     ③ 原生 select 一并兜底（万一该处壳未生成，同样不竖排）。
   ★ 为什么样式打在 .picker-field 上：`Pages.upgradeSelects` 会把 select 置 display:none、
     另建 div.picker-field 当【可见的壳】并插到 select 前面（pages-core.js:6860-6878）
     ⇒ 规则打在 select[data-k="driver"] 上等于没写（R919 已定此律）。 */
#mpSheet #ofRows .of-row > .btn-ghost.btn-sm:not(.of-del) {
  flex: 0 0 34px !important;
  width: 34px !important;
  min-width: 34px !important;
  max-width: 34px !important;
  height: 45px !important;
  box-sizing: border-box !important;
  padding: 0 !important;
  margin: 0 !important;
  border-radius: 10px !important;
  background: transparent !important;
  border: 0 !important;
  color: #B4BDCA !important;
  font-size: 14px !important;
}
#mpSheet #ofRows .of-row > .picker-field {
  flex: 1 1 auto !important;
  min-width: 0 !important;
  width: auto !important;
  height: 45px !important;
  min-height: 45px !important;
  box-sizing: border-box !important;
  display: block !important;
  line-height: 43px !important;
  padding: 0 26px 0 13px !important;
  background: #E8ECF3 !important;
  border: 1px solid #DDE3EC !important;
  border-radius: 12px !important;
  font-size: 14px !important;
  color: var(--text, #1f2937) !important;
  text-align: left !important;
  white-space: nowrap !important;
  overflow: hidden !important;
  text-overflow: ellipsis !important;
}
#mpSheet #ofRows .of-row > .picker-field::after { content: '▾' !important; right: 12px !important; color: #98A2B3 !important; font-size: 12px !important; }
#mpSheet #ofRows .of-row > select { flex: 1 1 auto !important; min-width: 0 !important; width: auto !important; height: 45px !important; }

/* ===== R934 · 上传磅单弹窗「订单信息」一行（老板 2026-10-05 拍板：乙案，且不要合同名）=====
   驾驶员上传磅单时要核对「这一车是给谁的」⇒ 在订单号下面加一行「发货单位 → 收货单位」（B 自营拉运 / C 购销运输 共用）。
   车道窄 ⇒ 两个单位名各自省略号截断，中间箭头固定不缩；取不到单位时整行转红提示（与票面体检同口径）。 */
#mpSheet .oi-ar-line { display: flex; align-items: center; gap: 6px; margin: 0 0 10px; font-size: 12.5px; line-height: 1.45; }
#mpSheet .oi-ar-line .oi-a,
#mpSheet .oi-ar-line .oi-b { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 700; color: var(--text, #1f2937); }
#mpSheet .oi-ar-line .oi-ar { flex: none; color: var(--primary, #f97316); font-weight: 700; }
#mpSheet .oi-ar-line.miss .oi-a,
#mpSheet .oi-ar-line.miss .oi-b { color: #DC2626; }

/* ================= R967 · 预约单 / 厂内提货：待生成清单 + 字段编辑 + 逐用户偏好 =================
   全部为新增规则，不改动任何既有选择器的声明（避免影响其它页面）。
   追加位置在文件末尾 ⇒ 同特异性下按"后写胜出"覆盖，无需改动上面的旧规则。 */

/* ---- ① 待生成清单（把「加入」与「提交」拆成两步） ---- */
.pk-picks { margin-top: 10px; border: 1px solid #BFDBFE; background: #EFF6FF; border-radius: 10px; padding: 10px 12px; }
.pk-picks-h { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 8px; }
.pk-picks-t { font-size: 13px; color: #0C447C; }
.pk-picks-note { font-size: 11.5px; color: #3B82F6; }
.pk-picks-clr { margin-left: auto; border: 0; background: none; color: #0C447C; font-size: 12px; font-family: inherit; cursor: pointer; padding: 2px 8px; border-radius: 6px; }
.pk-picks-clr:hover { background: #DBEAFE; }
.pk-picks-l { display: flex; flex-wrap: wrap; gap: 6px; }
.pk-pick { display: inline-flex; align-items: center; gap: 6px; background: #fff; border: 1px solid #BFDBFE; border-radius: 999px; padding: 3px 6px 3px 8px; font-size: 13px; font-family: ui-monospace, Consolas, monospace; }
.pk-pick-no { display: inline-flex; align-items: center; justify-content: center; min-width: 16px; height: 16px; border-radius: 50%; background: #DBEAFE; color: #0C447C; font-size: 10px; font-weight: 700; font-family: inherit; }
.pk-pick-x { font-style: normal; cursor: pointer; color: #94A3B8; padding: 0 2px; }
.pk-pick-x:hover { color: #DC2626; }
.pk-picks-f { margin-top: 8px; font-size: 11.5px; color: #3B82F6; }

/* ---- ② 字段编辑（「⋯ → 编辑字段」打开后才出现 ↕ ✕；默认一个都不显示） ---- */
.pk-fld-hint { margin-top: 8px; font-size: 11.5px; color: #92400E; background: #FFFBEB; border: 1px solid #FCD34D; border-radius: 8px; padding: 7px 10px; }
.pk-fld-bar { display: inline-flex; align-items: center; gap: 3px; flex: none; margin-left: auto; padding-left: 6px; }
.pk-fld-b { font-style: normal; cursor: pointer; width: 24px; height: 24px; display: inline-flex; align-items: center; justify-content: center; border: 1px solid var(--border, #E2E8F0); border-radius: 7px; font-size: 13px; line-height: 1; color: var(--text-2, #64748B); background: #fff; -webkit-tap-highlight-color: transparent; }
.pk-fld-b:hover { border-color: #93C5FD; color: #0C447C; }
.pk-fld-x:hover { border-color: #FCA5A5; color: #DC2626; }

/* ---- ③ 每行字段数由「逐用户偏好」驱动；未设置时回落旧观感（电脑 2 列 / 手机 1 列） ---- */
.tf-grid { grid-template-columns: repeat(var(--tfcols, 2), minmax(0, 1fr)); }
.tf-grid.mb-list { grid-template-columns: repeat(var(--tfcols, 1), minmax(0, 1fr)); }
/* R972 · 自动适应的第二/三级：长字段跨格 + dense 回填 + 极窄时省略号兜底。
   ⚠️ 作用域一律限定到这两个字段区（id 选择器），不碰全站其它表单。 */
#tempFieldsList, #pickupFieldsList { grid-auto-flow: dense; }
/* R973 · 极窄兜底：格宽不足时标签改占整行、控件落到下一排，避免「标签把整格吃掉」。
   说明：自动档下 cell 恒 >= 206px（见 pages-bill.js 的 _fillLastRow 注释），故此类实际不参与渲染；
   保留它是「契约」—— 将来若列数/宽度口径再改，挤压时自动兜住，不必再动布局代码。 */
#tempFieldsList.tf-narrow .tf-row, #pickupFieldsList.tf-narrow .tf-row { flex-wrap: wrap; align-items: flex-start; row-gap: 4px; }
#tempFieldsList.tf-narrow .tf-row > .tf-lbl, #pickupFieldsList.tf-narrow .tf-row > .tf-lbl {
  width: auto !important; flex: 0 0 100%; text-align: left; }
#tempFieldsList .tf-row[data-span="3"], #pickupFieldsList .tf-row[data-span="3"] { grid-column: span 3; }
#tempFieldsList .tf-row[data-span="4"], #pickupFieldsList .tf-row[data-span="4"] { grid-column: span 4; }
#tempFieldsList .tf-row > .picker-field, #pickupFieldsList .tf-row > .picker-field {
  flex: 1 1 auto; min-width: 0; display: block; line-height: 37px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* ---- ④ 页头「⋯」菜单里的设置项（分段按钮，选中态用主色） ---- */
.mh-menu .mh-lb { padding: 6px 10px 2px; font-size: 11px; color: var(--text-3, #9CA3AF); font-weight: 600; }
.mh-menu .mh-row { display: flex; gap: 4px; padding: 2px 8px 6px; }
.mh-menu .mh-row button { flex: 1; width: auto; height: 28px; padding: 0; border: 1px solid var(--border, #E2E8F0); border-radius: 7px; background: #fff; font-size: 12.5px; font-family: inherit; color: var(--text-2, #64748B); cursor: pointer; }
.mh-menu .mh-row button:hover { background: #F9FAFB; }
.mh-menu .mh-row button.on { background: var(--primary-light, #FFEDD5); border-color: var(--primary, #F97316); color: #9A3412; font-weight: 700; }

/* ---- ⑤ 提交按钮：清单非空时加醒目底色 —— 让"这一下会建 N 张"看得见 ---- */
.btn.btn-o.is-batch { background: #15803D; }

/* ---- ⑥ 手机端底部动作栏瘦身（老板：减小占用、提升空间利用率）----
   只压缩内边距与按钮高度，不改操作方式（仍是「取消 + 提交」，用户无感）。
   留白与按钮高度是"契约"：正文滚动区末尾的留白必须 ≥ 底栏实高，否则最后一条会被盖住。 */
#mpSheet .of-sheet-foot { padding: 6px 14px calc(6px + env(safe-area-inset-bottom)); margin: 10px -18px -18px; }
#mpSheet .of-sheet-foot .btn { height: 44px; border-radius: 12px; font-size: 15px; }

/* ==================================================================
   R982 · 手机端订单抽屉「车牌清单区」—— 对齐可交互原型
   ------------------------------------------------------------------
   老板 2026-10-08 真机报 3 问题（同一根因：R981 只扫了 .form-grid 域）：
     ① 车牌框仍是灰底 rgb(232,236,243) ⇒ 看着像禁用/不可填
     ② 车牌框与「次数」框错位 8px（实测车牌 top=89、次数 top=97）
     ③ 「⇉ 批量提取」是清单头里 100×44 的大按钮，与原型不符
   根因（全部实测）：
     ① 车牌框走 `#mpSheet #ofRows .of-row input.of-plate`（2,2,1 高特异性），
        R981 只覆盖了 `.form-grid > div > .input` ⇒ 车牌区没被扫到（我的漏点）。
     ② `.of-plate-box` 里的 `[data-plate-tip]`（min-height:15px）把它撑到 60px，
        行内 align-items:center ⇒ 45px 的车牌框被整体上移 8px。
     ③ 按钮用 `.btn-sm.btn-soft`，而移动端 `.btn-sm` = 44px 高、又占满清单头右侧。
   ⚠️ 作用域仍限 #mpSheet（手机端抽屉）；电脑端零影响。
   🔴 本段必须落在【文件里所有既有车牌规则之后】—— `input.of-plate` 在 L2191 与 L2916
      有两处 (2,2,1) 带 !important 的老规则；同特异性下「谁在后谁赢」。
      本段若插在它们之前会被整段压掉（R982 首次落码就栽在这：底色没变、白改一场）。 */

/* ① 车牌行改「顶部对齐」消掉 8px 错位；提示条转绝对定位、不再撑高父盒 */
#mpSheet #ofRows .of-row { align-items: flex-start !important; }
#mpSheet #ofRows .of-row > .of-plate-box { position: relative !important; align-self: flex-start !important; }
#mpSheet #ofRows .of-row > .of-plate-box > [data-plate-tip] { position: absolute !important; top: 100% !important; left: 0 !important; right: 0 !important; padding-top: 1px !important; }
#mpSheet #ofRows .of-row > .of-lb { display: flex !important; align-items: center !important; height: 45px !important; }

/* ② 车牌框 / 次数框 → 白底（可用状态），与原型 .prow input 同口径。
      ⚠️ 不重复设 border —— 既有 2878 行 `border:1px solid #DDE3EC !important` 本就是
         细边框，重复设会再压一次内联 borderColor（`Pages.onPlateInput` 写的红边）。
      另补一条错误态显式规则把红边捞回来：实测该红边原本就被 2878 的 !important 压住
      （既有缺陷，非本轮引入；老板要的「可用状态」包含「填错能看到红边」这层反馈）。 */
#mpSheet #ofRows .of-row input.of-plate { background-color: #fff !important; border-radius: 9px !important; }
#mpSheet #ofRows .of-row input.of-plate:focus { background-color: #fff7ed !important; }
#mpSheet #ofRows .of-row input.of-plate[style*="dc2626"] { border-color: #dc2626 !important; }
#mpSheet #ofRows .of-row > input[data-k="cnt"] { background: #fff !important; border-radius: 9px !important; }

/* ③ 车牌清单下方「双按钮行」（与原型 .prow-acts 同构）：
      左 = ＋添加车牌（灰虚线扁平）、右 = 📋 一次粘贴多台（浅橙实边框 + 橙字加粗） */
#mpSheet .of-plate-acts { display: flex !important; gap: 8px !important; margin-top: 8px !important; }
#mpSheet .of-plate-acts .btn.btn-ghost.btn-sm,
#mpSheet .of-plate-acts .btn.btn-sm.of-bulk { flex: 1 1 0 !important; width: auto !important; height: 40px !important; margin: 0 !important; padding: 0 8px !important; border-radius: 11px !important; font-size: 13px !important; white-space: nowrap !important; }
#mpSheet .of-plate-acts .btn.of-bulk { background: #fff7ed !important; border: 1px solid #fed7aa !important; color: #c2410c !important; font-weight: 600 !important; box-shadow: none !important; }

/* ================= R968 · 待生成清单「表格化」（对齐预览版表格视图） ================= */
.pk-sec-t { display: flex; align-items: baseline; gap: 8px; margin: 0 0 8px; font-size: 13.5px; font-weight: 700; color: var(--text, #1f2937); }
.pk-sec-t .pk-sec-s { font-size: 11.5px; font-weight: 400; color: var(--text-3, #9ca3af); }
.pk-plate-sec { background: #f8fafc; border: 1px solid var(--border, #e2e8f0); border-radius: 10px; padding: 8px 10px; }
.pk-plate-sec .tf-row { background: #fff; margin: 0; }

.pk-picks-tb { border-color: #c7d2fe; background: #eef2ff; }
.pk-tb-w { overflow-x: auto; border: 1px solid #dbeafe; border-radius: 8px; background: #fff; }
.pk-tb { border-collapse: collapse; width: 100%; font-size: 12.5px; }
.pk-tb th, .pk-tb td { border-bottom: 1px solid #eef2f7; padding: 0; text-align: left; white-space: nowrap; }
.pk-tb th { background: #f8fafc; font-weight: 600; color: var(--text-2, #64748b); padding: 6px 8px; position: relative; }
.pk-tb td { position: relative; }
.pk-tb tr:last-child td { border-bottom: 0; }
.pk-tb-no { width: 34px; text-align: center !important; color: var(--text-3, #9ca3af); }
.pk-tb-del { width: 40px; text-align: center !important; }
.pk-tb-del i { color: #94a3b8; cursor: pointer; font-style: normal; padding: 0 4px; }
.pk-tb-del i:hover { color: #dc2626; }
.pk-tb-pl { min-width: 118px; }
.pk-tb-in { width: 100%; min-width: 96px; border: 0; outline: 0; font: inherit; font-size: 12.5px; padding: 6px 8px; background: transparent; color: inherit; box-sizing: border-box; }
.pk-tb-in:focus { background: #fff7ed; box-shadow: inset 0 0 0 2px var(--primary, #f97316); border-radius: 4px; }
.pk-tb-in.mono { font-family: ui-monospace, Consolas, monospace; font-weight: 700; }
.pk-tb-in.ovr { background: #eff6ff; color: #1d4ed8; font-weight: 600; }
.pk-tb-rs { margin-left: 4px; font-style: normal; cursor: pointer; color: #2563eb; font-size: 12px; }
.pk-tb-rs:hover { color: #1e40af; }

/* 手机端车号行的「批量」小按钮（原来手机端压根没有批量入口） */
.mb-tf-row .mb-tf-ext { flex: none; height: 28px; padding: 0 10px; margin-left: 6px; border: 1px solid var(--primary-200, #fed7aa);
  background: var(--primary-light, #ffedd5); color: #9a3412; border-radius: 8px; font-size: 12.5px; font-family: inherit; font-weight: 600; }

/* ============ R969 · 两页字段区与预览版对齐 ============
   ① 车号行 R968 起独立成区（.pk-plate-sec），落在 .tf-grid 之外 ⇒ 原来那批
      「.tf-grid .tf-row {…}」的后代选择器全部失效，表现为「标签 / 输入框 / ✕ 竖排堆叠、✕ 常显」。
      这里用独立选择器补齐同一套规则（不改 DOM 结构、数据流一字不动）。
   ② 字段格对齐预览版：格子有边框、格内输入区无边框透明（预览版 .cf-i 同款；
      原来 .input 自带边框，格子套盒子，观感比预览版重）。
      聚焦时给整个格子描边，保证可点性与可辨识。 */
.pk-plate-sec .tf-row { display: flex; align-items: center; gap: 8px; min-width: 0; background: #fff;
  border: 1px solid var(--border, #e2e8f0); border-radius: 8px; padding: 5px 10px; }
.pk-plate-sec .tf-row .tf-lbl { width: 88px; flex: none; color: var(--text-2, #64748b); font-size: 13px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pk-plate-sec .tf-row .tf-del { flex: none; padding: 2px 8px; }
@media (hover: hover) and (pointer: fine) {
  .pk-plate-sec .tf-row .tf-del { opacity: 0; transition: opacity .12s; }
  .pk-plate-sec .tf-row:hover .tf-del, .pk-plate-sec .tf-row:focus-within .tf-del { opacity: 1; }
}
.tf-grid .tf-row > .input,
.tf-grid .tf-row > .picker-field,
.tf-grid .tf-row .pk-plate-wrap > .input,
.tf-grid .tf-row .pk-plate-outer .pk-plate-wrap > .input,
.pk-plate-sec .tf-row > .input,
.pk-plate-sec .tf-row .pk-plate-wrap > .input,
.pk-plate-sec .tf-row .pk-plate-outer .pk-plate-wrap > .input {
  border: 0; background: transparent; box-shadow: none; padding: 0 2px; min-height: 30px; font-size: 13px; }
.tf-grid .tf-row > .input:focus,
.pk-plate-sec .tf-row > .input:focus { background: transparent; box-shadow: none; }
.tf-grid .tf-row:focus-within,
.pk-plate-sec .tf-row:focus-within { border-color: var(--primary); box-shadow: 0 0 0 3px rgba(249,115,22,.12); }
/* ===== R974 · 手机端「待核对清单」卡片形态（一车一张卡，卡内列出全部字段值）=====
   背景：旧版手机端清单只有一排车号标签，看不到货物/发货单位/收货单位/日期
   ⇒ 无法按老板要求「先核对、再生成」；表格形态在窄屏要横向滚，所以改用纵向卡片。
   只读展示：要改就改上方「本次统一信息」，卡片就地跟随（Pages._pickTableSync）。 */
.pk-cards { display: block; }
.pk-card { background: #fff; border: 1px solid var(--border, #e2e8f0); border-radius: 10px; padding: 10px 12px; margin-top: 8px; }
.pk-card-h { display: flex; align-items: center; gap: 8px; padding-bottom: 6px; border-bottom: 1px dashed var(--border, #e2e8f0); }
.pk-picks-card .pk-pick-no { flex: none; width: 18px; height: 18px; line-height: 18px; text-align: center; border-radius: 50%;
  background: var(--primary-100, #ffedd5); color: var(--primary-darker, #c2410c); font-size: 11px; }
.pk-card-pl { flex: 1; min-width: 0; font-size: 14px; }
.pk-picks-card .pk-pick-x { flex: none; padding: 2px 8px; color: var(--text-3, #94a3b8); font-style: normal; cursor: pointer; }
.pk-card-b { padding-top: 6px; }
.pk-card-r { display: flex; align-items: baseline; gap: 8px; padding: 3px 0; font-size: 13px; }
.pk-card-k { flex: none; width: 68px; color: var(--text-2, #64748b); }
.pk-card-v { flex: 1; min-width: 0; color: var(--text, #0f172a); word-break: break-all; }
.pk-card-v.is-empty { color: var(--text-3, #94a3b8); }

/* ==================================================================
   R1025 · 「批量开单」入口收进【车号】行右侧
   ------------------------------------------------------------------
   老板 2026-10-09 反馈（附截图）：入口「位置不对、而且不需要这么大」。
   实测（真样式表渲染）：原来 312×40px、独占整行、夹在「司机」与「货物」之间
   ⇒ 把「车辆与司机」这一组切成两截。
   机制根因：本文件 2980 行的
     #mpSheet .fm .form-grid > div > :not(label):not(.input):not(.picker-field)
       { flex-basis:100% !important }
   —— 手机端抽屉里**除 label / input / picker-field 外的任何子元素都被拉成整行**。
   该规则不可删（它防「选项卡 / 说明文字」与标签挤一行导致中文竖排），
   所以只能让按钮"作为该行成员"存在。
   ⚠️ 必须【双 id】：上面那条特异性是 (1,4,1)，单 id(1,3,0) / 双 class(0,4,0) / 元素+class 都压不过。
      #mpSheet #dlvPlateRow = (2,1,0) ⇒ 稳赢。
   ⚠️ 作用域严格限定 #mpSheet（手机端抽屉）⇒ 电脑端弹窗一字不动。
   ================================================================== */
#mpSheet #dlvPlateRow > .dlv-plate-batch { flex:0 0 auto !important; flex-basis:auto !important; width:auto !important; height:32px !important; min-height:0 !important; padding:0 10px !important; margin:0 !important; border:1px solid #fed7aa !important; background:#fff7ed !important; color:#c2410c !important; border-radius:9px !important; font-size:12px !important; font-weight:600 !important; line-height:1 !important; white-space:nowrap !important; display:inline-flex !important; align-items:center !important; gap:3px !important; cursor:pointer; }

/* ==================================================================================
   R1043 · 发货单「粘贴文本自动识别」面板样式（前缀 dlv-recog- / dlv-ai-filled，
   全部新增，不改既有任何一条规则 ⇒ 对其它页面零影响）
   ================================================================================== */
.dlv-recog { margin: 0 0 12px; border: 1px dashed #cbd5e1; border-radius: 10px; background: #f8fafc; overflow: hidden; }
.dlv-recog-bar { display: flex; align-items: center; gap: 7px; padding: 9px 12px; cursor: pointer; user-select: none; font-size: 13px; color: #475569; }
.dlv-recog-bar:hover { background: #f1f5f9; }
.dlv-recog-ic { font-size: 14px; }
.dlv-recog-tx { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dlv-recog-ar { color: #94a3b8; font-size: 12px; }
.dlv-recog-body { display: none; padding: 0 12px 12px; border-top: 1px solid #e2e8f0; }
.dlv-recog-ta { width: 100%; min-height: 76px; margin-top: 10px; padding: 9px 10px; font-size: 13px; line-height: 1.7; border: 1px solid #cbd5e1; border-radius: 9px; background: #fff; resize: vertical; box-sizing: border-box; font-family: inherit; }
.dlv-recog-acts { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 8px; }
.dlv-recog-sum { font-size: 12px; color: #64748b; }
.dlv-recog-out { margin-top: 10px; }
.dlv-recog-g { font-size: 12.5px; font-weight: 600; color: #0f172a; margin: 12px 0 5px; padding-bottom: 3px; border-bottom: 1px solid #e2e8f0; }
.dlv-recog-tip { font-weight: 400; color: #94a3b8; font-size: 11.5px; }
.dlv-recog-row { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; padding: 5px 0; font-size: 12.5px; border-bottom: 1px solid #f1f5f9; }
.dlv-recog-row.is-warn { background: #fffbeb; border-radius: 6px; padding: 6px 8px; }
.dlv-recog-k { flex: 0 0 84px; color: #64748b; }
.dlv-recog-v { flex: 1; min-width: 0; color: #0f172a; word-break: break-all; }
.dlv-recog-v.mono { font-family: ui-monospace, Consolas, monospace; }
.dlv-recog-miss { flex: 1; color: #cbd5e1; }
.dlv-recog-c { flex: 0 0 auto; font-size: 11px; padding: 1px 6px; border-radius: 5px; }
.dlv-recog-c.is-h { background: #dcfce7; color: #166534; }
.dlv-recog-c.is-m { background: #fef3c7; color: #92400e; }
.dlv-recog-c.is-l { background: #f1f5f9; color: #64748b; }
.dlv-recog-w { font-size: 11.5px; color: #94a3b8; }
.dlv-recog-pend { font-size: 10.5px; padding: 1px 5px; border-radius: 5px; background: #f1f5f9; color: #64748b; border: 1px solid #e2e8f0; }
.dlv-recog-use { flex: 0 0 auto; font-size: 11.5px; padding: 3px 9px; border-radius: 6px; border: 1px solid #93c5fd; background: #eff6ff; color: #1d4ed8; cursor: pointer; font-family: inherit; }
.dlv-recog-use:hover { background: #dbeafe; }
.dlv-recog-arch, .dlv-recog-sus, .dlv-recog-alts { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; margin: 6px 0; padding: 6px 8px; font-size: 12px; border-radius: 7px; background: #f1f5f9; color: #334155; }
.dlv-recog-sus { background: #fef3c7; color: #78350f; }
.dlv-recog-empty { font-size: 12.5px; color: #475569; padding: 8px 0; }
.dlv-recog-eh { font-size: 12px; color: #94a3b8; line-height: 1.85; }
.dlv-recog-undo { display: flex; align-items: center; gap: 9px; margin-top: 10px; padding: 7px 10px; font-size: 12px; border-radius: 8px; background: #ecfdf5; color: #166534; flex-wrap: wrap; }
/* 被识别填过的字段 ⇒ 左侧一条橙杠（一眼看出哪些是系统填的） */
.dlv-ai-filled { position: relative; }
.dlv-ai-filled::before { content: ""; position: absolute; left: -1px; top: 3px; bottom: 3px; width: 3px; border-radius: 2px; background: #f59e0b; }
/* 手机端抽屉：识别区不需要额外处理（就是普通块级元素），只把恢复条撑满一行 */
#mpSheet .dlv-recog { margin-bottom: 10px; }
#mpSheet .dlv-recog-undo { align-items: flex-start; }

/* ==================================================================================
   R1046 · 发货单识别面板「识别 / 清空 / 全部填入」三个按钮 —— 样式与大小统一
   （老板 2026-10-10 要求「优化一下这几个按钮的样式和大小」）

   为什么要改：
     ① 清空 / 全部填入 用的是裸 .btn，而全局有 button{background:none;border:none}
        ⇒ 这两个按钮渲染出来是【无底色、无边框的纯文字】，跟橙实心的「识别」完全不搭，
          也不像"能点的按钮"。
     ② 「全部填入」= 把认出来的全填进表单；「清空」= 把已粘贴的原文清掉。
        两个后果相反的操作长得一模一样 ⇒ 容易点错。
     ③ 手机端 ≤820px 的 .btn-sm 被统一抬到 44px（R441 为磅房触控区加大的），
        在识别面板里就变成又高又散的三大块；「全部填入（高置信）」标签过长还会折行。

   改成什么样：
     · 尺寸统一：桌面 32px 高 / 12.5px 字 / 圆角 8px / 最小宽 74px；手机 38px 高 / 13.5px 字，
       三个按钮【均分整行】，右侧汇总文字换行到按钮下方。
     · 配色分层：识别=橙色实心（主操作）｜全部填入=浅橙底＋橙描边（批量快捷）｜清空=白底＋灰描边（次级）。
     · 文案：「全部填入（高置信）」→「全部填入」；"高置信"移到右侧汇总提示里说，信息不丢。

   影响范围：所有选择器都以 .dlv-recog-acts 打头 ⇒ 只作用于发货单识别面板，
             不影响任何其它页面的按钮（有断言守着）。
   ================================================================================== */
.dlv-recog-acts > .btn {
  height: 32px;
  min-width: 74px;
  padding: 0 14px;
  border-radius: 8px;
  font-size: 12.5px;
  font-weight: 600;
  flex: 0 0 auto;
}
/* 识别 = 主操作（橙实心，保持原有主色，只统一尺寸与悬停） */
.dlv-recog-acts > .btn#dlvRecogRun { background: var(--primary-dark, #ea580c); color: #fff; }
.dlv-recog-acts > .btn#dlvRecogRun:hover { background: var(--primary-darker, #c2410c); }
/* 全部填入 = 批量快捷（浅橙底 + 橙描边；醒目，但不与「识别」的实心主按钮抢主次） */
.dlv-recog-acts > .btn#dlvRecogAll {
  background: var(--primary-light, #fff7ed);
  color: var(--primary-darker, #c2410c);
  box-shadow: inset 0 0 0 1px #fdba74;
}
.dlv-recog-acts > .btn#dlvRecogAll:hover { background: #ffedd5; }
/* 清空 = 次级（白底 + 灰描边：看得出能点，但权重最低，避免与「全部填入」混淆） */
.dlv-recog-acts > .btn#dlvRecogClr {
  background: #fff;
  color: #475569;
  box-shadow: inset 0 0 0 1px #cbd5e1;
}
.dlv-recog-acts > .btn#dlvRecogClr:hover { background: #f8fafc; color: #1e293b; box-shadow: inset 0 0 0 1px #94a3b8; }
/* 三个按钮统一的按下反馈 */
.dlv-recog-acts > .btn:active { transform: translateY(1px); }
.dlv-recog-sum { flex: 0 1 auto; }

/* 手机端（≤820px）：三个按钮等高、均分整行、触控区足够（38px）；汇总文字换行到按钮下方 */
@media (max-width: 820px) {
  .dlv-recog-acts > .btn {
    flex: 1 1 0;
    min-width: 0;
    height: 38px;
    padding: 0 8px;
    border-radius: 10px;
    font-size: 13.5px;
  }
  .dlv-recog-sum { flex: 1 1 100%; order: 3; margin-top: 2px; }
}

/* ==================================================================================
   R1046 · 发货单【车号】行右侧「⧉ 批量」小胶囊 —— 电脑端补样式 + 不再独占一行
   （老板 2026-10-10：这颗按钮是否需要存在？如需存在，把样式和大小也设计一下 ——
     现在的毛病是它单独占用了一行）

   研判结论：**需要保留**（理由见交付报告）。真正的问题出在电脑端：
     · 这颗按钮的样式此前【只写在 #mpSheet 作用域里】（手机端抽屉）⇒ 电脑端它没有任何外观，
       渲染出来是一行【无底色、无边框的裸文字】「⧉ 批量」；
     · 电脑端「车号」那一格（#dlvPlateRow）是普通块容器，而 .input 是 width:100%
       ⇒ 输入框自己独占一行 ⇒ 排在它后面的这颗按钮只能掉到【第三行】，这就是
       「单独占用了一行」的由来。
       ⚠️ 不是 935 行那条 flex-basis:100%（那条在 886~963 的 @media (max-width:820px) 块里，
          只管手机端）—— 这一点是实测（按 CSS 规范算特异性+媒体条件）纠正过来的。
     （手机端早在 R1025 就用 #mpSheet 双 id 覆盖修好了，本段不动它。）

   处置：① 外观提到通用层（两端同一套：32px 高 / 12px 字 / 浅橙底 + 橙描边 + 圆角 9px）；
         ② 电脑端把 #dlvPlateRow 变成 flex 行（并且让车号输入框 flex:1 吃掉剩余宽度），
            三者同行 ⇒ 车号行从"两行"收到"一行"，整组还矮了 40px。
   影响范围：#dlvPlateRow / .dlv-plate-batch 都是发货单专属 ⇒ 其它页面零影响。
   ⚠️ 只包在 @media (min-width:821px) 里 ⇒ 手机端抽屉那套（#mpSheet）一个字节都不动。
   ================================================================================== */
.dlv-plate-batch {
  height: 32px;
  padding: 0 9px;
  border: 1px solid #fed7aa;
  background: #fff7ed;
  color: #c2410c;
  border-radius: 9px;
  font-size: 12px;
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  gap: 3px;
  cursor: pointer;
}
.dlv-plate-batch:hover { background: #ffedd5; border-color: #fdba74; }
/* 两端统一：不占整行、贴着车号输入框放 */
#dlvPlateRow > .dlv-plate-batch {
  flex: 0 0 auto;
  flex-basis: auto;
  width: auto;
  min-height: 0;
  margin: 0;
  align-self: center;
}
/* 电脑端：让「车号 / 输入框 / 批量」回到同一行 */
@media (min-width: 821px) {
  #dlvPlateRow { display: flex; align-items: center; gap: 8px; }
  #dlvPlateRow > label { flex: 0 0 auto; margin: 0; white-space: nowrap; }
  #dlvPlateRow > .input { flex: 1 1 auto; min-width: 0; width: auto; }
}

/* ============================================================================
   R1119 · 手机端「车号卡」（老板 2026-10-27：「车牌的输入框和其他组件不适配」）
   为什么单独建卡、而不再复用 .mp-input：
     .veh-combo .mp-input[readonly] 的 background（特异性 30）压过了
     .mp-ln .mp-input 的 transparent（20）⇒ 整个抽屉里只有车牌那一个是白底圆角框，
     毛重/皮重/过磅/备注全是纯文字。改为独立结构后，车牌不再染指 .mp-input，
     那条历史规则对卡片天然不生效（**不动它**，避免误伤下拉里的手填框）。
   三处共用（自提 / 提单 / 购销），样式只写这一份。
   ============================================================================ */
.veh-card-wrap { position: relative; margin-top: 10px; }
/* 卡片紧接着重量三格时去掉那道重复分隔线：视觉上归成「这辆车 + 这三个数」一组 */
.veh-card-wrap + .mp-3col { border-top: none; }

.veh-card {
  position: relative; display: flex; align-items: center; gap: 12px;
  width: 100%; min-height: 62px; padding: 11px 14px;
  border-radius: 13px; overflow: hidden; text-align: left;
  border: 1.5px solid transparent;
  font-family: inherit; cursor: pointer;
  transition: background .16s, border-color .16s;
}
.veh-card-ico {
  width: 42px; height: 42px; border-radius: 11px; flex: none;
  display: flex; align-items: center; justify-content: center;
  transition: background .16s, color .16s;
}
.veh-card-main { flex: 1 1 auto; min-width: 0; }
.veh-card-no {
  display: block; line-height: 1.12; letter-spacing: 1.2px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-weight: 800;
}
.veh-card-sub { display: block; font-size: 11.5px; line-height: 1.35; margin-top: 3px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.veh-card-act {
  flex: none; font-size: 12.5px; font-weight: 700; white-space: nowrap;
  border-radius: 9px; padding: 6px 12px; border: 1.5px solid transparent;
}

/* 已选：白底 + 左侧 3.5px 橙竖条（用 inset 阴影，不受 13px 圆角裁切） */
.veh-card.picked {
  background: #fff; border-color: var(--border); padding-left: 17px;
  box-shadow: inset 3.5px 0 0 0 var(--primary);
}
.veh-card.picked .veh-card-ico { background: var(--primary-100); color: var(--primary-dark); }
.veh-card.picked .veh-card-no { font-size: 22px; color: var(--text); }
.veh-card.picked .veh-card-sub { color: var(--text-3); }
.veh-card.picked .veh-card-act {
  background: none; color: var(--text-2); border-color: var(--border); padding: 6px 10px;
}

/* 未选：浅灰底 + 橙虚线（“这里还没填”），右侧橙色实心按钮做引导 */
.veh-card.empty {
  background: var(--surface-2); border-style: dashed; border-color: var(--primary-200);
}
.veh-card.empty .veh-card-ico {
  background: #fff; border: 1px solid var(--border); color: var(--text-3);
}
.veh-card.empty .veh-card-no {
  font-size: 15px; font-weight: 700; letter-spacing: 0;
  font-family: inherit; color: var(--text-3);
}
.veh-card.empty .veh-card-sub { color: var(--text-3); }
.veh-card.empty .veh-card-act { background: var(--primary); color: #fff; }

/* ── R1139 · 取景器交互修五条（老板 2026-10-30 12:10）────────────────────
   ④ 上黑边两行改成**强绑定**：第 2 行 = 第 1 行 + 36px，不再各自 max()。
      原来两行各算各的：band 偏小时（如 360×720 屏 ⇒ band≈120）第 2 行的 max(40px,…)
      这个兜底会把标题顶到第 1 行身上 —— 这就是「把整张磅单放进画面里」被「自动拍」压住的原因。
      强绑定之后，无论 band 多大，两行永远差 36px，绝不重叠。
   ⑤ ✕ 改成 44×44 圆形图标钮：原来是「✕ 关闭」带字胶囊（占位 ~76px、贴边、热区小）。
      44px 是苹果/谷歌的最小推荐点击尺寸；文字隐掉只留 ✕，也就不再和标题抢宽度。 */
#shCamMask.sh-fs:not(.sh-bandless) {
  --shR1: max(8px, calc((var(--shBand, 0px) - 96px) / 2 + 2px));
  --shR2: calc(var(--shR1) + 36px);
}
#shCamMask.sh-fs:not(.sh-bandless) #shCamPick,
#shCamMask.sh-fs:not(.sh-bandless) #shAuto { top: var(--shR1) !important; }
#shCamMask.sh-fs:not(.sh-bandless) #shAuto {
  right: 10px !important; max-width: 54% !important; max-height: 30px !important;
  line-height: 20px !important;
  white-space: nowrap !important; overflow: hidden !important; text-overflow: ellipsis !important;
}
#shCamMask.sh-fs:not(.sh-bandless) #shCamTitle {
  top: var(--shR2) !important; height: 34px !important;
  padding: 0 58px !important; justify-content: center !important;
  white-space: nowrap !important; overflow: hidden !important; text-overflow: ellipsis !important;
}
#shCamMask.sh-fs:not(.sh-bandless) #shCamX {
  top: calc(var(--shR2) - 5px) !important; right: 8px !important;
  width: 44px !important; height: 44px !important; min-width: 44px !important;
  padding: 0 !important; border-radius: 50% !important;
  font-size: 0 !important; color: transparent !important;
  background: rgba(0, 0, 0, .55) !important;
  border: 1px solid rgba(255, 255, 255, .28) !important;
  display: flex !important; align-items: center !important; justify-content: center !important;
  box-shadow: none !important;
}
#shCamMask.sh-fs:not(.sh-bandless) #shCamX::before {
  content: '✕'; font-size: 18px; line-height: 1; color: #fff; font-weight: 400;
}

/* ① 闪光灯两态：关 / 开 / 不可用 —— 原来只有静态小字「闪光灯」，开没开全靠猜 */
#shCamMask.sh-fs #shBtnTorch[data-torch="off"]::after { content: '闪光灯 关'; }
#shCamMask.sh-fs #shBtnTorch[data-torch="on"]::after { content: '闪光灯 开'; color: #facc15; }
#shCamMask.sh-fs #shBtnTorch[data-torch="na"]::after { content: '不可用'; color: #6b7280; }
#shCamMask.sh-fs #shBtnTorch[data-torch="na"] { opacity: .55 !important; }

/* R1145 · 取景/填表状态区里的「红字警告」样式
   —— 三格全红时配这句提示（"毛重和皮重读反了，已自动对调"）。 */
.hint-line.err { color: #b91c1c; }
.hint-line.err b { color: #991b1b; }
/* R1146 · 三数对不上时，红字里的〔采用〕按钮 —— 点了才改数，不点照样能提交 */
.hint-line .fixbtn { margin-left: 3px; padding: 0 6px; border-radius: 6px; border: 1px solid #fca5a5;
  background: #fff; color: #b91c1c; font-size: 11px; font-weight: 700; line-height: 1.6;
  cursor: pointer; vertical-align: baseline; }
.hint-line .fixbtn:active { background: #fef2f2; }

/* ══ R1148 · 拍照核对页：改造成「取景页的第二屏」（手机端）════════════════════════
   老板 2026-10-30 14:37 发真机截图并拍板"可以"。截图里的四个毛病：
     ① 拍完 `_setFS(false)` 把全屏关掉 ⇒ 核对页缩成中间一块，上下露出 App 的顶栏和底部导航
     ② 半透明遮罩 ⇒ 底下订单列表（磅房直录 / 待过磅 / 货物）清清楚楚，跟照片抢注意力
     ③ 四行字（标题 / 记住翻转 / 绿条 / 灰字两行）把照片压到只剩一小条
     ④ `调整 ▾` 孤零零占一整行居中
   改法：另立一个 `sh-pc` 类（**不与取景器的 sh-fs 共用**，互不干扰）——
       核对页期间整块遮罩变成纯黑全屏，照片撑满屏宽，按钮落在底部黑边区，
       文字只剩"质量结论"一句。回取景时由 _showPreview 摘掉这个类。
   ⚠️ 所有规则都由 `#shCamMask.sh-pc` 限定 ⇒ 取景器（sh-fs）与电脑端一个字都不动。 */
#shCamMask.sh-pc { background: #000 !important; gap: 0 !important; justify-content: flex-start !important; }
#shCamMask.sh-pc #shCamTitle { display: none !important; }
#shCamMask.sh-pc #shCamBox {
  position: fixed !important; left: 0 !important; right: 0 !important;
  top: 56px !important; bottom: 136px !important;
  display: flex !important; flex-direction: column !important;
  align-items: center !important; justify-content: center !important; gap: 14px !important;
}
#shCamMask.sh-pc #shCamStage {
  width: 100% !important; max-width: 100% !important; max-height: 56vh !important;
  min-width: 0 !important; min-height: 0 !important;
  border-radius: 0 !important; box-shadow: none !important; padding: 0 !important;
  background: transparent !important;
}
#shCamMask.sh-pc #shCamStage > div { width: 100% !important; max-width: 100% !important; }
#shCamMask.sh-pc #shCamHint {
  position: static !important; background: transparent !important;
  color: #9a9aa0 !important; font-size: 12.5px !important;
  padding: 0 24px !important; border-radius: 0 !important;
}
#shCamMask.sh-pc #shCamOps {
  position: fixed !important; left: 0 !important; right: 0 !important; bottom: 0 !important;
  height: auto !important; box-sizing: border-box !important;
  padding: 12px 20px calc(30px + env(safe-area-inset-bottom)) !important;
  align-items: center !important; flex-wrap: wrap !important;
  background: #000 !important;
}
