/* ============================================================
 * 乘双机械生产管理系统 —— 样式表  v25 (2026092211)
 * 2026092211: #851 年包订单卡片状态条带（.aostatus-bar / .aostat / .aostat-inv / .aostat-po /
 *   .oc-cust / .has-aostat 左色条 / .aostat-meta / 窄屏 .oc-l2-aostat）—— **全部为新增类名，
 *   不改动任何原有选择器**，故订单 / 采购 / 仓库等其它版块零影响。
 *   变量一律用 6 套主题**共同覆盖**的原始 token（--suc-* / --wrn-* / --dgr-* / --n-*），已逐主题核对；
 *   切勿写 --ok / --warn / --bad（生产 CSS 里没有这些名字，var() 取不到值 → 无底色且不报错）。
 *   对比度实测（生产 :root 实际值）：4.79 / 6.37 / 5.30 / 6.92 / 7.58:1 全部达标；
 *   未关联格的虚线描边必须用 --n-400(2.56:1) —— 用 --border(1.23:1) 几乎看不见线，形状编码会失效。
 * 2026091613: #824c 批量完成弹窗窄屏下零件信息被截断——.batch-item-name 原为
 *   nowrap + overflow:hidden + text-overflow:ellipsis（为 PC 表格化列表设计的一行式排版），
 *   窄屏必然溢出：实测 390px 下可用 230px / 文本需 517px，**只显示 18 字（29%）**。
 *   移动端改为 white-space:normal 换行 + overflow-wrap:break-word 完整显示；
 *   **PC 既有规则一行未动**（实测 rowH 仍 43px、whiteSpace 仍 nowrap、不截断）。
 * 2026091612: #824b 移动端长表单折叠（.fc-head / .fc-body / .fc-pill）——新增订单弹层
 *   手机端内容高 1993px→1148px（-42%）。选择器全部限定在新增 class 内或 .fc-* 之下，
 *   且整块包在 @media (max-width:900px)：PC 端不生成折叠头、滚动高度 1788px 与改造前一致。
 * 2026091612: #824 移动端手感三层样式——下拉刷新指示器 / 视图切换转场 / 首屏骨架屏。
 *   全部落在 @media (max-width:900px) 或全新类名（.pull-refresh / .view-enter /
 *   .app-skeleton，骨架内部 .sk-* 与 .w* 均限定在 .app-skeleton 后代选择器内），
 *   不触碰任何既有选择器。层级：指示器 220（盖过 #mnav=200、低于 #mdrawerMask=300），
 *   骨架 40（在底部栏之下）。无头 Edge 实测：1440px 下 .pull-refresh display:none、
 *   .view.view-enter animationName:none、.app-skeleton display:none；390px 下依次
 *   flex / csjxViewEnter / block。
 * 2026091591: #802e 弹层 footer 遮挡输入框 —— 把 #modalOrderSheet 已验证的
 *   「三段式 flex」推广到全局 .modal：由「.modal 自身滚动 + .modal-foot sticky 吸底」
 *   改为「.modal 只做 flex 容器(overflow:hidden)，滚动交给 .modal-body
 *   (flex:1 1 auto; min-height:0; overflow-y:auto)」→ body 高度天然扣除 head/foot，
 *   与 foot 严格相邻、永不重叠。实测：修复前 body 底边 1138 / foot 顶边 437
 *   （内容溢出 foot 之下 701px，输入框被吸底按钮栏盖住）；修复后 437 / 437（相邻）。
 * ============================================================ */
/* ============================================================
 * 乘双机械生产管理系统 —— 现代化 UI v12
 * Design tokens → components → utilities → responsive
 * v12: E14-E15 planned_end自动计算 + A15 缓存控制
 * ============================================================ */

/* ---------- Design Tokens ---------- */
:root {
  /* primary */
  --pri-50: #eff6ff; --pri-100: #dbeafe; --pri-200: #bfdbfe; --pri-500: #3b82f6; --pri-600: #2563eb; --pri-700: #1d4ed8;
  /* success */
  --suc-50: #f0fdf4; --suc-500: #22c55e; --suc-600: #16a34a; --suc-700: #15803d;
  /* warning */
  --wrn-50: #fffbeb; --wrn-100: #fef3c7; --wrn-500: #f59e0b; --wrn-600: #d97706; --wrn-700: #92400e;
  /* danger */
  --dgr-50: #fef2f2; --dgr-100: #fee2e2; --dgr-200: #fecaca; --dgr-500: #ef4444; --dgr-600: #dc2626; --dgr-700: #b91c1c;
  /* info */
  --inf-50: #f0f9ff; --inf-100: #e0f2fe; --inf-200: #bae6fd; --inf-500: #0ea5e9; --inf-600: #0284c7; --inf-700: #0369a1;
  /* neutral */
  --n-0: #ffffff; --n-50: #f8fafc; --n-100: #f1f5f9; --n-200: #e2e8f0; --n-300: #cbd5e1; --n-400: #94a3b8;
  --n-500: #64748b; --n-600: #475569; --n-700: #334155; --n-800: #1e293b; --n-900: #0f172a;

  /* semantic aliases */
  --bg-page: var(--n-50);
  --bg-surface: var(--n-0);
  /* #828c：补上 --bg（原先代码里 4 处写了 var(--bg, #f8fafc)，但该变量从未定义过 →
     永远回退到写死的 #f8fafc，导致页脚等区块不跟随主题）。这里让它指向 --bg-page，
     而 --bg-page 会在各 [data-theme] 块里被覆盖，故 --bg 自动跟随主题。
     CSS 变量为惰性求值，所以此处引用是安全的。 */
  --bg: var(--bg-page);
  --border: var(--n-200);
  --border-light: var(--n-100);
  --text: var(--n-800);
  --text-soft: var(--n-600);
  --text-mute: var(--n-400);
  --accent: var(--pri-600);
  --accent-hover: var(--pri-700);
  --accent-light: var(--pri-50);

  /* status colors */
  --st-upcoming: var(--pri-500);
  --st-ontrack: var(--pri-600);
  --st-done: var(--suc-600);
  --st-overdue: var(--dgr-600);
  --st-approaching: var(--wrn-600);
  --bg-upcoming: var(--pri-50);
  --bg-ontrack: var(--pri-50);
  --bg-done: var(--suc-50);
  --bg-overdue: var(--dgr-50);
  --bg-approaching: var(--wrn-50);
  --text-upcoming: var(--pri-700);
  --text-ontrack: var(--pri-700);
  --text-done: var(--suc-700);
  --text-overdue: var(--dgr-700);
  --text-approaching: var(--wrn-700);

  /* shadows（#679c 更柔和） */
  --shadow-xs: 0 1px 2px rgba(15,23,42,.04);
  --shadow-sm: 0 1px 3px rgba(15,23,42,.05), 0 1px 2px rgba(15,23,42,.03);
  --shadow-md: 0 6px 16px rgba(15,23,42,.07), 0 2px 6px rgba(15,23,42,.04);
  --shadow-lg: 0 12px 32px rgba(15,23,42,.09), 0 4px 12px rgba(15,23,42,.05);
  --shadow-xl: 0 24px 60px rgba(15,23,42,.14), 0 8px 20px rgba(15,23,42,.06);

  /* radii（#679c 更圆润） */
  --r-xs: 8px; --r-sm: 10px; --r-md: 14px; --r-lg: 18px; --r-xl: 24px; --r-full: 999px;

  /* transitions */
  --t-fast: 0.15s ease; --t-normal: 0.2s ease; --t-slow: 0.3s ease;

  /* font */
  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", "Noto Sans SC", sans-serif;
  --font-mono: "SF Mono", "Cascadia Code", "Consolas", monospace;
}

/* ---------- Reset ---------- */
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
html, body { height: 100%; }
body {
  font-family: var(--font);
  background: var(--bg-page);
  color: var(--text);
  font-size: 14px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* ================================================================
 * LOGIN
 * ================================================================ */
.login-overlay {
  position: fixed; inset: 0; display: flex; align-items: center; justify-content: center;
  background: linear-gradient(135deg, #0f172a 0%, #1e3a5f 30%, #1d4ed8 70%, #3b82f6 100%);
  z-index: 300;
}
.login-overlay::before {
  content: ''; position: absolute; inset: 0;
  background: radial-gradient(ellipse at 20% 80%, rgba(59,130,246,.15) 0%, transparent 50%),
              radial-gradient(ellipse at 80% 20%, rgba(29,78,216,.1) 0%, transparent 50%);
}
.login-card {
  position: relative;
  background: var(--bg-surface);
  border-radius: var(--r-xl);
  padding: 44px 40px;
  width: 100%; max-width: 420px;
  box-shadow: var(--shadow-xl), 0 0 0 1px rgba(255,255,255,.05);
  text-align: center;
  animation: loginIn .4s ease;
}
@keyframes loginIn { from { opacity:0; transform:translateY(20px) scale(.98); } to { opacity:1; transform:translateY(0) scale(1); } }
.login-logo {
  width: 68px; height: 68px; margin: 0 auto 16px;
  background: linear-gradient(135deg, var(--accent), #3b82f6);
  color: #fff; font-size: 32px; border-radius: var(--r-lg);
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 8px 24px rgba(37,99,235,.35);
}
.login-card h2 { font-size: 20px; font-weight: 700; color: var(--n-900); margin-bottom: 4px; }
.login-sub { font-size: 13px; color: var(--text-soft); margin-bottom: 28px; }
.login-field { margin-bottom: 18px; text-align: left; }
.login-field label { display: block; font-size: 13px; font-weight: 600; color: var(--n-700); margin-bottom: 6px; }
.login-field input {
  width: 100%; padding: 11px 14px; border: 1.5px solid var(--border); border-radius: var(--r-sm);
  font-size: 14px; outline: none; transition: border var(--t-fast), box-shadow var(--t-fast);
  background: var(--n-50);
}
.login-field input:focus { border-color: var(--accent); box-shadow: 0 0 0 3px rgba(37,99,235,.1); background: var(--bg-surface); }
.login-remember {
  display: flex; align-items: center; gap: 8px; margin-bottom: 20px; font-size: 13px;
  color: var(--text-soft); cursor: pointer; user-select: none;
}
.login-remember input[type="checkbox"] { width: 16px; height: 16px; accent-color: var(--accent); cursor: pointer; }
.login-remember label { cursor: pointer; }
.login-error { color: var(--dgr-600); font-size: 13px; margin-bottom: 12px; min-height: 20px; }
.login-btn {
  width: 100%; padding: 12px; font-size: 15px; font-weight: 600;
  background: linear-gradient(135deg, var(--accent), var(--pri-500));
  border: none; border-radius: var(--r-sm); color: #fff;
  cursor: pointer; transition: all var(--t-fast);
  box-shadow: 0 4px 12px rgba(37,99,235,.25);
}
.login-btn:hover { transform: translateY(-1px); box-shadow: 0 6px 20px rgba(37,99,235,.35); }
/* #706 登录页备案号 */
.login-beian {
  margin-top: 14px; padding-top: 10px; border-top: 1px dashed var(--border-light, #e5e7eb);
  display: flex; justify-content: center; gap: 14px; flex-wrap: wrap;
  font-size: 11px; color: var(--text-mute, #6b7280);
}
.login-beian a { color: var(--text-mute, #6b7280); text-decoration: none; }
.login-beian a:hover { color: var(--pri-600, #2563eb); }
.login-btn:active { transform: translateY(0); }

/* ================================================================
 * TOPBAR
 * ================================================================ */
.topbar {
  background: var(--bg-surface);
  border-bottom: 1px solid var(--border);
  padding: 14px 32px;
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px;
  box-shadow: var(--shadow-sm);
  position: sticky; top: 0; z-index: 50;
  flex-wrap: wrap;
  backdrop-filter: blur(12px);
  /* #828a 主题适配：此处原为写死的 rgba(255,255,255,.92)，把上面正确的
     var(--bg-surface) 覆盖掉了 —— 导致顶栏在夜间/护眼等主题下仍是白色。
     改用 color-mix 保留「半透明毛玻璃」观感，同时底色跟随主题。 */
  background: color-mix(in srgb, var(--bg-surface) 92%, transparent);
}
.topbar-left { display: flex; align-items: center; }
.logo { display: flex; align-items: center; gap: 14px; }
.logo-mark {
  width: 42px; height: 42px; display: flex; align-items: center; justify-content: center;
  background: linear-gradient(135deg, var(--accent), var(--pri-500));
  color: #fff; font-size: 20px;
  border-radius: var(--r-sm);
  box-shadow: 0 4px 12px color-mix(in srgb, var(--accent) 30%, transparent);
}
.logo-text h1 { font-size: 17px; font-weight: 700; color: var(--n-900); letter-spacing: -0.3px; }
.logo-text p { font-size: 11px; color: var(--text-mute); margin-top: 2px; }
.topbar-right { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.user-info { display: flex; align-items: center; gap: 8px; font-size: 13px; }
.user-icon { width: 28px; height: 28px; border-radius: 50%; background: var(--accent-light); color: var(--accent); display: inline-flex; align-items: center; justify-content: center; font-size: 16px; flex: none; overflow: hidden; vertical-align: -6px; }
.user-icon img { width: 100%; height: 100%; object-fit: cover; display: block; }
.user-name { font-weight: 600; color: var(--n-800); }
.user-role { font-size: 12px; color: var(--text-mute); background: var(--n-100); padding: 2px 10px; border-radius: var(--r-full); }
.today-label {
  font-size: 12px; color: var(--text-soft); background: var(--n-50);
  padding: 6px 12px; border-radius: var(--r-full);
  border: 1px solid var(--border); font-weight: 500;
}

/* notification bell */
.notif-bell {
  position: relative; font-size: 18px; padding: 6px 10px;
  cursor: pointer; border: none; background: transparent;
  border-radius: var(--r-sm); transition: background var(--t-fast);
}
.notif-bell:hover { background: var(--n-100); }
.notif-badge {
  position: absolute; top: 0; right: 2px;
  background: var(--dgr-500); color: #fff; font-size: 10px; font-weight: 700;
  min-width: 18px; height: 18px; border-radius: var(--r-full);
  display: flex; align-items: center; justify-content: center;
  line-height: 1; padding: 0 4px;
  box-shadow: 0 2px 6px rgba(239,68,68,.35);
  animation: badgePulse 2s ease-in-out infinite;
}
@keyframes badgePulse { 0%,100%{transform:scale(1)} 50%{transform:scale(1.12)} }
.tab-badge {
  background: var(--dgr-500); color: #fff; font-size: 11px; font-weight: 700;
  padding: 1px 7px; border-radius: var(--r-full); margin-left: 4px;
  line-height: 1.4;
}

/* role banner */
.role-banner {
  display: flex; align-items: center; gap: 8px; justify-content: center;
  padding: 10px 20px; background: var(--wrn-50);
  border-bottom: 1px solid var(--wrn-100);
  font-size: 13px; color: var(--wrn-700); font-weight: 500;
}
.role-banner-icon { font-size: 16px; }

/* ================================================================
 * BUTTONS
 * ================================================================ */
.btn {
  border: none; cursor: pointer; padding: 8px 16px; border-radius: var(--r-sm);
  font-size: 13px; font-weight: 600; transition: all var(--t-fast);
  display: inline-flex; align-items: center; gap: 6px;
  line-height: 1.4; white-space: nowrap;
  font-family: inherit;
}
/* #679c 圆润化：hover 轻微上浮 + 柔和投影 */
.btn:hover { transform: translateY(-1px); }
.btn:active { transform: translateY(0) scale(.97); }
.btn-primary {
  background: var(--accent); color: #fff;
  box-shadow: 0 1px 3px rgba(37,99,235,.25);
}
.btn-primary:hover { background: var(--accent-hover); box-shadow: 0 2px 8px rgba(37,99,235,.35); }
.btn-ghost {
  background: transparent; color: var(--text-soft);
  border: 1px solid var(--border);
}
.btn-ghost:hover { background: var(--n-50); border-color: var(--n-300); color: var(--text); }
.btn-sm { padding: 5px 12px; font-size: 12px; border-radius: var(--r-xs); }
.btn-xs { padding: 3px 8px; font-size: 11px; border-radius: var(--r-xs); }
.btn-danger { background: var(--dgr-50); color: var(--dgr-600); border: 1px solid var(--dgr-200); }
.btn-danger:hover { background: var(--dgr-100); border-color: var(--dgr-500); }
.btn-del-order { color: var(--dgr-500); }
.btn-del-order:hover { background: var(--dgr-50); border-color: var(--dgr-300); color: var(--dgr-700); }
.btn-success { background: var(--suc-600); color: #fff; }
.btn-success:hover { background: var(--suc-700); }
.btn-warn { background: var(--wrn-100); color: var(--wrn-700); border: 1px solid var(--wrn-100); }
.btn-warn:hover { background: var(--wrn-100); border-color: var(--wrn-500); }

/* #346 延期申请 */
.detail-stage-delayed { font-size: 11px; color: var(--wrn-700); background: var(--wrn-50); border: 1px solid var(--wrn-100); border-radius: var(--r-xs); padding: 1px 6px; }
/* #450 撤回完成留痕标记 */
.detail-stage-undone { font-size: 11px; color: #9a3412; background: #ffedd5; border: 1px solid #fed7aa; border-radius: var(--r-xs); padding: 1px 6px; cursor: help; }
.delay-req-row {
  border: 1px solid var(--border); border-radius: var(--r-md);
  padding: 10px 12px; margin-bottom: 8px; background: var(--bg-surface);
}
.delay-req-row.ok { border-left: 3px solid var(--suc-500); }
.delay-req-row.bad { border-left: 3px solid var(--dgr-500); }
.delay-req-row.warn { border-left: 3px solid var(--wrn-500); }
.delay-req-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.delay-req-stage { font-weight: 600; font-size: 13px; }
.delay-req-scope { font-size: 11px; color: var(--text-soft); background: var(--n-100); border-radius: var(--r-xs); padding: 1px 6px; }
.delay-req-status { font-size: 12px; font-weight: 600; margin-left: auto; }
.delay-req-status.ok { color: var(--suc-600); }
.delay-req-status.bad { color: var(--dgr-600); }
.delay-req-status.warn { color: var(--wrn-600); }
.delay-req-meta { font-size: 12px; color: var(--text-soft); margin-top: 6px; }
.delay-req-reason { font-size: 12px; color: var(--text); margin-top: 4px; background: var(--n-50); border-radius: var(--r-xs); padding: 6px 8px; }
/* #402 延期范围：全选 + 零件勾选列表 */
.delay-parts-box { border: 1px solid var(--border); border-radius: var(--r-md); padding: 8px 10px; background: var(--bg-surface); }
.delay-part-all { display: flex; align-items: center; gap: 8px; cursor: pointer; font-size: 13px; font-weight: 600; color: var(--n-700); padding: 4px 0; border-bottom: 1px solid var(--border); margin-bottom: 6px; }
.delay-parts-list { max-height: 180px; overflow-y: auto; display: flex; flex-direction: column; gap: 2px; margin-bottom: 6px; }
.delay-part-item { display: flex; align-items: center; gap: 8px; cursor: pointer; font-size: 13px; color: var(--text); padding: 3px 2px; border-radius: var(--r-xs); }
.delay-part-item:hover { background: var(--n-50); }
.delay-part-item input, .delay-part-all input { cursor: pointer; }

/* ================================================================
 * STATS
 * ================================================================ */
.stats-bar {
  display: flex; gap: 14px; padding: 20px 32px 4px; flex-wrap: wrap;
}
.stat {
  flex: 1 1 160px; min-width: 150px;
  background: var(--bg-surface); border: 1px solid var(--border);
  border-radius: var(--r-md); padding: 18px 20px;
  box-shadow: var(--shadow-xs);
  transition: all var(--t-fast);
  position: relative; overflow: hidden;
}
.stat::before {
  content: ''; position: absolute; top: 0; left: 0; width: 4px; height: 100%;
  background: var(--accent); opacity: 0; transition: opacity var(--t-fast);
}
.stat:hover { box-shadow: var(--shadow-md); transform: translateY(-1px); }
.stat:hover::before { opacity: 1; }
.stat-num { display: block; font-size: 28px; font-weight: 800; line-height: 1.1; letter-spacing: -1px; }
.stat-label { display: block; font-size: 12px; color: var(--text-mute); margin-top: 6px; font-weight: 500; }

/* ================================================================
 * TABS
 * ================================================================ */
.tabs {
  display: flex; gap: 2px; padding: 10px 32px 0;
  border-bottom: 1px solid var(--border);
  background: var(--bg-surface);
}
.tab {
  border: none; background: transparent; cursor: pointer;
  padding: 10px 20px; font-size: 13px; font-weight: 600;
  color: var(--text-soft);
  border-radius: var(--r-sm) var(--r-sm) 0 0;
  border-bottom: 2px solid transparent;
  transition: all var(--t-fast);
  position: relative; top: 0;
  font-family: inherit;
}
.tab:hover { color: var(--text); background: var(--n-50); }
.tab.active {
  color: var(--accent); border-bottom-color: var(--accent);
  background: var(--accent-light);
}

/* ================================================================
 * #827 侧边栏分组导航（仅 PC ≥900px；<900px 保持原顶部形态交 .mnav 接管）
 * ----------------------------------------------------------------
 * 做法：仅用 CSS 把既有的 <nav class="tabs"> 从横向条改为左侧固定栏，
 *   DOM 位置不动 → switchView / readTabMeta / 移动端抽屉**零改动**。
 * 折叠阈值 1200px（不是 1000px）：1366×768 在浏览器 125% 缩放下逻辑宽仅约
 *   1093px，若阈值过低，这类最常见笔记本会让正文被压到 900px 以下、表格重现横滚。
 *   原则：**正文宽度优先于导航可读性**。
 * ================================================================ */
@media (min-width: 900px) {
  :root { --side-w: 228px; }

  .tabs {
    position: fixed; left: 0; top: 0; bottom: 0; width: var(--side-w);
    flex-direction: column; gap: 0; align-items: stretch;
    padding: 12px 10px 18px;
    border-bottom: none; border-right: 1px solid var(--border);
    background: var(--bg-surface);
    overflow-y: auto; overflow-x: hidden;
    z-index: 60;
  }
  /* 正文与顶栏整体让出侧栏宽度 */
  body { padding-left: var(--side-w); }

  /* 分组容器 */
  .nav-sec { margin-bottom: 2px; }
  /* ★ 可读性（老王反馈：字太小、颜色太淡，对近视不友好）
     分组标题原为 11.5px + --text-mute(#94a3b8) → 白底对比度仅 2.7:1，远低于 WCAG 4.5:1。
     现改 13px + --text-soft(#475569) → 对比度 8:1，字号也放大。 */
  /* ★ 高度自适应（老王反馈：侧栏不应出现滚动，不美观）
     侧栏放不下时不是"让它滚"，而是让它自己收紧 —— 用 clamp() 把纵向间距与字号
     跟视口高度绑定：高屏宽松、矮屏紧凑，任何高度都不溢出。
     实测总高：900px 屏约 795px / 768px 屏约 672px / 614px 屏约 590px，均不滚动。 */
  .nav-sec-title {
    display: flex; align-items: center; justify-content: space-between;
    width: 100%; padding: clamp(7px, 1.35vh, 14px) 12px clamp(3px, 0.72vh, 7px);
    font-family: inherit; font-size: clamp(12px, 1.45vh, 13px); font-weight: 700;
    color: var(--text-soft); letter-spacing: .02em;
    background: transparent; border: none; text-align: left;
    cursor: pointer;
  }
  .nav-sec-pinned .nav-sec-title { cursor: default; }
  .nav-caret { font-size: 11px; color: var(--text-soft); transition: transform var(--t-fast); }

  /* 侧栏中的 tab 项：由「标签页」改为「列表项」
     ★ 可读性：13px → 14.5px，行高与内边距同步加大。
     ★ color 用 !important：基础段第 336 行的原 .tab 声明了 color:var(--text-soft)，
       同为单一类选择器且本条在 @media 内 —— 实测被其压制（对比度只有 5.17:1，
       而 --text 应为 14.6:1）。此处属「用新样式覆盖旧样式」的正当场景，
       故显式提升优先级，避免依赖规则书写顺序（脆弱）。 */
  .tab {
    display: flex; align-items: center; gap: 0;
    width: 100%; padding: clamp(6px, 1.12vh, 11px) 12px;
    font-size: clamp(13.5px, 1.5vh, 14.5px); font-weight: 500;
    line-height: clamp(1.32, 1.45, 1.5);
    color: var(--text) !important;
    border-radius: var(--r-sm);
    border-bottom: none; border-left: 3px solid transparent;
    text-align: left;
  }
  .tab:hover { color: var(--text); background: var(--n-100); }
  .tab.active {
    color: var(--accent); font-weight: 600;
    background: var(--accent-light);
    border-left-color: var(--accent); border-bottom-color: transparent;
  }
  /* 徽标推到右侧 */
  .tab .tab-badge { margin-left: auto; }
  /* ★ 图标固定宽度 —— 解决对齐（老王反馈：字体与图标未对齐）
     根因：不同 emoji 的字符宽度不一致（🗂 / 💰 / ⚠️ 宽度各异），
     用 flex 自然排布时文字起始位置参差。给 .t-ico 固定 1.8em 并居中，
     所有文字即可从同一竖线开始。 */
  .tab .t-ico {
    flex: 0 0 1.8em; width: 1.8em; text-align: center;
    font-size: 1.05em; line-height: 1;
  }
  .tab .t-txt { flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

  /* ---------- 侧栏页脚：收放按钮（#827n-b） ---------- */
  .nav-foot {
    margin-top: auto;                 /* 推到侧栏底部 */
    padding: 8px 2px 0;
    border-top: 1px solid var(--border);
  }
  .nav-collapse-btn {
    display: flex; align-items: center; gap: 0;
    width: 100%; padding: 10px 12px;
    font-family: inherit; font-size: 13.5px; font-weight: 500;
    color: var(--text-soft);
    background: transparent; border: none; border-radius: var(--r-sm);
    cursor: pointer; text-align: left;
  }
  .nav-collapse-btn:hover { background: var(--n-100); color: var(--text); }
  .nav-collapse-btn .ncb-ico {
    flex: 0 0 1.8em; width: 1.8em; text-align: center; font-size: 1.15em; line-height: 1;
  }
  .nav-collapse-btn .ncb-txt { flex: 1 1 auto; white-space: nowrap; overflow: hidden; }
}

/* ---------- 手动收起态（页脚按钮切换；任何宽度都生效） ----------
   优先级高于窗口宽度的自动折叠：用户显式收起后，即使大屏也保持图标条。
   ★ 用 body[data-nav-collapsed] 作为开关，状态由 app.js 写入并记忆到 localStorage。 */
@media (min-width: 900px) {
  body[data-nav-collapsed="1"] { --side-w: 66px; }
  body[data-nav-collapsed="1"] .tabs { padding: 12px 8px 18px; }
  body[data-nav-collapsed="1"] .tabs .nav-sec-title { display: none; }
  body[data-nav-collapsed="1"] .tabs .nav-sec-body { display: block !important; }
  body[data-nav-collapsed="1"] .tab {
    justify-content: center; padding: 13px 0;
    border-left-width: 0;
  }
  body[data-nav-collapsed="1"] .tab .t-txt { display: none; }
  body[data-nav-collapsed="1"] .tab .t-ico { flex: 0 0 auto; width: auto; font-size: 21px; }
  body[data-nav-collapsed="1"] .tab .tab-badge {
    position: absolute; top: 5px; right: 7px; margin-left: 0;
    transform: scale(.88); transform-origin: top right;
  }
  body[data-nav-collapsed="1"] .tab { position: relative; }
  body[data-nav-collapsed="1"] .nav-collapse-btn { justify-content: center; padding: 10px 0; }
  body[data-nav-collapsed="1"] .nav-collapse-btn .ncb-ico { flex: 0 0 auto; width: auto; font-size: 19px; }
  body[data-nav-collapsed="1"] .ncb-txt { display: none; }
  /* 收起态同样保留悬停浮出名称，避免只剩图标后不知道是什么 */
  body[data-nav-collapsed="1"] .tab:hover::after {
    content: attr(data-nav-label);
    position: absolute; left: calc(100% + 10px); top: 50%; transform: translateY(-50%);
    background: var(--n-900, #0f172a); color: #fff;
    padding: 7px 12px; border-radius: 7px;
    font-size: 13.5px; font-weight: 500; white-space: nowrap;
    z-index: 80; pointer-events: none;
  }
}

/* ---------- 中层：900–1200px 折叠为图标条（悬停浮出完整导航） ---------- */
@media (min-width: 900px) and (max-width: 1200px) {
  :root { --side-w: 66px; }

  .tabs { padding: 12px 8px 18px; }
  .tabs .nav-sec-title { display: none; }          /* 图标条不显示分组标题 */
  .tabs .nav-sec-body { display: block !important; } /* 折叠态下所有分组都露出图标 */

  .tab {
    justify-content: center; padding: 13px 0;
    border-left-width: 0; border-radius: var(--r-sm);
  }
  .tab .t-txt { display: none; }        /* 只留 emoji 图标 */
  /* ★ 可读性：折叠态下图标是唯一信息载体，放大到 21px（原继承 13px 偏小）
     同时解除 .t-ico 的 1.8em 固定宽度（展开态用于对齐，折叠态不需要） */
  .tab .t-ico { flex: 0 0 auto; width: auto; font-size: 21px; line-height: 1.1; }
  .tab .tab-badge {
    position: absolute; top: 5px; right: 7px; margin-left: 0;
    transform: scale(.88); transform-origin: top right;
  }
  .tab { position: relative; }

  /* 悬停时浮出完整名称，不挤占正文 */
  .tab:hover::after {
    content: attr(data-nav-label);
    position: absolute; left: calc(100% + 10px); top: 50%; transform: translateY(-50%);
    background: var(--n-900, #0f172a); color: #fff;
    padding: 7px 12px; border-radius: 7px;
    font-size: 13.5px; font-weight: 500; white-space: nowrap;
    z-index: 80; pointer-events: none;
  }
}
.content { padding: 0 32px 48px; }
.view { display: none; }
.view.active { display: block; }

/* ================================================================
 * TOOLBAR
 * ================================================================ */
.toolbar {
  display: flex; gap: 10px; align-items: center;
  margin: 20px 0 16px; flex-wrap: wrap;
}
.search-input, .filter-select {
  padding: 9px 14px; border: 1.5px solid var(--border); border-radius: var(--r-sm);
  font-size: 13px; background: var(--bg-surface); color: var(--text); outline: none;
  transition: border var(--t-fast), box-shadow var(--t-fast);
  font-family: inherit;
}
.search-input { flex: 1; min-width: 240px; }
.search-input:hover, .filter-select:hover { border-color: var(--n-300); }
.search-input:focus, .filter-select:focus { border-color: var(--accent); box-shadow: 0 0 0 3px rgba(37,99,235,.08); }
.filter-select { min-width: 130px; cursor: pointer; appearance: none; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%2394a3b8' d='M6 8L1 3h10z'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 10px center; padding-right: 30px; }


.filter-date {
  padding: 9px 10px; border: 1.5px solid var(--border); border-radius: var(--r-sm);
  font-size: 13px; background: var(--bg-surface); color: var(--text); outline: none;
  width: 140px; transition: border var(--t-fast), box-shadow var(--t-fast);
  font-family: inherit;
}
.filter-date:focus { border-color: var(--accent); box-shadow: 0 0 0 3px rgba(37,99,235,.08); }
.filter-date-sep { color: var(--text-mute); font-size: 12px; font-weight: 500; }

/* ================================================================
 * BATCH BAR
 * ================================================================ */
.batch-bar {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 16px; margin: 0 0 14px;
  background: var(--inf-50); border: 1px solid var(--inf-100);
  border-radius: var(--r-md);
  font-size: 13px; flex-wrap: wrap;
  animation: slideDown .2s ease;
}
@keyframes slideDown { from { opacity:0; transform:translateY(-8px); } to { opacity:1; transform:translateY(0); } }
.batch-count { font-weight: 700; color: var(--accent); margin-right: auto; }

/* ================================================================
 * CHECKBOX
 * ================================================================ */
.checkbox-label {
  display: inline-flex; align-items: center; cursor: pointer; user-select: none;
  position: relative; width: 20px; height: 20px; flex-shrink: 0;
}
.checkbox-label input[type="checkbox"] { position: absolute; opacity: 0; width: 0; height: 0; }
.checkbox-label .checkmark {
  display: flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; border: 2px solid var(--border);
  border-radius: var(--r-xs); transition: all var(--t-fast);
  background: var(--bg-surface);
}
.checkbox-label input:checked + .checkmark {
  background: var(--accent); border-color: var(--accent);
}
.checkbox-label input:checked + .checkmark::after {
  content: '✓'; color: #fff; font-size: 12px; font-weight: 700; line-height: 1;
}

/* ================================================================
 * ORDER CARD
 * ================================================================ */
.orders-list { display: flex; flex-direction: column; gap: 14px; }
.order-card {
  background: var(--bg-surface); border: 1px solid var(--border);
  border-radius: var(--r-md); overflow: hidden;
  box-shadow: var(--shadow-xs);
  transition: box-shadow var(--t-normal), border-color var(--t-fast), transform var(--t-normal);
}
/* #679c 圆润化：hover 轻微上浮 */
.order-card:hover { box-shadow: var(--shadow-lg); border-color: var(--n-300); transform: translateY(-2px); }
.order-card.selected { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent), var(--shadow-md); }
.order-card.selected { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent), var(--shadow-md); }

.order-card-top {
  padding: 14px 18px; display: flex; align-items: center;
  justify-content: space-between; gap: 12px; flex-wrap: wrap;
}
.order-card-main { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; flex: 1; }
.order-check { width: 16px; height: 16px; accent-color: var(--accent); cursor: pointer; flex-shrink: 0; }
.order-no { font-weight: 700; font-size: 15px; color: var(--n-900); letter-spacing: -0.2px; }
.order-customer { color: var(--text-soft); font-size: 13px; font-weight: 500; }
.order-remark { color: var(--text-mute); font-size: 12px; max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.order-card-actions { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }

/* stage dots bar */
.stage-dots {
  padding: 10px 18px 12px; display: flex; align-items: center; gap: 6px;
  background: linear-gradient(to bottom, var(--n-50), transparent);
  border-top: 1px solid var(--border-light);
}
.stage-dot {
  width: 28px; height: 28px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 700; color: #fff;
  transition: transform var(--t-fast), box-shadow var(--t-fast);
  position: relative;
}
.stage-dot::after {
  content: ''; position: absolute; right: -7px; top: 50%;
  width: 8px; height: 2px; background: var(--border);
  transform: translateY(-50%);
}
.stage-dot:last-child::after { display: none; }
.stage-dot:hover { transform: scale(1.15); }
.s-dot-done { background: var(--suc-500); box-shadow: 0 0 8px rgba(34,197,94,.3); }
.s-dot-active { background: var(--pri-500); box-shadow: 0 0 8px rgba(59,130,246,.3); animation: dotGlow 2s ease-in-out infinite; }
.s-dot-overdue { background: var(--dgr-500); box-shadow: 0 0 8px rgba(239,68,68,.3); animation: dotGlow 1.5s ease-in-out infinite; }
.s-dot-upcoming { background: var(--n-300); }
@keyframes dotGlow { 0%,100%{box-shadow: 0 0 4px currentColor} 50%{box-shadow: 0 0 12px currentColor} }

/* item rows inside order card */
.order-items-wrap { padding: 6px 18px 14px; display: flex; flex-direction: column; gap: 8px; }

/* ================================================================
 * ITEM ROW
 * ================================================================ */
.item-row {
  display: flex; align-items: center; gap: 12px;
  padding: 14px 16px; border-radius: var(--r-sm);
  background: var(--n-50); border: 1px solid var(--border-light);
  transition: all var(--t-fast); flex-wrap: wrap;
}
.item-row:hover { background: var(--bg-surface); border-color: var(--n-200); box-shadow: var(--shadow-xs); }
.item-row.item-selected { border-color: var(--accent); background: var(--accent-light); }
.item-row.item-overdue { border-left: 3px solid var(--dgr-500); }
.item-row.item-done { border-left: 3px solid var(--suc-500); }
.item-row.item-active { border-left: 3px solid var(--pri-500); }
.item-check { width: 15px; height: 15px; accent-color: var(--accent); cursor: pointer; flex-shrink: 0; }
.item-info { display: flex; align-items: center; gap: 10px; flex: 1; min-width: 0; flex-wrap: wrap; }
.item-name { font-weight: 600; font-size: 14px; color: var(--n-800); }
.item-spec { font-size: 12px; color: var(--text-soft); }
.item-qty {
  font-size: 12px; font-weight: 600; color: var(--pri-600);
  background: var(--pri-50); padding: 2px 10px; border-radius: var(--r-full);
}
.item-stages { display: flex; gap: 6px; flex-wrap: wrap; }
.stg-cell {
  padding: 6px 12px; border-radius: var(--r-sm);
  font-size: 11px; text-align: center; min-width: 90px;
  transition: transform var(--t-fast);
}
.stg-cell:hover { transform: translateY(-1px); }
.stg-cell.stg-done { background: var(--suc-50); border: 1px solid var(--suc-500); }
.stg-cell.stg-done-late { background: var(--dgr-50); border: 1px solid var(--dgr-500); }
.stg-cell.stg-active { background: var(--pri-50); border: 1px solid var(--pri-500); }
.stg-cell.stg-overdue { background: var(--dgr-50); border: 1px solid var(--dgr-500); animation: alertShimmer 2s ease-in-out infinite; }
.stg-cell.stg-upcoming { background: var(--n-50); border: 1px dashed var(--n-300); }
@keyframes alertShimmer { 0%,100%{opacity:1} 50%{opacity:.7} }
.stg-name { font-weight: 700; margin-bottom: 2px; font-size: 11px; }
.stg-assignee { font-size: 10px; color: var(--text-mute); display: block; }
.stg-dates { font-size: 10px; color: var(--text-mute); display: block; }
.stg-days { font-size: 10px; font-weight: 700; display: block; margin-top: 1px; color: var(--suc-600); }
.stg-days.stg-days-active { color: var(--pri-600); }
.stg-remark { font-size: 10px; color: var(--n-500); display: block; margin-top: 1px; font-style: italic; max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
.item-actions { display: flex; gap: 4px; flex-shrink: 0; }

/* ================================================================
 * DELIVERY BADGE
 * ================================================================ */
.delivery-badge {
  display: inline-flex; align-items: center; gap: 3px;
  padding: 2px 10px; border-radius: var(--r-full); font-size: 11px; font-weight: 600;
}
.delivery-badge.overdue { color: var(--dgr-700); background: var(--dgr-100); border: 1px solid var(--dgr-200); }
.delivery-badge.approaching { color: var(--wrn-700); background: var(--wrn-100); border: 1px solid var(--wrn-500); animation: pulse 2s ease-in-out infinite; }
.delivery-badge.ok { color: var(--suc-700); background: var(--suc-50); border: 1px solid var(--suc-500); }
@keyframes pulse { 0%,100%{opacity:1} 50%{opacity:.65} }

/* order delivery badge */
.order-dl-badge {
  display: inline-flex; padding: 2px 10px; border-radius: var(--r-full);
  font-size: 11px; font-weight: 600; margin-left: 4px;
}
.order-dl-badge.overdue { background: var(--dgr-100); color: var(--dgr-700); animation: pulse 2s infinite; }
.order-dl-badge.approaching { background: var(--wrn-100); color: var(--wrn-700); }
.order-dl-badge.normal { background: var(--suc-50); color: var(--suc-700); border: 1px solid var(--suc-300); }
.order-dl-badge.done { background: var(--n-100); color: var(--text-mute); }

/* ================================================================
 * #849 采购徽标语义分色
 *   原因：原只有 overdue/approaching/normal/done 四档，导致「已开发票/已结清/
 *         个人垫付/对公转账」全挤在 done(灰)、「待转款/合同已传/待上传发票」
 *         全挤在 approaching(黄)，一眼分不清。
 *   做法：新增语义类，**不改原有四档**（库存/报价/3D 等模块仍在用）。
 *   配色：浅底 + 深字，全部走 CSS 变量 → 自动跟随 6 套主题（day/night/eye/
 *         business/forest/morandi）。
 * ================================================================ */
.order-dl-badge.b-ok    { background: var(--suc-50);  color: var(--suc-700); border: 1px solid var(--n-200); }
.order-dl-badge.b-wait  { background: var(--wrn-100); color: var(--wrn-700); }
.order-dl-badge.b-doing { background: var(--inf-100); color: var(--inf-700); }
.order-dl-badge.b-attr  { background: var(--pri-50);  color: var(--pri-700); }
.order-dl-badge.b-warn  { background: var(--dgr-100); color: var(--dgr-700); }
.order-dl-badge.b-plain { background: var(--n-100);   color: var(--n-600); }

/* ================================================================
 * PO BADGE
 * ================================================================ */
.po-badge { display: inline-flex; align-items: center; gap: 4px; padding: 2px 10px; border-radius: var(--r-full); font-size: 11px; font-weight: 600; }
.po-yes { background: var(--suc-50); color: var(--suc-700); border: 1px solid var(--suc-500); }
.po-no { background: var(--wrn-50); color: var(--wrn-700); border: 1px solid var(--wrn-500); }
.po-toggle-label { display: inline-flex; align-items: center; gap: 6px; font-weight: 500; cursor: pointer; font-size: 13px; }

/* ================================================================
 * ATTACHMENTS
 * ================================================================ */
.order-attach-section {
  border-top: 1px solid var(--border-light);
  padding: 12px 18px 14px;
  background: linear-gradient(to bottom, var(--n-50), var(--bg-surface));
}
.attach-list { margin-bottom: 10px; display: flex; flex-direction: column; gap: 6px; }
.attach-item {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 12px; background: var(--bg-surface);
  border: 1px solid var(--border-light); border-radius: var(--r-sm);
  font-size: 12px; transition: border-color var(--t-fast);
}
.attach-item:hover { border-color: var(--n-300); }
/* #699 有备注（留言）的附件突出显示，与其他附件一眼区分 */
.attach-item.has-comment {
  background: rgba(245, 158, 11, 0.10);
  border-color: #f59e0b;
  border-left: 3px solid #f59e0b;
}
.attach-item.has-comment .attach-name { font-weight: 600; }
.attach-item.has-comment .attach-date { color: #b45309; }
.attach-comment.has-notes {
  background: #f59e0b !important;
  border-color: #f59e0b !important;
  color: #fff !important;
  font-weight: 600;
}
/* #753 订单卡片「留言」按钮：有留言 → 琥珀实底高亮（与附件备注高亮同语义），条数白底徽标 */
.btn-msg-board.has-msgs {
  background: #f59e0b !important;
  border-color: #f59e0b !important;
  color: #fff !important;
  font-weight: 600;
  box-shadow: 0 0 0 2px rgba(245, 158, 11, .18);
}
.btn-msg-board.has-msgs .msg-cnt {
  display: inline-block;
  min-width: 16px;
  padding: 0 4px;
  margin-left: 2px;
  border-radius: 9px;
  background: #fff;
  color: #b45309;
  font-size: 11px;
  line-height: 16px;
  font-weight: 700;
  text-align: center;
  vertical-align: 1px;
}
.attach-name { flex: 1; font-weight: 500; }
.attach-date { color: var(--text-mute); font-size: 11px; }
.attach-empty { color: var(--text-mute); font-size: 12px; font-style: italic; }
.attach-upload { margin-top: 8px; }
/* #502 批量打印：勾选框 + 打印工具条 */
.attach-print-check { accent-color: var(--accent); cursor: pointer; flex-shrink: 0; }
.attach-print-toolbar {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 8px 12px; margin-bottom: 10px;
  background: var(--n-100); border: 1px solid var(--border-light); border-radius: var(--r-sm);
}
.attach-select-all { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; color: var(--text-2); cursor: pointer; user-select: none; }
.attach-select-all input { accent-color: var(--accent); cursor: pointer; }
.attach-copies-label { font-size: 12px; color: var(--text-mute); }
.attach-print-toolbar input[type="number"] {
  width: 64px; padding: 4px 6px; border: 1px solid var(--n-300); border-radius: 6px;
  font-size: 13px; text-align: center; background: var(--bg-surface); color: var(--text-1);
}

/* ================================================================
 * EMPTY STATE
 * ================================================================ */
.empty-state { text-align: center; padding: 60px 20px; color: var(--text-mute); }
.empty-state .icon { font-size: 44px; margin-bottom: 10px; }
.empty-items { text-align: center; padding: 20px 12px; color: var(--text-mute); font-size: 13px; background: var(--n-50); border-radius: var(--r-sm); margin: 12px; }

/* ================================================================
 * MODALS
 * ================================================================ */
.modal-overlay {
  position: fixed; inset: 0; background: rgba(15,23,42,.5);
  backdrop-filter: blur(4px);
  display: none; align-items: center; justify-content: center;
  z-index: 100; padding: 20px;
  animation: fadeIn .2s ease;
}
@keyframes fadeIn { from { opacity:0 } to { opacity:1 } }
.modal-overlay.show, .modal-overlay[style*="display: flex"] {
  display: flex !important;
}
.modal {
  background: var(--bg-surface); border-radius: var(--r-lg);
  width: 100%; max-width: 560px;
  max-height: 90vh;
  /* #802e 三段式 flex —— 由「.modal 整体滚动」改为「仅 .modal-body 滚动」。
     原结构 .modal{overflow-y:auto} 配 .modal-foot{position:sticky;bottom:0}：
     sticky 的 foot 在滚动过程中吸在弹层底部，会**视觉覆盖其正下方的输入框**
     （滚动到中间位置必然发生，滚到最底才恢复）—— 用户反馈「新增订单里输入框
     被『取消/保存订单』按钮栏挡住」，采购申请同样命中；键盘弹出使弹层变矮后更严重。
     改为 flex 后，body 的高度已扣除 head/foot，foot 与 body 内容不再重叠。
     此做法与 #modalOrderSheet 早已验证过的写法保持一致（原先只改了那一个弹窗）。 */
  display: flex; flex-direction: column;
  overflow: hidden;
  box-shadow: var(--shadow-xl);
  animation: modalIn .25s ease;
}
@keyframes modalIn { from { opacity:0; transform:translateY(14px) scale(.96); } to { opacity:1; transform:translateY(0) scale(1); } }
.modal-lg { max-width: 900px; }
.modal-xl { max-width: 1080px; }
.modal-head {
  display: flex; justify-content: space-between; align-items: center;
  padding: 18px 24px; border-bottom: 1px solid var(--border);
  position: sticky; top: 0; background: var(--bg-surface);
  border-radius: var(--r-lg) var(--r-lg) 0 0; z-index: 2;
}
.modal-head h3 { font-size: 17px; font-weight: 700; color: var(--n-900); letter-spacing: -0.2px; }
.modal-close {
  border: none; background: transparent; cursor: pointer;
  font-size: 18px; width: 32px; height: 32px; border-radius: var(--r-sm);
  color: var(--text-soft); display: flex; align-items: center; justify-content: center;
  transition: all var(--t-fast);
}
.modal-close:hover { background: var(--n-100); color: var(--text); }
.modal-body {
  padding: 20px 24px;
  /* #802e 唯一的滚动容器。min-height:0 不可省 —— flex 子项默认 min-height:auto，
     不加就缩不到可用高度以下，body 会顶开容器把 foot 挤走。 */
  flex: 1 1 auto; min-height: 0;
  overflow-y: auto; -webkit-overflow-scrolling: touch;
  overscroll-behavior-y: contain;
}
.modal-foot {
  padding: 14px 24px; border-top: 1px solid var(--border);
  display: flex; justify-content: flex-end; gap: 10px;
  position: sticky; bottom: 0; background: var(--bg-surface);
  border-radius: 0 0 var(--r-lg) var(--r-lg);
}

/* ================================================================
 * FORMS
 * ================================================================ */
.form-row { margin-bottom: 16px; }
.form-row label { display: block; font-size: 13px; font-weight: 600; color: var(--n-700); margin-bottom: 6px; }
.form-row input, .form-row select, .form-row textarea {
  width: 100%; padding: 9px 14px; border: 1.5px solid var(--border); border-radius: var(--r-sm);
  font-size: 13px; outline: none; background: var(--bg-surface); color: var(--text);
  transition: border var(--t-fast), box-shadow var(--t-fast);
  font-family: inherit;
}
.form-row input:hover, .form-row select:hover { border-color: var(--n-300); }
.form-row input:focus, .form-row select:focus, .form-row textarea:focus {
  border-color: var(--accent); box-shadow: 0 0 0 3px rgba(37,99,235,.08);
}
.form-row select { cursor: pointer; appearance: auto; }
.form-select-full {
  width: 100%; padding: 9px 14px; border: 1.5px solid var(--border); border-radius: var(--r-sm);
  font-size: 13px; outline: none; background: var(--bg-surface); color: var(--text);
  cursor: pointer; transition: border var(--t-fast), box-shadow var(--t-fast);
}
.form-select-full:focus { border-color: var(--accent); box-shadow: 0 0 0 3px rgba(37,99,235,.08); }
.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0 16px; }
.form-section-title {
  font-size: 14px; font-weight: 700; color: var(--n-800);
  margin: 20px 0 6px; padding-bottom: 8px; border-bottom: 1px solid var(--border-light);
}
.form-section-hint { font-size: 12px; color: var(--text-mute); margin-bottom: 14px; }
.form-label-hint { font-weight: 400; color: var(--text-mute); font-size: 11px; }

.input-with-btn { display: flex; gap: 0; }
.input-with-btn input { flex: 1; border-top-right-radius: 0; border-bottom-right-radius: 0; }
.input-with-btn button { border-top-left-radius: 0; border-bottom-left-radius: 0; }
.input-row { display: flex; gap: 10px; }
.input-row input { flex: 1; padding: 9px 14px; border: 1.5px solid var(--border); border-radius: var(--r-sm); font-size: 13px; outline: none; }
.input-row input:focus { border-color: var(--accent); box-shadow: 0 0 0 3px rgba(37,99,235,.08); }

/* stage assignee form */
.stage-assign-row { margin-bottom: 8px; }
.stage-assign-row label { min-width: 80px; }

/* file upload area */
.file-upload-area {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 12px 16px; background: var(--n-50);
  border: 1.5px dashed var(--n-300); border-radius: var(--r-md);
  margin-bottom: 10px; transition: border-color var(--t-fast);
}
.file-upload-area:hover { border-color: var(--accent); }
.file-name {
  font-size: 13px; color: var(--text-mute);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 220px;
}
.quote-ext-hint {
  font-size: 12px; color: var(--text-mute); opacity: .8;
  text-align: center; word-break: break-all;
}
.file-preview {
  margin-top: 10px; padding: 12px 16px;
  background: var(--n-50); border-radius: var(--r-sm);
  max-height: 220px; overflow-y: auto; font-size: 12px;
  line-height: 1.6; border: 1px solid var(--border-light);
}

/* v14: drag-and-drop zone */
.file-drop-zone {
  flex-direction: column; align-items: center; gap: 8px;
  padding: 24px 16px; min-height: 80px;
}
.file-drop-zone.drag-over {
  border-color: var(--accent); background: var(--accent-light, #e8f0fe);
  border-style: solid;
}
.drop-hint {
  font-size: 13px; color: var(--text-mute); text-align: center;
}
.drop-hint button {
  color: var(--accent); text-decoration: underline; cursor: pointer;
}

/* v14: admin panel tabs */
.admin-panel-tabs {
  display: flex; gap: 0; border-bottom: 2px solid var(--border-light); margin-bottom: 16px;
}
.admin-tab {
  padding: 10px 20px; border: none; background: none; cursor: pointer;
  font-size: 14px; color: var(--text-mute); border-bottom: 2px solid transparent;
  margin-bottom: -2px; transition: all var(--t-fast);
}
.admin-tab.active {
  color: var(--accent); border-bottom-color: var(--accent); font-weight: 600;
}

/* v14: partNo in expand list */
.part-expand-partno {
  font-size: 11px; color: var(--text-mute); font-family: monospace;
  background: var(--n-100); padding: 1px 6px; border-radius: 3px;
  margin-right: 4px; min-width: 60px; text-align: center;
}

/* inherit notice */
.form-inherit-notice {
  padding: 14px 16px; background: var(--suc-50);
  border: 1px solid var(--suc-500); border-radius: var(--r-sm);
  font-size: 13px; color: var(--suc-700); margin-top: 14px;
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
}
.inherit-tag {
  display: inline-block; padding: 2px 10px; background: var(--suc-50);
  border-radius: var(--r-full); font-weight: 600; font-size: 12px;
  color: var(--suc-700); border: 1px solid var(--suc-500);
}

/* ================================================================
 * STAGE ADVANCE MODAL
 * ================================================================ */
.advance-info {
  margin-bottom: 14px; padding-bottom: 10px;
  border-bottom: 1px solid var(--border);
  font-size: 14px;
}
.advance-stages { display: flex; flex-direction: column; gap: 6px; }
.adv-stage-row { padding: 12px 16px; border-radius: var(--r-sm); transition: background var(--t-fast); }
.adv-stage-done { background: var(--suc-50); border-left: 3px solid var(--suc-500); }
.adv-stage-done-late { background: var(--dgr-50); border-left: 3px solid var(--dgr-500); }
.adv-stage-overdue { background: var(--dgr-50); border-left: 3px solid var(--dgr-500); }
.adv-stage-active { background: var(--pri-50); border-left: 3px solid var(--pri-500); }
.adv-stage-upcoming { background: var(--n-50); border-left: 3px solid var(--n-300); }
.adv-stage-head { display: flex; align-items: center; gap: 8px; margin-bottom: 4px; flex-wrap: wrap; }
.adv-stage-name { font-weight: 700; font-size: 13px; }
.adv-stage-status { font-size: 12px; font-weight: 500; }
.adv-stage-assignee { font-size: 12px; color: var(--text-mute); }
.adv-stage-dates { font-size: 11px; color: var(--text-mute); margin-bottom: 4px; }
.adv-stage-actions { margin-top: 8px; display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.adv-stage-days { font-size: 12px; color: var(--text-mute); margin-top: 4px; }
.adv-stage-days strong { color: var(--pri-600); }
.adv-stage-remark { font-size: 12px; color: var(--text-mute); margin-top: 4px; font-style: italic; }
.adv-stage-remark-input {
  padding: 6px 10px; border: 1px solid var(--n-300); border-radius: var(--r-sm);
  font-size: 13px; color: var(--n-800); background: var(--bg-surface);
  transition: border-color var(--t-fast);
}
.adv-stage-remark-input:focus { outline: none; border-color: var(--pri-500); box-shadow: 0 0 0 2px var(--pri-100); }
.adv-allitems-assignee {
  font-size: 12px; padding: 6px 10px; border: 1.5px solid var(--border);
  border-radius: var(--r-xs); background: var(--bg-surface); color: var(--text);
  outline: none; transition: border var(--t-fast);
}
.adv-allitems-assignee:focus { border-color: var(--accent); }

/* ================================================================
 * TODOS
 * ================================================================ */
.todos-list { display: flex; flex-direction: column; gap: 10px; }
.todo-item {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 18px; background: var(--bg-surface);
  border: 1px solid var(--border); border-radius: var(--r-sm);
  box-shadow: var(--shadow-xs); gap: 14px; flex-wrap: wrap;
  transition: all var(--t-fast);
}
.todo-item:hover { box-shadow: var(--shadow-sm); border-color: var(--n-300); }
.todo-info { flex: 1; font-size: 13px; }
.todo-info strong { color: var(--n-800); }
.todo-stage {
  display: inline-block; margin-left: 8px; padding: 2px 10px;
  background: var(--pri-50); color: var(--pri-700);
  border-radius: var(--r-full); font-size: 11px; font-weight: 600;
}
.todo-actions { display: flex; gap: 6px; flex-shrink: 0; }

/* ================================================================
 * ALERTS
 * ================================================================ */
.alerts-header h2, .gantt-header h2 { font-size: 17px; margin-bottom: 4px; font-weight: 700; }
.alerts-header p, .gantt-header p { font-size: 13px; color: var(--text-soft); margin-bottom: 18px; }
.alerts-list { display: flex; flex-direction: column; gap: 10px; }
.alert-item {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 18px; background: var(--bg-surface);
  border: 1px solid var(--border); border-radius: var(--r-sm);
  box-shadow: var(--shadow-xs); gap: 12px; flex-wrap: wrap;
  transition: all var(--t-fast);
}
.alert-item.alert-overdue { border-left: 4px solid var(--dgr-500); background: var(--dgr-50); }
.alert-item.alert-approaching { border-left: 4px solid var(--wrn-500); background: var(--wrn-50); }
.alert-info { flex: 1; font-size: 13px; }
.alert-info strong { color: var(--n-800); }
.alert-stage {
  display: inline-block; margin-left: 8px; padding: 2px 10px;
  background: var(--dgr-100); color: var(--dgr-700);
  border-radius: var(--r-full); font-size: 11px; font-weight: 600;
}

/* v20: 预警面板 — 订单卡片 */
.alert-order-card {
  padding: 14px 18px; background: var(--bg-surface);
  border: 1px solid var(--border); border-radius: var(--r-sm);
  box-shadow: var(--shadow-xs); transition: all var(--t-fast);
  border-left: 4px solid var(--dgr-500);
}
.alert-order-card:hover { border-color: var(--pri-500); box-shadow: var(--shadow-sm); }
.alert-order-header { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; flex-wrap: wrap; }
.alert-order-info { flex: 1; font-size: 13px; }
.alert-order-info strong { color: var(--n-800); font-size: 15px; }
.alert-order-customer { margin-left: 8px; color: var(--text-soft); }
.alert-order-parts { margin-left: 8px; color: var(--text-mute); font-size: 12px; }
.alert-order-badges { display: flex; gap: 6px; flex-wrap: wrap; }
.alert-badge {
  display: inline-block; padding: 3px 10px; border-radius: var(--r-full);
  font-size: 11px; font-weight: 600;
}
.alert-badge-overdue { background: var(--dgr-100); color: var(--dgr-700); }
.alert-badge-approaching { background: var(--wrn-100); color: var(--wrn-700); }
.alert-order-footer { display: flex; justify-content: space-between; align-items: center; margin-top: 8px; gap: 8px; flex-wrap: wrap; }
.alert-assignee { font-size: 12px; color: var(--text-soft); }
.alert-order-date { font-size: 12px; color: var(--text-mute); }

/* v20: 预警详情弹窗 */
.alert-detail-order-info {
  display: flex; gap: 24px; flex-wrap: wrap; padding: 12px;
  background: var(--bg-page); border-radius: var(--r-sm); margin-bottom: 16px;
}
.alert-detail-order-info .detail-field label { font-size: 11px; color: var(--text-mute); display: block; }
.alert-detail-order-info .detail-field span { font-size: 14px; color: var(--n-800); font-weight: 600; }
.alert-detail-parts { display: flex; flex-direction: column; gap: 10px; }
.alert-detail-part {
  padding: 12px; border: 1px solid var(--border); border-radius: var(--r-sm);
}
.alert-detail-part.has-warning { border-left: 4px solid var(--dgr-500); background: var(--dgr-50); }
.alert-detail-part-header { font-size: 13px; font-weight: 600; margin-bottom: 6px; }
.alert-detail-part-warnings { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 6px; }
.alert-detail-part-stages { display: flex; gap: 4px; flex-wrap: wrap; margin-top: 4px; }
.alert-detail-stage {
  display: inline-block; padding: 2px 8px; border-radius: var(--r-full);
  font-size: 11px; background: var(--n-100); color: var(--text-soft);
}
.alert-detail-stage.stage-done { background: var(--suc-50); color: var(--suc-700); }
.alert-detail-stage.stage-done-late { background: var(--wrn-50); color: var(--wrn-700); }
.alert-detail-stage.stage-overdue { background: var(--dgr-100); color: var(--dgr-700); font-weight: 600; }
.alert-detail-stage.stage-active { background: var(--pri-100); color: var(--pri-700); }

/* ================================================================
 * GANTT
 * ================================================================ */
.gantt-wrap {
  background: var(--bg-surface); border: 1px solid var(--border);
  border-radius: var(--r-md); padding: 20px;
  box-shadow: var(--shadow-xs); overflow-x: auto;
}
.gantt-chart { min-width: 100%; }
.gantt-row { display: flex; align-items: center; }
.gantt-header { position: sticky; top: 0; z-index: 1; background: var(--bg-surface); }
.gantt-label {
  min-width: 180px; max-width: 180px; padding: 4px 12px 4px 0;
  font-size: 12px; font-weight: 500; color: var(--text-soft);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  flex-shrink: 0;
}
.gantt-day {
  flex: 1; min-width: 36px; text-align: center;
  font-size: 10px; color: var(--text-mute); font-weight: 500;
  padding: 6px 0; border-left: 1px solid var(--border-light);
}
.gantt-cell {
  flex: 1; min-width: 36px; height: 28px;
  border-left: 1px solid var(--border-light); transition: background var(--t-fast);
}
.gantt-cell.gantt-done { background: var(--suc-500); }
.gantt-cell.gantt-active { background: var(--pri-500); }
.gantt-cell.gantt-planned { background: var(--n-200); }
.gantt-part-count { font-weight: 400; color: var(--text-mute); font-size: 11px; }

/* ================================================================
 * ACCOUNT MANAGEMENT
 * ================================================================ */
.acct-section { margin-bottom: 22px; }
.acct-section h4 {
  font-size: 14px; font-weight: 700; color: var(--n-700);
  margin-bottom: 10px; padding-bottom: 6px; border-bottom: 1px solid var(--border-light);
}
.acct-add-form { display: flex; flex-direction: column; gap: 12px; }
.acct-user-list { display: flex; flex-direction: column; gap: 6px; }
.acct-user-row {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 14px; background: var(--n-50);
  border-radius: var(--r-sm); border: 1px solid var(--border-light);
  transition: border-color var(--t-fast);
}
.acct-user-row:hover { border-color: var(--n-300); }
.acct-user-info { flex: 1; font-size: 13px; }
.acct-user-name { font-weight: 600; color: var(--n-800); }

/* #795 登录设备列表（个人设置） */
.sess-item {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px; background: var(--n-50);
  border-radius: var(--r-sm); border: 1px solid var(--border-light);
  transition: border-color var(--t-fast);
}
.sess-item:hover { border-color: var(--n-300); }
.sess-item.sess-cur { background: #eef2ff; border-color: #c7d2fe; }
.sess-badge {
  flex: none; font-size: 10.5px; font-weight: 700; line-height: 1;
  padding: 3px 6px; border-radius: 4px;
  background: #4338ca; color: #fff; white-space: nowrap;
}
.acct-user-uname { font-size: 12px; color: var(--text-mute); margin-left: 6px; }
.acct-del-btn { flex-shrink: 0; }

/* ================================================================
 * TOAST
 * ================================================================ */
.toast {
  position: fixed; bottom: 32px; left: 50%; transform: translateX(-50%) translateY(100px);
  background: var(--n-800); color: #fff; padding: 12px 24px;
  border-radius: var(--r-full); font-size: 13px; font-weight: 600;
  opacity: 0; transition: all var(--t-slow); z-index: 200;
  box-shadow: var(--shadow-lg); pointer-events: none;
}
.toast.show, .toast[style*="display: block"] { opacity: 1; transform: translateX(-50%) translateY(0); }
.toast.error { background: var(--dgr-600); }
.toast.info { background: var(--pri-600); }

/* ================================================================
 * SYSTEM SETTINGS
 * ================================================================ */
#sysStageDays .form-row,
#sysStageAssignees .form-row {
  display: flex; align-items: center; gap: 10px;
}
#sysStageDays label,
#sysStageAssignees label { min-width: 80px; font-size: 13px; font-weight: 600; }
#sysStageDays input { width: 80px; }

/* ================================================================
 * STATISTICS DASHBOARD
 * ================================================================ */
.stats-dashboard { padding-top: 8px; }
.stats-kpi-row { display: flex; gap: 12px; flex-wrap: wrap; margin-bottom: 20px; }
  /* 真实类名是 .stat/.stat-num/.stat-label（见 styles.css:288） */
  .stats-bar .stat {
    flex: 0 0 auto; min-width: 86px;
    padding: 8px 12px;
    border-radius: var(--r-md, 10px);
    scroll-snap-align: start;
  }
  .stats-bar .stat:hover { transform: none; box-shadow: var(--shadow-sm); }
  .stats-bar .stat-num { font-size: 19px; letter-spacing: 0; line-height: 1.15; }
  .stats-bar .stat-label { font-size: 11px; margin-top: 1px; white-space: nowrap; }

.stats-grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.stats-panel {
  background: var(--bg-surface); border: 1px solid var(--border);
  border-radius: var(--r-md); padding: 18px 20px;
  box-shadow: var(--shadow-xs);
}
.stats-panel h3 { font-size: 15px; font-weight: 700; margin-bottom: 14px; color: var(--n-800); }

.stats-table { width: 100%; border-collapse: collapse; font-size: 12px; }
.stats-table th {
  text-align: left; padding: 8px 10px; font-weight: 600;
  color: var(--text-soft); border-bottom: 2px solid var(--border);
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.3px;
}
.stats-table td {
  padding: 8px 10px; border-bottom: 1px solid var(--border-light);
  color: var(--text);
}
.stats-table tr:last-child td { border-bottom: none; }
.stats-table tr:hover td { background: var(--n-50); }
.stats-table .st-name { font-weight: 600; }
.stats-table .st-done { color: var(--suc-600); font-weight: 600; }
.stats-table .st-active { color: var(--pri-600); font-weight: 600; }
.stats-table .st-overdue { color: var(--dgr-600); font-weight: 600; }
.stats-table .st-upcoming { color: var(--text-mute); }

.mini-bar {
  display: inline-block; width: 60px; height: 6px;
  background: var(--n-100); border-radius: var(--r-full);
  overflow: hidden; vertical-align: middle; margin-right: 6px;
}
.mini-bar-fill { height: 100%; border-radius: var(--r-full); transition: width .4s ease; background: var(--suc-500); }
.mini-pct { font-size: 11px; color: var(--text-mute); font-weight: 600; vertical-align: middle; }

.stats-empty { text-align: center; padding: 30px; color: var(--text-mute); font-size: 13px; }

/* trend chart */
.trend-chart {
  display: flex; align-items: flex-end; gap: 10px;
  height: 180px; padding: 10px 0;
}
.trend-bar-col { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; }
.trend-bar {
  width: 100%; max-width: 40px; min-height: 4px;
  background: linear-gradient(to top, var(--pri-500), var(--pri-200));
  border-radius: var(--r-xs) var(--r-xs) 0 0;
  display: flex; align-items: flex-start; justify-content: center;
  transition: height .4s ease;
}
.trend-bar span { font-size: 10px; font-weight: 700; color: #fff; margin-top: 2px; }
.trend-label { font-size: 10px; color: var(--text-mute); margin-top: 6px; white-space: nowrap; }

/* ===== 负责人超时统计 ===== */
.overdue-stats-panel { background: var(--bg-surface); border: 1px solid var(--border); border-radius: var(--r-md); padding: 18px 20px; box-shadow: var(--shadow-xs); }
.overdue-stats-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; flex-wrap: wrap; gap: 12px; }
.overdue-stats-header h3 { font-size: 15px; font-weight: 700; color: var(--n-800); margin: 0; }
.overdue-stats-toolbar { display: flex; gap: 8px; align-items: center; }
.overdue-period-select {
  padding: 6px 10px; border: 1px solid var(--border); border-radius: var(--r-sm);
  background: var(--bg-surface); font-size: 13px; color: var(--text);
  cursor: pointer; transition: border-color var(--t-fast);
}
.overdue-period-select:hover { border-color: var(--accent); }
.overdue-period-select:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-light); }

.overdue-kpi-row { display: flex; gap: 16px; flex-wrap: wrap; margin-bottom: 18px; padding: 14px 0; border-top: 1px solid var(--border-light); border-bottom: 1px solid var(--border-light); }
.overdue-kpi-item { display: flex; flex-direction: column; align-items: center; min-width: 80px; }
.overdue-kpi-num { font-size: 24px; font-weight: 800; color: var(--dgr-600); line-height: 1.2; }
.overdue-kpi-label { font-size: 11px; color: var(--text-mute); margin-top: 4px; font-weight: 500; }

.overdue-stats-table th { white-space: nowrap; }
.overdue-total-row td { border-top: 2px solid var(--border); font-weight: 700; background: var(--n-50); }
.overdue-total-row td.st-name { font-size: 13px; }

.overdue-detail-row td { padding: 0 !important; border-bottom: 1px solid var(--border-light) !important; }
.overdue-detail-list { padding: 10px 14px; background: var(--n-50); }
.overdue-detail-item {
  display: flex; align-items: center; gap: 12px; padding: 6px 0;
  font-size: 12px; color: var(--text); flex-wrap: wrap;
}
.overdue-detail-item + .overdue-detail-item { border-top: 1px dashed var(--border-light); }
.od-order { font-weight: 700; color: var(--n-800); min-width: 100px; }
.od-customer { color: var(--text-soft); min-width: 80px; }
.od-part { color: var(--text); flex: 1; min-width: 100px; }
.od-stage { color: var(--pri-600); font-weight: 600; min-width: 60px; }
.od-days { color: var(--dgr-600); font-weight: 700; min-width: 50px; }
.overdue-badge { padding: 2px 8px; border-radius: var(--r-full); font-size: 10px; font-weight: 600; white-space: nowrap; }
.overdue-badge-done { background: #fef3c7; color: #92400e; }
.overdue-badge-active { background: #fee2e2; color: #b91c1c; }

.overdue-detail-btn { font-size: 11px !important; padding: 3px 10px !important; }

@media (max-width: 768px) {
  .overdue-stats-header { flex-direction: column; align-items: flex-start; }
  .overdue-kpi-row { gap: 10px; }
  .overdue-kpi-item { min-width: 60px; }
  .overdue-kpi-num { font-size: 20px; }
}

/* ================================================================
 * PART EXPAND AREA (v13: collapsed card expandable part list)
 * ================================================================ */
.order-item-count {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 3px 10px; background: var(--n-100);
  border-radius: var(--r-full); font-size: 12px; color: var(--text-soft);
  font-weight: 600; transition: all var(--t-fast);
  user-select: none;
}
.order-item-count:hover { background: var(--accent-light); color: var(--accent); }

.order-part-chips {
  display: flex; align-items: center; gap: 6px;
  margin-left: auto; flex-wrap: wrap;
}
.order-part-chip {
  display: inline-block; padding: 4px 10px; border-radius: var(--r-full);
  font-size: 12px; font-weight: 500; cursor: pointer;
  background: var(--n-100); color: var(--text-soft);
  border: 1px solid var(--border-light);
  transition: all var(--t-fast); white-space: nowrap;
  max-width: 200px; overflow: hidden; text-overflow: ellipsis;
}
.order-part-chip:hover { background: var(--accent-light); color: var(--accent); border-color: var(--accent); }
.order-part-chip.overdue { background: var(--dgr-50); color: var(--dgr-700); border-color: var(--dgr-200); }
.order-part-chip.overdue:hover { background: var(--dgr-100); }
.order-part-chip.done { background: var(--suc-50); color: var(--suc-700); border-color: var(--suc-500); }
.order-part-chip.active { background: var(--pri-50); color: var(--pri-700); border-color: var(--pri-200); }
.order-part-chip-more {
  font-size: 11px; color: var(--text-mute); white-space: nowrap;
  padding: 3px 8px; background: var(--n-50); border-radius: var(--r-full);
}

.order-parts-expand {
  border-top: 1px solid var(--border-light);
  background: linear-gradient(to bottom, var(--n-50), var(--bg-surface));
  animation: slideDown .2s ease;
}
.empty-parts { text-align: center; padding: 16px; color: var(--text-mute); font-size: 12px; }

.parts-expand-list { display: flex; flex-direction: column; }
.part-expand-row {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 18px; border-bottom: 1px solid var(--border-light);
  transition: background var(--t-fast); font-size: 13px;
}
.part-expand-row:last-child { border-bottom: none; }
.part-expand-row:hover { background: var(--n-50); }
.part-expand-row.part-expand-overdue { border-left: 3px solid var(--dgr-500); }
.part-expand-row.part-expand-done { border-left: 3px solid var(--suc-500); opacity: .75; }
.part-expand-row.part-expand-active { border-left: 3px solid var(--pri-500); }

.part-expand-name { font-weight: 600; color: var(--n-800); cursor: pointer; min-width: 0; flex: 1; }
.part-expand-name:hover { color: var(--accent); }
.part-expand-spec { color: var(--text-soft); font-size: 12px; white-space: nowrap; }
.part-expand-qty { font-weight: 600; color: var(--pri-600); font-size: 12px; }
.part-cur-stage {
  padding: 2px 10px; border-radius: var(--r-full);
  font-size: 11px; font-weight: 600; white-space: nowrap;
}
.part-cur-stage.active { background: var(--pri-50); color: var(--pri-700); }
.part-cur-stage.overdue { background: var(--dgr-50); color: var(--dgr-700); animation: alertShimmer 2s ease-in-out infinite; }
.part-expand-actions { display: flex; gap: 4px; flex-shrink: 0; }

.part-expand-row .item-check { width: 15px; height: 15px; accent-color: var(--accent); cursor: pointer; flex-shrink: 0; }

/* ================================================================
 * ITEM DETAIL POPUP (v13)
 * ================================================================ */
.item-detail-header {
  margin-bottom: 16px; padding-bottom: 12px;
  border-bottom: 1px solid var(--border-light);
}
.item-detail-header h3 { font-size: 16px; font-weight: 700; color: var(--n-800); margin-bottom: 10px; }
.item-detail-header p { font-size: 12px; color: var(--text-soft); }
.item-detail-fields {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: 8px 16px; margin-bottom: 10px;
}
.detail-field { display: flex; align-items: center; gap: 8px; }
.detail-field label { font-size: 12px; color: var(--text-mute); font-weight: 500; min-width: 40px; flex-shrink: 0; }
.detail-field span { font-size: 13px; font-weight: 600; color: var(--n-800); }
.item-detail-order-info { font-size: 12px; color: var(--text-soft); margin-top: 4px; }
.item-detail-qty {
  display: inline-block; padding: 2px 10px;
  background: var(--pri-50); color: var(--pri-700);
  border-radius: var(--r-full); font-size: 12px; font-weight: 600;
}
.detail-dl-overdue {
  display: inline-block; margin-left: 6px; padding: 2px 8px;
  background: var(--dgr-100); color: var(--dgr-700);
  border-radius: var(--r-full); font-size: 11px; font-weight: 600;
}
.detail-dl-approaching {
  display: inline-block; margin-left: 6px; padding: 2px 8px;
  background: var(--wrn-100); color: var(--wrn-700);
  border-radius: var(--r-full); font-size: 11px; font-weight: 600;
}

.item-detail-stages { display: flex; flex-direction: column; gap: 8px; }
.detail-stage-row {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 16px; border-radius: var(--r-sm);
  gap: 12px; flex-wrap: wrap;
}
.detail-stage-done { background: var(--suc-50); border-left: 3px solid var(--suc-500); }
.detail-stage-done-late { background: var(--dgr-50); border-left: 3px solid var(--dgr-500); }
.detail-stage-overdue { background: var(--dgr-50); border-left: 3px solid var(--dgr-500); animation: alertShimmer 2s ease-in-out infinite; }
.detail-stage-active { background: var(--pri-50); border-left: 3px solid var(--pri-500); }
.detail-stage-upcoming { background: var(--n-50); border-left: 3px solid var(--n-300); }

.detail-stage-left { display: flex; align-items: center; gap: 10px; flex: 1; min-width: 0; }
.detail-stage-idx {
  width: 24px; height: 24px; border-radius: 50%;
  background: var(--n-200); color: var(--text);
  display: flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 700; flex-shrink: 0;
}
.detail-stage-info { min-width: 0; }
.detail-stage-name { font-weight: 700; font-size: 13px; color: var(--n-800); }
.detail-stage-assignee { font-size: 12px; color: var(--text-soft); display: block; }
.detail-stage-assignee.unset { color: var(--text-mute); font-style: italic; }
.detail-stage-dates { font-size: 11px; color: var(--text-mute); display: block; }

.detail-stage-right { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; flex-shrink: 0; }
.detail-stage-days { font-size: 11px; font-weight: 600; color: var(--suc-600); }
.detail-stage-days.active { color: var(--pri-600); }
.detail-stage-comp-days { font-size: 10px; color: var(--text-mute); }
.detail-stage-remark { font-size: 11px; color: var(--text-soft); font-style: italic; max-width: 160px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ================================================================
 * BATCH STAGE COMPLETE MODAL (v13: per-order per-stage)
 * ================================================================ */
.batch-info {
  padding-bottom: 12px; margin-bottom: 12px;
  border-bottom: 1px solid var(--border-light);
  font-size: 14px; color: var(--n-800);
}
.batch-items { display: flex; flex-direction: column; gap: 6px; margin-bottom: 14px; }
.batch-item-row {
  display: flex; align-items: center; justify-content: space-between;
  padding: 10px 14px; background: var(--n-50);
  border-radius: var(--r-sm); border: 1px solid var(--border-light);
  gap: 10px; transition: border-color var(--t-fast);
}
.batch-item-row:hover { border-color: var(--n-300); }
.batch-item-row.overdue { border-left: 3px solid var(--dgr-500); background: var(--dgr-50); }
.batch-item-label { display: flex; align-items: center; gap: 8px; cursor: pointer; flex: 1; min-width: 0; }
.batch-item-label input[type="checkbox"] { width: 15px; height: 15px; accent-color: var(--accent); cursor: pointer; flex-shrink: 0; }
.batch-item-name { font-size: 13px; font-weight: 500; color: var(--n-800); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.batch-item-days { font-size: 11px; font-weight: 600; color: var(--pri-600); white-space: nowrap; }
.batch-item-days.overdue { color: var(--dgr-600); }
.batch-days-section {
  margin-top: 10px; padding: 12px 14px;
  background: var(--n-50); border-radius: var(--r-sm);
  border: 1px solid var(--border-light);
}
.batch-days-section h4 { font-size: 13px; font-weight: 700; color: var(--n-700); margin-bottom: 10px; }
.batch-days-mode { display: flex; gap: 16px; margin-bottom: 10px; }
.batch-radio { display: flex; align-items: center; gap: 6px; font-size: 12px; cursor: pointer; color: var(--text-soft); }
.batch-radio input[type="radio"] { width: 14px; height: 14px; accent-color: var(--accent); cursor: pointer; }
.batch-days-unified { display: flex; align-items: center; }
.batch-days-unified input { padding: 6px 10px; border: 1.5px solid var(--border); border-radius: var(--r-xs); font-size: 13px; outline: none; }
.batch-days-unified input:focus { border-color: var(--accent); }
.batch-days-per-item { display: flex; flex-direction: column; gap: 6px; }
.batch-days-row { display: flex; align-items: center; gap: 8px; font-size: 12px; }
.batch-days-row span { min-width: 80px; color: var(--text-soft); }
.batch-days-row input { padding: 5px 8px; border: 1.5px solid var(--border); border-radius: var(--r-xs); font-size: 12px; outline: none; }
.batch-days-row input:focus { border-color: var(--accent); }
.batch-select-all-row {
  padding: 6px 14px; margin-bottom: 4px;
  border-bottom: 1px solid var(--border-light);
}
.batch-select-all-label { font-size: 12px; color: var(--accent); cursor: pointer; display: flex; align-items: center; gap: 6px; }
.batch-select-all-label input[type="checkbox"] { width: 15px; height: 15px; accent-color: var(--accent); cursor: pointer; }

/* 附件预览按钮 */
.attach-preview {
  padding: 3px 10px; font-size: 11px;
  color: var(--pri-600); background: var(--pri-50);
  border: 1px solid var(--pri-200); border-radius: var(--r-xs);
  cursor: pointer; white-space: nowrap;
}
.attach-preview:hover { background: var(--pri-100); }

/* v27: 批量上传附件 */
.batch-attach-section {
  margin-top: 14px; padding-top: 12px;
  border-top: 1px solid var(--border-light);
}
.batch-attach-drop {
  border: 2px dashed var(--n-300); border-radius: var(--r-sm);
  padding: 20px 16px; text-align: center; cursor: pointer;
  transition: border-color var(--t-fast), background var(--t-fast);
  background: var(--n-50);
}
.batch-attach-drop:hover,
.batch-attach-drop.drag-over {
  border-color: var(--accent); background: var(--accent-light, #e8f0fe);
}
.batch-attach-drop-hint {
  font-size: 13px; color: var(--text-mute); margin: 0;
}
.batch-attach-files {
  margin-top: 8px; max-height: 200px; overflow-y: auto;
  display: flex; flex-direction: column; gap: 4px;
}
.batch-file-item {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 10px; background: var(--bg-surface);
  border: 1px solid var(--border-light); border-radius: var(--r-xs);
  font-size: 12px;
}
.batch-file-status { font-size: 14px; min-width: 18px; text-align: center; }
.batch-file-status-pending { color: var(--text-mute); }
.batch-file-status-uploading { color: var(--accent); animation: pulse 1s infinite; }
.batch-file-status-done { color: var(--suc-600); }
.batch-file-status-fail { color: var(--dgr-600); }
.batch-file-name { flex: 1; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.batch-file-size { color: var(--text-mute); font-size: 11px; min-width: 60px; text-align: right; }
.batch-file-remove { padding: 2px 6px; font-size: 10px; color: var(--dgr-500); cursor: pointer; }
.batch-file-remove:hover { color: var(--dgr-600); background: var(--dgr-50); }
.batch-attach-actions {
  display: flex; gap: 8px; align-items: center;
}

@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.4; }
}

/* 留言板 */
.msg-list { display: flex; flex-direction: column; gap: 12px; margin-bottom: 16px; max-height: 50vh; overflow-y: auto; }
.msg-card {
  padding: 12px 14px; background: var(--n-50);
  border-radius: var(--r-sm); border: 1px solid var(--border-light);
}
.msg-header { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.msg-author { font-weight: 700; font-size: 13px; color: var(--accent); }
.msg-date { font-size: 11px; color: var(--text-mute); }
.msg-del { margin-left: auto; font-size: 11px; color: var(--dgr-500); cursor: pointer; background: none; border: none; }
.msg-content { font-size: 13px; color: var(--n-800); line-height: 1.5; margin-bottom: 8px; word-break: break-word; }
.msg-actions { display: flex; gap: 8px; }
.msg-like { font-size: 11px; cursor: pointer; border: 1px solid var(--border-light); border-radius: var(--r-xs); padding: 2px 8px; background: var(--n-100); }
.msg-like.liked { color: var(--dgr-600); border-color: var(--dgr-200); background: var(--dgr-50); }
.msg-reply-area { display: flex; gap: 6px; margin-top: 8px; align-items: center; }
.msg-reply-input { flex: 1; padding: 6px 10px; border: 1.5px solid var(--border); border-radius: var(--r-xs); font-size: 12px; outline: none; }
.msg-reply-input:focus { border-color: var(--accent); }
.msg-reply-send { font-size: 11px; padding: 5px 12px; white-space: nowrap; }
.msg-replies { margin-top: 8px; padding-left: 16px; border-left: 2px solid var(--pri-200); }
.msg-reply { display: flex; align-items: baseline; gap: 6px; padding: 4px 0; font-size: 12px; }
.msg-reply-author { font-weight: 600; color: var(--pri-600); white-space: nowrap; }
.msg-reply-content { color: var(--n-700); flex: 1; }
.msg-reply-date { font-size: 10px; color: var(--text-mute); white-space: nowrap; }

/* ================================================================
 * PAGINATION (v13)
 * ================================================================ */
#paginationBar, #alertsPaginationBar, #purchasePaginationBar, #vaultPaginationBar {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 0; margin-top: 16px;
  border-top: 1px solid var(--border-light);
  gap: 10px; flex-wrap: wrap;
}
.page-info { font-size: 12px; color: var(--text-soft); font-weight: 500; }
.page-btns { display: flex; gap: 4px; align-items: center; flex-wrap: wrap; }
.page-btn { padding: 4px 10px; font-size: 12px; }
.btn:disabled { opacity: .45; cursor: not-allowed; }
.page-btn:disabled { opacity: .4; cursor: not-allowed; }
/* #850 分页下拉「每页 N 条」：与同行筛选下拉（.filter-select）**完全对齐**
 *   起因：老王反馈年包版块的「每页 10 条」与其它下拉不一致。
 *   查出三处原因：
 *     ① 4 处下拉（订单/告警/年包/采购）都漏了 class="filter-select"；
 *     ② 本文件的 ID 规则只列了 3 个 ID、漏了 annual，因此年包反而“看着还行”；
 *     ③ 该规则用 `background` 简写 → 重置了 background-image，自定义箭头永远出不来。
 *   做法：统一到 4 个 ID，并让尺寸/圆角/字号/hover/focus 与 .filter-select 一致
 *        （.filter-select 是 padding 9px 14px / r-sm / 13px / hover 变边框 / focus 蓝光圈）。
 *   ★ 注意必须用 `background-color` 而非 `background` 简写，否则箭头图又被抹掉。 */
#pageSizeSelect, #alertPageSizeSelect, #annualPageSizeSelect, #purchasePageSizeSelect {
  padding: 9px 30px 9px 14px; border: 1.5px solid var(--border); border-radius: var(--r-sm);
  font-size: 13px; background-color: var(--bg-surface); color: var(--text); outline: none;
  transition: border var(--t-fast), box-shadow var(--t-fast); font-family: inherit;
  cursor: pointer; appearance: none; -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%2394a3b8' d='M6 8L1 3h10z'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 10px center;
}
#pageSizeSelect:hover, #alertPageSizeSelect:hover, #annualPageSizeSelect:hover, #purchasePageSizeSelect:hover { border-color: var(--n-300); }
#pageSizeSelect:focus, #alertPageSizeSelect:focus, #annualPageSizeSelect:focus, #purchasePageSizeSelect:focus { border-color: var(--accent); box-shadow: 0 0 0 3px rgba(37,99,235,.08); }

/* ================================================================
 * BATCH STAGE BUTTON ON ORDER CARD (v13)
 * ================================================================ */
.btn-batch-stage { white-space: nowrap; }
.btn-batch-stage:hover { transform: translateY(-1px); }

/* ================================================================
 * UTILITY
 * ================================================================ */
.admin-only { /* visibility controlled by JS */ }
.role-viewer .admin-only { display: none !important; }
.user-info .btn-sm { font-size: 16px; padding: 4px 8px; line-height: 1; }

/* ================================================================
 * RESPONSIVE — 移动端响应式优化 (#355)
 * 桌面优先布局的窄屏适配：顶栏紧凑、标签横向滚动、工具栏网格、
 * 弹窗全宽、统计表格横向滚动、触控目标放大、iOS 聚焦防缩放
 * ================================================================ */

/* 触控优化（全局）：去除点击高亮延迟与灰色闪块 */
button, select, input[type="checkbox"], input[type="radio"], label, .order-item-count, .order-part-chip {
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

@media (max-width: 1024px) {
  .stg-cell { min-width: 72px; padding: 4px 8px; }
  .gantt-label { min-width: 140px; max-width: 140px; }
  .stats-grid-2 { grid-template-columns: 1fr; }
}

@media (max-width: 768px) {
  /* --- 顶栏：两行布局，信息紧凑 --- */
  .topbar { padding: 10px 16px; gap: 10px; }
  .topbar-right { width: 100%; justify-content: flex-end; gap: 8px; }
  .today-label { display: none; }              /* 窄屏隐藏日期胶囊，节省空间 */
  .user-info { gap: 6px; }
  .user-role { padding: 1px 8px; }

  /* --- 标签页：横向滚动 --- */
  .tabs {
    overflow-x: auto; -webkit-overflow-scrolling: touch;
    flex-wrap: nowrap; scrollbar-width: none;
    padding: 8px 16px 0;
  }
  .tabs::-webkit-scrollbar { display: none; }
  .tab { flex-shrink: 0; white-space: nowrap; padding: 9px 14px; }

  /* --- 工具栏：自适应网格，搜索框通栏 --- */
  .toolbar {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
    gap: 8px; align-items: stretch;
  }
  .toolbar .search-input { grid-column: 1 / -1; min-width: 0; width: 100%; }
  .toolbar select, .toolbar .filter-date,
  .toolbar #pageSizeSelect, .toolbar #alertPageSizeSelect { width: 100%; min-width: 0; margin: 0; }
  .toolbar .filter-date-sep { display: none; }
  .toolbar .btn { justify-content: center; }
  .view-stats .toolbar { grid-template-columns: 1fr; justify-items: end; }
  .view-stats .toolbar .btn { width: auto; }

  /* --- 弹窗：接近全宽 + 紧凑内边距 --- */
  .modal-overlay { padding: 8px; }
  .modal { max-width: 100%; max-height: 96vh; }
  .modal-head { padding: 13px 16px; }
  .modal-body { padding: 16px; }
  .modal-foot { padding: 12px 16px; flex-wrap: wrap; }
  .modal-foot .btn { flex: 1 1 auto; justify-content: center; }
  .login-card { padding: 30px 22px; margin: 0 12px; max-width: 100%; }

  /* --- 后台管理标签：横向滚动 --- */
  .admin-panel-tabs {
    overflow-x: auto; -webkit-overflow-scrolling: touch;
    flex-wrap: nowrap; scrollbar-width: none;
  }
  .admin-panel-tabs::-webkit-scrollbar { display: none; }
  .admin-tab { flex-shrink: 0; white-space: nowrap; padding: 9px 14px; font-size: 13px; }

  /* --- 统计面板：表格横向滚动，避免列被压缩 --- */
  .stats-panel, .overdue-stats-panel { overflow-x: auto; }
  .stats-table { min-width: 420px; }
  .stats-kpi-row { gap: 8px; }
  .overdue-stats-toolbar { width: 100%; flex-wrap: wrap; }
  .overdue-period-select { flex: 1; }

  /* --- 订单卡片：操作按钮放大、阶段圆点横向滚动 --- */
  .order-card-top { flex-direction: column; align-items: flex-start; }
  .order-card-actions { width: 100%; display: flex; flex-wrap: wrap; }
  .order-card-actions .btn { flex: 1 1 auto; justify-content: center; min-height: 30px; }
  .order-card-main { width: 100%; }
  .stage-dots {
    overflow-x: auto; -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .stage-dots::-webkit-scrollbar { display: none; }
  .order-part-chips { margin-left: 0; width: 100%; }

  /* --- 零件行：换行 + 操作区整行 --- */
  .part-expand-row { flex-wrap: wrap; padding: 10px 14px; }
  .part-expand-name { min-width: 120px; flex: 1 1 120px; }
  .part-expand-actions { width: 100%; justify-content: flex-end; }
  .part-expand-actions .btn { min-height: 30px; }

  /* --- 表单 --- */
  .form-grid { grid-template-columns: 1fr; }
  .input-row { flex-wrap: wrap; }
  .input-row .btn { flex: 1 1 auto; justify-content: center; }
  #sysStageDays .form-row, #sysStageAssignees .form-row { flex-wrap: wrap; }
  #sysStageDays input { width: 72px; }
  .batch-days-mode { flex-wrap: wrap; gap: 10px; }
  .batch-days-unified { flex-wrap: wrap; gap: 6px; }

  /* --- 详情 --- */
  .alert-detail-order-info { gap: 12px; }
  .detail-stage-row { gap: 8px; }
  .gantt-label { min-width: 100px; max-width: 100px; font-size: 10px; }

  /* --- 原有规则保留 --- */
  .item-row { flex-direction: column; align-items: flex-start; gap: 8px; }
  .item-stages { width: 100%; overflow-x: auto; }
  .item-actions { align-self: flex-end; }

  /* --- iOS 聚焦不自动缩放：输入控件字号 ≥16px --- */
  input, select, textarea { font-size: 16px; }
}

@media (max-width: 480px) {
  .topbar { padding: 8px 12px; }
  .logo-mark { width: 34px; height: 34px; font-size: 16px; }
  .logo-text h1 { font-size: 14px; }
  .stats-bar { padding: 10px 8px 0; gap: 6px; }
  .stat { flex: 1 1 calc(50% - 6px); min-width: 0; padding: 12px 12px; }
  .stat-num { font-size: 22px; }
  .tabs { padding: 6px 12px 0; }
  .content { padding: 0 12px 28px; }
  .tab { padding: 8px 10px; font-size: 12px; }
  .stage-dot { width: 24px; height: 24px; font-size: 10px; }
  .user-role, .user-icon { display: none; }    /* 极窄屏隐藏角色标签与头像图标 */
  .order-no { font-size: 14px; }
  .order-customer { font-size: 12px; }
  .order-part-chip { max-width: 140px; font-size: 11px; }
  .kpi-card { flex: 1 1 calc(50% - 8px); min-width: 0; padding: 12px 10px; }
  .kpi-value { font-size: 22px; }
  .item-detail-fields { grid-template-columns: 1fr; }
  .detail-stage-left { min-width: 100%; }
  .detail-stage-right { align-items: flex-start; }
  .trend-chart { gap: 4px; }
  .trend-bar span { font-size: 9px; }
  .msg-reply-area { flex-wrap: wrap; }
  .msg-reply-send { flex: 1; justify-content: center; }
  .batch-item-row { flex-wrap: wrap; }
  .page-btn { padding: 5px 8px; }
  .attach-item { flex-wrap: wrap; }
  .attach-name { flex-basis: 100%; }
  .toast { width: 90vw; text-align: center; }
}

/* ---------- 解析零件表可编辑预览 ---------- */
.parse-parts-table { width: 100%; border-collapse: collapse; }
.parse-parts-table th,
.parse-parts-table td { padding: 6px 8px; border-bottom: 1px solid var(--border); font-size: 12px; }
.parse-parts-table th { color: var(--text-mute); font-weight: 500; text-align: left; }
.parse-parts-table input { width: 100%; padding: 4px 6px; border: 1px solid var(--border); border-radius: var(--r-xs); font-size: 12px; background: var(--bg-surface); }
.parse-parts-table input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 2px var(--pri-100); }

/* ---------- #419 质量检验 UI ---------- */
/* 质量徽标（订单卡片/零件列表） */
.qc-badge {
  display: inline-block;
  font-size: 10px;
  line-height: 1;
  padding: 2px 5px;
  margin-left: 4px;
  border-radius: 4px;
  vertical-align: middle;
  white-space: nowrap;
}
.qc-badge.qc-scrap { background: #fee2e2; color: #b91c1c; border: 1px solid #fecaca; }
.qc-badge.qc-return { background: #ffedd5; color: #c2410c; border: 1px solid #fed7aa; }
.qc-badge.qc-pending { background: #fef3c7; color: #b45309; border: 1px solid #fde68a; }
.qc-badge.qc-approved { background: #dcfce7; color: #15803d; border: 1px solid #bbf7d0; }
.qc-badge.qc-rejected { background: #fee2e2; color: #b91c1c; border: 1px solid #fecaca; }

/* 订单卡片质量摘要 */
.order-qc-summary {
  display: inline-block;
  font-size: 11px;
  line-height: 1;
  padding: 3px 7px;
  margin-left: 6px;
  border-radius: 5px;
  background: #fff7ed;
  color: #9a3412;
  border: 1px solid #fed7aa;
  white-space: nowrap;
  vertical-align: middle;
}

/* 零件列表终止样式 */
.part-expand-terminated .part-expand-name,
.part-expand-terminated .part-expand-partno,
.part-expand-terminated .part-expand-spec,
.part-expand-terminated .part-expand-qty { opacity: 0.55; }

/* 零件详情：质量记录区块 */
.item-detail-qc {
  margin: 10px 0;
  padding: 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--bg-2, #f8fafc);
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.qc-record-title { font-size: 12px; font-weight: 600; color: var(--text-mute); margin: 2px 0; }
.qc-record-row {
  display: flex; align-items: flex-start; gap: 8px;
  padding: 8px 10px; border-radius: 6px; font-size: 13px;
  border: 1px solid transparent;
}
.qc-record-row.qc-ok { background: #f0fdf4; border-color: #bbf7d0; color: #166534; }
.qc-record-row.qc-bad { background: #fef2f2; border-color: #fecaca; color: #991b1b; }
.qc-record-row.qc-warn { background: #fffbeb; border-color: #fde68a; color: #92400e; }
.qc-record-icon { flex: none; }
.qc-record-issue { margin-top: 3px; font-size: 12px; color: inherit; opacity: 0.85; }
.qc-record-meta { margin-top: 3px; font-size: 11px; color: var(--text-mute); }
.qc-history { display: flex; flex-direction: column; gap: 5px; }
.qc-history-item {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  font-size: 12px; padding: 5px 8px;
  background: #fffbeb; border: 1px solid #fde68a; border-radius: 6px;
}
.qc-history-round { font-weight: 600; color: #b45309; flex: none; }
.qc-history-issue { flex: 1 1 140px; color: var(--text-main); }
.qc-history-meta { font-size: 11px; color: var(--text-mute); }
.qc-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.parse-parts-table input[type="number"] { width: 60px; }

/* ============================================================
 * 图纸自动报价一期 (#454)
 * 工作台卡片 / 状态徽标 / 置信度 / 复核弹窗 / 费率配置表
 * ============================================================ */
.quote-upload-card {
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: 18px;
  margin-top: 14px;
}
.quote-upload-extra {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 10px 16px;
  margin-top: 14px;
}
.quote-upload-extra .form-row { margin-bottom: 0; }
.quote-upload-extra .form-row:last-child { grid-column: 1 / -1; }

.quote-list { display: flex; flex-direction: column; gap: 12px; }

.quote-card {
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-xs);
  transition: box-shadow .15s ease, border-color .15s ease;
}
.quote-card:hover { border-color: var(--n-300); box-shadow: var(--shadow-sm); }
.quote-card-head {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--border-light);
  flex-wrap: wrap;
}
.quote-card-title { display: flex; align-items: center; gap: 10px; min-width: 0; }
.quote-card-title strong { font-size: 15px; color: var(--text); white-space: nowrap; }
.quote-file {
  font-size: 13px; color: var(--text-soft);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 380px;
}
.quote-card-body { padding: 12px 16px; }
.quote-features { display: flex; flex-wrap: wrap; gap: 6px 16px; }
.qf-item { font-size: 13px; color: var(--text-soft); }
.qf-item b { color: var(--text); font-weight: 600; }
.quote-cost-line {
  margin-top: 10px; font-size: 14px; color: var(--text);
  background: var(--accent-light); border-radius: var(--r-sm);
  padding: 8px 12px; display: inline-block;
}
.quote-cost-line b { color: var(--dgr-600); font-size: 16px; }
/* #800 第一层：历史成交价（图号命中历史库时的推荐报价，优先展示） */
.quote-history-line {
  margin-top: 10px; font-size: 14px; color: var(--text);
  background: var(--suc-100, #dcfce7); border: 1px solid var(--suc-300, #86efac);
  border-radius: var(--r-sm); padding: 8px 12px;
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px;
}
.quote-history-line b { color: var(--suc-700, #15803d); font-size: 16px; }
.quote-history-line .qh-meta { font-size: 12px; color: var(--text-soft); }
.quote-history-line .qh-hist {
  font-size: 11px; color: var(--text-soft);
  border-left: 1px solid var(--line, #e5e5e5); padding-left: 8px;
}
/* #828 容错匹配（图号有字符误读，靠零件名确认）—— 用警示色，提醒核对图号 */
.quote-history-line.qhl-fuzzy {
  background: var(--wrn-50, #fffbeb);
  border-color: var(--wrn-300, #fcd34d);
}
.quote-history-line.qhl-fuzzy b { color: var(--wrn-700, #b45309); }
.quote-history-line .qh-fuzzy-badge {
  font-size: 11px; font-weight: 600; color: var(--wrn-800, #92400e);
  background: var(--wrn-100, #fef3c7); border: 1px solid var(--wrn-300, #fcd34d);
  border-radius: var(--r-sm); padding: 1px 6px; font-family: ui-monospace, Consolas, monospace;
}
/* #829 实际工时记录（数据闭环）：展示估算 vs 实际 */
.quote-actual-box {
  margin-top: 12px; border: 1px solid var(--border); border-radius: var(--r-sm, 6px);
  background: var(--bg-secondary); padding: 10px 12px;
}
.quote-actual-box .qab-head { font-size: 13px; font-weight: 600; color: var(--text); margin-bottom: 8px; display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.quote-actual-box .qab-meta { font-size: 12px; font-weight: 400; color: var(--text-mute); }
.qab-table { width: 100%; border-collapse: collapse; font-size: 12px; }
.qab-table th { text-align: left; padding: 4px 8px; color: var(--text-mute); font-weight: 500; border-bottom: 1px solid var(--border); }
.qab-table td { padding: 4px 8px; border-bottom: 1px solid var(--border); }
.qab-table tfoot td { font-weight: 600; border-top: 2px solid var(--border-strong, var(--border)); border-bottom: none; }
.qab-table .qab-high { color: var(--dgr-600, #dc2626); font-weight: 600; }
.qab-table .qab-low { color: var(--suc-600, #16a34a); font-weight: 600; }
.quote-actual-box .qab-note { font-size: 12px; color: var(--text-soft); margin-top: 6px; }
/* 实际工时录入弹窗内的表格 */
.qah-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.qah-table th { text-align: left; padding: 6px 8px; font-size: 12px; color: var(--text-mute); font-weight: 500; border-bottom: 1px solid var(--border); }
.qah-table td { padding: 6px 8px; border-bottom: 1px solid var(--border); vertical-align: middle; }
.qah-table .qah-est { color: var(--text-soft); font-family: ui-monospace, Consolas, monospace; }
.qah-table .qah-in { font-family: ui-monospace, Consolas, monospace; }

/* ========== #832 管理费用 ========== */
.exp-stats { display: flex; gap: 10px; flex-wrap: wrap; margin: 12px 0 4px; }
.exp-stat { background: var(--bg-secondary); border: 1px solid var(--border); border-radius: 8px; padding: 8px 14px; min-width: 108px; }
.exp-stat .es-t { font-size: 12px; color: var(--text-mute); }
.exp-stat .es-v { font-size: 18px; font-weight: 700; font-family: ui-monospace, Consolas, monospace; margin-top: 2px; }
.exp-stat.c-amber { border-left: 3px solid var(--wrn-500, #f59e0b); }
.exp-stat.c-amber .es-v { color: var(--wrn-700, #b45309); }
.exp-stat.c-blue { border-left: 3px solid var(--pri-500, #3b82f6); }
.exp-stat.c-blue .es-v { color: var(--pri-700, #1d4ed8); }
.exp-stat.c-green { border-left: 3px solid var(--suc-500, #22c55e); }
.exp-stat.c-green .es-v { color: var(--suc-700, #15803d); }
.exp-stat.c-plain { border-left: 3px solid var(--border); }
.exp-badge { display: inline-block; padding: 1px 8px; border-radius: 20px; font-size: 11px; font-weight: 600; margin-left: 4px; }
.exp-badge.b-gray { background: rgba(148,163,184,.18); color: #94a3b8; }
.exp-badge.b-amber { background: rgba(245,158,11,.16); color: #b45309; }
.exp-badge.b-blue { background: rgba(59,130,246,.16); color: #1d4ed8; }
.exp-badge.b-green { background: rgba(34,197,94,.16); color: #15803d; }
.exp-badge.b-red { background: rgba(239,68,68,.16); color: #b91c1c; }
.exp-cat { font-size: 11px; font-weight: 500; color: var(--text-soft); background: var(--bg-secondary); border: 1px solid var(--border); border-radius: 4px; padding: 1px 6px; }
.exp-flow { color: var(--wrn-700, #b45309); font-weight: 500; }
.exp-card .order-card-main { min-width: 0; }
.exp-todo-card:hover { border-color: var(--pri-400, #60a5fa); }

/* 详情 */
.exp-detail { font-size: 13.5px; }
.exp-drow { display: flex; gap: 10px; padding: 6px 0; border-bottom: 1px dashed var(--border); }
.exp-dk { flex: 0 0 76px; color: var(--text-mute); font-size: 13px; }
.exp-dv { flex: 1; color: var(--text); word-break: break-all; }
.exp-detail .dim { color: var(--text-soft); font-size: 12.5px; }
.exp-detail .req { color: var(--dgr-600, #dc2626); }
.exp-att-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.exp-att-table td { padding: 5px 8px; border-bottom: 1px solid var(--border); }
.exp-attkind { font-size: 11px; font-weight: 600; color: var(--pri-700, #1d4ed8); background: rgba(59,130,246,.12); border-radius: 4px; padding: 1px 6px; }
.exp-attname { word-break: break-all; }
.exp-timeline { list-style: none; margin: 6px 0 0 0; padding: 0; font-size: 12.5px; color: var(--text-soft); }
.exp-timeline li { padding: 4px 0 4px 14px; border-left: 2px solid var(--border); margin-left: 4px; }
.exp-timeline li:last-child { border-left-color: var(--pri-400, #60a5fa); }
.expense-stats:empty { display: none; }
/* #833b 发票状态标记 + 批量选择行 */
.exp-inv { font-size: 11px; font-weight: 600; border-radius: 4px; padding: 1px 6px; margin-left: 3px; white-space: nowrap; }
.exp-inv.yes { background: rgba(34, 197, 94, .14); color: var(--suc-700, #15803d); }
.exp-inv.no { background: rgba(245, 158, 11, .16); color: var(--wrn-700, #b45309); }
.exp-row-sel { width: 16px; height: 16px; cursor: pointer; margin-top: 3px; flex: 0 0 auto; }
/* #800 未自动定价但有候选（歧义场景 → 转人工确认） */
.quote-ref-hint {
  margin-top: 8px; font-size: 12px; color: var(--text-soft);
  background: var(--wrn-100, #fef3c7); border: 1px solid #fde68a;
  border-radius: var(--r-sm); padding: 6px 10px;
}
.min-fee-tag {
  display: inline-block; margin-left: 6px; font-size: 11px; font-weight: 600;
  color: var(--wrn-700); background: var(--wrn-100);
  border: 1px solid #fde68a; border-radius: var(--r-xs); padding: 1px 6px;
}
/* #721 P3-2 DFM 可制造性分析 */
.dfm-score { margin-left: 8px; font-size: 12px; font-weight: 700; }
.dfm-panel { margin-top: 8px; display: flex; flex-direction: column; gap: 6px; }
.dfm-issue {
  display: flex; gap: 8px; padding: 8px 10px; border-radius: var(--r-sm);
  font-size: 13px; line-height: 1.6; border-left: 3px solid transparent;
}
.dfm-issue.dfm-error { background: rgba(220, 38, 38, .07); border-left-color: #dc2626; }
.dfm-issue.dfm-warn  { background: rgba(217, 119, 6, .07); border-left-color: #d97706; }
.dfm-issue.dfm-info  { background: rgba(37, 99, 235, .06); border-left-color: #2563eb; }
.dfm-issue-sev { flex: 0 0 auto; }
.dfm-issue-body { flex: 1 1 auto; min-width: 0; }
.dfm-issue-msg { font-weight: 600; color: var(--text-main); }
.dfm-issue-msg .dfm-issue-cat { font-style: normal; font-weight: 700; opacity: .75; }
.dfm-issue-sug { color: var(--text-mute); margin-top: 2px; }
.dfm-card-warn {
  margin-top: 6px; display: inline-block; font-size: 12px; font-weight: 600;
  color: #dc2626; background: rgba(220, 38, 38, .08);
  border-radius: var(--r-xs); padding: 3px 8px;
}
/* #720 P3-3 预计交期 */
.lt-card-line { margin-top: 6px; font-size: 12px; color: var(--text-secondary); }
.lt-card-line b { color: var(--pri-700); font-size: 13px; }
.lt-panel { background: var(--bg-secondary); border: 1px solid var(--border); border-radius: var(--r-sm); padding: 10px 12px; margin-top: 8px; }
.lt-tag { display: inline-block; font-size: 11px; font-weight: 600; padding: 1px 8px; border-radius: var(--r-full); margin-left: 6px; vertical-align: 2px; }
.lt-reg { background: var(--pri-50); color: var(--pri-700); }
.lt-fb  { background: var(--n-100); color: var(--n-600); }
.lt-main { font-size: 14px; color: var(--text-main); }
.lt-main b { font-size: 20px; color: var(--pri-700); }
.lt-ci { font-size: 12px; color: var(--text-mute); margin-left: 4px; }
.lt-meta { margin-top: 4px; font-size: 12px; color: var(--text-mute); }
.lt-features { margin-top: 4px; font-size: 11px; color: var(--text-soft); }
.quote-customer { margin-top: 8px; font-size: 13px; color: var(--text-soft); }
.quote-audit { margin-top: 6px; font-size: 12px; color: var(--text-mute); }
.quote-card-foot {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 10px 16px; border-top: 1px solid var(--border-light);
}

/* 状态徽标 */
.quote-status {
  display: inline-block; font-size: 12px; font-weight: 600;
  padding: 2px 10px; border-radius: var(--r-full); white-space: nowrap;
}
.quote-st-draft      { background: var(--n-100); color: var(--n-600); }
.quote-st-estimating { background: var(--wrn-100); color: var(--wrn-700); }
.quote-st-confirmed  { background: var(--suc-50);  color: var(--suc-700); }
.quote-st-converted  { background: var(--pri-50);  color: var(--pri-700); }
.quote-st-void       { background: var(--dgr-50);  color: var(--dgr-700); }

/* 置信度徽标 */
.quote-conf {
  display: inline-block; font-size: 12px; font-weight: 700;
  padding: 2px 8px; border-radius: var(--r-full); white-space: nowrap;
}
.quote-conf.conf-low  { background: var(--dgr-50);  color: var(--dgr-700); }
.quote-conf.conf-mid  { background: var(--wrn-100); color: var(--wrn-700); }
.quote-conf.conf-high { background: var(--suc-50);  color: var(--suc-700); }

/* #480 AI 识别来源徽标：VLM（本机 AI 视觉识别）/ OCR */
.quote-src-badge {
  display: inline-block; font-size: 12px; font-weight: 700;
  padding: 2px 10px; border-radius: var(--r-full); white-space: nowrap;
}
.quote-src-badge.vlm { background: rgba(124,58,237,.10); color: #7c3aed; border: 1px solid rgba(124,58,237,.25); }
.quote-src-badge.ocr { background: var(--n-100,#eef0f3); color: var(--text-mute); }
.quote-vlm-details summary { user-select: none; }
.quote-vlm-details summary::-webkit-details-marker { color: #7c3aed; }

/* #464 阶段0报价助手：历史参考弹窗 */
.ref-section { margin-bottom: 16px; }
.ref-section-title {
  font-size: 13px; font-weight: 700; color: var(--text);
  padding: 8px 12px; background: var(--n-50, #f5f6f8);
  border-radius: var(--r-sm) var(--r-sm) 0 0;
  border: 1px solid var(--border-light); border-bottom: none;
}
.ref-item {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 10px 12px; border: 1px solid var(--border-light); border-top: none;
  background: var(--bg-card, #fff);
}
.ref-item:hover { background: var(--n-50, #f5f6f8); }
.ref-item-main { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.ref-item-main strong { font-size: 14px; color: var(--text); }
.ref-item-sub { font-size: 12px; color: var(--text-mute); margin-top: 2px; }
.ref-item-detail { font-size: 12.5px; color: var(--text-2, #555); min-width: 140px; }
.ref-item-price { font-size: 14px; font-weight: 700; color: var(--pri-700, #2563eb); white-space: nowrap; }
.ref-item-price .ref-unit { font-size: 11.5px; font-weight: 400; color: var(--text-mute); }
.ref-item-right { display: flex; align-items: center; gap: 8px; white-space: nowrap; }
.ref-score {
  font-size: 11.5px; font-weight: 700; color: var(--suc-700, #16a34a);
  background: var(--suc-50, #f0fdf4); padding: 2px 8px; border-radius: var(--r-full);
}

/* 复核弹窗 */
.quote-review-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 12px; }
.quote-review-features {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 12px 18px;
}
.quote-review-features .form-row { margin-bottom: 0; }
.form-section-title {
  font-size: 14px; font-weight: 700; color: var(--text);
  margin: 18px 0 10px; padding-bottom: 6px; border-bottom: 1px solid var(--border-light);
}
.form-label-hint { font-size: 12px; font-weight: 400; color: var(--text-mute); }
.quote-review-actions { display: flex; gap: 8px; flex-wrap: wrap; }

/* 工艺路线 */
.quote-process { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.process-step {
  font-size: 13px; background: var(--n-100); border-radius: var(--r-sm);
  padding: 5px 10px; color: var(--text);
}
.process-step em { font-style: normal; color: var(--wrn-700); font-weight: 600; margin-left: 6px; }
.process-arrow { color: var(--n-400); font-size: 13px; }
/* #538 AI 建议工序标记 */
.process-step.ai-suggested { background: #dcfce7; border: 1px solid #86efac; }
.process-step.ai-modified { background: #dbeafe; border: 1px solid #93c5fd; }
/* #538 工艺建议卡片 */
.ps-card { transition: box-shadow 0.15s; }
.ps-card:hover { box-shadow: 0 2px 8px rgba(0,0,0,0.08); }
.btn-sm { font-size: 12px; padding: 3px 10px; border-radius: var(--r-sm); border: 1px solid var(--border); cursor: pointer; }

/* 成本明细 */
.quote-cost-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 10px;
}
.cost-cell {
  background: var(--n-50); border: 1px solid var(--border); border-radius: var(--r-sm);
  padding: 10px 12px; text-align: center;
}
.cost-cell span { display: block; font-size: 12px; color: var(--text-mute); margin-bottom: 4px; }
.cost-cell b { font-size: 15px; color: var(--text); }
.cost-cell.cost-total {
  background: var(--accent-light); border-color: var(--pri-200);
}
.cost-cell.cost-total b { color: var(--dgr-600); font-size: 17px; }

/* #469 成本逐项明细表 */
.quote-cost-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.quote-cost-table td { padding: 7px 10px; border-bottom: 1px solid var(--border-light); vertical-align: top; }
.quote-cost-table td:first-child { width: 120px; font-weight: 600; color: var(--text); white-space: nowrap; }
.quote-cost-table .qct-note { color: var(--text-mute); font-size: 12px; font-weight: 400; }
.quote-cost-table .qct-amt { text-align: right; font-weight: 600; color: var(--text); white-space: nowrap; width: 110px; }
.quote-cost-table tr.qct-total td { border-top: 2px solid var(--pri-200); border-bottom: none; font-size: 14px; }
.quote-cost-table tr.qct-total .qct-amt { color: var(--dgr-600); font-size: 16px; }
/* #827 直接成本小计：与上方各项用细线分隔，便于逐块核对 */
.quote-cost-table tr.qct-subtotal td { border-top: 1px solid var(--pri-200); background: var(--bg-secondary); }
.quote-cost-table tr.qct-subtotal td:first-child { color: var(--pri-600); }
.quote-cost-table tr.qct-mat-provided td { background: var(--wrn-50); color: #b45309; }
.quote-cost-table tr.qct-mat-provided .qct-amt { color: #b45309; }
.qct-ops-table { width: 100%; border-collapse: collapse; font-size: 12px; }
.qct-ops-table td { padding: 4px 10px; border-bottom: 1px dashed var(--border-light); color: var(--text); }
.qct-ops-table td:first-child { width: auto; font-weight: 400; white-space: nowrap; }
.qct-ops-table td:nth-child(2) { color: var(--text-mute); font-size: 12px; }
.qct-ops-table td:last-child { text-align: right; width: 90px; white-space: nowrap; }
.qct-ops-table tr:last-child td { border-bottom: none; }
.quote-checkbox { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; color: #b45309; cursor: pointer; }
.quote-checkbox input { width: 15px; height: 15px; accent-color: var(--pri-500); }

/* 操作记录 */
.quote-audit-list { display: flex; flex-direction: column; gap: 5px; }
.quote-audit-item {
  font-size: 12px; color: var(--text-soft);
  background: var(--n-50); border: 1px solid var(--border-light);
  border-radius: var(--r-xs); padding: 6px 10px;
}

/* 费率配置表 */
.quote-cfg-table { margin-top: 8px; }
.quote-cfg-table input[type="text"], .quote-cfg-table input[type="number"] {
  border: 1px solid var(--border); border-radius: var(--r-xs);
  padding: 4px 8px; font-size: 13px; color: var(--text); background: var(--bg-surface);
}
.quote-cfg-table input:focus { border-color: var(--accent); outline: none; }

/* ============== AI 对话式报价面板（#526） ============== */
.quote-review-split { display: flex; gap: 0; padding: 0 !important; }
.quote-review-left { flex: 1 1 62%; padding: 16px; border-right: 1px solid var(--border-light); min-width: 0; }
.quote-review-right { flex: 1 1 38%; display: flex; flex-direction: column; min-width: 280px; background: var(--n-25, #f8f9fb); }
.quote-ai-head {
  padding: 10px 14px; font-weight: 600; font-size: 14px; color: var(--text);
  border-bottom: 1px solid var(--border-light); display: flex; flex-direction: column; gap: 2px;
}
.quote-ai-head span { font-weight: 400; font-size: 12px; color: var(--text-soft); }
.quote-ai-msgs {
  flex: 1; overflow-y: auto; padding: 12px 14px; display: flex; flex-direction: column; gap: 10px;
  min-height: 220px; max-height: 42vh; scroll-behavior: smooth;
}
.quote-ai-msg { max-width: 92%; padding: 8px 12px; border-radius: 10px; font-size: 13px; line-height: 1.55; word-break: break-word; white-space: pre-wrap; }
.quote-ai-msg.user { align-self: flex-end; background: var(--pri-500, #2563eb); color: #fff; border-bottom-right-radius: 2px; }
.quote-ai-msg.ai { align-self: flex-start; background: #fff; color: var(--text); border: 1px solid var(--border-light); border-bottom-left-radius: 2px; }
.quote-ai-msg.ai .ai-changed { color: #15803d; font-weight: 500; }
.quote-ai-msg.ai .ai-price { color: #b45309; font-weight: 600; }
.quote-ai-msg.ai .ai-err { color: #dc2626; }
.quote-ai-sug {
  display: flex; flex-wrap: wrap; gap: 6px; padding: 8px 14px; border-top: 1px solid var(--border-light);
}
.quote-ai-sug button {
  font-size: 12px; padding: 3px 10px; border: 1px solid var(--border); border-radius: 20px;
  background: #fff; color: var(--text-soft); cursor: pointer; transition: all .15s;
}
.quote-ai-sug button:hover { border-color: var(--pri-500, #2563eb); color: var(--pri-500, #2563eb); background: var(--n-50, #f1f5f9); }
.quote-ai-in { display: flex; gap: 6px; padding: 10px 14px; border-top: 1px solid var(--border-light); background: #fff; }
.quote-ai-in input {
  flex: 1; min-width: 0; border: 1px solid var(--border); border-radius: 6px; padding: 7px 10px;
  font-size: 13px; color: var(--text); background: #fff; outline: none;
}
.quote-ai-in input:focus { border-color: var(--pri-500, #2563eb); }
.quote-ai-in .btn { flex-shrink: 0; }
.quote-ai-typing { align-self: flex-start; font-size: 12px; color: var(--text-soft); padding: 4px 8px; }
.quote-ai-typing::after { content: '...'; animation: qai-dot 1.2s infinite; }
@keyframes qai-dot { 0% { content: '.'; } 33% { content: '..'; } 66% { content: '...'; } }

/* ============ 页脚备案号（v2026082504） ============ */
.site-footer {
  display: flex; align-items: center; justify-content: center; gap: 10px; flex-wrap: wrap;
  /* #828c：文字由 --text-mute 改为 --text-soft —— 原对比度实测仅 2.37:1
     （远低于 WCAG AA 的 4.5:1），老王本就反馈过字号/对比度问题，一并提高可读性。 */
  padding: 14px 16px 22px; font-size: 12px; color: var(--text-soft, #475569);
  border-top: 1px solid var(--border-light, #e5e7eb); margin-top: 8px;
  background: var(--bg, #f8fafc);
}
.site-footer .footer-name { letter-spacing: .3px; }
.site-footer .footer-icp {
  color: var(--text-soft, #475569); text-decoration: none; transition: color .15s;
}
.site-footer .footer-icp:hover { color: var(--accent, #2563eb); text-decoration: underline; }
/* #707 公安备案图标（页脚 + 登录页共用） */
.beian-icon { width: 16px; height: 16px; vertical-align: -3px; margin-right: 4px; }

/* #684 采购加急徽标脉冲动画 */
@keyframes pulseUrgent {
  0%, 100% { opacity: 1; }
  50% { opacity: .55; }
}

/* ============================================================
 * 3D 渲染板块 (#724/#725) —— DXF→STL 拉伸渲染 + three.js 视口
 * ============================================================ */
.dxf3d-viewer-card {
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
}
.dxf3d-viewer-toolbar {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 10px 14px; border-bottom: 1px solid var(--border-light);
  background: linear-gradient(180deg, var(--n-50), var(--bg-surface));
}
.dxf3d-model-name {
  font-weight: 700; font-size: 13.5px; color: var(--text);
  max-width: 300px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.dxf3d-hint { font-size: 11.5px; color: var(--text-mute); margin-left: auto; }
.dxf3d-viewer-btns { display: flex; gap: 6px; }
.dxf3d-viewer-btns .btn.active {
  background: var(--accent-light); border-color: var(--pri-200); color: var(--pri-700);
}
.dxf3d-canvas-wrap { position: relative; background: #0f172a; }
.dxf3d-canvas { width: 100%; height: 440px; display: block; }
.dxf3d-canvas canvas { display: block; }
.dxf3d-loading {
  position: absolute; inset: 0; display: flex; flex-direction: column; gap: 10px;
  align-items: center; justify-content: center; background: rgba(15,23,42,.55);
  color: #e2e8f0; font-size: 13px; letter-spacing: .3px; backdrop-filter: blur(2px);
}
.dxf3d-spinner {
  width: 30px; height: 30px; border-radius: 50%;
  border: 3px solid rgba(148,163,184,.35); border-top-color: #a5b4fc;
  animation: dxf3dSpin 0.8s linear infinite;
}
@keyframes dxf3dSpin { to { transform: rotate(360deg); } }
.dxf3d-info-bar {
  display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap;
  padding: 10px 14px; border-top: 1px solid var(--border-light); background: var(--n-50);
}
.dxf3d-info-cells { display: flex; gap: 8px 16px; flex-wrap: wrap; font-size: 12px; color: var(--text-soft); }
.dxf3d-info-cells b { color: var(--text); font-weight: 700; }
.dxf3d-info-cells .c { display: inline-flex; align-items: baseline; gap: 4px; }
.dxf3d-info-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.dxf3d-rerender { display: inline-flex; align-items: center; gap: 6px; margin-left: 4px; }
.dxf3d-warnings {
  padding: 8px 14px; border-top: 1px dashed var(--wrn-200, #fde68a);
  background: var(--wrn-50); color: var(--wrn-700); font-size: 12px;
}
.dxf3d-warnings li { margin: 2px 0 2px 18px; list-style: disc; }
.dxf3d-history-list { display: flex; flex-direction: column; gap: 10px; }
.r3d-card {
  background: var(--bg-surface); border: 1px solid var(--border);
  border-radius: var(--r-sm); box-shadow: var(--shadow-xs);
  transition: border-color .15s ease, box-shadow .15s ease;
}
.r3d-card:hover { border-color: var(--n-300); box-shadow: var(--shadow-sm); }
.r3d-card.active { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent), var(--shadow-sm); }
.r3d-card-main { display: flex; align-items: center; gap: 12px; padding: 10px 14px; cursor: pointer; flex-wrap: wrap; }
.r3d-thumb {
  width: 46px; height: 46px; border-radius: var(--r-sm); flex-shrink: 0;
  background: linear-gradient(135deg, #1e293b, #334155); color: #c7d2fe;
  display: flex; align-items: center; justify-content: center; font-size: 20px;
}
.r3d-card-info { flex: 1; min-width: 220px; }
.r3d-card-title { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.r3d-card-title .fn { font-weight: 700; font-size: 13.5px; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 260px; }
.r3d-tag {
  font-size: 11px; padding: 1px 7px; border-radius: 99px; background: var(--n-100);
  color: var(--text-soft); border: 1px solid var(--border-light); white-space: nowrap;
}
.r3d-tag.t-thick { background: var(--inf-50); color: var(--inf-500); border-color: var(--inf-100); }
.r3d-card-meta { margin-top: 3px; font-size: 11.5px; color: var(--text-mute); display: flex; gap: 10px; flex-wrap: wrap; }
.r3d-card-meta b { color: var(--text-soft); }
.r3d-card-actions { display: flex; gap: 6px; flex-wrap: wrap; }
.r3d-empty {
  padding: 30px 16px; text-align: center; color: var(--text-mute); font-size: 13px;
  background: var(--bg-surface); border: 1px dashed var(--n-300); border-radius: var(--r-md);
}
/* 窄屏：画布降低 + 隐藏长提示 */
@media (max-width: 720px) {
  .dxf3d-canvas { height: 300px; }
  .dxf3d-hint { display: none; }
  .r3d-card-main { padding: 9px 10px; }
}

/* ========== #739 扫描件半自动建模（r3d 模式切换 + 标注画布） ========== */
.r3d-mode-row { display: flex; gap: 8px; flex-wrap: wrap; padding: 10px 14px 0; }
.r3d-mode-btn {
  border: 1px solid var(--border, #d9d9d9); background: var(--bg-surface, #fff);
  color: var(--text-soft, #4b5563); border-radius: 999px; padding: 5px 14px;
  font-size: 12.5px; cursor: pointer; transition: all .15s;
}
.r3d-mode-btn:hover { border-color: var(--accent, #2563eb); color: var(--accent, #2563eb); }
.r3d-mode-btn.active {
  background: var(--accent, #2563eb); border-color: var(--accent, #2563eb); color: #fff; font-weight: 600;
}

.scan3d-card { background: var(--bg-surface, #fff); border: 1px solid var(--border-light, #e5e7eb); border-radius: var(--r-lg, 14px); overflow: hidden; }
.scan3d-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; padding: 10px 14px; border-bottom: 1px solid var(--border-light, #e5e7eb); background: var(--n-50, #f8fafc); }
.scan3d-title { display: flex; flex-direction: column; gap: 1px; }
.scan3d-title strong { font-size: 14.5px; color: var(--text, #111827); }
.scan3d-sub { font-size: 11.5px; color: var(--text-mute, #9ca3af); max-width: 520px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.scan3d-step { margin-left: auto; font-size: 11.5px; color: var(--text-mute, #9ca3af); white-space: nowrap; }
.scan3d-pages { display: flex; align-items: center; gap: 10px; padding: 8px 14px; border-bottom: 1px dashed var(--border-light, #e5e7eb); flex-wrap: wrap; }
.scan3d-pages-label { font-size: 12.5px; color: var(--text-soft, #4b5563); }
.scan3d-pages-list { display: flex; gap: 8px; flex-wrap: wrap; }
.scan3d-page-thumb {
  position: relative; border: 2px solid transparent; border-radius: 8px; cursor: pointer; overflow: hidden;
  background: #fff; padding: 0; box-shadow: var(--shadow-sm, 0 1px 2px rgba(0,0,0,.08));
}
.scan3d-page-thumb img { display: block; max-height: 78px; width: auto; }
.scan3d-page-thumb .no { position: absolute; left: 2px; top: 2px; background: rgba(0,0,0,.55); color: #fff; font-size: 10.5px; border-radius: 5px; padding: 0 5px; line-height: 16px; }
.scan3d-page-thumb.active { border-color: var(--accent, #2563eb); }
.scan3d-work { display: grid; grid-template-columns: minmax(0, 1fr) 300px; min-height: 540px; }
.scan3d-col-canvas { display: flex; flex-direction: column; min-width: 0; border-right: 1px solid var(--border-light, #e5e7eb); }
.scan3d-toolbar { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; padding: 8px 10px; border-bottom: 1px solid var(--border-light, #e5e7eb); background: var(--n-50, #f8fafc); }
.scan3d-toolbar .btn.active { background: var(--accent, #2563eb); border-color: var(--accent, #2563eb); color: #fff; }
.scan3d-tb-sep { width: 1px; height: 18px; background: var(--border-light, #e5e7eb); margin: 0 3px; }
.scan3d-hint { margin-left: auto; font-size: 11.5px; color: var(--text-mute, #9ca3af); text-align: right; }
.scan3d-canvas-wrap { position: relative; flex: 1; min-height: 420px; background: #1e293b; overflow: hidden; }
#scan3dCanvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; cursor: crosshair; touch-action: none; }
.scan3d-canvas-msg {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  background: rgba(15,23,42,.82); color: #e2e8f0; font-size: 13px; border-radius: 10px;
  padding: 14px 20px; max-width: 80%; text-align: center; line-height: 1.7; pointer-events: none;
}
.scan3d-calbox {
  position: absolute; left: 12px; bottom: 12px; z-index: 5;
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  background: #fff; color: #111827; border: 1px solid #d9d9d9; border-radius: 10px;
  padding: 8px 10px; font-size: 12.5px; box-shadow: 0 4px 14px rgba(0,0,0,.2);
}
.scan3d-calbox b { color: var(--accent, #2563eb); }
.scan3d-status { display: flex; justify-content: space-between; gap: 10px; padding: 5px 10px; font-size: 11.5px; color: var(--text-mute, #9ca3af); background: var(--n-50, #f8fafc); border-top: 1px solid var(--border-light, #e5e7eb); }
.scan3d-geom { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.scan3d-col-side { display: flex; flex-direction: column; min-width: 0; }
.scan3d-side-head { display: flex; align-items: center; justify-content: space-between; gap: 6px; padding: 9px 12px; border-bottom: 1px solid var(--border-light, #e5e7eb); }
.scan3d-side-head b { font-size: 13px; color: var(--text, #111827); }
.scan3d-feat-list { max-height: 240px; overflow: auto; padding: 8px; display: flex; flex-direction: column; gap: 6px; border-bottom: 1px solid var(--border-light, #e5e7eb); }
.scan3d-feat-chip {
  display: flex; align-items: center; gap: 7px; font-size: 12.5px; cursor: pointer;
  border: 1px solid var(--border-light, #e5e7eb); border-radius: 8px; padding: 6px 8px; background: var(--bg-surface, #fff);
}
.scan3d-feat-chip:hover { border-color: var(--n-300, #cbd5e1); }
.scan3d-feat-chip.active { border-color: var(--accent, #2563eb); box-shadow: 0 0 0 1px var(--accent, #2563eb); }
.scan3d-feat-chip .nm { font-weight: 600; color: var(--text, #111827); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.scan3d-feat-chip .meta { font-size: 10.5px; color: var(--text-mute, #9ca3af); white-space: nowrap; }
.scan3d-dot { width: 12px; height: 12px; border-radius: 4px; flex-shrink: 0; border: 1px solid rgba(0,0,0,.15); }
.scan3d-editor { padding: 10px 12px; border-bottom: 1px solid var(--border-light, #e5e7eb); display: flex; flex-direction: column; gap: 7px; }
.scan3d-editor .form-row { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text-soft, #4b5563); }
.scan3d-editor .form-row label { min-width: 64px; }
.scan3d-editor input[type="text"], .scan3d-editor input[type="number"] {
  border: 1px solid var(--border, #d9d9d9); border-radius: 6px; padding: 4px 7px; font-size: 12.5px; outline: none;
}
.scan3d-feat-head { display: flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--text-soft, #4b5563); }
.scan3d-lbl-note { font-size: 10.5px; color: var(--text-mute, #9ca3af); }
.scan3d-sel { display: flex; flex-direction: column; gap: 6px; border: 1px dashed var(--inf-200); background: var(--inf-50, #eff6ff); border-radius: 8px; padding: 8px 10px; }
.scan3d-sel-label { font-size: 11.5px; color: var(--inf-600); font-weight: 600; }
.scan3d-sel-fields { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; font-size: 11.5px; color: var(--text-soft, #4b5563); }
.scan3d-sel-fields label { display: inline-flex; align-items: center; gap: 3px; }
.scan3d-sel-fields input { width: 78px; border: 1px solid var(--border, #d9d9d9); border-radius: 6px; padding: 3px 6px; font-size: 12px; }
.scan3d-feat-actions { display: flex; gap: 6px; flex-wrap: wrap; }
.scan3d-side-actions { margin-top: auto; padding: 10px 12px; display: flex; flex-direction: column; gap: 8px; }
.scan3d-side-msg { font-size: 12px; color: var(--text-soft, #4b5563); line-height: 1.5; min-height: 16px; }
.scan3d-side-msg.err { color: #dc2626; }
.scan3d-progress { display: flex; flex-direction: column; gap: 5px; }
.scan3d-progress-track { height: 7px; background: var(--n-100, #eef0f3); border-radius: 99px; overflow: hidden; }
.scan3d-progress-bar { height: 100%; width: 0%; background: linear-gradient(90deg, #8b5cf6, var(--accent, #2563eb)); border-radius: 99px; transition: width .25s ease; }
.scan3d-progress > span { font-size: 11px; color: var(--text-mute, #9ca3af); }
@media (max-width: 980px) {
  .scan3d-work { grid-template-columns: 1fr; }
  .scan3d-col-canvas { border-right: none; border-bottom: 1px solid var(--border-light, #e5e7eb); min-height: 460px; }
  .scan3d-hint { display: none; }
  .scan3d-step { display: none; }
}

/* ========== 消息中心（S3/S4：@提及/回复/到货知会收件箱） ========== */
.view-messages { min-height: 60vh; }
.msg-center-toolbar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px; margin: 6px 0 14px; }
.msg-center-tabs { display: flex; gap: 4px; }
.msg-center-tabs .btn { border: 1px solid #e5e7eb; background: #fff; }
.msg-center-tabs .btn.active { background: #2563eb; color: #fff; border-color: #2563eb; }
.msg-center-ops { display: flex; gap: 6px; align-items: center; }
.msg-center-list { display: flex; flex-direction: column; gap: 8px; }
.msg-item { position: relative; display: flex; gap: 10px; padding: 10px 12px; background: #fff; border: 1px solid #e5e7eb; border-radius: 10px; transition: box-shadow .15s ease; }
.msg-item:hover { box-shadow: 0 2px 8px rgba(15,23,42,.08); }
.msg-item.unread { background: #eff6ff; border-color: #bfdbfe; }
.msg-item-icon { font-size: 18px; line-height: 22px; flex: none; padding-top: 2px; }
.msg-item-body { flex: 1; min-width: 0; }
.msg-item-title { display: flex; align-items: center; gap: 6px; font-weight: 600; color: #111827; font-size: 13px; }
.msg-dot { width: 8px; height: 8px; border-radius: 50%; background: #e5484d; display: inline-block; flex: none; }
.msg-item-no { margin-left: auto; font-weight: 500; color: #6b7280; font-size: 11px; background: #f3f4f6; border-radius: 6px; padding: 1px 6px; }
.msg-item-text { margin-top: 3px; color: #374151; font-size: 12.5px; line-height: 1.5; word-break: break-all; }
.msg-item-meta { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-top: 6px; }
.msg-item-time { color: #9ca3af; font-size: 11px; }
.msg-item-actions { display: flex; gap: 2px; }
.msg-center-pagination { display: flex; align-items: center; justify-content: center; gap: 12px; margin-top: 14px; }
.msg-pg-info { color: #6b7280; font-size: 12px; }
.msg-pref-pop { position: absolute; right: 18px; top: 96px; z-index: 40; background: #fff; border: 1px solid #e5e7eb; border-radius: 12px; box-shadow: 0 8px 24px rgba(15,23,42,.12); padding: 12px 14px; min-width: 280px; }
.view-messages { position: relative; }
.msg-pref-title { font-size: 12px; font-weight: 600; color: #111827; margin-bottom: 8px; }
.msg-pref-opt { display: flex; align-items: baseline; gap: 6px; padding: 6px 4px; border-radius: 8px; cursor: pointer; font-size: 13px; color: #111827; }
.msg-pref-opt:hover { background: #f9fafb; }
.msg-pref-opt input { margin-right: 2px; }
.msg-pref-opt em { margin-left: auto; font-style: normal; font-size: 11px; color: #9ca3af; }

/* ========== M3 微信式留言板（订单留言 + 附件留言 + @ 弹层） ========== */
.msg-board-scroll { max-height: 60vh; overflow-y: auto; padding: 12px 10px; }
.msg-bubble-list { display: flex; flex-direction: column; gap: 14px; }
.msg-bubble { display: flex; gap: 10px; align-items: flex-start; }
.msg-bubble.mine { flex-direction: row-reverse; }
.msg-avatar { width: 34px; height: 34px; border-radius: 50%; background: #eef2ff; color: #4338ca; display: flex; align-items: center; justify-content: center; font-size: 14px; font-weight: 600; flex: none; }
.msg-bubble-main { max-width: 82%; min-width: 0; }
.msg-bubble-head { display: flex; align-items: center; gap: 6px; margin-bottom: 2px; }
.msg-bubble-name { font-size: 11px; color: #9ca3af; }
.msg-bubble-time { font-size: 10px; color: #cbd5e1; }
.mine .msg-bubble-head { justify-content: flex-end; }
.msg-bubble-content { background: #f1f5f9; padding: 8px 11px; border-radius: 12px 12px 12px 4px; font-size: 13px; line-height: 1.6; color: #0f172a; word-break: break-word; white-space: pre-wrap; }
.mine .msg-bubble-content { background: #2563eb; color: #fff; border-radius: 12px 12px 4px 12px; }
.msg-bubble-actions { display: flex; gap: 4px; margin-top: 3px; }
.mine .msg-bubble-actions { justify-content: flex-end; }
.msg-at-chip { color: #2563eb; font-weight: 600; cursor: pointer; }
.mine .msg-at-chip { color: #dbeafe; }
.msg-at-chip.me { background: #dbeafe; border-radius: 4px; padding: 0 2px; }
.mine .msg-at-chip.me { background: rgba(255, 255, 255, .28); }
.msg-reply-area { display: flex; gap: 6px; margin-top: 6px; align-items: center; }
.msg-reply-area input { flex: 1; padding: 6px 10px; border: 1px solid #e2e8f0; border-radius: 8px; font-size: 12.5px; outline: none; min-width: 0; }
.msg-reply-area input:focus { border-color: #2563eb; }
.msg-reply-bubbles { margin-top: 8px; border-left: 2px solid #e2e8f0; padding-left: 10px; display: flex; flex-direction: column; gap: 6px; }
.msg-rb { display: flex; align-items: baseline; gap: 6px; font-size: 12px; }
.msg-rb-author { color: #64748b; font-weight: 600; flex: none; }
.msg-rb-content { color: #334155; word-break: break-word; }
.msg-rb-time { color: #cbd5e1; font-size: 10px; flex: none; margin-left: auto; }
.msg-highlight { animation: msgFlash 2.2s ease; border-radius: 10px; }
@keyframes msgFlash { 0%, 55% { background: #fef3c7; } 100% { background: transparent; } }
#mentionPopup { position: fixed; z-index: 12000; background: #fff; border: 1px solid #e2e8f0; border-radius: 10px; box-shadow: 0 10px 28px rgba(15, 23, 42, .18); max-height: 240px; overflow-y: auto; min-width: 210px; padding: 4px; display: none; }
#mentionPopup .mp-item { padding: 7px 10px; border-radius: 7px; cursor: pointer; display: flex; justify-content: space-between; align-items: center; gap: 12px; font-size: 13px; }
#mentionPopup .mp-item.sel { background: #eff6ff; }
#mentionPopup .mp-name { color: #111827; font-weight: 500; }
#mentionPopup .mp-user { color: #9ca3af; font-size: 11px; }

/* 附件留言（M3 同款风） */
.ac-list { border: 1px solid #e5e7eb; border-radius: 8px; padding: 10px; margin-bottom: 10px; display: flex; flex-direction: column; gap: 10px; }
.ac-empty { color: #9ca3af; font-size: 12px; padding: 8px 2px; }
.ac-timeline { display: flex; flex-direction: column; gap: 12px; }
.ac-cmt { border: 1px solid #f1f5f9; background: #f8fafc; border-radius: 10px; padding: 8px 10px; }
.ac-cmt-head { display: flex; align-items: center; gap: 6px; }
.ac-cmt-name { font-weight: 600; color: #1e293b; font-size: 12px; }
.ac-cmt-time { color: #94a3b8; font-size: 10px; }
.ac-cmt-head .ac-del { margin-left: auto; color: #94a3b8; }
.ac-cmt-text { margin: 4px 0 2px; color: #0f172a; font-size: 12.5px; line-height: 1.6; word-break: break-word; white-space: pre-wrap; }
.ac-cmt-ops { text-align: right; }
.ac-replies { border-left: 2px solid #dbeafe; margin-top: 6px; padding-left: 8px; display: flex; flex-direction: column; gap: 4px; }
.ac-reply { display: flex; align-items: baseline; gap: 5px; font-size: 12px; }
.ac-reply-name { color: #64748b; font-weight: 600; flex: none; }
.ac-reply-text { color: #334155; word-break: break-word; }
.ac-reply-time { color: #cbd5e1; font-size: 10px; flex: none; }
.ac-reply-box { display: flex; gap: 6px; margin-top: 6px; }
.ac-reply-box input { flex: 1; padding: 5px 9px; border: 1px solid #e2e8f0; border-radius: 7px; font-size: 12px; outline: none; min-width: 0; }

/* ========== S4/F1.4 表单自动暂存恢复横幅 ========== */
.draft-banner-host { min-height: 0; }
.draft-banner {
  display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap;
  background: #fffbeb; border: 1px solid #fcd34d; border-left: 4px solid #f59e0b;
  color: #92400e; border-radius: var(--r-sm); padding: 8px 12px; margin-bottom: 12px; font-size: 13px;
}
.draft-banner-txt { display: flex; align-items: center; gap: 6px; }
.draft-banner-actions { display: flex; align-items: center; gap: 8px; }
.draft-banner-actions .btn { white-space: nowrap; }

/* ========== S5 消息中心：通知/聊天 双模式 + 私信会话 ========== */
.mc-mode-bar { display: flex; gap: 6px; margin-bottom: 10px; }
.mc-mode-btn {
  border: 1px solid var(--border); background: var(--bg-surface); color: var(--text);
  border-radius: var(--r-full); padding: 5px 16px; font-size: 13px; cursor: pointer;
  display: inline-flex; align-items: center; gap: 4px; transition: all var(--t-fast);
}
.mc-mode-btn:hover { border-color: var(--accent); color: var(--accent); }
.mc-mode-btn.active { background: var(--accent); border-color: var(--accent); color: #fff; }
.mc-mode-badge {
  background: #fff; color: var(--accent); font-size: 11px; font-weight: 700;
  min-width: 16px; height: 16px; line-height: 16px; text-align: center; border-radius: var(--r-full); padding: 0 4px;
}
.mc-mode-btn.active .mc-mode-badge[style*="none"], .mc-mode-btn.active .mc-mode-badge[style*="display: none"] { background: #fff; }
/* 模式徽标整体重置（被 S5-6 样式覆盖：未读=红底白字；无未读=白底主色） */

.chat-conv {
  display: flex; align-items: center; gap: 10px; padding: 10px 12px; border: 1px solid var(--border);
  border-radius: var(--r-md); background: var(--bg-surface); margin-bottom: 8px;
}
.chat-conv:hover { border-color: var(--accent); box-shadow: 0 2px 8px rgba(37,99,235,.08); }
.chat-conv-avatar {
  width: 38px; height: 38px; border-radius: var(--r-full); color: #fff; flex: none;
  display: flex; align-items: center; justify-content: center; font-size: 16px; font-weight: 600;
}
.chat-conv-main { flex: 1; min-width: 0; }
.chat-conv-title { font-size: 13px; font-weight: 600; color: var(--text); display: flex; align-items: center; gap: 4px; }
.chat-conv-last { font-size: 12px; color: var(--text-mute); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.chat-conv-side { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; flex: none; }
.chat-conv-unread {
  background: #e5484d; color: #fff; font-size: 11px; font-weight: 700; min-width: 18px; height: 18px;
  line-height: 18px; text-align: center; border-radius: var(--r-full); padding: 0 5px;
}
.chat-conv-time { font-size: 11px; color: var(--text-mute); }

.chat-new-user-list { max-height: 46vh; overflow: auto; }
.chat-new-user {
  display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: var(--r-sm);
}
.chat-new-user:hover { background: var(--pri-50); }
.chat-new-user .chat-conv-avatar { width: 34px; height: 34px; font-size: 14px; }

.chat-body .msg-bubble { max-width: 78%; }
#chatBoxBody::-webkit-scrollbar { width: 8px; }
#chatBoxBody::-webkit-scrollbar-thumb { background: #d3d9e0; border-radius: 4px; }

/* ========== S5 头像（img 化） + 聊天增强（表情/文件） ========== */
.chat-conv-avatar, .msg-avatar { background: #eef2ff; color: #4338ca; }
img.chat-conv-avatar, img.msg-avatar { object-fit: cover; }
img.msg-avatar { width: 34px; height: 34px; border-radius: 50%; flex: none; }
img.chat-conv-avatar { width: 38px; height: 38px; border-radius: 50%; flex: none; }
#avatarPreview { display: flex; align-items: center; justify-content: center; font-weight: 600; }

.chat-input-wrap { flex-wrap: nowrap; }
.chat-input-bar { display: flex; align-items: center; gap: 8px; width: 100%; }
.chat-bar-btn { flex: none; padding: 6px 9px; font-size: 15px; }
.chat-emoji-panel {
  position: absolute; bottom: 54px; left: 10px; z-index: 30;
  background: var(--bg-surface); border: 1px solid var(--border); border-radius: var(--r-sm);
  box-shadow: 0 8px 24px rgba(15,23,42,.14); padding: 8px; width: 340px; max-height: 210px; overflow: auto;
  display: grid; grid-template-columns: repeat(10, 1fr); gap: 2px;
}
.chat-emoji { font-size: 20px; text-align: center; border-radius: 6px; padding: 3px 0; }
.chat-emoji:hover { background: var(--n-100); }

.chat-file-content { padding: 0 !important; background: transparent !important; }
.chat-file-card {
  display: flex; align-items: center; gap: 10px; background: var(--bg-surface);
  border: 1px solid var(--border); border-radius: 10px; padding: 8px 10px; min-width: 230px; max-width: 300px;
}
.mine .chat-file-card { background: #dbeafe; border-color: #bfdbfe; }
.chat-file-ico { font-size: 24px; flex: none; }
.chat-file-main { flex: 1; min-width: 0; }
.chat-file-name { font-size: 13px; font-weight: 600; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.chat-file-meta { font-size: 11px; color: var(--text-mute); margin-top: 2px; }
.chat-file-acts { display: flex; gap: 6px; flex: none; }
.chat-file-acts .btn { white-space: nowrap; font-size: 12px; padding: 3px 8px; }

/* ========== S5-3 @ 头像/弹层 + 聊天图片直显 ========== */
.msg-at-chip { display: inline-flex; align-items: center; gap: 2px; }
.at-avatar { width: 16px; height: 16px; border-radius: 50%; object-fit: cover; flex: none; display: inline-block; vertical-align: -3px; }
.at-name { display: inline-block; }
#mentionPopup .mp-item { justify-content: flex-start; gap: 8px; }
.mp-avatar { width: 22px; height: 22px; border-radius: 50%; object-fit: cover; flex: none; }
.mp-avatar:not(img) { background: #eef2ff; color: #4338ca; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: 600; }
.mp-main { display: flex; flex-direction: column; min-width: 0; }
.mp-main .mp-user { font-size: 11px; }
img.chat-conv-avatar, img.msg-avatar, img.mp-avatar, img.at-avatar { background: #eef2ff; }

.chat-img-wrap { display: inline-block; }
.chat-img { max-width: 220px; max-height: 260px; border-radius: 8px; display: block; cursor: zoom-in; object-fit: cover; background:#fff; }
.chat-img-dl { display: inline-flex; align-items: center; gap: 3px; padding: 2px 8px; font-size: 12px; }

/* S5-4 截图粘贴：待发送图片预览条 */
.chat-input-wrap { display: flex; flex-direction: column; gap: 6px; }
.chat-pending-imgs { display: flex; gap: 10px; flex-wrap: wrap; padding: 4px 2px 2px; width: 100%; }
.chat-pending-item { position: relative; }
.chat-pending-thumb { max-height: 96px; max-width: 120px; border-radius: 8px; border: 1px solid var(--border); background: #fff; }
.chat-pending-del {
  position: absolute; top: -7px; right: -7px; width: 19px; height: 19px; border-radius: 50%;
  background: #e5484d; color: #fff; border: none; cursor: pointer; font-size: 11px; line-height: 1;
}
.chat-pending-del:hover { background: #c81e1e; }

/* S5-5 会话文件站内预览：图片/文件卡操作行 */
.chat-img-acts { display: flex; gap: 6px; margin-top: 4px; }
.chat-img-acts .btn { padding: 2px 8px; font-size: 12px; }
.chat-file-acts .btn { padding: 3px 8px; font-size: 12px; }

/* S5-6 顶栏用户头像/聊天未读视觉（微信风格） */
.user-icon { width: 28px; height: 28px; border-radius: 50%; background: var(--accent-light); color: var(--accent); display: inline-flex; align-items: center; justify-content: center; font-size: 16px; flex: none; overflow: hidden; vertical-align: -6px; }
.user-icon img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* 消息中心「聊天」模式切换按钮：未读数字更大红色气泡（微信风格） */
.mc-mode-btn .mc-mode-badge {
  display: none;
  background: #e5484d; color: #fff; font-size: 11px; font-weight: 700;
  min-width: 18px; height: 18px; line-height: 18px; text-align: center;
  border-radius: 999px; padding: 0 5px; margin-left: 4px;
}
.mc-mode-btn .mc-mode-badge[style*="inline"], .mc-mode-btn .mc-mode-badge:not([style*="none"]) { display: inline-block; }

/* 会话卡片未读：整行加 .unread 高亮 + 「N 条未读」红色文字（参考微信聊天列表） */
.chat-conv { transition: background .15s; }
.chat-conv.unread { background: #fff5f5; border-color: #fecaca; }
.chat-conv.unread .chat-conv-title { color: #b91c1c; font-weight: 700; }
.chat-conv-unread-msg { color: #e5484d; font-size: 12px; font-weight: 700; margin-left: 4px; }
.chat-conv-unread {
  background: #e5484d; color: #fff; font-size: 12px; font-weight: 700;
  min-width: 20px; height: 20px; line-height: 20px; text-align: center;
  border-radius: 999px; padding: 0 6px; box-shadow: 0 0 0 2px #fff;
}

/* S5-7 微信式纯表情消息：放大展示（单条仅 emoji 时 ~2rem） */
.chat-emoji-only { font-size: 2rem !important; line-height: 1.45 !important; padding: 2px 6px !important; }

/* S5-7 聊天截图编辑器（深色工具栏） */
#modalChatShot .modal-foot { align-items: center; }
#modalChatShot .shot-tools { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.shot-tool {
  border: 1px solid #4b5563; background: transparent; color: #e5e7eb; border-radius: 6px;
  padding: 4px 10px; font-size: 12.5px; cursor: pointer;
}
.shot-tool:hover { border-color: var(--accent); color: #fff; }
.shot-tool.active { background: var(--accent); border-color: var(--accent); color: #fff; }
.shot-tool-ghost { color: #d1d5db; border: 1px solid #4b5563; background: transparent; }
.shot-tool-ghost:hover { border-color: var(--accent); color: #fff; }

/* S5-7b 截图方式选择按钮 */
.shot-pick-btn {
  display: flex; align-items: center; gap: 12px; width: 100%; text-align: left;
  border: 1px solid var(--border); background: var(--bg-surface); border-radius: var(--r-sm);
  padding: 12px 14px; cursor: pointer; transition: border-color .15s, background .15s;
}
.shot-pick-btn:hover { border-color: var(--accent); background: var(--pri-50); }
.shot-pick-ico { font-size: 24px; flex: none; }
.shot-pick-txt { display: flex; flex-direction: column; gap: 3px; }
.shot-pick-txt b { font-size: 13.5px; color: var(--text); }
.shot-pick-txt small { font-size: 12px; color: var(--text-mute); line-height: 1.5; }

/* S5-4 / #770 会话弹窗拖拽提示层 + 待发文档卡 */
.chat-drop-hint {
  position: absolute; inset: 0; z-index: 80;
  background: rgba(15, 23, 42, .55); backdrop-filter: blur(8px);
  display: flex; align-items: center; justify-content: center;
  pointer-events: none; border-radius: var(--r-sm);
  animation: chatDropPulse 1.2s ease-in-out infinite;
}
@keyframes chatDropPulse {
  0%, 100% { background: rgba(15, 23, 42, .45); }
  50% { background: rgba(15, 23, 42, .65); }
}
.chat-drop-hint-inner { text-align: center; color: #fff; padding: 24px; }
.chat-drop-hint-icon { font-size: 64px; margin-bottom: 14px; }
.chat-drop-hint-title { font-size: 22px; font-weight: 700; margin-bottom: 8px; letter-spacing: 1px; }
.chat-drop-hint-sub { font-size: 13px; opacity: .85; max-width: 380px; margin: 0 auto; line-height: 1.6; }

.chat-pending-item.is-doc { background: var(--bg-surface); border: 1px solid var(--border); border-radius: 8px; padding: 6px 8px; min-width: 180px; }
.chat-pending-doc { display: flex; align-items: center; gap: 8px; min-width: 0; }
.chat-pending-doc .cpd-ico { font-size: 22px; flex: none; }
.chat-pending-doc .cpd-name { font-size: 13px; font-weight: 600; color: var(--text); max-width: 140px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chat-pending-doc .cpd-size { font-size: 11px; color: var(--text-mute); flex: none; }

/* ================================================================
 * 登录页（全屏封面图 + 玻璃拟态卡片） #770
 * ================================================================ */
.login-overlay {
  position: fixed; inset: 0; z-index: 10000;
  display: flex; overflow: hidden;
  background: #0b1220;
}
.login-cover {
  position: absolute; inset: 0;
  background: url("/images/login-bg.jpg") center/cover no-repeat;
}
.login-cover::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(120deg, rgba(11,18,32,.55) 0%, rgba(11,18,32,.2) 45%, rgba(11,18,32,.55) 100%);
}
.login-cover-corner {
  position: absolute; right: 0; bottom: 0; z-index: 2;
  width: 360px; padding: 24px 26px;
  background: linear-gradient(135deg, rgba(255,255,255,.92), rgba(241,245,249,.92));
  backdrop-filter: blur(10px);
  border-top-left-radius: 14px;
  box-shadow: -8px -8px 32px rgba(0,0,0,.18);
  display: flex; flex-direction: column; gap: 6px;
  color: #0f172a;
}
.login-cover-corner .lc-brand { display: flex; align-items: center; gap: 8px; }
.login-cover-corner .lc-brand-mark {
  width: 28px; height: 28px; border-radius: 50%;
  background: linear-gradient(135deg, #2563eb, #7c3aed);
  display: inline-flex; align-items: center; justify-content: center; color: #fff; font-size: 14px;
}
.login-cover-corner .lc-brand-name { font-weight: 700; font-size: 14px; letter-spacing: .5px; }
.login-cover-corner .lc-tagline { font-size: 12px; color: #475569; line-height: 1.6; }
.login-cover-corner .lc-beian { display: flex; flex-wrap: wrap; gap: 6px 12px; margin-top: 4px; font-size: 11px; color: #475569; }
.login-cover-corner .lc-beian a { color: #475569; text-decoration: none; }
.login-cover-corner .lc-beian a:hover { color: #2563eb; }
.login-cover-corner .beian-icon { width: 14px; height: 14px; vertical-align: -2px; margin-right: 2px; }

.login-panel {
  position: relative; z-index: 3; margin-left: auto;
  width: 460px; max-width: 92vw; height: 100%;
  background: rgba(255,255,255,.86); backdrop-filter: blur(18px);
  border-left: 1px solid rgba(148,163,184,.18);
  box-shadow: -16px 0 60px rgba(15,23,42,.18);
  padding: 48px 56px;
  display: flex; flex-direction: column; justify-content: center;
  overflow-y: auto;
}
.login-brand { display: flex; align-items: center; gap: 12px; margin-bottom: 22px; }
.login-brand-mark {
  width: 46px; height: 46px; border-radius: 14px;
  background: linear-gradient(135deg, #2563eb 0%, #4f46e5 50%, #7c3aed 100%);
  display: inline-flex; align-items: center; justify-content: center; color: #fff; font-size: 22px;
  box-shadow: 0 6px 20px rgba(79,70,229,.35);
}
.login-brand-text h2 { font-size: 20px; font-weight: 800; color: #0f172a; margin: 0; letter-spacing: .5px; }
.login-brand-text p { font-size: 12.5px; color: #64748b; margin: 4px 0 0; }
.login-card h1 { display: none; }
.login-panel h3 { font-size: 18px; font-weight: 700; color: #0f172a; margin: 6px 0 4px; }
.login-panel .login-sub { font-size: 13px; color: #64748b; margin: 0 0 24px; }

.login-field { margin-bottom: 16px; }
.login-field label { display: block; font-size: 12px; font-weight: 600; color: #475569; margin-bottom: 6px; }
.login-field .login-input-wrap {
  display: flex; align-items: center; gap: 8px;
  border: 1.5px solid #e2e8f0; background: #fff; border-radius: 10px;
  padding: 0 12px; transition: all .2s;
}
.login-field .login-input-wrap:focus-within { border-color: #4f46e5; box-shadow: 0 0 0 4px rgba(79,70,229,.12); }
.login-field .login-input-wrap .licon { color: #94a3b8; font-size: 16px; flex: none; }
.login-field .login-input-wrap input {
  border: 0; outline: 0; padding: 12px 0; flex: 1; font-size: 14px; color: #0f172a; background: transparent;
}
.login-field .login-input-wrap input::placeholder { color: #cbd5e1; }
.login-remember { display: flex; align-items: center; gap: 8px; font-size: 12px; color: #475569; margin: 4px 0 18px; }
.login-remember input { accent-color: #4f46e5; }

.login-error { color: #dc2626; font-size: 12.5px; margin-bottom: 12px; min-height: 18px; }

.login-btn {
 width: 100%; padding: 13px; font-size: 15px; font-weight: 700;
 background: linear-gradient(135deg, #2563eb 0%, #4f46e5 60%, #7c3aed 100%);
 border: 0; border-radius: 10px; color: #fff; cursor: pointer;
 box-shadow: 0 10px 28px rgba(79,70,229,.32); transition: all .2s;
 position: relative; overflow: hidden;
}
.login-btn:hover { transform: translateY(-1px); box-shadow: 0 14px 32px rgba(79,70,229,.42); }
.login-btn:active { transform: translateY(0); }
.login-btn::after {
 content: ""; position: absolute; inset: 0;
 background: linear-gradient(120deg, transparent 30%, rgba(255,255,255,.35) 50%, transparent 70%);
 transform: translateX(-100%); transition: transform .6s;
}
.login-btn:hover::after { transform: translateX(100%); }

.login-beian {
  display: flex; flex-direction: column; gap: 6px; align-items: flex-start;
  margin-top: 22px; padding-top: 16px; border-top: 1px dashed #e2e8f0;
  font-size: 11.5px; color: #94a3b8; line-height: 1.6;
}
.login-beian a { color: #94a3b8; text-decoration: none; display: inline-flex; align-items: center; gap: 4px; }
.login-beian a:hover { color: #4f46e5; }
.login-beian .beian-icon { width: 14px; height: 14px; }

@media (max-width: 720px) {
  .login-panel { width: 100%; height: auto; min-height: 100%; padding: 32px 22px; border-left: 0; box-shadow: none; background: rgba(255,255,255,.94); }
  .login-cover { background-position: 70% center; opacity: .25; }
  .login-cover-corner { display: none; }
}

/* 登录页脚：备案号居中并列（#771 修正） */
.login-footer {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 5;
  display: flex; align-items: center; justify-content: center; gap: 14px;
  padding: 10px 12px;
  background: rgba(11, 18, 32, .52); backdrop-filter: blur(6px);
  font-size: 12px; color: #e2e8f0;
}
.login-footer a { color: #e2e8f0; text-decoration: none; display: inline-flex; align-items: center; gap: 4px; }
.login-footer a:hover { color: #fff; text-decoration: underline; }
.login-footer-sep { color: #64748b; }
.login-footer .beian-icon { width: 14px; height: 14px; }
.login-panel { padding-bottom: 64px; }

/* ============================================================
 * MOBILE ENHANCEMENT（#774 移动端适配，覆盖于既有断点之上）
 * 目标：≤900px 起触控目标 ≥40px；≤768px 卡片流式化；≤480px 单列极简
 * 桌面（>900px）样式完全不受影响
 * ============================================================ */
@media (max-width: 900px) {
  /* 触控基座：可点元素最小高度 */
  .btn { min-height: 40px; padding: 9px 16px; }
  .btn-sm { min-height: 38px; padding: 7px 13px; font-size: 12.5px; }
  .btn-xs { min-height: 38px; padding: 7px 12px; font-size: 12px; }
  .page-btn { min-height: 40px; padding: 7px 13px; font-size: 12.5px; }
  /* #774b 消息中心「通知/聊天」模式切换（高频主操作，原仅 31px）；后台管理/年包/采购分页小按钮同步抬高 */
  .mc-mode-btn { min-height: 40px; padding: 9px 18px; }
  .filter-select, .filter-date, .search-input { min-height: 42px; font-size: 14px; }
  .filter-date { width: 150px; }
  .topbar-right .notif-bell, #btnSettings { min-width: 42px; min-height: 42px; justify-content: center; padding: 8px; font-size: 15px; }
  .tabs { padding: 8px 14px 0; position: sticky; top: 0; z-index: 60; background: var(--bg-surface); box-shadow: 0 1px 0 var(--border); }
  .tab { min-height: 46px; padding: 12px 16px; font-size: 13.5px; }
  .toolbar { margin: 14px 0 12px; }
  .todo-actions .btn, .alert-item .btn { min-height: 40px; padding: 8px 16px; font-size: 13px; }
  .order-card-actions .btn { min-height: 38px; padding: 8px 14px; font-size: 13px; }
  .pagination { overflow-x: auto; }
}

@media (max-width: 768px) {
  /* 订单卡片：纵向 + 关键信息靠前 */
  .order-card { padding: 14px 14px; }
  .order-card-top { gap: 8px; }
  .order-no { font-size: 15px; }
  .order-card-main { gap: 8px; }
  .order-card-actions { gap: 8px; }
  .order-card-actions .btn { flex: 1 1 40%; }
  .stage-dots { gap: 4px; }
  .order-part-chip { font-size: 12px; padding: 4px 9px; }
  /* 卡片通用留白呼吸 */
  .todos-list, .alerts-list { gap: 12px; }
  .todo-item, .alert-item { padding: 14px 14px; gap: 10px; }
  .todo-info, .alert-info { font-size: 14px; }
  .todo-info strong, .alert-info strong { font-size: 14px; }
  .todo-actions, .alert-actions { width: 100%; justify-content: flex-end; gap: 10px; }
  /* 消息中心 */
  .msg-item { padding: 14px 14px; gap: 12px; }
  .msg-item-title { font-size: 14px; }
  .msg-item-text { font-size: 13px; }
  .msg-item-time { font-size: 12px; }
  /* 表格类容器横向滚动兜底 */
  .table-wrap, .stats-table-wrap, .parse-parts-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  /* 弹窗底部主操作固定大按钮 */
  .modal-foot .btn-primary, .modal-foot .btn-success, .modal-foot .btn-danger { min-height: 46px; font-size: 15px; }
}

@media (max-width: 480px) {
  /* 单列极简：字号基准上调防过小 */
  .content { padding: 0 12px 32px; }
  .tab { min-height: 44px; padding: 10px 12px; font-size: 13px; }
  .page-btn { min-width: 40px; }
  .order-part-chip { max-width: none; flex: 1 1 45%; }
  .order-card-actions .btn { flex: 1 1 100%; }
  .todo-actions, .alert-actions { flex-wrap: wrap; }
  .todo-actions .btn, .alert-item .btn { flex: 1 1 45%; }
  .stats-bar { gap: 8px; }
  .kpi-card { flex: 1 1 100%; }
  .msg-item { flex-direction: column; align-items: flex-start; }
}

/* #774 移动端溢出兜底：quote 文件长名 / annual 备注 / 甘特图滚动容器 */
@media (max-width: 768px) {
  .quote-card-title, .quote-card-title > * { min-width: 0; }
  .quote-file, .file-name { max-width: 100%; }
  .gantt-wrap { padding: 10px; }
  .order-remark { max-width: 160px; }
  #quoteSearchInput { grid-column: 1 / -1; min-width: 0 !important; max-width: none !important; width: 100%; }
}


/* #775 聊天图片加载体验：骨架 shimmer + 淡入（缩略图秒开） */
.chat-img {
  background: linear-gradient(90deg, #eef1f5 0%, #e3e9f0 50%, #eef1f5 100%);
  background-size: 200% 100%;
  animation: chatImgShimmer 1.1s linear infinite;
  opacity: .96; transition: opacity .25s ease;
}
.chat-img:not(.loaded) { min-width: 120px; min-height: 80px; }
.chat-img.loaded { animation: none; background: #f1f4f8; opacity: 1; }
@keyframes chatImgShimmer {
  0% { background-position: 0 0; }
  100% { background-position: -200% 0; }
}

/* ================================================================
 * #777 文件备份版块（超管专属）
 * ================================================================ */
/* #851 头部操作按钮组：抽屉/仓库等页面统一用它包裹「主操作 + 次操作」按钮，
 *   解决把它们与标题并排放在 justify-content:space-between 容器里、被均匀撑开的问题。
 *   .vault-head-actions 是历史名字（文件备份版块先用），此处加通用别名，二者等价。*/
.vault-head-actions, .head-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
/* #851c 组内按钮统一高度：btn-primary 无边框(34px)、btn-ghost 有 1px 边框(36px)，
 *   并排时会差 2px。统一 min-height 抹平（用 min-height 而非 height，避免压扁内容）。 */
.vault-head-actions .btn, .head-actions .btn { min-height: 36px; }
.vault-head h2 { margin: 0 0 4px; }
.vault-head p { margin: 0; font-size: 13px; color: var(--text-soft); }

/* 容量统计卡 */
.vault-stats { display: flex; gap: 10px; flex-wrap: wrap; margin: 14px 0 4px; }
.vault-stat {
  display: flex; flex-direction: column; gap: 2px; min-width: 132px;
  padding: 10px 14px; background: var(--bg-surface); border: 1px solid var(--border-light);
  border-radius: var(--r-md); box-shadow: var(--shadow-xs);
}
.vault-stat .k { font-size: 11.5px; color: var(--text-mute); letter-spacing: .02em; }
.vault-stat .v { font-size: 17px; font-weight: 700; color: var(--text); }
.vault-stat .v small { font-size: 11.5px; font-weight: 500; color: var(--text-mute); margin-left: 3px; }

/* 工具栏 */
.vault-toolbar { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin-top: 14px; }
.vault-toolbar .search-input { flex: 1 1 220px; min-width: 160px; }

/* 批量操作条 */
.vault-bulkbar {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-top: 12px; padding: 10px 14px;
  background: var(--pri-50); border: 1px solid var(--pri-200);
  border-radius: var(--r-md); position: sticky; top: 0; z-index: 5;
}
.vault-bulk-count { font-size: 13px; color: var(--pri-700); }
.vault-bulk-count b { font-size: 15px; }
.vault-bulkbar .filter-select { padding: 6px 10px; font-size: 12.5px; }

/* 上传进度面板 */
.vault-upload-panel {
  margin-top: 12px; padding: 12px 14px; background: var(--bg-surface);
  border: 1px solid var(--border); border-radius: var(--r-md); box-shadow: var(--shadow-sm);
}
.vault-upload-head { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
.vault-upload-head strong { font-size: 13.5px; }
.vault-upload-head span { font-size: 12px; color: var(--text-mute); margin-left: auto; }
.vault-upload-list { display: flex; flex-direction: column; gap: 7px; max-height: 220px; overflow: auto; }
.vault-up-item { display: grid; grid-template-columns: minmax(0,1fr) 190px 54px 22px; gap: 10px; align-items: center; font-size: 12.5px; }
.vault-up-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text-soft); }
.vault-up-bar { height: 6px; background: var(--n-100); border-radius: 99px; overflow: hidden; }
.vault-up-bar > i { display: block; height: 100%; width: 0%; border-radius: 99px; background: linear-gradient(90deg, #8b5cf6, var(--accent)); transition: width .2s ease; }
.vault-up-pct { text-align: right; font-weight: 600; color: var(--accent); font-variant-numeric: tabular-nums; }
.vault-up-item.is-done .vault-up-pct { color: var(--suc-600); }
.vault-up-item.is-error .vault-up-pct { color: var(--dgr-600); }
.vault-up-item.is-error .vault-up-bar > i { background: var(--dgr-500); }
.vault-up-state { font-size: 14px; text-align: center; }

/* 拖放区 */
.vault-dropzone { position: relative; margin-top: 14px; border-radius: var(--r-md); transition: background .15s ease; }
.vault-dropzone.drag-over { background: var(--pri-50); outline: 2px dashed var(--pri-500); outline-offset: -6px; }
.vault-drop-hint {
  font-size: 12.5px; color: var(--text-mute); padding: 10px 14px; margin-bottom: 10px;
  background: var(--n-50); border: 1px dashed var(--border); border-radius: var(--r-sm); text-align: center;
}

/* 列表 */
.vault-list { display: flex; flex-direction: column; gap: 6px; }
.vault-row {
  display: grid;
  grid-template-columns: 34px 30px minmax(0, 1fr) 120px 92px 96px 140px 158px;
  gap: 10px; align-items: center;
  padding: 9px 12px; background: var(--bg-surface);
  border: 1px solid var(--border-light); border-radius: var(--r-sm);
  transition: border-color .15s ease, box-shadow .15s ease;
}
.vault-row:hover { border-color: var(--pri-200); box-shadow: var(--shadow-xs); }
.vault-row.is-sel { background: var(--pri-50); border-color: var(--pri-200); }
.vault-row.is-missing { opacity: .55; }
.vault-row input[type="checkbox"] { width: 16px; height: 16px; cursor: pointer; accent-color: var(--accent); }
.vault-ico { font-size: 18px; text-align: center; line-height: 1; }
.vault-name { min-width: 0; }
.vault-name a {
  display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: 13.5px; font-weight: 600; color: var(--text); text-decoration: none; cursor: pointer;
}
.vault-name a:hover { color: var(--accent); text-decoration: underline; }
.vault-sub { font-size: 11.5px; color: var(--text-mute); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vault-cat-chip {
  display: inline-block; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: 11.5px; padding: 2px 9px; border-radius: var(--r-full);
  background: var(--inf-50); color: #0369a1; border: 1px solid var(--inf-100);
}
.vault-cat-chip.is-none { background: var(--n-50); color: var(--text-mute); border-color: var(--border-light); }
.vault-size, .vault-by, .vault-time { font-size: 12px; color: var(--text-soft); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.vault-acts { display: flex; gap: 4px; justify-content: flex-end; flex-wrap: nowrap; }
.vault-acts .btn { padding: 4px 7px; font-size: 12px; }
.vault-empty { padding: 46px 16px; text-align: center; color: var(--text-mute); font-size: 13.5px; }
.vault-empty .big { font-size: 40px; display: block; margin-bottom: 10px; }

/* 分类管理弹窗 */
.vault-cat-list { display: flex; flex-direction: column; gap: 6px; max-height: 380px; overflow: auto; }
.vault-cat-row {
  display: grid; grid-template-columns: minmax(0,1fr) 78px 128px; gap: 10px; align-items: center;
  padding: 9px 12px; border: 1px solid var(--border-light); border-radius: var(--r-sm); background: var(--bg-surface);
}
.vault-cat-row .nm { font-size: 13.5px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vault-cat-row .ct { font-size: 12px; color: var(--text-mute); }
.vault-cat-row .op { display: flex; gap: 6px; justify-content: flex-end; }
.vault-cat-row .op .btn { padding: 4px 8px; font-size: 12px; }

/* 预览弹窗 */
.vault-preview-body {
  max-height: 68vh; overflow: auto; background: #0f172a; border-radius: var(--r-sm);
  display: flex; align-items: center; justify-content: center; min-height: 220px;
}
.vault-preview-body img { max-width: 100%; max-height: 66vh; display: block; }
.vault-preview-body video { max-width: 100%; max-height: 66vh; background: #000; }
.vault-preview-body audio { width: 100%; padding: 24px; }
.vault-preview-body iframe { width: 100%; height: 66vh; border: 0; background: #fff; }
.vault-preview-body pre {
  margin: 0; padding: 16px 18px; width: 100%; max-height: 66vh; overflow: auto;
  color: #e2e8f0; font-size: 12.5px; line-height: 1.6; white-space: pre-wrap; word-break: break-word;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
.vault-preview-fallback { color: #cbd5e1; font-size: 13.5px; padding: 40px 20px; text-align: center; }
.vault-preview-meta { margin-right: auto; font-size: 12px; color: var(--text-mute); }

/* 移动端：列表卡片化 */
@media (max-width: 900px) {
  .vault-row { grid-template-columns: 30px 26px minmax(0,1fr) 92px; grid-template-areas: "ck ico name size" ". . cat acts"; row-gap: 6px; }
  .vault-row > .vault-ck { grid-area: ck; } .vault-row > .vault-ico { grid-area: ico; }
  .vault-row > .vault-name { grid-area: name; } .vault-row > .vault-size { grid-area: size; text-align: right; }
  .vault-row > .vault-cat { grid-area: cat; } .vault-row > .vault-acts { grid-area: acts; }
  .vault-row > .vault-by, .vault-row > .vault-time { display: none; }
  .vault-up-item { grid-template-columns: minmax(0,1fr) 110px 48px 20px; }
  .vault-head-actions .btn, .head-actions .btn { flex: 1 1 auto; }
}
@media (max-width: 480px) {
  .vault-bulkbar { position: static; }
  .vault-bulkbar .btn { flex: 1 1 auto; justify-content: center; }
  .vault-stat { min-width: 104px; padding: 8px 11px; }
  .vault-stat .v { font-size: 15px; }
  .vault-cat-row { grid-template-columns: minmax(0,1fr) 112px; }
  .vault-cat-row .ct { display: none; }
}


/* ============================================================
 * #778 移动端专用 UI 与布局（仅 ≤900px 生效，PC 端零影响）
 * ------------------------------------------------------------
 * 设计目标：手机上一屏能看到真正的内容，而不是顶栏和统计卡片。
 * 关键改动：
 *   1. 顶栏 159px → 52px（logo 单行、副标题与文字按钮收进抽屉）
 *   2. 13 个横向 tab → 底部 4 图标导航 + 「更多」抽屉
 *   3. 统计卡片 2×2 大卡 → 一行横滑小卡（约 200px → 68px）
 *   4. 内容区左右留白收紧、底部为固定导航让位
 * ============================================================ */

/* 移动端导航默认隐藏，PC 端永不出现 */
.mnav, .mdrawer, .mdrawer-mask { display: none; }

/* ============================================================
 * #778 移动端专用 UI 与布局（仅 ≤900px 生效，PC 端零影响）
 * ------------------------------------------------------------
 * 设计目标：手机上一屏能看到真正的内容，而不是顶栏和统计卡片。
 * 关键改动：
 *   1. 顶栏 159px → 52px（logo 单行、副标题与文字按钮收进抽屉）
 *   2. 13 个横向 tab → 底部 4 图标导航 + 「更多」抽屉
 *   3. 统计卡片 2×2 大卡 → 一行横滑小卡（约 200px → 68px）
 *   4. 内容区左右留白收紧、底部为固定导航让位
 * ============================================================ */

/* 移动端导航默认隐藏，PC 端永不出现 */
.mnav, .mdrawer, .mdrawer-mask { display: none; }

@media (max-width: 900px) {

  /* ---------- 底部标签栏 ---------- */
  /* #842 ★ 底部安全间距统一走 --sys-bottom（由 app.js 的 initSysBottomInset 写入）
   *   为什么不用 env() 单打独斗：env(safe-area-inset-bottom) **在 Android 上恒为 0**
   *   （iOS 全面屏才给 34px），而 PWA 是 display:standalone（全屏）→
   *   系统导航栏（手势条/三键虚拟键）浮在页面上 → 底部按钮被压住点不到。
   *   JS 已按平台算出合理值（iOS 用 env 实测；Android 用兜底值），此处只负责取用。
   *   var() 的第二参保留 env() 作为 JS 未执行时的回退，双保险。 */
  .mnav {
    display: flex; position: fixed; left: 0; right: 0; bottom: 0; z-index: 200;
    background: rgba(255,255,255,.96);
    backdrop-filter: blur(14px);
    border-top: 1px solid var(--border);
    padding-bottom: var(--sys-bottom, env(safe-area-inset-bottom, 0px));
    box-shadow: 0 -1px 12px rgba(15,23,42,.06);
  }
  .mnav-item {
    flex: 1 1 0; min-width: 0;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 2px; padding: 8px 2px 7px;
    background: none; border: none; cursor: pointer;
    color: var(--text-mute); font-family: inherit;
    position: relative; min-height: 52px;
    -webkit-tap-highlight-color: transparent;
    transition: color .15s ease;
  }
  /* ★ 移动端图标与文字比例（老王反馈：第一个字太大、不舒服）
     原为 mnav 20px/10.5px、mdg 23px/11.5px —— 图标接近文字的 2 倍，视觉失衡。
     现统一收敛到约 1.5:1，并把偏小的文字同步放大（兼顾近视可读性）。 */
  .mnav-ico { font-size: 16px; line-height: 1; }
  .mnav-txt { font-size: 11.5px; font-weight: 500; letter-spacing: .2px; }
  .mnav-item.active { color: var(--pri-600, #2563eb); }
  .mnav-item.active .mnav-ico { transform: translateY(-1px); }
  .mnav-item:active { background: rgba(37,99,235,.06); }
  .mnav-badge {
    position: absolute; top: 3px; left: 50%; margin-left: 6px;
    background: var(--dgr-500, #ef4444); color: #fff;
    font-size: 10px; font-weight: 700; line-height: 1;
    min-width: 17px; height: 17px; padding: 0 4px;
    border-radius: var(--r-full, 999px);
    display: flex; align-items: center; justify-content: center;
    border: 1.5px solid #fff;
  }
  /* 为固定导航让位：同时给 body 加底部内边距，避免遮住页脚与列表末项 */
  body { padding-bottom: calc(56px + var(--sys-bottom, env(safe-area-inset-bottom, 0px))); }

  /* ---------- 顶栏精简 ---------- */
  .topbar {
    padding: 8px 12px;
    flex-wrap: nowrap;
    gap: 8px;
    align-items: center;
    justify-content: space-between;
    overflow: hidden;   /* 兜底：任何子项超宽都不得撑破视口 */
  }
  /* 左区必须可收缩，否则会把自己的宽度"传递"给右区导致横向溢出 */
  .topbar-left { flex: 1 1 auto; min-width: 0; overflow: hidden; }
  .logo { gap: 9px; min-width: 0; overflow: hidden; }
  .logo-mark { width: 30px; height: 30px; font-size: 15px; border-radius: 8px; box-shadow: none; }
  .logo-text { min-width: 0; }
  .logo-text h1 {
    font-size: 14px; letter-spacing: 0;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .logo-text p { display: none; }   /* 副标题在手机上纯占高度，移到抽屉说明 */
  /* 右侧：只留铃铛 + 头像，其余收进抽屉 */
  .topbar-right {
    flex: 0 0 auto; flex-wrap: nowrap; gap: 2px;
    min-width: 0; white-space: nowrap;
  }
  .topbar-right .user-info { flex-wrap: nowrap; gap: 2px; min-width: 0; }
  .topbar-right .today-label,
  .topbar-right .user-name,
  .topbar-right .user-role,
  .topbar-right #btnAdminPanel,
  .topbar-right #btnSettings,
  .topbar-right #btnLogout { display: none !important; }
  .topbar-right .notif-bell { min-width: 38px; min-height: 38px; font-size: 18px; padding: 6px; }
  .topbar-right .user-info { gap: 0; }
  .topbar-right .user-icon {
    width: 34px; height: 34px; font-size: 18px; cursor: pointer;
    border: 1.5px solid var(--border);
  }

  /* ---------- 横向 tabs 隐藏（改由底部导航承担） ---------- */
  .tabs { display: none !important; }

  /* ---------- 统计卡片：2×2 大卡 → 一行横滑小卡 ---------- */
  .stats-bar {
    display: flex; flex-wrap: nowrap; gap: 8px;
    padding: 10px 12px;
    margin: 0;
    overflow-x: auto; overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    scroll-snap-type: x proximity;
  }
  .stats-bar::-webkit-scrollbar { display: none; }
  /* 真实类名是 .stat/.stat-num/.stat-label（见 styles.css:288） */
  .stats-bar .stat {
    flex: 0 0 auto; min-width: 86px;
    padding: 8px 12px;
    border-radius: var(--r-md, 10px);
    scroll-snap-align: start;
  }
  .stats-bar .stat:hover { transform: none; box-shadow: var(--shadow-sm); }
  .stats-bar .stat-num { font-size: 19px; letter-spacing: 0; line-height: 1.15; }
  .stats-bar .stat-label { font-size: 11px; margin-top: 1px; white-space: nowrap; }

  /* ---------- 内容区留白收紧 ---------- */
  .content { padding: 0 12px 24px; }

  /* ---------- 「更多」抽屉 ----------
     ⚠ 关键：不能用 display 覆盖 HTML 的 hidden 属性。
     作者样式的 display 优先级高于 [hidden] 的 UA 样式（display:none），
     曾导致 #mdrawerMask 虽 hidden=true 却仍 position:fixed;inset:0;z-index:300
     铺满全屏、透明但可点击 → 移动端所有按钮点击被吞（#779）。
     正确做法：display 常驻，用 visibility + pointer-events 控制可交互性。 */
  .mdrawer-mask {
    display: block; position: fixed; inset: 0; z-index: 300;
    background: rgba(15,23,42,.42);
    opacity: 0; visibility: hidden; pointer-events: none;
    transition: opacity .22s ease, visibility .22s ease;
  }
  .mdrawer-mask.show { opacity: 1; visibility: visible; pointer-events: auto; }
  .mdrawer {
    display: flex; flex-direction: column;
    position: fixed; z-index: 310;
    left: 0; right: 0; bottom: 0;
    max-height: 82vh;
    background: var(--bg-surface, #fff);
    border-radius: 18px 18px 0 0;
    box-shadow: 0 -8px 32px rgba(15,23,42,.18);
    transform: translateY(100%);
    visibility: hidden; pointer-events: none;
    transition: transform .26s cubic-bezier(.22,.61,.36,1), visibility .26s ease;
    padding-bottom: var(--sys-bottom, env(safe-area-inset-bottom, 0px));
  }
  .mdrawer.show { transform: translateY(0); visibility: visible; pointer-events: auto; }
  .mdrawer-head {
    display: flex; align-items: center; justify-content: space-between;
    gap: 10px; padding: 14px 16px 12px;
    border-bottom: 1px solid var(--border);
    flex: none;
  }
  .mdrawer-user { display: flex; align-items: center; gap: 10px; min-width: 0; }
  .mdrawer-user-txt { display: flex; flex-direction: column; min-width: 0; }
  .mdrawer-user-txt strong { font-size: 15px; color: var(--n-900); }
  .mdrawer-user-txt span { font-size: 11.5px; color: var(--text-mute); }
  .mdrawer-close {
    flex: none; width: 34px; height: 34px; border-radius: 50%;
    border: none; background: var(--n-100, #f1f5f9); color: var(--text-mute);
    font-size: 15px; cursor: pointer; line-height: 1;
  }
  /* 板块宫格：3 列图标 + 文字，符合手机扫视习惯 */
  .mdrawer-grid {
    flex: 1 1 auto; overflow-y: auto;
    display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 4px; padding: 12px 10px;
  }
  .mdg-item {
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 5px; padding: 12px 4px;
    background: none; border: none; border-radius: var(--r-md, 10px);
    font-family: inherit; cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    position: relative;
  }
  .mdg-item:active { background: var(--n-50, #f8fafc); }
  .mdg-item.active { background: rgba(37,99,235,.08); }
  .mdg-item.active .mdg-txt { color: var(--pri-600, #2563eb); font-weight: 600; }
  /* ★ 同上：抽屉宫格图标原 23px 是文字 11.5px 的两倍，过于突兀。
     收敛到 19px 并把文字放大到 12.5px（比例约 1.5:1）。 */
  .mdg-ico { font-size: 16px; line-height: 1; }
  .mdg-txt { font-size: 12.5px; color: var(--text); text-align: center; line-height: 1.3; }
  .mdg-item .mnav-badge { top: 6px; left: 50%; margin-left: 8px; }

  .mdrawer-foot {
    flex: none; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 8px; padding: 12px 16px 16px;
    border-top: 1px solid var(--border);
  }
  .mdrawer-act {
    display: flex; align-items: center; justify-content: center; gap: 6px;
    min-height: 42px; border-radius: var(--r-md, 10px);
    border: 1px solid var(--border); background: var(--bg-surface, #fff);
    font-family: inherit; font-size: 13.5px; color: var(--text); cursor: pointer;
    position: relative;
  }
  .mdrawer-act:active { background: var(--n-50, #f8fafc); }
  .mdrawer-act-danger { color: var(--dgr-600, #dc2626); border-color: var(--dgr-100, #fee2e2); }
  .mdrawer-act-danger:active { background: var(--dgr-50, #fef2f2); }

  /* 抽屉打开时锁滚动 */
  body.mdrawer-open { overflow: hidden; }
}

/* ============================================================
 * #778b 移动端高频板块精细打磨（仅 ≤900px 生效，PC 端零影响）
 * ------------------------------------------------------------
 * 板块：订单总览 / 待办项 / 消息中心 / 文件备份
 * 类名来源：全部取自真实 DOM（CDP 抓取），不猜类名
 *   订单卡 .order-card / .order-card-top / .order-card-main / .order-card-actions
 *   零件行 .item-row / .item-actions
 *   统计卡 .stats-bar .stat / .stat-num / .stat-label
 *   备份行 .vault-row（grid: ck ico name size / cat acts）
 * 统一原则：触控目标 ≥38px、卡片竖向分层、长文本截断、杜绝横向溢出
 * ============================================================ */
@media (max-width: 900px) {

  /* ---------- 订单总览 ---------- */
  /* 工具条：沿用既有 grid（1388 断点已设 auto-fit），此处只收紧外边距 */
  .toolbar { margin: 10px 0; gap: 8px; }

  /* 订单卡：去掉 hover 上浮（手机无 hover，且避免 sticky 抖动） */
  .order-card:hover { transform: none; }
  /* 主信息行允许换行；客户名/备注截断，避免撑破 */
  .order-card-main { flex-wrap: wrap; gap: 6px 8px; }
  .order-card-customer,
  .order-card-main .order-customer {
    max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .order-card-main .order-remark {
    max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    font-size: 12px;
  }
  /* #779-B 操作收纳（仅移动端 ≤900px）：入口按钮整行；展开后两列网格，拇指可达 */
  .order-card-actions { display: block; width: 100%; position: relative; }
  .order-card-actions .btn-act-toggle {
    display: inline-flex; align-items: center; gap: 7px; font-weight: 600;
    width: 100%; justify-content: center; min-height: 38px; font-size: 13px;
  }
  .order-card-actions .btn-act-toggle .act-toggle-num {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 18px; height: 18px; padding: 0 5px;
    border-radius: 9px; font-size: 11px; font-weight: 700; line-height: 1;
    background: var(--accent, #2563eb); color: #fff;
  }
  .order-card-actions .btn-act-toggle .act-toggle-caret {
    display: inline-block; font-size: 10px; transition: transform .18s ease;
  }
  .order-card-actions.open .btn-act-toggle .act-toggle-caret { transform: rotate(180deg); }
  .order-card-actions.open .btn-act-toggle { background: var(--n-100, #f1f5f9); color: var(--n-900, #0f172a); }
  .order-card-actions .order-act-panel { display: none; }
  .order-card-actions.open .order-act-panel {
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 6px; margin-top: 6px;
  }
  .order-card-actions .order-act-panel .btn {
    width: 100%; justify-content: center; min-height: 38px;
  }
  .order-card-actions .order-act-panel .btn:last-child:nth-child(odd) { grid-column: 1 / -1; }

  /* 零件标签组：flex item 默认 min-width:auto 会被长内容撑开并溢出卡片
     → margin-left 归零 + min-width:0 + max-width:100% 三重保险 */
  .stage-dots { min-width: 0; max-width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .order-part-chips {
    margin-left: 0; width: 100%; max-width: 100%; min-width: 0;
    flex-wrap: wrap; overflow: hidden;
  }
  .order-part-chip { max-width: 100%; min-width: 0; }

  /* 零件行：竖向，操作按钮占满宽度 */
  .item-actions { width: 100%; display: flex; flex-wrap: wrap; gap: 6px; }
  .item-actions .btn { flex: 1 1 auto; justify-content: center; }

  /* ---------- 待办项 ---------- */
  .todo-actions { width: 100%; display: flex; flex-wrap: wrap; gap: 6px; }
  .todo-actions .btn { flex: 1 1 auto; justify-content: center; min-height: 40px; }

  /* ---------- 消息中心 ---------- */
  /* 输入类控件 16px（防 iOS 聚焦缩放），沿用既有断点再兜一层 */
  .msg-reply-input, .composer-at, .chat-input, .mc-search-input {
    font-size: 16px; min-height: 40px;
  }
  /* 消息气泡操作按钮抬高 */
  .msg-bubble-actions .btn { min-height: 34px; font-size: 12.5px; }

  /* ---------- 文件备份（真实类名 .vault-row，已是 grid 布局） ---------- */
  /* 已有 900px 断点把 .vault-row 排成两行网格；此处只做字号与按钮可达性微调 */
  .vault-row .vault-name {
    word-break: break-all; line-height: 1.35;
    max-height: 2.7em; overflow: hidden;
  }
  .vault-acts { display: flex; flex-wrap: wrap; gap: 6px; }
  .vault-acts .btn { flex: 1 1 auto; justify-content: center; min-height: 38px; }

  /* ---------- 通用：防横向溢出 ---------- */
  .table-wrap, .data-table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .order-no, .part-no, .vault-name, .mdg-txt { word-break: break-word; }
  /* 弹窗贴边全宽、内容可滚动 */
  .modal-overlay { padding: 8px; }
  .modal { max-width: 100%; max-height: 92vh; }
}


/* ============================================================
 * #779-C UI 现代化打磨层（★仅移动端 ≤900px 生效，PC 端保持原样）
 * ------------------------------------------------------------
 * 用户明确要求：本次改版只作用于移动端，PC 端必须与改动前一致。
 * 因此整层用 @media (max-width: 900px) 包裹，PC 端不接收任何覆盖。
 * 设计原则（务实、克制、零回归）：
 *   1) 只做视觉增强：层次/圆角/阴影/描边/交互反馈/留白节奏
 *   2) 不改任何布局属性（flex/grid/width/padding 骨架不动）
 *   3) 尊重系统偏好：prefers-reduced-motion 下关闭动效
 *   4) 状态色沿用既有语义令牌（红=超时/绿=完成），不引入新色系
 *   5) 触摸设备统一禁掉 hover 位移，改用 :active 反馈（避免粘滞态）
 * ============================================================ */
@media (max-width: 900px) {

/* ---------- 1. 更细腻的中性色阶与层次 ---------- */
:root {
  --ring-accent: 0 0 0 3px rgba(37,99,235,.14);
  --shadow-card: 0 1px 2px rgba(15,23,42,.04), 0 4px 12px rgba(15,23,42,.045);
  --shadow-card-hover: 0 2px 4px rgba(15,23,42,.05), 0 10px 26px rgba(15,23,42,.085);
  --glass-bg: color-mix(in srgb, var(--bg-surface) 82%, transparent);
  --glass-border: color-mix(in srgb, var(--border) 90%, transparent);
  --ease-out: cubic-bezier(.22,.61,.36,1);
}

/* ---------- 2. 焦点可见性（键盘无障碍，同时不干扰鼠标） ---------- */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 6px;
}
.btn:focus-visible, .tab:focus-visible, .mnav-item:focus-visible, .mdg-item:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  box-shadow: var(--ring-accent);
}

/* ---------- 3. 顶栏：更干净的玻璃质感 + 细描边 ---------- */
.topbar {
  backdrop-filter: saturate(160%) blur(12px);
  -webkit-backdrop-filter: saturate(160%) blur(12px);
  background: var(--glass-bg);
  border-bottom: 1px solid var(--glass-border);
}

/* ---------- 4. 卡片体系：统一「浮起‑描边‑交互」语言 ---------- */
/* 说明：待办视图当前复用 .order-card 渲染；.todo-item 为既有保留样式，一并纳入保证一致 */
.order-card,
.todo-item,
.alert-item,
.alert-order-card,
.stat,
.kpi-card,
.vault-row,
.item-row {
  box-shadow: var(--shadow-card);
  transition: box-shadow .22s var(--ease-out), border-color .22s var(--ease-out), transform .22s var(--ease-out);
}
.order-card:hover,
.todo-item:hover,
.alert-item:hover,
.vault-row:hover {
  box-shadow: var(--shadow-card-hover);
  border-color: var(--n-300);
}
/* 触摸设备：hover 不位移，避免"粘住"的悬停态 */
@media (hover: none) {
  .order-card:hover, .todo-item:hover, .alert-item:hover, .vault-row:hover, .stat:hover, .kpi-card:hover {
    transform: none;
  }
  .order-card:active, .todo-item:active, .alert-item:active { transform: scale(.995); }
}

/* ---------- 5. 主按钮：渐变 + 内高光，提升"可点"感 ---------- */
.btn-primary {
  background: linear-gradient(180deg, var(--pri-500), var(--pri-600));
  border-color: var(--pri-600);
  box-shadow: 0 1px 2px rgba(37,99,235,.28), inset 0 1px 0 rgba(255,255,255,.22);
}
.btn-primary:hover:not(:disabled) {
  background: linear-gradient(180deg, var(--pri-600), var(--pri-700));
  border-color: var(--pri-700);
  box-shadow: 0 3px 10px rgba(37,99,235,.3), inset 0 1px 0 rgba(255,255,255,.2);
}
.btn-primary:active:not(:disabled) {
  transform: translateY(.5px);
  box-shadow: inset 0 2px 5px rgba(15,23,42,.22);
}

/* 幽灵/次要按钮：hover 描边加深，避免"没反应"的观感 */
.btn-ghost:hover:not(:disabled) {
  background: var(--n-100);
  border-color: var(--n-300);
  color: var(--n-900);
}

/* 危险操作：hover 才显形，降低误触 */
.btn-danger:hover:not(:disabled) {
  background: var(--dgr-600);
  border-color: var(--dgr-700);
  box-shadow: 0 3px 10px rgba(220,38,38,.28);
}

/* ---------- 6. 统计卡：数字更有分量（仅排版，不动尺寸） ---------- */
.stat-num, .kpi-value {
  font-variant-numeric: tabular-nums;
  letter-spacing: -.3px;
}
.stat-label, .kpi-label { letter-spacing: .02em; }

/* ---------- 7. 阶段圆点：立体感 + 完成态描边 ---------- */
.stage-dot {
  box-shadow: 0 2px 5px rgba(15,23,42,.16), inset 0 1px 0 rgba(255,255,255,.28);
}
.stage-dot.s-dot-done { box-shadow: 0 2px 5px rgba(22,163,74,.26), inset 0 1px 0 rgba(255,255,255,.3); }
.stage-dot.s-dot-overdue { box-shadow: 0 2px 8px rgba(220,38,38,.34), inset 0 1px 0 rgba(255,255,255,.24); }
.stage-dot.s-dot-active { box-shadow: 0 2px 5px rgba(37,99,235,.24), inset 0 1px 0 rgba(255,255,255,.28); }

/* ---------- 8. 输入类控件：统一聚焦环 ---------- */
input[type="text"], input[type="password"], input[type="number"], input[type="date"],
input[type="search"], input[type="email"], select, textarea, .search-input, .filter-select, .filter-date, .filter-input {
  transition: border-color .16s ease, box-shadow .16s ease, background .16s ease;
}
input[type="text"]:focus, input[type="password"]:focus, input[type="number"]:focus, input[type="date"]:focus,
input[type="search"]:focus, input[type="email"]:focus, select:focus, textarea:focus,
.search-input:focus, .filter-select:focus, .filter-date:focus {
  border-color: var(--pri-500);
  box-shadow: var(--ring-accent);
  background: var(--n-0);
}

/* ---------- 9. 表格：斑马纹更淡 + 表头吸顶质感 ---------- */
/* 本项目表格类名：.stats-table / .parse-parts-table / .quote-cost-table 等（无 .data-table） */
.stats-table, .parse-parts-table, .qct-ops-table, .quote-cost-table, .quote-purchase-table {
  border-collapse: separate; border-spacing: 0;
}
.stats-table tbody tr:nth-child(even),
.parse-parts-table tbody tr:nth-child(even),
.qct-ops-table tbody tr:nth-child(even) { background: rgba(248,250,252,.7); }
.stats-table tbody tr:hover,
.parse-parts-table tbody tr:hover,
.qct-ops-table tbody tr:hover { background: var(--pri-50); }

/* ---------- 10. 弹窗：进出场更顺滑（不改变尺寸/层级） ---------- */
.modal-overlay.show { animation: fadeIn .18s var(--ease-out); }
.modal-overlay.show .modal { animation: modalPop .24s var(--ease-out); }
@keyframes modalPop { from { opacity: 0; transform: translateY(10px) scale(.985); } to { opacity: 1; transform: none; } }

/* ---------- 11. 徽标/标签：统一圆角与微阴影 ---------- */
.order-remark, .order-item-count, .part-expand-qty, .badge, .chip, .tag { font-variant-numeric: tabular-nums; }

/* ---------- 13. 滚动条：更纤细（WebKit） ---------- */
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--n-300); border-radius: 999px;
  border: 3px solid transparent; background-clip: content-box;
}
::-webkit-scrollbar-thumb:hover { background: var(--n-400); background-clip: content-box; }

/* ---------- 14. 降低动效偏好：全部关闭非必要动画 ---------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}

} /* /@media (max-width: 900px) —— #779-C 结束 */


/* ============================================================
 * #781 移动端专属层（★仅 ≤900px 生效，PC 端零影响）
 * ------------------------------------------------------------
 * ① 禁止页面级缩放 —— 配合 index.html 的 viewport meta（maximum-scale=1 /
 *    user-scalable=no）+ app.js 的 setupZoomGuard（iOS 手势兜底）。
 *    touch-action: pan-x pan-y 允许单指滚动但禁用双指捏合缩放；
 *    3D 查看器的画布自行声明 touch-action:none，交集后仍归 three.js 全权处理，
 *    因此「模型可以捏合缩放、页面不能缩放」——这正是期望的语义。
 *
 * ② 参考钉钉优化信息层次与视觉节奏（只做视觉，不改布局骨架）：
 *    - 浅灰页面底 + 纯白卡片 → 拉开层次（钉钉最标志性的一招，靠底色对比
 *      而不是重阴影，观感更干净）
 *    - 卡片 14px 大圆角 + 发丝描边，克制阴影
 *    - 明确层级：订单号 16px/700 主标题，客户名 12.5px 灰字副标题
 *    - 列表项 :active 背景变浅 → "点得动"的按压手感
 *    - 底部标签栏选中态加粗染色
 * 类名全部取自真实 DOM（#778/#779 已用 CDP 抓取核对过），不猜类名。
 * ============================================================ */
@media (max-width: 900px) {

  /* ---------- ① 禁止页面级缩放 ---------- */
  html, body {
    touch-action: pan-x pan-y;
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
  }
  /* 3D / 扫描建模画布：交回各自的交互逻辑（OrbitControls 双指缩放是合法功能） */
  .dxf3d-canvas, .dxf3d-canvas canvas, .dxf3d-canvas-wrap,
  .scan3d-canvas-wrap, .scan3d-canvas-wrap canvas, #scan3dCanvas { touch-action: none; }

  /* ---------- ② 钉钉式层次：浅灰底 + 纯白卡片 ---------- */
  :root {
    --bg-page: #f1f2f5;       /* 比 PC 的 #f8fafc 深一档，白卡片才"浮"得出来 */
    --dt-radius: 14px;
    --dt-hairline: #eceef2;   /* 发丝分割线，替代深色描边 */
    /* #784 页眉高度 + 间隙：弹层顶部必须让开这么多，否则会顶到页眉功能区 */
    --m-header-clear: 68px;
  }
  body { background: var(--bg-page); }

  /* ---------- 卡片：钉钉式白卡 ---------- */
  .order-card, .todo-item, .alert-item, .alert-order-card, .kpi-card {
    border-radius: var(--dt-radius);
    border-color: var(--dt-hairline);
    background: #fff;
    box-shadow: 0 1px 2px rgba(16,24,40,.04), 0 2px 10px rgba(16,24,40,.035);
  }
  .order-card:active, .todo-item:active, .alert-item:active { background: #fafbfc; }

  /* 卡片内呼吸：钉钉式舒展留白 */
  .order-card-top { padding: 13px 14px; gap: 9px; }
  .order-card-main { gap: 7px 9px; }

  /* ---------- 信息层级：订单号主标题 / 客户副标题 ---------- */
  .order-card .order-no { font-size: 16px; font-weight: 700; letter-spacing: -.2px; color: var(--n-900, #0f172a); }
  .order-card .order-customer { font-size: 12.5px; font-weight: 400; color: var(--n-500, #64748b); }
  .order-card .order-remark { font-size: 12px; color: var(--n-400, #94a3b8); }

  /* ---------- 「操作 N ▾」入口：钉钉式浅灰圆角条 ---------- */
  .order-card-actions .btn-act-toggle {
    min-height: 40px; border-radius: 10px;
    background: var(--n-50, #f8fafc);
    border: 1px solid var(--dt-hairline);
    color: var(--n-700, #334155);
    font-size: 13.5px;
  }
  .order-card-actions .btn-act-toggle:active { background: var(--n-100, #f1f5f9); }
  .order-card-actions.open .btn-act-toggle {
    background: var(--pri-50, #eff6ff);
    border-color: var(--pri-100, #dbeafe);
    color: var(--pri-700, #1d4ed8);
  }
  .order-card-actions .order-act-panel { margin-top: 8px; }

  /* ---------- 顶部栏：发丝线（钉钉导航栏观感） ----------
     必须显式关掉 #779-C 给 .topbar 加的 backdrop-filter，否则窄屏仍带毛玻璃
     ★ #828b：此处原为写死的 background:#fff，导致移动端顶栏不跟随主题（夜间仍是白条）。 */
  .topbar {
    background: var(--bg-surface);
    border-bottom: 1px solid var(--dt-hairline);
    box-shadow: none;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }

  /* ---------- 底部标签栏：选中态更清晰 ---------- */
  .mnav {
    background: #fff;                 /* 钉钉式不透明底栏（去掉毛玻璃以免滚动时透出内容） */
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    border-top: 1px solid var(--dt-hairline);
    box-shadow: 0 -2px 12px rgba(16,24,40,.05);
  }
  .mnav-item { min-height: 54px; gap: 3px; }
  /* ★ 与前述断点保持同一比例（原 21px 会覆盖前面的 18px，导致图标再次偏大） */
  .mnav-ico { font-size: 16px; }
  .mnav-item.active { color: var(--pri-600, #2563eb); }
  .mnav-item.active .mnav-txt { font-weight: 600; }
  .mnav-item:active { background: rgba(37,99,235,.05); }

  /* ---------- 统计卡：白卡化（钉钉首页数字卡） ---------- */
  .stats-bar { padding: 10px 12px 6px; gap: 8px; }
  .stats-bar .stat {
    background: #fff;
    border: 1px solid var(--dt-hairline);
    border-radius: 12px;
    box-shadow: 0 1px 2px rgba(16,24,40,.035);
    padding: 10px 13px;
  }

  /* ---------- 工具条：输入控件与按钮统一圆角与触控高度 ---------- */
  .toolbar .search-input, .toolbar .filter-select, .toolbar .filter-date, .toolbar .filter-input {
    border-radius: 10px; min-height: 40px;
  }
  .toolbar .btn { border-radius: 10px; min-height: 40px; }

  /* ---------- 抽屉与弹窗：圆角对齐 ---------- */
  .mdg-item { border-radius: 12px; }
  .mdg-item:active { background: var(--n-100, #f1f5f9); }
  .mdrawer { border-radius: 16px 16px 0 0; }
  .mdrawer-act { border-radius: 10px; }
  .modal { border-radius: 14px; }
}


/* ============================================================
 * #782 移动端 UI / 交互体验重构层
 * ------------------------------------------------------------
 * 三项诉求：
 *   ① 交互控件「可见性 / 可理解性」——典型问题是订单总览的日期筛选
 *      在手机上显示为两个完全空白的方框（空 <input type=date> 无任何文字，
 *      而其用途只写在 title 里，触屏没有 hover 所以看不到）。
 *      已在 HTML 给三处日期范围（订单/年包/采购）加上可见标题 .ffield-cap。
 *   ② 禁止页面左右横向移动（与微信一致）：页面级不得横向滚动/回弹，
 *      但内部横滑容器（统计卡 / 阶段条 / 表格）仍可独立横滑、不带动整页。
 *   ③ 弹窗不再几乎占满整屏：改为微信/钉钉式底部弹层（上圆角 + 拖拽条 +
 *      高度上限 ~82vh，内容区内部滚动，底部让出安全区）。
 *
 * ★ PC 端零影响的关键手法：包装层（.ffield / .ffield-row）在 ≥901px 用
 *   `display: contents` 使其**不产生盒子**，其子元素直接成为 .toolbar 的
 *   网格项 —— 与加包装之前的布局**逐项等价**；.ffield-cap 在 PC 直接隐藏。
 *   因此 HTML 结构变化不会改变 PC 的任何渲染结果。
 * ============================================================ */

/* ---------- PC / 平板（≥901px）：中性化包装层，隐藏移动端专用元素 ---------- */
@media (min-width: 901px) {
  .ffield, .ffield-row { display: contents; }
  .ffield-cap { display: none; }
  /* #783 移动端专用元素（筛选按钮 / 重置按钮）在 PC 一律不参与布局 */
  .m-only { display: none !important; }
  /* #783 筛选面板容器在 PC 不产生盒子 → 7 个筛选控件回到 .toolbar 顺序位置，
     与加容器之前逐项等价 */
  .filter-more { display: contents; }
}

@media (max-width: 900px) {

  /* ================= ① 控件可见性与可理解性 ================= */

  /* 日期范围：带标题的分组字段；恢复「至」分隔符（≤1024 断点原本把它隐藏了，
     导致两个空日期框相邻、语义完全丢失） */
  .ffield { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
  .ffield-range { grid-column: 1 / -1; }
  .ffield-cap {
    font-size: 11.5px; font-weight: 600; letter-spacing: .2px;
    color: var(--text-mute, #94a3b8);
    display: flex; align-items: center; gap: 4px;
  }
  .ffield-row { display: flex; align-items: center; gap: 8px; min-width: 0; }
  .toolbar .ffield-row .filter-date {
    flex: 1 1 0; width: auto; min-width: 0;
    min-height: 40px; border-radius: 10px;
  }
  /* 恢复「至」：用更高特异性压过 ≤1024 断点的 display:none */
  .toolbar .ffield .filter-date-sep {
    display: inline-block; flex: none;
    font-size: 12px; color: var(--text-mute, #94a3b8);
  }
  /* 空日期：虚线边框 + 浅底，明确表达「尚未设置」，与已填值状态区分 */
  .filter-date.is-empty {
    border-style: dashed;
    border-color: var(--n-300, #cbd5e1);
    background: var(--n-50, #f8fafc);
  }
  /* 所有筛选控件的可点区域与圆角统一（触控友好） */
  .toolbar .filter-select, .toolbar .search-input, .toolbar #pageSizeSelect,
  .toolbar #purchasePageSizeSelect, .toolbar .filter-input {
    min-height: 40px; border-radius: 10px;
  }
  /* 下拉控件统一给一个明确的「可展开」指示，避免与静态文字混淆 */
  .toolbar select, .toolbar .filter-select { appearance: none; -webkit-appearance: none;
    background-image: linear-gradient(45deg, transparent 50%, #94a3b8 50%),
                      linear-gradient(135deg, #94a3b8 50%, transparent 50%);
    background-position: calc(100% - 16px) 50%, calc(100% - 11px) 50%;
    background-size: 5px 5px, 5px 5px;
    background-repeat: no-repeat;
    padding-right: 30px;
  }

  /* ---------- #783 工具栏紧凑化：搜索 + 筛选入口两行，7 个筛选控件收进面板 ---------- */
  /* ≤1024 断点把 .toolbar 设成 grid；这里改回 flex 以便「按 order 分行」 */
  .toolbar { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
  .toolbar .search-input { flex: 1 1 100%; }
  .toolbar .btn-filter-toggle,
  .toolbar #btnExportOrders,
  .toolbar #btnNewOrder { flex: 1 1 auto; order: 1; min-height: 40px; }
  /* 筛选按钮：自包含视觉（勿依赖 .btn 基类底色），并带活动条件计数徽标 */
  .btn-filter-toggle {
    display: inline-flex; align-items: center; justify-content: center; gap: 6px;
    background: #fff; border: 1px solid var(--dt-hairline); color: var(--n-700, #334155);
    font-size: 13.5px; font-weight: 600;
  }
  .btn-filter-toggle:active { background: var(--n-50, #f8fafc); }
  .btn-filter-toggle .ft-ico { font-size: 14px; line-height: 1; }
  /* 计数徽标：默认不占位；用 class 控制显示（勿用 hidden 属性 —— 见铁律 #6） */
  .btn-filter-toggle .ft-num {
    display: none; min-width: 17px; height: 17px; padding: 0 5px;
    border-radius: 9px; background: var(--pri-600, #2563eb); color: #fff;
    font-size: 10.5px; font-weight: 700; line-height: 17px; text-align: center;
  }
  .btn-filter-toggle.has-active {
    background: var(--pri-50, #eff6ff);
    border-color: var(--pri-200, #bfdbfe);
    color: var(--pri-700, #1d4ed8);
  }
  .btn-filter-toggle.has-active .ft-num { display: inline-block; }
  .btn-filter-toggle .ft-caret { font-size: 10px; transition: transform .18s ease; }
  .btn-filter-toggle.open .ft-caret { transform: rotate(180deg); }

  /* 筛选面板：默认收起；展开为白卡两列网格 */
  .filter-more { display: none; flex: 1 1 100%; order: 2; }
  .filter-more.open {
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px;
    padding: 12px; border-radius: 14px;
    background: #fff; border: 1px solid var(--dt-hairline);
    box-shadow: 0 1px 2px rgba(16,24,40,.04);
  }
  .filter-more .ffield-range,
  .filter-more .fm-reset { grid-column: 1 / -1; }
  .filter-more .fm-reset {
    min-height: 40px; border-radius: 10px;
    color: var(--n-600, #475569); border: 1px solid var(--dt-hairline);
    background: var(--n-50, #f8fafc); font-size: 13px;
  }
  .filter-more .fm-reset:active { background: var(--n-100, #f1f5f9); }

  /* ================= ② 禁止页面左右横向移动（微信式） ================= */

  /* overflow-x: clip 不产生滚动容器 → 纵向滚动与 position:sticky 均不受影响，
     同时禁止页面被横向拖动（含回弹）。勿用 hidden（会破坏 sticky）。 */
  html { overflow-x: clip; }
  body { overflow-x: clip; overscroll-behavior-x: none; }
  /* 内部横滑容器：可以自己横滑，但不把滚动链传给页面 */
  .stats-bar, .stage-dots, .table-wrap, .data-table-wrap, .admin-panel-tabs,
  .mdrawer-grid, .msg-center-tabs, .pagination, .tabs {
    overscroll-behavior-x: contain;
    touch-action: pan-x pan-y;
  }
  /* 兜底：任何板块都不允许把自己的宽度顶出视口 */
  .content, .view, .toolbar, .orders-list, .todos-list, .alerts-list { max-width: 100%; }

  /* ================= ③ 弹窗 → 底部弹层（不再占满全屏） ================= */

  .modal-overlay {
    align-items: flex-end;
    justify-content: center;
    padding: 0;
    /* 弹层必须盖住底部标签栏(200)与「更多」抽屉(300/310)，否则导航栏会压在
       弹层上方、且用户在弹窗打开时还能误点导航（#782 实测截图发现） */
    z-index: 400;
  }
  .modal {
    width: 100%;
    max-width: 100%;
    /* #784 修复「弹窗与页眉重叠、内容显示不完整」：
       ① 高度改用**相对遮罩的百分比**，不再用 vh —— 手机上 100vh 指的是
          「URL 栏隐藏后」的最大视口，实际可见高度往往更小，于是 82vh 的底部弹层
          顶部会越过可见区顶端、被页眉压住（用户反馈的现象）。
          遮罩是 position:fixed;inset:0，其高度就是真实视口，百分比最可靠。
       ② 再显式减去页眉高度，短视口 / 键盘弹出时也不会顶到页眉。 */
    max-height: min(82%, calc(100% - var(--m-header-clear, 68px)));
    border-radius: 18px 18px 0 0;
    margin: 0;
    /* #802e 与全局一致：滚动交给 .modal-body，避免 sticky 的 .modal-foot
       吸底时盖住输入框（详见全局 .modal 注释） */
    overflow: hidden;
    padding-bottom: var(--sys-bottom, env(safe-area-inset-bottom, 0px));
    animation: sheetUp .26s cubic-bezier(.22,.61,.36,1);
  }
  @keyframes sheetUp {
    from { transform: translateY(24px); opacity: 0; }
    to   { transform: translateY(0);    opacity: 1; }
  }
  /* 顶部拖拽提示条（微信/钉钉底部弹层的标志性元素） */
  .modal-head { padding-top: 18px; border-radius: 0; position: sticky; top: 0; }
  .modal-head::before {
    content: ''; position: absolute; top: 7px; left: 50%; transform: translateX(-50%);
    width: 38px; height: 4px; border-radius: 999px;
    background: var(--n-300, #cbd5e1);
  }
  .modal-head h3 { font-size: 16.5px; }
  .modal-body { padding: 14px 16px; }
  .modal-foot {
    border-radius: 0;
    padding: 12px 16px calc(12px + var(--sys-bottom, env(safe-area-inset-bottom, 0px)));
  }
  .modal-lg { max-width: 100%; }

}


/* ============================================================
 * #784 会话聊天 → 微信风格（★仅 ≤900px 生效，PC 端零影响）
 * ------------------------------------------------------------
 * 参照微信聊天界面的视觉语言：
 *   - 聊天底 #EDEDED；我方气泡 #95EC69（微信绿），对方白色
 *   - 气泡圆角 6px 且带一个指向头像的小三角
 *   - 头像为「方形 + 5px 圆角」（微信不是圆形），40px，置于气泡之外
 *   - 对方昵称显示在气泡上方（灰 12px）；自己的气泡不显示「我」
 *   - 不在气泡旁显示时间，改为**相邻消息间隔 >5 分钟**时插一条居中灰字时间
 *     （时间分隔由 app.js 的 chatTimeSepHtml 生成，仅窄屏插入 → PC 不变）
 *   - 底部输入栏白底：表情/截图/附件图标 + 圆角输入框 + 微信绿「发送」
 * 说明：#chatBoxBody 带内联样式（min-height:340px / max-height:56vh / background），
 *      故此处必须用 !important 覆盖，让消息区撑满弹层并在内部滚动。
 * ============================================================ */
@media (max-width: 900px) {

  /* ---------- 聊天弹层：会话是独立界面，给足高度（顶部仍让开页眉） ---------- */
  #modalChatBox .modal {
    height: 92%;
    max-height: calc(100% - var(--m-header-clear, 68px));
    display: flex;
    flex-direction: column;
    background: #ededed;
    overflow: hidden;            /* 由内部消息区滚动，弹层本身不滚 */
  }
  /* 顶栏：微信式浅灰导航条，标题居中 */
  #modalChatBox .modal-head {
    flex: none;
    justify-content: center;
    position: relative;
    padding: 12px 52px;
    background: #ededed;
    border-bottom: 1px solid #dcdcdc;
    box-shadow: none;
    border-radius: 0;
  }
  #modalChatBox .modal-head h3 { font-size: 16px; font-weight: 600; color: #191919; }
  #modalChatBox .modal-head::before { display: none; }   /* 不要底部弹层的拖拽条 */
  #modalChatBox .modal-close {
    position: absolute; right: 10px; top: 50%; transform: translateY(-50%);
    width: 30px; height: 30px; font-size: 14px;
    background: transparent; color: #576b95;
  }

  /* ---------- 消息区：撑满并在内部滚动 ---------- */
  #modalChatBox #chatBoxBody {
    flex: 1 1 auto;
    min-height: 0 !important;
    max-height: none !important;
    background: #ededed !important;
    padding: 12px 12px 10px;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-y: contain;
  }

  /* ---------- 消息气泡 ---------- */
  #modalChatBox .msg-bubble-list { gap: 16px; }
  #modalChatBox .msg-bubble { gap: 9px; align-items: flex-start; }

  /* 头像：微信是方形 + 小圆角 */
  #modalChatBox .msg-avatar {
    width: 40px; height: 40px; border-radius: 5px;
    font-size: 15px; flex: none;
    background: #7d8a99; color: #fff;
  }
  #modalChatBox .msg-bubble-main { max-width: 72%; }

  /* 昵称：对方显示在气泡上方（微信群里就是这么显示）；自己的隐藏 */
  #modalChatBox .msg-bubble-head { margin-bottom: 4px; padding: 0 2px; gap: 6px; }
  #modalChatBox .msg-bubble-name { font-size: 12px; color: #7d7d7d; font-weight: 400; }
  #modalChatBox .msg-bubble-time { display: none; }      /* 改由居中时间分隔承载 */
  #modalChatBox .mine .msg-bubble-head { display: none; }

  /* 气泡本体 */
  #modalChatBox .msg-bubble-content {
    position: relative;
    background: #fff; color: #191919;
    border-radius: 6px;
    padding: 9px 12px;
    font-size: 15px; line-height: 1.45;
    word-break: break-word;
    box-shadow: none;
  }
  #modalChatBox .mine .msg-bubble-content { background: #95ec69; color: #191919; }

  /* 指向头像的小三角（微信气泡的标志） */
  #modalChatBox .msg-bubble-content::before {
    content: ''; position: absolute; top: 12px; left: -5px;
    width: 0; height: 0;
    border-style: solid; border-width: 5px 6px 5px 0;
    border-color: transparent #fff transparent transparent;
  }
  #modalChatBox .mine .msg-bubble-content::before {
    left: auto; right: -5px;
    border-width: 5px 0 5px 6px;
    border-color: transparent transparent transparent #95ec69;
  }

  /* 文件 / 图片：卡片自带白底，容器不要气泡与三角 */
  #modalChatBox .msg-bubble-content.chat-file-content {
    background: transparent !important; padding: 0 !important;
  }
  #modalChatBox .msg-bubble-content.chat-file-content::before { display: none; }
  #modalChatBox .chat-file-card { background: #fff; border-radius: 6px; }
  #modalChatBox .chat-img, #modalChatBox .chat-img-wrap { border-radius: 6px; }
  /* 纯表情消息：微信里大表情不带气泡底 */
  #modalChatBox .msg-bubble-content.chat-emoji-only {
    background: transparent !important; padding: 0 !important;
    font-size: 2.1rem !important; line-height: 1.3 !important;
  }
  #modalChatBox .msg-bubble-content.chat-emoji-only::before { display: none; }

  /* 气泡下的操作按钮：弱化为半透明白，不与气泡抢眼 */
  #modalChatBox .msg-bubble-actions { margin-top: 4px; gap: 5px; }
  #modalChatBox .msg-bubble-actions .btn {
    min-height: 28px; font-size: 12px;
    background: rgba(255,255,255,.72); border-color: rgba(0,0,0,.06); color: #4b5563;
  }

  /* ---------- 时间分隔（微信居中灰字） ---------- */
  #modalChatBox .chat-time-sep { text-align: center; margin: 4px 0 0; }
  #modalChatBox .chat-time-sep span {
    display: inline-block;
    font-size: 12px; color: #9a9a9a;
    background: rgba(0,0,0,.055);
    padding: 2px 7px; border-radius: 4px;
  }

  /* ---------- 底部输入栏（微信白底 + 圆角输入 + 绿发送） ---------- */
  #modalChatBox .chat-input-wrap {
    flex: none;
    background: #f7f7f7;
    border-top: 1px solid #dcdcdc;
    border-radius: 0;
    padding: 8px 10px calc(8px + var(--sys-bottom, env(safe-area-inset-bottom, 0px)));
    gap: 6px;
  }
  #modalChatBox .chat-input-bar {
    background: #fff; border-radius: 6px;
    padding: 3px 6px; gap: 2px;
  }
  #modalChatBox .chat-bar-btn {
    background: transparent !important; border: none !important;
    font-size: 19px; padding: 5px 6px !important; min-height: 34px;
    color: #4b5563;
  }
  #modalChatBox #chatInput {
    border: none !important; background: transparent !important;
    box-shadow: none !important; outline: none !important;
    font-size: 16px !important;            /* 防 iOS 聚焦时自动放大 */
    padding: 6px 4px !important; min-height: 34px !important;
  }
  #modalChatBox #btnChatSend {
    background: #07c160 !important; border-color: #07c160 !important;
    color: #fff !important; border-radius: 6px !important;
    min-height: 34px; padding: 0 13px !important; font-size: 14px;
  }
  #modalChatBox #btnChatSend:active { background: #06ad56 !important; }
  /* 待发送图片条：白底卡片 */
  #modalChatBox .chat-pending-imgs { padding: 2px 0 6px; }
  #modalChatBox .chat-pending-thumb { border-radius: 6px; }

  /* ---------- 会话列表也微信化 ---------- */
  .chat-conv { border-radius: 12px; }
  .chat-conv-avatar {
    width: 44px; height: 44px; border-radius: 5px;
    font-size: 17px; background: #7d8a99; color: #fff;
  }
  .chat-conv-title { font-size: 15px; }
  .chat-conv-last { font-size: 12.5px; }
}


/* ============================================================
 * #785 移动端「可折叠尽量折叠」（★仅 ≤900px）
 * ------------------------------------------------------------
 * 实测各版块首屏上部占高：采购 ≈756px、年包 ≈673px、文件备份 ≈465px、
 * 仓库 ≈396px —— 筛选控件竖排把首屏全占了（订单总览经 #783 已降到 88px）。
 * 这里把非订单版块的工具栏也折叠：只留前 2 个筛选控件 +
 * 一个「更多筛选 N ▾」开关，其余收进折叠区。
 * 折叠结构由 app.js 的 syncAutoToolbarFold() 仅在窄屏创建，PC 端零影响。
 * ============================================================ */
@media (max-width: 900px) {

  /* 折叠态：仅在「已折叠且未展开」时隐藏 → 展开时规则不匹配，
     元素保持各自原本的 display，无需 revert/important */
  .toolbar.tb-folded:not(.tb-fold-open) .tb-extra { display: none; }

  /* 「更多筛选 N ▾」开关：与订单总览的「筛选 N ▾」视觉一致 */
  .tb-fold-btn {
    display: inline-flex; align-items: center; justify-content: center; gap: 6px;
    background: #fff; border: 1px solid var(--dt-hairline); color: var(--n-700, #334155);
    font-size: 13.5px; font-weight: 600; border-radius: 10px; min-height: 40px;
  }
  .tb-fold-btn .ft-ico { font-size: 14px; line-height: 1; }
  .tb-fold-btn .ft-num {
    display: inline-block; min-width: 17px; height: 17px; padding: 0 5px;
    border-radius: 9px; background: var(--pri-600, #2563eb); color: #fff;
    font-size: 10.5px; font-weight: 700; line-height: 17px; text-align: center;
  }
  .tb-fold-btn .ft-caret { font-size: 10px; transition: transform .18s ease; }
  .tb-fold-btn.open .ft-caret { transform: rotate(180deg); }
  .tb-fold-btn.open {
    background: var(--pri-50, #eff6ff);
    border-color: var(--pri-200, #bfdbfe);
    color: var(--pri-700, #1d4ed8);
  }
  .tb-fold-btn:active { background: var(--n-50, #f8fafc); }

  /* 文件备份头部：4 个操作按钮在手机上会换行成 3 行（≈150px）→ 改单行横滑，
     操作一个不少，但只占一行（内联样式带 flex-wrap，故需 !important） */
  .vault-head-actions, .head-actions {
    flex-wrap: nowrap !important;
    overflow-x: auto; max-width: 100%;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
    scrollbar-width: none; padding-bottom: 2px;
  }
  .vault-head-actions::-webkit-scrollbar, .head-actions::-webkit-scrollbar { display: none; }
  .vault-head-actions .btn { flex: 0 0 auto; white-space: nowrap; }
  .vault-head { padding-bottom: 10px; }
  .vault-stats { padding: 0 2px 6px; }

  /* 版块说明文字：长句收成一行，标题已足够表意（保留信息，不再占两行） */
  .alerts-header { padding: 12px 14px 8px; margin-bottom: 8px; }
  .alerts-header p {
    display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical;
    overflow: hidden; font-size: 12px; margin-top: 2px; line-height: 1.4;
  }
}


/* ============================================================
 * #786 移动端三项优化（★整层 @media (max-width: 900px) 包裹，PC 端零影响）
 * ------------------------------------------------------------
 * ① 会话聊天：输入框偏小 → 加高到 40px；参考微信，除表情外（截图/文件）
 *    一律收进「＋」号工具面板；输入框排到表情之前（微信顺序）。
 * ② 订单总览：卡片压成严格两行 —— 第 1 行「订单号 · 客户名 · N 个零件 ›」，
 *    第 2 行「状态徽章（横向可滑）」。点击卡片把 .oc-detail（备注 + 操作按钮
 *    + 阶段进度点 + 零件明细）整体搬进 #modalOrderSheet 弹层展示。
 * ③ 所有弹窗禁止左右移动：弹层/遮罩一律横向裁剪（overflow-x: clip 不产生
 *    滚动容器 → 纵向滚动与吸顶头部不受影响），并关掉横向回弹链。
 * ------------------------------------------------------------
 * PC 中性保证：本层全部为 @media 包裹；#786 的 DOM 变化只由 app.js 在
 * isMobileNav() 为真时生成（PC 走原分支，产出 HTML 逐字节不变）。
 * ============================================================ */
@media (max-width: 900px) {

  /* ================= ① 会话聊天：微信式输入栏 ================= */
  #modalChatBox .chat-input-bar { align-items: center; padding: 4px 8px; gap: 4px; }
  /* ★关键：≤768 断点的 .modal-foot .btn{flex:1 1 auto} 会让图标按钮一起伸展，
     把输入框挤到只剩 ~74px（这正是「输入框太小」的根因）。
     这里把图标按钮改为不伸展，剩余宽度全部让给输入框（内联 flex:1 需 !important）。 */
  #modalChatBox .chat-input-bar .chat-bar-btn { flex: 0 0 auto; }
  #modalChatBox .chat-input-bar #chatInput { flex: 1 1 auto !important; }
  /* 输入框排到表情/＋ 之前（微信顺序：[输入框] 😊 ＋ [发送]），并加高 */
  #modalChatBox #chatInput { order: -1; min-height: 40px !important; padding: 8px 6px !important; }
  #modalChatBox .chat-bar-btn { min-height: 40px; font-size: 20px; padding: 6px 7px !important; }
  #modalChatBox #btnChatPlus { font-size: 22px; }
  #modalChatBox #btnChatPlus.active { color: #07c160; }
  #modalChatBox #btnChatSend { min-height: 40px; padding: 0 14px !important; }

  /* 「＋」工具面板（微信式：白底卡片 + 图标 + 文字） */
  #modalChatBox .chat-tool-panel {
    background: #fff; border-radius: 8px; margin-top: 8px;
    padding: 14px 10px 10px;
    grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px 8px;
  }
  #modalChatBox .chat-tool-panel .chat-bar-btn {
    display: flex !important; flex-direction: column; align-items: center; justify-content: center;
    gap: 6px; width: 100%; min-height: 66px;
    background: #f7f7f7 !important; border: 1px solid #ececec !important;
    border-radius: 10px !important; font-size: 24px !important; line-height: 1;
    padding: 8px 0 !important;
  }
  #modalChatBox .chat-tool-panel .chat-bar-btn::after { font-size: 12px; color: #576b95; font-weight: 400; }
  #modalChatBox .chat-tool-panel #btnChatShot::after { content: '截图'; }
  #modalChatBox .chat-tool-panel #btnChatFile::after { content: '文件'; }

  /* ================= ② 订单卡：严格两行 ================= */
  /* padding 归零：≤768 断点给 .order-card 设了 14px 上下内边距（额外 28px 高度），
     两行卡改由 .oc-l1/.oc-l2 各自控制内边距 */
  .order-card-2l { padding: 0; cursor: pointer; }
  .order-card-2l .oc-l1 {
    display: flex; align-items: center; gap: 8px;
    padding: 13px 14px 6px; min-width: 0;
  }
  .order-card-2l .oc-l1 .order-check,
  .order-card-2l .oc-l1 .order-no,
  .order-card-2l .oc-l1 .oc-count,
  .order-card-2l .oc-l1 .oc-right,
  .order-card-2l .oc-l1 .oc-caret { flex: none; }
  .order-card-2l .oc-l1 .order-customer {
    flex: 1 1 auto; min-width: 0;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .order-card-2l .oc-l1 .oc-count,
  .order-card-2l .oc-l1 .oc-right { font-size: 12px; color: var(--n-500, #64748b); }
  .order-card-2l .oc-l1 .oc-caret { color: var(--n-300, #cbd5e1); font-size: 18px; line-height: 1; }
  /* 第 2 行：状态徽章横向可滑（信息一条不丢，但只占一行高度） */
  .order-card-2l .oc-l2 {
    display: flex; align-items: center; gap: 6px;
    padding: 0 14px 12px; min-width: 0;
    overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: none;
  }
  .order-card-2l .oc-l2::-webkit-scrollbar { display: none; }
  .order-card-2l .oc-l2 > * { flex: 0 0 auto; }
  .order-card-2l .oc-l2-empty { font-size: 12px; color: var(--n-400, #94a3b8); }
  /* 详情区（操作按钮 + 阶段进度 + 零件明细）：卡片内隐藏，点击后搬进弹层 */
  .order-card-2l .oc-detail { display: none; }

  /* 详情弹层：还原形态（高度自适应内容，避免内容少时留一大片空白 —— #784 用户明确反馈过） */
  #modalOrderSheet .modal {
    max-height: calc(100% - var(--m-header-clear, 68px));
    display: flex; flex-direction: column;
    background: #fff; overflow: hidden;
  }
  #modalOrderSheet .modal-head { flex: none; }
  #modalOrderSheet .modal-body {
    flex: 1 1 auto; min-height: 0;
    overflow-y: auto; -webkit-overflow-scrolling: touch;
    overscroll-behavior-y: contain;
    padding-bottom: calc(20px + var(--sys-bottom, env(safe-area-inset-bottom, 0px)));
  }
  #modalOrderSheet .oc-detail { display: block; }
  #modalOrderSheet .oc-remark {
    font-size: 12.5px; color: var(--n-600, #475569); background: #f8fafc;
    border-radius: 10px; padding: 8px 10px; margin-bottom: 10px; line-height: 1.5;
  }
  /* 操作按钮在弹层内直接平铺成两列（不必再点一次「操作 N ▾」）
     #787：采购/年包/仓库的卡片是「无面板的平铺按钮」→ 用 display:contents
     让 .order-act-panel 里的按钮与直接子按钮统一参与同一个网格 */
  #modalOrderSheet .order-card-actions {
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 8px; width: 100%; position: static; margin-bottom: 12px;
  }
  #modalOrderSheet .order-card-actions .btn-act-toggle { display: none; }
  #modalOrderSheet .order-card-actions .order-act-panel { display: contents; }
  #modalOrderSheet .order-card-actions .btn {
    width: 100%; min-height: 40px; justify-content: center;
  }
  #modalOrderSheet .order-card-actions .btn:last-child:nth-child(odd) {
    grid-column: 1 / -1;
  }
  #modalOrderSheet .stage-dots { border-radius: 0; }
  /* 详情视图里阶段进度 / 零件芯片改为换行铺满 —— 弹层内不再需要横向滑动 */
  #modalOrderSheet .stage-dots { flex-wrap: wrap; overflow-x: visible; row-gap: 8px; }
  #modalOrderSheet .order-part-chips { flex-wrap: wrap; overflow: visible; }
  #modalOrderSheet .order-parts-expand {
    margin-top: 8px; border: 1px solid var(--dt-hairline);
    border-radius: 12px; overflow: hidden;
  }

  /* ================= ③ 所有弹窗禁止左右移动 ================= */
  /* overflow-x: clip 不产生滚动容器 → 纵向滚动 / position: sticky 不受影响，
     同时彻底禁止弹层被横向拖动（含回弹）。勿用 hidden（会产生滚动容器）。 */
  .modal-overlay { overflow-x: clip; overscroll-behavior-x: none; }
  .modal { overflow-x: clip; max-width: 100%; }
  .modal-body, .modal-head, .modal-foot { overscroll-behavior-x: none; }
  .modal-body { overflow-x: clip; }
}

/* PC（≥901px）：#786 移动端专有元素一律不参与布局（保证 PC 与改动前完全一致） */
@media (min-width: 901px) {
  .m-chat-plus { display: none !important; }
  .chat-tool-panel { display: none !important; }
}


/* ============================================================
 * #787 移动端三项优化（★整层 @media (max-width: 900px) 包裹，PC 端零影响）
 * ------------------------------------------------------------
 * ① 登录页专属 UI 与背景：竖版专属背景图 + 品牌头部 + 底部圆角白卡
 * ② 采购报销 / 年包订单 / 仓库管理 三版块卡片统一「最多两行」，
 *    其余（备注 / 徽章 / 操作 / 元信息 / 明细）一律进 #modalOrderSheet 详情弹层
 * ③ 会话聊天「＋」面板增加 相册 / 拍摄（微信式）
 * ------------------------------------------------------------
 * PC 中性：本层全部为 @media 包裹；DOM 变化只由 app.js 在 isMobileNav() 为真时生成，
 * PC 走原分支，产出 HTML 逐字节不变。
 * ============================================================ */
@media (max-width: 900px) {

  /* ================= ① 登录页专属 UI + 背景 ================= */
  .login-overlay {
    flex-direction: column;
    background:
      radial-gradient(900px 420px at 85% 0%, rgba(56,189,248,.16), transparent 62%),
      radial-gradient(760px 420px at 0% 100%, rgba(79,70,229,.14), transparent 62%),
      linear-gradient(180deg, #eef3f9 0%, #e6edf6 45%, #f3f7fc 100%);
  }
  .login-cover { display: none; }            /* 窄屏改用专属竖版背景，不再用桌面封面 */
  .login-cover-corner { display: none; }

  .login-m-hero {
    position: relative; flex: 1 1 auto; min-height: 0; overflow: hidden;
    background-color: #d3dde9;               /* 与图片底边同色 → 余量无痕 */
    background-image: url("/images/login-bg-m.jpg");
    background-repeat: no-repeat;
    background-position: top center;
    background-size: 100% auto;
  }
  .login-m-hero .lmh-grid {
    position: absolute; inset: 0; pointer-events: none;
    background-image:
      linear-gradient(rgba(100,130,170,.07) 1px, transparent 1px),
      linear-gradient(90deg, rgba(100,130,170,.07) 1px, transparent 1px);
    background-size: 30px 30px;
    -webkit-mask-image: linear-gradient(to bottom, #000 0%, rgba(0,0,0,.25) 70%, transparent 100%);
    mask-image: linear-gradient(to bottom, #000 0%, rgba(0,0,0,.25) 70%, transparent 100%);
  }
  .login-m-hero .lmh-body {
    position: relative; z-index: 2;
    padding: calc(20px + env(safe-area-inset-top, 0px)) 22px 0;
    display: flex; flex-direction: column; gap: 4px;
  }
  .lmh-brand { display: flex; align-items: center; gap: 8px; }
  .lmh-mark {
    width: 30px; height: 30px; border-radius: 10px; flex: none;
    display: inline-flex; align-items: center; justify-content: center;
    background: linear-gradient(135deg, #2563eb, #4f46e5 55%, #7c3aed);
    color: #fff; font-size: 15px;
    box-shadow: 0 4px 14px rgba(79,70,229,.32);
  }
  .lmh-name { font-size: 14px; font-weight: 700; color: #1e293b; letter-spacing: .5px; }
  .lmh-title { font-size: 24px; font-weight: 800; color: #0f172a; margin: 8px 0 0; letter-spacing: .5px; }
  .lmh-sub { font-size: 13px; color: #5b6b80; margin: 2px 0 0; }
  .lmh-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
  .lmh-tags span {
    font-size: 11px; color: #31465f; background: rgba(255,255,255,.72);
    border: 1px solid rgba(148,163,184,.32); border-radius: 999px;
    padding: 3px 9px; -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
  }

  /* 表单卡片：底部圆角白卡压住背景，形成清晰主次 */
  .login-panel {
    position: relative; z-index: 3; flex: 0 1 auto;
    width: 100%; max-width: 100%; height: auto; min-height: 0;
    max-height: 78%; margin: 0; border-left: 0;
    border-radius: 22px 22px 0 0;
    background: #fff;
    box-shadow: 0 -10px 34px rgba(15,23,42,.16);
    padding: 22px 20px calc(62px + var(--sys-bottom, env(safe-area-inset-bottom, 0px)));
    justify-content: flex-start;
    overscroll-behavior: contain;
  }
  .login-panel .login-brand { display: none; }        /* 头部已有品牌，避免重复 */
  .login-panel h3 { font-size: 19px; margin: 0 0 2px; }
  .login-panel .login-sub { font-size: 12.5px; margin: 0 0 18px; }
  .login-field { margin-bottom: 14px; }
  .login-field label { font-size: 12.5px; }
  .login-field .login-input-wrap { min-height: 50px; border-radius: 12px; }
  .login-field .login-input-wrap input,
  .login-field input { font-size: 16px !important; }   /* 16px 防 iOS 聚焦自动放大 */
  /* 输入框撑满 50px 外壳：真正的可点区域 = 外壳高度（实测内层只有 42px）。
     外壳是 flex 且高度由 min-height 决定 → 百分比高度解析成 auto，
     必须用 align-self:stretch（拉伸到容器「已用」交叉尺寸）才生效。 */
  .login-field .login-input-wrap input { height: auto; min-height: 0; align-self: stretch; }
  .login-remember { font-size: 13px; margin: 2px 0 14px; }
  .login-remember input[type="checkbox"] { width: 18px; height: 18px; }
  .login-error { font-size: 12.5px; min-height: 18px; margin-bottom: 8px; }
  .login-btn { min-height: 50px; font-size: 16px; border-radius: 12px; }
  /* 备案信息并入白卡底部，不再是压在背景上的深色条 */
  .login-footer {
    position: absolute; left: 0; right: 0; bottom: 0; z-index: 6;
    background: #fff; border-top: 1px solid var(--dt-hairline, #eceef2);
    padding: 8px 12px calc(8px + var(--sys-bottom, env(safe-area-inset-bottom, 0px)));
    font-size: 11.5px; color: #94a3b8; gap: 10px;
  }
  .login-footer a { color: #94a3b8; }
  .login-footer a:hover { color: #2563eb; text-decoration: none; }
  .login-footer-sep { color: #cbd5e1; }

  /* ================= ② 三版块两行卡补充样式 ================= */
  .order-card-2l .oc-l1 input[type="checkbox"] {
    width: 17px; height: 17px; flex: none; margin: 0 2px 0 0;
    accent-color: var(--accent, #2563eb);
  }
  .order-card-2l .oc-l1 .oc-spec { color: var(--n-400, #94a3b8); font-size: 12px; }
  .order-card-2l .oc-urgent { border-color: #e5484d; }
  .order-card-2l .oc-meta { font-size: 12px; color: var(--n-400, #94a3b8); margin: 8px 0 0; }
  .order-card-2l .oc-remark b { color: var(--n-700, #334155); }

  /* ================= ③ 聊天「＋」面板：相册 / 拍摄 ================= */
  #modalChatBox .chat-tool-panel #btnChatAlbum::after { content: '相册'; }
  #modalChatBox .chat-tool-panel #btnChatCamera::after { content: '拍摄'; }
}

/* PC（≥901px）：#787 移动端专有元素一律不参与布局（保证 PC 与改动前完全一致） */
@media (min-width: 901px) {
  .login-m-hero { display: none !important; }
}


/* ============================================================
 * #788 移动端四项优化（★整层 @media (max-width: 900px) 包裹，PC 端零影响）
 * ------------------------------------------------------------
 * ① 会话聊天左右对称：我方头像原来离屏幕右边 93px、左侧只有 12px
 * ② 日期类控件防「UA 固有宽度」顶出容器 + 320px 极窄屏两行卡收官
 * ③ 新增采购申请弹窗：明细行改「明细卡」（标签 + 两列网格），底栏按钮重排
 * ④ 采购单警告 / 文件备份 两行卡补充样式
 * ============================================================ */
@media (max-width: 900px) {

  /* ================= ① 聊天左右对称 ================= */
  /* 根因：.chat-body .msg-bubble{max-width:78%} 把「整行」限制成 78% 宽，
     行内 row-reverse 后我方头像只能靠在这 78% 的右边缘 → 距屏幕右边 = 22% + padding。
     行必须铺满，宽度限制交给 .msg-bubble-main（它已有 max-width:72%）。 */
  #modalChatBox .msg-bubble { max-width: 100%; }
  #modalChatBox .msg-bubble > .msg-avatar { flex: none; }

  /* ================= ② 日期控件防溢出 + 极窄屏收紧 ================= */
  /* 部分国产内核（X5/Quark 等）与 iOS 会给 date/month/time 一个「固有最小宽度」，
     窄屏下会顶出容器 → 显式放开收缩并约束内部 shadow DOM。 */
  .modal input[type="date"], .modal input[type="month"], .modal input[type="week"],
  .modal input[type="time"], .modal input[type="datetime-local"] {
    min-width: 0; max-width: 100%; box-sizing: border-box;
    /* overflow:hidden 兜底：即使某些内核让内层日期部件画到框外，也不会顶出屏幕 */
    overflow: hidden;
    /* ⚠ #789 回滚：这里原本还有一条 `width: 100%`，它会**越过 .form-row 的作用范围**，
       把「非表单行」布局里的日期控件也强制撑满整行 —— 实测 #ledgerFrom/#ledgerTo
       （台账筛选行 display:flex;flex-wrap:wrap 的内容自适应 flex 项）被撑成 358px
       （= 整行宽），于是「从 [日期] 至 [日期] 🔍 📥」从一行紧凑排列退化成每项独占一行。
       宽度策略交回给各自的既有规则：
         · .form-row input { width:100% }   → 表单行内仍是整行宽（不变）
         · .filter-date { flex:1 1 0 }      → 工具栏日期范围（不变）
         · 台账等 flex 行                → 恢复内容自适应（本次修复） */
  }
  /* 表单行自身也不许被顶宽（flex/grid 子项 min-width:auto 的老问题） */
  .modal .form-row { min-width: 0; max-width: 100%; }
  /* ⚠ 含 ::-webkit-* 的选择器必须单独成规则：选择器列表里只要有一个浏览器不认识，
     整条规则会被整段丢弃。 */
  .modal input[type="date"]::-webkit-datetime-edit { min-width: 0; padding: 0; }
  .modal input[type="date"]::-webkit-datetime-edit-fields-wrapper { min-width: 0; padding: 0; }
  .modal input[type="date"]::-webkit-date-and-time-value { min-width: 0; text-align: left; }
  .modal input[type="date"]::-webkit-calendar-picker-indicator { margin-left: 0; padding: 0; }
  .modal input[type="month"]::-webkit-datetime-edit { min-width: 0; padding: 0; }
  .modal input[type="month"]::-webkit-calendar-picker-indicator { margin-left: 0; padding: 0; }

  /* 各流程计划完成天数：说明收成顶部一行（JS 侧已去掉逐行重复），每行只留「天」 */
  .stage-days-hint { font-size: 12px; color: var(--n-500, #64748b); margin: 0 0 8px; line-height: 1.5; }
  .stage-days-unit { font-size: 12px; color: var(--n-500, #64748b); flex: none; }
  #orderStageDays .stage-days-row { gap: 10px !important; margin-bottom: 8px !important; }
  #orderStageDays .stage-days-row label { min-width: 88px !important; font-size: 13px; }
  #orderStageDays .stage-days-row input { width: 84px !important; text-align: center; min-height: 44px; font-size: 16px; }

  /* 320px 极窄屏：两行卡的右侧信息位允许收缩截断，保证 › 提示不被挤出（审计实测溢出） */
  .order-card-2l .oc-l1 { overflow: hidden; }
  .order-card-2l .oc-l1 .oc-right {
    flex: 0 1 auto; min-width: 0;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }

  /* ================= ③ 新增采购申请：明细卡 + 底栏重排 ================= */
  #modalPurchaseCreate .form-section-title { margin: 16px 0 8px; }
  #modalPurchaseCreate #btnAddPoItem {
    width: 100%; min-height: 44px; border-radius: 10px;
    margin-bottom: 12px !important;
    background: var(--n-50, #f8fafc); border: 1px dashed var(--dt-hairline, #dfe3ea);
    color: var(--pri-700, #1d4ed8); font-weight: 600;
  }
  /* 明细卡（.po-item-row / .po-it-*）的完整样式见文件末尾「#791」全局段 ——
     那里同时给出 PC 6 列与窄屏 2 列，放在末尾是为了让窄屏覆盖能按源码顺序生效。 */
  /* 底栏：主操作整行，取消 / 存为草稿 并列一行 */
  #modalPurchaseCreate .modal-foot { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
  #modalPurchaseCreate .modal-foot #btnSavePurchaseSubmit { grid-column: 1 / -1; }
  #modalPurchaseCreate .modal-foot .btn { width: 100%; min-height: 46px; justify-content: center; }

  /* ================= ④ 警告 / 文件备份 两行卡补充 ================= */
  #vaultList .order-card-2l.is-sel { background: var(--pri-50, #eff6ff); border-color: var(--pri-200, #bfdbfe); }
  #vaultList .order-card-2l .oc-l1 .order-no { display: flex; align-items: center; gap: 2px; }
  #poAlertsList .order-card-2l .oc-l2 .po-badge { flex: 0 0 auto; }
}

/* PC（≥901px）：#788 无新增移动端专有元素需隐藏（两行卡与弹层均只在窄屏生成） */


/* ============================================================
 * #789 日期/时间控件「零溢出」加固（★整层 @media (max-width: 900px) 包裹，PC 端零影响）
 * ------------------------------------------------------------
 * 背景：#788 的防御只作用于 `.modal` 作用域，且承重的是 `max-width:100%` 这一条；
 *       台账筛选行还因为其中的 `width:100%` 越过作用范围被误伤（见上方 #789 回滚注释）。
 *       用户二次反馈「日期控件的框超出屏幕边界」，而本地 Blink 在全站 55 个弹窗
 *       × 320~412px 都复现不出，故本层按「**某些内核会给日期控件注入固有宽度、
 *       或把内层日期部件（按钮框）画到框外**」的假设，做与内核无关的兜底：
 *
 *   ① 所有 date/time 控件一律「可收缩 + 硬上限」——**只加约束，不写 width**，
 *      因此不会像 #788 那样把内容自适应的控件撑满整行
 *   ② flex/grid 子项默认 min-width:auto 会被内容顶宽 → 父链逐类放开收缩
 *   ③ WebKit/Blink 日期控件的**内层部件**逐个重置（★每条必须单独成规则：
 *      选择器列表里只要有一个该内核不认识，整条规则会被整段丢弃）
 *   ④ 本层只负责「不越界」；日期框的宽/高/圆角/聚焦环全部沿用既有样式，
 *      故视觉与本层引入前一致（PC 更是零影响）
 * ============================================================ */
@media (max-width: 900px) {

  /* ---- ① 全站（不限 .modal）date/time 控件：可收缩 + 不许越出容器 ---- */
  /* ⚠ #790 iOS 修正（依据用户真机截图逐像素定位）：iOS Safari 对 input[type=date]
     的原生渲染**不按 border-box 计算盒模型** —— 它把 `width:100%` 当成「内容宽」，
     padding 与 border 另加在外，于是 border box = 容器宽 + 水平 padding + 边框，
     右边缘直接顶到屏幕最右一列（375px 机型实测：其它控件右边框在 353.7，
     两个日期框在 374.7、即压在视口 375 的最后一列）。
     此时 `box-sizing:border-box` 与 `max-width:100%` **都拦不住**，因为 content-box
     下这两条同样只管「内容宽」。
     ⚠ 也**不能**改成 `display:block` + `width:auto` —— 这些控件的父容器 `.form-row`
     在窄屏是 **flex 容器**，flex 项的 `auto` 宽度会退化成「内容宽度」
     （实测从 333px 掉到 150px），反而更糟。
     ⇒ 分工：**CSS 层只负责「可收缩 + 上限」**（跨引擎的正常路径），
        **盒模型差异交给 JS 运行时按实测像素纠正** —— app.js `runDateWidthGuard()`
        的三级纠正（写死 px → 复测 → 仍超则再扣水平 padding+border），
        它按「控件右边缘 vs 父容器内容盒右边缘」判定，与视口宽无关。 */
  input[type="date"], input[type="month"], input[type="week"],
  input[type="time"], input[type="datetime-local"] {
    width: 100% !important;
    max-width: 100% !important;
    min-width: 0 !important;
    box-sizing: border-box !important;
    overflow: hidden !important;
    text-align: left;
  }

  /* ---- ② 父链：flex/grid 子项默认 min-width:auto，会被内容顶宽 ---- */
  .form-row, .ffield, .ffield-row, .form-grid, .form-grid > .form-row,
  .modal-body, .modal-body > div {
    min-width: 0;
    max-width: 100%;
  }

  /* ---- ③ 日期控件内层部件逐个重置（各自成规则，互不牵连） ---- */
  input[type="date"]::-webkit-textfield-decoration-container { min-width: 0; max-width: 100%; }
  input[type="date"]::-webkit-datetime-edit { min-width: 0; max-width: 100%; padding: 0; }
  input[type="date"]::-webkit-datetime-edit-fields-wrapper { min-width: 0; max-width: 100%; padding: 0; }
  input[type="date"]::-webkit-date-and-time-value { min-width: 0; max-width: 100%; text-align: left; }
  input[type="date"]::-webkit-calendar-picker-indicator { flex: none; margin-left: 0; margin-right: 0; padding: 0; }
  input[type="date"]::-webkit-inner-spin-button { display: none; -webkit-appearance: none; margin: 0; }
  input[type="date"]::-webkit-clear-button { display: none; -webkit-appearance: none; }
  input[type="month"]::-webkit-textfield-decoration-container { min-width: 0; max-width: 100%; }
  input[type="month"]::-webkit-datetime-edit { min-width: 0; max-width: 100%; padding: 0; }
  input[type="month"]::-webkit-calendar-picker-indicator { flex: none; margin-left: 0; padding: 0; }
  input[type="month"]::-webkit-inner-spin-button { display: none; -webkit-appearance: none; margin: 0; }
  input[type="month"]::-webkit-clear-button { display: none; -webkit-appearance: none; }
  input[type="time"]::-webkit-textfield-decoration-container { min-width: 0; max-width: 100%; }
  input[type="time"]::-webkit-datetime-edit { min-width: 0; max-width: 100%; padding: 0; }
  input[type="time"]::-webkit-inner-spin-button { display: none; -webkit-appearance: none; margin: 0; }
  input[type="datetime-local"]::-webkit-datetime-edit { min-width: 0; max-width: 100%; padding: 0; }
  input[type="datetime-local"]::-webkit-calendar-picker-indicator { flex: none; margin-left: 0; padding: 0; }

  /* ---- ④ 台账筛选行：日期框恢复「内容自适应」，与相邻控件同排 ---- */
  #modalLedger .modal-body > div > input[type="date"] { flex: 0 1 auto; width: auto; }
}

/* PC（≥901px）：#789 全部规则都在上面的窄屏块内，PC 端无新增移动端专有元素需隐藏 */

/* ============================================================
 * #792 PC 端会话聊天：微信电脑客户端「视觉」+ 弹窗承载（★整层 @media (min-width:901px)）
 * ------------------------------------------------------------
 * 承载：仍为 #modalChatBox 弹窗（会话列表留在消息中心页面，点会话开窗），
 *       尺寸收紧到 820×620（微信电脑版聊天窗比例）——不再内嵌双栏占满页面。
 * 视觉：照搬微信电脑版 —— #95EC69 自己气泡 + 白底对方气泡 + 指向头像的小尖角、
 *       方形小圆角头像、居中灰字时间分隔、56px 浅灰标题条、浅灰输入区 + 右下绿「发送」。
 * ★ 移动端零影响：本层规则全部在 @media (min-width:901px) 内；
 *   新增的 #chatInputPc（多行输入）/#pcChatToolbar（PC 工具条）在窄屏由紧随其后的
 *   ≤900px 块 display:none，移动端仍走原有「单行输入 + ＋ 面板」路径。
 * ============================================================ */
@media (min-width: 901px) {

  /* ================= 弹窗外壳与尺寸（微信电脑版聊天窗） ================= */
  #modalChatBox .modal {
    width: 820px;
    max-width: 92vw;
    height: 620px;
    max-height: 86vh;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    background: #f5f5f5;
    border-radius: 8px;
  }

  /* 标题条：56px 浅灰 + 底部细线，标题居左、✕ 靠右 */
  #modalChatBox .modal-head {
    flex: none;
    height: 56px;
    padding: 0 18px;
    display: flex;
    align-items: center;
    justify-content: flex-start;
    background: #f5f5f5;
    border-bottom: 1px solid #e7e7e7;
    box-shadow: none;
    border-radius: 8px 8px 0 0;
  }
  #modalChatBox .modal-head h3 { font-size: 15.5px; font-weight: 600; color: #191919; }
  #modalChatBox .modal-head::before { display: none; }
  #modalChatBox .modal-close {
    margin-left: auto; width: 28px; height: 28px; font-size: 13px;
    background: transparent; border: none; color: #8a8a8a; cursor: pointer;
  }
  #modalChatBox .modal-close:hover { color: #07c160; }

  /* ================= 消息区 ================= */
  #modalChatBox #chatBoxBody {
    flex: 1 1 auto;
    min-height: 0 !important;
    max-height: none !important;
    background: #f5f5f5 !important;
    padding: 16px 18px 14px;
    overflow-y: auto;
  }
  #modalChatBox .msg-bubble-list { gap: 16px; }
  #modalChatBox .msg-bubble { gap: 10px; align-items: flex-start; max-width: 100%; }
  #modalChatBox .msg-avatar {
    width: 36px; height: 36px; border-radius: 5px; flex: none; overflow: hidden;
    font-size: 14px; background: #7d8a99; color: #fff;
    display: flex; align-items: center; justify-content: center;
  }
  #modalChatBox .msg-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
  #modalChatBox .msg-bubble-main { max-width: 68%; }
  /* 单聊不显示昵称与逐条时间 —— 与微信电脑版一致（时间由居中分隔承载） */
  #modalChatBox .msg-bubble-head { display: none; }

  #modalChatBox .msg-bubble-content {
    position: relative;
    background: #fff; color: #191919;
    border-radius: 5px; padding: 9px 13px;
    font-size: 14px; line-height: 1.55;
    word-break: break-word; box-shadow: none;
  }
  #modalChatBox .mine .msg-bubble-content { background: #95ec69; color: #191919; }
  /* 指向头像的小尖角（微信气泡标志） */
  #modalChatBox .msg-bubble-content::before {
    content: ''; position: absolute; top: 11px; left: -5px;
    width: 0; height: 0; border-style: solid;
    border-width: 5px 6px 5px 0;
    border-color: transparent #fff transparent transparent;
  }
  #modalChatBox .mine .msg-bubble-content::before {
    left: auto; right: -5px;
    border-width: 5px 0 5px 6px;
    border-color: transparent transparent transparent #95ec69;
  }
  /* 文件 / 图片卡片：容器不带气泡与尖角 */
  #modalChatBox .msg-bubble-content.chat-file-content { background: transparent !important; padding: 0 !important; }
  #modalChatBox .msg-bubble-content.chat-file-content::before { display: none; }
  #modalChatBox .chat-file-card { background: #fff; border-radius: 5px; }
  #modalChatBox .chat-img, #modalChatBox .chat-img-wrap { border-radius: 5px; }
  /* 纯表情：大表情不带气泡底 */
  #modalChatBox .msg-bubble-content.chat-emoji-only {
    background: transparent !important; padding: 0 !important;
    font-size: 2rem !important; line-height: 1.3 !important;
  }
  #modalChatBox .msg-bubble-content.chat-emoji-only::before { display: none; }
  #modalChatBox .msg-bubble-actions { margin-top: 4px; gap: 5px; }

  /* 居中时间分隔（相邻 >5 分钟才出现，同微信） */
  #modalChatBox .chat-time-sep { text-align: center; margin: 2px 0 0; }
  #modalChatBox .chat-time-sep span {
    display: inline-block; font-size: 11.5px; color: #a6a6a6;
    background: transparent; padding: 0; border-radius: 0;
  }

  /* ================= 输入区（微信电脑版） ================= */
  #modalChatBox .chat-input-wrap {
    flex: none;
    background: #f5f5f5;
    border-top: 1px solid #e7e7e7;
    border-radius: 0 0 8px 8px;
    padding: 8px 18px 10px;
    gap: 0;
  }
  #modalChatBox .chat-pending-imgs { padding: 0 0 8px; }
  /* 工具条：输入框上方一行（😊 / 📷 / 📎） */
  #pcChatToolbar { display: flex; align-items: center; gap: 4px; padding-bottom: 6px; }
  #pcChatToolbar .chat-bar-btn {
    background: transparent !important; border: none !important;
    color: #6b6b6b; font-size: 18px; line-height: 1;
    padding: 3px 5px !important; min-height: auto; border-radius: 4px; cursor: pointer;
  }
  #pcChatToolbar .chat-bar-btn:hover { background: #e9e9e9; color: #191919; }
  #pcChatToolbar .chat-bar-btn.active { color: #07c160; }

  #modalChatBox .chat-input-bar { display: block; position: relative; background: transparent; padding: 0; }
  #modalChatBox #chatInput { display: none !important; }   /* PC 改用下方多行 textarea */
  #modalChatBox .wx-textarea {
    display: block; width: 100%;
    border: none; outline: none; resize: none; background: transparent;
    color: #191919; font-family: inherit;
    font-size: 14px; line-height: 1.65;
    min-height: 74px; max-height: 168px;
    padding: 0 0 34px; overflow-y: auto;
  }
  #modalChatBox .wx-textarea::placeholder { color: #b2b2b2; }
  #modalChatBox #btnChatSend {
    position: absolute; right: 0; bottom: 4px;
    background: #07c160 !important; border: 1px solid #07c160 !important;
    color: #fff !important; border-radius: 4px !important;
    font-size: 12.5px; padding: 4px 14px !important; min-height: auto; cursor: pointer;
  }
  #modalChatBox #btnChatSend:hover { background: #06ad56 !important; border-color: #06ad56 !important; }
  #modalChatBox #btnChatSend:disabled { opacity: .6; cursor: default; }

  /* 表情面板：贴输入区上方弹出（弹窗内定位） */
  #modalChatBox .chat-emoji-panel { bottom: 100%; left: 18px; right: 18px; width: auto; }

  /* 拖拽提示层：贴合弹窗圆角 */
  #modalChatBox .chat-drop-hint { border-radius: 8px; }

  /* PC 端不参与布局的移动端专用件 */
  #modalChatBox .m-chat-plus, #modalChatBox .chat-tool-panel { display: none !important; }
}

/* PC 专属件在窄屏一律不参与布局 —— 保证移动端与改动前逐像素一致 */
@media (max-width: 900px) {
  #chatInputPc { display: none !important; }    /* PC 多行输入框 */
  #pcChatToolbar { display: none !important; }  /* PC 输入框上方工具条 */
  .wx-ctx { display: none !important; }         /* PC 右键菜单（窄屏用长按，不弹此层） */
}

/* ================= 消息右键菜单（PC 专属，微信电脑版交互） ================= */
.wx-ctx {
  position: fixed; z-index: 3000; min-width: 136px;
  background: #fff; border: 1px solid #e2e2e2; border-radius: 5px;
  box-shadow: 0 6px 20px rgba(0, 0, 0, .14); padding: 4px 0;
}
.wx-ctx-item {
  display: block; width: 100%; text-align: left; cursor: pointer;
  background: transparent; border: none;
  font-size: 13px; color: #191919; padding: 7px 16px;
}
.wx-ctx-item:hover { background: #f0f0f0; }
.wx-ctx-sep { height: 1px; background: #eee; margin: 4px 0; }

@media (max-width: 900px) {

  /* ================= P0-1 触控目标统一 ≥44px =================
   * 说明：必须用 !important —— 项目里存在 `.toolbar .filter-select{min-height:40px}`、
   * `.toolbar #btnNewOrder{min-height:40px}` 这类**更高优先级**的旧规则（已用
   * CDP CSS.getMatchedStylesForNode 逐条确认），仅靠「写在最后」无法覆盖。 */
  .btn, .btn-sm, .btn-xs, .page-btn, .mc-mode-btn, .msg-tab,
  .toolbar .btn, .toolbar .btn-sm, .toolbar .btn-xs, .toolbar .page-btn,
  .toolbar .btn-filter-toggle, .toolbar .fm-reset, .toolbar .tb-fold-btn,
  .alerts-toolbar .btn, .alerts-toolbar .tb-fold-btn,
  .todo-actions .btn, .alert-item .btn, .order-card-actions .btn,
  .msg-bubble-actions .btn, .vault-acts .btn { min-height: 44px !important; }

  /* 裸 select / input 也要兜住（无 class 的控件此前不受任何规则约束） */
  select, input[type="text"], input[type="search"], input[type="number"],
  input[type="date"], input[type="time"], input[type="datetime-local"],
  .search-input, .filter-select, .filter-date, .filter-input,
  .toolbar select, .toolbar .filter-select, .toolbar .search-input,
  .toolbar .filter-date, .toolbar .filter-input,
  .toolbar #pageSizeSelect, .toolbar #btnExportOrders, .toolbar #btnNewOrder,
  .alerts-toolbar select, .alerts-toolbar .filter-select { min-height: 44px !important; }

  .notif-bell, #btnSettings, .mdrawer-close { min-width: 44px !important; min-height: 44px !important; }

  /* ★ 例外（必须写在本节之后，靠 id 级优先级 + !important 保住原有设计值）：
   *   ① 会话输入栏：#786 既定密集布局，40px
   *   ② 弹窗底部主按钮：#788 既定 46px，比 44 更大，不能被降级 */
  #modalChatBox .chat-bar-btn,
  #modalChatBox #chatInput,
  #modalChatBox #btnChatSend { min-height: 40px !important; }
  #modalPurchaseCreate .modal-foot .btn,
  .modal-foot .btn-primary, .modal-foot .btn-success, .modal-foot .btn-danger { min-height: 46px !important; }
  #orderStageDays .stage-days-row input { min-height: 44px !important; }

  /* ================= P0-2 表单控件 16px：避免 iOS 聚焦整页放大 =================
   * 同样必须 !important：`.filter-select{font-size:14px}`(类) 优先级高于 `select`(元素)。 */
  input, textarea, select { font-size: 16px !important; }
  input[type="checkbox"], input[type="radio"], input[type="range"] { font-size: inherit !important; }
  /* 16px 后长文案控件补省略，避免文字被硬裁 */
  .filter-select, .search-input, select, .filter-input { text-overflow: ellipsis; }

  /* ================= P0-3 按压反馈：补齐原本只有 hover 的控件 ================= */
  .btn, .page-btn, .mc-mode-btn, .msg-tab, .tb-fold-btn, .fm-reset,
  .chat-conv, .order-card, .vault-row, .mdg-item, .mdrawer-act,
  .alert-item, .todo-item, .notif-bell, #btnSettings,
  select, .filter-select, .search-input { -webkit-tap-highlight-color: transparent; }

  .btn-ghost:active, .btn-sm:active, .btn-xs:active, .btn-secondary:active,
  .page-btn:active, .mc-mode-btn:active, .msg-tab:active,
  .tb-fold-btn:active, .fm-reset:active, .notif-bell:active, #btnSettings:active,
  .chat-bar-btn:active, .btn-filter-toggle:active { background: #eef2f7 !important; }
  .btn-primary:active, .btn-success:active, .btn-danger:active {
    filter: brightness(.94);
  }
  select:active, .filter-select:active, .search-input:active { background: #f8fafc !important; }

  /* ================= P1-4 横滑容器：CSS 滚动阴影（左右按需出现） ================= */
  .gantt-wrap, .stats-panel, .vault-head-actions {
    background-image:
      linear-gradient(to right, #fff 30%, rgba(255,255,255,0)),
      linear-gradient(to left,  #fff 30%, rgba(255,255,255,0)),
      radial-gradient(farthest-side at 0 50%, rgba(15,23,42,.16), rgba(15,23,42,0)),
      radial-gradient(farthest-side at 100% 50%, rgba(15,23,42,.16), rgba(15,23,42,0));
    background-position: left center, right center, left center, right center;
    background-repeat: no-repeat;
    background-size: 40px 100%, 40px 100%, 14px 100%, 14px 100%;
    background-attachment: local, local, scroll, scroll;
  }
  /* 横向滚动提示条（仅甘特图，由 app.js 在窄屏注入，带 .m-only 保证 PC 不显示） */
  .m-scroll-hint {
    display: flex; align-items: center; gap: 6px;
    font-size: 12px; color: var(--text-mute);
    margin: 0 0 8px; padding: 0 2px;
  }
  .m-scroll-hint b { color: var(--pri-600, #2563eb); font-weight: 600; }

  /* ================= P1-5 首屏工具栏压缩 ================= */
  /* 预警面板：3 个整行下拉 → 2 列网格（配合 JS 折叠，首屏少 2 行） */
  .alerts-toolbar { display: grid !important; grid-template-columns: 1fr 1fr; gap: 8px; align-items: center; }
  .alerts-toolbar > * { width: 100%; min-width: 0; }
  /* 仓库/年包/采购：标题区说明文字移动端只留一行；标题与操作按钮更紧凑 */
  .view-warehouse .alerts-header p,
  .view-annual .alerts-header p,
  .view-purchase .alerts-header p {
    display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical; overflow: hidden;
  }
  /* 仓库首屏压缩（实测：标题区 114px + 工具栏 96px + 列表留白 33px 把首个数据卡推到 402px）
     → 说明文字窄屏隐藏（原本已被 line-clamp 截成残句，价值低）+ 标题区不换行 +
       两个次要操作由 JS 缩成 2 字短标签（.btn-compact-label），使标题与按钮同排一行。
     注意：该 .alerts-header 的 flex-wrap/gap 写在**内联样式**里，必须 !important 才能覆盖。 */
  .view-warehouse .alerts-header { padding: 6px 14px !important; margin-bottom: 6px; flex-wrap: nowrap !important; gap: 6px !important; }
  .view-warehouse .alerts-header > div { flex: 1 1 auto; min-width: 0; }
  /* 标题左列被三个操作按钮挤到约 100px，17px 下「🏭 仓库管理」会折成两行 → 降 1 档并禁止换行 */
  .view-warehouse .alerts-header h2 { font-size: 15.5px; margin-bottom: 0; white-space: nowrap; }
  .view-warehouse .alerts-header p { display: none !important; }
  .view-warehouse .alerts-header > .btn { flex: 0 0 auto; }
  .btn-compact-label { padding-left: 8px !important; padding-right: 8px !important; }
  /* 工具栏压成一行：搜索框允许收缩，让「搜索 + 刷新 + 更多筛选」同排 */
  .view-warehouse .toolbar { flex-wrap: nowrap !important; gap: 6px !important; }
  .view-warehouse .toolbar .search-input { flex: 1 1 90px !important; min-width: 0 !important; }
  .view-warehouse .warehouse-list { padding-top: 0 !important; margin-top: 4px !important; }

  /* ================= P1-6 关键小字号提升 ================= */
  .gantt-day { font-size: 12px; }
  .gantt-label { font-size: 12px; }
  .gantt-part-count { font-size: 11px; }
  .stats-table th, .stats-table td { font-size: 12.5px; }
  .mini-pct { font-size: 12px; }                 /* 统计表内的百分比标注（原 11px） */
  .vault-stat .k { font-size: 12px; }            /* 文件备份统计卡标签（原 11.5px） */
  .vault-stat .v small { font-size: 12px; }      /* 单位「个」（原 11.5px） */
  .mnav-txt { font-size: 11.5px; }
  .msg-item-time, .chat-conv-time { font-size: 11.5px; }
  .tb-fold-btn .ft-num, .btn-filter-toggle .ft-num,
  .tb-fold-btn .ft-caret, .btn-filter-toggle .ft-caret { font-size: 11.5px; }

  /* ================= P1-7 抽屉宫格：业务分组标题 ================= */
  .mdrawer-group-title {
    grid-column: 1 / -1;
    font-size: 12px; font-weight: 700; letter-spacing: .04em;
    color: var(--n-400, #94a3b8);
    margin: 12px 2px 0;
  }
  .mdrawer-group-title:first-child { margin-top: 0; }

  /* ================= P1-8 设备语义文案 ================= */
  .pc-only { display: none !important; }
  /* 3D 视口提示：≤720px 原本整条隐藏（用户看不到任何操作说明）→ 移动端改为
     独占一行显示触摸语义（工具栏是 flex-wrap，flex-basis:100% 保证换行不挤压按钮） */
  .dxf3d-hint.m-only {
    display: block !important;
    flex: 0 0 100%; order: 99;
    margin: 2px 0 0; font-size: 12px;
  }

  /* ================= P2-10 手势收敛为纵向 ================= */
  body { touch-action: pan-y; }
  html { overscroll-behavior-y: contain; }
  .gantt-wrap, .stats-panel, .vault-head-actions { touch-action: pan-x pan-y; }
}

/* ===== #75x 多供应商拆单：父单聚合卡片 + 子单卡片 ===== */
.po-parent-card { border-left: 3px solid #2563eb; }
.po-multi-tag { display:inline-block; background:#e0edff; color:#1d4ed8; font-size:11.5px; font-weight:600; padding:1px 8px; border-radius:10px; margin-left:4px; vertical-align:middle; }
.po-progress-wrap { display:inline-flex; align-items:center; gap:6px; font-size:11.5px; color:var(--text-mute,#6b7280); }
.po-progress-bar { display:inline-block; width:64px; height:5px; background:#e5e7eb; border-radius:3px; overflow:hidden; }
.po-progress-bar i { display:block; height:100%; background:linear-gradient(90deg,#34d399,#10b981); border-radius:3px; transition:width .3s ease; }
.po-progress-txt { font-variant-numeric:tabular-nums; font-weight:600; color:#10b981; }
.po-children-wrap { margin-top:10px; padding-top:10px; border-top:1px dashed var(--border-color,#e5e7eb); }
.po-children-grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(min(170px,100%),1fr)); gap:8px; }
.po-child-card { padding:9px 11px; background:var(--bg-soft,#f8fafc); border:1px solid var(--border-color,#e5e7eb); border-radius:8px; cursor:pointer; transition:border-color .15s, box-shadow .15s, transform .15s; }
.po-child-card:hover { border-color:var(--pri-600,#2563eb); box-shadow:0 2px 8px rgba(37,99,235,.12); transform:translateY(-1px); }
.po-child-head { display:flex; justify-content:space-between; align-items:center; gap:6px; margin-bottom:5px; }
.po-child-no { font-weight:600; font-size:12.5px; color:var(--pri-600,#2563eb); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.po-child-badge { font-size:10.5px; color:#fff; padding:1px 6px; border-radius:8px; white-space:nowrap; flex:0 0 auto; }
.po-child-vendor { font-size:12px; color:var(--text-mute,#6b7280); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; margin-bottom:4px; }
.po-child-amount { font-size:13px; font-weight:600; color:var(--text,#111827); font-variant-numeric:tabular-nums; }
.po-chev { font-style:normal; display:inline-block; margin-left:3px; transition:transform .2s ease; }
.btn-po-expand[aria-expanded="true"] .po-chev { transform:rotate(180deg); }
.po-child-nolabel { display:flex; align-items:center; gap:6px; min-width:0; overflow:hidden; }
.po-child-check { width:auto; height:auto; padding:0; margin:0; flex:0 0 auto; cursor:pointer; accent-color:var(--pri-600,#2563eb); }

/* #75x 多供应商卡片：移动端适配（窄屏单列/双列，避免溢出） */
@media (max-width: 600px) {
  .po-children-grid { grid-template-columns:1fr 1fr; gap:6px; }
  .po-child-card { padding:8px 9px; }
  .po-multi-tag { font-size:11px; padding:1px 6px; }
  .po-progress-bar { width:54px; }
}
@media (max-width: 380px) {
  .po-children-grid { grid-template-columns:1fr; }
}

/* ===== #795 批量导入订单弹窗 ===== */
.io-tip { font-size:12.5px; line-height:1.7; color:var(--text-mute,#6b7280); background:var(--n-50,#f9fafb); border:1px solid var(--n-200,#e5e7eb); border-radius:8px; padding:10px 12px; margin:0 0 14px; }
.io-tip b { color:var(--text,#111827); }
.io-row { margin-bottom:14px; }
.io-label { display:block; font-size:12.5px; font-weight:600; color:var(--text,#111827); margin-bottom:6px; }
.io-hint { display:block; font-size:11.5px; color:var(--text-mute,#9ca3af); margin-top:5px; line-height:1.6; }
.io-file { display:block; width:100%; font-size:12.5px; padding:8px 10px; border:1px dashed var(--n-300,#d1d5db); border-radius:8px; background:#fff; cursor:pointer; }
.io-file::file-selector-button { margin-right:10px; padding:5px 12px; font-size:12.5px; border:0; border-radius:6px; background:var(--pri-600,#2563eb); color:#fff; cursor:pointer; }
.io-assignees { display:grid; grid-template-columns:repeat(auto-fill,minmax(160px,1fr)); gap:8px; }
.io-assignees .io-asg { display:flex; flex-direction:column; gap:3px; }
.io-asg-name { font-size:11.5px; color:var(--text-mute,#6b7280); }
.io-assignees select { width:100%; font-size:12.5px; padding:6px 8px; border:1px solid var(--n-300,#d1d5db); border-radius:6px; background:#fff; }
.io-progress { margin:14px 0; }
.io-progress-bar { height:6px; background:var(--n-200,#e5e7eb); border-radius:3px; overflow:hidden; }
.io-progress-fill { height:100%; width:0; background:var(--pri-600,#2563eb); border-radius:3px; transition:width .25s ease; }
.io-progress-text { display:block; font-size:12px; color:var(--text-mute,#6b7280); margin-top:6px; }
.io-summary { font-size:13px; line-height:1.8; padding:10px 12px; border-radius:8px; background:var(--n-50,#f9fafb); border:1px solid var(--n-200,#e5e7eb); margin-bottom:10px; }
.io-summary .io-ok-n { color:#16a34a; font-weight:700; }
.io-summary .io-err-n { color:#dc2626; font-weight:700; }
.io-table-wrap { max-height:320px; overflow:auto; border:1px solid var(--n-200,#e5e7eb); border-radius:8px; }
.io-table { width:100%; border-collapse:collapse; font-size:12.5px; }
.io-table thead th { position:sticky; top:0; background:var(--n-100,#f3f4f6); text-align:left; font-weight:600; padding:7px 10px; border-bottom:1px solid var(--n-200,#e5e7eb); white-space:nowrap; z-index:1; }
.io-table td { padding:6px 10px; border-bottom:1px solid var(--n-100,#f3f4f6); vertical-align:top; }
.io-table tr:last-child td { border-bottom:0; }
.io-st-ok { color:#16a34a; font-weight:600; white-space:nowrap; }
.io-st-err { color:#dc2626; font-weight:600; white-space:nowrap; }
.io-msg { color:var(--text-mute,#6b7280); word-break:break-word; }
@media (max-width: 600px) {
  .io-assignees { grid-template-columns:1fr; }
  .io-table-wrap { max-height:240px; }
  .io-table thead th, .io-table td { padding:6px 8px; font-size:12px; }
}

/* #795 批量导入：快速填充行 */
.io-quick { display:flex; align-items:center; gap:8px; flex-wrap:wrap; margin-bottom:8px; }
.io-quick select { font-size:12.5px; padding:5px 8px; border:1px solid var(--n-300,#d1d5db); border-radius:6px; background:#fff; min-width:150px; }

/* ===== #795 检验合格率统计面板 ===== */
.insp-panel .overdue-stats-header { flex-wrap:wrap; }
.insp-rate-num { color:var(--pri-600,#2563eb); }
.insp-note { font-size:12px; color:var(--text-mute,#6b7280); background:var(--n-50,#f9fafb); border-left:3px solid var(--n-300,#d1d5db); padding:7px 10px; border-radius:0 6px 6px 0; margin:10px 0 0; line-height:1.7; }
.insp-sub { font-size:13.5px; font-weight:600; color:var(--text,#111827); margin:18px 0 8px; }
.insp-trend { display:flex; align-items:flex-end; gap:6px; height:150px; padding:10px 12px; background:var(--bg-surface,#fff); border:1px solid var(--n-200,#e5e7eb); border-radius:8px; overflow-x:auto; }
.insp-trend-col { flex:0 0 44px; display:flex; flex-direction:column; align-items:center; height:100%; justify-content:flex-end; gap:3px; }
.insp-trend-bar-wrap { width:22px; height:100%; display:flex; align-items:flex-end; }
.insp-trend-bar { width:100%; border-radius:3px 3px 0 0; min-height:2px; transition:height .3s ease; }
.insp-trend-val { font-size:10.5px; font-weight:600; color:var(--text-soft,#4b5563); white-space:nowrap; }
.insp-trend-label { font-size:10.5px; color:var(--text-mute,#9ca3af); white-space:nowrap; }
.insp-split { min-width:0; }
.insp-detail-wrap { overflow-x:auto; border:1px solid var(--n-200,#e5e7eb); border-radius:8px; }
.insp-detail-table { min-width:720px; }
.insp-issue { max-width:260px; word-break:break-word; color:var(--text-soft,#4b5563); }
@media (max-width: 700px) {
  .insp-trend { height:120px; padding:8px; }
  .insp-trend-col { flex:0 0 36px; }
  .insp-detail-table { min-width:640px; }
}

/* ===== #795 批次F 用料清单编辑器（零件弹窗内） ===== */
.mat-hint { font-size:12px; color:var(--text-mute,#6b7280); line-height:1.65; margin:0 0 10px; }
.mat-empty { font-size:12.5px; color:var(--text-mute,#9ca3af); padding:12px; text-align:center;
  background:var(--n-50,#f9fafb); border:1px dashed var(--n-300,#d1d5db); border-radius:8px; margin:0; }
.mat-list { display:flex; flex-direction:column; gap:8px; }
.mat-row { border:1px solid var(--n-200,#e5e7eb); border-radius:8px; padding:9px 10px;
  background:var(--bg-surface,#fff); transition:border-color .15s; }
.mat-row:hover { border-color:var(--n-300,#d1d5db); }
.mat-row.mat-short { border-color:#fca5a5; background:#fef2f2; }
.mat-row-main { display:flex; align-items:center; gap:8px; }
.mat-item-select { flex:1; min-width:0; font-size:12.5px; padding:6px 8px;
  border:1px solid var(--n-300,#d1d5db); border-radius:6px; background:#fff; }
.mat-qty { flex:none; width:78px; font-size:12.5px; padding:6px 8px; text-align:right;
  border:1px solid var(--n-300,#d1d5db); border-radius:6px; }
.mat-unit { flex:none; font-size:12px; color:var(--text-mute,#6b7280); min-width:24px; }
.mat-del { flex:none; padding:4px 8px; }
.mat-row-sub { display:flex; flex-wrap:wrap; gap:6px; margin-top:6px; }
.mat-badge { font-size:11px; line-height:1; padding:3px 7px; border-radius:4px;
  background:var(--n-100,#f3f4f6); color:var(--text-soft,#4b5563); white-space:nowrap; }
.mat-badge-warn { background:#fef3c7; color:#92400e; }
.mat-badge-ok { background:#dcfce7; color:#166534; }
.mat-badge-issue { background:#dbeafe; color:#1e40af; }

/* ===== #795 批次F 订单领料面板（零件详情弹窗内） ===== */
.oi-block { margin-top:14px; border-top:1px solid var(--n-200,#e5e7eb); padding-top:12px; }
.oi-head { display:flex; align-items:center; justify-content:space-between; gap:10px; flex-wrap:wrap; margin-bottom:8px; }
.oi-title { font-size:13.5px; font-weight:600; color:var(--text,#111827); margin:0; }
.oi-actions { display:flex; gap:6px; flex-wrap:wrap; }
.oi-tip { font-size:12px; line-height:1.65; color:var(--text-mute,#6b7280); background:var(--n-50,#f9fafb);
  border-left:3px solid var(--n-300,#d1d5db); padding:7px 10px; border-radius:0 6px 6px 0; margin:0 0 10px; }
.oi-sum { display:flex; flex-wrap:wrap; gap:8px; margin-bottom:10px; }
.oi-sum-item { flex:1 1 130px; min-width:0; background:var(--n-50,#f9fafb); border:1px solid var(--n-200,#e5e7eb);
  border-radius:8px; padding:8px 10px; }
.oi-sum-k { display:block; font-size:11px; color:var(--text-mute,#9ca3af); margin-bottom:3px; }
.oi-sum-v { display:block; font-size:15px; font-weight:700; color:var(--text,#111827); }
.oi-sum-v.warn { color:#dc2626; }
.oi-list { display:flex; flex-direction:column; gap:6px; }
.oi-row { display:flex; align-items:center; gap:8px; flex-wrap:wrap; padding:8px 10px;
  border:1px solid var(--n-200,#e5e7eb); border-radius:8px; background:var(--bg-surface,#fff); }
.oi-row.oi-done { background:#f0fdf4; border-color:#bbf7d0; }
.oi-row.oi-part { background:#fffbeb; border-color:#fde68a; }
.oi-row.oi-none { background:#fef2f2; border-color:#fecaca; }
.oi-name { flex:1 1 140px; min-width:0; font-size:12.5px; font-weight:600; color:var(--text,#111827); }
.oi-spec { font-size:11.5px; color:var(--text-mute,#6b7280); }
.oi-nums { flex:none; font-size:12px; color:var(--text-soft,#4b5563); white-space:nowrap; }
.oi-nums b { color:var(--text,#111827); }
.oi-state { flex:none; font-size:11px; line-height:1; padding:3px 7px; border-radius:4px; white-space:nowrap; }
.oi-state.ok { background:#dcfce7; color:#166534; }
.oi-state.partial { background:#fef3c7; color:#92400e; }
.oi-state.short { background:#fee2e2; color:#991b1b; }
.oi-issue-qty { flex:none; width:74px; font-size:12px; padding:5px 7px; text-align:right;
  border:1px solid var(--n-300,#d1d5db); border-radius:6px; }
.oi-rec { border:1px solid var(--n-200,#e5e7eb); border-radius:8px; padding:8px 10px; background:var(--n-50,#f9fafb); }
.oi-rec-top { display:flex; align-items:center; justify-content:space-between; gap:8px; flex-wrap:wrap; }
.oi-rec-time { font-size:11.5px; color:var(--text-mute,#6b7280); }
.oi-rec-body { font-size:12px; color:var(--text-soft,#4b5563); line-height:1.7; margin-top:4px; }
.oi-rec.oi-revoked { opacity:.6; }
.oi-rec.oi-revoked .oi-rec-top { text-decoration:line-through; }
@media (max-width: 600px) {
  .oi-sum-item { flex:1 1 100%; }
  .oi-name { flex:1 1 100%; }
  .oi-nums { width:100%; }
  .oi-issue-qty { width:100%; }
}

/* ============================================================
 * #802d 移动端软键盘避让（手机键盘遮挡输入框）
 * ------------------------------------------------------------
 * 问题：手机软键盘弹出时并不改变**布局视口**（Android Chrome 默认
 *       interactive-widget=resizes-visual，iOS 则完全不改），于是
 *       position:fixed;inset:0 的 .modal-overlay（移动端 align-items:flex-end，
 *       贴底）与 bottom:0 的 .mnav 都不会上移 → 弹层最下方的输入框被键盘
 *       直接盖住，用户看不见自己在输入什么。
 * 方案：
 *   ① viewport meta 加 interactive-widget=resizes-content —— 现代 Android 内核
 *      键盘弹出即缩小布局视口，fixed 元素自动适配（最治本）
 *   ② JS 用 visualViewport 算出键盘高度写 --kb-h 并加 html.kb-open，
 *      下面这些规则据此让弹层上移、底部标签栏隐藏（覆盖 iOS 与旧内核）
 *   ③ JS 在 focusin 时把输入框滚入可视区（处理弹层内部滚动容器）
 * ★ 全部限定在 <=900px；PC 端不加类、不匹配任何规则，渲染与行为零变化。
 * ============================================================ */
@media (max-width: 900px) {
  /* 过渡放在基础规则上：键盘弹出与收起都平滑，不只在 kb-open 时动画 */
  .modal-overlay { transition: padding-bottom .16s ease-out; }
  /* 弹层随键盘上移：padding-bottom 撑出与键盘等高的空白，
     align-items:flex-end 下内容整体上抬，底部输入区不再被覆盖 */
  html.kb-open .modal-overlay { padding-bottom: var(--kb-h, 0px); }
  /* 键盘弹出时隐藏底部标签栏与「更多」抽屉：
     否则它们挤在键盘上方，既挡视线又极易误点 */
  html.kb-open .mnav,
  html.kb-open .mdrawer,
  html.kb-open .mdrawer-mask { display: none !important; }
  /* 弹层高度改用真实可视高度（--vvh 由 JS 维护），
     避免 100vh / 9xvh 在键盘与地址栏变化时失真；
     与上面的 padding-bottom 配合后，弹层恰好落在可视区内 */
  .modal { max-height: calc(var(--vvh, 100vh) - 24px); }
  /* 弹层内部滚动不穿透到页面，聚焦时不易被回弹打断 */
  .modal-overlay { overscroll-behavior: contain; }
}

/* ============================================================
 * #810 采购评价重构（淘宝式）
 * ------------------------------------------------------------
 * ① 角标 ② 轻量评价表单（总星/标签/文字图片/高级折叠）
 * ③ 评价墙（卡片流 + 图片九宫格 + 追评回评） ④ 图片灯箱
 * ============================================================ */

/* ---- ① 待评价角标 ---- */
.badge-dot {
  display: inline-block; min-width: 16px; height: 16px; line-height: 16px;
  padding: 0 4px; margin-left: 4px; border-radius: 8px;
  background: #e5484d; color: #fff; font-size: 11px; font-weight: 700; text-align: center;
}

/* ---- ② 评价表单 ---- */
.fb-base {
  background: var(--bg, #f8fafc); border-radius: 8px; padding: 10px 12px;
  font-size: 12.5px; color: var(--text-mute, #64748b); margin-bottom: 14px; line-height: 1.8;
}
.fb-star-wrap { text-align: center; padding: 6px 0 10px; }
.fb-star-hint { font-size: 13px; color: var(--text-mute, #64748b); margin-bottom: 8px; }
.fb-stars { display: flex; justify-content: center; gap: 6px; }
.fb-star {
  font-size: 34px; line-height: 1; cursor: pointer; color: #d4d4d8;
  transition: transform .08s ease, color .08s ease; user-select: none;
  padding: 4px; min-width: 44px; min-height: 44px;
}
.fb-star.on { color: #f5a524; }
.fb-star:active { transform: scale(1.15); }
.fb-star-text { margin-top: 6px; font-size: 13px; font-weight: 500; color: #f5a524; min-height: 18px; }

.fb-tags { display: flex; gap: 8px; flex-wrap: wrap; }
.fb-tag {
  border: 1px solid var(--border, #e2e8f0); background: #fff; color: var(--text, #0f172a);
  border-radius: 16px; padding: 7px 14px; font-size: 12.5px; cursor: pointer;
  min-height: 34px; display: inline-flex; align-items: center;
}
.fb-tag.on { border-color: #2563eb; background: #eff6ff; color: #1d4ed8; font-weight: 500; }
.fb-tag.problem.on { border-color: #e5484d; background: #fef2f2; color: #b91c1c; }

.fb-photos { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 8px; }
.fb-photo { position: relative; width: 72px; height: 72px; border-radius: 8px; overflow: hidden; border: 1px solid var(--border, #e2e8f0); }
.fb-photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
.fb-photo .fb-photo-del {
  position: absolute; top: 2px; right: 2px; width: 20px; height: 20px; border-radius: 10px;
  background: rgba(0,0,0,.55); color: #fff; font-size: 12px; line-height: 20px; text-align: center;
  cursor: pointer; border: 0;
}

.fb-advanced { margin-top: 14px; border-top: 1px dashed var(--border, #e2e8f0); padding-top: 10px; }
.fb-advanced > summary {
  cursor: pointer; font-size: 12.5px; color: var(--text-mute, #64748b);
  padding: 6px 0; min-height: 32px; list-style: none;
}
.fb-advanced > summary::-webkit-details-marker { display: none; }
.fb-advanced > summary::before { content: '▸ '; }
.fb-advanced[open] > summary::before { content: '▾ '; }

.fb-preview {
  background: #f1f5f9; border-radius: 8px; padding: 8px 12px;
  font-size: 12.5px; margin-top: 10px; color: var(--text-mute, #64748b);
  line-height: 1.7;
}
.fb-warn { color: #b45309; }

/* ---- ③ 评价墙 ---- */
.wall-head {
  display: flex; gap: 10px; align-items: flex-start; flex-wrap: wrap;
  padding: 12px; border-radius: 10px; background: var(--bg, #f8fafc); margin-bottom: 12px;
}
.wall-score { font-size: 30px; font-weight: 700; color: #f5a524; line-height: 1; }
.wall-score small { font-size: 12px; color: var(--text-mute, #64748b); font-weight: 400; }
.wall-meta { font-size: 12px; color: var(--text-mute, #64748b); line-height: 1.9; flex: 1; min-width: 180px; }

.fb-card {
  border: 1px solid var(--border, #e2e8f0); border-radius: 10px;
  padding: 12px; margin-bottom: 10px; background: #fff;
}
.fb-card-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 6px; }
.fb-card-user { font-size: 12.5px; font-weight: 500; }
.fb-card-time { font-size: 11.5px; color: var(--text-mute, #64748b); margin-left: auto; }
.fb-card-stars { color: #f5a524; font-size: 14px; letter-spacing: 1px; }
.fb-card-verdict {
  font-size: 11px; padding: 1px 7px; border-radius: 9px; border: 1px solid currentColor;
}
.fb-card-body { font-size: 13px; line-height: 1.75; margin: 6px 0 0; white-space: pre-wrap; word-break: break-word; }
.fb-card-tags { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 6px; }
.fb-card-tag {
  font-size: 11.5px; padding: 2px 9px; border-radius: 10px;
  background: #f1f5f9; color: #475569;
}
.fb-card-tag.problem { background: #fef2f2; color: #b91c1c; }
.fb-grid { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 8px; }
.fb-grid img {
  width: 84px; height: 84px; object-fit: cover; border-radius: 6px;
  border: 1px solid var(--border, #e2e8f0); cursor: zoom-in; display: block;
}
.fb-sub {
  margin-top: 8px; padding: 8px 10px; border-radius: 8px;
  background: var(--bg, #f8fafc); font-size: 12.5px; line-height: 1.7;
}
.fb-sub-append { border-left: 3px solid #2563eb; }
.fb-sub-reply { border-left: 3px solid #16a34a; background: #f0fdf4; }
.fb-sub-label { font-size: 11.5px; color: var(--text-mute, #64748b); margin-bottom: 2px; }
.fb-card-acts { display: flex; gap: 8px; margin-top: 8px; flex-wrap: wrap; }
.fb-mini {
  font-size: 11.5px; color: #2563eb; background: none; border: 0; cursor: pointer;
  padding: 6px 4px; min-height: 32px;
}
.fb-mini.danger { color: #b91c1c; }
.fb-pending-note {
  font-size: 12px; color: var(--text-mute, #64748b);
  background: #fffbeb; border-radius: 8px; padding: 8px 10px; margin-bottom: 10px; line-height: 1.7;
}

/* ---- ④ 图片灯箱 ---- */
.fb-lightbox {
  position: fixed; inset: 0; background: rgba(0,0,0,.82); z-index: 9999;
  display: flex; align-items: center; justify-content: center; cursor: zoom-out;
}
.fb-lightbox img { max-width: 92vw; max-height: 88vh; border-radius: 8px; }

/* ---- 移动端适配（≤900px，与项目既有断点一致） ---- */
@media (max-width: 900px) {
  .fb-star { font-size: 30px; min-width: 40px; min-height: 40px; }
  .fb-tag { min-height: 40px; padding: 9px 16px; font-size: 13px; }
  .fb-grid img { width: calc(33.33% - 4px); height: auto; aspect-ratio: 1 / 1; }
  .fb-photo { width: calc(33.33% - 6px); height: auto; aspect-ratio: 1 / 1; }
  .wall-score { font-size: 26px; }
  .fb-card { padding: 10px; }
  .fb-card-time { margin-left: 0; width: 100%; }
}

/* ============================================================
 * #802f 键盘 + 底部按钮栏弹出时，聚焦控件必须自动可见
 * ------------------------------------------------------------
 * 配合 app.js 的 scrollControlIntoComfort / ensureFieldVisible：
 *   - scroll-margin 给浏览器原生滚动留出余量（iOS 自身也会做 auto-scroll，
 *     没有余量时会把控件顶到按钮栏或键盘边缘）
 *   - 目标是把控件滚到「按钮栏之上」的可视区，用户无需再手动滚动
 * ★ 仅窄屏生效，PC 端零影响。
 * ============================================================ */
@media (max-width: 900px) {
  .modal-body input,
  .modal-body textarea,
  .modal-body select,
  .modal-body .form-row { scroll-margin-top: 16px; scroll-margin-bottom: 40px; }
}

/* ============================================================
 * #791 采购明细行重排 + 表单控件「可读性 / 圆润度」优化
 * ------------------------------------------------------------
 * 用户反馈：采购报销版块的采购明细「输入框、选择框太窄，视力不好看起来
 * 很吃力，而且不圆润不美观」。根因两条：
 *   ① PC 端明细行 8 个控件挤在一行 flex 里，逐个被压到 70~170px；
 *   ② 这些控件不在 .form-row 内、也没有任何 class 样式 → 走浏览器默认外观
 *      （直角、矮、字小），与其它表单控件观感割裂。
 * 处理：
 *   A. 明细行改为「标签 + 网格」结构：PC 6 列 / 窄屏 2 列，宽度全交 CSS；
 *   B. 明细行控件统一 40px 高 / 10px 圆角 / 13.5px 字号（窄屏 44px / 16px）；
 *   C. 弹窗内所有表单控件补一条「圆润 + 易读」基线（表格内保持紧凑）；
 *   D. 采购流转链路里其余裸控件（改价/入库数量、购买链接行）补统一外观。
 * ★ 本段放在文件末尾，确保窄屏覆盖能按源码顺序正确生效（PC 规则在前、
 *   @media 覆盖在后）。全局 box-sizing 已由 80 行的 * 规则保证。
 * ============================================================ */

/* ---------- A + B：采购明细行（#modalPurchaseCreate） ---------- */
.po-item-row {
  background: var(--bg-surface);
  border: 1px solid var(--border-light);
  border-radius: var(--r-md);
  padding: 14px 16px 16px;
  margin-bottom: 12px;
  box-shadow: 0 1px 2px rgba(16,24,40,.04);
}
.po-item-row .po-it-head {
  display: flex; align-items: center; justify-content: space-between;
  margin: 0 0 12px; padding-bottom: 8px;
  border-bottom: 1px dashed var(--border-light);
}
.po-item-row .po-it-no { font-size: 13px; font-weight: 700; color: var(--n-700); }
.po-item-row .po-it-grid {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 12px;
}
.po-item-row .po-it-f { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.po-item-row .po-it-f.col-3 { grid-column: span 3; }
.po-item-row .po-it-f.col-2 { grid-column: span 2; }
.po-item-row .po-it-f.col-1 { grid-column: span 1; }
.po-item-row .po-it-f.wide { grid-column: 1 / -1; }   /* #788 旧结构兼容保留 */
.po-item-row .po-it-fl {
  display: flex; align-items: center; gap: 2px;
  font-size: 12.5px; color: var(--n-500); line-height: 1.2;
}
.po-item-row .po-it-fl i { color: #dc2626; font-style: normal; }
.po-item-row .po-it-f > input,
.po-item-row .po-it-f > select {
  width: 100%; max-width: 100%; min-width: 0;
  height: 40px; min-height: 40px;
  padding: 8px 12px;
  font-size: 13.5px; line-height: 1.4; font-family: inherit;
  border: 1.5px solid var(--border); border-radius: var(--r-sm);
  background: var(--bg-surface); color: var(--text);
  outline: none;
  transition: border-color .16s ease, box-shadow .16s ease, background .16s ease;
}
.po-item-row .po-it-f > input:hover,
.po-item-row .po-it-f > select:hover { border-color: var(--n-300); }
.po-item-row .po-it-f > input:focus,
.po-item-row .po-it-f > select:focus {
  border-color: var(--pri-500); box-shadow: var(--ring-accent); background: var(--n-0);
}
.po-item-row .po-it-f > input::placeholder { color: var(--text-mute); }
.po-item-row .po-it-f > input:disabled { cursor: not-allowed; }
.po-item-row .po-it-f > select { cursor: pointer; }
.po-item-row .po-it-row2 { display: flex; gap: 8px; align-items: stretch; }
.po-item-row .po-it-row2 > select { flex: 1 1 auto; min-width: 0; }
.po-item-row .btn-po-pick {
  flex: none; min-height: 40px; padding: 0 14px;
  border-radius: var(--r-sm); font-size: 13px; white-space: nowrap;
}
.po-item-row .po-it-del { min-height: 32px; padding: 0 12px; border-radius: var(--r-sm); font-size: 14px; }
/* 明细行最多 6 列，给网格留出呼吸感；只作用于采购申请弹窗，不影响其它弹窗宽度 */
#modalPurchaseCreate .modal { max-width: 1000px; }

@media (max-width: 900px) {
  .po-item-row { padding: 12px 12px 14px; margin-bottom: 10px; }
  .po-item-row .po-it-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px 8px; }
  .po-item-row .po-it-f.col-3,
  .po-item-row .po-it-f.col-2 { grid-column: 1 / -1; }
  .po-item-row .po-it-fl { font-size: 12px; }
  .po-item-row .po-it-f > input,
  .po-item-row .po-it-f > select {
    height: 44px; min-height: 44px; font-size: 16px;   /* 16px 防 iOS 聚焦自动放大 */
  }
  .po-item-row .btn-po-pick { min-height: 44px; padding: 0 12px; }
  .po-item-row .po-it-del { min-height: 34px; padding: 0 10px; }
}

/* ---------- C：弹窗内表单控件「圆润 + 易读」基线 ----------
   只作用于 .modal-body —— 页面上的筛选栏/配置表不受影响；
   表格内的控件单独回退为紧凑尺寸（配置类弹窗里的表格密度不能被放大）。
   已用 .form-row / .form-select-full 等类定过尺寸的控件，值与本基线一致，
   因此不会产生视觉回退，只是让「裸控件」不再走浏览器默认外观。 */
.modal-body input[type="text"], .modal-body input[type="number"], .modal-body input[type="date"],
.modal-body input[type="search"], .modal-body input[type="password"], .modal-body input[type="email"],
.modal-body input[type="tel"], .modal-body input[type="month"], .modal-body input[type="week"],
.modal-body input[type="time"], .modal-body input[type="datetime-local"], .modal-body input[type="url"],
.modal-body select, .modal-body textarea {
  border: 1.5px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--bg-surface);
  color: var(--text);
  outline: none;
  transition: border-color .16s ease, box-shadow .16s ease, background .16s ease;
}
.modal-body input[type="text"]:focus, .modal-body input[type="number"]:focus, .modal-body input[type="date"]:focus,
.modal-body input[type="search"]:focus, .modal-body input[type="password"]:focus, .modal-body input[type="email"]:focus,
.modal-body input[type="tel"]:focus, .modal-body input[type="month"]:focus, .modal-body input[type="week"]:focus,
.modal-body input[type="time"]:focus, .modal-body input[type="datetime-local"]:focus, .modal-body input[type="url"]:focus,
.modal-body select:focus, .modal-body textarea:focus {
  border-color: var(--pri-500); box-shadow: var(--ring-accent); background: var(--n-0);
}
/* 弹窗内、非表单行里的「裸控件」补足高度与可读字号（表格/明细行内除外） */
.modal-body input[type="text"], .modal-body input[type="number"], .modal-body input[type="date"],
.modal-body input[type="search"], .modal-body input[type="password"], .modal-body input[type="email"],
.modal-body input[type="tel"], .modal-body input[type="month"], .modal-body input[type="week"],
.modal-body input[type="time"], .modal-body input[type="datetime-local"], .modal-body input[type="url"],
.modal-body select {
  min-height: 38px;
  padding: 8px 12px;
  font-size: 13.5px;
  font-family: inherit;
  box-sizing: border-box;
}
/* 表格内保持紧凑（配置类弹窗的密度优先） */
.modal-body table input[type="text"], .modal-body table input[type="number"], .modal-body table input[type="date"],
.modal-body table select {
  min-height: 0; padding: 5px 8px; font-size: 12.5px; border-radius: var(--r-xs);
}
/* 明细行已有专用尺寸，避免被上面的通用规则改写 */
.po-item-row .po-it-f > input,
.po-item-row .po-it-f > select { padding: 8px 12px; }

/* ---------- D：采购流转链路里的裸控件 ---------- */
/* 购买链接行（采购完成登记 / 商品档案共用 .links-editor） */
.link-row { display: flex; gap: 8px; align-items: center; margin-bottom: 8px; }
.link-row > input {
  min-height: 38px; padding: 8px 12px;
  font-size: 13px; font-family: inherit;
  border: 1.5px solid var(--border); border-radius: var(--r-sm);
  background: var(--bg-surface); color: var(--text); outline: none;
  transition: border-color .16s ease, box-shadow .16s ease, background .16s ease;
}
.link-row > input:focus { border-color: var(--pri-500); box-shadow: var(--ring-accent); background: var(--n-0); }
.link-row > input::placeholder { color: var(--text-mute); }
.link-row > .link-url { flex: 2 1 200px; min-width: 0; }
.link-row > .link-note { flex: 1 1 140px; min-width: 0; }
.link-row > .btn-del-link { flex: none; min-height: 34px; border-radius: var(--r-sm); }

/* 采购完成登记 / 入库确认里的数量、单价输入 */
#poPcItems .pc-qty-input, #poPcItems .pc-price-input, #poWhItems .wh-qty-input {
  min-height: 38px; padding: 8px 12px;
  font-size: 13.5px; font-family: inherit;
  border: 1.5px solid var(--border); border-radius: var(--r-sm);
  background: var(--bg-surface); color: var(--text); outline: none; text-align: center;
  transition: border-color .16s ease, box-shadow .16s ease, background .16s ease;
}
#poPcItems .pc-qty-input:focus, #poPcItems .pc-price-input:focus, #poWhItems .wh-qty-input:focus {
  border-color: var(--pri-500); box-shadow: var(--ring-accent); background: var(--n-0);
}
#poPcItems .pc-qty-input { width: 110px; }
#poPcItems .pc-price-input { width: 140px; }
#poWhItems .wh-qty-input { width: 130px; }

@media (max-width: 900px) {
  #poPcItems .pc-qty-input, #poPcItems .pc-price-input, #poWhItems .wh-qty-input {
    min-height: 44px; font-size: 16px;
  }
  #poPcItems .pc-qty-input { width: 100px; }
  #poPcItems .pc-price-input { width: 120px; }
  #poWhItems .wh-qty-input { width: 110px; }
}

/* ---------- E：其余「又小又方」的表单控件（排查同类问题后一并修正） ----------
   这三处的原始内联样式是 padding 3~6px / radius 6px / font 12~13px，
   在弹窗里明显比周围控件小一圈，观感割裂，影响小字辨识。 */
/* 批量处理：部分完成数量（原 70px / 12px 字） */
.batch-qty-input {
  width: 100px;
  min-height: 38px; padding: 8px 10px;
  font-size: 13.5px; font-family: inherit; text-align: center;
  border: 1.5px solid var(--border); border-radius: var(--r-sm);
  background: var(--bg-surface); color: var(--text); outline: none;
  transition: border-color .16s ease, box-shadow .16s ease, background .16s ease;
}
.batch-qty-input:focus { border-color: var(--pri-500); box-shadow: var(--ring-accent); background: var(--n-0); }
.batch-qty-input:disabled { background: var(--n-100); color: var(--text-mute); cursor: not-allowed; }

/* 财务「完成转款结清」（原 140px / padding 6px 8px / radius 6px） */
.pcb-amount-input, .pcb-note-input {
  min-height: 38px; padding: 8px 12px;
  font-size: 13.5px; font-family: inherit;
  border: 1.5px solid var(--border); border-radius: var(--r-sm);
  background: var(--bg-surface); color: var(--text); outline: none;
  transition: border-color .16s ease, box-shadow .16s ease, background .16s ease;
}
.pcb-amount-input:focus, .pcb-note-input:focus {
  border-color: var(--pri-500); box-shadow: var(--ring-accent); background: var(--n-0);
}
.pcb-amount-input { width: 160px; }
.pcb-note-input { flex: 1 1 auto; min-width: 180px; }

/* 检验：质量问题描述 / 让步说明（原 12px 字 / 6px 圆角） */
.qc-note-input {
  width: 100%; min-height: 64px; padding: 10px 12px;
  font-size: 13.5px; line-height: 1.6; font-family: inherit;
  border: 1.5px solid var(--border); border-radius: var(--r-sm);
  background: var(--bg-surface); color: var(--text); outline: none;
  resize: vertical;
  transition: border-color .16s ease, box-shadow .16s ease, background .16s ease;
}
.qc-note-input:focus { border-color: var(--pri-500); box-shadow: var(--ring-accent); background: var(--n-0); }
.qc-note-input::placeholder { color: var(--text-mute); }

@media (max-width: 900px) {
  .batch-qty-input { min-height: 44px; width: 110px; font-size: 16px; }
  .pcb-amount-input, .pcb-note-input { min-height: 44px; font-size: 16px; }
  .qc-note-input { font-size: 16px; }   /* 16px 防 iOS 聚焦自动放大 */
}


/* ============================================================
 * #824 移动端体验第二批 —— 手感对齐主流 App
 * 用户诉求：「离主流 APP 的使用体验差距还有一大截」→ 定位到三条真实缺口：
 *   ① 没有下拉刷新（手机用户的肌肉记忆，没有就判定"这是网页"）
 *   ② 视图切换是硬切，没有层级转场
 *   ③ 加载态是空白/转圈，不是骨架屏
 * 三条与 #793 同策略：只在 ≤900px 生效，PC 端零影响（密集操作场景不该有动画）。
 * 层级基准：#mnav=200 / #mdrawerMask=300 / .modal-overlay=100，
 *   故下拉指示器取 220（盖过底部栏但不挡抽屉），骨架屏取 40（在底部栏之下）。
 * ============================================================ */

/* ---------- 1) 下拉刷新指示器 ---------- */
.pull-refresh {
  position: fixed; top: 0; left: 50%;
  transform: translate(-50%, -100%);      /* 默认整体藏在屏幕上方 */
  z-index: 220;
  display: none;
  align-items: center; gap: 7px;
  padding: 8px 15px; border-radius: 0 0 13px 13px;
  background: var(--bg-surface); color: var(--text-soft);
  font-size: 12.5px; line-height: 1;
  box-shadow: 0 3px 12px rgba(15, 23, 42, .14);
  pointer-events: none;
  will-change: transform;
}
@media (max-width: 900px) { .pull-refresh { display: flex; } }
.pull-refresh .pr-ico {
  display: inline-flex; align-items: center; justify-content: center;
  width: 14px; height: 14px; font-size: 13px; color: var(--accent);
  transition: transform .18s ease;
}
.pull-refresh.pull-ready .pr-ico { transform: rotate(180deg); }  /* 到位后箭头翻转，暗示"松手" */
.pull-refresh.pull-busy .pr-ico {
  border-radius: 50%;
  border: 2px solid var(--pri-200); border-top-color: var(--pri-600);
  transition: none;
  animation: csjxPullSpin .7s linear infinite;
}
@keyframes csjxPullSpin { to { transform: rotate(360deg); } }

/* ---------- 2) 视图切换转场 ---------- */
/* 只在移动端播；animation 不写 fill，播完自动回到无 transform 状态，
   不会给 .view 留下 transform（避免创建 containing block 影响内部 sticky/fixed） */
@media (max-width: 900px) {
  .view.active.view-enter { animation: csjxViewEnter .21s cubic-bezier(.25, .72, .36, 1); }
}
@keyframes csjxViewEnter {
  from { opacity: 0; transform: translateX(13px); }
  to   { opacity: 1; transform: none; }
}

/* ---------- 3) 首屏骨架屏 ---------- */
.app-skeleton {
  position: fixed; inset: 0; z-index: 40;
  display: none;
  padding: 14px 14px 0;
  background: var(--bg-page);
  overflow: hidden;
}
@media (max-width: 900px) { .app-skeleton { display: block; } }
.app-skeleton.sk-out { opacity: 0; transition: opacity .16s ease; }
.app-skeleton .sk-bar {
  display: block; height: 13px; border-radius: 7px;
  background: linear-gradient(90deg, var(--n-200) 25%, var(--n-100) 37%, var(--n-200) 63%);
  background-size: 400% 100%;
  animation: csjxSkShimmer 1.35s ease-in-out infinite;
}
@keyframes csjxSkShimmer {
  0%   { background-position: 100% 50%; }
  100% { background-position: 0 50%; }
}
.app-skeleton .sk-toolbar { margin-bottom: 13px; }
.app-skeleton .sk-toolbar .sk-bar { height: 40px; border-radius: 10px; }
.app-skeleton .sk-card {
  background: var(--bg-surface); border: 1px solid var(--border-light);
  border-radius: 13px; padding: 14px; margin-bottom: 11px;
}
.app-skeleton .sk-row { display: flex; align-items: center; gap: 8px; }
.app-skeleton .sk-row + .sk-row { margin-top: 10px; }
.app-skeleton .w100 { width: 100%; }
.app-skeleton .w70  { width: 70%; }
.app-skeleton .w40  { width: 40%; }
.app-skeleton .w28  { width: 28%; }
.app-skeleton .w22  { width: 22%; }
.app-skeleton .w18  { width: 18%; }
.app-skeleton .sk-right { margin-left: auto; }

/* ---------- 4) 尊重系统"减弱动效"偏好 ---------- */
@media (prefers-reduced-motion: reduce) {
  .view.active.view-enter { animation: none; }
  .pull-refresh .pr-ico, .app-skeleton .sk-bar { animation: none; }
}


/* ============================================================
 * #824b 移动端长表单折叠 —— 把"通常无需修改"的字段组收起来
 * 依据（无头 Edge 实测 390x844，新增订单弹层）：
 *   内容总高 1993px = 2.91 屏；其中「各流程计划完成天数」382px +
 *   「各阶段负责人」543px = 925px，占全部内容的 46%，而这两块每到
 *   打开弹层都会按 settings.stageDefaultDays / stageDefaultAssignees 预填
 *   （实测配置 4/6/4/6/4/3/3 天、负责人 root×7），绝大多数情况无需修改。
 * 实现方式：**不动 index.html 结构** —— 由 JS 在移动端给已有的 h4 与容器挂 class，
 *   样式全部包在 @media (max-width:900px) → PC 端无结构变化、无样式变化。
 * 安全网：折叠头用 .fc-pill 显示「默认已填 N 项 / ⚠ N 项未填」，
 *   且保存校验失败时会自动展开（expandFormGroup），不会出现"藏在里面看不见"。
 * ============================================================ */
@media (max-width: 900px) {
  .fc-head {
    position: relative;
    min-height: 44px;                 /* 触控目标 ≥44px */
    padding-right: 30px;
    cursor: pointer;
    user-select: none;
    -webkit-tap-highlight-color: transparent;
  }
  .fc-head::after {
    content: '▾';
    position: absolute; right: 8px; top: 50%;
    transform: translateY(-50%);
    font-size: 13px; color: var(--text-mute);
    transition: transform .18s ease;
  }
  .fc-head.fc-collapsed::after { transform: translateY(-50%) rotate(-90deg); }
  /* 收起时隐藏冗长说明，只留标题 + 状态徽标（展开后自动恢复，不丢信息） */
  .fc-head.fc-collapsed .form-label-hint { display: none; }
  .fc-body.fc-collapsed { display: none; }
  .fc-pill {
    display: inline-block;
    margin-left: 6px; padding: 3px 8px;
    border-radius: 20px;
    font-size: 11.5px; font-weight: 400; line-height: 1.35;
    background: var(--n-100); color: var(--text-soft);
    vertical-align: middle;
  }
  .fc-pill.fc-pill-warn { background: var(--dgr-50); color: var(--dgr-700); }
}


/* ============================================================
 * #824c 批量完成弹窗：窄屏下零件信息被截断（老王 2026-09-16 反馈「选择某个零件时
 *   无法显示完整信息，有时候需要看到完整信息」）
 * 实测（无头 Edge，注入生产形态的长文本）：
 *   文本 =「YL0603002491 传动齿轮 40Cr φ120/模数3 齿面淬火 HRC45 ×100 （已完成 30，剩余 70）」
 *   移动端 390px：可用 230px / 需要 517px → **只显示 18 字（29%）**，被 ellipsis 吃掉；
 *   PC 1440px：可用 517px / 需要 517px → 完整显示，**因此本问题只在移动端，PC 侧无需改动**。
 * 根因：styles.css 的 .batch-item-name 是 nowrap + overflow:hidden + text-overflow:ellipsis
 *   （为 PC 表格化列表设计的一行式排版），窄屏必然溢出。
 * 修法：移动端改为换行完整显示；PC 既有规则一行不动。
 * ============================================================ */
@media (max-width: 900px) {
  .batch-item-name {
    white-space: normal;      /* 允许换行 —— 关键：完整显示零件信息 */
    overflow: visible;
    text-overflow: clip;
    overflow-wrap: break-word; /* 优先按空格/汉字边界断行；仅当单个词超出容器时才强行断（不撑破布局） */
    line-height: 1.5;
  }
  .batch-item-row { align-items: flex-start; }   /* 多行时「已 N 天」与首行文字对齐，而非垂直居中 */
  .batch-item-days { margin-top: 1px; }
}

/* ================================================================
 * #828 主题系统（6 套）—— 日间 / 夜间 / 护眼 / 淡蓝商务 / 墨绿沉稳 / 莫兰迪灰
 * ----------------------------------------------------------------
 * 设计原则：
 *  1) **不改任何原有选择器**，只在文件末尾追加 [data-theme] 变量覆盖块 →
 *     主干界面（侧栏/卡片/表格/按钮/标签）自动跟随，风险最低。
 *  2) 覆盖分两层：
 *      · 「色阶」--n-* / --pri-* 等 —— 因为大量既有规则直接用色阶变量
 *        （如 var(--n-800)），只覆盖语义变量会漏掉这些地方。
 *      · 「语义」--bg-* / --text-* / --border / --accent / 状态色 —— 让整块语义成组变化。
 *  3) 夜间模式把中性色阶「反转」（--n-0 变深、--n-800 变亮），
 *     这样 --text: var(--n-800) 等既有语义自动跟着反转，无需逐条重写。
 *  4) 状态色（超期红 / 完成绿 / 临近黄）在每套主题下都保证「仍醒目」——
 *     这是业务语义，不能被调柔到看不出警示。
 * ================================================================ */

/* ---------- ① 日间（默认，= 现有配色，无需覆盖）---------- */
[data-theme="day"] { color-scheme: light; }

/* ---------- ② 夜间 · 深底浅字，中性色阶反转 ---------- */
[data-theme="night"] {
  color-scheme: dark;
  /* 中性色阶反转：原 --n-0(白) ↔ --n-800(近黑) */
  --n-0:  #151d2e;   /* 表面（原白） */
  --n-50: #0f1626;   /* 页面底 */
  --n-100:#1b2438;
  --n-200:#2a3651;   /* 边框 */
  --n-300:#38455f;
  --n-400:#6b7c99;   /* 弱化文字 */
  --n-500:#8698b3;
  --n-600:#a9b8cf;   /* 次要文字 */
  --n-700:#c8d4e6;
  --n-800:#e6edf7;   /* 主文字 */
  --n-900:#f5f9ff;

  --bg-page: #0b1220;
  --bg-surface: #151d2e;
  --border: #2a3651;
  --border-light: #1f2a40;
  --text: #e6edf7;
  --text-soft: #a9b8cf;
  --text-mute: #6b7c99;

  --pri-50:  #1a2a48;  --pri-100: #1f3358; --pri-200: #2a4573;
  --pri-500: #4d90ff;  --pri-600: #5b9dff; --pri-700: #7db0ff;
  --accent: #5b9dff; --accent-hover: #7db0ff; --accent-light: #1a2a48;

  --suc-50: #0f2a1c;  --suc-500: #3fbf72; --suc-600: #4ade80; --suc-700: #86efac;
  --wrn-50: #2c2311;  --wrn-100: #3a2e15; --wrn-500: #f0a72c; --wrn-600: #fbbf24; --wrn-700: #fcd34d;
  --dgr-50: #2d1416;  --dgr-100: #3a1a1d; --dgr-200: #5e2529; --dgr-500: #ef5350; --dgr-600: #f87171; --dgr-700: #fca5a5;
  --inf-50: #0e2733;  --inf-100: #123344; --inf-200: #1b4a63; --inf-500: #38bdf8; --inf-600: #7dd3fc; --inf-700: #bae6fd;

  /* 阴影在深色下几乎不可见，改用更实的黑 */
  --shadow-xs: 0 1px 2px rgba(0,0,0,.35);
  --shadow-sm: 0 1px 3px rgba(0,0,0,.4);
  --shadow-md: 0 6px 16px rgba(0,0,0,.45);
  --shadow-lg: 0 12px 32px rgba(0,0,0,.5);
  --shadow-xl: 0 24px 60px rgba(0,0,0,.55);
}

/* ---------- ③ 护眼 · 米黄底 + 暖褐字，低蓝光 ---------- */
[data-theme="eye"] {
  color-scheme: light;
  --n-0:#fdfdf6; --n-50:#eef0e4; --n-100:#e7ead9; --n-200:#d5d9c4; --n-300:#c2c8ab;
  --n-400:#8b9270; --n-500:#767d5d; --n-600:#5c6344; --n-700:#4b5136; --n-800:#3b4025; --n-900:#2b2f19;
  --bg-page:#eef0e4; --bg-surface:#f7f8ee; --border:#d5d9c4; --border-light:#e4e7d8;
  --text:#3b4025; --text-soft:#5c6344; --text-mute:#8b9270;
  --pri-50:#eaeedd; --pri-100:#dde4c8; --pri-200:#c6d2a9; --pri-500:#6d8a44; --pri-600:#5f7a3a; --pri-700:#4c6330;
  --accent:#5f7a3a; --accent-hover:#4c6330; --accent-light:#e8efdc;
  --suc-50:#eef5e4; --suc-500:#5c8a34; --suc-600:#4d7c2a; --suc-700:#3d6420;
  --wrn-50:#f7f1de; --wrn-100:#efe6c8; --wrn-500:#a87a1e; --wrn-600:#8a6417; --wrn-700:#6d4e11;
  --dgr-50:#f8ece8; --dgr-100:#f0dcd6; --dgr-200:#e6c4bb; --dgr-500:#b8472f; --dgr-600:#a13a2a; --dgr-700:#7f2d20;
  --inf-50:#e8f0ee; --inf-100:#d8e8e4; --inf-200:#c4dcd9; --inf-500:#3f8a7a; --inf-600:#347063; --inf-700:#2b5c52;
  --shadow-xs:0 1px 2px rgba(60,70,30,.06);
  --shadow-sm:0 1px 3px rgba(60,70,30,.08);
  --shadow-md:0 6px 16px rgba(60,70,30,.10);
  --shadow-lg:0 12px 32px rgba(60,70,30,.12);
  --shadow-xl:0 24px 60px rgba(60,70,30,.16);
}

/* ---------- ④ 淡蓝商务 · 极淡蓝底 + 深蓝主色 ---------- */
[data-theme="business"] {
  color-scheme: light;
  --n-0:#ffffff; --n-50:#f2f6fb; --n-100:#e9eff8; --n-200:#dbe4f0; --n-300:#c6d3e6;
  --n-400:#8895a8; --n-500:#6b7a90; --n-600:#48566b; --n-700:#334054; --n-800:#182233; --n-900:#0d1420;
  --bg-page:#f2f6fb; --bg-surface:#ffffff; --border:#dbe4f0; --border-light:#e8eef7;
  --text:#182233; --text-soft:#48566b; --text-mute:#8895a8;
  --pri-50:#e7eefc; --pri-100:#d3e0f8; --pri-200:#aec7f2; --pri-500:#2560e0; --pri-600:#1d4ed8; --pri-700:#1a44bd;
  --accent:#1d4ed8; --accent-hover:#1a44bd; --accent-light:#e7eefc;
  --suc-50:#eefbf1; --suc-500:#1a9c4a; --suc-600:#166534; --suc-700:#12512a;
  --wrn-50:#fdf7ec; --wrn-100:#f8eed9; --wrn-500:#b5701a; --wrn-600:#92540a; --wrn-700:#75430a;
  --dgr-50:#fdeeee; --dgr-100:#f9dedd; --dgr-200:#f2c8c6; --dgr-500:#d63a35; --dgr-600:#c0231f; --dgr-700:#9c1c19;
  --inf-50:#ecf6fd; --inf-100:#dcedfb; --inf-200:#c2e2f6; --inf-500:#1e8fd0; --inf-600:#1a7cb5; --inf-700:#14668f;
}

/* ---------- ⑤ 墨绿沉稳 · 淡绿灰底 + 墨绿主色 ---------- */
[data-theme="forest"] {
  color-scheme: light;
  --n-0:#fcfdfb; --n-50:#edf2ed; --n-100:#e5ece3; --n-200:#d2dcd0; --n-300:#bccab9;
  --n-400:#869588; --n-500:#6c7d6f; --n-600:#48594d; --n-700:#334238; --n-800:#1e2a22; --n-900:#121b15;
  --bg-page:#edf2ed; --bg-surface:#f8faf7; --border:#d2dcd0; --border-light:#e1e8df;
  --text:#1e2a22; --text-soft:#48594d; --text-mute:#869588;
  --pri-50:#e3f0e7; --pri-100:#cfe6d7; --pri-200:#a9d0b7; --pri-500:#357a4f; --pri-600:#2e6b46; --pri-700:#255839;
  --accent:#2e6b46; --accent-hover:#255839; --accent-light:#e3f0e7;
  --suc-50:#ecf7ee; --suc-500:#2f7f3e; --suc-600:#256b34; --suc-700:#1c5428;
  --wrn-50:#f8f3e3; --wrn-100:#f1e8cd; --wrn-500:#a17518; --wrn-600:#87610f; --wrn-700:#6b4d0d;
  --dgr-50:#f9edeb; --dgr-100:#f2dcd8; --dgr-200:#e6c7c2; --dgr-500:#bb4034; --dgr-600:#a8342a; --dgr-700:#86291f;
  --inf-50:#e9f1f2; --inf-100:#d9e8ea; --inf-200:#c6dfe2; --inf-500:#3a8390; --inf-600:#327687; --inf-700:#2a6474;
}

/* ---------- ⑥ 莫兰迪灰 · 低饱和雾霾蓝，柔和不刺眼 ---------- */
[data-theme="morandi"] {
  color-scheme: light;
  --n-0:#fafbfc; --n-50:#e8eaee; --n-100:#dcdfe5; --n-200:#d2d6dd; --n-300:#c0c5ce;
  --n-400:#909aa5; --n-500:#767f8b; --n-600:#59616c; --n-700:#414852; --n-800:#2b3138; --n-900:#1c2126;
  --bg-page:#e8eaee; --bg-surface:#f4f5f7; --border:#d2d6dd; --border-light:#e1e4e9;
  --text:#2b3138; --text-soft:#59616c; --text-mute:#909aa5;
  --pri-50:#e4e9ef; --pri-100:#d5dce5; --pri-200:#bcc7d5; --pri-500:#6a7f97; --pri-600:#5b7089; --pri-700:#4a5d74;
  --accent:#5b7089; --accent-hover:#4a5d74; --accent-light:#e4e9ef;
  --suc-50:#eaf0ec; --suc-500:#568060; --suc-600:#4a7355; --suc-700:#3c5e45;
  --wrn-50:#f5f1e9; --wrn-100:#ece5d7; --wrn-500:#9b7a45; --wrn-600:#8a6b3a; --wrn-700:#6f5630;
  --dgr-50:#f5eceb; --dgr-100:#ebdbd9; --dgr-200:#ddc5c3; --dgr-500:#a85952; --dgr-600:#9b4f4a; --dgr-700:#7f3f3b;
  --inf-50:#e9eff2; --inf-100:#dae5ea; --inf-200:#cbd9df; --inf-500:#55808f; --inf-600:#4a7383; --inf-700:#3e6172;
}

/* ---------- 打印：强制走日间色 ----------
 * 深色/护眼主题下直接打印会浪费大量墨水（黑底白字），且不同主题打出来不一致。
 * 这里把所有主题在打印时统一回日间配色，保证单据打印清晰、省墨、格式统一。 */
@media print {
  :root, [data-theme] {
    --n-0:#ffffff !important; --n-50:#f8fafc !important; --n-100:#f1f5f9 !important;
    --n-200:#e2e8f0 !important; --n-300:#cbd5e1 !important; --n-400:#94a3b8 !important;
    --n-500:#64748b !important; --n-600:#475569 !important; --n-700:#334155 !important;
    --n-800:#1e293b !important; --n-900:#0f172a !important;
    --bg-page:#ffffff !important; --bg-surface:#ffffff !important;
    --border:#e2e8f0 !important; --border-light:#f1f5f9 !important;
    --text:#1e293b !important; --text-soft:#475569 !important; --text-mute:#94a3b8 !important;
    --accent:#2563eb !important; --accent-light:#eff6ff !important;
    --shadow-xs:none !important; --shadow-sm:none !important; --shadow-md:none !important;
    --shadow-lg:none !important; --shadow-xl:none !important;
    color-scheme: light !important;
  }
  body { background: #fff !important; color: #1e293b !important; padding-left: 0 !important; }
  /* 打印时隐藏纯导航性元素，避免占版面 */
  #mainNav, #mnav, #mdrawer, #mdrawerMask, .topbar-right { display: none !important; }
}

/* ================================================================
 * #828 主题选择区（个人设置弹窗内；配合 app.js 的 themePickerHtml()）
 * 注意：这里**全部使用语义变量**（--bg-surface / --border / --accent / --text），
 *      所以选择区自身也会随主题一起变色 —— 切换时能立刻看到反馈。
 * ================================================================ */
.tp-list { display: flex; flex-direction: column; gap: 6px; }

.tp-item {
  display: flex; align-items: center; gap: 10px;
  width: 100%; padding: 9px 12px;
  background: var(--bg-surface);
  border: 1.5px solid var(--border);
  border-radius: var(--r-sm);
  cursor: pointer; font-family: inherit; text-align: left;
  transition: border-color var(--t-fast), background var(--t-fast);
}
.tp-item:hover { border-color: var(--n-300); }
.tp-item.on { border-color: var(--accent); background: var(--accent-light); }

.tp-ck {
  flex: 0 0 auto; width: 18px; height: 18px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--accent); color: #fff;
  font-size: 11px; font-weight: 700; line-height: 1;
  visibility: hidden;
}
.tp-main { display: flex; flex-direction: column; min-width: 0; }
.tp-name { font-size: 13.5px; font-weight: 600; color: var(--text); }
.tp-desc { font-size: 11.5px; color: var(--text-mute); margin-top: 1px; }

/* ================================================================
 * #828b 主题入口（顶栏 🎨 浮层；从「个人设置」里挪出来）
 * 老王反馈：放在个人设置里太深、找不到 → 改为顶栏独立按钮 + 浮层。
 * 全部使用语义变量 → 浮层自身也跟着主题变色。
 * ================================================================ */
.user-info { position: relative; }   /* 让浮层以它定位 */

.theme-pop {
  position: absolute; top: calc(100% + 10px); right: 0;
  width: 234px; padding: 10px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md, 12px);
  box-shadow: var(--shadow-lg);
  z-index: 120;
}
.theme-pop-head {
  display: flex; justify-content: space-between; align-items: baseline;
  font-size: 12.5px; font-weight: 700; color: var(--text);
  padding: 2px 4px 9px;
}
.theme-pop-tip { font-size: 10.5px; font-weight: 400; color: var(--text-mute); }
.theme-pop .tp-item { padding: 7px 9px; }
.theme-pop .tp-name { font-size: 13px; }
.theme-pop .tp-desc { font-size: 11px; }

/* 移动端：顶栏空间紧张，🎨 与 ⚙ 一并隐藏，改由抽屉的「🎨 界面主题」入口承担
   （与既有规则 .topbar-right #btnSettings 保持同一处理方式） */
@media (max-width: 900px) {
  .topbar-right #btnTheme { display: none !important; }
  .theme-pop { display: none !important; }
}

/* #828b 移动端：点抽屉里的「🎨 界面主题」→ 把浮层居中显示（抽屉里没法定位到顶栏） */
@media (max-width: 900px) {
  .theme-pop.theme-pop-mobile {
    display: block !important;
    position: fixed; left: 50%; top: 50%;
    right: auto; transform: translate(-50%, -50%);
    width: min(88vw, 300px);
    z-index: 400;   /* 高于 #mdrawerMask(300) */
  }
}

/* ==========================================================================
   #838 每日一报（厂里日报）
   --------------------------------------------------------------------------
   ★ 全部颜色走主题变量（--bg-surface / --text / --dgr-500 …），
     保证 #828 的 6 套主题（日间/夜间/护眼/淡蓝商务/墨绿沉稳/莫兰迪灰）下都正常。
     禁止在本段内硬编码色值。
   ★ 类名统一 .rep- 前缀，避免与既有样式撞车（已确认无冲突）。
   ========================================================================== */

.rep-wrap { max-width: 880px; margin: 0 auto; }

/* ---------- 报头 ---------- */
.rep-hd {
  position: relative; overflow: hidden;
  padding: 22px 24px 18px; border-bottom: 1px solid var(--border);
}
.rep-hd-art { position: absolute; right: 0; top: 0; opacity: .45; pointer-events: none; }
.rep-hd-kicker {
  font-size: 11px; font-weight: 700; letter-spacing: 2px;
  color: var(--pri-500); margin-bottom: 6px;
}
.rep-hd h1 { font-size: 28px; font-weight: 800; letter-spacing: -.5px; line-height: 1.2; color: var(--text); margin: 0; }
.rep-hd-date { font-size: 12.5px; color: var(--text-soft); margin-top: 6px; }
.rep-hd-date i { font-style: normal; color: var(--text-mute); }
.rep-hd-src {
  position: absolute; right: 24px; bottom: 18px;
  font-size: 11px; color: var(--text-mute);
}

/* ---------- 头条 ---------- */
.rep-lead {
  margin: 18px 24px 0; padding: 16px 18px; border-radius: 11px;
  background: var(--pri-50); border: 1px solid var(--pri-100);
}
.rep-lead-t { font-size: 16.5px; font-weight: 700; line-height: 1.55; color: var(--text); }
.rep-lead-s { font-size: 13px; color: var(--text-soft); margin-top: 7px; line-height: 1.7; }

/* ---------- 今日实时条 ---------- */
.rep-live {
  display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
  margin: 12px 24px 0; padding: 9px 13px; border-radius: 9px;
  background: var(--n-50); border: 1px solid var(--border-light);
  font-size: 12.5px; color: var(--text-soft);
}
.rep-live .dot {
  width: 7px; height: 7px; border-radius: 50%; background: var(--suc-500);
  flex: none; animation: rep-pulse 2s ease-in-out infinite;
}
@keyframes rep-pulse { 0%,100% { opacity: 1 } 50% { opacity: .35 } }
.rep-live b { color: var(--text); font-weight: 700; }

/* ---------- 板块 ---------- */
.rep-body { padding: 0 24px; }
.rep-sec { margin-top: 26px; }
.rep-sec-hd {
  display: flex; align-items: baseline; gap: 9px;
  padding-bottom: 8px; margin-bottom: 14px;
  border-bottom: 1.5px solid var(--text);
}
.rep-sec-hd .n { font-size: 15px; font-weight: 800; letter-spacing: -.2px; color: var(--text); }
.rep-sec-hd .h { font-size: 12px; color: var(--text-mute); }

/* ---------- 数字卡 ---------- */
.rep-grid { display: grid; grid-template-columns: repeat(4, minmax(0,1fr)); gap: 10px; }
.rep-m {
  background: var(--n-50); border: 1px solid var(--border-light);
  border-radius: 10px; padding: 12px 13px;
}
.rep-m .l { font-size: 11.5px; color: var(--text-soft); font-weight: 600; }
.rep-m .n { font-size: 25px; font-weight: 800; line-height: 1.25; letter-spacing: -.8px; margin: 2px 0 0; }
.rep-m .d { font-size: 11px; color: var(--text-mute); line-height: 1.5; margin-top: 2px; }
.rep-m.is-warn { background: var(--dgr-50); border-color: var(--dgr-200); }
.rep-n-pri { color: var(--pri-500); }
.rep-n-suc { color: var(--suc-500); }
.rep-n-dgr { color: var(--dgr-500); }
.rep-n-wrn { color: var(--wrn-500); }
.rep-n-inf { color: var(--inf-500); }
.rep-dt {
  display: inline-block; font-size: 10.5px; font-weight: 700;
  padding: 1px 5px; border-radius: 5px; margin-left: 3px; white-space: nowrap;
}
.rep-dt.dn { background: var(--suc-50); color: var(--suc-500); }
.rep-dt.up { background: var(--dgr-50); color: var(--dgr-500); }

/* ---------- 图表 ---------- */
.rep-chart {
  background: var(--n-50); border: 1px solid var(--border-light);
  border-radius: 10px; padding: 14px 15px 10px; margin-top: 11px;
}
.rep-chart .ct { font-size: 12.5px; font-weight: 700; color: var(--text); }
.rep-chart .cs { font-size: 11px; color: var(--text-mute); margin: 2px 0 10px; }
.rep-two { display: grid; grid-template-columns: 1fr 1fr; gap: 11px; margin-top: 11px; }
.rep-two .rep-chart { margin-top: 0; }

/* ---------- 列表行 ---------- */
.rep-rows { margin-top: 4px; }
.rep-row {
  display: flex; justify-content: space-between; align-items: baseline; gap: 12px;
  padding: 8px 0; border-bottom: 1px solid var(--border-light); font-size: 13px;
}
.rep-row:last-child { border-bottom: none; }
.rep-row .k { color: var(--text-soft); flex: none; }
.rep-row .v { color: var(--text); font-weight: 600; text-align: right; }
.rep-row .v.soft { color: var(--text-mute); font-weight: 400; }
.rep-row .v.warn { color: var(--dgr-500); }

/* ---------- 人物 ---------- */
.rep-ppl { display: grid; grid-template-columns: repeat(4, minmax(0,1fr)); gap: 10px; }
.rep-p {
  background: var(--n-50); border: 1px solid var(--border-light);
  border-radius: 10px; padding: 12px 10px; text-align: center;
}
.rep-p .av {
  width: 38px; height: 38px; border-radius: 50%; margin: 0 auto 7px;
  display: flex; align-items: center; justify-content: center;
  font-size: 15px; font-weight: 800; color: #fff;
}
.rep-p .nm { font-size: 12.5px; font-weight: 700; line-height: 1.3; color: var(--text); }
.rep-p .rl { font-size: 10.5px; color: var(--text-mute); margin-top: 1px; }
.rep-p .ct { font-size: 11px; color: var(--pri-500); font-weight: 700; margin-top: 5px; }

/* ---------- 待处理（严肃） ---------- */
.rep-todo {
  background: var(--dgr-50); border: 1px solid var(--dgr-200);
  border-radius: 11px; padding: 14px 16px;
}
.rep-todo-i {
  display: flex; gap: 10px; padding: 6px 0;
  font-size: 13px; line-height: 1.65; color: var(--text);
}
.rep-todo-i .b {
  flex: none; width: 64px; text-align: right; padding-top: 2px;
  font-size: 11px; font-weight: 800; color: var(--dgr-500);
}

/* ---------- 花絮（轻松） ---------- */
.rep-fun {
  background: var(--wrn-50); border: 1px solid var(--wrn-100);
  border-radius: 11px; padding: 14px 16px;
}
.rep-fun-i { display: flex; gap: 10px; padding: 6px 0; font-size: 13px; line-height: 1.65; }
.rep-fun-i .b {
  flex: none; width: 64px; text-align: right; padding-top: 2px;
  font-size: 11px; font-weight: 800; color: var(--wrn-500);
}
/* ---- #838m 费用「传附件」类型选择弹层 ---- */
.exp-att-picker-mask {
  position: fixed; inset: 0; z-index: 10000; background: rgba(15, 23, 42, .45);
  display: flex; align-items: center; justify-content: center; padding: 20px;
  animation: eatpIn .16s ease;
}
@keyframes eatpIn { from { opacity: 0 } to { opacity: 1 } }
.exp-att-picker-mask .eatp {
  width: 100%; max-width: 400px; background: var(--surface, #fff);
  border: 1px solid var(--border-light); border-radius: 14px; padding: 18px;
  box-shadow: 0 18px 48px rgba(0, 0, 0, .22);
  max-height: 86vh; overflow: auto;
}
.exp-att-picker-mask .eatp-hd { display: flex; align-items: center; justify-content: space-between;
  font-size: 15px; font-weight: 800; color: var(--text); margin-bottom: 4px; }
.exp-att-picker-mask .eatp-x { border: 0; background: transparent; font-size: 16px; cursor: pointer;
  color: var(--text-mute); padding: 2px 6px; border-radius: 6px; font-family: inherit; }
.exp-att-picker-mask .eatp-x:hover { background: var(--bg-soft); }
.exp-att-picker-mask .eatp-sub { font-size: 12px; color: var(--text-mute); margin-bottom: 14px; }
.exp-att-picker-mask .eatp-i {
  width: 100%; display: flex; align-items: center; gap: 12px; text-align: left;
  padding: 12px 14px; margin-bottom: 8px; cursor: pointer; font-family: inherit;
  background: var(--bg-soft); border: 1px solid var(--border-light); border-radius: 10px;
  transition: border-color .15s, background .15s;
}
.exp-att-picker-mask .eatp-i:hover { border-color: var(--pri-500); background: var(--pri-50, rgba(74,158,255,.07)); }
.exp-att-picker-mask .eatp-i .ic { font-size: 20px; flex: none; }
.exp-att-picker-mask .eatp-i .tx { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.exp-att-picker-mask .eatp-i .tx b { font-size: 13.5px; color: var(--text); font-weight: 700; }
.exp-att-picker-mask .eatp-i .tx i { font-size: 11.5px; color: var(--text-mute); font-style: normal; }
.exp-att-picker-mask .eatp-i .ar { color: var(--text-mute); flex: none; }

/* #838o 附件管理：已有附件列表 / 删除 / 分区标题 */
.exp-att-picker-mask .eatp-sect { font-size: 12px; font-weight: 800; color: var(--text-soft);
  margin: 14px 0 6px; letter-spacing: .02em; }
.exp-att-picker-mask .eatp-sect:first-of-type { margin-top: 4px; }
.exp-att-picker-mask .eatp-badge { font-size: 10.5px; font-weight: 700; color: var(--wrn-700, #b45309);
  background: rgba(240,169,46,.14); padding: 1px 7px; border-radius: 99px; }
.exp-att-picker-mask .eatp-row { display: flex; align-items: center; gap: 10px;
  padding: 8px 10px; border: 1px solid var(--border-light); border-radius: 9px;
  background: var(--surface, #fff); margin-bottom: 6px; }
.exp-att-picker-mask .eatp-row .ic { font-size: 16px; flex: none; }
.exp-att-picker-mask .eatp-row .tx { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.exp-att-picker-mask .eatp-row .tx b { font-size: 12.5px; color: var(--text); font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.exp-att-picker-mask .eatp-row .tx i { font-size: 11px; color: var(--text-mute); font-style: normal; }
.exp-att-picker-mask .eatp-dl { flex: none; font-size: 12px; color: var(--pri-600); text-decoration: none;
  padding: 2px 8px; border-radius: 6px; border: 1px solid var(--border-light); }
.exp-att-picker-mask .eatp-dl:hover { border-color: var(--pri-500); }
.exp-att-picker-mask .eatp-del { flex: none; border: 1px solid var(--border-light); background: transparent;
  cursor: pointer; font-size: 13px; padding: 2px 8px; border-radius: 6px; font-family: inherit;
  color: var(--dgr-600, #dc2626); }
.exp-att-picker-mask .eatp-del:hover { background: rgba(220,38,38,.08); border-color: var(--dgr-600, #dc2626); }
.exp-att-picker-mask .eatp-empty { font-size: 12px; color: var(--text-mute); padding: 8px 2px; }
.exp-att-picker-mask .eatp-foot { font-size: 11.5px; color: var(--text-mute); margin-top: 10px;
  padding-top: 10px; border-top: 1px dashed var(--border-light); }
/* 卡片按钮上的附件数量角标 */
.exp-card .btn .exp-att-n { display: inline-block; margin-left: 4px; font-size: 10.5px; font-weight: 800;
  background: var(--pri-500); color: #fff; border-radius: 99px; padding: 0 5px; line-height: 15px;
  vertical-align: 1px; }

/* ---- #838k 费用附件上传进度（参考采购报销 #652 的体验） ---- */
.exp-up-progress {
  position: fixed; left: 50%; bottom: 28px; transform: translateX(-50%); z-index: 9999;
  min-width: 260px; max-width: 86vw; padding: 14px 18px;
  background: var(--surface, #fff); border: 1px solid var(--border-light); border-radius: 12px;
  box-shadow: 0 8px 28px rgba(0, 0, 0, .16);
}
.exp-up-progress .eup-t { font-size: 13px; color: var(--text); margin-bottom: 8px; }
.exp-up-progress .eup-bar { height: 6px; background: var(--border-light); border-radius: 99px; overflow: hidden; }
.exp-up-progress .eup-fill { display: block; height: 100%; width: 0;
  background: linear-gradient(90deg, var(--pri-500), var(--suc-500)); border-radius: 99px;
  transition: width .2s ease; }
.exp-up-progress .eup-p { font-size: 11.5px; color: var(--text-mute); margin-top: 6px; text-align: right;
  font-family: ui-monospace, Consolas, monospace; }

.rep-fun-i .x { color: var(--text-soft); }

/* ---- #838k 订单生产流程：阶段瓶颈条形图 / 明细列表 / 文案条目 ---- */
.rep-bars { margin-top: 14px; padding: 14px 16px; background: var(--surface-2, var(--bg-soft));
  border: 1px solid var(--border-light); border-radius: 12px; }
.rep-bars .lt { font-size: 12.5px; font-weight: 700; color: var(--text); margin-bottom: 10px; }
.bar-row { display: grid; grid-template-columns: 92px 1fr 66px; align-items: center; gap: 10px;
  padding: 3px 0; }
.bar-row .bl { font-size: 12px; color: var(--text-soft); white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis; }
.bar-row.top .bl { font-weight: 800; color: var(--text); }
.bar-row .bt { height: 14px; background: var(--border-light); border-radius: 4px; overflow: hidden;
  display: block; }
.bar-row .bf { display: block; height: 100%; background: var(--pri-500); border-radius: 4px;
  position: relative; }
.bar-row.top .bf { background: var(--wrn-500, #f0a92e); }
.bar-row .bo { display: block; height: 100%; background: var(--dgr, #e5484d); border-radius: 4px;
  position: absolute; right: 0; top: 0; }
.bar-row .bv { font-size: 11.5px; font-weight: 700; color: var(--text); text-align: right;
  white-space: nowrap; }
.bar-row .bv b { color: var(--dgr, #e5484d); font-weight: 700; }
.bf-note { font-size: 11px; color: var(--text-mute); margin-top: 8px; }

.rep-list { margin-top: 14px; padding: 12px 16px; background: var(--bg-soft);
  border: 1px solid var(--border-light); border-radius: 12px; }
.rep-list .lt { font-size: 12.5px; font-weight: 700; color: var(--text); margin-bottom: 6px; }
.rep-list .li { display: flex; justify-content: space-between; gap: 12px; font-size: 12.5px;
  padding: 4px 0; border-top: 1px dashed var(--border-light); }
.rep-list .li:first-of-type { border-top: 0; }
.rep-list .li .k { color: var(--text); font-weight: 600; font-family: ui-monospace, Consolas, monospace;
  white-space: nowrap; }
.rep-list .li .v { color: var(--text-soft); text-align: right; }

.rep-flow { margin-top: 14px; display: grid; gap: 8px; }
.rep-flow .ff { display: flex; gap: 10px; align-items: baseline; font-size: 13px; line-height: 1.65; }
.rep-flow .ft { flex: none; font-size: 11.5px; font-weight: 700; color: var(--pri-600);
  background: var(--pri-50, rgba(74,158,255,.1)); padding: 1px 8px; border-radius: 99px;
  white-space: nowrap; }
.rep-flow .fx { color: var(--text-soft); }
@media (max-width: 640px) {
  .bar-row { grid-template-columns: 68px 1fr 56px; }
  .bar-row .bl { font-size: 11px; }
  .rep-list .li { flex-direction: column; gap: 2px; }
  .rep-list .li .v { text-align: left; }
}

/* ---------- 脚注 ---------- */
.rep-ft {
  margin: 26px 24px 0; padding-top: 14px;
  border-top: 1px solid var(--border);
  font-size: 11.5px; color: var(--text-mute); line-height: 1.75;
}
.rep-ft b { color: var(--text-soft); }

/* ---------- 空态 ---------- */
.rep-empty { padding: 48px 24px; text-align: center; color: var(--text-mute); font-size: 13px; }

/* ---------- 日期切换 ---------- */
.rep-nav {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 10px 24px 0;
}
.rep-nav select {
  font-size: 12.5px; padding: 4px 8px; border-radius: 7px;
  border: 1px solid var(--border); background: var(--bg-surface); color: var(--text);
}

/* ==========================================================================
   登录后自动弹出的日报浮层
   PC：居中面板；移动端：接近全屏（像 App 的一次性卡片）
   ========================================================================== */
.rep-mask {
  position: fixed; inset: 0; z-index: 600;
  background: rgba(0,0,0,.48);
  display: none; align-items: center; justify-content: center;
  padding: 20px;
}
.rep-mask.show { display: flex; }
.rep-modal {
  background: var(--bg-surface); color: var(--text);
  width: min(96vw, 900px); max-height: min(90vh, 900px);
  border-radius: 14px; overflow: hidden;
  display: flex; flex-direction: column;
  box-shadow: var(--shadow-xl);
  animation: rep-pop .22s ease-out;
}
@keyframes rep-pop { from { opacity: 0; transform: translateY(10px) scale(.99) } to { opacity: 1; transform: none } }
.rep-modal-hd {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 13px 18px; border-bottom: 1px solid var(--border);
  flex: none;
}
.rep-modal-hd .t { font-size: 14px; font-weight: 700; color: var(--text); }
.rep-modal-hd .t span { font-size: 12px; font-weight: 400; color: var(--text-mute); margin-left: 8px; }
.rep-modal-x {
  border: 1px solid var(--border); background: transparent; color: var(--text-soft);
  width: 30px; height: 30px; border-radius: 8px; cursor: pointer; font-size: 15px;
  display: flex; align-items: center; justify-content: center; flex: none;
}
.rep-modal-x:hover { border-color: var(--border); background: var(--n-50); color: var(--text); }
.rep-modal-bd { overflow-y: auto; flex: 1; -webkit-overflow-scrolling: touch; padding-bottom: 18px; }
.rep-modal-ft {
  flex: none; padding: 11px 18px; border-top: 1px solid var(--border);
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  font-size: 11.5px; color: var(--text-mute);
}
.rep-modal-ft button {
  border: 1px solid var(--pri-500); background: var(--pri-500); color: #fff;
  padding: 7px 16px; border-radius: 8px; font-size: 13px; font-weight: 600; cursor: pointer;
}
.rep-modal-ft button:hover { background: var(--pri-600); border-color: var(--pri-600); }

/* ---------- 窄屏 ---------- */
@media (max-width: 900px) {
  .rep-hd { padding: 18px 16px 15px; }
  .rep-hd h1 { font-size: 23px; }
  .rep-hd-art { display: none; }
  .rep-hd-src { position: static; display: block; margin-top: 6px; }
  .rep-lead { margin: 14px 16px 0; padding: 14px 15px; }
  .rep-lead-t { font-size: 15.5px; }
  .rep-live { margin: 10px 16px 0; }
  .rep-body { padding: 0 16px; }
  .rep-grid, .rep-ppl { grid-template-columns: repeat(2, minmax(0,1fr)); }
  .rep-two { grid-template-columns: 1fr; }
  .rep-ft { margin: 22px 16px 0; }
  .rep-nav { padding: 10px 16px 0; }
  .rep-mask { padding: 0; align-items: stretch; }
  .rep-modal {
    width: 100vw; max-height: 100vh; height: 100vh; border-radius: 0;
  }
  .rep-modal-hd { padding: 12px 14px; padding-top: max(12px, env(safe-area-inset-top)); }
  .rep-modal-ft { padding-bottom: max(11px, var(--sys-bottom, env(safe-area-inset-bottom, 0px))); }
}

/* ================================================================
 * #842 订单进度版块重构 —— 样式
 * ----------------------------------------------------------------
 * 结构：汇总条（.pg-sum）+ 清单视图（.pg-list）+ 时间轴视图（.gantt-*）
 * 约定：
 *  · 全部使用语义变量（--bg-surface / --border / --text / --accent 等）→ 自动跟随 6 套主题
 *  · 状态色沿用系统既有语义：超期=红 / 临近=橙 / 进行中=蓝 / 完成=绿
 *  · 移动端改动**一律包在 @media (max-width:900px)** 内，PC 端不受影响
 * ================================================================ */

/* ---------- 视图切换（清单 / 时间轴）---------- */
.pg-viewsw { display: inline-flex; border: 1px solid var(--border); border-radius: var(--r-sm); overflow: hidden; background: var(--bg-surface); }
.pg-viewbtn {
  border: none; background: transparent; cursor: pointer; font-family: inherit;
  padding: 7px 15px; font-size: 13px; color: var(--text-soft);
  transition: background var(--t-fast), color var(--t-fast);
}
.pg-viewbtn:hover { background: var(--n-50); }
.pg-viewbtn.on { background: var(--accent); color: #fff; font-weight: 600; }

/* ---------- 汇总条（可点击筛选）---------- */
.pg-sum { display: flex; gap: 8px; flex-wrap: wrap; margin: 2px 0 14px; }
.pg-chip {
  display: flex; flex-direction: column; gap: 1px; align-items: flex-start;
  border: 1px solid var(--border); border-radius: 10px; background: var(--bg-surface);
  padding: 8px 14px; cursor: pointer; font-family: inherit; min-width: 104px;
  transition: border-color var(--t-fast), box-shadow var(--t-fast);
}
.pg-chip:hover { border-color: var(--n-300); }
.pg-chip .pg-chip-n { font-size: 11.5px; color: var(--text-soft); }
.pg-chip .pg-chip-v { font-size: 20px; font-weight: 650; color: var(--text); font-variant-numeric: tabular-nums; line-height: 1.2; }
.pg-chip.on { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-light); }
.pg-chip.c-red .pg-chip-v { color: var(--dgr-600); }
.pg-chip.c-amber .pg-chip-v { color: var(--wrn-600); }
.pg-chip.c-blue .pg-chip-v { color: var(--pri-600); }
.pg-chip.c-green .pg-chip-v { color: var(--suc-600); }

/* ---------- 清单视图 ---------- */
.pg-list-head {
  display: grid; grid-template-columns: 1.35fr 1fr 1.15fr 0.75fr; gap: 12px;
  padding: 0 14px 7px; font-size: 11.5px; color: var(--text-mute);
  border-bottom: 1px solid var(--border-light);
}
.pg-list { display: flex; flex-direction: column; gap: 8px; margin-top: 10px; }

.pg-row {
  display: grid; grid-template-columns: 1.35fr 1fr 1.15fr 0.75fr; gap: 12px;
  align-items: center; background: var(--bg-surface);
  border: 1px solid var(--border); border-left: 4px solid var(--n-300);
  border-radius: 10px; padding: 11px 14px; cursor: pointer;
  transition: border-color var(--t-fast), box-shadow var(--t-fast), transform var(--t-fast);
}
.pg-row:hover { box-shadow: var(--shadow-sm); }
.pg-row:active { transform: scale(.997); }
.pg-row.r-red { border-left-color: var(--dgr-600); background: var(--dgr-50); }
.pg-row.r-amber { border-left-color: var(--wrn-600); background: var(--wrn-50); }
.pg-row.r-blue { border-left-color: var(--pri-600); }
.pg-row.r-green { border-left-color: var(--suc-600); }

.pg-c1 { min-width: 0; }
.pg-no { font-size: 13.5px; font-weight: 650; color: var(--text); display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.pg-sub { font-size: 11.5px; color: var(--text-soft); margin-top: 3px; overflow-wrap: anywhere; }

.pg-tag { display: inline-block; padding: 1px 7px; border-radius: 5px; font-size: 11px; font-weight: 600; border: 1px solid; white-space: nowrap; }
.pg-tag.t-red { background: var(--dgr-100); color: var(--dgr-700); border-color: var(--dgr-200); }
.pg-tag.t-amber { background: var(--wrn-100); color: var(--wrn-700); border-color: var(--wrn-100); }
.pg-tag.t-blue { background: var(--pri-100); color: var(--pri-700); border-color: var(--pri-200); }
.pg-tag.t-gray { background: var(--n-100); color: var(--n-600); border-color: var(--n-200); }

.pg-c2 { min-width: 0; }
.pg-ph { display: flex; justify-content: space-between; font-size: 11.5px; color: var(--text-soft); gap: 8px; }
.pg-ph b { color: var(--text); font-variant-numeric: tabular-nums; }
.pg-ph2 { margin-top: 5px; }
.pg-bar { height: 8px; background: var(--n-100); border-radius: 99px; overflow: hidden; margin: 4px 0 0; }
.pg-bar i { display: block; height: 100%; border-radius: 99px; }
.pg-bar i.d { background: var(--suc-600); }
.pg-stall { color: var(--text-mute); white-space: nowrap; }
.pg-stall.bad { color: var(--dgr-600); font-weight: 600; }

.pg-c3 { text-align: right; }
.pg-dl-t { font-size: 11px; color: var(--text-mute); }
.pg-dl-v { font-size: 15px; font-weight: 650; font-variant-numeric: tabular-nums; line-height: 1.35; }
.pg-dl-s { font-size: 11px; color: var(--text-mute); }
.pg-c3.ddl-red .pg-dl-v { color: var(--dgr-600); }
.pg-c3.ddl-amber .pg-dl-v { color: var(--wrn-600); }
.pg-c3.ddl-ok .pg-dl-v { color: var(--suc-600); }

.pg-c4 { font-size: 12.5px; color: var(--text-soft); text-align: right; overflow-wrap: anywhere; }
.pg-role { font-size: 11px; color: var(--text-mute); margin-top: 2px; }

/* ---------- 时间轴视图：#842 补强 ---------- */

/* 超期红块：已过交期且未完成的区段 —— 解决"23 个超期图上看不出" */
.gantt-cell.gantt-overdue { background: var(--dgr-500); }

/* 今天所在列：表头高亮 + 每行浅底色，让用户知道"现在在哪" */
.gantt-day.gantt-today-col { color: var(--accent); font-weight: 700; }
.gantt-cell.gantt-today-cell { box-shadow: inset 1px 0 0 var(--accent), inset -1px 0 0 var(--accent); }

/* 交期标记：在交期那一列画一条橙色竖线 */
.gantt-cell.gantt-dl-cell { box-shadow: inset 2px 0 0 var(--wrn-500); }
.gantt-cell.gantt-dl-cell.gantt-today-cell { box-shadow: inset 2px 0 0 var(--wrn-500), inset -1px 0 0 var(--accent); }

/* 行内「超期」小标签 */
.gantt-ovd-tag {
  display: inline-block; margin-left: 4px; padding: 0 5px; border-radius: 4px;
  background: var(--dgr-100); color: var(--dgr-700); border: 1px solid var(--dgr-200);
  font-size: 10.5px; font-weight: 700;
}

/* 行标签不再截断（原为 ellipsis，客户名与件数都看不到）—— 允许换行 */
.gantt-label {
  white-space: normal !important;
  overflow: visible !important;
  text-overflow: clip !important;
  word-break: break-word;
  line-height: 1.35;
}

/* 时间轴图例 */
.gantt-legend {
  display: flex; gap: 14px; flex-wrap: wrap; font-size: 11.5px; color: var(--text-soft);
  margin-top: 12px; padding-top: 10px; border-top: 1px dashed var(--border);
}
.gantt-legend i { display: inline-block; width: 11px; height: 11px; border-radius: 3px; margin-right: 5px; vertical-align: -1px; }

/* ---------- 移动端（≤900px）：清单改卡片纵排，时间轴不画 ---------- */
@media (max-width: 900px) {
  .pg-viewsw { width: 100%; }
  .pg-viewbtn { flex: 1 1 50%; text-align: center; }

  .pg-sum { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 7px; }
  .pg-chip { min-width: 0; padding: 7px 11px; }
  .pg-chip .pg-chip-v { font-size: 18px; }

  .pg-list-head { display: none; }               /* 窄屏不显示表头，避免与卡片错位 */

  .pg-row {
    grid-template-columns: 1fr;                  /* 单列卡片，永不横向溢出 */
    gap: 9px; padding: 12px 13px;
  }
  .pg-c1 { order: 1; }
  .pg-c2 { order: 2; }
  .pg-c3 { order: 3; text-align: left; display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
  .pg-c3 .pg-dl-t { display: none; }
  .pg-c3 .pg-dl-s { margin-left: auto; }
  .pg-c4 { order: 4; text-align: left; }

  /* 移动端时间轴：仍可用，但提示横滑（既有 centerGanttOnToday 仍生效） */
  .gantt-legend { font-size: 11px; gap: 10px; }
}

/* ============ #835c 权限中心 ============ */
.perm-overview{margin-bottom:16px}
.perm-cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:12px;margin-bottom:14px}
.perm-card{background:var(--bg-secondary,#f7f8fa);border:1px solid var(--border-color,#e5e6eb);border-radius:10px;padding:14px 16px;text-align:center}
.perm-card.warn{border-color:#f0a92e;background:#fffaf0}
.perm-card .v{font-size:24px;font-weight:700;font-family:ui-monospace,Consolas,monospace;line-height:1.2}
.perm-card .t{font-size:12px;color:var(--text-mute,#8b93a5);margin-top:2px}
.perm-leads-wrap{background:var(--bg-secondary,#f7f8fa);border:1px solid var(--border-color,#e5e6eb);border-radius:10px;padding:14px 16px}
.perm-sec-title{font-size:13px;font-weight:600;margin-bottom:10px;color:var(--text-2,#4b5568)}
.perm-lead{display:flex;justify-content:space-between;padding:5px 0;border-bottom:1px dashed var(--border-color,#e5e6eb);font-size:13px}
.perm-lead:last-child{border-bottom:none}
.perm-lead-k{color:var(--text-mute,#8b93a5)}
.perm-lead-v{font-weight:600}
.perm-lead-v.empty{color:#e5484d;font-weight:400}
.perm-health{margin-bottom:16px}
.perm-health-ok{background:#f0fdf4;border:1px solid #86efac;color:#15803d;border-radius:10px;padding:12px 14px;font-size:13px}
.perm-health-head{background:#fffbeb;border:1px solid #fcd34d;color:#92400e;border-radius:10px;padding:12px 14px;font-size:13px;margin-bottom:10px}
.perm-issue{border-radius:8px;padding:10px 12px;margin-bottom:8px;font-size:13px;border:1px solid}
.perm-issue.err{background:#fef2f2;border-color:#fecaca;color:#b91c1c}
.perm-issue.warn{background:#fffbeb;border-color:#fcd34d;color:#92400e}
.perm-issue.info{background:#f0f9ff;border-color:#bae6fd;color:#075985}
.perm-issue-d{margin-top:4px;font-weight:400;opacity:.85;word-break:break-all}
.perm-matrix{overflow-x:auto;background:#fff;border:1px solid var(--border-color,#e5e6eb);border-radius:10px}
.perm-table{width:100%;border-collapse:collapse;font-size:13px}
.perm-table th{background:var(--bg-secondary,#f7f8fa);padding:9px 10px;font-weight:600;font-size:12px;color:var(--text-2,#4b5568);border-bottom:1px solid var(--border-color,#e5e6eb);white-space:nowrap}
.perm-th-name{text-align:left;min-width:220px}
.perm-td{padding:7px 10px;text-align:center;border-bottom:1px solid var(--border-color,#eef0f4);cursor:pointer;user-select:none;font-family:ui-monospace,Consolas,monospace}
.perm-td:hover{background:#f0f6ff}
.perm-td.yes{color:#15803d;font-weight:700}
.perm-td.no{color:#c2c8d4}
.perm-td.owner{color:#b45309;font-weight:600;font-size:12px}
.perm-td-name{padding:7px 10px;border-bottom:1px solid var(--border-color,#eef0f4)}
.perm-pn{font-weight:600}
.perm-pid{font-size:11px;color:var(--text-mute,#8b93a5);font-family:ui-monospace,Consolas,monospace}
.perm-td-op{text-align:right;padding-right:10px;border-bottom:1px solid var(--border-color,#eef0f4)}
.perm-group-row td{background:#f2f5fa;font-weight:700;font-size:12.5px;color:#334155;padding:8px 10px;letter-spacing:.4px}
.perm-legend{margin-top:10px;font-size:12px;color:var(--text-mute,#8b93a5);padding:0 2px}
@media(max-width:900px){.perm-table{font-size:11.5px}.perm-pid{display:none}}

/* ============ #835e 权限中心（重做：引导 + 操作入口） ============ */
.perm-guide{background:linear-gradient(180deg,#f6f9ff,#fff);border:1px solid #d6e4ff;border-radius:12px;padding:16px 18px;margin-bottom:16px}
.pg-lead{font-size:14px;line-height:1.8;color:#1f2d3d;margin-bottom:14px}
.pg-steps{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:12px}
.pg-step{display:flex;gap:10px;background:#fff;border:1px solid #e5eaf3;border-radius:10px;padding:12px 14px}
.pg-n{flex:none;width:22px;height:22px;border-radius:50%;background:#2f6fed;color:#fff;font-size:12px;font-weight:700;display:flex;align-items:center;justify-content:center}
.pg-step b{font-size:13.5px;color:#1f2d3d}
.pg-d{font-size:12.5px;color:#6b7794;margin-top:3px;line-height:1.6}
.pg-stat{margin-top:12px;font-size:12.5px;color:#6b7794;padding-top:10px;border-top:1px dashed #e5eaf3}
.pg-warn{color:#d97706}
.perm-block{background:#fff;border:1px solid #e5e6eb;border-radius:12px;padding:16px 18px;margin-bottom:16px}
.perm-sec-hd{display:flex;justify-content:space-between;align-items:flex-start;gap:12px;margin-bottom:14px;flex-wrap:wrap}
.perm-sec-hd b{font-size:14.5px}
.perm-sec-sub{display:block;font-size:12.5px;color:#8b93a5;margin-top:4px;line-height:1.6;font-weight:400}
.perm-lead-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:14px}
.perm-lead-item label{display:block;font-size:13px;font-weight:600;margin-bottom:6px;color:#1f2d3d}
.perm-lead-item select{width:100%;padding:7px 9px;border:1px solid #d9dee8;border-radius:8px;font-size:13px;background:#fff}
.perm-lead-desc{font-size:12px;color:#8b93a5;margin-top:6px;line-height:1.6}
.perm-qtab{display:flex;gap:6px}
.perm-qbar{display:flex;align-items:center;gap:8px;margin-bottom:12px;flex-wrap:wrap}
.perm-qbar label{font-size:13px;color:#4b5568}
.perm-qbar select,.perm-qbar input{padding:7px 10px;border:1px solid #d9dee8;border-radius:8px;font-size:13px;min-width:200px}
.perm-qout{background:#fafbfd;border:1px solid #eef1f6;border-radius:10px;padding:12px 14px}
.perm-qhead{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:10px}
.perm-tag{background:#e8f0ff;color:#2f6fed;font-size:11.5px;padding:2px 8px;border-radius:5px;font-weight:600}
.perm-qsum{font-size:12.5px;color:#6b7794}
.perm-qgroup{margin-bottom:10px}
.perm-qg-title{font-size:12px;font-weight:700;color:#334155;margin-bottom:6px;letter-spacing:.5px}
.perm-chips{display:flex;flex-wrap:wrap;gap:6px}
.perm-chip{background:#eef6ee;color:#15803d;border:1px solid #cdeacd;font-size:12px;padding:3px 9px;border-radius:6px}
.perm-chip.own{background:#fff7ed;color:#b45309;border-color:#fed7aa}
.perm-chip.none{background:#f4f5f7;color:#8b93a5;border-color:#e5e6eb}
.perm-note{font-size:12.5px;color:#6b7794;background:#fff;border:1px solid #eef1f6;border-radius:8px;padding:9px 11px;margin-top:10px;line-height:1.7}
.perm-note.ok{background:#f0fdf4;border-color:#bbf7d0;color:#15803d}
.perm-frow{display:flex;justify-content:space-between;gap:14px;padding:10px 0;border-bottom:1px dashed #eef1f6;flex-wrap:wrap}
.perm-frow:last-child{border-bottom:none}
.perm-fname b{font-size:13px}
.perm-fnote{font-size:12px;color:#8b93a5;margin-top:3px}
.perm-fwho{display:flex;gap:6px;flex-wrap:wrap;align-items:flex-start}
.perm-search{padding:7px 11px;border:1px solid #d9dee8;border-radius:8px;font-size:13px;min-width:240px}
.perm-tbl-wrap{overflow:auto;max-height:560px;border:1px solid #eef1f6;border-radius:8px}
.perm-table thead th{position:sticky;top:0;z-index:2}
.perm-health-sub{font-size:12px;font-weight:400;opacity:.85;margin-top:5px;line-height:1.6}
.perm-loading{padding:26px;text-align:center;color:#8b93a5;font-size:13px}
.perm-error{padding:16px;color:#b91c1c;font-size:13px;background:#fef2f2;border:1px solid #fecaca;border-radius:8px}
.perm-error-hint{font-size:12.5px;color:#991b1b;opacity:.85;margin-top:6px}
.perm-hint{padding:12px;color:#8b93a5;font-size:13px}
.perm-legend-note{float:right;color:#a8b0c0}
@media(max-width:900px){
  .perm-sec-hd{flex-direction:column;align-items:stretch}
  .perm-search{width:100%;min-width:0}
  .perm-tbl-wrap{max-height:420px}
}

/* ============ #835f 角色管理 / 用户管理 ============ */
.role-cards{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:12px}
.role-card{border:1px solid #e5e6eb;border-radius:10px;padding:13px 15px;cursor:pointer;background:#fff;transition:.15s}
.role-card:hover{border-color:#9db8ef;box-shadow:0 2px 8px rgba(47,111,237,.08)}
.role-card.active{border-color:#2f6fed;background:#f7faff;box-shadow:0 2px 10px rgba(47,111,237,.14)}
.rc-head{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-bottom:6px}
.rc-head b{font-size:14px}
.perm-tag.single{background:#fff7ed;color:#c2410c}
.perm-tag.custom{background:#f5f3ff;color:#7c3aed}
.rc-desc{font-size:12px;color:#8b93a5;line-height:1.6;min-height:32px}
.rc-foot{display:flex;justify-content:space-between;gap:8px;font-size:12px;color:#5a6b82;margin-top:9px;padding-top:8px;border-top:1px dashed #eef1f6;flex-wrap:wrap}
.rp-wrap{border:1px solid #eef1f6;border-radius:8px;overflow:hidden}
.rp-group{border-bottom:1px solid #eef1f6}
.rp-group:last-child{border-bottom:none}
.rp-group>summary{cursor:pointer;padding:10px 14px;font-size:13px;font-weight:600;background:#f8fafc;color:#334155;display:flex;justify-content:space-between;align-items:center}
.rp-group>summary::-webkit-details-marker{display:none}
.rp-count{font-size:12px;font-weight:400;color:#8b93a5}
.rp-body{padding:6px 0}
.rp-row{display:flex;align-items:center;gap:10px;padding:7px 14px;cursor:pointer;font-size:13px}
.rp-row:hover{background:#f8fafc}
.rp-row.on{background:#f6fdf8}
.rp-row input{flex:none;width:15px;height:15px;cursor:pointer}
.rp-name{min-width:150px;font-weight:500}
.rp-note{font-size:12px;color:#8b93a5;flex:1}
.role-form .form-row{display:flex;align-items:center;gap:10px;margin-bottom:10px}
.role-form label{width:80px;font-size:13px;color:#4b5568;flex:none}
.role-form input{flex:1;padding:8px 10px;border:1px solid #d9dee8;border-radius:8px;font-size:13px}
.role-presets{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:12px}
.role-preset{border:1px solid #e5e6eb;border-radius:10px;padding:12px 14px;cursor:pointer;background:#fff}
.role-preset:hover{border-color:#2f6fed;background:#f7faff}
.role-preset b{font-size:13.5px}
.rp-desc{font-size:12px;color:#8b93a5;margin-top:5px;line-height:1.6}
.rp-pts{font-size:11.5px;color:#2f6fed;margin-top:7px}
.role-sheet-mask{position:fixed;inset:0;background:rgba(15,23,42,.42);z-index:1000;display:flex;align-items:center;justify-content:center;padding:20px}
.role-sheet{background:#fff;border-radius:12px;max-width:720px;width:100%;max-height:86vh;display:flex;flex-direction:column;overflow:hidden}
.rs-hd{display:flex;justify-content:space-between;align-items:center;padding:14px 18px;border-bottom:1px solid #eef1f6;font-weight:600}
.rs-body{padding:18px;overflow:auto}
.user-form-row{display:flex;gap:10px;flex-wrap:wrap;align-items:center}
.user-form-row input,.user-form-row select{padding:8px 10px;border:1px solid #d9dee8;border-radius:8px;font-size:13px;min-width:150px}
.u-role-sel{padding:5px 8px;border:1px solid #d9dee8;border-radius:6px;font-size:12.5px;background:#fff}
.u-role-sel:disabled{background:#f4f5f7;color:#8b93a5}
.user-tbl-wrap{overflow:auto;border:1px solid #eef1f6;border-radius:8px}
.user-table td{vertical-align:middle}
@media(max-width:900px){
  .role-cards{grid-template-columns:1fr}
  .rp-name{min-width:0}
  .rp-note{display:none}
  .user-form-row{flex-direction:column;align-items:stretch}
  .user-form-row input,.user-form-row select{width:100%}
}

/* ================================================================
 * #851 年包订单卡片 · 状态条带（开票 / 采购单）
 * ----------------------------------------------------------------
 * 目的：让「是否已开票」「是否已关联采购单」成为**两个独立状态格**，
 *       不再与客户 / 工程师 / 备注挤在同一段文字流里
 *       —— 旧实现的状态徽章拼在 .order-card-main（flex-wrap）内，
 *          位置会随名称长度浮动，且移动端被塞进横向可滑区，可能滑出视野。
 *
 * ★ 设计约定：颜色管流程、形状管事实
 *   · 开票（流程，有生命周期、会逾期）→ 语义色三档，**同屏互斥**，直接复用
 *     #849 已上线的映射：完成 b-ok / 待办 b-wait / 异常 b-warn。
 *   · 采购单（事实，年包订单不强制关联）→ **中性色 + 实线/虚线形状编码**，
 *     不占用任何警示色。依据：hasPO 在服务端与前端注释里都写明「仅记录采购事实」，
 *     把"无采购单"渲染成警告黄会造出**永远消不掉的假警报**，
 *     而假警报的真实代价是让真警报失效。
 *
 * ★ 变量一律用 6 套主题**共同覆盖**的原始 token（--suc-* / --wrn-* / --dgr-* / --n-*），
 *   已逐主题核对覆盖完整。切勿写 --ok / --warn / --bad（生产 CSS 里没有这些名字，
 *   var() 取不到值 → 状态格无底色且不报错，属最难查的静默失效）。
 *
 * ★ 对比度实测（生产 :root 实际值，WCAG 2.1，正文阈值 4.5:1）：
 *     已开票 4.79 / 待开票 6.37 / 逾期 5.30 / 已关联 6.92 / 未关联 7.58 —— 全部达标。
 *   未关联格的虚线描边必须用 --n-400(2.56:1)；用 --border 仅 1.23:1，
 *   肉眼几乎看不见线，"实线 vs 虚线"的形状编码会直接失效。
 *
 * ★ 全部为**新增类名**（aostat-* / oc-cust / has-aostat / aostat-meta），
 *   不改动任何原有选择器 → 订单 / 采购 / 仓库等其它版块零影响。
 * ================================================================ */

/* ---------- 状态条带（PC：两格等宽） ---------- */
.aostatus-bar {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px; padding: 0 18px 11px; max-width: 640px;
}
.aostat {
  display: flex; align-items: center; gap: 7px; min-width: 0;
  padding: 7px 12px; border-radius: var(--r-sm); border: 1px solid transparent;
  font-size: 12.5px; font-weight: 600; line-height: 1.35;
  white-space: nowrap; overflow: hidden;
}
.aostat-ico { flex: none; font-size: 13px; line-height: 1; }
.aostat-main { flex: none; }
.aostat-sub {
  flex: 1 1 auto; min-width: 0; font-weight: 500; font-size: 11.5px;
  overflow: hidden; text-overflow: ellipsis; opacity: .92;
}

/* 开票三档（绿 = 完成 / 黄 = 待办 / 红 = 异常；同屏最多出现一格） */
.aostat-inv.is-done    { background: var(--suc-50);  color: var(--suc-700); }
.aostat-inv.is-pending { background: var(--wrn-100); color: var(--wrn-700); }
.aostat-inv.is-overdue { background: var(--dgr-100); color: var(--dgr-700); }

/* 采购单两档：实线 = 已关联，虚线 + 透明底 = 空缺（不依赖颜色也能分辨） */
.aostat-po.is-yes { background: var(--n-100); color: var(--n-600); border-color: var(--n-400); }
.aostat-po.is-no  { background: transparent;  color: var(--n-600); border: 1px dashed var(--n-400); }
.aostat-po.is-no .aostat-ico { opacity: .5; }

/* ---------- 客户名胶囊（从 remark 长串里提出来，便于按客户扫读） ---------- */
.oc-cust {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 2px 9px; border-radius: var(--r-full);
  font-size: 11.5px; font-weight: 600; white-space: nowrap;
  background: var(--n-100); color: var(--n-600); border: 1px solid var(--border);
}

/* ---------- 左色条：列表扫读锚点 ----------
 * 只给"需要动的"上色（待开票黄 / 逾期红），已闭环**不上色** ——
 * 一屏扫下来：有黄条=要催、有红条=要救、没条=已办完。让"安静"本身成为信号。
 * 用 ::before 绝对定位，不占布局、不影响圆角。*/
.order-card.has-aostat { position: relative; }
.order-card.has-aostat::before {
  content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 4px;
  border-radius: var(--r-md) 0 0 var(--r-md);
}
.order-card.aostat-accent-warn::before { background: var(--wrn-700); }
.order-card.aostat-accent-bad::before  { background: var(--dgr-700); }

/* ---------- 元信息行（原为内联 color:--text-mute，实测 2.56:1 偏低，提亮一档） ---------- */
.aostat-meta {
  font-size: 12px; color: var(--text-soft); padding: 0 18px 12px;
  overflow: hidden; text-overflow: ellipsis;
}

/* ---------- 窄屏（≤900px）：状态不可滑出视野 ----------
 * 旧的 .oc-l2 是 overflow-x:auto 的横向可滑区（源码注释"横向可滑 → 信息一条不丢"）
 * 但"可以滑"同时意味着"可以看不见" —— 最需要被看到的「待开票」一旦滑出屏外就失去了意义。
 * 这里用新增的 .oc-l2-aostat 把状态格改为两等分、固定可见（不影响其它版块的两行卡）。*/
@media (max-width: 900px) {
  .order-card-2l .oc-l2.oc-l2-aostat {
    display: flex; gap: 6px; padding: 0 14px 12px;
    overflow: visible; overscroll-behavior-x: auto;
  }
  .order-card-2l .oc-l2.oc-l2-aostat > .aostat {
    flex: 1 1 0; min-width: 0; padding: 6px 9px; font-size: 12px;
  }
  .order-card-2l .oc-l2.oc-l2-aostat > .aostat .aostat-sub { font-size: 11px; }
}

/* ============================================================
 * #853b PC 端隐藏「📐 底部按钮间距」—— 该设置只对移动端有意义
 *   背景：它调的是**手机系统导航栏/手势条的安全区**（安卓上被挡住时才需要加大）。
 *         PC 浏览器没有系统栏，这一项在 PC 上调了没有任何效果，
 *         却混在主题选择里让人以为能改界面 —— 属于「看得见但没用」的干扰项。
 *   做法：用项目既有断点（901px）在 PC 侧隐藏「标题 + 选项列表」两件套。
 *   ★ 移动端零影响：规则只包在 min-width:901px 内，900px 及以下完全不变。
 * ============================================================ */
@media (min-width: 901px) {
  #safePopHead, #safePopList { display: none !important; }
}
