* { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: -apple-system, "PingFang SC", "Microsoft YaHei", sans-serif; background: #f5f5f7; color: #222; }
.hidden { display: none !important; }

/* 登录 */
.login-box { max-width: 340px; margin: 14vh auto; background: #fff; padding: 32px 28px; border-radius: 14px; text-align: center; box-shadow: 0 4px 24px rgba(0,0,0,0.06); }
.login-box h1 { color: #b08d57; font-size: 26px; letter-spacing: 2px; }
.login-box p { color: #999; margin: 8px 0 20px; }
.login-box input { width: 100%; padding: 12px; border: 1px solid #ddd; border-radius: 8px; margin-bottom: 14px; font-size: 15px; }
.login-box button { width: 100%; padding: 12px; border: none; border-radius: 8px; background: #b08d57; color: #fff; font-size: 15px; cursor: pointer; }
.login-box button:disabled { opacity: .55; cursor: not-allowed; }

/* 品牌 Logo（缺图时自动隐藏，退回金色字标）
   ★ logo.svg 是「透明底 + 菱形 + 十字镂空」，所以：
     - object-fit 必须 contain（cover 会把上下尖角裁掉）；
     - 不能再用米色底 / border-radius / 方形 box-shadow —— 那三样是给不透明方图准备的，
       套在菱形上会露出一个米色方块；
     - 也不要用 filter: drop-shadow()：十字缝是透明的，投影会从缝里透出来，
       在菱形底端拖出一条脏线。想要立体感靠外包卡片本身的投影就够了。 */
.brand-logo { display: block; width: 76px; height: 76px; margin: 0 auto 14px; object-fit: contain; }
.hdr-logo { width: 24px; height: 24px; object-fit: contain; vertical-align: -7px; margin-right: 8px; }

/* 图形验证码 */
.cap-row { display: flex; gap: 10px; align-items: stretch; margin-bottom: 6px; }
.cap-row input { flex: 1; margin-bottom: 0 !important; letter-spacing: 3px; text-transform: uppercase; }
.cap-row canvas { width: 132px; height: 46px; border-radius: 8px; border: 1px solid #e6ded1; cursor: pointer; flex: 0 0 auto; background: #faf7f2; }
.cap-tip { color: #bbb; font-size: 12px; text-align: right; margin-bottom: 14px; }

.err { color: #e4393c; font-size: 13px; min-height: 18px; margin-top: 10px; line-height: 1.65; white-space: pre-line; text-align: left; }
.err .err-title { font-weight: 600; display: block; margin-bottom: 4px; }
.err ol { margin: 6px 0 0 18px; }
.err li { margin-bottom: 3px; }
/* 「我已开启，重新连接」是次要动作，要跟主按钮区分开（.login-box button 优先级更高，这里压回来） */
.login-box button.ghost { background: #f6f2ea; color: #8a6a33; border: 1px solid #e2d6c0; margin-top: 10px; font-size: 14px; }
.login-box button.ghost:hover { background: #efe8d9; }

/* 主界面 */
header { display: flex; justify-content: space-between; align-items: center; background: #fff; padding: 14px 20px; box-shadow: 0 1px 4px rgba(0,0,0,0.04); }
.brand { font-weight: 600; color: #b08d57; font-size: 17px; }

/* Tab 栏 */
/* ★ 18 个标签在 1440 宽的屏幕上按原来的 padding 放不下，flex 会把按钮压扁、
   中文被折成竖排两行（「成本测 / 算」），既难认又白占一行高度。
   改成：按钮不参与压缩 + 文字不折行 + 真放不下时整条横向滚动。 */
.tabs { display: flex; gap: 4px; background: #fff; padding: 10px 20px 0; border-bottom: 1px solid #eee; overflow-x: auto; overflow-y: hidden; scrollbar-width: thin; }
.tabs::-webkit-scrollbar { height: 4px; }
.tabs::-webkit-scrollbar-thumb { background: #ddd; border-radius: 2px; }
.tab { flex: 0 0 auto; white-space: nowrap; border: none; background: none; padding: 10px 12px; cursor: pointer; font-size: 14px; color: #666; border-bottom: 2px solid transparent; }
.tab.active { color: #b08d57; font-weight: 600; border-bottom-color: #b08d57; }

.panel { padding-bottom: 40px; }

/* ★★★ 整页同一条竖线（2026-10-30，Jeff：「为何页面的上方不统一两边对齐」）
   上一版只让表格 / 工具栏 / 分页条居中，页头和 tab 栏还是 100% 通栏：
   结果上方顶到屏幕两边、下方缩在中间，看着像两张皮。
   统一做法：body 上有一个 --col-w（= 当前面板的内容列宽，由 admin.js 的
   syncPageColumn 在切 tab / 表格渲染后同步），页头、tab 栏、提示条、面板全部用它。
   ★ 面板内部的 --tbl-w 是「面板级」变量，不会被这里影响；
     而 --col-w 只在 body 上，页面外壳和当前面板因此永远同一个宽度、同一条中心线。
   ★ 宽度不给死值、跟着当前面板走：切到分类页就该和分类表一样宽，不能留商品页的宽度。 */
header, .tabs, .ver-warn, .idle-warn, .panel {
  max-width: var(--col-w, none);
  margin-left: auto;
  margin-right: auto;
}

.toolbar { display: flex; gap: 8px; padding: 14px 20px 12px; flex-wrap: wrap; }
.toolbar input { flex: 1; min-width: 180px; padding: 9px 12px; border: 1px solid #ddd; border-radius: 8px; }
.toolbar button, .modal-actions button, .pager button, .item-actions button { padding: 9px 14px; border: none; border-radius: 8px; cursor: pointer; font-size: 14px; }
.primary { background: #b08d57; color: #fff; }
.ghost { background: #eee; color: #555; }
.ghost.small { padding: 5px 10px; font-size: 13px; }
.ghost.danger { background: #fde8e8; color: #e4393c; }

.list { padding: 0 20px 20px; display: grid; grid-template-columns: repeat(auto-fill, minmax(208px, 1fr)); gap: 12px; }
.card { background: #fff; border-radius: 10px; overflow: hidden; box-shadow: 0 1px 6px rgba(0,0,0,0.05); }
/* 商品缩略图只用来辨认，不用占那么大地方（原 180px 太高，一屏看不完几件） */
.card img { width: 100%; height: 116px; object-fit: cover; background: #f0f0f0; }
.card .info { padding: 10px 12px; }
.card .name { font-weight: 600; margin-bottom: 6px; }
.card .meta { color: #888; font-size: 13px; display: flex; justify-content: space-between; }
.card .price { color: #e4393c; font-weight: 600; font-size: 16px; }
.card .code { color: #b8860b; font-size: 12px; letter-spacing: .5px; }
.tag { display: inline-block; font-size: 12px; padding: 1px 8px; border-radius: 10px; }
.tag.on { background: #e8f7ee; color: #1aad19; }
.tag.off { background: #f3f3f3; color: #999; }
.tag.wait { background: #fdf3e6; color: #e6a23c; }
/* 客户类型：企业用金色、个人用灰蓝，跟「等级」的绿色区分开（两个 tag 挨着放时不混） */
.tag.gold { background: #fbf3df; color: #b8860b; }
.tag.grey { background: #eef1f5; color: #6b7a8d; }
/* 蓝色 = 注册用户（区别于「订单」绿、「手工」灰） */
.tag.blue { background: #e8f2fd; color: #1f6fb2; }
.item-actions { display: flex; gap: 8px; padding: 0 12px 12px; }
.item-actions button { flex: 1; }

.pager { text-align: center; padding: 10px 0 40px; }
.pager button { margin: 0 6px; }
.pager .disabled { opacity: 0.4; pointer-events: none; }

/* 弹窗 */
.modal { position: fixed; inset: 0; background: rgba(0,0,0,0.45); display: flex; align-items: flex-start; justify-content: center; overflow: auto; padding: 30px 12px; z-index: 50; }
.modal-card { background: #fff; width: 100%; max-width: 480px; border-radius: 12px; padding: 22px; }
.modal-card.wide { max-width: 640px; }.modal-card h2 { color: #b08d57; margin-bottom: 16px; }
form label { display: block; font-size: 13px; color: #666; margin-bottom: 12px; }
.modal-card label { display: block; font-size: 13px; color: #666; margin-bottom: 12px; }
.modal-card label input, .modal-card label select, .modal-card label textarea { width: 100%; margin-top: 5px; padding: 9px 11px; border: 1px solid #ddd; border-radius: 8px; font-size: 14px; font-family: inherit; }
.row { display: flex; gap: 12px; }
.row label { flex: 1; }
.img-preview { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 12px; }
.img-preview .thumb { position: relative; }
.img-preview img { width: 64px; height: 64px; object-fit: cover; border-radius: 6px; border: 1px solid #eee; }
.img-preview .del { position: absolute; top: -6px; right: -6px; background: #e4393c; color: #fff; border: none; border-radius: 50%; width: 18px; height: 18px; font-size: 12px; cursor: pointer; line-height: 1; }
/* 分类图标：预览 + 上传/清除 + 一句状态（fileID 不外露给商家） */
.icon-fld { margin-bottom: 12px; }
.icon-cap { font-size: 13px; color: #666; margin-bottom: 6px; }
.icon-row { display: flex; align-items: flex-start; gap: 12px; }
.icon-prev {
  width: 56px; height: 56px; flex: 0 0 56px; border: 1px dashed #ddd; border-radius: 10px;
  display: flex; align-items: center; justify-content: center; overflow: hidden;
  background: #fafafa; cursor: pointer;
}
.icon-prev:hover { border-color: #b08d57; }
.icon-prev img { width: 100%; height: 100%; object-fit: cover; display: block; }
.icon-prev .c-emoji { font-size: 26px; line-height: 1; }
.icon-prev .icon-empty { font-size: 11px; color: #bbb; text-align: center; line-height: 1.3; padding: 0 4px; }
.icon-ops { flex: 1; min-width: 0; }
.icon-btns { display: flex; gap: 8px; }
.icon-state { display: block; margin-top: 7px; font-size: 12px; color: #b3a894; line-height: 1.5; }
.icon-state.warn { color: #d4380d; }
.modal-actions { display: flex; gap: 10px; justify-content: flex-end; margin-top: 6px; }
/* 弹窗里标题下的一句说明（如「停用后历史流水仍保留」） */
.modal-card .modal-sub { font-size: 12.5px; line-height: 1.7; color: #8b8074; margin: -6px 0 14px; }

/* ==========================================================================
   测试单清理弹层（2026-10-30）
   ★ 这里**刻意不复用 .tbl**：.tbl 那套带 table-layout:fixed + max-width:var(--tbl-w)，
     放进弹层会因为 var 取自外层面板而宽度错乱。弹层里就 6 列、内容短，用网格最省事。
   ========================================================================== */
#modal-testPurge .modal-card { max-width: 880px; }
.tp-sum { font-size: 13px; color: #5f4a2c; margin: 0 0 10px; }
.tp-sum b { color: #b8860b; font-size: 15px; }
.tp-sum .warn { color: #c0392b; }
.tp-scroll { max-height: 320px; overflow: auto; border: 1px solid #efe9dd; border-radius: 8px; }
.tp-row {
  display: grid;
  grid-template-columns: 168px 122px 78px minmax(140px, 1fr) 132px 64px;
  gap: 8px; align-items: center;
  padding: 7px 10px; font-size: 12.5px; color: #333;
  border-bottom: 1px solid #f6f2ea;
}
.tp-row:last-child { border-bottom: none; }
.tp-row.head { background: #faf8f4; color: #7a7062; font-weight: 600; position: sticky; top: 0; z-index: 1; }
.tp-row .mono { font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 12px; }
.tp-row .ellip { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tp-blocked {
  margin-top: 10px; padding: 9px 12px; border-radius: 8px;
  background: #fdf6e3; border-left: 4px solid #b8860b;
  font-size: 12px; color: #6b5b3a; line-height: 1.8; max-height: 130px; overflow: auto;
}
.tp-ops { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 14px; }
.tp-ops .tp-sp { flex: 1 1 auto; }
/* ★ 弹层里的 label 会被 `.modal-card label { display:block }` 接管 —— 复选框会被顶到
   文字上面一行、右边再撑出 100% 宽度（预览时一眼就看出来：「含已发货的单」竖着长）。
   所以这里把这条链上的 display / width / margin 全部写死回 inline。 */
.tp-ops .stat-chk {
  display: inline-flex; align-items: center; gap: 6px;
  margin: 0; font-size: 12.5px; color: #6b5b3a; white-space: nowrap;
}
.tp-ops .stat-chk input { width: 15px; height: 15px; margin: 0; accent-color: #b8860b; }
.tp-ops input[type=password] {
  width: 200px; padding: 9px 11px; border: 1px solid #ddd; border-radius: 8px; font-size: 13px;
}
/* 危险动作：和普通主按钮区分开，避免手滑 */
.btn-danger, .primary.danger { background: #c0392b !important; color: #fff !important; }
.btn-danger:hover, .primary.danger:hover { background: #a93226 !important; }
.primary.danger:disabled { background: #d8b3ae !important; cursor: not-allowed; }

.toast { position: fixed; bottom: 30px; left: 50%; transform: translateX(-50%); background: rgba(0,0,0,0.8); color: #fff; padding: 10px 18px; border-radius: 8px; font-size: 14px; z-index: 99; }

/* ==========================================================================
   统一表格：后台所有列表页共用这一套（商品/分类/轮播/订单/售后/咨询/经纪人/券/会员/账号）
   ★ 以前每个模块各写一套（.table / .tbl / .acct-table），行高、表头色、空态
     全都对不齐，看着就「乱」。新增列表一律用 .tbl-wrap > table.tbl
   ========================================================================== */
.tbl-wrap, .table-wrap { padding: 0 20px 14px; overflow-x: auto; }
/* ★★★ 面板内的「内容列」对齐（2026-10-29 第三版）
   表格是按内容宽度排的（见 renderTable 的 max-width），大屏上它会只占左边一段。
   如果工具栏 / 筛选条 / 分页条继续 100% 铺满，就会出现「表格在左、搜索框拉到 1000px、
   「导出 CSV」甩到屏幕最右边」——那是 Jeff 在 2K 屏上看到并质疑的形态。
   --tbl-w 由 renderTable 写在 .panel 上（取该面板内最宽的那张表），
   下面这几块统一跟它对齐，左右边界就和表格完全一致。 */
.toolbar, .filter-bar, .tbl-wrap, .table-wrap, .hint-box {
  max-width: var(--tbl-w, none);
  /* ★★★ 居中（2026-10-30，Jeff：「后台页面能否做到两段对齐」）
     上面那句 max-width 只做到「收窄」，元素依然贴左 → 宽屏上右边空出 972px，
     看着像内容只占了半个页面。真正让「左右留白相等」的是 margin:auto。
     ★ 窗口比 --tbl-w 窄时，元素本身就是 100% 宽，margin:auto 自动失效，小屏行为不变。 */
  margin-left: auto;
  margin-right: auto;
}
/* ★ 子标签栏 / 列表标题行也要跟着同一把尺子（2026-10-30，客户 → 购物车）。
   两者都是 `padding: … 20px …`、和 .toolbar 一致，所以加上来之后
   子标签按钮、工具栏第一个按钮、表格左边缘严格对齐。
   ★ 不加上来会怎么样：面板 1200 宽居中，购物车表只有 1116 → 工具栏居中后
     左移 42px，子标签还贴在 1200 的最左边 → 又变成「上面一截、下面一截」。
   ★ .list-head 同理，尤其是它右边那个「刷新」按钮用 space-between 顶到最右，
     不跟尺子就会甩到面板最右边、跟表格右边缘错开。 */
.subtabs, .list-head {
  max-width: var(--tbl-w, none);
  margin-left: auto;
  margin-right: auto;
}
/* 分页条的两次修正（别各改一半，会互相打架）：
   ① 2026-10-29：按钮不能再往右推 —— 原来有个 `.tp-sp { flex:1 }` 把按钮甩到面板最右边，
      Jeff 在 2K 屏上一眼看出来「表格在左、按钮在最右」。改成 `flex: 0 0 auto`，按钮紧跟统计。
   ② 2026-10-30：分页条**要**跟表格同一把尺子（--tbl-w）并一起居中，见下面 .tbl-pager 里那条。
   ★ 这一条才是生效的那条（同名规则后者胜，别再在后面补一条 flex:1）。 */
/* 报表分页条：一屏只留一条工具条（共 N 条 · 每页 N 条 · 翻页 · 导出） */
.tbl-pager {
  display: flex; align-items: center; flex-wrap: wrap; gap: 8px;
  padding: 4px 20px 18px; font-size: 13px; color: #666;
  /* ★★ 分页条跟表格用同一把尺子并一起居中（2026-10-30）。
     以前这里故意不设 max-width：怕把它压窄了折行。现在设了，但只有在
     .tbl-pager 内容比表格还宽时才会折 —— 实测最窄的带分页条的表是分类表 612px，
     内容区 572px，而分页条内容约 480px，仍有 90px 余量。
     ★ 它自带和 .tbl-wrap 一样的左右 20px padding，所以内容起点/终点和表格严格对齐。 */
  max-width: var(--tbl-w, none);
  margin-left: auto;
  margin-right: auto;
}
.tbl-pager .tp-info b { color: #333; font-size: 14px; }
.tbl-pager .tp-hint { margin-left: 8px; color: #b8860b; font-size: 12px; }
.tbl-pager .tp-sp { flex: 0 0 auto; }
.tbl-pager .tp-size { color: #666; white-space: nowrap; }
.tbl-pager .tp-sel {
  height: 30px; padding: 0 6px; border: 1px solid #ddd; border-radius: 6px;
  background: #fff; font-size: 13px; font-family: inherit; color: #333;
}
.tbl-pager .tp-btn {
  height: 30px; padding: 0 12px; border: 1px solid #ddd; border-radius: 6px;
  background: #fff; color: #555; font-size: 13px; font-family: inherit; cursor: pointer;
}
.tbl-pager .tp-btn:hover { border-color: #b8860b; color: #b8860b; }
.tbl-pager .tp-btn.primary { background: #b8860b; border-color: #b8860b; color: #fff; }
.tbl-pager .tp-btn.primary:hover { opacity: .9; color: #fff; }
.tbl-pager .tp-btn[disabled] { color: #bbb; border-color: #eee; background: #fafafa; cursor: not-allowed; }
.tbl-pager .tp-btn[disabled]:hover { color: #bbb; border-color: #eee; }

.tbl, .table { width: 100%; border-collapse: collapse; font-size: 13px; background: #fff; border-radius: 10px; overflow: hidden; box-shadow: 0 1px 6px rgba(0,0,0,0.05); }
/* ★★★ table-layout: fixed —— 让「声明了多少就是多少」
   默认的 auto 布局里，width 只是**建议值**：浏览器会按内容重新分配。
   实测（优惠券表）声明「生效日 96px、操作 124px」，因为券名称那列文字长，
   浏览器把这两列压到 85px 和 103px → 「操作」里两个按钮被挤成上下两行，行高从 44 变 71。
   这正是 Jeff 说的「表格格式做得太差」的一种形态：看着空的地方不空，看着该宽的地方反而窄。
   fixed 之后列宽完全按 renderTable 里的 w 走，行高稳定；超长内容交给 .ellip 省略号。
   ★ 代价：内容比列宽长时不会「自动撑开」，所以列宽必须量过（tools/audit-table-cols.js）。 */
.tbl { table-layout: fixed; }
.tbl th, .table th { background: #faf7f2; color: #6b5a3e; font-weight: 600; font-size: 13px; padding: 9px 12px; text-align: left; white-space: nowrap; border-bottom: 1px solid #ece5d8; }
.tbl td, .table td {
  padding: 8px 12px; text-align: left; border-bottom: 1px solid #f2efe9; vertical-align: middle;
  /* fixed 布局下格子不会自动变宽，漏了 .ellip 的长文本会横穿到隔壁列（看着像乱码）。
     兜一道：宁可截断，也不许压别人的格子。 */
  overflow: hidden;
}
.tbl tbody tr:last-child td, .table tr:last-child td { border-bottom: none; }
.tbl tbody tr:hover td { background: #fdfbf7; }
.tbl tr.is-off td { color: #b5b5b5; }

/* 单元格内的排版小件 */
.tbl .num { text-align: right; font-variant-numeric: tabular-nums; }
.tbl .ctr { text-align: center; }
.tbl .u { font-family: Consolas, Monaco, monospace; color: #8a6a33; }
.tbl .money { color: #c0392b; font-weight: 600; }
/* 已取消 / 已停用的行整行变灰，金额也别再抢眼 */
.tbl tr.is-off .money { color: #a8a8a8; font-weight: 500; }

/* 商品列表「上架 / 下架」两行小字（Jeff：显示上架日期和下架日期）
   ★ 为什么挤一列两行而不是并排两列：商品表 11 列自然宽已 1002px，
     可用宽只有 1052px（1092 窗口 − 40），再加两列必然要横向拖才能看到日期。
   ★ 两行**不会把行撑高**：缩略图 40px 已经把行撑到 56px，两行 11.5px 才 34px。
   ★ white-space:nowrap 不能少 —— 少了之后窄列里「2026-10-21 20:57」
     会被折成「2026-10-21」+「20:57」两行，一行变四行，整张表立刻散架。 */
.tbl .shelf { line-height: 1.45; }
.tbl .shelf-l { display: flex; align-items: baseline; gap: 4px; white-space: nowrap; }
.tbl .shelf-l + .shelf-l { margin-top: 1px; }
.tbl .shelf-k {
  flex: 0 0 auto; font-style: normal; font-size: 11px; line-height: 1.45;
  padding: 0 2px; border-radius: 3px; color: #8a7a5e; background: #f5f1e9;
}
/* 上架=绿、下架=灰，跟原来那颗 tag 的配色一致，扫一眼就知道在不在卖 */
.tbl .shelf-k.on { color: #1aad19; background: #e8f7ee; }
.tbl .shelf-k.off { color: #8f8f8f; background: #f3f3f3; }
.tbl .shelf-v { font-size: 11.5px; color: #555; font-variant-numeric: tabular-nums; }
/* 虚线 = 这个时间是按商品创建时间推算的（上线前就建好的老商品，库里没记真实上架时刻） */
.tbl .shelf-v.guess { border-bottom: 1px dotted #c9bda6; cursor: help; }
/* ★★★ 必须 display:inline-block —— max-width / overflow / text-overflow 对**行内元素无效**！
   咨询列表的「最新消息」就是纯 <span class="ellip">，没有 inline-block，
   于是 max-width 300px 完全不生效，文字直接压到右边「openid / 状态 / 更新时间」三列上
   （Jeff 截图里那一行字横穿整行就是这个）。商品名称那种自带 style="display:inline-block"
   的反而没事 —— 所以这问题只在个别表冒出来，很容易漏。 */
.tbl .ellip {
  display: inline-block; max-width: 100%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  vertical-align: bottom;
}
/* ★★★ fixed 布局的必配兜底：超长文字不会再把格子撑开，不截断就会**压到隔壁列上**。
   商品表就是现成的例子：商品名称 170px，`.ellip` 的内联 max-width 写着 280px，
   fixed 之后它按 280 渲染 → 名字后半截直接盖住「编号」列（截图里一眼就看见）。
   内联样式优先级最高，所以这里必须 !important；100% = 单元格内容宽度。 */
.tbl td .ellip { max-width: 100% !important; }
/* 售后「商品」列：一单多件就一行一件。
   ★ 必须 nowrap —— 不写的话列一窄中文会「一个字一行」竖着排，行高直接翻几倍。
     完整名称在 title 里（鼠标悬停可见），不要为了显示全名把整张表撑爆。 */
.goods-cell > div { max-width: 232px; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; line-height: 1.75; }
/* ★★ 232px 是给「售后 / 订单」那种固定列宽的表定的。客户购物车那张表的「内容」列
   天生更宽（一列里装好几个商品），照抄 232px 会被截掉一半、右边空一大片 ——
   和 .ellip 那次（max-width 挂在行内元素上）是同一类坑：**上限借错了地方**。
   所以给个修饰类，只在使用它的那处放开到列宽本身。 */
.goods-cell.wide > div { max-width: 100%; }
.tbl .nowrap { white-space: nowrap; }
.tbl .row-actions { white-space: nowrap; text-align: right; }
.tbl .row-actions button { margin-right: 6px; }
.tbl .row-actions button:last-child { margin-right: 0; }
/* 主标题 + 副标题两行：商品名 + 编号、订单号 + 下单时间 等 */
.tbl .tbl-main { font-weight: 600; color: #333; line-height: 1.4; }
.tbl .tbl-sub { color: #999; font-size: 12px; margin-top: 3px; line-height: 1.4; }
/* 表格里直接编辑的单元格（会员档位门槛/折扣、经纪人佣金比例） */
.tbl td > input, .tbl td > select { width: 100%; padding: 6px 9px; border: 1px solid #ddd; border-radius: 6px; font-size: 13px; font-family: inherit; }
.tbl td > input.narrow { width: 88px; }
/* 表格里的「排序」小输入框：窄、居中，改完自动保存 */
// 排序输入框：54px 装 4 位数绰绰有余（原来 62 白占 8px 列宽）。
// ★ 必须把 up/down 箭头关掉：type=number 的 spinner 会吃掉十几个像素，
//   54px 时占位符「默认」被切成「默」+ 半个箭头（截图确认过）。
.tbl .tbl-sort { width: 54px; height: 30px; padding: 0 4px; text-align: center; border-radius: 6px; }
.tbl .tbl-sort::-webkit-inner-spin-button, .tbl .tbl-sort::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
.tbl .tbl-sort { -moz-appearance: textfield; }
.tbl td > input[type=number] { text-align: right; }

.c-icon { font-size: 22px; }
.c-emoji { font-size: 22px; }
.thumb-sm, .thumb-img { width: 40px; height: 40px; object-fit: cover; border-radius: 6px; background: #f0f0f0; vertical-align: middle; }
.thumb-wide { width: 96px; height: 54px; object-fit: cover; border-radius: 6px; background: #f0f0f0; vertical-align: middle; }
.link-cell { max-width: 220px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: #888; }
.row-actions { white-space: nowrap; }

.empty { text-align: center; color: #999; padding: 60px 20px; font-size: 14px; }
/* 列表空态：包一张白卡片，别在灰底上孤零零一行字 */
.tbl-empty { background: #fff; border-radius: 10px; box-shadow: 0 1px 6px rgba(0,0,0,0.05); margin: 0 20px; padding: 48px 20px; }

/* 订单筛选 */
.order-filter { display: flex; gap: 8px; padding: 16px 20px 4px; flex-wrap: wrap; }
.order-filter input { padding: 9px 12px; border: 1px solid #ddd; border-radius: 8px; font-size: 14px; width: 150px; }
.order-filter button { padding: 9px 14px; border: none; border-radius: 8px; cursor: pointer; font-size: 14px; }
.count-tip { padding: 6px 20px 0; color: #999; font-size: 13px; }

/* 订单卡片 */
.order-list { padding: 10px 20px 20px; display: grid; grid-template-columns: repeat(auto-fill, minmax(340px, 1fr)); gap: 14px; }
.o-card { background: #fff; border-radius: 10px; padding: 14px; box-shadow: 0 1px 6px rgba(0,0,0,0.05); cursor: pointer; transition: box-shadow 0.15s; }
.o-card:hover { box-shadow: 0 3px 12px rgba(0,0,0,0.1); }
.o-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; }
.o-no { font-weight: 600; font-size: 14px; color: #555; word-break: break-all; }
/* ★ white-space: nowrap 必须加：表格被挤窄时「已付款」会竖成「已付/款」三个字两行，
   一行高度直接翻倍。宁可让表格横向滚动，也不要状态标签变形。 */
.o-status { display: inline-block; font-size: 13px; padding: 2px 10px; border-radius: 10px; color: #fff; flex-shrink: 0; white-space: nowrap; }
.o-status.s0 { background: #e6a23c; }
.o-status.s1 { background: #409eff; }
.o-status.s2 { background: #07a35a; }
.o-status.s3 { background: #b08d57; }
.o-status.s4 { background: #e4393c; }
/* s5 / s6 不是订单 status，是「售后状态」的显示用色：
   已退款（紫）要和已完成的金、已取消的红都区分开，一眼能看出钱退回去了 */
.o-status.s5 { background: #8b6fb8; }
.o-status.s6 { background: #d48806; }
/* 状态列的第二行：原订单状态，小字灰，别抢主标签 */
.rf-sub { font-size: 11px; color: #a99a80; margin-top: 3px; }
.o-line { font-size: 13px; color: #666; margin-bottom: 6px; line-height: 1.5; }
.o-label { color: #999; margin-right: 6px; }
.o-foot { display: flex; justify-content: space-between; align-items: center; margin-top: 10px; padding-top: 10px; border-top: 1px solid #f0f0f0; }
.o-time { color: #999; font-size: 12px; }
.o-total { color: #e4393c; font-weight: 600; font-size: 15px; }
.o-tip { margin-top: 8px; font-size: 12px; color: #b08d57; text-align: right; }

/* 订单详情 */
.od-status { display: inline-block; font-size: 14px; padding: 3px 14px; border-radius: 12px; color: #fff; margin-bottom: 14px; }
.od-status.s0 { background: #e6a23c; }
.od-status.s1 { background: #409eff; }
.od-status.s2 { background: #07a35a; }
.od-status.s3 { background: #b08d57; }
.od-status.s4 { background: #e4393c; }

.timeline { padding: 6px 0 16px; }
.t-item { display: flex; gap: 12px; padding-bottom: 16px; position: relative; }
.t-item:not(:last-child)::before { content: ''; position: absolute; left: 7px; top: 18px; bottom: 0; width: 2px; background: #eee; }
.t-item.done:not(:last-child)::before { background: #b08d57; }
.t-dot { width: 16px; height: 16px; border-radius: 50%; background: #ddd; flex-shrink: 0; margin-top: 2px; }
.t-item.done .t-dot { background: #b08d57; }
.t-title { font-size: 14px; font-weight: 600; color: #999; }
.t-item.done .t-title { color: #333; }
.t-time { font-size: 12px; color: #bbb; margin-top: 2px; }
.t-item.done .t-time { color: #999; }

.od-block { border-top: 1px solid #f0f0f0; padding: 12px 0; }
.od-title { font-size: 14px; font-weight: 600; color: #b08d57; margin-bottom: 8px; }
.od-row { display: flex; font-size: 13px; color: #555; margin-bottom: 6px; line-height: 1.5; }
.od-label { width: 70px; color: #999; flex-shrink: 0; }
.og-item { display: flex; align-items: center; gap: 10px; padding: 6px 0; }
.og-img { width: 48px; height: 48px; object-fit: cover; border-radius: 6px; background: #f0f0f0; flex-shrink: 0; }
.og-info { flex: 1; min-width: 0; }
.og-name { font-size: 13px; color: #333; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.og-meta { font-size: 12px; color: #999; margin-top: 3px; }
.og-sub { font-size: 13px; color: #b08d57; font-weight: 600; flex-shrink: 0; }
.od-total { text-align: right; font-size: 15px; color: #e4393c; font-weight: 600; padding-top: 12px; border-top: 1px solid #f0f0f0; }

/* 咨询 */
.msg-list { padding: 16px 20px 20px; display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 14px; }
.m-card { background: #fff; border-radius: 10px; padding: 14px; box-shadow: 0 1px 6px rgba(0,0,0,0.05); cursor: pointer; }
.m-card:hover { box-shadow: 0 3px 12px rgba(0,0,0,0.1); }
.m-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; }
.m-name { font-weight: 600; font-size: 14px; }
.m-content { font-size: 13px; color: #666; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; margin-bottom: 10px; }
.m-foot { display: flex; justify-content: space-between; font-size: 12px; color: #999; }

.chat-history { max-height: 300px; overflow-y: auto; padding: 10px; background: #f7f7f9; border-radius: 8px; margin-bottom: 12px; }
.bubble { max-width: 78%; padding: 8px 12px; border-radius: 10px; font-size: 14px; margin-bottom: 10px; line-height: 1.5; }
.bubble.shop { background: #fff; border: 1px solid #eee; margin-right: auto; }
.bubble.me { background: #b08d57; color: #fff; margin-left: auto; }
.b-time { font-size: 11px; opacity: 0.6; margin-top: 4px; }

/* ===== 商品编辑弹窗扩展 ===== */
.modal-card.wide { width: 92vw; max-width: 880px; max-height: 92vh; overflow-y: auto; }
.section { background: #fafafa; border-radius: 8px; padding: 14px; margin-bottom: 14px; }
.section h3 { margin: 0 0 10px; font-size: 15px; color: #333; }

/* 规格项 */
.spec-item { background: #fff; padding: 10px; border-radius: 6px; margin-bottom: 10px; }
.spec-head-row { display: flex; gap: 8px; margin-bottom: 8px; }
.spec-head-row input { flex: 1; padding: 6px 10px; border: 1px solid #ddd; border-radius: 6px; font-size: 13px; }
.spec-vals-row { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.spec-val-input { display: flex; align-items: center; background: #fff; border: 1px solid #ddd; border-radius: 6px; }
.spec-val-input input { width: 130px; padding: 6px 10px; border: none; font-size: 13px; outline: none; }
.spec-val-input button { background: transparent; border: none; color: #999; padding: 0 8px; cursor: pointer; }

/* SKU 子表 */
.sku-item { background: #fff; padding: 10px; border-radius: 6px; margin-bottom: 10px; }
.sku-head-row { display: flex; gap: 8px; margin-bottom: 8px; }
.sku-head-row input { flex: 1; padding: 6px 10px; border: 1px solid #ddd; border-radius: 6px; font-size: 13px; font-weight: 600; }
.sku-spec-row { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 8px; }
.sku-spec-cell { flex: 1; min-width: 130px; display: flex; flex-direction: column; }
.sku-spec-cell .lbl { font-size: 11px; color: #999; margin-bottom: 2px; }
.sku-spec-cell input { padding: 5px 8px; border: 1px solid #ddd; border-radius: 4px; font-size: 12px; }
.sku-price-row { display: flex; gap: 8px; margin-bottom: 8px; }
.sku-price-row label { flex: 1; font-size: 12px; color: #666; }
.sku-price-row label input { width: 100%; padding: 5px 8px; border: 1px solid #ddd; border-radius: 4px; font-size: 12px; margin-top: 2px; }
.sku-img-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.sku-thumb { position: relative; display: inline-block; }
.sku-thumb img { width: 60px; height: 60px; object-fit: cover; border-radius: 4px; }
.sku-thumb button { position: absolute; top: -6px; right: -6px; background: rgba(0,0,0,0.6); color: #fff; border: none; border-radius: 50%; width: 20px; height: 20px; cursor: pointer; font-size: 12px; }

/* ==========================================================================
   新增模块通用件（售后 / 经纪人 / 优惠券 / 会员 / 店铺）
   ========================================================================== */
.section-card { background: #fff; border-radius: 8px; padding: 16px; margin-bottom: 14px; }
.section-card h3 { margin: 0 0 12px; font-size: 15px; border-left: 4px solid #b8860b; padding-left: 8px; }
.section-card .row { align-items: flex-end; }

.hint-box {
  background: #fdf6e3; border-left: 4px solid #b8860b;
  /* ★ 左右必须是 auto 不能是 0（2026-10-30）：上面那条组规则给了
     max-width: var(--tbl-w)，可这里是 `margin` 简写、且写在后面 ——
     简写会把 margin-left/right 一起重置成 0，居中当场失效（同名后者胜）。
     实测：面板 1200、购物车表 1116 时会偏左 42px，一眼就能看出「上面一截下面一截」。 */
  padding: 10px 12px; margin: 10px auto; font-size: 12.5px; color: #6b5b3a; line-height: 1.7;
}
.hint-box b { color: #8a6d0b; }
.hint-box:empty { display: none; }
label.inline { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; color: #333; }
label.inline input[type="checkbox"] { width: auto; margin: 0; }

.muted { color: #999; }
.err-text { color: #c0392b; }
hr { border: none; border-top: 1px solid #eee; margin: 14px 0; }

/* 表格里的小按钮（行内操作） */
.rf-btn.sm { padding: 4px 10px; font-size: 12px; }
.tbl .rf-btns { display: flex; flex-wrap: wrap; gap: 6px; justify-content: flex-end; }
/* 待处理的行给一点底色，一眼看到该干活的单子 */
.tbl tr.is-wait td { background: #fffdf6; }

/* 售后（列表已改成表格，卡片样式只留弹窗/详情里可能用到） */
.rf-card { background: #fff; border-radius: 8px; padding: 14px; margin-bottom: 12px; }
.rf-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.rf-no { font-weight: 600; font-size: 14px; }
.rf-line { font-size: 13px; color: #555; margin: 4px 0; }
.rf-g { font-size: 13px; padding: 2px 0; }
.rf-acts { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; padding-top: 10px; border-top: 1px dashed #eee; }
.rf-btn {
  background: #fff; border: 1px solid #ddd; color: #555;
  padding: 6px 14px; border-radius: 6px; font-size: 13px; cursor: pointer;
}
.rf-btn:hover { border-color: #b8860b; color: #b8860b; }
.rf-btn.primary { background: #b8860b; border-color: #b8860b; color: #fff; }
.rf-btn.primary:hover { opacity: .9; color: #fff; }
.rf-btn.danger { background: #fff; border-color: #c0392b; color: #c0392b; }

/* 状态标签（售后 / 经纪人 / 券 共用） */
.rf-status { font-size: 12px; padding: 3px 9px; border-radius: 4px; background: #f2f2f2; color: #777; white-space: nowrap; }
.rf-status.s-applied    { background: #fdecea; color: #c0392b; }   /* 待处理：要紧 */
.rf-status.s-agreed     { background: #fdf6e3; color: #8a6d0b; }
.rf-status.s-returned   { background: #fdf6e3; color: #8a6d0b; }
.rf-status.s-refunding  { background: #eaf2fa; color: #1c5d99; }
.rf-status.s-refunded   { background: #eaf7f0; color: #1e7f4f; }
.rf-status.s-rejected   { background: #f2f2f2; color: #999; }
.rf-status.s-canceled   { background: #f2f2f2; color: #999; }
.rf-status.s-failed     { background: #fdecea; color: #c0392b; }
.rf-status.s-applying   { background: #fdf6e3; color: #8a6d0b; }
.rf-status.s-on         { background: #eaf7f0; color: #1e7f4f; }
.rf-status.s-off        { background: #f2f2f2; color: #999; }

/* 会员档位行 */
.lv-row { display: flex; gap: 8px; align-items: center; padding: 8px 0; border-bottom: 1px solid #f5f5f5; }
.lv-in { padding: 7px 10px; border: 1px solid #ddd; border-radius: 6px; font-size: 13px; }
.lv-name { flex: 2; }
.lv-min { flex: 1; text-align: center; }
.lv-dis { flex: 1; text-align: center; }

/* 店铺营业状态 */
.shop-state { font-size: 22px; font-weight: 700; padding: 10px 0; }
.shop-state.on { color: #1e7f4f; }
.shop-state.off { color: #c0392b; }

/* ===== 顶栏登录账号信息 ===== */
.hdr-right { display: flex; align-items: center; gap: 14px; }
.who { font-size: 13px; color: #6b5a3e; background: #faf7f2; border: 1px solid #e8e0d0; padding: 5px 12px; border-radius: 20px; white-space: nowrap; }
.who b { color: #8a6a33; font-weight: 600; }
.who .role { color: #b08d57; margin-left: 6px; }
.who .via { color: #b9ab90; margin-left: 6px; font-size: 12px; }

/* ===== 账号管理 ===== */
/* 面板里的按钮：这些按钮不在 .toolbar / .modal-actions 里，得单独给一套尺寸 */
.section-card button { padding: 9px 16px; border: none; border-radius: 8px; cursor: pointer; font-size: 14px; }
.section-card button.ghost { background: #eee; color: #555; }
/* 账号表沿用统一 .tbl，这里只放账号专属的小件 */
.acct-badge { display: inline-block; font-size: 12px; padding: 1px 8px; border-radius: 10px; background: #f3efe7; color: #8a6a33; }
.acct-badge.off { background: #f2f2f2; color: #999; }
.acct-ops { display: flex; gap: 6px; flex-wrap: wrap; }

/* 角色权限勾选 */
.role-editor { display: grid; gap: 14px; }
.role-row { border: 1px solid #eee6d8; border-radius: 10px; padding: 12px 14px; background: #fff; }
.role-row .rh { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.role-row .rh b { color: #5f4a2c; font-size: 15px; }
.role-row .rh input { width: 130px; padding: 5px 8px; border: 1px solid #ddd; border-radius: 6px; font-size: 13px; }
.role-row .rh .tagkey { font-size: 12px; color: #b9ab90; font-family: Consolas, Monaco, monospace; }
.perm-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.perm-chip { display: inline-flex; align-items: center; gap: 5px; font-size: 13px; padding: 4px 11px; border: 1px solid #e2d6c0; border-radius: 16px; background: #faf7f2; cursor: pointer; color: #6b5a3e; user-select: none; }
.perm-chip input { margin: 0; cursor: pointer; }
.perm-chip.on { background: #f5e9d4; border-color: #c9a76a; color: #7a5c2c; font-weight: 600; }
.perm-chip.all { background: #fdf3e6; border-color: #e0c48e; color: #a0762e; }

/* ==========================================================================
   表单卡片 / 列表头 / 筛选条 —— 设置页与新建页统一版式（2026-10-24）
   ★ 为什么之前优惠券、经纪人、会员、店铺这几页看着乱：
     这些 <label> 不在 <form> 里，站内只有 `form label { display:block }` 这一条规则，
     所以它们拿到的是**浏览器默认样式**：label 是 inline 的 → 标签文字和输入框挤在同一行，
     三列的宽度又靠内容撑 → 上下两行的标签起点对不齐。看着「说不上哪错但就是不齐」。
   ========================================================================== */

/* 卡片：.form-card 与老的 .section-card 长得一样，老代码不用改 */
.form-card, .section-card {
  background: #fff; border-radius: 12px; padding: 18px 22px 20px;
  margin: 0 20px 16px; box-shadow: 0 1px 6px rgba(0,0,0,0.05);
}
.form-card > h3, .section-card > h3 {
  margin: 0 0 16px; font-size: 15px; color: #5f4a2c;
  padding-left: 10px; border-left: 4px solid #b8860b; line-height: 1.25;
}

/* 统计口径条（客户列表上方）—— 金额对不上时问题几乎都在这，所以给它一条独立的底色 */
.stat-bar {
  display: flex; flex-wrap: wrap; align-items: center; gap: 14px;
  margin: 0 20px 12px; padding: 10px 14px;
  background: #fdfaf4; border: 1px solid #efe9dd; border-radius: 10px;
  font-size: 12.5px; color: #7b6a4e;
}
.stat-bar .stat-lbl { font-weight: 700; color: #5f4a2c; }
.stat-bar label { display: inline-flex; align-items: center; gap: 7px; }
.stat-bar input[type=date] {
  height: 30px; padding: 0 8px; border: 1px solid #ded6c8; border-radius: 7px;
  font-size: 12.5px; font-family: inherit; background: #fff;
}
.stat-bar .stat-chk input { width: 15px; height: 15px; accent-color: #b8860b; }
.stat-bar button {
  height: 30px; padding: 0 14px; border: 1px solid #ded6c8; border-radius: 7px;
  background: #fff; color: #7b6a4e; font-size: 12.5px; cursor: pointer;
}
.stat-bar button:hover { border-color: #c9a76a; color: #b8860b; }
/* ★ 给个 flex 基准宽度而不是靠 margin-left:auto 硬顶：
   诊断文字较长（计入/排除/退款三项），窄屏时靠 auto 会顶出容器被切掉，
   这样写空间不够就自己换行，最多掉到下一行，不会消失。 */
.stat-bar .stat-last { margin-left: auto; flex: 1 1 260px; min-width: 0; text-align: right; color: #a99a80; }
/* 统计数字：金色加粗，跟旁边的说明文字拉开层次 */
.stat-bar b { color: #b8860b; font-weight: 700; font-size: 13.5px; margin-left: 3px; }
.stat-bar .stat-sep { width: 1px; height: 16px; background: #e5dccb; }
.stat-bar .muted { color: #b3a894; }
/* 筛选栏里的行内勾选框（售后「只看真实支付」） */
.chk-inline { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px;
  color: #7b6a4e; white-space: nowrap; cursor: pointer; }
.chk-inline input { width: 15px; height: 15px; accent-color: #b8860b; cursor: pointer; }
/* ★ 弹窗里的「勾选一行」必须单独压回来：
   上面 .chk-inline 只有一个类名，压不过 .modal-card label{display:block} 与
   .modal-card label input{width:100%}（都带元素选择器，权重更高）。
   不压的话复选框会被撑成整行宽，文字被挤到右下角 —— 看着像排版散架。 */
.modal-card label.chk-inline { display: inline-flex; align-items: center; gap: 8px;
  font-size: 13px; color: #7b6a4e; margin-bottom: 12px; }
.modal-card label.chk-inline input { width: 15px; height: 15px; margin-top: 0; padding: 0; }

/* 表单里的二级小标题：同一个卡片里再分出一组字段（如供应商的「收款账户」） */
.sub-hd { display: flex; align-items: baseline; gap: 10px; margin: 20px 0 12px; padding-top: 14px; border-top: 1px dashed #eee; }
.sub-hd-t { font-size: 13.5px; font-weight: 700; color: #7b6a4e; }
.sub-hd-s { font-size: 11.5px; color: #b3a894; }
.sub-hd .rf-btn { margin-left: auto; align-self: center; }

/* 收款账户：一行一个账户，可增删。列宽固定，多个账户排下来才对得齐 */
.payee-list { display: flex; flex-direction: column; gap: 10px; }
.payee-row {
  display: grid; grid-template-columns: 150px 1fr 1fr 190px 104px;
  gap: 12px; align-items: end;
  padding: 12px 14px; border: 1px solid #efe9dd; border-radius: 10px; background: #fdfaf4;
}
.payee-row .fld > .lbl { font-size: 11.5px; }
.payee-row .payee-acts { display: flex; gap: 6px; justify-content: flex-end; padding-bottom: 3px; }
.payee-empty {
  padding: 14px 16px; border: 1px dashed #e2d9c6; border-radius: 10px;
  font-size: 12.5px; color: #a99a80; background: #fdfcf9;
}
@media (max-width: 960px) {
  .payee-row { grid-template-columns: 1fr 1fr; }
  .payee-row .payee-acts { grid-column: 1 / -1; justify-content: flex-start; }
}

/* 选账户弹窗里的每一行 */
.payee-pick-list { display: flex; flex-direction: column; gap: 10px; }
.payee-pick {
  display: flex; align-items: center; gap: 14px;
  padding: 12px 14px; border: 1px solid #efe9dd; border-radius: 10px; background: #fdfaf4;
}
.payee-pick-main { flex: 1; min-width: 0; }
.pp-name { font-size: 14px; font-weight: 600; color: #333; display: flex; align-items: center; gap: 8px; }
.pp-type { font-size: 11px; font-weight: 400; padding: 1px 8px; border-radius: 10px; background: #fbf3df; color: #b8860b; border: 1px solid #e8c97a; }
.pp-acc { font-size: 13px; color: #5f4a2c; letter-spacing: 0.4px; margin-top: 2px; font-variant-numeric: tabular-nums; }
.payee-more { margin-left: 6px; font-size: 11px; padding: 1px 7px; border-radius: 9px; background: #fbf3df; color: #b8860b; white-space: nowrap; }

/* 经纪人收款账户弹窗（2026-10-29）：纵向「标签 | 值」信息表
   ★ 卡号单独放大 + 等宽 + 数字等宽对齐：商家要照着念/核对，
     普通字体的 8 和 0、1 和 l 在一串数字里极容易看错一位。 */
.ag-acc { display: flex; flex-direction: column; }
.ag-acc-row { display: flex; align-items: baseline; gap: 10px; padding: 9px 0; border-bottom: 1px dashed #f0ece4; }
.ag-acc-row:last-child { border-bottom: 0; }
.ag-acc-k { flex: 0 0 104px; font-size: 13px; color: #9b9b9b; }
.ag-acc-v { flex: 1; font-size: 14px; color: #333; word-break: break-all; }
.ag-acc-no {
  font-size: 16px; letter-spacing: 1px; color: #333;
  font-family: "SF Mono", Menlo, Consolas, "Courier New", monospace;
  font-variant-numeric: tabular-nums;
}
/* 红/绿文字标记：表格里的「未填」和弹窗里的「不一致」共用 */
.warn-txt { color: #c0392b; }
.ok-txt { color: #2e7d32; }
/* 「收款账户」列：银行名 + 尾号**分两行**。
   ★ 合成一行时「农村商业银行 尾0021」会被省略号截掉尾号 ——
     而尾号正是打款前唯一要核对的东西，绝不能省。
   第一行仍然限宽 + 省略号兜超长行名，但不许把第二行挤掉。 */
.ag-payee-cell { display: block; max-width: 120px; text-align: left; }
.ag-payee-bank {
  display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ag-payee-tail {
  display: block; margin-top: 1px;
  font-size: 11px; color: #999; font-variant-numeric: tabular-nums;
}
/* 「签约时间 / 解约时间」列：日期一行、时分一行。
   ★ 一行写「2026-10-29 14:06」要 108px（16 个字符），两列就把表撑爆；
     拆两行后列宽只由日期决定（约 91px），时分掉到第二行的 11px 灰字。
     日期必须 nowrap —— 不写的话浏览器会在「-」处折行，变成「2026-10-」/「29」。 */
.ag-time { display: block; line-height: 1.3; }
.ag-time b { font-weight: 400; white-space: nowrap; font-variant-numeric: tabular-nums; }
.ag-time i {
  display: block; font-style: normal; font-size: 11px; color: #999;
  font-variant-numeric: tabular-nums;
}
.ag-time em { font-style: normal; color: #b8860b; }
/* 表格里的灰色小副行（待收 / 冷静期 / 风控） */
.ag-sub { font-size: 12px; color: #999; line-height: 1.4; }
.ag-sub.warn { color: #e4393c; }

/* 字段网格：标签在上、输入框在下，列宽自动均分 */
.form-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 14px 18px; }
/* 字段数固定的表单：指定列数，避免尾行空一片 */
.form-grid.cols-2 { grid-template-columns: repeat(2, 1fr); }
.form-grid.cols-3 { grid-template-columns: repeat(3, 1fr); }
.form-grid.cols-4 { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 960px) {
  .form-grid.cols-3, .form-grid.cols-4 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 620px) {
  .form-grid.cols-2, .form-grid.cols-3, .form-grid.cols-4 { grid-template-columns: 1fr; }
}
/* 一组勾选框竖着排在同一个字段里（经纪人那两项） */
.fld .checks { display: flex; flex-direction: column; gap: 8px; min-height: 38px; justify-content: center; }
.fld { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.fld > .lbl { font-size: 12.5px; font-weight: 600; color: #7b6a4e; }
.fld > .lbl i { color: #c0392b; font-style: normal; margin-left: 2px; }
.fld > .tip { font-size: 11.5px; color: #b3a894; margin-top: -2px; }
.fld input[type=text], .fld input[type=number], .fld input[type=date],
.fld input[type=password], .fld select, .fld textarea {
  width: 100%; height: 38px; padding: 0 11px; border: 1px solid #ded6c8; border-radius: 8px;
  background: #fff; color: #222; font-size: 14px; font-family: inherit;
  transition: border-color .15s, box-shadow .15s;
}
/* 多行文本（支付页的商户私钥）：固定高度会把 PEM 挤成一行，改成自动高度 + 等宽字体 */
.fld textarea {
  height: auto; min-height: 120px; padding: 9px 11px; line-height: 1.6; resize: vertical;
  font-family: Consolas, Menlo, 'Courier New', monospace; font-size: 12.5px; white-space: pre;
  overflow-wrap: normal; overflow-x: auto;
}
.fld textarea:focus { outline: none; border-color: #c9a76a; box-shadow: 0 0 0 3px rgba(176,141,87,0.15); }
.fld select { cursor: pointer; }
/* 多选框（选参与商品）不能被 38px 高度压扁 */
.fld select[multiple] { height: auto; padding: 6px; line-height: 1.7; }
.fld input:focus, .fld select:focus { outline: none; border-color: #c9a76a; box-shadow: 0 0 0 3px rgba(176,141,87,0.15); }
.fld input:disabled { background: #f7f5f1; color: #999; }
.fld.wide { grid-column: 1 / -1; }
/* 只有勾选框的字段：整格竖直居中。
   ★ 别给它固定 height:38px —— 文案一长就换成两行，固定高度会溢出到下一行去
     （「开市（取消勾选＝休市…）」就踩过这个坑，勾选框跑到表格下面去了） */
.fld.fld-check { justify-content: center; }
.fld.fld-check label.inline { height: auto; display: inline-flex; align-items: flex-start; gap: 6px; line-height: 1.55; }

/* 支付凭证状态行：只显示「有没有 / 末尾 4 位 / 指纹」，不回显原文 */
.pay-secret-state { display: grid; gap: 8px; margin-bottom: 14px; }
.pay-secret-state .row {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 9px 12px; border-radius: 8px; background: #faf8f4; border: 1px solid #f0ece3;
  font-size: 13px; color: #6b5c45;
}
.pay-secret-state .row.set { background: #f2f8f3; border-color: #dcece0; }
.pay-secret-state .row b { color: #333; font-weight: 600; }
.pay-secret-state code {
  font-family: Consolas, Menlo, 'Courier New', monospace; font-size: 12px;
  background: #fff; border: 1px solid #e6e0d4; border-radius: 4px; padding: 1px 5px; color: #8a6d0b;
}
.pay-secret-state .tag { font-size: 12px; padding: 2px 8px; border-radius: 10px; background: #eee; color: #777; }
.pay-secret-state .tag.on { background: #e3f2e6; color: #1e7f4f; }

/* 按钮区：右下角，分隔线与卡片内容分开 */
.form-actions {
  display: flex; gap: 10px; justify-content: flex-end; align-items: center;
  margin-top: 18px; padding-top: 15px; border-top: 1px solid #f2efe9;
}
.form-actions .left { margin-right: auto; }
.form-actions button { padding: 9px 18px; border: none; border-radius: 8px; cursor: pointer; font-size: 14px; }

/* 列表区标题：左边标题、右边刷新 */
.list-head { display: flex; align-items: center; justify-content: space-between; padding: 4px 20px 10px; }
.list-head h3 { margin: 0; font-size: 15px; color: #5f4a2c; padding-left: 10px; border-left: 4px solid #b8860b; line-height: 1.25; }
.list-head button { padding: 7px 14px; border: none; border-radius: 8px; cursor: pointer; font-size: 13px; background: #f0ece4; color: #6b5a3e; }
.list-head button:hover { background: #e7e0d2; }

/* 筛选条：一行输入 + 按钮 */
.filter-bar { display: flex; flex-wrap: wrap; gap: 9px; align-items: center; padding: 4px 20px 12px; }
.filter-bar input, .filter-bar select {
  height: 36px; padding: 0 10px; border: 1px solid #ded6c8; border-radius: 8px;
  font-size: 13.5px; font-family: inherit; background: #fff; color: #222;
}
/* 窄一点，6 个条件 + 2 个按钮才能在 1080px 里排成一行不换行 */
.filter-bar input[type=text] { width: 134px; }
/* 强制换行的占位元素：筛选条件多的时候（关键词 + 3 个下拉 + 2 个日期 + 2 个按钮）
   ★ 不要靠「自然换行」—— 窗口窄一点最后一个按钮会孤零零掉到第二行，看着像布局坏了。
     用这行明确切成「条件在上、时间+操作在下」，任何宽度都整齐。 */
.filter-bar .fb-break { flex: 0 0 100%; height: 0; margin: 0; padding: 0; }
/* 关键词框要能看清 placeholder（客户/供应商的搜索词是最长的） */
.filter-bar input.wide { width: 240px; }
.filter-bar input[type=date] { width: 138px; }
.filter-bar select { min-width: 150px; cursor: pointer; }
.filter-bar input:focus, .filter-bar select:focus { outline: none; border-color: #c9a76a; box-shadow: 0 0 0 3px rgba(176,141,87,0.15); }
.filter-bar button { height: 36px; padding: 0 17px; border: none; border-radius: 8px; cursor: pointer; font-size: 13.5px; }
.filter-bar .spacer { flex: 1 1 auto; }

/* 订单状态筛选胶囊（带条数，点一下就筛） */
.st-chips { display: flex; flex-wrap: wrap; gap: 8px; padding: 0 20px 12px; }
.st-chip {
  display: inline-flex; align-items: center; gap: 7px; height: 32px; padding: 0 13px;
  border: 1px solid #e4dccd; background: #fff; color: #6b5a3e; border-radius: 16px;
  font-size: 13px; cursor: pointer; transition: background .15s, border-color .15s, color .15s;
  user-select: none;
}
.st-chip:hover { border-color: #c9a76a; color: #8a6a33; }
.st-chip.active { background: #b08d57; border-color: #b08d57; color: #fff; font-weight: 600; }
.st-chip .n {
  font-size: 12px; padding: 0 6px; border-radius: 8px; min-width: 20px; text-align: center;
  background: rgba(0,0,0,0.06); color: inherit; font-variant-numeric: tabular-nums;
}
.st-chip.active .n { background: rgba(255,255,255,0.26); }
.st-chip.zero { opacity: 0.5; }

/* 表格放进卡片里时不要再多一层左右留白 */
.tbl-wrap.flush { padding: 0; }
.tbl-empty.in-card { margin: 0; }

/* 版本号 + 版本不一致提示 ------------------------------------------------ */
.ver-tag { font-size: 11.5px; color: #b9ab90; font-family: Consolas,Monaco,monospace;
  border: 1px dashed #e0d6c4; border-radius: 10px; padding: 2px 7px; white-space: nowrap; }
.ver-warn { margin: 14px 20px 0; padding: 13px 16px 14px; border-radius: 10px; font-size: 13.5px;
  line-height: 1.75; color: #8a3b2e; background: #fdf1ef;
  border: 1px solid #f3cfc7; border-left: 4px solid #c0392b; }
.ver-warn code { font-family: Consolas,Monaco,monospace; background: #f7e2de;
  padding: 1px 5px; border-radius: 4px; font-size: 12.5px; }

/* 空闲超时提醒（快自动登出时出现，动一下就续期） -------------------------------- */
.idle-warn { margin: 14px 20px 0; padding: 13px 16px 14px; border-radius: 10px;
  font-size: 13.5px; line-height: 1.75; color: #8a5a12;
  background: #fdf6e9; border: 1px solid #f0e0b8; border-left: 4px solid #b8860b; }

/* 订单列表的收货地址：整段可读，允许换行（发货要靠它，截断了等于没有） */
/* 收货地址：最多 2 行，超出用省略号。
   ★ 以前是 white-space:normal + break-all，地址一长就三四行，整行被撑高，
     14 列的表看着像散了架。完整地址仍在 title 里，点「详情」也能看全文。
   ★ 不用 break-all：它会把「广东省」这种词从任意位置拆开，读起来更费劲。 */
.tbl .addr {
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  max-width: 250px; overflow: hidden;
  line-height: 1.45; color: #555; word-break: break-word;
}

/* 登录页底部的 ICP 备案信息 */
.login-icp { margin-top:22px; padding-top:14px; border-top:1px solid #f0ece4;
  text-align:center; font-size:11.5px; line-height:1.9; color:#b5ab9b; }
.login-icp a { color:#a8987c; text-decoration:none; border-bottom:1px dotted #d8cdb6; }
.login-icp a:hover { color:#b08d57; border-bottom-color:#b08d57; }
/* 公司名单独一行：13 个字放 284px 内宽刚好，字号再大一号就会折行 */
.login-icp-org { font-size:11.5px; color:#bdb3a4; letter-spacing:.2px; }

/* 密码框右边的「显示 / 隐藏」眼睛
   ★ 必须用 .login-box .pwd-eye 两个类：上面 .login-box button 带元素选择器，
     只写 .pwd-eye 会被它压过（变成整宽金色大按钮）。 */
.pwd-wrap { position:relative; }
.pwd-wrap input { padding-right:46px; }
.login-box .pwd-eye { position:absolute; right:6px; top:50%; transform:translateY(-50%);
  width:34px; height:34px; padding:0; border:none; border-radius:8px; background:none;
  color:#b3a892; display:flex; align-items:center; justify-content:center;
  cursor:pointer; line-height:1; }
.login-box .pwd-eye:hover { color:#b08d57; background:#f7f2e9; }
.login-box .pwd-eye:active { transform:translateY(-50%) scale(.94); }
.login-box .pwd-eye svg { display:block; pointer-events:none; }

/* ===== 优惠券「已领 N」点开看人 =====
   ★ 为什么是虚线而不是实线下划线：这一列在表格里挨着「0」，实线看起来像
     数据本身带下划线；虚线一眼就知道是「可以点」。 */
.num-link { background:none; border:none; padding:0; margin:0; cursor:pointer;
  font:inherit; font-size:inherit; color:#1c5d99; border-bottom:1px dashed #a9c6e0;
  line-height:1.35; }
.num-link:hover { color:#14456f; border-bottom-color:#14456f; }

/* 领取明细：现在改成面板里的子标签 + 完整表格，
   原来弹窗专用的 .cc-filter 已随弹窗一起删掉（死样式留着只会让人以为还有那个弹窗）。 */

/* ===== 面板内的子标签（优惠券：券管理 / 领取记录） =====
   ★ 为什么不新增顶部 tab：后台每个 tab 都要对应一个权限点，
     新增 tab 不会自动进已有角色 → 老账号会突然看不到新页面（踩过）。
     子标签复用父 tab 的权限点，天然不会出这个事。
   ★ 视觉上要「比顶部 tab 轻一档」：背景浅灰胶囊、无下划线，
     否则会让人以为多了一个一级页面。 */
.subtabs { display: flex; gap: 6px; padding: 14px 20px 0; }
.subtab { border: 1px solid #e6dfd2; background: #faf8f4; color: #7a7062;
  padding: 7px 16px; border-radius: 999px; font-size: 13px; cursor: pointer;
  font-family: inherit; line-height: 1.4; transition: all .15s; }
.subtab:hover { border-color: #d8c9a8; color: #5f4a2c; }
.subtab.active { background: #b08d57; border-color: #b08d57; color: #fff; font-weight: 600; }

/* 等宽字体：邀请码 / 订单号这类「要一个字符一个字符念给对方听」的值
   ★ 邀请码字符集已经去掉了 0/1/i/l/o，等宽 + 一点字距就能一眼分清每个字符。 */
.mono { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, "Courier New", monospace;
  letter-spacing: .06em; }

/* ===== 客户归属修复弹窗 =====
   ★ 两段之间要有分隔线：上半是「一键扫描」（会改库），下半是「手动补录」，
     混在一起很容易点错按钮。 */
.fix-sec { padding: 14px 0; border-top: 1px solid #f0ece4; }
.fix-sec:first-of-type { border-top: none; padding-top: 0; }
.fix-sec h4 { font-size: 14px; color: #4a4438; margin: 0 0 6px; font-weight: 600; }
.fix-tip { font-size: 12.5px; color: #8b8074; line-height: 1.7; margin: 0 0 10px; }
.fix-result { margin-top: 10px; padding: 11px 13px; border-radius: 8px; font-size: 12.5px;
  line-height: 1.75; background: #f7f5f1; color: #5a5348; white-space: pre-wrap; word-break: break-all; }
.fix-result.ok { background: #eaf7f0; color: #1e7f4f; }
.fix-result.warn { background: #fdf6e3; color: #8a6d0b; }
.fix-result.err { background: #fdecea; color: #a3312a; }
/* 经纪人表的操作按钮比别处紧一档：这一列要塞「停用 + 结算」两个按钮，
   默认 4px 10px 的内边距会把两个按钮挤成上下两行（行高翻倍）。 */
.tbl .ag-act .rf-btn.sm { padding: 4px 8px; }
