/* 希捷 ERP —— 样式全部走变量 (§8)
   字号 5 级 / 圆角 4 级 / 断点 1024 920 720
   金额显示: ¥ + 千分位 + 2 位小数
*/
:root{
  /* ★ 2026-09-16 换肤：对齐百草商贸通（色值从本机百草 swf + 官网截图提取）
     ★★ 2026-09-26（张总「界面美化对标百草」P0）：中性色换成**百草真机取样**的暖色系 ——
        内容底 #F3F1E9（暖米）、分组灰字 #999999、顶栏 #373737。
        ★ 只动"底/描边/文字"这些中性色：**主色与顶栏仍由官网皮肤注入**
          （张总拍板：ERP 继续跟随官网皮肤，这一条不学百草）。 */
  --bg:#F3F1E9;              /* 主背景 暖米（百草真机取样） */
  --panel:#ffffff;           /* 卡片 / 面板 */
  --panel-2:#FAF7F0;         /* 表头 / 悬停底（暖白） */
  --line:#E6E0D2;            /* 描边 暖灰（跟着暖底走，冷蓝灰会显脏） */
  --ink:#373737;             /* 主文字（百草真机取样） */
  --ink-2:#5c6670;           /* 次要文字 */
  --ink-3:#95a0ab;           /* 弱文字 */
  --brand:#3da7ff;           /* 品牌 / 选中态 亮天蓝（被官网皮肤覆盖，见上） */
  --brand-dk:#2d8fe0;        /* 按下 / 悬停 深蓝 */
  --brand-ink:#ffffff;       /* 品牌上的文字 */
  --brand-soft:#e6f4ff;      /* 选中浅底 */
  --ok:#5cb85c;              /* 成功 / 库存充足 */
  --warn:#f5a623;            /* 预警 / 低于安全库存 */
  --danger:#ff4d4f;          /* 逾期应收 / 盘亏 / 负毛利 */
  --topbar:#2f2f2f;          /* 顶部栏深灰（百草同款；实际值由皮肤注入） */
  --topbar-ink:#e8edf3;      /* 顶部栏文字 */
  --topbar-ink-2:#9aa5b1;    /* 顶部栏弱文字 */
  --fs-1:20px; --fs-2:16px; --fs-3:14px; --fs-4:13px; --fs-5:12px;
  /* 圆角：百草的卡片比我们"方"一点（≈6px）⇒ --r-3 由 8 收成 6（只影响面板/卡片 8 处） */
  --r-1:4px; --r-2:6px; --r-3:6px; --r-4:12px;
  --sp-1:4px; --sp-2:8px; --sp-3:12px; --sp-4:16px; --sp-5:24px; --sp-6:32px;
  /* ★★ 2026-09-29（张总「全部 字段拥挤   对不齐的都优化掉」）：
     一行控件的**统一口径**。为什么必须有一个 token，而不是各处调 padding ——
     本文件原来**没有任何一处**定义"一个控件有多高"：高度是 padding 加上各自
     的行高碰出来的（`input/select` 走浏览器默认的 line-height:normal，
     `button` / `a.btnlike` 继承 body 的 1.6）。于是同一行里实测出五种高度：
       input 27.0 · select 29.0 · button 31.0 · a.btnlike 34.8 · 快捷药丸 27.2
     （1440/1280/1024 三个宽度上真浏览器量出来的实数，不是估的）。
     现在所有控件都吃 --ctl-h，所有相邻间距都吃 --ctl-gap，一处改全站改。 */
  --ctl-h:32px; --ctl-gap:8px;
  --sh-1:0 1px 3px rgba(90,80,60,.06);
  --sh-2:0 6px 20px rgba(90,80,60,.10);
}
*{box-sizing:border-box}
/* ★ [hidden] 必须真的隐藏。
   作者样式里的 display:flex/block 会盖掉浏览器默认样式表的 [hidden]{display:none}
   （.gate 就踩过这个坑：开单页上空的「门禁条」变成一根细黄条）。
   这一条是全局兜底，别再逐类写 .xxx[hidden]。 2026-09-18 */
[hidden]{display:none!important}
body{margin:0;background:var(--bg);color:var(--ink);
  font:var(--fs-3)/1.6 "Microsoft YaHei","Segoe UI",system-ui,sans-serif}
a{color:var(--brand);text-decoration:none}
a:hover{text-decoration:underline}

.top{height:52px;background:var(--topbar);color:var(--topbar-ink);
  border-bottom:none;box-shadow:var(--sh-1);
  display:flex;align-items:center;gap:var(--sp-4);padding:0 var(--sp-5);position:sticky;top:0;z-index:9}
.top .logo{font-size:var(--fs-2);font-weight:600;letter-spacing:.5px;color:#fff}
.top .logo small{font-size:var(--fs-5);color:var(--topbar-ink-2);font-weight:400;margin-left:var(--sp-2)}
.top .spacer{flex:1}
.top .who{font-size:var(--fs-4);color:var(--topbar-ink-2)}
.top .who b{color:#fff}
.top .role{display:inline-block;padding:2px var(--sp-2);border-radius:var(--r-1);
  background:rgba(255,255,255,.16);color:#fff;font-size:var(--fs-5);margin-left:var(--sp-2)}
.top a{color:var(--topbar-ink-2)}
.top a:hover{color:#fff}
.top .topnav{padding:4px var(--sp-3);border-radius:var(--r-1);font-size:var(--fs-4);
  text-decoration:none;margin-left:var(--sp-3)}
.top .topnav:hover{background:rgba(255,255,255,.12)}
.top .topnav.on{background:rgba(255,255,255,.2);color:#fff;font-weight:600}
.backlink{display:inline-block;margin-bottom:var(--sp-4);font-size:var(--fs-4);
  color:var(--ink-2);text-decoration:none}
.backlink:hover{color:var(--brand)}

.wrap{display:flex;min-height:calc(100vh - 52px)}
.side{width:168px;background:var(--panel);border-right:1px solid var(--line);padding:var(--sp-4) 0}
.side h4{margin:var(--sp-3) var(--sp-4) var(--sp-2);font-size:var(--fs-5);color:var(--ink-3);font-weight:500}
.side a{display:block;padding:7px var(--sp-4);font-size:var(--fs-4);color:var(--ink-2);
  border-radius:0 var(--r-2) var(--r-2) 0;margin-right:var(--sp-2);
  transition:background .15s ease,color .15s ease}
.side a:hover{background:var(--panel-2);text-decoration:none;color:var(--ink)}
.side a.on{background:var(--brand-soft);color:var(--brand);font-weight:600;
  box-shadow:inset 3px 0 0 var(--brand)}
.main{flex:1;padding:var(--sp-5);min-width:0}

h1{font-size:var(--fs-1);margin:0 0 var(--sp-4);font-weight:600}
h2{font-size:var(--fs-2);margin:var(--sp-5) 0 var(--sp-3);font-weight:600}

.cards{display:grid;gap:var(--sp-3);grid-template-columns:repeat(auto-fill,minmax(150px,1fr))}
.card{background:var(--panel);border:1px solid var(--line);border-radius:var(--r-3);
  padding:var(--sp-4);box-shadow:var(--sh-1);transition:box-shadow .2s ease,transform .2s ease}
.card .k{font-size:var(--fs-5);color:var(--ink-3)}
.card .v{font-size:var(--fs-1);font-weight:600;margin-top:var(--sp-2)}
.card .v.warn{color:var(--danger)}

.panel{background:var(--panel);border:1px solid var(--line);border-radius:var(--r-3);
  overflow:hidden;box-shadow:var(--sh-1)}
.panel .hd{padding:var(--sp-3) var(--sp-4);border-bottom:1px solid var(--line);
  display:flex;align-items:center;gap:var(--sp-3);flex-wrap:wrap}
.panel .hd .t{font-size:var(--fs-2);font-weight:600}
.panel .bd{padding:0}

table{width:100%;border-collapse:collapse;font-size:var(--fs-4)}
th,td{padding:7px var(--sp-3);text-align:left;border-bottom:1px solid var(--line);
  white-space:nowrap;max-width:320px;overflow:hidden;text-overflow:ellipsis}
th{background:var(--panel-2);color:var(--ink-2);font-weight:500;font-size:var(--fs-5)}
tbody tr:hover{background:var(--panel-2)}
/* ★ #24 列表整行双击进编辑（老板 4 次截图 = 商品/客户/仓库同一个根因）。
   ★ 为什么只给 .rowlink 加手型、不给所有 tr：只读视图 / 无详情页的行
     双击没去处，光标变手型就是**骗人**（点了没反应比不点更糟）。
   ★ 数量列逐格标单位那条也一并强化：hover 底色已是既有行为，这里只补
     "这行能点"的视觉暗示（左侧 2px 品牌色条）+ 手型。 */
tbody tr.rowlink{cursor:pointer}
tbody tr.rowlink:hover{background:var(--panel-2);box-shadow:inset 2px 0 0 var(--brand)}
/* 行尾「编辑」入口。默认低调（它是"显式入口"，不是每行都要抢眼），
   hover 到这一行时才变明显 —— 免得整张表一片蓝按钮。 */
th.editcol,td.editcol{width:1%;text-align:right;white-space:nowrap}
a.rowedit{color:var(--ink-2);font-size:var(--fs-5);text-decoration:none;
  padding:2px 8px;border:1px solid var(--line);border-radius:var(--r-2)}
tbody tr.rowlink:hover a.rowedit{color:var(--brand);border-color:var(--brand)}
a.rowedit:hover{background:var(--brand);color:var(--brand-ink);border-color:var(--brand)}
/* ★ #24 键盘流的“当前行”高亮：↑/↓ 移动到哪一行，回车打开它。
   ★ 为什么必须比 hover 更重：悬停的鼠标会离开，而“当前行”的高亮
     要在手离开之后照旧在 —— 否则老板按一下↓就不知道自己选了哪一行。
   ★ 左侧色条用 3px（比 .rowlink:hover 的 2px 粗一点点）
     —— 两者可能同时在（鼠标正停在这一行上），差一个像素才看得出“选中”更重。 */
tbody tr.sel{background:var(--panel-2);box-shadow:inset 3px 0 0 var(--brand)}
tbody tr.sel a.rowedit{color:var(--brand);border-color:var(--brand)}
td.num{text-align:right;font-variant-numeric:tabular-nums}
td.money{text-align:right;font-variant-numeric:tabular-nums;color:var(--ink)}
/* ★ 数字单元格的告警态。原来只写了 .tag.warn / .sub.warn，模板里
   class="num warn" 是**没有任何样式**的 —— 锁定面板「可用库存不够」
   的红字高亮一直不显示（2026-09-18 实机验收抓到）。 */
td.num.warn{color:var(--warn);font-weight:600}

/* ★ M4 / A1-14：表单控件（下拉 / 输入框）的告警态。
   与上面那条同一个毛病 —— 光加 class 不加规则等于没加：
   过账面板「这一行还没选批次」要把那一格框成红的，员工才知道改哪里。
   ★ 用 border + 阴影两条：只改 border 在浅色边框的表格里很不显眼。 */
select.warn,input.warn{border-color:var(--danger) !important;
  box-shadow:0 0 0 2px rgba(198,40,40,.14)}

.empty{padding:var(--sp-6);text-align:center;color:var(--ink-3);font-size:var(--fs-4)}

.tag{display:inline-block;padding:1px var(--sp-2);border-radius:var(--r-1);
  font-size:var(--fs-5);border:1px solid var(--line);color:var(--ink-2)}
.tag.ok{color:var(--ok);border-color:var(--ok)}
.tag.warn{color:var(--warn);border-color:var(--warn)}
.tag.danger{color:var(--danger);border-color:var(--danger)}
/* ★ A组 #37/#38（2026-09-22）：补两个色档。
   原来只有 ok/warn/danger 三档，「中性」是靠"不加类"实现的 ——
   但那样一来 .tag 和 .tag.mute 没法在模板里用同一个函数切出来。
   补上 mute（不用管了）与 brand（进行中，用品牌蓝）。
   一句话记法：橙＝要你做 · 蓝＝在做 · 绿＝做完了 · 灰＝不用做。 */
.tag.brand{color:var(--brand);border-color:var(--brand)}
.tag.mute{color:var(--ink-3);border-color:var(--line)}
/* ★ 2026-09-28（多租户平台控制台）：套餐里"基础必含"的功能点要一眼分得出来
   —— 它们是**恒开**的（`is_core`），跟"可以买的增值项"不是一回事。
   做成唯一一个**实心底**的档：其余四档都是描边彩字（同一张页面上第一眼就能扫到）。
   颜色只用现成 token（brand-soft 底 + brand-dk 字），不引入新色 —— 与图标那套同一条纪律。 */
.tag.core{color:var(--brand-dk);border-color:var(--brand-soft);background:var(--brand-soft)}

/* ★ 同上：状态按钮的四档色。用在不同状态的动作按钮上 ——
   「当前所处的那个状态」实心打勾禁用，其余素色描边、hover 才预告颜色。
   为什么不用现成的 .ok/.warn：按钮要的是**实心底 + 白字**，
   跟标签的"描边 + 彩字"不是一回事，硬套会让按钮在白底上看不清。 */
.stbtn{transition:background .12s,color .12s,border-color .12s}
.stbtn.is-warn{background:var(--warn);border-color:var(--warn);color:#fff}
.stbtn.is-brand{background:var(--brand);border-color:var(--brand);color:#fff}
.stbtn.is-ok{background:var(--ok);border-color:var(--ok);color:#fff}
.stbtn.is-mute{background:var(--ink-3);border-color:var(--ink-3);color:#fff}
.stbtn[disabled]{opacity:1;cursor:default}
/* 素色按钮 hover 时预告自己的颜色（"标记才显示颜色"：没选中的不抢戏） */
.stbtn:not([disabled]):hover[data-hint="warn"]{border-color:var(--warn);color:var(--warn)}
.stbtn:not([disabled]):hover[data-hint="brand"]{border-color:var(--brand);color:var(--brand)}
.stbtn:not([disabled]):hover[data-hint="ok"]{border-color:var(--ok);color:var(--ok)}
.stbtn:not([disabled]):hover[data-hint="mute"]{border-color:var(--ink-3);color:var(--ink-3)}

/* ★ 工具栏一行内的**统一间距**。原来写死 var(--sp-2)，值一样（8px），
   但"这一行有多松"没有名字 —— 于是 .quicktime 自己又加了个 4px 的
   margin-inline-end，实测出现 ['12.0','8.0','8.0'…]（张总说的"间距忽宽忽窄"）。
   现在这一行只有一个间距变量。 */
.toolbar{display:flex;gap:var(--ctl-gap);align-items:center;flex-wrap:wrap}
/* ★★ 工具条里的**裸 <form>**（网站线索的筛选表单就是这种写法：
   `<form style="display:inline"><select><input><button></form>`）。
   行内元素之间只靠一个空格分开 ⇒ 控件之间是 **4.2px**，而工具条自己的
   gap 是 8px，实测 ['4.2','4.2','8.0'] —— 一笔"忽宽忽窄"就是这么来的
   （张总截图那一页正是它）。让它也按工具条的间距排，空格不再参与。 */
.toolbar > form{display:inline-flex;align-items:center;flex-wrap:wrap;
  gap:var(--ctl-gap);margin:0}

/* ---------------------------------------------------------------- #42 列表页业务日期区间
   起止两个 <input type=date>。★ 为什么要写这一条：
   `input[type=date]` **不在**上面 `input[type=text]...` 那条选择器里，
   不补的话两个日期框会是浏览器默认的窄小样式，跟旁边灰底下拉**明显不是一套** ——
   老板会以为「这俩框是坏的/没做完」。这类「加了 class 没加规则」的坑本仓踩过多次。
   ★ 与下拉的 min-width:180px 对齐（两个日期框并排已是 360px 级），不再撑宽。 */
.daterange{display:inline-flex;align-items:center;gap:var(--ctl-gap)}
.daterange input[type=date]{
  padding:0 var(--sp-2);border:1px solid var(--line);border-radius:var(--r-2);
  font-size:var(--fs-4);background:var(--panel);color:var(--ink);min-width:0}
.daterange .dash{color:var(--ink-3);padding:0 2px}
/* ★★ 2026-09-29（张总「全部 字段拥挤   对不齐的都优化掉」）：
   这一条原来只列了 text/password/search/select —— **date / number / file
   完全没有规则**，于是它们退回浏览器默认样式。真浏览器量到的实数：
   销售报表「自选日期」21.3px、商品表单的数字框 21.0px、商品表单视频那一行的
   文件框 23.0px，而同一行的文本框是 27.0px。
   本仓其实栽过一次同类（见上面那段注释：「`input[type=date]` 不在上面
   `input[type=text]...` 那条选择器里」）—— 但当时**只补了 .daterange 里那两个**，
   报表页 / 表单页 / 对账单上那些裸的没补。这次一次列全，不再按"用在哪"零敲碎打。
   ★ 高度改由 --ctl-h 一处定死：一行里 input / select / 日期框 / 按钮**一样高**。
   ★ line-height 显式写 normal：input/select 本来就是这个值，写出来是为了
     不让 body 的 1.6 从别处漏进来 —— 那正是"按钮比输入框高 4px"的根因。 */
input[type=text],input[type=password],input[type=search],input[type=email],
input[type=tel],input[type=url],input[type=number],input[type=date],
input[type=month],input[type=week],input[type=time],input[type=datetime-local],
input[type=file],select{
  height:var(--ctl-h);padding:0 var(--sp-3);border:1px solid var(--line);
  border-radius:var(--r-2);font-size:var(--fs-4);line-height:normal;
  /* ★ vertical-align:middle：非 flex 的行（如对账单的
     `<label>起 <input type=date></label>`、报表页的 `<label>自选 …</label>`）
     里控件是**行内**排的，默认按基线对齐 —— 不同控件的基线偏移不一样，
     等高的两个框也会差几像素。按中线对齐，等高就真的齐。 */
  vertical-align:middle;
  background:var(--panel);color:var(--ink);min-width:180px}
/* ★ 按钮高度必须与输入框**同源**：原来靠 `padding:6px` 撑（6+6+边框+
   继承来的行高 1.6 ⇒ 31px），跟输入框的 27px 天然差 4px，谁也没错、就是不等。 */
button{height:var(--ctl-h);padding:0 var(--sp-4);border:1px solid var(--brand);
  border-radius:var(--r-2);line-height:normal;vertical-align:middle;
  background:var(--brand);color:var(--brand-ink);font-size:var(--fs-4);cursor:pointer;
  transition:background .12s ease,border-color .12s ease,transform .12s ease}
button:hover:not(:disabled){background:var(--brand-dk);border-color:var(--brand-dk)}
button:active:not(:disabled){transform:scale(.98)}
button.ghost{background:var(--panel);color:var(--ink-2);border-color:var(--line)}
button.ghost:hover:not(:disabled){background:var(--brand-soft);color:var(--brand);
  border-color:var(--brand)}
button:disabled{opacity:.5;cursor:not-allowed}

/* ★ 报表页的「快捷区间 / 导出」是 <a>，不是 <button>（它们要能直接进 URL、
   能被收藏、能在新标签页打开），所以 button 那套样式吃不到 —— 这里补一份
   同形外观，让它看起来就是个按钮而不是链接。
   ★ 本仓教训（见上面 .warn 那两条注释）：光在模板里写 class、CSS 里没有对应
   规则 = 等于没加，而且不报错。所以这个类必须在 CSS 里真的有。 2026-09-22 */
a.crumb-btn{display:inline-flex;align-items:center;height:var(--ctl-h);
  padding:0 var(--sp-4);line-height:normal;
  border:1px solid var(--line);border-radius:var(--r-2);background:var(--panel);
  color:var(--ink-2);font-size:var(--fs-4);cursor:pointer;text-decoration:none;
  transition:background .12s ease,border-color .12s ease,color .12s ease}
a.crumb-btn:hover{background:var(--brand-soft);border-color:var(--brand);
  color:var(--brand);text-decoration:none}
a.crumb-btn[aria-current="true"]{background:var(--brand);border-color:var(--brand);
  color:var(--brand-ink);font-weight:600}
a.crumb-btn[aria-current="true"]:hover{background:var(--brand-dk);
  border-color:var(--brand-dk);color:var(--brand-ink)}

/* ★ 与区间按钮同形、但语义不是"一个区间"的按钮（如「导出 CSV」）。
   2026-09-22 加：导出原本也用 crumb-btn，真浏览器 E2E 里被"快捷区间"的
   选择器一并选中（它的 href 本来就带 start=/end=）⇒ 断言误判。
   给它一个独立类，既好选也好读。
   ★ 注意：这里只是**轻微弱化**（别抢区间的视觉焦点），
   仍要是可点的按钮，别做成禁用态。
   ★★ 返工记录（同日，看截图后改）：第一版写成 `color:var(--ink-3)`
   （#95a0ab，白底上对比度只有约 2.6:1）—— 那不是"弱化"，是**看不清**，
   老板第一眼会以为这个按钮是禁用的。改成 ink-2(#5c6670，约 6.7:1)，
   仍然比区间按钮的 ink-2 弱一档靠**透明底 + 常规字重**来体现，
   而不是靠把字调灰。结论：弱化手段要用"底色/字重"，不要用"降低对比度"。 */
a.crumb-btn-aux{background:transparent;color:var(--ink-2);font-weight:400}
a.crumb-btn-aux:hover{background:var(--brand-soft);border-color:var(--brand);
  color:var(--brand)}

/* ---- 图标（内联 SVG sprite，见 _icons.html）---- */
.ic{width:16px;height:16px;flex:none;vertical-align:-3px;stroke-width:2}
.side .ic{width:15px;height:15px;color:var(--ink-3);margin-right:2px}
.side a:hover .ic{color:var(--ink-2)}
.side a.on .ic{color:var(--brand)}
.side a{display:flex;align-items:center;gap:var(--sp-2)}
/* ★ 侧栏角标：待处理条数（老板 2026-09-20）。
   margin-inline-start:auto 把它推到行尾 —— .side a 是 flex，不用绝对定位。
   0 条时后端**根本不渲染**这个元素（见 base.html 的 leads_nav_item 宏）：
   一堆 "0" 是噪音，没有数字反而说明"没事"。 */
.side .navnum{margin-inline-start:auto;flex:0 0 auto;min-width:18px;padding:0 5px;
  border-radius:999px;background:var(--brand);color:#fff;font-size:var(--fs-5);
  font-weight:600;line-height:18px;text-align:center;font-variant-numeric:tabular-nums}

/* ---- 顶栏全局搜索 ---- */
.gsearch{display:flex;align-items:center;gap:var(--sp-2);
  background:rgba(255,255,255,.13);border:1px solid rgba(255,255,255,.18);
  border-radius:18px;padding:3px var(--sp-3);min-width:230px;
  transition:background .15s ease,border-color .15s ease}
.gsearch:focus-within{background:rgba(255,255,255,.2);border-color:rgba(255,255,255,.35)}
.gsearch .ic{width:15px;height:15px;color:var(--topbar-ink-2)}
.gsearch input[type=search]{background:transparent;border:none;outline:none;
  color:#fff;font-size:var(--fs-4);width:100%;min-width:0;padding:2px 0;
  /* ★ 顶栏这颗搜索框是**胶囊里的内嵌件**，不是工具条里的一行控件 ——
     显式退回"按内容定高"，免得吃全站统一高度后把顶栏胶囊撑变形。 */
  height:auto;line-height:inherit}
.gsearch input[type=search]::placeholder{color:var(--topbar-ink-2)}
.gsearch.big{min-width:380px;max-width:520px;background:var(--panel);
  border-color:var(--line);border-radius:var(--r-3);padding:var(--sp-2) var(--sp-3);
  margin-bottom:var(--sp-4)}
.gsearch.big .ic{color:var(--ink-3);width:18px;height:18px}
.gsearch.big input[type=search]{color:var(--ink);font-size:var(--fs-3)}

.kv{display:grid;grid-template-columns:140px 1fr;gap:1px 0;background:var(--panel);
  border:1px solid var(--line);border-radius:var(--r-3);overflow:hidden;margin-bottom:var(--sp-4)}
.kv .k{background:var(--panel-2);padding:7px var(--sp-4);font-size:var(--fs-4);color:var(--ink-2);
  border-bottom:1px solid var(--line)}
.kv .v{padding:7px var(--sp-4);font-size:var(--fs-4);border-bottom:1px solid var(--line);
  word-break:break-all;white-space:normal}

.login{max-width:320px;margin:14vh auto;background:var(--panel);border:1px solid var(--line);
  border-radius:var(--r-4);padding:var(--sp-6)}
.login h1{text-align:center;font-size:var(--fs-2)}
.login input{width:100%;margin-bottom:var(--sp-3)}
.login button{width:100%}
.err{color:var(--danger);font-size:var(--fs-4);margin-bottom:var(--sp-3);text-align:center}

.hint{color:var(--ink-3);font-size:var(--fs-5);padding:var(--sp-3) var(--sp-4)}

@media (max-width:1024px){
  .side{width:132px}
  .main{padding:var(--sp-4)}
}
@media (max-width:920px){
  .wrap{flex-direction:column}
  .side{width:100%;border-right:0;border-bottom:1px solid var(--line);
    display:flex;overflow-x:auto;padding:var(--sp-2)}
  .side h4{display:none}
  .side a{white-space:nowrap;border-radius:var(--r-2)}
  .side a.on{box-shadow:none}
}
@media (max-width:720px){
  :root{--fs-1:18px}
  .kv{grid-template-columns:110px 1fr}
  th,td{max-width:180px}
}
/* ═══════════ #11 审核状态条 + 标题两层 + 手机端单据页 ═══════════
   ★ 为什么这些规则必须**有**（不是样式偏好）：
     老板 2026-09-20 在手机上打开 192.168.0.115:8002 的一张销售单，反馈两件：
       ① 「审核的要在明显的地方看」  ② 「界面不友好，挤在一堆」
     实测根因：本文件有 11 个 @media 断点，**没有一条碰过**
     .top / .who / h1 / .tag / .bar —— 顶栏和标题在手机上
     "不是适配得不好，是**根本没做**"。所以下面这段是新写的，不是微调。 */

/* 审核大状态条：位置在标题之前（见 order.html 顶部），这里只管"更醒目"。
   ★ 配色**不在这里定义** —— 直接用 .alert 的 err/ok/warn 三档
     （同一个意思只留一处定义，避免"改了一处忘一处"）。 */
.alert.verifybar{border-left-width:6px}
.verifybar .vb-h{font-size:var(--fs-2);font-weight:700;line-height:1.35}
.verifybar .vb-why{font-size:var(--fs-4);font-weight:600;margin-top:var(--sp-1)}
.verifybar .vb-by,.verifybar .vb-tip{font-size:var(--fs-5);margin-top:4px}

/* 次要状态一层（款 / 关 / 票 / 锁 / 业务已完成）—— 从 h1 里降下来。
   负 margin-top 是把 h1 的底距收回来一点，免得两行之间空得发虚。 */
.tags2{display:flex;flex-wrap:wrap;gap:var(--sp-2);
  margin:calc(-1 * var(--sp-3)) 0 var(--sp-4);font-size:var(--fs-5)}

@media (max-width:720px){
  /* ① 顶栏溢出：老板截图里"标 所 有""老板"重复三次就是这么来的 ——
        口号 / 角色标签 /「所有」入口 全挤在一行。
        手机上：口号不显示、角色标签不显示、「所有」收起来（从侧栏进），
        搜索框吃掉剩下的宽度。
     ★ 只改**显示与宽度**，不动 DOM、不动任何链接 —— 桌面端逐字不变。 */
  .top{gap:var(--sp-2);padding-left:var(--sp-3);padding-right:var(--sp-3)}
  .top .logo{flex:0 0 auto;min-width:0}
  .top .logo small{display:none}
  .top .topnav{display:none}
  .top .spacer{display:none}
  .top .gsearch{flex:1 1 auto;min-width:0}
  .top .gsearch input{width:100%;min-width:0}
  .top .who{flex:0 0 auto;font-size:var(--fs-5)}
  .top .who .role{display:none}

  /* ② 单据页操作条钉在屏幕底部 ——「打开就能审」，不用往下滚两三屏找按钮。
     ★ 只钉 #actions（单据页那一条），**不钉所有 .toolbar**：
       列表页的工具栏（搜索 / 筛选 / 批量审核）钉在底部会一直盖住表格。
     ★ 44px 是"手指点得准"的下限，不是审美选择。 */
  .bar#actions{position:fixed;left:0;right:0;bottom:0;z-index:20;
    margin:0;padding:var(--sp-2) var(--sp-3);
    background:var(--panel);border-top:1px solid var(--line);
    box-shadow:0 -2px 10px rgba(28,36,48,.10);
    /* ★ 不换行、可横滑。这一条是**真浏览器量出来**才改的：
       换行版在 375px 下条高 **273px**，吃掉屏幕三分之一，
       而且审核按钮被挤到第三行 —— 正好违反"打开就能审"。
       改成一整行 + 横滑后条高约 62px。 */
    flex-wrap:nowrap;overflow-x:auto;overflow-y:hidden}
  .bar#actions button,.bar#actions .btnlink,.bar#actions .btnlike{
    flex:0 0 auto;min-height:44px;white-space:nowrap;margin-left:0}
  /* ★★ 这一条是**真浏览器量出来**才补的（第一次改完条高只从 273 → 238）。
     工具栏的直接子项**不只有 <button>** —— 还有两个裸 <span> 包装器
     （#customsBtns / #fapiaoBtns，一个套报关按钮、一个套发票按钮）。
     它们没被上面那条规则覆盖 ⇒ 作为 flex 项被挤压到 99px 宽，
     里面的文字竖着排，span 自己长到 132px / 221px，
     而**条高由最高的子项决定** ⇒ 整条又被撑回 238px。
     ★ 判据：只要“有一个子项能缩”，条高就不可控 ⇒ 统一不缩。 */
  .bar#actions > *{flex:0 0 auto}
  /* 包装器内部自己排成一行（不再换行），否则里面的按钮照样竖排。 */
  .bar#actions > span{display:flex;align-items:center;flex-wrap:nowrap;
    gap:var(--sp-2)}

  /* ★ 只改**视觉顺序**（order），不动 DOM —— Tab 顺序与桌面端一字不变。
     老板要"打开就能审" ⇒ 审核那一组排最左，「返回列表」排最右。 */
  .bar#actions .verify-act{order:-3}
  .bar#actions .btnlink{order:9}
  /* 固定条会盖住页面最后一段内容 —— 给它留出高度 */
  .main{padding-bottom:88px}
}

/* ================= 开单页 / 单据页 (§8 样式全部走变量) ================= */
.alert{padding:var(--sp-3) var(--sp-4);border-radius:var(--r-2);font-size:var(--fs-4);
  margin-bottom:var(--sp-4);border:1px solid}
.alert.err{background:#fff0f0;border-color:#ffd6d6;color:#c62828}
.alert.ok{background:#eaf7ee;border-color:#bfe6c8;color:#1a7f42}
/* ★ A 组 #62（2026-09-22）：补 .alert.warn。
   原来只有 err / ok 两档，而 customer_pool.html 写的是 class="alert warn"
   —— 那条「还剩 N 天掉公海，快去跟进」的提醒**一直是没有底色的**
   （跟普通 div 长得一样，飘在页面上没人注意）。
   ★ 这次全仓普查还发现：order.html / refund_detail.html 的「审核不通过」
   横幅写的是 class="alert bad"，而 .alert 只有 .err —— 已一并统一成 .err
   （同一个意思只留一个名字，别让 CSS 里存在两个别名）。 */
.alert.warn{background:#fff8e6;border-color:#ffe3a3;color:#a86a00}

.fgrid{display:grid;gap:var(--sp-3);
  grid-template-columns:repeat(auto-fit,minmax(190px,1fr))}
.fitem{display:flex;flex-direction:column;gap:var(--sp-1);min-width:0}
.fitem label{font-size:var(--fs-5);color:var(--ink-3);line-height:22px}
.fitem input,.fitem select{width:100%;min-width:0}
.fwide{grid-column:span 2}
@media (max-width:720px){.fwide{grid-column:span 1}}

.pick{position:relative}
.pick input{width:100%}
/* 商品格: 输入框 + 「⋯」按钮并排, 按钮是"不记货号也能选"的入口 */
.pickRow{display:flex;gap:var(--sp-1);align-items:stretch;min-width:0}
.pickRow input{flex:1;min-width:0}
/* ★ 这三族是**刻意的非标准高度**，显式退出全站统一高度：
   · .pickRow button.pickBtn —— 挤在输入框右端的一颗极小「⋯」
   · .skuBook .hd input —— 选商品面板的搜索框（字号 16px，自己更大）
   · .lgrid input/select —— 表格里就地编辑用的密排格（行高本来就矮）
   不写这三条的话，它们会被 --ctl-h 拉齐，格子和面板反而被撑开。 */
.pickRow button.pickBtn{flex:none;padding:1px 6px;font-size:var(--fs-3);
  line-height:1.3;height:auto}

/* 「选择商品」面板 —— 给记不住货号的人用的大列表 */
.skuBook{width:min(920px,94vw);max-height:86vh;display:flex;flex-direction:column;
  padding:0;overflow:hidden}
.skuBook .hd{padding:var(--sp-4) var(--sp-5);border-bottom:1px solid var(--line);
  display:flex;gap:var(--sp-3);align-items:center}
.skuBook .hd h3{margin:0;font-size:var(--fs-2);flex:none}
.skuBook .hd input{flex:1;min-width:0;padding:6px var(--sp-3);
  font-size:var(--fs-2);height:auto;line-height:inherit}
.skuBook .cols{display:grid;grid-template-columns:120px 1fr 150px 130px 88px 88px;
  gap:var(--sp-2);padding:6px var(--sp-5);background:var(--panel-2);
  color:var(--ink-2);font-size:var(--fs-5);border-bottom:1px solid var(--line)}
.skuBook .cols .num{text-align:right}
.skuBook .list{flex:1;overflow-y:auto;min-height:200px}
.skuBook .it{display:grid;grid-template-columns:120px 1fr 150px 130px 88px 88px;
  gap:var(--sp-2);padding:9px var(--sp-5);border-bottom:1px solid var(--line);
  cursor:pointer;font-size:var(--fs-3);align-items:baseline}
.skuBook .it:hover{background:var(--panel-2)}
.skuBook .it.on{background:var(--brand-soft);box-shadow:inset 3px 0 0 var(--brand)}
.skuBook .it .code{color:var(--ink-2);font-variant-numeric:tabular-nums}
.skuBook .it .nm{font-weight:500}
.skuBook .it .sp{color:var(--ink-3);font-size:var(--fs-5)}
.skuBook .it .num{text-align:right;font-variant-numeric:tabular-nums}
.skuBook .it .zero{color:var(--ink-3)}
.skuBook .it .neg{color:var(--danger)}
.skuBook .ft{padding:var(--sp-3) var(--sp-5);border-top:1px solid var(--line);
  display:flex;gap:var(--sp-3);align-items:center;color:var(--ink-2);font-size:var(--fs-5)}
.skuBook .ft .spacer{flex:1}
.skuBook .empty{padding:var(--sp-6);text-align:center;color:var(--ink-3)}
.pickMenu{position:absolute;z-index:20;left:0;right:0;top:100%;margin-top:2px;
  max-height:250px;overflow-y:auto;background:var(--panel);border:1px solid var(--line);
  border-radius:var(--r-2);font-size:var(--fs-4)}
.pickMenu .mi{padding:6px var(--sp-3);cursor:pointer;display:flex;gap:var(--sp-2);
  align-items:baseline;flex-wrap:wrap;border-bottom:1px solid var(--line)}
.pickMenu .mi:last-child{border-bottom:0}
.pickMenu .mi:hover{background:var(--brand-soft)}
.pickMenu .mi b{font-weight:500}
.pickMenu .mi em{font-style:normal;color:var(--ink-3);font-size:var(--fs-5);
  margin-left:auto}
.pickMenu .mi em.danger{color:var(--danger)}
.muted{color:var(--ink-3);font-weight:400}

.lgrid{display:grid;gap:var(--sp-2);align-items:center;padding:7px var(--sp-4)}
.lgrid.lhead{background:var(--panel-2);color:var(--ink-2);font-size:var(--fs-5);
  border-bottom:1px solid var(--line)}
.lgrid.lrow{border-bottom:1px solid var(--line);font-size:var(--fs-4)}
.lgrid.lrow:hover{background:var(--panel-2)}
.lgrid.lrow.bad{background:#fdf6f6}
.lgrid input,.lgrid select{width:100%;min-width:0;padding:4px var(--sp-2);
  font-size:var(--fs-4);height:auto;line-height:inherit}
.cellstack{display:flex;flex-direction:column;gap:1px;min-width:0}
.cellops{text-align:right}
.ta-r{text-align:right}
.strong{font-variant-numeric:tabular-nums}
.sub{font-size:var(--fs-5);color:var(--ink-3);font-variant-numeric:tabular-nums}
.sub.warn{color:var(--warn)}
.sub.danger{color:var(--danger)}
.chklab{display:flex;align-items:center;gap:4px;font-size:var(--fs-5);
  color:var(--ink-3)}
.chk{width:auto!important;min-width:0!important}
button.tiny{padding:1px var(--sp-2);font-size:var(--fs-5);line-height:1.4;
  height:auto}
button.danger{border-color:var(--danger);color:var(--danger)}

.bar{margin-top:var(--sp-4);align-items:center}
.btnlink{font-size:var(--fs-4);margin-left:auto}
.gate{margin-top:var(--sp-3);padding:var(--sp-3) var(--sp-4);
  border-radius:var(--r-2);background:#fdf3e6;border:1px solid #f0d5a8;color:#854f0b;
  font-size:var(--fs-4);display:flex;flex-direction:column;gap:var(--sp-2)}
.gate .chklab{color:#854f0b}
.card .v.ok{color:var(--ok)}

.modalBack{position:fixed;inset:0;background:rgba(31,35,41,.35);display:flex;
  align-items:center;justify-content:center;z-index:50}
.modal{background:var(--panel);border-radius:var(--r-4);padding:var(--sp-5);
  width:340px;max-width:92vw;
  /* ★ 2026-09-24 全站弹窗统一限高（老板实测「弹出的是卡死的」后定的通用法则）：
     内容比屏幕高的弹窗（49 个勾选框那种）以前会顶出屏幕外 ——
     保存/取消看不见 + 遮罩锁整页 = 用户看是"死机"。
     矮弹窗不受影响（max-height 只封顶）；超高的内部滚动。
     overscroll-behavior 防止滚到头把后面整页带着滚。 */
  max-height:86vh;overflow:auto;overscroll-behavior:contain}
.modal h3{margin:0 0 var(--sp-4);font-size:var(--fs-2);font-weight:600}
.modal .flab{display:flex;flex-direction:column;gap:var(--sp-1);
  margin-bottom:var(--sp-3)}
.modal .flab span{font-size:var(--fs-5);color:var(--ink-3)}
.modal .flab input{width:100%}

@media (max-width:920px){
  .lgrid{min-width:760px}
}

/* ===== 求助名片弹窗（093，张总 2026-09-28「求助打开这样」）+ 顶栏入口 =====
   为什么单独一段而不是复用 .modal 就够了：
     · .modal 固定 340px 且只管"表单弹窗"的字号，名片是**展示型**卡片，
       要更宽（380px）且行距不同 ⇒ 只在这里覆盖宽度，不动 .modal 本体
       （动它会波及全站 49 处弹窗）。
     · 头像/二维码用 object-fit:contain —— 传上来的图比例千奇百怪，
       cover 会把二维码**裁掉一个角**（客户扫不出来，而页面上看着"有图"）。
     ★ 顶栏入口 .navhelp 只借 .topnav 的输赢态样式，位置由它自己决定
       （顶栏右侧一串动作的**最前面**，与「⌨ 快捷键」同侧、同一档）——
       刻意**不**去动左边那四个「定目标 / 管钱货 / 做推广 / 所有」的结构。 */
.helpcard{width:380px}
/* ★ max-height 比通用 .modal（86vh）再收一点：名片是"展示型"卡片，
   内容比屏幕高的后果是**底部的「知道了」要滚动才看得见**（真浏览器截图看到过）。
   收到 82vh + 内部滚动，短名片不受影响。 */
.helpcard{max-height:82vh}
.helpcard .hc-top{display:flex;gap:var(--sp-4);align-items:center}
.helpcard .hc-ava{width:72px;height:72px;border-radius:50%;object-fit:cover;
  border:1px solid var(--line);background:var(--panel-2);flex:0 0 auto}
.helpcard .hc-ava.ph{display:flex;align-items:center;justify-content:center;
  font-size:26px;color:var(--ink-3)}
.helpcard .hc-name{font-size:var(--fs-2);font-weight:600}
.helpcard .hc-title{font-size:var(--fs-5);color:var(--ink-3);margin-top:2px}
.helpcard .hc-intro{margin:var(--sp-3) 0 0;font-size:var(--fs-4);line-height:1.7;
  white-space:pre-wrap}
/* ★ 二维码 180px 太高会把自我介绍顶出可视区（实测），收到 140px：
   二维码扫得出来靠的是"图清楚 + 屏幕亮"，不靠像素大。 */
.helpcard .hc-qr{margin:var(--sp-3) auto 0;width:140px;max-width:60%;
  border:1px solid var(--line);border-radius:var(--r-2);padding:6px;background:#fff}
.helpcard .hc-qr img{width:100%;display:block;object-fit:contain}
.helpcard .hc-qr .cap{font-size:var(--fs-5);color:var(--ink-3);text-align:center;
  margin-top:4px}
.helpcard .hc-row{display:flex;align-items:center;gap:var(--sp-2);
  margin-top:var(--sp-3);font-size:var(--fs-4)}
.helpcard .hc-row .k{color:var(--ink-3);flex:0 0 52px}
.helpcard .hc-row .v{font-weight:600;word-break:break-all}
.helpcard .hc-guide{font-size:var(--fs-4);line-height:1.7}
.helpcard .hc-guide ol{margin:var(--sp-2) 0 0;padding-left:1.3em}
.helpcard .hc-guide li{margin:4px 0}

/* ===== [UI] 经营看板 /dash + 快捷入口 =====
   这一块是验证方（界面侧）加的，看到 [UI] 标记请整块保留。
   变量全部走 :root，不写死颜色。
*/
.cards .card.kpi{border-left:3px solid var(--line)}
.cards .card.kpi.brand{border-left-color:var(--brand)}
.cards .card.kpi.red{border-left-color:var(--danger)}
.cards .card.kpi.orange{border-left-color:var(--warn)}
.cards .card.kpi.ok{border-left-color:var(--ok)}
.cards .card.kpi .sub{font-size:var(--fs-5);color:var(--ink-3);
  margin-top:var(--sp-1);line-height:1.4}
.kpi-link{display:block;color:inherit;text-decoration:none}
.kpi-link:hover{text-decoration:none}
.cards .card.kpi:hover{box-shadow:var(--sh-2)}

.quick{display:flex;flex-wrap:wrap;gap:var(--sp-3);
  padding:var(--sp-3) var(--sp-4)}
.qbtn{display:inline-flex;align-items:center;gap:var(--sp-2);
  padding:10px var(--sp-4);border:1px solid var(--line);
  border-radius:var(--r-3);color:var(--ink);background:var(--panel)}
.qbtn:hover{border-color:var(--brand);color:var(--brand);text-decoration:none}
.qbtn .ic{width:16px;height:16px;color:var(--brand)}

/* ===== [UI] 丝滑动效（2026-09-16 统一补）=====
   全部走 CSS transition，不引动画库、不拖慢渲染。
   时长分级：交互反馈 120ms / 卡片 200ms / 侧栏 150ms / 页面 200ms。
   遵循 prefers-reduced-motion，用户系统开了「减少动态」就全部关闭。
*/
/* 侧栏：激活项左侧滑入 + 图标微动 */
.side a{transition:background .15s ease,color .15s ease,padding-inline-start .18s ease}
.side a:hover{padding-inline-start:calc(var(--sp-4) + 2px)}
.side a.on{padding-inline-start:calc(var(--sp-4) + 2px)}
.side a .ic{transition:transform .2s ease,color .15s ease}
.side a:hover .ic{transform:translateX(2px)}

/* 卡片：hover 上浮（KPI 卡已有一份，这里覆盖通用 .card） */
.card{transition:box-shadow .2s ease,transform .2s ease,border-color .2s ease}
.card:hover{box-shadow:var(--sh-2);transform:translateY(-2px)}

/* 快捷入口按钮 */
.qbtn{transition:border-color .15s ease,color .15s ease,background .15s ease,transform .12s ease}
.qbtn:hover{transform:translateY(-1px)}
.qbtn:active{transform:scale(.98)}

/* 表格行 hover 微亮 */
table tr{transition:background .12s ease}

/* 消息提示：滑入淡入 */
.alert{animation:xj-slide-in .24s ease}
@keyframes xj-slide-in{from{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:none}}

/* 弹窗：淡入上浮 */
.modalBack{animation:xj-fade .18s ease}
.modal{animation:xj-pop .22s ease}
@keyframes xj-fade{from{opacity:0}to{opacity:1}}
@keyframes xj-pop{from{opacity:0;transform:translateY(10px) scale(.98)}to{opacity:1;transform:none}}

/* 主内容区：页面切换淡入 */
.main{animation:xj-page-in .2s ease}
@keyframes xj-page-in{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}

/* 顶栏下拉菜单（若有）展开 */
.top select,.sel{transition:border-color .15s ease,box-shadow .15s ease}

/* 尊重系统「减少动态」设置 */
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{animation:none!important;transition:none!important}
}

/* ===== [UI] 网站管理中枢（2026-09-16）===== */
.tabs{display:flex;flex-wrap:wrap;gap:var(--sp-2);
  border-bottom:1px solid var(--line);margin-bottom:var(--sp-4)}
.tabs a{display:inline-flex;align-items:center;gap:6px;
  padding:9px var(--sp-4);font-size:var(--fs-4);color:var(--ink-2);
  border-bottom:2px solid transparent;cursor:pointer;
  transition:color .15s ease,border-color .15s ease,background .15s ease;
  text-decoration:none;border-radius:var(--r-2) var(--r-2) 0 0}
.tabs a:hover{color:var(--brand);background:var(--brand-soft)}
.tabs a.on{color:var(--brand);border-bottom-color:var(--brand);font-weight:600}
.tabs a .ic{width:16px;height:16px}

.tab-panel{display:none}
.tab-panel.on{display:block;animation:xj-page-in .2s ease}

.skin-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(160px,1fr));
  gap:var(--sp-3)}
.skin-card{display:flex;flex-direction:column;gap:var(--sp-3);align-items:flex-start;
  padding:var(--sp-4);border:2px solid var(--line);border-radius:var(--r-3);
  background:var(--panel);color:var(--ink);cursor:pointer;
  transition:border-color .15s ease,box-shadow .15s ease,transform .12s ease}
.skin-card:hover{border-color:var(--brand);box-shadow:var(--sh-2);transform:translateY(-2px)}
.skin-card.sel{border-color:var(--brand);box-shadow:0 0 0 3px var(--brand-soft)}
.skin-card .sw{display:flex;gap:4px}
.skin-card .sw i{width:22px;height:22px;border-radius:6px;border:1px solid var(--line)}
.skin-card .lbl{font-size:var(--fs-4);font-weight:600}

.form-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));
  gap:var(--sp-3)}
.field{display:flex;flex-direction:column;gap:var(--sp-1)}
.field label{font-size:var(--fs-4);font-weight:600}
.field label .muted{font-weight:400}
.field input{padding:0 var(--sp-3);border:1px solid var(--line);border-radius:var(--r-2);
  font:inherit;line-height:normal;background:var(--panel)}
.field input:focus{outline:none;border-color:var(--brand);box-shadow:0 0 0 2px var(--brand-soft)}

.btnlink{display:inline-flex;align-items:center;gap:6px;margin:var(--sp-3) 0 0;
  color:var(--brand);font-weight:500}

/* ★★ 2026-09-29（张总「全部 字段拥挤   对不齐的都优化掉」）：
   工具条 / 按钮行里的 `.btnlink` 必须**没有段间距**。
   为什么会有这一条 —— 本文件里 `.btnlink` 有**两条互相打架**的规则：
     · 452 行那条给了 `margin-left:auto`          ← "推到行尾"
     · 624 行那条给了 `margin:var(--sp-3) 0 0`    ← "链接型入口"的段间距
   两者选择器权重相同（都是单类），源顺序在后的赢 ⇒ 工具条里那个 <a> 被顶上
   12px，盒心比邻居低 **6.0px**。真浏览器量到中心 196.3 vs 202.3 ——
   **张总截图里「导出 CSV 比旁边矮半截」就是这个**（网站线索的 /leads 页，
   它把「导出 CSV」的 button 套在一个 btnlink 的 <a> 里，正是本文件下面
   那条注释里点名禁止的写法）。
   ★ 这里只把"工具条上下文里的段间距"归零，不动那条给正文用的规则
     （商品详情之类页面上的「查看全部 →」仍要保持段间距）。
   ★ 注释里**一个花括号都不要写**：本仓多个门禁（test_button_contrast /
     test_hidden_attr）用「最朴素的正则按花括号切规则」读这个文件，注释里
     出现花括号会把后面的规则切错 —— 我第一版就在这一条里抄了一整条规则
     （选择器带大括号那种），当场把 test_button_contrast 的反证弄红。
     写"某个选择器 + 某个属性"就够了，别把整条规则抄进注释。 */
.toolbar .btnlink,.bar .btnlink,.sec-tools .btnlink,.sec-head .btnlink,
.panel .hd .btnlink{margin:0;height:var(--ctl-h);line-height:normal}
.btnlink:hover{text-decoration:none;color:var(--brand-dk)}

/* 导航型按钮（长得像 button，其实是个链接）。
   ★ 为什么要这个类：`<a class="btnlink"><button>取消</button></a>` 是**非法
     HTML** —— `<button>` 不能嵌在 `<a>` 里。浏览器解析时会把内层 button
     提出来，于是页面上出现一个「空心胶囊 + 一个按钮」的怪东西。
     实测 2026-09-18：通用表单页的保存/取消区就是这个样子。
     凡是"点了要跳页"的按钮一律用 a.btnlike，别再套 button。 */
a.btnlike{display:inline-flex;align-items:center;gap:6px;
  height:var(--ctl-h);padding:0 var(--sp-4);line-height:normal;
  border:1px solid var(--line);
  border-radius:var(--r-2);background:var(--panel);color:var(--ink-2);
  font-size:var(--fs-4);text-decoration:none;cursor:pointer}
a.btnlike:hover{background:var(--brand-soft);color:var(--brand);
  border-color:var(--brand);text-decoration:none}

/* ══════════ 内容编辑 · 板块可视化 ══════════ */
.section-list{display:flex;flex-direction:column;gap:var(--sp-3)}
.sec-item{border:1px solid var(--line);border-radius:var(--r-2);background:var(--panel);
  overflow:hidden}
.sec-item.is-off{opacity:.55}
.sec-head{display:flex;align-items:center;gap:var(--sp-2);padding:var(--sp-3)}
.sec-head b{font-size:var(--fs-3);font-family:ui-monospace,monospace}
.sec-actions{margin-inline-start:auto;display:flex;gap:var(--sp-2)}
/* ★★ .sec-btn / .skin-card 必须显式写 color（2026-09-18 实测抓到）
   基础的 `button{background:var(--brand); color:var(--brand-ink /* #fff */)}` 是**白字**。
   这两个类只把底色改成了 var(--panel)（也是 #fff），**却没改文字色** ——
   于是白底白字，按钮上的字完全看不见（框还在、点得动、就是不显示文字）。
   受影响的都是"次要按钮"：客户公海弹窗的「取消 / × 关闭」、网站管理的
  「编辑 / 删除 / 上架 / 翻译成 9 语种 / ＋ 加 FAQ」、主题卡片的名字、工作台。
   `.sec-btn.primary` 因为显式写了 `color:#fff`（brand 底）才一直正常 ——
   正因为"主要的那个看得见"，这个缺陷才这么久没被发现。
   守卫：tests/test_button_contrast.py（含自测 + 反证）。 */
.sec-btn{padding:5px 12px;border:1px solid var(--line);border-radius:var(--r-2);
  /* ★ 刻意保留自己高度：它是网站后台内容编辑区的小按钮，不要吃 --ctl-h
     （吃了会被撑成 32px、与它旁边的小字不搭）。
     ★ 这一条**写在 color 那几句之前**是有意的：tests/test_button_contrast.py
     的反证补丁按字面量（background / color / cursor / font-size 连着的那一段
     直到右花括号）去替换 CSS。把这几个声明拆开、或插在它们中间，那个补丁就
     匹配不上、反证不红 —— 别人的门禁锚点不许被我顺手弄断。
     ★ 这段注释里**一个花括号都没有**，原因同上一条：朴素正则读不得花括号。 */
  height:auto;line-height:inherit;
  background:var(--panel);color:var(--ink);cursor:pointer;font-size:var(--fs-4)}
.sec-btn:hover{border-color:var(--brand)}
/* ★ .sec-btn 原本只给 button 用。表格里的「选它」是**跳转**，必须是 <a>
   （<a> 里再套 <button> 会渲染成空心胶囊，2026-09-18 已在 list.html 踩过）。
   但 <a> 默认 display:inline，纵向 padding 不撑行高，看着是扁的；
   而且链接色/下划线要压掉。这三行就是给 a.sec-btn 补上的。 */
a.sec-btn{display:inline-block;text-decoration:none;color:var(--ink)}
.sec-btn.primary{background:var(--brand);color:#fff;border-color:var(--brand)}
.sec-btn.primary:hover{background:var(--brand-dk)}
.sec-body{padding:var(--sp-3);border-top:1px solid var(--line);display:flex;
  flex-direction:column;gap:var(--sp-3)}
.sec-body .field{display:flex;flex-direction:column;gap:var(--sp-1)}
.sec-body .field label{font-size:var(--fs-4);font-weight:600}
.sec-body input[type="text"],.sec-body input:not([type]),.sec-body .sec-url{
  padding:0 var(--sp-3);border:1px solid var(--line);border-radius:var(--r-2);
  font:inherit;line-height:normal;background:var(--panel)}
.sec-body textarea{padding:8px var(--sp-3);border:1px solid var(--line);
  border-radius:var(--r-2);font:inherit;background:var(--panel);resize:vertical}
.sec-imgs{display:flex;gap:var(--sp-2);flex-wrap:wrap;margin-bottom:var(--sp-2)}
.sec-img{position:relative;width:90px;height:90px;border:1px solid var(--line);
  border-radius:var(--r-2);overflow:hidden}
.sec-img img{width:100%;height:100%;object-fit:cover;display:block}
.sec-img i{position:absolute;top:2px;right:2px;width:20px;height:20px;background:rgba(0,0,0,.6);
  color:#fff;border-radius:50%;display:grid;place-items:center;cursor:pointer;font-style:normal;
  font-size:13px;line-height:1}
.sec-addimg{display:flex;gap:var(--sp-2);align-items:center;flex-wrap:wrap}
.sec-addimg .sec-url{flex:1;min-width:180px}

/* ══════════ 版块行 · 员工友好版（2026-09-23 张总要求）
   原话：「中文部分要写清楚 是网页的哪个部分 点击进去不知道 有个截图图标
           让员工一眼就知道 以后维护靠他们 他们文化不高」
   设计：每行左侧一张"这一块在官网长什么样"的缩略图 + 详细中文位置说明，
         右侧「🔍 看官网效果」按钮直接跳到官网那一块。
   ★ 全部用 light 主题变量，不写死颜色。 */
.sec-row{display:flex;gap:var(--sp-3);align-items:flex-start;padding:var(--sp-3)}
.sec-thumb{flex:0 0 168px;width:168px;height:104px;border:1px solid var(--line);
  border-radius:var(--r-2);overflow:hidden;background:var(--panel-2,#f3f5f7);
  position:relative;cursor:zoom-in}
.sec-thumb img{width:100%;height:100%;object-fit:cover;object-position:top center;display:block}
.sec-thumb .no-pic{display:grid;place-items:center;height:100%;font-size:var(--fs-4);
  color:var(--muted);text-align:center;padding:var(--sp-2);line-height:1.5}
.sec-thumb .shot-at{position:absolute;left:0;right:0;bottom:0;background:rgba(0,0,0,.55);
  color:#fff;font-size:11px;padding:2px 6px;text-align:right;letter-spacing:.2px}
.sec-thumb.stale{border-color:#e0a800;box-shadow:0 0 0 2px rgba(224,168,0,.18)}
.sec-thumb .stale-badge{position:absolute;left:0;top:0;background:#e0a800;color:#3a2c00;
  font-size:11px;padding:2px 6px;border-bottom-right-radius:var(--r-2);font-weight:600}
.sec-main{flex:1;min-width:0;display:flex;flex-direction:column;gap:6px}
.sec-where{font-size:var(--fs-3);font-weight:600;line-height:1.5;color:var(--ink)}
.sec-where .pg{display:inline-block;background:var(--brand);color:#fff;border-radius:var(--r-2);
  padding:1px 8px;font-size:var(--fs-4);margin-inline-end:6px;white-space:nowrap}
.sec-where .none{color:var(--muted);font-weight:400}
.sec-key{font-family:ui-monospace,monospace;font-size:var(--fs-4);color:var(--muted)}
.sec-tools{display:flex;gap:var(--sp-2);flex-wrap:wrap;align-items:center;margin-top:2px}
.sec-tools .sec-btn{white-space:nowrap}
.sec-tools .spacer{flex:1}
/* ★ 保存反馈就地显示在按钮上（2026-09-23 张总"点保存没提示"）：
   顶部 #alert 在页面最顶上，滚到下面编辑根本看不见 ⇒ 按钮自己变色变字。 */
.sec-btn.saved-ok{background:#1e9e5a;color:#fff;border-color:#1e9e5a}
.sec-btn.saved-err{background:#c0392b;color:#fff;border-color:#c0392b}
.sec-btn:disabled{opacity:.7;cursor:wait}
/* 保存失败的具体原因，就地显示在保存按钮左边 */
.save-err{margin-inline-end:auto;align-self:center;font-size:var(--fs-4);
  color:#c0392b;background:#fdecea;border:1px solid #f5c6c0;
  border-radius:var(--r-2);padding:3px 10px;max-width:60%;line-height:1.5}
/* 顶部的体检/重抓工具条 */
.thumb-bar{display:flex;gap:var(--sp-2);align-items:center;flex-wrap:wrap;
  padding:var(--sp-3);border:1px solid var(--line);border-radius:var(--r-2);
  background:var(--panel);margin-bottom:var(--sp-3)}
.thumb-bar .tip{font-size:var(--fs-4);color:var(--muted);line-height:1.6;flex:1;min-width:220px}
.thumb-bar .tip b{color:#c0392b}
/* 图片放大预览（点缩略图看大图） */
.thumb-zoom{position:fixed;inset:0;background:rgba(0,0,0,.72);display:none;
  align-items:center;justify-content:center;z-index:9999;cursor:zoom-out;padding:24px}
.thumb-zoom.on{display:flex}
.thumb-zoom img{max-width:92vw;max-height:92vh;border-radius:var(--r-2);
  box-shadow:0 12px 48px rgba(0,0,0,.5);background:#fff}
.sec-foot{display:flex;justify-content:flex-end}

/* ══════════ 博客编辑 + 客户授权 ══════════ */
.sec-editor{position:fixed;inset:0;background:rgba(0,0,0,.45);z-index:60;
  display:flex;align-items:center;justify-content:center;padding:var(--sp-4)}
.sec-editor[hidden]{display:none}
.sec-editor>.hd{background:var(--panel);border-bottom:1px solid var(--line);
  padding:var(--sp-3);border-radius:var(--r-2) var(--r-2) 0 0;display:flex;
  align-items:center;gap:var(--sp-2);font-weight:600}
.sec-editor>.bd{background:var(--panel);border-radius:0 0 var(--r-2) var(--r-2);
  padding:var(--sp-4);max-width:920px;width:100%;max-height:86vh;overflow:auto}
.blog-langs{display:grid;grid-template-columns:1fr 1fr 1fr;gap:var(--sp-3);margin-top:var(--sp-3)}
.blog-lang{border:1px solid var(--line);border-radius:var(--r-2);padding:var(--sp-3);
  display:flex;flex-direction:column;gap:var(--sp-2)}
.blog-lang b{font-size:var(--fs-3)}
.blog-lang label{display:flex;flex-direction:column;gap:var(--sp-1);font-size:var(--fs-4)}
.blog-lang input,.blog-lang textarea{border:1px solid var(--line);
  border-radius:var(--r-2);font:inherit;background:var(--panel)}
.blog-lang input{padding:0 var(--sp-3);line-height:normal}
.blog-lang textarea{padding:8px var(--sp-3);resize:vertical}
.frm{display:grid;grid-template-columns:1fr 1fr;gap:var(--sp-2) var(--sp-3)}
.frm label{display:flex;flex-direction:column;gap:var(--sp-1);font-size:var(--fs-4)}
.frm input,.frm select,.frm .inp{padding:0 var(--sp-3);border:1px solid var(--line);
  border-radius:var(--r-2);font:inherit;line-height:normal;background:var(--panel)}
.cust-item{display:flex;align-items:center;gap:var(--sp-3);padding:var(--sp-3);
  border:1px solid var(--line);border-radius:var(--r-2);background:var(--panel);flex-wrap:wrap}
.cust-item .ci-main{display:flex;flex-direction:column;gap:2px;min-width:200px}
.cust-item .ci-main b{font-size:var(--fs-3)}
.cust-item .ci-tags{display:flex;gap:var(--sp-2);flex-wrap:wrap;margin-inline-start:auto;align-items:center}
.cust-item .ci-actions{display:flex;gap:var(--sp-2)}
.badge{display:inline-block;padding:2px 8px;border-radius:999px;font-size:var(--fs-4);border:1px solid var(--line)}
.badge.t1{background:#fff3e0;color:#b26a00;border-color:#ffd8a8}
.badge.t2{background:#e3f2fd;color:#1565c0;border-color:#b3e5fc}
.badge.t3{background:#ede7f6;color:#5e35b1;border-color:#d1c4e9}
.badge.off{background:#fbe9e7;color:#c62828;border-color:#ffccbc}
.blog-meta{display:flex;gap:var(--sp-2);flex-wrap:wrap;align-items:center}
.blog-meta .muted{font-size:var(--fs-4)}
@media (max-width:760px){.blog-langs{grid-template-columns:1fr}.frm{grid-template-columns:1fr}}

/* ══════════ 监控统计 ══════════ */
.stats-grid{display:grid;grid-template-columns:1fr 1fr;gap:var(--sp-3);margin-top:var(--sp-3)}
.stats-grid>.panel{margin:0}
.stats-grid>.panel>.hd{font-size:var(--fs-4);font-weight:600}
.bars{display:flex;flex-direction:column;gap:6px}
.bar-row{display:flex;align-items:center;gap:var(--sp-2);font-size:var(--fs-4)}
.bar-label{width:120px;flex-shrink:0;color:var(--ink-2);white-space:nowrap;overflow:hidden;
  text-overflow:ellipsis;font-variant-numeric:tabular-nums}
.bar-track{flex:1;height:14px;background:var(--panel-2);border-radius:7px;overflow:hidden}
.bar-fill{display:block;height:100%;background:var(--brand);border-radius:7px;
  transition:width .4s ease}
.bar-num{width:80px;text-align:right;color:var(--ink-3);font-variant-numeric:tabular-nums}
@media (max-width:760px){.stats-grid{grid-template-columns:1fr}.bar-label{width:80px}}



/* ══════════ 知识库投喂 ══════════ */
.kb-top{display:flex;flex-direction:column;gap:var(--sp-3)}
.kb-actions{display:flex;gap:var(--sp-3);align-items:center;flex-wrap:wrap}
.kb-upload{display:inline-flex;align-items:center;gap:8px;padding:8px 16px;
  border:1px dashed var(--brand);color:var(--brand);border-radius:var(--r-2);
  cursor:pointer;font-size:var(--fs-4)}
.kb-upload:hover{background:var(--brand-soft,rgba(26,127,90,.06))}

/* ══════════ 希捷工作台（并入 ERP 的管理台账） ══════════ */
.ws-kpi{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--sp-3);margin:var(--sp-3) 0}
.ws-kpi-box{border:1px solid var(--line);border-radius:var(--r-2);background:var(--panel);
  padding:var(--sp-4);display:flex;flex-direction:column;gap:var(--sp-1)}
.ws-kpi-box .n{font-size:28px;font-weight:700;color:var(--brand);font-variant-numeric:tabular-nums}
.ws-kpi-box .l{font-size:var(--fs-4);color:var(--ink-2)}
.badge.warn{background:#fdecea;color:#c62828;border-color:#ffcdd2}
/* ★★ 2026-09-26（参考百草·一期 1-5）：列表页**状态色块**要用到的三档。
   原来 .badge 只有 t1/t2/t3/off/warn 五个实心档（都偏"标签"用途）——
   缺「做完了(绿)」「作废/停用(灰)」「卡住了(红)」这三档，而那正是状态列的语义。
   ★ 颜色与 .tag.ok / .tag.mute / .tag.danger 用同一套 CSS 变量，
     免得同一个"已审核"在详情页是绿字标签、在列表页是另一个绿。
   ★ 为什么必须加规则：本仓反复踩过「加了 class 没加规则」——
     那样子元素会退回 .badge 的灰底，老板看不出哪个做完了（等于没上色）。 */
.badge.ok{background:#e8f5e9;color:var(--ok);border-color:#c8e6c9}
.badge.mute{background:#f4f5f6;color:var(--ink-3);border-color:var(--line)}
.badge.danger{background:#fdecea;color:var(--danger);border-color:#ffcdd2}
/* ★ 时间筛选快捷档（一期 1-2）：一排药丸，选中那个实心。
   ★★ 2026-09-29：药丸**也吃 --ctl-h**（原来 3px 上下内边距 ⇒ 实测 27.2px，
   与旁边 31/32px 的按钮挤在一行里"高矮不一"，张总说的就是这一排）。
   同时干掉 `margin-inline-end:var(--sp-1)` —— 那一笔 4px 让药丸与后一个
   控件之间变成 12px，而工具条别的间距都是 8px（实测 ['12.0','8.0','8.0'…]）
   ⇒ 这就是"间距忽宽忽窄"的另一半。药丸仍是胶囊形（999px 圆角），
   只统一**高度与间距**，不动颜色/字号。 */
.quicktime{display:inline-flex;flex-wrap:wrap;gap:var(--ctl-gap)}
.quicktime .qchip{display:inline-flex;align-items:center;height:var(--ctl-h);
  padding:0 10px;border:1px solid var(--line);border-radius:999px;
  font-size:var(--fs-5);color:var(--ink-2);text-decoration:none;background:var(--panel);
  white-space:nowrap}
.quicktime .qchip:hover{border-color:var(--brand);color:var(--brand)}
.quicktime .qchip.on{background:var(--brand);border-color:var(--brand);color:var(--brand-ink)}
/* ★ 列选择器面板（一期 1-1）：钉在工具条下方的浮层 */
.colspanel{position:absolute;z-index:40;margin-top:6px;width:min(760px,92vw);
  max-height:60vh;display:flex;flex-direction:column;
  background:var(--panel);border:1px solid var(--line);border-radius:var(--r-2);
  box-shadow:0 8px 24px rgba(0,0,0,.14)}
.colspanel .cp-hd{padding:var(--sp-3) var(--sp-4);border-bottom:1px solid var(--line);
  display:flex;gap:var(--sp-3);align-items:baseline;font-size:var(--fs-4)}
.colspanel .cp-bd{padding:var(--sp-3) var(--sp-4);overflow:auto;
  display:grid;grid-template-columns:repeat(auto-fill,minmax(210px,1fr));gap:2px 12px}
.colspanel .colitem{display:flex;align-items:center;gap:6px;font-size:var(--fs-4);
  padding:2px 0;cursor:pointer}
.colspanel .colitem .muted{font-size:var(--fs-5)}
.colspanel .cp-ft{padding:var(--sp-3) var(--sp-4);border-top:1px solid var(--line);
  display:flex;gap:var(--sp-2);justify-content:flex-end}
@media (max-width:760px){.ws-kpi{grid-template-columns:1fr}}

/* ══════════ OKR 对齐树 ══════════ */
.okr-legend{display:flex;align-items:center;gap:16px;font-size:var(--fs-4);color:var(--ink-2);margin-bottom:var(--sp-3)}
.okr-legend .dot{display:inline-block;width:10px;height:10px;border-radius:50%;margin-inline-end:5px;vertical-align:middle}
.okr-legend .dot.g{background:#639922}.okr-legend .dot.y{background:#EF9F27}.okr-legend .dot.r{background:#E24B4A}
.okr-tree{min-height:200px;overflow-x:auto;padding:var(--sp-3) 0}
.okr-tree .okr-row{display:flex;align-items:center;gap:12px;padding:8px 4px;border-radius:var(--r-2);cursor:pointer;transition:background .15s}
.okr-tree .okr-row:hover{background:var(--bg-2)}
.okr-tree .okr-row .nd{flex:0 0 auto;padding:8px 14px;border-radius:999px;border:1px solid var(--line);
  background:var(--panel);font-size:var(--fs-4);color:var(--ink);white-space:nowrap;position:relative}
.okr-tree .okr-row .nd .pct{font-weight:700;margin-inline-start:6px;font-variant-numeric:tabular-nums}
.okr-tree .okr-row .nd.g{border-color:#97C459;background:#EAF3DE}
.okr-tree .okr-row .nd.y{border-color:#FAC775;background:#FAEEDA}
.okr-tree .okr-row .nd.r{border-color:#F09595;background:#FCEBEB}
.okr-tree .okr-row .nd.g .pct{color:#3B6D11}
.okr-tree .okr-row .nd.y .pct{color:#854F0B}
.okr-tree .okr-row .nd.r .pct{color:#A32D2D}
.okr-tree .okr-row .own{font-size:var(--fs-4);color:var(--ink-2);white-space:nowrap}
.okr-tree .okr-children{margin-inline-start:32px;padding-inline-start:16px;border-inline-start:2px dashed var(--line)}
.okr-tree .okr-krs{font-size:var(--fs-4);color:var(--ink-2);margin-inline-start:8px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:360px}
.okr-tree .okr-acts{margin-inline-start:auto;display:flex;gap:6px;opacity:0;transition:opacity .15s}
.okr-tree .okr-row:hover .okr-acts{opacity:1}

/* ══════════ 首页三大板块入口 ══════════ */
.home-hero h1{font-size:24px;font-weight:500;margin-bottom:4px}
.home-hero .sub{color:var(--ink-2);font-size:14px;margin-bottom:var(--sp-5)}
.home-boards{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--sp-4)}
.home-boards .board{display:flex;gap:var(--sp-3);align-items:flex-start;padding:var(--sp-5);
  border:1px solid var(--line);border-radius:var(--r-2);background:var(--panel);
  text-decoration:none;transition:transform .12s,box-shadow .12s}
.home-boards .board:hover{transform:translateY(-2px)}
.home-boards .board .ic{width:44px;height:44px;border-radius:12px;display:flex;
  align-items:center;justify-content:center;flex:0 0 44px}
.home-boards .board .ic .ic{width:22px;height:22px;color:#fff}
.home-boards .board .name{font-size:17px;font-weight:500;color:var(--ink);margin-bottom:2px}
.home-boards .board .desc{font-size:13px;color:var(--ink-2);margin-bottom:8px}
.home-boards .board .items{font-size:12px;color:var(--ink-3)}
.home-boards .b-goal .ic{background:#534AB7}
.home-boards .b-money .ic{background:#0F6E56}
.home-boards .b-grow .ic{background:#185FA5}
@media (max-width:760px){.home-boards{grid-template-columns:1fr}}

/* ══════════ 经营看板 全屏驾驶舱（老板专属） ══════════ */
.dash-head{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-4);flex-wrap:wrap}
.dash-okr{display:flex;align-items:center;gap:var(--sp-3);background:var(--panel);
  border:1px solid var(--line);border-radius:var(--r-3);padding:var(--sp-3) var(--sp-4)}
.dash-okr-label{font-size:var(--fs-5);color:var(--ink-3)}
.dash-okr-pct{font-size:22px;font-weight:600;color:var(--brand)}
.dash-okr-dots{display:flex;align-items:center;gap:var(--sp-1);font-size:var(--fs-5);color:var(--ink-2)}
.dash-okr-dots .d{width:9px;height:9px;border-radius:50%;display:inline-block}
.dash-okr-dots .d.green{background:var(--ok)}
.dash-okr-dots .d.yellow{background:var(--warn)}
.dash-okr-dots .d.red{background:var(--danger)}

.dash-grid{display:grid;grid-template-columns:1.4fr 1fr;gap:var(--sp-4);margin-bottom:var(--sp-4)}
.dash-todos h2,.dash-right h2{font-size:var(--fs-2);margin:0;padding:var(--sp-3) var(--sp-4);border-bottom:1px solid var(--line)}
.dash-todo-desc{font-size:var(--fs-5);color:var(--ink-3);margin-top:2px}
.dash-right{display:flex;flex-direction:column;gap:var(--sp-4)}

.dash-trend{display:flex;align-items:flex-end;gap:var(--sp-2);height:140px;padding:var(--sp-4)}
.dash-trend .bar-col{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:flex-end;height:100%}
.dash-trend .bar{width:70%;max-width:34px;background:var(--brand);border-radius:var(--r-1) var(--r-1) 0 0;min-height:2px}
.dash-trend .bar-label{font-size:11px;color:var(--ink-3);margin-top:var(--sp-1)}

.dash-okr-list{list-style:none;margin:0;padding:var(--sp-2) var(--sp-4) var(--sp-4)}
.dash-okr-list li{display:flex;align-items:center;gap:var(--sp-2);padding:5px 0;font-size:var(--fs-4)}
.dash-okr-list .okr-name{flex:0 0 auto;max-width:150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--ink-2)}
.dash-okr-list .okr-owner{flex:0 0 auto;font-size:var(--fs-5);color:var(--ink-3)}
.dash-okr-list .okr-bar{flex:1;height:6px;background:var(--panel-2);border-radius:3px;overflow:hidden}
.dash-okr-list .okr-bar .fill{display:block;height:100%;border-radius:3px}
.dash-okr-list .okr-bar .fill.green{background:var(--ok)}
.dash-okr-list .okr-bar .fill.yellow{background:var(--warn)}
.dash-okr-list .okr-bar .fill.red{background:var(--danger)}
.dash-okr-list .okr-pct{flex:0 0 auto;width:38px;text-align:right;font-size:var(--fs-5);color:var(--ink-2)}

@media (max-width:920px){.dash-grid{grid-template-columns:1fr}}

/* ══════════ 管钱货板块页 · 手风琴 ══════════ */
.acc{background:var(--panel);border:1px solid var(--line);border-radius:var(--r-3);
  margin-bottom:var(--sp-3);overflow:hidden}
.acc summary{display:flex;align-items:center;gap:var(--sp-3);padding:var(--sp-4);
  cursor:pointer;list-style:none;user-select:none}
.acc summary::-webkit-details-marker{display:none}
.acc summary:hover{background:var(--panel-2)}
.acc-ic{width:36px;height:36px;border-radius:10px;background:var(--brand-soft);
  display:flex;align-items:center;justify-content:center;flex:0 0 36px}
.acc-ic .ic{width:18px;height:18px;color:var(--brand)}
.acc-t{flex:1;display:flex;flex-direction:column}
.acc-t b{font-size:var(--fs-2);font-weight:600;color:var(--ink)}
.acc-t small{color:var(--ink-3);font-size:var(--fs-5)}
.acc-arrow{color:var(--ink-3);transition:transform .15s}
.acc[open] .acc-arrow{transform:rotate(180deg)}
.acc-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(160px,1fr));
  gap:var(--sp-2);padding:0 var(--sp-4) var(--sp-4)}
.acc-item{display:flex;align-items:center;gap:var(--sp-2);padding:var(--sp-3);
  border:1px solid var(--line);border-radius:var(--r-2);background:var(--panel);
  color:var(--ink);font-size:var(--fs-3);text-decoration:none;transition:border-color .12s}
.acc-item:hover{border-color:var(--brand);text-decoration:none}
.acc-item .tag{flex:0 0 auto}

/* ══════════════ 客户档案「账务」面板（2026-09-26 对标百草 · 台账第 1 项）══════════════
   ★ 为什么单独一套 grid 而不用现成的 .cards：`.cards` 是 `auto-fill(minmax(150px,1fr))`，
     auto-fill 会**留着空轨道** —— 4 张卡被塞进 8 条 150px 的轨道里，每张只剩 ~165px，
     于是「¥2,780,651.10」这种七位数就被挤出框了（真浏览器探针量到的，不是猜的）。
     `auto-fit` 会把空轨道收掉、卡片撑满整行 ⇒ 4 张卡每张 ~330px，七位数也放得下。 */
.acct-cards{display:grid;gap:var(--sp-3);
  grid-template-columns:repeat(auto-fit,minmax(230px,1fr))}
.acct-cards .card .v{font-size:19px;white-space:nowrap}

/* ══════════════ P3（2026-09-26 对标百草）：商品**卡片视图**（带图）══════════════
   百草的「商品」是带图的卡片墙（张总截图：「销售点击进来要是这样的」）。
   我们原来是 12 列密表 —— 认货靠看图的活（选品、报价、给客户发图）干不了。
   ★ 只对有图的视图开放（服务端 CARD_VIEWS 判），表格一键切回。
   ★ 图是**懒加载**的：一屏 50 张，不 lazy 会在打开瞬间发 50 个请求。 */
.skucards{display:grid;grid-template-columns:repeat(auto-fill,minmax(178px,1fr));
  gap:var(--sp-3);padding:var(--sp-4)}
.skucard{display:flex;flex-direction:column;background:var(--panel);
  border:1px solid var(--line);border-radius:var(--r-2);overflow:hidden;
  text-decoration:none;color:var(--ink);box-shadow:var(--sh-1);
  transition:box-shadow .18s ease,transform .18s ease,border-color .18s ease}
.skucard:hover{box-shadow:var(--sh-2);transform:translateY(-2px);
  border-color:var(--brand);text-decoration:none}
.skucard.nolink{cursor:default}
.skucard .sc-img{display:block;aspect-ratio:1/1;background:#F7F4EC;overflow:hidden;
  position:relative}
.skucard .sc-img img{width:100%;height:100%;object-fit:cover;display:block}
/* ★ 没有图的商品：**明说「无图」**（灰底 + 一行小字）——
   不拿别的图凑、也不留一个让人以为是"图没加载出来"的空白格。 */
.skucard.noimg .sc-img::after{content:'无图';position:absolute;right:6px;bottom:6px;
  font-size:var(--fs-5);color:var(--ink-3);background:rgba(255,255,255,.85);
  border:1px solid var(--line);border-radius:var(--r-1);padding:0 4px}
.skucard .sc-t{padding:6px 8px 0;display:flex;flex-direction:column;gap:1px;min-width:0}
.skucard .sc-t b{font-size:var(--fs-4);font-weight:600;white-space:nowrap;overflow:hidden;
  text-overflow:ellipsis}
.skucard .sc-t small{font-size:var(--fs-5);color:var(--ink-3)}
.skucard .sc-p{padding:2px 8px 8px;font-size:var(--fs-4);font-weight:600;color:var(--brand)}
.skucard .sc-p i{font-style:normal;font-weight:400;color:var(--ink-3);
  font-size:var(--fs-5)}
/* 卡片/表格 切换键的"当前态" */
#btnCard.on{background:var(--brand-soft);color:var(--brand);border-color:var(--brand)}
@media (max-width:920px){.skucards{grid-template-columns:repeat(auto-fill,minmax(132px,1fr))}}

   ① 工具条按钮里加小图标（百草是「图标+文字」）—— 只加壳，不动任何 JS/参数；
   ② 表格**行悬停**：暖底（--panel-2）—— 一屏 20+ 行时，眼睛不容易串行；
   ③ 表头**吸顶**：长列表往下滚时列名不跑掉（`.list-panel` 见下面的 overflow 说明）。 */
.btnico{display:inline-flex;align-items:center;gap:6px}
.btnico .ic{width:15px;height:15px;flex:0 0 15px;color:currentColor;opacity:.9}
tbody tr:hover>td{background:var(--panel-2)}
thead th{position:sticky;top:52px;z-index:2}
/* ★ .panel 原本是 overflow:hidden（为圆角裁切）—— 那会让里头的 sticky 表头失效
   （sticky 只能相对"可滚动的祖先"生效）。列表页这张面板显式放开，
   代价只是表格四角不再被圆角裁切（视觉上几乎看不出）。 */
.panel.list-panel{overflow:visible}
/* 卡片入场：轻微上浮淡入（百草那种"一片片铺开"的感觉）。
   ★ 尊重 prefers-reduced-motion：系统里关了动画的人不该被这个晃到。 */
@keyframes xjCardIn{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
.card-grid .gcard{animation:xjCardIn .18s ease both}
.cards .card{animation:xjCardIn .18s ease both}
.card-grid .gcard:nth-child(4n+2),.cards .card:nth-child(2){animation-delay:.02s}
.card-grid .gcard:nth-child(4n+3),.cards .card:nth-child(3){animation-delay:.04s}
.card-grid .gcard:nth-child(4n+4),.cards .card:nth-child(4){animation-delay:.06s}
@media (prefers-reduced-motion:reduce){
  .card-grid .gcard,.cards .card{animation:none}
  .gcard:hover{transform:none}
}

/* ══════════════ P1（2026-09-26 对标百草）：卡片宫格 + 彩色扁平图标 ══════════════
   为什么**新加**一套而不是改 .acc：`.acc` 是「所有」与「管钱货」两页共用的手风琴
   （money.html 还在用），改它会连带动那两页；这里只给「所有」页换成百草那种
   **一眼看全、点卡直达**的宫格（对照图 对比1_首页宫格.png）。
   ★ 图标：卡片用彩色扁平 `#if-*`（40px），拿不到扁平图的分组回落线条 `#i-*`。 */
.grid-sec{margin-bottom:var(--sp-5)}
.grid-sec-t{font-size:var(--fs-5);font-weight:400;color:#999999;margin:0 0 var(--sp-3)}
.grid-sec-t .muted{color:var(--ink-3)}
.card-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(228px,1fr));
  gap:var(--sp-3)}
.gcard{display:flex;align-items:center;gap:var(--sp-3);padding:14px 16px;
  background:var(--panel);border:1px solid var(--line);border-radius:var(--r-3);
  box-shadow:var(--sh-1);color:var(--ink);text-decoration:none;
  transition:box-shadow .18s ease,transform .18s ease,border-color .18s ease}
.gcard:hover{box-shadow:var(--sh-2);transform:translateY(-2px);
  border-color:var(--brand);text-decoration:none}
.gcard-ic{flex:0 0 44px;width:44px;height:44px;display:flex;align-items:center;
  justify-content:center}
.gcard-ic .iflat{width:40px;height:40px}
.gcard-ic .ic{width:20px;height:20px;color:var(--brand)}

/* ★★ 2026-09-27 P4.3 模块彩色扁平图标（`#if-*`，自绘，见 templates/_icons.html）：
   新接线处（人事页四板块卡 / 预警中心卡片 / 报表中心分组标题）的尺寸。
   ★ 为什么必须有 `.iflat` 这条兜底：`<svg class="iflat">` 不带 width/height 时，
     浏览器按 SVG 的默认尺寸（约 300×150）铺开 ⇒ 整块版面被撑破，
     而且**页面不报错**、HTML 也没坏，只有真浏览器截图才看得出来。
   ★ 更具体的两条（.gcard-ic .iflat 40px / .card.kpi .kpi-ic .iflat 30px）
     优先级更高，宫格与看板KPI 的尺寸一个字没动。 */
.iflat{display:inline-block;vertical-align:middle;flex:0 0 auto;
  width:32px;height:32px}
.acc-item .iflat{width:26px;height:26px;flex:0 0 26px}   /* 人事四板块卡 */
/* ★ 人事四板块卡要更宽的列：`.acc-grid` 的 160px 列宽是给「管钱货」那种
   **短条目密集排列**用的（那里的卡片 49px 高）；人事这四张卡每张是一整句中文
   说明，160px 里塞进"图标 + 板块标签 + 整句"之后整句被挤成竖排 ——
   真浏览器实测：卡片高度从 138px 涨到 250px，一屏全是竖排字。
   ⇒ 这一页单独放宽容度（自动填充：1600 屏宽下 4 张卡各 ~346px，文字 2 行内）。 */
.acc-grid.hr-cards{grid-template-columns:repeat(auto-fill,minmax(340px,1fr))}
.wcard-ic{flex:0 0 26px;display:flex;align-items:center}  /* 预警中心卡片 */
.wcard-ic .iflat{width:26px;height:26px}
.rpt-grp-ic{flex:0 0 26px;display:flex;align-items:center} /* 报表中心分组标题 */
.rpt-grp-ic .iflat{width:26px;height:26px}
.gcard-t{min-width:0;display:flex;flex-direction:column;gap:1px}
.gcard-t b{font-size:var(--fs-3);font-weight:600;color:var(--ink);
  /* ★ 2026-09-26 P1：**不省略号**。原来写 nowrap+ellipsis，真浏览器量到
     「预警中心（要动手的清单）」被截成「预警中心（要动手…」—— 名字被吃掉一半。
     宫格卡允许换行（卡片高度自己撑），宁可高一行，也不把入口名字藏起来。 */
  white-space:normal;overflow-wrap:anywhere}
.gcard-t small{font-size:var(--fs-5);color:var(--ink-3)}
@media (max-width:920px){.card-grid{grid-template-columns:repeat(auto-fill,minmax(160px,1fr))}}

/* 空状态：百草那种「居中插画 + 一句说明 + 一个出口」（原来是干巴巴一行灰字）。
   ★ 插画是**自绘**的内联 SVG（见 pages/all.html 的 .empty-ill），不是图片素材。 */
.empty-ill{width:132px;height:92px;display:block;margin:0 auto var(--sp-3)}
.empty-cta{margin-top:var(--sp-4)}

/* 看板 KPI 卡：百草风（彩色图标 + 大数字 + 副说明）—— 数字一个都没改口径
   ★ 图标放在**标签那一行**（不是单独一列）：这样金额能占满整张卡的宽度。
     第一版把图标做成左侧独立一列，真浏览器量到「¥29,600.00」被挤到出框
     （探针 _shot_p1_home.py 的 clipped 检查抓的）。 */
.card.kpi .kpi-head{display:flex;align-items:center;gap:var(--sp-2);margin-bottom:2px}
.card.kpi .kpi-ic{flex:0 0 32px;width:32px;height:32px;display:flex;align-items:center;
  justify-content:center}
.card.kpi .kpi-ic .iflat{width:30px;height:30px}
.card.kpi .kpi-ic .ic{width:18px;height:18px;color:var(--brand)}
.card.kpi .v{font-size:19px;white-space:nowrap}

/* 目标健康度环图（★ 只有**真的是百分比**的指标才画环 —— 见 _dash_body.html 的说明） */
.ring{position:relative;width:92px;height:92px;flex:0 0 92px}
.ring svg{width:92px;height:92px;transform:rotate(-90deg)}
.ring .track{fill:none;stroke:var(--panel-2);stroke-width:9}
.ring .val{fill:none;stroke:var(--ok);stroke-width:9;stroke-linecap:round;
  transition:stroke-dasharray .4s ease}
.ring .ring-txt{position:absolute;inset:0;display:flex;flex-direction:column;
  align-items:center;justify-content:center;line-height:1.1}
.ring .ring-txt b{font-size:20px;font-weight:600;color:var(--ink)}
.ring .ring-txt small{font-size:10px;color:var(--ink-3)}
.ring-card{display:flex;align-items:center;gap:var(--sp-4);background:var(--panel);
  border:1px solid var(--line);border-radius:var(--r-3);padding:var(--sp-3) var(--sp-4)}

/* ===== A组: 录入键盘流焦点高亮 (#23, 2026-09-22) =====
   为什么要有这块：键盘流靠"回车跳下一格"，如果焦点看不见，
   员工敲两下就不知道光标跑到哪去了 —— 那还不如用鼠标点。
   所以焦点必须**一眼可见**，且不能只靠浏览器默认的细虚线（投影仪/老显示器上看不清）。

   ★ 用 :focus-visible 而不是 :focus：
     鼠标点进来不该亮（会闪得很吵），只有键盘走格才亮 —— 这正是我们要区分的。
     浏览器不支持 :focus-visible 时，后面那条 :focus 兜底（老 Edge/旧内核）。

   ★ 只加"描边 + 浅底"，不改尺寸/边距 —— 免得一聚焦整页就跳一下。 */
.fitem input:focus-visible,
.fitem select:focus-visible,
.fitem textarea:focus-visible,
.fitem input:focus,
.fitem select:focus,
.fitem textarea:focus{
  outline:none;
  border-color:var(--brand);
  box-shadow:0 0 0 3px var(--brand-soft);
  background:var(--panel);
  position:relative;
  z-index:2;
}
/* 键盘走格时，整格轻微提亮；鼠标悬停不亮，避免"到处都亮" */
.fitem:focus-within > label{color:var(--brand);font-weight:600}
.fitem input.chk:focus-visible,
.fitem input.chk:focus{
  box-shadow:0 0 0 3px var(--brand-soft);
}

/* ══════════════════════════════════════════════════════════════════
   [账号与权限] 双击详情抽屉 + 权限矩阵标签（2026-09-24）
   ------------------------------------------------------------------
   ★ 显隐一律由 JS 设 style.display，**不靠 [hidden]**：
     本块自己写了 display:flex/none，作者样式会压掉 [hidden] 的 UA 样式 ——
     这个坑在 [hidden] 被作者样式顶掉那一次已经交过学费。
   ★ 颜色全部走 :root 变量，不写死色值（换肤才不会漏掉这一块）。
   ══════════════════════════════════════════════════════════════════ */
.drBack{position:fixed;inset:0;background:rgba(31,35,41,.35);z-index:60}
.dr{position:absolute;right:0;top:0;bottom:0;width:560px;max-width:94vw;
  background:var(--panel);box-shadow:-6px 0 24px rgba(16,24,40,.16);
  display:flex;flex-direction:column;animation:xj-dr .2s ease}
@keyframes xj-dr{from{transform:translateX(28px);opacity:.5}to{transform:none;opacity:1}}
.dr-hd{display:flex;align-items:center;gap:var(--sp-3);
  padding:var(--sp-4) var(--sp-5);border-bottom:1px solid var(--line)}
.dr-hd .t{flex:1;font-size:var(--fs-2);font-weight:600}
.dr-bd{flex:1;overflow:auto;padding:var(--sp-5)}
.dr-kv{display:grid;grid-template-columns:88px 1fr;gap:6px var(--sp-3);
  font-size:var(--fs-4)}
.dr-kv b{color:var(--ink-3);font-weight:500}
.mxhd{margin:var(--sp-5) 0 var(--sp-2);font-size:var(--fs-3);font-weight:600}
.mxgrp{margin-bottom:var(--sp-3)}
.mxgrp .gh{font-size:var(--fs-5);color:var(--ink-3);margin-bottom:6px}
.dr-line{font-size:var(--fs-4);padding:3px 0}
.mxitem{display:inline-block;margin:0 6px 6px 0;padding:1px 8px;
  border-radius:var(--r-1);font-size:var(--fs-5);border:1px solid var(--line);
  color:var(--ink-2);background:var(--panel)}
/* 三档一眼分清：能改（品牌浅底）/ 只能看（灰底）/ 看不见（淡到几乎融进背景） */
.mxitem.rw{background:var(--brand-soft);border-color:var(--brand);
  color:var(--brand-dk)}
.mxitem.ro{background:var(--panel-2);border-color:var(--line);color:var(--ink-2)}
.mxitem.no{border-style:dashed;color:var(--ink-3);opacity:.6}
.dr-act{display:flex;gap:8px;align-items:center;flex-wrap:wrap;
  margin-top:var(--sp-5);padding-top:var(--sp-4);border-top:1px solid var(--line)}

/* ══════════════════════════════════════════════════════════════════════
   条码标签打印（2026-09-27 / erp/templates/pages/barcode_labels.html）
   ──────────────────────────────────────────────────────────────────────
   用途：一张 A4 排多联标签，剪开贴在货上，手机/扫码枪扫条码查商品。
   为什么样式写在这里而不是模板里：全仓规矩 —— 颜色只走 :root 变量，
   模板里写死色值一换肤就漏一块（本仓踩过）。
   ★ 尺寸全部按**毫米**给：打印是物理尺寸，px 在不同 DPI 的打印机上不一样，
     而 1mm 永远是 1mm。
   ★ 条码四周的空白（静区）算在 SVG 里（core/barcode.py 的 QUIET_LEFT/RIGHT），
     这里只给标签留内边距 —— 两处都留，剪标签时才有安全的留白。
   ══════════════════════════════════════════════════════════════════════ */
.barcode-labels{display:grid;grid-template-columns:repeat(4,50mm);
  gap:3mm;justify-content:flex-start;align-items:start;
  background:var(--panel);padding:var(--sp-4);border:1px solid var(--line);
  border-radius:var(--r-2)}
.bc-label{border:1px dashed var(--line);border-radius:var(--r-1);
  padding:1.2mm 2mm;box-sizing:border-box;width:50mm;height:25mm;
  overflow:hidden;background:var(--panel)}
.bc-name{font-size:var(--fs-5);font-weight:600;color:var(--ink);
  line-height:1.1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.bc-code{font-size:var(--fs-6);color:var(--ink-3);line-height:1.1;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* ★ 条码图撑满可用宽度但**不拉伸**（height:auto 保持 SVG 自己的长宽比）：
   拉伸会把 1 模块宽的细条拉粗/拉细，扫码枪就读不出宽度比了。
   ★ SVG 的 module_px/height 由 erp/barcode_bp.py 按**联宽**算（1.5px/模块、
     46px 高）——这里只负责把它摆好，不再二次缩放。 */
.bc-bar{margin:.6mm 0}
.bc-bar svg{display:block;width:100%;height:auto;max-height:9.5mm}
.bc-meta{font-size:var(--fs-6);color:var(--ink-2);line-height:1.1;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

/* ── 打印：只在本页生效 ───────────────────────────────────────────────
   ★ 为什么用 `:has()` 而不是给 <body> 加类：base.html 是**两个会话共用**的文件，
     能不碰就不碰（同 erp/app.py 的理由）。`:has()` 现代浏览器都支持
     （Edge/Chrome 105+，本仓验收用的就是系统 Edge）；
     万一某个老浏览器不认，这一整块**整体不生效** —— 结果是"打印时多出页头
     和侧栏"，不是排版错乱，属于可接受的降级。 */
@media print{
  @page{size:A4 portrait;margin:8mm}
  /* ★★ 这一串是"标签纸之外的一切"，实测是逐次补出来的（每一条都是真浏览器
     截图上抓到的，不是拍脑袋列的）：
       .top/.side     —— 页头与侧栏；
       .backlink      —— base.html 里那个「← 返回」（在 .main 里，页头藏了它还在，
                         打印预览左上角就挂着两个字）；
       .noprint       —— 本页的标题/按钮/说明（模板里显式标了）。 */
  body:has(.barcode-labels) .top,
  body:has(.barcode-labels) .side,
  body:has(.barcode-labels) .backlink,
  body:has(.barcode-labels) .noprint{display:none !important}
  body:has(.barcode-labels){background:#fff}
  /* 去掉侧栏那 168px 的缩进，让 4 联刚好占满 A4 的可用宽度（194mm） */
  body:has(.barcode-labels) .wrap{margin-left:0;padding:0;display:block}
  body:has(.barcode-labels) .barcode-labels{border:none;padding:0;gap:2mm;
    grid-template-columns:repeat(4,47mm)}
  body:has(.barcode-labels) .bc-label{width:47mm;height:26mm;
    page-break-inside:avoid;break-inside:avoid;border-color:#ccc}
}

/* ══════════════════════════════════════════════════════════════════
   P4.2 单据详情页的页签（对标百草：它的销售单详情有 26 个页签）
   ------------------------------------------------------------------
   ★ 为什么要有：改造前详情页是一条长条
     （单据链 → 收付款记录 → 商品行 → 汇总 → 发货面板 → 锁定），
     跟单在手机上要翻好几屏才找得到"这单挂的物流单是哪张"。
   ★ 颜色**全部走 :root 变量**，不写死色值（全仓规矩：换肤不能漏一块）。
   ★ 默认显隐：`.tabpane{display:none}` + `.tabpane.on{display:block}`，
     **不用 `!important`、也不在模板里写行内 display** —— 两者都要不得：
       · 模板里的行内 `display:none` 优先级高于作者样式，只能配 `!important` 打开，
         而 `!important` 又会把 JS 后面写的 `style.display='none'` 一起压掉
         ⇒ 表现就是"点了页签，新内容出来了、旧内容不下去"（真浏览器验收当场抓到）；
       · 纯 class 方案没有这个陷阱，且**JS 挂了也照样看得见第一个页签**
         （服务端已经给它 .on）—— 换肤/降级都不会漏。
   ★ JS 只负责**改 class**，绝不写 style.display（同一个坑的另一半）。
   ★ postPanel / lockPanel / draftBar **不在页签里**（张总拍板）——
     那是主流程动作，藏起来会让人找不到。这里只管页签自己的样式。
   ══════════════════════════════════════════════════════════════════ */
.dtabs{margin-top:var(--sp-3)}
.dtabbar{display:flex;flex-wrap:wrap;gap:var(--sp-1);
  border-bottom:1px solid var(--line);margin-bottom:var(--sp-1)}
.dtab{background:none;border:1px solid transparent;border-bottom:none;
  border-radius:var(--r-2) var(--r-2) 0 0;padding:var(--sp-2) var(--sp-3);
  font-size:var(--fs-4);color:var(--ink-2);cursor:pointer;line-height:1.4}
.dtab:hover{background:var(--panel-2);color:var(--ink)}
.dtab.on{background:var(--panel);border-color:var(--line);
  color:var(--brand);font-weight:600;
  margin-bottom:-1px;padding-bottom:calc(var(--sp-2) + 1px)}
.tabpane{display:none}
.tabpane.on{display:block}
/* ★★ 页签里的表头**不吸顶** —— 这条是**真浏览器验收当场抓到的**：
   main.css 全局有一条 `thead th{position:sticky;top:52px}`（为长列表页写的），
   而详情页这些新表在页面很下面（top ≈ 650px，早已滚过 52px），
   于是表头一进视口就粘在 52px 处、**盖住了下面唯一那一行数据**
   （门禁全绿、innerText 也查得到，就是屏幕上什么都看不见 ——
   元素命中测试命中的是 `TH|行`，不是 TD）。
   ★ 为什么用 `!important`：要压掉的是**别处**（全局段）那条规则，
     不是本段自己的开关 —— 与上面 `.tabpane` 的纯 class 方案不冲突。
   ★ 单行数据的详情页页签不需要吸顶；表头跟着表格走才是对的。 */
.tabpane .bd thead th{position:static !important}
/* ★ 这里**故意不写** `.tabpane > .panel{margin-top:...}`：
   商品行/汇总那些面板的上边距是它们自己行内就有的（原来怎么排就还怎么排）——
   在页签里再叠一条 margin 规则，等于把"搬家"变成了"顺带改了排版"。 */
