/* 公司业务系统 · 样式
   无框架、无构建。改完直接刷新页面。 */

:root{
  --bg:#F4F5F7; --card:#fff; --line:#E6E8EC; --line-2:#F0F2F5;
  --ink:#1F2430; --ink-2:#5A6272; --ink-3:#8C94A3;
  --blue:#006EFF; --blue-50:#EAF2FF;
  --green:#2E9E5B; --green-50:#EAF7EF;
  --amber:#E08A00; --amber-50:#FFF6E6;
  --red:#D93838; --red-50:#FDECEC;
  --r:10px; --r-lg:14px;
}
*{box-sizing:border-box}
html,body{height:100%}
body{
  margin:0;background:var(--bg);color:var(--ink);
  font-family:-apple-system,BlinkMacSystemFont,"PingFang SC","Microsoft YaHei",sans-serif;
  font-size:14px;line-height:1.65;-webkit-font-smoothing:antialiased;
}
.hidden{display:none !important}
button,input,select,textarea{font-family:inherit;font-size:inherit}

/* ---------------- 通用控件 ---------------- */
.btn{
  border:1px solid var(--line);background:var(--card);color:var(--ink);
  border-radius:var(--r);padding:8px 16px;cursor:pointer;transition:.15s;
}
.btn:hover{border-color:#C9D6EA;background:#FCFDFF}
.btn.primary{background:var(--blue);border-color:var(--blue);color:#fff}
.btn.primary:hover{background:#0059D6;border-color:#0059D6}
.btn.tiny{padding:5px 12px;font-size:13px}
/* ★★ 2026-10-19：全站 44 处写着 `btn xs`、4 处写着 `sb-row`，
   但这两个类**从来没定义过** —— 表格行内的小按钮退化成普通按钮（撑得老高），
   弹层底部的按钮行也**不右对齐**（挤在左边）。
   ⇒ 在这里补定义，而不是去改 44 个调用点（改漏一个又复发）。
   `.xs` 专门给「表格行内」用，比 `.tiny` 再小一档，一行才放得下几个。 */
.btn.xs{padding:3px 9px;font-size:12px;border-radius:6px;line-height:1.6}
.sb-row{display:flex;gap:8px;justify-content:flex-end;align-items:center;margin-top:14px}
.btn.block{width:100%}
.btn:disabled{opacity:.5;cursor:not-allowed}
.btn.danger{color:var(--red);border-color:#F3C9C9}
.btn.danger:hover{background:var(--red-50)}

input,select,textarea{
  width:100%;border:1px solid var(--line);background:var(--card);
  border-radius:var(--r);padding:9px 12px;outline:none;transition:.15s;
}
/* ★★★ 2026-10-21 修（老板：「我看不到界面内容，你修改一下」）
   上面那条 `width:100%` 是给**要打字的输入框**准备的，但它把**勾选框**也一起套上了。
   勾选框的宽度是**自己的内容宽度**（就那么大一个方块），一旦被写成 100%：
     ① 在 flex 容器里它会**独占整行的宽度**（flex:0 0 auto + width:100%）
     ② 旁边的文字被挤到几十像素宽 ⇒ 中文一个字一行、竖着排
   现场（2026-10-21 实测）：「初始化新账套」那页 8 张分档卡，勾选框实测 1172px 宽
   （卡片总宽 1198px），标题「销售单据」实测 14×92px（横排本该 56×20）
   ⇒ 老板看到「一大块空白 + 最右边一列竖着的字」。
   ⇒ 在**根上**豁免：勾选框/单选框的宽度回到内容本身。
   ★ 下面移动端那条 media query（width:20px;height:20px）在文件更后面、优先级相同
     ⇒ 手机上仍然是 20px 的大勾选框，不受影响。 */
input[type=checkbox],input[type=radio]{width:auto}
input:focus,select:focus,textarea:focus{border-color:var(--blue);box-shadow:0 0 0 3px rgba(0,110,255,.12)}
textarea{resize:vertical;min-height:64px;line-height:1.6}
/* ★★ 2026-10-06 老板：「整个系统填写数值的时候，取消波动变值。就执行用输入数值的方式」
   浏览器给 type=number 默认画了一对上下小箭头（点一下 ±一个 step）。老板在
   「返利单价」那种窄框里很容易点错 —— 全系统每一个数值框都是同一对箭头，
   所以在**通用控件**这一层一次藏掉，业务模块零改动。
   ★ 滚轮 / ↑↓ 键那两条在 js/numguard.js（CSS 管不了）。 */
input[type=number]::-webkit-outer-spin-button,
input[type=number]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
input[type=number]{-moz-appearance:textfield;appearance:textfield}
.f-label{display:block;font-size:12.5px;color:var(--ink-3);margin:14px 0 5px}
.req::after{content:" *";color:var(--red)}
.msg{margin:12px 0 0;font-size:13px;color:var(--red);min-height:19px}
.msg.ok{color:var(--green)}

/* ══════════════════════════════════════════════════════════════════════
   ★ 报价顺序设置面板（2026-10-11 老板：「按价格册的顺序呈现，
     价格册里商品的顺序也能设置更改」→ 拍板「两级都要 + 在价格册页里改」）
   ══════════════════════════════════════════════════════════════════════ */
/* ★ 排序区容器（在报价单弹窗内部，与 #ps-sheet 平级）。
   ⚠️ 2026-10-11：这里原来是「排序面板 = 另一个弹窗」的设计，
      老板点一下就把整份报价单冲掉了（页面顶部飘红条）。
      ⇒ 现在排序区是**报价单内部的一块**，上下留边距免得贴着报价单挤。 */
#ps-order-box{margin:12px 0 16px;padding:0}
#ps-order-box .qp{
  border:1px solid var(--line);border-radius:10px;background:#FAFBFD;padding:14px 16px;
}
.qp{min-width:0}
.qp-head{display:flex;justify-content:space-between;align-items:flex-end;gap:14px;
  flex-wrap:wrap;padding-bottom:10px;border-bottom:1px solid var(--line)}
.qp-head-t b{font-size:15px;color:var(--ink)}
.qp-sub{display:block;font-size:12px;color:var(--ink-3);margin-top:3px}
.qp-head-b{display:flex;align-items:center;gap:10px}
.qp-lab{font-size:12.5px;color:var(--ink-3);white-space:nowrap}

.qp-tip{margin:12px 0;padding:10px 12px;background:#F7F9FC;border:1px solid var(--line);
  border-radius:8px;font-size:12.5px;line-height:1.85;color:var(--ink-2)}
.qp-tip b{color:var(--ink)}

/* ★ 打错的型号名必须显眼 —— 它「看着设好了但永远不生效」 */
.qp-warn{margin:10px 0;padding:10px 12px;background:#FDF1F0;border:1px solid #F3C6C2;
  border-radius:8px;font-size:12.5px;line-height:1.8;color:#9A2B26}

.qp-h4{margin:16px 0 8px;font-size:13.5px;font-weight:600;color:var(--ink)}
.qp-h4n{font-weight:400;font-size:12px;color:var(--ink-3);margin-left:4px}

.qp-tb{width:100%;border-collapse:collapse;font-size:12.5px}
.qp-tb th{background:#F2F5F9;color:var(--ink-2);font-weight:600;font-size:12px;
  text-align:left;padding:7px 9px;border-bottom:1px solid var(--line)}
.qp-tb td{padding:5px 9px;border-bottom:1px solid #F0F2F5;vertical-align:middle}
.qp-tb tbody tr:hover{background:#FAFBFD}
.qp-no,.qp-no2{width:56px;height:28px;padding:0 7px;text-align:center;
  border:1px solid #D8DCE4;border-radius:6px;font-size:12.5px;font-variant-numeric:tabular-nums}
.qp-no:focus,.qp-no2:focus{outline:none;border-color:var(--blue);box-shadow:0 0 0 2px rgba(31,56,100,.12)}
.qp-pos{font-size:12px;color:var(--ink-3)}
/* ★★ 2026-10-21 老板：「手动机型排序」—— 加「▲▼」直接上下挪，
   不用自己算 1、2、3…（挪完自动重排成连续序号）。 */
.qp-move{white-space:nowrap;line-height:1}
.qp-move button{width:24px;height:22px;margin:0 1px;padding:0;border:1px solid #D8DCE4;
  background:#fff;color:#48505F;border-radius:5px;font-size:10px;line-height:20px;
  cursor:pointer;vertical-align:middle}
.qp-move button:hover:not(:disabled){border-color:var(--blue);color:var(--blue);background:#F4F7FC}
.qp-move button:disabled{opacity:.32;cursor:default}
.qp-none{color:#B9C0CC}
.qp-empty{text-align:center;padding:20px 10px !important;font-size:12.5px;
  color:var(--ink-3);line-height:1.8}
.qp-empty b{color:var(--ink-2)}
.qp-empty2{margin:0;padding:12px;font-size:12.5px;color:var(--ink-3);line-height:1.8;
  background:#FAFBFD;border:1px dashed var(--line);border-radius:8px}

.qp-add{display:flex;align-items:center;gap:8px;margin-top:10px;flex-wrap:wrap}
.qp-hint{font-size:12.5px;color:var(--blue,#1F3864)}
.qp-out{margin-top:8px}
/* ★ 搜索结果（2026-10-11 老板批评「手打型号名太容易错」后加）——
   两栏排布，一屏能看十几个，点一个就选中。 */
.qp-slist{display:grid;grid-template-columns:repeat(auto-fill,minmax(250px,1fr));
  gap:6px;max-height:230px;overflow-y:auto;padding:2px}
.qp-sitem{display:flex;flex-direction:column;align-items:flex-start;gap:2px;
  width:100%;text-align:left;padding:7px 10px;border:1px solid var(--line);
  border-radius:8px;background:#fff;cursor:pointer;font-size:12.5px;color:var(--ink)}
.qp-sitem:hover{border-color:var(--blue,#1F3864);background:#F7F9FE}
.qp-sitem.on{border-color:var(--blue,#1F3864);background:#EAF1FE;
  box-shadow:0 0 0 2px rgba(31,56,100,.1)}
.qp-sitem b{font-weight:600;line-height:1.35}
.qp-sitem .sub{font-size:11.5px;color:var(--ink-3)}
@media (max-width:820px){
  .qp-slist{grid-template-columns:1fr}
}
.qp-foot{display:flex;align-items:center;gap:10px;margin-top:18px;padding-top:14px;
  border-top:1px solid var(--line)}
.qp-tip2{font-size:12.5px;color:var(--ink-3)}

@media (max-width:820px){
  .qp-head-b{width:100%;justify-content:space-between}
  .qp-foot{flex-wrap:wrap}
}

/* ---------------- 登录 ---------------- */
/* ⚠️ 2026-10-10 连返工三次，都记在这里别再犯：
   ① 原来是横排 flex（align-items:center）—— 挂上备案号后，
      备案号会和登录卡片**并排**；
   ② 改成 absolute;bottom:14px —— 短屏（实测 633px 高）**压住卡片底部 19px**，
      正好压在「登录」按钮附近；
   ③ 改成 flex 正常流 —— 不压了，但短屏下**备案号还是出界 87px**
      （真浏览器量出来 top=612/bottom=634，视口高只有 546）。
      ⚠️ 工信部扫描是按**页面 DOM 文本**抓备案号的 ——
         看不见就等于没挂 ⇒ 会被判不合规、可能撤备案。

   ⇒ 根因与最终解法（三个要点缺一不可）：
   a) `justify-content:center` + 内容超一屏 ⇒ **上下同时溢出**（浏览器都这样）
      ⇒ 去掉，改用 auto margin 居中（放得下时视觉仍居中，超一屏时 auto 塌成 0）。
   b) ★ 只给卡片 `flex-shrink` **不够** —— flex item 的 `min-height` 默认是
      `auto`，意思是「不许比内容矮」。实测 375×568 时卡片高 587px、
      页脚照样被顶出视口 73px。
      ⇒ 必须显式 `min-height:0`（解除这个下限）**+ `overflow-y:auto`**
      （超出部分变成卡片内部滚动），页脚才真的留得住。
   c) ⚠️ 还有一条容易漏：`.login-wrap` 用 `min-height:100vh` 而不是 `height:100vh`。
      容器只保证「至少一屏高」，内容超了它会**跟着长高**，滚动的是整个页面，
      `overflow-y:auto` 在卡片上就形同虚设（实测就是这里出的问题）。
      ⇒ 改成 `height:100vh` + `overflow:hidden`，让滚动只发生在卡片内部。

   实测（真浏览器 · CDP 精确设视口）：
     375×667 / 390×844 / 768×1024 / 1440×900  → 页脚完整可见 ✅
     375×568 / 1280×580                        → 出界 73px / 54px ❌（修前）
*/
.login-wrap{
  height:100vh;overflow:hidden;
  display:flex;flex-direction:column;
  align-items:center;padding:24px 24px 16px;
}
#login .login-card{
  flex:0 1 auto;min-height:0;overflow-y:auto;
  margin-top:auto;overscroll-behavior:contain;
}
.login-card{
  width:100%;max-width:380px;background:var(--card);border:1px solid var(--line);
  border-radius:16px;padding:34px 30px 30px;
}
.login-card .kicker{font-size:12.5px;color:var(--blue);margin:0 0 10px;letter-spacing:.05em}
.login-card h1{font-size:24px;margin:0 0 6px;font-weight:600}
.login-card .sub{font-size:13.5px;color:var(--ink-2);margin:0}
.chips{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px}
.chips:empty{display:none}
.chip{
  border:1px solid var(--line);border-radius:999px;padding:4px 12px;font-size:12.5px;
  color:var(--ink-2);cursor:pointer;background:var(--card);
}
.chip:hover{border-color:var(--blue);color:var(--blue)}
.login-card .btn{margin-top:16px}

/* ---------------- 备案号（2026-10-10 工信部硬要求）-----------------
   ICP 备案通过后，网站底部必须展示备案号并链到工信部查询页，
   否则工信部扫描到「有域名无备案号」会把备案驳回、并给主体记风险。
   ⚠️ 换备案号 / 加公安备案号 = 改 index.html 与 portal.html 里
      class="site-foot" 的那段，改完刷新即生效（纯前端，不用重启）。
   ⚠️ 这里**不能**用 position:absolute —— 登录卡片高度随内容变，
      绝对定位的页脚会在短屏上压住卡片底部（实测重叠 19px）。
      现在用 flex 让它正常占位。*/
.site-foot{
  flex:0 0 auto;margin:14px 0 12px;text-align:center;
  font-size:12px;line-height:1.9;color:var(--ink-3);
}
.site-foot a{color:inherit;text-decoration:none;border-bottom:1px solid currentColor;padding-bottom:1px}
.site-foot a:hover{color:var(--blue)}
/* ★ 安全居中：内容超一屏时 auto 塌成 0，只向下溢出，页脚仍在视口内
   （必须写在 .site-foot 主体之后，否则被后面的 margin 覆盖）*/
#login .login-card{margin-top:auto}
#login .site-foot{margin-bottom:auto}
/* 手机版：屏幕更矮，页脚再瘦一点，别把登录按钮挤下去 */
@media (max-width:820px){
  .login-wrap{padding:16px 16px 12px}
  #login .login-card{padding:26px 20px 24px}
  .site-foot{font-size:11.5px}
}

/* ---------------- 主布局 ---------------- */
.app-wrap{display:flex;min-height:100vh}
.side{
  width:216px;flex:none;background:var(--card);border-right:1px solid var(--line);
  display:flex;flex-direction:column;position:sticky;top:0;height:100vh;
}
.brand{display:flex;gap:11px;align-items:center;padding:20px 18px 18px}
.logo{
  width:30px;height:30px;flex:none;border-radius:9px;background:var(--blue);
  position:relative;
}
.logo::after{
  content:"";position:absolute;inset:9px 9px auto auto;width:12px;height:12px;
  border:2px solid #fff;border-radius:3px;
}
.brand-name{font-size:14.5px;font-weight:600;margin:0}
.brand-stage{font-size:11.5px;color:var(--ink-3);margin:1px 0 0}

.nav{padding:6px 10px 14px;overflow-y:auto;flex:1}

/* ---------------- 左侧菜单 · 分组可折叠（2026-10-02）----------------
   老板：「左边这个界面太长，是不是可以像博远一样，可以合并在一起，可以自由的
         点开与合并」。
   逻辑在 js/router.js（foldedGroups / toggleGroup / toggleAllGroups），这里只管长相。
   ⚠️ `.nav-group` 从「一行灰字」变成了**按钮** —— 箭头 + 组名 + 项数。
   ⚠️ 折叠用 display:none，**故意不加高度动画** —— 动画要猜高度，这层是天天用的
      经营工具，稳比好看要紧。 */
.nav-tools{display:flex;justify-content:flex-end;padding:2px 2px 2px}
.nav-fold-btn{
  border:1px solid transparent;background:none;border-radius:999px;cursor:pointer;
  padding:2px 9px;font-family:inherit;font-size:11.5px;color:var(--ink-3);line-height:1.7;
}
.nav-fold-btn:hover{border-color:var(--line);background:var(--card);color:var(--blue)}

.nav-group{
  display:flex;align-items:center;gap:6px;width:100%;box-sizing:border-box;
  border:0;background:none;cursor:pointer;text-align:left;border-radius:var(--r);
  font-family:inherit;font-size:11.5px;color:var(--ink-3);letter-spacing:.04em;
  padding:13px 9px 5px;
}
.nav-group:hover{color:var(--ink-2)}
.nav-group .caret{
  flex:none;width:0;height:0;border:4px solid transparent;border-left-color:currentColor;
  border-right-width:0;opacity:.65;transition:transform .13s;
}
.nav-g:not(.folded) .nav-group .caret{transform:rotate(90deg)}
.nav-group .gt{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.nav-group .gcount{flex:none;font-size:10.5px;opacity:.75}
.nav-body{display:block}
.nav-g.folded .nav-body{display:none}
.nav-item{
  display:flex;align-items:center;gap:9px;padding:8px 11px;border-radius:var(--r);
  font-size:13.5px;color:var(--ink-2);cursor:pointer;margin-bottom:1px;
}
.nav-item:hover{background:#F7F8FA;color:var(--ink)}
.nav-item.active{background:var(--blue-50);color:var(--blue);font-weight:600}
.nav-item .dot{width:6px;height:6px;border-radius:50%;background:currentColor;opacity:.55;flex:none}
.nav-item .lbl{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.nav-item .soon{margin-left:auto;font-size:10.5px;color:var(--ink-3);background:var(--line-2);
  padding:1px 7px;border-radius:999px}

/* 阶段标签：待建（灰）/ 在建（黄）。已能用的模块不显示标签，画面干净 */
.stage{margin-left:auto;flex:none;font-size:10.5px;color:var(--ink-3);background:var(--line-2);
  padding:1px 7px;border-radius:999px}
.stage.wip{background:var(--amber-50);color:var(--amber)}

.side-foot{padding:14px;border-top:1px solid var(--line-2)}
.who{font-size:12.5px;color:var(--ink-2);margin-bottom:9px}
.who b{display:block;font-size:13.5px;color:var(--ink);font-weight:600}

/* ---------------- 内容区 ---------------- */
.main{flex:1;min-width:0;display:flex;flex-direction:column}
.topbar{
  display:flex;align-items:center;gap:14px;flex-wrap:wrap;
  padding:22px 28px 18px;border-bottom:1px solid var(--line);background:var(--bg);
  position:sticky;top:0;z-index:5;
}
.topbar h2{font-size:20px;margin:0;font-weight:600}
.page-sub{font-size:13px;color:var(--ink-2);margin:2px 0 0}
/* 标题块吃掉剩余宽度，右边的搜索框和按钮自然被推到最右 */
.title-box{flex:1;min-width:0}
.topbar .search{width:260px;margin-left:0}
.content{padding:22px 28px 60px;flex:1}

/* ---------------- 统计卡 ---------------- */
.stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:12px;margin-bottom:22px}
.stat{background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);padding:16px 18px}
.stat .k{font-size:12.5px;color:var(--ink-3);margin:0 0 4px}
.stat .v{font-size:26px;font-weight:600;margin:0;letter-spacing:-.02em;font-variant-numeric:tabular-nums}
.stat .u{font-size:12.5px;color:var(--ink-3);margin:3px 0 0}

/* ---------------- 表格 ---------------- */
.table-wrap{background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);overflow:hidden}
.table-scroll{overflow-x:auto}
table{width:100%;border-collapse:collapse;font-size:13.5px}
th{
  text-align:left;font-weight:500;color:var(--ink-3);font-size:12.5px;
  padding:12px 16px;background:#FAFBFC;border-bottom:1px solid var(--line);white-space:nowrap;
}
td{padding:12px 16px;border-bottom:1px solid var(--line-2);white-space:nowrap}
tbody tr:hover{background:#FCFDFF}
tr:last-child td{border-bottom:none}
td.mono{font-family:ui-monospace,Menlo,Consolas,monospace;font-size:12.5px}
td.actions{text-align:right}
td.actions button{margin-left:6px}

.pill{display:inline-block;padding:2px 9px;border-radius:999px;font-size:12px;background:var(--line-2);color:var(--ink-2)}
.pill.on{background:var(--green-50);color:var(--green)}
.pill.off{background:var(--line-2);color:var(--ink-3)}

/* ---------------- 空态 / 占位 ---------------- */
.empty{padding:56px 24px;text-align:center;color:var(--ink-3)}
.empty h3{font-size:15px;color:var(--ink-2);margin:0 0 6px;font-weight:500}
.empty p{margin:0;font-size:13.5px}

.soon-card{
  background:var(--card);border:1px dashed #D3D8E0;border-radius:var(--r-lg);
  padding:26px 28px;
}
.soon-card h3{font-size:15px;margin:0 0 8px;font-weight:600}
.soon-card p{font-size:13.5px;color:var(--ink-2);margin:0 0 8px}
.soon-card ul{margin:10px 0 0;padding-left:20px;font-size:13.5px;color:var(--ink-2);line-height:1.9}

/* ---------------- 弹窗 ---------------- */
.modal{position:fixed;inset:0;z-index:50;display:flex;align-items:center;justify-content:center;padding:20px}
.modal-mask{position:absolute;inset:0;background:rgba(20,24,32,.42)}
.modal-box{
  position:relative;background:var(--card);border-radius:16px;width:100%;max-width:640px;
  max-height:88vh;display:flex;flex-direction:column;overflow:hidden;
}
.modal-head{
  display:flex;align-items:center;justify-content:space-between;
  padding:18px 22px;border-bottom:1px solid var(--line);
}
.modal-head h3{font-size:16px;margin:0;font-weight:600}
.modal-head .x{border:none;background:none;font-size:24px;line-height:1;color:var(--ink-3);cursor:pointer;padding:0 4px}
.modal-body{padding:6px 22px 20px;overflow-y:auto}
.grid2{display:grid;grid-template-columns:1fr 1fr;gap:0 16px}
.modal-foot{
  display:flex;align-items:center;justify-content:flex-end;gap:12px;
  padding:16px 22px;border-top:1px solid var(--line);background:#FCFCFD;
}
.modal-foot .msg{margin:0;flex:1}
.hint{font-size:12px;color:var(--ink-3);margin:5px 0 0}

/* ---------------- 弹窗能自由拉大 ----------------
   老板 2026-10-19：「结算单也不能自由的拉大（不方便看到更多的内容）」
   ★ 做在框架层（core.js:fitModalBox），串号轨迹 / 对账单 / 导入预览一个地方全受益。
   尺寸只在他**主动拖过**之后才记住 —— 小表单拉成一大块更难看。 */
.mb-resizable{position:relative}
.mb-grip{
  position:absolute;right:0;bottom:0;width:18px;height:18px;
  cursor:nwse-resize;z-index:6;touch-action:none;
}
.mb-grip::after{
  content:'';position:absolute;right:4px;bottom:4px;width:8px;height:8px;
  border-right:2px solid #C4CBD6;border-bottom:2px solid #C4CBD6;border-radius:0 0 2px 0;
}
.mb-grip:hover::after{border-color:var(--blue)}
.modal-head .mb-max{font-size:17px;color:var(--ink-3);margin-left:auto;margin-right:8px;border:none;background:none;cursor:pointer}
.modal-head .mb-max:hover{color:var(--blue)}
@media (max-width:720px){
  /* 手机上弹层本来就是全屏，拖拽没有意义 */
  .mb-grip{display:none}
  .modal-head .mb-max{display:none}
}

/* ---------------- 「抵的单 / 开单明细」里的机型 + 串号 ----------------
   老板 2026-10-19：「我看不出客户转的到底是哪一台机子，不好核对」
   ⇒ 一台一行，串号用等宽字体（15 位数字眼对眼核，不能让字距飘）。 */
.sd-items td{vertical-align:top}
.sd-units{font-size:12px;line-height:1.6;white-space:normal;min-width:190px}
.sd-u{display:flex;gap:8px;align-items:baseline;flex-wrap:wrap}
.sd-u+.sd-u{margin-top:3px}
.sd-u-nm{color:var(--ink-2);font-size:12px}
.sd-u-sn{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  font-size:12px;color:var(--ink);letter-spacing:.3px;white-space:nowrap}

/* ---------------- 销售场景（激活地域看板） ---------------- */
.scope-board{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin-bottom:18px}
.scope-card{
  background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);
  padding:16px 18px;position:relative;overflow:hidden;
}
.scope-card::before{content:"";position:absolute;left:0;top:0;bottom:0;width:4px;background:currentColor;opacity:.85}
.scope-card.lv0{color:var(--ink-3)}
.scope-card.lv1{color:var(--blue)}
.scope-card.lv2{color:var(--green)}
.scope-card .t{font-size:13.5px;font-weight:600;color:var(--ink);margin:0 0 2px}
.scope-card .reach{font-size:12px;color:currentColor;margin:0 0 10px;font-weight:500}
.scope-card .num{font-size:26px;font-weight:600;color:var(--ink);margin:0;letter-spacing:-.02em;font-variant-numeric:tabular-nums}
.scope-card .u{font-size:12.5px;color:var(--ink-3);margin:2px 0 0}
.scope-card .sub{font-size:12px;color:var(--ink-3);margin:8px 0 0;line-height:1.7}

.scope-toolbar{
  display:flex;align-items:center;gap:12px;flex-wrap:wrap;
  background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);
  padding:13px 18px;margin-bottom:18px;
}
.scope-toolbar .n{font-size:13.5px;color:var(--ink-2)}
.scope-toolbar .n b{color:var(--blue);font-weight:600}
.scope-toolbar .sp{margin-left:auto}

.scope-section{margin-bottom:20px}
.scope-section .head{
  display:flex;align-items:center;gap:10px;padding:0 2px 9px;
}
.scope-section .head h3{font-size:14.5px;margin:0;font-weight:600}
.scope-section .head .cnt{font-size:12.5px;color:var(--ink-3)}
.scope-section .head .line{flex:1;height:1px;background:var(--line-2)}

.scope-badge{display:inline-block;padding:2px 10px;border-radius:999px;font-size:12px;font-weight:500}
.scope-badge.lv0{background:var(--line-2);color:var(--ink-2)}
.scope-badge.lv1{background:var(--blue-50);color:var(--blue)}
.scope-badge.lv2{background:var(--green-50);color:var(--green)}

.scope-num{font-variant-numeric:tabular-nums}
.scope-num b{font-weight:600}
.scope-num s{color:var(--ink-3);text-decoration:none}

td.pick{width:36px;padding-right:0}
td.pick input{width:16px;height:16px;cursor:pointer}

.scope-picker{display:flex;gap:10px;flex-wrap:wrap;margin-top:4px}
.scope-pick{
  flex:1;min-width:150px;border:1px solid var(--line);border-radius:var(--r);
  padding:12px 14px;cursor:pointer;transition:.15s;background:var(--card);
}
.scope-pick:hover{border-color:#C9D6EA}
.scope-pick.on{border-color:var(--blue);background:var(--blue-50);box-shadow:0 0 0 3px rgba(0,110,255,.08)}
.scope-pick .k{font-size:13.5px;font-weight:600;margin:0 0 3px}
.scope-pick.on .k{color:var(--blue)}
.scope-pick .d{font-size:12px;color:var(--ink-3);margin:0;line-height:1.6}

.scope-what{
  background:#FAFBFC;border:1px solid var(--line);border-radius:var(--r);
  padding:12px 16px;font-size:13px;color:var(--ink-2);line-height:1.9;
}
.scope-what b{color:var(--ink)}
.scope-tip{margin-top:14px;font-size:13px;line-height:1.85;color:var(--ink-2);
  background:var(--amber-50);border:1px solid #F5DFB0;border-radius:var(--r);padding:11px 15px}
.scope-tip:empty{display:none}
.scope-tip.wide{background:var(--green-50);border-color:#C7E6D3;color:#1C6639}

.log-row{font-size:12.5px;color:var(--ink-2)}
.log-row .who{color:var(--ink-3)}

@media (max-width:820px){
  .scope-board{grid-template-columns:1fr}
  .scope-pick{min-width:100%}
}

/* ---------------- 门店合规看板 ---------------- */
.cmp-bar{
  display:flex;align-items:center;gap:12px;flex-wrap:wrap;
  background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);
  padding:13px 18px;margin-bottom:16px;
}
.cmp-bar .lb{font-size:12.5px;color:var(--ink-3);margin-right:-6px}
.cmp-bar input,.cmp-bar select{width:auto;min-width:132px;padding:7px 11px}
.cmp-bar .sp{margin-left:auto}

.rate{display:inline-flex;align-items:center;gap:8px;font-variant-numeric:tabular-nums}
.rate .num{font-weight:600;min-width:46px;text-align:right}
.rate .track{width:64px;height:6px;border-radius:3px;background:var(--line-2);position:relative;overflow:hidden;flex:none}
.rate .fill{position:absolute;left:0;top:0;bottom:0;border-radius:3px}
.rate .tick{position:absolute;top:-2px;bottom:-2px;width:1.5px;background:var(--ink-3);opacity:.55}
.rate.ok .num{color:var(--green)}
.rate.ok .fill{background:var(--green)}
.rate.warn .num{color:var(--amber)}
.rate.warn .fill{background:var(--amber)}
.rate.bad .num{color:var(--red)}
.rate.bad .fill{background:var(--red)}
.rate.na .num{color:var(--ink-3)}
.rate.na .fill{background:var(--line)}

.lv{padding:2px 10px;border-radius:999px;font-size:12px;font-weight:500}
.lv.ok{background:var(--green-50);color:var(--green)}
.lv.warn{background:var(--amber-50);color:var(--amber)}
.lv.bad{background:var(--red-50);color:var(--red)}
.lv.na{background:var(--line-2);color:var(--ink-3)}

.cmp-detail{margin-top:16px}
.cmp-detail .hd{display:flex;align-items:center;gap:10px;margin-bottom:10px}
.cmp-detail .hd h3{font-size:14.5px;margin:0;font-weight:600}

.tag{display:inline-block;padding:1px 8px;border-radius:5px;font-size:11.5px;font-weight:500}
.tag.bad{background:var(--red-50);color:var(--red)}
.tag.warn{background:var(--amber-50);color:var(--amber)}
.tag.ok{background:var(--green-50);color:var(--green)}

/* ---------------- 提示条 ---------------- */
.toast{
  position:fixed;left:50%;bottom:36px;transform:translateX(-50%);
  background:#22272F;color:#fff;padding:11px 20px;border-radius:10px;font-size:13.5px;z-index:99;
}
.toast.bad{background:var(--red)}

/* --------------------------------------------------------------------------
   ⚠️ 窄屏（手机）样式**不在这一层了**，统一挪到文件末尾的「手机版」那一段
      （2026-10-02）。
   这里原来写的是：侧栏压成 64px、菜单项只留一个小圆点、分组标题只留一条横线 ——
   在手机上等于「一排看不出是什么的点」，老板点不了。现在改成**滑出的抽屉**，
   完整显示组名和菜单项。要看效果搜 `手机版（2026-10-02）`。
   -------------------------------------------------------------------------- */

/* ==========================================================================
   入库单 / 串码台账（2026-09-20 新增）
   已有的基础类（.btn .pill .stats .soon-card 等）复用，这里只补缺的。
   ========================================================================== */

/* ---- 缺的通用件 ---- */
.card{background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);overflow:hidden}
.grid{width:100%;border-collapse:collapse;font-size:13.5px}
.grid th{
  text-align:left;font-weight:600;color:var(--ink-2);background:var(--line-2);
  padding:10px 12px;border-bottom:1px solid var(--line);white-space:nowrap;
}
.grid td{padding:9px 12px;border-bottom:1px solid var(--line-2);vertical-align:middle}
.grid tbody tr:hover{background:#FBFCFE}
.grid td.num,.grid th.num{text-align:right;font-variant-numeric:tabular-nums}
.grid tr.voided td{opacity:.45;text-decoration:line-through}
.loading{padding:40px;text-align:center;color:var(--ink-3)}
.note{border-radius:var(--r);padding:10px 14px;font-size:13.5px;line-height:1.7;margin:10px 0}
.note.blue{background:var(--blue-50);border-left:3px solid var(--blue)}
.note.green{background:var(--green-50);border-left:3px solid var(--green)}
.note.amber{background:var(--amber-50);border-left:3px solid var(--amber)}
.note.red{background:var(--red-50);border-left:3px solid var(--red)}
.pill.blue{background:var(--blue-50);color:#0059D6;border-color:#C7DEFF}
.row{display:flex;gap:10px;flex-wrap:wrap;align-items:flex-start}
.sep{border:0;border-top:1px solid var(--line);margin:16px 0}
.mono{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12.5px}

/* ---- 分页 ---- */
.pager{display:flex;align-items:center;gap:6px;padding:12px;color:var(--ink-3);font-size:13px}
.pg{border:1px solid var(--line);background:var(--card);border-radius:7px;
    min-width:30px;padding:4px 8px;cursor:pointer}
.pg:hover{border-color:#C9D6EA}
.pg.cur{background:var(--blue);border-color:var(--blue);color:#fff}
.pg-dots{color:var(--ink-3);padding:0 2px}
/* ---- 分页条：共 N 条 · 每页条数下拉 · 页码 ---- */
.pager{flex-wrap:wrap;row-gap:8px}
.pg-info{white-space:nowrap}
.pg-info b{color:var(--ink)}
.pg-sz{display:inline-flex;align-items:center;gap:4px;white-space:nowrap;
    margin-left:4px;padding-left:10px;border-left:1px solid var(--line)}
.pg-sz select{border:1px solid var(--line);background:var(--card);border-radius:7px;
    padding:3px 6px;font-size:13px;color:var(--ink);cursor:pointer}
.pg-sz select:hover{border-color:#C9D6EA}
.pg-btns{display:inline-flex;align-items:center;gap:6px;flex-wrap:wrap}

/* ---- 入库页工具条 ---- */
.ib-bar{display:flex;gap:8px;align-items:center;margin:16px 0 12px;flex-wrap:wrap}
.ib-bar .search{flex:1 1 200px;max-width:320px;padding:8px 12px}
.ib-bar .btn{white-space:nowrap}
.ib-dash{color:var(--ink-3)}
.ib-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(210px,1fr));gap:10px;margin:12px 0}
.ib-grid label{display:flex;flex-direction:column;gap:4px;font-size:12.5px;color:var(--ink-3)}
.ib-grid label select,.ib-grid label input{padding:7px 10px;font-size:13.5px;color:var(--ink)}
.ib-grid > div{display:flex;flex-direction:column;gap:2px}
.ib-grid .k{font-size:12.5px;color:var(--ink-3)}
.ib-grid .v{font-size:13.5px}
.ib-paste{display:block;margin-top:12px;font-size:12.5px;color:var(--ink-3)}
.ib-paste textarea{min-height:150px;margin-top:5px;font-family:ui-monospace,Menlo,monospace;font-size:12.5px}
.ib-h{margin:18px 0 8px;font-size:14px;color:var(--ink)}
.ib-kv{display:flex;flex-wrap:wrap;gap:8px 18px;font-size:13px;color:var(--ink-2)}
.ib-kv b{color:var(--ink)}
.ib-note{font-size:12.5px;color:var(--ink-3);margin:6px 0 0;line-height:1.7}
.ib-io{display:flex;gap:12px;margin:8px 0}
.ib-io .io{flex:1;border-radius:var(--r);padding:10px 14px;text-align:center}
.ib-io .io.in{background:var(--green-50)}
.ib-io .io.out{background:var(--red-50)}
.ib-io .io .v{font-size:22px;font-weight:600;margin:0}
.ib-io .io.in .v{color:var(--green)}
.ib-io .io.out .v{color:var(--red)}
.ib-io .io .k{font-size:12px;color:var(--ink-3);margin:2px 0 0}
.ib-miss{max-height:190px;overflow:auto;border:1px solid var(--line);border-radius:var(--r);
         padding:8px 10px;font-size:12.5px;background:#FCFDFF}
.ib-miss .n{color:var(--amber);font-weight:600;margin-right:6px}
.ib-errs{font-size:12.5px;color:var(--ink-2);max-height:170px;overflow:auto;
         border-left:2px solid var(--line);padding-left:10px;margin:6px 0}
.ib-errs.warn{border-left-color:var(--amber)}
.ib-moves{max-height:400px;overflow:auto;border:1px solid var(--line);border-radius:var(--r)}

/* ---- 串码轨迹时间线 ---- */
.timeline{margin-top:8px;padding-left:6px}
.tl-item{display:flex;gap:12px;padding-bottom:14px;position:relative}
.tl-item:not(:last-child)::before{
  content:"";position:absolute;left:11px;top:26px;bottom:0;width:2px;background:var(--line);
}
.tl-dot{
  width:24px;height:24px;border-radius:50%;flex:0 0 24px;display:flex;
  align-items:center;justify-content:center;font-size:12px;color:#fff;z-index:1;
}
.tl-item.in .tl-dot{background:var(--green)}
.tl-item.out .tl-dot{background:var(--red)}
.tl-item.voided{opacity:.45}
.tl-body{flex:1;padding-top:1px}
.tl-t{margin:0;font-size:13.5px}
.tl-s{margin:2px 0 0;font-size:12.5px;color:var(--ink-3)}
.tl-s.red{color:var(--red)}

/* ===========================================================================
   框架层新增：模块地图（系统 → 使用说明）
   =========================================================================== */
.map{display:flex;flex-direction:column;gap:18px}
.map-group h4{
  font-size:13px;margin:0 0 8px;font-weight:600;color:var(--ink-2);
  display:flex;align-items:center;gap:8px;
}
.map-group h4 .sub{font-size:11.5px;color:var(--ink-3);font-weight:400}
.map-row{
  display:flex;align-items:baseline;gap:10px;padding:9px 14px;background:var(--card);
  border:1px solid var(--line);border-radius:var(--r);margin-bottom:6px;
}
.map-row .lv{flex:none;min-width:52px;text-align:center}
.map-name{flex:none;min-width:110px;font-size:13.5px;font-weight:500}
.map-desc{flex:1;font-size:12.5px;color:var(--ink-3);line-height:1.7}
@media (max-width:720px){
  .map-row{flex-wrap:wrap}
  .map-desc{flex-basis:100%}
  .topbar .search{width:100%;order:3}
}

/* ===========================================================================
   库存看板 —— 「客户要这个货，哪儿的能卖给他」
   一个型号一行，给一个明确结论；每个结论一组色带
   =========================================================================== */
.iv-quota{background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);
  margin-bottom:12px;overflow:hidden}   /* padding 交给 summary / list，折叠时才没有空档 */
.iv-quota-total{margin-left:auto;font-size:13px}
.iv-quota-total b{font-size:19px;color:var(--green);font-variant-numeric:tabular-nums}
.iv-quota-list{display:flex;flex-wrap:wrap;gap:2px;margin-top:2px}
.iv-quota-empty{margin:8px 0 0;font-size:12.5px;color:var(--ink-3);line-height:1.7}

.iv-filter{display:flex;flex-wrap:wrap;gap:6px;margin:0 0 12px}

.iv-group{border:1px solid var(--line);border-radius:var(--r-lg);background:var(--card);
  margin-bottom:14px;overflow:hidden}
.iv-head{display:flex;align-items:center;gap:10px;padding:13px 18px;flex-wrap:wrap;
  border-bottom:1px solid var(--line-2)}
.iv-head b{font-size:14.5px}
.iv-dot{font-size:11px}
.iv-cnt{font-size:12.5px;color:var(--ink-2);font-variant-numeric:tabular-nums}
.iv-hint{font-size:12px;color:var(--ink-3);margin-left:auto}
.iv-group.iv-local .iv-dot{color:var(--green)}
.iv-group.iv-local .iv-head{background:var(--green-50)}
.iv-group.iv-province .iv-dot{color:var(--blue)}
.iv-group.iv-province .iv-head{background:var(--blue-50)}
.iv-group.iv-release .iv-dot{color:var(--amber)}
.iv-group.iv-release .iv-head{background:var(--amber-50)}
.iv-group.iv-blocked .iv-dot{color:var(--red)}
.iv-group.iv-blocked .iv-head{background:var(--red-50)}
.iv-group.iv-none-v .iv-dot{color:var(--ink-3)}
.iv-group table.grid{border:0;border-radius:0}

.iv-name{font-weight:500;font-size:13.5px}
.iv-places{line-height:2}
.iv-place{display:inline-flex;align-items:baseline;gap:5px;background:var(--line-2);
  border-radius:999px;padding:2px 10px;font-size:12.5px;margin:2px 6px 2px 0}
.iv-place s{text-decoration:none;color:var(--ink-3);font-size:11.5px}
.iv-place b{font-variant-numeric:tabular-nums}
.iv-place.bad{background:var(--red-50)}
.iv-place .iv-can{color:var(--amber);font-weight:600}

.iv-n{font-size:12.5px;font-variant-numeric:tabular-nums;margin-right:6px;white-space:nowrap}
.iv-n.good{color:var(--green)}
.iv-n.blue{color:var(--blue)}
.iv-n.warn{color:var(--amber)}
.iv-n.bad{color:var(--red)}

.iv-serials{padding:10px 18px;background:#FAFBFC;font-size:12px;line-height:2}
.iv-serials .mono{margin-right:4px}
.iv-serials s{text-decoration:none;color:var(--ink-3);margin-right:12px;font-size:11.5px}

/* ===========================================================================
   库存看板改版（2026-10-01 老板：「显示不够直观，有信息看不全」「加品牌/系列/品类多选」）
   ---------------------------------------------------------------------------
   改前的病根：一张 5 列的表格，最后一列「在哪儿/什么档位」把表**横向撑出屏幕**，
   老板只看得见「厦门…」半截。所以位置信息一律改成**会自动换行的小方块**（flex-wrap），
   卡片本身又是个普通 div —— 从根上不可能再横向溢出。
   =========================================================================== */

/* ---- 搜索区 ---- */
.iv-search{background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);
  padding:13px 16px;margin-bottom:12px}
.iv-srow{display:flex;align-items:center;gap:9px;flex-wrap:wrap}
.iv-srow #iv-q{flex:1;min-width:200px;width:auto}
.iv-slabel{font-size:12.5px;color:var(--ink-3);white-space:nowrap}

/* 品牌 / 系列 / 品类：一排一个横向滚动条都不给，直接换行 */
.iv-frow{display:flex;align-items:flex-start;gap:9px;margin-top:9px;padding-top:9px;
  border-top:1px dashed var(--line)}
.iv-frow:first-child{border-top:0;padding-top:0}
.iv-flabel{font-size:12.5px;color:var(--ink-3);white-space:nowrap;padding-top:4px;min-width:30px}
.iv-fchips{display:flex;flex-wrap:wrap;gap:6px;flex:1}
.iv-fchip s{text-decoration:none;color:var(--ink-3);margin-left:5px;font-size:11px;
  font-variant-numeric:tabular-nums}
.iv-fchip.on s{color:rgba(255,255,255,.85)}
.iv-fall{background:var(--line-2);color:var(--ink-2)}
.iv-more{border-style:dashed;color:var(--blue);border-color:#BBD4FF}

/* 口径说明：收起来，别占地方 */
.iv-legend{margin:0 0 12px;font-size:12.5px}
.iv-legend>summary{cursor:pointer;color:var(--ink-3);padding:2px 0}
.iv-legend>summary:hover{color:var(--blue)}

/* ---- 最值钱的那句话 ---- */
.iv-tip{display:flex;gap:10px;align-items:baseline;background:var(--card);
  border:1px solid var(--line);border-left:4px solid var(--ink-3);
  border-radius:var(--r);padding:11px 15px;margin-bottom:12px;font-size:14px;line-height:1.7}
.iv-tip>b{white-space:nowrap;font-size:14px}
.iv-tip span{flex:1}
.iv-tip.good{border-left-color:var(--green);background:var(--green-50)}
.iv-tip.warn{border-left-color:var(--amber);background:var(--amber-50)}

/* ---- 额度：收进 details ---- */
.iv-quota>summary{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;
  cursor:pointer;list-style:none;padding:12px 18px}
.iv-quota>summary::-webkit-details-marker{display:none}
.iv-quota>summary::before{content:"▸";color:var(--ink-3);font-size:11px}
.iv-quota[open]>summary::before{content:"▾"}
.iv-quota>summary>b{font-size:14px}
.iv-quota-list{padding:0 18px 14px}

/* ---- 结论分组：卡片容器 ---- */
.iv-cards{padding:2px 0}

/* ---- 一张卡 ---- */
.iv-card{border-top:1px solid var(--line);padding:13px 18px}
.iv-cards .iv-card:first-child{border-top:0}
.iv-card:hover{background:#FCFDFF}
.iv-ctop{display:flex;gap:14px;align-items:flex-start;flex-wrap:wrap}
.iv-cname{flex:1;min-width:240px}
.iv-cname>b{font-size:13.5px;font-weight:600;line-height:1.5}
.iv-attrs{display:flex;flex-wrap:wrap;gap:5px;margin-top:5px}
.iv-attrs span{font-size:11.5px;color:var(--ink-2);background:var(--line-2);
  border-radius:5px;padding:1px 7px}

/* 台数：4 个带颜色的小方块（现货 / 调货 / 可放开 / 卡住） */
.iv-cright{display:flex;align-items:center;gap:9px;flex-wrap:wrap;justify-content:flex-end}
.iv-nums{display:flex;gap:7px;flex-wrap:wrap}
.iv-cacts{display:flex;gap:7px}
.iv-num{min-width:56px;text-align:center;border-radius:var(--r);padding:4px 9px 5px;
  border:1px solid var(--line);background:var(--card);cursor:help}
.iv-num b{display:block;font-size:19px;line-height:1.15;font-variant-numeric:tabular-nums}
.iv-num s{display:block;text-decoration:none;font-size:11px;color:var(--ink-3);line-height:1.3}
.iv-num.good{border-color:#C6E7D3;background:var(--green-50)}
.iv-num.good b{color:var(--green)}
.iv-num.blue{border-color:#C7DDFF;background:var(--blue-50)}
.iv-num.blue b{color:var(--blue)}
.iv-num.warn{border-color:#F5E0B8;background:var(--amber-50)}
.iv-num.warn b{color:var(--amber)}
.iv-num.bad{border-color:#F3C9C9;background:var(--red-50)}
.iv-num.bad b{color:var(--red)}

/* ---- 一级：每个「堆」一行摘要（明细在二级看板）----
   ★ 2026-10-01 老板第二轮：「看板这里很乱，我建议生成二级看板」。
     所以一级不再是「每处货位一个小块铺满整张卡」，而是**一堆一行**：
     几处、几台、前 3 个位置长什么样、最久放了多久 —— 整行可点，进二级。
   ★ 行内一律 flex-wrap：位置名有长有短（「厦门市翔安区永翌德通信经营部」），
     定宽 grid 会被它顶出去（上一轮「信息看不全」就是这么来的）。 */
.iv-stacks{margin-top:9px;display:flex;flex-direction:column;gap:5px}
.iv-stk{display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  padding:6px 10px;border:1px solid var(--line);border-radius:var(--r);
  background:var(--card);cursor:pointer;transition:.15s}
.iv-stk:hover{border-color:#C9D6EA;background:#FCFDFF}
.iv-stk-h{flex:none;font-size:12.5px;white-space:nowrap}
.iv-stk-h i{font-style:normal;margin-right:3px}
.iv-stk-h b{font-weight:600}
.iv-stk-ok .iv-stk-h b{color:var(--green)}
.iv-stk-go .iv-stk-h b{color:var(--blue)}
.iv-stk-out .iv-stk-h b{color:var(--ink-2)}
.iv-stk-no .iv-stk-h b{color:var(--red)}
.iv-stk-cnt{flex:none;font-size:12px;color:var(--ink-2);font-variant-numeric:tabular-nums}
.iv-stk-cnt b{font-size:14px;color:var(--ink)}
.iv-stk-pl{flex:1;min-width:200px;display:flex;flex-wrap:wrap;gap:5px;align-items:center}
.iv-pm{display:inline-flex;align-items:baseline;gap:4px;background:var(--line-2);
  border-radius:6px;padding:1px 8px;font-size:12px;max-width:100%}
.iv-pm i{font-style:normal}
.iv-pm s{text-decoration:none;color:var(--ink-3);font-size:11px}
.iv-pm b{font-variant-numeric:tabular-nums;color:var(--ink)}
.iv-stk-more{font-size:11.5px;color:var(--blue)}
.iv-stk-can{flex:none;font-size:11.5px;color:var(--amber);font-weight:600}
.iv-stk-age{flex:none;font-size:11.5px;color:var(--ink-3);font-variant-numeric:tabular-nums}
.iv-stk-age.bad{color:var(--red)}
.iv-stk-age.warn{color:var(--amber)}
.iv-stk-go{flex:none;font-size:11.5px;color:var(--ink-3);white-space:nowrap}
.iv-stk:hover .iv-stk-go{color:var(--blue)}
.iv-attrs-age{background:var(--amber-50);color:var(--amber)}
.iv-warn{margin-top:12px;padding:9px 14px;border-radius:var(--r);
  background:var(--amber-50);border-left:3px solid var(--amber);font-size:12.5px;color:var(--ink-2)}

.iv-sc{font-style:normal;border-radius:5px;padding:1px 6px;font-size:11px;white-space:nowrap}
.iv-sc.warn{background:#FFF1D6;color:var(--amber)}
.iv-sc.blue{background:#DCEAFF;color:var(--blue)}
.iv-sc.on{background:#D6F0E0;color:var(--green)}

/* ===========================================================================
   二级看板（弹窗里）：这个型号的货都在哪、每一台串码和库龄
   挂在 #imodal（宽 1100），所以内容列可以多一点；但**照样不许横向溢出**。
   =========================================================================== */
.ivm-top{padding:2px 0 10px;border-bottom:1px solid var(--line);margin-bottom:12px}
.ivm-name{font-size:15px;font-weight:600;line-height:1.5}
.ivm-meta{display:flex;flex-wrap:wrap;gap:6px 16px;margin-top:6px;font-size:12.5px;color:var(--ink-2)}
.ivm-meta b{color:var(--ink);font-variant-numeric:tabular-nums}

/* 库龄分布：一眼看出这批货压了多久 */
.ivm-agebar{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin:10px 0 2px}
.ivm-agecell{min-width:78px;text-align:center;border:1px solid var(--line);
  border-radius:var(--r);padding:5px 10px;background:var(--card)}
.ivm-agecell b{display:block;font-size:18px;line-height:1.2;font-variant-numeric:tabular-nums}
.ivm-agecell s{display:block;text-decoration:none;font-size:11px;color:var(--ink-3)}
.ivm-agecell.good b{color:var(--green)}
.ivm-agecell.blue b{color:var(--blue)}
.ivm-agecell.warn b{color:var(--amber)}
.ivm-agecell.bad b{color:var(--red)}
.ivm-agehint{flex:1;min-width:180px}

/* 一堆一块 */
.ivm-stk{margin-top:16px}
.ivm-stk-h{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;
  padding:8px 12px;border-radius:var(--r) var(--r) 0 0;background:var(--line-2);font-size:13px}
.ivm-stk-h i{font-style:normal}
.ivm-stk-h b{font-weight:600}
.ivm-stk-h span{font-size:12px;color:var(--ink-2)}
.ivm-stk-h span b{font-size:14px;color:var(--ink)}
.ivm-stk-hint{margin-left:auto}
.ivm-stk-ok .ivm-stk-h{background:var(--green-50)}
.ivm-stk-ok .ivm-stk-h b{color:var(--green)}
.ivm-stk-go .ivm-stk-h{background:var(--blue-50)}
.ivm-stk-go .ivm-stk-h b{color:var(--blue)}
.ivm-stk-no .ivm-stk-h{background:var(--red-50)}
.ivm-stk-no .ivm-stk-h b{color:var(--red)}

/* 一个位置（可展开） */
.ivm-pls{border:1px solid var(--line);border-top:0;border-radius:0 0 var(--r) var(--r);overflow:hidden}
.ivm-pl{border-top:1px solid var(--line)}
.ivm-pl:first-child{border-top:0}
.ivm-pl>summary{display:flex;align-items:baseline;gap:9px;flex-wrap:wrap;
  padding:9px 12px;cursor:pointer;font-size:12.5px;list-style:none}
.ivm-pl>summary::-webkit-details-marker{display:none}
.ivm-pl>summary::before{content:"▸";color:var(--ink-3);font-size:11px}
.ivm-pl[open]>summary::before{content:"▾"}
.ivm-pl>summary:hover{background:#FCFDFF}
.ivm-pl[open]>summary{background:#FCFDFF}
.ivm-picon{font-style:normal}
.ivm-pname{font-size:13px;max-width:340px;overflow-wrap:anywhere}
.ivm-kind{font-style:normal;font-size:11px;color:var(--blue);background:var(--blue-50);
  border-radius:5px;padding:1px 6px;white-space:nowrap}
.ivm-pcity{text-decoration:none;color:var(--ink-3);font-size:11.5px}
.ivm-pqty{font-variant-numeric:tabular-nums;font-size:15px;color:var(--ink)}
.ivm-punit{text-decoration:none;color:var(--ink-3);font-size:11px;margin-left:-5px}
.ivm-page{font-size:11.5px;color:var(--ink-3);font-variant-numeric:tabular-nums}
.ivm-page.bad{color:var(--red)}
.ivm-page.warn{color:var(--amber)}
.ivm-pcan{font-style:normal;font-size:11.5px;color:var(--amber);font-weight:600}
.ivm-popen{margin-left:auto;font-size:11.5px;color:var(--ink-3)}
.ivm-pl[open] .ivm-popen{visibility:hidden}

/* 每一台串码：flex-wrap —— 长串号也溢不出去 */
.ivm-sl{padding:2px 12px 8px;background:#FAFBFC}
.ivm-s{display:flex;align-items:baseline;gap:9px;flex-wrap:wrap;
  padding:4px 0;border-bottom:1px dashed var(--line-2);font-size:12px}
.ivm-s:last-child{border-bottom:0}
.ivm-fifo{font-style:normal;flex:none;min-width:46px;font-size:11px;
  color:var(--green);background:var(--green-50);border-radius:5px;padding:1px 5px;text-align:center}
.ivm-fifo.off{background:none}
.ivm-sn{font-size:12.5px;color:var(--ink);font-weight:500;overflow-wrap:anywhere}
.ivm-imei{color:var(--ink-3)}
.ivm-sage{font-variant-numeric:tabular-nums;color:var(--ink-2)}
.ivm-sage.bad{color:var(--red)}
.ivm-sage.warn{color:var(--amber)}
.ivm-sage.blue{color:var(--blue)}
.ivm-sdate{color:var(--ink-3);font-variant-numeric:tabular-nums}
.ivm-sform{font-size:11px;color:var(--blue);background:var(--blue-50);border-radius:5px;padding:1px 6px}
.ivm-scost{color:var(--ink-2);font-variant-numeric:tabular-nums}
.ivm-scomp{color:var(--ink-3);margin-left:auto}
.ivm-sst{font-size:11px;color:var(--amber);background:var(--amber-50);border-radius:5px;padding:1px 6px}
.ivm-sfoot{display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  padding:8px 12px 10px;background:#FAFBFC;border-top:1px solid var(--line-2)}

@media (max-width:720px){
  .iv-stk-pl{min-width:0}
  .ivm-pname{max-width:200px}
  .ivm-scomp{margin-left:0}
}

/* 徽标补充：结论用的三档 */
.pill.good{background:var(--green-50);color:var(--green)}
.pill.warn{background:var(--amber-50);color:var(--amber)}
.pill.bad{background:var(--red-50);color:var(--red)}
/* ★ 2026-09-24 补：statusPill() 里一直在用 'amber'，但这里**从来没定义过** ——
   所以「部分到货」「审批中」这些一直显示成默认灰色，看不出是在办。 */
.pill.amber{background:var(--amber-50);color:var(--amber)}
.pill.red{background:var(--red-50);color:var(--red)}

/* 改档弹窗里的「会花谁家的额度」 */
.scope-quota{margin-top:12px;padding:10px 12px;background:var(--blue-50);border-radius:var(--r);
  font-size:12.5px;line-height:1.9}
.scope-quota .k{margin:0 0 4px;font-size:12px;color:var(--ink-3);font-weight:600}

/* ===========================================================================
   门店改档 —— 老板周六的固定动作
   顺序：选门店 → 看额度 → 在这家店的库存里搜货 → 勾选 → 放开
   =========================================================================== */
.rl-head{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:10px}
.rl-quota{display:flex;gap:20px;flex-wrap:wrap;align-items:center;
  background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);
  padding:14px 18px;margin-bottom:12px}
.rl-quota-main{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap}
.rl-quota-main .k{font-size:13.5px;color:var(--ink-2)}
.rl-quota-main .v{font-size:32px;font-weight:600;font-variant-numeric:tabular-nums;line-height:1}
.rl-quota-main .v.good{color:var(--green)}
.rl-quota-main .v.off{color:var(--ink-3)}
.rl-quota-main .u{font-size:13px;color:var(--ink-2)}
.rl-quota-side{margin-left:auto;font-size:12.5px;color:var(--ink-2);line-height:1.9;text-align:right}
.rl-quota-side b{font-variant-numeric:tabular-nums}

.rl-search{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:10px}
.rl-search input#rl-q{flex:1;min-width:220px;max-width:none}
.rl-check{display:inline-flex;align-items:center;gap:6px;font-size:13px;color:var(--ink-2);
  white-space:nowrap;cursor:pointer}
.rl-check input{width:auto}

.rl-bar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;
  background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);
  padding:10px 14px;margin-bottom:10px}
.rl-sel{font-size:13.5px}
.rl-sel b{font-size:17px;font-variant-numeric:tabular-nums}
.goodTxt{color:var(--green)}
.badTxt{color:var(--red)}
.blueTxt{color:var(--blue)}
.amberTxt{color:var(--amber)}
.rl-name{font-size:13.5px;font-weight:500}
.rl-pager{display:flex;align-items:center;gap:12px;justify-content:center;padding:12px 0}

table.grid tbody tr.on,table tbody tr.on{background:var(--amber-50)}
table tbody tr td .mono.sub{color:var(--ink-3);font-size:11.5px}
@media (max-width:760px){
  .rl-quota-side{margin-left:0;text-align:left}
  .rl-search input#rl-q{min-width:140px}
}

/* ===========================================================================
   价格册 —— 一个商品一行 × 一个价档一列，格子点开就改
   形状照老板那张「报价图」：列多、要横向滚，所以第一列固定住
   =========================================================================== */
.px-bar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:6px}
.px-tiers-label{font-size:12.5px;color:var(--ink-3);flex:none}
.px-tiers{display:flex;flex-wrap:wrap;gap:6px;align-items:center}

/* ★ 2026-10-01 老板：「表上方可以减少一些，让整个报价表显示的比例到 80%」。
   做法：把「价格档」和「品牌」两排挤进**同一行**（各自横向滚，永远不换行），
   原来那几行说明收进「怎么用」折叠里，统计挪到工具栏最右边。
   省下来的高度全部让给表格（见下面 .px-wrap 的 max-height）。 */
.px-bar-top{gap:6px;margin-bottom:6px}
.px-bar-top .px-tiers{flex:1 1 260px;min-width:0;flex-wrap:nowrap;
  overflow-x:auto;overflow-y:hidden;padding-bottom:2px}
.px-bar-top .px-tiers::-webkit-scrollbar{height:5px}
.px-bar-top .px-tiers::-webkit-scrollbar-thumb{background:#D6DCE6;border-radius:3px}
.px-bar-top .px-tiers .chip{flex:none;padding:3px 11px;font-size:12px}
.px-sep{margin-left:2px;padding-left:10px;border-left:1px solid var(--line)}
.px-stat{margin-left:auto;font-size:12.5px;color:var(--ink-2);white-space:nowrap}
.px-stat b{font-variant-numeric:tabular-nums}

/* 「怎么用」折叠：默认只占一行，要看点开 —— 说明还在，但不占地方 */
.px-help{font-size:12px;color:var(--ink-3);margin:0 0 8px}
.px-help summary{cursor:pointer;color:var(--blue);font-size:12.5px;outline:none;
  display:inline-flex;align-items:center;gap:5px;user-select:none}
.px-help summary::-webkit-details-marker{display:none}
.px-help summary::before{content:'?';display:inline-flex;width:15px;height:15px;
  border-radius:50%;background:var(--blue-50);color:var(--blue);font-size:11px;
  font-weight:700;align-items:center;justify-content:center}
.px-help[open] summary{margin-bottom:6px}
.px-help p{margin:0;line-height:1.85;background:#FAFBFD;border:1px solid var(--line);
  border-radius:var(--r);padding:9px 13px}
.px-tiers .chip s{text-decoration:none;color:var(--amber);margin-left:2px;font-size:10px}
.px-tiers .chip.px-all{background:var(--line-2);color:var(--ink-2)}
.px-tiers .chip.px-all:not(.on){border-style:solid}

/* ★ 2026-09-24 老板反馈「显示哪些城市的点击后没有明显的视觉效果」——
   查下来是 .chip 压根没有 .on 的样式定义，选中和没选中长得一模一样。
   补上：选中 = 实心蓝底白字；没选中的淡下去 + 虚线边，一眼分得清。 */
.chip.on{
  background:var(--blue);border-color:var(--blue);color:#fff;font-weight:600;
  box-shadow:0 1px 3px rgba(0,110,255,.3);
}
.chip.on:hover{background:#0059D6;border-color:#0059D6;color:#fff}
.px-tiers .chip:not(.on):not(.px-all){color:var(--ink-3);border-style:dashed}
.px-tiers .chip:not(.on):not(.px-all):hover{color:var(--blue);border-style:solid}
.px-tiers .chip.on s{color:#CFE3FF}

/* 品牌那一排：跟档位同一套交互，后面缀一个款式数量的灰色小字 */
.px-brands .chip .n{font-size:11px;opacity:.65;margin-left:3px;font-variant-numeric:tabular-nums}
.px-brands .chip.on .n{opacity:.9}

/* 商品列拖拽调宽：表格用 fixed 布局，宽度由 colgroup 控制，拖的时候只改 col 不重绘 */
.px-table{table-layout:fixed}
.px-grip{
  position:absolute;top:0;right:-3px;width:7px;height:100%;
  cursor:col-resize;z-index:6;
}
.px-grip::after{
  content:'';position:absolute;top:24%;left:3px;width:1px;height:52%;background:var(--line);
}
.px-grip:hover{background:var(--blue-50)}
.px-grip:hover::after{background:var(--blue);width:2px;left:2.5px}
body.px-dragging{cursor:col-resize;user-select:none}
.px-check{display:inline-flex;align-items:center;gap:6px;font-size:13px;color:var(--ink-2);
  white-space:nowrap;cursor:pointer}
.px-check input{width:auto}
.px-head{margin-bottom:8px}
.px-stat{font-size:13px;color:var(--ink-2)}
.px-stat b{font-variant-numeric:tabular-nums}
.warnTxt{color:var(--amber)}
.goodTxt{color:var(--green)}
.badTxt{color:var(--red)}

/* ★ 2026-10-01：高度从「视口 − 300」提到「视口 − 170」——
   顶部瘦身之后，表格能占到屏幕的八成，老板不用老往下滚。 */
.px-wrap{overflow:auto;border:1px solid var(--line);border-radius:var(--r-lg);background:var(--card);
  max-height:calc(100vh - 170px);min-height:320px}
.px-table{border:0;border-radius:0;min-width:100%}
.px-table th,.px-table td{border-bottom:1px solid var(--line-2);padding:6px 10px;font-size:13px}
.px-table thead th{position:sticky;top:0;z-index:3;background:var(--card);border-bottom:1px solid var(--line)}

/* ★ 2026-10-01 修「字体回重叠了」——
   根因两条，缺一条都还会叠：
     ① 商品名 white-space:nowrap，格子 260px 而名字宽到 296px，
        溢出的 36px 直接画到隔壁价格格上，和价格数字叠在一起
        → 给格子加 overflow:hidden + 文字走省略号，**永远不许溢出**。
     ② `.sub` 这个类在样式表里**压根没定义过**，第二行是按 body 的 14px 渲染的，
        比第一行标题（13px）还大，两行贴在一起看着就是一坨
        → 这里把商品列两行的字号/行高钉死。
   顺带：sticky 列提到 z-index 12（原来 4 跟价格格的定位层容易打架），
   右边缘加一道渐隐阴影，一眼看得出「这一列浮在别的列上面」。 */
.px-table th.px-fix,.px-table td.px-fix{position:sticky;left:0;z-index:12;background:var(--card);
  border-right:1px solid var(--line);min-width:220px;max-width:280px;text-align:left;
  overflow:hidden}
.px-table thead th.px-fix{z-index:13}
.px-table th.px-fix::after,.px-table td.px-fix::after{
  content:'';position:absolute;top:0;right:-7px;width:7px;height:100%;pointer-events:none;
  background:linear-gradient(90deg,rgba(24,38,72,.08),rgba(24,38,72,0))}
.px-fix-in{overflow:hidden}
/* ★ 2026-10-01 价档列：一列一套色 + 右对齐
   老板原话：「每个地市列和价格没有对齐，会影响到地市的价格判断。
             建议不同列有不同色系区隔，对齐。」
   ① **对齐**：表头和价格都右对齐、共用同一条右边缘 —— 8 个市并排时，
      一眼看得出这个价属于哪个市（以前表头居中、数字靠右，两边不搭）。
   ② **色系**：每列一条 3px 色条 + 极浅同色底 + 格子左边线；鼠标压到哪一格，
      整列一起亮（.px-hl，表头也整块变色）。颜色按「档的固定次序」发，
      相邻两列永远不同色（厦门有两个档，按地市取色会撞成一个颜色）。
   颜色由 renderTable() 里那段 <style id="px-colors"> 按「第几列」写下来，
   这里只用变量 --tc（色条/字色）和 --tcl（同色浅底）。 */
.px-table thead th.px-th{text-align:right;min-width:96px;white-space:nowrap;font-size:12.5px;
  padding-right:14px;border-top:3px solid var(--tc,#9AA2B1);
  background:var(--tcl,#F5F7FA);color:var(--tc,#3C4658)}
.px-th .px-s{display:block;text-decoration:none;color:var(--ink-3);font-size:10px;font-weight:400}
.px-table thead th.px-cost{border-top-color:var(--tc,#5A6272)}
.px-table tbody td.px-cell{border-left:1px solid var(--tcl,#F1F3F7)}
.px-name{font-size:13px;font-weight:600;line-height:1.5;white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis}
.px-nm{font-weight:500}
/* 品牌小牌 —— 「同城苹果」蓝、「苹果」橙，扫一眼就分得清是两套档案 */
.px-bd{display:inline-block;font-size:10.5px;font-weight:700;line-height:1.5;
  padding:0 6px;border-radius:4px;background:var(--blue-50);color:var(--blue);margin-right:5px}
.px-bd.px-bd-other{background:#FFF3E0;color:#B26A00}
.px-fix .sub{font-size:11.5px;line-height:1.5;color:var(--ink-3);white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis}
.px-cell{text-align:right;cursor:pointer;font-variant-numeric:tabular-nums;position:relative;
  padding-right:14px}
.px-cell:hover{background:var(--tcl,#EAF2FF)}
.px-v{font-weight:500}
.px-none{color:#C2C8D2;font-size:12px}

/* 底价列（权限够的人才看得到）—— 中性灰，跟价档列区分开 */
.px-table tbody td.px-cost{background:var(--tcl,#EFF1F5)}
.px-table tbody td.px-cost:hover{background:#E7EAF0}
.px-table tbody td.px-cost.px-miss{
  background:repeating-linear-gradient(45deg,#FCFCFD,#FCFCFD 6px,#F2F4F7 6px,#F2F4F7 12px)}

/* 空格子 = 这个档没报这款（斜纹底，一眼看出「不是 0 元」） */
.px-table tbody td.px-miss{
  background:repeating-linear-gradient(45deg,#FCFCFD,#FCFCFD 6px,#F5F7FA 6px,#F5F7FA 12px)}

/* 整列高亮 —— 鼠标压在哪一格，这一列全亮 */
.px-table tbody td.px-hl{background:var(--tcl,#EAF2FF)}
.px-table tbody td.px-miss.px-hl{
  background:repeating-linear-gradient(45deg,var(--tcl,#EAF2FF),var(--tcl,#EAF2FF) 6px,#F5F7FA 6px,#F5F7FA 12px)}
.px-table thead th.px-hl{background:var(--tc,#3C4658);color:#fff}
.px-table thead th.px-hl .px-s{color:rgba(255,255,255,.85)}

/* 改了还没保存 → 这格镶一圈琥珀色边 + 右上角一个小点（保存后自动消失） */
.px-table tbody td.px-dirty{box-shadow:inset 0 0 0 2px var(--amber)}
.px-table tbody td.px-dirty::after{
  content:'';position:absolute;top:3px;right:3px;width:5px;height:5px;
  border-radius:50%;background:var(--amber);pointer-events:none}

/* 「保存改动」有货时闪一下，让老板知道「还有东西没写进去」 */
#px-save:not(:disabled){box-shadow:0 0 0 3px var(--amber-50)}
#px-undo:not(:disabled){color:var(--ink-2);border-color:var(--line)}
/* ★ 2026-10-01 价格册：格子里那行「盈亏」（= 报价 − 底价，底价按库存同机型均价自动算）。
   正数绿（赚）、负数红（亏）——前面带 + / − 号，不靠颜色也能看懂。 */
.px-m{display:block;text-decoration:none;font-size:11px;font-weight:400;color:var(--green);margin-top:1px}
.px-m.px-neg{color:var(--red)}
.px-src{display:block;text-decoration:none;font-size:10px;font-weight:400;color:var(--ink-3)}
.px-editing{outline:2px solid var(--blue);outline-offset:-2px;background:#fff}
.px-in{width:100%;min-width:84px;text-align:right;font-size:13px;padding:4px 6px}

/* 保存前那张「改动清单」（老板要的：低于底价先给个汇总、再确认一次） */
.px-low{background:var(--red-50);border:1px solid #F3C9C9;border-left:4px solid var(--red);
  border-radius:var(--r);padding:10px 14px;margin:0 0 10px}
.px-low h4{margin:0 0 4px;font-size:13.5px;color:var(--red);font-weight:700}
.px-low p{margin:0;font-size:12.5px;color:var(--ink-2);line-height:1.75}
.px-ok{background:var(--green-50);border:1px solid #CBEBD8;border-left:4px solid var(--green);
  border-radius:var(--r);padding:9px 14px;margin:0 0 10px;font-size:12.5px;color:var(--green)}
.px-difftb{max-height:44vh;overflow:auto;border:1px solid var(--line);border-radius:var(--r)}
.px-difftb td,.px-difftb th{white-space:nowrap;font-variant-numeric:tabular-nums;font-size:12.5px}
.px-difftb td:first-child{white-space:normal;min-width:180px}
.px-confirm-bar{display:flex;align-items:center;gap:10px;margin-top:14px}
.px-confirm-bar .px-note{flex:1;font-size:12px;color:var(--ink-3)}
.btn.danger.solid{background:var(--red);border-color:var(--red);color:#fff}
.btn.danger.solid:hover{background:#C42F2F;border-color:#C42F2F}

/* ===========================================================================
   对外报价单（弹窗里的那张单子 + 导出的报价图）
   ---------------------------------------------------------------------------
   2026-10-01 老板两句话：
     ①「这个报价图的表头需要改动：同城苹果保持；非同城苹果不需要同城激活，
        可以表头备注『全国货』（全国货三个字用红色字体）」
     ②「整个页面的美观度不好看，需要你调整一下」
   所以这里把工具栏、抬头、表格三块都重排了一遍。
   =========================================================================== */
.qs-bar{background:#FAFBFD;border:1px solid var(--line);border-radius:var(--r);
  padding:10px 12px;margin-bottom:12px}
.qs-bar-row{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.qs-bar-row+.qs-bar-out{margin-top:8px;padding-top:8px;border-top:1px dashed var(--line)}
.qs-lab{font-size:12.5px;color:var(--ink-3);flex:none}
.qs-bar .search{width:auto}
.qs-tip{margin-left:auto;font-size:12.5px;color:var(--ink-3)}
.btn.ghost{background:transparent;border-color:transparent;color:var(--ink-2)}
.btn.ghost:hover{background:#EFF2F7;border-color:transparent}

/* ★ 2026-10-01 单子本体照老板手工那张报价图重排：
   白底 + 深蓝标题居中 + 副标题药丸 + **两栏并排** + 底下一条深蓝脚注带。
   这么改还有一层用意：弹窗里看到的这一屏，**就是导出的那张图**（同一套
   分行规则 planPanes、同一套抬头口径 sheetHead），老板「看到什么样，发出去就什么样」。

   为什么两栏：一栏的话 70 款就是一张 3000px 的长条，发到微信里要划半天；
   两栏高度直接减半，一屏能看完。 */
.qs{border:1px solid var(--line);border-radius:var(--r-lg);overflow:hidden;background:var(--card)}

/* 抬头：白底（不是深蓝条了 —— 深蓝留给表头和底下那条脚注带） */
.qs-title{background:#fff;padding:20px 20px 14px;text-align:center;
  border-bottom:1px solid var(--line-2)}
.qs-title h2{margin:0;font-size:21px;font-weight:700;color:#1F3864;letter-spacing:.4px}
.qs-subline{margin-top:9px;display:flex;align-items:center;justify-content:center;
  gap:10px;flex-wrap:wrap}
.qs-sub{display:inline-block;border-radius:999px;padding:3px 16px;font-size:13px;
  background:#EAF1FE;color:#1F3864;font-weight:600}
/* 「全国货」—— 要红字。白底上做成淡红药丸 + 红字：一眼看见，又不像警告那么吵。 */
.qs-sub.qs-red{background:#FDECEA;color:#C0322F;font-weight:700;letter-spacing:1.5px}
.qs-badge{display:inline-block;border-radius:999px;padding:3px 13px;font-size:12.5px;
  background:var(--line-2);color:var(--ink-2);white-space:nowrap}
.qs-badge.other{background:#FDECEA;color:#C0322F;font-weight:700}
.qs-date{font-size:12px;color:var(--ink-3);white-space:nowrap}

/* 两栏
   ★ 2026-10-01：两栏的行数天然不一样（一个型号的颜色不能劈到两栏去），
     各高各的会一栏长一栏短、下缘参差。改成 align-items:stretch ——
     两栏的框一样高，矮的那栏底下是一块规整留白，版面看着才齐。
     （导出图那边同理，见 price.js 的 paneBot） */
.qs-panes{display:flex;gap:16px;padding:14px 16px;align-items:stretch}
.qs-pane{flex:1;min-width:0;display:flex;flex-direction:column;
  border:1px solid var(--line);border-radius:10px;overflow:hidden}
.qs table{border-collapse:collapse;width:100%;table-layout:fixed}
.qs thead th{background:#1F3864;color:#fff;font-weight:600;font-size:12.5px;
  padding:9px 8px;text-align:center;border-bottom:1px solid #1F3864}
.qs tbody td{padding:8px 8px;font-size:13.5px;text-align:center;
  border-bottom:1px solid var(--line-2);color:var(--ink)}
.qs tbody tr:last-child td{border-bottom:0}
.qs tbody tr.alt td:not(.qs-model){background:#FAFBFD}
/* ⚠️ 必须写成 `.qs tbody td.qs-model`：`.qs tbody td` 有 3 个选择器，
   单写 `.qs-model` 会被它盖掉（以前踩过）。 */
.qs tbody td.qs-model{background:#F2F5F9;vertical-align:middle;
  border-right:1px solid var(--line-2)}
.qs tbody td.qs-model b{display:block;color:#C0322F;font-size:15px;font-weight:700;line-height:1.35}
.qs-gb2{display:block;color:#C0322F;font-size:12.5px;font-weight:600;text-decoration:none;
  line-height:1.4}
.qs-gbd{display:block;font-size:11px;color:var(--ink-3);font-weight:400;text-decoration:none}
.qs tbody td.qs-price{font-variant-numeric:tabular-nums}
.qs-price b{font-size:16px;color:#C0322F;font-weight:700}
.qs-na{color:var(--ink-3);font-size:12.5px}
.qs-cond{font-size:12px;color:var(--ink-3);text-decoration:none}

/* 底下那条深蓝带（老板手工图里那句「本地激活，按标准拍照返图」） */
.qs-band{background:#1F3864;color:#fff;text-align:center;font-size:14.5px;font-weight:600;
  padding:13px 16px;letter-spacing:1px}

/* ===========================================================================
   客户端预览（内部系统里看「客户手机上长什么样」）
   =========================================================================== */
.cp-bar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;
  background:#FAFBFD;border:1px solid var(--line);border-radius:var(--r);
  padding:10px 12px;margin-bottom:10px}
.cp-bar .search{width:auto}
.cp-tip{font-size:12.5px;color:var(--ink-2);line-height:1.8;background:var(--blue-50);
  border-left:3px solid var(--blue);border-radius:var(--r);padding:8px 13px;margin:0 0 12px}
.cp-count{font-size:13px;color:var(--ink-2);margin:0 0 10px}
.cp-card{border:1px solid var(--line);border-radius:var(--r-lg);overflow:hidden;
  background:var(--card);margin-bottom:8px}
/* ★★★ 2026-10-21 老板第 3/5 条（「品牌名称要显眼，字体要粗」
   +「整页显示内容要多 30% 的机型，字体可以调节小一些」）：
   ① **品牌当大标题**（18px/800 字重）—— 改之前品牌只是右上角一个
      10.5px 的小标签、大标题是型号名 ⇒ 一眼扫过去全是型号。
   ② 型号降成**同行小字**（`cp-model`），徽标靠右。
   ③ 卡片头从**两行压成一行**（省约 20px/卡）、表格行距 9px→5px。
   ⇒ 单个 4 色型号块高度 ≈ 246px → 180px（**-27%**），
     再加上卡片间距 12px→8px，一屏能多看三成以上。 */
.cp-hd{background:#1F3864;color:#fff;padding:7px 12px}
.cp-brandrow{margin:0;display:flex;align-items:baseline;gap:8px;line-height:1.25}
.cp-brand{font-size:18px;font-weight:800;color:#fff;letter-spacing:.5px;white-space:nowrap}
.cp-brand.other{color:#FFD9D6}
.cp-model{text-decoration:none;font-size:12.5px;font-weight:600;color:rgba(255,255,255,.92);
  flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cp-cap{margin-left:auto;font-size:11px;font-weight:500;color:rgba(255,255,255,.86);
  flex:none;white-space:nowrap}
.cp-bd{background:rgba(255,255,255,.16);border-radius:999px;padding:1px 9px;
  font-size:11px;font-weight:500;text-decoration:none}
.cp-bd.other{background:#fff;color:#C0322F;font-weight:700}
.cp-red{background:#fff;color:#C0322F;border-radius:999px;padding:1px 10px;font-weight:700;
  font-size:11px;flex:none}
.cp-dim{font-weight:500;color:#fff}
.cp-tb{border-collapse:collapse;width:100%}
.cp-tb th{background:#F3F6FA;color:#48505F;font-weight:600;font-size:11.5px;
  padding:5px 10px;text-align:center;border-bottom:1px solid var(--line)}
.cp-tb td{padding:5px 10px;font-size:12.5px;text-align:center;color:var(--ink);
  border-bottom:1px solid var(--line-2)}
.cp-tb tr:last-child td{border-bottom:0}
.cp-pr{font-weight:700;color:#C0322F;font-variant-numeric:tabular-nums;font-size:13.5px}
.cp-cond{margin-left:5px;font-size:10.5px;color:var(--ink-3);text-decoration:none}
.cp-stk{display:block;font-size:10.5px;color:var(--ink-3);text-decoration:none;margin-top:1px}
.cp-foot{font-size:12px;color:var(--ink-3);text-align:center;padding:6px 0 2px}

/* ===========================================================================
   开单 —— 客户决定价，价格册自动带出来
   =========================================================================== */
.or-head{display:flex;gap:14px;flex-wrap:wrap;align-items:flex-end;margin-bottom:6px}
.or-tier{background:var(--blue-50);border-radius:var(--r);padding:8px 14px;font-size:13px;
  display:flex;align-items:baseline;gap:8px;flex-wrap:wrap}
.or-tier-k{font-size:11.5px;color:var(--ink-3)}
.or-tier b{font-size:15px}
/* ★★ 2026-10-14 信用条（选客户就地显示，不等提交）——
     红=开不了（超期/超额度/停开单），绿=正常。跟提交时拦人的口径同一份。 */
.or-credit{margin:-2px 0 8px}
.or-credit-bar{border-radius:var(--r);padding:8px 14px;font-size:13px;line-height:1.5}
.or-credit-bar.bad{background:#fdecec;border:1px solid #f3c2c2;color:#a3242b}
.or-credit-bar.ok{background:#eaf6ec;border:1px solid #bfe3c6;color:#1d6b33}
.or-credit-bar b{font-size:13.5px}
.or-st-done{padding:4px 10px;font-size:12.5px}
/* 送货任务详情（2026-10-14）*/
.dl-detail{display:grid;gap:6px}
.dl-row{display:flex;gap:12px;font-size:13px}
.dl-row>span{flex:0 0 88px;color:var(--ink-3);font-size:12.5px}
.dl-row>b{font-weight:500}
.dl-photo{margin-top:8px}
.dl-photo img{max-width:100%;max-height:280px;border-radius:var(--r);border:1px solid var(--line)}
.dl-photo-preview{margin-top:6px}
.or-add{position:relative;display:flex;gap:8px;margin-bottom:12px}
.or-hits{position:absolute;top:100%;left:0;right:0;z-index:30;background:#fff;margin-top:4px;
  border:1px solid var(--line);border-radius:var(--r);box-shadow:0 8px 24px rgba(20,30,60,.12);
  max-height:320px;overflow:auto}
.or-hit{display:flex;align-items:baseline;gap:10px;padding:9px 14px;cursor:pointer;font-size:13px}
.or-hit:hover{background:var(--blue-50)}
.or-hit s{text-decoration:none;margin-left:auto}
.or-table td{vertical-align:middle}
.or-c{text-align:center;white-space:nowrap}
.or-num{width:88px;text-align:center;font-size:13px;padding:5px 6px}
.or-sum{display:flex;align-items:center;gap:22px;flex-wrap:wrap;background:var(--card);
  border:1px solid var(--line);border-radius:var(--r-lg);padding:12px 18px;margin-top:12px}
.or-sum>div{display:flex;flex-direction:column;gap:2px}
.or-sum .k{font-size:11.5px;color:var(--ink-3)}
.or-sum b{font-size:17px;font-variant-numeric:tabular-nums}
.or-sum #or-save{margin-left:auto}
.or-h3{font-size:14px;margin:22px 0 8px;font-weight:600}
.or-actions{display:flex;gap:8px;margin-top:14px;flex-wrap:wrap}

/* ---- 串号相关（2026-09-24 加）----
   开单就等于出库，扫串号是开单动作的一部分 —— 所以要让老板一眼看出
   哪一行还没扫、扫到第几台了。 */
/* 待补串码提醒条：常驻页面最上面，直到他补完 */
.or-todo{
  display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  background:var(--amber-50);color:#8A5A00;border:1px solid #F0DCB4;
  border-radius:var(--r);padding:9px 14px;margin-bottom:10px;font-size:13px;
}
.or-todo b{color:#6B4600}
.or-todo .btn{margin-left:auto;background:#fff;border-color:#E7D3A8;color:#8A5A00}
/* 「扫串号」按钮：没扫齐是普通样，扫齐了变绿（一眼扫过去就知道哪行还没弄完） */
.btn.or-scan.ok,.btn.or-scan3.ok{border-color:var(--green);color:var(--green);background:var(--green-50)}
/* 扫码输入框要够大 —— 扫码枪和整批粘贴都靠它 */
.sc-in{
  width:100%;font-size:16px;padding:9px 12px;border:1px solid var(--line);
  border-radius:var(--r);resize:vertical;
  font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
}
.sc-in:focus{outline:2px solid var(--blue);outline-offset:-2px;border-color:var(--blue)}
.sc-msg{min-height:20px;font-size:13px;margin:8px 0}
.sc-msg.ok{color:var(--green)}
.sc-msg.warn{color:var(--amber)}
.sc-msg.bad{color:var(--red)}
/* 扫到的串号做成小标签，扫一堆也看得清、还能单独删 */
.sc-list{display:flex;flex-wrap:wrap;gap:6px;min-height:28px}
.sn-list{display:flex;flex-wrap:wrap;gap:4px;margin-top:5px}
.sc-sn{
  display:inline-flex;align-items:center;gap:5px;
  background:var(--line-2);border-radius:6px;padding:2px 8px;font-size:12px;
  font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
}
.sc-sn s{text-decoration:none;color:var(--ink-3);cursor:pointer;font-size:13px}
.sc-sn s:hover{color:var(--red)}
.sc-done{
  margin-top:10px;padding:8px 12px;border-radius:var(--r);
  background:var(--green-50);color:var(--green);font-size:13px;
}

/* ---- 「从系统里挑串号」（2026-10-01）--------------------------------------
   老板的原话：「我们大部分的货都是委托在客户那里的，需要增加一个选择 sn 的条件
   去做销售。你优化一下，尽量提高效率」+「我们目前是群沟通，会看实物串码，
   所以要有手动输入，模糊搜索」。

   所以这块的目标很具体：**搜一截串号 → 点一下就选上**，不用扫、不用粘。
   老板要的四点全在样式里体现：
     · 一屏看全不翻页 → `.pk-list` 给足高度，只滚不分页
     · 列表直接带库龄和在谁手上 → 每行都写着，不用点进去查
     · 点一下就选中 → 整行可点，不用打勾再确认
     · 不能卖的灰掉但仍可挑（老板的口径：只提醒不拦）→ `.pk-row.off`
   -------------------------------------------------------------------------- */
.pk{margin-top:16px;border-top:1px dashed var(--line);padding-top:12px}
.pk-head{display:flex;align-items:baseline;gap:9px;margin-bottom:9px;flex-wrap:wrap}
.pk-head b{font-size:13.5px}
.pk-head .sub{font-size:12px;color:var(--ink-3)}
.pk-bar{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-bottom:8px}
.pk-bar input[type=text]{
  flex:1 1 240px;min-width:180px;font-size:14px;padding:7px 11px;
  border:1px solid var(--line);border-radius:var(--r);
}
.pk-bar input[type=text]:focus{outline:2px solid var(--blue);outline-offset:-2px;border-color:var(--blue)}
.pk-bar select{font-size:13.5px;padding:7px 9px;border:1px solid var(--line);border-radius:var(--r);max-width:230px}
.pk-chk{display:inline-flex;align-items:center;gap:6px;font-size:13px;color:var(--ink-2);cursor:pointer;white-space:nowrap}
.pk-note{font-size:12.5px;color:var(--ink-3);margin-bottom:7px;line-height:1.7}
.pk-list{
  max-height:min(50vh,430px);overflow:auto;
  border:1px solid var(--line);border-radius:var(--r);background:#fff;
}
.pk-row{
  display:flex;align-items:center;gap:10px;
  padding:7px 11px;font-size:13px;cursor:pointer;
  border-bottom:1px solid var(--line-2);
}
.pk-row:last-child{border-bottom:0}
.pk-row:hover{background:var(--blue-50)}
.pk-row.off{color:var(--ink-3);background:#FAFBFC}
.pk-row.off:hover{background:var(--amber-50)}
.pk-row.taken{opacity:.35;text-decoration:line-through;cursor:default}
.pk-row.taken:hover{background:transparent}
.pk-sn{
  font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  font-weight:600;letter-spacing:.01em;min-width:158px;
}
.pk-holder{color:var(--ink-2);min-width:150px;flex:1 1 130px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pk-flag{
  font-size:11px;padding:1px 7px;border-radius:5px;white-space:nowrap;
  background:var(--line-2);color:var(--ink-2);
}
.pk-flag.out{background:#FFF3E0;color:#8A5A00}
.pk-flag.bad{background:#FDECEC;color:var(--red)}
/* ★ 2026-10-13「要提醒」这一档：能卖，但有合规/串货风险 → 醒目又不拦（点一下确认就放行） */
.pk-flag.warn{background:var(--amber-50);color:var(--amber);font-weight:600}
.pk-row.needwarn{background:#FFFCF5}
.pk-row.needwarn:hover{background:var(--amber-50)}
.pk-age{font-size:12px;color:var(--ink-3);white-space:nowrap;font-variant-numeric:tabular-nums}
.pk-ok{margin-left:auto}
.pk-empty{padding:20px 14px;text-align:center;color:var(--ink-3);font-size:13px;line-height:1.9}
.pk-alt{
  font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  font-size:12px;color:var(--ink-2);padding:2px 0;
}
.pk-alt b{color:var(--ink)}
.pk-foot{display:flex;align-items:center;gap:10px;margin-top:9px;flex-wrap:wrap}
.pk-stat{font-size:12.5px;color:var(--ink-3)}

/* ---- 员工与权限（2026-09-24）----
   权限是一勾一勾分配出来的，所以勾选框要**大、清楚、一眼看出勾了哪些**。 */
.tm-tag{
  display:inline-block;text-decoration:none;margin-left:6px;
  font-size:11px;color:var(--ink-3);background:var(--line-2);
  border-radius:5px;padding:1px 6px;
}
.tm-top{display:flex;gap:14px;align-items:flex-end;flex-wrap:wrap}
.tm-top>div{flex:1 1 180px}
.tm-perms{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:6px}
.tm-perm-row{
  display:flex;align-items:center;gap:9px;cursor:pointer;
  border:1px solid var(--line);border-radius:var(--r);
  padding:8px 12px;background:var(--card);transition:.12s;
}
.tm-perm-row:hover{border-color:#C9D6EA}
.tm-perm-row.on{border-color:var(--blue);background:var(--blue-50)}
.tm-perm-row input{width:auto;flex:none;margin:0}
.tm-perm-name{font-size:13px;flex:1}
.tm-perm-row.on .tm-perm-name{font-weight:600;color:var(--blue)}
.tm-perm-sug{text-decoration:none;font-size:11.5px;color:var(--ink-3);flex:none}
.tm-perm-row.on .tm-perm-sug{color:var(--blue);opacity:.75}

/* 报价单预览（打印时只留报价单本身） */
/* ===========================================================================
   采购主干（采购申请 / 采购订单 / 收货 / 付款 / 返利与成本 / 审批）
   2026-09-24
   =========================================================================== */

/* ---- 通用：必填标记、表单头尾、信息条 ---- */
.req-mark{color:var(--red);font-style:normal;font-size:11.5px}
.pr-head{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:0 12px}
.pr-foot{display:flex;gap:16px;align-items:flex-end;flex-wrap:wrap;margin-top:14px}
.pr-foot>div{flex:1;min-width:180px}
.pr-info{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px 14px;
  background:var(--line-2);border-radius:var(--r);padding:12px 14px;margin-bottom:10px}
.pr-info>div{display:flex;flex-direction:column}
.pr-info s{font-size:12px;color:var(--ink-3);text-decoration:none}
.pr-info b{font-weight:500}
.pr-total{display:flex;gap:22px;justify-content:flex-end;padding:10px 4px;
  border-top:1px solid var(--line);margin-top:6px;font-size:13px}
.or-flag{display:flex;align-items:center;gap:8px;font-size:13px;color:var(--ink-2);cursor:pointer;
  padding:9px 0;white-space:nowrap}
.or-flag input{width:auto}

/* ---- 机型模糊搜索下拉 ---- */
.pr-search{position:relative}

/* ---- 附件（凭证） ---- */
.at-box{margin-top:14px;border-top:1px dashed var(--line);padding-top:12px}
.at-list{display:flex;flex-direction:column;gap:6px;margin:6px 0}
.at-item{display:flex;align-items:center;gap:10px;font-size:13px;
  background:var(--line-2);border-radius:8px;padding:6px 10px}
.at-item a{color:var(--blue);text-decoration:none}
.at-item s{color:var(--ink-3);text-decoration:none;font-size:12px}
.at-item em{color:var(--ink-2);font-style:normal;font-size:12px}
.at-item .btn{margin-left:auto}
.at-up{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.at-up input[type=file]{width:auto;padding:6px 8px;font-size:12.5px}
.at-note{width:auto}
/* 2026-10-05：付款凭证 —— 缩略图 + 粘贴/拍照按钮 */
.at-thumb{width:46px;height:46px;object-fit:cover;border-radius:6px;
  border:1px solid var(--line);background:#fff;flex:0 0 auto}
.at-quick{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-top:8px}
.at-quick .sub{font-size:12px;color:var(--ink-3)}

/* ---- 上传核对表：「颜色/容量没精确对上」的行（2026-10-05）----
   老板真机截图踩出来的：勃艮第红被配到冰川蓝色、页面却照样打勾。
   现在这种行**不默认勾**，整行标黄，让人一眼扫到。 */
.up-warn{background:var(--amber-50)}
.up-warn td{color:var(--ink)}

/* ---- 上传核对表：货源门店（2026-10-05 方案 A）----
   一张采购订单只挂一家门店，所以门店要显眼、混门店要警告。 */
.up-store{display:flex;gap:14px;align-items:center;flex-wrap:wrap;
  border:1px solid var(--line);border-radius:var(--r);
  padding:10px 14px;margin:10px 0;background:#fbfcfd}
.up-store.warn{border-color:var(--amber);background:var(--amber-50)}
.up-store .f-label{font-size:12px;margin-bottom:3px}
.up-store select{min-width:230px;width:auto}
.up-store .sub{flex:1;min-width:240px;margin:0}

/* ---- 上传供应商明细：★「当场新建商品」（2026-10-05） ----
   老板要「在这个界面直接新增对应的系统名称」——表单就地长在核对表上面，
   所以样式要能一眼看出"这是新开的一块、不是表格里的一行"。 */
.up-new:empty{display:none}
.up-new{border:1px solid var(--blue);border-radius:var(--r);background:var(--blue-50);
  padding:12px 14px;margin:10px 0}
.upn-head{margin-bottom:10px}
.upn-head>b{font-size:14px}
.upn-head .sub{font-size:12px;color:var(--ink-3);margin-top:3px}
.upn-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));
  gap:0 12px;margin-bottom:8px}
.upn-grid .f-label{font-size:12px}
.upn-bar{display:flex;gap:10px;align-items:center;flex-wrap:wrap;margin:4px 0 6px}
.upn-bar .sub{font-size:12px;color:var(--ink-3);flex:1;min-width:220px}
.upn-hits{display:flex;flex-direction:column;gap:6px;margin:6px 0}
.upn-hits .btn{text-align:left;justify-content:flex-start}

/* ---- 采购订单：到货进度条 / 三笔账 ---- */
.po-bar{height:6px;background:var(--line);border-radius:4px;overflow:hidden;min-width:70px}
.po-bar i{display:block;height:100%;background:var(--green);border-radius:4px}
.po-3ledger{display:flex;gap:10px;flex-wrap:wrap;margin:10px 0}
.po-3ledger>div{flex:1;min-width:88px;background:var(--card);border:1px solid var(--line);
  border-radius:var(--r);padding:8px 12px;display:flex;flex-direction:column;gap:2px}
.po-3ledger s{font-size:12px;color:var(--ink-3);text-decoration:none}
.po-3ledger b{font-weight:500;font-size:15px}
.po-st{max-width:150px}

/* ---- ★ 采购订单列表：横向看不全（老板 2026-10-06：「显示不完整，字体小一号」）----
   ⚠️ 为什么这么改（三轮实测换来的，别拍脑袋再改）：
     1080 窗口下量到 容器 806px / 表格 **1358px ⇒ 超 552px**。
     ① 只**调字号**（13.5 → 12px + 收内边距）省了 ~250px，剩下 300px 治不了 ——
        门店名「厦门移动坚坐-厦门翔安祥美自营厅」本来就长，字再小也放不下。
     ② 逐列加 `max-width` **收不动**：表格按内容算 min-content，`max-width` 只是上限
        （实测磨到只剩 4px 也降不下来，而且列宽会互相挤，此消彼长）。
     ③ ⇒ 最后靠 **`table-layout:fixed` + `width:100%`** 一钉死，各列比例分配
        （比例写在 `purchaseorder.js` 的 `<col>` 里）—— **100% 之内必然装得下**。

   ★ 为什么不用全局字号（铁律「宽屏 >820 一个字不能变」）：
     这段只作用于 `#content .po-list`（采购订单列表这一张表），别的表格一个字都不动。

   ⚠️ fixed 布局的代价：内容过长**不再自动撑宽**，一律省略号截断
     ⇒ 所以每个可能截断的格子都挂了 `title`，**鼠标悬停看全名**。
*/
#content .po-list{font-size:12px}
#content table.grid.po-list{font-size:12px;
  table-layout:fixed;width:100%;border-spacing:0}
#content .po-list th,
#content .po-list td{padding:6px 5px;overflow:hidden;text-overflow:ellipsis}
/* 单号下面那行日期、进度百分比那行小字都缩一号，不然大题小字更难看 */
#content .po-list td .sub,
#content .po-list td .mono{font-size:11px;line-height:1.45}
/* 长名字一律「悬停看全」：这三列内容天然放不下（门店名最典型） */
#content .po-list td.po-store,
#content .po-list td.po-supplier,
#content .po-list td.po-company{white-space:nowrap}
/* 数字列不许换行（换了列就乱） */
#content .po-list td.or-c,
#content .po-list td.po-paid,
#content .po-list td.po-amount{white-space:nowrap}
/* 「提交 / 打开」那列右对齐，按钮小一号 */
#content .po-list td.po-act{text-align:right;padding:5px 4px;white-space:nowrap;
  overflow:visible}
#content .po-list .btn.tiny{padding:3px 7px;font-size:11px;margin-left:3px}
/* 到货进度条跟着缩 */
#content .po-list .po-bar{min-width:44px;height:5px}
/* 表头里那两句长的（「下单/已到」+「待收」、「状态」+「收货/审批」）拆两行，省宽度 */
#content .po-list th.po-qty .sub,
#content .po-list th.po-status-h .sub,
#content .po-list th.po-company .sub,
#content .po-list th:not(.or-c) .sub{display:block;font-weight:400;font-size:11px;
  line-height:1.3}
/* 合并后的「收货状态 + 审批」列：两个标签竖排，中间一条虚线分开 */
#content .po-list td.po-status{padding:4px 5px;line-height:1.4;vertical-align:top}
#content .po-list .po-approval{margin-top:3px;padding-top:3px;
  border-top:1px dashed var(--line)}
/* 订单号列：单号 + 下方一行日期，各占一行不叠 */
#content .po-list td.mono{line-height:1.5}
#content .po-list td.mono .mono,
#content .po-list td.mono .sub{display:block;white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis}

/* ---- 审批中心（2026-10-05 三个 tab）----
   ⚠️ 这批类**以前一个都没定义过** —— 老 approval.js 用的就是这些名字，
   页面能开（DOM 全对）但长得像没上妆的表格。一起补上。 */
.ap-tabs{display:flex;gap:6px;margin:0 0 14px;border-bottom:1px solid var(--line);flex-wrap:wrap}
.ap-tab{
  border:1px solid transparent;border-bottom:none;background:none;color:var(--ink-2);
  padding:8px 16px;cursor:pointer;border-radius:var(--r) var(--r) 0 0;font-size:14px;
  position:relative;top:1px;
}
.ap-tab:hover{color:var(--ink);background:var(--line-2)}
.ap-tab.on{background:var(--card);border-color:var(--line);color:var(--ink);font-weight:500}
.ap-tab .dot{
  display:inline-block;min-width:18px;padding:0 5px;margin-left:6px;border-radius:999px;
  background:var(--red);color:#fff;font-size:11.5px;font-weight:600;text-align:center;
}
.ap-hero{
  display:flex;align-items:center;gap:16px;background:var(--card);border:1px solid var(--line);
  border-radius:var(--r-lg);padding:16px 20px;margin-bottom:14px;flex-wrap:wrap;
}
.ap-hero.has{border-color:#F3D9A8;background:linear-gradient(180deg,#FFFDF7,#fff)}
.ap-hero-num{font-size:38px;font-weight:600;line-height:1;color:var(--ink-3)}
.ap-hero.has .ap-hero-num{color:var(--amber)}
.ap-hero-txt{flex:1;min-width:200px;display:flex;flex-direction:column;gap:2px}
.ap-hero-txt b{font-size:16px;font-weight:500}
.ap-hero-txt s{color:var(--ink-3);font-size:13px;text-decoration:none}
/* 看板 KPI：老板扫一眼就知道「卡在哪、还差多少、谁该动」 */
.ap-kpis{display:flex;gap:10px;flex-wrap:wrap;margin:0 0 12px}
.ap-kpi{
  flex:1;min-width:104px;background:var(--card);border:1px solid var(--line);
  border-radius:var(--r);padding:10px 12px;display:flex;flex-direction:column;gap:2px;
}
.ap-kpi-v{font-size:22px;font-weight:600;line-height:1.2}
.ap-kpi-v.red{color:var(--red)}
.ap-kpi-v.amber{color:var(--amber)}
.ap-kpi-t{font-size:12.5px;color:var(--ink-3)}
/* 看板那几行「订单货款 / 已到 / 已付 / 还欠」 */
.ap-ledger{display:flex;gap:10px;flex-wrap:wrap;margin:0 0 14px}
.ap-ledger>div{flex:1;min-width:96px;background:var(--card);border:1px solid var(--line);
  border-radius:var(--r);padding:9px 12px;display:flex;flex-direction:column;gap:2px}
.ap-ledger s{font-size:12px;color:var(--ink-3);text-decoration:none}
.ap-ledger b{font-weight:500;font-size:15px}
/* 「等我审」的行：整行淡黄底，扫一眼就知道该我动 */
tr.ap-mine>td{background:#FFFCF3}
tr.ap-mine>td:first-child{box-shadow:inset 3px 0 0 var(--amber)}
.ap-open{
  border:none;background:none;color:var(--blue);cursor:pointer;font-size:12px;
  padding:0 0 0 6px;text-decoration:underline;
}
/* 流程图：商务提单 → 主管 → 财务 → 生效/打款 */
.ap-flow{background:var(--card);border:1px solid var(--line);border-radius:var(--r);
  padding:12px 14px;margin-bottom:10px}
.ap-flow-head{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;margin-bottom:8px}
.ap-flow-head b{font-size:14.5px;font-weight:500}
.ap-flow-head s{text-decoration:none;flex:1}
.ap-steps{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.ap-step{
  display:inline-flex;flex-direction:column;line-height:1.35;font-size:12.5px;
  border:1px solid var(--line);border-radius:var(--r);padding:5px 11px;background:var(--line-2);
  color:var(--ink-2);
}
.ap-step b{font-weight:500;font-size:13px;color:var(--ink)}
.ap-step.done{background:var(--green-50);border-color:#C6E7D4}
.ap-step.done b{color:var(--green)}
.ap-step.end{background:var(--blue-50);border-color:#C7DEFF}
.ap-step.end b{color:var(--blue)}
.ap-arrow{color:var(--ink-3);font-style:normal;font-size:13px}

/* ---- 采购明细表（采购申请 / 采购订单共用）----
   ★ 2026-09-24 老板要求：机型搜索做在「机型」那一列里、常驻最少 10 行、要有增减行按钮。
   js/purchase-ui.js 的 mountItemTable 生成下面这些类。 */
.it-wrap{overflow-x:auto}          /* 列多的时候横向滚（最后手段，正常情况下放得下） */
.it-table{min-width:0}
.it-table th,.it-table td{padding:6px 8px}
.it-table .or-num{width:74px}      /* 比别处的 88 窄一点 —— 7 列要挤得下 */
/* ★★ 2026-11-04 老板：「增加一行 IMEI2（可选项：我有要求的时候供应商再扫）」
   ⇒ 采购需求单的明细表多一列「IMEI2 要就勾」—— 勾了＝这一行供应商必扫。 */
.imi2-chk{display:inline-flex;align-items:center;gap:5px;cursor:pointer;
  font-size:12.5px;color:var(--ink-2);white-space:nowrap}
.imi2-chk input{width:17px;height:17px;margin:0;cursor:pointer;accent-color:var(--blue)}
.imi2-chk:hover{color:var(--blue)}

.it-sku{position:relative}          /* 下拉候选的定位基准 */
/* ★★ 2026-11-04 13:26 老板报「手机搜索还是没有能跳出可以选择的机型」
   ⇒ 在机型输入框旁边加一个「▼」按钮：**纯 click** 就把候选列表弹出来，
      不依赖打字、不依赖输入法、不依赖键盘时序 —— 老板点它必定看得到。 */
.it-sku-row{display:flex;align-items:center;gap:6px}
.it-sku-row .it-sku-in{flex:1 1 auto;min-width:0}
.it-sku-btn{
  flex:0 0 auto;width:34px;height:34px;padding:0;
  border:1px solid var(--line);border-radius:var(--r);
  background:var(--card);color:var(--ink-2);
  font-size:13px;line-height:1;cursor:pointer;
}
.it-sku-btn:active{background:var(--blue-50);border-color:var(--blue);color:var(--blue)}
/* ★ 候选数量的「信号」行 —— 让老板一眼分清「没搜到」和「搜到但没弹出来」 */
.it-hint{font-size:11.5px;color:var(--blue);margin-top:2px;line-height:1.5}
.it-hint:empty{display:none}
.it-sku-in{
  width:100%;min-width:172px;font-size:13px;padding:6px 9px;
  border:1px solid var(--line);border-radius:var(--r);background:var(--card);
  color:var(--ink);outline:none;
}
.it-sku-in:focus{border-color:var(--blue);box-shadow:0 0 0 3px var(--blue-50)}
.it-sku-in::placeholder{color:var(--ink-3)}

.it-line{font-size:11.5px;line-height:1.5}
.it-line:empty{display:none}
.it-ops{display:inline-flex;gap:4px}
.it-ops .btn{padding:2px 8px;font-size:13px;line-height:1.3}
.it-foot{display:flex;align-items:center;gap:14px;flex-wrap:wrap;padding:9px 2px 0;font-size:13px}
.it-foot b{font-weight:600}

/* ---- 付款：告警带（财务一进来就要看见） ---- */
.pay-alerts{border:1px solid #F3C9C9;border-radius:var(--r-lg);overflow:hidden;
  background:var(--card);margin-bottom:6px}
.pay-alert-head{display:flex;justify-content:space-between;align-items:center;gap:12px;
  padding:10px 14px;background:var(--red-50);color:var(--red);flex-wrap:wrap}
.pay-alert-head .sub{color:var(--red);opacity:.8}
.pay-alert{display:flex;gap:12px;align-items:center;padding:8px 14px;
  border-top:1px solid var(--line-2);font-size:13px;flex-wrap:wrap}
.pay-alert.lv-danger{background:#FFF8F8}
.pay-alert.lv-warn{background:#FFFCF5}
.pay-alert.lv-info{background:#F8FBFF}
.pay-alert-kind{flex:0 0 auto;font-weight:500;padding:2px 8px;border-radius:6px;
  background:var(--line-2);font-size:12px}
.pay-alert.lv-danger .pay-alert-kind{background:#FBDDDD;color:#A32323}
.pay-alert.lv-warn .pay-alert-kind{background:#FBEBCB;color:#8A5A00}
.pay-alert.lv-info .pay-alert-kind{background:#D9E9FF;color:#0B4C9E}
.pay-alert-text{flex:1 1 240px}
.pay-alert-po{color:var(--ink-3);font-size:12px}
.pay-alert em{margin-left:auto;font-style:normal;color:var(--blue);
  border:1px solid #C9DCFA;border-radius:6px;padding:2px 10px;font-size:12.5px;white-space:nowrap}
.pay-links-title{margin:16px 0 6px;font-weight:500;font-size:13px;color:var(--ink-2)}
.pay-links-title:first-child{margin-top:6px}
.pay-link{display:flex;gap:14px;align-items:center;flex-wrap:wrap;font-size:13px;
  border:1px solid var(--line);border-left:3px solid var(--green);
  border-radius:8px;padding:8px 12px;margin-bottom:6px}
.pay-link.bad{border-left-color:var(--red);background:#FFFBFB}
.pay-link em{font-style:normal;color:var(--ink-2);font-size:12.5px}

/* 缺回单提醒 —— 复用付款告警的样子，但换成琥珀色（是"待办"不是"出错"） */
.pv-alert{border-color:#FBE0B0;background:#FFFDF8}
.pv-alert .pay-alert-head .sub{color:var(--amber)}
.pv-alert .pay-alert{background:#FFFDF8}
.pv-alert .pay-alert.lv-warn{background:#FFFCF5}
.pv-alert .pay-alert .btn{margin-left:6px;flex:0 0 auto}

/* 付款通知单预览 */
.nt-wrap{margin:12px 0;border:1px solid var(--line);border-radius:var(--r-lg);
  background:#EEF1F6;padding:12px;max-height:52vh;overflow:auto;text-align:center}
.nt-img{max-width:100%;border-radius:8px;box-shadow:0 2px 12px rgba(20,40,80,.12)}
.nt-actions{display:flex;gap:10px;align-items:center;flex-wrap:wrap;margin-top:4px}
.nt-sep{width:1px;height:20px;background:var(--line);margin:0 2px}
.nt-actions .btn.tiny{text-decoration:none;display:inline-flex;align-items:center;gap:4px}
.pay-tl{display:flex;flex-direction:column;gap:6px}
.pay-tl-item{display:flex;gap:10px;align-items:center;font-size:13px;
  background:var(--line-2);border-radius:8px;padding:6px 12px;flex-wrap:wrap}
.pay-tl-item b{font-weight:500;min-width:52px}
.pay-tl-item s{color:var(--ink-3);text-decoration:none;font-size:12px}
.pay-tl-item em{font-style:normal;color:var(--amber);font-size:12.5px}
.pay-tl-item.act-打回{background:var(--red-50)}
.pay-tl-item.act-通过{background:var(--green-50)}

/* ---- 财务与成本：标签页 / 成本矩阵 ---- */
.fn-tabs{display:flex;gap:6px;border-bottom:1px solid var(--line);margin-bottom:4px}
.fn-tab{background:none;border:0;border-bottom:2px solid transparent;padding:9px 16px;
  cursor:pointer;color:var(--ink-2);font-size:14px;border-radius:8px 8px 0 0}
.fn-tab:hover{background:var(--line-2)}
.fn-tab.on{color:var(--blue);border-bottom-color:var(--blue);font-weight:500}
.cost-matrix td{vertical-align:top}
.cost-cell{text-align:left !important;min-width:180px}
.cost-cell.assess{background:var(--amber-50)}
.cost-cell.actual{background:var(--green-50)}
.cost-cell b{font-size:14px}
.cost-rates{display:flex;gap:16px;align-items:flex-end;flex-wrap:wrap;
  margin:14px 0 4px;padding:12px 14px;background:var(--line-2);border-radius:var(--r)}
.cost-rates>div{min-width:190px}
.cost-rates .sub{flex:1 1 100%;color:var(--ink-3);font-size:12.5px}

/* ---- 审批中心 ---- */
.ap-hero{display:flex;align-items:center;gap:18px;padding:18px 22px;border-radius:var(--r-lg);
  background:var(--card);border:1px solid var(--line);margin-bottom:14px}
.ap-hero.has{background:var(--amber-50);border-color:#F0D9A8}
.ap-hero-num{font-size:34px;font-weight:500;color:var(--ink-3);line-height:1}
.ap-hero.has .ap-hero-num{color:var(--amber)}
.ap-hero-txt{display:flex;flex-direction:column}
.ap-hero-txt b{font-weight:500;font-size:15px}
.ap-hero-txt s{color:var(--ink-2);text-decoration:none;font-size:12.5px}
.ap-flow{background:var(--card);border:1px solid var(--line);border-radius:var(--r);
  padding:12px 16px;margin-bottom:10px}
.ap-flow-head{display:flex;justify-content:space-between;gap:12px;flex-wrap:wrap;margin-bottom:10px}
.ap-steps{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.ap-step{display:flex;flex-direction:column;background:var(--blue-50);border-radius:8px;
  padding:6px 14px;font-size:13px;min-width:88px;text-align:center}
.ap-step b{font-weight:500;font-size:12px;color:var(--blue)}
.ap-step.done{background:var(--green-50)}
.ap-step.done b{color:var(--green)}
.ap-step.end{background:var(--line-2)}
.ap-step.end b{color:var(--ink-2)}
.ap-arrow{color:var(--ink-3);font-style:normal}

/* ---- 按订单收货 ---- */
.rc-head{display:flex;align-items:center;gap:12px;flex-wrap:wrap;background:var(--card);
  border:1px solid var(--line);border-radius:var(--r);padding:10px 14px;margin-bottom:12px}
.rc-cards{display:grid;grid-template-columns:repeat(auto-fill,minmax(270px,1fr));gap:12px}
.rc-card{background:var(--card);border:1px solid var(--line);border-radius:var(--r);
  padding:14px;display:flex;flex-direction:column;gap:6px}
.rc-card-top{display:flex;justify-content:space-between;align-items:center;gap:8px}
.rc-card-mid{font-size:13px;color:var(--ink-2)}

/* ★★ 选单卡片的「门店」行（老板 2026-10-06：「看不到门店信息，会照成入错串码」）
   为什么放这么显眼：待收列表里**同一个供应商常常有十几张单**（真实库：
   「厦门移动堡垒」10 张待收，全是同城苹果 18Pro Max，差别只在门店名）——
   只写供应商，仓管根本分不清是哪一家，货就记到别的门店名下了。
   门店名本身很长（「厦门移动堡垒-厦门翔安祥美自营厅」）⇒ 放大 + 不截断 + 换行。 */
/* ═══ ★★ 返利政策「多行登记」（老板 2026-10-06）═══
   一台一行：机型（搜索选择）+ 品牌（自动带出）+ 那台自己的返利单价。 */
.rf-line{display:flex;align-items:center;gap:8px;margin-bottom:6px;flex-wrap:wrap}
.rf-line-sku{flex:1;min-width:230px;position:relative}
.rf-line-sku .search{width:100%}
.rf-line-brand{width:96px;font-size:12.5px;flex:none;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rf-line .rf-price-in{flex:none;width:110px}
/* 选中之后把机型名标成「已选定」，避免看着像还没选（其实是搜出来的但没点） */
.rf-line[data-picked="1"] .rf-sku-in{border-color:var(--brand,#2b6cb0);
  background:var(--blue-50,#eaf2fc)}

/* ═══ ★★ 返利预估台账（老板 2026-10-06：「每次入库做个预估登记，做好台账」）═══
   汇总条是这一页的重点 —— 老板要**在看板上就看到预估值**，不用点进去算。 */
.rb-sum{background:var(--card);border:1px solid var(--line);border-radius:var(--r);
  padding:12px 14px;margin:8px 0}
/* 差异 ≥10% 标黄提醒 —— 只是提醒，**不追责、不拦任何人**（老板原话） */
.rb-sum.warn{border-color:#f0d9a8;background:#fffdf8}
.rb-sum-k{font-size:14.5px;font-weight:500;line-height:1.5}
.rb-sum-h{margin-top:3px;font-size:12.5px;color:var(--ink-3);line-height:1.5}
.rb-kpis{display:flex;gap:10px;flex-wrap:wrap;margin-top:10px}
.rb-kpi{background:var(--card-2,#f7f9fc);border:1px solid var(--line);
  border-radius:8px;padding:7px 12px;min-width:118px;display:flex;
  flex-direction:column;gap:1px}
.rb-kpi span{font-size:12px;color:var(--ink-3)}
.rb-kpi b{font-size:19px;font-weight:600;line-height:1.2}
.rb-kpi i{font-style:normal;font-size:11.5px;color:var(--ink-3)}
.rb-kpi.bad{background:var(--red-50);border-color:#F3C9C9}
.rb-kpi.bad b,.rb-kpi.bad i{color:var(--red)}
.rb-kpi.amber{background:var(--amber-50);border-color:#f0d9a8}
.rb-kpi.amber b{color:var(--amber)}

/* 按供应商拆开 —— 哪个供应商差得多一眼看出来 */
.rb-sups{display:flex;gap:8px;flex-wrap:wrap;margin:8px 0 4px}
.rb-sup{background:var(--card);border:1px solid var(--line);border-radius:8px;
  padding:6px 11px;display:flex;flex-direction:column;gap:1px;font-size:13px}
.rb-sup b{font-weight:500}
/* 「还欠着没勾兑」比「已勾兑」更显眼 —— 那是下一步该做的事 */
.rb-sup-un{font-size:12px;color:var(--amber)}
.rb-sup-ok{font-size:12px;color:var(--ok)}

.rc-card-store{font-size:13.5px;font-weight:500;color:var(--ink);line-height:1.45;
  padding:5px 8px;border-radius:6px;background:var(--blue-50);
  border-left:3px solid var(--blue);word-break:break-all}
/* 没指定门店 = 有隐患，红色警示（扫完货会记成「位置未知」） */
.rc-card-store.none{background:var(--red-50);border-left-color:var(--red);
  font-weight:400;font-size:12.5px}
/* 搜索框旁边那句提醒 */
.rc-store-tip{color:var(--amber)}
.rc-card-num{display:flex;gap:16px;font-size:13px;margin:2px 0}
.rc-card-num b{font-weight:500}
.rc-card-lines{max-height:96px;overflow:auto;font-size:12px;color:var(--ink-3)}
.rc-card .btn{margin-top:auto}
.rc-line{background:var(--card);border:1px solid var(--line);border-radius:var(--r);
  padding:12px 14px;margin-bottom:10px}
.rc-line-head{display:flex;justify-content:space-between;gap:12px;flex-wrap:wrap;margin-bottom:8px}
.rc-line-head b{font-weight:500}
.rc-line-head em{font-style:normal}
.rc-sn{min-height:52px;font-family:ui-monospace,Menlo,Consolas,monospace;font-size:13px}

/* ═══ ★★ 流式扫码台（老板 2026-10-06：「不需要一个一个商品点开」）═══
   参考博远的版面：一整页**一个**串码框，点商品行切当前录入、扫完点「下一个商品」。
   跟原来「一行一个 textarea」最大的不同：串码框**固定在中间不动** ——
   眼睛不用来回找，行会自己滚到当前那行。
   ⚠️ 宽屏下（>820）两栏：左边扫码台 sticky、右边商品清单 —— 清单长也不怕。 */
/* ★★★ 扫码台顶部那条「门店」（老板 2026-10-06 报的入错串码问题）
   这是真正**扫串码时盯着的那块屏幕** ⇒ 门店必须顶在最上面、字号最大。
   ⚠️ 不许截断：门店名是唯一区分「这批货记在哪个门店名下」的依据，
      截掉一半就等于没显示（「翔安祥美」和「同安城南」后面都一样是「自营厅」）。 */
.sf-store{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;
  margin:10px 0 0;padding:10px 14px;border-radius:var(--r);
  background:var(--blue-50);border:1px solid #BFD8FF;border-left:4px solid var(--blue)}
.sf-store-lb{flex:none;font-size:12px;color:var(--blue);
  border:1px solid currentColor;border-radius:4px;padding:1px 7px}
.sf-store-name{font-size:19px;font-weight:600;line-height:1.4;color:var(--ink);
  word-break:break-all;flex:1;min-width:220px}
.sf-store-r{flex:none;font-size:12.5px;color:var(--ink-2);margin-left:auto}
/* 没指定门店：整条变红，并说清后果 */
.sf-store.none{background:var(--red-50);border-color:#F3C9C9;border-left-color:var(--red)}
.sf-store.none .sf-store-lb{color:var(--red)}
.sf-store.none .sf-store-name{color:var(--red);font-size:14.5px;font-weight:500}

.sf-scan{background:var(--card);border:1px solid var(--line);border-radius:var(--r);
  padding:12px 14px;margin:10px 0}
.sf-scan-head{display:flex;align-items:center;gap:10px;margin-bottom:8px;flex-wrap:wrap}
.sf-scan-head .sf-cur-name{font-weight:500;font-size:15px}
/* 那个大框：扫码枪焦点在这儿，行高留够，别让光标跳 */
.sf-box{width:100%;min-height:88px;font-family:ui-monospace,Menlo,Consolas,monospace;
  font-size:14px;line-height:1.6;padding:10px 12px}
.sf-box:focus{outline:2px solid var(--brand,#2b6cb0);outline-offset:-1px}
.sf-hint{margin-top:6px}
.sf-checks:empty{display:none}
.sf-rest{margin-top:6px;font-size:12.5px}
.sf-rest summary{cursor:pointer;color:var(--ink-3)}

/* 商品清单：每行可点，当前那行高亮 */
.sf-list{display:flex;flex-direction:column;gap:6px}
.sf-row{display:flex;align-items:center;gap:12px;flex-wrap:wrap;
  background:var(--card);border:1px solid var(--line);border-radius:var(--r);
  padding:9px 12px;cursor:pointer}
.sf-row:hover{border-color:var(--brand,#2b6cb0)}
/* ★ 当前正在录入的那行：左边一条粗色带 + 底色，一眼就知道「现在扫的是谁」 */
.sf-row.on{border-color:var(--brand,#2b6cb0);box-shadow:inset 3px 0 0 var(--brand,#2b6cb0);
  background:var(--card-2,#f7f9fc)}
/* 收满的行淡一点（没到货的等到货再来，不用现在点它） */
.sf-row.done{opacity:.62}
.sf-row-main{flex:1;min-width:220px;display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.sf-row-main b{font-weight:500}
.sf-row-num{font-size:13px;color:var(--ink-2);white-space:nowrap}
.sf-row-num em{font-style:normal}
.sf-badge{font-size:12px;padding:2px 8px;border-radius:10px;
  background:var(--line);color:var(--ink-3)}
.sf-badge.ok{background:#e6f4ea;color:#1a7f37}

/* 本批已扫台数（老板扫完要知道扫到哪儿了、扫的是哪一行） */
.sf-badge.scan{background:#e7f0ff;color:#1c5fb8;margin-left:6px}
/* 每行扫到的串码清单：默认收起，点开能逐条核对/删 */
/* 受托入库整页（2026-10-10）：照采购收货那套 sf-* 版式，
   采购那边只有 .sf-row-num，.sf-row-pn 在 app.css 里没有 —— 补上（两边长得一样）。 */
.sf-row-pn{display:flex;gap:6px;align-items:center;flex-wrap:wrap;margin-top:4px}

.sf-scanned{width:100%;font-size:12px;color:var(--ink-3);padding-top:2px}
.sf-scanned summary{cursor:pointer}
.sf-sn-list{display:flex;flex-wrap:wrap;gap:6px;margin-top:6px}
.sf-sn-chip{display:inline-flex;align-items:center;gap:5px;
  font-family:ui-monospace,Menlo,Consolas,monospace;font-size:12px;
  padding:2px 6px;border-radius:6px;background:var(--card);border:1px solid var(--line)}
.sf-sn-chip u{text-decoration:none;color:var(--ink-3)}
.sf-sn-del{cursor:pointer;border:0;background:transparent;color:var(--ink-3);
  font-size:14px;line-height:1;padding:0 2px}
.sf-sn-del:hover{color:var(--red,#c0392b)}

@media (max-width:820px){
  /* 手机上门店名太大会把扫码框顶出屏幕 ⇒ 缩一档，但**仍然比别处大** */
  .sf-store-name{font-size:16px;min-width:0}
  .sf-store-r{width:100%;margin-left:0}
  .rc-cards{grid-template-columns:1fr}
}

@media (min-width:821px){
  /* 宽屏：扫码台左边固定、商品清单右边跟着滚（清单再长也不影响扫码） */
  .sf-wrap{display:flex;gap:14px;align-items:flex-start}
  .sf-wrap .sf-scan{flex:0 0 min(58%,560px);position:sticky;top:8px}
  .sf-wrap .sf-list{flex:1;min-width:0}
}
.rc-checks{margin-top:6px}
.rc-checks .note{margin:6px 0;padding:7px 10px;font-size:12.5px}
.rc-chips{display:flex;flex-wrap:wrap;gap:6px;margin-top:4px}
.rc-chip{display:inline-flex;align-items:center;gap:6px;font-family:ui-monospace,Menlo,monospace;
  font-size:12px;padding:3px 9px;border-radius:6px;background:var(--green-50);color:var(--green)}
.rc-chip s{text-decoration:none;font-family:inherit;font-size:11.5px;opacity:.85}
.rc-chip.lv-dup{background:var(--line-2);color:var(--ink-2)}
.rc-chip u.rc-imei{text-decoration:none;font-size:11.5px;color:var(--ink-3);border-left:1px solid var(--line);padding-left:6px}
.rc-chip s{font-family:inherit}
.rc-chip.lv-warn{background:var(--amber-50);color:var(--amber)}
.rc-chip.lv-bad{background:var(--red-50);color:var(--red)}
/* 双串码：一个 chip 里并排显示 串号1 + IMEI（IMEI 用浅一点的底色分开放）*/
.rc-chip u{text-decoration:none;font-style:normal;background:rgba(255,255,255,.7);
  border-radius:4px;padding:0 5px;margin-left:2px}

/* 串码格式标签（可点 → 改这个机型的串码格式）*/
.rc-fmt{display:inline-flex;align-items:center;gap:6px;cursor:pointer;
  padding:2px 6px;border-radius:6px;border:1px dashed var(--line)}
.rc-fmt:hover{border-color:#C9D6EA;background:#FCFDFF}
.rc-fmt-tag{font-style:normal;font-size:12px;padding:1px 8px;border-radius:5px;
  background:var(--line-2);color:var(--ink-2)}
.rc-fmt-tag.dual{background:var(--blue-50);color:var(--blue)}
.rc-fmt .sub{font-size:11.5px}

/* ---------------- 供应商银行账户（专用窗口 + 总览） ----------------
   老板 2026-09-25：一家供应商可以有好几个银行账号 —— 照博远「账户信息」那张网格：
   总览里一个供应商占一行、行内竖着列出它的所有账号；
   专用窗口里一行一个账号，直接在格子里改。 */
.bk-line{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:12.5px;line-height:1.85}
.bk-line + .bk-line{border-top:1px dashed var(--line-2)}
.bk-line.off{opacity:.45}
.bk-line .bk-no{color:var(--ink-2)}
.bk-line .bk-owner{color:var(--ink-3);font-size:12px}
.bk-table td{padding:6px 9px}
.bk-table input,.bk-table select{padding:6px 9px;font-size:13px}
.bk-table input[type=checkbox]{width:auto;box-shadow:none}
.bk-table input[data-k="bank_name"]{min-width:190px}

/* 品牌 → 系列窗口（跟银行账户那个窗口是同一套写法，见 js/series.js） */
.sr-table td{padding:6px 9px}
.sr-table input,.sr-table select{padding:6px 9px;font-size:13px}
.sr-table input[type=checkbox]{width:auto;box-shadow:none}
.sr-table input[data-k="name"]{min-width:190px}

/* ---------------- 省 / 市 / 区县：打字筛 + 下拉选（js/region.js） ----------------
   老板 2026-09-25：「要做成模糊搜索，选择的（省份，城市，区/县）」
   面板挂在 body 上、用 fixed 定位（`.modal-body` 是 overflow:auto，挂在里面会被裁掉）。 */
.rg-wrap{position:relative}
.rg-wrap .rg-caret{position:absolute;right:10px;top:50%;transform:translateY(-50%);
  color:var(--ink-3);font-size:11px;pointer-events:none}
.rg-wrap input{padding-right:28px}
.rg-pop{position:fixed;z-index:60;background:var(--card);border:1px solid var(--line);
  border-radius:var(--r);box-shadow:0 10px 30px rgba(20,24,32,.14);
  /* ★★ 2026-11-04 老板（手机）：「这个不能滑动，轻碰一下就确认了」
     ⇒ ① 高度放宽（JS 里按可视区算，这里只是兜底，别写死太小）
     ⇒ ② 加上 iOS 惯性滚动那行属性（微信里更跟手）
     ⇒ ③ `overscroll-behavior:contain` = 滚到头不会把整页也带着滚 */
  max-height:300px;overflow-y:auto;padding:4px;
  -webkit-overflow-scrolling:touch;overscroll-behavior:contain;touch-action:pan-y}
.rg-item{display:flex;align-items:baseline;gap:8px;padding:7px 10px;border-radius:8px;
  cursor:pointer;font-size:13.5px}
.rg-item:hover,.rg-item.on{background:var(--blue-50)}
.rg-item b{font-weight:600}
.rg-sub{color:var(--ink-3);font-size:12px}
.rg-empty{padding:10px 12px;color:var(--ink-3);font-size:12.5px}

/* ---------------- 长下拉「打字筛 + 选中」（js/searchselect.js） ----------------
   老板 2026-10-02：「系统这样的选择都做成可以打字模糊快速匹配的选择方式」。
   选项多的下拉（供应商 / 客户 / 商品 / 门店 / 价格档）点一下不弹原生列表，
   改成弹这一个：顶上永远是搜索框，下面列表，↑↓ 选、回车定、Esc 收。
   复用上面 .rg-pop / .rg-item 的长相，只加一个搜索头，老板看不出是两套东西。 */
.ss-pop{max-height:324px;overflow:hidden;padding:0;display:flex;flex-direction:column}
.ss-head{flex:none;padding:6px;border-bottom:1px solid var(--line);background:var(--card)}
.ss-q{width:100%;height:34px;padding:0 10px;border:1px solid var(--line);border-radius:8px;
  font-size:13.5px;font-family:inherit;background:#fff;color:var(--ink);outline:none}
.ss-q:focus{border-color:var(--blue);box-shadow:0 0 0 2px var(--blue-50)}
.ss-list{overflow-y:auto;padding:4px;min-height:44px}
.ss-pop .rg-item{align-items:center}
.ss-pop .rg-item b{flex:none;width:15px;color:var(--blue)}
.ss-pop .rg-item .ss-t{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ss-pop .rg-item .rg-sub{flex:none}
.ss-more{padding:6px 10px;margin-top:2px;border-top:1px dashed var(--line);
  color:var(--ink-3);font-size:12px}

/* ---------------- 上传表格文件（批量导入的第一条路 · js/filepick.js） ----------------
   老板 2026-09-25：「既然做好了导入模板，能不能上传文件批量导入」
   这个控件只做一件事：把文件读成文本，填进下面原来那个粘贴框
   （上传和粘贴走**同一套解析**，不会两边行为不一样）。 */
.fdrop{display:flex;align-items:center;gap:14px;padding:18px 20px;cursor:pointer;
  border:1.5px dashed #C6D3E6;border-radius:var(--r-lg);background:#FBFCFE;transition:.15s}
.fdrop:hover,.fdrop:focus{border-color:var(--blue);background:var(--blue-50);outline:none}
.fdrop.over{border-color:var(--blue);background:var(--blue-50);border-style:solid}
.fdrop .fd-ico{color:var(--blue);line-height:0;flex:none}
.fdrop .fd-txt{display:block;font-size:14px}
.fdrop .fd-txt b{font-weight:600}
.fdrop .fd-a{color:var(--blue);text-decoration:underline}
.fdrop .fd-txt em{display:block;margin-top:3px;font-style:normal;
  font-size:12.5px;color:var(--ink-3);line-height:1.6}
.fd-picked{display:flex;align-items:center;gap:12px;margin-top:10px;padding:9px 14px;
  background:var(--card);border:1px solid var(--line);border-radius:var(--r);font-size:13.5px}
.fd-picked .fd-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.fd-state{margin-top:10px;padding:10px 14px;border-radius:var(--r);font-size:13.5px;line-height:1.7}
.fd-state.ok{background:var(--green-50);border-left:3px solid var(--green)}
.fd-state.bad{background:var(--red-50);border-left:3px solid var(--red)}
/* 「这份文件里有好几张表，你要导哪张」—— 老板 2026-09-30：期初那个工作簿里
   同时有「期初库存」和「库存明细」，自动挑表挑了库存明细，他没法换。 */
.fd-sheets{margin-top:10px;padding:10px 14px;border-radius:var(--r);font-size:13.5px;
  line-height:1.9;background:var(--blue-50);border-left:3px solid var(--blue)}
.fd-sheets b{color:var(--ink)}
.fd-sheets select{margin-left:8px;padding:4px 8px;border:1px solid var(--line);
  border-radius:8px;background:#fff;color:var(--ink);font-size:13px;font-family:inherit}
.spin{display:inline-block;width:12px;height:12px;margin-right:6px;vertical-align:-1px;
  border:2px solid var(--blue);border-top-color:transparent;border-radius:50%;
  animation:spin .7s linear infinite}
@keyframes spin{to{transform:rotate(360deg)}}
.paste-box{margin-top:16px}
.paste-box > summary{cursor:pointer;font-size:13px;color:var(--ink-2);
  padding:7px 2px;list-style:none;user-select:none}
.paste-box > summary::-webkit-details-marker{display:none}
.paste-box > summary::before{content:"▸ ";color:var(--ink-3)}
.paste-box[open] > summary::before{content:"▾ "}
.paste-box > summary:hover{color:var(--blue)}

/* ===========================================================================
   商品名称映射（suppliermap.js）—— 老板 2026-10-05
   「配一次就不用猜」：左供应商 / 右对应关系。
   ★ 宽屏样式放这里（media 块之外）；窄屏的收在文件末尾那个
     @media (max-width:820px) 块里 —— 阈值要对齐 mobile.js: NARROW_MAX=820。
   =========================================================================== */
.sm-wrap{display:grid;grid-template-columns:250px 1fr;gap:14px;align-items:start}
.sm-side{background:#fff;border:1px solid var(--line);border-radius:10px;overflow:hidden}
.sm-side .search{width:100%;margin:8px;border:1px solid var(--line);border-radius:7px;
  padding:7px 10px;font-size:13px}
.sm-list{max-height:calc(100vh - 260px);overflow:auto;padding:0 6px 8px}
.sm-sup{display:flex;align-items:center;justify-content:space-between;gap:6px;
  padding:7px 9px;border-radius:7px;cursor:pointer;font-size:13px}
.sm-sup:hover{background:#eef2f8}
.sm-sup.on{background:var(--navy,#1F3864);color:#fff;font-weight:600}
.sm-sup .nm{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sm-sup .ct{font-size:11px;min-width:20px;text-align:center;border-radius:10px;
  padding:1px 6px;background:#eef2f8;color:var(--ink3)}
.sm-sup .ct.has{background:#e6f7ed;color:#237804;font-weight:600}
.sm-sup.on .ct{background:rgba(255,255,255,.25);color:#fff}
.sm-main{min-width:0}
.sm-sug{max-height:230px;overflow:auto;border:1px solid var(--line);border-radius:8px;
  margin-top:5px;background:#fff}
.sm-sug-item{padding:7px 10px;cursor:pointer;font-size:13px;border-bottom:1px solid #f2f5f9}
.sm-sug-item:hover{background:#eef2f8}
.sm-sug-item .sub{display:block;font-size:11.5px}

@media print{
  body *{visibility:hidden}
  #imodal,#imodal *{visibility:visible}
  #imodal{position:absolute;left:0;top:0;width:100%}
}

/* ==========================================================================
   主数据列表 = 录入界面（表格里直接改）· 2026-09-25 老板
   --------------------------------------------------------------------------
   老板先说要「在当页面最下方用增加行的形式新增」，接着贴了博远「商品型号」那张
   网格截图：「参考一下博远的新增逻辑，因为这里做就可以在修改或者新增的时候在
   同一个页面上，做到更直观，出错率会降低」。

   → 表格的列铺开成**这个实体的全部字段**，一格一个控件：
     · 点行尾「改」→ 那一行原地变输入框（`.editing`），上下几行都能对照
     · 「＋ 新增一行」→ 末尾追加一个空行
     · 行尾「保存 / 取消」，改哪行存哪行；`.dirty` 淡黄底 = 有没保存的改动
     · 焦点在哪一格，下面 `#md-hint` 就说明这一格怎么填
   ⚠️ 列会很多（商品 20 列）→ 横向滚动，跟他天天用的博远一样。
   ========================================================================== */
.grid-bar{
  display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);
  padding:10px 14px;margin-bottom:10px;
}
.grid-bar .sub{font-size:12.5px;color:var(--ink-2)}
.grid-bar .sub b{color:var(--amber)}
.grid-bar #md-discard{margin-left:auto}

.grid-edit{table-layout:fixed;font-size:12.5px}
.grid-edit th{
  padding:6px 9px;font-size:12px;line-height:1.25;white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis;
}
.grid-edit th.req-col::after{content:" *";color:var(--red)}
/* ★★ 2026-09-26 老板：「右边的改/记录/删，已经和表头的功能是重复的…去掉了右边的，
   整行的显示就会变得更丰富了」→ **操作列整个撤掉**（连带那条 sticky;right:0 的钉右规则），
   动作全搬到上面那排工具条、改到一半的保存/取消搬到下面那条说明行（`.edit-bar`）。
   → 少了这一列，20 列的商品表等于多出 ~186px 给数据；
   字体也按他的要求「同比例小一点点」（13→12.5 / 表头 12.5→12）→ 一屏多两行。 */
/* 行高按老板「再小一点点、能多看几行」调：一格 27px（原来 33），706px 的表格区
   能多出 4~5 行。⚠️ 行高卡在 `line-height` 上（全局 `td{padding:12px 16px}` 是 12px 大留白，
   这里必须显式写死）。 */
.grid-edit td{padding:3px 5px;line-height:1.3;white-space:nowrap;vertical-align:middle}
.grid-edit td.sel-col{padding:2px 6px}
.grid-edit td.mono{font-family:ui-monospace,Menlo,Consolas,monospace;font-size:12px}
.grid-edit td.ro-col{color:var(--ink-2)}
/* ★★ 只读派生列（「系列」「银行卡」）不只是个数字 —— 它就是**下一级菜单的入口**。
   老板 2026-09-26：「系列名称怎么看不到了，没有下一级菜单出来」——
   原来这里是个灰徽标（cursor:auto、没绑事件），点上去毫无反应。
   现在：手型 + 蓝底 + 结尾一个 ▸，跟链接一样一眼看得出能点。
   ⚠️ 文字单独包一层 `.ro-txt` 做省略号 —— 名字太长时只截文字，▸ 永远看得见。 */
.grid-edit td.ro-col .ro-open{
  display:inline-flex;align-items:center;gap:2px;max-width:100%;
  padding:2px 8px;border-radius:999px;background:var(--blue-50);color:var(--blue);
  font-size:12px;cursor:pointer;border:1px solid transparent;
}
.grid-edit td.ro-col .ro-open:hover{background:#DCEAFF;border-color:#B9D6FF}
.grid-edit td.ro-col .ro-open .ro-txt{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.grid-edit td.ro-col .ro-open .ro-caret{font-style:normal;font-size:10px;opacity:.7;flex:none}
/* 还没建 / 全停用 → 琥珀色（要他去补的） */
.grid-edit td.ro-col .ro-open.ro-todo{background:var(--amber-50);color:var(--amber)}
.grid-edit td.ro-col .ro-open.ro-todo:hover{background:#FFEFD6;border-color:#F5DFB0}
/* ★ 信用状态（2026-09-27）：超期（红）/ 超额度（橙）/ 手动停开单（紫）
   —— 老板要"一眼看出谁是超期、谁是超额度"，所以三种颜色分得开 */
.grid-edit td.ro-col .ro-open.ro-bad{background:#FDECEC;color:#D93838}
.grid-edit td.ro-col .ro-open.ro-bad:hover{background:#FBDCDC;border-color:#F3B9B9}
.grid-edit td.ro-col .ro-open.ro-warn{background:#FFF4E0;color:#C77700}
.grid-edit td.ro-col .ro-open.ro-warn:hover{background:#FFEBC7;border-color:#F0D6A6}
.grid-edit td.ro-col .ro-open.ro-stop{background:#F3E8FF;color:#7A3BB5}
.grid-edit td.ro-col .ro-open.ro-stop:hover{background:#EAD9FF;border-color:#D5BCF5}
/* 正在改的行：淡黄底 + 左侧一条蓝线，扫一眼就知道"这几行还没存" */
.grid-edit tr.editing{background:#FFFDF5}
.grid-edit tr.editing td:first-child{box-shadow:inset 3px 0 0 var(--blue)}
.grid-edit tr.dirty{background:#FFF7E4}
.grid-edit tr.dirty td:first-child{box-shadow:inset 3px 0 0 var(--amber)}
/* 格子里的小控件：比表单里紧凑一档，看不出边框、聚焦才亮 */
.grid-edit td.cell input,.grid-edit td.cell select,.grid-edit td.cell textarea{
  width:100%;padding:4px 7px;font-size:12px;border-radius:6px;
}
.grid-edit td.cell textarea{min-height:30px;height:30px;resize:vertical}
.grid-edit td.cell .rg-caret{right:7px}
/* 必填没填 → 那一格红框（保存时会被点出来） */
.grid-edit td.need input,.grid-edit td.need select,.grid-edit td.need textarea{
  border-color:var(--red);background:var(--red-50);
}

/* 说明书 / 报错行 —— 原来表单里那些提示，现在跟着焦点走。
   ★ 必须**吸在屏幕底部**：商品表有 46 行、十几列，放在表格后面他根本看不见
   （第一版就是这么写的，真机上焦点提示和红字全在屏幕外）。 */
.grid-hint{
  position:sticky;bottom:0;z-index:15;margin-top:10px;
  padding:7px 12px;border-radius:var(--r);
  background:#F7F9FC;border:1px solid var(--line);
  box-shadow:0 -6px 16px rgba(20,24,32,.08);
  font-size:12.5px;color:var(--ink-2);line-height:1.6;
}
/* ★ 「正在改：xx ｜ 保存 ｜ 取消」—— 行尾操作列撤掉后，改到一半的存/弃挪到这里。
   ⚠️ 它是 `.md-foot` 里的**独立一格**（`#md-editbar`），**不能塞进 `.grid-hint` 里**：
      说明行有 `max-height`，塞进去会被裁掉（真机截图才发现——量 DOM 元素是在的，
      只是在可视区外面看不见）。空着时 `:empty` 让它整个收起，不占宽度。 */
.md-foot .edit-slot{
  flex:none;display:inline-flex;align-items:center;gap:8px;
  padding:6px 12px;font-size:12.5px;
  background:var(--card);border:1px solid var(--line);border-radius:var(--r);
  box-shadow:0 -6px 16px rgba(20,24,32,.06);
}
.md-foot .edit-slot:empty{display:none}
.md-foot .edit-slot b{font-weight:600;color:var(--ink);
  max-width:220px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.md-foot .edit-slot .btn.tiny{padding:3px 10px;font-size:12px}
.grid-hint b{color:var(--ink)}
.grid-hint .ok-t{color:var(--green)}
.grid-hint.ok{background:var(--green-50);border-color:#CDEBD8;color:var(--green)}
.grid-hint.ok b{color:var(--green)}
.grid-hint.bad{background:var(--red-50);border-color:#F3C9C9;color:var(--red)}
.grid-hint.bad b{color:var(--red)}

@media (max-width:820px){
  .grid-bar{align-items:flex-start}
  .grid-bar #md-discard{margin-left:0}
}

/* ==========================================================================
   列宽可拖 + 字段配置（2026-09-26 老板）
   --------------------------------------------------------------------------
   老板原话：「这里所属渠道显示供应商全称比较好 还有 2 列字体重叠在一起…这个问题整个系统
   都会出现，不美观。你看看是不是可以做成我能每一列都能自由调整宽度，再增加字段配置，
   可以自行设置需要显示的字段模式」
   ========================================================================== */

/* ★★ 字体重叠的根治：`table-layout:fixed` 下 `white-space:nowrap` 的内容会**画到隔壁列上**。
   必须 overflow:hidden + 省略号，看不全的用鼠标停上去的 title 补。 */
.grid-edit td{overflow:hidden;text-overflow:ellipsis}

/* 列名的右边界上放一根可拖的线。
   ★ 平时就有一条**淡线**，不是拖到才出现 —— 不然他根本不知道这里能拖
     （视觉跟「价格册」那套拖宽 `.px-grip` 保持一致，同一个手势、同一个观感）。 */
.grid-edit th{position:relative}
.grid-edit .col-resizer{
  position:absolute;top:0;right:-4px;bottom:0;width:9px;z-index:4;
  cursor:col-resize;user-select:none;
}
.grid-edit .col-resizer::after{
  content:"";position:absolute;top:24%;bottom:24%;right:4px;width:1px;background:var(--line);
}
.grid-edit .col-resizer:hover{background:var(--blue-50)}
.grid-edit .col-resizer:hover::after,
body.col-dragging .grid-edit .col-resizer::after{background:var(--blue);width:2px;right:3.5px}
/* 拖的时候别选中文字、别显示文本光标 */
body.col-dragging{cursor:col-resize;user-select:none}

/* 「字段配置」弹窗 */
.req-mark{color:var(--red)}
.cfg-bar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:10px 0}
.cfg-bar .sub{font-size:12.5px;color:var(--ink-3)}
.cfg-table td{padding:5px 10px;white-space:nowrap}
.cfg-table th{padding:8px 10px}
.cfg-table input[type=checkbox]{width:auto}

/* ==========================================================================
   冻住左边几列（2026-09-26 老板）
   --------------------------------------------------------------------------
   老板原话：「你可以再优化，重点列是不是用冻结的方式，我左右拉动的时候可以一直显示着」
   → 左边连续 N 列 `position:sticky`，每格一个 `left` 偏移（JS 量出来，见 masterdata.applyFreeze）。
     操作按钮那一列本来就已经钉在右边了，这样**左右两头都固定**，中间随便滚。
   ⚠️ 钉住的格子必须**自带底色**（默认 / 编辑中 / 改了没存 / 悬停 四种），否则滚过去的内容会透出来。
   ⚠️ 最后一列冻结列加一道右边阴影，让他一眼看出"冻到这儿为止"。
   ========================================================================== */
.grid-edit .frozen{position:sticky;background:var(--card)}
.grid-edit thead th.frozen{position:sticky;background:#FAFBFC;z-index:3}
.grid-edit tbody td.frozen{z-index:2}
.grid-edit .frozen-last{box-shadow:7px 0 9px -7px rgba(20,24,32,.18)}
.grid-edit tr.editing td.frozen{background:#FFFDF5}
.grid-edit tr.dirty td.frozen{background:#FFF7E4}
.grid-edit tbody tr:hover td.frozen{background:#FCFDFF}
/* 左侧那条"这一行在改"的彩线，和冻结边界阴影都写在 box-shadow 上（后者会盖掉前者）→
   两样碰在同一格时合起来写一条，别丢东西。 */
.grid-edit tr.editing td.frozen-last:first-child{
  box-shadow:inset 3px 0 0 var(--blue),7px 0 9px -7px rgba(20,24,32,.18);
}
.grid-edit tr.dirty td.frozen-last:first-child{
  box-shadow:inset 3px 0 0 var(--amber),7px 0 9px -7px rgba(20,24,32,.18);
}

/* 「字段配置」里被冻住的那几行给点底色，一眼看出冻了哪几列 */
.cfg-table tr.cfg-fz td{background:var(--blue-50)}
.cfg-table tr.cfg-fz td:first-child{border-left:3px solid var(--blue)}

/* ==========================================================================
   批量修改 / 批量删除 / 排序（2026-09-26 老板）
   --------------------------------------------------------------------------
   老板原话：「批量修改和排序功能的增加」
   · 最左边一列勾选框（永远钉在最左边）→ 工具条上出现「批量修改 / 批量删除」
   · 点列名排序：升 → 降 → 取消；当前的排序列加底色 + ▲▼
   ========================================================================== */

/* 勾选列：跟冻结列一样，钉在最左边（偏移 0），冻结的数据列从它右边开始排 */
.grid-edit th.sel-col,.grid-edit td.sel-col{
  position:sticky;left:0;width:42px;min-width:42px;padding:2px 6px;text-align:center;
  background:var(--card);z-index:3;
}
.grid-edit thead th.sel-col{background:#FAFBFC;z-index:5}
.grid-edit tr.editing td.sel-col{background:#FFFDF5}
.grid-edit tr.dirty td.sel-col{background:#FFF7E4}
.grid-edit tbody tr:hover td.sel-col{background:#FCFDFF}
.grid-edit .sel-col input[type=checkbox]{width:auto;cursor:pointer;vertical-align:-2px}

/* 勾了行 → 工具条上冒出来的那一条 */
.sel-bar{display:inline-flex;align-items:center;gap:8px}
.sel-bar b{font-size:13px;color:var(--blue)}

/* 排序：当前排的列加点底色，列名后面缀 ▲ / ▼（列名被截断时也认得出在按它排） */
.grid-edit th.sorted{background:var(--blue-50);color:var(--blue)}
.grid-edit tbody tr td.sort-tint{background:#FCFDFF}
.grid-edit th .sort-ind{margin-left:5px;font-size:10px;color:var(--blue)}

/* ==========================================================================
   表头行也冻住（2026-09-26 老板：「表头行，也是要做冻结处理的哦」）
   --------------------------------------------------------------------------
   老板先把左边几列冻了，接着就发现表头本身也会被滚走。

   ⚠️⚠️ 光写 `position:sticky;top:0` 是**没用的**：sticky 是相对**最近的滚动容器**吸的，
   而表格外面就套着 `.table-scroll{overflow-x:auto}`（横向滚动必须留着）——
   它本身就是滚动容器、高度又跟着内容长，永远不纵滚 → 表头等于吸在一个不会动的框上。
   → 所以 `renderGrid` 里的 `sizeGrid()` 给 `#md-scroll` 按屏幕算了个 `max-height`，
     让它**自己纵向也能滚**。这样：表头吸它的顶、冻结列吸它的左、操作列吸它的右，
     全都在同一个滚动区里，互不打架。

   z-index 顺序（表头必须在所有行之上）：表头普通格 6 < 表头冻结列 7 < 表头勾选/操作列 8
   ========================================================================== */
.grid-edit thead th{position:sticky;top:0;z-index:6}
.grid-edit thead th.frozen{z-index:7}
.grid-edit thead th.sel-col{z-index:8}

/* ==========================================================================
   上方工具条 + 查询窗口 + 分页条（2026-09-26 老板，参照博远）
   --------------------------------------------------------------------------
   老板原话（贴博远「商品型号」截图）：
     1、上方增加查询的窗口（关联的字段）
     2、改，查询，删除也是放在上方
     3、同步列数据（批量改的好方式）
     4、页面选择可以调配（借鉴右下角）

   → 顶部一条工具栏（改 / 删除 / 同步列数据 / 查询 / 字段配置 / 撤销），
     下面一块可收起的查询区（这个实体的每个字段一格），
     最底下一行分页（每页条数 + 记录 1-50/1841 + 首页/上下页/末页 + 跳页）。
   ========================================================================== */

/* 工具条：状态字和「已选 N 行」推到右边 */
.grid-bar{gap:8px}
.grid-bar #md-discard{margin-left:0}
.grid-bar #md-state{margin-left:auto}
.grid-bar .gsep{width:1px;height:20px;background:var(--line);align-self:center;flex:none}
.grid-bar .btn{flex:none}

/* ---- 查询窗口 ---- */
.q-panel{
  background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);
  padding:12px 14px;margin-bottom:10px;
  /* ⚠️ 这块一撑开就吃掉表格的高度（商品有 19 个字段）—— 卡在 30vh，
     超了自己在里面滚。他嫌挤就点「🔍 查询」收起来，表格立刻长回来。 */
  max-height:30vh;overflow:auto;
}
.q-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(214px,1fr));gap:8px 14px}
.q-cell{display:flex;flex-direction:column;gap:3px;min-width:0}
.q-cell label{font-size:11.5px;color:var(--ink-3);line-height:1.4}
.q-cell input,.q-cell select{width:100%;padding:4px 8px;font-size:12.5px;border-radius:6px}
.q-cell .rg-wrap{position:relative}
.q-actions{
  display:flex;align-items:center;gap:8px;flex-wrap:wrap;
  margin-top:12px;padding-top:10px;border-top:1px solid var(--line);
}
.q-actions .hint{margin:0;flex:1;min-width:180px}

/* ---- 底部：说明行 + 分页条（两块一起吸在屏幕底部） ---- */
.md-foot{
  position:sticky;bottom:0;z-index:15;margin-top:10px;
  display:flex;flex-direction:column;gap:8px;
}
.md-foot .grid-hint{position:static;margin:0;box-shadow:none}
.grid-pager{
  display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  padding:7px 12px;background:var(--card);border:1px solid var(--line);
  border-radius:var(--r);font-size:12.5px;color:var(--ink-2);
  box-shadow:0 -6px 16px rgba(20,24,32,.06);
}
.grid-pager .pg-size{display:inline-flex;align-items:center;gap:5px}
.grid-pager .pg-info{color:var(--ink-3)}
.grid-pager .pg-nav{display:inline-flex;align-items:center;gap:6px}
.grid-pager .pg-no{color:var(--ink-2)}
.grid-pager .pg-no b{color:var(--ink)}
.grid-pager .pg-jump{display:inline-flex;align-items:center;gap:5px;margin-left:auto}
.grid-pager select{width:auto;padding:2px 6px;font-size:12.5px;border-radius:6px}
.grid-pager .pg-jump input{width:60px;padding:2px 7px;font-size:12.5px;border-radius:6px;text-align:center}
.grid-pager .btn.tiny{padding:3px 9px;font-size:12px}

/* ---- 「同步列数据」弹窗里的范围选择 ---- */
.sc-scope{display:flex;flex-direction:column;gap:8px;margin:12px 0}
.sc-opt{
  display:flex;align-items:center;gap:9px;font-size:13px;line-height:1.5;
  padding:9px 11px;border:1px solid var(--line);border-radius:var(--r);cursor:pointer;
}
.sc-opt:hover{border-color:#C9D6EA;background:#FCFDFF}
.sc-opt input{width:auto;flex:none;margin:0}
.sc-opt.off{opacity:.55;cursor:not-allowed}

@media (max-width:820px){
  .grid-bar .gsep{display:none}
  .grid-bar #md-state{margin-left:0;width:100%}
  .q-grid{grid-template-columns:repeat(auto-fill,minmax(150px,1fr))}
  .grid-pager .pg-jump{margin-left:0}
}

/* ==========================================================================
   版面配比：数据区要占到屏幕的 ~80%（2026-09-26 老板第 2 条）
   --------------------------------------------------------------------------
   老板原话（截了一张只有 4 行数据的图）：
     「这个显示具体行的内容太少，整个比例不非常不好 至少整个行显示要占比到80%。
       所以你要好好去分布」

   做到 80% 的四个动作（都在这一节）：
     ① 说明行 + 分页条 **并成一行**（原来上下两行，白吃 ~50px）
     ② 说明文字压到**一行**（完整版挂 title），原来那段四行的自述吃掉一条行高
     ③ 只有一页时**不画「跳到 _ 页」**
     ④ 查询区**查完自动收起**（`runQuery` 里），要看条件点「🔍 查询（N）」再摊开
   ========================================================================== */
.md-foot{
  /* ⚠️ 必须显式写 flex-direction:row —— 上面那条 `.md-foot` 写的是 column，
     这里只改 display/align 的话 **column 会继续生效**（同优先级、后写的只覆盖它写到的属性），
     表现就是"设了并排却还是上下两行"（真踩到，量出来两个子元素都是全宽）。 */
  display:flex;flex-direction:row;align-items:stretch;gap:8px;
  margin-top:8px;
}
.md-foot .grid-hint{
  flex:1;min-width:0;margin:0;box-shadow:none;
  padding:7px 12px;line-height:1.5;
  /* 长文案（报错逐条列出来）最多两行，超了自己在里面滚 —— 不把数据区顶下去 */
  max-height:3.4em;overflow:auto;
}
.md-foot .grid-pager{flex:none;box-shadow:none}

/* 工具条再收紧一档（按钮和留白各让 2px，一屏下来也是 8~10px） */
.grid-bar{padding:8px 12px}
.grid-bar .btn{padding:7px 13px}
.grid-bar .btn.tiny{padding:4px 10px}

/* 查询区摊开时最多 24vh —— 摊着也要给数据区留下大半屏 */
.q-panel{max-height:24vh}
.q-actions{margin-top:10px;padding-top:8px}

@media (max-width:900px){
  /* 窄屏放不下一行：退回上下两行（说明在上面、分页在下面） */
  .md-foot{flex-direction:column}
  .md-foot .grid-pager{box-shadow:0 -6px 16px rgba(20,24,32,.06)}
}

/* ==========================================================================
   再挤一层：把「标题栏 / 工具条 / 底栏」三处固定高度都收一档
   --------------------------------------------------------------------------
   数据区占比 = (屏幕高 − 标题栏 − 工具条 − 底栏) / 屏幕高。
   上面那几种固定高度每省 10px，数据区就多 10px（1440×900 上约 1.1%，622 高的小窗约 1.6%）。
   这里都是**全站通用**的收紧（留白少一点、行高紧一点），不是只给主数据页开小灶 ——
   不然各页留白不一样，翻页的时候会跳。
   ========================================================================== */
.content{padding:16px 28px 16px}          /* 原 22 / 60：底部那 60px 纯留白，收掉给数据区 */
.topbar{padding:14px 28px 12px}           /* 原 22 / 18 */
/* 标题和「共 N 条」并成一行 —— 原来上下两行白吃 ~19px */
.topbar .title-box{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap}
.topbar h2{line-height:1.25}
.topbar .page-sub{margin:0;line-height:1.35}
/* 工具条按钮：再矮 6px（仍然好点，宽度没动） */
.grid-bar{padding:7px 12px}
.grid-bar .btn{padding:5px 12px;font-size:13.5px;line-height:1.45}
.grid-bar .btn.tiny{padding:4px 10px;font-size:12.5px}
/* 分页条：padding 收 2px；里面的小控件也矮一点 */
.grid-pager{padding:5px 11px}
.grid-pager .btn.tiny{padding:2px 8px;font-size:11.5px;line-height:1.5}
.grid-pager select,.grid-pager .pg-jump input{padding:1px 6px}
/* 最后再收 6~10px：工具条留白、分页条里那几个小控件 */
.grid-bar{padding:5px 12px}
.grid-pager{padding:5px 11px}
.grid-pager .btn.tiny{padding:2px 8px;font-size:11.5px;line-height:1.3}
.grid-pager select,.grid-pager .pg-jump input{padding:1px 6px;line-height:1.3;height:auto}
.grid-pager .pg-info,.grid-pager .pg-no,.grid-pager .pg-size{line-height:1.4}
.md-foot .grid-hint{padding:6px 12px}
/* 收尾 4+8px：内容区上下留白、页头留白再各让一档（仍然是全站一致的） */
.content{padding:12px 28px 12px}
.topbar{padding:10px 28px 10px}
.grid-bar{padding:4px 12px}
/* 收最后 12px —— 目标是把数据区顶到 80%（1440×900 上 79% → 80%）。
   都是 2~4px 的微调，单看没感觉，加起来正好一条数据行。 */
.content{padding:10px 28px 10px}
.topbar{padding:9px 28px 9px}
.md-foot .grid-hint{padding:5px 12px}
.grid-pager{padding:4px 10px}

/* ==========================================================================
   查询区「浮」在表格上方，不占版面（2026-09-26 老板两条要求合起来看）
   --------------------------------------------------------------------------
   老板两条：① 上方要有查询窗口 ② 数据区至少占 80%。
   两条**互相挤**：查询区一摊开就吃掉两三百像素。→ 让它 `position:absolute` 浮起来，
   表格永远占满剩下的高度；查询区摊开时盖在头几行上，点「查询」自己收掉。
   ⚠️ 挂在 `.table-wrap` 里（那个容器已有 `overflow:hidden` + 圆角，正好裁边）。
   ⚠️ 别忘了 `.md-wrap{position:relative}` —— 少了它，浮层会跑到页面左上角去。
   ========================================================================== */
.md-wrap{position:relative}
.md-wrap .q-panel{
  position:absolute;top:0;left:0;right:0;z-index:11;
  margin:0;border:0;border-bottom:1px solid var(--line);border-radius:0;
  box-shadow:0 14px 26px rgba(20,24,32,.16);
  /* 浮着的时候不用那么矮（不再挤压表格）—— 一屏能看全大部分字段，少一次内部滚动 */
  max-height:46vh;
}

/* ==========================================================================
   「一条都没有」的提示：居中、永远看得见（2026-09-26 真踩到）
   --------------------------------------------------------------------------
   原来是把提示塞进 `<td colspan="N">` —— 商品表 20 列、固定布局，总宽 2966px，
   居中之后文字落在 x≈1728（视口才 1440）→ **屏幕上就是一片空白**。
   老板把 45 款商品全设成「停用」之后，屏幕上那句「全被收起来了、点开关能看到」
   一个字都没显示出来 —— 他会以为数据被删了。
   → 没有数据时干脆不画表格，改画这块居中提示（`height:100%` 让它占满表格区）。
   ========================================================================== */
.md-empty{
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:8px;height:100%;min-height:180px;padding:26px 20px;text-align:center;
}
.md-empty h3{margin:0;font-size:15px;font-weight:600;color:var(--ink-2)}
.md-empty p{margin:0;font-size:13px;color:var(--ink-3);line-height:1.8;max-width:560px}
.md-empty b{color:var(--ink)}

/* ==========================================================================
   期初建账 · 「要你定」的冲突卡（2026-09-30 深夜）
   --------------------------------------------------------------------------
   老板原话：「这个系统觉得有错误的提示，要做出让我自己去选择改正……
   我的判定好像比较正确」。原来是「跟商品档案对不上 …… 以档案为准」——
   系统替他拍了板，他改不了；而档案里那些值本身也可能是老 ERP 带过来的脏数据。
   现在按「同一个商品 + 同一个字段 + 同一个值」归组，一行一个决定：
   左边是"你写的"、右边是"档案里的"，点哪边听哪边；同类的还能一次全选。
   ========================================================================== */
.dec-wrap{margin:12px 0;border:1px solid var(--line);border-radius:var(--r-lg);overflow:hidden}
.dec-top{display:flex;align-items:baseline;gap:10px;padding:10px 14px;
  background:var(--amber-50);border-bottom:1px solid var(--line)}
.dec-top b{font-size:13.5px}
.dec-top .sub{font-size:12px;color:var(--ink-3)}
.dec-grp{padding:10px 14px;border-bottom:1px solid var(--line-2)}
.dec-grp:last-child{border-bottom:0}
.dec-gh{display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  font-size:12.5px;color:var(--ink-2);margin-bottom:6px}
.dec-gh>b{font-size:13.5px;color:var(--ink)}
.dec-all{display:inline-flex;align-items:center;gap:6px;margin-left:auto;color:var(--ink-3)}
.dec-all button{padding:2px 8px;font-size:12px;border:1px solid var(--line);
  border-radius:6px;background:var(--card);cursor:pointer;color:var(--ink-2)}
.dec-all button:hover{border-color:var(--blue);color:var(--blue)}
.dec{padding:8px 10px;border-radius:var(--r);background:var(--bg);margin:6px 0}
.dec-t{font-size:13px;color:var(--ink);line-height:1.6;word-break:break-all}
.dec-t .sub{font-size:12px;color:var(--ink-3);white-space:nowrap}
.dec-hint{margin:4px 0 8px;font-size:12.5px;color:var(--ink-2);line-height:1.7}
.dec-btn{display:flex;gap:8px;flex-wrap:wrap}
.dec-btn button{display:flex;flex-direction:column;align-items:flex-start;gap:1px;
  padding:6px 12px;font-size:13px;border:1px solid var(--line);border-radius:8px;
  background:var(--card);cursor:pointer;color:var(--ink-2);text-align:left}
.dec-btn button:hover{border-color:var(--blue)}
.dec-btn button.on{border-color:var(--blue);background:var(--blue-50);
  color:var(--blue);font-weight:600}
.dec-tip{font-size:11.5px;color:var(--ink-3);font-weight:400}
.dec-btn button.on .dec-tip{color:var(--blue)}
.dec-sel{width:100%;max-width:420px;padding:6px 10px;font-size:13px;
  border:1px solid var(--line);border-radius:8px;background:var(--card);color:var(--ink)}
.op-more{margin:10px 0}
.op-more>summary{cursor:pointer;font-size:12.5px;color:var(--ink-3);padding:4px 0}
.op-more>summary:hover{color:var(--blue)}

/* ===========================================================================
   串码台账：按导入格式摆全部列（2026-10-01 老板）
   --------------------------------------------------------------------------
   老板原话：
     「串码台账的信息列没有按我导入的格式去做所有列的显示」
     「整个页面也没有导出的按钮」

   30 列摆一屏是不可能的，所以这套版式解决三件事：
     ① **横向滚**（列多）—— `.tbl-x` 同时管横向和纵向，
        纵向给个 `max-height`，表头才吸得住（跟主数据表格同一个道理：
        sticky 是相对**最近的滚动容器**吸的，容器不纵滚，表头就等于没吸）。
     ② **首列钉住** —— 往右滚时串号始终在眼前。勾选列在 0，串号列接在它右边（34px）。
        ⚠️ 钉住的格子**必须自带底色**，否则滚过去的内容会从底下透出来。
     ③ **「列」面板** —— 他嫌挤就勾掉几列，勾过记住。
   =========================================================================== */
.tbl-x{overflow:auto;max-height:calc(100vh - 330px);min-height:280px}
.tbl-x table.grid{min-width:100%;width:auto}
.tbl-x table.grid th,
.tbl-x table.grid td{white-space:nowrap}

/* 表头吸顶（在这个滚动容器里吸）；钉住的列要盖在表头之上 */
.tbl-x thead th{position:sticky;top:0;z-index:6}
.tbl-x th.stick1,.tbl-x td.stick1{
  position:sticky;left:0;z-index:5;width:34px;min-width:34px;
  padding-left:10px;padding-right:6px;background:var(--card);
}
.tbl-x thead th.stick1{z-index:9;background:var(--line-2)}
.tbl-x th.stick2,.tbl-x td.stick2{
  position:sticky;left:34px;z-index:4;background:var(--card);
  box-shadow:7px 0 9px -7px rgba(20,24,32,.18);   /* 冻到这儿为止的那道影 */
}
.tbl-x thead th.stick2{z-index:8;background:var(--line-2)}
.tbl-x tbody tr:hover td.stick1,.tbl-x tbody tr:hover td.stick2{background:#FBFCFE}
.tbl-x th.num-head{text-align:right}

/* ---- 「列」面板 ---- */
.colpanel{
  border:1px solid var(--line);border-radius:var(--r);background:var(--card);
  padding:10px 12px;margin:-4px 0 12px;
}
.cp-head{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin:0 0 8px;font-size:13px}
.cp-head .sub{color:var(--ink-3);font-size:12px}
.cp-head button{margin-left:0}
.cp-list{
  display:flex;flex-wrap:wrap;gap:4px 14px;
  max-height:150px;overflow:auto;
}
.cp-item{
  display:inline-flex;align-items:center;gap:5px;
  font-size:12.5px;color:var(--ink-2);white-space:nowrap;cursor:pointer;padding:2px 0;
}
.cp-item:hover{color:var(--blue)}
.cp-item input[type=checkbox]{width:auto;cursor:pointer}

/* ===========================================================================
   串码管理 · 串号全程跟踪（#serial_trace）+ 串号批量跟踪（#serial_batch）
   —— 2026-10-01 晚。老板拿博远的「串号管理」10 个子菜单来，拍板做这个板块。
   =========================================================================== */

/* ---- 首列钉住（**没有勾选列**时用这个）----
   ⚠️ `.stick1` 是给「勾选框」那一列用的，写死了 34px；批量跟踪/跟踪页没有勾选框，
      直接套 stick1 会把串号列压成 34px 宽。
      `.stick0` = 钉最左边、宽度自动、自带底色（不底色的话右边内容会从底下透出来）。 */
.tbl-x th.stick0,.tbl-x td.stick0{
  position:sticky;left:0;z-index:5;background:var(--card);
  box-shadow:7px 0 9px -7px rgba(20,24,32,.18);
}
.tbl-x thead th.stick0{z-index:9;background:var(--line-2)}
.tbl-x tbody tr:hover td.stick0{background:#FBFCFE}

/* ---- 串号全程跟踪：贴多个号时的一排可点号 + 「从 → 到」 ---- */
.st-list{margin:-4px 0 12px}
.st-chips{display:flex;flex-wrap:wrap;gap:6px}
.st-chip{font-family:ui-monospace,SFMono-Regular,Menlo,monospace}
.st-chip.on{background:var(--blue-50);border-color:var(--blue);color:var(--blue)}
.st-cur{background:var(--line-2)}
.st-cur-h{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:0 0 2px}
.st-ends{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.st-from{color:var(--ink-2)}
.st-arrow{color:var(--ink-3)}
.st-to{color:var(--ink);font-weight:500}

/* ---- 串号批量跟踪：一个能贴一坨号的大框 + 「查无此号」的红色号牌 ---- */
.sb-input{
  width:100%;min-height:96px;padding:9px 11px;
  font-size:13.5px;line-height:1.6;
  font-family:ui-monospace,SFMono-Regular,Menlo,monospace;
  color:var(--ink);background:var(--card);
  border:1px solid var(--line);border-radius:var(--r);resize:vertical;
}
.sb-input:focus{outline:none;border-color:var(--blue)}
.sb-miss{display:flex;flex-wrap:wrap;gap:6px;align-items:center;margin-top:6px}
.sb-miss .mono{
  background:var(--red-50);border:1px solid var(--red);border-radius:4px;padding:2px 7px;
}

/* ===========================================================================
   串码台账 · 批量指定仓库 / 货源门店弹窗（2026-10-01 晚）
   老板：「你新增「做仓库门店批量指定」」—— 期初 446 台没仓库、1341 台没货源门店。
   =========================================================================== */
.asg-grid{
  display:grid;grid-template-columns:88px 1fr;gap:10px 12px;align-items:center;
  margin:14px 0 4px;
}
.asg-l{font-size:13px;color:var(--ink-2);text-align:right}
.asg-grid select,.asg-grid input{
  padding:8px 10px;font-size:13.5px;color:var(--ink);
  border:1px solid var(--line);border-radius:var(--r);background:var(--card);
  width:100%;max-width:420px;
}
.asg-grid select:focus,.asg-grid input:focus{outline:none;border-color:var(--blue)}
.asg-list{
  border:1px solid var(--line);border-radius:var(--r);background:#FBFCFE;
  padding:8px 12px;margin:6px 0 12px;max-height:190px;overflow:auto;
}
.asg-list > div{display:flex;gap:10px;align-items:center;flex-wrap:wrap;padding:2px 0;font-size:13px}
.asg-foot{display:flex;align-items:center;justify-content:flex-end;gap:12px;margin-top:6px}
.asg-foot .msg{margin:0;flex:1}

/* ==========================================================================
   多标签页（2026-10-02）
   --------------------------------------------------------------------------
   老板：「不要每一个页面打开，我再点开另一个页面，打开的页面就关掉了，这样也是
         非常不方便的，我需要可以多开页面，而且还能让我快速找到我打开的页面。」
   结构见 index.html 的 #tabs / #stage 和 js/tabs.js。这里只管长相。
   ========================================================================== */
/* 标签条是**白吃一行高度**的（老板一直盯着「数据区占比」）—— 所以这条压到最矮：
   标签 22px 高、和标题行之间只留 6px。整条连间距一共约 28px。 */
.topbar{flex-direction:column;align-items:stretch;gap:6px;min-width:0}
/* ★★ 2026-10-02 真机撞到的横向溢出（手机上整页被撑宽 134～438px）：
     390 视口下实测 —— `.topbar` 宽 390，可它的两个子项 `.tabbar` / `.topbar-row`
     却拿到了**内容宽 816**（把 `.main` 的 scrollWidth 顶到 828）。
     后果不止「要左右拖整页」：手机浏览器发现内容比屏幕宽，会**自动缩小整页**
     （实测 innerWidth 从 390 变成 828）—— 老板看到的又成了「挤窄的电脑版」，
     字小、点不准。**溢出才是根，缩放是果。**
     修法：给这两个 flex 容器钉死 `max-width:100%`，它们必然会缩到父容器宽，
     里面的 `.tb-scroll`（overflow-x:auto）自己滚，标签与表格照样看得到。
     ⚠️ 别再给它们加 `width:100%` 之外的宽度值，也别去掉这个上限。 */
.topbar-row{display:flex;align-items:center;gap:14px;flex-wrap:wrap;min-width:0;max-width:100%}

.tabbar{display:flex;align-items:center;gap:8px;min-width:0;max-width:100%}
.tabbar:empty{display:none}
.tb-scroll{display:flex;align-items:center;gap:6px;flex:1;min-width:0;overflow-x:auto;
  scrollbar-width:none}
.tb-scroll::-webkit-scrollbar{display:none}
.tb-item{display:flex;align-items:center;gap:6px;flex:none;max-width:190px;
  padding:0 6px 0 10px;border:1px solid var(--line);border-radius:999px;height:22px;
  background:var(--card);color:var(--ink-2);font-size:12.5px;line-height:1;
  cursor:pointer;user-select:none}
.tb-item:hover{border-color:#C7D6EF;color:var(--ink)}
.tb-item.active{background:var(--blue-50);border-color:#B9D5FF;color:var(--blue);font-weight:600}
.tb-item .tb-t{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tb-item .tb-x{flex:none;width:15px;height:15px;line-height:14px;text-align:center;
  border-radius:50%;color:var(--ink-3);font-size:13.5px}
.tb-item .tb-x:hover{background:#D8E4F8;color:var(--red)}
.tb-find{flex:none;display:flex;align-items:center;gap:5px;padding:0 10px;height:22px;
  border:1px solid var(--line);border-radius:999px;background:var(--card);
  color:var(--ink-2);font-size:12.5px;font-family:inherit;line-height:1;cursor:pointer}
.tb-find:hover{border-color:var(--blue);color:var(--blue)}
.tb-find .tb-kbd{font-size:10.5px;color:var(--ink-3);border:1px solid var(--line);
  border-radius:4px;padding:0 3px;line-height:1.5}
.tb-find:hover .tb-kbd{border-color:#B9D5FF;color:var(--blue)}

.tb-menu{position:fixed;z-index:1200;width:132px;padding:4px;background:var(--card);
  border:1px solid var(--line);border-radius:var(--r);box-shadow:0 10px 26px rgba(20,24,32,.16)}
.tb-mi{padding:7px 10px;border-radius:7px;font-size:13px;color:var(--ink-2);cursor:pointer}
.tb-mi:hover{background:var(--blue-50);color:var(--blue)}

/* 舞台：当前页的壳挂在这儿。
   正在后台渲染的壳挂在屏幕外的 #stage-off —— 它**还在文档里**，
   模块 render 里那种 `document.querySelectorAll('.sl-pick')` 才找得到自己刚画的元素。 */
#stage{flex:1;min-width:0;display:flex;flex-direction:column}
#stage-off{position:absolute;left:-20000px;top:0;width:100%;
  visibility:hidden;pointer-events:none;z-index:-1}

/* 快速找页面（⌘K） */
.tq-mask{position:fixed;inset:0;z-index:1300;background:rgba(19,23,31,.28);
  display:flex;justify-content:center;align-items:flex-start;padding:96px 16px 16px}
.tq-pop{width:100%;max-width:520px;background:var(--card);border-radius:var(--r-lg);
  box-shadow:0 24px 60px rgba(15,20,30,.28);overflow:hidden;display:flex;flex-direction:column;
  max-height:min(70vh,520px)}
.tq-head{display:flex;align-items:center;gap:10px;padding:12px 14px;border-bottom:1px solid var(--line)}
.tq-q{flex:1;min-width:0;height:38px;padding:0 12px;border:1px solid var(--line);border-radius:9px;
  font-size:14.5px;font-family:inherit;background:#fff;color:var(--ink);outline:none}
.tq-q:focus{border-color:var(--blue);box-shadow:0 0 0 2px var(--blue-50)}
.tq-hint{flex:none;font-size:11.5px;color:var(--ink-3)}
.tq-list{overflow-y:auto;padding:6px}
.tq-sec{padding:9px 10px 4px;font-size:11.5px;color:var(--ink-3);letter-spacing:.03em}
.tq-item{display:flex;align-items:center;gap:8px;padding:8px 10px;border-radius:8px;
  font-size:13.5px;color:var(--ink);cursor:pointer}
.tq-item.cur{background:var(--blue-50);color:var(--blue);font-weight:600}
.tq-item .tq-t{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tq-item .tq-tag{flex:none;font-size:10.5px;font-weight:400;color:var(--green);
  background:var(--green-50);padding:1px 7px;border-radius:999px}
.tq-empty{padding:22px 14px;font-size:13px;color:var(--ink-3);line-height:1.9;text-align:center}

/* ===========================================================================
   委托 / 受托代销页顶部那排金额块（2026-10-02）
   ---------------------------------------------------------------------------
   老板手机上看到「162.3 万」右边被切掉一截（真机量：要 61px，只给了 51.5px）。
   根因：这块的 grid 是**内联写死** `repeat(4,minmax(0,1fr))` —— 手机屏 390px
   减掉内边距只有 370px，四列每列 83px，而 24px 的「162.3 万」要 61px+。
   → 把内联样式搬成这个 class（声明一模一样，**桌面一个像素都不变**），
     窄屏就能在 @media 里把它改成 2 列。改内联样式是改不动的：
     内联优先级比任何类选择器都高，只能靠 !important，那才是真难维护。
   =========================================================================== */
.cs-stats{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px;margin-bottom:1rem}

/* ===========================================================================
   补开单页（激活反查）（2026-10-03）
   ---------------------------------------------------------------------------
   老板：「每天都有先走后补。我们要打通查询激活的方式，去做补开。」
   这一页三块：① 导入激活名单 ② 该补的单 ③ 逐台补开。

   样式只补缺的三件（其余全部复用 .card/.hint/.grid/.sc-in/.sc-msg）：
     · .bf-wrap / .bf-sec —— 三块之间的竖向留白（.card 自己不带内边距）
     · .bf-cards / .bf-card —— 按「货在谁手上」归堆的卡片（宽屏自动铺满）
     · .bf-row —— 一行排开的小表单（标签 + 输入 + 按钮，窄屏会竖过来）

   ⚠️ 全是**新类名**，老页面一个都用不到；窄屏适配在下面的手机版 @media 里。
   =========================================================================== */
.bf-wrap{display:flex;flex-direction:column;gap:14px}
.bf-sec{padding:16px 18px}
.bf-row{display:flex;align-items:flex-end;gap:8px;flex-wrap:wrap}
.bf-row .f-label{margin:0}
/* 卡片区：列宽不小于 238px，能放几张放几张（不写死列数，免得以后加筛选要重算） */
.bf-cards{display:grid;grid-template-columns:repeat(auto-fill,minmax(238px,1fr));gap:12px;margin:4px 0 14px}
.bf-card{
  display:flex;flex-direction:column;gap:3px;
  border:1px solid var(--line);border-radius:var(--r-lg);
  background:var(--card);padding:12px 14px;
}
.bf-card-h{display:flex;align-items:center;justify-content:space-between;gap:10px}
.bf-card-h b{font-size:13.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.bf-card-go{align-self:flex-start;margin-top:8px}

/* ==========================================================================
   手机版（2026-10-02）
   --------------------------------------------------------------------------
   老板：「给我开通一下手机版，我试试看」+「出差在外也要用」。

   改之前在手机上打开的样子（真机量过）：
     · 左侧菜单被压成 64px 宽，菜单项只剩一排**小圆点** —— 看不出哪一项是什么
     · 弹窗在 88vh 的小盒子里挤，长表单要横着拖
     · 输入框 14px，iOS 一点就**把整页放大**（然后整页错位）
     · 按钮 30px 高，拇指点不中（苹果建议 ≥44px）
     · 底部没有留 iPhone 那条横杠的安全区，最后一行被盖住

   这一版：侧栏变**滑出抽屉**（完整组名 + 菜单项 + 退出登录），弹窗全屏，
   输入 16px，按钮加大，留安全区。开关在 js/mobile.js，这里只管长相。

   ⚠️ 宽屏（>820px）**一个字都不受影响** —— 所有规则都关在 @media 里。
   ⚠️ 821 这个阈值必须跟 js/mobile.js 的 NARROW_MAX 对上（那边也是 820）。
   ========================================================================== */

/* ☰ 按钮和遮罩：宽屏不显示（宽屏有常驻侧栏，用不着） */
.mnav-btn{display:none}
.mnav-mask{display:none}
body.mnav-locked{overflow:hidden}

@media (max-width:820px){
  html{-webkit-text-size-adjust:100%}

  /* ---------------- 侧栏 → 滑出抽屉 ---------------- */
  .side{
    position:fixed;left:0;top:0;bottom:0;height:auto;
    width:min(82vw,320px);z-index:60;
    transform:translateX(-102%);transition:transform .18s ease;
    box-shadow:0 0 44px rgba(15,20,30,.26);
  }
  .app-wrap.mnav-open .side{transform:none}
  .mnav-mask{
    display:block;position:fixed;inset:0;z-index:55;
    background:rgba(19,23,31,.42);
    opacity:0;pointer-events:none;transition:opacity .18s ease;
  }
  .app-wrap.mnav-open .mnav-mask{opacity:1;pointer-events:auto}

  .brand{padding:calc(16px + env(safe-area-inset-top)) 16px 14px}
  .side-foot{padding:12px 14px calc(14px + env(safe-area-inset-bottom))}
  /* 抽屉里恢复完整的菜单手感：项高够手指点 */
  .nav{padding:4px 10px 12px}
  .nav-item{padding:11px 12px;font-size:14.5px}
  .nav-group{padding:14px 10px 6px;font-size:12px}
  .side-foot .btn.tiny{padding:9px 12px;font-size:13.5px}

  /* ☰ */
  .mnav-btn{
    display:inline-flex;align-items:center;justify-content:center;
    width:40px;height:40px;flex:none;padding:0;cursor:pointer;
    border:1px solid var(--line);border-radius:10px;
    background:var(--card);color:var(--ink-2);
  }
  .mnav-btn:active{background:var(--blue-50);color:var(--blue)}

  /* ---------------- 顶栏 ---------------- */
  .topbar{padding:calc(10px + env(safe-area-inset-top)) 12px 10px;gap:6px}
  .topbar-row{gap:8px;flex-wrap:wrap}
  .topbar h2{font-size:17px}
  .page-sub{font-size:12px}
  .title-box{flex:1 1 auto}
  /* 搜索框单独占一行、放到最下面（手机上横着排根本不够宽） */
  .topbar .search{width:100%;margin-left:0;order:9;height:40px}
  .topbar #import-btn,.topbar #new-btn{order:10}
  .topbar .btn{padding:9px 14px}

  /* 标签条：手机上手指点，22px 太细了 */
  .tb-item{height:30px;font-size:13px;max-width:150px}
  .tb-item .tb-x{width:20px;height:20px;line-height:19px;font-size:15px}
  .tb-find{height:30px;font-size:13px}
  .tb-find .tb-kbd{display:none}          /* 手机没键盘，⌘K 那行别占地方 */

  /* ---------------- 内容区 ---------------- */
  .content{padding:12px 12px calc(28px + env(safe-area-inset-bottom))}
  .stats{grid-template-columns:repeat(auto-fit,minmax(132px,1fr));gap:10px}
  .stat{padding:13px 14px}
  .stat .v{font-size:23px}
  .grid2{grid-template-columns:1fr}
  .px-bar{gap:6px}
  .grid-bar{flex-wrap:wrap}

  /* 表格：横着滑（列太多没办法），首列已经钉住了；高度按手机屏重算 ——
     原来那个 `100vh - 330px` 是按电脑的两行页头算的，手机上会剩得太少 */
  .tbl-x{max-height:calc(100vh - 240px);min-height:180px}
  th,td{padding:10px 12px}

  /* ---------------- 输入 / 按钮：手指点得中 ---------------- */
  /* ⚠️ 16px 是硬要求：iOS 上输入框小于 16px，一点就自动放大整页 */
  /* ★ 2026-10-02 修：原来这条写成 `input,select,textarea` —— 把 **勾选框** 也一起套上了
     `padding:10px 12px`。勾选框本来 13px 宽，被撑到 40px 上下，
     「☐ 连已作废的一起看」这种行尾的勾选项直接把容器顶爆
     （真机量：hint 370 宽的盒子被推到 377，整页跟着横向溢 5px）。
     → 16px 那条只留给**真正要打字的**输入框；勾选框单独给个够手指点的大小。 */
  input:not([type="checkbox"]):not([type="radio"]),select,textarea{font-size:16px;padding:10px 12px}
  input[type="checkbox"],input[type="radio"]{
    width:20px;height:20px;padding:0;margin:0 7px 0 0;vertical-align:-4px;flex:none;
  }
  .btn{padding:10px 16px}
  .btn.tiny{padding:7px 12px;font-size:13px}
  .chip{padding:6px 13px;font-size:13.5px}

  /* ---------------- 弹窗：手机上全屏 ---------------- */
  /* 小屏上「88vh 的小盒子」是最难受的：里面表单一窄就得横着拖，键盘一弹更挤。
     直接铺满整屏，头部固定、内容滚、底部按钮固定在拇指区。 */
  .modal{padding:0;align-items:stretch}
  .modal-box{
    max-width:none;width:100%;height:100%;max-height:100%;border-radius:0;
  }
  .modal-head{padding:14px 16px;padding-top:calc(14px + env(safe-area-inset-top))}
  .modal-head h3{font-size:16.5px}
  .modal-head .x{width:44px;height:44px;font-size:26px;line-height:1;padding:0}
  .modal-body{padding:4px 16px 20px}
  .modal-foot{
    padding:12px 16px;padding-bottom:calc(12px + env(safe-area-inset-bottom));
    gap:10px;
  }
  .modal-foot .btn{padding:12px 18px}

  /* ---------------- 登录页 ---------------- */
  .login-wrap{padding:16px}
  .login-card{padding:26px 20px 24px;border-radius:14px}
  .login-card h1{font-size:22px}

  /* ---------------- 「找页面」面板（⌘K） ---------------- */
  .tq-mask{padding:44px 10px 12px;align-items:flex-start}
  .tq-pop{max-height:calc(100vh - 70px)}
  .tq-q{height:44px}
  .tq-item{padding:11px 12px;font-size:14.5px}

  /* ======================================================================
     第二轮（2026-10-02 深夜）—— 老板两张截图：「把整个页面看到的信息更多、更清晰」
     ----------------------------------------------------------------------
     真机 390×844 量到的三处病（都不是猜的，是量出来的）：

     ① 库存看板一级卡片：货位小方块被挤成 **27.3px 宽、101px 高** ——
        「福州档口仓」一个字一行地竖着排。
        根因：`.iv-stk` 是 flex-wrap 的一行，`✅直接卖`(62) + `1处·159台`(74)
        + `最久108天`(72) + `看串码›`(56) + 间距 40 ≈ 304，正好把 328px 塞满，
        于是 `flex:1 1 0%` 且有 `min-width:0` 的 `.iv-stk-pl` 只剩 27px；
        `.iv-pm{max-width:100%}` 再把中文压成 1 个字宽。
     ② 对外报价单：宽屏的两栏硬塞进 390px → 每栏 154px、表格 152px、每列 51.7px，
        而价格是 16px 的 `5,650`（约 45px）—— 在 `padding:9px 8px` 后只剩 35px，
        于是被裁成「5,66」并压到颜色上（老板截图里就是糊成一团）。
     ③ 顺手量出来的**真 bug**：`.table-wrap{overflow:hidden}` ——
        采购申请那张表宽 976px，装进手机上 364px 的盒子，
        右边 600px 的列是**直接裁掉**的，老板根本不知道有那几列（滑也滑不到）。
        同样的问题在采购订单 / 付款申请 / 开单 / 串号异动明细（`.card`）上都有。

     三处病根是同一个：**宽屏的横向排布硬搬到窄屏**。
     修法也是同一条：窄屏一律换成竖排布局；该滑的让它真能滑。

     ⚠️ 全部关在 @media 里，>820px 一个字都不受影响。
     ⚠️ `.iv-stk-pl` 给 `flex-basis:100%` 是「独占一行」最省事的写法；
        别改成 `width:100%`（在 flex 行里 basis 优先，width 会被 grow 抢回去）。
     ====================================================================== */

  /* ---- ① 表格容器：手机上要能横滑，不能再把右边的列裁掉 ---- */
  .table-wrap,.card{overflow-x:auto;overflow-y:hidden}

  /* ---- ② 库存看板一级卡片：位置上第二行，中文不许再竖过来 ---- */
  .iv-stk-pl{flex:1 1 100%;min-width:0;order:9}
  .iv-pm{white-space:nowrap;flex:0 0 auto}
  .iv-stk-more{white-space:nowrap}
  .iv-stk-go{order:8;margin-left:auto}      /* 「看串码 ›」靠右，不占第二行 */
  .iv-stk{padding:6px 9px;gap:7px}
  .iv-stk-h,.iv-stk-cnt,.iv-stk-age,.iv-stk-can,.iv-stk-go{font-size:12px}
  .iv-card{padding:10px 12px}
  .iv-ctop{gap:8px}
  .iv-cname{flex:1 1 100%;min-width:0}
  .iv-attrs{margin-top:4px;gap:4px}
  .iv-attrs span{font-size:11px;padding:1px 6px}
  .iv-cright{gap:7px;justify-content:flex-start}
  .iv-nums{gap:6px}
  .iv-num{min-width:48px;padding:3px 7px 4px}
  .iv-num b{font-size:17px}
  .iv-num s{font-size:10.5px}
  .iv-cacts .btn{padding:7px 12px;font-size:13px}
  /* 搜索区原来 345px 高（占掉一屏四成）→ 收紧 */
  .iv-search{padding:10px 12px;margin-bottom:10px}
  .iv-srow{gap:7px}
  .iv-frow{gap:7px;margin-top:7px;padding-top:7px}
  .iv-fchips{gap:5px}
  .iv-fchip{padding:5px 10px;font-size:12.5px}
  .iv-fchip s{font-size:10.5px}
  .iv-tip{padding:9px 12px;font-size:13px}
  .iv-quota>summary{padding:10px 12px}
  /* 二级看板（弹窗）：位置名不再限 200px 宽 */
  .ivm-pl>summary{padding:8px 10px}
  .ivm-pname{max-width:100%}
  .ivm-s{padding:3px 0}
  .ivm-agecell{min-width:66px;padding:4px 8px}

  /* ---- ③ 对外报价单：手机上改一栏（两栏挤成一团，价格都看不清） ---- */
  .qs-bar{padding:9px 11px}
  .qs-bar-row{gap:6px}
  .qs-panes{flex-direction:column;gap:10px;padding:10px}
  .qs-title{padding:14px 12px 10px}
  .qs-title h2{font-size:18px}
  .qs thead th{padding:7px 6px;font-size:12px}
  .qs tbody td{padding:7px 6px;font-size:13px}
  .qs tbody td.qs-model b{font-size:14px}
  .qs-gb2{font-size:12px}
  .qs-price b{font-size:15px}
  .qs-band{font-size:13px;padding:11px 12px;letter-spacing:.5px}

  /* ---- ④ 全局再挤一档：一屏多看一行是一行 ---- */
  .content{padding:10px 10px calc(22px + env(safe-area-inset-bottom))}
  th,td{padding:9px 10px}
  .stat{padding:11px 12px}
  .stat .v{font-size:21px}
  .modal-body{padding:2px 12px 16px}

  /* ---- ⑤ 剩两个「差一点点」的溢出 ---- */
  /* 代销页那排金额块：4 列 → 2 列（24px 的「162.3 万」在 83px 的列里放不下） */
  .cs-stats{grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}
  /* 长提示文字里有「——」和引号，最后一行会顶出去 15px */
  .hint{overflow-wrap:anywhere}
  /* ★ 串号异动明细那条提示：末尾那个「☐ 连已作废的一起看」是 inline 的 <label>，
     它排在最后一行行尾时**不会折行**，一路顶到 392（容器才 370）——
     整页因此横向溢出 5px（真机量：docSW 395 / vw 390）。
     逐字量过：把这个 label 摘掉，hint 立刻回到 370。→ 让它自己占一行。 */
  .hint label{display:block;margin-top:3px}

  /* ---- ⑥ 补开单页：卡片收一列、表单竖排、按钮占满行（2026-10-03） ----
     这一页的输入框在 HTML 里带行内 style="max-width:160px" 这类小限制 ——
     行内样式优先级高于任何类选择器，所以这里必须用 !important 才压得住。
     （宽屏靠的就是那个 160px，别把它当垃圾删掉。） */
  .bf-cards{grid-template-columns:1fr}
  .bf-row{flex-direction:column;align-items:stretch;gap:6px}
  .bf-row .search,.bf-row input,.bf-row select{max-width:100% !important}
  .bf-row .f-label{margin-top:8px}
  .bf-card-go{align-self:stretch}
  .bf-sec{padding:12px 13px}

  /* ---- 商品名称映射：左右两栏在窄屏改成上下叠（2026-10-05）----
     左栏供应商清单改成固定高度 180px 的横条（点一下就换右边），
     不然 113 家在窄屏会把右边的表格顶到屏幕外。 */
  .sm-wrap{grid-template-columns:1fr;gap:10px}
  .sm-list{max-height:180px}
  .sm-side .search{margin:6px}

}

/* ----（2026-10-19 删除）一次按门店建多张的确认清单样式 `.ba-comp*` ----
   老板：「不要做门店拆分采购单的动作」⇒ 入口与弹层一起下线，这里不留死样式。 */

/* ---- 采购明细「人工匹配」面板（2026-10-06 老板要的当场匹配）---- */
.ns-box{border:1px solid var(--line);border-radius:var(--r);
  padding:12px 14px;margin:10px 0;background:#fbfcfd}
.ns-head{font-size:13.5px;line-height:1.7}
.ns-head b{color:var(--ink)}
.mt-list{display:flex;flex-direction:column;gap:4px;
  max-height:260px;overflow:auto;border:1px solid var(--line);
  border-radius:var(--r);padding:6px;background:#fff}
.mt-item{display:flex;align-items:center;gap:10px;text-align:left;
  padding:6px 9px;border:1px solid transparent;border-radius:6px;
  background:none;cursor:pointer;font-size:13px;width:100%}
.mt-item:hover{background:var(--blue-50,#f2f6fd);border-color:var(--line)}
.mt-item b{flex:0 1 auto}
.mt-item .sub{flex:1;text-align:right}

/* ---- 采购明细「人工匹配」面板（2026-10-06 老板要的当场匹配）---- */
.ns-box{border:1px solid var(--line);border-radius:var(--r);
  padding:12px 14px;margin:10px 0;background:#fbfcfd}
.ns-head{font-size:13.5px;line-height:1.7}
.ns-head b{color:var(--ink)}
.mt-list{display:flex;flex-direction:column;gap:4px;
  max-height:260px;overflow:auto;border:1px solid var(--line);
  border-radius:var(--r);padding:6px;background:#fff}
.mt-item{display:flex;align-items:center;gap:10px;text-align:left;
  padding:6px 9px;border:1px solid transparent;border-radius:6px;
  background:none;cursor:pointer;font-size:13px;width:100%}
.mt-item:hover{background:var(--blue-50,#f2f6fd);border-color:var(--line)}
.mt-item b{flex:0 1 auto}
.mt-item .sub{flex:1;text-align:right}

/* ===========================================================================
   业务拜访打卡（老板 2026-10-08 新增板块）
   ---------------------------------------------------------------------------
   ★ 全部写在**普通段**（不是 @media 里）⇒ 手机和电脑都能用同一套。
     理由：这一页是**手机为主**的（业务在客户店里单手操作），
     而看板是**电脑为主**的，两个都要好看 ⇒ 不能只塞进窄屏块。
   ★ 触摸目标一律 ≥44px（iOS 建议值，见 skill: mobile 版）——
     业务是站在店门口单手点，格子小了会点错。
   =========================================================================== */
.vs-top{display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:14px 16px;margin-bottom:14px;border-radius:12px;
  background:var(--bg-2,#f7f8fa);border:1px solid var(--bd,#e6e8eb)}
.vs-top-n{font-size:15px;font-weight:600}
.vs-top-s{font-size:13px;color:var(--fg-2,#666);margin-top:2px}
.vs-warn{color:#b8860b}
.vs-geo-ok{font-size:12px;padding:4px 10px;border-radius:999px;
  background:#e6f7ef;color:#0a7a4a;white-space:nowrap}
.vs-geo-no{font-size:12px;padding:4px 10px;border-radius:999px;
  background:#f3f4f6;color:#666;white-space:nowrap}

.vs-card{padding:14px 16px;margin-bottom:12px;border-radius:12px;
  border:1px solid var(--bd,#e6e8eb);background:var(--bg-1,#fff)}
.vs-step{font-size:12px;color:var(--fg-2,#666);margin-bottom:10px}
.vs-step b{color:#b03030}

.vs-inp,.vs-card .inp{width:100%;min-height:44px;font-size:16px;margin-bottom:8px}
.vs-row{display:flex;gap:8px;flex-wrap:wrap;align-items:center}
.vs-row-2>*{flex:1 1 180px;min-width:0}
.vs-chip{min-height:44px;padding:0 18px;border:1px solid var(--bd,#d8dbe0);
  border-radius:10px;background:#fff;font-size:14px;cursor:pointer}
.vs-chip.on{background:#e6f2ff;border-color:#3b82f6;color:#1d4ed8;font-weight:500}
.vs-hint{font-size:12px;color:var(--fg-2,#666);margin-top:8px;line-height:1.6}
.vs-hint b{color:#b03030}

.vs-cust-list{margin-top:8px;max-height:280px;overflow:auto}
.vs-cust-row{padding:10px 12px;border:1px solid var(--bd,#e6e8eb);border-radius:10px;
  margin-bottom:6px;cursor:pointer;min-height:44px;display:flex;
  align-items:center;gap:8px;flex-wrap:wrap}
.vs-cust-row:hover{border-color:#3b82f6;background:#f7fbff}
.vs-cust-picked{border-color:#3b82f6;background:#f0f7ff;cursor:default}
.vs-cust-n{font-size:14px;font-weight:500;flex:1 1 auto}
.vs-cust-m{font-size:12px;color:var(--fg-2,#666);flex:1 1 100%}
.vs-empty{font-size:13px;color:var(--fg-2,#666);padding:10px 0}

.vs-photo{display:flex;align-items:center;gap:12px;flex-wrap:wrap}
.vs-photo-btn{display:inline-flex;align-items:center;justify-content:center;
  min-height:44px;padding:0 20px;border:1px dashed #b9bec6;border-radius:10px;
  cursor:pointer;font-size:14px;background:#fafbfc}
.vs-photo-img{max-width:140px;max-height:100px;border-radius:8px;border:1px solid var(--bd,#e6e8eb)}

.vs-intents{margin:8px 0}
.vs-intent{display:flex;gap:6px;margin-bottom:6px;align-items:center}
.vs-intent .inp{flex:1 1 auto;min-width:0;min-height:44px;font-size:16px}
.vs-intent .vs-qty{flex:0 0 90px}

.vs-go{width:100%;min-height:52px;font-size:16px;font-weight:500;
  background:#1d9e75;color:#fff;border:none;border-radius:12px;cursor:pointer}
.vs-go:disabled{background:#9fb8b0}
.vs-msg{margin-top:10px;padding:12px 14px;border-radius:10px;font-size:14px;line-height:1.6}
.vs-msg-ok{background:#e6f7ef;color:#0a7a4a}
.vs-msg-bad{background:#fdecea;color:#a32020}
.vs-msg-warn{background:#fff7e6;color:#8a6100}

.vs-today{margin-top:20px}
.vs-row-card{display:flex;gap:10px;align-items:flex-start;padding:10px 0;
  border-bottom:1px solid var(--bd,#eef0f2)}
.vs-row-card.vs-doubt{background:#fffaf0}
.vs-row-card.vs-invalid{background:#fdf3f3}
.vs-rc-l{flex:1 1 auto;min-width:0}
.vs-rc-t{font-size:14px;font-weight:500}
.vs-rc-m{font-size:12px;color:var(--fg-2,#666);margin-top:2px}
.vs-rc-s{font-size:13px;margin-top:4px}
.vs-rc-w{font-size:12px;color:#8a6100;margin-top:4px}
.vs-rc-img{width:64px;height:64px;object-fit:cover;border-radius:8px;flex:0 0 auto}

/* ---- 看板 ---- */
.vs-kpi{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));
  gap:10px;margin-bottom:14px}
.vs-kpi-c{padding:14px 16px;border-radius:12px;border:1px solid var(--bd,#e6e8eb);
  background:var(--bg-1,#fff)}
.vs-kpi-l{font-size:12px;color:var(--fg-2,#666)}
.vs-kpi-v{font-size:22px;font-weight:600;margin:4px 0 2px}
.vs-kpi-s{font-size:12px;color:var(--fg-2,#666)}

.vs-cols{display:grid;grid-template-columns:1fr 320px;gap:12px;align-items:start}
.vs-panel{padding:14px 16px;border-radius:12px;border:1px solid var(--bd,#e6e8eb);
  background:var(--bg-1,#fff);margin-bottom:12px}
.vs-panel-t{font-size:15px;font-weight:600;margin-bottom:4px}
.vs-panel-s{font-size:12px;color:var(--fg-2,#666);line-height:1.6;margin-bottom:10px}

.vs-ach{display:grid;grid-template-columns:70px 1fr 52px;grid-template-areas:
  "n bar v" "m m m";gap:4px 10px;align-items:center;padding:8px 0;
  border-bottom:1px solid var(--bd,#eef0f2);cursor:pointer;min-height:44px}
.vs-ach:hover{background:#f7fbff}
.vs-ach-n{grid-area:n;font-size:14px}
.vs-ach-bar{grid-area:bar;height:10px;border-radius:5px;background:#eef0f2;overflow:hidden}
.vs-ach-fill{height:100%;border-radius:5px}
.vs-ach-ok{background:#1d9e75}
.vs-ach-mid{background:#e0a020}
.vs-ach-bad{background:#d04040}
.vs-ach-v{grid-area:v;font-size:13px;text-align:right}
.vs-ach-m{grid-area:m;font-size:12px;color:var(--fg-2,#666)}

.vs-watch{padding:10px 12px;border-radius:10px;margin-bottom:8px;cursor:pointer;
  border-left:3px solid}
.vs-watch-bad{background:#fdf3f3;border-color:#d04040}
.vs-watch-warn{background:#fffaf0;border-color:#e0a020}
.vs-watch-info{background:#f0f7ff;border-color:#3b82f6}
.vs-watch-t{font-size:14px;font-weight:500}
.vs-watch-s{font-size:12px;color:var(--fg-2,#666);margin-top:2px}

.vs-bad-num{color:#a32020;font-weight:600}
.vs-bad{color:#a32000;font-weight:600}
.vs-click{cursor:pointer}
.vs-click:hover{background:#f7fbff}

/* ---- 客户档案弹窗 ---- */
.vs-cv-head{margin-bottom:12px}
.vs-cv-n{font-size:17px;font-weight:600}
.vs-cv-m{font-size:13px;color:var(--fg-2,#666);margin-top:2px}
.vs-cv-a{font-size:12px;color:var(--fg-3,#999);margin-top:2px}
.vs-cv-cols{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-bottom:14px}
.vs-cv-col{padding:12px 14px;border-radius:10px;background:var(--bg-2,#f7f8fa);
  border:1px solid var(--bd,#e6e8eb)}
.vs-cv-t{font-size:13px;font-weight:600;margin-bottom:6px}
.vs-cv-t2{font-size:14px;font-weight:600;margin:14px 0 8px;
  padding-top:10px;border-top:1px solid var(--bd,#e6e8eb)}
.vs-cv-v{padding:8px 0;border-bottom:1px solid var(--bd,#eef0f2)}
.vs-cv-v.vs-doubt{background:#fffaf0}
.vs-cv-d{font-size:12px;color:var(--fg-2,#666)}
.vs-cv-s{font-size:14px;margin-top:3px}
.vs-cv-i{font-size:12px;color:var(--fg-2,#666);margin-top:3px}
.vs-cv-w{font-size:12px;color:#8a6100;margin-top:3px}
.vs-modal-s{font-size:13px;color:var(--fg-2,#666);margin-bottom:10px;line-height:1.6}

/* ---- 窄屏：看板两列改一列（拜访页本来就在手机主用） ---- */
@media(max-width:820px){
  .vs-cols{grid-template-columns:1fr}
  .vs-cv-cols{grid-template-columns:1fr}
  .vs-kpi{grid-template-columns:repeat(2,1fr)}
  .vs-ach{grid-template-columns:64px 1fr 48px}
  .vs-inp,.vs-card .inp,.vs-intent .inp{font-size:16px}
}

/* ---------------- 串码台账 · 状态锁定标签（2026-10-09）----------------
   库存页固定「在库」、出库页固定「已出库」—— 那一栏不再是能随便换的下拉，
   改成只读标签 + 一个「换页看」的提示，免得有人拿它当筛选器用。 */
.sl-locked{display:inline-flex;align-items:center;gap:6px;height:34px;
  padding:0 10px;border:1px solid var(--line);border-radius:var(--r-sm);
  background:var(--bg-2,#f6f7f9);color:var(--ink-1);font-size:13px;
  white-space:nowrap;cursor:default;}
.sl-locked-go{font-size:11px;font-weight:400;color:var(--blue);
  border-left:1px solid var(--line);padding-left:6px;margin-left:2px;}

/* ---------------- 串码台账 · 状态锁定标签（2026-10-09）----------------
   库存页固定「在库」、出库页固定「已出库」—— 那一栏不再是能随便换的下拉，
   改成只读标签 + 一个「换页看」的提示，免得有人拿它当筛选器用。 */
.sl-locked{display:inline-flex;align-items:center;gap:6px;height:34px;
  padding:0 10px;border:1px solid var(--line);border-radius:var(--r-sm);
  background:var(--bg-2,#f6f7f9);color:var(--ink-1);font-size:13px;
  white-space:nowrap;cursor:default;}
.sl-locked-go{font-size:11px;font-weight:400;color:var(--blue);
  border-left:1px solid var(--line);padding-left:6px;margin-left:2px;}

/* ---------------- 仓库调拨（2026-10-09 新板块）----------------
   顶部三个数字（在途/待签收/超期）+ 单据明细 + 详情签收。
   ★ 超期那格要显眼：老板第③条「超3天没签收标红提醒」。 */
.tf-top{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));
  gap:12px;margin-bottom:14px;}
.tf-kpi{background:var(--card,#fff);border:1px solid var(--line);border-radius:var(--r);
  padding:14px 16px;}
.tf-kpi-v{font-size:26px;font-weight:500;line-height:1.1;color:var(--ink-1);}
.tf-kpi-k{font-size:13px;color:var(--ink-2);margin-top:4px;}
.tf-kpi-s{font-size:12px;color:var(--ink-3);margin-top:6px;line-height:1.5;}
.tf-kpi-warn{border-color:#A32D2D;background:#FCEBEB;}
.tf-kpi-warn .tf-kpi-v{color:#A32D2D;}
.tf-kpi-act{display:flex;flex-direction:column;justify-content:center;gap:8px;}
/* 在途那一格标黄 —— 它是最需要被看见的数字 */
.tf-kpi:nth-child(1){border-color:#BA7517;background:#FAEEDA;}
.tf-kpi:nth-child(1) .tf-kpi-v{color:#854F0B;}
.tf-ov-warn{color:#A32D2D;}

.tf-onway{color:var(--blue,#185FA5);font-weight:500;}
/* ★ 超期未签收的整行标红（老板第③条） */
tr.tf-overdue td{background:#FCEBEB;}
tr.tf-overdue td:first-child{border-left:3px solid #A32D2D;}

.tf-detail .tf-route{display:flex;align-items:center;gap:10px;margin-bottom:8px;
  flex-wrap:wrap;}
.tf-wh{font-size:14px;font-weight:500;padding:4px 10px;border-radius:6px;
  background:#E6F1FB;color:#0C447C;}
.tf-wh-to{background:#E1F5EE;color:#085041;}
.tf-arrow{color:var(--ink-3);}
.tf-dmeta{display:flex;gap:14px;flex-wrap:wrap;font-size:12px;color:var(--ink-3);
  margin-bottom:10px;}
.tf-overdue-tip{background:#FCEBEB;border:1px solid #A32D2D;border-radius:8px;
  padding:10px 12px;font-size:13px;line-height:1.6;margin-bottom:10px;color:#501313;}
.tf-items{margin-top:10px;border:1px solid var(--line);border-radius:8px;
  overflow:hidden;max-height:280px;overflow-y:auto;}
.tf-items-h{padding:8px 12px;background:var(--bg-2,#f6f7f9);font-size:12px;
  color:var(--ink-2);}
.tf-item{display:flex;gap:10px;align-items:center;padding:6px 12px;
  border-top:1px solid var(--line);}
.tf-item-sn{font-family:var(--font-mono);font-size:12px;flex:none;min-width:150px;}
.tf-item-sku{flex:1;font-size:12px;color:var(--ink-2);overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap;}
/* ★ 签收前的提醒框：老板原话「请核对机型和串码再签收」 */
.tf-warn-box{background:#FAEEDA;border:1px solid #BA7517;border-radius:8px;
  padding:12px 14px;font-size:13px;line-height:1.7;color:#412402;margin-bottom:12px;}
.tf-check{border:1px solid var(--line);border-radius:8px;overflow:hidden;
  max-height:300px;overflow-y:auto;}
.tf-check-h{padding:8px 12px;background:var(--bg-2,#f6f7f9);font-size:12px;}

/* ---------------- 价格册 · 导入导出（2026-10-09）----------------
   导回后的结果块：成功提示 + ★ 缺货清单（老板自己标的，要显眼）。 */
.pi-ok{background:#E1F5EE;border:1px solid #0F6E56;border-radius:8px;
  padding:10px 12px;font-size:13px;color:#04342C;line-height:1.6;}
.pi-short{margin-top:10px;background:#FAEEDA;border:1px solid #854F0B;
  border-radius:8px;padding:10px 12px;font-size:13px;color:#412402;line-height:1.6;}
.pi-short-list{margin:8px 0;max-height:190px;overflow-y:auto;
  font-family:var(--font-mono);font-size:12px;color:#633806;
  background:var(--card,#fff);border-radius:6px;padding:8px 10px;}

/* ---------------- 价格册 · 导入导出（2026-10-09）----------------
   导回后的结果块：成功提示 + ★ 缺货清单（老板自己标的，要显眼）。 */
.pi-ok{background:#E1F5EE;border:1px solid #0F6E56;border-radius:8px;
  padding:10px 12px;font-size:13px;color:#04342C;line-height:1.6;}
.pi-short{margin-top:10px;background:#FAEEDA;border:1px solid #854F0B;
  border-radius:8px;padding:10px 12px;font-size:13px;color:#412402;line-height:1.6;}
.pi-short-list{margin:8px 0;max-height:190px;overflow-y:auto;
  font-family:var(--font-mono);font-size:12px;color:#633806;
  background:var(--card,#fff);border-radius:6px;padding:8px 10px;}

/* ======================================================================
   ★★ 客户订单接单闭环（2026-10-11 老板新板块）
   铁律：**全部作用域限定在 .it- 前缀类上**，一个全局选择器都不加 ——
   项目铁律「宽屏 >820px 一个字不能变」：新样式只许影响它自己那几个类。
   ====================================================================== */
.it-tb{table-layout:fixed;width:100%}
.it-tb td,.it-tb th{vertical-align:top}
/* 标红 = 已等超过阈值（阈值后端给的，默认 30 秒，老板可在设置里改）。
   ★ 只加左边一条粗红条 + 淡红底，**不整行变红字** —— 整行红字在明细表上刺眼到看不清。 */
.it-row.overdue{background:var(--red-50)}
.it-row.overdue td:first-child{border-left:3px solid var(--red)}
/* 机型列：最多显示 3 行，多的用省略号 + 悬停看全
   （一单十几款全列出来会把表格撑得没法看，标题栏也跟着歪） */
.it-items{max-height:66px;overflow:hidden}
.it-acts{white-space:nowrap}
/* 详情弹窗那两列信息 */
.it-dt{display:grid;grid-template-columns:repeat(4,1fr);gap:8px 16px;margin:0 0 14px}
.it-dt>div{display:flex;flex-direction:column;gap:2px}
.it-dt span{font-size:12px;color:var(--ink-3)}
.it-dt b{font-weight:500;font-size:14px}
@media(max-width:820px){
  /* 手机：信息两列、操作按钮换行、机型列不限高 */
  .it-dt{grid-template-columns:repeat(2,1fr)}
  .it-items{max-height:none}
  .it-tb{table-layout:auto}
}

/* ★ 2026-10-11 客户端订单页：接单信息行（接单人 / 线下确认结论 / 取消原因）。
   作用域限死 .p-taker，不影响别处。 */
.p-taker{margin:4px 0 0;font-size:13px;color:var(--ink-2)}

/* ======================================================================
   ★★ 2026-10-12 开单「没扫完串码」要一眼能挑出来
   老板原话：「所有的开单，没有扫串码，就不是真正意义的完成开单……
     而且整个界面没有明显的提示。让我去补最终的扫串码环节。」

   为什么要在**整行**上做：明细里那栏「扫串码 0/1」是**很小的红字**，
   列表一屏 20 行，眼睛一扫根本注意不到 —— 老板截图里那张单就是这么漏掉的。
   ⇒ 整行淡红底 + 左边一条粗红条，扫一眼就挑出来。
   铁律：作用域只限 `.or-noserial`，**一个字都不许碰通用表格**（宽屏不能变）。
   ====================================================================== */
tr.or-noserial > td{background:var(--red-50)}
tr.or-noserial > td:first-child{box-shadow:inset 3px 0 0 var(--red)}
tr.or-noserial:hover > td{background:var(--red-50)}
/* 「去补扫」按钮：放在状态格旁边，红色描边，一眼看得出是件没做的事 */
.btn.or-fixserial{background:#fff;color:var(--red);border:1px solid var(--red);
  padding:2px 8px;font-size:12px;margin-left:6px;border-radius:6px;cursor:pointer}
.btn.or-fixserial:hover{background:var(--red);color:#fff}

/* ======================================================================
   ★★ 2026-10-12 待办与预警（弹窗 + 语音 + 红点）
   铁律：全部作用域限定在 .td- / .nav-badge 上，一个通用选择器都不加。
   ====================================================================== */
.td-sum{display:flex;align-items:center;justify-content:space-between;gap:12px;
  flex-wrap:wrap;padding:10px 14px;border:1px solid var(--line);border-radius:8px;
  margin-bottom:12px;background:var(--card,#fff)}
.td-sum.urgent{border-color:var(--red);background:var(--red-50)}
.td-sum-n{font-size:15px}
.td-sum-n b{font-size:20px;color:var(--red)}
.td-sum-b{display:flex;align-items:center;gap:12px;flex-wrap:wrap}
.td-mute{display:inline-flex;align-items:center;gap:4px;font-size:13px;
  color:var(--ink-2);cursor:pointer}
.td-grp{border:1px solid var(--line);border-radius:8px;padding:10px 12px;
  margin-bottom:10px;background:var(--card,#fff)}
.td-grp.urgent{border-color:var(--red)}
.td-grp-h{display:flex;align-items:center;gap:8px;margin-bottom:4px}
.td-grp-h b{font-size:14px}
.td-ic{font-size:15px}
.td-cnt{background:var(--line-2);color:var(--ink-2);border-radius:10px;
  padding:0 8px;font-size:12px}
.td-cnt.ok{background:var(--green-50);color:var(--green)}
.td-urg{background:var(--red);color:#fff;border-radius:10px;padding:0 8px;font-size:12px}
.td-hint{margin:0 0 6px;font-size:12px;color:var(--ink-3)}
.td-empty{margin:0;font-size:13px;color:var(--ink-3)}
.td-item{display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding:6px 0;border-top:1px solid var(--line-2)}
.td-item.urgent .td-it-l b{color:var(--red)}
.td-it-l{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap;min-width:0}
.td-wait{font-size:12px;color:var(--red)}
.td-miss{font-size:12px;background:var(--red-50);color:var(--red);
  border-radius:4px;padding:0 6px}
/* 菜单红点 */
.nav-badge{background:var(--red);color:#fff;border-radius:9px;
  padding:0 6px;font-size:11px;font-style:normal;margin-left:auto}
@media(max-width:820px){
  .td-item{flex-direction:column;align-items:stretch}
  .td-sum{align-items:flex-start}
}

/* ======================================================================
   ★★ 2026-10-12 国补返佣（开单返佣场景 + 佣金单页 + 对账看板两块）

   铁律：作用域全部限定在 `.or-rb-` / `.cm-` / `.rb-ledger-` 前缀上，
        **一个通用选择器都不加**（项目铁律「宽屏 >820px 一个字不能变」）。
   ====================================================================== */

/* ---- 开单页：返佣场景 ---- */
.or-scene{margin:0 0 8px}
.or-scene-cb{display:inline-flex;align-items:center;gap:8px;cursor:pointer;
  font-size:13.5px;padding:4px 2px}
.or-scene-cb input{width:15px;height:15px;cursor:pointer}
.or-scene-hint{color:var(--ink-3);font-size:12.5px}
.or-rb-box{border:1px solid var(--line);border-left:3px solid var(--amber);
  border-radius:8px;background:#fffdf8;padding:10px 12px;margin-top:4px}
.or-rb-box.hidden{display:none}
.or-rb-row{display:flex;align-items:flex-end;gap:14px;flex-wrap:wrap}
.or-rb-hint{font-size:12.5px;padding-bottom:6px;min-width:180px}
.or-rb-warn{color:var(--red)}
.or-rb-done{color:var(--green)}
.or-rb-must{border-color:var(--red) !important;background:var(--red-50)}
.or-rb-sum{font-size:13px;color:var(--ink-2);padding-bottom:6px;margin-left:auto}
.or-rb-sum b{font-size:14.5px}

/* ---- 佣金单页 ---- */
.cm-sum{display:flex;align-items:center;gap:14px;flex-wrap:wrap;
  padding:8px 12px;border:1px solid var(--line);border-radius:8px;
  margin-bottom:10px;font-size:13.5px;background:var(--card,#fff)}
.cm-sum b{font-size:17px;color:var(--red)}
.cm-hint{color:var(--ink-3);font-size:12.5px}
.cm-tb{table-layout:fixed;width:100%}
.cm-tb td,.cm-tb th{vertical-align:top}
.cm-tb th:nth-child(1){width:112px}
.cm-tb th:nth-child(2){width:auto}
.cm-tb th:nth-child(3){width:130px}
.cm-tb th:nth-child(4),.cm-tb th:nth-child(5),
.cm-tb th:nth-child(6),.cm-tb th:nth-child(7){width:78px}
.cm-tb th:nth-child(8){width:82px}
.cm-tb th:nth-child(9){width:150px}
/* ★ 「还没给」的钱（我方还欠着的）标红 —— 这是老板最关心的那个数 */
.cm-left{color:var(--red)}
/* 待财务审且还有未结 ⇒ 整行淡红底，一眼挑出来（对齐接单那套做法） */
tr.cm-due>td{background:var(--red-50)}
tr.cm-due:hover>td{background:var(--red-50)}
.cm-acts{white-space:nowrap}

.cm-dt{display:grid;grid-template-columns:repeat(4,1fr);gap:8px 16px;margin:0 0 12px}
.cm-dt>div{display:flex;flex-direction:column;gap:2px}
.cm-dt label{font-size:12px;color:var(--ink-3)}
.cm-dt b{font-weight:500;font-size:14px}
.cm-h4{margin:14px 0 6px;font-size:14px;padding-bottom:4px;
  border-bottom:1px solid var(--line)}
.cm-money{margin:0}
.cm-money th{width:96px;background:#f6f7f9;font-weight:500}
.cm-money td{font-variant-numeric:tabular-nums}
.cm-bank{display:grid;grid-template-columns:repeat(3,1fr);gap:8px 14px;
  border:1px solid var(--line);border-radius:8px;padding:8px 12px;background:#fafbfc}
.cm-bank>div{display:flex;flex-direction:column;gap:2px}
.cm-bank label{font-size:12px;color:var(--ink-3)}
.cm-note{margin:8px 0;padding:6px 10px;background:var(--amber-50);
  border-left:3px solid var(--amber);border-radius:6px;font-size:13px}
.cm-warn{margin:8px 0;padding:8px 12px;background:var(--red-50);
  border-left:3px solid var(--red);border-radius:6px;font-size:13px;line-height:1.7}
/* ★ 2026-10-13 驳回闭环：改单弹窗里「点我换客户」的那个框 ——
   它是 readonly 的，光靠光标看不出能点，得给点视觉暗示。 */
.cm-pick{cursor:pointer;background:var(--amber-50);border-color:var(--amber)!important}
.cm-pick:hover{background:#FFF0D6}
.cm-qrbox{margin:8px 0}
.cm-qrbox label{display:block;font-size:12px;color:var(--ink-3);margin-bottom:4px}
.cm-qrs{display:flex;align-items:flex-end;gap:10px;flex-wrap:wrap}
.cm-qr{width:92px;height:92px;object-fit:contain;border:1px solid var(--line);
  border-radius:6px;background:#fff;cursor:zoom-in}
.cm-up{display:inline-flex;align-items:center;gap:5px;padding:4px 9px;
  border:1px dashed var(--line);border-radius:6px;font-size:12.5px;
  color:var(--ink-2);cursor:pointer}
.cm-up input{display:none}
.cm-pay{display:flex;gap:16px;flex-wrap:wrap;margin:4px 0 8px;font-size:13.5px}
.cm-pay label{display:inline-flex;align-items:center;gap:4px;cursor:pointer}
.cm-grid2{display:grid;grid-template-columns:1fr 1fr;gap:0 14px}
.cm-confirm{display:flex;align-items:flex-start;gap:7px;margin:8px 0;
  padding:8px 10px;background:var(--red-50);border-radius:6px;
  font-size:13px;line-height:1.6;cursor:pointer}
.cm-flow{display:flex;flex-direction:column;gap:6px}
.cm-flow-i{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap;
  padding:5px 0;border-bottom:1px dashed var(--line2);font-size:13px}
.cm-flow-i:last-child{border-bottom:none}
.cm-flow-i b{font-weight:600}

/* ---- 对账看板：应收 / 应付分两块（老板：「要能看清楚每一个客户的应收应付」）---- */
.rb-ledger{border:1px solid var(--line);border-radius:10px;margin-bottom:10px;
  overflow:hidden;background:var(--card,#fff)}
.rb-ledger-h{padding:7px 12px;background:#f2f4f7;font-weight:600;display:flex;
  justify-content:space-between;gap:10px;flex-wrap:wrap;font-size:14px}
.rb-ledger-sec{padding:6px 12px 2px;font-size:12.5px;font-weight:600;color:var(--ink-3)}
.rb-ledger-r{display:flex;justify-content:space-between;gap:12px;
  padding:5px 12px;border-bottom:1px solid var(--line2);font-size:13.5px}
.rb-ledger-r:last-child{border-bottom:none}
.rb-ledger-r.pay{background:var(--red-50)}
.rb-ledger-r.tot{background:#f2f4f7;font-weight:700;border-top:2px solid #2c3138;
  border-bottom:none;margin-top:4px}
.rb-ledger-net{font-size:15px;font-weight:700}
.rb-ledger-net.owe{color:var(--red)}
.rb-ledger-net.they{color:var(--green)}

@media(max-width:820px){
  .cm-dt{grid-template-columns:repeat(2,1fr)}
  .cm-bank,.cm-grid2{grid-template-columns:1fr}
  .cm-tb{table-layout:auto}
  .or-rb-sum{margin-left:0;width:100%}
}

/* ===== 国补价目表（2026-10-15 老板：「国补的带入价格，我希望做到价格册」）=====
   页面要点：政策参数条一眼可见（那几个数是公式，不是写死的）、
   表格里零售价/佣金是「你填的」，另外三列是「现算的」，视觉上要分得开。 */
.gp-policy {
  display: flex; flex-wrap: wrap; gap: 8px 18px; align-items: center;
  background: var(--color-background-secondary, #f7f7f8);
  border: 1px solid var(--color-border-tertiary, rgba(0,0,0,.08));
  border-radius: 8px; padding: 8px 12px; margin-bottom: 4px; font-size: 13px;
}
.gp-policy b { font-weight: 500; }
.gp-grid .or-c { text-align: right; }
.gp-grid tr.gp-bad { background: rgba(220, 60, 60, .05); }
.gp-form { display: flex; flex-wrap: wrap; gap: 10px 14px; }
.gp-form .gp-f { flex: 1 1 220px; }
.gp-form .gp-f.wide { flex: 1 1 100%; }
.gp-form input, .gp-form select, .gp-form textarea { width: 100%; }
.gp-sku { display: flex; gap: 6px; }
.gp-sku input { flex: 1; }
.gp-calc {
  background: var(--color-background-secondary, #f7f7f8);
  border-radius: 8px; padding: 8px 12px; font-size: 13px; line-height: 1.7;
}
.gp-calc b { font-weight: 500; margin-right: 10px; }
.gp-calc .sub { display: inline; margin-right: 12px; }

/* ===== 结算认款 + 客户对账单（2026-10-15）=====
   页面要点：老板认款时要「一眼看清这笔款会造成什么」——
   抵哪几张、抵多少、还差多少、多收多少，四种情况都用颜色分开；
   账单页的两个板块（应收 / 应付佣金）要视觉上明显分开，
   净额那一行是客户真正会看的数字，给它最大字号。 */
.st-pick .st-cust {
  max-height: 320px; overflow: auto; margin-top: 6px;
  border: 1px solid var(--color-border-tertiary, rgba(0,0,0,.08));
  border-radius: 8px;
}
.st-cust-row {
  display: flex; justify-content: space-between; align-items: center;
  gap: 10px; padding: 8px 12px; cursor: pointer;
  border-bottom: 1px solid var(--color-border-tertiary, rgba(0,0,0,.06));
}
.st-cust-row:hover { background: var(--color-background-secondary, #f6f6f7); }
.st-cust-row:last-child { border-bottom: none; }

.st-form { display: flex; flex-wrap: wrap; gap: 10px 14px; margin: 12px 0; }
.st-form > div { flex: 1 1 180px; }
.st-form input, .st-form select { width: 100%; }

.st-photos { display: flex; flex-wrap: wrap; gap: 8px; margin: 6px 0; }
.st-ph { position: relative; display: inline-block; }
.st-ph img {
  width: 84px; height: 84px; object-fit: cover;
  border: 1px solid var(--color-border-tertiary, rgba(0,0,0,.1));
  border-radius: 6px;
}
.st-ph .x {
  position: absolute; top: -6px; right: -6px;
  width: 20px; height: 20px; line-height: 18px; text-align: center;
  border: none; border-radius: 50%; background: #d33; color: #fff;
  font-size: 14px; cursor: pointer; padding: 0;
}

.st-plan {
  margin: 12px 0; padding: 10px 12px; font-size: 13px; line-height: 1.8;
  background: var(--color-background-secondary, #f7f7f8);
  border-radius: 8px;
}
.st-plan .st-sum { font-size: 14px; margin-bottom: 6px; }
.st-plan .st-lns { border-top: 1px dashed var(--color-border-tertiary, rgba(0,0,0,.12)); padding-top: 6px; }
.st-ln { display: flex; gap: 12px; align-items: center; font-size: 13px; }
.st-ln .money { margin-left: auto; font-weight: 500; }

.st-bills { margin-top: 12px; }
.st-bill {
  display: flex; align-items: center; gap: 10px;
  padding: 6px 4px; border-bottom: 1px dashed var(--color-border-tertiary, rgba(0,0,0,.08));
  font-size: 13px;
}
.st-bill .no { min-width: 150px; }
.st-bill .due { margin-left: auto; }
.st-bill .st-take { width: 100px; text-align: right; }
/* ★ 2026-10-19 按台认款：一台一行（单号/日期/机型串号/开单额/现欠/结算按钮） */
.st-bill .sn { flex: 1 1 auto; min-width: 0; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
.st-bill.st-bill-on { background: var(--color-background-secondary, #f2f7ff); }
.st-warn {
  margin: 10px 0; padding: 8px 12px; font-size: 13px;
  background: var(--color-background-warning, #fdf3e3);
  border-radius: 8px;
}

.bb-sec { margin: 14px 0; }
.bb-h { font-size: 14px; font-weight: 500; margin-bottom: 4px; }
.bb-sum {
  display: grid; grid-template-columns: 1fr auto; gap: 2px 12px;
  margin-top: 6px; padding: 8px 10px; font-size: 13px;
  background: var(--color-background-secondary, #f7f7f8); border-radius: 6px;
}
.bb-sum .tot { font-weight: 500; border-top: 1px solid var(--color-border-tertiary, rgba(0,0,0,.1)); padding-top: 4px; }
.bb-net {
  display: flex; justify-content: space-between; align-items: center;
  margin-top: 12px; padding: 12px 16px;
  background: var(--color-background-secondary, #f0f0f1);
  border-radius: 8px; font-size: 15px; font-weight: 500;
}
.bb-net b { font-size: 20px; }
.bb-net.neg { background: var(--color-background-warning, #fdf3e3); }

/* ---- 对账单：含税/未税提醒条 + 回款过程（老板 2026-10-19 要的两块） ----
   ⚠️ 变量名先查了本文件真实存在的（--ink-2 / --line / --line-2 / --card），
      别凭印象写 --bg2 / --blue600 那种 —— 名字不存在就是**静默没样式**，
      界面上看着像「这块没做」。 */
.bb-tax {
  margin: 8px 0; padding: 8px 10px; border-radius: var(--r, 8px);
  background: var(--card, #fff); border: 1px solid var(--line, rgba(0, 0, 0, .08));
}
.bb-tax-h { font-size: 12px; color: var(--ink-2, #666); margin-bottom: 2px; }
.bb-tax-row {
  display: flex; align-items: center; gap: 8px;
  font-size: 13px; padding: 3px 0;
  border-top: 1px dashed var(--line-2, rgba(0, 0, 0, .06));
}
.bb-tax-row:first-of-type { border-top: none; }
.bb-tax-row .sp { flex: 1; }
.bb-pay-h { font-size: 13px; font-weight: 500; margin: 12px 0 4px; }
.bb-pay-eq { margin-top: 6px; line-height: 1.7; }

.bl-need {
  margin: 10px 0; padding: 10px 12px;
  background: var(--color-background-secondary, #f7f7f8); border-radius: 8px;
}
.bl-need-h { font-size: 14px; font-weight: 500; margin-bottom: 6px; }
.bl-need-row {
  display: flex; align-items: center; gap: 12px;
  padding: 5px 0; border-bottom: 1px dashed var(--color-border-tertiary, rgba(0,0,0,.08));
  font-size: 13px;
}
.bl-need-row:last-child { border-bottom: none; }
.bl-need-row button { margin-left: auto; }

tr.rowlink { cursor: pointer; }
.warn { color: var(--color-text-warning, #b8860b); }
.warnbtn { border-color: var(--color-border-warning, #d9a441); color: var(--color-text-warning, #b8860b); }

/* ══════════════════════════════════════════════════════════════════════════
   对账单明细账（2026-10-15 老板要的一页 + 三个页面的时间维度筛选）
   ══════════════════════════════════════════════════════════════════════════ */

/* 客户列表条：横向排，点了高亮 */
.ld-clist {
  margin: 10px 0; border: 1px solid var(--color-border, #e0e0e0);
  border-radius: 6px; background: var(--color-surface, #fff);
}
.ld-clist-h {
  padding: 8px 12px; font-size: 13px; font-weight: 500;
  border-bottom: 1px solid var(--color-border, #e0e0e0);
  background: var(--color-surface-alt, #fafafa);
}
.ld-clist-b { max-height: 220px; overflow-y: auto; }
.ld-clist-row {
  display: flex; align-items: center; gap: 12px;
  padding: 8px 12px; border-bottom: 1px solid var(--color-border-subtle, #f0f0f0);
  cursor: pointer;
}
.ld-clist-row:last-child { border-bottom: none; }
.ld-clist-row:hover { background: var(--color-surface-hover, #f5f5f5); }
.ld-clist-row.on {
  background: var(--color-primary-light, #e8f0fe);
  box-shadow: inset 3px 0 0 var(--color-primary, #1a73e8);
}
.ld-clist-row .money { margin-left: auto; font-weight: 600; }

/* 头部：客户信息 + 导出 */
.ld-head {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 12px; margin: 14px 0 10px;
}
.ld-head .sub { margin-left: 10px; }

/* 四个数：期初 / 开单 / 回款 / 期末 */
.ld-boxes {
  display: grid; grid-template-columns: repeat(4, 1fr);
  gap: 10px; margin-bottom: 8px;
}
.ld-box {
  padding: 12px 14px; border: 1px solid var(--color-border, #e0e0e0);
  border-radius: 6px; background: var(--color-surface, #fff);
}
.ld-box-k { font-size: 12px; color: var(--color-text-secondary, #777); }
.ld-box-v {
  font-size: 22px; font-weight: 600; line-height: 1.3;
  font-variant-numeric: tabular-nums;
}
.ld-box-t { font-size: 11px; color: var(--color-text-tertiary, #999); }
.ld-box.green .ld-box-v { color: #0a7d3f; }
.ld-box.red   .ld-box-v { color: #c5221f; }
.ld-box.blue  .ld-box-v { color: var(--color-primary, #1a73e8); }

/* 恒等式那行：期初 + 开单 − 回款 = 期末 */
.ld-eq { margin: 0 0 4px; }
.ld-eq .pill { margin-left: 8px; }

/* 分段小标题 */
.ld-sec-h {
  margin: 18px 0 6px; font-size: 14px; font-weight: 600;
  padding-bottom: 5px; border-bottom: 1px solid var(--color-border, #e0e0e0);
}

/* 手机上四个数改两列，别挤成一团 */
@media (max-width: 820px) {
  .ld-boxes { grid-template-columns: repeat(2, 1fr); }
  .ld-box-v { font-size: 19px; }
  .ld-head { flex-direction: column; }
  .ld-head .sub { margin-left: 0; display: block; }
}

/* ══════════════════════════════════════════════════════════════════════════
   挑串码：按推荐顺序分三档（2026-10-15 老板要「让我做选择」）
   —— 后端已排好序，这里只负责「分组显示 + 说清为什么推它」
   ══════════════════════════════════════════════════════════════════════════ */

/* 档位组头：标题 + 为什么推它 + 台数 */
.pk-tier {
  display: flex; align-items: center; gap: 10px;
  padding: 7px 10px; margin: 8px 0 4px;
  background: var(--blue-50, #F2F6FF);
  border-left: 3px solid var(--blue-200, #A9C4F5);
  border-radius: 0 4px 4px 0;
}
.pk-tier:first-child { margin-top: 2px; }
.pk-tier.best {
  background: #E8F5EC;                 /* 首推档用绿色，一眼区分 */
  border-left-color: #1E9E52;
}
.pk-tier-l { font-weight: 600; font-size: 13px; white-space: nowrap; }
.pk-tier-h { font-size: 12px; color: var(--ink-3, #6B7280); flex: 1; }
.pk-tier-n { font-size: 12px; color: var(--ink-3, #6B7280); white-space: nowrap; }

/* 首推档里的机器：左侧加一条绿标，肉眼扫过去就是它 */
.pk-row.best { box-shadow: inset 3px 0 0 #1E9E52; }
.pk-row.best .pk-sn { font-weight: 600; }

@media (max-width: 820px) {
  .pk-tier { flex-wrap: wrap; gap: 2px 8px; }
  .pk-tier-h { flex-basis: 100%; }     /* 手机上原因另起一行，别挤成两行 */
}

/* ══════════════════════════════════════════════════════════════════════════
   挑串码：按推荐顺序分三档（2026-10-15 老板要「让我做选择」）
   —— 后端已排好序，这里只负责「分组显示 + 说清为什么推它」
   ══════════════════════════════════════════════════════════════════════════ */

/* 档位组头：标题 + 为什么推它 + 台数 */
.pk-tier {
  display: flex; align-items: center; gap: 10px;
  padding: 7px 10px; margin: 8px 0 4px;
  background: var(--blue-50, #F2F6FF);
  border-left: 3px solid var(--blue-200, #A9C4F5);
  border-radius: 0 4px 4px 0;
}
.pk-tier:first-child { margin-top: 2px; }
.pk-tier.best {
  background: #E8F5EC;                 /* 首推档用绿色，一眼区分 */
  border-left-color: #1E9E52;
}
.pk-tier-l { font-weight: 600; font-size: 13px; white-space: nowrap; }
.pk-tier-h { font-size: 12px; color: var(--ink-3, #6B7280); flex: 1; }
.pk-tier-n { font-size: 12px; color: var(--ink-3, #6B7280); white-space: nowrap; }

/* 首推档里的机器：左侧加一条绿标，肉眼扫过去就是它 */
.pk-row.best { box-shadow: inset 3px 0 0 #1E9E52; }
.pk-row.best .pk-sn { font-weight: 600; }

@media (max-width: 820px) {
  .pk-tier { flex-wrap: wrap; gap: 2px 8px; }
  .pk-tier-h { flex-basis: 100%; }     /* 手机上原因另起一行，别挤成两行 */
}

/* ══════════════════════════════════════════════════════════════════════════
   串码流水明细（2026-10-15 老板：退货看不见 + 要数量列与两种毛利）
   ══════════════════════════════════════════════════════════════════════════ */

/* 顶部合计条：五个数打头，一眼对出这段时间卖了多少、赚了多少 */
.fl-sum {
  display: flex; flex-wrap: wrap; gap: 8px 26px;
  padding: 10px 14px; margin: 8px 0 10px;
  border: 1px solid var(--color-border, #e0e0e0);
  border-radius: 6px; background: var(--color-surface-alt, #fafafa);
}
.fl-sum > div { display: flex; align-items: baseline; gap: 6px; }
.fl-sum span { font-size: 12px; color: var(--color-text-secondary, #777); }
.fl-sum b { font-size: 17px; font-variant-numeric: tabular-nums; }

/* 退货行：整行淡红底，一眼扫到"这台退了" */
tr.fl-back { background: #FDF3F2; }
tr.fl-back:hover { background: #FBE9E7 !important; }
tr.fl-back td { border-bottom-color: #F5D9D6; }

@media (max-width: 820px) {
  .fl-sum { gap: 4px 16px; padding: 8px 10px; }
  .fl-sum b { font-size: 15px; }
}

/* 佣金审批提示（2026-10-15 老板：「业务审批时提示返款还是抵货款」）
   —— 有欠款用 cm-warn（醒目黄/红），不欠款用 cm-tip（平静灰） */
.cm-tip {
  padding: 8px 11px; margin: 8px 0;
  border-left: 3px solid #6B7280; border-radius: 0 4px 4px 0;
  background: #F7F8FA; font-size: 13px; line-height: 1.6;
}
.cm-pay label input[disabled] + *,
.cm-pay label:has(input[disabled]) { opacity: .5; cursor: not-allowed; }

/* 对账单明细里的「串号」列（2026-10-16 老板：「账单要有明细台账。
   不然会对不清楚具体哪一台」）
   —— 串号逐个换行、等宽字体，看着像一列货号而不是一段话 */
.bb-sn {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 11.5px; line-height: 1.75; color: #1f2937;
  word-break: break-all; max-width: 220px;
}
.bb-sn .sub { font-family: inherit; font-size: 11px; }

/* 「上次发出去是 X，现在变成 Y」的黄条 —— 提醒商务重新发一次 */
.st-warn { margin: 8px 0; line-height: 1.7; }

/* 对账单明细里的「串号」列（2026-10-16 老板：「账单要有明细台账。
   不然会对不清楚具体哪一台」）
   —— 串号逐个换行、等宽字体，看着像一列货号而不是一段话 */
.bb-sn {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 11.5px; line-height: 1.75; color: #1f2937;
  word-break: break-all; max-width: 220px;
}
.bb-sn .sub { font-family: inherit; font-size: 11px; }

/* 「上次发出去是 X，现在变成 Y」的黄条 —— 提醒商务重新发一次 */
.st-warn { margin: 8px 0; line-height: 1.7; }

/* ── 2026-10-16 老板要的「补串码阶段可改单」───────────────────────────
 *  · 单号做成链接（成熟做法：点单号跳出来）
 *  · 「正在改这张单」的提示条 —— 要一眼看出在改哪张、别把改的忘了保存
 *  · 载入已有单时的短暂高亮（不然他以为没跳转）
 */
.or-list .or-no,
#or-list a.or-no {
  color: var(--blue, #2563eb);
  cursor: pointer;
  text-decoration: none;
  border-bottom: 1px dashed currentColor;
}
#or-list a.or-no:hover { color: #1d4ed8; }

.or-editbar {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 8px 12px; margin: 8px 0;
  background: #fff8e6; border: 1px solid #f0c36d;
  border-radius: 6px; font-size: 13px;
}
.or-editbar b { color: #8a5a00; }
.or-editbar .sub { color: #8a6d3b; }
.or-editbar .badTxt { color: #b45309; }

.or-editing { animation: orEditFlash 2.2s ease-out; }
@keyframes orEditFlash {
  0%, 30% { background: #fff8e6; box-shadow: 0 0 0 2px #f0c36d inset; }
  100% { background: transparent; box-shadow: none; }
}
@media (prefers-reduced-motion: reduce) {
  .or-editing { animation: none; }
}

/* ── 2026-10-16 老板要的「补串码阶段可改单」───────────────────────────
 *  · 单号做成链接（成熟做法：点单号跳出来）
 *  · 「正在改这张单」的提示条 —— 要一眼看出在改哪张、别把改的忘了保存
 *  · 载入已有单时的短暂高亮（不然他以为没跳转）
 */
.or-list .or-no,
#or-list a.or-no {
  color: var(--blue, #2563eb);
  cursor: pointer;
  text-decoration: none;
  border-bottom: 1px dashed currentColor;
}
#or-list a.or-no:hover { color: #1d4ed8; }

.or-editbar {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 8px 12px; margin: 8px 0;
  background: #fff8e6; border: 1px solid #f0c36d;
  border-radius: 6px; font-size: 13px;
}
.or-editbar b { color: #8a5a00; }
.or-editbar .sub { color: #8a6d3b; }
.or-editbar .badTxt { color: #b45309; }

.or-editing { animation: orEditFlash 2.2s ease-out; }
@keyframes orEditFlash {
  0%, 30% { background: #fff8e6; box-shadow: 0 0 0 2px #f0c36d inset; }
  100% { background: transparent; box-shadow: none; }
}
@media (prefers-reduced-motion: reduce) {
  .or-editing { animation: none; }
}

/* ---- 初始化新账套（2026-10-18）：分档勾选卡片 ----
   为什么自己写而不用 .card：这一页的每张"卡"本身**是可点的**（整块点一下就勾/取消），
   要有明显的「已勾上」态，老板才看得出自己点了哪几档。 */
.ds-grp{display:flex;gap:10px;align-items:flex-start;padding:10px 12px;margin-bottom:8px;
  border:1px solid var(--line);border-radius:var(--r);cursor:pointer;transition:all .12s}
.ds-grp:hover{border-color:var(--ink-3)}
.ds-grp.on{border-color:var(--red);background:var(--red-50)}
.ds-grp input[type=checkbox]{margin-top:2px;flex:none}
/*   ↑ 宽度不在这里设：全局那条 `input[type=checkbox]{width:auto}` 已经管了
     （2026-10-21 修「界面看不到内容」时加的）。这里只管对齐和不许被压缩。 */

/* ---- 预售看板（2026-10-18 22:05）----
   为什么自己写：老板要的是「一眼看到 哪里有货 / 卖了多少 / 还剩几台」，
   三个数必须**并排**，不能塞进通用表格的三列（那样每行要横着扫很远）。 */
.bs-wrap{display:flex;flex-wrap:wrap;gap:8px}
.bs-city{border:1px solid var(--line);border-radius:10px;padding:6px 10px;
  min-width:190px;background:#FAFBFC}
.bs-city>b{font-size:13.5px}
.bs-city .sub{font-size:12px;margin-left:6px}
.bs-num{display:flex;gap:10px;margin-top:3px;font-size:12.5px;color:var(--ink2)}
.bs-num b{font-size:14px;color:var(--ink)}
.bs-num .goodTxt b{color:var(--green800)}
.bs-num .badTxt b{color:var(--red800)}

/* ---- 预售看板（2026-10-18 22:05）----
   为什么自己写：老板要的是「一眼看到 哪里有货 / 卖了多少 / 还剩几台」，
   三个数必须**并排**，不能塞进通用表格的三列（那样每行要横着扫很远）。 */
.bs-wrap{display:flex;flex-wrap:wrap;gap:8px}
.bs-city{border:1px solid var(--line);border-radius:10px;padding:6px 10px;
  min-width:190px;background:#FAFBFC}
.bs-city>b{font-size:13.5px}
.bs-city .sub{font-size:12px;margin-left:6px}
.bs-num{display:flex;gap:10px;margin-top:3px;font-size:12.5px;color:var(--ink2)}
.bs-num b{font-size:14px;color:var(--ink)}
.bs-num .goodTxt b{color:var(--green800)}
.bs-num .badTxt b{color:var(--red800)}

/* ---- 预售机型范围（2026-10-19 老板：「可以选择机型，然后去做预售的形式」）
   为什么单独写：这个页面的核心动作是「勾」，被勾的行必须**一眼能挑出来**，
   否则 176 行里勾了哪几个，老板自己都找不着。
   ⚠️ 只用 `--blue` / `--green-50` / `--card` 这些**本文件真实存在**的变量
      （我第一版凭印象写了 `--blue600` / `--green100` / `--bg2`，
      全都不存在 ⇒ 颜色静默失效，看着「没样式」又查不出原因）。 */
.sc-tip{border:1px solid var(--line);border-left:3px solid var(--blue);
  border-radius:8px;padding:8px 12px;margin-bottom:10px;font-size:13px;
  background:var(--card);line-height:1.7}
.sc-tip.warn{border-left-color:var(--amber);background:var(--amber-50)}
.sc-on{background:var(--green-50)}
.sc-badge{display:inline-block;margin-left:8px;padding:1px 7px;border-radius:9px;
  font-size:11.5px;background:var(--blue-50);color:var(--blue)}

/* ---- 预售页头部分块 / 建单卡片（2026-10-19 11:21 老板报的四条一起修） ----
   ★ 老板 ①：「预售库/看板/预售单/定金明细/预售机型是单独的 5 个小板块……
     这个（同步/登记货源）就不能和上面 5 个小板块并排放着，让人看不清楚」
   ⇒ `.ps-tabs` 只放板块、`.ps-acts` 只放当前板块的操作，**物理分行**。 */

/* ---- ④ 手机开单界面：机型/价格看不清 ⇒ 竖着排、大字号 ----
   原来一行 7 个输入框横排，窄屏下每列被压到只剩一个下拉箭头。
   ⇒ 每行一个卡片：型号一整行、台数/价格各占一半宽、字号 16px。 */
.pn-tabs,.ps-tabs{gap:6px;margin-bottom:2px}
.ps-acts{padding-top:2px;margin-top:-4px}
/* 大号输入（手机上够大才好按；★ 别用 px 猜，14px 在 375 宽屏上就是难点） */
.pn-big{font-size:16px;padding:10px 12px;min-height:42px}
.pn-ro{background:var(--line-2);color:var(--ink-2)}
.pn-row{border:1px solid var(--line);border-radius:var(--r);
  padding:10px;margin-bottom:10px;background:var(--card)}
.pn-row-hd{display:flex;align-items:center;gap:8px;margin-bottom:6px}
.pn-sku{flex:1;text-align:left;border:1px solid var(--line);border-radius:8px;
  background:var(--bg);padding:8px 10px;cursor:pointer;min-width:0}
.pn-sku:hover{border-color:var(--blue)}
.pn-sku-lbl{display:block;font-size:11.5px;color:var(--ink-3);margin-bottom:2px}
.pn-sku b{display:block;font-size:14px;line-height:1.45;word-break:break-all}
.pn-stock{display:flex;flex-wrap:wrap;gap:6px;font-size:12px;margin-bottom:8px}
.pn-stock span{padding:2px 8px;border-radius:9px;background:var(--line-2);color:var(--ink-2)}
.pn-stock .pn-here{background:var(--blue-50);color:var(--blue);font-weight:500}
.pn-stock .pn-none{color:var(--ink-3)}
.pn-stock .pn-warn{background:var(--amber-50);color:var(--amber)}
.pn-line{display:flex;gap:8px;margin-bottom:8px}
.pn-f{flex:1;min-width:0;display:flex;flex-direction:column;gap:3px}
.pn-f>span{font-size:11.5px;color:var(--ink-3)}
.pn-store{margin-top:2px}
.pn-citytip{border-left:3px solid var(--blue);background:var(--card);
  padding:6px 10px;border-radius:8px;font-size:12.5px;margin:0 0 8px;line-height:1.7}
/* 机型选择：底部大卡片，窄屏一列、宽屏两列
   ⚠️ `#pn-pick` 是**装在 `#imodal-body` 里面**的（openSkuPicker 写进去的），
     不是盖在最外层 ⇒ 定位用 `position:sticky/absolute` 都不行，
     直接当**普通的块**排版即可（它已经在弹层里了，视觉上就是弹层里的内容）。 */
#pn-pick{display:flex;flex-direction:column;min-height:0}
#pn-pick .pn-pick-list{max-height:56vh}
.pn-pick-list{overflow:auto;padding:8px 2px;
  display:grid;grid-template-columns:1fr;gap:8px;margin-top:8px}
.pn-card{text-align:left;border:1px solid var(--line);border-radius:10px;
  background:var(--card);padding:10px 12px;cursor:pointer}
.pn-card:hover{border-color:var(--blue);background:var(--blue-50)}
.pn-card-n{font-size:14px;font-weight:500;line-height:1.5;word-break:break-all}
.pn-card-s{display:flex;flex-wrap:wrap;gap:6px;margin-top:5px;font-size:12px;color:var(--ink-2)}
.pn-card-s span{padding:1px 7px;border-radius:9px;background:var(--line-2)}
@media (min-width:560px){.pn-pick-list{grid-template-columns:1fr 1fr}}

/* ---- 预售单明细：改门店 + 付款截图（老板 2026-10-19 12:12） ----
   ★ 变量只用本文件真实存在的（--line-2 / --blue / --blue-50 / --amber-50 / --green-50），
     写不存在的会**静默失效**（我今天已经栽过一次 --bg2）。 */

/* 「补充选择门店」窗口里的候选门店 */
.pd-list{display:flex;flex-direction:column;gap:8px;margin-top:8px}
.pd-opt{text-align:left;border:1px solid var(--line);border-radius:10px;
  background:var(--card);padding:10px 12px;cursor:pointer}
.pd-opt:hover{border-color:var(--blue);background:var(--blue-50)}
.pd-opt.is-here{border-color:var(--blue)}
.pd-opt-n{font-size:14px;font-weight:500;display:flex;align-items:center;
  gap:8px;flex-wrap:wrap;line-height:1.5}
.pd-opt-c{font-size:11.5px;font-weight:400;padding:1px 7px;border-radius:9px;
  background:var(--blue-50);color:var(--blue)}
.pd-badge{font-size:11.5px;font-weight:400;padding:1px 7px;border-radius:9px;
  background:var(--green-50);color:var(--green)}
.pd-opt-l{font-size:12.5px;color:var(--ink-2);margin-top:4px}
.pd-opt-l small{color:var(--amber);font-size:11.5px}

/* 付款截图：缩略图横排 + 上传按钮 */
.pd-shots{display:flex;flex-wrap:wrap;gap:10px;align-items:flex-start}
.pd-shot{width:112px;font-size:11.5px;color:var(--ink-2)}
.pd-shot img{width:112px;height:78px;object-fit:cover;border-radius:8px;
  border:1px solid var(--line);display:block;background:var(--line-2)}
.pd-shot .sub{margin-top:3px;line-height:1.5}
.pd-up{cursor:pointer}
.pd-up .btn{white-space:nowrap}
