:root{
  --bg:#f4f6f9; --panel:#ffffff; --line:#e3e8ef; --ink:#1f2937; --ink2:#64748b; --ink3:#94a3b8;
  --brand:#0f766e; --brand-d:#115e59; --brand-l:#ccfbf1;
  --warn:#b45309; --warn-bg:#fffbeb; --warn-line:#fde68a;
  --bad:#b91c1c;  --bad-bg:#fef2f2;  --bad-line:#fecaca;
  --ok:#15803d;   --ok-bg:#f0fdf4;   --ok-line:#bbf7d0;
  --r:8px; --shadow:0 1px 3px rgba(15,23,42,.06),0 1px 2px rgba(15,23,42,.04);
}
*{box-sizing:border-box}
html,body{margin:0;padding:0}
body{background:var(--bg);color:var(--ink);
  font:14px/1.6 "PingFang SC","Microsoft YaHei","Segoe UI",system-ui,sans-serif;
  -webkit-font-smoothing:antialiased}

/* ── 顶栏 ─────────────────────────────────────────────────────────────── */
.topbar{height:56px;background:#0f172a;color:#e2e8f0;display:flex;align-items:center;
  padding:0 20px;gap:16px;position:sticky;top:0;z-index:50}
.logo{font-size:16px;font-weight:700;letter-spacing:.5px;white-space:nowrap}
.logo b{color:#5eead4}
.spacer{flex:1}
.userbox{display:flex;align-items:center;gap:10px;font-size:13px}
.rolechip{background:#1e293b;border:1px solid #334155;border-radius:20px;padding:2px 10px;font-size:12px;color:#94a3b8}
.rolechip.admin{background:#134e4a;border-color:#0f766e;color:#5eead4}

/* ── 骨架 ─────────────────────────────────────────────────────────────── */
.shell{display:flex;min-height:calc(100vh - 56px)}
.side{width:196px;flex:0 0 196px;background:var(--panel);border-right:1px solid var(--line);padding:14px 0}
.side button{display:block;width:100%;text-align:left;border:0;background:none;cursor:pointer;
  padding:10px 18px;font:inherit;color:var(--ink2);border-left:3px solid transparent}
.side button:hover{background:#f8fafc;color:var(--ink)}
.side button.on{color:var(--brand);background:var(--brand-l);border-left-color:var(--brand);font-weight:600}
.side .grp{padding:12px 18px 4px;font-size:11px;color:var(--ink3);letter-spacing:1px}
.main{flex:1;padding:22px;min-width:0}
.wrap{max-width:1000px;margin:0 auto}

/* ── 卡片与排版 ───────────────────────────────────────────────────────── */
h1{font-size:20px;margin:0 0 4px}
h2{font-size:15px;margin:0 0 12px}
.sub{color:var(--ink2);font-size:13px;margin:0 0 18px}
.card{background:var(--panel);border:1px solid var(--line);border-radius:var(--r);
  padding:16px 18px;margin-bottom:16px;box-shadow:var(--shadow)}
.row{display:flex;gap:12px;flex-wrap:wrap}
.grid2{display:grid;grid-template-columns:1fr 1fr;gap:16px}
@media(max-width:900px){.grid2{grid-template-columns:1fr}}

/* KPI */
.kpis{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin-bottom:16px}
@media(max-width:900px){.kpis{grid-template-columns:repeat(2,1fr)}}
/* ★ 81 轮：卡密管理页是【5 个 KPI】，照原型必须一行五个 ——
   用 4 列网格会把「已作废」甩到第二行独自一个，看着像少画了东西。
   判据：一排 KPI 的个数由原型决定，不由"默认 4 列"决定。 */
.kpis.k5{grid-template-columns:repeat(5,1fr)}
@media(max-width:1200px){.kpis.k5{grid-template-columns:repeat(3,1fr)}}
@media(max-width:700px){.kpis.k5{grid-template-columns:repeat(2,1fr)}}
.kpi{background:var(--panel);border:1px solid var(--line);border-radius:var(--r);padding:14px 16px;box-shadow:var(--shadow)}
.kpi .k{font-size:12px;color:var(--ink2)}
.kpi .v{font-size:24px;font-weight:700;margin-top:2px;letter-spacing:-.5px}
.kpi .d{font-size:12px;color:var(--ink3);margin-top:2px}

/* 表 */
table{width:100%;border-collapse:collapse;font-size:13px}
th,td{padding:9px 10px;border-bottom:1px solid var(--line);text-align:left;vertical-align:top}
th{color:var(--ink2);font-weight:600;background:#f8fafc;font-size:12px;white-space:nowrap}
tbody tr:hover{background:#fafbfc}
td.nowrap,th.nowrap{white-space:nowrap}
.num{text-align:right;font-variant-numeric:tabular-nums}

/* 表单 */
label{display:block;font-size:12px;color:var(--ink2);margin:0 0 4px}
input[type=text],input[type=password],input[type=number],select,textarea{
  width:100%;padding:7px 10px;border:1px solid var(--line);border-radius:6px;font:inherit;
  background:#fff;color:var(--ink)}
input:focus,select:focus,textarea:focus{outline:2px solid var(--brand-l);border-color:var(--brand)}
textarea{resize:vertical;min-height:70px;font-family:ui-monospace,Consolas,monospace;font-size:12px}
.field{margin-bottom:12px}
.hint{font-size:12px;color:var(--ink3);margin-top:4px}

/* 按钮 */
.btn{border:1px solid var(--line);background:#fff;color:var(--ink);border-radius:6px;
  padding:7px 14px;font:inherit;cursor:pointer}
.btn:hover{background:#f8fafc}
.btn.pri{background:var(--brand);border-color:var(--brand);color:#fff}
.btn.pri:hover{background:var(--brand-d)}
.btn.dan{background:#fff;border-color:var(--bad-line);color:var(--bad)}
.btn.dan:hover{background:var(--bad-bg)}
.btn.sm{padding:4px 9px;font-size:12px;border-radius:5px}
.btn:disabled{opacity:.45;cursor:not-allowed}

/* 徽标 */
.tag{display:inline-block;padding:1px 8px;border-radius:20px;font-size:11px;line-height:18px;white-space:nowrap}
.tag.g{background:var(--ok-bg);color:var(--ok);border:1px solid var(--ok-line)}
.tag.y{background:var(--warn-bg);color:var(--warn);border:1px solid var(--warn-line)}
.tag.r{background:var(--bad-bg);color:var(--bad);border:1px solid var(--bad-line)}
.tag.n{background:#f1f5f9;color:var(--ink2);border:1px solid var(--line)}
/* ★ 81 轮照原型 ST_TAG 补的三色（待发卡蓝 / 待平台审核橙 / 已作废灰）——
   原来的 .tag.r（红）在代理端不合适：已作废是【按进货价退回余额】的正常收尾，
   不是事故，标成红色会让人以为出事了。原型用的是灰。 */
.tag.b{background:#eff6ff;color:#1d4ed8;border:1px solid #bfdbfe}
.tag.o{background:#fff7ed;color:#c2410c;border:1px solid #fed7aa}
.tag.gray{background:#f3f4f6;color:#6b7280;border:1px solid #e5e7eb}

/* 提示条 */
.alert{border-radius:6px;padding:9px 12px;font-size:12.5px;margin-bottom:12px;line-height:1.7}
.alert.warn{background:var(--warn-bg);border:1px solid var(--warn-line);color:#92400e}
.alert.bad{background:var(--bad-bg);border:1px solid var(--bad-line);color:#991b1b}
.alert.ok{background:var(--ok-bg);border:1px solid var(--ok-line);color:#14532d}
.alert.info{background:#eff6ff;border:1px solid #bfdbfe;color:#1e40af}
.alert b{font-weight:700}
.hard{background:#fffbeb;border:1px solid #fde68a;border-radius:6px;padding:9px 12px;font-size:12.5px;color:#92400e}

.mono{font-family:ui-monospace,Consolas,monospace;font-size:12px}
.muted{color:var(--ink3)}
.empty{padding:28px;text-align:center;color:var(--ink3);font-size:13px}

/* ★ 卡片内的三件套（照原型）：h3 标题 / .ch 一句说明 / .mini 脚注。
   代理端同样适用「只做事不解释」——.ch 写的都是【这一块怎么用】，
   不是【平台怎么算成本】那种解释性文字。 */
.card h3{font-size:14px;margin:0 0 6px}
.ch{color:var(--ink2);font-size:12.5px;margin:0 0 12px;line-height:1.7}
.mini{color:var(--ink3);font-size:12px;line-height:1.8;margin-top:10px}
.mini b{color:var(--ink2)}
.row .lb{flex:0 0 88px;color:var(--ink2);font-size:12.5px;padding-top:8px}
.calc{background:#f9fafb;border:1px solid var(--line);border-radius:6px;
  padding:10px 12px;margin:10px 0;font-size:12.5px;line-height:1.9;white-space:pre-line}
.calc .tot{color:var(--bad);font-weight:700}

/* 登录页 */
.loginbox{max-width:340px;margin:12vh auto;background:var(--panel);border:1px solid var(--line);
  border-radius:10px;padding:26px;box-shadow:var(--shadow)}
.loginbox h1{font-size:18px;margin-bottom:2px}
.loginbox .sub{margin-bottom:18px}

/* 二维码 */
.qrbox{display:flex;gap:18px;align-items:flex-start}
.qrbox canvas,#qrimg{background:#fff;border:1px solid var(--line);border-radius:6px;padding:6px}

.toast{position:fixed;right:18px;bottom:18px;background:#0f172a;color:#fff;padding:10px 16px;
  border-radius:8px;font-size:13px;z-index:99;box-shadow:0 6px 20px rgba(0,0,0,.2);opacity:0;
  transition:opacity .18s;pointer-events:none}
.toast.show{opacity:1}
.money-in{color:#b91c1c;font-weight:600}
.money-out{color:#15803d;font-weight:600}
.tablebox{overflow:auto}
.toolbar{display:flex;gap:10px;align-items:flex-end;flex-wrap:wrap}
.toolbar .field{min-width:180px;flex:1}
.toolbar .field:last-child{flex:0 0 auto;min-width:0}

/* ★ 81 轮：卡密管理页照原型 tabCodes 补的三件套 —— 状态标签条 / 批量条 / 行内文字链。
   原型里这三样是这一页的骨架：① 状态标签是「点一下只看这一类」的筛选入口，
   ② 批量条只在勾选后出现，③ 文字链（复制/详情/作废退款）是行内唯一操作位。
   尺寸与配色逐字照原型（#4338ca 主色 / #eef2ff 底 / #c7d2fe 边）。 */
.stTabs{display:flex;flex-wrap:wrap;gap:8px;margin:2px 0 6px}
.stTab{border:1px solid var(--line);background:#fff;border-radius:16px;padding:4px 12px;
  font-size:12px;color:#4b5563;cursor:pointer}
.stTab:hover{border-color:#4338ca;color:#4338ca}
.stTab.on{background:#4338ca;border-color:#4338ca;color:#fff;font-weight:600}
.stTab b{font-size:11.5px;opacity:.85;margin-left:2px}
.bulk{display:flex;align-items:center;gap:12px;flex-wrap:wrap;background:#eef2ff;
  border:1px solid #c7d2fe;border-radius:6px;padding:8px 12px;margin-bottom:10px}
.lab{color:#4338ca;cursor:pointer;font-size:11.5px;margin-left:4px}
.lab2{color:#4338ca;cursor:pointer;font-size:12px}
.lab2:hover,.lab:hover{text-decoration:underline}
/* ★ 81 轮：卡密清单是 10 列，容器只有 1000px —— 强行 width:100% 会把每一列挤到
   放不下内容，最后「操作」列直接看不见（不是被裁，是被压没了）。
   正解是给表一个最小宽度，让 .tablebox 横向滚动：【宁可横向滚，不可丢列】。 */
#allCardsBody{white-space:normal}
.card .tablebox table.wide{min-width:1080px}
.filterbar{display:flex;gap:8px;flex-wrap:wrap;align-items:center}
.filterbar input,.filterbar select{width:auto}
.filterbar input[type=text]{flex:1;min-width:220px}
#qrimg:empty{display:none}
#qrimg svg{display:block;max-width:220px;height:auto}

/* ══════════════════════════════════════════════════════════════════════════
   83 轮：财务页照原型补的五块所需的样式（零依赖，不引 CDN）

   ★ 为什么图自己做 CSS 柱图、而不是等 echarts：
     原型里 echarts 是"优先用、断网降级"的角色，而 83 轮这一版的判断是
     **直接不引 CDN** —— 渠道后台是给代理用的，代理的网不一定好；
     引一个 CDN 只为了画 14 根柱子，代价是断网时整页脚本可能被拖死。
     （后台那边已经踩过这个坑：CDN 同步加载失败会中断后面全部脚本。）
   ══════════════════════════════════════════════════════════════════════════ */

/* 可用余额大号块（原型 74 轮定案）—— 独立成块 + 字号显著大于普通 KPI */
.bigbal{background:linear-gradient(180deg,#f8fafc,#fff);border:1px solid var(--line);
  border-radius:var(--r);padding:18px 20px;margin-bottom:16px;box-shadow:var(--shadow)}
.bigbal .lb{font-size:13px;color:var(--ink2)}
.bigbal .lb .tip{font-size:11.5px;color:var(--ink3);margin-left:6px}
.bigbal .amt{font-size:38px;font-weight:800;letter-spacing:-1px;margin:4px 0 2px}
.bigbal .sub{font-size:12.5px;color:var(--ink3);line-height:1.8;margin-bottom:10px}
.bigbal .sub b{color:#b45309}
.bigbal.ok .amt{color:#15803d}
.bigbal.low{border-color:#fcd34d;background:linear-gradient(180deg,#fffbeb,#fff)}
.bigbal.low .amt{color:#b45309}
.bigbal.zero{border-color:#fca5a5;background:linear-gradient(180deg,#fef2f2,#fff)}
.bigbal.zero .amt{color:#b91c1c}

/* 充值金额快捷档（原型是可按的 ¥500/¥1000/… 小方块） */
.amt-chip{display:inline-block;border:1px solid var(--line);background:#fff;border-radius:6px;
  padding:6px 14px;font-size:12.5px;color:var(--ink2);cursor:pointer;user-select:none}
.amt-chip:hover{border-color:#4338ca;color:#4338ca}
.amt-chip.on{background:#eef2ff;border-color:#c7d2fe;color:#4338ca;font-weight:600}
.paybox{border:1px solid #c7d2fe;background:#eef2ff;border-radius:6px;padding:8px 14px}
.paybox b{color:#4338ca;font-size:12.5px}
.paybox span{display:block;font-size:11.5px;color:var(--ink3);margin-top:2px}

/* 14 天柱图：两根并排（充值/支出）+ 单根（估算收入） */
/* ★★ 84 轮：`.fchart` 是**宿主**，它里面同时装着 `.fbars` 和 `.faxis` 两个块。
   原先写成 `display:flex`，于是这两个块成了横向兄弟 ——
   `.faxis` 被压成 0 宽，里面绝对定位的刻度全按 0 宽算，7 个日期叠成一坨。
   **症状是"刻度挤在右端"，看起来像 left 百分比算错了，其实是容器布局错了。**
   正解：宿主必须是纵向容器（柱子占满剩余高度，刻度在下面一行）。 */
.fchart{height:170px;display:flex;flex-direction:column}
.fchart .fbars{flex:1;min-height:0}
/* ★ 84 轮：柱子之间的间距用 padding 而不是 gap 实现。
   原因：x 轴刻度按「柱子中心 = (i+0.5)/n」摆位，这个等式只有在
   每列**等宽且占满 100%/n** 时才成立；`gap` 会把 3px 从容器宽里扣掉，
   列宽变成 (100%−39px)/14，刻度就会逐根累积偏移（第 7 根偏半根柱子）。
   用 padding 做视觉间距，列宽仍是严格的 1/n，两边就永远对得上。 */
.fbars{display:flex;align-items:flex-end;height:100%;width:100%}
.fbars i{flex:1;margin:0 1.5px;background:#6366f1;border-radius:2px 2px 0 0;min-height:2px;display:block}
.fbars i.o{background:#f59e0b}
.fbars i.g{background:#10b981}
/* ★ 84 轮：刻度从「首尾两个」改成「每 2 天一个」，所以必须能按百分比摆位。
   用相对定位容器 + 绝对定位刻度，刻度中心对齐柱子中心（left = (i+0.5)/n）。
   ★ 为什么不用 flex 均分：柱子是 14 根等宽的，flex 均分出来的刻度会整体
     偏移半根柱子的宽度，日期看着像对错了柱子。 */
.faxis{position:relative;height:14px;font-size:10.5px;color:var(--ink3);margin-top:4px}
.faxis span{position:absolute;transform:translateX(-50%);white-space:nowrap}
.legend{font-size:11.5px;color:var(--ink3);margin-top:8px}

/* ★ 83 轮：财务页「③ 资金流水」的类型筛选下拉。
   不加这条它会撑满整行（select 默认 width:auto 在 flex 容器里退化成 100%），
   而「全部」两个字配一条 1000px 宽的下拉框，看起来像表单没做完。 */
#p-fin .row select{width:auto;min-width:140px}
#p-fin .tablebox table{white-space:nowrap}
#finReconRows .lab2{font-size:12px}


@media(max-width:700px){.side{width:132px;flex-basis:132px}.main{padding:14px}.topbar{padding:0 12px}.logo{font-size:14px}.userbox{gap:6px}}

/* ═══ 87 轮：弹窗（代理端此前没有任何弹窗机制，这里从运营后台搬同一套）═══
   ★ 为什么不用 alert / prompt：
     ① 密码输入必须走 <input type="password">，prompt 会明文回显在历史里；
     ② alert 无法做"旧密码 / 新密码 / 确认新密码"三行表单。
   ★ 样式与运营后台保持同一套（.mask / .dlg / .dlg-x / .dlg-bd），
     两端长得一样，运营同事教一遍就会用。 */
.mask{position:fixed;inset:0;background:rgba(15,23,42,.42);z-index:80;display:none;
  align-items:flex-start;justify-content:center;padding:52px 16px;overflow:auto}
.mask.on{display:flex}
.dlg{background:var(--panel);border:1px solid var(--line);border-radius:12px;
  box-shadow:0 20px 60px rgba(15,23,42,.28);width:100%;max-width:520px}
.dlg-hd{display:flex;align-items:center;justify-content:space-between;
  padding:14px 18px;border-bottom:1px solid var(--line);font-size:14px}
.dlg-x{cursor:pointer;color:var(--ink2);font-size:15px;line-height:1;padding:4px 6px;border-radius:6px}
.dlg-x:hover{background:#f1f5f9;color:var(--ink)}
.dlg-bd{padding:16px 18px;max-height:calc(100vh - 200px);overflow:auto}
.dlg-ft{padding:12px 18px;border-top:1px solid var(--line);display:flex;gap:8px;justify-content:flex-end}
.pwfield{margin-bottom:12px}
.pwfield label{display:block;font-size:12px;color:var(--ink2);margin-bottom:4px}
.pwfield input{width:100%;box-sizing:border-box;padding:7px 10px;border:1px solid var(--line);
  border-radius:6px;font-size:13px}
.pwtip{font-size:12px;color:var(--ink2);line-height:1.7;margin:10px 0 0}
.pwerr{font-size:12px;color:var(--bad);margin-top:8px;min-height:16px}
