*{margin:0;padding:0;box-sizing:border-box}
body{font-family:'Microsoft YaHei','PingFang SC','Segoe UI',sans-serif;background:#f0f2f5;color:#333;font-size:14px}
:root{--primary:#1677ff;--gold:#c9942a;--gold-light:#f0c060;--success:#52c41a;--warning:#faad14;--danger:#ff4d4f;--border:#d9d9d9;--bg:#fff;--sidebar-w:220px}

/* 布局 */
#app{display:flex;height:100vh;overflow:hidden}
.sidebar{width:var(--sidebar-w);background:linear-gradient(180deg,#001529,#002b4d);color:#fff;display:flex;flex-direction:column;flex-shrink:0;overflow-y:auto}
.sidebar-logo{padding:20px 16px;font-size:16px;font-weight:700;border-bottom:1px solid rgba(255,255,255,.1);display:flex;align-items:center;gap:8px}
.sidebar-logo span{font-size:22px}
.sidebar-logo .logo-text{color:#f0c060;letter-spacing:1px}
.nav-group{padding:6px 0}
.nav-title{padding:9px 16px;font-size:12px;color:rgba(255,255,255,.45);text-transform:uppercase;letter-spacing:1px;cursor:pointer;user-select:none;display:flex;align-items:center;justify-content:space-between}
.nav-title::after{content:'▾';font-size:10px;margin-left:auto;padding-left:8px;transition:transform .2s;opacity:.7}
.nav-title:hover{color:rgba(255,255,255,.85)}
.nav-group.collapsed .nav-title::after{transform:rotate(-90deg)}
.nav-group.collapsed .nav-item{display:none}
.nav-item{padding:10px 16px 10px 32px;cursor:pointer;display:flex;align-items:center;gap:8px;transition:.2s;font-size:13px;color:rgba(255,255,255,.75)}
.nav-item:hover{background:rgba(255,255,255,.08);color:#fff}
.nav-item.active{background:var(--primary);color:#fff}
.nav-item .icon{width:16px;text-align:center;flex-shrink:0}
.main{flex:1;display:flex;flex-direction:column;overflow:hidden}
.topbar{background:#fff;padding:0 20px;height:48px;display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid var(--border);flex-shrink:0}
.topbar-left{display:flex;align-items:center;gap:10px}
.topbar-title{font-size:16px;font-weight:600;color:#333}
.topbar-info{font-size:12px;color:#888}

/* ── v1.2.226 短信余量提醒（顶栏常驻）──────────────────────────
   为什么顶栏要放一个"红色"状态：短信用完会让验证码登录与领料核销**同时失效**，
   而这两个都是"临时要用"的功能 —— 等用户发不出去再发现，已经晚了。
   阈值分三档（而不是只有"有/无"）：
     · 正常   灰色，20 条以内 → 提醒但不刺眼
     · 偏少   橙色，1~20 条
     · 告急   红色，0 条
   ⚠️ 「不限量」（平台端没分配额度）**不显示任何徽标** —— 显示"剩 0 条"
      会让运营以为系统坏了（与第��三条「0 是合法值」同源）。 */
.sms-quota-bar{display:inline-flex;align-items:center;gap:4px;font-size:12px;
  padding:3px 9px;border-radius:11px;background:#f5f5f5;color:#888;white-space:nowrap;cursor:default}
.sms-quota-bar.warn{background:#fff3e0;color:#e67e22}
.sms-quota-bar.danger{background:#fdecea;color:#c0392b;font-weight:600}
.topbar-right{display:flex;align-items:center;gap:16px}
.topbar-user{display:flex;align-items:center;gap:10px}
.topbar-user .uname{font-size:13px;font-weight:600;color:#333}
.topbar-user .urole{font-size:12px;background:#e6f7ff;color:#0958d9;padding:2px 8px;border-radius:10px}
.logout-btn{font-size:12px;color:#999;cursor:pointer;border-left:1px solid #eee;padding-left:10px}
.logout-btn:hover{color:var(--danger)}
.menu-toggle{display:none;background:none;border:none;font-size:18px;cursor:pointer;color:#333}
.content{flex:1;overflow-y:auto;padding:20px}

/* 软件到期提醒：顶部常驻横幅 + 登录弹窗 */
.renew-banner{display:flex;align-items:center;gap:8px;padding:9px 20px;font-size:13px;background:#fff7e6;color:#ad6800;border-bottom:1px solid #ffe0a3;flex-shrink:0}
.renew-banner.urgent{background:#fff1f0;color:#cf1322;border-bottom-color:#ffccc7}
.renew-banner .rb-ico{font-size:15px}
.renew-banner .rb-txt{font-weight:600}
.renew-body{text-align:center;padding:4px 0 2px}
.renew-days{display:flex;align-items:flex-end;justify-content:center;gap:6px;color:#d48806;margin-bottom:10px}
.renew-days b{font-size:44px;line-height:1;font-weight:800;letter-spacing:-1px}
.renew-days span{font-size:13px;padding-bottom:5px}
.renew-p{font-size:14px;color:#333;line-height:1.7;margin:0 0 8px}
.renew-sub{font-size:12px;color:#999;margin:0;line-height:1.6}

/* 语言切换 */
.lang-select{position:relative;display:inline-flex;align-items:center}
.lang-select select{padding:5px 8px;border:1px solid #d9d9d9;border-radius:6px;font-size:12px;background:#fff;cursor:pointer;outline:none}
.lang-select select:hover{border-color:var(--primary)}
.lang-select .globe{font-size:14px;margin-right:4px}

/* 卡片 */
.card{background:#fff;border-radius:8px;padding:20px;margin-bottom:16px;box-shadow:0 1px 4px rgba(0,0,0,.08)}
.card-title{font-size:15px;font-weight:600;margin-bottom:16px;color:#333;display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.card-title::before{content:'';width:3px;height:16px;background:var(--primary);border-radius:2px;display:inline-block}
.card-title .spacer{flex:1}
.card-tools{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.card-sub{font-size:12px;color:#999;font-weight:400;margin-left:4px}

/* 统计卡片 */
.stat-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;margin-bottom:16px}
/* v1.2.270 首次使用提示横幅：金色玻璃底 + 引导按钮，紧贴工作台顶部 */
.first-use-banner{display:flex;align-items:center;gap:10px;margin:0 0 14px;padding:12px 16px;border:1px solid rgba(201,148,42,.35);border-radius:12px;background:linear-gradient(135deg,rgba(251,234,160,.28),rgba(224,189,85,.16));font-size:14px;color:#7a5a10}
.first-use-banner .fu-icon{font-size:18px}
.first-use-banner .fu-text{flex:1;line-height:1.5}
/* 报表页 6 卡布局：PC 端 6 列一行；移动端由媒体查询降级为 3/2/1 列，避免挤压变形 */
.stat-grid-6{grid-template-columns:repeat(6,1fr)}
/* 工作台 5 卡布局（存料欠料 / 存款欠款拆分后）：PC 端 5 列一行 */
.stat-grid-5{grid-template-columns:repeat(5,1fr)}
.stat-grid-3{grid-template-columns:repeat(3,1fr)}
.stat-card{background:#fff;border-radius:8px;padding:20px;box-shadow:0 1px 4px rgba(0,0,0,.08);position:relative;overflow:hidden;cursor:pointer;transition:.2s}
.stat-card:hover{transform:translateY(-2px);box-shadow:0 4px 12px rgba(0,0,0,.12)}
.stat-card::after{content:'';position:absolute;right:-10px;top:-10px;width:80px;height:80px;border-radius:50%;opacity:.08}
.stat-card.blue::after{background:var(--primary)}.stat-card.gold::after{background:var(--gold)}.stat-card.green::after{background:var(--success)}.stat-card.orange::after{background:var(--warning)}.stat-card.red::after{background:var(--danger)}
.stat-label{font-size:13px;color:#888;margin-bottom:8px}
.stat-value{font-size:26px;font-weight:700;color:#333}
.stat-value.wf{font-size:19px}
.stat-value.gold{color:var(--gold)}
.stat-sub{font-size:12px;color:#aaa;margin-top:4px}
/* 工作台存欠卡：存/欠两行等大字号布局 */
.stat-duo{display:flex;flex-direction:column;gap:5px;margin-top:2px}
.stat-duo .row{display:flex;justify-content:flex-start;align-items:baseline;font-size:17px;font-weight:600;color:#333;line-height:1.3}
.stat-duo .row .lbl{font-size:13px;font-weight:400;color:#888;margin-right:8px;flex-shrink:0}
.stat-duo .row.neg span:last-child{color:#e02020}
.stat-icon{position:absolute;right:16px;top:16px;font-size:28px;opacity:.25}

/* 表格 */
.table-wrap{overflow-x:auto}
table{width:100%;border-collapse:collapse}
th,td{padding:10px 12px;text-align:left;border-bottom:1px solid #f0f0f0;white-space:nowrap}
th{background:#fafafa;font-weight:600;color:#666;font-size:13px}
tr:hover td{background:#fafffe}
td .num{font-variant-numeric:tabular-nums}
/* v2.3.26：表格里数字列右对齐。CSS 里原本只有 `td .num`（后代选择器），
   `<td class="num">` 本身没有被右对齐 → 表头右对齐、数字贴左边，看上去"标题和数据错位"。*/
td.numr{text-align:right;font-variant-numeric:tabular-nums}
.badge{display:inline-block;padding:2px 8px;border-radius:10px;font-size:12px;font-weight:500}
.badge-0{background:#fff7e6;color:#d46b08}.badge-1{background:#e6f7ff;color:#0958d9}.badge-2{background:#f6ffed;color:#389e0d}.badge-3{background:#f0f9ff;color:#1890ff}.badge-4{background:#f5f5f5;color:#666}.badge-warn{background:#fff7e6;color:#d46b08;cursor:pointer}
.badge-danger{background:#fff1f0;color:#cf1322}.badge-gold{background:#fff7e6;color:#c9942a}
.text-danger{color:#ff4d4f}.text-success{color:#52c41a}.text-warning{color:#faad14}.text-primary{color:#1677ff}.text-muted{color:#999}

/* 按钮 */
.btn{display:inline-flex;align-items:center;gap:4px;padding:6px 14px;border-radius:6px;border:1px solid var(--border);background:#fff;cursor:pointer;font-size:13px;transition:.2s;line-height:1;color:#333}
.btn:hover{border-color:var(--primary);color:var(--primary)}
.btn-primary{background:var(--primary);color:#fff;border-color:var(--primary)}.btn-primary:hover{background:#4096ff;border-color:#4096ff;color:#fff}
.btn-success{background:var(--success);color:#fff;border-color:var(--success)}.btn-success:hover{background:#73d13d;border-color:#73d13d;color:#fff}
.btn-warning{background:var(--warning);color:#fff;border-color:var(--warning)}.btn-warning:hover{background:#ffc53d;border-color:#ffc53d;color:#fff}
.btn-danger{background:var(--danger);color:#fff;border-color:var(--danger)}.btn-danger:hover{background:#ff7875;border-color:#ff7875;color:#fff}
.btn-gold{background:var(--gold);color:#fff;border-color:var(--gold)}.btn-gold:hover{background:#e0a92f;border-color:#e0a92f;color:#fff}
.btn-sm{padding:3px 8px;font-size:12px}
.btn-link{border:none;background:none;color:var(--primary);cursor:pointer;padding:2px 4px;font-size:12px}
.btn-link:hover{text-decoration:underline}
.btn-link.danger{color:var(--danger)}
/* ── v1.2.147 实时对账：可点的存欠数字 ────────────────────────────────────
   用户要求「点击存欠料、存欠款数字可跳转查看对应的流水明细」。
   数字本身要**一眼看得出能点**，但又不能抢走「欠/存」的红绿语义 ——
   所以只加虚线下划线 + hover 变色，字号沿用表格数字，不改视觉层级。 */
.num-link{font-size:inherit;font-weight:600;text-decoration:underline dotted;text-underline-offset:3px}
.num-link:hover{text-decoration:underline solid}
/* 从实时对账点进来时，被定位到的那一段短暂高亮一下，提示"你点的就是这个" */
.recon-focus{background:#fff8e1;border-radius:4px;padding:2px 6px;transition:background .4s}
/* ── v1.2.147 默认商品 ────────────────────────────────────────────────────
   「一个系统有且只有一个默认商品」是硬约束，所以要把当前默认放在页面顶部常驻可见，
   颜色用琥珀金（和 ★ 呼应），不用红色 —— 它不是错误状态，只是一个「当前选中项」。 */
.default-goods-bar{margin:0 0 10px;padding:10px 14px;border:1px solid #f5e2b0;border-left:3px solid #f0b429;
  background:#fffcf3;border-radius:8px;font-size:13px;line-height:1.5}
.default-goods-bar .dg-name{color:#b8860b;font-weight:700}
.default-goods-bar .dg-hint{margin-top:4px;color:#999;font-size:12px}
/* 默认商品所在行高亮一眼：只加左侧色条 + 极浅底色，不抢表格数字的注意力 */
tr.row-default{background:#fffdf5}
tr.row-default td:first-child{box-shadow:inset 3px 0 0 #f0b429}
.dg-star{color:#f0b429;font-size:15px;vertical-align:middle}
/* v1.2.207 商品档案「计算方式=按件」标记。
   「按重」是默认档、不加标签（满屏都是标签反而看不出重点）；
   只给「按件」加一个醒目的标记 —— 它是需要用户留意的那一档。 */
.tag-piece{display:inline-block;padding:1px 7px;border-radius:9px;background:#fff4e0;color:#b7791f;border:1px solid #f5d9a8;font-size:12px;white-space:nowrap}
/* ── v1.2.138 反操作按钮与弹窗 ────────────────────────────────────────────
   反入库/撤销结价这类「危险但正当」的动作用橙黄色（--warning）而非红色：
   红色（--danger）在本项目里已专用于「作废/删除」这类不可逆动作，
   反操作之后单据还在、只是退回「已审核」，用红色会让人误以为点下去就毁了。 */
.btn-link.warn{color:var(--warning)}
.btn-link.warn:hover{text-decoration:underline}
/* 弹窗里的选项行：单选/复选的整行都可点，比只点小圆点好按 */
.rv-opt{display:flex;align-items:flex-start;gap:8px;padding:7px 6px;margin:2px 0;border-radius:4px;cursor:pointer;font-size:13px;line-height:1.6;color:#333}
.rv-opt:hover{background:#f7f9fc}
.rv-opt.sub{margin-left:22px;font-size:12px;color:#666;padding:5px 6px}
.rv-opt input{margin:2px 0 0;flex:0 0 auto}
/* 未勾「我已知悉」时确认按钮置灰 —— 前端防呆，服务端还会独立再校验一道 */
#rv-ok[disabled]{opacity:.45;cursor:not-allowed}

/* 表单 */
.form-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:12px 20px}
.form-grid-2{display:grid;grid-template-columns:repeat(2,1fr);gap:12px 20px}
/* v1.2.131：收付款的「关联单据」下拉要整行宽度 ——
   .form-grid 是 3 列 grid，不处理的话这个下拉只占 1 格（约 250px），
   而选项文案形如「[定价不提料] DJ20261007-003  ¥89,700.00  应付余额」（40+ 字符）会被截断，
   根本认不出是哪张单。跨列 1/-1 让它占满整行，与其它单据字段的可用宽度一致。
   移动端 .form-grid 本就是单列（见 @media），grid-column 不影响，无需额外处理。 */
.form-grid .form-row-wide{grid-column:1/-1;min-width:0}
.form-grid .form-row-wide select{width:100%}
.form-row{display:flex;flex-direction:column;gap:4px}
.form-row label{font-size:13px;color:#555;font-weight:600}
.form-row label .req{color:#ff4d4f;margin-left:2px}
.form-row input,.form-row select,.form-row textarea{width:100%;padding:8px 10px;border:1px solid #d9d9d9;border-radius:6px;font-size:13px;outline:none;transition:.2s;background:#fff}
.form-row input:focus,.form-row select:focus,.form-row textarea:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(22,119,255,.12)}
/* 金额框输入负数时的错误提示（红框） */
.form-row input.inp-err{border-color:#e02020;box-shadow:0 0 0 2px rgba(224,32,32,.15)}
.form-row textarea{resize:vertical;min-height:60px}
/* 证照信息分区标题 + 图片上传预览（往来单位营业执照/身份证） */
.form-sec-title{margin:14px 0 8px;padding-top:12px;border-top:1px dashed #e5e5e5;font-size:13px;font-weight:700;color:#333}
.form-row input[type=file]{padding:6px}
.pimg-prev{margin-top:6px;display:flex;gap:8px;flex-wrap:wrap}
.pimg-prev img{max-width:180px;max-height:120px;border:1px solid #e3d9c8;border-radius:8px;object-fit:cover;background:#fafafa}
/* 多卡收付款明细（收料/出料/换料结算） */
.pay-lines-wrap{width:100%}
.pay-lines{display:flex;flex-direction:column;gap:6px;margin-bottom:8px}
.pay-line{display:flex;gap:8px;align-items:center}
.pay-line .pl-bank{flex:1;min-width:0}
.pay-line .pl-acc{flex:1.3;min-width:0}
.pay-line .pl-amt{width:110px;flex-shrink:0}
.pay-line .pl-del{flex-shrink:0;width:32px;padding:4px 0;text-align:center;font-size:16px;line-height:1;color:#cf1322}
.pay-line-head{display:flex;gap:8px;align-items:center;font-size:12px;color:#888;font-weight:600;margin-bottom:4px;padding:0 2px}
.pay-line-head .h-bank{flex:1}
.pay-line-head .h-acc{flex:1.3}
.pay-line-head .h-amt{width:110px;flex-shrink:0;text-align:right}
.pay-line-head .h-del{width:32px;flex-shrink:0}
.pay-sum-row{text-align:right;font-size:13px;color:#555;margin-top:4px}
.pay-sum-row .pay-sum{font-size:15px}
.form-row .hint{font-size:12px;color:#999;font-weight:400}

/* 搜索栏 */
.filter-bar{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-bottom:16px}
.filter-bar input,.filter-bar select{padding:7px 10px;border:1px solid #d9d9d9;border-radius:6px;font-size:13px;outline:none;min-width:140px}
.filter-bar input:focus,.filter-bar select:focus{border-color:var(--primary)}

/* AI 助手栏（仅移动端显示，桌面端隐藏） */
/* v1.2.154：原来这里是 display:none（只在 ≤640px 的媒体查询里才 display:flex），
   结果**桌面端反而看不到 AI 输入条、只有手机上有** —— 与预期完全相反。
   现改为默认 display:flex，桌面/移动都可见，移动端在媒体查询里堆叠得更紧凑。 */
.ai-bar{display:flex;align-items:center;gap:10px;background:linear-gradient(135deg,#eef4ff,#f6f9ff);border:1px solid #c8d8f8;border-radius:10px;padding:12px 14px;margin-bottom:14px;flex-wrap:wrap}
.ai-bar .ai-ico{font-size:22px;flex-shrink:0}
/* v1.2.154：输入框字号 16px —— iOS Safari 对 <16px 的输入框会在聚焦时自动放大页面，
   导致移动端输入指令时整个页面被撑大、输入框被顶出可视区。 */
.ai-input{flex:1;min-width:220px;padding:10px 14px;border:1px solid #adc6ff;border-radius:8px;font-size:16px;outline:none;background:#fff}
.ai-input:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(22,119,255,.12)}
.ai-bar .btn{padding:10px 20px;font-size:14px}
.ai-model{max-width:190px;padding:9px 10px;border:1px solid #adc6ff;border-radius:8px;font-size:13px;background:#fff;color:#334;outline:none;cursor:pointer}
.ai-model:focus{border-color:var(--primary)}
.ai-bar .btn:disabled{opacity:.6;cursor:not-allowed}
.ai-tip{flex-basis:100%;font-size:12px;color:#7b8aa6;line-height:1.6}
/* v1.2.154：示例短语（点击填入输入框）——移动端少打字的关键 */
.ai-chips{flex-basis:100%;display:flex;flex-wrap:wrap;gap:6px}
.ai-chip{padding:5px 11px;border:1px solid #bcd2f8;border-radius:14px;background:#fff;color:#3a6ea5;
  font-size:12px;cursor:pointer;line-height:1.5;white-space:nowrap;transition:all .15s}
.ai-chip:hover{background:#eaf1ff;border-color:var(--primary);color:var(--primary)}
.ai-chip:active{transform:scale(.97)}
.ai-status{flex-basis:100%;display:flex;align-items:center;gap:8px;font-size:13px;color:#1677ff;font-weight:500}
.ai-status[hidden]{display:none}
.ai-spin{width:14px;height:14px;border:2px solid #c8d8f8;border-top-color:#1677ff;border-radius:50%;animation:aiSpin .7s linear infinite;flex-shrink:0}
@keyframes aiSpin{to{transform:rotate(360deg)}}
.ai-draft-hint{margin:0 0 10px;padding:8px 12px;background:#fff7e6;border:1px solid #ffe0a3;border-radius:8px;font-size:13px;color:#ad6800;line-height:1.6}
.ai-pick-opt{background:#fff;border:1px solid #d9d9d9;color:#333;border-radius:8px;padding:10px 14px;font-size:14px;cursor:pointer}
.ai-pick-opt:hover{border-color:var(--primary);color:var(--primary);background:#f0f5ff}
.ai-pick-none{background:none;border:none;color:#999;font-size:13px;cursor:pointer}
.ai-pick-none:hover{color:#333}

/* 扫码 */
.scan-box{display:flex;align-items:center;gap:8px;background:linear-gradient(135deg,#fffbe6,#fff7e6);border:1px solid #ffe58f;border-radius:8px;padding:10px 14px;margin-bottom:12px}
.scan-box input{flex:1;padding:9px 12px;border:1px solid #ffd666;border-radius:6px;font-size:14px;outline:none;letter-spacing:.5px}
.scan-box input:focus{border-color:var(--gold);box-shadow:0 0 0 2px rgba(201,148,42,.15)}
.scan-box .scan-ico{font-size:20px}
.scan-result{font-size:13px;padding:8px 12px;border-radius:6px;margin-bottom:10px}
.scan-result.ok{background:#f6ffed;color:#389e0d;border:1px solid #b7eb8f}
.scan-result.err{background:#fff1f0;color:#cf1322;border:1px solid #ffa39e}
.bc-chip{display:inline-flex;align-items:center;gap:4px;background:#f0f5ff;color:#0958d9;border:1px solid #adc6ff;border-radius:4px;padding:1px 6px;font-size:12px;margin:1px 2px;font-family:monospace}

/* 弹窗 */
.modal-mask{position:fixed;inset:0;background:rgba(0,0,0,.45);z-index:9990;display:flex;align-items:center;justify-content:center;padding:20px}
.modal{background:#fff;border-radius:10px;width:96%;max-width:860px;max-height:92vh;display:flex;flex-direction:column;box-shadow:0 20px 60px rgba(0,0,0,.3);animation:pop .18s ease}
.modal.sm{max-width:520px}.modal.lg{max-width:1080px}
@keyframes pop{from{transform:scale(.96);opacity:0}to{transform:scale(1);opacity:1}}
.modal-head{display:flex;align-items:center;justify-content:space-between;padding:16px 20px;border-bottom:1px solid #f0f0f0}
.modal-head h3{font-size:16px;font-weight:600}
.modal-close{border:none;background:none;font-size:20px;color:#999;cursor:pointer;line-height:1}
.modal-close:hover{color:#333}
.modal-body{padding:20px;overflow-y:auto;flex:1}
.modal-foot{padding:14px 20px;border-top:1px solid #f0f0f0;display:flex;justify-content:flex-end;gap:10px}

/* ===== 登录（v1.2.246「暗夜鎏金」视觉升级）=====
   设计语言：深空藏青极光背景 + 鎏金玻璃拟态卡片。
   契约保持不变：#login-overlay 的 .hidden 显隐、.login-tab.active、#login-err 文案
   均由 app.js 控制；文案全部来自 i18n 既有键，本块不新增任何 DOM/键。 */
/* v2.0.64【需求 2】padding 底部留出页脚（站点信息）的高度，避免窄屏下内容压到页脚上 */
#login-overlay{position:fixed;inset:0;z-index:10000;display:flex;align-items:center;justify-content:center;overflow:auto;padding:24px 0 74px;
  background:
    radial-gradient(1100px 760px at 10% -12%, rgba(201,148,42,.17), transparent 60%),
    radial-gradient(980px 720px at 108% 112%, rgba(22,86,190,.30), transparent 55%),
    linear-gradient(160deg,#060a18 0%,#0a1230 48%,#070d22 100%)}
#login-overlay::before{content:'';position:absolute;inset:-25%;pointer-events:none;
  background:
    repeating-linear-gradient(90deg, rgba(212,175,55,.055) 0 1px, transparent 1px 76px),
    repeating-linear-gradient(0deg, rgba(212,175,55,.055) 0 1px, transparent 1px 76px);
  -webkit-mask-image:radial-gradient(closest-side at 50% 46%, #000 28%, transparent 76%);
  mask-image:radial-gradient(closest-side at 50% 46%, #000 28%, transparent 76%);
  animation:loginGridDrift 26s linear infinite}
@keyframes loginGridDrift{from{transform:translate3d(0,0,0)}to{transform:translate3d(76px,76px,0)}}
#login-overlay::after{content:'';position:absolute;left:30%;top:52%;width:620px;height:620px;margin:-310px 0 0 -310px;pointer-events:none;
  background:radial-gradient(closest-side, rgba(245,215,110,.10), transparent 70%);
  animation:loginGlowPulse 7s ease-in-out infinite}
@keyframes loginGlowPulse{0%,100%{transform:scale(1);opacity:.75}50%{transform:scale(1.14);opacity:1}}
#login-overlay.hidden{display:none}
/* v2.0.62【需求 4】登录页左右分栏：左宣传图+宣传语、右登录框。
   窄屏（≤900px）由下方媒体查询改为上下单列，宣传区折叠为简洁横幅。 */
.login-split{position:relative;z-index:2;display:flex;align-items:stretch;gap:0;
  width:min(960px,94vw);border-radius:20px;overflow:hidden;
  box-shadow:0 32px 90px rgba(0,0,0,.55);animation:loginCardIn .55s cubic-bezier(.22,.9,.32,1) both}
.login-promo{position:relative;flex:1 1 46%;min-width:0;display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:22px;padding:52px 40px;text-align:center;
  background:
    radial-gradient(560px 480px at 30% 22%, rgba(245,215,110,.18), transparent 62%),
    linear-gradient(165deg, rgba(28,38,74,.94), rgba(12,18,40,.96));
  border-right:1px solid rgba(212,175,55,.22)}
.login-promo .promo-visual{display:flex;align-items:center;justify-content:center;width:118px;height:118px;border-radius:50%;
  background:radial-gradient(circle at 34% 28%, rgba(251,234,160,.22), rgba(201,148,42,.06) 62%, transparent 72%);
  border:1px solid rgba(212,175,55,.28);
  box-shadow:0 0 0 10px rgba(212,175,55,.05), 0 0 46px rgba(245,215,110,.22)}
.login-promo .promo-coin{font-size:56px;line-height:1;
  filter:drop-shadow(0 6px 14px rgba(0,0,0,.4));animation:promoFloat 5.5s ease-in-out infinite}
@keyframes promoFloat{0%,100%{transform:translateY(0)}50%{transform:translateY(-9px)}}
.login-promo .promo-slogan{font-size:22px;font-weight:800;line-height:1.7;letter-spacing:2px;max-width:15em;
  background:linear-gradient(180deg,#fdf3d0,#e9c766 55%,#c9942a);
  -webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;
  min-height:1.7em;white-space:pre-line}
.login-box{position:relative;flex:0 0 46%;max-width:46%;width:auto;padding:46px 46px 32px;
  border-radius:0;border:none;
  background:linear-gradient(165deg, rgba(23,31,60,.92), rgba(10,15,34,.96));
  -webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px);
  display:flex;flex-direction:column;justify-content:center}
@keyframes loginCardIn{from{opacity:0;transform:translateY(26px) scale(.97)}to{opacity:1;transform:none}}
.login-logo{text-align:center;margin-bottom:26px}
.login-logo .icon{display:inline-flex;align-items:center;justify-content:center;width:64px;height:64px;font-size:33px;margin-bottom:14px;border-radius:50%;
  background:radial-gradient(circle at 32% 28%, #fbeaa0, #e8bf4e 44%, #b9832a 100%);
  box-shadow:0 0 0 6px rgba(212,175,55,.10), 0 0 34px rgba(245,215,110,.35), 0 6px 16px rgba(0,0,0,.45)}
.login-logo h2{font-size:22px;font-weight:800;letter-spacing:2px;color:#e9c766;
  background:linear-gradient(180deg,#fdf3d0,#e9c766 55%,#c9942a);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent}
.login-logo p{font-size:12px;color:#8d97b2;margin-top:8px;letter-spacing:3px}
.login-logo::after{content:'';display:block;width:130px;height:1px;margin:18px auto 0;
  background:linear-gradient(90deg, transparent, rgba(212,175,55,.6), transparent)}
.login-field{margin-bottom:18px}
.login-field label{display:block;font-size:12px;color:#9aa4bd;margin-bottom:8px;font-weight:600;letter-spacing:.5px}
.login-field input{width:100%;padding:12px 14px;border-radius:10px;font-size:14px;outline:none;transition:.22s;
  background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.13);color:#eef1f8}
.login-field input::placeholder{color:#5d6780}
.login-field input:focus{border-color:rgba(245,215,110,.75);background:rgba(255,255,255,.08);
  box-shadow:0 0 0 3px rgba(212,175,55,.16), 0 0 18px rgba(212,175,55,.12)}
.login-field input:-webkit-autofill{-webkit-text-fill-color:#eef1f8;caret-color:#eef1f8;-webkit-box-shadow:0 0 0 1000px rgba(24,32,62,.96) inset}
.login-btn{position:relative;overflow:hidden;width:100%;padding:13px;border:none;border-radius:10px;font-size:15px;font-weight:700;letter-spacing:3px;text-indent:3px;cursor:pointer;margin-top:10px;color:#3a2a05;
  background:linear-gradient(135deg,#fbeaa0 0%,#e9c766 45%,#c9942a 100%);
  box-shadow:0 8px 24px rgba(201,148,42,.35), inset 0 1px 0 rgba(255,255,255,.35);
  transition:transform .18s, box-shadow .18s, filter .18s}
.login-btn:hover{transform:translateY(-2px);filter:brightness(1.05);box-shadow:0 14px 34px rgba(201,148,42,.45), inset 0 1px 0 rgba(255,255,255,.4)}
.login-btn:active{transform:translateY(0);filter:brightness(.97)}
.login-btn::after{content:'';position:absolute;top:0;left:-90%;width:55%;height:100%;transform:skewX(-24deg);pointer-events:none;
  background:linear-gradient(90deg, transparent, rgba(255,255,255,.55), transparent)}
.login-btn:hover::after{animation:loginBtnShine .85s ease}
@keyframes loginBtnShine{to{left:135%}}
.login-err{color:#ff9093;font-size:13px;margin-top:12px;min-height:20px;text-align:center;line-height:1.5}
.login-err:not(:empty){background:rgba(255,77,79,.10);border:1px solid rgba(255,77,79,.32);border-radius:9px;padding:7px 10px}
.login-hint{margin-top:16px;font-size:12px;color:#78809a;text-align:center;line-height:1.7;
  background:rgba(212,175,55,.05);border:1px dashed rgba(212,175,55,.28);border-radius:10px;padding:9px 10px}
.login-platform-entry{margin-top:16px;text-align:center}
.login-platform-entry a{font-size:12px;color:#c9a84c;text-decoration:none;letter-spacing:.5px;transition:.2s}
.login-platform-entry a:hover{color:#f0d78a;text-decoration:underline}
.login-lang{position:absolute;top:18px;right:20px;z-index:1}
.login-lang select{padding:6px 10px;border:1px solid rgba(255,255,255,.18);border-radius:8px;font-size:12px;background:rgba(13,19,40,.7);color:#dfe4f0;cursor:pointer;outline:none}
.login-lang select:hover{border-color:rgba(212,175,55,.55)}
.login-lang select option{background:#131a33;color:#dfe4f0}
.login-lang .globe{font-size:14px;margin-right:4px;opacity:.85}
.login-remember-row{margin:0 0 14px;font-size:13px;color:#9aa4bd}
.login-remember-row label{display:inline-flex;align-items:center;gap:8px;cursor:pointer;user-select:none}
.login-remember-row input{width:15px;height:15px;accent-color:#e0bd55;cursor:pointer}
.login-field select{width:100%;padding:12px 14px;border:1px solid rgba(255,255,255,.13);border-radius:10px;font-size:14px;outline:none;background:rgba(255,255,255,.05);color:#eef1f8;transition:.22s}
.login-field select:focus{border-color:rgba(245,215,110,.75);box-shadow:0 0 0 3px rgba(212,175,55,.16)}
.login-field select option{background:#131a33;color:#dfe4f0}
.login-tabs{display:flex;gap:6px;margin:4px 0 20px;padding:4px;border-radius:12px;background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.09)}
.login-tab{flex:1;padding:9px 0;border:none;background:none;font-size:13px;color:#8d97b2;cursor:pointer;border-radius:9px;transition:.2s;font-weight:600}
.login-tab:hover{color:#dfe4f0}
/* v1.2.259：选中 tab 与「登录」按钮撞色修复 —— 原来也是同一套实心金渐变，
   视觉上像两个主按钮。改为「暗色玻璃底 + 金色发丝描边 + 金字」：
   保留金色语义（选中态）但明度/质感与实心金按钮明显区分。 */
.login-tab.active{color:#f0d78a;background:linear-gradient(135deg,rgba(251,234,160,.16),rgba(224,189,85,.08));box-shadow:inset 0 0 0 1px rgba(224,189,85,.55), 0 2px 10px rgba(0,0,0,.22)}

/* 通用分段页签（期初建账等多分区页面） */
.seg-tabs{display:flex;gap:2px;border-bottom:1px solid var(--border);margin:6px 0 16px;overflow-x:auto}
.seg-tab{padding:9px 18px;border:none;background:none;font-size:14px;color:#888;cursor:pointer;border-bottom:2px solid transparent;transition:.2s;font-weight:600;white-space:nowrap}
.seg-tab:hover{color:#333}
.seg-tab.active{color:var(--primary);border-bottom-color:var(--primary)}
.op-inp{width:140px;padding:5px 8px;border:1px solid var(--border);border-radius:6px;font-size:13px;text-align:right}
.op-inp:disabled{background:#f7f7f7;color:#555}
.op-txt{width:100%;max-width:520px;padding:6px 8px;border:1px solid var(--border);border-radius:6px;font-size:13px}
.op-hint{margin-top:12px;font-size:12px;color:#999;line-height:1.7}
/* v1.2.74：移除 v1.2.72 临时加的 .op-deprecated-banner / .stat-card.grey（已恢复银行账户期初录入；库存现金字段不再展示） */
.login-panel{animation:fadeIn .25s ease}
.login-code-row{display:flex;gap:8px}
.login-code-row input{flex:1;width:auto}
.login-code-btn{flex-shrink:0;padding:0 16px;border:1px solid rgba(212,175,55,.5);background:rgba(212,175,55,.08);color:#e9c766;border-radius:10px;font-size:13px;cursor:pointer;white-space:nowrap;transition:.2s;font-weight:600}
.login-code-btn:hover{background:linear-gradient(135deg,#fbeaa0,#e0bd55);color:#3a2a05;border-color:transparent}
.login-code-btn:disabled{opacity:.5;cursor:not-allowed}
.oauth-desc{font-size:13px;color:#8d97b2;text-align:center;margin:6px 0 18px;line-height:1.6}
.oauth-btn{width:100%;padding:13px;border:none;border-radius:10px;font-size:15px;font-weight:700;cursor:pointer;color:#fff;transition:.2s;display:flex;align-items:center;justify-content:center;gap:8px;box-shadow:0 8px 22px rgba(0,0,0,.35)}
.oauth-btn .oauth-ico{font-size:18px}
.oauth-btn:hover{transform:translateY(-1px);filter:brightness(1.06)}
.oauth-wechat{background:linear-gradient(135deg,#2fd66e,#07a84f);box-shadow:0 8px 22px rgba(7,193,96,.28)}
.oauth-wechat:hover{background:linear-gradient(135deg,#3ade7b,#07b856)}
.oauth-qq{background:linear-gradient(135deg,#3fc4f8,#0e9fd8)}
.oauth-qq:hover{background:linear-gradient(135deg,#55d0fa,#12a9de)}
/* v2.0.60：登录页站点信息（ICP备案号 / 版权所有 / 服务商地址 / 电话）
   🔴 v2.0.64【需求 2】位置改到**页面最下方**：原来是 .login-box 内部的一段（排在「忘记密码」提示下面），
   现在移出登录框，作为整页页脚绝对定位贴在 #login-overlay 底部（overlay 是 position:fixed 全屏层，
   故绝对定位即「贴视口底」）。上边框去掉、改为极淡的分隔线，避免看起来仍像登录框的一部分。 */
.login-site{position:absolute;left:0;right:0;bottom:14px;z-index:3;margin:0;padding:0 16px;
  font-size:12px;color:#8d97b2;text-align:center;line-height:1.9;word-break:break-all}
.login-site a{color:#9fb0d6;text-decoration:none}
.login-site a:hover{text-decoration:underline}
@media (prefers-reduced-motion: reduce){
  #login-overlay::before,#login-overlay::after,.login-box{animation:none}
  .login-btn:hover{transform:none}
  .login-btn:hover::after{animation:none}
}
.tenant-badge{display:inline-block;background:rgba(22,119,255,.1);color:var(--primary);font-size:12px;padding:2px 8px;border-radius:10px;margin-right:10px;font-weight:600}
@keyframes fadeIn{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}

/* 图表 */
.chart-box{width:100%;overflow:auto}
.chart-legend{display:flex;gap:16px;flex-wrap:wrap;font-size:12px;color:#666;margin-top:8px}
.chart-legend .dot{display:inline-block;width:10px;height:10px;border-radius:2px;margin-right:4px;vertical-align:middle}
.grid-2{display:grid;grid-template-columns:1fr 1fr;gap:16px}
.dash-duo{display:grid;grid-template-columns:1fr 1fr;gap:16px}

/* 存欠料/款卡片（平板/手机端展示，PC 端隐藏） */
.dash-bal-cards{display:none}
.bal-card{background:#fff;border:1px solid #eee;border-radius:10px;overflow:hidden}
.bal-card-head{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:10px 12px;background:#fafafa;border-bottom:1px solid #f0f0f0}
.bal-name{font-size:14px;font-weight:600;color:#333;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.bal-card-grid{display:grid;grid-template-columns:1fr 1fr;gap:1px;background:#f0f0f0}
.bal-item{background:#fff;padding:10px 12px;display:flex;flex-direction:column;gap:3px;min-width:0}
.bal-l{font-size:11px;color:#999}
.bal-v{font-size:14px;font-weight:600;color:#333;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.bal-v.neg{color:#e02020}

/* 净重饼图 */
.pie-wrap{display:flex;flex-direction:column;align-items:center}
.pie-box{width:220px;max-width:100%}
.pie-wrap .chart-legend{justify-content:center;margin-top:12px}

/* 最近单据卡片（入库单/销售出库单样式） */
.doc-list{display:grid;grid-template-columns:repeat(auto-fill,minmax(320px,1fr));gap:12px}
.doc-card{border:1px solid #eee;border-radius:8px;overflow:hidden;cursor:pointer;transition:.15s;background:#fff}
.doc-card:hover{box-shadow:0 4px 14px rgba(0,0,0,.08);transform:translateY(-1px)}
.doc-card .doc-head{display:flex;align-items:center;gap:8px;padding:9px 12px;color:#fff;font-size:13px}
.doc-card .doc-badge{font-weight:700}
.doc-card .doc-code{margin-left:auto;font-size:12px;opacity:.9;letter-spacing:.3px}
.doc-po .doc-head{background:linear-gradient(90deg,#c9942a,#e0b45c)}
.doc-so .doc-head{background:linear-gradient(90deg,#1677ff,#4c9bff)}
.doc-ex .doc-head{background:linear-gradient(90deg,#8b5cf6,#b197fc)}
.doc-card .doc-body{display:grid;grid-template-columns:1fr 1fr;gap:8px 14px;padding:12px}
.doc-cell{display:flex;flex-direction:column;min-width:0}
.doc-l{font-size:11px;color:#999;margin-bottom:2px}
.doc-v{font-size:13px;color:#333;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.doc-v.gold{color:#c9942a}

/* 其它 */
.empty{text-align:center;color:#999;padding:40px 0;font-size:13px}
.toast{position:fixed;top:60px;left:50%;transform:translateX(-50%);background:#333;color:#fff;padding:10px 20px;border-radius:6px;z-index:99999;font-size:13px;opacity:0;transition:.3s;pointer-events:none;max-width:80vw}
.toast.show{opacity:1;top:70px}
.toast.success{background:#52c41a}.toast.error{background:#ff4d4f}
/* v1.2.107：明细网格列宽调整
   - 「结式」「数量」两列收窄到与列标题等宽（原 0.9fr / 0.6fr 偏宽，浪费空间）
   - 释放出的宽度给「商品名称」，长名称不再频繁换行
   - 末尾删除列由 30px 收到 26px，匹配新的圆形 ✕ 按钮 */
/* ══════════════════════════════════════════════════════════════════════
   v1.2.113：明细行列宽重排
   ──────────────────────────────────────────────────────────────────────
   用户反馈（截图）：删除按钮被挤到第二行，整行布局撑破。

   根因：12 列全部用 `fr` 弹性单位，而 fr 是**按比例分配剩余空间**，
   容器宽度不够时每列都压到最小值以下 → grid 自动换行 → 删除按钮掉行。

   改法：
   ① 「数量 / 单价 / 工费 / 提成·元/克」四列改为 **auto**（按标题文字宽度），
      不再参与弹性分配 —— 这正是用户要求的「只保留列标题文字的宽度」。
   ② 「结式 / 商品名称」保持弹性（这两个要容纳下拉框，天然需要宽度）。
   ③ 毛重/纯度/净重/金额 用**略大于标题**的固定值，保证数字不挤。
   ④ 整行加 `min-width`，容器窄时用横向滚动而不是换行 —— 换行正是布局被破坏的元凶。
   ══════════════════════════════════════════════════════════════════════ */
/* ══════════════════════════════════════════════════════════════════════
   v1.2.114：明细行列宽 —— 从「两处独立定义」改为「一份变量，表头数据共用」
   ──────────────────────────────────────────────────────────────────────
   为什么必须重写（这是 v1.2.113「样式乱套」的真正根因，不是数值没调好）：

   桌面端 .fld{display:contents} —— .fld 自身不是 grid item，真正成为格子的是
   它内部的 input/select。而**每一行 .item-row 都是独立的 grid 容器**。

   v1.2.113 给窄列写了 `auto`。但 auto 轨道是**按各自容器内的内容**算的：
     表头行容器里 auto 列的内容是「数量」两个字  → 实测 24px
     数据行容器里 auto 列的内容是 <input>       → 实测 86.5px
   同一个 grid-template-columns，两行算出两套宽度 → 全部错位（实测最大偏差 123px）。

   教训：**grid-template-columns 里绝对不能用 auto / fr 去对齐"表头 vs 数据"**，
   因为表头和数据是两个独立容器，只有确定值（px）才保证两边算出同一个结果。

   本版做法：
   ① 列宽全部用 CSS 变量写成**确定 px**，定义在 .item-row / .ex-item-row 上；
   ② 表头 .row-head 通过继承变量用同一份定义，**物理上不可能不一致**；
   ③ 取消 min-width + 横向滚动条（改为容器自适应 + 窄列收窄，弹窗内直接放得下）。
   ══════════════════════════════════════════════════════════════════════ */
.item-row{
  /* ── 12 列（用户指定顺序）───────────────────────────────
     结式 | 商品名称 | 数量 | 毛重 | 纯度 | 净重 | 单价 | 工费 | 金额 | 备注 | 提成·元/克 | 删除
     窄列宽度 = 该列标题文字宽（12px 汉字 × 字数 + 8px 内边距）
     数量 2 字 → 34px；毛重(g)/纯度(%)/净重(g) 6 半角字符 → 58px
     提成·元/克 最长（5 字）→ 70px

     v1.2.133【用户要求】单价、工费两列宽度 ×1.5：34px → 51px。
       为什么这两列要加宽：单价是本行最需要「一眼看清」的数字（常三位小数），
       34px 装下 "¥1000.50" 就已经贴边，加 1.5 倍后数字不再被裁切/省略号；
       工费同理（0.00~几十元/g）。两列合计 +34px，弹窗 lg 可用 1040px 仍装得下（见下方宽度自检）。 */
  --c-settle:60px;      /* 结式（下拉「结价」需 2 汉字 + 箭头） */
  --c-goods:150px;      /* 商品名称（下拉框，需容长名称） */
  --c-qty:34px;         /* 数量   */
  --c-gw:58px;          /* 毛重(g) */
  --c-pu:58px;          /* 纯度(%) */
  --c-nw:58px;          /* 净重(g) */
  --c-price:51px;       /* 单价（v1.2.133：34 × 1.5） */
  --c-fee:51px;         /* 工费（v1.2.133：34 × 1.5） */
  --c-amount:76px;      /* 金额（¥0.00 起步，读数只读框） */
  --c-remark:110px;     /* 备注（可输入文字） */
  --c-comm:70px;        /* 提成·元/克 */
  --c-del:26px;         /* 删除按钮 */
  display:grid;
  grid-template-columns:
    var(--c-settle) var(--c-goods)
    var(--c-qty) var(--c-gw) var(--c-pu) var(--c-nw)
    var(--c-price) var(--c-fee) var(--c-amount) var(--c-remark) var(--c-comm)
    var(--c-del);
  gap:6px;align-items:center;margin-bottom:8px;
}
/* 表头：只改字体/颜色，列宽靠继承上面的变量 → 与数据行必然对齐 */
.item-row.row-head{font-weight:600;color:#666;font-size:12px;padding:2px 0 6px;margin-bottom:4px}

/* ══════════════════════════════════════════════════════════════════════
   v1.2.116：定价不提料（pnp）7 列专属列宽
   ──────────────────────────────────────────────────────────────────────
   定价不提料只有 7 列（无结式/毛重/纯度/工费/提成），列宽需求与收料完全不同，
   用独立 class 定制，**不影响**其它单据的 12 列 / 换料 10 列布局。

   列顺序（用户指定）：
     商品名称 │ 数量 │ 净重(g) │ 定价单价 │ 金额 │ 备注 │ 删除

   列宽依据（12px 字号：汉字≈12px、数字≈7.2px/位；输入框 padding 6×2 + border 1×2）：
   | 列| 需求 | 宽度 | 计算 |
   |---|---|---|---|
   | 商品名称 | 6 个汉字 | **102px** | 6×12 + 14 + 16(下拉箭头) |
   | 数量 | **与商品名称同宽** | **102px** | 同上 |
   | 净重(g) | 6 位整数 + 4 位小数 | **94px** | 11 字符×7.2 + 14 |
   | 定价单价 | 12 位数字 | **101px** | 12×7.2 + 14 |
   | 金额 | 显示 10 亿 | **130px** | 按**最坏情况**「1,000,000,000.00」16 字符×7.2 + 14 |
   | 备注 | 20 个汉字 | **254px** | 20×12 + 14 |
   | 删除 | 不变 | **26px** | — |

   ⚠️ 金额列宽按**含千位逗号**的最坏情况算（16 字符）。
      定价单金额走 fmtNum → _numFmt → toFixed，中文界面不带逗号（越南语界面带），
      按最坏算才能保证**两种语言下都不显示截断/溢出**。

   合计 806 + gap 36 = 842px，弹窗 lg 可用 1040px → 富余 198px，不会出横向滚动条。
   ══════════════════════════════════════════════════════════════════════ */
.item-row.pnp-row{
  --p-goods:102px;      /* 商品名称：6 个汉字 */
  --p-qty:102px;        /* 数量：与商品名称同宽 */
  --p-net:94px;         /* 净重(g)：6 位整数 + 4 位小数 */
  --p-price:101px;      /* 定价单价：12 位数字 */
  --p-amt:130px;        /* 金额：10 亿（含千分位最坏情况） */
  --p-rem:254px;        /* 备注：20 个汉字 */
  --p-del:26px;         /* 删除按钮（不变） */
  display:grid;
  grid-template-columns:
    var(--p-goods) var(--p-qty) var(--p-net) var(--p-price)
    var(--p-amt) var(--p-rem) var(--p-del);
  gap:6px;align-items:center;margin-bottom:8px;
}

/* ══════════════════════════════════════════════════════════════════════
   v1.2.158：定价不提料 9 列（净重后新增「出料克重」，金额后新增「成本单价」）
   ──────────────────────────────────────────────────────────────────────
   列顺序（v1.2.158）：
     商品名称 │ 数量 │ 净重(g) │ **出料克重(g)** │ 定价单价 │ 金额 │ **成本单价** │ 备注 │ 删除
   三种形态：
     .item-row.pnp-row                       7 列 —— 整体毛利计算法（默认），成本列与出料克重列都不显示
     .item-row.pnp-row.pnp-row-cost           9 列 —— 单据毛利计算法 + 有成本查看权

   ⚠️ 为什么出料克重列**跟着成本列一起**显隐（pnpPickWeightCol() === pnpCostCol()）：
     出料克重只在「按单据提料 / 算单据毛利」时用得到。整体法按整体收料金额算毛利，
     这一列不参与任何计算 → 显示出来只会让人误以为有用。
     两列同一条件 → 表头/数据行/CSS 三者始终一致，不会出现错位。

   宽度自检：
     7 列 = 102+102+94+101+130+254+26= 809 + gap 36 = 845px
     9 列 = 809 + 94(出料克重) + 101(成本) + gap 12 = 1016px
     弹窗 lg 可用 1040px → 9 列形态刚好装下（余 24px）；
     **且列宽可由「表格列设置」自定义（v1.2.158 需求4），超宽时弹窗会自动变宽**。
   ══════════════════════════════════════════════════════════════════════ */
.item-row.pnp-row.pnp-row-cost{
  --p-cost:101px;       /* 成本单价：与定价单价同形态、同宽度 */
  --p-pick:94px;        /* 出料克重：与净重同形态（6 位整数 + 4 位小数）、同宽度 */
  display:grid;
  grid-template-columns:
    var(--p-goods) var(--p-qty) var(--p-net) var(--p-pick) var(--p-price)
    var(--p-amt) var(--p-cost)
    var(--p-rem) var(--p-del);
  gap:6px;align-items:center;margin-bottom:8px;
}
   ──────────────────────────────────────────────────────────────────────
   列顺序（用户指定：成本两列放在**备注前面**）：
     结式 │ 商品名称 │ 数量 │ 毛重 │ 纯度 │ 净重 │ 单价 │ 工费 │ 金额
     │ **成本单价** │ **成本金额** │ 备注 │ 提成·元/克 │ 删除

   为什么单独一个 class 而不改 .item-row：
     .item-row 是 po/so/pn 三个模块**共用**的 12 列网格。直接往里插两列会把
     收料单、提料不定价的表头与数据行一起错位（表头 12 列、数据行 14 列 → 全部串行）。
     与 .item-row.pnp-row（定价不提料 7 列）同一手法：只在出料单上加so-row，
     其它模块的布局逐字不变 —— 用户明确要求「其他五个业务模块不需要」。

   两列宽度依据（与既有两列对齐，便于扫读时上下对比）：
   | 列 | 需求 | 宽度 | 说明 |
   |---|---|---|---|
   | 成本单价 | 与「单价」同形态（元/克，常三位小数） | **51px** | 直接沿用 --c-price |
   | 成本金额 | 与「金额」同形态（含千位逗号最坏情况） | **76px** | 直接沿用 --c-amount |
   两列刻意与「单价/金额」**同宽**：同一行左右两侧数字纵向对齐，
   一眼就能看出「成本 <售价」还是「成本 >售价」（后者就是亏本卖）。

   宽度自检：原 12 列合计 771px + gap 72px = 843px；加两列（51+76+gap 6×2）= 983px。
   弹窗 lg 可用 1040px → 富余 57px，仍不出横向滚动条。
   （若将来嫌挤，优先压 --c-remark 110 → 90px，可再腾 20px。）
   ══════════════════════════════════════════════════════════════════════ */
.item-row.so-row{
  /* 成本两列复用「单价」「金额」的宽度变量 —— 语义相同、形态相同 */
  --c-costprice:51px;
  --c-costamt:76px;
  display:grid;
  grid-template-columns:
    var(--c-settle) var(--c-goods)
    var(--c-qty) var(--c-gw) var(--c-pu) var(--c-nw)
    var(--c-price) var(--c-fee) var(--c-amount)
    var(--c-costprice) var(--c-costamt)
    var(--c-remark) var(--c-comm) var(--c-del);
  gap:6px;align-items:center;margin-bottom:8px;
}
/* 成本列无录入权限时的锁定态：与既有 sensInput 风格一致（灰底 + 🔒） */
.item-row.so-row .cost-lock{background:#f7f7f7;color:#aaa;text-align:center}
/* 成本金额是「由成本单价 × 净重」算出来的，只读框比普通金额框再淡一档，
   避免用户以为可以直接改它（改了会被下一次输入冲掉）。 */
.item-row.so-row .cost-amt{background:#f4f4f4;color:#555}
/* v1.2.114：换料单 10 列（无结式、进场侧无提成，布局与收料同构） */
.ex-item-row{
  --c-goods:150px;
  --c-qty:34px; --c-gw:58px; --c-pu:58px; --c-nw:58px;
  /* v1.2.133【用户要求】换料表单的工费列同样 ×1.5：34 → 51px（换料没有「单价」列，只有工费） */
  --c-fee:51px;
  --c-amount:76px; --c-remark:110px; --c-comm:70px; --c-del:26px;
  display:grid;
  grid-template-columns:
    var(--c-goods)
    var(--c-qty) var(--c-gw) var(--c-pu) var(--c-nw)
    var(--c-fee) var(--c-amount) var(--c-remark) var(--c-comm)
    var(--c-del);
  gap:6px;align-items:center;margin-bottom:8px;
}
/* 表头里的删除列占位：与数据行对齐用，不显示任何内容 */
.item-row .hd-del,.ex-item-row .hd-del{display:block;width:var(--c-del,26px)}
/* 数字列的输入框：去掉左右 padding 里多余的部分，贴合窄列 */
.item-row input[type=number],.ex-item-row input[type=number]{text-align:center;padding:6px 2px}
/* 旧定义：v1.2.107 的按钮样式（保留，供移动端复用） */
.item-row select,.item-row input{padding:6px 6px;border:1px solid #d9d9d9;border-radius:5px;font-size:12px;width:100%;min-width:0}
/* 删除按钮：压缩成一个 X 的宽度（正方形小按钮） */
.item-row .del{display:flex;align-items:center;justify-content:center}
.item-row .del .btn{width:26px;height:26px;min-width:26px;padding:0;line-height:1;
  display:inline-flex;align-items:center;justify-content:center;font-size:13px;border-radius:6px}
.ex-item-row select,.ex-item-row input{padding:6px 6px;border:1px solid #d9d9d9;border-radius:5px;font-size:12px;width:100%;min-width:0}
.ex-item-row .del{display:flex;align-items:center;justify-content:center}
.ex-item-row .del .btn{width:26px;height:26px;min-width:26px;padding:0;line-height:1;
  display:inline-flex;align-items:center;justify-content:center;font-size:13px;border-radius:6px}
.ex-item-row .ex-no-fee{font-size:12px;color:#aaa;text-align:center}
/* v1.2.114 曾用 .ex-blank 占位空格保证来料侧列数；
   v1.2.115 来料侧改成真实提成输入框后该占位已废弃，样式一并移除（不留死代码）。 */
/* 表头里的删除列占位：与数据行对齐用，不显示任何内容 */
.ex-head{font-weight:600;color:#666;font-size:12px}
.ex-side-head{display:flex;align-items:center;gap:8px;font-weight:700;font-size:13px;padding:8px 10px;border-radius:6px;margin-bottom:8px}
.ex-side-head.gold{background:#fdf6e3;color:#8a6d1a}
.ex-side-head.blue{background:#eef4ff;color:#2456a6}
.ex-side-sub{font-weight:500;font-size:12px;color:#888}
.ex-net-line{margin-top:10px;padding:8px 10px;border-radius:6px;background:#f6f8fa;font-size:13px;font-weight:600;display:flex;gap:16px;flex-wrap:wrap}
.pager-bar{display:flex;align-items:center;gap:10px;margin-top:10px;font-size:12px;color:#666;flex-wrap:wrap}
.pager-bar .pg-info{white-space:nowrap}
.pager-bar .pg-size{padding:4px 6px;border:1px solid #d9d9d9;border-radius:5px;font-size:12px}
.pager-bar .pg-btns{display:flex;gap:4px;align-items:center}
.owe-info{margin:10px 0 4px;padding:8px 12px;background:#fdf8ee;border:1px solid #f0e2c0;border-radius:6px;font-size:13px;color:#8a6d1a;font-weight:600;white-space:nowrap;overflow-x:auto}
.pager-bar .pg-btn{min-width:28px;padding:4px 8px;border:1px solid #d9d9d9;border-radius:5px;background:#fff;cursor:pointer;font-size:12px}
.pager-bar .pg-btn:hover:not(:disabled){border-color:#c8a24a;color:#a87f2f}
.pager-bar .pg-btn.active{background:#c8a24a;border-color:#c8a24a;color:#fff}
.pager-bar .pg-btn:disabled{opacity:.4;cursor:default}
.pager-bar .pg-dots{color:#999;padding:0 2px}
table tfoot tr{border-top:2px solid #eee}
.items-scroll{overflow-x:auto;padding-bottom:4px}
/* v1.2.158【表格列设置】说明（配合 JS 侧 colLayoutOf / modalWidthForCols）：
   · 列宽由用户配置（像素值），通过**行内 style="grid-template-columns:..."** 下发，
     行内优先级高于本文件里的 .item-row class 规则 → 用户设置**立刻生效**、不会被压缩变形。
   · 列宽合计超过弹窗宽度时，弹窗按 modalWidthForCols() 精确变宽（showModal 支持传数字宽度）；
     极端宽时（超出视口 95%）由 .items-scroll 的 overflow-x:auto 横向滚动兜底，
     列**始终保持设定宽度、不会变形换行** —— 这正是用户强调的核心诉求。
   · 移动端（≤640px）媒体查询里是 `grid-template-columns:1fr 1fr!important`，
     卡片式两列布局**不受列宽设置影响** —— 手机屏幕本就放不下十几列，强行套 px 会挤成一条。 */

/* 明细字段包裹：桌面端 display:contents 保持原网格布局；移动端在媒体查询中变为带标签表单项 */
.fld{display:contents}
.order-meta{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin-bottom:14px}
.order-meta .it{background:#fafafa;border:1px solid #f0f0f0;border-radius:6px;padding:10px 12px}
.order-meta .it .l{font-size:12px;color:#999;margin-bottom:4px}
.order-meta .it .v{font-size:16px;font-weight:600}
/* 存欠数值：符号（+ / -）必须与数字同进同退。
   ASCII 的 - 属 HY 换行类、+ 属 PR 换行类，窄容器里浏览器会把符号甩到上一行，
   看起来像「减号后面空了」，极易误读。用 nb 类把「符号+数字+单位」锁成一个不可断的整体。 */
.nb{white-space:nowrap}
.order-meta .it .v.gold{color:var(--gold)}
.order-meta .it input,.order-meta .it select{width:100%;padding:5px 8px;border:1px solid #d9d9d9;border-radius:5px;font-size:13px}
/* 存欠类提示条（收料/出料/换料/结价表单里的当前存欠、结价后存欠、方向提示）整体不可断，
   避免「存欠料:-1400.00g　存欠款:-¥83,561.00」被拆散。 */
.form-hint{font-size:12px;color:#8a6d1a;line-height:1.7;white-space:normal}
.form-hint .nb,.form-val .nb,.owe-info .nb,.dept-tag .nb{display:inline-block;white-space:nowrap}
/* 结价凭证四宫格里的「结价前/后存欠」：两个数值各自成块，块内不断行、块间可换行 */
.order-meta .it .v .nb+.nb{margin-left:6px}

@media(max-width:900px){
  .stat-grid{grid-template-columns:repeat(2,1fr)}.stat-grid-5{grid-template-columns:repeat(2,1fr)}.grid-2,.dash-duo{grid-template-columns:1fr}.form-grid{grid-template-columns:1fr 1fr}.order-meta{grid-template-columns:1fr 1fr}
  /* v1.2.154：平板（641~900px）AI 助手栏窄化 —— 输入框与模型同行，按钮独占下一行。
     原来这个区间没有 AI 相关规则，靠基础规则的 display:none 干脆不显示，
     现在基础规则默认显示了，必须补一段窄屏适配，否则平板上会挤成一行。 */
  .ai-bar{gap:8px;padding:10px 12px}
  .ai-input{flex:1 1 160px;min-width:0}
  .ai-model{max-width:150px}
  .ai-bar .btn{flex:0 0 auto;padding:9px 16px;white-space:nowrap}
  .stat-grid-6{grid-template-columns:repeat(3,1fr)}
  /* 存欠料/款：平板/手机端切换为卡片式，隐藏表格 */
  .dash-bal-table{display:none}
  .dash-bal-cards{display:grid;grid-template-columns:1fr;gap:10px}
  /* 近14天趋势图：移动端不加载 */
  .dash-trend-card{display:none}
  /* 列表表格卡片化（收料/换料/出料/收付款/费用/提成/发票/期初/期末/用户） */
  .mcard{display:block!important}
  .mcard thead{display:none}
  .mcard tfoot{display:none}
  .mcard tbody{display:block}
  .mcard tbody tr{display:block;border:1px solid #eee;border-radius:10px;padding:10px 12px;margin-bottom:10px;background:#fff;box-shadow:0 1px 3px rgba(0,0,0,.04)}
  /* 费用明细移动端卡片：支出 / 收入用不同左色条与底色区分（PC 表格样式不变） */
  .mcard tbody tr.fin-exp-row{border-left:4px solid #e02020;background:#fff7f7}
  .mcard tbody tr.fin-inc-row{border-left:4px solid #18a058;background:#f3fbf5}
  .mcard tbody td{display:flex;justify-content:space-between;align-items:center;gap:12px;padding:7px 0;border:none;border-bottom:1px dashed #f0f0f0;font-size:14px;text-align:right;word-break:break-word;min-width:0}
  .mcard tbody td::before{content:attr(data-label);font-size:12px;color:#999;flex-shrink:0;text-align:left;font-weight:600}
  .mcard tbody td:last-child{border-bottom:none}
  .mcard tbody td[data-label=""]::before{content:none}
  .mcard tbody td .dept-tag{margin-left:6px}
  .mcard tbody td.empty{display:block;text-align:center;color:#999;border:none;padding:20px 0}
  .mcard tbody td.empty::before{content:none}
  /* 操作列：按钮横排、不显示列名 */
  .mcard tbody td.td-op{display:flex;flex-wrap:wrap;gap:6px;border-bottom:none;justify-content:flex-end}
  .mcard tbody td.td-op::before{content:none}
  .mcard tbody td.td-op .btn-link,.mcard tbody td.td-op .btn{margin:0}
  .mcard tbody td input,.mcard tbody td select{flex:1;min-width:0;font-size:16px;padding:6px 8px}
  /* 页头操作按钮：移动端独占一行、均分铺满，保证「新增/打印/导出Excel/导出PDF」可见易点 */
  .card-title{row-gap:10px}
  .card-tools{flex-basis:100%;width:100%;gap:8px}
  .card-tools .btn{flex:1 1 auto;justify-content:center;min-height:40px;font-size:14px;padding:8px 12px}
  .card-tools select{flex:1 1 auto;min-height:40px;font-size:16px}
  .card-tools .badge{flex:0 0 auto;align-self:center}
  /* 卡片内操作列按钮：加大触控，便于手机点按 */
  .mcard tbody td.td-op .btn-link{font-size:14px;padding:7px 10px;min-height:34px;border:1px solid #e5e5e5;border-radius:6px;background:#fff;text-decoration:none;line-height:1}
  .mcard tbody td.td-op .btn-link.danger{color:var(--danger);border-color:#ffd6d6}
  .menu-toggle{display:block}
  .sidebar{position:fixed;left:-220px;top:0;bottom:0;z-index:9999;transition:.25s}.sidebar.open{left:0}
  .sidebar-mask{position:fixed;inset:0;background:rgba(0,0,0,.4);z-index:9998;display:none}.sidebar-mask.show{display:block}
}
@media(max-width:640px){
  .stat-grid{grid-template-columns:1fr 1fr;gap:10px}
  .stat-grid-6{grid-template-columns:1fr 1fr}
  .stat-grid-3{grid-template-columns:1fr}
  .stat-card{padding:14px}
  .stat-value{font-size:20px;overflow-wrap:anywhere}
  .stat-sub{overflow-wrap:anywhere}
  .form-grid,.form-grid-2{grid-template-columns:1fr}
  .order-meta{grid-template-columns:1fr}
  .content{padding:12px}
  .topbar{padding:0 12px;height:auto;min-height:48px;flex-wrap:wrap;gap:6px}
  .topbar-title{font-size:14px}
  .topbar-info{display:none}
  .topbar-right{gap:10px;flex-wrap:wrap}
  .card{padding:14px}
  .login-box{width:92vw;padding:34px 24px 26px;border-radius:16px}
  /* v2.0.62【需求 4】窄屏登录页：左右分栏改上下单列，宣传区收成顶部简洁横幅（只留宣传语） */
  .login-split{flex-direction:column;width:92vw;border-radius:16px}
  .login-promo{flex:none;padding:26px 22px 20px;gap:12px;border-right:none;border-bottom:1px solid rgba(212,175,55,.22)}
  .login-promo .promo-visual{width:74px;height:74px}
  .login-promo .promo-coin{font-size:36px}
  .login-promo .promo-slogan{font-size:16px;max-width:100%}
  .login-box{flex:none;max-width:100%;width:100%}
  /* v2.0.64【需求 2】窄屏页脚：字号收小、贴底更近，避免占掉本就不多的竖向空间 */
  .login-site{bottom:8px;padding:0 10px;font-size:11px;line-height:1.7}
  .login-logo .icon{width:54px;height:54px;font-size:28px;margin-bottom:10px}
  .login-logo h2{font-size:19px}
  .login-logo p{letter-spacing:2px}
  .login-lang{top:12px;right:12px}

  /* ---- 移动端弹窗：全屏化 + 底部操作栏 ---- */
  .modal-mask{padding:0;align-items:flex-end}
  .modal{width:100%;max-width:100%;max-height:94dvh;border-radius:14px 14px 0 0;animation:sheetUp .22s ease}
  .modal.sm,.modal.lg{max-width:100%}
  @keyframes sheetUp{from{transform:translateY(24px);opacity:.6}to{transform:none;opacity:1}}
  .modal-head{padding:13px 14px}
  .modal-head h3{font-size:15px}
  .modal-body{padding:14px}
  .modal-foot{position:sticky;bottom:0;background:#fff;padding:10px 14px calc(10px + env(safe-area-inset-bottom));box-shadow:0 -4px 12px rgba(0,0,0,.06)}
  .modal-foot .btn{flex:1;justify-content:center;padding:11px 14px;font-size:15px}
  /* 弹窗内输入框加大字号，避免 iOS 聚焦自动缩放 */
  .modal input,.modal select,.modal textarea{font-size:16px}
  .modal .btn{min-height:36px}

  /* ---- 明细行卡片化：告别横向拖动 ---- */
  .items-scroll{overflow:visible}
  .item-row,.ex-item-row{display:grid;grid-template-columns:1fr 1fr!important;gap:9px 10px;border:1px solid #eee;border-radius:10px;padding:12px;position:relative;background:#fff;min-width:0!important;margin-bottom:10px;box-shadow:0 1px 3px rgba(0,0,0,.05)}
  .item-row.row-head,.ex-item-row.ex-head{display:none}
  .fld{display:flex;align-items:center;gap:8px;min-width:0}
  .fld::before{content:attr(data-lb);font-size:12px;color:#999;flex-shrink:0;min-width:4.4em;font-weight:600}
  .fld.wide{grid-column:1/-1}
  /* v1.2.107：移动端删除按钮同样是紧凑的 X（不再是 4px 10px 的长条） */
  .fld.del{position:absolute;top:8px;right:8px}
  .fld.del::before{content:none}
  .fld.del .btn{width:28px;height:28px;min-width:28px;min-height:28px;padding:0;
    display:inline-flex;align-items:center;justify-content:center;font-size:14px;border-radius:6px}
  /* 移动端「结式」「数量」字段要留出右上角按钮的位置，避免与 X 重叠 */
  .item-row .fld[data-lb]::before{min-width:4.4em}
  .item-row .fld:nth-child(1),.item-row .fld:nth-child(3){padding-right:32px}
  .item-row input,.item-row select,.ex-item-row input,.ex-item-row select{font-size:16px;padding:8px 10px;flex:1;min-width:0}
  .item-row input[readonly],.ex-item-row input[readonly]{background:#fafafa}
  .ex-no-fee{flex:1;text-align:center;color:#bbb}
  .pager-bar{justify-content:center}

  /* ---- AI 助手栏 + 筛选栏移动端 ---- */
  /* v1.2.154：桌面端已默认显示（见 .ai-bar 基础规则），这里只做窄屏堆叠优化：
       第一行「模型 + 发送」并排（省高度），第二行输入框整行（输入区够宽好打字）。 */
  .ai-bar{gap:8px;padding:10px 12px}
  .ai-bar .ai-ico{display:none}          /* 手机上标题栏空间紧张，图标让位给输入框 */
  .ai-input{flex:1 1 100%;order:2;min-width:0}   /* 输入框整行、排在模型之后 */
  .ai-model{order:1;flex:1 1 0;max-width:none;min-width:0}
  .ai-bar .btn{order:1;flex:0 0 auto;padding:10px 16px;white-space:nowrap}
  .ai-chips{order:3;flex-basis:100%;gap:6px}
  /* 手机上按钮最小 40px 高（手指点得准），短语改成横向可滑动的一条，避免占太高 */
  .ai-bar .btn{min-height:40px}
  .ai-chip{padding:7px 12px;font-size:12.5px;min-height:32px;display:inline-flex;align-items:center}
  .ai-tip{order:4}
  .filter-bar input,.filter-bar select{flex:1;min-width:0}
  .filter-bar .btn{flex:1}
  /* ---- 收料/换料/出料列表查询条件：移动端网格化（往来单位/状态整行，日期并排，关键词+重置整行） ---- */
  .doc-filter{display:grid;grid-template-columns:1fr 1fr;gap:8px}
  .doc-filter select{grid-column:1/-1;width:100%}
  .doc-filter input{width:100%;min-width:0}
  .doc-filter input[type=date]{grid-column:auto}
  .doc-filter input:not([type=date]){grid-column:1/-1}
  .doc-filter .btn{grid-column:1/-1;width:100%}

  /* ---- 日志查询：筛选栏两列排布，关键词整行 ---- */
  .al-filter{display:grid;grid-template-columns:1fr 1fr;gap:8px}
  .al-filter #al-q{grid-column:1/-1}
  .al-filter input,.al-filter select{width:100%;min-width:0}
  /* ---- 日志详情：修改前后字段对比表转 KV 卡片 ---- */
  .al-kv thead{display:none}
  .al-kv tbody{display:block}
  .al-kv tr{display:block;border-bottom:1px dashed #eee;padding:8px 0}
  .al-kv tr:last-child{border-bottom:none}
  .al-kv td{display:block;width:100%!important;padding:0;border:none}
  .al-kv td:first-child{font-size:12px;color:#999;font-weight:600;margin-bottom:3px}
  .al-kv td:last-child{font-size:14px;word-break:break-all;white-space:normal}

  /* ---- 单据详情弹窗：明细表转 KV 卡片（PC 端不变）---- */
  .doc-items{overflow:visible}
  .doc-items table,.doc-items tbody,.doc-items tfoot{display:block;min-width:0!important}
  .doc-items thead{display:none}
  .doc-items tr{display:block;border:1px solid #eee;border-radius:10px;padding:6px 12px;margin-bottom:8px;background:#fff;box-shadow:0 1px 3px rgba(0,0,0,.04)}
  .doc-items td{display:flex;justify-content:space-between;align-items:center;gap:12px;padding:5px 0;border:none;text-align:right!important;font-size:13px;word-break:break-all}
  .doc-items td::before{content:attr(data-l);font-size:12px;color:#999;flex-shrink:0;font-weight:600;text-align:left}
  .doc-items td:not([data-l]){display:none}
  .doc-items tfoot tr{background:#fafdf6;border-color:#e2efd8}
  .doc-items tfoot td::before{color:#666}

  /* ---- 对账管理：往来单位卡片两列网格，单位名作卡片标题 ---- */
  .recon-cards tr{display:grid;grid-template-columns:1fr 1fr;gap:2px 12px;padding:10px 12px}
  .recon-cards td:first-child{grid-column:1/-1;justify-content:flex-start;text-align:left!important;border-bottom:1px dashed #eee;padding-bottom:6px;margin-bottom:4px;font-size:14px}
  .recon-cards td:first-child::before{content:none}
  .recon-cards td .badge{flex-shrink:0}

  /* 🔴 v2.0.72【结价表单移动端】明细行原来是一条固定像素的多列网格（7 列×56~150px），
     手机上每列只剩几十像素、输入框挤成一条线。这里按收料/出料明细同款做法改成"两列卡片 + 左侧列名"。
     表头行隐藏（列名已经显示在每格左侧），合计行改成一条可换行的摘要。 */
  .st-head .it{min-width:100%}
  .st-table{border:none;border-radius:0;overflow:visible}
  .st-trow{grid-template-columns:1fr 1fr!important;gap:9px 10px;align-items:center;
    border:1px solid #eee;border-radius:10px;padding:12px;background:#fff;margin-bottom:10px;
    box-shadow:0 1px 3px rgba(0,0,0,.05);position:relative;min-width:0}
  .st-trow.row-head{display:none}
  .st-trow.row-foot{display:flex;flex-wrap:wrap;gap:6px 16px;background:#fafbfc;font-weight:700}
  .st-trow.row-foot > *{padding:0;flex:0 0 auto}
  .st-trow > .st-cell{display:flex;align-items:center;gap:8px;padding:0;overflow:visible;text-overflow:clip}
  .st-trow > .st-cell::before{content:attr(data-lb);font-size:12px;color:#999;flex-shrink:0;min-width:4.6em;font-weight:600}
  .st-trow > .st-cell[data-lb=""]::before{content:none}
  .st-trow > .st-cell input,.st-trow > .st-cell select{font-size:16px;padding:8px 10px}
  .st-trow > .st-cell-del{position:absolute;top:8px;right:8px;display:block;padding:0}
  .st-trow > .st-cell-del::before{content:none}
  .st-trow > .st-cell-del .btn{width:28px;height:28px;min-width:28px;min-height:28px;padding:0;
    display:inline-flex;align-items:center;justify-content:center;font-size:14px;border-radius:6px}
  /* 商品/备注整行显示（内容较长），并给右上角的删除按钮留位 */
  .st-trow > .st-cell:first-child{grid-column:1/-1}
  .st-trow > .st-cell[data-lb] > select,
  .st-trow > .st-cell[data-lb] > input{min-width:0}
}
@media(max-width:400px){
  .stat-grid,.stat-grid-5,.stat-grid-6{grid-template-columns:1fr}
  .login-lang{top:10px;right:10px}
  /* 顶栏超窄屏：隐藏次要元素（日期已在 640 隐藏），保证标题/筛选/退出可点 */
  .topbar{padding:0 10px}
  .topbar-title{font-size:13px;max-width:34vw;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .topbar-right{gap:8px}
  .topbar-user .urole{display:none}
  .topbar-user .tenant-badge{display:none}
  .dept-filter{margin-right:4px}
  .dept-filter select{max-width:104px}
  .logout-btn{padding-left:8px}
}

/* ===== 权限分配（用户管理）===== */
.perm-sec-title,.pd-sec-title{font-weight:600;font-size:13px;color:#8a6d1f;margin:16px 0 8px;display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.perm-tip{font-weight:400;font-size:12px;color:#aaa}
.perm-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px}
.perm-cell{display:flex;align-items:center;gap:6px;padding:7px 10px;border:1px solid #e8e8e8;border-radius:8px;font-size:13px;cursor:pointer;background:#fafafa;user-select:none;transition:.15s}
.perm-cell:hover{border-color:#d4af37}
.perm-cell.on{background:#fffaf0;border-color:#e0b84c;color:#8a6d1f;font-weight:600}
.perm-cell input{margin:0;flex:none}
.perm-chk{accent-color:#d4af37}
.perm-tag{display:inline-block;margin:2px 4px 2px 0;padding:1px 7px;border-radius:10px;font-size:11px;background:#fff3f0;color:#c0392b;border:1px solid #f3d3cd}
.perm-tag.ok{background:#f0faf3;color:#1e9e5a;border-color:#cdeed9}
.perm-lock{color:#c9a227;font-size:13px}
.perm-groups{display:flex;flex-direction:column;gap:10px;max-height:420px;overflow:auto;padding:2px}
.perm-group{border:1px solid #eee;border-radius:10px;padding:8px 10px;background:#fff}
.perm-group-name{font-size:13px;font-weight:700;color:#333;margin-bottom:6px}
.perm-subname{font-size:12px;color:#8a6d3b;font-weight:600;margin:8px 0 4px}
.dept-filter{display:flex;align-items:center;gap:5px;margin-right:12px;font-size:13px}
.dept-filter select{height:30px;border:1px solid #e3d9c8;border-radius:6px;background:#fffdf8;padding:0 6px;font-size:13px;color:#5b4a2f;max-width:150px}
.dept-tag{display:inline-block;padding:2px 8px;border-radius:99px;background:#f4ede1;color:#8a6d3b;font-size:12px;font-weight:600}
.perm-cells{display:flex;flex-wrap:wrap;gap:6px}
.perm-cells .perm-cell{padding:5px 9px;font-size:12px}
/* 审批流程开关 */
.switch-row{display:flex;align-items:center;gap:10px;cursor:pointer;user-select:none}
.switch-row input{display:none}
.switch-ui{position:relative;width:44px;height:24px;border-radius:99px;background:#ccc;transition:.18s;flex:none}
.switch-ui:before{content:'';position:absolute;top:3px;left:3px;width:18px;height:18px;border-radius:50%;background:#fff;transition:.18s}
.switch-row input:checked + .switch-ui{background:#1e9e5a}
.switch-row input:checked + .switch-ui:before{left:23px}
/* ===== 期末处理 ===== */
.pd-period{padding:5px 8px;border:1px solid #ddd;border-radius:6px;font-size:13px;background:#fff;margin-left:8px}
.pd-chk{font-weight:700}
.pd-chk.good{color:#1e9e5a}
.pd-chk.bad{color:#c0392b}
@media(max-width:900px){.perm-grid{grid-template-columns:1fr 1fr}}
@media(max-width:560px){.perm-grid{grid-template-columns:1fr}}

/* ===== 数据导入导出中心 ===== */
.io-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px}
.io-grid .form-row{margin:0}
.io-actions{display:flex;gap:10px;flex-wrap:wrap;margin-top:14px}
.io-chip{display:inline-block;margin:3px 5px 0 0;padding:1px 8px;border-radius:10px;font-size:12px;background:#f4f6f8;color:#5a6472;border:1px solid #e6eaef}
.io-chip.req{background:#fff7e6;color:#a8760f;border-color:#f0dca6}
.io-prev{margin-top:4px;max-height:320px;overflow:auto}
.io-prev table{font-size:13px}
.io-prev th{vertical-align:top;background:#fafbfc;min-width:120px}
.io-col{color:#8a6d1f;font-weight:600;margin-bottom:4px}
.io-map-sel{width:100%;font-size:12px;padding:3px 4px;border:1px solid #ddd;border-radius:6px;background:#fff}
.io-res{display:flex;gap:8px;flex-wrap:wrap;margin-top:14px}
.io-badge{padding:5px 12px;border-radius:8px;font-size:13px;background:#f4f6f8;color:#4b5563;border:1px solid #e6eaef}
.io-badge.ok{background:#f0faf3;color:#1e9e5a;border-color:#cdeed9}
.io-badge.warn{background:#fff8ec;color:#b5760b;border-color:#f2e0b8}
.io-errs{margin-top:12px;font-size:13px;color:#c0392b}
.io-errs ul{margin:6px 0 0;padding-left:20px;max-height:240px;overflow:auto}
.io-errs li{margin:2px 0}
@media(max-width:820px){.io-grid{grid-template-columns:1fr}}

/* ===== 项目台账 ===== */
.prj-prog{display:inline-block;width:72px;height:8px;border-radius:4px;background:#eee;vertical-align:middle;overflow:hidden}
.prj-prog-bar{height:100%;border-radius:4px;transition:width .3s}
.prj-prog-ok{background:#52c41a}
.prj-prog-warn{background:#faad14}
.prj-prog-bad{background:#c0392b}
.prj-prog-txt{font-size:12px;color:#888;margin-left:6px;vertical-align:middle}
/* ===== 数据报表中心 ===== */
.rp-custom{display:inline-flex;gap:6px;align-items:center;font-size:12px;color:#888}

/* ===== 数据清除（按模块）===== */
.pg-warn{background:#fffbe6;border:1px solid #ffe58f;border-radius:8px;padding:10px 12px;font-size:13px;line-height:1.8;color:#874d00;margin-bottom:14px}
.pg-grp{margin-bottom:14px}
.pg-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:10px}
.pg-cell{display:flex;gap:8px;align-items:flex-start;border:1px solid #eee;border-radius:8px;padding:10px 12px;cursor:pointer;background:#fff;transition:.15s}
.pg-cell:hover{border-color:#d9b26a}
.pg-cell.on{border-color:#c99a2e;background:#fffdf5;box-shadow:0 0 0 1px #f0dcae inset}
.pg-cell.blocked{border-color:#ffccc7;background:#fff8f7}
.pg-cell.locked{cursor:default;background:#fafafa;border-style:dashed;opacity:.9}
.pg-cell input{margin-top:2px}
.pg-main{flex:1;min-width:0}
.pg-name{font-size:13px;font-weight:600;color:#333;display:flex;align-items:center;gap:6px}
.pg-num{background:#f5f5f5;color:#8c8c8c;border-radius:9px;padding:0 7px;font-size:11px;font-weight:600}
.pg-cell.on .pg-num{background:#fdf1d6;color:#a67c12}
.pg-sub{font-size:11px;color:#999;margin-top:3px;word-break:break-all}
.pg-lock{font-size:11px;color:#cf1322;margin-top:4px;line-height:1.6}
.pg-actions{display:flex;align-items:center;gap:8px;margin-top:6px;flex-wrap:wrap}
.pg-actions .spacer{flex:1}
.pg-run{display:flex;align-items:flex-end;gap:12px;margin-top:14px;padding-top:14px;border-top:1px dashed #eee;flex-wrap:wrap}
.pg-run .form-row{flex:1;min-width:260px;margin:0}
.pg-res{border-radius:8px;padding:12px 14px;font-size:13px;line-height:1.8;margin-top:12px}
.pg-res.ok{background:#f6ffed;border:1px solid #b7eb8f}
.pg-res.bad{background:#fff1f0;border:1px solid #ffa39e}
.pg-res-title{font-weight:600;margin-bottom:4px}
.pg-res.ok .pg-res-title{color:#389e0d}
.pg-res.bad .pg-res-title{color:#cf1322}
.pg-list{margin:6px 0 0;padding-left:18px}
.pg-list.bad li{color:#cf1322}
.pg-list.warn li{color:#d46b08}
.pg-plan{margin-top:6px;color:#666;font-size:12px}
.pg-chip{display:inline-block;background:#f5f5f5;color:#666;border-radius:9px;padding:1px 8px;font-size:11px;margin-right:4px}
.pg-chip.latest{background:#f6ffed;color:#389e0d;font-weight:600}
.pg-miss{color:#cf1322;font-size:12px}
/* ===== 操作日志查询 ===== */
.al-meta{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:8px;margin-bottom:14px;font-size:13px;color:#333;line-height:1.7;background:#fafafa;border:1px solid #f0f0f0;border-radius:8px;padding:12px}
.al-meta .lbl{color:#999}
.al-cols{display:grid;grid-template-columns:1fr 1fr;gap:16px}
@media (max-width:640px){.al-cols{grid-template-columns:1fr}}

/* ===== 往来单位银行账户（一个往来单位多卡号）===== */
.pba-list{max-height:56vh;overflow:auto}
.pba-row{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:9px 4px;border-bottom:1px solid #f4ede1}
.pba-row:last-child{border-bottom:none}
.pba-main{flex:1;min-width:0}
.pba-title{font-size:14px;font-weight:600;color:#333;font-family:Consolas,monospace;word-break:break-all}
.pba-sub{font-size:12px;color:#999;margin-top:3px;word-break:break-all}
.pba-ops{display:inline-flex;gap:2px;flex-shrink:0}

/* ===== 智能中心（AI 中心 · 敬请期待）===== */
.ai-center-hero{text-align:center;padding:42px 30px 30px;background:linear-gradient(135deg,#fdf6ec 0%,#f6f0ff 100%);border:1px solid #f0e4cc;border-radius:12px;box-shadow:0 4px 20px rgba(201,148,42,.08);margin-bottom:16px}
.ai-center-icon{font-size:64px;margin-bottom:12px;animation:ai-bounce 2.4s ease-in-out infinite}
.ai-center-title{font-size:26px;color:#c9942a;font-weight:600;margin-bottom:8px;letter-spacing:.5px}
.ai-center-subtitle{font-size:14px;color:#666;line-height:1.6;max-width:680px;margin:0 auto 14px}
.ai-center-waiting{font-size:18px;color:#1677cc;font-weight:600;margin-bottom:6px}
@keyframes ai-bounce{0%,100%{transform:translateY(0)}50%{transform:translateY(-8px)}}

/* 全宽双栏 grid：左边 4 场景卡片，右边 4 阶段路线，避免右边留白 */
.ai-center-grid{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:16px}
.ai-card{background:#fff;border:1px solid #f0e4cc;border-radius:12px;padding:22px 24px;box-shadow:0 2px 10px rgba(201,148,42,.04)}
.ai-card-title{font-size:15px;color:#c9942a;font-weight:600;margin-bottom:14px;padding-bottom:10px;border-bottom:1px dashed #f0e4cc}

/* 4 张场景卡片：2x2 网格 */
.ai-scenarios{display:grid;grid-template-columns:1fr 1fr;gap:12px}
.ai-scenario-card{background:linear-gradient(135deg,#fcfaf5 0%,#faf7ff 100%);border:1px solid #efe6d0;border-radius:8px;padding:14px 12px;transition:all .2s}
.ai-scenario-card:hover{border-color:#c9942a;box-shadow:0 2px 8px rgba(201,148,42,.1);transform:translateY(-1px)}
.ai-scenario-icon{font-size:26px;margin-bottom:6px}
.ai-scenario-title{font-size:13px;color:#333;font-weight:600;margin-bottom:4px}
.ai-scenario-desc{font-size:12px;color:#777;line-height:1.6}

/* 4 阶段路线图：竖排时间线 */
.ai-stages{display:flex;flex-direction:column;gap:10px}
.ai-stage-item{display:flex;align-items:flex-start;gap:10px;padding:10px 12px;background:linear-gradient(90deg,#fcfaf5 0%,#fff 100%);border-left:3px solid #c9942a;border-radius:6px}
.ai-stage-tag{flex-shrink:0;background:#c9942a;color:#fff;font-size:11px;font-weight:600;padding:3px 10px;border-radius:10px;line-height:1.4}
.ai-stage-desc{font-size:12px;color:#555;line-height:1.5;flex:1}

/* 末尾告别语 + 萌表情 */
.ai-center-farewell{display:flex;align-items:center;justify-content:center;gap:10px;padding:18px 20px;background:linear-gradient(135deg,#fff8ec 0%,#f9f4ff 100%);border:1px dashed #f0d9a8;border-radius:10px;margin-bottom:8px}
.ai-center-mascot{font-size:24px;animation:ai-mascot-bounce 1.8s ease-in-out infinite;display:inline-block}
.ai-center-farewell-text{font-size:14px;color:#666;font-style:italic;line-height:1.6}
@keyframes ai-mascot-bounce{0%,100%{transform:translateY(0) rotate(0deg)}25%{transform:translateY(-4px) rotate(-3deg)}75%{transform:translateY(-2px) rotate(3deg)}}

@media (max-width:900px){
  .ai-center-grid,.ai-scenarios{grid-template-columns:1fr}
}


/* ===== v1.2.76 实时价格（行情参考页） ===== */
/* 标题栏：品牌 + 时钟 + 营业状态，参照 tiyan.zbxxw.net/h7 顶部品牌区样式 */
.lp-title-bar{display:flex;align-items:center;gap:24px;padding:18px 24px;background:linear-gradient(135deg,#fff7e6 0%,#f9f4ff 60%,#fff 100%);border:1px solid #f0e0c2;border-radius:10px;margin-bottom:12px;flex-wrap:wrap;position:relative;overflow:hidden}
.lp-title-bar::before{content:'';position:absolute;left:0;top:0;width:6px;height:100%;background:linear-gradient(180deg,#c9942a 0%,#f0c060 50%,#c9942a 100%);border-radius:3px 0 0 3px}
.lp-brand{display:flex;align-items:center;gap:10px;flex:1;min-width:240px}
.lp-logo{font-size:28px;line-height:1;filter:drop-shadow(0 1px 2px rgba(201,148,42,.3))}
.lp-brand-name{font-size:20px;font-weight:700;color:#5a4216;letter-spacing:1px;line-height:1.2}
.lp-clock-wrap{display:flex;flex-direction:column;align-items:flex-end;gap:2px;min-width:200px}
.lp-clock{font-family:'Consolas','Courier New',monospace;font-size:24px;font-weight:700;color:#5a4216;line-height:1.2;letter-spacing:1px;font-variant-numeric:tabular-nums}
.lp-day{font-size:13px;color:#8a6d1a;font-weight:600;letter-spacing:1px}
.lp-status{display:inline-flex;align-items:center;gap:6px;padding:6px 14px;border-radius:20px;font-size:13px;font-weight:600;background:#f6ffed;border:1px solid #b7eb8f;color:#389e0d;line-height:1;flex-shrink:0}
.lp-status.online .lp-dot{width:8px;height:8px;border-radius:50%;background:#52c41a;box-shadow:0 0 0 0 rgba(82,196,26,.6);animation:lp-pulse 1.8s ease-in-out infinite;display:inline-block}
.lp-status.closed{background:#fafafa;border-color:#d9d9d9;color:#999}
.lp-status.closed .lp-dot{width:8px;height:8px;border-radius:50%;background:#bfbfbf;display:inline-block}
@keyframes lp-pulse{0%{box-shadow:0 0 0 0 rgba(82,196,26,.6)}70%{box-shadow:0 0 0 8px rgba(82,196,26,0)}100%{box-shadow:0 0 0 0 rgba(82,196,26,0)}}

/* 风险提示条 */
.lp-risk{display:flex;align-items:flex-start;gap:10px;padding:10px 16px;background:linear-gradient(90deg,#fff7e6 0%,#fff1f0 100%);border:1px solid #ffd591;border-left:4px solid #fa8c16;border-radius:6px;font-size:13px;color:#874d00;line-height:1.6;margin-bottom:14px}
.lp-risk-ico{font-size:16px;color:#fa8c16;flex-shrink:0;line-height:1.6}

/* 3 个 tab（视觉占位） */
.lp-tabs{display:flex;gap:2px;border-bottom:2px solid #f0e0c2;margin-bottom:14px}
.lp-tab{padding:9px 22px;font-size:14px;font-weight:600;color:#888;cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-2px;transition:.2s;user-select:none}
.lp-tab:hover{color:#5a4216;background:#fdf8ec}
.lp-tab.active{color:#5a4216;border-bottom-color:#c9942a;background:linear-gradient(180deg,transparent 0%,#fdf8ec 100%)}

/* 行情表格 */
.lp-table-wrap{overflow-x:auto;border:1px solid #f0e0c2;border-radius:8px;background:#fff}
.lp-table{width:100%;border-collapse:collapse;font-size:13px}
/* v1.2.105：四列统一居中（原先名称列左对齐、价格列右对齐） */
.lp-table thead th{background:linear-gradient(180deg,#fdf8ec 0%,#f9f3df 100%);color:#5a4216;font-weight:700;padding:10px 12px;border-bottom:2px solid #e8d8a8;text-align:center;white-space:nowrap;font-size:13px;letter-spacing:.5px;vertical-align:middle}
.lp-table thead th.lp-th-price{text-align:center}
.lp-table tbody td{padding:11px 12px;border-bottom:1px solid #f5efde;color:#333;font-size:13px;vertical-align:middle;text-align:center}
.lp-table tbody tr:hover{background:#fdf8ec}
.lp-table tbody tr:last-child td{border-bottom:none}
.lp-table .lp-price{text-align:center;font-weight:700;font-size:15px;color:#333;font-variant-numeric:tabular-nums;font-family:'Consolas','Courier New',monospace;letter-spacing:.5px}
.lp-table .lp-time{font-family:'Consolas','Courier New',monospace;color:#8a6d1a;font-size:12px;font-variant-numeric:tabular-nums}
/* 🔴 v1.2.203：报价名称列宽由 **10 个汉字** 收窄为 **6 个汉字**（用户再次提出，
   说明 v1.2.158 那次根本没生效）。
   计算：13px 字号下汉字约 13px/字 → 6 字 = 78px；再留左右内边距 12×2 + 边框 1×2 ≈ 103px。
   取 103px。超长名称用 ellipsis 截断而不是撑宽表格 —— 撑宽会把三个价格列挤变形。
   表头 th 与数据 td 必须**同时**带这个宽度，否则表头与数据列宽不一致会错位。

   ⚠️ 上一版（156px / 10 字）为什么没生效 —— 见下方 table-layout 处的说明：
      `thead th{width:25%}` 排在这条**之后**，fixed 布局下首列宽度由 th 决定，
      实测声明 156px 却渲染成 241px。**改了没生效，而且不报任何错。**
      所以下面这条特意用了 !important —— 不是"加保险"，
      而是防止以后有人在后面又加一条同类规则把它悄悄盖掉。 */
.lp-table .lp-th-name{width:103px!important;min-width:103px;max-width:103px}
.lp-table .lp-name{width:103px!important;min-width:103px;max-width:103px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.lp-table .lp-name b{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:700}

/* 涨跌色块（核心视觉）· v1.2.105：text-align 全部由 right 改为 center（四列统一居中） */
.lp-chg{text-align:center;font-weight:600;font-variant-numeric:tabular-nums;font-family:'Consolas','Courier New',monospace}
/* 渐变原本是「左透明 → 右有色」，配合右对齐；居中后改为**居中向两侧淡出**，视觉重心才在中间 */
.lp-chg-up{color:#cf1322;background:radial-gradient(ellipse at center,rgba(255,241,240,.95) 0%,rgba(255,241,240,0) 78%);padding:4px 8px;border-radius:4px;display:inline-block;min-width:60px;text-align:center}
.lp-chg-up::before{content:'▲';margin-right:3px;font-size:10px;opacity:.7}
.lp-chg-down{color:#389e0d;background:radial-gradient(ellipse at center,rgba(246,255,237,.95) 0%,rgba(246,255,237,0) 78%);padding:4px 8px;border-radius:4px;display:inline-block;min-width:60px;text-align:center}
.lp-chg-down::before{content:'▼';margin-right:3px;font-size:10px;opacity:.7}
.lp-chg-flat{color:#999;padding:4px 8px;display:inline-block;min-width:60px;text-align:center}
.lp-chg-flat::before{content:'—';margin-right:3px;opacity:.7}

/* 品类标签 */
.lp-cat{display:inline-block;padding:3px 10px;border-radius:10px;font-size:11px;font-weight:700;letter-spacing:.5px;line-height:1.4}
.lp-cat-au{background:#fff1f0;color:#cf1322;border:1px solid #ffa39e}
.lp-cat-ag{background:#f0f5ff;color:#1d39c4;border:1px solid #adc6ff}
.lp-cat-pt{background:#f9f0ff;color:#531dab;border:1px solid #d3adf7}
.lp-cat-pd{background:#fff7e6;color:#ad6800;border:1px solid #ffd591}

/* 数据源标签 */
.lp-src{display:inline-block;padding:2px 8px;border-radius:10px;font-size:11px;background:#fafafa;color:#888;border:1px solid #e8e8e8}

/* 演示提示 */
.lp-demo-hint{display:flex;align-items:center;gap:10px;padding:10px 16px;background:linear-gradient(90deg,#e6f7ff 0%,#f0f5ff 100%);border:1px dashed #91d5ff;border-radius:6px;font-size:12px;color:#0050b3;line-height:1.6;margin-top:12px}
.lp-demo-tag{display:inline-block;padding:2px 10px;background:#1890ff;color:#fff;border-radius:10px;font-size:11px;font-weight:600;flex-shrink:0}

/* API 配置抽屉 */
#lp-cfg-drawer{margin-top:18px;border-radius:8px;overflow:hidden}
#lp-cfg-drawer .card{margin-bottom:0}

/* v1.2.77 配置区顶部订阅摘要横幅 */
.lp-feed-banner{background:linear-gradient(90deg,#f6ffed 0%,#f0f5ff 100%);border:1px solid #b7eb8f;border-left:4px solid #52c41a;border-radius:6px;padding:10px 14px;margin-bottom:14px}
.lp-feed-banner-row{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:13px}
.lp-feed-label{font-weight:600;color:#389e0d}
.lp-feed-pill{display:inline-flex;align-items:center;gap:4px;padding:2px 10px;border-radius:12px;font-size:12px;font-weight:600;background:#fff;border:1px solid #d9d9d9}
.lp-feed-pill.ok{background:#f6ffed;border-color:#b7eb8f;color:#389e0d}
.lp-feed-pill.empty{background:#fafafa;border-color:#d9d9d9;color:#999}
.lp-feed-pill.warn{background:#fff7e6;border-color:#ffd591;color:#d48806}
.lp-feed-banner-url{margin-top:6px;font-size:12px;color:#666;font-family:Consolas,monospace;word-break:break-all}

/* v1.2.77 订阅状态条 */
.lp-status-bar{display:flex;flex-wrap:wrap;align-items:center;gap:10px;padding:10px 14px;margin-top:12px;border-radius:8px;border:1px solid #e8e0c8;background:linear-gradient(90deg,#fdf8ec 0%,#fff 100%);font-size:13px}
.lp-status-bar.lp-tone-ok{background:linear-gradient(90deg,#f6ffed 0%,#fff 100%);border-color:#b7eb8f}
.lp-status-bar.lp-tone-warn{background:linear-gradient(90deg,#fff7e6 0%,#fff 100%);border-color:#ffd591}
.lp-status-bar.lp-tone-empty{background:linear-gradient(90deg,#fafafa 0%,#fff 100%);border-color:#e0e0e0}
.lp-stat-pill{display:inline-flex;align-items:center;gap:4px;padding:3px 10px;border-radius:14px;font-size:12px;font-weight:600;background:#fff;border:1px solid #d9d9d9;color:#666}
.lp-stat-pill.ok{background:#f6ffed;border-color:#b7eb8f;color:#389e0d}
.lp-stat-pill.warn{background:#fff7e6;border-color:#ffd591;color:#d48806}
.lp-stat-pill.empty{background:#fafafa;border-color:#e0e0e0;color:#999}
.lp-stat-info{font-size:12px;color:#555}
.lp-stat-info b{color:#1677ff;font-weight:600;margin:0 4px}
.lp-stat-err{color:#cf1322 !important}
/* 顶栏订阅徽章（替代原来的「营业中」静态徽章） */
.lp-status.warn{background:#fff7e6;border-color:#ffd591;color:#d48806}
.lp-status.warn .lp-dot{background:#faad14;animation:lp-pulse-warn 1.8s ease-in-out infinite}
.lp-status.empty{background:#fafafa;border-color:#e0e0e0;color:#999}
.lp-status.empty .lp-dot{background:#bfbfbf}
@keyframes lp-pulse-warn{0%{box-shadow:0 0 0 0 rgba(250,173,20,.6)}70%{box-shadow:0 0 0 8px rgba(250,173,20,0)}100%{box-shadow:0 0 0 0 rgba(250,173,20,0)}}

@media (max-width:900px){
  .lp-title-bar{gap:14px;padding:14px 16px}
  .lp-clock{font-size:18px}
  .lp-brand-name{font-size:16px}
  .lp-clock-wrap{min-width:auto;align-items:flex-start}
  .lp-table thead th,.lp-table tbody td{padding:8px 6px;font-size:12px}
  .lp-table .lp-price{font-size:13px}
}
  /* v1.2.86：未推送 wareid 行（表格全表兜底）灰显 */
  .lp-row-empty td{color:#bbb;background:#fafafa}
  .lp-row-empty td b{color:#bbb;font-weight:500}
  .lp-row-empty .lp-price{color:#ccc;font-weight:500}
  .lp-row-empty:hover td{background:#f5f5f5}


/* v1.2.87 实时价格页：SSE 实时推送 + 未推送品种灰显 + 涨跌箭头 + 提示条 */
.lp-banner{margin:0 0 12px;padding:10px 14px;border:1px solid #f0d9a8;background:#fffaf0;border-radius:8px;color:#8a6d1f;font-size:13px;line-height:1.7}
/* v1.2.106：名称列已去掉 wareid 编号（.lp-id 随之删除，避免留死样式） */
.lp-arrow{display:inline-block;margin-right:4px;font-size:11px;line-height:1}
.lp-arrow.up{color:#d93025}
.lp-arrow.down{color:#1a9b57}
.lp-foot{margin-top:10px;font-size:12px;color:#999;line-height:1.7;text-align:right}
.lp-table tbody tr{transition:background .15s}
.lp-table tbody tr:hover{background:#fffdf6}
.lp-row-empty td{color:#c4c4c4;background:#fbfbfb}
.lp-row-empty td b{color:#c4c4c4;font-weight:500}
.lp-row-empty .lp-price{color:#dcdcdc;font-weight:500}
/* 价格刷新时的轻微高亮，让"数据在动"看得见 */
@keyframes lp-flash{0%{background:#fff8e1}100%{background:transparent}}
.lp-row-flash td{animation:lp-flash .8s ease-out}
.lp-closed{color:#c9a227;font-size:12px;font-style:italic}
.lp-row-closed td{background:#fcfaf2}
.lp-row-closed td b{color:#a89670}
/* v1.2.88：企业端只显示平台端启用的商品，名称以下发 name 为准 */
.lp-table tbody td b{font-weight:600}
/* v1.2.90：实时价格四列逐列涨跌着色 + 箭头（回购/销售/最高/最低各自与上一帧比较）
   涨=红、跌=绿（与国内行情习惯一致），持平=灰，无历史=默认深灰。
   背景用极淡的渐变，长时间盯盘不刺眼；箭头与数字同色，一眼看出方向。 */
/* v1.2.105：justify-content 由 flex-end 改为 center（四列居中，箭头+数字整体居中） */
.lp-chg{display:inline-flex;align-items:center;justify-content:center;gap:2px;padding:2px 6px;border-radius:4px;min-width:64px;text-align:center;transition:background .2s}
.lp-chg .lp-arrow{font-style:normal;font-size:10px;line-height:1;opacity:.85}
/* 居中后渐变改为从中心向两侧淡出（原先左透明→右有色是配合右对齐的） */
.lp-chg.up{color:#cf1322;background:radial-gradient(ellipse at center,rgba(255,241,240,.9) 0%,rgba(255,241,240,0) 80%)}
.lp-chg.down{color:#389e0d;background:radial-gradient(ellipse at center,rgba(246,255,237,.9) 0%,rgba(246,255,237,0) 80%)}
.lp-flat{display:inline-block;padding:2px 6px;border-radius:4px;min-width:64px;text-align:center;color:#8c8c8c}
/* 首帧（无历史）不加背景，保持中性 */
.lp-table tbody td.lp-price{font-weight:600}

/* v1.2.93：最高/最低合并成一列，上下两行显示，不带箭头 */
.lp-th-hl{width:150px}
/* v1.2.105：最高/最低两行各自居中（原先靠右 flex-end） */
.lp-price-hl{line-height:1.65;white-space:nowrap;text-align:center}
.lp-hl-row{display:flex;align-items:center;justify-content:center;gap:5px}
.lp-hl-row+.lp-hl-row{margin-top:1px}
.lp-hl-tag{display:inline-block;min-width:17px;padding:0 3px;border-radius:3px;background:#f3efe4;color:#8a7a55;font-size:10px;font-style:normal;text-align:center;line-height:15px}
/* v1.2.95：4 列等宽自适应 + 消除整列抖动 + 最高红/最低绿 + 停用态 */
/* 列宽：table-layout:fixed 让 4 列各占 25%，内容变化不再引起列宽重算
   —— 原来 .lp-chg / .lp-flat 带 min-width:64px，价格位数一变就把整列撑开/收窄，所有行一起抖 */
.lp-table{table-layout:fixed;width:100%}
/* ⚠️ 只有**第一列**按固定宽度，其余三列（价格）平分剩下的宽度。
   —— 原来这里写的是 `.lp-table thead th{width:25%}`（四列等分），
      而它在下方 961 行的 `.lp-th-name{width:156px}` **之后**，
      于是在 table-layout:fixed 下**首列宽度由 th 决定** → 名称列固定 156px 完全失效。
      实测（真实 Chrome）：声明 156px，实际渲染 241px。
      这就是用户「报价名称这一列太宽，之前说过但没改成功」的真正原因 ——
      **不是没改，是改了没生效，而且没有任何报错。**
   ⚠️ 三列价格必须显式分掉剩余宽度：table-layout:fixed 下，
      若不给它们宽度，浏览器会把**剩余空间全补回首列** ——
      实测三列各只有 38px（内容撑不开），名称列被撑到 126px 而非设定的 103px。
      用 calc 平均分掉「100% − 名称列」即可精确控制。 */
.lp-table thead th:not(:first-child),
.lp-table tbody td:not(:first-child){width:calc((100% - 103px) / 3)}
.lp-table tbody td{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.lp-table .lp-price{width:100%}
/* 涨跌块：固定宽度 + **居中**。
   v1.2.105：箭头从「绝对定位钉在左侧」改为「参与文档流」——
   居中布局下绝对定位会直接压在数字上（之前是右对齐，数字靠右、箭头靠左才不冲突）。
   改成 inline-flex 后，箭头与数字成对居中，价格位数变化时一起移动，永不重叠。 */
.lp-table .lp-chg{position:static;display:inline-flex;align-items:center;justify-content:center;gap:3px;width:100%;min-width:0;padding:2px 6px;border-radius:4px;text-align:center;box-sizing:border-box;transition:background .2s}
.lp-table .lp-chg .lp-arrow{position:static;transform:none;flex:0 0 auto;font-style:normal;font-size:10px;line-height:1;opacity:.85}
.lp-table .lp-flat{display:inline-block;width:100%;min-width:0;padding:2px 6px;border-radius:4px;text-align:center;box-sizing:border-box;color:#8c8c8c}
.lp-table .lp-closed{display:inline-block;width:100%;text-align:right;color:#c9a227;font-size:12px;font-style:italic}
/* 🔴 v1.2.222：商品档案 / 库存台账的「实时价」列复用同一套 lp-chg 涨跌样式。
   为什么必须单独限定：
     .lp-chg / .lp-flat 的 min-width:64px 是给行情页那几根**宽价格列**设计的，
     而商品档案、库存台账的实时价列很窄 —— 直接复用会把整列撑宽 64px 起，
     表格横向溢出、手机上尤其难看（这两页都有搜索框，横向滚动体验更差）。
   这里改成自适应宽度：不撑列、居中、与行高一致。
   ⚠️ 颜色/箭头沿用上面那套（涨红▲/跌绿▼/平灰），三处视觉完全一致。 */
.goods-live-delta,.inv-live-delta{display:inline-flex;align-items:center;justify-content:center;
  gap:2px;padding:1px 4px;border-radius:4px;min-width:0;width:100%;box-sizing:border-box;
  text-align:center;font-variant-numeric:tabular-nums;transition:background .2s}
.goods-live-delta .lp-arrow,.inv-live-delta .lp-arrow{font-style:normal;font-size:10px;line-height:1;opacity:.85;margin-right:2px}
.goods-live-delta.up,.inv-live-delta.up{color:#cf1322;background:radial-gradient(ellipse at center,rgba(255,241,240,.9) 0%,rgba(255,241,240,0) 80%)}
.goods-live-delta.down,.inv-live-delta.down{color:#389e0d;background:radial-gradient(ellipse at center,rgba(246,255,237,.9) 0%,rgba(246,255,237,0) 80%)}
.goods-live-flat,.inv-live-flat{display:inline-block;width:100%;min-width:0;padding:1px 4px;
  border-radius:4px;box-sizing:border-box;text-align:center;color:#8c8c8c}
/* 最高=红 / 最低=绿（含「高/低」小标签同色） */
.lp-hl-max{color:#cf1322!important;font-weight:700}
.lp-hl-min{color:#15803d!important;font-weight:700}
.lp-hl-max .lp-hl-tag{background:#fff1f0;border-color:#ffccc7;color:#cf1322}
.lp-hl-min .lp-hl-tag{background:#f6ffed;border-color:#b7eb8f;color:#15803d}
/* 订阅停用态：状态条灰化 + 「已停用」徽章 + 刷新按钮置灰 + 表格提示 */
.lp-status-bar.lp-tone-disabled{background:#f7f7f5;border-color:#e0e0dc;color:#8a8a85}
.lp-badge-stopped{display:inline-block;padding:2px 9px;border-radius:12px;font-size:12px;font-weight:600;background:#f0f0ee;border:1px solid #dcdcd8;color:#8a8a85;margin:0 4px}
.btn.btn-disabled{opacity:.45;cursor:not-allowed;filter:grayscale(.4)}
.btn.btn-disabled:hover{background:#f5f5f3!important;border-color:#d9d9d9!important;color:#8a8a85!important}
.lp-empty-disabled{color:#8a8a85!important;font-size:13px!important;padding:26px 12px!important}
/* 🔴 v1.2.203：报价名称列收窄到 6 个汉字 —— **改的是这一条**。
   （之前两次都改错了地方，见下方说明。）
   <colgroup> 在 table-layout:fixed 下的**优先级高于 th / td**，
   所以真正决定列宽的是这条 col 规则，不是 .lp-th-name。 */
.lp-table col.lp-c-name{width:103px}
.lp-table col.lp-c-buy,.lp-table col.lp-c-sale,.lp-table col.lp-c-hl{width:auto}

/* ⚠️ v1.2.203：这里曾经踩了一个很典型的坑，值得记下来 ——
//   「CSS 写了但没生效，改了两次都没用，而且没有任何报错」：
//
//   ① v1.2.158 写的是 `.lp-th-name{width:156px}`（10 汉字）。
//      用户反馈「还是太宽」→ 又改成 103px（6 汉字）→ **依然没变**。
//   ② 真实 Chrome 实测：声明 156px，实际渲染 **241px**（= 25% × 964px）。
//   ③ 真正的原因：表格用了 `<colgroup><col class="lp-c-name">…`，
//      而 `table-layout:fixed` 下 **colgroup 的优先级高于 th/td**。
//      本文件 1122 行有 `col.lp-c-name{width:25%}` ——
//      它把前面所有的 th/td 宽度设置**全部压住了**。
//   ④ 所以修 th、改 th:not(:first-child) 都无效，
//      必须改这条 col 规则本身。
//
// 🔑 教训：**改表格列宽前，先确认列宽到底由谁决定。**
//   table-layout:fixed 下优先级是：colgroup/col > th > td。
//   不确定就先用 DevTools 查 computed style，或者直接量 getBoundingClientRect()，
//   **别看自己写的 CSS 就以为它生效了**。 */

/* ══════════════════════════════════════════════════════════════════════
   v1.2.105：实时价格四列全部**上下左右居中**
   ──────────────────────────────────────────────────────────────────────
   改之前：名称列左对齐、三个价格列右对齐（text-align:right）。

   ⚠️ 关键：箭头原本是 `position:absolute; left:2px` 钉在单元格左边 ——
      那是**右对齐布局的配套写法**（数字靠右、箭头靠左，正好不冲突）。
      一旦改成居中，绝对定位的箭头会直接压在数字上。
      所以箭头必须同时改回**文档流**：inline-flex 让「箭头 + 数字」成对居中，
      价格位数变化时一起移动，永不重叠。

   实现方式：直接改掉各层历史规则里的 text-align / justify-content /
   position（.lp-chg 在本文件里有 5 处历史定义，层层覆盖），
   **不在文件末尾打补丁** —— 末尾追加只会再多一层覆盖，是以前留下技术债的原因。
   ══════════════════════════════════════════════════════════════════════ */
/* 表头 + 数据单元格统一居中；名称列的 wareid 编号随名称一起居中 */
.lp-table thead th,
.lp-table thead th.lp-th-price{text-align:center}
.lp-table tbody td{text-align:center}
.lp-table tbody td.lp-price{text-align:center}
.lp-table .lp-price{text-align:center}
.lp-table .lp-hl-row{justify-content:center}
/* 涨跌块：箭头回文档流，成对居中 */
.lp-table .lp-chg{vertical-align:middle}
/* 停牌（.lp-closed）本文件里只有这一处 text-align 定义 */
.lp-table .lp-closed{text-align:center}
.lp-table .lp-hl-row{display:flex;align-items:center;justify-content:center;gap:5px}

/* ══════════════════════════════════════════════════════════════════════
   v1.2.107：单行明细限制的提示文案
   ──────────────────────────────────────────────────────────────────────
   「添加商品」按钮置灰时，在旁边说明为什么不能加 —— 只置灰不说原因，
   操作员会以为按钮坏了。开启单行模式且已有明细时显示。
   ══════════════════════════════════════════════════════════════════════ */
.additem-tip{font-size:12px;color:#b45309;margin-left:8px;line-height:1.5}
@media (max-width:768px){
  /* 移动端：提示独占一行，避免和标题、按钮挤在一起 */
  .additem-tip{display:block;margin:6px 0 0;width:100%}
}

/* ══════════════════════════════════════════════════════════════════════
   v1.2.113：明细标题栏（「商品明细」+「添加商品」同一行）
   ──────────────────────────────────────────────────────────────────────
   原来用 inline style 的 `justify-content:space-between`，按钮被推到**最右侧**。
   现在要求：按钮紧跟在「商品明细」四个字后面，**间隙留 2 个汉字宽度**。
   2 个汉字 ≈ 2em（中文正文字号 1em=一个汉字宽），这里用 2em 精确对应。
   ══════════════════════════════════════════════════════════════════════ */
.lp-items-bar{display:flex;align-items:center;gap:2em;margin-bottom:8px;flex-wrap:wrap}
/* 「添加商品」置灰时的提示（单行明细限制）
   ⚠️ v1.2.114：提示与标题之间隔了 2em + 与按钮之间又隔 2em，
   提示文字较长时会「插在」标题和按钮中间，视觉上把按钮顶得远离标题。
   这里给提示单独加大左间距，让「标题 + 按钮」保持成一个紧凑的整体，
   提示退到右侧成为附属说明。 */
.lp-items-bar .additem-tip{font-size:12px;color:#b45309;line-height:1.5;margin-left:1.5em;flex:1 1 auto;min-width:0}
/* 换料单侧栏标题：标题 / 小计 / 添加按钮 同一行，按钮紧跟，间隙 2em */
.ex-side-head{gap:2em}
.ex-side-head .ex-side-sub{font-weight:400;font-size:12px;opacity:.85}

/* ══════════════════════════════════════════════════════════════════════
   v1.2.113 需求④：明细下方的「备注」输入框不能被挡住
   ──────────────────────────────────────────────────────────────────────
   现象：删除按钮换行后把整行撑高，底部的单据备注框被遮住 / 挤到视口外。
   处理：
   ① 明细区本身限高并允许纵向滚动，行再多也不会无限撑高弹窗；
   ② 单据备注框加最小高度与 flex-shrink:0，保证不被压扁；
   ③ 明细区与备注之间留出间距，视觉上不粘连。
   ══════════════════════════════════════════════════════════════════════ */
.items-scroll{max-height:42vh;overflow:auto;padding-bottom:6px}
.items-scroll .item-row,.items-scroll .ex-item-row{margin-bottom:8px}
/* 单据级备注（po_remark / so_remark / ex_remark / pn_remark 等）不被压缩 */
.modal-body .form-row{margin-top:12px;flex-shrink:0}
.modal-body .form-row input[type=text],
.modal-body .form-row input:not([type]),
.modal-body .form-row textarea{min-height:34px}
.modal-body textarea{flex-shrink:0}

/* ══════════════════════════════════════════════════════════════════════
   v1.2.114：明细行响应式断点修正 —— 640px → 900px
   ──────────────────────────────────────────────────────────────────────
   问题（真实 Chrome 实测 820px 平板视口）：
   12 列固定像素合计 768 + gap 66 = 834px，而 820 视口下弹窗内容区只有 747px
   → **溢出 87px，出现横向滚动条**，且仍是横向 12 列挤在一起，可读性很差。

   原来卡片化断点是 640px，于是 641~900px 这段区间正好是
   「桌面 12 列布局」但「容器装不下」的最差状态。

   现在把**明细行专属**的卡片化提前到 900px，与页面其它 900px 断点一致。
   放在独立的 @media(max-width:900px) 块里，不改动 640px 块里的其它规则
   （stat-grid / perm-grid 等与明细无关），避免误伤。

   ──────────────────────────────────────────────────────────────────────
   v1.2.133：单价/工费各 ×1.5 后总宽由 834px → **868px**，
   原 900px 断点已不够（900 视口下弹窗内容区仅 824px，会溢出 44px）。
   按 0.96×视口 − 40px 内边距 反推：868px 需要视口 ≥ 946px，
   取整把断点提到 **960px**（留 14px 余量），保证「非卡片模式 = 一定装得下」。
   ══════════════════════════════════════════════════════════════════════ */
@media (max-width:960px){
  /* 明细行 → 卡片化（两列网格，标签在上、控件在下） */
  .items-scroll .item-row,
  .items-scroll .ex-item-row{
    display:grid;
    grid-template-columns:1fr 1fr!important;   /* !important 覆盖上面的 12 列定义 */
    gap:9px 10px;
    border:1px solid #eee;border-radius:10px;padding:12px;position:relative;
    background:#fff;margin-bottom:10px;
    box-shadow:0 1px 3px rgba(0,0,0,.05);
    min-width:0!important;
  }
  /* 表头在卡片模式下没有意义（标签已用 data-lb 伪元素显示） */
  .items-scroll .item-row.row-head,
  .items-scroll .ex-item-row.ex-head{display:none}
  /* .fld 恢复成「标签 + 控件」一行（覆盖 640px 块里的同规则，效果一致但提前生效） */
  .items-scroll .fld{display:flex;align-items:center;gap:8px;min-width:0}
  .items-scroll .fld::before{content:attr(data-lb);font-size:12px;color:#999;flex-shrink:0;min-width:4.4em;font-weight:600}
  .items-scroll .fld.wide{grid-column:1/-1}
  /* 删除按钮移到卡片右上角 */
  .items-scroll .fld.del{position:absolute;top:8px;right:8px}
  .items-scroll .fld.del::before{content:none}
  .items-scroll .fld.del .btn{width:28px;height:28px;min-width:28px;min-height:28px;padding:0;
    display:inline-flex;align-items:center;justify-content:center;font-size:14px;border-radius:6px}
  /* 「结式」「数量」避开右上角的 X */
  .items-scroll .item-row .fld[data-lb]::before{min-width:4.4em}
  .items-scroll .item-row .fld:nth-child(1),
  .items-scroll .item-row .fld:nth-child(3){padding-right:32px}
  /* 触屏字号放大 */
  .items-scroll .item-row input,.items-scroll .item-row select,
  .items-scroll .ex-item-row input,.items-scroll .ex-item-row select{
    font-size:16px;padding:8px 10px;flex:1;min-width:0
  }
  .items-scroll .item-row input[readonly],
  .items-scroll .ex-item-row input[readonly]{background:#fafafa}
  .items-scroll .ex-no-fee{flex:1;text-align:center;color:#bbb}
  /* v1.2.114：卡片模式下**保留限高**，否则行数一多会把弹窗撑到几万像素，
     单据底部的「备注」框被推到天边（实测 390px 视口下备注 top=8002px）。
     给一个较高的上限即可兼顾「能看全」与「备注不被推走」。 */
  .items-scroll{max-height:60vh;overflow:auto}
}

/* ══════════════════════════════════════════════════════════════════════
   v1.2.114：居间介绍下拉 = 8 个汉字宽
   ──────────────────────────────────────────────────────────────────────
   原来它没有 class，直接继承 .form-row select{width:100%} → 撑满整行（实测 820px）。
   按需求限制为 8 个汉字宽度。

   ⚠️ 特异性要点：`.form-row input,.form-row select` 的特异性是 (0,1,1)，
      比 `.ref-select`(0,1,0) **更高**。所以这里必须写成 `.form-row select.ref-select`
      才能真正覆盖 width；否则 width:100% 会把它重新拉满。
   ⚠️ 同时显式给 height（与同排其它控件一致 34px），避免被内容撑成竖长条。
   ══════════════════════════════════════════════════════════════════════ */
.form-row select.ref-select{
  width:138px;max-width:138px;min-width:0;
  /* ⚠️ 不用 flex:0 0 138px —— .form-row 是 flex-direction:column，
     这里的 flex-basis 控制的是**高度**而不是宽度，会把下拉撑成 138px 高的竖条（实测）。
     只锁 width，让它按内容高度自适应；align-self 防 stretch 拉宽。 */
  align-self:flex-start;
  height:34px;padding:6px 26px 6px 8px;
}
@media (max-width:768px){
  /* 移动端按 8 汉字等比放大（16px 字号） */
  .form-row select.ref-select{width:9em;max-width:9em;height:40px}
}

@media (max-width:768px){
  /* v1.2.114 修正：原先这里是 max-height:none —— 明细一多就把弹窗撑到几万像素，
     单据底部的「备注」框被推到视口外（实测 390px 视口下备注 top=8002px）。
     卡片化后单行本身很高，但仍要给一个上限，否则备注框形同消失。 */
  .items-scroll{max-height:60vh;overflow:auto}
  .lp-items-bar{gap:1em}
  .ex-side-head{gap:1em;flex-wrap:wrap}
}

/* ══════════════════════════════════════════════════════════════════════
   v1.2.121：「不适用」占位（提料不定价的单价列）
   ──────────────────────────────────────────────────────────────────────
   结算方式锁死为「结料」的单据，单价根本不参与计算（金额 = 数量×净重×工费），
   服务端明细表也没有 price 列。用「—」占位而不是置灰输入框 ——
   表头写着「单价」而下面放个灰框，用户会更困惑。
   手法与换料来料侧的工费列（ex-no-fee）保持一致。
   ══════════════════════════════════════════════════════════════════════ */
.lp-no-applicable{display:block;text-align:center;font-size:12px;color:#bbb;cursor:help;user-select:none}

/* ── v1.2.148 期末对账：把「算出来的结果」与「过程构成项」在视觉上分开 ──
   背景：表格下方写了「期末存欠料 = ……」的公式，但表里 15 列全是过程项，
        结果列「存欠料/存欠款」夹在中间没有任何视觉区分，用户既找不到、也
        不知道该加哪几列。本版把结果列挪到最右并加左边框 + 浅底色。
   为什么用「左边框 + 浅底」而不是深色底：深色会让人以为这是可点击的按钮或
        需要特殊权限的字段；浅底只表达「这是结论」，不改变语义。 */
.recon-cards th.col-final,
.recon-cards td.col-final {
  position: relative;
  background: #fffaf0;
  font-weight: 600;
}
.recon-cards th.col-final::before,
.recon-cards td.col-final::before {
  content: '';
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 2px;
  background: #d9b36c;
}
.recon-cards th.col-final { background: #fdf3e0; }
/* 窄屏（转卡片布局）时不需要分隔线，底色保留即可 */
@media (max-width: 820px) {
  .recon-cards td.col-final::before { display: none; }
  .recon-cards td.col-final { border-top: 2px solid #d9b36c; }
}

/* ══════════════════════════════════════════════════════════════════════════
   v1.2.152：实时价格页拆成两个 tab —— 「价格设置」/「实时价格」
   （企业端自己管：显示哪些商品、自定义名称、要不要加价；
     平台端只管：对接地址、心跳、刷新频率、开放几号数据源）
   ══════════════════════════════════════════════════════════════════════════ */
.lp-tabs{display:flex;gap:4px;margin:0 0 14px;border-bottom:2px solid #e8d8a8}
.lp-tab{padding:9px 22px;border:1px solid #e8d8a8;border-bottom:none;border-radius:8px 8px 0 0;
  background:linear-gradient(180deg,#fdf8ec 0%,#f7efdc 100%);color:#8a6d1a;font-size:14px;font-weight:600;
  cursor:pointer;user-select:none;transition:all .15s}
.lp-tab:hover{background:linear-gradient(180deg,#fffaf0 0%,#fbf3e2 100%);color:#6b551a}
.lp-tab.on{background:linear-gradient(180deg,#fff 0%,#fffdf6 100%);color:#5a4216;
  border-color:#d9b36c;box-shadow:0 -2px 6px rgba(217,179,108,.25);font-weight:700}
.lp-tab-body{display:none}
.lp-tab-body.on{display:block}

/* 价格设置表 */
.lp-set-wrap{overflow-x:auto;border:1px solid #f0e0c2;border-radius:8px;background:#fff}
.lp-set-tb{width:100%;border-collapse:collapse;font-size:13px;min-width:760px}
/* 🔴 v1.2.237：没有 table-layout:fixed 时，浏览器按内容分配列宽，
   td 上的 min-width/width 对表格列**无效** —— 这就是"报价名称列改不窄"的真凶。
   配合 app.js 里的 <colgroup> 才能真正生效。 */
.lp-set-tb{table-layout:fixed}
.lp-set-tb thead th{background:linear-gradient(180deg,#fdf8ec 0%,#f9f3df 100%);color:#5a4216;
  font-weight:700;padding:10px 12px;border-bottom:2px solid #e8d8a8;text-align:center;
  white-space:nowrap;font-size:13px;letter-spacing:.5px}
.lp-set-tb tbody td{padding:7px 10px;border-bottom:1px solid #f5efde;color:#333;text-align:center;vertical-align:middle}
.lp-set-tb tbody tr:hover{background:#fdf8ec}
.lp-set-tb tbody tr:last-child td{border-bottom:none}
.lp-set-tb tbody tr.lp-set-off{color:#a0a0a0;background:#fbfbfb}
.lp-set-tb tbody tr.lp-set-off .lp-set-name{color:#a0a0a0}
.lp-set-tb .lp-set-id{width:62px;color:#999;font-variant-numeric:tabular-nums}
.lp-set-tb .lp-set-origin{text-align:left;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* 🔴 v1.2.237：报价名称列的 `white-space:nowrap` 会**撑宽整列** ——
   内容多长列就多宽，td 上的 min-width 完全不起作用（用户第 3 次提出这个问题）。
   改成不换行 + 溢出省略，宽度才由 <colgroup> 说��。 */
.lp-set-tb .lp-set-name{text-align:left;color:#333;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* v1.2.237：宽度真正由 app.js 里的 <colgroup> 控制（104px ≈ 6 个汉字 + 内边距）。
   这里只保证 input 不撑破容器。 */
.lp-set-tb .lp-set-name input{width:100%;min-width:0;max-width:100%}
.lp-set-tb .lp-set-chk{width:52px}
.lp-set-tb .lp-set-chk input{width:auto}
.lp-set-tb .lp-set-num{width:86px}
.lp-set-tb .lp-set-num input{width:74px;text-align:center;padding:4px 6px}
.lp-set-tb .lp-set-eff{font-size:12px;color:#8a7a55;text-align:left}
.lp-set-tag{display:inline-block;margin-left:6px;padding:1px 6px;border-radius:8px;font-size:11px;
  background:#fff7e6;border:1px solid #ffd591;color:#d48806}
.lp-set-bar{display:flex;flex-wrap:wrap;align-items:center;gap:10px;margin-bottom:12px;
  padding:10px 14px;border-radius:8px;border:1px solid #e8e0c8;
  background:linear-gradient(90deg,#fdf8ec 0%,#fff 100%);font-size:13px}
.lp-set-bar .spacer{flex:1}
.lp-set-bar input[type=number]{width:74px;text-align:center;padding:4px 6px}
@media (max-width:820px){
  .lp-tab{padding:8px 14px;font-size:13px}
  .lp-set-tb{font-size:12px;min-width:700px}
}

/* ══════════════════════════════════════════════════════════════════════════
   v1.2.161【操作知识库】AI 问答的展示样式
   ──────────────────────────────────────────────────────────────────────────
   设计取舍：答案区放在 AI 输入条**下方**、用卡片包住 —— 而不是弹窗或跳转新页。
     ① 用户问完话还能看到答案，再问下一个时直接被覆盖，不堆积；
     ② 答案里带「参考出处」可展开，用户能核对原文，答案有据可依；
     ③ 移动端天然在输入框附近，不用往上滑。
   ══════════════════════════════════════════════════════════════════════════ */
.ai-chips-label{font-size:11px;color:#8a7a55;margin-right:2px;align-self:center}
.ai-chip-kb{background:#f3f7ff;border-color:#c8d8f8;color:#2563eb}
.ai-chip-kb:hover{background:#e6efff;border-color:#adc6ff;color:#1d4ed8}

.ai-answer{
  flex-basis:100%;margin-top:4px;padding:12px 14px;border-radius:8px;
  background:#fbfcfe;border:1px solid #dbe4f0;font-size:13.5px;color:#333;
  line-height:1.75;max-height:60vh;overflow-y:auto;
}
.ai-answer-head{font-size:12px;color:#2563eb;font-weight:600;margin-bottom:6px}
.ai-answer-q{
  font-size:13px;color:#555;background:#fff;border-left:3px solid #93c5fd;
  padding:6px 10px;border-radius:0 5px 5px 0;margin-bottom:8px;
}
.ai-answer-body ol,.ai-answer-body ul{margin:4px 0;padding-left:20px}
.ai-answer-body>div>mark,.ai-answer-body mark{background:#fff3bf;color:inherit;padding:0 1px;border-radius:2px}
.ai-answer details{border-left:2px solid #e5e7eb;padding-left:9px}
.ai-answer details summary:hover{text-decoration:underline}
.ai-answer details[open] summary{margin-bottom:2px}

@media (max-width:640px){
  .ai-answer{max-height:52vh;font-size:13px;padding:10px 12px}
}

/* ══════════════════════════════════════════════════════════════════════════
   v1.2.165 操作手册页
   ──────────────────────────────────────────────────────────────────────────
   布局：左目录 + 右正文（PC）；移动端目录收起、正文全宽。
   ⚠️ 移动端不能沿用「两列 grid」—— 说明书表格本来就宽，再分一半就没法读了。
     所以 ≤768px 改成**单列 + 目录横向滚动条**，保证表格有整屏宽度。
   ══════════════════════════════════════════════════════════════════════════ */
.mn-search-card{padding:14px 16px}
.mn-q{width:100%;height:40px;padding:0 12px;border:1px solid #ddd;border-radius:8px;font-size:15px;box-sizing:border-box;outline:none}
.mn-q:focus{border-color:var(--primary)}
.mn-hint{font-size:12px;color:#999;margin-top:6px}
.mn-result{margin-top:10px}
.mn-res-t{font-size:12px;color:#888;margin-bottom:6px}
.mn-res-i{display:flex;gap:8px;align-items:baseline;padding:8px 10px;border-radius:6px;cursor:pointer;font-size:14px;line-height:1.5}
.mn-res-i:hover{background:#f7f8fa}
.mn-res-c{font-size:11px;color:#fff;background:#9aa4b2;border-radius:4px;padding:1px 6px;flex-shrink:0;white-space:nowrap}
.mn-res-n{color:#333}
.mn-no{font-size:13px;color:#b45309;padding:6px 0}

.mn-layout{display:flex;gap:16px;align-items:flex-start}
/* 目录：PC 端固定宽度、过长时自身内部滚动（不撑高整页） */
.mn-nav{flex:0 0 232px;position:sticky;top:12px;max-height:calc(100vh - 96px);overflow:auto;
  background:#fff;border-radius:8px;padding:8px;box-shadow:0 1px 4px rgba(0,0,0,.08);margin-bottom:16px}
.mn-chap{border-radius:6px;padding:4px 0;margin-bottom:2px}
.mn-chap-t{font-size:13px;font-weight:600;color:#444;padding:7px 10px;border-radius:6px;cursor:pointer}
.mn-chap-t:hover{background:#f5f6f8}
.mn-chap.on .mn-chap-t{background:var(--primary);color:#fff}
.mn-chap-s{display:none;padding:2px 0 6px}
.mn-chap.on .mn-chap-s{display:block}
.mn-sec{font-size:12.5px;color:#666;padding:5px 10px 5px 20px;border-radius:6px;cursor:pointer;line-height:1.45}
.mn-sec:hover{background:#f5f6f8;color:#333}
.mn-sec.on{background:#fff3e0;color:#b8791f;font-weight:600}

.mn-main{flex:1;min-width:0;margin-bottom:16px}
.mn-doc-title{font-size:19px;font-weight:700;color:#222;padding-bottom:10px;border-bottom:2px solid #f0f0f0;margin-bottom:6px}
.mn-doc-sec{font-size:15px;font-weight:600;color:#444;margin:14px 0 10px}
.mn-doc-body{font-size:14.5px;line-height:1.9;color:#333;word-break:break-word}
.mn-h3{font-size:15px;font-weight:600;color:#333;margin:16px 0 6px;padding-left:9px;border-left:3px solid var(--primary)}
.mn-h4{font-size:14px;font-weight:600;color:#555;margin:12px 0 4px}
.mn-p{margin:6px 0}
.mn-ul,.mn-ol{margin:6px 0;padding-left:22px}
.mn-ul li,.mn-ol li{margin:3px 0}
.mn-li-sub{font-size:13px;color:#666;padding-left:14px;margin:2px 0 2px 0}
.mn-quote{background:#f8f9fb;border-left:3px solid #dcdfe6;padding:8px 12px;margin:8px 0;border-radius:0 6px 6px 0;color:#555;font-size:13.5px;line-height:1.8}
.mn-pre{background:#282c34;color:#e6e6e6;padding:12px 14px;border-radius:6px;overflow:auto;font-size:12.5px;line-height:1.7;margin:8px 0;
  font-family:Consolas,Monaco,'Courier New',monospace;white-space:pre-wrap}
.mn-code{background:#f3f4f6;padding:1px 5px;border-radius:3px;font-size:12.5px;font-family:Consolas,Monaco,monospace}
.mn-link{color:#2563eb;text-decoration:none;border-bottom:1px dashed #bfdbfe;cursor:default}
.mn-hr{border:0;border-top:1px solid #eee;margin:14px 0}
/* 表格：说明书里表格是主要信息载体，必须能横向滚动而不是被挤变形 */
.mn-tbl-wrap{overflow-x:auto;margin:10px 0;-webkit-overflow-scrolling:touch}
.mn-tbl{border-collapse:collapse;width:100%;min-width:420px;font-size:13.5px}
.mn-tbl th,.mn-tbl td{border:1px solid #e3e6ea;padding:7px 10px;text-align:left;vertical-align:top;line-height:1.7}
.mn-tbl th{background:#f7f8fa;font-weight:600;color:#444;white-space:nowrap}
.mn-tbl tr:nth-child(even) td{background:#fcfcfd}

.mn-toc{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:10px;margin-top:8px}
.mn-toc-i{border:1px solid #e8eaed;border-radius:8px;padding:10px 12px;cursor:pointer;background:#fcfcfd}
.mn-toc-i:hover{border-color:var(--primary);background:#fff}
.mn-toc-t{display:block;font-size:14px;font-weight:600;color:#333;margin-bottom:3px}
.mn-toc-p{display:block;font-size:12px;color:#999;line-height:1.6;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mn-more{margin-top:22px;padding-top:14px;border-top:1px solid #eee}
.mn-more-t{font-size:13px;color:#888;margin-bottom:8px}
.mn-more-i{display:inline-block;font-size:13px;color:#2563eb;background:#f3f7ff;border-radius:6px;padding:5px 10px;margin:0 6px 6px 0;cursor:pointer}
.mn-more-i:hover{background:#e5eeff}
.mn-doc-body mark,.mn-toc-i mark{background:#fff3bf;padding:0 1px;border-radius:2px}

@media (max-width:768px){
  /* 单列：目录变成横向滚动的章标签，正文占满整屏 —— 说明书表格有整屏宽度才读得下去 */
  .mn-layout{flex-direction:column;gap:10px}
  .mn-nav{flex:none;width:100%;position:static;max-height:none;display:flex;gap:6px;overflow-x:auto;overflow-y:hidden;padding:6px;
    -webkit-overflow-scrolling:touch;scrollbar-width:none}
  .mn-nav::-webkit-scrollbar{display:none}
  .mn-chap{flex:0 0 auto;margin:0}
  .mn-chap-t{white-space:nowrap;padding:6px 12px;font-size:13px}
  .mn-chap-s{display:none!important}
  .mn-main{width:100%}
  .mn-doc-title{font-size:17px}
  .mn-doc-body{font-size:14px;line-height:1.85}
  .mn-toc{grid-template-columns:1fr}
  .mn-search-card{padding:12px}
  .mn-q{height:38px;font-size:14px}
}

/* ══════════════════════════════════════════════════════════════════════════
   v1.2.174 合同签署操作指南弹窗
   ──────────────────────────────────────────────────────────────────────────
   场景：用户已经在合同管理页，要开单了才想起来"流程怎么走"。
   所以做成**就地展开的弹窗**，不去新页面、不打断上下文。
   移动端：与手册页同样的处理 —— 目录收成横向滚动条，正文占满整屏。
   ══════════════════════════════════════════════════════════════════════════ */
.gd-layout{display:flex;gap:14px;align-items:flex-start}
.gd-nav{flex:0 0 210px;position:sticky;top:0;max-height:calc(100vh - 220px);overflow:auto;
  background:#fbfbfc;border-radius:8px;padding:8px}
.gd-nav-t{font-size:12px;font-weight:700;color:#8a7a55;padding:6px 8px 8px;line-height:1.5}
.gd-nav-i{font-size:12.5px;color:#555;padding:7px 9px;border-radius:6px;cursor:pointer;line-height:1.5}
.gd-nav-i:hover{background:#f0f1f3;color:#333}
.gd-nav-i.on{background:#fff3e0;color:#b8791f;font-weight:600}

.gd-main{flex:1;min-width:0}
.gd-doc-sec{font-size:15px;font-weight:600;color:#444;margin-bottom:10px;padding-bottom:8px;
  border-bottom:1px solid #f0f0f0}
.gd-doc-body{font-size:14.5px;line-height:1.9;color:#333;word-break:break-word}
/* 复用手册页的排版（mn-* 是现成的，这里只做尺寸微调） */
.gd-doc-body .mn-tbl{font-size:13px}
.gd-doc-body .mn-pre{font-size:12px}
.gd-doc-body .mn-quote{font-size:13px}
.gd-doc-body .mn-li-sub{font-size:13px}
.gd-foot{display:flex;align-items:center;gap:10px;margin-top:20px;padding-top:14px;border-top:1px solid #eee}

@media (max-width:768px){
  /* 单列：目录横向滚动，正文占满整屏（指南里的表格本来就宽） */
  .gd-layout{flex-direction:column;gap:8px}
  .gd-nav{flex:none;width:100%;position:static;max-height:none;display:flex;gap:6px;overflow-x:auto;
    padding:6px;-webkit-overflow-scrolling:touch;scrollbar-width:none}
  .gd-nav::-webkit-scrollbar{display:none}
  .gd-nav-t{display:none}
  .gd-nav-i{flex:0 0 auto;white-space:nowrap;padding:6px 12px;font-size:13px}
  .gd-main{width:100%}
  .gd-doc-body{font-size:14px;line-height:1.85}
}

/* ══════════════════════════════════════════════════════════════════════════
   v1.2.175 图形化流程图（```flow 围栏）
   ──────────────────────────────────────────────────────────────────────────
   为什么要图形化：原来的 ASCII 字符画（①…→…↓）在等宽代码块里，
   字号、行距、粗细全被锁死；手机上挤成一团、箭头错位，几乎读不了。

   设计要点：
   ① **配色按角色分** —— 客户(蓝) / 你(琥珀) / 系统(绿)。
      操作员一眼就能看出"这一步是谁做"，不用读文字才知道。
   ② 卡片左侧一个序号圆点，箭头单独占一行（不是字符画的 ↓）。
   ③ **移动端优先**：竖排本来就适合窄屏，只需缩小圆点与内边距。
   ④ 徽标（"必须先做"/"必做一步"）用右侧浅色小标签，不抢主标题。
   ══════════════════════════════════════════════════════════════════════════ */
.fl-wrap{margin:14px 0 18px;padding:4px 0;max-width:100%;overflow-x:hidden}
/* 一步 */
.fl-step{display:flex;align-items:stretch;gap:12px;min-width:0}
.fl-no{flex:0 0 30px;width:30px;height:30px;border-radius:50%;display:flex;align-items:center;
  justify-content:center;font-size:14px;font-weight:700;color:#fff;position:relative;top:12px;
  background:#9aa4b2;box-shadow:0 1px 3px rgba(0,0,0,.15)}
.fl-card{flex:1 1 auto;min-width:0;max-width:100%;border:1px solid #e6e8eb;border-left:3px solid #9aa4b2;
  border-radius:8px;padding:11px 14px;background:#fff}
/* ⚠️ flex 容器链路上**每一层都要 min-width:0** ——
   否则里面的长中文/长路径（如「合同管理 → 点「🔄 同步状态」」）会把 flex 行撑到内容宽度，
   手机上表现为整页横向滚动、内容被裁掉一半。
   v1.2.175 实测：未加时 390px 容器被撑到 scrollWidth=749。*/
.fl-head{display:flex;align-items:center;gap:8px;flex-wrap:wrap;line-height:1.5;min-width:0}
.fl-role{font-size:11px;font-weight:600;padding:2px 8px;border-radius:10px;
  background:#eef0f3;color:#5b6472;white-space:nowrap}
.fl-title{font-size:14.5px;font-weight:600;color:#2b2f36;min-width:0;
  overflow-wrap:anywhere;word-break:break-word}
.fl-badge{font-size:11px;padding:1px 7px;border-radius:8px;background:#f4f6f8;color:#78828f;
  border:1px solid #e8ebee;white-space:nowrap;max-width:100%;overflow:hidden;text-overflow:ellipsis}
.fl-desc{font-size:13px;color:#666;line-height:1.75;margin-top:4px;min-width:0;
  overflow-wrap:anywhere;word-break:break-word}
/* 「自动」标识：系统步骤不需要人操作，给个视觉区分 */
.fl-auto{font-size:10.5px;font-weight:600;padding:1px 6px;border-radius:8px;
  background:#1f9d6b;color:#fff;white-space:nowrap}

/* 三种角色配色 */
.fl-cust .fl-no{background:#2f6fd0}
.fl-cust .fl-card{border-left-color:#2f6fd0;background:#f7faff}
.fl-cust .fl-role{background:#e3edfb;color:#2f6fd0}

.fl-you .fl-no{background:#d98218}
.fl-you .fl-card{border-left-color:#d98218;background:#fffaf2}
.fl-you .fl-role{background:#fdefdc;color:#b96d0c}

.fl-sys .fl-no{background:#1f9d6b}
.fl-sys .fl-card{border-left-color:#1f9d6b;background:#f5fbf8}
.fl-sys .fl-role{background:#dff3ea;color:#1b8359}

/* 箭头：竖线 + 箭头头部（纯 CSS，不用字符）
   ⚠️ 位置要对准**卡片的中轴**，不是序号圆点 ——
   箭头偏在圆点左边会显得松散、像没对齐（v1.2.175 截图后发现）。
   公式：卡片左边界 = 圆点宽(30) + gap(12) = 42px，卡片宽 = 100% - 42px，
   中轴 = 42 + (100% - 42)/2 = 50% + 21px。用 calc 表达，随容器自适应。 */
.fl-arrow{position:relative;height:22px}
.fl-arrow span{position:absolute;top:0;bottom:0;width:2px;background:#cdd3da;
  left:calc(50% + 21px);transform:translateX(-1px)}
.fl-arrow span::after{content:'';position:absolute;left:-4px;bottom:0;
  border-left:5px solid transparent;border-right:5px solid transparent;
  border-top:7px solid #cdd3da}

@media (max-width:768px){
  .fl-step{gap:9px}
  .fl-no{flex-basis:24px;width:24px;height:24px;font-size:12px;top:11px}
  .fl-card{padding:9px 11px;border-radius:6px}
  .fl-title{font-size:14px}
  .fl-desc{font-size:12.5px;line-height:1.7}
  .fl-role,.fl-badge{font-size:10.5px;padding:1px 6px}
  /* 中轴同样要跟着挪：圆点 24 + gap 9 = 33 → 中轴 = 50% + 16.5px */
  .fl-arrow{height:18px}
  .fl-arrow span{left:calc(50% + 16.5px)}
  /* 徽标在窄屏换行到下一行，避免标题被挤成两行 */
  .fl-head{gap:6px}
}

/* ══════════════════════════════════════════════════════════════
   🔴 v1.2.247 扫码核销（USB 扫码枪键盘流）
   状态灯：idle 灰 / busy 黄闪 / ok 绿 / err 红 —— 操作员扫一下
   就知道系统接没接收到，不用盯着输入框猜。
   ══════════════════════════════════════════════════════════════ */
.pwo-lamp{width:10px;height:10px;border-radius:50%;background:#d9d9d9;flex:none;transition:background .15s}
.pwo-lamp.busy{background:#faad14;animation:pwo-blink .8s infinite}
.pwo-lamp.ok{background:#52c41a}
.pwo-lamp.err{background:#ff4d4f}
@keyframes pwo-blink{50%{opacity:.25}}
/* 预检卡 / 完成卡 / 错误卡：完成态用绿色边框+淡绿底，扫没扫中一眼可分 */
.pwo-card{border:1px solid #e8e8e8;border-radius:10px;padding:14px 16px;margin-top:12px;background:#fafafa}
.pwo-card.pwo-done{border-color:#b7eb8f;background:#f6ffed}
.pwo-card.pwo-err{border-color:#ffccc7;background:#fff2f0}
.pwo-card-title{font-size:15px;font-weight:600;margin-bottom:8px}
.pwo-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:6px 18px;font-size:13.5px;line-height:1.9}
.pwo-kv{color:#666}
.pwo-kv b{color:#1f1f1f;font-weight:600}
@media (max-width:640px){.pwo-grid{grid-template-columns:1fr 1fr}}

/* ============================================================================
   🔴 v2.0.15 移动端 App 壳层
   ---------------------------------------------------------------------------
   为什么要单独一块而不是散进 640px 媒体查询：
     ① 壳层是一整套结构（顶栏/横幅/三页签/底栏），散进 640px 块里会被前后规则互相覆盖；
     ② 它的显隐由 JS 的 mShellShow/mShellHide 控制，CSS 只需管「壳层开着时长什么样」；
     ③ 桌面端**完全不受影响** —— 壳层 display:none 在基础规则里写死。
   ============================================================================ */

/* ---- 基础：壳层默认隐藏（桌面端永远看不到），返回键默认隐藏 ---- */
.mshell{display:none}
.msh-back{display:none;background:none;border:none;cursor:pointer;color:#333;padding:2px;margin-right:-2px}
.msh-back svg{width:22px;height:22px;display:block}

/* ---- 顶栏横幅（壳层专用，与原顶栏 renew-banner/sms-quota-bar 同一套数据源） ---- */
.msh-banners:empty{display:none}
.msh-banner{display:flex;align-items:center;gap:6px;padding:8px 14px;font-size:12.5px;line-height:1.5}
.msh-banner.warn{background:#fff7e6;color:#ad6800;border-bottom:1px solid #ffe0a3}
.msh-banner.urgent{background:#fff1f0;color:#cf1322;border-bottom-color:#ffccc7}
.msh-banner.info{background:#e6f4ff;color:#0958d9;border-bottom:1px solid #bae0ff}
.msh-banner .mb-go{margin-left:auto;background:none;border:none;color:inherit;font-weight:600;cursor:pointer;font-size:12.5px;padding:2px 6px;flex-shrink:0}

@media (max-width:900px){
  /* 壳层开启时：占满全屏，业务主区（#app）隐藏 */
  body.mshell-on #app{display:none}
  body.mshell-on #mshell{display:flex}
  /* 进入业务页（壳层关闭）：显示返回键 */
  body.mshell-off .msh-back{display:block}

  .mshell{flex-direction:column;height:100vh;height:100dvh;background:#f5f5f7;overflow:hidden}
  /* 深色顶栏：系统名 + 当天日期 */
  .msh-top{background:#1f2933;color:#fff;padding:calc(12px + env(safe-area-inset-top)) 16px 14px;display:flex;align-items:center;justify-content:space-between;gap:10px;flex-shrink:0}
  .msh-top-l{display:flex;align-items:center;gap:8px;min-width:0}
  .msh-logo{font-size:19px;line-height:1}
  .msh-title{font-size:17px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .msh-date{font-size:12.5px;color:rgba(255,255,255,.7);flex-shrink:0;font-variant-numeric:tabular-nums}

  /* 内容区：可滚动，底部留出标签栏高度 + 安全区 */
  .msh-body{flex:1;overflow-y:auto;-webkit-overflow-scrolling:touch;padding:12px 12px calc(12px + env(safe-area-inset-bottom))}
  .msh-page{display:block}

  /* 问候卡片：左侧大数字 + 右侧用户信息 */
  .msh-hello{background:#fff;border-radius:14px;padding:16px;display:flex;align-items:center;gap:16px;margin-bottom:4px}
  .msh-hello-num{font-size:34px;font-weight:700;color:#e02020;line-height:1.05;text-align:center;flex-shrink:0;font-variant-numeric:tabular-nums}
  .msh-hello-num i{display:block;font-size:12px;font-style:normal;font-weight:400;color:#999;margin-top:4px}
  .msh-hello-info{border-left:1px solid #f0f0f0;padding-left:16px;font-size:12.5px;color:#666;line-height:1.75;min-width:0}
  .msh-hello-info b{display:block;color:#333;font-weight:600;font-size:13.5px}

  /* 分组标题 + 图标卡片网格 */
  .msh-sec{font-size:15px;font-weight:600;color:#1f1f1f;margin:18px 2px 10px}
  .msh-sec:first-child{margin-top:6px}
  .msh-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}
  .msh-tile{background:#fff;border-radius:12px;padding:14px 4px 10px;text-align:center;cursor:pointer;border:1px solid #f0f0f0;transition:transform .12s,border-color .12s}
  .msh-tile:active{transform:scale(.96);border-color:var(--primary)}
  .msh-tile-ico{width:44px;height:44px;border-radius:13px;margin:0 auto 9px;display:flex;align-items:center;justify-content:center}
  .msh-tile-ico svg{width:23px;height:23px;display:block}
  .msh-tile-lb{font-size:12px;color:#333;line-height:1.35;word-break:break-word}

  /* 「我的」页 */
  .msh-me-card{background:#fff;border-radius:14px;padding:16px;display:flex;align-items:center;gap:14px;margin-bottom:4px}
  .msh-me-ava{width:48px;height:48px;border-radius:50%;background:#e6f4ff;color:#0958d9;font-size:19px;font-weight:600;display:flex;align-items:center;justify-content:center;flex-shrink:0}
  .msh-me-name{font-size:16px;font-weight:600;color:#1f1f1f}
  .msh-me-sub{font-size:12.5px;color:#999;margin-top:3px}
  .msh-me-kv{background:#fff;border-radius:14px;padding:4px 16px;margin-top:12px}
  .msh-me-row{display:flex;align-items:center;gap:10px;padding:13px 0;border-bottom:1px solid #f5f5f5;font-size:14px;color:#333}
  .msh-me-row:last-child{border-bottom:none}
  .msh-me-row .mr-ico{width:20px;height:20px;color:#8c8c8c;flex-shrink:0}
  .msh-me-row .mr-ico svg{width:18px;height:18px;display:block}
  .msh-me-row .mr-lb{flex:1;min-width:0}
  .msh-me-row .mr-val{font-size:13px;color:#999;max-width:52%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .msh-me-row.danger{color:#e02020}
  .msh-me-sel{border:none;background:#f5f5f7;border-radius:8px;padding:6px 8px;font-size:13px;color:#333;max-width:56%}
  .msh-me-empty{text-align:center;color:#bbb;font-size:13px;padding:12px 0}

  /* 底部标签栏：含 iPhone 安全区，固定在壳层底部（壳层本身是 flex 列，不随内容滚走） */
  .msh-tabs{flex-shrink:0;display:flex;background:#fff;border-top:1px solid #ececec;padding:6px 0 calc(6px + env(safe-area-inset-bottom))}
  .msh-tab{flex:1;text-align:center;font-size:11px;color:#9a9a9a;cursor:pointer;padding:4px 0;display:flex;flex-direction:column;align-items:center;gap:4px}
  .msh-tab svg{width:22px;height:22px;display:block}
  .msh-tab.active{color:var(--primary)}

  /* 首次使用引导横幅在壳层里的排版（原 first-use-banner 宽度撑满会溢出图标区） */
  .msh-banners .first-use-banner{margin:0}
}

/* 极窄屏（≤360px）：两列更稳，避免「提料不定价」这类长名换行成三行 */
@media (max-width:360px){
  .msh-grid{grid-template-columns:repeat(2,1fr)}
  .msh-hello{padding:14px;gap:12px}
  .msh-hello-num{font-size:30px}
}

/* v2.0.17：横幅与顶栏里的 emoji 在部分设备/字体下渲染成豆腐块（□），改用内联 SVG */
.msh-logo svg{width:22px;height:22px;display:block;color:#f0c060}
.msh-banner .mb-ico{width:17px;height:17px;flex-shrink:0;display:inline-flex;align-items:center;justify-content:center}
.msh-banner .mb-ico svg{width:16px;height:16px;display:block}

/* ============================================================================
   v2.0.27 存欠料按商品分行 —— 六大业务表单与结价凭证/打印共用
   ---------------------------------------------------------------------------
   Boss 定的呈现：每个商品一行（黄金/铂金/…）+ 末尾合计行，每行三列
   （上次存欠料 / 本次存欠料 / 总存欠料）。
   为什么用 CSS Grid 而不是真<table>：这块要嵌在各种宽度的弹窗里，
   Grid 的列宽用 fr 就能自适应，不需要为每种弹窗宽度写一份表格。
   ============================================================================ */
.owe-sum{background:#fafbfc;border:1px solid #e8eaec;border-radius:10px;padding:10px 14px 6px;margin:10px 0}
.owe-sum .t{font-size:13px;color:#666;margin-bottom:6px;font-weight:600}
/* 列宽：商品名自适应（长名不截断），三个数值列等宽 —— 数字列必须等宽，否则上下行对不齐 */
.owe-trow{display:grid;grid-template-columns:minmax(90px,1.6fr) repeat(3,minmax(96px,1fr));
  align-items:center;gap:6px;padding:5px 4px;font-size:13px;border-bottom:1px solid #f0f1f3}
.owe-trow:last-child{border-bottom:none}
/* v2.0.97：换料等"来料/出料两段可能不同商品"的分项表，多一列「库存单位」，
   用「商品品名 + 库存单位」区分行，避免同名不同单位的商品被看成同一行 */
.owe-trow.with-unit{grid-template-columns:minmax(90px,1.6fr) minmax(56px,.7fr) repeat(3,minmax(96px,1fr))}
.owe-trow .u{text-align:left;color:#666;font-size:12px}
.owe-trow > *{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.owe-trow .g{font-weight:500;color:#1f1f1f}
.owe-trow .n{text-align:right;font-variant-numeric:tabular-nums}
.owe-trow.head{background:#f2f3f5;border-radius:6px;font-size:12px;color:#666;padding:5px 4px;margin-bottom:2px}
/* 表头/合计行的数值列右对齐，和数据行一致（否则表头「上次存欠料」会左对齐，看着歪） */
.owe-trow.head .n{text-align:right;color:#666;font-weight:400}
.owe-trow.foot{background:#f7f8fa;font-weight:700;border-top:1px solid #e8eaec;border-radius:6px;margin-top:2px}
/* 正负配色：欠我（正）红 / 我欠（负）绿 —— 与全站存欠口径一致 */
.owe-trow .n .pos{color:#e02020}
.owe-trow .n .neg{color:#0a8f4d}

@media (max-width:640px){
  .owe-sum{padding:8px 8px 4px}
  .owe-trow{grid-template-columns:minmax(64px,1.2fr) repeat(3,minmax(72px,1fr));
    gap:4px;padding:5px 2px;font-size:12px}
  .owe-trow .n{font-size:11.5px}
}

/* ============================================================================
   v2.0.20 结价单重构界面
   ---------------------------------------------------------------------------
   Boss 要求：表头「往来单位 / 门店 / 日期」→ 明细表（商品/库存单位/存欠料/
   结价净重/单价/金额/备注）→ 存欠料三行 → 应付(应收)/实付(实收)。
   原来结价明细是 flex 小行、没有库存单位与金额，也没有合计行。
   ============================================================================ */
.st-head{display:flex;gap:16px;flex-wrap:wrap;margin-bottom:4px}
.st-head .it{flex:1;min-width:200px}
.st-head .it .l{font-size:12.5px;color:#888;margin-bottom:4px}
.st-head .it .v{display:flex}
.st-head .it .v > input,.st-head .it .v > select{flex:1;width:100%}

/* 明细表：CSS Grid。列宽比例必须与 stItemRowHTML 里写入顺序**逐字一致**，
   否则表头与数据行错位（与 v1.2.158 表格列设置同源约束）。 */
.st-table{border:1px solid #e8eaec;border-radius:8px;overflow:hidden;margin:4px 0 2px}
.st-trow{display:grid;grid-template-columns:2.2fr 70px 90px 90px 90px 110px 1.4fr 34px;
  align-items:center;border-bottom:1px solid #f2f3f5}
.st-trow:last-child{border-bottom:none}
.st-trow > *{padding:7px 8px;font-size:13px;min-width:0;overflow:hidden;text-overflow:ellipsis}
.st-trow input,.st-trow select{width:100%;padding:5px 6px;font-size:13px}
.st-trow.row-head{background:#f7f8fa;font-weight:600;color:#666;font-size:12px}
.st-trow.row-foot{background:#fafbfc;font-weight:700}
.st-trow.row-foot > *{color:#1f1f1f}
.st-cell-name{text-align:left;white-space:nowrap}
.st-cell-unit{text-align:center;color:#888;font-size:12px}
.st-cell-owe{text-align:right;font-variant-numeric:tabular-nums;font-weight:600;font-size:12px}
.st-cell-num{text-align:right;font-variant-numeric:tabular-nums}
.st-del{padding:4px 6px;justify-self:center}
/* v2.0.72：明细格子外面多包了一层（窄屏要按格子显示列名），PC 端保持原样：
   删除列居中、格子内部不撑破列宽 */
.st-trow .st-cell{display:block;min-width:0}
.st-trow .st-cell-del{display:flex;justify-content:center;align-items:center}

/* 应付（应收）/ 实付（实收）/ 未付（未收）—— 三个金额卡横排 */
.st-money{display:flex;gap:12px;flex-wrap:wrap;margin:12px 0 0}
.st-money .card{flex:1;min-width:150px;background:#fafbfc;border:1px solid #e8eaec;border-radius:10px;padding:10px 14px}
.st-money .card .l{font-size:12.5px;color:#888;line-height:1.4}
.st-money .card .v{font-size:21px;font-weight:700;line-height:1.3;margin-top:3px;font-variant-numeric:tabular-nums}
.st-money .card .v input{width:100%;padding:2px 0;border:none;background:transparent;font-size:21px;font-weight:700;color:#1677ff}
/* 金额配色：应付=金（待结金额）、实付=蓝、未付=橙（有尾款才需要引起注意） */
.st-money .amt-gold{color:#c8912a}
.st-money .amt-blue{color:#1677ff}
.st-money .amt-warn{color:#e02020}

@media (max-width:900px){
  .st-trow{grid-template-columns:1.8fr 56px 72px 72px 72px 90px 1fr 30px}
  .st-trow > *{padding:6px 4px;font-size:12px}
  .st-money .card{min-width:100%}
  .st-money .card .v{font-size:19px}
}
/* v2.0.25：存欠料三行的口径提示（本单商品合计 ≠ 该单位全部商品合计时才出现） */
.owe-sum .t{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.owe-sum .t .scope{font-size:11.5px;color:#a0761a;background:#fdf6e6;border:1px solid #f0e0b8;
  border-radius:5px;padding:2px 7px;white-space:nowrap}
@media (max-width:640px){ .owe-sum .t .scope{white-space:normal} }
/* v2.0.26：结价「实付（实收）金额」卡内的货币符号（输入框左侧） */
.st-money .card .v .cur{color:#1677ff;font-size:19px;font-weight:700;margin-right:2px;align-self:center}
.st-money .card .v{display:flex;align-items:center}
