/*!
 * web/assets/css/index/04-components.css
 * 多规格编辑器 / BOM / 登录 / 打印 / 弹窗 / 富文本 / G2
 *
 * 本文件由 tools/split_spa.py 从单文件 SPA 机械拆出，请勿手工改动切分边界。
 * 加载顺序由入口 HTML 统一控制（经典 script 共享全局词法环境）。
 */

/* 多规格编辑器（#324 淘宝式：颜色 × 尺码矩阵）*/
.spec-editor{background:var(--cd);border-radius:10px;padding:12px;margin-top:6px}
.spec-editor .sec-title{font-size:13px;font-weight:600;margin-bottom:6px;display:flex;align-items:center;gap:6px}
.spec-chip-input{display:flex;flex-wrap:wrap;gap:6px;align-items:center;border:1px solid var(--bd);border-radius:8px;padding:6px;background:var(--cb);min-height:40px;cursor:text}
.spec-chip-input input{flex:1;min-width:120px;border:none;outline:none;background:transparent;color:var(--tc);font-size:13px;padding:3px}
.spec-chip{display:inline-flex;align-items:center;gap:4px;padding:3px 8px;background:var(--pc);color:#fff;border-radius:14px;font-size:12px;font-weight:500}
.spec-chip .x{cursor:pointer;opacity:.85;font-size:14px;line-height:1}
.spec-matrix-wrap{overflow-x:auto;max-width:100%;border:1px solid var(--bd);border-radius:8px;margin-top:8px;background:var(--cb)}
.spec-matrix{width:100%;border-collapse:collapse;font-size:12px}
.spec-matrix th,.spec-matrix td{border:1px solid var(--bd);padding:4px;text-align:center;vertical-align:middle}
.spec-matrix th{background:var(--cd);font-weight:600;position:sticky;top:0;color:var(--tc)}
.spec-matrix th.color-head{background:var(--cd);color:var(--tc)}
.spec-matrix td.color-row{background:var(--cd);font-weight:600;color:var(--tc);position:sticky;left:0;z-index:1}
.spec-matrix input[type=number]{width:64px;border:1px solid var(--bd);border-radius:4px;padding:3px;background:var(--cd);color:var(--tc);text-align:center;font-size:12px}
.spec-matrix input[type=number]:focus{outline:none;border-color:var(--pc)}
.spec-cell{display:flex;flex-direction:column;gap:3px;align-items:stretch}
.spec-cell__row{display:flex;align-items:center;gap:6px}
.spec-cell__lbl{flex-shrink:0;width:38px;font-size:11px;color:var(--ts);text-align:right}
.spec-cell__row input{flex:1;min-width:0;width:100%}
.spec-cell__img{display:flex;align-items:center;gap:4px;justify-content:center}
.spec-cell__thumb{width:26px;height:26px;object-fit:cover;border-radius:4px;border:1px solid var(--bd)}
.spec-cell__btn{font-size:11px;padding:2px 6px;border:1px solid var(--pc);color:var(--pci);background:transparent;border-radius:4px;cursor:pointer;line-height:1}
/* #449 规格图独立成列 */
.spec-img-head{min-width:72px}
.spec-img-cell{display:flex;flex-direction:column;gap:4px;align-items:center;justify-content:center;padding:4px}
.spec-img-cell__img{width:48px;height:48px;object-fit:cover;border-radius:6px;border:1px solid var(--bd);display:block}
.spec-img-cell .spec-cell__btn{white-space:nowrap}
/* BOM 物料行（显式编辑/删除按钮）*/
.bom-list{display:flex;flex-direction:column;gap:8px;padding:0 12px}
.bom-row{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:10px 12px;background:var(--cb);border:1px solid var(--bd);border-radius:10px}
.bom-row__main{min-width:0;flex:1}
.bom-row__name{font-size:14px;font-weight:600;color:var(--tc);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.bom-row__meta{font-size:12px;color:var(--wc);margin-top:2px}
.bom-row__acts{display:flex;gap:6px;flex-shrink:0}
/* 登录页注册模式（公司信息分区提示）*/
.reg-company-hint{font-size:12px;color:var(--wc);margin:15px 0 12px;padding:0 2px}
/* 发货打印纸张模式（#453）：热敏窄版 + 三联分页 */
.delivery-print{padding:16px;background:#fff;color:#000}
.delivery-print.paper-thermal{padding:8px;margin:0 auto;font-size:11px}
.delivery-print.paper-thermal.paper-t58{width:58mm}
.delivery-print.paper-thermal.paper-t76{width:76mm}
.delivery-print.paper-thermal.paper-t80{width:80mm}
.dtri{border:1px solid #333;margin-bottom:16px;padding:14px 12px 16px;background:#fff;color:#000}
.dtri__tag{text-align:right;font-size:12px;color:#333;margin-bottom:6px}
.dtri__sign{display:flex;justify-content:space-between;gap:12px;font-size:13px;color:#333;margin-top:14px;padding-top:8px;border-top:1px dashed #999}
@media print{.dtri{page-break-after:always;border:none;margin:0}.dtri:last-child{page-break-after:auto}}
/* 销售单打印页（#454）*/
.sp-head{text-align:center;border-bottom:2px solid #333;padding-bottom:8px;margin-bottom:10px}
.sp-head__title{font-size:20px;font-weight:700;color:#000}
.sp-head__no{font-size:13px;color:#333;margin-top:4px}
.sp-meta{font-size:13px;color:#000;display:flex;flex-direction:column;gap:4px}
.sp-total{display:flex;justify-content:space-between;flex-wrap:wrap;gap:6px;font-size:13px;margin-top:8px;color:#000}
.sp-total__due{font-weight:700;color:#b00}
.sp-thanks{text-align:center;font-size:12px;color:#666;margin-top:14px}
.spec-color-tag{display:inline-block;padding:1px 8px;border-radius:10px;background:var(--pc);color:#fff;font-size:11px;font-weight:600}
.spec-bulk{display:flex;gap:6px;flex-wrap:wrap;margin-top:8px;padding-top:8px;border-top:1px dashed var(--bd)}
.spec-bulk input{width:80px;border:1px solid var(--bd);border-radius:6px;padding:4px 6px;background:var(--cb);color:var(--tc);font-size:12px}
/* 商品图片上传（图块+加号在底，删除悬浮）*/
.prod-imgs{display:flex;flex-wrap:wrap;gap:8px;padding:8px 0}
.prod-imgs .thumb{position:relative;width:72px;height:72px;border-radius:8px;overflow:hidden;border:1px solid var(--bd);background:var(--cb,#f5f5f5)}
.prod-imgs .thumb img{width:100%;height:100%;object-fit:cover}
.prod-imgs .thumb .x{position:absolute;top:2px;right:2px;width:18px;height:18px;border-radius:50%;background:rgba(0,0,0,.55);color:#fff;display:flex;align-items:center;justify-content:center;font-size:12px;cursor:pointer;line-height:1}
.prod-imgs .add{width:72px;height:72px;border:2px dashed var(--bd);border-radius:8px;display:flex;flex-direction:column;align-items:center;justify-content:center;color:var(--ts);cursor:pointer;background:var(--cb);font-size:11px}
.prod-imgs .add:hover{border-color:var(--pc);color:var(--pci)}
.prod-imgs .add input{display:none}
/* #326 参考图槽位（模特照 / 面料小样 / 场景图）：比商品缩略图小一档，
   整行 flex-wrap 保证 360~390 窄屏不会把提示文字顶出屏；必填态只描边不改布局。 */
.ai-refs{display:flex;align-items:center;flex-wrap:wrap;gap:8px;margin:2px 0 8px}
.ai-refs-label{font-size:12px;color:var(--ts);flex:0 0 auto}
.ai-ref{position:relative;flex:0 0 auto;width:52px;height:52px;border:1px solid var(--bd);border-radius:8px;overflow:hidden;background:var(--cb)}
.ai-ref img{width:100%;height:100%;object-fit:cover;display:block}
.ai-ref .x{position:absolute;top:2px;right:2px;width:18px;height:18px;border-radius:50%;background:rgba(0,0,0,.55);color:#fff;display:flex;align-items:center;justify-content:center;font-size:12px;cursor:pointer;line-height:1}
.ai-ref.add{display:flex;align-items:center;justify-content:center;border-style:dashed;border-width:2px;color:var(--ts);cursor:pointer}
.ai-ref.add:hover{border-color:var(--pc);color:var(--pci)}
.ai-ref.add input{display:none}
.ai-ref.need,.ai-ref-hint.need{border-color:var(--danger);color:var(--danger)}
.ai-ref-hint{flex:1 1 150px;font-size:11px;color:var(--ts);min-width:0;word-break:break-word}
/* 统一弹窗（#324 分类/供应商/品牌/门店/仓库 全部统一为「搜索+列表++快速添加」）*/
.pick-pop{background:var(--cb);max-height:80vh;overflow:auto}
.pick-pop-head{padding:14px 16px 8px;border-bottom:1px solid var(--bd)}
.pick-pop-head .tt{font-size:16px;font-weight:600;margin-bottom:8px}
.pick-pop-search{display:flex;gap:8px}
.pick-pop-body{padding:8px 0}
.pick-pop-empty{padding:30px 16px;text-align:center;color:var(--ts);font-size:13px}
/* 富文本工具栏（#323）*/
.remark-toolbar{display:flex;flex-wrap:wrap;gap:4px;padding:6px 8px;background:var(--cd);border-radius:6px 6px 0 0;border:1px solid var(--bd);border-bottom:none}
.remark-toolbar button{padding:3px 10px;border:1px solid var(--bd);border-radius:4px;background:var(--cb);color:var(--tc);font-size:12px;cursor:pointer}
.remark-toolbar button:hover{background:var(--pc);color:#fff;border-color:var(--pc)}
.remark-editor{border:1px solid var(--bd);border-radius:0 0 6px 6px;padding:8px;min-height:80px;background:var(--cb);color:var(--tc);font-size:13px;line-height:1.7}
.remark-editor:focus{outline:none}
.remark-editor:empty:before{content:attr(data-placeholder);color:var(--ts)}
/* 2026-09-20（AGENTS.md §11）：.mini-bars/.mini-bar（div 手拼条形图）随门店/仓库看板改 G2 一并删除。
   数据可视化图表一律走 window.EpChart，不得再用 div 拼条形。 */
/* G2 交互式图表容器统一样式 */
.g2-chart-wrap{background:var(--cd);border-radius:8px;padding:4px;min-height:180px;position:relative;overflow:hidden}
.g2-chart-wrap canvas{display:block!important}
.g2-chart-empty{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);color:var(--ts);font-size:12px}
.cust-view-btn{font-size:12px;color:var(--pci);margin-left:8px;cursor:pointer;white-space:nowrap}
.help-fab{position:fixed;bottom:calc(90px + env(safe-area-inset-bottom));left:20px;z-index:60;width:40px;height:40px;border-radius:50%;background:var(--pc);color:#fff;display:flex;align-items:center;justify-content:center;font-size:20px;cursor:pointer;box-shadow:0 2px 8px rgba(0,0,0,.15);opacity:.9}@media(min-width:768px){.help-fab{bottom:calc(40px + env(safe-area-inset-bottom));left:24px}}
/* 帮助中心栏目选中态（#216）：除 van-tag type 主色外，再叠加加粗+放大，确保选中清晰可见 */
.hp-sec-on{font-weight:700;transform:scale(1.05);box-shadow:0 0 0 2px var(--pc) inset}
.hp-sec-off{opacity:.82}
.section-title{font-size:15px;font-weight:600;margin:16px 0 8px;display:flex;align-items:center;gap:8px}
.rpt-summary{display:grid;grid-template-columns:repeat(2,1fr);gap:10px;padding:12px}
.rpt-card{border-radius:12px;padding:16px 14px;color:#fff;position:relative;overflow:hidden;box-shadow:0 4px 12px rgba(0,0,0,.08)}
.rpt-card__v{font-size:22px;font-weight:800;line-height:1.1}
.rpt-card__l{font-size:12px;opacity:.92;margin-top:4px}
.rpt-card--orders{background:linear-gradient(135deg,#5b86e5,#36d1dc)}
.rpt-card--sale{background:linear-gradient(135deg,#ff6a00,#ee0979)}
.rpt-card--net{background:linear-gradient(135deg,#11998e,#38ef7d)}
.rpt-card--recv{background:linear-gradient(135deg,#f7971e,#ffd200);color:#5a3b00}
.rpt-sub{display:flex;gap:16px;flex-wrap:wrap;padding:0 16px 8px;font-size:12px;color:var(--ts)}
.rpt-sec{margin:8px 16px 6px!important}
.rpt-chart-card{margin:0 16px;background:var(--cd);border-radius:12px;padding:10px;box-shadow:0 2px 8px rgba(0,0,0,.06)}
.rpt-area{width:100%;height:120px;display:block}
.rpt-bars{margin:0 16px;background:var(--cd);border-radius:12px;padding:12px;box-shadow:0 2px 8px rgba(0,0,0,.06)}
.rpt-bar-row{margin-bottom:12px}
.rpt-bar-row:last-child{margin-bottom:0}
.rpt-bar-name{font-size:13px;color:var(--tc);margin-bottom:5px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.rpt-bar-style{font-size:11px;color:var(--ts);font-weight:400;margin-left:4px}
.rpt-bar-track{background:var(--bd);border-radius:6px;height:10px;overflow:hidden}
.rpt-bar-fill{height:100%;border-radius:6px;background:linear-gradient(90deg,#ff6a00,#ee0979);transition:width .5s ease}
.rpt-bar-fill--store{background:linear-gradient(90deg,#5b86e5,#36d1dc)}
.rpt-bar-val{font-size:12px;color:var(--ts);margin-top:4px}
.empty-state--mini{padding:10px 0;font-size:13px}
.empty-state{text-align:center;padding:40px 0;color:var(--ts);font-size:14px}.empty-state--compact{padding:18px 0}
/* #741：破损图占位从前由 52-ep-shims.js 内联写死 color:#bbb / background:#f5f5f7，
   暗黑档下等于贴一块亮灰壳。配色归到 CSS 走令牌（文字 --ts、底 --cd），
   宽高留给内联（那是逐张图量出来的数据，不是形制）。 */
.img-err-ph{display:inline-flex;align-items:center;justify-content:center;flex:none;vertical-align:middle;font-size:10px;color:var(--ts);background:var(--cd);border:1px solid var(--br);border-radius:4px}
/* #257：ep-cell 垫片把默认插槽放进 .ep-cell__value（右对齐、flex-shrink:0），
   空态插槽文字因此贴在行最右，而 .empty-state 的 text-align:center 打在外层 flex 容器上不管用。
   下面这条原先写的是 .van-cell（Vant 时代的类名，垫片换成 .ep-cell 后成了孤儿规则，没人渲染它）。
   实测（390px 视口）只给两列各 flex:1 仍然偏右 —— 空的 .ep-cell__main 还占着左半边，
   文字只是在**右半边的中间**居中（中心 274 / 行中心 195）。所以要把空标题列收掉。 */
.empty-state.ep-cell{justify-content:center}
.empty-state.ep-cell .ep-cell__main{display:none}
.empty-state.ep-cell .ep-cell__value{flex:none;padding-left:0;text-align:center}
.detail-label{font-size:12px;color:var(--ts);margin-bottom:2px}
.detail-value{font-size:16px;color:var(--tc);margin-bottom:12px}
.action-bar{display:flex;gap:8px;margin:16px 0;flex-wrap:wrap}
.ord-date-bar{display:flex;align-items:center;gap:6px;padding:4px 12px 8px;background:var(--cd);border-radius:10px;margin:4px 12px;flex-wrap:nowrap}
.ord-date-bar__label{font-size:12px;color:var(--ts);flex:none;white-space:nowrap;margin-right:2px}
.ord-date-bar__pick{flex:1 1 0;min-width:0;max-width:none}
.ord-date-bar__pick .dt-picker{min-width:0}
.ord-date-bar__sep{color:var(--ts);flex:none;font-size:14px;margin:0 2px}
.ord-date-bar__reset{flex:none;white-space:nowrap;height:28px;padding:0 10px}
/* 2026-09-25（#57 移动端全流程排查实测）：窄屏原本**强制 nowrap**，而日期选择器内部有 120px 的
   最小宽度，390px 下整条要 396px、容器只有 334px，且 overflow-x:hidden ——
   实测「搜索」按钮 x=358..384（半颗出界）、「重置」x=398..424（**整颗在裁剪框外，手机上点不到**）。
   改为允许换行 + 让选择器真能收缩，两条都解决：一行放得下就还是一行。 */
@media(max-width:768px){.ord-date-bar{flex-wrap:wrap}.ord-date-bar__pick{flex:1 1 120px;max-width:none;min-width:0}.ord-date-bar__pick .dt-picker{width:100%;min-width:0}
/* 同一批实测：搜索/重置在窄屏实测 26×36 / 50×36，低于 §42 的 44px 触摸下限（原 .ord-date-bar__reset 还写死 height:28px）。
   只抬高热区不改字号，视觉仍是小按钮。 */
.ord-date-bar .el-button,.ord-date-bar__reset{min-height:44px}}
/* 搜索面板展开收起（统一：订单列表 / 发货记录 / 销售财务对账） */
.search-panel{overflow:hidden;transition:max-height .3s ease,opacity .25s ease,border-color .2s ease;border-top:1px solid transparent}
.search-panel > .search-panel__inner{max-height:1200px;opacity:1;transition:max-height .3s ease,opacity .25s ease}
.search-panel--collapsed > .search-panel__inner{max-height:0!important;opacity:0;pointer-events:none}
.search-panel--collapsed{border-top-color:transparent}
.search-toggle{display:flex;align-items:center;justify-content:center;gap:6px;padding:6px 12px;font-size:13px;color:var(--ts);cursor:pointer;border-top:1px solid var(--bd);background:var(--cb);transition:background .15s,color .15s;user-select:none}
.search-toggle:hover{color:var(--pci);background:rgba(0,122,255,.04)}
.search-toggle:active{background:rgba(0,122,255,.08)}
.search-toggle__arrow{display:inline-flex;transition:transform .25s ease}
.search-toggle--open .search-toggle__arrow{transform:rotate(180deg)}
.search-toggle__badge{display:inline-flex;align-items:center;height:18px;min-width:18px;padding:0 6px;border-radius:9px;background:var(--pc);color:#fff;font-size:11px;font-weight:600;line-height:18px;animation:badgePop .25s ease}
@keyframes badgePop{from{transform:scale(.6);opacity:0}to{transform:scale(1);opacity:1}}
.search-toggle__hint{font-size:12px;color:var(--ts);margin-left:2px}
/* Print Agent 安装提示（打印设置-设备扫描/空设备态） */
.agent-hint{margin:8px 0;padding:12px;background:rgba(255,149,0,.07);border:1px dashed rgba(255,149,0,.45);border-radius:10px;line-height:1.6;font-size:12px;color:var(--tc)}
.agent-hint__title{font-weight:600;color:#ed6a0c;margin-bottom:6px;font-size:13px;display:flex;align-items:center;gap:6px}
.agent-hint__msg{color:var(--ts);margin-bottom:8px}
.agent-hint__how{font-weight:600;margin:8px 0 4px;color:var(--tc)}
.agent-hint ol{list-style:none;counter-reset:ag;padding:0;margin:0}
.agent-hint ol li{counter-increment:ag;position:relative;padding-left:22px;margin:4px 0;color:var(--ts)}
.agent-hint ol li::before{content:counter(ag);position:absolute;left:0;top:1px;width:16px;height:16px;border-radius:50%;background:var(--pc);color:#fff;font-size:10px;font-weight:600;display:flex;align-items:center;justify-content:center}
/* 兼容旧类名（订单列表已用 ord-search-panel） */
.ord-search-panel{background:var(--cb);transition:all .3s ease;overflow:hidden}
.ord-search-panel--collapsed .search-grid,
.ord-search-panel--collapsed .ord-search-row2,
.ord-search-panel--collapsed .ord-date-bar{max-height:0!important;opacity:0!important;margin:0!important;padding:0!important;overflow:hidden;pointer-events:none}
.ord-search-panel .search-grid,
.ord-search-panel .ord-search-row2,
.ord-search-panel .ord-date-bar{max-height:500px;opacity:1;transition:all .3s ease}
.ord-search-row2{padding:0 12px 4px}
/* 财务对账搜索面板：使用统一 .search-panel 样式 */
.recon-search-panel{background:var(--cb);overflow:hidden;transition:max-height .3s ease,opacity .25s ease}
.recon-search-panel > .recon-search-panel__inner{max-height:1200px;opacity:1;transition:max-height .3s ease,opacity .25s ease}
.recon-search-panel--collapsed > .recon-search-panel__inner{max-height:0!important;opacity:0;pointer-events:none}
/* #550：公司信息保存成功短暂高亮（视觉反馈） */
.company-form--saved{animation:companySavedGlow 1.5s ease}
@keyframes companySavedGlow{
  0%{box-shadow:0 0 0 0 rgba(52,199,89,.45)}
  35%{box-shadow:0 0 0 6px rgba(52,199,89,.18)}
  100%{box-shadow:0 0 0 0 rgba(52,199,89,0)}
}
/* #550 财务报表页（7.md） */
.fr-range{display:flex;align-items:center;gap:6px;padding:10px 12px;background:var(--cb)}
.fr-range__sep{color:var(--ts);flex:none}
.fr-body{padding:10px 0 16px}
.fr-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:8px;padding:0 12px}
@media(min-width:768px){.fr-grid{grid-template-columns:repeat(4,1fr)}}
.fr-card{background:var(--cd);border-radius:12px;padding:14px 12px;text-align:center;box-shadow:var(--sh)}
.fr-card__v{font-size:18px;font-weight:700;color:var(--tc);line-height:1.3}
.fr-card--up .fr-card__v{color:var(--sc)}
.fr-card--down .fr-card__v{color:var(--dc)}
.fr-card__l{font-size:11px;color:var(--ts);margin-top:4px}
.fr-sec{font-weight:600;font-size:14px;margin:12px 16px 6px}
.fr-cell-strong{font-weight:700}
.fr-note{font-size:11px;color:var(--ts);margin:10px 16px;line-height:1.6}
.fr-chart{margin:12px;background:var(--cd);border-radius:12px;padding:12px;box-shadow:var(--sh)}
.fr-chart__title{font-size:13px;font-weight:600;margin-bottom:8px}
.fr-svg{width:100%;height:auto}
.fr-chart__legend{display:flex;gap:14px;margin-top:8px;font-size:11px;color:var(--ts)}
.fr-chart__legend i{display:inline-block;width:10px;height:10px;border-radius:2px;margin-right:4px;vertical-align:middle}
/* #550 客户抹零汇总条 */
.fr-round{display:flex;align-items:center;justify-content:space-between;margin:10px 12px 0;padding:12px 14px;background:rgba(255,149,0,.08);border:1px dashed rgba(255,149,0,.45);border-radius:12px}
.fr-round__lbl{font-size:13px;color:var(--ts)}
.fr-round__v{font-size:18px;font-weight:700;color:#ed6a0c}
/* #366 芯片的显示形态原先只写在 @media(max-width:767px) 里，桌面档由模板内联
   style="display:flex" 顶上；内联压不过断点也反过来压掉手机档，两边只能留一个真源。
   形态上移到顶层基线，媒体查询那条只留 44px 热区要求。 */
.seg-chip{display:inline-flex;align-items:center;justify-content:center}
/* 搜索区第一行：日期范围 */
.sr-search-row1{display:flex;align-items:center;gap:6px;padding:10px 12px;border-bottom:1px solid var(--bd);flex-wrap:nowrap}
.sr-search-row1__label{font-size:13px;color:var(--ts);white-space:nowrap;flex:none}
.sr-search-row1__pick{flex:1;min-width:0}
.sr-search-row1__sep{color:var(--ts);flex:none;font-size:14px}
/* 2026-09-10：筛选条件改为「一行 2 个」（原来 grid-template-columns:1fr 导致 4 个输入框各占一整行） */
.recon-filter-row{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;padding:12px;border-bottom:1px solid var(--bd)}
.recon-filter-input{width:100%;min-width:0}
.recon-filter-input .ep-field__control,
.recon-filter-input .ep-field__native,
.recon-filter-input input{min-width:0;width:100%}
/* 窄屏（手机）回退单列，避免两个输入框挤在一起无法输入 */
@media (max-width:420px){.recon-filter-row{grid-template-columns:1fr}}
.recon-btn-row{display:flex;gap:10px;padding:12px}
.recon-btn{flex:1}
/* 发货记录搜索面板：使用统一 .search-panel 样式 */
.ship-search-panel{overflow:hidden;transition:max-height .3s ease,opacity .25s ease}
.ship-search-panel > .ship-search-panel__inner{max-height:1200px;opacity:1;transition:max-height .3s ease,opacity .25s ease}
.ship-search-panel--collapsed > .ship-search-panel__inner{max-height:0!important;opacity:0;pointer-events:none}
/* 发货汇总条吸顶 */
.ship-sumbar--sticky{position:sticky;top:0;z-index:10;box-shadow:0 2px 4px rgba(0,0,0,.08)}
/* 2026-10-02（#295/#296）：客户页排序页签。原来把 padding/圆角/字号/光标全写在内联 style 里
   （内联固定尺寸在窄屏既压不动也点不准，实测只有 31px 高）—— 尺寸归位到类，内联只剩选中态配色。 */
.sort-chip{display:inline-flex;align-items:center;padding:7px 12px;border-radius:16px;font-size:12px;
           cursor:pointer;min-height:32px;line-height:1.2}
.filter-bar{display:flex;gap:8px;margin:12px 0;overflow-x:auto;white-space:nowrap;scrollbar-width:none}.filter-bar::-webkit-scrollbar{display:none}.preview-modal{position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,.5);z-index:200;overflow-y:auto;padding:20px}
.preview-content{background:#fff;border-radius:var(--rl);padding:20px;max-width:800px;margin:20px auto;min-height:300px}
.preview-content .print-header{text-align:center;font-size:18px;font-weight:600;margin-bottom:16px;padding-bottom:12px;border-bottom:2px solid #000}
.preview-content .print-row{display:flex;padding:6px 0;border-bottom:1px dashed #ccc;font-size:13px}
.preview-content .print-row .label{width:100px;color:var(--ts)}.preview-content .print-row .value{flex:1}
.preview-triplicate{display:block}.preview-triplicate .tri-receipt{position:relative;padding:14px 12px 16px;margin:0;border:1px solid #333;background:#fff;color:#000}
.preview-thermal{max-width:300px;margin:0 auto;font-size:14px}
.print-actions{display:flex;gap:8px;margin-top:16px;justify-content:center;flex-wrap:wrap}
.lang-switch{position:fixed;top:12px;right:12px;z-index:50;display:flex;align-items:center;gap:4px;padding:6px 10px;background:var(--cd);border-radius:16px;box-shadow:var(--sh);cursor:pointer;font-size:12px;border:1px solid var(--bd)}
.top-controls{position:fixed;top:12px;right:12px;z-index:50;display:flex;gap:6px}
@media(min-width:768px){.lang-switch{right:24px}}.top-controls@media(min-width:768px){.top-controls{right:24px}}
.platform-card{border:1px solid var(--bd);border-radius:var(--rm);padding:12px;margin-bottom:8px}
.platform-card .header{display:flex;justify-content:space-between;align-items:center;margin-bottom:8px}
.platform-card .status{font-size:11px;padding:2px 6px;border-radius:8px}
/* #379：物料行改成「一格一字段、字段带列标签」的自适应网格。
   列宽地板 112px 而不是 136px：360pt 屏（390px 视口减去外边距）要能并排放下两个字段 + 标签，
   原来模板里内联了 grid-template-columns，把下面 max-width:359px 的断点整块压死了。 */
.mat-row{display:grid;grid-template-columns:repeat(auto-fit,minmax(112px,1fr));gap:8px 6px;margin-top:4px;align-items:start}
.mat-field{display:flex;flex-direction:column;gap:2px;min-width:0}
.mat-field__l{font-size:12px;line-height:1.3;color:var(--tc);overflow-wrap:anywhere}
.mat-field--act{justify-content:flex-end}
.mat-row--dup{outline:1px solid var(--dc);outline-offset:3px;border-radius:6px}
.mat-dup-tip{margin-top:6px;font-size:12px;line-height:1.5;color:var(--dc)}
.mat-row .mat-input{width:100%;border:1px solid var(--bd);border-radius:4px;padding:4px 4px;font-size:12px;background:transparent;color:var(--tc);box-sizing:border-box}
.mat-row .mat-spec{width:100%;border:1px solid var(--bd);border-radius:4px;padding:4px 4px;font-size:12px;background:transparent;color:var(--tc);box-sizing:border-box}
/* #377 金额区：标签列 / 输入列 / 后缀列三段定宽网格。
   两行步进器必须严格对齐 —— 原来是 flex + 后缀 flex:none，「每采购单优惠」6 字与「手动填写」4 字
   直接把输入框拉成两种宽度（业主：「优惠金额步进器没有对齐实付金额的」）。 */
.amt-rows{padding:2px 12px 8px}
.amt-row{display:grid;grid-template-columns:76px minmax(0,1fr) 84px;align-items:center;gap:8px;padding:9px 0;border-bottom:1px solid var(--bd)}
.amt-row__l{font-size:14px;color:var(--tc);overflow-wrap:anywhere}
.amt-row__v{font-size:15px;font-weight:600;color:var(--tc);text-align:right;overflow-wrap:anywhere}
.amt-row__v--warn{color:var(--wc)}
.amt-row__i{width:100%;min-width:0}
.amt-row__s{font-size:12px;color:var(--ts);text-align:right;overflow-wrap:anywhere}
.amt-row__s--auto{color:var(--sc)}
.amt-row--act{border-bottom:none;padding-top:2px;padding-bottom:2px}
@media(max-width:359px){.amt-row{grid-template-columns:64px minmax(0,1fr) 72px}}
/* 动作文字可读性（业主：「动作文字看不清」）：步进器 ± 与行内 plain 按钮原来在近黑底上
   是 EP 默认的浅灰描边字，暗黑档对比度不足。统一改走主题墨水色。 */
.mat-row .el-input-number__decrement,.mat-row .el-input-number__increment{color:var(--tc);background:var(--cd)}
.mat-field--act .el-button,.amt-row .el-button{color:var(--tc)}
/* 采购单明细「关联商品」栏（图1，2026-09-23）：裸下拉看不懂是什么，补标题 + 用途说明。
   颜色一律走主题变量，暗色模式下不能是硬编码深色字（历史踩坑见 #51）。 */
.pos-pay__method--empty{color:var(--ts);font-style:normal}
.rec-detail{display:flex;flex-direction:column;gap:0}
.rec-detail__row{display:grid;grid-template-columns:96px minmax(0,1fr);gap:8px;padding:8px 0;border-bottom:1px solid var(--bd);font-size:14px}
.rec-detail__row:last-child{border-bottom:none}
.rec-detail__row>span{color:var(--ts);overflow-wrap:anywhere}
.rec-detail__row>b{color:var(--tc);font-weight:600;text-align:right;overflow-wrap:anywhere}
.rec-detail__after{color:var(--pci)}
.rec-detail__void{color:var(--dc)}
.mat-link-label{flex:none;font-size:12px;color:var(--tc);font-weight:600}
.mat-link-tip{font-size:11px;line-height:1.5;color:var(--sc);opacity:.85;margin-top:3px}
.mat-row .el-input-number{width:100%;min-width:0}
.mat-row .el-input-number .el-input{width:100%}
.mat-row .el-input-number .el-input__inner{text-align:center;font-size:12px;height:28px;padding:0 8px}
.mat-row .el-input-number .el-input-number__decrement,
.mat-row .el-input-number .el-input-number__increment{height:28px}
/* 超窄屏：整格单列。原来这一档用 nth-of-type(3/4/5) 按「第几个步进器」定位，
   结构一改（控件包进 .mat-field）序数就全错 —— 这正是 #366 登记的 nth-of-type 盲区，
   现在按字段类名定位，不再依赖兄弟节点顺序。 */
@media(max-width:359px){
  .mat-row{grid-template-columns:1fr 1fr}
  .mat-field--color,.mat-field--spec{grid-column:1 / -1}
  }
.referral-tier-row{display:flex;align-items:center;gap:8px;margin-bottom:8px}
.referral-tier-row label{min-width:80px;font-size:13px;color:var(--ts)}
.referral-tier-row input{flex:1;border:1px solid var(--bd);border-radius:var(--rs);padding:6px 10px;font-size:14px}
/* ============ 打印输出（2026-09-12 重写） ============
   送审反馈：「打印 → 浏览器打印 → 弹出打印窗口显示空白」。
   根因是两件事叠在一起：

   ① **暗色模式没有回浅色**。`:root.dark` 把 `--tc` 设成 #F5F5F7（近白）、`--bg` 设成 #000，
      而打印时浏览器默认**不输出背景色**，于是白纸上印的是近白色的字 → 看起来就是一张空白页。
      这是「空白」的主因，而且只在暗色模式下出现（所以此前没被发现）。
   ② SPA 的滚动容器会把 `#print-area` 裁掉。`#print-area` 只是 `position:absolute`，
      并不能脱离 `.app/.main/.page` 这些 `overflow:auto` 祖先的裁剪，
      一旦主容器处于滚动状态，打印出来就是空白或只有一条。
      所以先把祖先链的 height/overflow/position 全部还原成普通文档流。

   另外把「打印区域」的白名单选择器统一收口（#print-area / #printArea / .delivery-print /
   .print-area / [data-print-area]），避免各页面各写一套、漏一个就白屏。 */
@media print{
  /* ① 打印一律按浅色渲染：重置主题变量 + 强制白底黑字 */
  :root, :root.dark, :root.light{
    --bg:#fff; --cd:#fff; --cb:#fff; --tc:#000; --ts:#333;
    --bd:#999; --br:#999; --sh:none; --seg:#ddd; --seg-active:#fff;
  }
  html,body{height:auto!important;overflow:visible!important;background:#fff!important;color:#000!important}
  body{-webkit-print-color-adjust:exact;print-color-adjust:exact}
  /* ② 解除 SPA 布局的滚动/裁剪，让打印区域按正常文档流从页首开始 */
  #gp-app,.app,.main,.page,.layout,.content-area,.admin-tabs-bar{
    display:block!important;position:static!important;
    height:auto!important;max-height:none!important;min-height:0!important;
    overflow:visible!important;animation:none!important;transform:none!important;
  }
  /* ③ 只保留打印区域 */
  body *{visibility:hidden}
  #print-area,#print-area *,
  #printArea,#printArea *,
  .delivery-print,.delivery-print *,
  .print-area,.print-area *,
  [data-print-area],[data-print-area] *{visibility:visible}
  /* #196：带 .gpl-paper 的纸面由版式引擎按选中的纸张写内联 mm 尺寸，而下面那条 100%/auto 会把 A4、58mm 热敏、针式 241×93 压成同一种纸 —— 设计器里选的纸到送打就失效。这类纸面只豁免尺寸，其余归零项照旧。
     #632 把合同的纸面（.ct-paperbox，同为引擎按 paper.wMm 出内联 mm）一起纳进来：
     合同在屏幕上是"210mm 的一张 A4"，被这条压成 100% 后，打出来的宽度与预览的不是同一张纸。 */
  #printArea.gpl-paper,#printArea.ct-paperbox{position:absolute!important;left:0!important;top:0!important;
    max-width:none!important;overflow:visible!important;margin:0!important;padding:0!important;
    box-shadow:none!important;border:none!important;background:#fff!important;color:#000!important}
  #print-area,#printArea:not(.gpl-paper):not(.ct-paperbox),.delivery-print:not(.gpl-paper),.print-area,[data-print-area]{
    position:absolute!important;left:0!important;top:0!important;
    width:100%!important;max-width:none!important;max-height:none!important;
    height:auto!important;overflow:visible!important;
    margin:0!important;padding:0;box-sizing:border-box;
    box-shadow:none!important;border:none!important;
    background:#fff!important;color:#000!important;
  }
  .no-print{display:none!important}
}
.ann-popup-wrap{display:flex;align-items:flex-start;justify-content:center;min-height:100vh;padding:48px 16px;box-sizing:border-box;overflow:auto}
.ann-popup{background:#fff;border-radius:12px;display:flex;flex-direction:column;min-width:280px;max-width:90vw;width:auto;max-height:calc(100vh - 96px);box-shadow:0 12px 36px rgba(0,0,0,.18)}
.ann-popup-header{display:flex;justify-content:space-between;align-items:flex-start;gap:8px;padding:14px 14px 10px;font-size:16px;flex-shrink:0}
.ann-popup-body{padding:4px 14px 14px;font-size:14px;line-height:1.6;overflow-y:auto;flex:1 1 auto;min-height:0;word-break:break-word;overflow-wrap:break-word}
.ann-popup-body img,.ann-popup-body video,.ann-popup-body iframe{max-width:100%;height:auto;border-radius:6px}
.ann-popup-body table{max-width:100%;overflow:auto;display:block}
.ann-popup-footer{display:flex;justify-content:flex-end;gap:8px;padding:10px 14px;border-top:1px solid var(--bd);flex-shrink:0}
/* Contacts */
.contact-list-item{padding:12px 16px;background:var(--cd);border-bottom:1px solid var(--bd);cursor:pointer}
.contact-list-item:last-child{border-bottom:none}
/* Finance */
.finance-stat-row{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-bottom:12px;align-items:stretch}
.finance-stat-box{background:var(--cd);border-radius:8px;padding:14px;text-align:center;box-shadow:var(--sh)}
.finance-stat-box .val{font-size:22px;font-weight:700;color:var(--pci)}
.finance-stat-box .val.green{color:#34C759}
.finance-stat-box .val.red{color:#FF3B30}
.finance-stat-box .lbl{font-size:11px;color:#8e8e93;margin-top:2px}
/* ===== 动画：页面进入 / 弹窗 / 微交互（点5：告别生硬卡顿） ===== */
.page{animation:pageIn .28s cubic-bezier(.22,.61,.36,1)}
/* 2026-09-18：纯淡入去 transform，避免 .page 成为 fixed 包含块 */
@keyframes pageIn{from{opacity:0}to{opacity:1}}
@keyframes dialogIn{from{opacity:0;transform:translateY(18px) scale(.98)}to{opacity:1;transform:none}}
@keyframes fadeIn{from{opacity:0}to{opacity:1}}
.sidebar-nav li,.contact-list-item,.kanban-card,.ann__item,.credit-banner{transition:background .15s,transform .12s,box-shadow .2s}
.kanban-card:hover,.credit-banner:hover{box-shadow:0 4px 16px rgba(0,0,0,.1)}
/* 这一族禁令原来写成 `{.page,.van-dialog,.van-popup,.ann-popup,}` —— 选择器表尾多一个逗号且
   **零声明**，是一条永不生效的假兜底（print.html 只载 04-components.css，不载 09-anim-layer.css 那份全局兜底，
   所以这里写坏了等于打印页完全没有减弱动效的路径）。补成真声明。
   类名换成垫片真正渲染出的那一份：`van-*` 是 Vant 时代的残留，全仓零命中（dead_css_scan 实测），
   留着只会让这条兜底看着像有覆盖、实际弹层照样动（el-dialog 279 处、ep-popup 499 处）。 */
@media(prefers-reduced-motion:reduce){.page,.el-dialog,.ep-popup,.ann-popup{animation:none;transition:none}}
/* ===== 弹窗统一留白与观感基线（全项目 padding 一致性） ===== */
/* #507：弹窗内边距统一（与 admin #158 一致）——防文字贴边 */

/* 采购单货款摘要卡片（detail.js 供应商账目区）*/
.po-sup-pay{display:flex;flex-wrap:wrap;gap:6px 18px;align-items:baseline;line-height:1.7}
.po-sp-item{font-size:13px;color:var(--ts)}
.po-sp-item i{font-style:normal;margin-right:5px;font-weight:400}
.po-sp-item b{font-size:14px;color:var(--tx);font-weight:700}

/* 2026-09-09：全项目 UI 一致性——按钮/弹窗/输入框对齐规范 */
/* #366：原来 .dp-toolbar 的内联 padding 把 @media(max-width:768px) 那条改小的规则压死了
   （内联的特异度高于任何单类选择器），移动端工具条永远按桌面间距排。
   声明搬进基础规则，断点规则才真的能覆盖它。
   批次86 续四把剩下的内联声明一并搬过来（flex-wrap/display/gap/align/justify/text-align）：
   当时 20-mobile-layout.css ⑪ 只能靠 !important 压行内，等于把断点写成「只能靠强权」，
   内联摘掉后那条 !important 一起撤（见同文件 ⑪ 的注释）。 */
.dp-toolbar{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:4px;text-align:center;padding:8px 16px}
/* #366：登录页原来把 padding 写在内联 style 上，压掉了 02-responsive 的移动端断点规则。
   内联已摘，页面留白交回给 .page 自己（02-responsive 的断点 + 03-global-fix 的 !important 侧边距）。
   这里**不能再补一条 .login-page{padding:...}**：特异度只有 0,1,0，会被后面的
   .main .page{padding-top:0} 和 !important 侧边距逐条压掉，写下去就是一条死规则（8123 实测
   computed=0 16px 60px，声明根本没生效）。 */
.page .el-button--small{height:28px;line-height:26px;padding:0 12px;font-size:12px}
.page .el-button--small.is-round{padding:0 12px}
.page .el-button+.el-button{margin-left:8px}
.ep-cell-group.inset{padding:0;margin:0 12px}
.el-dialog{--el-dialog-padding-primary:16px}
.el-dialog .el-dialog__body{padding:14px 20px}
.el-form-item--default{margin-bottom:12px}
.el-form-item__label{font-size:13px;color:var(--ts)}
.ep-field{font-size:14px;padding:10px 12px}
.ep-field__label{font-size:13px;color:var(--ts)}
.ep-popup{font-size:14px}
.el-input__inner,.el-textarea__inner{font-size:14px}
.el-table th.el-table__cell{font-size:12px;font-weight:600;color:var(--ts)}
.el-table td.el-table__cell{padding:8px 0}
@media (max-width:768px){
  .page .el-button--small{height:30px;line-height:28px;padding:0 14px}
  .el-dialog{width:92vw!important;margin:0 4vw}
}

/* 2026-09-10：DateTimePicker 改为封装 el-date-picker 后的布局样式 */
.dt-picker__field{display:flex;align-items:center;gap:10px;padding:8px 12px;border-bottom:1px solid var(--bd)}
.dt-picker__label{font-size:14px;color:var(--ts);min-width:70px;flex:none}
.dt-picker__dp{flex:1;min-width:0}
.dt-picker .el-date-editor.el-input,
.dt-picker .el-date-editor.el-input__wrapper{width:100%}
.dt-picker--cell .el-date-editor{width:100%}
/* #601：农历选择器的 cell 长相（标题在外层 ep-cell，这里只出「值」）。
   与 .dt-picker--cell 同一条契约：日期行不得有两套字体/宽度（原来农历走 ep-field 的 88px 标签、
   阳历走 .dt-picker__label 的 70px 且颜色是 --ts，两者又都和整页的 ep-cell 标题不一致）。 */
.lunar-picker--cell{width:100%}
.lp-cell{display:flex;align-items:center;justify-content:flex-end;gap:6px;min-height:24px;font-size:14px;cursor:pointer}
.lp-cell__text{color:var(--tc);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.lp-cell__text--ph{color:var(--ts)}
.lp-cell__icon{color:var(--ts);flex:none}

/* ===== 2026-09-10：套装统一徽标（全项目一眼可辨，避免漏发子商品） ===== */
.pos-bundle-badge{
  display:inline-block;padding:0 4px;margin-right:4px;border-radius:4px;
  background:#e5484d;color:#fff;font-size:10px;line-height:15px;font-weight:600;vertical-align:1px;
}
.bundle-flag{
  display:inline-block;padding:0 5px;border-radius:4px;background:rgba(229,72,77,.12);
  color:#e5484d;border:1px solid rgba(229,72,77,.35);font-size:10px;line-height:16px;margin-right:4px;
}
.bundle-group{
  border-left:3px solid #e5484d;background:rgba(229,72,77,.04);border-radius:6px;
  padding:2px 0;margin:4px 0;
}

/* ===== 2026-09-10：补换下单——单据性质选择卡 ===== */
.rep-kind{
  flex:1 1 30%;min-width:96px;padding:8px 10px;border-radius:10px;cursor:pointer;
  border:1px solid var(--bd);background:var(--cd);color:var(--tc);
  transition:all .15s;text-align:center;font-size:13px;
}
.rep-kind--on{background:var(--wc,#ff9500);color:#fff;border-color:var(--wc,#ff9500);box-shadow:0 2px 8px rgba(255,149,0,.25)}

/* ===== 2026-09-10：站点底部信息固定在「页面底部」而非内容末尾 =====
   原实现：footer 只是 body 末尾的普通 div，内容少时紧贴内容下方（页面中部），
   视觉上像"悬在半空"。改为 body 纵向 flex + 应用区自适应撑开 + footer margin-top:auto。 */
html{min-height:100%}
body{min-height:100vh;display:flex;flex-direction:column}
#gp-app{flex:1 0 auto;min-width:0}
#gp-site-footer{flex:none;margin-top:auto}
/* 桌面端：footer 避让固定侧边栏，不被遮挡 */
@media (min-width:768px){
  #gp-site-footer{margin-left:var(--sbw,220px);padding-bottom:20px!important}
}
/* 移动端：footer 避让底部 Tab 栏 */
@media (max-width:767px){
  #gp-site-footer{padding-bottom:80px!important}
}

/* ===== 2026-09-10：发货页「套装（组合商品）」分区 ===== */
.bundle-section{
  margin:10px 12px;border:1px solid rgba(229,72,77,.35);border-left:4px solid #e5484d;
  border-radius:10px;background:rgba(229,72,77,.04);overflow:hidden;
}
.bundle-section__hd{
  display:flex;align-items:center;gap:8px;padding:10px 12px;
  background:rgba(229,72,77,.08);border-bottom:1px solid rgba(229,72,77,.2);flex-wrap:wrap;
}
.bundle-section__title{font-size:14px;font-weight:600;color:var(--tc);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.bundle-section__cnt{font-size:11px;color:var(--ts);flex:none}
.bundle-section__hd .el-button{margin-left:auto;flex:none}
.bundle-section__hint{padding:6px 12px;font-size:11px;color:var(--ts);line-height:1.6}
.bundle-row{display:flex;align-items:center;gap:10px;padding:8px 12px;border-bottom:1px solid rgba(229,72,77,.12)}
.bundle-row:last-of-type{border-bottom:0}
.bundle-row__main{flex:1;min-width:0}
.bundle-row__name{font-size:13px;font-weight:500;color:var(--tc);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.bundle-row__sub{font-size:11px;color:var(--ts);margin-top:2px}
.bundle-section__state{padding:7px 12px;font-size:12px;font-weight:600}
.bundle-section__state.is-ok{color:#1f7a3f;background:rgba(52,199,89,.1)}
.bundle-section__state.is-warn{color:#b26a00;background:rgba(255,149,0,.12)}

/* ===== 2026-09-10：销售开单「销量前30」与「全部商品」分段 ===== */
.pos-sec-divider{
  grid-column:1 / -1;              /* 网格布局下跨整行 */
  width:100%;
  margin:4px 0 2px;padding:6px 10px;
  font-size:12px;font-weight:700;color:#e5484d;
  background:rgba(229,72,77,.08);
  border-left:3px solid #e5484d;border-radius:6px;
}
/* 热销前30 的商品卡：加边框与普通商品区分（一眼看出置顶区） */
.pos-card--hot{
  border:1.5px solid rgba(229,72,77,.55) !important;
  box-shadow:0 2px 10px rgba(229,72,77,.12) !important;
}

/* ===== 2026-09-12（送审反馈 #11）：底部自定义 HTML 区块 =====
   管理员在「系统设置 → 底部描述」开启后，site_footer_html 原样渲染到这里。
   这里只做「不破坏页面结构」的兜底约束：图片自适应、链接继承颜色、块级间距。 */
.site-footer__custom{margin-top:8px;line-height:1.8}
.site-footer__custom img{max-width:100%;height:auto}
.site-footer__custom a{color:inherit}
.site-footer__custom p{margin:4px 0}
.site-footer__custom *{max-width:100%}

/* 步进器样式统一移至 assets/css/stepper.css，前后台共享，避免重复定义覆盖。 */

/* ===== 2026-09-19（单品销售分析）：客户下单排名徽标 + 客户订单列表弹窗 =====
   product-detail.js「统计」tab 的排名行徽标（.pd-rank-badge + .pd-rank-1/2/3/n）
   与「该客户在本店订单」弹窗（.pd-cust-orders）专用样式。前代理已写好模板引用，
   此处补齐缺失的样式定义（否则名次退化为纯文本、金银铜视觉丢失）。
   · 1/2/3 名用金银铜固定色，白字在明/暗主题下均可读；其余名次走主题变量自动适配。
   · 禁 emoji：徽标内容为名次数字（模板内 {{ci+1}}），此处不加任何图标。 */
.pd-rank-badge{display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:18px;padding:0 4px;border-radius:9px;font-size:11px;font-weight:700;line-height:1;color:#fff;background:var(--ts);vertical-align:middle}
.pd-rank-n{background:var(--cb);color:var(--ts);border:1px solid var(--bd)}
.pd-rank-1{background:linear-gradient(135deg,#FFD700,#FF9500);color:#fff;box-shadow:0 1px 3px rgba(255,149,0,.35)}
.pd-rank-2{background:linear-gradient(135deg,#C7CCD4,#8E939B);color:#fff}
.pd-rank-3{background:linear-gradient(135deg,#E0A168,#B87333);color:#fff}
.pd-cust-orders .pd-cust-orders__row{cursor:pointer}
/* #106（2026-09-24）：订单弹窗里的「规格/颜色」内嵌表 —— 一个规格一行。
   线框只画内部横线，避免与外层 el-table 边框叠成双线；窄列下数字右对齐，颜色/规格允许换行。 */
/* #113（2026-09-24）：追溯流水弹窗的信息条 + 行可点提示 */
.pd-trace__head{display:flex;flex-wrap:wrap;gap:4px 14px;font-size:12px;color:var(--ts);background:var(--bg);border-radius:8px;padding:8px 10px;margin-bottom:10px}
.pd-trace .pd-trace__row{cursor:pointer}
.pd-spec-tbl{width:100%;border-collapse:collapse;font-size:12px;line-height:1.5}
.pd-spec-tbl th{font-weight:500;color:var(--ts);text-align:left;padding:1px 6px 3px 0;border-bottom:1px solid var(--br);white-space:nowrap}
.pd-spec-tbl td{padding:3px 6px 3px 0;border-bottom:1px dashed var(--br);color:var(--tc);word-break:break-word}
.pd-spec-tbl tr:last-child td{border-bottom:0}
.pd-spec-tbl__n{text-align:right !important;white-space:nowrap;font-variant-numeric:tabular-nums;padding-right:0 !important}

/* ===== 2026-09-19（需求 #23）：额度「购买记录 + 按天折算退款」弹窗 =====
   组件 web/assets/js/index/components/quota-records.js（门店 / 仓库 / 子账户三页共用）。
   约束：只用主题变量（var(--c*)/--tc/--ts/--bd/--sc/--dc/--wc），暗色主题自动跟随；
        移动端单列、桌面 900px 内自适应，不出现横向滚动。 */
.qr-filter{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-bottom:10px}
.qr-sum{display:flex;flex-wrap:wrap;gap:10px;padding:8px 10px;margin-bottom:10px;
  background:var(--cb);border:1px solid var(--bd);border-radius:8px;font-size:12px;color:var(--ts)}
.qr-list{display:flex;flex-direction:column;gap:8px}
.qr-item{padding:10px 12px;background:var(--cd);border:1px solid var(--bd);border-radius:10px}
.qr-item__top{display:flex;align-items:center;justify-content:space-between;gap:8px}
.qr-item__name{font-size:14px;font-weight:600;color:var(--tc)}
.qr-item__meta{display:flex;flex-wrap:wrap;gap:4px 10px;margin-top:4px;font-size:12px;color:var(--ts)}
.qr-item__rf{margin-top:6px;font-size:12px;line-height:1.6;word-break:break-all}
.qr-item__act{display:flex;justify-content:flex-end;margin-top:6px}
@media (max-width:640px){
  .qr-item__act{justify-content:stretch}
  .qr-item__act .el-button{width:100%}
}

/* 2026-09-22（图4）：自定义物料的名称输入框 —— 必须是「一眼看出能输入」的样式。
   旧样式无边框无底色，和分组标题完全同形，用户不知道要在这里打字。 */
.mat-name-input{width:100%;border:1px solid var(--bd);border-radius:6px;padding:6px 8px;font-size:14px;font-weight:500;background:var(--cd);color:var(--tc);box-sizing:border-box}
.mat-name-input:focus{outline:none;border-color:var(--pc)}
.mat-name-input::placeholder{font-weight:400;opacity:.75}
.mat-name-input--empty{border-color:var(--dc)}

/* #103（2026-09-24）：开单规格弹窗 —— 多选模式「一行一个规格 + 各自数量」。
   步进器右对齐、宽度自适应；行高 ≥40px 保证移动端可点；删除按钮收在行尾不抢宽度。 */
.pos-sheet__lines{border:1px solid var(--bd);border-radius:8px;overflow:hidden}
.pos-sheet__line{display:flex;align-items:center;gap:8px;padding:5px 8px;min-height:42px;border-bottom:1px solid var(--br)}
.pos-sheet__line:last-child{border-bottom:0}
.pos-sheet__line:nth-child(odd){background:var(--bg)}
.pos-sheet__line-spec{flex:1;min-width:0;font-size:13px;color:var(--tc);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pos-sheet__line-slash{color:var(--ts);margin:0 3px}
.pos-sheet__line .el-input-number{width:118px;flex:none}
@media (max-width:420px){.pos-sheet__line .el-input-number{width:100px}}
.pos-sheet__link{font-size:12px;color:var(--pci);cursor:pointer;margin-left:auto;font-weight:400}
.pos-sheet__lines-empty{font-size:12px;color:var(--ts);padding:8px 10px}
/* ===== 2026-09-24 #55 提成结算账单重做（PC 表格 / 移动卡片双版式 + 四段额） =====
   版式来自用户选定的「都要」：宽屏用专业表格（对齐对账单读法），窄屏/移动 web 用卡片账期。
   两端共用同一份 csList 与同一组动作，只有渲染分支两份；四段额字段由
   commission/settlement/list 的分组派生表给出（frozen_amount / released_amount / line_count）。 */
.cs-wrap{padding:12px 16px}
.cs-cfg{background:var(--cd);border:1px solid var(--bd);border-radius:var(--rl);padding:10px 12px}
.cs-cfg__row{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.cs-cfg__lb{font-size:12.5px;color:var(--ts)}
.cs-cfg__sp{flex:1;min-width:8px}
.cs-cfg__hint{font-size:12px;color:var(--ts);margin-top:6px;line-height:1.6}
.cs-range{margin-top:10px;padding-top:8px;border-top:1px dashed var(--bd);font-size:13px;display:flex;gap:8px;flex-wrap:wrap;align-items:baseline}
/* 顶部 KPI 合计条：先看总量，再看每张单 */
.cs-kpi{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin:12px 0}
.cs-kpi__i{background:var(--cd);border:1px solid var(--bd);border-radius:var(--rl);padding:10px 12px;min-width:0}
.cs-kpi__l{font-size:11.5px;color:var(--ts);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cs-kpi__v{font-size:21px;font-weight:700;letter-spacing:-.4px;margin-top:2px;line-height:1.2}
.cs-kpi__i--a .cs-kpi__v{color:var(--pci)}
.cs-num{font-variant-numeric:tabular-nums;font-feature-settings:"tnum" 1}
.cs-warn{color:var(--wc)}
.cs-red{color:var(--dc)}
.cs-dim{color:var(--ts)}
.cs-empty{background:var(--cd);border:1px dashed var(--bd);border-radius:var(--rl);padding:16px;text-align:center;font-size:13px;color:var(--ts)}
/* PC 专业表格：grid 定列，表头吸顶，金额右对齐 */
.cs-tbl{background:var(--cd);border:1px solid var(--bd);border-radius:var(--rl);overflow:hidden}
.cs-tbl__head,.cs-tbl__row,.cs-tbl__sum{display:grid;grid-template-columns:110px minmax(140px,1.2fr) 70px 56px minmax(150px,1.1fr) 84px minmax(236px,auto);
  gap:10px;align-items:center;padding:9px 12px}
.cs-tbl__head{background:var(--cb);font-size:11.5px;font-weight:600;color:var(--ts);position:sticky;top:0;z-index:1}
.cs-tbl__row{border-top:1px solid var(--cb);font-size:13px}
.cs-tbl__row:nth-child(even){background:rgba(0,0,0,.012)}
.cs-tbl__row--on{background:rgba(0,122,255,.05);box-shadow:inset 3px 0 0 var(--pc)}
.cs-tbl__row .r,.cs-tbl__head .r,.cs-tbl__sum .r{text-align:right}
.cs-who{font-weight:650;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cs-per{display:flex;flex-direction:column;line-height:1.35;min-width:0}
.cs-per b{font-weight:600;font-size:13px}
.cs-per em{font-style:normal;font-size:11.5px;color:var(--ts)}
.cs-amt{font-size:15px;font-weight:700;letter-spacing:-.2px}
.cs-amt--zero{color:var(--ts);font-weight:500}
.cs-amt--s{color:var(--sc)}
.cs-frz{display:block;font-style:normal;font-size:10.5px;color:var(--wc);margin-top:1px;white-space:nowrap}
.cs-tbl__row>span{min-width:0;overflow:hidden}
.cs-det__tbl th{font-size:11px;font-weight:600;color:var(--ts);text-align:left;padding:6px 0 4px;border-bottom:1px solid var(--bd)}
.cs-det__tbl th.r{text-align:right}
.cs-st{display:inline-flex;align-items:center;gap:5px;font-style:normal;font-size:11.5px;white-space:nowrap;color:var(--wc)}
.cs-st i{width:6px;height:6px;border-radius:50%;background:currentColor;display:inline-block}
.cs-st--s{color:var(--sc)}
.cs-acts{display:flex;gap:6px;justify-content:flex-end;flex-wrap:wrap}
.cs-tbl__sum{border-top:2px solid var(--bd);background:var(--cb);font-weight:700;font-size:13px}
/* 行内展开明细：不弹窗、不跳页（点单号才进订单弹层） */
.cs-det{grid-column:1/-1;padding:2px 12px 12px 26px;border-left:3px solid var(--pc);margin:0 12px 10px}
.cs-tbl .cs-det{margin-left:12px}
.cs-det__hd{font-size:12px;color:var(--ts);margin:8px 0 4px;display:flex;gap:10px;flex-wrap:wrap}
.cs-det__tbl{width:100%;border-collapse:collapse;font-size:12.5px}
.cs-det__tbl td{padding:5px 0;border-bottom:1px solid var(--cb)}
.cs-det__tbl td.r{text-align:right}
.cs-det__tbl a{color:var(--pci);text-decoration:none;font-weight:600}
.cs-det__tbl .cs-row-red td{color:var(--dc)}
.cs-legend{font-size:11.5px;color:var(--ts);margin-top:8px;line-height:1.7}
/* 移动卡片：大号金额 + 四段额 2×2 + 操作整排 */
.cs-cards{display:flex;flex-direction:column;gap:10px}
.cs-card{background:var(--cd);border:1px solid var(--bd);border-radius:var(--rl);padding:12px 14px}
.cs-card--on{border-color:var(--pc);box-shadow:0 0 0 2px rgba(0,122,255,.12)}
.cs-card__hd{display:flex;align-items:flex-start;gap:10px}
.cs-per2{font-size:11.5px;color:var(--ts);margin-top:3px}
.cs-card__amt{margin-left:auto;text-align:right;flex:none}
.cs-card__amt .cs-amt{font-size:21px;display:block;letter-spacing:-.5px}
.cs-card__amt .cs-st{margin-top:4px}
.cs-seg{display:grid;grid-template-columns:1fr 1fr;gap:2px 10px;margin-top:10px;padding-top:9px;border-top:1px solid var(--cb)}
.cs-seg div{font-size:11.5px;color:var(--ts);display:flex;justify-content:space-between;gap:8px;line-height:1.9}
.cs-seg b{font-size:13px;color:var(--tc);font-weight:650}
.cs-card__acts{display:flex;gap:6px;flex-wrap:wrap;margin-top:10px;padding-top:9px;border-top:1px solid var(--cb)}
.cs-card .cs-det{margin:10px 0 0;padding:2px 0 0 10px}
@media (max-width:768px){
  .cs-wrap{padding:10px 12px}
  .cs-kpi{grid-template-columns:1fr 1fr;gap:8px}
  .cs-kpi__v{font-size:19px}
  .cs-card__acts .el-button{flex:1;margin-left:0}
}
/* 暗黑：半透明行底/焦点环在深色上会发灰，统一换成提亮色（与 :root.dark .recon-summary 同一手法） */
:root.dark .cs-tbl__row:nth-child(even){background:rgba(255,255,255,.03)}
:root.dark .cs-tbl__row--on{background:rgba(76,141,255,.12)}
:root.dark .cs-kpi__i--a .cs-kpi__v{color:#4C8DFF}
:root.dark .cs-card--on{box-shadow:0 0 0 2px rgba(76,141,255,.22)}
:root.dark .cs-det{border-left-color:#4C8DFF}

/* ============ #117 客户对账单导出对话框（pages/customers.js → core/75-statement.js v5 版式） ============
   行本身只用既有 ep-cell / ep-cell-group 类（表单行类名约定），这里只补三件事：
   1) 说明文字要能换行（默认 ep-cell__label 是单行，长提示会被裁掉）；
   2) 开关所在行给到 34px 触摸下限（AGENTS.md §42.3）；
   3) 对话框内的分组卡去掉外缘多余留白。 */
.recon-export-dlg{padding:2px 0 0}
.recon-export-dlg .ep-cell-group{margin:0}
.recon-export-dlg .ep-cell__label{white-space:normal;line-height:1.6}
.recon-export-dlg .ep-cell__value{display:flex;align-items:center;justify-content:flex-end;min-height:34px}
/* #117 导出对话框被对账抽屉（ep-pop__mask）遮住：EP el-dialog 内部 useZIndex 只给到 2006，
   且 MutationObserver 的抬层会被 EP 下一 tick 的响应式 z-index 覆盖 → 点「导出Excel」看不到开关。
   append-to-body 让 overlay 跳出 .app 上下文，再用 !important 压住 EP 写进 style 的值。
   ⚠️ #162 复发过一次：当年钉的是**写死的 5000**，而弹层分配器 _nextZ() 只增不减（每次 +10，封顶 40000），
   会话里弹层开到几百个之后抽屉爬到 5030，导出框又被盖住。现在改成跟着 --gp-ztop 走：
   永远比「当前最高弹层」高一级，不再和计数器比谁数字大。低于 .el-popper(50000) 仍然成立。 */
.el-overlay:has(.recon-export-dlg){z-index:calc(var(--gp-ztop,2000) + 10) !important}
.el-overlay:has(.recon-export-dlg) .el-dialog{z-index:calc(var(--gp-ztop,2000) + 10) !important}

/* ============ 2026-09-25 客户对账「八项金额」（pages/customers.js 对账弹窗抬头汇总区） ============
   与 xlsx/PDF 抬头同一批字段、同一条口径说明。要点：
   1) 每格两行：名称 + 金额在上，口径说明在下且必须能换行（说明是被裁掉就得罪「讲清楚」这个需求本身）；
   2) 宽屏两列、窄屏一列（§42.3 多分辨率红线），整格高度给到 34px 以上触摸下限；
   3) 颜色全部走主题令牌，暗色下由 .recon-amt / .recon-tie 的 --cd/--bd 自动跟上，不再自建一套。 */
.recon-amts{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px;margin:0 0 8px}
.recon-amt{border:1px solid var(--bd);border-radius:8px;background:var(--cd);padding:6px 9px;min-height:34px;display:flex;flex-direction:column;justify-content:center}
.recon-amt__top{display:flex;align-items:baseline;justify-content:space-between;gap:8px}
.recon-amt__name{font-size:13px;font-weight:600;color:var(--tc);white-space:nowrap}
.recon-amt__val{font-size:14px;color:var(--pci);white-space:nowrap}
.recon-amt__val--neg{color:var(--dc)}
.recon-amt__note{font-size:11px;line-height:1.5;color:var(--ts);white-space:normal;word-break:break-word;margin-top:2px}
.recon-tie{font-size:12px;line-height:1.6;border-radius:8px;padding:7px 10px;margin:0 0 10px;white-space:normal;word-break:break-word}
.recon-tie--ok{color:var(--sc);background:rgba(52,199,89,.1);border:1px solid rgba(52,199,89,.32)}
.recon-tie--fail{color:var(--dc);background:rgba(255,59,48,.1);border:1px solid rgba(255,59,48,.36);font-weight:600}
@media (max-width:560px){.recon-amts{grid-template-columns:1fr}}


/* #192：物料列表读失败时的常驻说明条。以前只弹一次 toast 就留一张空表，
   操作员报上来的永远是「物料没有显示」，真实原因（权限/接口错）看不见。
   底色 + 边框 + --wci 文字，浅色下实测对比度 ≥4.5，不靠颜色单独表意。 */
.mat-err{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:10px 12px;padding:10px 12px;font-size:13px;line-height:1.5;color:var(--wci);background:rgba(255,149,0,.10);border:1px solid rgba(255,149,0,.35);border-radius:10px}

/* #261：打印设置页的 @page 预览行 —— 必须整行可见并允许折行（原来是单行只读输入框，
   被 88px 标签挤到从中间截断）。等宽字体 + pre-wrap 让人能逐字核对下发给打印机的口径。 */
.ppc-css{padding:6px 16px 10px;font-size:12px;color:var(--ts);font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;white-space:pre-wrap;word-break:break-all;line-height:1.6}
.ppc-css b{color:var(--tc);font-weight:600}

/* ===== #336 局部重绘遮罩编辑器 =====
   画布必须是**贴图的绝对层**：显示尺寸跟容器走，导出时另按原图像素尺寸重画，
   两处用同一份归一化笔迹，位置才对得上（touch-action:none 是手机上能画的关键）。 */
.ai-mask{display:flex;flex-direction:column;gap:10px}
.ai-mask__stage{position:relative;line-height:0;background:var(--bg2,#f5f5f7);border-radius:8px;overflow:hidden}
.ai-mask__img{display:block;width:100%;height:auto;user-select:none;-webkit-user-drag:none}
.ai-mask__view{position:absolute;left:0;top:0;width:100%;height:100%;touch-action:none;cursor:crosshair}
.ai-mask__bar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;min-height:44px}
.ai-mask__lab{font-size:12px;color:var(--ts)}
/* #424：弹层画布宽度由用户拖出来（拖这一条改 el-dialog 的宽度，图宽 = 容器宽 → 画布跟着放大）。
   视觉 8px、命中区 ::after 外扩到 44px（AGENTS §42.3）。 */
/* #431 成品预览的"垫子"与垫上那句话的颜色：屏幕 UI 不许写死 hex（#364 那条），
   所以成对定义在令牌里 —— 浅色档把垫子压深、把话压深灰；深色档把垫子压到比卡片还暗、
   把话提到够读的亮灰。纸面本身（白）是打印纸的既定例外，不进这两个令牌。 */
:root{--gp-pv-mat:#525659;--gp-pv-ink:#5f6672;--gp-pv-paper:#fff}
:root.dark{--gp-pv-mat:#232326;--gp-pv-ink:#9ca3af;--gp-pv-paper:#fff}
/* 分隔条可聚焦（tabindex + 方向键步进）之后，焦点环必须看得见，否则"键盘可操作"是空话 */
.ai-desk__split:focus-visible,.pd-split:focus-visible,.pd-vsplit:focus-visible,
.le-split:focus-visible,.le-vsplit:focus-visible{outline:2px solid var(--pci);outline-offset:2px;border-radius:4px}
.ai-desk__split{flex:none;height:18px;position:relative;cursor:ew-resize;touch-action:none;border-radius:4px;
  background:linear-gradient(to right,transparent 0,transparent 45%,var(--bd) 45%,var(--bd) 55%,transparent 55%)}
.ai-desk__split:hover{background:linear-gradient(to right,transparent 0,transparent 45%,var(--pc) 45%,var(--pc) 55%,transparent 55%)}
.ai-desk__split::after{content:'';position:absolute;left:0;right:0;top:-13px;bottom:-13px}
.ai-mask__pvbox{margin:0;display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.ai-mask__pvlbl{font-size:12px;color:var(--ts)}
.ai-mask__pv{max-width:180px;max-height:120px;border:1px solid var(--bd);border-radius:6px;background:#000}
.ai-mask__hint{margin:0;font-size:12px;line-height:1.6;color:var(--ts)}
.ai-mask__err{margin:0;font-size:12px;color:var(--e,#f56c6c)}
/* 面板里的遮罩状态行：没圈 / 已圈 都要一眼看出来，不能等提交才发现 */
.ai-mask-row{display:flex;align-items:center;gap:8px;flex-wrap:wrap;min-height:44px;margin-top:6px}
.ai-mask-row .ai-mask-btn{min-height:44px;padding:0 12px;border-radius:999px;border:1px solid var(--bd,#dcdfe6);
  background:var(--bg,#fff);font-size:13px;cursor:pointer;display:inline-flex;align-items:center;gap:6px}
.ai-mask-row .ai-mask-btn.need{border-color:var(--e,#f56c6c);color:var(--e,#f56c6c)}
.ai-mask-row .ai-mask-btn.on{border-color:var(--pc,#409eff);color:var(--pci,#409eff)}
.ai-mask-row .ai-mask-x{cursor:pointer;font-size:16px;padding:0 6px;min-height:44px;display:inline-flex;align-items:center}
/* 「重绘这一张」是真正下单的那一颗（aiInpaintImage 的唯一调用点）：没圈选时置灰而不是隐藏，
   隐藏会让用户以为这块根本不能重绘（§82「看不见」≠「没有」）。 */
.ai-mask-row .ai-mask-run{min-height:44px;padding:0 14px;border-radius:999px;cursor:pointer;
  border:1px solid var(--pc,#409eff);background:var(--pc,#409eff);color:#fff;font-size:13px;display:inline-flex;align-items:center}
.ai-mask-row .ai-mask-run:disabled{opacity:.45;cursor:not-allowed}
/* ============================================================================
 * AI 处理的公共件（#342 补）。两支此前一直"写了标记没写样式"的类：
 *   .ai-text / .ai-plan —— 商品表单、物料表单、商品详情、配图工作台四处都在用，
 *   但整个 assets/css 目录里一条规则都没有（check_css_class_wired 只查「定义了没人用」，
 *   不查「用了没定义」，所以这条空档一路绿着）—— 这正是业主说的"不知道是什么东西"：
 *   计划回显就是一行没边距的默认字，输入框跟着 .inp 的通用样式挤成一条。
 * 规则放静态层不放页面 CSS：四处共用，写进懒加载页就是四份副本、改一处漏三处。
 * ==========================================================================*/
.inp.ai-text{flex:1 1 180px;min-width:0;box-sizing:border-box;font-size:13px;line-height:1.5;
  padding:8px 10px;border:1px solid var(--bd,#dcdfe6);border-radius:8px;background:var(--bg,#fff);color:var(--tc,#303133)}
.inp.ai-text:focus{border-color:var(--pc,#409eff);outline:none}
textarea.inp.ai-text{width:100%;min-height:64px;resize:vertical;flex:1 1 100%}
/* 计划回显：动作流 + 合计 + 跳过原因分三段，各段颜色分工（不是把三件事写成一行灰字） */
.ai-plan{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin:6px 0 8px;padding:8px 10px;
  border-radius:8px;background:var(--cb,#f5f7fa);font-size:12px;color:var(--ts,#606266);word-break:break-word}
.ai-plan__flow{font-weight:600;color:var(--tc,#303133)}
.ai-plan__cost{color:var(--p,#409eff);font-variant-numeric:tabular-nums}
.ai-plan__skip{color:var(--e,#f56c6c);flex:1 1 100%}
/* 平台选择器（ai-platform-picker.js）：每一步一行，「自动」把实际会走的那家说出来 */
.ai-plat{min-width:0}
.ai-plat__row{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.ai-plat__k{font-size:12px;color:var(--ts,#606266);flex:0 0 auto}
.ai-plat__sel{flex:1 1 160px;min-width:0;max-width:260px}
.ai-plat__hint{font-size:11px;color:var(--p,#409eff);flex:1 1 100%}
.ai-plat__none{display:flex;flex-direction:column;gap:2px;font-size:12px;color:var(--e,#f56c6c)}
.ai-plat__none-c{color:var(--ts,#606266)}
/* 表单里的平台行：选择器 + "在工作台打开"并排，窄屏自然换行（不许横向溢出） */
.ai-plat-inline{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin:2px 0 8px}
.ai-plat-inline .ai-plat{flex:1 1 220px;min-width:0}

/* ==========================================================================
 * #445 表单里的 AI 处理区（AiImageStudio）—— 业主：「商品上出图片的 ai 处理，UI 布局需要加强，
 * 目前排版混乱，看不懂功能」。这块历史上是四次需求各加一行长出来的（#321/#326/#336/#342），
 * 控件之间"谁属于哪一步"没有任何视觉交代，所以这一层做的不是配色，是**归属**：
 *   · 每一步一个带序号的标题，标题右侧留一句"这一步在回答什么问题"；
 *   · 拒因（.ai-plan.bad）留在第 2 步内部，紧挨它所描述的那个动作；
 *   · 第 3 步两个出口并排，各自带一行"什么时候走这条"，不再只剩一颗孤零零的按钮；
 *   · 第 4 步把"跑完放哪儿"做成一个能选的落点（追加 / 换掉第 N 张 / 换掉规格图）。
 * 颜色一律语义变量 + 浅色兜底（暗黑档不许白底黑字）；命中区一律 ≥44px；不写内联固定宽度。
 * ========================================================================*/
.aif{margin:6px 12px 10px;padding:0;border:1px solid var(--bd,#dcdfe6);border-radius:12px;
  background:var(--cd,#fff);overflow:hidden}
.aif__bar{display:flex;align-items:center;gap:8px;width:100%;min-height:48px;padding:10px 12px;
  border:0;background:var(--cb,#f5f7fa);color:var(--tc,#303133);font-size:14px;font-weight:600;
  text-align:left;cursor:pointer;line-height:1.3}
.aif__bar > .ic{font-size:18px;flex:none;color:var(--pci,#409eff)}
.aif__t{flex:0 1 auto;min-width:0}
.aif__sum{flex:1 1 auto;min-width:0;font-size:12px;font-weight:400;color:var(--ts,#606266);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.aif__caret{margin-left:auto;flex:none;font-size:20px;color:var(--ts,#606266)}
.aif__lead{margin:0;padding:6px 12px 10px;font-size:12px;line-height:1.6;color:var(--ts,#606266)}
.aif-step{padding:10px 12px;border-top:1px solid var(--bd,#dcdfe6)}
.aif-h{display:flex;align-items:center;gap:8px;margin:0 0 8px;font-size:13px;font-weight:600;color:var(--tc,#303133)}
.aif-n{flex:none;width:20px;height:20px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;
  font-size:12px;font-weight:600;color:var(--pci,#409eff);background:var(--cb,#eef1f6)}
/* 第 1 步：字段名 + 计数（原来"商品图片 (0/60)"和一句 AI 输入框挤在同一行，读作一个字段） */
.aif-field{display:flex;align-items:baseline;gap:8px;margin-bottom:6px;min-width:0}
.aif-field__l{font-size:13px;color:var(--tc,#303133);font-weight:600;min-width:0;overflow-wrap:anywhere}
.aif-field__n{font-size:12px;color:var(--ts,#606266);font-variant-numeric:tabular-nums;flex:none}
.aif-note{font-size:12px;color:var(--ts,#606266);margin-top:2px}
.aif-pick{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:8px}
.aif-pick__l{font-size:12px;color:var(--ts,#606266);flex:0 1 auto}
.aif-pick__s{flex:1 1 160px;min-width:0;max-width:280px}
/* 第 2 步：两选一的模式开关 —— 互斥关系用"同一组里只有一个 on"表达，不靠文字声明 */
.aif-modes{display:flex;gap:8px;flex-wrap:wrap}
.aif-mode{display:inline-flex;align-items:center;gap:6px;min-height:44px;padding:0 14px;border-radius:999px;
  border:1px solid var(--bd,#dcdfe6);background:var(--cd,#fff);color:var(--tc,#303133);font-size:13px;cursor:pointer}
.aif-mode.on{border-color:var(--pc,#409eff);background:var(--pc,#409eff);color:#fff}
.aif-say{margin-top:8px;width:100%}
.aif-chips{display:flex;flex-wrap:wrap;gap:8px;margin-top:8px}
.aif-chip{display:inline-flex;align-items:center;gap:6px;min-height:44px;padding:6px 12px;border-radius:10px;
  border:1px solid var(--bd,#dcdfe6);background:var(--cd,#fff);color:var(--tc,#303133);font-size:13px;cursor:pointer;flex:0 1 auto;min-width:0}
.aif-chip.on{border-color:var(--pc,#409eff);background:rgba(64,158,255,.14);color:var(--pci,#0069dc)}
/* 跑不动的动作：淡出 + 描边变灰，但**照样点得动**（AGENTS §182.2：不许用置灰代替"做不了"），
   点完立刻在第 2 步的 .ai-plan.bad 那一行里说清"没有平台能跑 + 接入谁之后可用"。 */
.aif-chip.off{opacity:.62;border-style:dashed}
.aif-chip__n{min-width:0;overflow-wrap:anywhere}
.aif-chip__c{font-size:12px;color:var(--ts,#606266);font-variant-numeric:tabular-nums;flex:none}
.ai-plan.bad{color:var(--e,#f56c6c);background:rgba(245,108,108,.12)}
.aif-refs,.aif-plat{margin-top:8px;min-width:0}
/* 第 3 步：两个出口并排。窄屏各占一行，谁也不许把对方挤掉（不许内联固定宽度） */
.aif-exits{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:10px}
.aif-exit{display:flex;flex-direction:column;gap:6px;padding:10px 12px;min-width:0;
  border:1px solid var(--bd,#dcdfe6);border-radius:10px;background:var(--cb,#f7f8fa)}
.aif-exit__h{font-size:13px;font-weight:600;color:var(--tc,#303133)}
.aif-exit__x{margin:0;font-size:12px;line-height:1.6;color:var(--ts,#606266)}
.aif-exit__w{margin:0;font-size:12px;line-height:1.5;color:var(--sci,#6b7280)}
.aif-btn{display:inline-flex;align-items:center;justify-content:center;gap:6px;min-height:44px;padding:0 14px;
  border-radius:999px;border:1px solid var(--pc,#409eff);background:var(--pc,#409eff);color:#fff;font-size:13px;
  cursor:pointer;align-self:flex-start;max-width:100%}
.aif-btn.ghost{background:var(--cd,#fff);color:var(--pci,#409eff)}
.aif-btn.run:disabled{background:var(--cb,#f5f7fa);border-color:var(--bd,#dcdfe6);color:var(--sci,#98a2b3);opacity:1}
.aif-btn.tiny{min-height:36px;padding:0 10px;font-size:12px}
.aif-tip{margin:6px 0 0;font-size:12px;line-height:1.6;color:var(--ts,#606266);word-break:break-word}
.aif-err{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:8px;padding:8px 10px;
  font-size:12px;line-height:1.5;color:var(--wci,#8a5300);background:rgba(255,149,0,.10);
  border:1px solid rgba(255,149,0,.35);border-radius:8px}
.aif-err.slim{margin-top:6px}
/* 第 4 步：落点。这一格是业主真正要的那件事（"处理完的图怎么绑定到商品中"）的界面答案 */
.aif-bind{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.aif-bind__l{font-size:12px;color:var(--ts,#606266);flex:0 1 auto}
.aif-bind__s{flex:1 1 200px;min-width:0;max-width:320px}
/* 物料那张图位（single 形态）：不套多图网格，一行图 + 两颗按钮 */
.aif-mat{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.aif-mat__i{width:72px;height:72px;object-fit:cover;border-radius:8px;border:1px solid var(--bd,#dcdfe6);flex:none}

/* ===== 出入库排名页 /rankings（#389，2026-10-07）=====
   这段样式原来整条写在 rankings.js 模板的内联 style 上，结果是窄屏想改一行都得跟内联样式打架
   （内联优先级压过所有选择器）。基准值与原来逐字一致，桌面外观不变；窄屏的覆盖在 20-mobile-layout.css。 */
.rank-card{padding:10px 12px}
.rank-tags{display:flex;flex-wrap:wrap;align-items:center;gap:6px}
.rank-tags--time{gap:8px;margin-top:10px}
.rank-tools{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-top:10px}
.rank-tools__lbl{font-size:12px;color:var(--ts)}
.rank-limit{width:130px}
.rank-chart{padding:0 12px}
.rank-chart__hd{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-bottom:6px}
.rank-chart__t{font-size:13px;font-weight:600;color:var(--tc)}
.rank-chart__lbl{font-size:11px;color:var(--ts)}
.rank-chart__box{background:var(--cd);border-radius:10px;padding:6px;border:1px solid var(--bd);max-height:480px;overflow:auto}
.rank-chart__foot{display:flex;flex-wrap:wrap;align-items:center;gap:8px;padding-top:4px;font-size:11px;color:var(--ts)}

/* ============================================================
 * #429 数据看板视觉层（门店 stores.js / 仓库 warehouses.js 共用一份）
 * 业主口径「现在的没有任何效果就是简单的文字」→ 排名出条、指标出块、
 * 每一块都要有 空/加载/失败 三态。
 * 只用既有令牌：文字一律 --tc/--ts/--pci 系；主色 --pc 只做底/轨道/强调块，
 * 绝不拿它当墨色（#364 刚清掉的 248 处不许在这一层重新长出来）。
 * 字号下限 12px（F1 判据）；触摸下限由 20-mobile-layout.css / 14-ui-unify.css
 * 末尾按控件族统一兜，这里不逐页贴补丁。
 * ============================================================ */
.db-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(148px,1fr));gap:8px;margin-bottom:12px}
.db-metric{position:relative;display:flex;flex-direction:column;gap:3px;padding:10px 12px;
  background:var(--cd);border:1px solid var(--bd);border-radius:var(--rm);box-shadow:var(--sh);overflow:hidden}
.db-metric::before{content:'';position:absolute;left:0;top:0;bottom:0;width:4px;background:var(--pc)}
.db-metric--ok::before{background:var(--sc)}
.db-metric--warn::before{background:var(--wc)}
.db-metric--bad::before{background:var(--dc)}
.db-metric--mut::before{background:var(--seg)}
.db-metric__v{font-size:20px;font-weight:700;line-height:1.25;color:var(--tc);
  font-variant-numeric:tabular-nums;word-break:break-all}
.db-metric__v--sub{font-size:14px;font-weight:600}
.db-metric__l{font-size:12px;color:var(--ts);display:flex;flex-wrap:wrap;align-items:baseline;gap:4px;min-width:0}
.db-metric__x{font-size:12px;color:var(--pci);font-weight:600;font-variant-numeric:tabular-nums}

.db-block{background:var(--cd);border:1px solid var(--bd);border-radius:var(--rm);margin-bottom:12px;overflow:hidden}
.db-block__hd{display:flex;flex-wrap:wrap;align-items:center;gap:8px;padding:9px 12px;
  border-bottom:1px solid var(--bd);background:var(--cb)}
.db-block__t{font-size:14px;font-weight:600;color:var(--tc);display:flex;align-items:center;gap:6px;min-width:0}
.db-block__n{font-size:12px;font-weight:400;color:var(--ts);font-variant-numeric:tabular-nums}
.db-block__tools{margin-left:auto;display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.db-count{display:flex;align-items:center;gap:6px}
.db-count__lbl{font-size:12px;color:var(--ts);white-space:nowrap}

.db-rank{display:flex;align-items:center;gap:10px;min-height:44px;padding:6px 12px;
  border-bottom:1px solid var(--bd);background:var(--cd)}
.db-rank:last-child{border-bottom:0}
.db-rank__idx{flex:none;min-width:22px;height:22px;padding:0 4px;border-radius:11px;
  display:inline-flex;align-items:center;justify-content:center;
  font-size:12px;font-weight:600;color:var(--ts);background:var(--cb);font-variant-numeric:tabular-nums}
.db-rank--1 .db-rank__idx{color:var(--seg-on-fg);background:var(--seg-on-bg)}
.db-rank--2 .db-rank__idx,.db-rank--3 .db-rank__idx{color:var(--pci);background:rgba(0,105,220,.1)}
.db-rank__name{flex:1 1 auto;min-width:0;font-size:13px;color:var(--tc);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.db-rank__sub{display:block;font-size:12px;font-weight:400;color:var(--ts)}
.db-rank__track{flex:1 1 46%;min-width:56px;height:8px;border-radius:999px;background:var(--cb);overflow:hidden}
.db-rank__fill{display:block;height:100%;border-radius:999px;background:var(--pc);transition:width .35s ease}
.db-rank--1 .db-rank__fill{background:var(--seg-on-bg)}
.db-rank__val{flex:none;min-width:64px;text-align:right;font-size:13px;font-weight:600;color:var(--tc);
  font-variant-numeric:tabular-nums}
.db-rank__val--amt{color:var(--pci)}

.db-row{display:flex;align-items:center;gap:10px;min-height:var(--db-row-h,56px);padding:6px 12px;
  border-bottom:1px solid var(--bd);background:var(--cd);cursor:pointer;transition:background .15s}
.db-row:last-child{border-bottom:0}
.db-row:hover{background:var(--cb)}
.db-row:active{background:rgba(0,105,220,.08)}
.db-row__main{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;gap:2px}
.db-row__no{font-size:13px;font-weight:600;color:var(--pci);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.db-row__meta{font-size:12px;color:var(--ts);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.db-row__amt{flex:none;font-size:14px;font-weight:700;color:var(--tc);font-variant-numeric:tabular-nums}
.db-row__go{flex:none;display:inline-flex;align-items:center;gap:2px;font-size:12px;color:var(--pci)}
.db-rows .db-row--lead{box-shadow:inset 3px 0 0 var(--pci)}

.db-state{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;
  padding:22px 12px;text-align:center;font-size:13px;color:var(--ts)}
.db-state--err{color:var(--dci)}
.db-state__act{margin-top:2px}

/* 看板订单区的展开/收起：沿用 #363 那套「标题行即开关 + v-show 主体」的机制，
   只是看板这一栏的行数由分页决定（一页 100 行），240px 的内滚窗口装不下，
   所以只加一档高度修饰，不改机制本身。 */
.tsh--dash{margin-top:0;border-top:0;padding-top:0}
.tsh--dash .tsh__hd{border-radius:var(--rm) var(--rm) 0 0;background:var(--cb);padding:9px 12px;
  border-bottom:1px solid var(--bd)}
.tsh__body--list{--db-row-h:56px;max-height:min(58vh,520px);overflow-y:auto;-webkit-overflow-scrolling:touch;padding-bottom:0}
.db-od__grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:8px;margin:10px 0}
.db-od__cell{display:flex;justify-content:space-between;gap:8px;padding:8px 10px;
  background:var(--cb);border-radius:var(--rs);font-size:13px;color:var(--tc);min-width:0}
.db-od__k{color:var(--ts);flex:none}
.db-od__v{min-width:0;overflow:hidden;text-overflow:ellipsis;font-variant-numeric:tabular-nums}

/* #429 仓库看板加强：进/出货两张榜的条色分开（出货=警告、进货=成功），第一名实心条；
   数值下方带「占榜首 N%」。文字一律走墨色/次级色令牌，不许拿品牌色 --pc 当墨水（#364 清过 248 处）。 */
.db-rank__fill--out{background:var(--wc)}
.db-rank__fill--in{background:var(--sc)}
.db-rank--1 .db-rank__fill--out,.db-rank--1 .db-rank__fill--in{background:var(--seg-on-bg)}
.db-rank__pct{display:block;font-size:12px;font-weight:400;color:var(--ts);font-variant-numeric:tabular-nums}
/* 调拨流水行的方向徽标：底色是主题色薄纱，暗黑同样读得出来（不靠 opacity 表达状态，#103） */
.db-row__dir{flex:none;min-width:44px;padding:3px 8px;border-radius:999px;font-size:12px;
  text-align:center;font-weight:600}
.db-row__dir--in{color:var(--sci);background:rgba(52,199,89,.14)}
.db-row__dir--out{color:var(--wci);background:rgba(255,149,0,.16)}
/* 选中行标记原先只在 .db-rows 容器里定义，看板那一条走的是 .tsh__body--list（#429 详情弹窗与行同键高亮） */
.tsh__body--list .db-row--lead{box-shadow:inset 3px 0 0 var(--pci)}

/* #469 合同操作台账弹层：采购合同页（contract.js）与合同管理页（contract-manage.js）共用一份。
   页面 CSS 是按路由懒加载的，写在页面里另一页就得复制第二份，所以放全局组件层。
   只用既有语义变量（暗黑随 var() 走），宽度交给弹层自身的百分比，表体不设固定宽度。 */
.audit-log-tip,.audit-log-empty,.audit-log-load{padding:10px 2px;color:var(--ts);font-size:13px;line-height:1.6}
.audit-log{width:100%;border-collapse:collapse;font-size:13px;color:var(--tc)}
.audit-log th,.audit-log td{padding:8px 10px;border-bottom:1px solid var(--bd);text-align:left;vertical-align:top;word-break:break-word}
.audit-log th{color:var(--ts);font-weight:600;background:var(--bg)}
/* 台账是查证据用的，纸面上不留表头与说明（打出来只有时间/人/动作/名称） */
@media print{.audit-log-tip,.audit-log-load,.audit-log th{display:none}}

/* #475 备注按人留痕面板（.rt*）的样式已搬到 assets/css/remark-thread.css。
   原因：#478 把同一份面板接进管理端（web/admin.html），而 admin 不加载 index 这套样式表；
   留在这里只有两条错路 —— 给 admin 抄第二份（一份版式两份真身），或让 admin 整份引 04-components
   （主站组件规则去改管理端界面）。跨入口共用组件按 stepper.css 先例放 assets/css/ 顶层。
   这里不再放 .rt 规则，也不要"顺手加回来"：check_media_security A24-10 判 .rt 只有一处真身。 */

/* #673：商品详情页「查无此商品 / 读取失败」的状态块。原来读不到数据时页签照画、面板全空，
   界面上没有任何一句话说明"是没有这条，还是没加载出来"，手机视口下整屏就是白的。
   min-height 用 60vh 是为了让这块自己占住首屏（内容锚点量得到，不是靠页签顶上来的）。 */
.pd-page .state{display:flex;flex-direction:column;align-items:center;justify-content:center;
  min-height:60vh;padding:24px 16px;text-align:center;gap:10px}
.pd-page .state__txt{font-size:15px;font-weight:600;color:var(--tc);max-width:100%}
.pd-page .state__hint{font-size:13px;color:var(--ts);line-height:1.6;max-width:30em}
.pd-page .state__acts{display:flex;flex-wrap:wrap;gap:10px;justify-content:center;margin-top:6px}
