/* ============================================================================
 * 观客来 · 应用台（一期自研）· 样式层
 * ----------------------------------------------------------------------------
 * ★ 视觉对齐「新控台」：
 *   深蓝渐变侧栏（#0A2540→#113F7C）+ 白顶栏 + 浅灰内容底 + 白卡片。
 *   色值单一真源 = 控台 `gkl-web/src/theme.css` 的 brand 档令牌（手抄在此，两边同值）：
 *     主色 #1668DC ｜ 悬停 #0E5BC4 ｜ 深蓝 #0A2540 ｜ 更深蓝 #061B30
 *     页面底 #F5F7FA ｜ 卡片 #FFF ｜ 描边 #E4E7EC
 *     主文 #1D2939 ｜ 次文 #667085 ｜ 弱文 #98A2B3
 *   移动端（m.supay.tech）主色同为 #1668DC ⇒ 三端一套色。
 *
 * ★★ 417 批（大人 2026-10-08）新增三件事：
 *   ① 深浅色外观（`<html data-theme="light|dark">`，令牌化，`index.html` 内联防闪）
 *   ② 侧栏收缩（220px ↔ 64px 图标条，偏好落 localStorage）
 *   ③ 侧栏背景图案（28px 网格向下渐隐 + 双光晕 —— 与登录页左栏同一套图案语言）
 *   ★ 登录页左栏文案与深色图案取自**原登录页**（控台 `LoginView.vue` 的左卡）。
 * 🔴 零依赖：不引任何外部 CSS/字体库，纯手写。
 * ==========================================================================*/

:root {
  /* —— 687n：品牌色阶。原散落 6 个近似蓝（#1668DC/#1677ff/#4C8FF0/#2E7BE6/#3B82F6/#5aa2ff）
     全部归一到下面这三个令牌，正文一律引变量。 —— */
  --brand: #1668DC;          /* 主品牌蓝（唯一真源） */
  /* ★ 722：品牌色底上的文字色。深色主题下品牌底仍是深蓝 ⇒ 文字恒白，
     故本令牌**不随主题变化**（`html[data-theme='dark']` 里无需覆盖）。 */
  --on-brand: #fff;
  --brand-hover: #0E5BC4;
  --brand-soft: #EDF3FC;
  --brand-lite: #4C8FF0;     /* 品牌浅蓝：渐变尾 / 侧栏强调 / 图例 */
  --brand-on-dark: var(--brand-on-dark);  /* 深蓝底上的浅蓝字（登录页左栏专用） */
  --navy: #0A2540;
  --navy-deep: #061B30;
  --bg: #F5F7FA;
  --card: #ffffff;
  --line: #E4E7EC;
  --line-soft: #F2F4F7;
  /* ★ r772：「纸张白」—— 二维码底色。🔴 **恒白、不跟随主题**：
     深色主题下若把码底也变深，码就扫不出来（相机按亮度找定位点）。
     这是**功能要求**不是配色，所以单独给一个令牌，别处也不该用它做背景。 */
  --qr-paper: #ffffff;
  /* —— 687n 可读性：文字三级灰全部 ≥ WCAG AA 4.5:1（对白底 / #F5F7FA 底）——
     原 --text-mute #98A2B3 仅 2.6:1（不达标）⇒ 调深；为保住「主/次/弱」三级层次，
     次文同步调深，避免弱文与次文挤成同一亮度。 */
  --text: #1D2939;           /* 主文 · 12.9:1 */
  --text-dim: #4B5563;       /* 次文 · 7.6:1 */
  --text-mute: #667085;      /* 弱文 · 5.0:1（原 #98A2B3 = 2.6:1 ✗） */
  --ok: #1D9E75;
  --ok-soft: #ECF8F3;
  --warn: #B45309;
  --warn-soft: #FDF6E9;
  --bad: #C8222B;
  --bad-hover: #A81C24;
  --bad-soft: #FDF0F0;
  /* ★★★ 5286（大人令 2026-10-16）：**多分辨率适配缩放层**
     ----------------------------------------------------------------------------
     病症（无头 Edge 四档实测，改前一览）：
       视口 1920 → 内容 1700 / 卡片 1656 / 表格 1614 / 正文 14px / 行高 45px
       视口 3840 → 内容 3620 / 卡片 3576 / 表格 3534 / 正文 14px / 行高 45px  ← 🔴
     即：字号 / 行高 / 侧栏**四档完全不变**，而卡片与表格被**无限拉宽**
     ⇒ 4K 下 14px 正文视觉等效 1080 屏上的 7px，表格单行跨 3500px（≈250 字符）
     ⇒ 「小、稀、散」—— 这正是「有的分辨率看起来不舒服、没有高级感」的真根因。
     做法：把「字号 / 关键间距 / 大圆角」抽成 `基准 × 缩放因子`，只在**根令牌层**改：
       --ui-s    字号与间距缩放（1920:1 · 2048:1.06 · 2560:1.13 · 3200:1.22 · 3840:1.3 · 5120:1.4）
       --ui-r    大圆角缩放（同上六档：1 · 1.06 · 1.12 · 1.18 · 1.24 · 1.3）
       --pg-max  内容区舒适上限（超宽屏居中；留白即高级感）
     🔴 **档位按「视口宽度」而非物理分辨率** —— 浏览器分不清「4K@150%」与「2.5K@100%」
        （两者视口都是 2560 CSS px）。见文件末尾 `5286` 媒体查询块。
     🔴 小圆角（2/3/4/6/7px）与 1px 细线**不参与缩放**（等比放大会显笨）。
     🔴 `--ui-s: 1` 时所有 calc 恒等于原值 ⇒ 1080p 及以下**观感零变化**（可逐像素回归验证）。 */
  --ui-s: 1;
  --ui-r: 1;
  --pg-max: none;

  /* —— 687n：圆角阶梯（原 13 种取值 → 令牌；正文不再写 px）——
     ★ 5286：8px 及以上的「大圆角」随 --ui-r 缩放；2/3/4/6/7px 小圆角保持原值。 */
  --r-2: 2px; --r-3: 3px; --r-4: 4px; --r-6: 6px; --r-7: 7px;
  --r-8: calc(8px * var(--ui-r)); --r-9: calc(9px * var(--ui-r));
  --r-10: calc(10px * var(--ui-r)); --r-11: calc(11px * var(--ui-r));
  --r-12: calc(12px * var(--ui-r)); --r-20: calc(20px * var(--ui-r));
  --r-26: calc(26px * var(--ui-r)); --r-full: 999px;
  --radius: var(--r-12);     /* 旧名保留，等于 12px */
  --radius-lg: calc(16px * var(--ui-r));
  /* —— 687n：字号阶梯（原 20 种取值 → 令牌；正文不再写 px）——
     ★ 5286：全部 = 基准 × --ui-s ⇒ 改一处、202 处引用点同时生效。 */
  --fs-10: calc(10px * var(--ui-s)); --fs-11: calc(11px * var(--ui-s)); --fs-11-5: calc(11.5px * var(--ui-s));
  --fs-12: calc(12px * var(--ui-s)); --fs-12-5: calc(12.5px * var(--ui-s));
  --fs-13: calc(13px * var(--ui-s)); --fs-13-5: calc(13.5px * var(--ui-s));
  --fs-14: calc(14px * var(--ui-s)); --fs-14-5: calc(14.5px * var(--ui-s)); --fs-15: calc(15px * var(--ui-s));
  --fs-16: calc(16px * var(--ui-s)); --fs-17: calc(17px * var(--ui-s)); --fs-18: calc(18px * var(--ui-s));
  --fs-19: calc(19px * var(--ui-s)); --fs-20: calc(20px * var(--ui-s));
  --fs-21: calc(21px * var(--ui-s)); --fs-23: calc(23px * var(--ui-s)); --fs-25: calc(25px * var(--ui-s));
  --fs-26: calc(26px * var(--ui-s)); --fs-28: calc(28px * var(--ui-s));
  /* —— 5286：间距阶梯（padding / gap / margin 用；命名 = 基准像素值）——
     ★ 只给「骨架与高频组件」用（主壳 / 卡片 / 表格 / 工具条 / 按钮 / 输入框 / 弹层）；
       细线与微小尺寸（1/2px）不参与。漏改处 = 不缩放，**不会破版**。 */
  --sp-3: calc(3px * var(--ui-s)); --sp-4: calc(4px * var(--ui-s)); --sp-5: calc(5px * var(--ui-s));
  --sp-6: calc(6px * var(--ui-s)); --sp-7: calc(7px * var(--ui-s)); --sp-8: calc(8px * var(--ui-s));
  --sp-9: calc(9px * var(--ui-s)); --sp-10: calc(10px * var(--ui-s)); --sp-11: calc(11px * var(--ui-s));
  --sp-12: calc(12px * var(--ui-s)); --sp-13: calc(13px * var(--ui-s)); --sp-14: calc(14px * var(--ui-s));
  --sp-16: calc(16px * var(--ui-s)); --sp-18: calc(18px * var(--ui-s)); --sp-20: calc(20px * var(--ui-s));
  --sp-22: calc(22px * var(--ui-s)); --sp-24: calc(24px * var(--ui-s)); --sp-28: calc(28px * var(--ui-s));
  --sp-32: calc(32px * var(--ui-s)); --sp-34: calc(34px * var(--ui-s));
  --sp-40: calc(40px * var(--ui-s)); --sp-44: calc(44px * var(--ui-s));
  --elev-1: 0 1px 2px rgba(0,0,0,.04), 0 1px 3px rgba(0,0,0,.05);
  --elev-2: 0 2px 6px rgba(0,0,0,.07), 0 8px 20px rgba(0,0,0,.08);
  /* 侧栏 */
  --side-bg: radial-gradient(150px 200px at 92% 4%, rgba(200,34,43,.20), transparent 72%),
             radial-gradient(340px 460px at 0% 98%, rgba(22,104,220,.42), transparent 72%),
             linear-gradient(135deg, #0a2540 0%, #0e3260 60%, #113f7c 100%);
  --side-line: rgba(255,255,255,.10);
  --side-grid: rgba(255,255,255,.055);
  --side-fg: rgba(255,255,255,.80);
  --side-fg-dim: rgba(255,255,255,.55);
  --side-fg-mute: rgba(255,255,255,.38);
  --side-on: rgba(22,104,220,.26);
  --side-hover: rgba(255,255,255,.08);
  --side-accent: var(--brand-lite);   /* 687n：与品牌浅蓝同一真源 */
  /* ★ 5286：侧栏宽度随 --ui-s 缩放 —— 否则字号放大后侧栏内容反而变挤 */
  --side-w: calc(220px * var(--ui-s));
  --side-w-collapsed: calc(64px * var(--ui-s));
}

/* ---------- 深色外观（417）：近中性灰黑，侧栏比内容**略暗**、靠色差分界 ---------- */
html[data-theme='dark'] {
  --brand: #4B93F5;
  --brand-hover: #3A84EA;
  --brand-soft: #17273C;
  --bg: #101317;
  --card: #171B21;
  --line: #262C35;
  --line-soft: #1E242C;
  --text: #E6EAF0;
  --text-dim: #98A2B3;      /* 6.7:1 ✓ */
  --text-mute: #7E8798;     /* 687n：原 #6B7684 仅 3.7:1 ⇒ 调亮至 4.8:1 ✓ */
  --ok: #48C79B;
  --ok-soft: #14291F;
  --warn: #E0A44A;
  --warn-soft: #2B2214;
  --bad: #F2727C;
  --bad-soft: #2C1A1D;
  --elev-1: 0 1px 2px rgba(0,0,0,.4);
  --elev-2: 0 2px 8px rgba(0,0,0,.45), 0 12px 28px rgba(0,0,0,.4);
  --side-bg: radial-gradient(320px 420px at 0% 98%, rgba(24,60,110,.35), transparent 72%),
             linear-gradient(160deg, #0A0D11 0%, #0B0F14 60%, #0C1218 100%);
  --side-line: rgba(255,255,255,.07);
  --side-grid: rgba(255,255,255,.035);
  --side-fg: rgba(255,255,255,.76);
  --side-fg-dim: rgba(255,255,255,.50);
  --side-fg-mute: rgba(255,255,255,.32);
  --side-on: rgba(75,147,245,.22);
  --side-hover: rgba(255,255,255,.06);
  --side-accent: #4B93F5;
}

/* ============================================================ r948 · 侧栏配色：「WorkBuddy 浅色」
   ★★ 大人令 2026-10-27「左侧栏 增加一个 WorkBuddy 左侧栏的配色」= **增加一套**，不是替换。
   开关 = `<html data-side="wb">`（唯一真源，localStorage.gkl_app_sidetheme 持久化）。
   🔴 与 `data-theme`（主区深浅色）**正交**：这里只重新定义 `--side-*` 一族令牌，
      主区令牌一个都不动 ⇒ 深色主区 + 浅色侧栏也能正常组合。
   🔴 必须写在 `html[data-theme='dark']` **之后**：两者特异性相同（都是 html[attr]），
      靠源码顺序取胜 ⇒ 删/挪本块会让深色主题下的浅色侧栏失效。
   取自 WorkBuddy 客户端实际观感：白底、近黑字、无渐变无图案、选中态是浅灰圆角块、
   左侧无彩色指示条、分组标题是浅灰小字。 */
html[data-side='wb'] {
  /* ★ r949（2026-10-27 大人指出「这个左边栏和 workbuddy 左边栏的颜色不一样」）：
     实拍 WorkBuddy 客户端侧栏取色 ⇒ 底色是**浅灰 #F2F2F2**，不是纯白。
     原来写 #FFFFFF 时侧栏与纯白主区**同色无层次**，看起来就是「没做到一样」。
     取色口径：截图 795×1896，左栏 x 0~348 / WB 栏 x 350~795，
     两处空白带众数均为 #F2F2F2（6.7万+11.5万像素），选中块众数 #EBEBEB。 */
  --side-bg: #F2F2F2;                /* 浅灰底（WB 实拍值）· 与纯白主区形成层次 */
  --side-line: #E5E5E5;
  --side-grid: transparent;          /* 关掉 28px 网格图案（WorkBuddy 侧栏是纯色） */
  --side-fg: #181818;                /* 常态菜单字：WB 实拍 #181818（原 #333 偏灰） */
  --side-fg-dim: #808080;
  --side-fg-mute: #9E9E9E;           /* 分组标题（与 WB 同灰阶） */
  --side-on: #EBEBEB;                /* 选中态：WB 实拍 #EBEBEB 浅灰圆角块 */
  --side-hover: #EDEDED;             /* 悬停：在 #F2F2F2 底上是**压暗**而非提亮 */
  --side-accent: transparent;        /* 无左侧彩色指示条 */
}
/* 品牌区文字：深色主题下原本恒白（`.side-brand .txt b { color:#fff }`）⇒ 这里必须反色 */
html[data-side='wb'] .side-brand .txt b { color: #181818; }
html[data-side='wb'] .side-brand .txt i { color: #808080; }
/* 浅灰侧栏 + 白色主区分离线（深色主区下也是它兜底） */
html[data-side='wb'] .side { border-right: 1px solid var(--side-line); }
/* 网格图案层直接不生成（WorkBuddy 侧栏是纯色；留着透明层只是白占一个合成层） */
html[data-side='wb'] .side::after { display: none; }
/* 选中项：原本 `color:#fff` 硬编码白字 + 伪元素指示条 ⇒ 一并改掉 */
html[data-side='wb'] .side-nav button.nav.on { color: #181818; font-weight: 600; }
html[data-side='wb'] .side-nav button.nav.on::before { display: none; }
html[data-side='wb'] .side-nav .grp { letter-spacing: .5px; text-transform: none; }
/* ============================================================ r954 · 侧栏三色：第三档「纯黑」
   ★★ 大人令 2026-10-27「这个开关应该三种颜色切换 浅色 经典深色 还有深色背景的黑色」。
   🔴 事实前提：**三套配色早就存在**（默认蓝黑渐变 / `data-theme='dark'` 近黑 / `data-side='wb'` 浅灰），
      但「近黑」那套当时挂在**主区深色主题**上 ⇒ 开关只有两态可切。
      本档把「黑」从 `data-theme` 里**抽出来**，改为纯侧栏令牌 ⇒ 主区是浅色时侧栏也能纯黑，
      三档互相独立（`data-side` 只重定义 `--side-*`，主区令牌一个不碰）。
   🔴 必须写在 `html[data-side='wb']` **之后**：两者特异性相同（html[attr]），靠源码顺序取胜；
      同时它也要压过 `html[data-theme='dark']` 的侧栏令牌 ⇒ 放在两块的后面。
   🔴 纯黑 (#000) 而非近黑：大人要的就是「深色背景的黑色」，不掺蓝调渐变。
      纯黑底上 rgba 白字会显得更亮 ⇒ 常态字提到 .86、次要字 .58，保证对比度仍够。 */
html[data-side='black'] {
  --side-bg: #000000;
  --side-line: rgba(255,255,255,.12);
  --side-grid: transparent;          /* 纯黑不铺 28px 网格 */
  --side-fg: rgba(255,255,255,.86);
  --side-fg-dim: rgba(255,255,255,.58);
  --side-fg-mute: rgba(255,255,255,.40);
  --side-on: rgba(255,255,255,.13);  /* 选中态：纯黑底上用白色蒙层，不用蓝色（去掉品牌色偏） */
  --side-hover: rgba(255,255,255,.07);
  --side-accent: var(--brand-lite);
}
html[data-side='black'] .side { border-right: 1px solid var(--side-line); }
html[data-side='black'] .side::after { display: none; }
html[data-side='black'] .side-brand .txt b { color: #FFFFFF; }
html[data-side='black'] .side-brand .txt i { color: rgba(255,255,255,.58); }

/* 顶栏那个「侧栏配色」按钮：开着时给个视觉标识 */
button.icon-btn.is-on { color: var(--brand); background: var(--brand-soft); }

* { box-sizing: border-box; }

html, body { height: 100%; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  /* ★ 5286：字号走令牌（原为硬编码 14px）—— 拆开 font 简写，便于 --ui-s 生效 */
  font-size: var(--fs-14);
  line-height: 1.55;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
        "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  transition: background .18s, color .18s;
}
h1, h2, h3, h4 { margin: 0; font-weight: 600; }
a { color: var(--brand); text-decoration: none; }
a:hover { text-decoration: underline; }
code { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: var(--fs-12-5); }
[hidden] { display: none !important; }

/* ============================================================ 通用控件 */
button {
  font: inherit; cursor: pointer; border: 1px solid var(--line);
  background: var(--card); color: var(--text); border-radius: var(--r-8); padding: var(--sp-7) var(--sp-14);
  transition: background .15s, border-color .15s, color .15s;
}
button:hover:not(:disabled) { border-color: var(--brand); background: var(--brand-soft); }
button:disabled { opacity: .5; cursor: not-allowed; }
button.primary { background: var(--brand); border-color: var(--brand); color: #fff; }
button.primary:hover:not(:disabled) { background: var(--brand-hover); border-color: var(--brand-hover); color: #fff; }
button.block { width: 100%; padding: var(--sp-10) var(--sp-14); font-size: var(--fs-15); margin-top: var(--sp-6); }
button.mini { padding: var(--sp-4) var(--sp-10); font-size: var(--fs-12-5); border-radius: var(--r-6); }
button.link { border: 0; background: none; color: var(--brand); padding: 2px 4px; }
button.link:hover { background: none; text-decoration: underline; }
/* 687n：danger 原来在文件里定义了**两份**（此处 + 后半段「终端表单」块内），
   后者把前者覆盖成实心红；现合并为**唯一一份**（实心红底白字 = 危险操作的规范样式）。 */
button.danger { background: var(--bad); border-color: var(--bad); color: #fff; }
button.danger:hover:not(:disabled) { background: var(--bad-hover); border-color: var(--bad-hover); color: #fff; }

/* 图标按钮（顶栏：外观切换 / 侧栏收起） */
button.icon-btn {
  width: 32px; height: 32px; padding: 0; flex: none; display: grid; place-items: center;
  border-radius: var(--r-8); color: var(--text-dim);
}
button.icon-btn svg { width: 18px; height: 18px; display: block; }
button.icon-btn:hover:not(:disabled) { color: var(--brand); border-color: var(--brand); background: var(--brand-soft); }

input, select, textarea {
  font: inherit; width: 100%; padding: var(--sp-8) var(--sp-11); border: 1px solid var(--line);
  border-radius: var(--r-8); background: var(--card); color: var(--text); outline: none;
  transition: border-color .15s, box-shadow .15s;
}
textarea { min-height: 76px; resize: vertical; font-size: var(--fs-12-5);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
input:focus, select:focus, textarea:focus { border-color: var(--brand); box-shadow: 0 0 0 3px rgba(22,104,220,.14); }
input:disabled, select:disabled, textarea:disabled { background: var(--line-soft); color: var(--text-mute); }
input::placeholder, textarea::placeholder { color: var(--text-mute); }

label.fld { display: block; margin: var(--sp-12) 0 var(--sp-4); font-size: var(--fs-13); color: var(--text-dim); }
label.fld input, label.fld select, label.fld textarea { margin-top: var(--sp-6); }

/* 「标签在上、控件在下」的横排字段（搜索区 / 生成区通用） */
.fi { margin-top: var(--sp-12); }
.fi > span { display: block; font-size: var(--fs-12-5); color: var(--text-dim); margin-bottom: var(--sp-6); }

.badge {
  display: inline-block; padding: 1px 8px; border-radius: var(--r-full);
  font-size: var(--fs-12); line-height: 18px; border: 1px solid transparent; white-space: nowrap;
}
.badge.b-ok   { background: var(--ok-soft);   color: var(--ok);   border-color: rgba(29,158,117,.28); }
.badge.b-warn { background: var(--warn-soft); color: var(--warn); border-color: rgba(180,83,9,.26); }
.badge.b-bad  { background: var(--bad-soft);  color: var(--bad);  border-color: rgba(200,34,43,.26); }
.badge.b-info { background: var(--brand-soft);color: var(--brand);border-color: rgba(22,104,220,.26); }
.badge.b-mute { background: var(--line-soft); color: var(--text-dim); border-color: var(--line); }

/* ★ 755：商户列表「平台母户 / 母户简称」角标
   · 母户用品牌深蓝实心 —— 「我方以平台身份入网」是个身份，不是一个状态，
     所以用实心而不是浅底，和「齐备 / 缺号」那类状态角标天然分层。
   · 子户用中性描边 —— 它显示的是一层归属信息，不该和母户抢同一个视觉权重。 */
.badge.b-parent { background: var(--navy); color: #fff; border-color: var(--navy); font-weight: 600; }
.badge.b-child  { background: var(--line-soft); color: var(--text-dim); border-color: var(--line); }
/* 角标容器：竖向排在商户名称下方；`:empty` 兜住「既不是母户也不是子户」的空 div，不留多余行距 */
.mbd { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 4px; }
.mbd:empty { display: none; }

.note { margin-top: var(--sp-10); padding: var(--sp-9) var(--sp-12); border-radius: var(--r-8); font-size: var(--fs-13); border: 1px solid; }
.note.ok   { background: var(--ok-soft);   border-color: rgba(29,158,117,.3); color: var(--ok); }
.note.bad  { background: var(--bad-soft);  border-color: rgba(200,34,43,.3); color: var(--bad); }
.note.info { background: var(--brand-soft);border-color: rgba(22,104,220,.28); color: var(--brand); }
.note.warn { background: var(--warn-soft); border-color: rgba(180,83,9,.3); color: var(--warn); }
.sub { color: var(--text-dim); font-size: var(--fs-13); margin: var(--sp-6) 0 0; }
.sub b { color: var(--text); }
.tip { color: var(--text-mute); font-size: var(--fs-12-5); margin: var(--sp-10) 0 0; }
.ok { color: var(--ok); }

/* ---------- 687n：错误态（app.js `paintError` / `errRow`）----------
   🔴 原来接口失败时只渲染一行灰字（或空表 + 永久「加载中…」）= 死页。
      统一为「警示图标 + 错误文案 + 重试按钮」，两种落点：
      · .err-state  —— 页级 / 容器级（bare 时去掉卡外壳，避免卡中卡）
      · .err-row    —— 表格内一行，`colspan` 占满 */
.err-state { text-align: center; padding: 34px 16px; }
.err-state .err-ico { display: block; width: 34px; height: 34px; margin: 0 auto 10px; color: var(--warn); }
.err-state .err-ico svg { width: 34px; height: 34px; display: block; }
.err-state .err-msg { color: var(--text-dim); font-size: var(--fs-13-5); margin: 0 0 14px; word-break: break-word; }
.err-inline { display: flex; align-items: center; gap: 8px; justify-content: center; padding: 12px 8px; color: var(--text-dim); font-size: var(--fs-13); flex-wrap: wrap; }
.err-inline .err-ico { display: inline-flex; color: var(--warn); flex: none; }
.err-inline .err-ico svg { width: 16px; height: 16px; display: block; }
.err-inline .err-msg { word-break: break-word; }
.err-row > td { background: var(--warn-soft); }

/* ---------- 425：密钥文本框即时提示（PEM 头行缺失 / 非 PEM） ---------- */
.pem-hint { font-size: var(--fs-12); line-height: 1.5; margin-top: 5px; }
.pem-hint:empty { display: none; }
.pem-hint.is-warn { color: var(--warn); }
.pem-hint.is-bad { color: var(--bad); }

/* ============================================================ 登录
   左栏形态沿用应用台（整屏左右分栏），**文案与深色图案取自原登录页**（417）。 */
.login { display: flex; min-height: 100vh; }
.login-aside {
  flex: 0 0 52%; max-width: 720px; position: relative; overflow: hidden;
  color: #fff; display: flex; flex-direction: column; justify-content: center;
  padding: 40px 48px;
  background: linear-gradient(135deg, #0a2540 0%, #0e3260 60%, #113f7c 100%);
}
/* 双光晕（原登录页 `.login-left::before`） */
.login-aside::before {
  content: ''; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background:
    radial-gradient(circle at 82% 16%, rgba(200,34,43,.24), transparent 52%),
    radial-gradient(circle at 10% 88%, rgba(22,104,220,.40), transparent 56%);
}
/* 28px 网格向下渐隐（原登录页 `.login-left::after`） */
.login-aside::after {
  content: ''; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background-image:
    linear-gradient(rgba(255,255,255,.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,.05) 1px, transparent 1px);
  background-size: 28px 28px;
  -webkit-mask-image: linear-gradient(180deg, #000, transparent 88%);
  mask-image: linear-gradient(180deg, #000, transparent 88%);
}
.la-inner { position: relative; z-index: 1; max-width: 560px; }

.la-brand { display: flex; align-items: center; gap: 12px; }
.la-brand .mark, .side-brand .mark {
  width: 38px; height: 38px; border-radius: var(--r-11); flex: none;
  display: grid; place-items: center; font-size: var(--fs-20); font-weight: 700;
  background: linear-gradient(135deg,var(--brand), var(--brand-lite)); color: #fff;
  box-shadow: 0 4px 12px rgba(22,104,220,.35);
}
.la-brand .txt { display: flex; flex-direction: column; line-height: 1.3; }
.la-brand .txt b { font-size: var(--fs-18); letter-spacing: 2px; }
.la-brand .txt i { font-style: normal; font-size: var(--fs-12); letter-spacing: 1.2px; color: var(--brand-on-dark); }
.la-brand .txt i.dim { font-size: var(--fs-11); letter-spacing: 2px; color: rgba(255,255,255,.48); }

.la-h1 { margin: 26px 0 14px; font-size: var(--fs-28); font-weight: 500; line-height: 1.34; letter-spacing: .4px; }
.la-h1 b { font-weight: 600; color: var(--brand-on-dark); }
.la-h1 .h1-sub {
  display: block; margin-top: 8px; font-size: var(--fs-14-5); font-weight: 400;
  line-height: 1.55; color: rgba(255,255,255,.66);
}
.la-lead { font-size: var(--fs-13); line-height: 1.9; color: rgba(255,255,255,.68); margin: 0 0 14px; }
.la-lead b { font-weight: 600; color: #fff; }
.la-slogan {
  font-size: var(--fs-15); font-weight: 600; line-height: 1.7; letter-spacing: .6px;
  color: var(--brand-on-dark); margin: 0 0 16px;
}
.kw-row { display: flex; flex-wrap: wrap; gap: 7px; margin-bottom: 18px; }
.kw {
  font-size: var(--fs-12); line-height: 1; padding: 7px 11px; border-radius: var(--r-full);
  color: rgba(255,255,255,.72); border: 1px solid rgba(255,255,255,.17);
  background: rgba(255,255,255,.07);
}
.kw.kw-hot {
  color: var(--brand-on-dark); border-color: rgba(122,190,255,.45);
  background: rgba(122,190,255,.14); font-weight: 600; letter-spacing: .6px;
}
.la-points {
  list-style: none; padding: 0; margin: 0 0 16px;
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px 20px;
}
.la-points li { display: flex; flex-direction: column; gap: 3px; padding-left: 13px; position: relative; }
.la-points li::before {
  content: ''; position: absolute; left: 0; top: 7px;
  width: 3px; height: 13px; border-radius: var(--r-2); background: var(--brand-on-dark); opacity: .85;
}
.la-points li b { font-size: var(--fs-13-5); font-weight: 600; color: #fff; }
.la-points li span { font-size: var(--fs-12); line-height: 1.65; color: rgba(255,255,255,.52); }
.agent-strip {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px 14px;
  padding: 13px; border: 1px solid rgba(255,255,255,.14); border-radius: var(--r-12);
  background: rgba(255,255,255,.06);
}
.agent-cell { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.agent-head { display: flex; align-items: center; gap: 6px; font-size: var(--fs-12-5); font-weight: 600; color: #fff; }
.agent-note { font-size: var(--fs-11-5); line-height: 1.6; color: rgba(255,255,255,.5); }
.dot { width: 6px; height: 6px; flex: none; border-radius: 50%; display: inline-block; }
.dot.is-on { background: #34D399; box-shadow: 0 0 6px rgba(52,211,153,.85); }
.dot.is-plan { background: transparent; box-shadow: inset 0 0 0 1.5px rgba(255,255,255,.35); }

/* ---------------------------------------------------------------- 右栏（登录框）
   ★★ 418 批（大人令）：**1:1 还原「原登录页」的右栏**。
      蓝本 = 原登录页（`gkl.supay.tech/#/login`）右栏，权威产物：
        · DOM    _tmp/login-redesign/v6-live-dom.html（.lr-head / .lr-tabs / .lr-cap / .lr-oauth / .lr-foot / .lr-powered）
        · 样式   _tmp/login-redesign/login-v4.css §4 ~ §4.6 + §9 + §10
        · 实拍   _tmp/login-redesign/v6-live.png
      逐条数值（字号/间距/圆角/描边/动效）与蓝本一致；差异只有两处，均为**有意增强**：
        ① 配色由 `--lr-*` 映射到应用台主题令牌 ⇒ 深浅色自动适配（蓝本只做了浅色）
        ② tab 顺序照蓝本「账号登录 / 短信登录」，但**默认选中短信登录**
           （应用台的手机号验证码是真实功能，且「同号多账号」靠它才能选号）
   -------------------------------------------------------------------------- */
.login-main {
  flex: 1; display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  padding: 40px 24px;
  background: var(--card);
  /* ---- 蓝本令牌（login-v4.css §变量），映射到应用台主题令牌 ---- */
  --lr-brand: var(--brand);
  --lr-brand-deep: var(--brand-hover);
  --lr-brand-bright: var(--brand-lite);
  --lr-ink: var(--text);
  --lr-ink-2: var(--text-dim);
  --lr-ink-3: var(--text-mute);
  --lr-line: var(--line);
  --lr-field: var(--line-soft);
  --lr-radius: 12px;
  --lr-h: 48px;
  /* 蓝本里的中性色（浅色档），深色档在下方覆盖 */
  --lr-field-hover: #F1F3F6;
  --lr-solid: #fff;
  --lr-hair: #EEF0F4;
  --lr-cap-bg: #F4F6F8;
  --lr-faint: #A8AEB8;
  --lr-ck-line: #CBD0D8;
  --lr-dot: #D8DCE3;
  --lr-oauth-fg: #4A5260;
  --lr-off-bg: #F0F2F5;
  --lr-soon-fg: #B6BCC6;
  --lr-powered: #A8B0BD;
  --lr-powered-b: #7A8798;
}
/* 一列同宽（蓝本 .login-main 宽 86% / max 398px） */
.login-main > * { width: 100%; max-width: 398px; }

/* 深色档：把蓝本的浅色中性值换成语义等价的中性深色 */
html[data-theme='dark'] .login-main {
  --lr-field-hover: #232A33;
  --lr-solid: #1B2028;
  --lr-hair: #262C35;
  --lr-cap-bg: #1A1F26;
  --lr-faint: #6B7684;
  --lr-ck-line: #3A424E;
  --lr-dot: #39414C;
  --lr-oauth-fg: #B9C2CE;
  --lr-off-bg: #20262E;
  --lr-soon-fg: #5A6472;
  --lr-powered: #5F6A78;
  --lr-powered-b: #7E8899;
}

/* ---------- 4.1 标题区 ---------- */
.lr-head { margin-bottom: 18px; }
.lr-head h2 {
  margin: 0 0 7px; font-size: var(--fs-25); font-weight: 600; line-height: 1.28;
  letter-spacing: 1px; color: var(--lr-ink);
  animation: lr-fade-up .55s cubic-bezier(.22,1,.36,1) .04s both;
}
.lr-head p {
  margin: 0; font-size: var(--fs-12-5); line-height: 1.5; letter-spacing: .4px;
  color: var(--lr-ink-3);
  animation: lr-fade-up .55s cubic-bezier(.22,1,.36,1) .08s both;
}

/* ---------- 4.2 双 tab ---------- */
.lr-tabs {
  display: flex; gap: 28px; border-bottom: 1px solid var(--lr-hair);
  margin-bottom: 18px;
  animation: lr-fade-up .55s cubic-bezier(.22,1,.36,1) .12s both;
}
.lr-tab {
  position: relative; padding: 0 1px 11px; border: 0; background: none;
  font-family: inherit; font-size: var(--fs-15); font-weight: 500; letter-spacing: .6px;
  color: var(--lr-ink-2); cursor: pointer; transition: color .2s;
}
.lr-tabs .lr-tab:hover { color: var(--lr-ink); background: none; border-color: transparent; }
.lr-tab.is-on { color: var(--lr-brand); font-weight: 600; }
.lr-tab.is-on::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: -1px; height: 2.5px;
  border-radius: var(--r-3); background: linear-gradient(90deg, var(--lr-brand-bright), var(--lr-brand));
}
.lr-tab.is-soon { color: var(--lr-soon-fg); cursor: not-allowed; }
.lr-tab.is-soon::after { display: none; }

/* ---------- 4.3 表单面板与字段 ---------- */
.lr-pane { animation: lr-fade-up .4s cubic-bezier(.22,1,.36,1) both; }
.lr-field { position: relative; margin-bottom: 16px; }
.lr-input {
  width: 100%; height: var(--lr-h);
  border: 1.5px solid transparent; border-radius: var(--lr-radius);
  background: var(--lr-field); padding: 0 16px 0 42px;
  font-family: inherit; font-size: var(--fs-14); color: var(--lr-ink); outline: none;
  transition: background .2s, border-color .2s, box-shadow .2s;
}
.lr-input::placeholder { color: var(--lr-ink-3); }
.lr-input:hover { background: var(--lr-field-hover); }
.lr-input:focus { background: var(--lr-solid); border-color: var(--lr-brand); box-shadow: 0 0 0 4px rgba(22,104,220,.10); }
.lr-field .lr-ico {
  position: absolute; left: 13px; top: 0; height: var(--lr-h);
  display: flex; align-items: center; pointer-events: none;
}
.lr-field .lr-ico svg { width: 18px; height: 18px; stroke: var(--lr-ink-3); transition: stroke .2s; }
.lr-field.is-focus .lr-ico svg { stroke: var(--lr-brand); }
.lr-input-code { padding-right: 108px; }
.lr-input-eye { padding-right: 44px; }
.lr-field .lr-send {
  position: absolute; right: 6px; top: 6px; height: calc(var(--lr-h) - 12px);
  padding: 0 14px; border: 0; border-radius: var(--r-9);
  background: rgba(22,104,220,.08); color: var(--lr-brand);
  font-family: inherit; font-size: var(--fs-12-5); font-weight: 600; letter-spacing: .3px;
  cursor: pointer; transition: background .2s, color .2s; white-space: nowrap;
}
.lr-field .lr-send:hover:not(:disabled) { background: rgba(22,104,220,.14); border-color: transparent; }
.lr-field .lr-send:disabled { background: var(--lr-off-bg); color: var(--lr-faint); cursor: not-allowed; }
.lr-field .lr-eye {
  position: absolute; right: 6px; top: 6px; height: calc(var(--lr-h) - 12px); width: 34px;
  display: flex; align-items: center; justify-content: center;
  border: 0; background: none; padding: 0; cursor: pointer;
}
.lr-field .lr-eye svg { width: 18px; height: 18px; stroke: var(--lr-ink-3); transition: stroke .2s; }
.login-main .lr-field .lr-eye:hover { background: none; border-color: transparent; }
.lr-field .lr-eye:hover svg { stroke: var(--lr-brand); }
.lr-field .lr-eye.is-on svg { stroke: var(--lr-brand); }

/* ---------- 4.4 滑动验证（1:1 照蓝本） ---------- */
.lr-cap {
  position: relative; height: var(--lr-h); margin: 0 0 16px;
  border-radius: var(--lr-radius); border: 1.5px solid var(--lr-line);
  background: var(--lr-cap-bg); overflow: hidden;
  user-select: none; -webkit-user-select: none; touch-action: none;
  animation: lr-fade-up .55s cubic-bezier(.22,1,.36,1) .16s both;
}
.lr-cap-fill {
  position: absolute; left: 0; top: 0; bottom: 0; width: 0;
  background: linear-gradient(90deg, rgba(22,104,220,.07), rgba(22,104,220,.20));
}
.lr-cap-tip {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  padding-left: 46px; font-size: var(--fs-13); letter-spacing: .6px; color: var(--lr-ink-3);
  pointer-events: none; transition: color .2s;
}
.lr-cap-handle {
  position: absolute; left: 2px; top: 2px; width: 56px;
  height: calc(var(--lr-h) - 4px - 3px); border-radius: var(--r-9);
  background: var(--lr-solid);
  box-shadow: 0 2px 8px rgba(16,20,28,.15), 0 0 0 1px rgba(16,20,28,.05);
  display: flex; align-items: center; justify-content: center;
  cursor: grab; will-change: left; transition: background .22s;
}
.lr-cap-handle svg { width: 18px; height: 18px; stroke: var(--lr-ink-3); transition: stroke .22s; }
.lr-cap.is-drag .lr-cap-handle { cursor: grabbing; }
.lr-cap.is-ok { border-color: var(--ok); background: var(--ok-soft); }
.lr-cap.is-ok .lr-cap-fill { background: linear-gradient(90deg, rgba(56,201,124,.10), rgba(56,201,124,.24)); }
.lr-cap.is-ok .lr-cap-tip { color: #189A5C; font-weight: 600; }
.lr-cap.is-ok .lr-cap-handle { background: var(--ok); }
.lr-cap.is-ok .lr-cap-handle svg { stroke: #fff; }
.lr-cap.is-err { border-color: #E4143C; animation: lr-shake .4s; }
.lr-cap.is-err .lr-cap-tip { color: #E4143C; }

@keyframes lr-fade-up { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
@keyframes lr-shake {
  0%,100% { transform: translateX(0); }
  20% { transform: translateX(-6px); }
  40% { transform: translateX(6px); }
  60% { transform: translateX(-4px); }
  80% { transform: translateX(4px); }
}

/* ---------- 4.5 协议行 ---------- */
.lr-tip { margin: 0 0 12px; font-size: var(--fs-12); line-height: 1.65; color: var(--lr-ink-3); }
.lr-agree {
  display: flex; align-items: flex-start; gap: 8px; margin: 4px 0 0;
  font-size: var(--fs-12-5); line-height: 1.7; color: var(--lr-ink-2); cursor: pointer;
}
.lr-agree input {
  appearance: none; -webkit-appearance: none;
  width: 15px; height: 15px; margin: 3px 0 0; flex: none;
  border: 1px solid var(--lr-ck-line); border-radius: var(--r-4); background: var(--lr-solid);
  cursor: pointer; position: relative; transition: background .2s, border-color .2s;
}
.lr-agree input:checked { background: var(--lr-brand); border-color: var(--lr-brand); }
.lr-agree input:checked::after {
  content: ''; position: absolute; left: 4.5px; top: 1px; width: 3.5px; height: 7.5px;
  border: solid #fff; border-width: 0 1.6px 1.6px 0; transform: rotate(43deg);
}
.lr-agree em { font-style: normal; color: var(--lr-brand); font-weight: 500; cursor: pointer; }
.lr-agree i { font-style: normal; color: var(--lr-ink-3); }

/* ---------- 4.6 主按钮（海军渐变 + 大字距） ---------- */
.lr-submit {
  width: 100%; height: 50px; margin-top: 18px;
  border: 0; border-radius: var(--lr-radius);
  background: linear-gradient(135deg, var(--lr-brand-bright) 0%, var(--lr-brand) 55%, var(--lr-brand-deep) 100%);
  color: #fff; font-family: inherit; font-size: var(--fs-16); font-weight: 600;
  letter-spacing: 5px; text-indent: 5px; cursor: pointer;
  box-shadow: 0 12px 26px -10px rgba(22,104,220,.55);
  transition: transform .18s, box-shadow .22s, filter .22s;
}
/* 🔴🔴 悬停/按下必须**重述 background + color**（不能只写 transform/filter）：
   本文件顶部那条全局 `button:hover:not(:disabled){ background: var(--brand-soft) }` 特异性 (0,2,1)
   **高于** `.lr-submit` 的 (0,1,0) ⇒ 悬停时渐变被换成 #EDF3FC 浅蓝底，而字仍是白的 ⇒
   「登录」二字**看不见**（大人 2026-10-08 实拍报障）。
   正解 = 在这两条里把 `background` 一并重述（特异性 (0,3,0) 压回），别处同理。 */
.lr-submit:hover:not(:disabled),
.lr-submit:active:not(:disabled) {
  background: linear-gradient(135deg, var(--lr-brand-bright) 0%, var(--lr-brand) 55%, var(--lr-brand-deep) 100%);
  border-color: transparent; color: #fff;
}
.lr-submit:hover:not(:disabled) { transform: translateY(-1px); filter: brightness(1.06); }
.lr-submit:active:not(:disabled) { transform: translateY(0); filter: brightness(.97); }
.lr-submit:disabled { opacity: .72; transform: none; cursor: not-allowed; }

/* ---------- 4.7 其他登录方式 ---------- */
.lr-oauth { margin-top: 20px; }
.lr-oauth-sep {
  display: flex; align-items: center; gap: 12px;
  font-size: var(--fs-11-5); letter-spacing: 1.2px; color: var(--lr-faint);
}
.lr-oauth-sep::before, .lr-oauth-sep::after { content: ''; flex: 1 1 auto; height: 1px; background: var(--lr-hair); }
.lr-oauth-row { display: flex; gap: 10px; margin-top: 14px; }
.lr-oauth-btn {
  flex: 1 1 0; min-width: 0; height: 42px;
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  border: 1.5px solid var(--lr-line); border-radius: var(--r-10); background: var(--lr-solid);
  font-family: inherit; font-size: var(--fs-13); color: var(--lr-oauth-fg); cursor: pointer;
  transition: border-color .2s, color .2s, background .2s, transform .18s, box-shadow .2s;
}
.lr-oauth-btn svg { width: 17px; height: 17px; flex: none; }
/* 🔴 同上：必须重述 background，否则被全局 `button:hover:not(:disabled)` 染成 --brand-soft 浅蓝底 */
.lr-oauth-btn:hover:not(.is-soon) {
  background: var(--lr-solid);
  border-color: var(--lr-brand); color: var(--lr-brand);
  transform: translateY(-1px); box-shadow: 0 6px 14px -8px rgba(22,104,220,.5);
}
.lr-oauth-btn.is-soon { opacity: .52; }
.lr-oauth-btn.is-soon:hover { border-color: var(--lr-line); transform: none; background: var(--lr-solid); }

/* 未开通入口的点击提示（照蓝本 §9 .lr-soon-tip） */
.lr-soon-tip {
  position: fixed; left: 50%; bottom: 32px; transform: translateX(-50%);
  max-width: 92%; padding: 9px 15px; border-radius: var(--r-9);
  font-size: var(--fs-12-5); line-height: 1.5; color: #fff; text-align: center;
  background: rgba(22,30,44,.92); box-shadow: 0 12px 30px -12px rgba(0,0,0,.5);
  z-index: 200; pointer-events: none;
}

/* ---------- 4.8 底部链接与署名 ---------- */
.lr-foot {
  display: flex; align-items: center; justify-content: center; gap: 11px;
  margin-top: 18px; font-size: var(--fs-12-5); color: var(--lr-ink-3);
}
.lr-foot a { color: var(--lr-ink-2); text-decoration: none; cursor: pointer; transition: color .2s; }
.lr-foot a:hover { color: var(--lr-brand); text-decoration: none; }
.lr-foot i { font-style: normal; color: var(--lr-dot); }
.lr-powered { margin-top: 12px; text-align: center; font-size: var(--fs-11-5); letter-spacing: .2px; color: var(--lr-powered); }
.lr-powered b { font-weight: 600; color: var(--lr-powered-b); }

/* ---------- 4.9 登录页响应式（照蓝本 992 / 480 断点） ---------- */
@media (max-width: 992px) {
  .login-aside { display: none; }
  .login-main { padding: 32px 20px; }
  .login-main > * { max-width: 420px; }
}
@media (max-width: 480px) {
  .lr-head h2 { font-size: var(--fs-23); }
  .lr-oauth-row { gap: 8px; }
  .lr-oauth-btn { font-size: var(--fs-12-5); }
}


/* ============================================================ 主壳 */
.shell { display: flex; min-height: 100vh; }

.side {
  flex: 0 0 var(--side-w); width: var(--side-w); display: flex; flex-direction: column;
  position: relative; overflow: hidden;
  background: var(--side-bg);
  position: sticky; top: 0; height: 100vh;
  transition: flex-basis .18s ease, width .18s ease;
}
/* ★ 417：侧栏背景图案（28px 网格向下渐隐）—— 与登录页左栏同一套图案语言 */
.side::after {
  content: ''; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background-image:
    linear-gradient(var(--side-grid) 1px, transparent 1px),
    linear-gradient(90deg, var(--side-grid) 1px, transparent 1px);
  background-size: 28px 28px;
  -webkit-mask-image: linear-gradient(180deg, #000, transparent 82%);
  mask-image: linear-gradient(180deg, #000, transparent 82%);
}
.side > * { position: relative; z-index: 1; }

.side-brand {
  display: flex; align-items: center; gap: var(--sp-10);
  padding: var(--sp-18) var(--sp-18) var(--sp-16); border-bottom: 1px solid var(--side-line);
}
.side-brand .txt { display: flex; flex: 1; min-width: 0; flex-direction: column; line-height: 1.25; white-space: nowrap; }
/* ★ r953（大人令「侧栏配色挪到 观客来商业支付应用管家 右边」）：
   品牌行末端一个小图标按钮 —— 与 footer 的 foot-ico 同一套「隐形幽灵按钮」口径，
   显式压掉全局 button 的 border/padding/背景（否则会多出一个描边方块）。 */
.side-brand button.brand-ico {
  display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; padding: 0; flex: none;
  border: 0; border-radius: var(--r-7); background: none;
  color: var(--side-fg-dim); line-height: 1;
}
.side-brand button.brand-ico svg { width: 15px; height: 15px; display: block; }
.side-brand button.brand-ico:hover:not(:disabled) {
  border-color: transparent; background: var(--side-hover); color: var(--side-fg);
}
.side-brand button.brand-ico.is-on,
.side-brand button.brand-ico.is-on:hover:not(:disabled) {
  color: var(--side-fg); background: var(--side-on);
}
.side-brand .txt b { color: #fff; font-size: var(--fs-15); letter-spacing: .5px; }
.side-brand .txt i { font-style: normal; font-size: var(--fs-11); color: var(--side-fg-dim); }

.side-nav { flex: 1; overflow-y: auto; overflow-x: hidden; padding: var(--sp-12) var(--sp-10); }
.side-nav .grp {
  padding: var(--sp-12) var(--sp-10) var(--sp-6); font-size: var(--fs-11); letter-spacing: 1px;
  color: var(--side-fg-mute); text-transform: uppercase; white-space: nowrap;
}
.side-nav button.nav {
  position: relative; width: 100%; display: flex; align-items: center; gap: var(--sp-10);
  padding: var(--sp-10) var(--sp-12); margin-bottom: var(--sp-3); border: 0; border-radius: var(--r-9);
  background: none; color: var(--side-fg); font-size: var(--fs-14); text-align: left;
  white-space: nowrap; overflow: hidden;
}
.side-nav button.nav:hover:not(:disabled) { background: var(--side-hover); border-color: transparent; }
.side-nav button.nav.on {
  background: var(--side-on); color: #fff; font-weight: 600;
}
.side-nav button.nav.on::before {
  content: ''; position: absolute; left: 0; top: 9px; bottom: 9px;
  width: 3px; border-radius: 0 var(--r-3) var(--r-3) 0; background: var(--side-accent);
}
.side-nav button.nav .ico { width: 16px; height: 16px; flex: none; opacity: .85; }
.side-nav button.nav .ico svg { width: 16px; height: 16px; display: block; }
.side-nav button.nav.on .ico { opacity: 1; }

.side-foot {
  padding: var(--sp-12) var(--sp-18); border-top: 1px solid var(--side-line);
  /* ★ r976：footer 由「一行两端对齐」改成「两行」—— 移动端入口独占一行才看得见。
     第一行 = 移动端胶囊（全宽），第二行 = Powered by + 版本号。 */
  display: flex; flex-direction: column; align-items: stretch; gap: var(--sp-8);
  font-size: var(--fs-11-5); color: var(--side-fg-mute); white-space: nowrap;
}
/* ★ r950（大人令 2026-10-27「这个移动端放到左下角 workbuddy 右侧」）：
   footer 右侧动作区 = 移动端入口 + 版本号。
   🔴 必须显式压掉全局 `button` 的 border/padding/背景，否则会出现一个描边方块。 */
.side-foot .foot-act { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-6); min-width: 0; }
.side-foot button.foot-ico {
  display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; padding: 0; flex: none;
  border: 0; border-radius: var(--r-7); background: none;
  color: var(--side-fg-dim); line-height: 1;
}
.side-foot button.foot-ico svg { width: 15px; height: 15px; display: block; }
.side-foot button.foot-ico:hover:not(:disabled) {
  border-color: transparent; background: var(--side-hover); color: var(--side-fg);
}
/* ★★ r976（大人令 2026-10-28「移动端 标出来 不然用户会注意不到」）：
   r950 的入口是 24×24 幽灵图标、前景 `--side-fg-dim`（55% 白）、无底无边 ⇒ 等于隐形。
   改法：全宽胶囊 + 图标 + 文字 + 浅底 + 细描边 + **亮前景**（`--side-fg`）。
   ⚠️ 只动这一枚的尺寸与配色，`.foot-ico` 基础口径（r951 的 is-on 态）全部保留。 */
.side-foot button.foot-mobile {
  width: 100%; height: 30px; padding: 0 12px; gap: 7px;
  justify-content: flex-start; border-radius: var(--r-8);
  border: 1px solid var(--side-line); background: var(--side-hover);
  color: var(--side-fg); font-size: var(--fs-12); font-weight: 600;
}
.side-foot button.foot-mobile svg { width: 15px; height: 15px; flex: none; }
.side-foot button.foot-mobile .fm-txt { line-height: 1; letter-spacing: .2px; }
.side-foot button.foot-mobile:hover:not(:disabled) {
  background: var(--side-on); color: #fff;
}
/* ★ r951：侧栏配色开关的「已开启」态（WB 浅色）—— 用侧栏自己的令牌上色，
   深色侧栏 = 半透明蓝块，浅灰侧栏 = 灰块，两边都看得出「亮着」。 */
.side-foot button.foot-ico.is-on,
.side-foot button.foot-ico.is-on:hover:not(:disabled) {
  color: var(--side-fg); background: var(--side-on);
}

/* ---- 417：侧栏收缩（64px 图标条） ---- */
.shell.is-collapsed .side { flex-basis: var(--side-w-collapsed); width: var(--side-w-collapsed); }
.shell.is-collapsed .side-brand { flex-direction: column; gap: var(--sp-6); justify-content: center; padding: var(--sp-14) 0; }
.shell.is-collapsed .side-brand .txt { display: none; }
.shell.is-collapsed .side-nav { padding: var(--sp-10) var(--sp-8); }
.shell.is-collapsed .side-nav .grp { display: none; }
.shell.is-collapsed .side-nav button.nav { justify-content: center; padding: var(--sp-11) 0; gap: 0; }
.shell.is-collapsed .side-nav button.nav .lbl { display: none; }
/* ★ r951：侧栏配色开关搬进 footer 后，收起态**不能再整行隐藏** —— 否则唯一的开关
   会被藏进 64px 里再也点不到。收起时只留图标（竖排），文字与版本号隐去。
   ★ r976：footer 结构改为「移动端胶囊 + meta 行」两行 ⇒ 收起态把 meta 整行隐去、
     移动端胶囊退回 28×28 纯图标（与 `#tb-side` 在品牌区的位置对称）。 */
.shell.is-collapsed .side-foot {
  display: flex; flex-direction: column; justify-content: center; align-items: center;
  padding: var(--sp-10) 0; gap: var(--sp-6);
}
.shell.is-collapsed .side-foot .foot-act { display: none; }
.shell.is-collapsed .side-foot button.foot-mobile {
  width: 28px; height: 28px; padding: 0; justify-content: center;
  border-color: transparent; background: none;
}
.shell.is-collapsed .side-foot button.foot-mobile .fm-txt { display: none; }

.main { flex: 1; min-width: 0; display: flex; flex-direction: column; }

.topbar {
  height: calc(56px * var(--ui-s)); flex: none; display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-12); padding: 0 var(--sp-18) 0 var(--sp-12); background: var(--card);
  border-bottom: 1px solid var(--line);
  position: sticky; top: 0; z-index: 20;
}
.tb-left { display: flex; align-items: center; gap: var(--sp-10); min-width: 0; }
.crumb { font-size: var(--fs-15); font-weight: 600; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.top-right { display: flex; align-items: center; gap: var(--sp-8); }
.who {
  display: flex; align-items: center; gap: var(--sp-8); padding: var(--sp-4) var(--sp-10) var(--sp-4) var(--sp-4);
  border-radius: var(--r-full); background: var(--line-soft); font-size: var(--fs-13);
}
.who .avatar {
  width: 26px; height: 26px; border-radius: 50%; display: grid; place-items: center;
  background: linear-gradient(135deg,var(--brand), var(--brand-lite)); color: #fff; font-size: var(--fs-12); font-weight: 700;
}
.who .nm { color: var(--text); font-weight: 600; }

/* ============================================================ 内容区 */
.content { flex: 1; padding: var(--sp-20) var(--sp-22) var(--sp-40); }
/* ★★ 5286：超宽屏「舒适上限」—— 内容区**不无限拉宽**，居中留白（留白即高级感）。
   1080p(1920) 及以下 `--pg-max: none` ⇒ `max-width:none` + `margin:auto` 无效 ⇒ **零变化**；
   2.5K / 3.2K / 4K 起逐档收窄（见文件末尾 5286 分档块）。
   ★ 判据用「视口宽」而非物理分辨率 —— 4K@150% 与 2.5K@100% 视口同为 2560。 */
.content > * { max-width: var(--pg-max); margin-inline: auto; }
/* 🔴🔴 r954（大人令 2026-10-27「余额付款页 还是不齐 你检查下 4K 下的界面」）—— 真因就在这一行下面：
   页面块若写 `margin: 10px 0 14px` 这种**四值简写**，会把上面 `margin-inline: auto` 一并清零
   （同特异性、后出现的胜） ⇒ 该块在 `--pg-max` 生效的 4K/2.5K 上**贴左边**，与兄弟块错开半屏。
   实测 4K：`pg-head` / 单笔卡片 left=843，而「放行策略 / 可用余额 / 三页签」left=315 —— 差 528px。
   1080p 下 `--pg-max: none` ⇒ `max-width` 不生效 ⇒ 看不出来（所以只在超大屏露馅）。
   兜底：在 pg-max 生效的档位用**更高特异性**把左右外边距拉回 auto（不写 !important，
   各块自身改 `margin-block` 才是正解；这也是给后来新增块的保险）。 */
@media (min-width: 2048px) {
  .content > .card,
  .content > .bar,
  .content > .bp-tabs,
  .content > .pg-head { margin-left: auto; margin-right: auto; }
}
.pg-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--sp-16); margin-bottom: var(--sp-14); }
.pg-head h3 { font-size: var(--fs-17); }
.pg-head .sub { margin-top: var(--sp-4); }

.card {
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--elev-1); padding: var(--sp-18) var(--sp-20); margin-bottom: var(--sp-16);
}
.card > h4 { font-size: var(--fs-15); margin-bottom: var(--sp-4); }
.card .card-body { margin-top: var(--sp-14); }

/* 交易域汇总条（417） */
.stats { display: flex; flex-wrap: wrap; gap: var(--sp-12) var(--sp-34); }
.stats .stat { display: flex; flex-direction: column; gap: var(--sp-3); }
.stats .stat > span { font-size: var(--fs-12-5); color: var(--text-dim); }
.stats .stat > b { font-size: var(--fs-20); font-weight: 600; letter-spacing: .3px; }

.bar { display: flex; align-items: center; gap: var(--sp-8); flex-wrap: wrap; }
.bar .grow { flex: 1; }
.search { display: flex; flex-wrap: wrap; gap: var(--sp-12) var(--sp-18); align-items: flex-end; margin-top: var(--sp-14); }
.search .fi { min-width: calc(180px * var(--ui-s)); }
.search .fi span { display: block; font-size: var(--fs-12-5); color: var(--text-dim); margin-bottom: var(--sp-5); }
.search .acts { display: flex; gap: var(--sp-8); }

.grid-2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 var(--sp-18); }
.grid-3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0 var(--sp-18); }
.grid-4 { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0 var(--sp-18); }
@media (max-width: 1180px) { .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 900px) { .grid-2, .grid-3, .grid-4 { grid-template-columns: 1fr; } }

/* 表格 */
.tbl-wrap { overflow-x: auto; margin-top: var(--sp-14); }
/* ★ 5285b（大人令 2026-10-15）：宽表**顶部镜像横向滚动条** —— 常驻可见，免「拖到底才见」。
   🔴 结构由 app.js `xsScan()` 注入（`.tbl-wrap`/`.ma-tblwrap` 的**前一个兄弟节点**）；
      不溢出时带 `hidden`，完全不占位。 */
.tbl-xscroll {
  overflow-x: scroll; overflow-y: hidden; height: 12px;
  margin-top: var(--sp-14); border-radius: var(--r-full);
}
.tbl-xscroll[hidden] { display: none; }
.tbl-xscroll-in { height: 1px; }
/* 强制「经典」滚动条：Chromium 的 overlay 滚动条会淡出 ⇒ 与「常驻可见」相悖 */
.tbl-xscroll::-webkit-scrollbar { height: 12px; }
.tbl-xscroll::-webkit-scrollbar-track { background: var(--line-soft); border-radius: var(--r-full); }
.tbl-xscroll::-webkit-scrollbar-thumb { background: var(--line); border-radius: var(--r-full); border: 2px solid var(--line-soft); }
.tbl-xscroll::-webkit-scrollbar-thumb:hover { background: var(--text-dim); }
.tbl-xscroll + .tbl-wrap, .tbl-xscroll + .ma-tblwrap { margin-top: var(--sp-6); }
table.tbl { width: 100%; border-collapse: separate; border-spacing: 0; font-size: var(--fs-13-5); }
table.tbl th {
  text-align: left; font-weight: 600; color: var(--text-dim); font-size: var(--fs-12-5);
  background: var(--line-soft); padding: var(--sp-10) var(--sp-12); border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
table.tbl td { padding: var(--sp-11) var(--sp-12); border-bottom: 1px solid var(--line-soft); vertical-align: middle; }
table.tbl tbody tr:hover td { background: var(--brand-soft); }
table.tbl td.nowrap { white-space: nowrap; }
/* 🔴 操作列按钮**必须单行**：`wrap` 在 11 列表格里会把 4 个按钮摞成 4 行，
   行高被撑到 3 倍、表格没法扫读。改成 nowrap ⇒ 列宽自适应、超出时由
   `.tbl-wrap` 横向滚动承接（与旧控台 Avue 表格同一观感）。 */
table.tbl .acts { display: flex; gap: 6px; align-items: center; flex-wrap: nowrap; }
/* 🔴 关键：`.acts` 里按钮必须 `flex:none` + `nowrap`。
   否则 flex 会把按钮当可压缩项挤窄，按钮内部文字竖排（"二维码"→"二/维/码"），
   比原来的换行更难看。给 `flex:none` 后列不会压扁按钮。 */
table.tbl .acts > button, table.tbl .acts > a {
  flex: 0 0 auto; white-space: nowrap;
}

/* ---------- 宽表（列多 + 操作列按钮多）----------
   观感目标 = 旧控台 Avue：列按自然宽度铺开 ⇒ 超出由 `.tbl-wrap` 横向滚动承接，
   **操作列吸右常驻** ⇒ 横滚时不丢「撤销确认」这类末位按钮。 */
table.tbl.wide { min-width: 1210px; }
table.tbl td.w2 { min-width: 104px; }
table.tbl.wide th:last-child,
table.tbl.wide td:last-child {
  position: sticky; right: 0; z-index: 2;
  background: var(--card);
  box-shadow: -8px 0 8px -8px rgba(16, 24, 40, .22);
}
table.tbl.wide thead th:last-child { background: var(--line-soft); }
table.tbl.wide tbody tr:hover td:last-child { background: var(--brand-soft); }

.empty {
  padding: var(--sp-44) var(--sp-16); text-align: center; color: var(--text-mute);
  border: 1px dashed var(--line); border-radius: var(--r-10); margin-top: var(--sp-14);
}

.pager { display: flex; align-items: center; justify-content: flex-end; gap: var(--sp-12); margin-top: var(--sp-14); font-size: var(--fs-13); color: var(--text-dim); }
.pager .btns { display: flex; gap: var(--sp-6); align-items: center; }

/* 机构多选行 */
.pfs { margin-top: var(--sp-16); border: 1px solid var(--line); border-radius: var(--r-10); overflow: hidden; }
.pfs-hd { padding: var(--sp-9) var(--sp-12); background: var(--line-soft); font-size: var(--fs-12-5); color: var(--text-dim); }
.pf-row { display: flex; align-items: center; gap: var(--sp-12); padding: var(--sp-9) var(--sp-12); border-top: 1px solid var(--line-soft); }
.pf-row .pf-chk { display: flex; align-items: center; gap: var(--sp-8); min-width: calc(150px * var(--ui-s)); font-size: var(--fs-13-5); cursor: pointer; }
.pf-row .pf-chk input { width: auto; }
.pf-row input.c-pc { flex: 1; }
.pf-row .c-cred { flex: none; }
.pf-row .c-cred-st { flex: none; min-width: 60px; margin: 0; }

/* 「使用商户密钥」开关（417） */
.keysrc {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin-top: 16px; padding: 11px 13px;
  border: 1px solid var(--line); border-radius: var(--r-10); background: var(--line-soft);
}
.keysrc .sw { display: inline-flex; align-items: center; gap: 9px; cursor: pointer; white-space: nowrap; }
.keysrc .sw input { position: absolute; opacity: 0; width: 0; height: 0; }
.keysrc .sw-track {
  width: 42px; height: 23px; border-radius: var(--r-full); flex: none; position: relative;
  background: var(--text-mute); transition: background .18s;
}
.keysrc .sw-track::after {
  content: ''; position: absolute; top: 2px; left: 2px; width: 19px; height: 19px;
  border-radius: 50%; background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,.28);
  transition: transform .18s;
}
.keysrc .sw input:checked + .sw-track { background: var(--brand); }
.keysrc .sw input:checked + .sw-track::after { transform: translateX(19px); }
.keysrc .sw input:focus-visible + .sw-track { box-shadow: 0 0 0 3px rgba(22,104,220,.22); }
.keysrc .sw-txt { font-size: var(--fs-13-5); font-weight: 600; color: var(--text); }
.keysrc .sub { margin: 0; }

/* ★ r978（大人令 2026-10-28）：汇付官方密钥 txt 一键导入。
   「绑定机构 · 斗拱汇付」的密钥区多一行：选 txt ⇒ 私钥 / 汇付公钥 / 我方公钥 / 机构号 一次填好。 */
.huifu-txt {
  display: flex; align-items: center; gap: var(--sp-10); flex-wrap: wrap;
  margin-top: var(--sp-10); padding: var(--sp-9) var(--sp-12);
  border: 1px dashed var(--line); border-radius: var(--r-10); background: var(--line-soft);
}
.huifu-txt[hidden] { display: none; }
.huifu-txt .huifu-pick {
  display: inline-flex; align-items: center; gap: 6px; cursor: pointer; white-space: nowrap;
  padding: var(--sp-6) var(--sp-12); border-radius: var(--r-6);
  font-size: var(--fs-12-5); font-weight: 600; color: var(--brand);
  border: 1px solid var(--brand); background: var(--brand-soft);
  transition: background .15s, color .15s;
}
.huifu-txt .huifu-pick:hover { background: var(--brand); color: var(--on-brand); }
.huifu-txt .huifu-pick input { position: absolute; opacity: 0; width: 0; height: 0; }
.huifu-txt .sub { margin: 0; font-size: var(--fs-12); color: var(--text-mute); }
.huifu-txt .sub.ok { color: var(--ok); }
.huifu-txt .sub.bad { color: var(--bad); }

/* 反向自测 */
.case {
  display: flex; align-items: center; gap: 12px; padding: 9px 4px;
  border-bottom: 1px solid var(--line-soft); font-size: var(--fs-13-5);
}
.case .nm { flex: 1; }
.case .exp { color: var(--text-mute); font-size: var(--fs-12-5); }

/* 打印 / 二维码 */
.qr { display: grid; place-items: center; padding: 10px; }
.qr img, .qr svg { width: 196px; height: 196px; }

/* ============================================================ 弹层 */
.mask {
  position: fixed; inset: 0; z-index: 100; display: grid; place-items: center;
  background: rgba(16,24,40,.45); padding: 24px; overflow: auto;
}
.modal {
  position: relative;   /* ★ 704：给「右上角 ✕」定包含块 */
  width: 100%; max-width: calc(460px * var(--ui-s)); background: var(--card); border-radius: var(--radius-lg);
  padding: 24px; box-shadow: 0 20px 50px rgba(16,24,40,.24);
}
.modal.wide { max-width: calc(560px * var(--ui-s)); }
.modal h3 { font-size: var(--fs-17); margin-bottom: 4px; }
.modal .sect { margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--line-soft); }
.modal .sect:first-of-type { border-top: 0; padding-top: 4px; }
.modal .sect h4 { font-size: var(--fs-14); margin-bottom: 2px; }
.modal .actions { display: flex; gap: 10px; margin-top: 18px; }
.modal .actions button { flex: 1; }

/* ---------- 2026-10-23：个人设置「登录方式」合并框（手机号 + 微信）----------
   🔴 大人令：手机号与微信**收进一个框**，避免用户以为「微信绑的是另一个账号」。
      两行等宽三列：左标签 / 中当前值 / 右动作，行间虚线分隔 ⇒ 一眼看出
      「手机号 = 账号身份，微信 = 登录手段，两者同属一个账号」。 */
.bind-list {
  margin: 12px 0 0; border: 1px solid var(--line-soft);
  border-radius: var(--radius); background: var(--bg-soft, rgba(0,0,0,.02)); overflow: hidden;
}
.bind-row {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 12px; border-top: 1px dashed var(--line-soft);
}
.bind-row:first-child { border-top: 0; }
.bind-k {
  flex: 0 0 64px; font-size: var(--fs-13); color: var(--text-dim);
}
.bind-v {
  flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
.bind-v code { font-size: var(--fs-13); }
.bind-a { flex: 0 0 auto; }
.bind-a > button { white-space: nowrap; }
#pf-phone-form { margin-top: 12px; }
/* 用户管理 · unionid / openid 列：等宽小字。
   2026-10-23 大人点头：定宽 150px + 省略号 —— 28 位原文会把表撑到 1920px，
   1440 视口下「状态/根用户/密码/创建时间」全被挤出屏；截断后 `title` 悬停看全量，
   逐字核对仍可（配合「显示完整手机号」旁的复制入口）。表格 min-width 同步降到 1700px。 */
code.wx-id {
  display: inline-block; max-width: 150px; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; vertical-align: middle;
  font-size: 11px; letter-spacing: -.2px; color: var(--text-dim);
}

/* r874 · 入金记录「买家 OpenId」列 —— 微信下单用户的唯一标识（28 位）。
   与上一格 `code.wx-id` 同思路：定宽截断防表格爆宽，`title` 悬停看全量；
   额外 `user-select:all` —— 点一下即整串选中，Ctrl+C 拿到的就是完整值（对账要复制）。 */
code.oid {
  display: inline-block; max-width: 170px; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; vertical-align: middle;
  font-size: 11px; letter-spacing: -.2px; color: var(--text-dim);
  user-select: all;
}

/* ---------- r952：全局脚本异常提示条（app.js `toastErr`） ----------
   🔴 为什么必须有：脚本异常若无人接管，浏览器**一点提示都不给**，用户只看到「点了没反应」。
   宁可丑，不许静默。z-index 高于所有既有层（最高 .cfmask=400）。 */
.toast-err, .toast-info {
  position: fixed; left: 50%; top: 18px; transform: translateX(-50%);
  z-index: 9999; max-width: min(680px, 92vw);
  padding: 10px 16px; border-radius: 10px;
  background: #FDECEC; color: #A61B1B; border: 1px solid #F5C2C2;
  box-shadow: 0 8px 24px rgba(16, 24, 40, .16);
  font-size: var(--fs-13, 13px); line-height: 1.55; word-break: break-word;
  white-space: pre-line;            /* 多行提示用 \n 就能换行（替代原生 alert） */
  transition: opacity .35s ease, transform .35s ease;
}
.toast-err.out, .toast-info.out { opacity: 0; transform: translateX(-50%) translateY(-8px); }
.toast-info { background: #EAF3FF; color: #1B4F9C; border-color: #C2DCFB; }
html[data-theme='dark'] .toast-err { background: #3A1D1D; color: #FFB4B4; border-color: #5C2A2A; }
html[data-theme='dark'] .toast-info { background: #17293F; color: #A9CDFF; border-color: #2A4A6E; }

/* ---------- 687n：确认弹层（app.js `confirmDialog`）----------   🔴 替代原生 `confirm()`：原生框会被浏览器「阻止更多对话框」静默吞掉（返回 false），
      资金/解绑类操作会被**误拒**。此处自建遮罩，独立挂到 body 且 z-index 高于
      所有既有层（.mask 100 / .mask.stack 200 / .qrmask 200 / .agmask 300）。
   🔴 「确认 / 取消」为两个并排按钮，都明确可见可点。 */
.cfmask {
  position: fixed; inset: 0; z-index: 400; display: grid; place-items: center;
  background: rgba(16,24,40,.5); padding: 24px; overflow: auto;
}
.cf-modal { max-width: 420px; }
.cf-modal .cf-body { margin: 0; }
.cf-modal .actions button#cf-ok { font-weight: 600; }

/* 查看二维码弹层（独立挂载 · iframe 复用 /app/qrcode.html?embed=1）
   —— 与 .mask 分开：z-index 更高 + 独有 DOM，可叠在既有弹窗之上不被顶掉 */
.qrmask {
  position: fixed; inset: 0; z-index: 200; display: grid; place-items: center;
  background: rgba(16,24,40,.52); padding: 24px; overflow: auto;
}
.qrbox {
  width: 100%; max-width: 470px; background: var(--card); border-radius: var(--radius-lg);
  box-shadow: 0 24px 60px rgba(16,24,40,.30); overflow: hidden;
  display: flex; flex-direction: column;
}
.qrbox__hd {
  display: flex; align-items: center; gap: 10px; padding: 13px 14px 13px 18px;
  border-bottom: 1px solid var(--line-soft); font-size: var(--fs-15); font-weight: 600; color: var(--text);
}
.qrbox__x {
  margin-left: auto; width: 30px; height: 30px; padding: 0; border: 0; border-radius: var(--r-8);
  background: transparent; color: var(--text-mute); font-size: var(--fs-20); line-height: 1;
  cursor: pointer; transition: .16s;
}
.qrbox__x:hover { background: var(--line-soft); color: var(--text); }
.qrbox__fr { display: block; width: 100%; height: min(80vh, 820px); border: 0; background: #fff; }
@media (max-width: 560px) {
  .qrmask { padding: 12px; }
  .qrbox { max-width: none; }
  .qrbox__fr { height: min(84vh, 820px); }
}

/* ---------- ★ 613m/n/o/p 微信登录面板（官方 JS SDK 内嵌二维码 · 登录页**默认主入口**）----------
   大人令 2026-10-12：微信登录 = 默认，次级短信验证码，最后账号登录（顺序参照腾讯云登录卡）。
   —— 独立类名（.lr-wx-*），不与通用 .mask/.modal 抢样式。
   🔴🔴 613o（2026-10-13）：微信 iframe 内部文字色**由系统主题媒体查询决定**
     （`.web_qrcode_wrp{color:#000}` 默认黑；`@media (prefers-color-scheme:dark)` 内改白），
     `color_scheme` 参数只改 `data-weui-theme`、**改不动**这条 ⇒ 宿主**必须给跟随系统的底色**：
       浅色系统 → 白底 + 黑字（页面同为白底 ⇒ 无缝、无框）
       深色系统 → #191919（与微信 dark 页面同色）+ 白字 ⇒ 无缝可见
   🔴🔴 613p（大人 2026-10-13 选定 V1）：尺寸**回归微信原生**（iframe 300×400、内部码 282px），
     去掉 613n/o 的 `zoom:.62`（大人判定 .62 太小、与面板比例不合）。
     ⚠️ 微信 iframe 内部「码偏上、下方一片留白」的比例**是微信写死的**，无任何参数可改
     （`sizetype`/`bgcolor` 已僵尸、`href` 注入被硬编码关闭、`color_scheme` 只管 weui 主题）。 */
.lr-wx-qr {
  display: grid; justify-items: center; align-content: center;
  min-height: 404px;   /* = 降级按钮态留白；内嵌二维码时由 :has(iframe) 覆盖为自适应 */
}
/* 内嵌微信二维码时：底色**跟随系统**（须与微信文字色的媒体查询同步，否则白字落白底看不见） */
.lr-wx-qr:has(iframe) {
  background: #fff; border-radius: var(--r-12); min-height: 0;
}
@media (prefers-color-scheme: dark) {
  .lr-wx-qr:has(iframe) { background: #191919; }
}
.lr-wx-slot { display: grid; place-items: center; }
.lr-wx-slot iframe { display: block; border: 0; }   /* 613p：不缩放，用微信原生尺寸 */
/* 降级态：一颗大按钮（点击走整页跳转 `wechat/auth`；手机端会唤起微信） */
.lr-wx-go {
  display: inline-flex; align-items: center; gap: 9px; flex: 0 0 auto;
  height: 46px; padding: 0 24px;
  border: 1.5px solid #07C160; border-radius: var(--lr-radius);
  background: var(--lr-card-solid, #fff); color: #07C160;
  font-family: inherit; font-size: var(--fs-15); font-weight: 600;
  cursor: pointer; transition: background .18s, transform .18s;
}
.lr-wx-go svg { width: 20px; height: 20px; flex: 0 0 auto; }
.lr-wx-go:hover { background: var(--lr-brand-soft, #F0FBF5); transform: translateY(-1px); }
.lr-wx-note { margin: 12px 0 0; font-size: var(--fs-12-5); color: var(--lr-ink-3); text-align: center; }
@media (max-width: 560px) {
  .lr-wx-qr { min-height: 0; }   /* 小屏走「跳转按钮」，无需给 iframe 留高 */
}

/* 账号选择（同号多账号） */
.acc-list { margin-top: 16px; display: flex; flex-direction: column; gap: 10px; }
.acc-item {
  display: flex; align-items: center; gap: 12px; padding: 13px 14px;
  border: 1px solid var(--line); border-radius: var(--r-10); cursor: pointer; text-align: left;
  background: var(--card); width: 100%;
}
.acc-item:hover:not(:disabled) { border-color: var(--brand); background: var(--brand-soft); }
.acc-item .av {
  width: 34px; height: 34px; border-radius: var(--r-9); flex: none; display: grid; place-items: center;
  background: var(--brand-soft); color: var(--brand); font-weight: 700;
}
.acc-item .meta { flex: 1; min-width: 0; }
.acc-item .meta b { display: block; font-size: var(--fs-14); }
.acc-item .meta small { color: var(--text-dim); font-size: var(--fs-12-5); }
.acc-item .cur { color: var(--ok); font-size: var(--fs-12-5); }

/* ============================================================ 移动端兜底 */
@media (max-width: 760px) {
  .login { flex-direction: column; }
  .login-aside { flex: none; max-width: none; padding: 24px 20px; }
  .la-h1 { margin-top: 18px; font-size: var(--fs-21); }
  .la-lead, .la-points, .agent-strip { display: none; }
  .kw-row { margin-bottom: 4px; }
  .shell { flex-direction: column; }
  .side { position: static; width: auto !important; flex: none; height: auto; }
  .shell.is-collapsed .side-nav .grp { display: block; }
  .shell.is-collapsed .side-nav button.nav { justify-content: flex-start; padding: 10px 12px; gap: 10px; }
  .shell.is-collapsed .side-nav button.nav .lbl { display: inline; }
  .side-nav { display: flex; gap: 6px; overflow-x: auto; padding: 8px; }
  .side-nav .grp { display: none; }
  .side-nav button.nav { width: auto; white-space: nowrap; margin: 0; }
  .side-foot { display: none; }
  .content { padding: 14px; }
  .who .nm { display: none; }
}


/* ============================================================ 终端管理（419 批 · 版式照控台 10067）
   蓝本 = gkl-src/gkl-web/src/views/PaymentCodeView.vue（1:1 复刻旧控台）
   · 工具条：左「新 增」/ 右「刷新 · 列显示」
   · 表格：边框 + 斑马纹 + 全居中 + 紧凑（el-table border/stripe/small 的观感）
   · 行内动作 = 文字链接（复用全局 button.link，不另造按钮） */
.pc-bar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; flex-wrap: wrap; margin-bottom: 2px;
}
/* 页签（420 批：终端管理「收款单 ↔ 静态码」）—— 复用分页按钮观感 */
.pc-tabs { display: flex; align-items: center; gap: 8px; margin: 6px 0 12px; }
.pc-tabs button.is-cur { border-color: var(--brand); color: var(--brand); font-weight: 600; }

/* 渠道号（421 批：按机构分组 · 组内多项） */
.cn-rows { max-height: 46vh; overflow: auto; padding-right: 2px; }
.cn-pf {
  border: 1px solid var(--line); border-radius: var(--r-10);
  padding: 10px 12px; margin: 8px 0; background: var(--line-soft);
}
.cn-pf-h { display: flex; align-items: baseline; gap: 8px; margin-bottom: 8px; }
.cn-pf-h b { font-size: var(--fs-13-5); color: var(--text); }
.cn-pf-h .sub { font-size: var(--fs-12); color: var(--text-mute); }
/* 组内一行：[支付方式] [渠道号] [删除] —— 🔴 按钮必须 `flex:0 0 auto` + `nowrap`，否则被压扁成竖排文字 */
.cn-list { display: block; }
/* ★ 426：每行升级为「两排卡片」—— 上排 类型 + 渠道号 + 删除；下排 名称 + 认证码 */
.cn-row { display: block; margin: 8px 0; padding: 8px 10px;
  border: 1px solid var(--line-soft); border-radius: var(--r-9); }
.cn-l1, .cn-l2 { display: flex; align-items: center; gap: 8px; }
.cn-l2 { margin-top: 6px; }
.cn-row select.cn-type { flex: 0 0 96px; }
.cn-row input.cn-no { flex: 1 1 auto; min-width: 0; }
.cn-row button.cn-del { flex: 0 0 auto; white-space: nowrap; }
.cn-row input.cn-name { flex: 1 1 auto; min-width: 0; }
.cn-auth { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 8px; white-space: nowrap; }
.cn-auth .sub { font-size: var(--fs-12); color: var(--text-mute); }
.cn-view { font-size: var(--fs-12-5); color: var(--brand); cursor: pointer; }
.cn-view[hidden] { display: none; }
.cn-pf > button.cn-add { margin-top: 8px; }
.cn-pf-act { display: flex; align-items: center; gap: 8px; margin-top: 8px; flex-wrap: wrap; }
.cn-pf-act .mini { flex: 0 0 auto; white-space: nowrap; }
.cn-pf-act .sub { font-size: var(--fs-12); color: var(--text-mute); }
/* ★ 721-E（大人令 2026-10-16）：「我方公钥」只读框 —— 机构验签/加密回包用，
   汇付·斗拱须复制到控台【开发设置】→【系统公钥】。
   🔴 与可编辑的「我方私钥 / 机构公钥」两框**视觉区分**：
      实线边框 + 主文字色 = 可改；**虚线边框 + 次文字色 + 更小字号** = 只读产物。
      （🔴 不能用灰底 —— `.cn-pf` 卡片底就是 `--line-soft`，灰底会糊成一片看不出是输入框还是输出框） */
.pk-fld { margin-top: var(--sp-12); }
.pk-box { display: flex; gap: var(--sp-8); align-items: flex-start; }
/* ★ 大人令 10-17：这格**可粘贴**（能填也能算）⇒ 用正常输入框外观（实线 + 正文色），
   不再用「虚线 + 次文字色」的只读长相 —— 那个长相会让人以为不能改。 */
.pk-box textarea {
  flex: 1 1 auto; min-width: 0; background: var(--card); color: var(--text);
  border-style: solid; font-size: var(--fs-11-5); line-height: 1.5; cursor: text;
}
.pk-box .mini { flex: 0 0 auto; white-space: nowrap; }
/* 真正只读的场合（如降级态）仍要看得出来 */
.pk-box textarea[readonly] { background: var(--card); color: var(--text-dim); border-style: dashed; }
.pk-fld .pk-hint { margin: var(--sp-6) 0 0; font-size: var(--fs-11-5); color: var(--text-mute); line-height: 1.6; }
.pk-fld .pk-hint b { color: var(--text-dim); }
/* 422 批 · 商户「绑定机构」：默认机构单选圈（`align-self` 治 `.cn-pf-h{align-items:baseline}` 导致的错位） */
.mb-def {
  display: inline-flex; align-items: center; gap: 5px; align-self: center;
  margin-right: 2px; font-size: var(--fs-12); color: var(--text-dim);
  cursor: pointer; white-space: nowrap;
}
.mb-def input { width: auto; flex: none; accent-color: var(--brand); }
/* 删除确认弹窗里的「将被删除」清单 */
.del-list {
  margin: 8px 0 4px; padding: 10px 12px; border-radius: var(--r-10);
  border: 1px solid var(--line); background: var(--line-soft);
  font-size: var(--fs-13); color: var(--text-dim); line-height: 1.9;
}
.del-list code { font-size: var(--fs-12); }

/* 多选下拉（420 批 · 大人偏好「级联多选」，体验优先）—— 按钮 + 勾选面板 */
.ms { position: relative; display: inline-block; }
.ms-btn { display: inline-flex; align-items: center; gap: 6px; }
.ms-cnt {
  display: inline-block; min-width: 16px; padding: 0 5px; border-radius: var(--r-9);
  background: var(--brand); color: #fff; font-size: var(--fs-11); line-height: 16px; text-align: center;
}
.ms-caret { font-size: var(--fs-10); opacity: .7; }
.ms-menu {
  position: absolute; left: 0; top: 34px; z-index: 30; min-width: 250px;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r-10);
  box-shadow: var(--elev-1); padding: 8px 10px;
}
.ms-menu label {
  display: flex; align-items: center; gap: 8px; padding: 5px 2px;
  font-size: var(--fs-13); color: var(--text); cursor: pointer;
}
.ms-menu input { width: auto; flex: none; }
.ms-menu code { font-size: var(--fs-11-5); color: var(--text-mute); margin-left: auto; }
.pc-bar-left, .pc-bar-right { display: flex; align-items: center; gap: 8px; }
.pc-col-wrap { position: relative; }
.pc-col-menu {
  position: absolute; right: 0; top: 34px; z-index: 30; min-width: 186px;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r-10);
  box-shadow: var(--elev-1); padding: 8px 10px;
}
.pc-col-menu label {
  display: flex; align-items: center; gap: 8px; padding: 5px 2px;
  font-size: var(--fs-13); color: var(--text); cursor: pointer;
}
.pc-col-menu input { width: auto; flex: none; }

table.pc-table { width: 100%; border-collapse: collapse; font-size: var(--fs-13); }
table.pc-table th,
table.pc-table td {
  border: 1px solid var(--line); padding: 7px 10px;
  text-align: center; vertical-align: middle;
}
table.pc-table th {
  background: var(--line-soft); color: var(--text-dim);
  font-weight: 600; font-size: var(--fs-12-5); white-space: nowrap;
}
table.pc-table tbody tr:nth-child(even) td { background: var(--line-soft); }
table.pc-table tbody tr:hover td { background: var(--brand-soft); }
.pc-code {
  display: block; word-break: break-all;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
.pc-dash { color: var(--text-mute); }
/* 行内文字按钮 —— 全局 `button.link` 已有底色/下划线规则，这里只调密度 */
td button.pc-act { font-size: var(--fs-12-5); padding: 1px 3px; }
td button.pc-act + button.pc-act { margin-left: 6px; }
td button.pc-act:disabled { color: var(--text-mute); text-decoration: none; }
td button.pc-act.pc-danger { color: var(--bad); }
/* ★ 2026-10-14：`gap` 取 6px（原此处 2px 早被后文同名规则覆盖为 6px ⇒ 已合并到本处，死值消除） */
.pc-ops { display: flex; align-items: center; justify-content: center; gap: 6px; flex-wrap: nowrap; }

/* 分页条（照控台：右对齐 · 共 N 条 · « ‹ 页码 › »） */
.pc-pager {
  display: flex; align-items: center; justify-content: flex-end; gap: 12px;
  margin-top: 14px; font-size: var(--fs-13); color: var(--text-dim);
}
.pc-pager .btns { display: flex; gap: 6px; align-items: center; }
.pc-pager button.is-cur { border-color: var(--brand); color: var(--brand); font-weight: 600; }

/* 轻提示（复制链接成功等） */
.pc-toast {
  position: fixed; left: 50%; bottom: 32px; transform: translateX(-50%);
  padding: 9px 15px; border-radius: var(--r-9); font-size: var(--fs-12-5); color: #fff;
  background: rgba(22,30,44,.92); box-shadow: 0 12px 30px -12px rgba(0,0,0,.5);
  z-index: 200; pointer-events: none;
}
html[data-theme='dark'] .pc-toast { background: rgba(240,244,250,.94); color: #16202C; }

/* ---------- 449b：首页（概览）---------- */
/* 快捷入口：一排「图标 + 文字」的胶囊按钮（图标来自 ICON，随主题着色） */
.hm-quick { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 14px; }
button.hm-chip {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 9px 14px; border-radius: var(--r-9); font-size: var(--fs-13-5);
}
button.hm-chip .ico { display: inline-flex; }
button.hm-chip svg { width: 16px; height: 16px; display: block; }
/* 提特异性压过全局 button:hover（否则悬停被染成主题色底，图标与文字对比度丢失） */
button.hm-chip:hover:not(:disabled) { border-color: var(--brand); background: var(--brand-soft); color: var(--brand); }

/* ============================================================================
 * 449c 批（大人令）：首页**照账单台首页样式**重做（gkl-bill/public/admin/app.css）。
 * ----------------------------------------------------------------------------
 * ★ 结构逐段搬：身份信息卡 + 概览卡（两栏）→ 收款数据概览（今日/本周/本月）
 *   → 收款趋势·近 7 日（SVG 双轴）→ 最近收款表。
 * 🔴 原版颜色是**硬编码浅色**（#fff/#f8fafd/#1677ff…），这里**全部换成应用台令牌**
 *    ⇒ 浅色/深色外观都正确（原版直接抄过来在深色下会瞎眼）。
 * ★ 类名与既有样式**零冲突**（逐个 grep 核对过）。
 * ==========================================================================*/

/* ---------- 两栏：身份信息卡 + 收款概览卡 ---------- */
.home-top { display: grid; grid-template-columns: 1fr 1.4fr; gap: 16px; }
.home-top .card { margin-bottom: 16px; }
/* 465：渠道商/平台无「账户余额」框 ⇒ 身份卡独占整行 */
.home-top.solo { grid-template-columns: 1fr; }

/* 身份信息卡 */
.hinfo .hinfo-body { display: flex; gap: 14px; align-items: flex-start; }
.hinfo .avatar {
  width: 46px; height: 46px; border-radius: 50%; flex: 0 0 auto;
  background: linear-gradient(135deg, var(--brand), var(--brand-lite)); color: #fff;
  display: flex; align-items: center; justify-content: center; font-size: var(--fs-18); font-weight: 700;
}
.hinfo .rows { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 11px; }
.hinfo .rows > div { display: flex; gap: 10px; font-size: var(--fs-13); align-items: baseline; }
.hinfo .rows span { flex: 0 0 auto; min-width: 76px; white-space: nowrap; color: var(--text-dim); }
.hinfo .rows b { color: var(--text); font-weight: 600; min-width: 0; word-break: break-all; }
.hinfo .rows b.mono { font-family: ui-monospace, Menlo, Consolas, monospace; letter-spacing: .3px; }

/* 卡片标题（账单台风格：左标题 + 右工具） */
.card-title { font-size: var(--fs-15); font-weight: 600; margin: 0 0 var(--sp-14); display: flex; justify-content: space-between; align-items: center; gap: var(--sp-12); }
.card-title .subtle { font-size: var(--fs-12-5); color: var(--text-mute); font-weight: 400; }
.card-title .fbtns { display: flex; gap: var(--sp-10); align-items: center; }
/* ★ r772（大人令）：进件页的按钮**紧贴标题右侧**，不再被 space-between 推到整行最右 */
.card-title.ob-head { justify-content: flex-start; }

/* 收款概览卡（视觉对齐账单台「账户余额」卡；🔴 语义=收款，
   **渠道商视角不出资金余额** —— 守「渠道商不持资金」红线） */
.bal-total { font-size: var(--fs-12-5); color: var(--text-mute); font-weight: 400; }
.bal-total .bal-num { color: var(--text); font-weight: 700; font-size: var(--fs-14); }
.bal-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; }
.bal { border: 1px solid var(--line); border-radius: var(--r-8); padding: 16px; background: var(--line-soft); }
/* 两主题通用：用**固定品牌色半透明渐变**叠在卡片底上，不用 color-mix（兼容性更稳） */
.bal.is-primary { background: linear-gradient(135deg, rgba(22,104,220,.10), rgba(22,104,220,.03)); border-color: rgba(22,104,220,.20); }
.bal.is-amber   { background: linear-gradient(135deg, rgba(180,83,9,.10), rgba(180,83,9,.03)); border-color: rgba(180,83,9,.20); }
.bal-k { font-size: var(--fs-12-5); color: var(--text-dim); margin-bottom: 8px; }
/* ★★ r909（大人令 2026-10-26）：可用余额旁的**小眼睛** —— 人点一下才向上游查（r880 铁律：不自动出网）。
   · `is-busy` 只做「图标转圈 + 禁用」，绝不再替换 textContent（否则图标会消失、得靠重绘复原）。
   · `on` = 当前金额已是上游实时值（眼睛变品牌色，暗示「已看过」）。 */
.bal-k { display: flex; align-items: center; gap: 6px; }
.bal-eye { display: inline-flex; align-items: center; justify-content: center; flex: none;
  width: 20px; height: 20px; padding: 0; border: 0; border-radius: 5px;
  background: transparent; color: var(--text-mute); cursor: pointer; transition: color .15s; }
.bal-eye svg { width: 15px; height: 15px; display: block; }
.bal-eye:hover { color: var(--brand); }
.bal-eye.on { color: var(--brand); }
.bal-eye:disabled { cursor: default; }
.bal-eye.is-busy svg { animation: balEyeSpin .9s linear infinite; }
@keyframes balEyeSpin { to { transform: rotate(360deg); } }
.bal-v { font-size: var(--fs-26); font-weight: 700; line-height: 1.15; color: var(--text); letter-spacing: .3px; }
.bal.is-primary .bal-v { color: var(--brand); }
.bal.is-amber .bal-v { color: var(--warn); }
.bal-foot { margin-top: 12px; display: flex; align-items: center; gap: 10px; }
/* 🔴 按钮必须 flex:none + nowrap：否则被 flex 压窄后「提现」两字会竖排（踩过） */
.bal-foot button { flex: none; white-space: nowrap; }
.bal-sub { font-size: var(--fs-12); color: var(--text-mute); }
.bal-note { margin-top: 12px; font-size: var(--fs-12); color: var(--warn); }
.bal-line { margin-top: 14px; padding-top: 12px; border-top: 1px dashed var(--line); font-size: var(--fs-12); color: var(--text-mute); }
.bal-src { margin-top: 8px; font-size: var(--fs-12); color: var(--text-mute); }
.bal-src.ok { color: var(--ok, #16a34a); }
.bal-src.warn { color: var(--warn); }
/* ★★ r911：商户列表「商户余额」单元格 —— 缺省星号，点小眼睛后才出数（未查 = 灰，已查 = 正常） */
.mbal-v { font-variant-numeric: tabular-nums; font-weight: 600; color: var(--text-mute); }
.mbal-v.up { color: var(--text); }
.mbal-v.loc { color: var(--text-dim, var(--text)); }
.mbal-v.bad { color: var(--warn); font-weight: 500; }
td .mbal-v { margin-right: 4px; }

/* ---------- 收款数据概览（今日 / 本周 / 本月）---------- */
.period-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
.pcell { border: 1px solid var(--line); border-radius: var(--r-8); padding: 15px 16px; background: var(--card); }
.pcell .pk { font-size: var(--fs-13-5); font-weight: 600; margin-bottom: 12px; color: var(--text); }
.pcell .prow { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 9px; font-size: var(--fs-13); color: var(--text-dim); }
.pcell .prow b { font-size: var(--fs-19); font-weight: 700; color: var(--text); }
.pcell .pdiff { margin-top: 2px; padding-top: 10px; border-top: 1px dashed var(--line); font-size: var(--fs-12); color: var(--text-mute); }
.pcell .pdiff em { font-style: normal; font-weight: 600; color: var(--text-mute); }
.pcell .pdiff.up em { color: var(--ok); }
.pcell .pdiff.down em { color: var(--bad); }

/* ---------- 收款趋势（内联 SVG 双轴）---------- */
.legend { display: inline-flex; align-items: center; gap: 7px; font-size: var(--fs-12-5); color: var(--text-dim); font-weight: 400; }
.legend i { display: inline-block; }
.legend .lg-bar { width: 11px; height: 11px; border-radius: var(--r-3); background: linear-gradient(180deg, var(--brand-lite), var(--brand)); margin-right: 5px; }
.legend .lg-line { width: 15px; height: 2px; background: var(--ok); margin: 0 5px 0 12px; }
.chart-host { width: 100%; }
.trend-svg { width: 100%; height: 250px; display: block; }
/* 🔴 SVG 内颜色走 CSS 类 ⇒ 随主题切换（原版在标签里硬编码，深色下轴字看不见） */
.trend-svg .ct { font-size: var(--fs-11); fill: var(--text-mute); }
.trend-svg .axis { stroke: var(--line); }
.trend-svg .ln { stroke: var(--ok); }
.trend-svg .dot { fill: var(--ok); stroke: var(--card); }
.chart-foot { text-align: right; font-size: var(--fs-13); color: var(--text-dim); padding-top: 8px; }
.chart-foot b { color: var(--text); font-size: var(--fs-15); }

/* ---------- 首页内嵌小表：末列不做吸附 ---------- */
table.tbl.plain th:last-child, table.tbl.plain td:last-child { position: static; box-shadow: none; background: var(--card); }
table.tbl.plain { min-width: 0; }

@media (max-width: 1180px) {
  .home-top { grid-template-columns: 1fr; }
  .bal-grid, .period-grid { grid-template-columns: 1fr; }
}

/* ============================================================ 449e 批 · 终端管理（照控台 10067 1:1）
   蓝本 = gkl-web/src/views/PaymentCodeView.vue。本节只补「本页新用到的件」，不改既有视觉。
   · 工具条两枚圆形图标按钮（刷新 / 列显隐）
   · 终端编码列里的复制图标 / 空表行
   · 分页的「条数 + 前往」（照 el-pagination 的 sizes / jumper 两件套）
   · 表单开关（把 `.keysrc` 那套抽成通用 `.pc-sw`）与表单块排版 */
.pc-ico {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; padding: 0; border-radius: 50%;
}
.pc-ico svg { display: block; }
.pc-copy { display: inline-flex; align-items: center; padding: 1px 3px; margin-left: 6px; vertical-align: middle; }
td .pc-empty { color: var(--text-mute); padding: 26px 0; }

/* 分页：条数下拉 + 前往页码 */
/* ★ 2026-10-14：`flex`/`width` 已从后文同选择器的补丁合并到本处（属性互补，合并后行为不变） */
.pc-pager select.pg-size { padding: 3px 6px; font-size: var(--fs-12-5); border-radius: var(--r-6); flex: none; width: auto; }
.pc-pager .pg-jump { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.pc-pager .pg-jump input {
  width: 54px; padding: 3px 6px; font-size: var(--fs-12-5); border-radius: var(--r-6); text-align: center;
}

/* 开关：`.keysrc` 那套抽成通用件（终端表单用；结构与 keysrc 完全一致 ⇒ 观感一致） */
.pc-sw { display: inline-flex; align-items: center; gap: 9px; cursor: pointer; white-space: nowrap; margin-top: 8px; }
.pc-sw input { position: absolute; opacity: 0; width: 0; height: 0; }
.pc-sw .sw-track {
  width: 42px; height: 23px; border-radius: var(--r-full); flex: none; position: relative;
  background: var(--text-mute); transition: background .18s;
}
.pc-sw .sw-track::after {
  content: ''; position: absolute; top: 2px; left: 2px; width: 19px; height: 19px;
  border-radius: 50%; background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,.28);
  transition: transform .18s;
}
.pc-sw input:checked + .sw-track { background: var(--brand); }
.pc-sw input:checked + .sw-track::after { transform: translateX(19px); }
.pc-sw input:focus-visible + .sw-track { box-shadow: 0 0 0 3px rgba(22,104,220,.22); }
.pc-sw .sw-txt { font-size: var(--fs-13-5); font-weight: 600; color: var(--text); }
/* ★ r923（大人令 2026-10-26）：能力未开通 ⇒ **显示但置灰**（不做隐藏），鼠标不可点，旁边标「未开通」 */
.pc-sw--lock { opacity: .55; cursor: not-allowed; }
.pc-sw--lock input, .pc-sw--lock .sw-track { cursor: not-allowed; }
.pc-sw--lock .sw-txt { color: var(--text-dim); }
.pc-sw .sw-lock {
  font-size: var(--fs-12); font-weight: 700; line-height: 1; color: var(--warn);
  border: 1px dashed currentColor; border-radius: var(--r-6); padding: 2px 5px;
}
/* ★★★ r971（大人令 2026-10-28）：终端「关联手机号」—— 一枚开关 + 一张勾选清单
   · 开关：上层（商户功能应用）没开通 ⇒ `.pc-sw--lock` 置灰 + 「未开通」标记（r923 同一套） */
.tm-pb { display: flex; flex-direction: column; gap: var(--sp-6); min-width: 0; }
.tm-pb .pc-sw { margin-top: 0; }
.tm-pb .tip { margin: 0; }
.tm-pb-list {
  display: flex; flex-wrap: wrap; gap: var(--sp-6) var(--sp-16);
  padding: var(--sp-8) var(--sp-11);
  border: 1px solid var(--line); border-radius: var(--r-8); background: var(--line-soft);
}
.pc-check {
  display: inline-flex; align-items: center; gap: var(--sp-6);
  font-size: var(--fs-13-5); color: var(--text); cursor: pointer;
  white-space: nowrap; flex: none;   /* 名称不许在框内折断（换行交给外层 flex-wrap） */
}
.pc-check input { margin: 0; accent-color: var(--brand); cursor: pointer; }
/* ★ r923：对客密钥申请 —— 公钥支持「选文件 / 拖文件」，不再只能手粘 */
.ak-filebar { display: flex; align-items: center; gap: var(--sp-10); margin-bottom: var(--sp-6); flex-wrap: wrap; }
.ak-filebar .ak-sub { font-size: var(--fs-12); color: var(--text-dim); }
textarea.ak-drop { outline: 2px dashed var(--brand); outline-offset: -4px; background: var(--brand-soft, rgba(22,104,220,.06)); }

/* 终端表单：收银台开关一区两列（窄屏落单列）；必填星号；说明文字 */
.tm-form .tm-sws { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 2px 18px; }
@media (max-width: 900px) { .tm-form .tm-sws { grid-template-columns: 1fr; } }
/* ★ 2026-10-16（大人令）：「预下单小程序管理」是「预下单收银台」的**下级项** ——
   作为该网格的**整行**元素紧随其后（`grid-column: 1/-1` ⇒ 恒自成一行、不受两列排布挤压）。 */
.tm-form .tm-app-inline { grid-column: 1 / -1; min-width: 0; margin-top: 2px; }
.tm-form .tm-app-inline select { max-width: 100%; }
/* ★★★ r969（甲方案）：开关下面那块是「收款商户 → 机构 → 号」三联格 ——
   同排三列（窄屏 auto-fit 自动折行），比竖着堆三行省一半纵向空间。 */
.tm-form .tm-ch-pf { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 4px 14px; }
.tm-form .tm-ch-pf > .fi { margin-top: var(--sp-6); min-width: 0; }
.tm-form .req { color: var(--bad); }
.tm-form .tip { margin-top: 8px; }

/* 宽表底宽 ⇒ 超出由 .tbl-wrap 横向滚动承接（与控台 avue 同一观感）。
   ★ 2026-10-14：本条是 `.tbl-wrap > table.pc-table` 的**唯一定义**。
   原有一处 `min-width:1180px` 基线（同特异性、位置更前）被本条完全覆盖 = 死规则，已删；
   删除前后实际生效值同为 1280px ⇒ **视觉零变化**。 */
.tbl-wrap > table.pc-table { min-width: 1280px; }

/* ---------- 449e 修正（首轮实拍发现，2026-10-09）
   ① 行内动作列被 flex 压扁 ⇒ 「编 辑 / 删 除 / 订单付款」文字竖排
      （全局 `button:active`/`flex` 会压缩子项 —— 正解是给子项 `flex:0 0 auto` + `nowrap`）
   ② 分页控件被拉伸：全局 `select{width:100%}` 让「20条/页」吃掉整行，把其余件挤开 */
td .pc-ops button.pc-act { flex: 0 0 auto; white-space: nowrap; }
table.pc-table th:last-child, table.pc-table td:last-child { white-space: nowrap; }
.pc-pager .pg-total { flex: none; white-space: nowrap; }
.pc-pager .btns { flex: none; }
.pc-pager .pg-jump { flex: none; }
.pc-pager .pg-jump input { flex: none; width: 54px; }

/* ============================================================ 449g 批：终端「四能力」
   分组 / 固定金额 / 强制备注 / 有效期
   —— 列表四列 + 表单三段分段控件 + 分组管理弹窗。
   🔴 全部新增类都带 `tm-` / `tg-` / `pc-tag` 前缀，不与既有类冲突。 */

/* ---- 分段控件（收款方式 / 备注 / 有效期 三处共用）----
   🔴 悬停态必须**提特异性**（`.tm-seg button:hover:not(.is-on)`）——
      全局 `button:hover` 同为 (0,1,1)，会让选中态被主题色洗掉（424 批血教训）。 */
.tm-seg {
  display: inline-flex; align-items: stretch;
  border: 1px solid var(--line); border-radius: var(--r-10); overflow: hidden;
  background: var(--line-soft);
}
.tm-seg button {
  flex: 0 0 auto; white-space: nowrap;
  border: 0; border-radius: 0; background: transparent; color: var(--text-dim);
  padding: 7px 14px; font-size: var(--fs-13); font-weight: 600; cursor: pointer;
  transition: background .15s, color .15s;
}
.tm-seg button + button { border-left: 1px solid var(--line); }
.tm-seg button:hover:not(.is-on) { background: var(--card); color: var(--text); }
.tm-seg button.is-on {
  background: var(--card); color: var(--brand); font-weight: 700;
  box-shadow: inset 0 0 0 1.5px var(--brand);
}

/* ---- 次级字段区（随分段选择显隐）---- */
.tm-sub {
  margin-top: 10px; padding: 10px 12px; border-radius: var(--r-10);
  border: 1px dashed var(--line); background: var(--line-soft);
}
.tm-sub[hidden] { display: none; }
.tm-sub .fi:first-child { margin-top: 0; }
.tm-sub .tip { margin-top: 8px; font-size: var(--fs-12-5); color: var(--text-mute); line-height: 1.75; }
.tm-sub .tip b { color: var(--text-dim); }

/* ---- 分组下拉 + 「分组管理」入口 ---- */
.tm-grp { display: flex; align-items: center; gap: 8px; }
.tm-grp select { flex: 1 1 auto; min-width: 0; }
.tm-grp button { flex: 0 0 auto; white-space: nowrap; }

/* ---- 终端表单弹窗：内容变多 ⇒ 自身限高滚动（`.mask` 是 grid 居中，
      子项一旦高过视口会向上溢出且滚不到顶 ⇒ 必须让弹窗自己滚）---- */
.modal.tm-modal { max-width: calc(620px * var(--ui-s)); max-height: calc(100vh - 48px); overflow-y: auto; }

/* ---- 列表四列：分组标签 / 金额 / 备注 / 有效期 ---- */
.pc-tag {
  display: inline-block; padding: 1px 8px; border-radius: var(--r-full);
  font-size: var(--fs-12); border: 1px solid rgba(22,104,220,.26);
  background: var(--brand-soft); color: var(--brand); white-space: nowrap;
}
.pc-tag.plain { background: var(--line-soft); color: var(--text-mute); border-color: var(--line); }
.pc-amt { font-weight: 700; color: var(--text); white-space: nowrap; }
.pc-amt .yuan { font-size: var(--fs-11-5); color: var(--text-mute); font-weight: 600; }
.pc-rmk { font-size: var(--fs-12); color: var(--text-mute); margin-top: 3px; }
.pc-exp { font-size: var(--fs-12); color: var(--text-mute); margin-top: 3px; white-space: nowrap; }

/* ---- 分组管理弹窗（独立挂载，可叠在终端表单之上）---- */
.tg-list { max-height: 42vh; overflow: auto; margin: 10px 0 4px; }
.tg-row {
  display: flex; align-items: center; gap: 8px; padding: 8px 10px;
  border: 1px solid var(--line-soft); border-radius: var(--r-9); margin-bottom: 8px;
  background: var(--card);
}
.tg-row .tg-name { flex: 1 1 auto; min-width: 0; font-size: var(--fs-13-5); font-weight: 600; color: var(--text); }
.tg-row .tg-edit { flex: 1 1 auto; min-width: 0; }
.tg-row .tg-cnt { flex: 0 0 auto; font-size: var(--fs-12); color: var(--text-mute); white-space: nowrap; }
.tg-row button { flex: 0 0 auto; white-space: nowrap; }
.tg-add { display: flex; align-items: center; gap: 8px; margin-top: 10px; }
.tg-add input { flex: 1 1 auto; min-width: 0; }
.tg-add button { flex: 0 0 auto; white-space: nowrap; }
.tg-empty { padding: 20px; text-align: center; color: var(--text-mute); font-size: var(--fs-13); }

/* ---------- 449i · 订单付款弹窗新增（订单标题 / 数量 / 有效期 / 附件 / 备注） ---------- */
.op-filerow { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.op-filerow .mini { flex: 0 0 auto; white-space: nowrap; }
.op-fileinfo { display: flex; align-items: center; gap: 8px; font-size: var(--fs-12-5); color: var(--text-mute); min-height: 22px; }
.op-fileinfo .op-att {
  display: inline-block; max-width: 340px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  padding: 2px 9px; border-radius: var(--r-full); font-size: var(--fs-12);
  background: var(--brand-soft); color: var(--brand); border: 1px solid rgba(22,104,220,.26);
}
.op-fileinfo .link { flex: 0 0 auto; }

/* ======================== 452 批 · 余额付款 / 功能开关 ======================== */
/* 文本语义色（此前只有 .ok；补 .warn/.bad，与 note/badge 同一套变量） */
.warn { color: var(--warn); }
.bad  { color: var(--bad); }

/* 复选行（保存为常用收款人 / 开关）
   🔴 全局 `input { width: 100% }` 会把 `checkbox` 撑满整行、把标签文字挤到最右（同一行的
     复选框看起来「跑到中间」）。凡「复选框 + 文字」的行都必须显式收回宽度，并给 `nowrap`
     ——否则窄单元格（如「状态」列）里的「已开启」会被逐字竖排。 */
.ck { display: inline-flex; align-items: center; gap: 8px; white-space: nowrap; }
.ck > input[type="checkbox"] { width: auto; flex: 0 0 auto; margin: 0; }
label.fld.ck { display: flex; align-items: center; gap: 8px; margin: 12px 0 4px; white-space: nowrap; }
label.fld.ck input { width: auto; flex: 0 0 auto; margin: 0; }

/* 余额付款页：归属商户条 + 三 tab */
.bp-mch { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: var(--fs-13); color: var(--text-dim); }
.bp-mch code { color: var(--text); }
.bp-tabs { display: flex; gap: 8px; margin-block: 4px 14px; flex-wrap: wrap; }
.bp-tab {
  padding: 7px 16px; border-radius: var(--r-9); border: 1px solid var(--line);
  background: var(--card); color: var(--text-dim); cursor: pointer; font-size: var(--fs-13-5);
}
.bp-tab:hover { border-color: var(--brand); color: var(--brand); }
.bp-tab.on { background: var(--brand); border-color: var(--brand); color: var(--on-brand); font-weight: 600; }

/* ---- 707 · 余额付款「放行策略」条 + 设置面板 ---- */
.bp-polbar {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  margin-block: 10px 14px; flex-wrap: wrap;
}
.bp-polbar > div { min-width: 0; }
.bp-polbar .sub { display: block; }

/* ============================================================ r948 · 余额付款对齐重做
   ★★ 大人令 2026-10-27「界面对齐一下」（截图 ① 单笔付款表单）。原先的问题：
     ① 表单直接铺满卡片 ⇒ 在 2.5K/4K 屏上一列宽近 900px，输入框被拉成「细长条」；
     ② `label.fld` 是 `display:block` + `margin-top:12px`，行距靠外边距堆，控件高低不齐；
     ③ 必填没有视觉标记，全靠 placeholder 里的「必填」二字。
   ⇒ 做法：**约束表单宽度**（860px 一屏可读完）+ **每行一条 `display:grid` 双列** +
      **标签单独一行（span）且固定行高** + **控件统一 36px 高** + **必填打红星**。
   🔴 显隐（对公/对私）仍用 `display:none`：grid 会自动回流，不留空洞。 */
.bp-balcard {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-16);
  margin-block: var(--sp-10) var(--sp-14); flex-wrap: wrap;
}
/* ★ r984：余额标签行里要放那只小眼睛（三处共用 `balEyeHtml`）⇒ 用 flex 让图标与文字中线对齐 */
.bp-bal-lb { display: flex; align-items: center; flex-wrap: wrap; gap: 6px;
  font-size: var(--fs-12-5); color: var(--text-dim); letter-spacing: .3px; }
.bp-bal-v {
  font-size: calc(24px * var(--ui-s)); font-weight: 700; line-height: 1.2;
  color: var(--text); font-variant-numeric: tabular-nums; letter-spacing: .2px;
}
.bp-bal-v.is-masked { letter-spacing: 4px; color: var(--text-mute); font-weight: 600; }
.bp-bal-sub { margin-top: 2px; font-size: var(--fs-12); color: var(--text-dim); }
.bp-bal-sub b { font-weight: 600; color: var(--text); }
.bp-bal-act { display: flex; align-items: center; gap: var(--sp-8); flex-wrap: wrap; }

.bp-form { min-width: 0; }
/* 单笔卡片整体收窄：标题栏、字段区、按钮行**同一宽度**（否则超宽屏上「选择常用收款人」
   会飘到卡片最右端、离表单 800px 远，看着像两件事） */
/* ★★ r951（大人令「还是不齐啊」）：单笔付款卡片原来限宽 920px ⇒ 右边缘与上方
   「放行策略 / 可用余额」两张全宽卡片差了整整一截，视觉上就是「不齐」。
   现在卡片恢复**全宽**（与兄弟卡片同宽、四边对齐），靠 3 列网格控制单格宽度，
   而不是靠缩窄整张卡片。 */
.bp-single-card { max-width: none; }
.bp-frow {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--sp-14) var(--sp-20); margin-top: var(--sp-12);
}
/* 单格：竖排「标签行 + 控件」，标签行固定高 ⇒ 同行两格基线必定对齐 */
.bp-frow > label.fld {
  display: flex; flex-direction: column; gap: var(--sp-6);
  margin: 0; min-width: 0; font-size: var(--fs-13); color: var(--text-dim);
}
.bp-frow > label.fld > span.lb {
  display: flex; align-items: center; gap: 4px;
  height: calc(18px * var(--ui-s)); line-height: 1.4; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}
.bp-frow > label.fld > span.lb em.req {
  font-style: normal; font-weight: 700; color: var(--bad); line-height: 1;
}
.bp-frow > label.fld > input,
.bp-frow > label.fld > select {
  margin-top: 0; height: calc(36px * var(--ui-s)); line-height: 1.2;
}
.bp-frow > label.fld > input::placeholder { color: var(--text-mute); }
/* 条件字段整格隐藏（对公 ⇄ 对私）：grid 自动回流，不留空位 */
.bp-frow > label.fld[hidden] { display: none !important; }
/* 勾选框作为网格最后一格：横向排列、贴控件底边（与同行输入框同一条底基线） */
.bp-frow > label.fld.ck {
  display: flex; flex-direction: row; align-items: center; gap: var(--sp-8);
  align-self: end; height: calc(36px * var(--ui-s));
  margin: 0; white-space: nowrap; cursor: pointer;
}
.bp-frow > label.fld.ck > input {
  width: 15px; height: 15px; margin: 0; flex: none; padding: 0;
  accent-color: var(--brand);
}
.bp-frow > label.fld.ck > span { color: var(--text-dim); font-size: var(--fs-13); }
@media (max-width: 1180px) {
  .bp-frow { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 760px) {
  .bp-frow { grid-template-columns: 1fr; }
  .bp-frow > label.fld.ck { align-self: start; }
}

.bp-pol-sec { margin-top: 16px; }
.bp-pol-sec h4 { margin: 0 0 8px; font-size: var(--fs-13-5); color: var(--text-dim); font-weight: 600; }
.bp-pol-list { display: flex; flex-direction: column; gap: 8px; }
.bp-pol-opt {
  display: flex; align-items: flex-start; gap: 10px; padding: 10px 12px;
  border: 1px solid var(--line); border-radius: var(--r-9); cursor: pointer;
  background: var(--card); transition: border-color .12s, background .12s;
}
.bp-pol-opt:hover { border-color: var(--brand); }
.bp-pol-opt.on { border-color: var(--brand); background: var(--brand-soft, var(--line-soft)); }
.bp-pol-opt.off { opacity: .6; cursor: not-allowed; }
.bp-pol-opt input { width: auto; flex: 0 0 auto; margin: 4px 0 0; }
.bp-pol-opt > span { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.bp-pol-opt b { font-weight: 600; }
.bp-pol-opt em { font-style: normal; font-size: var(--fs-12-5); color: var(--text-mute); }
.tag-wait {
  display: inline-block; margin-left: 6px; padding: 1px 6px; border-radius: var(--r-4, 4px);
  font-size: var(--fs-11); font-weight: 500; vertical-align: middle;
  background: var(--line-soft); color: var(--text-mute); border: 1px solid var(--line);
}

/* ---- 707 附 · 「智能体制单」入口预留（大人令 2026-10-15）----
   🔴 本批未接入 ⇒ 整块 `.off` 降透明度 + 按钮 disabled 更淡，一眼看出「还没开」。 */
.bp-ai { margin-bottom: 14px; }
.bp-ai .bar { align-items: center; }
.bp-ai.off { opacity: .8; }
.bp-ai.off .tip { color: var(--text-mute); }
.bp-ai button[disabled] { cursor: not-allowed; opacity: .55; }

/* ======================== 453 批 · AT入网 / 商户能力 ======================== */
/* AT入网 字段多 ⇒ 用一个更宽的弹层档（`.wide` 是 560px，会被两列栅格挤爆） */
.modal.xwide { max-width: calc(920px * var(--ui-s)); }

/* ---- 469 · AT入网（照蓝本列表形态）：工具条 / 搜索 / 表格 / 行内操作 ---- */
.mask.stack { z-index: 200; }                    /* 二级弹窗：叠在列表弹窗之上 */
.ma-page { max-height: calc(100vh - 48px); display: flex; flex-direction: column; min-width: 0; }
/* 🔴 AT入网 宽表：列宽合计 1508px
   （序号56·**所属机构120**·类型92·简称118·渠道号150·认证码120·商户号150·类目240·实名132·备注130·操作200）
   ★ r884（大人令 2026-10-25「at入网里面 还要加一列所属机构的」）：新增「所属机构」列后
   旧值 1220/1160 已装不下 11 列 ⇒ 弹窗与表格 `min-width` **同步放宽**，否则「备注」列被挤成竖排。
   ⇒ 弹窗比通用 `xwide`(920) 更宽，表格给 min-width 由 `.ma-tblwrap` 横向滚动兜底。
   🔴🔴 `min-width: 0`（大人令 2026-10-15「横着的拉条不要拖到最下面才出现」）：
   `.mask` 是 grid 居中容器 ⇒ 弹窗为 grid item，其 `min-width: auto` = **min-content**（=表宽+padding）。
   不写这一行，视口 < 表宽时**弹窗自己撑破视口**、横向滚动落到**整个遮罩层**上（`.ma-tblwrap`
   永不溢出 ⇒ 顶部镜像条永不出现，且用户要拖到屏幕最下面才够得着）。写 0 后弹窗按视口收窄，
   横向滚动**收回 `.ma-tblwrap`**，顶部镜像条才管用。 */
.modal.xwide.ma-page { max-width: calc(1740px * var(--ui-s)); min-width: 0; }   /* r929：随「本地商户号」列同步加宽 */
.ma-tblwrap > table.tbl.wide { min-width: 1680px; }   /* r929/r930：新增「本地商户号」列后同步加宽 */
.ma-page > .sub { margin-bottom: 12px; }
.ma-bar { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.ma-bar .primary { flex: 0 0 auto; }
/* 🔴 「绑 定」= 橙色提醒按钮：子商户号属资金相关操作，与两个「新增」按钮（主色蓝）拉开区分
   特异性 (1,2,1) > 全局 `button:hover:not(:disabled)` (0,2,1) ⇒ hover 不会被压过 */
.ma-bar #ma-bind {
  flex: 0 0 auto;
  background: var(--warn); border-color: var(--warn); color: #fff;
}
.ma-bar #ma-bind:hover:not(:disabled) { background: #94430A; border-color: #94430A; color: #fff; }
.ma-bar #ma-count { margin-left: 4px; }
.ma-search {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 10px 12px; margin-bottom: 10px;
  border: 1px solid var(--line); border-radius: var(--r-10); background: var(--line-soft);
}
.ma-search label { display: flex; align-items: center; gap: 6px; font-size: var(--fs-13); color: var(--text-dim); }
.ma-search input { width: 200px; }
.ma-tblwrap { overflow: auto; flex: 1 1 auto; min-height: 160px; }
.ma-empty { text-align: center; padding: 20px; color: var(--text-dim); font-size: var(--fs-13); }
.ma-sub { color: var(--bad); font-weight: 600; }    /* 商户号红字 —— 蓝本 staticStyle color:#F56C6C */
.ma-act { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; }
/* ★ 5285：AT入网列表「实名结果」列（V1.0.4 §3.10）—— 已授权/已确认=绿 · 未授权/未确认=橙 · 已销户=红 */
.ma-rn { display: inline-block; padding: 2px 8px; border-radius: var(--r-full); font-size: var(--fs-12); white-space: nowrap; border: 1px solid transparent; }
.ma-rn-ok { color: var(--ok); border-color: var(--ok); background: color-mix(in srgb, var(--ok) 12%, transparent); }
.ma-rn-warn { color: var(--warn); border-color: var(--warn); background: color-mix(in srgb, var(--warn) 12%, transparent); }
.ma-rn-bad { color: var(--bad); border-color: var(--bad); background: color-mix(in srgb, var(--bad) 12%, transparent); }
.ma-rn-unknown, .ma-rn-none { color: var(--text-dim); border-color: var(--line); }
.ma-view { color: var(--brand); cursor: pointer; font-size: var(--fs-13); }
.ma-form label.fld { display: block; margin: 10px 0 0; font-size: var(--fs-13); color: var(--text-dim); }
.ma-form label.fld i { color: var(--bad); font-style: normal; }
.ma-form input, .ma-form select { display: block; width: 100%; margin-top: 5px; }
.ma-hint { margin: 8px 0 2px; font-size: var(--fs-13); line-height: 1.75; color: var(--text-dim); }
/* ★ 5285c：AT入网「绑定子商户号」弹层（支持直连机构；切换机构 ⇒ 号输入框就地重画） */
/* ★ r886：每通道两行（子商户号 + 渠道号）⇒ 弹层加宽。
   🔴 必须**同时**给 `max-width`：`.modal` 基础 `max-width: 460px` 会把 width 压回去
      （只写 width 时 computed 仍是 460，实测踩过）。走 `--ui-s` 缩放令牌，大屏小屏自适应。 */
.ma-bindm { width: min(calc(820px * var(--ui-s)), 94vw); max-width: min(calc(820px * var(--ui-s)), 94vw);
  max-height: 88vh; overflow: auto; }
.ma-bindm .ma-form label.fld .ma-sub, .ma-bindm .ma-form label.fld .ma-sub-rm { margin-left: 6px; font-weight: 400; }
.ma-fnote { margin-top: 8px; }

/* ---- r879 · 绑定子商户号：每通道一行 = 输入框 + 【查 询】 + 来源徽标 ----
   🔴 查不到的通道明说「查不到 · 只能手填」，不给点下去必然失败的按钮（能力由 subMerQuery 下发）。 */
.mb-row { display: flex; align-items: flex-end; gap: 10px; }
.mb-row > label.fld { flex: 1 1 auto; min-width: 0; }
/* ★ r886：每通道的第二行 = 渠道号（落 `channel_mer_no`）。紧跟子商户号、间距收紧，
   视觉上仍属同一通道（查询按钮与来源徽标只在第一行，避免两行各挂一堆按钮）。 */
.mb-row2 { margin-top: 6px; }
.mb-row2 > label.fld { flex: 1 1 auto; min-width: 0; }
.mb-row2 > label.fld input,
.mb-row2 > label.fld select { font-size: var(--fs-12-5); }
.mb-row2 > label.fld select { width: 100%; }
.mb-side { flex: 0 0 auto; display: flex; flex-direction: column; align-items: flex-end; gap: 4px;
  padding-bottom: 2px; min-width: 96px; }
.mb-noq { font-size: var(--fs-12); color: var(--text-dim); white-space: nowrap; }
.mb-src { font-size: var(--fs-12); padding: 1px 7px; border-radius: 999px; white-space: nowrap;
  border: 1px solid var(--line); color: var(--text-dim); background: var(--line-soft); }
.mb-src.mb-none { opacity: .65; }
.mb-src.mb-k-query { color: var(--ok); border-color: var(--ok); background: var(--ok-bg, var(--line-soft)); }
.mb-src.mb-k-onboard { color: var(--brand); border-color: var(--brand); background: var(--line-soft); }
.mb-res:empty { display: none; }
.mb-res { margin: 4px 0 2px; }
.mb-cand { display: flex; align-items: center; gap: 10px; flex-wrap: nowrap;
  padding: 6px 9px; margin-top: 5px; border-radius: var(--r-7);
  background: var(--line-soft); border: 1px solid var(--line); }
/* ★ r890（大人令 2026-10-26 08:31）：候选行**只留号 + 极短中文标签 + 按钮** ——
   `子商户号 · bank_mer_code · 银联/联` / `汇付二级商户号 · sub_mer_id · 银联/联` 这类
   技术标注一律不铺在界面上（完整说明留在 `title` 悬停里，排查时还能看）。
   保留两个汉字标签是**必要信息**：否则两个号长得一样，人不知道该点哪个「填 入」。 */
.mb-cand code { font-size: var(--fs-12-5); color: var(--text); flex: 1 1 auto; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mb-candtag { flex: 0 0 auto; font-size: var(--fs-12); color: var(--text-dim); white-space: nowrap; }
/* 旧类保留（其它弹层仍在用），本弹层不再渲染 */
.mb-candnote { flex: 1 1 auto; min-width: 0; font-size: var(--fs-12); color: var(--text-dim);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mb-cand > .mini, .mb-cand > .mb-noq { flex: 0 0 auto; }
.mb-note { margin-top: 6px; font-size: var(--fs-12); color: var(--text-dim); line-height: 1.7; }
.mb-err { margin-top: 6px; font-size: var(--fs-12-5); color: var(--bad); line-height: 1.7; }

/* ---- 613：弹层「框下最近 5 条记录」只读块（绑定公众号/小程序/授权目录配置共用） ---- */
.ma-hist { margin-top: 14px; padding-top: 10px; border-top: 1px dashed var(--line); }
.ma-hist-t { font-size: var(--fs-12-5); color: var(--text-dim); margin-bottom: 8px; }
.ma-hist-l { list-style: none; margin: 0; padding: 0; max-height: 200px; overflow: auto; }
.ma-hist-l li { display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 6px 9px; margin-bottom: 5px; border-radius: var(--r-7); background: var(--line-soft); }
.ma-hist-v { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: var(--fs-12-5); color: var(--text); }
.ma-hist-tm { flex: 0 0 auto; font-size: var(--fs-12); color: var(--text-dim); }
.ma-hist-e { font-size: var(--fs-12-5); color: var(--text-dim); padding: 4px 2px; }

/* ---- 商户能力：四枚能力卡 + 「打开后商户端可见」菜单树（照蓝本全展开） ---- */
.cap-item { border: 1px solid var(--line); border-radius: var(--r-10); padding: 12px 14px; margin: 10px 0; background: var(--card); }
.cap-head { display: flex; align-items: center; gap: 12px; }
.cap-name { font-weight: 600; font-size: var(--fs-14); color: var(--text); }
.cap-sw { margin-left: auto; margin-top: 0; }  /* 开关靠右 · 复用通用件 `.pc-sw`（观感与终端表单/凭证弹窗一致） */
.cap-desc { margin: 6px 0 8px; font-size: var(--fs-13); color: var(--text-dim); }
.cap-menus { border-top: 1px dashed var(--line); padding-top: 8px; }
.cap-mlabel { font-size: var(--fs-12-5); color: var(--text-dim); margin-bottom: 4px; }
.cap-tree { list-style: none; margin: 0; padding-left: 0; font-size: var(--fs-13); color: var(--text); }
.cap-tree li { padding: 1px 0; }
.cap-tree ul { list-style: none; margin: 2px 0 2px 6px; padding-left: 12px; border-left: 1px solid var(--line); }

/* ---------- 大额收款账户信息（456 批）----------
   只读 key/value：左列浅底标签 + 右列值，账号/固号用等宽字。
   沿用 `.card` 一套令牌（`--line/--card/--text`）⇒ 深浅色自动适配，不另起观感。 */
.lacct { margin-top: 12px; border: 1px solid var(--line); border-radius: var(--r-10); overflow: hidden; }
.lacct .lrow { display: grid; grid-template-columns: 128px 1fr; align-items: stretch; }
.lacct .lrow + .lrow { border-top: 1px solid var(--line-soft); }
.lacct .lk {
  padding: 10px 14px; font-size: var(--fs-12-5); color: var(--text-dim);
  background: var(--line-soft); display: flex; align-items: center;
}
.lacct .lv {
  padding: 10px 14px; font-size: var(--fs-13-5); color: var(--text);
  display: flex; align-items: center; gap: 9px; min-width: 0; word-break: break-all;
}
.lacct .mono { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; letter-spacing: .4px; }
.lacct .lv .mini { flex: 0 0 auto; white-space: nowrap; }
@media (max-width: 620px) { .lacct .lrow { grid-template-columns: 104px 1fr; } }

/* ---------- 登录页协议弹层（488 批）----------
   承载《用户协议》/《隐私政策》V2.0 正文（136 批正本）。
   🔴 独立类名（.agmask/.agbox）不与通用 .mask/.modal 抢样式；
   🔴 正文带内联 `color:#333` 的文档式排版 ⇒ **弹层固定浅色**，
      不跟 data-theme 变，避免深色主题下白底黑字/深底深字看不清。 */
.agmask {
  position: fixed; inset: 0; z-index: 300; display: grid; place-items: center;
  background: rgba(16,24,40,.52); padding: 24px; overflow: auto;
}
.agbox {
  width: 100%; max-width: 760px; max-height: 86vh; background: #fff;
  border-radius: var(--radius-lg); box-shadow: 0 24px 60px rgba(16,24,40,.30);
  display: flex; flex-direction: column; overflow: hidden;
}
.agbox__hd {
  display: flex; align-items: baseline; gap: 10px; padding: 15px 18px 13px;
  border-bottom: 1px solid #eef0f3; flex: 0 0 auto;
}
.agbox__hd b { font-size: var(--fs-16); font-weight: 600; color: #111; }
.agbox__hd small { font-size: var(--fs-12); color: #8a8a8a; }
.agbox__x {
  margin-left: auto; width: 30px; height: 30px; padding: 0; border: 0; border-radius: var(--r-8);
  background: transparent; color: #8a8a8a; font-size: var(--fs-20); line-height: 1; cursor: pointer; transition: .16s;
}
.agbox__x:hover { background: #f2f3f5; color: #111; }
.agbox__bd {
  flex: 1 1 auto; min-height: 0; overflow-y: auto; -webkit-overflow-scrolling: touch;
  padding: 18px 22px 22px; background: #fff;
}
.agbox__bd::-webkit-scrollbar { width: 8px; }
.agbox__bd::-webkit-scrollbar-thumb { background: #d8dce2; border-radius: var(--r-4); }
.agbox__ft { flex: 0 0 auto; border-top: 1px solid #eef0f3; padding: 12px 18px; display: flex; background: #fff; }
.agbox__ok {
  flex: 1 1 auto; height: 40px; border: 0; border-radius: var(--r-8); cursor: pointer;
  background: var(--brand); color: #fff; font-size: var(--fs-14); font-weight: 600; transition: .16s;
}
.agbox__ok:hover { background: #0e57bd; }
@media (max-width: 560px) {
  .agmask { padding: 0; place-items: stretch; }
  .agbox { max-width: none; max-height: none; height: 100%; border-radius: 0; }
  .agbox__bd { padding: 16px 16px 20px; }
}

/* ======================== 489 · 取现 / 结算账户 ======================== */
/* 只读展示框（取现弹层里的「收款账户」· 与蓝本 `withdraw-submit-dialog` 同口径） */
.ro {
  margin-top: 6px; padding: 8px 11px; border: 1px solid var(--line); border-radius: var(--r-8);
  background: var(--line-soft); color: var(--text); font-size: var(--fs-13-5); line-height: 1.55;
}
/* 单选组（账户类型：对公 / 对私）*/
.radios { display: flex; flex-wrap: wrap; gap: 8px 20px; margin-top: 6px; }
.radios label { display: flex; align-items: center; gap: 6px; color: var(--text); font-size: var(--fs-13-5); cursor: pointer; white-space: nowrap; }
.radios label input[type="radio"] { width: auto; flex: 0 0 auto; margin: 0; }

/* ================= ★ 489e：好生意「自动提现」开关 与 只读键值列表 =================
   · `.wd-auto` —— 取现弹层顶部的开关条（开关=自动提现；开⇒提现按钮暗）
   · `.kv-list` —— 「到账账户」弹层的只读键值行（好生意卡号/开户行/持卡人）
   · `.bal-txt` —— 首页账户卡里「自动提现」的**文字态**（替代金额数字）*/
.wd-auto {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 12px 14px; margin: 12px 0 4px;
  border: 1px solid var(--line); border-radius: var(--r-10); background: var(--line-soft);
}
.wd-auto .wa-t { font-size: var(--fs-14); font-weight: 700; color: var(--text); }
.wd-auto .wa-s { font-size: var(--fs-12-5); color: var(--text-dim); margin-top: 3px; }
.wd-auto .pc-sw { margin-top: 0; }
.kv-list { display: grid; gap: 8px; margin: 10px 0 4px; }
.kv-list > div {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  padding: 9px 12px; border: 1px solid var(--line); border-radius: var(--r-8); background: var(--line-soft);
}
.kv-list > div > span { color: var(--text-dim); font-size: var(--fs-13); white-space: nowrap; }
.kv-list > div > b { color: var(--text); font-size: var(--fs-13-5); text-align: right; word-break: break-all; }
.bal-txt { font-size: var(--fs-15); font-weight: 700; letter-spacing: .3px; }

/* ============================================================================
 * r964：大额支付「入账回单」弹层（`app.js#largeReceiptHtml`）
 *   🔴 只用主题变量（深色/浅色自动跟随）；打印走新窗口内联样式，**不吃这份 CSS**。
 * ==========================================================================*/
.rcpt-host { margin: 10px 0 4px; }
.rcpt h2 {
  font-size: var(--fs-17); font-weight: 700; letter-spacing: 2px;
  text-align: center; margin: 4px 0 14px; color: var(--text);
}
.rcpt-tbl { width: 100%; border-collapse: collapse; }
.rcpt-tbl th, .rcpt-tbl td {
  border-bottom: 1px solid var(--line); padding: 8px 10px;
  font-size: var(--fs-13); text-align: left; vertical-align: top; word-break: break-all;
}
.rcpt-tbl th { width: 32%; color: var(--text-dim); font-weight: 500; background: var(--line-soft); }
.rcpt-tbl td { color: var(--text); }
.rcpt-note {
  margin: 14px 0 0; padding-top: 10px; border-top: 1px dashed var(--line);
  font-size: var(--fs-12); color: var(--text-dim); line-height: 1.7;
}

/* ============================================================================
 * 489j：渠道商列表「简称」行内编辑
 *   点一下 → 变输入框 + ✓ 保存 / ✕ 取消；Enter 保存、Esc 取消。
 *   🔴 保存按钮的 hover 必须**提特异性** —— 全局 `button:hover:not(:disabled)`
 *      是 (0,2,1)，单类 `.rne-save:hover` 只有 (0,2,0)，会被它压成灰底蓝字。
 * ==========================================================================*/
.rne {
  display: inline-flex; align-items: center; gap: 5px; cursor: pointer;
  border-radius: var(--r-6); padding: 2px 7px; margin: -2px -7px;
  transition: background .15s;
}
.rne:hover { background: var(--brand-soft); }
.rne .rne-pen {
  font-style: normal; font-size: var(--fs-11); line-height: 1;
  opacity: 0; color: var(--brand); transition: opacity .15s;
}
.rne:hover .rne-pen { opacity: .8; }
.rne-edit { display: inline-flex; align-items: center; gap: 6px; }
.rne-input {
  width: 120px; padding: 4px 8px; font: inherit; font-size: var(--fs-13);
  border: 1px solid var(--brand); border-radius: var(--r-6); outline: none;
  background: var(--card); color: var(--text);
}
.rne-input:focus { box-shadow: 0 0 0 3px rgba(22,104,220,.14); }
button.rne-save {
  background: var(--brand); border-color: var(--brand); color: #fff;
  padding: 4px 9px; font-size: var(--fs-12-5); line-height: 1.2;
}
button.rne-save:hover:not(:disabled) {
  background: var(--brand-hover); border-color: var(--brand-hover); color: #fff;
}
button.rne-cancel { padding: 4px 9px; font-size: var(--fs-12-5); line-height: 1.2; }

/* ======================== 489t 商户档案三页（大人令 2026-10-10） ========================
   注：`.pf-card/.pf-k/.pf-v` 与「商户能力」那组 `.pf-row/.pf-chk` 是两套东西，
   前缀相同纯属巧合，选择器互不冲突。 */
.pf-card {
  border: 1px solid var(--line-soft); border-radius: var(--radius);
  padding: 12px 14px; margin: 10px 0; background: var(--card);
}
.pf-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.pf-title { font-size: var(--fs-14-5); font-weight: 600; color: var(--text); }
.pf-title small { font-weight: 400; color: var(--text-dim); margin-left: 6px; font-size: var(--fs-12-5); }
.pf-meta { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-left: auto; }
@media (max-width: 860px) { .pf-meta { margin-left: 0; } }
.pf-head > button.pf-sync { flex: 0 0 auto; white-space: nowrap; }
/* ★ r860：同步按钮旁的「选择机构」下拉（绑了几家就逐家同步） */
.pf-syncwrap { display: inline-flex; align-items: center; gap: 6px; flex: 0 0 auto; }
.pf-syncwrap select.pf-pf { max-width: 220px; }
/* ★ r860：修改弹层里的危险区（删除入口并入此处） */
.danger-zone { margin-top: 18px; padding-top: 12px; border-top: 1px dashed var(--line); }
.danger-zone .dz-t { font-size: var(--fs-12); color: var(--bad); letter-spacing: .06em; margin-bottom: 6px; }
.danger-zone .tip { margin: 0 0 10px; }
.pf-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 8px 18px; margin-top: 12px;
}
/* 🔴 每个字段**自成一块**（标签在上、值在下）—— 若 k/v 直接做 grid 的独立格，
   auto-fill 会把「标签/值/标签/值」拉成一排 ⇒ 标签与值错位（489t 实拍抓到）。 */
.pf-item { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.pf-k { font-size: var(--fs-12); color: var(--text-dim); }
.pf-v { font-size: var(--fs-13); color: var(--text); word-break: break-all; }

.tag {
  display: inline-block; padding: 0 8px; border-radius: var(--r-full);
  font-size: var(--fs-12); line-height: 18px; border: 1px solid var(--line);
  color: var(--text-dim); background: transparent;
}
.tag.ok { color: var(--ok); border-color: var(--ok); background: var(--ok-soft); }
.tag.warn { color: var(--warn); border-color: var(--warn); background: var(--warn-soft); }
.dim { color: var(--text-dim); }

/* 全项 key=value 网格（鲲鹏 / 好生意 完整信息）
   ★ 612b（大人令 2026-10-11）：三列 = **英文字段 | 中文说明 | 值** */
.kv-grid {
  display: grid; grid-template-columns: minmax(170px, max-content) minmax(110px, max-content) 1fr;
  gap: 0 14px; margin-top: 10px;
}
.kv-k {
  font-size: var(--fs-12); color: var(--text-dim); padding: 3px 0;
  border-top: 1px dashed var(--line-soft); word-break: break-all;
}
.kv-d {
  font-size: var(--fs-12); color: var(--text-dim); padding: 3px 0;
  border-top: 1px dashed var(--line-soft); word-break: break-all; opacity: .82;
}
.kv-v {
  font-size: var(--fs-12-5); color: var(--text); padding: 3px 0;
  border-top: 1px dashed var(--line-soft); word-break: break-all;
}
@media (max-width: 720px) {
  .kv-grid { grid-template-columns: 1fr; }
  .kv-k { border-top: 1px dashed var(--line-soft); padding-bottom: 0; }
  .kv-d { border-top: none; padding-top: 0; padding-left: 10px; }
  .kv-v { border-top: none; padding-top: 0; padding-left: 10px; }
}

/* ★ 612b：子商户号后面紧跟的备注小字（号池列表 / 绑定场景） */
.ma-sub-rm { color: var(--text-dim); font-size: var(--fs-12); margin-left: 6px; }

/* ==================== 612 批（大人令 2026-10-10 17:38）：商户档案三页 可搜可查 ==================== */
/* ★ 大人原话「数量多了以后 没法看啊 没法查啊」⇒ 三页统一补：搜索框 + 计数 + 分页 + 全项折叠 */

/* 搜索框（.bar 内右对齐，与刷新按钮同排） */
.pf-search { flex: 0 0 auto; }
.bar > input[type="search"] {
  background: var(--bg-soft, transparent);
  border: 1px solid var(--line);
  border-radius: var(--r-6);
  color: var(--text);
  padding: 4px 10px;
  font-size: var(--fs-13);
  outline: none;
}
.bar > input[type="search"]::placeholder { color: var(--text-dim); }
.bar > input[type="search"]:focus { border-color: var(--brand, #1668DC); }

/* 计数行 */
.pf-counter { font-size: var(--fs-12-5); color: var(--text-dim); margin: 8px 0 2px; }

/* 分页条 */
.pf-pager {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--line-soft);
}
.pf-pager .pf-pginfo { font-size: var(--fs-12-5); color: var(--text-dim); }
.pf-pager select.mini { flex: 0 0 auto; }
.pf-pager > button { flex: 0 0 auto; white-space: nowrap; }

/* 上游两页：卡内中文名行 + 全项折叠 */
.pf-names { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-top: 8px; }
.pf-sub { margin-top: 10px; }
.pf-up { margin-bottom: 12px; }
.pf-raw { margin-top: 4px; }

/* 大卡片场景（上游两页每页 5 户，卡内空间足） */
@media (max-width: 720px) {
  .bar > input[type="search"] { width: 100% !important; }
  .bar { flex-wrap: wrap; }
}

/* ==================== 613q 批（大人令 2026-10-13）：退款记录 / 上游交互日志 ==================== */
/* tag 补两档：失败（退款失败）/ 中性（出站方向 → 与「入站」区分） */
.tag.bad   { color: var(--bad);  border-color: var(--bad);  background: var(--bad-soft); }
.tag.muted { color: var(--text-dim); border-color: var(--line); background: var(--line-soft); }

/* 弹层里「小按钮 + 说明」同一行（退款弹层的「全额退」） */
.fld-row { display: flex; align-items: center; gap: 10px; margin: 8px 0 0; flex-wrap: wrap; }
.fld-row > button { flex: 0 0 auto; }

/* 原文块（请求 / 请求业务明文 / 响应 / 回调）—— 等宽、可换行、可选中复制。
   🔴 原文**不截断**展示，只给固定高度 + 滚动，避免弹层被一段长报文撑爆。 */
pre.raw-box {
  margin: 8px 0 0; padding: 12px 14px; max-height: 320px; overflow: auto;
  background: var(--line-soft); border: 1px solid var(--line); border-radius: var(--r-10);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: var(--fs-12-5); line-height: 1.55; color: var(--text);
  white-space: pre-wrap; word-break: break-all; user-select: text;
}

/* kv-list 里的等宽值（单号 / 卡号 / 地址） */
.kv-list > div > b.mono { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; letter-spacing: .2px; }

/* 长地址单行省略（上游交互日志表的 URL 列） */
.ellip { display: inline-block; max-width: 220px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: bottom; }

/* ==================== 703 批（大人令 2026-10-15）：功能开关 / 绑定弹窗 ====================
   全部复用既有令牌（--brand / --line / --line-soft / --text / --text-dim / --r-* / --fs-*），
   🔴 不引入新的裸色值 —— 「界面风格保持应用台一致」是这一批的硬要求。 */

/* ---- ① 「绑定微信」弹层里的二维码区 ----
   🔴 与登录页 `.lr-wx-qr` 同一套路：**底色跟随系统**（微信 iframe 的文字色由系统媒体查询决定，
      宿主不改底色就会出现「深色系统白字落白底 = 看不见」）。 */
.wb-qr {
  margin-top: 16px; min-height: 404px;
  display: grid; justify-items: center; align-content: center; gap: 10px;
  border: 1px solid var(--line); border-radius: var(--r-12); background: var(--line-soft);
}
.wb-qr:has(iframe) { background: #fff; border-color: transparent; min-height: 0; }
@media (prefers-color-scheme: dark) { .wb-qr:has(iframe) { background: #191919; } }
.modal .wb-qr .lr-wx-note { color: var(--text-dim); }
@media (max-width: 560px) { .wb-qr { min-height: 200px; } }

/* ---- ② 「功能开关」区块（个人设置里的一段） ---- */
.fx-list { margin-top: 10px; }
.fx-item { padding: 10px 0; border-top: 1px solid var(--line-soft); }
.fx-item:first-child { border-top: 0; padding-top: 2px; }
.fx-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.fx-head .pc-sw { margin-top: 0; }
.fx-desc { font-size: var(--fs-12-5); color: var(--text-mute); flex: 1 1 220px; }
.fx-kids { display: flex; flex-wrap: wrap; gap: 6px 22px; margin: 8px 0 0 52px; }
.fx-kids .pc-sw { margin-top: 0; }
.fx-kids .sw-txt { font-weight: 500; font-size: var(--fs-13); color: var(--text-dim); }
.fx-kids .sw-track { width: 36px; height: 20px; }
.fx-kids .sw-track::after { width: 16px; height: 16px; }
.fx-kids input:checked + .sw-track::after { transform: translateX(16px); }

/* ============================================================
   ★ 704：全站弹窗统一「右上角 ✕」
   ------------------------------------------------------------
   观感对齐既有 `.qrbox__x`（台牌码层）/ `.agbox__x`（协议层）：
   30×30 · 圆角 8 · 透明底 · hover 变底色 —— 三处完全一致。
   🔴 **只对「自带关闭按钮」的弹窗注入**（见 app.js `injectModalXs`）：
      `openProfile(force)` 这类强制弹窗**故意不渲染关闭按钮** ⇒ 天然没有叉。
   🔴 `.tm-modal` 自身就是可滚动容器（max-height + overflow-y:auto）⇒ 直接直角定位会被内容
      滚走，故这一种改用 `sticky + 零高`：不占布局高度，且滚动时吸附在右上角。
   ============================================================ */
.modal > .modal-xbar { position: absolute; top: 10px; right: 12px; z-index: 4; }
.modal-x {
  width: 30px; height: 30px; padding: 0; border: 0; border-radius: var(--r-8);
  background: transparent; color: var(--text-mute); font-size: var(--fs-20); line-height: 1;
  cursor: pointer; transition: .16s; display: grid; place-items: center;
}
.modal-x:hover { background: var(--line-soft); color: var(--text); }
.modal > h3 { padding-right: 32px; }   /* 标题给叉让位，不撞字 */
.modal.tm-modal > .modal-xbar {
  position: sticky; top: 0; height: 0; display: flex; justify-content: flex-end;
  margin: -6px -12px 0 0;
}

/* ============================================================
   ★ 705：对客密钥（开放平台准入）
   ------------------------------------------------------------
   🔴 颜色一律走既有设计令牌（--ok/--warn/--bad/--line-soft/--text-dim…）
      ⇒ 深浅色两套主题**自动跟随**，本段不写任何硬编码色（等宽字体除外）。
   类名前缀统一 `ak-`，与既有 `.ma-*`（商户档案）等不冲突。
   ============================================================ */
.ak-sub {
  color: var(--text-mute); font-size: var(--fs-12); line-height: 1.45; margin-top: 3px;
}
.ak-sub > .mini { margin-top: 2px; color: var(--text); }   /* 别继承 .ak-sub 的灰字（那样像 disabled） */
.ak-key, .ak-fp {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, 'Courier New', monospace;
  font-size: var(--fs-12); word-break: break-all;
}
.ak-key { color: var(--text); }
/* 指纹缩写按 19 字符定长（见 `api_key.js#shortFp`）⇒ 不折行；但要防列被压窄时溢出 */
.ak-fp { color: var(--text-dim); white-space: nowrap; }
.ak-ip {
  display: inline-block; margin: 1px 4px 1px 0; padding: 1px 6px; border-radius: var(--r-4);
  background: var(--line-soft); color: var(--text-dim);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, 'Courier New', monospace;
  font-size: var(--fs-11-5);
}
.ak-badge {
  display: inline-block; padding: 2px 8px; border-radius: var(--r-6);
  font-size: var(--fs-11-5); font-weight: 600; white-space: nowrap; border: 1px solid transparent;
}
.ak-badge-ok   { background: var(--ok-soft);   color: var(--ok);          border-color: rgba(29, 158, 117, .3); }
.ak-badge-warn { background: var(--warn-soft); color: var(--warn);        border-color: rgba(180, 83, 9, .3); }
.ak-badge-bad  { background: var(--bad-soft);  color: var(--bad);         border-color: rgba(200, 34, 43, .3); }
.ak-badge-mute { background: var(--line-soft); color: var(--text-mute);   border-color: var(--line-soft); }

/* r931：审核弹层已下线，`.ak-kv` 键值行样式随之删除 */

/* ============================================================================
   r928 · 对客密钥「凭据模式」单选卡 + 一次性凭据弹层（大人令 2026-10-27）
   ----------------------------------------------------------------------------
   ① `.ak-modes` / `.ak-mode` —— 两张并排的模式卡（选中描边 + 勾标），点击整卡切换
   ② `.ak-gen` —— 生成按钮行（按钮 + 右侧一行说明）
   ③ `.ak-once-*` —— 「只显示一次」弹层：顶部红条、等宽值框、复制/已记录
   🔴 全部走设计令牌 ⇒ 深浅色自动跟随
   ========================================================================== */
.ak-modes { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-10, 10px); margin: var(--sp-6, 6px) 0 var(--sp-12, 12px); }
@media (max-width: 640px) { .ak-modes { grid-template-columns: 1fr; } }

.ak-mode {
  position: relative; text-align: left; cursor: pointer;
  border: 1px solid var(--line); border-radius: var(--r-9, 9px);
  background: var(--bg); padding: 11px 13px 12px;
  transition: border-color .16s ease, background .16s ease, box-shadow .16s ease;
}
.ak-mode:hover { border-color: var(--brand); }
.ak-mode[aria-checked="true"] {
  border-color: var(--brand); background: var(--brand-soft, rgba(22,104,220,.06));
  box-shadow: 0 0 0 1px var(--brand) inset;
}
.ak-mode[aria-disabled="true"] { cursor: not-allowed; opacity: .55; }
.ak-mode-hd { display: flex; align-items: center; gap: 7px; font-weight: 600; color: var(--text); font-size: var(--fs-13-5, 13.5px); }
.ak-mode-dot {
  flex: 0 0 auto; width: 14px; height: 14px; border-radius: 50%;
  border: 1.5px solid var(--line-strong, var(--line)); background: var(--bg);
  display: inline-flex; align-items: center; justify-content: center;
}
.ak-mode[aria-checked="true"] .ak-mode-dot { border-color: var(--brand); }
.ak-mode[aria-checked="true"] .ak-mode-dot::after {
  content: ''; width: 7px; height: 7px; border-radius: 50%; background: var(--brand);
}
.ak-mode-tag {
  margin-left: auto; font-family: var(--font-mono, ui-monospace, monospace);
  font-size: var(--fs-11, 11px); color: var(--text-dim);
  border: 1px solid var(--line); border-radius: 999px; padding: 0 7px;
}
.ak-mode-desc { margin: 6px 0 0; font-size: var(--fs-12, 12px); color: var(--text-dim); line-height: 1.6; }
.ak-mode-sign { margin: 5px 0 0; font-family: var(--font-mono, ui-monospace, monospace); font-size: var(--fs-11-5, 11.5px); color: var(--text-mute, var(--text-dim)); }

/* 生成按钮行 */
.ak-gen { display: flex; align-items: center; gap: var(--sp-10, 10px); flex-wrap: wrap; margin-bottom: var(--sp-6, 6px); }
.ak-gen .ak-sub { flex: 1 1 220px; min-width: 0; }

/* 一次性凭据弹层 */
.ak-once-warn {
  display: flex; gap: 9px; align-items: flex-start;
  border-left: 3px solid var(--bad); background: var(--bad-soft, rgba(200,34,43,.08));
  border-radius: var(--r-7, 7px); padding: 9px 12px; margin: 0 0 12px;
  font-size: var(--fs-13, 13px); color: var(--text); line-height: 1.65;
}
.ak-once-warn b { color: var(--bad); }
.ak-once-box {
  width: 100%; box-sizing: border-box; resize: vertical;
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: var(--fs-12, 12px); line-height: 1.55;
  background: var(--bg-soft, var(--bg)); color: var(--text);
  border: 1px solid var(--line); border-radius: var(--r-7, 7px);
  padding: 10px 11px; word-break: break-all;
}
.ak-once-foot { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 12px; }
.ak-once-foot .grow { flex: 1 1 auto; }
.ak-once-kv { display: flex; gap: 8px; align-items: baseline; font-size: var(--fs-12-5, 12.5px); margin: 0 0 8px; }
.ak-once-kv > span { color: var(--text-dim); flex: 0 0 auto; }
.ak-once-kv > b { font-family: var(--font-mono, ui-monospace, monospace); font-weight: 600; color: var(--text); word-break: break-all; }

/* 列表里的模式徽标 */
.ak-mode-chip {
  display: inline-block; padding: 0 6px; border-radius: var(--r-4, 4px);
  font-size: var(--fs-11, 11px); font-family: var(--font-mono, ui-monospace, monospace);
  border: 1px solid var(--line); color: var(--text-dim); background: var(--line-soft);
  white-space: nowrap;
}
.ak-mode-chip.rsa { color: var(--brand); border-color: rgba(22,104,220,.3); background: var(--brand-soft, rgba(22,104,220,.07)); }
.ak-mode-chip.hmac { color: var(--ok); border-color: rgba(29,158,117,.3); background: var(--ok-soft, rgba(29,158,117,.08)); }

/* ============================================================================
   r935 · 「开发管理」页的接口文档卡（大人令 2026-10-27「设计一下 接口文档 在对客密钥 放个入口」）
   ----------------------------------------------------------------------------
   四个出口等宽平铺：HTML 文档 / OpenAPI 契约 / AI 工具定义 / Markdown 全文。
   🔴 全走令牌 ⇒ 深浅色自动跟随；链接色用主文（不是品牌蓝一大片），悬停才染色。
   ========================================================================== */
.dev-doc-links {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(158px, 1fr));
  gap: var(--sp-10); margin-top: var(--sp-12);
}
.dev-doc-links a {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-8);
  padding: var(--sp-10) var(--sp-12);
  border: 1px solid var(--line); border-radius: var(--r-8);
  background: var(--card); color: var(--text);
  font-size: var(--fs-13); text-decoration: none;
  transition: border-color .15s ease, background .15s ease, color .15s ease;
}
.dev-doc-links a:hover {
  border-color: var(--brand); background: var(--brand-soft); color: var(--brand);
  text-decoration: none;
}
.dev-doc-links a > span {
  font-family: var(--font-mono, ui-monospace, monospace);
  font-size: var(--fs-11); color: var(--text-mute); flex: 0 0 auto;
}
.dev-doc-links a:hover > span { color: var(--brand); }

/* ★ r943：「在线演示」卡 —— 二维码 + 文案左右排（客户在 PC 上掏手机直接扫，不必先跳过去） */
.dev-demo { display: flex; gap: var(--sp-16, 16px); align-items: flex-start; margin-top: var(--sp-10); }
.dev-demo-qr { flex: 0 0 auto; width: 128px; text-align: center; }
.dev-demo-qr img {
  display: block; width: 128px; height: 128px; box-sizing: content-box;
  padding: 5px; border: 1px solid var(--line); border-radius: var(--r-8);
  background: var(--card); object-fit: contain;
}
.dev-demo-qr > span { display: block; margin-top: 5px; font-size: var(--fs-11); color: var(--text-mute); }
.dev-demo-tx { flex: 1; min-width: 0; max-width: 660px; }
.dev-demo-tx .sub { margin: 0; }
.dev-demo-tx .tip { margin: var(--sp-8, 8px) 0 0; }
/* 窄屏（手机后台）不必扫自己 —— 点按钮就直达 */
@media (max-width: 719px) { .dev-demo-qr { display: none; } }

/* ★ r947：移动端入口页 —— 地址框 + 复制按钮 + 「怎么用更顺手」三条
   🔴 色值一律走令牌（本站 705 段起有硬编码色护栏），别写裸色。 */
.mb-url { display: flex; align-items: center; gap: var(--sp-10); flex-wrap: wrap; margin-top: var(--sp-10); }
.mb-url code {
  flex: 0 1 auto; min-width: 0; padding: 6px 10px; background: var(--bg);
  border: 1px solid var(--line); border-radius: var(--r-8);
  font-size: var(--fs-13); overflow-wrap: anywhere;
}
.mb-note { margin-top: var(--sp-10); }
.mb-note .sub { margin: 0; }
.mb-note ul { margin: var(--sp-12) 0 0; padding-left: 20px; }
.mb-note li { margin: 5px 0; font-size: var(--fs-13); color: var(--text-mute); }
/* 宽屏下两张卡限宽：否则卡片被拉到 1100+，二维码贴左、右边一大片空，观感左倾 */
.mb-card { max-width: 920px; }
/* 窄屏：`.card-title` 原为 flex 一行 —— 副标题一长就把「移动端」三个字挤成两行。
   本页改成三段竖排（标题 / 副标题 / 按钮），标题不再折行。 */
@media (max-width: 719px) {
  .mb-card .card-title { display: block; }
  .mb-card .card-title > .subtle { display: block; margin-top: 3px; }
  .mb-card .card-title > .fbtns { display: block; margin-top: var(--sp-10); }
}


/* ============================================================================
   706 批 · 员工终端范围收口（大人令 2026-10-15）
   ----------------------------------------------------------------------------
   ① `.scope-note` —— 收银员 / 店长登录后页面顶部的**如实提示条**（数据变少不是故障）
   ② `.scope-box` / `.scope-it` —— 人员编辑弹窗里的「关联终端/分组」多选清单
   🔴 全部走设计令牌 ⇒ 深浅色自动跟随（本文件深色块已覆盖同名字典）
   ========================================================================== */
.scope-note {
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
  border-left: 3px solid var(--brand);
  background: var(--brand-soft);
  font-size: var(--fs-13); color: var(--text-dim);
}
.scope-note b { color: var(--text); }

/* 人员列表「关联范围」列里的终端编码小片 */
.scope-chip {
  display: inline-block; padding: 1px 6px; border-radius: var(--r-4);
  background: var(--line-soft); color: var(--text-dim);
  font-size: var(--fs-11-5); white-space: nowrap;
}

/* 编辑弹窗：关联范围选择区 */
.scope-q {
  width: 100%; margin-bottom: 6px;
  background: var(--bg); color: var(--text);
  border: 1px solid var(--line); border-radius: var(--r-7);
  padding: 6px 9px; font-size: var(--fs-13);
}
.scope-box {
  max-height: 190px; overflow: auto;
  border: 1px solid var(--line); border-radius: var(--r-7);
  background: var(--bg); padding: 4px;
}
.scope-it {
  display: flex; align-items: center; gap: 6px;
  padding: 5px 7px; border-radius: var(--r-6);
  font-size: var(--fs-13); color: var(--text); cursor: pointer;
}
.scope-it:hover { background: var(--line-soft); }
/* 🔴 `width: auto` 必须显式写：全局有 `input{width:100%}`（照 `.fld.ck` 的老坑），
   不写就会把复选框撑成整行宽 ⇒ 文字被挤到右边缘并截断（706 实拍抓出）。 */
.scope-it > input[type="checkbox"] {
  flex: 0 0 auto; width: auto; height: auto; margin: 0;
}
.scope-it code { font-size: var(--fs-12); }
.scope-warn { color: var(--warn); }

/* ============================================================================
 * 5286 · 多分辨率适配分档（大人令 2026-10-16）
 * ----------------------------------------------------------------------------
 * 档位按**视口宽度**（CSS px），不按物理分辨率 —— 浏览器**分不清**
 * 「4K@150%」与「2.5K@100%」（两者视口都是 2560）。故实际只认 5 个视口档：
 *   1920 ← 1080p@100% / 4K@200%                     ⇒ 现状最舒服 ⇒ **零覆盖**
 *   2048 ← 1440p@125% / 4K@187%
 *   2560 ← 2.5K@100% / 4K@150% / 1440p@150%          ⇒ **最常见的高分屏场景**
 *   3200 ← 带鱼屏 3440 / 2560@125%
 *   3840 ← 4K@100%
 * 每档只改三个令牌（--ui-s / --ui-r / --pg-max）⇒ 字号 / 间距 / 圆角 / 内容上限
 * **全站一次跟随**（202 处字号引用点、60 处骨架间距均自动生效）。
 * 🔴 1080p 及以下**不设任何覆盖** ⇒ 与 5286 之前**逐像素一致**（可回归验证）。
 * 🔴 内容上限 `--pg-max` 只在「视口可用宽 > 上限」时起作用，否则等于铺满。
 *    实测：1920→1700 可用（不收）｜2560→2311 可用 / 上限 2020（两侧各留 145）
 *          3840→3554 可用 / 上限 2440（两侧各留 557 ⇒ 杂志感留白）。
 * ==========================================================================*/
@media (min-width: 2048px) {
  :root {
    --ui-s: 1.06; --ui-r: 1.06;
    --pg-max: 1870px;      /* 2048 档可用 ≈1815 ⇒ 上限不生效，只放大字号 */
  }
}
@media (min-width: 2560px) {
  :root {
    --ui-s: 1.13; --ui-r: 1.12;
    --pg-max: 2020px;
    --elev-1: 0 1px 2px rgba(0,0,0,.05), 0 2px 6px rgba(0,0,0,.06);
    --elev-2: 0 3px 10px rgba(0,0,0,.09), 0 12px 30px rgba(0,0,0,.10);
  }
}
@media (min-width: 3200px) {
  :root {
    --ui-s: 1.22; --ui-r: 1.18;
    --pg-max: 2240px;
  }
}
@media (min-width: 3840px) {
  :root {
    --ui-s: 1.3; --ui-r: 1.24;
    --pg-max: 2440px;
  }
}
/* 超高分辨率（5120 带鱼 / 8K）—— 上限不再无限增长，避免又变「空散」 */
@media (min-width: 5120px) {
  :root {
    --ui-s: 1.4; --ui-r: 1.3;
    --pg-max: 2800px;
  }
}
/* 大屏深色外观：阴影要在近黑底上仍然可见（浅色档的 rgba(.04) 会消失） */
@media (min-width: 2560px) {
  html[data-theme='dark'] {
    --elev-1: 0 1px 3px rgba(0,0,0,.5);
    --elev-2: 0 4px 14px rgba(0,0,0,.55), 0 16px 36px rgba(0,0,0,.45);
  }
}

/* ============================================================================
 * r718 · 「机构能力总览」（大人令 2026-10-16）
 * ----------------------------------------------------------------------------
 * 管理员用的「我方能力 ↔ 机构接口」三域对照矩阵。
 * 🔴 全部颜色走既有令牌（浅色 / 深色 / 六档缩放自动生效），**零硬编码色**。
 * 🔴 类名一律 `cm-` 前缀，避免与既有页面串味。
 * ============================================================================ */

/* 无障碍：仅供读屏（表格 caption 用） */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* —— 机构切换区 —— */
.cm-plat-h { font-size: var(--fs-12); color: var(--text-mute); margin-bottom: var(--sp-8); }
.cm-chips { display: flex; flex-wrap: wrap; gap: var(--sp-8); }
.cm-chip {
  display: inline-flex; align-items: center; gap: var(--sp-6);
  height: calc(34px * var(--ui-s)); padding: 0 var(--sp-12) 0 var(--sp-8);
  border: 1px solid var(--line); background: var(--card); color: var(--text-dim);
  border-radius: var(--r-full); cursor: pointer; font-size: var(--fs-13);
  transition: border-color .15s, background .15s, color .15s;
}
.cm-chip:hover { border-color: var(--brand-lite); color: var(--text); }
.cm-chip.is-on { border-color: var(--brand); background: var(--brand-soft); color: var(--brand); font-weight: 500; }
.cm-chip:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.cm-chip-nm { white-space: nowrap; }
/* 虚拟渠道角标：同一机构下的渠道分支，不是独立机构记录 */
.cm-chip-vt { margin-left: var(--sp-4); padding: 0 var(--sp-4); border-radius: var(--r-2);
  font-size: 10px; font-style: normal; line-height: 1.6; vertical-align: 1px;
  background: var(--line-soft); color: var(--text-mute); }
.cm-chip-pct { font-size: var(--fs-12); color: var(--text-mute); font-variant-numeric: tabular-nums; }
.cm-chip.is-on .cm-chip-pct { color: var(--brand); }
.cm-ring { width: calc(20px * var(--ui-s)); height: calc(20px * var(--ui-s)); flex: none; }
.cm-ring-bg { fill: none; stroke: var(--line); stroke-width: 2.5; }
.cm-ring-bar { fill: none; stroke-width: 2.5; stroke-linecap: round; }
.cm-note { margin-top: var(--sp-8); font-size: var(--fs-12); color: var(--text-mute); }
/* ★ r855 机构能力标记（预下单 / 大额）：亮标 = 已开通；灰标 = 机构有该产品但本轮未开通。
   🔴 只吃 CSS 变量，深浅色主题自动跟随（不写死色值）。 */
.cm-caps { display: inline-flex; flex-wrap: wrap; gap: 6px; margin-left: 10px; vertical-align: middle; }
.cm-cap {
  font-style: normal; font-size: var(--fs-11-5); font-weight: 600; line-height: 1;
  padding: 3px 8px; border-radius: 999px; border: 1px solid transparent; white-space: nowrap;
}
.cm-cap.is-on { color: var(--brand); border-color: var(--brand); background: var(--brand-soft); }
.cm-cap.is-off { color: var(--text-mute); border-color: var(--line); border-style: dashed; background: transparent; }

/* 状态色（覆盖率环用 stroke 类） */
.is-done { stroke: var(--ok); }
.is-part { stroke: var(--warn); }
.is-todo { stroke: var(--bad); }
.is-tbd { stroke: var(--brand); }
.is-na { stroke: var(--text-mute); }

/* —— 工具条 —— */
.cm-tools { gap: var(--sp-10); flex-wrap: wrap; align-items: flex-end; }
.cm-sw {
  display: inline-flex; align-items: center; gap: var(--sp-5);
  font-size: var(--fs-13); color: var(--text-dim); white-space: nowrap;
  padding-bottom: var(--sp-6); cursor: pointer;
}

/* —— 覆盖度（2026-10-17 大人令：三域做成大按钮，选中哪个下面就只看哪个） —— */
.cm-covs { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sp-16); }
.cm-cov-big {
  border: 1px solid var(--line); border-radius: var(--radius-lg); background: var(--card);
  padding: var(--sp-14) var(--sp-16); cursor: pointer; text-align: left; width: 100%;
  transition: border-color .15s, background .15s, box-shadow .15s, transform .15s;
}
.cm-cov-big:hover { border-color: var(--brand-lite); box-shadow: var(--elev-1); }
.cm-cov-big:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.cm-cov-big.is-on {
  border-color: var(--brand); background: var(--brand-soft);
  box-shadow: 0 0 0 1px var(--brand) inset;
}
.cm-cov-big.is-on .cm-cov-top b { color: var(--brand); }
.cm-cov-big .cm-cov-desc { margin-top: var(--sp-4); }
.cm-cov-top { display: flex; align-items: center; gap: var(--sp-6); font-size: var(--fs-13); }
.cm-cov-top b { color: var(--text); }
.cm-cov-tag {
  font-size: var(--fs-11); padding: 0 var(--sp-5); border-radius: var(--r-4);
  background: var(--brand-soft); color: var(--brand);
}
.cm-cov-num { margin-left: auto; font-variant-numeric: tabular-nums; font-weight: 500; }
.cm-cov-num.is-done { color: var(--ok); }
.cm-cov-num.is-part { color: var(--warn); }
.cm-cov-num.is-todo { color: var(--bad); }
.cm-cov-num.is-na { color: var(--text-mute); }
.cm-cov-bar { height: 6px; border-radius: var(--r-full); background: var(--line-soft); margin: var(--sp-6) 0; overflow: hidden; }
.cm-cov-bar i { display: block; height: 100%; border-radius: var(--r-full); }
.cm-cov-bar i.is-done { background: var(--ok); }
.cm-cov-bar i.is-part { background: var(--warn); }
.cm-cov-bar i.is-todo { background: var(--bad); }
.cm-cov-bar i.is-na { background: var(--line); }
.cm-cov-desc { font-size: var(--fs-12); }

/* —— 域卡 —— */
.cm-dom { border-top: 1px solid var(--line); }
.cm-dom:first-child { border-top: 0; }
.cm-dom-h {
  width: 100%; display: flex; align-items: center; gap: var(--sp-8);
  padding: var(--sp-10) var(--sp-4); background: none; border: 0; cursor: pointer;
  text-align: left; font-size: var(--fs-14); color: var(--text);
}
.cm-dom-h:hover { background: var(--line-soft); }
/* 单域视图：表头只作标识，不可点（折叠已取消） */
.cm-dom-h.is-static { cursor: default; border-bottom: 1px solid var(--line-soft); }
.cm-dom-h.is-static:hover { background: none; }
.cm-dom-h:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px; }
.cm-dom-tag {
  font-size: var(--fs-11); padding: 1px var(--sp-6); border-radius: var(--r-4);
  background: var(--brand-soft); color: var(--brand); flex: none;
}
.cm-dom-h .sub { font-size: var(--fs-12); }
.cm-dom-num { margin-left: auto; font-size: var(--fs-12); color: var(--text-mute); font-variant-numeric: tabular-nums; }
.cm-caret { color: var(--text-mute); transition: transform .15s; }
.cm-dom-h.is-folded .cm-caret { transform: rotate(-90deg); }
.cm-empty { padding: var(--sp-18); text-align: center; color: var(--text-mute); font-size: var(--fs-13); }
/* 术语对齐条：小微 = 上游「个人商户」 = 无营业执照 */
.cm-term { margin: var(--sp-10) var(--sp-14) 0; padding: var(--sp-10) var(--sp-12);
  border-left: 3px solid var(--warn); border-radius: 6px;
  background: var(--warn-soft); color: var(--text-2); font-size: var(--fs-12); line-height: 1.65; }
.cm-term b { color: var(--text-1); margin-right: 6px; }
.cm-term b + b { margin-right: 0; }

/* —— 对照表（r732：行 = 机构接口，不再是「我方能力」） —— */
.cm-tb { width: 100%; border-collapse: collapse; font-size: var(--fs-13); }
.cm-tb { table-layout: fixed; }
.cm-tb col.c-no { width: 6%; }
.cm-tb col.c-iface { width: 21%; }
.cm-tb col.c-uri { width: 21%; }
.cm-tb col.c-judge { width: 17%; }
.cm-tb col.c-ref { width: 21%; }
.cm-tb col.c-twin { width: 7%; }
.cm-tb col.c-st { width: 7%; }
.cm-tb th {
  text-align: left; font-weight: 500; color: var(--text-mute); font-size: var(--fs-12);
  padding: var(--sp-8) var(--sp-10); border-bottom: 1px solid var(--line);
  background: var(--line-soft); white-space: nowrap;
}
.cm-tb td { padding: var(--sp-10); border-bottom: 1px solid var(--line-soft); vertical-align: top; color: var(--text-dim); }
/* 功能章节行（最高一层：下单与支付 / 查询与关单 / 退款 / 提现与资金归集 / 结果回调） */
.cm-sub td {
  background: var(--brand-soft); color: var(--text-1); font-weight: 600; font-size: var(--fs-13);
  padding: var(--sp-8) var(--sp-10); border-bottom: 1px solid var(--line);
  box-shadow: inset 3px 0 0 var(--brand);
}
.cm-sub .sub { font-weight: 400; color: var(--text-mute); margin-left: var(--sp-6); }
/* 产品线行（章节下面：移动支付 ATU / 银行卡快捷·协议·免密·代扣支付 …） */
.cm-grp td {
  background: var(--bg); color: var(--text-1); font-weight: 600; font-size: var(--fs-12);
  padding: var(--sp-8) var(--sp-10); border-bottom: 1px solid var(--line);
  box-shadow: inset 2px 0 0 var(--line-strong, var(--line));
}
.cm-grp .sub { font-weight: 400; color: var(--text-mute); }
.cm-grp i {
  font-style: normal; font-size: var(--fs-10); font-weight: 700; letter-spacing: .05em;
  color: var(--brand); border: 1px solid currentColor; border-radius: var(--r-4);
  padding: 0 4px; margin-left: var(--sp-6);
}
/* 同一条产品线还有 N 支落在别的域（三条银联线横跨交易/应用两域） */
.cm-grp .cm-cx { font-weight: 500; color: var(--text-mute); margin-left: var(--sp-8); font-size: var(--fs-11); }
.cm-row { cursor: pointer; }
.cm-row:hover td { background: var(--brand-soft); }
.cm-row.is-gap td.c-no { box-shadow: inset 3px 0 0 var(--bad); }
.cm-no { display: inline-flex; align-items: center; gap: 2px; text-decoration: none; color: var(--brand); font-variant-numeric: tabular-nums; }
.cm-no i { font-style: normal; font-size: var(--fs-10); opacity: .7; }
.cm-no:hover { text-decoration: underline; }
/* r834：7896 已下线 ⇒ 无深链的接口编号按纯文本展示（不可点，视觉降级） */
.cm-no-plain { display: inline-flex; align-items: center; gap: 2px; color: var(--text-dim); font-variant-numeric: tabular-nums; }
.cm-cap { color: var(--text); font-weight: 500; }
.cm-desc { font-size: var(--fs-12); margin-top: var(--sp-3); line-height: 1.45; }
.cm-tb code { font-size: var(--fs-12); color: var(--text); background: var(--line-soft); padding: 1px var(--sp-4); border-radius: var(--r-4); overflow-wrap: anywhere; }
.cm-judge {
  display: inline-block; font-size: var(--fs-11); padding: 1px var(--sp-5);
  border-radius: var(--r-4); background: var(--brand-soft); color: var(--brand);
  line-height: 1.5; overflow-wrap: anywhere;
}
.cm-m { font-size: var(--fs-11); color: var(--text-mute); margin-left: var(--sp-5); }
.cm-badge {
  display: inline-flex; align-items: center; gap: var(--sp-5); white-space: nowrap;
  font-size: var(--fs-12); padding: 1px var(--sp-8); border-radius: var(--r-full);
}
.cm-badge i { width: 6px; height: 6px; border-radius: var(--r-full); background: currentColor; flex: none; }
.cm-badge.is-done { color: var(--ok); background: var(--ok-soft); }
.cm-badge.is-part { color: var(--warn); background: var(--warn-soft); }
.cm-badge.is-todo { color: var(--bad); background: var(--bad-soft); }
.cm-badge.is-tbd { color: var(--brand); background: var(--brand-soft); }
.cm-badge.is-na { color: var(--text-mute); background: var(--line-soft); }
.cm-note-in { font-size: var(--fs-11-5); line-height: 1.45; margin-top: var(--sp-4); color: var(--text-mute); }
.cm-note-in.is-todo { color: var(--bad); }
.cm-note-in.is-part { color: var(--warn); }
.cm-note-in.is-tbd { color: var(--brand); }
/* 搜索命中高亮：走令牌（深色主题自动跟随）—— 🔴 本批**不新增任何色值** */
.cm-tb mark { background: var(--warn-soft); color: var(--warn); padding: 0 1px; border-radius: var(--r-2); }

/* —— 统计与对比（三域 × 各机构；格子可点，r732） —— */
.cm-cmp-wrap { overflow-x: auto; }
.cm-cmp-tb { width: 100%; border-collapse: collapse; font-size: var(--fs-13); min-width: calc(560px * var(--ui-s)); }
.cm-cmp-tb th, .cm-cmp-tb td { border: 1px solid var(--line-soft); padding: var(--sp-8) var(--sp-10); text-align: left; vertical-align: top; }
.cm-cmp-tb thead th { background: var(--line-soft); color: var(--text-mute); font-weight: 500; font-size: var(--fs-12); white-space: nowrap; }
.cm-cmp-tb tbody th { background: var(--bg); white-space: nowrap; font-weight: 500; }
.cm-cmp-tb tbody th b { color: var(--text); }
.cm-cmp-tag { margin-left: var(--sp-6); font-size: var(--fs-11); color: var(--text-mute); }
.cm-cmp-c { cursor: pointer; }
.cm-cmp-c:hover { background: var(--brand-soft); }
.cm-cmp-c.is-on { background: var(--brand-soft); box-shadow: inset 0 0 0 1px var(--brand); }
.cm-cmp-n { display: block; font-variant-numeric: tabular-nums; font-weight: 500; color: var(--text-1); }
.cm-cmp-n.is-done { color: var(--ok); }
.cm-cmp-n.is-part { color: var(--warn); }
.cm-cmp-n.is-todo { color: var(--bad); }
.cm-cmp-n.is-na { color: var(--text-mute); font-weight: 400; }
.cm-cmp-p { display: block; font-size: var(--fs-12); color: var(--text-dim); font-variant-numeric: tabular-nums; }
.cm-cmp-d { display: block; font-size: var(--fs-11); }
.cm-mans-extra { display: flex; gap: var(--sp-8); flex-wrap: wrap; }
.cm-cov-meta { font-size: var(--fs-11-5); margin-top: var(--sp-2); }
.cm-cov-meta b { color: var(--text-1); font-variant-numeric: tabular-nums; }
.cm-cov-acts { display: flex; gap: var(--sp-8); flex-wrap: wrap; margin-top: var(--sp-8); }

/* —— 行抽屉 —— */
.cm-mask { position: fixed; inset: 0; background: rgba(16,24,40,.45); z-index: 300; }
.cm-drawer {
  position: fixed; top: 0; right: 0; bottom: 0; width: min(560px, 94vw);
  background: var(--card); z-index: 301; box-shadow: var(--elev-2);
  display: flex; flex-direction: column; overflow: hidden;
}
.cm-dw-h {
  display: flex; align-items: center; gap: var(--sp-10);
  padding: var(--sp-14) var(--sp-18); border-bottom: 1px solid var(--line);
}
.cm-dw-h b { flex: 1; font-size: var(--fs-16); color: var(--text); }
.cm-dw-b { padding: var(--sp-18); overflow-y: auto; }
.cm-dw-sec { margin-bottom: var(--sp-18); }
.cm-dw-sec h5 { font-size: var(--fs-13); color: var(--text-mute); font-weight: 500; margin-bottom: var(--sp-8); }
.cm-dw-sec p { font-size: var(--fs-13); color: var(--text-dim); line-height: 1.6; }
.cm-kv { display: flex; gap: var(--sp-10); font-size: var(--fs-13); padding: var(--sp-4) 0; }
.cm-kv span { color: var(--text-mute); flex: none; min-width: calc(84px * var(--ui-s)); }
.cm-kv b { color: var(--text); font-weight: 500; word-break: break-all; }
.cm-dw-note { margin-top: var(--sp-8); padding: var(--sp-10); border-radius: var(--r-8); font-size: var(--fs-12); line-height: 1.6; }
.cm-dw-note.is-todo { background: var(--bad-soft); color: var(--bad); }
.cm-dw-note.is-part { background: var(--warn-soft); color: var(--warn); }
.cm-dw-note.is-tbd { background: var(--brand-soft); color: var(--brand); }
.cm-dw-note.is-done { background: var(--ok-soft); color: var(--ok); }
.cm-dw-note.is-na { background: var(--line-soft); color: var(--text-mute); }

/* —— 接口手册弹窗（2026-10-17 大人令：进件域卡片上的按钮 → 弹窗内嵌文档站） —— */
.cm-manual { margin-top: var(--sp-8); }
.cm-doc {
  position: fixed; inset: 0; z-index: 320; background: rgba(16,24,40,.45);
  display: flex; align-items: center; justify-content: center; padding: var(--sp-16);
}
.cm-doc[hidden] { display: none; }
.cm-doc-p {
  width: min(1180px, 96vw); height: min(88vh, 980px);
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius-lg);
  box-shadow: var(--elev-2); display: flex; flex-direction: column; overflow: hidden;
}
.cm-doc-h {
  display: flex; align-items: center; gap: var(--sp-10); flex: none;
  padding: var(--sp-12) var(--sp-18); border-bottom: 1px solid var(--line);
}
.cm-doc-h b { font-size: var(--fs-14); color: var(--text); white-space: nowrap; }
.cm-doc-h .sub { flex: 1; font-size: var(--fs-12); color: var(--text-mute); }
.cm-doc-h a.mini { text-decoration: none; }
.cm-doc-f { flex: 1; width: 100%; border: 0; background: var(--bg); }

/* —— 窄屏（1180 以下）：收掉两列次要信息，避免横向滚动 —— */
@media (max-width: 1180px) {
  .cm-covs { grid-template-columns: 1fr; }
  .cm-tb col.c-judge, .cm-tb col.c-ref { width: 0; }
  .cm-tb th:nth-child(4), .cm-tb td.c-judge,
  .cm-tb th:nth-child(5), .cm-tb td.c-ref { display: none; }
}

/* ============================================================================
 * 722 · 商户进件（渠道商代商户进件）· `public/app.js` 的 `.ob-*` 段
 * ----------------------------------------------------------------------------
 * ★ 设计取向（大人原话「要照顾用户体验，流程简单，易上手」）：
 *   ① 一屏一件事：左侧 7 步进度、右侧只放**当前这一步**的字段，不铺大长表；
 *   ② 每格都有「为什么填」的灰字提示（`hint` 由后端下发），不让人猜；
 *   ③ 必填星号分两色：实心 = 这个机构必填，空心 = 满足条件才必填（悬浮看条件）；
 *   ④ 附件是「卡片 + 缩略图」，拍糊了一眼能看出来，不用点开才知道；
 *   ⑤ 驳回只标红要改的格子，其余置灰 —— 不搞「整单重填」式返工。
 * 🔴 全部用令牌变量（`--card` / `--line` / `--text-*`），深色模式自动跟随，不硬编码色值。
 * ==========================================================================*/

/* ---------- 列表页：状态筛选条 + 搜索 ---------- */
.ob-chips { display: flex; flex-wrap: wrap; gap: var(--sp-8); margin-top: var(--sp-14); }
.ob-chip {
  padding: var(--sp-6) var(--sp-14); border-radius: var(--r-full); cursor: pointer;
  border: 1px solid var(--line); background: var(--card); color: var(--text-dim);
  font-size: var(--fs-13); line-height: 1.4; transition: all .15s;
}
.ob-chip:hover { border-color: var(--brand); color: var(--brand); }
.ob-chip.is-on { background: var(--brand); border-color: var(--brand); color: var(--on-brand); font-weight: 500; }
.ob-search { display: flex; gap: var(--sp-8); align-items: center; margin-top: var(--sp-12); }
.ob-search input {
  flex: 1; max-width: calc(360px * var(--ui-s)); height: calc(34px * var(--ui-s));
  padding: 0 var(--sp-12); border: 1px solid var(--line); border-radius: var(--r-8);
  background: var(--card); color: var(--text); font-size: var(--fs-13);
}
.ob-search input:focus { outline: none; border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-soft); }
.ob-no { font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace); letter-spacing: .2px; }
.ob-sub { font-size: var(--fs-12); color: var(--text-mute); line-height: 1.6; margin-top: 2px; }
.ob-bad-t { color: var(--bad); }

/* ---------- 向导：顶栏 ---------- */
.ob-top {
  display: flex; align-items: center; gap: var(--sp-14);
  padding: var(--sp-12) var(--sp-16); margin-bottom: var(--sp-12);
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r-12);
}
.ob-topmain { display: flex; align-items: center; gap: var(--sp-10); flex: 1; min-width: 0; flex-wrap: wrap; }
.ob-topact { display: flex; align-items: center; gap: var(--sp-10); }
.ob-savetag { font-size: var(--fs-12); color: var(--text-mute); transition: color .2s; }
.ob-savetag.is-dirty { color: var(--warn); }

/* ---------- 向导：左步骤条 + 右表单 ---------- */
.ob-body { display: grid; grid-template-columns: calc(168px * var(--ui-s)) 1fr; gap: var(--sp-14); align-items: start; }
.ob-steps { list-style: none; margin: 0; padding: var(--sp-10); background: var(--card);
  border: 1px solid var(--line); border-radius: var(--r-12); position: sticky; top: var(--sp-14); }
.ob-step {
  display: flex; align-items: center; gap: var(--sp-10); cursor: pointer;
  padding: var(--sp-9) var(--sp-10); border-radius: var(--r-8); font-size: var(--fs-13);
  color: var(--text-dim); transition: background .15s, color .15s;
}
.ob-step:hover { background: var(--line-soft); }
.ob-step i {
  flex: none; width: calc(20px * var(--ui-s)); height: calc(20px * var(--ui-s));
  display: grid; place-items: center; border-radius: 50%;
  border: 1px solid var(--line); font-style: normal; font-size: var(--fs-11);
  color: var(--text-mute); background: var(--card);
}
.ob-step.is-done i { background: var(--ok-soft); border-color: var(--ok); color: var(--ok); }
.ob-step.is-on { background: var(--brand-soft); color: var(--brand); font-weight: 600; }
.ob-step.is-on i { background: var(--brand); border-color: var(--brand); color: var(--on-brand); font-weight: 600; }
.ob-step.is-bad i { background: var(--bad-soft); border-color: var(--bad); color: var(--bad); }

.ob-main { background: var(--card); border: 1px solid var(--line); border-radius: var(--r-12);
  padding: var(--sp-18) var(--sp-20); min-width: 0; }
.ob-main > h3 { font-size: var(--fs-16); margin: 0 0 var(--sp-4); }
.ob-main > .sub { margin: 0 0 var(--sp-16); color: var(--text-mute); font-size: var(--fs-13); line-height: 1.6; }

/* ---------- 分组 + 字段网格 ---------- */
.ob-grp { margin-bottom: var(--sp-20); }
.ob-grp-t {
  font-size: var(--fs-13); font-weight: 600; color: var(--text-dim);
  padding-bottom: var(--sp-8); margin-bottom: var(--sp-12);
  border-bottom: 1px dashed var(--line);
}
.ob-grp-t .subtle { font-weight: 400; color: var(--text-mute); font-size: var(--fs-12); margin-left: var(--sp-6); }
.ob-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(calc(250px * var(--ui-s)), 1fr)); gap: var(--sp-14); }
.ob-f { min-width: 0; }
.ob-f > label {
  display: flex; align-items: center; gap: 3px; margin-bottom: var(--sp-5);
  font-size: var(--fs-12-5); color: var(--text-dim);
}
.ob-f input, .ob-f select, .ob-f textarea {
  width: 100%; box-sizing: border-box;
  min-height: calc(36px * var(--ui-s)); padding: var(--sp-7) var(--sp-10);
  border: 1px solid var(--line); border-radius: var(--r-8);
  background: var(--card); color: var(--text); font-size: var(--fs-13);
  font-family: inherit; transition: border-color .15s, box-shadow .15s;
}
.ob-f textarea { min-height: calc(70px * var(--ui-s)); resize: vertical; line-height: 1.6; }
.ob-f input:focus, .ob-f select:focus, .ob-f textarea:focus {
  outline: none; border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-soft);
}
.ob-f.is-lock input, .ob-f.is-lock select, .ob-f.is-lock textarea {
  background: var(--line-soft); color: var(--text-mute); cursor: not-allowed;
}
.ob-f.is-err input, .ob-f.is-err select, .ob-f.is-err textarea { border-color: var(--bad); }
.ob-f-bool { display: flex; flex-direction: column; justify-content: flex-end; }
.ob-chk { display: flex; align-items: center; gap: var(--sp-8); cursor: pointer;
  font-size: var(--fs-13); color: var(--text-dim); padding-bottom: var(--sp-7); }
.ob-chk input { width: calc(16px * var(--ui-s)); height: calc(16px * var(--ui-s)); accent-color: var(--brand); }
.ob-req { color: var(--bad); font-style: normal; font-weight: 600; }
.ob-req2 { color: var(--warn); font-weight: 400; opacity: .85; }
.ob-unit { font-style: normal; color: var(--text-mute); }
.ob-lock { font-style: normal; font-size: var(--fs-11); color: var(--text-mute);
  border: 1px solid var(--line); border-radius: var(--r-full); padding: 0 var(--sp-6); margin-left: auto; }
.ob-hint { margin-top: var(--sp-4); font-size: var(--fs-11-5); color: var(--text-mute); line-height: 1.6; }
.ob-err { margin-top: var(--sp-4); font-size: var(--fs-11-5); color: var(--bad); line-height: 1.6; }
.ob-hl { color: var(--bad); font-weight: 600; }

/* 省 / 市 / 区 三段 */
.ob-region { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: var(--sp-6); }

/* ★★★ r800：开户银行名称 = 可搜索联想框（蓝本同款）
   ----------------------------------------------------------------------------
   为什么不用 `<select>`：全量联行号几十万条，塞进 DOM 直接卡死页面。
   为什么下拉要 `position:absolute` 且容器 `position:relative`：
     表单在弹层 / 滚动容器里，固定定位会跟内容错位；绝对定位跟着输入框走才对得上。
   🔴 留出右侧放大镜位置（`padding-right`）—— 否则长支行名会压在图标底下。 */
.ob-bank { position: relative; }
.ob-bank > input {
  width: 100%; padding-right: calc(34px * var(--ui-s));
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23667085' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='M20 20l-3.6-3.6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right calc(11px * var(--ui-s)) center;
  background-size: calc(15px * var(--ui-s));
}
.ob-bank.is-open > input { border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-soft); }
.ob-bank-pop {
  position: absolute; left: 0; right: 0; top: calc(100% + 4px); z-index: 60;
  max-height: calc(300px * var(--ui-s)); overflow-y: auto;
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-8); box-shadow: 0 8px 24px rgba(16, 24, 40, .14);
  padding: var(--sp-4);
}
.ob-bank-i {
  padding: var(--sp-7) var(--sp-9); border-radius: var(--r-6); cursor: pointer;
  line-height: 1.35;
}
.ob-bank-i:hover, .ob-bank-i.is-on { background: var(--brand-soft); }
.ob-bank-i .bi-main { font-size: var(--fs-13); color: var(--text); }
.ob-bank-i .bi-sub {
  font-size: var(--fs-11-5); color: var(--text-mute); margin-top: 2px;
  font-variant-numeric: tabular-nums;
}
.ob-bank-empty {
  padding: var(--sp-10) var(--sp-9); font-size: var(--fs-12-5); color: var(--text-dim);
  line-height: 1.7;
}
.ob-bank-empty em { font-style: normal; color: var(--text-mute); font-size: var(--fs-11-5); }
/* 深色主题：下拉阴影要更重，否则和背景糊在一起 */
html[data-theme='dark'] .ob-bank-pop { box-shadow: 0 10px 28px rgba(0, 0, 0, .55); }
html[data-theme='dark'] .ob-bank > input {
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%237E8798' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='M20 20l-3.6-3.6'/%3E%3C/svg%3E");
}

/* ★★ r794：区划 / 级联格占两列 —— `.ob-grid` 一格只有 250px，塞三个下拉每个才 80px，
   省名都显示不全。窄屏（<980）退回一列，否则会把整行撑爆。 */
.ob-f-span2 { grid-column: span 2; }
@media (max-width: 980px) { .ob-f-span2 { grid-column: 1 / -1; } }
/* ★★★ r796（大人令「要能下拉式 逐级选择 能搜索的」）：行业类目 = 点开的下拉面板
   （三列逐级 + 顶部搜索）。容器只做定位锚点，不再是自己排版的三列 select。 */
.ob-region select:disabled { opacity: .55; cursor: not-allowed; }
.ob-casc { position: relative; }
/* 值载体：`display:none` 也要能读写 `.value` / 派发 change（原生 select 无渲染依赖）。
   🔴 别用 1px + clip 那套：全局 `select{width:100%}` 优先级更高，宽度会顶成整格，
     而 `clip` 在现代内核里只剩"绘制裁剪"、不给它撑出 36px 高的白框才怪。 */
.ob-casc-native { display: none; }
.ob-casc-btn { width: 100%; min-height: calc(34px * var(--ui-s)); display: flex; align-items: center;
  justify-content: space-between; gap: var(--sp-8); padding: 0 var(--sp-10); cursor: pointer;
  border: 1px solid var(--line); border-radius: var(--r-8); background: var(--card);
  color: var(--text); font-size: var(--fs-13); text-align: left; }
.ob-casc-btn:hover { border-color: var(--brand); }
.ob-casc-btn:disabled { opacity: .55; cursor: not-allowed; }
.ob-casc-txt { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ob-casc-txt.is-ph { color: var(--text-dim); }
.ob-casc-arw { flex: none; width: 0; height: 0; border-left: 4px solid transparent;
  border-right: 4px solid transparent; border-top: 5px solid var(--text-dim); transition: transform .15s; }
.ob-casc.is-open .ob-casc-arw { transform: rotate(180deg); }
/* 面板宽度按 ui 缩放走；左对齐 + 88vw 兜底，窄屏不顶出边界 */
.ob-casc-pop { display: none; position: absolute; z-index: 80; left: 0; top: calc(100% + var(--sp-4));
  width: calc(660px * var(--ui-s)); max-width: 88vw; padding: var(--sp-8);
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r-10);
  box-shadow: 0 10px 28px rgba(16, 24, 40, .16); }
.ob-casc.is-open .ob-casc-pop { display: block; }
.ob-casc-q { display: flex; align-items: center; gap: var(--sp-6); margin-bottom: var(--sp-8); }
.ob-casc-q input { flex: 1; min-width: 0; height: calc(32px * var(--ui-s)); padding: 0 var(--sp-8);
  border: 1px solid var(--line); border-radius: var(--r-8); background: var(--bg);
  color: var(--text); font-size: var(--fs-13); }
.ob-casc-q input:focus { outline: none; border-color: var(--brand); background: var(--card); }
.ob-casc-q input::placeholder { color: var(--text-dim); }
.ob-casc-clear { flex: none; padding: 0 var(--sp-4); border: 0; background: none;
  color: var(--brand); font-size: var(--fs-12-5); cursor: pointer; }
.ob-casc-cols { display: grid; grid-template-columns: 1fr 1fr 1.45fr; gap: var(--sp-6); }
.ob-casc.is-searching .ob-casc-cols { display: none; }
.ob-casc-col { list-style: none; margin: 0; padding: 0;
  max-height: calc(272px * var(--ui-s)); overflow-y: auto; }
.ob-casc-col + .ob-casc-col { border-left: 1px solid var(--line-soft); padding-left: var(--sp-6); }
.ob-casc-item { display: block; width: 100%; padding: var(--sp-6) var(--sp-8); border: 0;
  border-radius: var(--r-6); background: none; color: var(--text); font-size: var(--fs-13);
  text-align: left; cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ob-casc-item:hover { background: var(--line-soft); }
.ob-casc-item.is-on { background: var(--brand-soft); color: var(--brand); font-weight: 600; }
.ob-casc-item:disabled { opacity: .45; cursor: not-allowed; }
.ob-casc-tip { padding: var(--sp-8); color: var(--text-dim); font-size: var(--fs-12-5); }
.ob-casc-hits { display: none; list-style: none; margin: 0; padding: 0;
  max-height: calc(308px * var(--ui-s)); overflow-y: auto; }
.ob-casc.is-searching .ob-casc-hits { display: block; }
.ob-casc-hit { display: flex; flex-direction: column; gap: 2px; width: 100%; padding: var(--sp-6) var(--sp-8);
  border: 0; border-radius: var(--r-6); background: none; text-align: left; cursor: pointer; }
.ob-casc-hit:hover { background: var(--brand-soft); }
.ob-casc-hit:disabled { opacity: .45; cursor: not-allowed; }
.ob-casc-hit-path { color: var(--text-dim); font-size: var(--fs-12); }
.ob-casc-hit-name { color: var(--text); font-size: var(--fs-13); }
.ob-casc-empty { padding: var(--sp-10); color: var(--text-dim); font-size: var(--fs-13); }

/* ---------- 附件卡片 ---------- */
/* ★★★ r802（大人令）：非法人结算开关 —— 站在它管的那三张纸头上，勾了才出格子。
   🔴 不勾时整块不占位（大人：「不选则没有 不需要」），所以这里只是「开关卡」，不是灰掉的字段。 */
.ob-gate { border: 1px solid var(--line); border-radius: var(--r-10); background: var(--line-soft);
  padding: var(--sp-12) var(--sp-14); margin-bottom: var(--sp-12); }
.ob-gate-l { display: flex; align-items: center; gap: var(--sp-8); cursor: pointer; }
.ob-gate-l input { width: 18px; height: 18px; flex: 0 0 auto; margin: 0;
  accent-color: var(--brand); cursor: pointer; }
.ob-gate-t { font-weight: 600; font-size: var(--fs-13); color: var(--text); }
.ob-gate-h { margin-top: var(--sp-6); padding-left: 26px; font-size: var(--fs-12);
  color: var(--text-mute); line-height: 1.65; }
.ob-gate-s { margin-top: var(--sp-4); padding-left: 26px; font-size: var(--fs-12); color: var(--text-dim); }
/* ★★★ r802：模板下载（按机构一份）—— 只在 admin 传过之后才出现 */
.ob-tpl-box { display: flex; flex-wrap: wrap; gap: var(--sp-6); margin: var(--sp-8) 0 var(--sp-2); }
.ob-tpl { display: inline-flex; align-items: center; padding: 3px 9px; border-radius: 999px;
  font-size: var(--fs-12); color: var(--brand); background: var(--line-soft);
  border: 1px solid transparent; text-decoration: none; white-space: nowrap; }
.ob-tpl:hover { border-color: var(--brand); }
.ob-docs { display: grid; grid-template-columns: repeat(auto-fill, minmax(calc(160px * var(--ui-s)), 1fr)); gap: var(--sp-12); }
.ob-doc { border: 1px solid var(--line); border-radius: var(--r-10); padding: var(--sp-10);
  background: var(--card); display: flex; flex-direction: column; gap: var(--sp-8); }
.ob-doc.is-on { border-color: var(--ok); }
.ob-doc-hd { font-size: var(--fs-12-5); color: var(--text-dim); display: flex; align-items: center; gap: 3px; }
/* ★ r779：合并格认成了什么 —— 一句话说清，用户才知道自己拍对没拍对 */
.ob-doc-kind { color: var(--ok); }
.ob-doc-kind b { font-weight: 600; }
/* ★ r767：`cover` 会把竖版执照（电子营业执照 PDF 转出来几乎都是竖的）裁成中间一条黄片，
   用户根本认不出是不是自己那张 ⇒ 改 `contain` + 白底，整张都看得见。
   高度给到 150px：竖图不至于细成一条，横图（身份证正反）也不至于太扁。 */
.ob-doc-img { width: 100%; height: calc(150px * var(--ui-s)); object-fit: contain;
  border-radius: var(--r-8); background: var(--card); }
.ob-doc-img[data-zoom] { cursor: zoom-in; }
.ob-doc-ph { width: 100%; height: calc(96px * var(--ui-s)); border-radius: var(--r-8);
  display: grid; place-items: center; background: var(--line-soft);
  color: var(--text-mute); font-size: var(--fs-12); border: 1px dashed var(--line); }
.ob-doc-act { display: flex; gap: var(--sp-6); align-items: stretch; }
.ob-doc-act .mini { flex: 1 1 auto; white-space: nowrap; }
/* ★ r766：传完之后三件套 —— 缩略图 / 放大 / 替换。替换用 label 伪装成按钮，点了直接开文件框 */
.ob-doc-act .ob-replace { flex: 1 1 auto; display: inline-flex; align-items: center; justify-content: center;
  padding: var(--sp-4) var(--sp-10); font-size: var(--fs-12-5); border-radius: var(--r-6);
  border: 1px solid var(--line); cursor: pointer; color: var(--text); background: none; }
.ob-doc-act .ob-replace:hover { border-color: var(--brand, var(--ok)); }
.ob-doc-act .ob-del { flex: 0 0 auto; color: var(--text-mute); background: none; border-color: transparent; }
.ob-doc-act .ob-del:hover { color: var(--bad); }
/* 🔴 r764：整块（图片区 + 文字按钮）都是点击区 —— 别再让人去猜哪个小标签能点 */
.ob-doc-pick { display: block; cursor: pointer; }
.ob-doc-pick:hover .ob-doc-ph { border-color: var(--brand, var(--ok)); color: var(--text); }
.ob-doc-pick:hover .ob-upload { text-decoration: underline; }
.ob-upload { cursor: pointer; text-align: center; display: flex; align-items: center; justify-content: center;
  margin-top: var(--sp-6); }

/* ---------- ★ r766：小微岔路条（第 1 步照片区正下方） ---------- */
/* ★ r774（大人令）：按钮贴**左**边、说明跟在后面（`flex-start` 而不是 `space-between`）——
   这是「按一下免拍执照」的动作入口，动作在前、解释在后。 */
.ob-skip { margin-top: var(--sp-10); display: flex; align-items: center; gap: var(--sp-12);
  justify-content: flex-start; flex-wrap: wrap;
  border: 1px dashed var(--line); border-radius: var(--r-10);
  padding: var(--sp-9) var(--sp-12); }
.ob-skip.is-on { border-style: solid; border-color: var(--ok); }
.ob-skip-t { font-size: var(--fs-12-5); color: var(--text-dim); line-height: 1.6; flex: 1 1 260px; }
.ob-skip .mini { flex: 0 0 auto; white-space: nowrap; }
/* 未跳过时把按钮做成**看得见的按钮**（纯文字在长句右边太容易被当成说明文字） */
.ob-skip:not(.is-on) .mini { border: 1px solid var(--brand, var(--ok)); color: var(--brand, var(--ok)); background: none; }
.ob-skip.is-on .mini { border: 1px solid var(--line); background: none; color: var(--text-dim); }
.ob-skip.is-on .mini:hover { border-color: var(--brand, var(--ok)); color: var(--text); }
.ob-skip:not(.is-on) .mini:hover { background: var(--brand-weak, transparent); }

/* ---------- ★★ r783：一单多机构 ---------- */
/* 多选（进件机构）：用**勾选块**而不是 `<select multiple>` —— 手机上没人会「按住 Ctrl 多选」。 */
.ob-multi { display: flex; flex-wrap: wrap; gap: var(--sp-8); grid-column: 1 / -1; }
/* ★★ r792（大人令「横着排起来」）：四个机构块以前折成三行 —— 根因不是 flex 折行，
   而是**字段格本身只有 250px**（`.ob-grid` 是 minmax(250px,1fr)），
   一块「国通（好生意同套接口）」就 190px，第二块必然掉下去。
   ⇒ 多选格整行独占，四块才有一行排开的可能；窄屏（<980px）仍允许折行，
     宁可行数多也不能把「国通（好生意同套接口）」挤成三行字。 */
.ob-f-wide { grid-column: 1 / -1; }
.ob-f-wide .ob-multi { flex-wrap: nowrap; overflow-x: auto; padding-bottom: 2px; }
@media (max-width: 980px) {
  .ob-f-wide .ob-multi { flex-wrap: wrap; overflow-x: visible; padding-bottom: 0; }
}
/* 🔴 用 `.ob-multi .ob-mchip`（两个类）压过 `.ob-f label`（一个类+一个元素）——
   否则会被表单标签那套 `display:block / margin-bottom` 打回竖排。 */
.ob-multi .ob-mchip { display: inline-flex; align-items: center; gap: var(--sp-6);
  border: 1px solid var(--line); border-radius: var(--r-10);
  padding: var(--sp-7) var(--sp-12); cursor: pointer; user-select: none; margin: 0;
  font-size: var(--fs-13, 13px); color: var(--text-dim); background: var(--card); }
.ob-multi .ob-mchip:hover { border-color: var(--brand, var(--ok)); }
/* 🔴 r790：这里的 input 会吃到 `.ob-f input` 那套「宽度 100% / 高 36px / 内边距 / 边框」，
   结果复选框被撑成一个大方块、把文字挤成两行，整块看着像「巨人按钮」。必须逐项复位。 */
.ob-multi .ob-mchip input {
  width: calc(16px * var(--ui-s)); height: calc(16px * var(--ui-s));
  min-height: 0; padding: 0; border: 0; border-radius: 0;
  flex: 0 0 auto; margin: 0; accent-color: var(--brand, var(--ok));
}
/* 机构名一律不折行 —— 折了就会出现「乐刷 /（好生 / 意）」这种三行小块 */
.ob-multi .ob-mchip > span { white-space: nowrap; }
.ob-multi .ob-mchip.is-on { border-color: var(--brand, var(--ok)); color: var(--text); background: var(--brand-weak, transparent); }

/* 列表「已开通机构 / 进件进度」格：每家一个可点徽标（点谁进谁那张单） */
.ob-pfc { display: flex; flex-wrap: wrap; gap: 6px; }
.ob-pfb { display: inline-flex; align-items: center; gap: 6px;
  border: 1px solid var(--line); border-radius: var(--r-10); background: none;
  padding: 3px 7px 3px 8px; cursor: pointer; font: inherit; }
.ob-pfb:hover { border-color: var(--brand, var(--ok)); background: var(--brand-weak, transparent); }
.ob-pfb-n { font-size: var(--fs-12); color: var(--text-dim); white-space: nowrap; }
.ob-pfb .badge { font-size: var(--fs-11, 11px); padding: 1px 6px; }

/* 详情页顶部的「本批 N 家」切换条 */
.ob-batch { display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  margin: 0 0 var(--sp-12); padding: var(--sp-9) var(--sp-12);
  border: 1px dashed var(--line); border-radius: var(--r-10); }
.ob-batch-t { font-size: var(--fs-12); color: var(--text-mute); }
.ob-bchip { display: inline-flex; align-items: center; gap: 6px;
  border: 1px solid var(--line); border-radius: var(--r-10); background: none;
  padding: 4px 8px; cursor: pointer; font: inherit; color: var(--text-dim); }
.ob-bchip:hover { border-color: var(--brand, var(--ok)); color: var(--text); }
.ob-bchip.is-on { border-color: var(--brand, var(--ok)); color: var(--text);
  background: var(--brand-weak, transparent); font-weight: 600; }
.ob-bchip-n { font-size: var(--fs-12-5); white-space: nowrap; }
.ob-bchip .badge { font-size: var(--fs-11, 11px); padding: 1px 6px; }

/* ★ r774：「到期日 + 长期有效」焊成一格（内部竖排：日期在上、勾选在下）。
   两者是同一个问题（填日期 / 勾长期），网格换列时不许被拆到两行两端。 */
.ob-f-pair { display: flex; flex-direction: column; gap: var(--sp-6); min-width: 0; }

/* ---------- ★ r772：邀请填写弹窗（二维码 + 链接） ---------- */
.ob-inv { max-width: 420px; }
.ob-inv-qr { display: flex; justify-content: center; padding: var(--sp-14) 0 var(--sp-10); }
/* 🔴 二维码必须留白底（`--qr-paper` 恒白，见 `:root`）——
   深色主题下黑码压深底就扫不出来，所以这里**不许**改成 var(--card)。 */
.ob-inv-qr img { display: block; width: 200px; height: 200px; background: var(--qr-paper);
  border: 1px solid var(--line); border-radius: var(--r-10, 10px); padding: 6px; }
.ob-inv-no { text-align: center; font-size: var(--fs-13); color: var(--text-dim); margin-bottom: var(--sp-10); }
.ob-inv-no b { color: var(--text); }
.ob-inv-no .subtle { display: block; font-size: var(--fs-12); color: var(--text-mute); margin-top: 2px; }
.ob-inv-link { margin-bottom: var(--sp-12); }
.ob-inv-link input { width: 100%; font-size: var(--fs-12-5); color: var(--text-dim);
  background: var(--line-soft); border: 1px solid var(--line);
  border-radius: var(--r-8, 8px); padding: 9px 10px; }
.ob-inv-tip { margin: var(--sp-12) 0 0; font-size: var(--fs-12); line-height: 1.75; }

/* ---------- ★ r766：放大看图的灯箱 ---------- */
.ob-zoom { position: fixed; inset: 0; z-index: 9999; background: rgba(0, 0, 0, .78);
  display: flex; align-items: center; justify-content: center; padding: 24px; }
.ob-zoom-in { display: flex; flex-direction: column; align-items: center; gap: 10px; max-width: 94vw; }
.ob-zoom-in img { max-width: 94vw; max-height: 82vh; object-fit: contain;
  border-radius: var(--r-10); background: var(--card); }
.ob-zoom-bar { display: flex; align-items: center; gap: var(--sp-12);
  color: rgba(255, 255, 255, .92); font-size: var(--fs-13); }

/* ---------- 底部动作条 ---------- */
.ob-foot { display: flex; align-items: center; gap: var(--sp-10);
  margin-top: var(--sp-18); padding-top: var(--sp-14); border-top: 1px solid var(--line); }
.ob-foot-mid { flex: 1; font-size: var(--fs-12); color: var(--text-mute); text-align: center; }

/* ---------- 提交前核对卡 ---------- */
.ob-sum { margin-top: var(--sp-16); padding: var(--sp-14); border-radius: var(--r-10);
  background: var(--line-soft); border: 1px solid var(--line); }
.ob-sum-r { display: flex; gap: var(--sp-10); font-size: var(--fs-13); padding: var(--sp-4) 0; }
.ob-sum-r span { color: var(--text-mute); flex: none; min-width: calc(120px * var(--ui-s)); }
.ob-sum-r b { color: var(--text); font-weight: 500; word-break: break-all; }

/* ---------- 商户确认链接 ---------- */
.ob-linkrow { display: flex; align-items: center; gap: var(--sp-8); flex-wrap: wrap; margin-top: var(--sp-8); }
.ob-link { font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: var(--fs-12); background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-6); padding: var(--sp-5) var(--sp-8); word-break: break-all; color: var(--text-dim); }

/* ---------- ★★★ r797 机构工作台 / 单家预览（大人令：一次只填一家） ---------- */
/* 🔴 这两屏**没有左侧步骤条** ⇒ 绝不能套 `.ob-body`（它是 `168px 1fr` 两列网格，
   没有第一步就会把正文塞进窄列，整页变成一条竖着的文字柱）。 */
.ob-page { display: block; }
.ob-page > .ob-main { margin-top: var(--sp-14); }
/* 工作台：一行一家。为什么用 grid 两列而不是纯 flex：
   机构名那一行常常很长（「汇享（上海）数字科技」+状态徽标+「当前」），
   按钮必须钉在右侧不动，否则长名字会把按钮挤到下一行。 */
.ob-bench { display: grid; gap: var(--sp-10); margin: var(--sp-14) 0; }
.ob-brow { display: grid; grid-template-columns: 1fr auto; align-items: center;
  gap: var(--sp-4) var(--sp-12); padding: var(--sp-12) var(--sp-14);
  border: 1px solid var(--line); border-radius: var(--r-10); background: var(--card);
  transition: border-color .15s ease; }
.ob-brow:hover { border-color: var(--brand, var(--ok)); }
.ob-brow.is-cur { border-color: var(--brand, var(--ok)); box-shadow: inset 3px 0 0 var(--brand, var(--ok)); }
.ob-brow.is-lock { background: var(--line-soft); }
.ob-brow-h { display: flex; align-items: center; gap: var(--sp-8); flex-wrap: wrap;
  grid-column: 1; }
.ob-brow-h b { font-size: var(--fs-15); }
.ob-brow-s { display: flex; align-items: center; gap: var(--sp-10); flex-wrap: wrap;
  grid-column: 1; font-size: var(--fs-12); }
.ob-brow-s code { font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  color: var(--text-dim); }
.ob-brow-a { grid-column: 2; grid-row: 1 / span 2; }
.ob-bcur { font-size: var(--fs-11, 11px); color: var(--brand, var(--ok));
  border: 1px solid currentColor; border-radius: 4px; padding: 0 5px; line-height: 1.6; }
.ob-bbad { font-size: var(--fs-11, 11px); color: var(--bad);
  border: 1px solid currentColor; border-radius: 4px; padding: 0 5px; line-height: 1.6; }

/* 预览页里的材料缩略图 */
.ob-pv-docs { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
  gap: var(--sp-10); margin-top: var(--sp-12); }
.ob-pv-doc { display: grid; gap: var(--sp-4); justify-items: center;
  font-size: var(--fs-11, 11px); color: var(--text-mute); text-align: center; }
.ob-pv-doc img { width: 100%; height: 82px; object-fit: cover;
  border-radius: var(--r-6); border: 1px solid var(--line); }
.ob-pv-doc.is-on span { color: var(--text); }
.ob-pv-no { display: flex; align-items: center; justify-content: center;
  width: 100%; height: 82px; border-radius: var(--r-6);
  border: 1px dashed var(--line); font-style: normal; color: var(--text-mute); }
.ob-pv-peers { display: flex; flex-wrap: wrap; gap: var(--sp-8); margin-top: var(--sp-10); }

/* 「再加一家」勾选面板 */
.ob-pk { display: flex; flex-wrap: wrap; gap: var(--sp-8); margin-top: var(--sp-10); }
.ob-pk-i { display: inline-flex; align-items: center; gap: var(--sp-6);
  padding: 6px 10px; border: 1px solid var(--line); border-radius: var(--r-6);
  cursor: pointer; font-size: var(--fs-13); }
.ob-pk-i.is-off { opacity: .55; cursor: default; }
.ob-pk-i i { font-style: normal; font-size: var(--fs-11, 11px); }

/* 分组标题右侧的「改基本信息 / 回去改」小按钮 —— 不能让它把标题挤到下一行 */
.ob-grp-t .mini { float: right; margin-left: var(--sp-8); }

/* ---------- ★ r791 提交核对页：一屏一家 ---------- */
/* 为什么单独起一套：这一页是取消「商户确认」之后**唯一的人工闸**，
   机构名/单号/缺项三者必须一眼分清，不能和普通 note 混在一起。 */
.ob-ck-head { display: flex; align-items: center; gap: var(--sp-8); flex-wrap: wrap;
  margin: var(--sp-10) 0; padding: var(--sp-8) var(--sp-10);
  border: 1px solid var(--line); border-radius: var(--r-6); background: var(--card); }
.ob-ck-head b { font-size: var(--fs-15); }
.ob-ck-head code { margin-left: auto; font-size: var(--fs-12); color: var(--text-dim); }
.ob-ck-miss { margin: var(--sp-8) 0 0; padding-left: 18px; }
.ob-ck-miss li { margin: var(--sp-4) 0; line-height: 1.65; }
.ob-ck-step { display: inline-block; min-width: 46px; margin-right: var(--sp-5);
  padding: 0 var(--sp-4); border-radius: 4px;
  background: var(--brand-soft); font-size: var(--fs-11); color: var(--text-dim); }

/* ---------- 选机构弹层 ---------- */
.ob-pick { max-width: calc(560px * var(--ui-s)); }
.ob-pick-list { display: grid; gap: var(--sp-10); margin-top: var(--sp-12); }
.ob-pick-card {
  display: flex; flex-direction: column; gap: 3px; text-align: left; cursor: pointer;
  padding: var(--sp-12) var(--sp-14); border: 1px solid var(--line); border-radius: var(--r-10);
  background: var(--card); transition: all .15s;
}
.ob-pick-card:hover { border-color: var(--brand); background: var(--brand-soft); }
.ob-pick-card b { font-size: var(--fs-14); color: var(--text); }
.ob-pick-card span { font-size: var(--fs-12-5); color: var(--text-dim); line-height: 1.6; }
.ob-pick-card i { font-style: normal; font-size: var(--fs-11-5); color: var(--text-mute); }
.ob-pick-ch { margin-top: var(--sp-12); }

/* ---------- 窄屏：步骤条收成横排 ---------- */
@media (max-width: 980px) {
  .ob-body { grid-template-columns: 1fr; }
  .ob-steps { position: static; display: flex; overflow-x: auto; gap: var(--sp-4); }
  .ob-step { flex: none; }
  .ob-step span { display: none; }
  .ob-step.is-on span { display: inline; }
}

/* ============================================================================
 * r747 · 资金两操作台（大人令 2026-10-18：可用余额管理 / 等待确认订单）
 * ----------------------------------------------------------------------------
 * 两台共用一套版式语言，但**形态不同**：
 *   台一 = 四级步骤条 + 单块舞台（级联，选完就走）
 *   台二 = KPI + 分段 + 宽表（队列，天天清）
 * 🔴 全部引主题令牌（--card/--line/--text/--brand…）⇒ 深浅色自动跟随。
 * ========================================================================== */

/* ---- 共用 ---- */
.fd-mch { display: flex; align-items: center; gap: var(--sp-8); font-size: var(--fs-12-5); color: var(--text-dim); }
.fd-mch code { font-weight: 600; color: var(--text); }
.fd-hi { color: var(--brand); }
.fd-sub { margin-top: 2px; font-size: var(--fs-12); color: var(--text-mute); }
.bad { color: var(--bad); }

/* ---- 台一 · 步骤条 ----
 * 🔴 r756：改用 grid 四等分。flex + 中间插箭头时，箭头宽度参与分配 ⇒ 四格宽度
 *   随内容轻微不等，视觉上「第二行没对齐」（大人 2026-10-18 反馈）。
 *   grid 每列严格 1fr，minmax(0,…) 保证长文案不顶宽。
 *
 * 🔴🔴 r904（大人 2026-10-26 第三次反馈「修好几次了一直对不齐」）—— 这次的根因不在选择器：
 *   源码从上到下一直是「四等分 grid」，而现场渲染出来是「前三格按内容、第四格吃掉剩余」。
 *   那只可能是**现场生效的不是这份规则**（index.html 被缓存 ⇒ 带着旧的 `?v=` ⇒ 浏览器
 *   继续用旧 CSS；每次只改 CSS 不动版本串，就等于没改）。
 *   两手一起上，以后不会再栽：
 *     ① 列数**不写死在选择器里** —— 由元素内联带 `--fd-n`（= 实际步数/卡数），
 *        这里只把它翻成 `--fd-cols`。项目数变了（3 步/6 卡）自动跟着变，不会多一格空位。
 *     ② `--fd-cols` 可由 media query 直接覆盖 ⇒ 窄屏仍能降 2 列
 *        （若写死 `repeat(4,…)`，内联优先级压过 media，窄屏就没救了）。
 *   ⚠️ 别再往这里写死列数。 */
.fd-steps {
  --fd-cols: var(--fd-n, 4);
  display: grid;
  grid-template-columns: repeat(var(--fd-cols), minmax(0, 1fr));
  gap: var(--sp-8); margin: 0 0 var(--sp-14);
}
.fd-step {
  min-width: 0; display: flex; align-items: center; gap: var(--sp-10);
  padding: var(--sp-11) var(--sp-12);
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r-10);
  text-align: left; cursor: pointer; transition: border-color .15s, background .15s;
}
.fd-step:hover:not(:disabled) { border-color: var(--brand-lite); }
.fd-step:disabled { cursor: default; opacity: .55; }
.fd-step.on { border-color: var(--brand); background: var(--brand-soft); }
.fd-step.done .fd-step-n { background: var(--ok); border-color: var(--ok); color: var(--on-brand); }
.fd-step-n {
  flex: none; width: 22px; height: 22px; border-radius: 50%;
  border: 1px solid var(--line); background: var(--line-soft);
  display: flex; align-items: center; justify-content: center;
  font-size: var(--fs-12); font-weight: 600; color: var(--text-dim);
}
.fd-step.on .fd-step-n { background: var(--brand); border-color: var(--brand); color: var(--on-brand); }
.fd-step-body { display: flex; flex-direction: column; min-width: 0; }
.fd-step-body b { font-size: var(--fs-13); font-weight: 600; color: var(--text); }
.fd-step-body em {
  margin-top: 2px; font-size: var(--fs-12); font-style: normal; color: var(--text-mute);
  overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}
.fd-step.on .fd-step-body em { color: var(--brand); }

/* ---- 台一 · 舞台 ---- */
.fd-stage { min-height: 220px; }
.fd-lead { margin-bottom: var(--sp-12); }
.fd-plain b { font-size: var(--fs-14); }

/* 账户卡 —— 🔴 r904：同上，列数由内联 `--fd-n` 下发（卡数 1~5 家机构各不相同，
 *   写死列数一定会有一次不齐）。卡片撑满行高 + `margin-top:auto` 把末行提示推到底，
 *   保证同一行卡片高度与底部基线一致。 */
.fd-grid {
  --fd-cols: var(--fd-n, 4);
  display: grid;
  grid-template-columns: repeat(var(--fd-cols), minmax(0, 1fr));
  gap: var(--sp-12); align-items: stretch;
}
.fd-acc {
  display: flex; flex-direction: column;
  text-align: left; padding: var(--sp-12) var(--sp-13);
  background: var(--card); border: 1.5px solid var(--line); border-radius: var(--r-10);
  cursor: pointer; transition: border-color .15s, box-shadow .15s;
}
.fd-acc:hover { border-color: var(--brand-lite); }
.fd-acc.on { border-color: var(--brand); box-shadow: 0 3px 12px rgba(22, 104, 220, .14); }
.fd-acc-h { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-8); }
.fd-acc-h b { font-size: var(--fs-13-5); color: var(--text); }
.fd-acc-l { margin-top: var(--sp-10); font-size: var(--fs-12); color: var(--text-mute); }
.fd-acc-v { font-size: calc(var(--fs-20) * 1.05); font-weight: 700; color: var(--text); letter-spacing: -.2px; }
.fd-acc.on .fd-acc-v { color: var(--brand); }
.fd-acc-s { margin-top: 1px; font-size: var(--fs-12); color: var(--text-dim); }
.fd-acc-id { margin-top: var(--sp-8); padding-top: var(--sp-8); border-top: 1px solid var(--line-soft); font-size: var(--fs-12); color: var(--text-mute); }
.fd-acc-id code { color: var(--text-dim); }
.fd-acc-hint { margin-top: auto; padding-top: 2px; font-size: var(--fs-12); color: var(--text-mute); }

/* 动作卡 */
.fd-ops { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: var(--sp-12); }
.fd-op {
  text-align: left; padding: var(--sp-13);
  background: var(--card); border: 1.5px solid var(--line); border-radius: var(--r-10);
  cursor: pointer; display: flex; flex-direction: column; gap: 3px;
  transition: border-color .15s, background .15s;
}
.fd-op:hover:not(:disabled) { border-color: var(--brand-lite); }
.fd-op.on { border-color: var(--brand); background: var(--brand-soft); }
.fd-op.off { background: var(--line-soft); border-style: dashed; cursor: not-allowed; }
.fd-op.off b { color: var(--text-mute); }
.fd-op b { font-size: var(--fs-14); color: var(--text); }
.fd-op em { font-size: var(--fs-12); font-style: normal; color: var(--text-mute); }
.fd-op.on b { color: var(--brand); }
.fd-op-tag { margin-top: var(--sp-6); }
.fd-op-note { font-size: var(--fs-12); color: var(--text-mute); }

/* 收款方 */
.fd-pgroup { margin-bottom: var(--sp-12); }
/* 🔴 r808：原来是 `space-between` —— 标题在左、「N 个」被顶到容器最右（1207），
   但卡片网格是 `auto-fill`：某组只有 2 个时只占到 890，于是「2 个」孤零零悬在空白上方，
   与第二组（满行、数量正好落在卡片右边界）**对不齐**。
   改成标题与数量紧邻 —— 两组无论几个卡片，标题行都成组、左端对齐。 */
.fd-pgroup-h {
  display: flex; align-items: center; justify-content: flex-start; gap: var(--sp-8);
  padding: var(--sp-7) var(--sp-4); font-size: var(--fs-12-5); color: var(--text-dim);
}
.fd-pgroup-body { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: var(--sp-8); }
.fd-payee {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-10);
  padding: var(--sp-10) var(--sp-12); text-align: left;
  background: var(--card); border: 1.5px solid var(--line); border-radius: var(--r-10);
  cursor: pointer; transition: border-color .15s, background .15s;
}
.fd-payee:hover { border-color: var(--brand-lite); }
.fd-payee.on { border-color: var(--brand); background: var(--brand-soft); }
.fd-payee-main { display: flex; flex-direction: column; min-width: 0; }
.fd-payee-main b { font-size: var(--fs-13); color: var(--text); overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.fd-payee-main em { margin-top: 2px; font-size: var(--fs-12); font-style: normal; color: var(--text-mute); }

/* 参数表单 + 摘要 */
.fd-form-wrap { display: grid; grid-template-columns: minmax(0, 1fr) minmax(240px, 300px); gap: var(--sp-18); align-items: start; }
/* 🔴 r808：右侧摘要卡有 14px 内边距、左侧表单没有 ⇒ 两栏首行文字差一个行高（实测差 14px），
   看起来就是「摘要卡比表单低一截」。给表单补同样的上内边距，让两边文字落在同一条基线上。
   ⚠️ 补在 `.fd-form` 而不是 `.fd-summary`：摘要卡的内边距是卡片外观的一部分，不能削。 */
.fd-form { padding-top: var(--sp-14); }
.fd-fld { display: block; margin-bottom: var(--sp-16); }
.fd-fld > span { display: block; margin-bottom: var(--sp-7); font-size: var(--fs-12-5); color: var(--text-dim); }
.fd-fld > em { display: block; margin-top: var(--sp-6); font-size: var(--fs-12); font-style: normal; color: var(--text-mute); line-height: 1.55; }
.fd-amtbox { display: flex; align-items: center; gap: var(--sp-8); border-bottom: 1px solid var(--line); padding-bottom: var(--sp-7); }
.fd-amtbox i { font-style: normal; font-size: var(--fs-17); font-weight: 600; color: var(--text); }
.fd-amtbox input {
  flex: 1; border: 0; background: transparent; outline: none;
  font-size: calc(var(--fs-20) * 1.2); font-weight: 700; color: var(--text);
}
.fd-fees { display: flex; gap: var(--sp-10); flex-wrap: wrap; }
.fd-fee {
  flex: 1 1 200px; text-align: left; padding: var(--sp-10) var(--sp-12);
  background: var(--line-soft); border: 1.5px solid var(--line); border-radius: var(--r-10);
  cursor: pointer; display: flex; flex-direction: column; gap: 2px;
}
.fd-fee.on { border-color: var(--brand); background: var(--brand-soft); }
.fd-fee b { font-size: var(--fs-13); color: var(--text); }
.fd-fee.on b { color: var(--brand); }
.fd-fee em { font-size: var(--fs-12); font-style: normal; color: var(--text-mute); }

.fd-summary { padding: var(--sp-14); border: 1px solid var(--line); border-radius: var(--r-10); background: var(--line-soft); }
.fd-sum-h { margin-bottom: var(--sp-10); font-size: var(--fs-12-5); color: var(--text-dim); }
.fd-sum-row {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-10);
  padding: var(--sp-7) 0; border-top: 1px dashed var(--line); font-size: var(--fs-13);
}
.fd-sum-row:first-of-type { border-top: 0; }
.fd-sum-row span { color: var(--text-dim); flex: none; }
.fd-sum-row b { color: var(--text); text-align: right; font-weight: 600; word-break: break-all; }
.fd-sum-amt { font-size: var(--fs-17); color: var(--brand) !important; }

/* 台一 · 底部条 */
.fd-foot {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-16);
  margin-top: var(--sp-14); padding: var(--sp-12) var(--sp-16);
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r-10);
}
.fd-foot-l { display: flex; align-items: baseline; gap: var(--sp-10); min-width: 0; }
.fd-foot-l b { font-size: var(--fs-13-5); color: var(--text); overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.fd-foot-r { display: flex; gap: var(--sp-10); flex: none; }
.fd-foot-r .primary { min-width: calc(110px * var(--ui-s)); }

/* ---- 台二 · KPI / 分段 / 表 ---- */
.fd-kpi { display: flex; flex-wrap: wrap; gap: var(--sp-12) var(--sp-44); padding: var(--sp-16) var(--sp-18); }
.fd-kpi .stat { display: flex; flex-direction: column; gap: var(--sp-3); }
.fd-kpi .stat > span { font-size: var(--fs-12-5); color: var(--text-dim); }
.fd-kpi .stat > b { font-size: calc(var(--fs-20) * 1.05); font-weight: 700; letter-spacing: .2px; }
.fd-kpi .stat > b.bad { color: var(--bad); }

.fd-bar { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-12); flex-wrap: wrap; }
.fd-tabs { display: inline-flex; gap: var(--sp-4); padding: var(--sp-3); background: var(--line-soft); border-radius: var(--r-10); }
.fd-tab {
  padding: var(--sp-7) var(--sp-14); border: 0; border-radius: var(--r-8);
  background: transparent; font-size: var(--fs-13); color: var(--text-dim); cursor: pointer;
}
.fd-tab.on { background: var(--card); color: var(--text); font-weight: 600; box-shadow: 0 1px 2px rgba(16, 24, 40, .08); }
.fd-tab b { margin-left: 3px; color: var(--brand); }
.fd-bar-r { display: flex; align-items: center; gap: var(--sp-12); }

.fd-remain { font-weight: 600; font-size: var(--fs-13); color: var(--text); }
.fd-remain.warn { color: var(--warn); }
.fd-remain.bad { color: var(--bad); }

/* 🔴 表格里的状态徽标**必须单行** —— 否则「部分确认」会被压成一列一个字（列宽一紧就发生）。
   同样把「付款方式」这类长文案允许换行但控制行高，避免整行被撑到 3 倍高。 */
.fd-tbl .tag { display: inline-block; white-space: nowrap; }
.fd-tbl td { line-height: 1.45; }
.fd-tbl .fd-sub { line-height: 1.5; }

/* 预览 JSON */
.fd-json {
  margin-top: var(--sp-12); padding: var(--sp-12); max-height: 300px; overflow: auto;
  background: var(--line-soft); border: 1px solid var(--line); border-radius: var(--r-8);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: var(--fs-12-5); line-height: 1.6; color: var(--text); white-space: pre-wrap; word-break: break-all;
}

/* 分账接收方（模态内） */
.fd-recv { display: flex; flex-direction: column; gap: var(--sp-8); margin: var(--sp-12) 0; }
.fd-recv-row { display: flex; align-items: center; gap: var(--sp-8); }
.fd-recv-row select { flex: 1; }
.fd-recv-row .fd-recv-amt { width: 110px; text-align: right; }
.fd-recv-sum {
  display: flex; align-items: center; justify-content: space-between;
  margin: var(--sp-10) 0 var(--sp-12); padding-top: var(--sp-10);
  border-top: 1px dashed var(--line); font-size: var(--fs-13); color: var(--text-dim);
}
.fd-recv-sum b { font-size: var(--fs-15); color: var(--text); }

@media (max-width: 900px) {
  /* 🔴 r904：直接给 `--fd-cols` 赋值才能压过「按项目数推导」的默认值；
     元素内联只声明 `--fd-n`，所以这里有效（写死 repeat(4,…) 就会压不动）。 */
  .fd-steps { --fd-cols: 2; }
  .fd-grid { --fd-cols: 2; }
  .fd-form-wrap { grid-template-columns: 1fr; }
  /* 🔴 r808：`.fd-orgs` 有了 `flex:none`，窄屏下会把左侧副标题挤成四行（实测 820px）。
     这里让「带机构切换器的页头」整体换行 —— 切换器独占一行、右贴。
     用 `:has()` 精确限定，别的页头（只有按钮组的那些）行为一点不变；老浏览器不支持时
     只是退化为原来的挤压表现，不影响功能。 */
  .pg-head:has(.fd-orgs) { flex-wrap: wrap; }
  .fd-orgs { flex: 1 1 100%; justify-content: flex-end; }
}

/* ============================================================================
 * r749 · 机构能力切换 + 批量出款 + 三关复核（大人令 2026-10-18 12:36）
 * 🔴 全部引主题令牌（--card/--line/--text/--brand…）⇒ 深浅色自动跟随。
 * ========================================================================== */

/* ---- 机构切换器（页头右侧 pill 组） ----
 * 🔴 r808：**必须 `flex: none`**。`.pg-head` 是 flex，左侧副标题文案很长（好几行），
 *   右块默认 `flex-shrink:1` 会被压到 223px —— 比「机构」二字 + 四个 pill 的自然宽（≈260）
 *   还窄，于是 `flex-wrap:wrap` 把 pill 组整体折到第二行：
 *   「机构」孤零零挂在标题那行、pill 组掉到副标题下方，页头高度被撑成两倍。
 *   实测（CDP，1280 视口）：orgs 高 68px、label 在 y=76、pills 在 y=105 ⇒ 肉眼就是「没对齐」。
 *   给它 `flex:none` 保住自然宽，让左侧文案去收缩（中文可断行，代价只是一行字宽）。 */
.fd-orgs { display: flex; align-items: center; gap: var(--sp-10); flex-wrap: wrap; flex: none; }
.fd-orgs-l { font-size: var(--fs-12-5); color: var(--text-dim); }
.fd-orgs-b {
  display: inline-flex; gap: var(--sp-3); padding: var(--sp-3);
  background: var(--line-soft); border-radius: var(--r-10);
}
.fd-org {
  padding: var(--sp-6) var(--sp-13); border: 0; border-radius: var(--r-8);
  background: transparent; font-size: var(--fs-13); color: var(--text-dim);
  cursor: pointer; white-space: nowrap; transition: background .15s, color .15s;
}
.fd-org:hover { color: var(--text); }
.fd-org.on {
  background: var(--card); color: var(--brand); font-weight: 600;
  box-shadow: 0 1px 2px rgba(16, 24, 40, .1);
}

/* ---- 批量出款工具条 ---- */
.fd-batchbar {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-16);
  margin: var(--sp-14) 0 var(--sp-12); padding: var(--sp-12) var(--sp-16);
  background: var(--brand-soft); border: 1px dashed var(--brand-lite); border-radius: var(--r-10);
}
.fd-batchbar-l { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.fd-batchbar-l b { font-size: var(--fs-13-5); color: var(--text); }
.fd-batchbar-r { display: flex; gap: var(--sp-8); flex: none; }

/* ---- 导入清单 ---- */
.fd-batchlist { margin-bottom: var(--sp-14); padding: var(--sp-12) var(--sp-14); }
.fd-batchlist-h {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-12);
  margin-bottom: var(--sp-10); flex-wrap: wrap;
}
.fd-batchlist-h b { font-size: var(--fs-13-5); color: var(--text); }
.fd-batchlist-h .sub { margin-left: var(--sp-8); }
.fd-batchlist-r { display: flex; gap: var(--sp-8); }
.fd-batchlist .tbl { font-size: var(--fs-12-5); }
.fd-row-bad { background: var(--bad-soft); }
.fd-row-bad td { color: var(--text); }

/* 第 4 步：批量合计（替代金额输入框） */
.fd-batchsum {
  display: flex; align-items: baseline; gap: var(--sp-10); flex-wrap: wrap;
  padding-bottom: var(--sp-7); border-bottom: 1px solid var(--line);
}
.fd-batchsum b { font-size: calc(var(--fs-20) * 1.2); font-weight: 700; color: var(--brand); }
.fd-batchsum em { font-style: normal; font-size: var(--fs-12); color: var(--text-mute); }

/* ---- 三关复核弹层 ---- */
.fd-rv { display: flex; flex-direction: column; }
.fd-rv-head {
  display: flex; align-items: flex-start; justify-content: space-between; gap: var(--sp-16);
  padding: var(--sp-12) var(--sp-14); margin-bottom: var(--sp-12);
  background: var(--line-soft); border: 1px solid var(--line); border-radius: var(--r-10);
}
.fd-rv-head b { font-size: var(--fs-14); color: var(--text); }
.fd-rv-amt { text-align: right; }
.fd-rv-amt b { display: block; font-size: calc(var(--fs-20) * 1.05); color: var(--brand); letter-spacing: .2px; }

.fd-gates { display: flex; align-items: center; gap: var(--sp-6); margin-bottom: var(--sp-14); }
.fd-gate {
  display: inline-flex; align-items: center; gap: var(--sp-6);
  padding: var(--sp-5) var(--sp-11); border: 1px solid var(--line); border-radius: 999px;
  font-size: var(--fs-12-5); color: var(--text-mute); background: var(--card);
}
.fd-gate i {
  font-style: normal; font-weight: 600; width: 16px; height: 16px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--line-soft); color: var(--text-dim); font-size: 10px;
}
.fd-gate.on { border-color: var(--brand); color: var(--brand); font-weight: 600; }
.fd-gate.on i { background: var(--brand); color: var(--on-brand); }
.fd-gate.done { border-color: var(--ok); color: var(--ok); }
.fd-gate.done i { background: var(--ok); color: var(--on-brand); }
.fd-gate-arrow { color: var(--text-mute); font-size: var(--fs-13); }

.fd-rv-tbl { max-height: 260px; overflow: auto; margin-bottom: var(--sp-14); }
.fd-rv-tbl .tbl { font-size: var(--fs-12-5); }
.fd-rv-form { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: var(--sp-4) var(--sp-18); }
.fd-rv-ro { display: flex; align-items: baseline; gap: var(--sp-8); padding: var(--sp-9) 0; }
.fd-rv-ro b { font-size: var(--fs-13-5); color: var(--text); }
.fd-rv-kv {
  display: flex; align-items: baseline; gap: var(--sp-10);
  padding: var(--sp-7) 0; border-bottom: 1px dashed var(--line);
}
.fd-rv-kv span { font-size: var(--fs-12-5); color: var(--text-dim); min-width: 64px; }
.fd-rv-kv b { font-size: var(--fs-13); color: var(--text); }

.fd-rv-verify { max-width: 520px; }
.fd-ack {
  display: flex; align-items: flex-start; gap: var(--sp-8);
  margin-top: var(--sp-10); padding: var(--sp-11) var(--sp-13);
  background: var(--warn-soft); border: 1px solid rgba(180, 83, 9, .25); border-radius: var(--r-10);
  font-size: var(--fs-13); color: var(--text); line-height: 1.55; cursor: pointer;
}
.fd-ack input { margin-top: 2px; flex: none; }

.fd-rv-done {
  padding: var(--sp-14) var(--sp-16); margin-bottom: var(--sp-12);
  border-radius: var(--r-10); border: 1px solid var(--line);
}
.fd-rv-done.ok { background: var(--ok-soft); border-color: var(--ok); }
.fd-rv-done.bad { background: var(--bad-soft); border-color: var(--bad); }
.fd-rv-done b { font-size: var(--fs-15); }
.fd-rv-done.ok b { color: var(--ok); }
.fd-rv-done.bad b { color: var(--bad); }
.fd-rv-done p { margin: var(--sp-6) 0 0; line-height: 1.6; }

/* ---- r749 · 复核策略条 / 放行验证 / 应用开关弹层 ---- */
.fd-pol {
  display: flex; align-items: center; gap: var(--sp-8); flex-wrap: wrap;
  margin-bottom: var(--sp-12); padding: var(--sp-9) var(--sp-13);
  background: var(--line-soft); border: 1px solid var(--line); border-radius: var(--r-10);
  font-size: var(--fs-12-5);
}
.fd-pol b { color: var(--text); font-size: var(--fs-12-5); }
.fd-pol .mini { margin-left: auto; }
.fd-pol-sep { color: var(--text-mute); }

.fd-rv-sms { display: flex; gap: var(--sp-8); align-items: center; }
.fd-rv-sms input { flex: 1; }
.fd-rv-sms .mini { flex: none; }
.fd-rv-face {
  padding: var(--sp-12) var(--sp-14); margin-bottom: var(--sp-6);
  background: var(--line-soft); border: 1px dashed var(--line); border-radius: var(--r-10);
}
.fd-rv-face b { font-size: var(--fs-13-5); }
.fd-rv-face p { margin: var(--sp-6) 0 0; line-height: 1.6; }

/* 功能应用里的 AT 入网入口卡 */
.fd-applink {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-16);
  margin: var(--sp-12) 0; padding: var(--sp-12) var(--sp-16);
  background: var(--brand-soft); border: 1px solid var(--brand-lite); border-radius: var(--r-10);
}
.fd-applink b { font-size: var(--fs-13-5); color: var(--text); }
.fd-applink p { margin: var(--sp-3) 0 0; line-height: 1.55; max-width: 620px; }
.fd-applink .mini { flex: none; }

/* 应用开关项 */
.fd-appitem { margin-bottom: var(--sp-10); }
.fd-appcode { font-size: 10.5px; letter-spacing: .3px; opacity: .7; margin-left: var(--sp-4); }
.fd-appparam-box { transition: opacity .15s; }
.fd-appparam-box.off { opacity: .42; pointer-events: none; }
.fd-appparams {
  display: flex; flex-wrap: wrap; gap: var(--sp-8) var(--sp-16);
  margin-top: var(--sp-10); padding-top: var(--sp-10); border-top: 1px dashed var(--line);
}
.fd-appparams-h { width: 100%; font-size: var(--fs-12); color: var(--text-mute); margin-bottom: 2px; }
.fd-appparam { display: flex; align-items: center; gap: var(--sp-8); font-size: var(--fs-12-5); color: var(--text-dim); }
.fd-appparam > span { white-space: nowrap; }
.fd-appparam input, .fd-appparam select {
  width: 150px; padding: var(--sp-5) var(--sp-8);
  font-size: var(--fs-12-5);
}

/* r749 修正：勾选框继承全局 input 宽度会被拉满 ⇒ 显式定尺 */
.fd-ack input[type="checkbox"] { width: 15px; height: 15px; flex: none; margin-top: 3px; }
/* r749 修正：清单里「删除」被压成竖排两行 */
.fd-batchlist .mini, .fd-rv .mini { white-space: nowrap; }

/* r749 · 服务费配置卡片（不用表格：4 家 × 4 费项在弹层里会被压成一条缝） */
.fd-feegrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: var(--sp-12); margin: var(--sp-14) 0; }
.fd-feecard { padding: var(--sp-12) var(--sp-14); border: 1px solid var(--line); border-radius: var(--r-10); background: var(--line-soft); }
.fd-feecard-h { display: flex; align-items: center; gap: var(--sp-8); flex-wrap: wrap; margin-bottom: var(--sp-10); }
.fd-feecard-h b { font-size: var(--fs-13-5); color: var(--text); }
.fd-feerows { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-7) var(--sp-14); margin-bottom: var(--sp-10); }
.fd-feerows > div { display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-8); }
.fd-feerows span { font-size: var(--fs-12); color: var(--text-dim); white-space: nowrap; }
.fd-feerows b { font-size: var(--fs-13); color: var(--text); }

/* ==========================================================================
   ★ r773 · 快速模式（照片全丢进来，系统自己归位）
   —— 一屏只做一件事：把图丢进来、看它被放到哪、认错了改一下。
   🔴 配色一律引令牌（本轮新增 0 个字面色值），与 705/706/722 的样式闸同口径。
   ========================================================================== */
.obq-drop { display: flex; flex-direction: column; align-items: center; gap: var(--sp-6);
  padding: var(--sp-20) var(--sp-12); margin: var(--sp-8) 0 var(--sp-14);
  border: 1.5px dashed var(--line); border-radius: var(--r-10);
  background: var(--line-soft); cursor: pointer; user-select: none; }
.obq-drop:hover, .obq-drop.on { border-color: var(--brand); background: var(--brand-soft); }
.obq-drop b { font-size: var(--fs-14); color: var(--brand); }
.obq-drop span { font-size: var(--fs-12); color: var(--text-mute); }

.obq-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(196px, 1fr));
  gap: var(--sp-12); margin-bottom: var(--sp-14); }
.obq-card { display: flex; flex-direction: column; overflow: hidden;
  border: 1px solid var(--line); border-radius: var(--r-10); background: var(--card); }
.obq-card.pend { border-color: var(--warn); }
.obq-thumb { display: flex; align-items: center; justify-content: center;
  aspect-ratio: 4 / 3; background: var(--line-soft); overflow: hidden; }
.obq-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.obq-noimg { font-size: var(--fs-12); color: var(--text-mute); }
.obq-meta { display: flex; flex-direction: column; gap: var(--sp-6);
  padding: var(--sp-8) var(--sp-10) var(--sp-10); }
.obq-meta b { font-size: var(--fs-13); color: var(--text); }
.obq-tag { font-size: var(--fs-11-5); color: var(--text-mute); }
.obq-tag.ok { color: var(--ok); }
.obq-move, .obq-assign { width: 100%; font-size: var(--fs-12); padding: var(--sp-4) var(--sp-6);
  border: 1px solid var(--line); border-radius: var(--r-6); background: var(--card); color: var(--text-dim); }
.obq-empty { margin: var(--sp-8) 0 var(--sp-14); }

/* ============================================================================
   r813 · 超级模板「微信双环境」级联多选（大人令 2026-10-23）
   ----------------------------------------------------------------------------
   大人的原话：「级联样式对齐行业类目的样式 …… 这个级联功能替换到编辑的界面里面」
   形态**照抄进件向导的 `.ob-casc`**（按钮 → 下拉面板 → 顶部搜索 + 多列逐级），
   只把「单选」升级成「多选」：
     机构列 = 多选（点方框勾选 / 点名字看它的号）
     小程序列 = 单选（仅「微信环境外」有这一级）
     商户号列 = 多选（带备注；列头有「全选 / 清空」）
   为什么不用原生 select 载值（行业类目那套）：那里是单选，值可以塞进 select；
   这里是多选，值只能留在 JS 的 Map 里，控件只负责「勾」。
   🔴 全部走 CSS 变量，深色模式自动跟随，不写死颜色。
   🔴 尺寸数值与 `.ob-casc` 完全一致（34 / 660 / 272 / 308 / 88vw），改一处要两处一起改。
   ========================================================================== */
/* 🔴 全局 `input { width: 100% }` 会把勾选框撑满整行、图形被推到行中间 ——
   级联里的 checkbox / radio 必须显式收成 16px（这条是渲染实测抓出来的，别删）。 */
.cx-box[type="checkbox"], .cx-box[type="radio"] {
  width: 16px; height: 16px; min-width: 16px; padding: 0; margin: 0; flex: none;
  accent-color: var(--brand);
}
.wx-block .wx-hd { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-12); flex-wrap: wrap; }
.wx-block .wx-hd .pc-sw { margin-top: 0; }
.wx-hd-sum { font-size: var(--fs-12-5); color: var(--text-dim); }

/* 🔴 这里**不能** `overflow: hidden` —— 级联面板是 `.cx` 内的绝对定位元素，
   一旦在 `.wx-sec` 上裁剪，面板只会露出搜索框那一条（真机实测抓出来的）。
   圆角改由 `.wx-sec-hd` 自己负责顶部两角。 */
.wx-sec { margin-top: var(--sp-10); border: 1px solid var(--line); border-radius: var(--r-10); }
.wx-sec-hd {
  display: flex; align-items: baseline; gap: var(--sp-8); flex-wrap: wrap;
  padding: var(--sp-8) var(--sp-12); background: var(--line-soft); border-bottom: 1px solid var(--line);
  border-radius: var(--r-10) var(--r-10) 0 0;
}
.wx-sec-hd b { font-size: var(--fs-13-5); }
.wx-sec-sub {
  font-size: var(--fs-11-5); font-weight: 600; color: var(--brand);
  border: 1px solid var(--brand); border-radius: var(--r-full); padding: 0 7px;
}
.wx-sec-desc { font-size: var(--fs-11-5); color: var(--text-mute); }
.wx-sec-bd { padding: var(--sp-6) var(--sp-10) var(--sp-10); }

/* ---------------------------------------------------------------- 级联 cx-*
   下面这段的每一个数值都出自 `.ob-casc`（行业类目）。不复用类名是故意的：
   一个是单选（值经隐藏 select 落 payload）、一个是多选（值在 JS Map 里），
   两套混用迟早互相牵连 —— 视觉对齐、行为各走各的。 */
.cx { position: relative; }
.cx-btn {
  width: 100%; min-height: calc(34px * var(--ui-s)); display: flex; align-items: center;
  justify-content: space-between; gap: var(--sp-8); padding: 0 var(--sp-10); cursor: pointer;
  border: 1px solid var(--line); border-radius: var(--r-8); background: var(--card);
  color: var(--text); font-size: var(--fs-13); text-align: left;
}
.cx-btn:hover { border-color: var(--brand); }
.cx-txt { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cx-txt.is-ph { color: var(--text-dim); }
.cx-arw { flex: none; width: 0; height: 0; border-left: 4px solid transparent;
  border-right: 4px solid transparent; border-top: 5px solid var(--text-dim); transition: transform .15s; }
.cx.is-open .cx-arw { transform: rotate(180deg); }

.cx-pop {
  display: none; position: absolute; z-index: 80; left: 0; top: calc(100% + var(--sp-4));
  width: calc(660px * var(--ui-s)); max-width: 88vw; padding: var(--sp-8);
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r-10);
  box-shadow: var(--elev-2);   /* 🔴 用令牌不用字面 rgba：r773 的样式闸会扫到本段 */
}
.cx.is-open .cx-pop { display: block; }
.cx-q { display: flex; align-items: center; gap: var(--sp-6); margin-bottom: var(--sp-8); }
.cx-q input {
  flex: 1; min-width: 0; height: calc(32px * var(--ui-s)); padding: 0 var(--sp-8);
  border: 1px solid var(--line); border-radius: var(--r-8); background: var(--bg);
  color: var(--text); font-size: var(--fs-13);
}
.cx-q input:focus { outline: none; border-color: var(--brand); background: var(--card); }
.cx-q input::placeholder { color: var(--text-dim); }
.cx-clear {
  flex: none; padding: 0 var(--sp-4); border: 0; background: none;
  color: var(--brand); font-size: var(--fs-12-5); cursor: pointer;
}
.cx-clear:disabled { color: var(--text-mute); cursor: default; }

.cx-cols { display: grid; grid-template-columns: 1fr 2fr; gap: var(--sp-6); }
.cx-cols.is-out { grid-template-columns: 1fr 1fr 1.45fr; }
.cx.is-searching .cx-cols { display: none; }
.cx-col { list-style: none; margin: 0; padding: 0; max-height: calc(272px * var(--ui-s)); overflow-y: auto; }
.cx-col + .cx-col { border-left: 1px solid var(--line-soft); padding-left: var(--sp-6); }
.cx-col-hd {
  position: sticky; top: 0; z-index: 1; display: flex; align-items: center; gap: var(--sp-6);
  padding: var(--sp-4) var(--sp-8); margin-bottom: 2px;
  background: var(--card); border-bottom: 1px solid var(--line-soft);
  font-size: var(--fs-11-5); color: var(--text-mute);
}
.cx-col-hd b { font-weight: 600; color: var(--text-dim); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cx-col-hd em { font-style: normal; color: var(--text-mute); }
.cx-mini {
  margin-left: auto; padding: 0 4px; border: 0; background: none;
  color: var(--brand); font-size: var(--fs-11-5); cursor: pointer;
}
.cx-mini + .cx-mini { margin-left: 0; }

/* 一行：勾选方框（多选用）+ 名字区（点名字 = 看它的号） */
.cx-item {
  display: flex; align-items: center; gap: var(--sp-6); width: 100%;
  padding: var(--sp-6) var(--sp-8); border-radius: var(--r-6);
  color: var(--text); font-size: var(--fs-13);
}
.cx-item:hover { background: var(--line-soft); }
.cx-item.is-on { background: var(--brand-soft); }
.cx-item.is-on .cx-nm { color: var(--brand); font-weight: 600; }
.cx-item.is-act { box-shadow: inset 2px 0 0 var(--brand); }
.cx-item.cx-no, .cx-item.cx-app { cursor: pointer; }
.cx-tick {
  flex: none; width: 16px; height: 16px; padding: 0; margin: 0; cursor: pointer;
  border: 1px solid var(--line); border-radius: var(--r-4); background: var(--card);
  display: grid; place-items: center; position: relative;
}
.cx-tick:hover { border-color: var(--brand); }
.cx-tick[aria-pressed="true"] { border-color: var(--brand); background: var(--brand); }
.cx-tick[aria-pressed="true"]::after {
  content: ""; width: 8px; height: 4px; margin-top: -2px;
  border-left: 2px solid var(--on-brand); border-bottom: 2px solid var(--on-brand); transform: rotate(-45deg);
}
.cx-act {
  flex: 1; min-width: 0; display: flex; align-items: baseline; gap: var(--sp-6);
  padding: 0; border: 0; background: none; cursor: pointer; text-align: left;
  color: inherit; font: inherit;
}
.cx-nm { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cx-code { font-family: var(--font-mono, monospace); font-size: var(--fs-11); color: var(--text-mute);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cx-tail { margin-left: auto; flex: none; font-size: var(--fs-11-5); color: var(--text-dim); }
.cx-rmk {
  margin-left: auto; flex: none; max-width: 46%;
  font-size: var(--fs-11-5); color: var(--text-dim);
  background: var(--line-soft); border-radius: var(--r-full); padding: 0 8px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cx-tip, .cx-empty { padding: var(--sp-8); color: var(--text-mute); font-size: var(--fs-12-5); }
.cx-cols > .cx-empty { grid-column: 1 / -1; }   /* 空格态横跨整行，别缩在第一列里 */

/* 搜索命中：平铺一层，带层级路径 */
.cx-hits { display: none; list-style: none; margin: 0; padding: 0;
  max-height: calc(308px * var(--ui-s)); overflow-y: auto; }
.cx.is-searching .cx-hits { display: block; }
.cx-hit {
  display: flex; flex-direction: column; gap: 2px; width: 100%;
  padding: var(--sp-6) var(--sp-8); border: 0; border-radius: var(--r-6);
  background: none; text-align: left; cursor: pointer;
}
.cx-hit:hover { background: var(--brand-soft); }
.cx-hit-path { color: var(--text-dim); font-size: var(--fs-12); }
.cx-hit-name { color: var(--text); font-size: var(--fs-13); }

/* 已选回显：不打开面板也能一眼数清挂了几条、单个移除 */
.cx-chips {
  display: flex; align-items: center; gap: var(--sp-6); flex-wrap: wrap;
  margin-top: var(--sp-8); font-size: var(--fs-11-5); color: var(--text-mute);
}
.cx-ph { color: var(--text-mute); }
.cx-chips-hd { flex: none; }
.cx-chip {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 1px 6px 1px 8px; border: 1px solid var(--line); border-radius: var(--r-full);
  background: var(--card); font-size: var(--fs-11-5); color: var(--text-dim);
  max-width: 100%;
}
.cx-chip b { font-weight: 600; color: var(--text); }
.cx-chip em { font-style: normal; color: var(--brand); }
.cx-chip span { font-family: var(--font-mono, monospace); color: var(--text-dim);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 22em; }
.cx-x { flex: none; font-style: normal; cursor: pointer; color: var(--text-mute); padding: 0 2px; }
.cx-x:hover { color: var(--bad); }

.wx-none { padding: var(--sp-8) var(--sp-6); font-size: var(--fs-12); color: var(--text-mute); }


/* ==========================================================================
   ★★ r904 · 终端「外观 DIY」面板（收款码 / 收银台）
   🔴 只用主题令牌（--card / --line / --text / --text-mute），深色模式自动跟随；
      面板里出现的**客户主色**（预览中的按钮/标题）一律走内联 style —— 那是数据，不是样式。
   ========================================================================== */
.diy-box{border:1px solid var(--line);border-radius:var(--radius,12px);padding:var(--sp-12,12px);background:var(--line-soft)}
.diy-cols{display:grid;grid-template-columns:minmax(0,1fr) 250px;gap:var(--sp-14,14px);align-items:start}
.diy-form .fi{margin-bottom:var(--sp-10,10px)}
.diy-form .fi:last-child{margin-bottom:0}
.diy-logo{display:flex;gap:8px;align-items:center}
.diy-logo>input{flex:1;min-width:0}
.diy-up{cursor:pointer;white-space:nowrap}
.diy-color{display:flex;gap:8px;align-items:center}
.diy-color input[type=color]{
  width:38px;height:32px;padding:0;border:1px solid var(--line);border-radius:8px;
  background:var(--card);cursor:pointer;flex:none;
}
.diy-color input[type=color]::-webkit-color-swatch-wrapper{padding:3px}
.diy-color input[type=color]::-webkit-color-swatch{border:none;border-radius:5px}
.diy-color .diy-hex,.diy-color>input[type=text]{flex:1;min-width:0}
/* 预览：固定 250px 宽，等比缩小手机，避免把左侧表单挤窄 */
.diy-prev .tm-seg{margin-bottom:8px}
/* ★★ r975：预览容器自带一套 `--pv-*` 局部变量 —— 默认值 = 经典蓝（= 收银台 :root 的口径）。
   切模板时 `diyPaintPv()` 把后端 tokens 映射进来，**预览与真机同一份配色**。
   🔴 刻意不与后台主题令牌（--card/--line/--text/--radius）同名，避免互相串味。 */
.diy-phone{
  --pv-g1:#0A2540;--pv-g2:#0E3260;--pv-g3:#113F7C;
  --pv-fg:#FFFFFF;--pv-sub-fg:rgba(255,255,255,.72);
  --pv-chip-bg:rgba(255,255,255,.12);--pv-chip-bd:rgba(255,255,255,.18);--pv-chip-fg:rgba(255,255,255,.86);
  --pv-tag-bg:rgba(255,255,255,.12);--pv-tag-bd:rgba(255,255,255,.18);--pv-tag-fg:rgba(255,255,255,.9);
  --pv-deco:1;--pv-seal-r:10px;
  --pv-primary:#1668DC;--pv-accent:#C8222B;
  --pv-r:10px;--pv-r2:14px;
  border:1px solid var(--line);border-radius:16px;overflow:hidden;background:var(--card);
  box-shadow:var(--elev-1);
}
.pv-head{
  position:relative;padding:16px 12px 14px;text-align:center;color:var(--pv-fg);
  background:linear-gradient(135deg,var(--pv-g1) 0%,var(--pv-g2) 60%,var(--pv-g3) 100%);
}
.pv-head::before{
  content:'';position:absolute;inset:0;opacity:var(--pv-deco);
  background:radial-gradient(circle at 82% 16%,rgba(200,34,43,.24),transparent 52%),
             radial-gradient(circle at 10% 88%,rgba(22,104,220,.40),transparent 56%);
}
.pv-head>*{position:relative;z-index:1}
.pv-seal{
  width:34px;height:34px;margin:0 auto 7px;border-radius:var(--pv-seal-r);display:flex;align-items:center;justify-content:center;
  font-size:15px;font-weight:700;color:#fff;overflow:hidden;box-shadow:var(--elev-2);
}
.pv-seal img{width:100%;height:100%;object-fit:cover}
.pv-nm{font-size:13px;font-weight:700;line-height:1.3}
.pv-sub{margin-top:3px;font-size:10px;color:var(--pv-sub-fg);line-height:1.3}
.pv-body{padding:12px}
.pv-methods{display:flex;flex-direction:column;gap:7px}
.pv-m{
  display:flex;align-items:center;gap:7px;padding:7px 9px;border:1.5px solid var(--line);
  font-size:11px;color:var(--text);border-radius:var(--pv-r);
}
.pv-m i{width:14px;height:14px;border-radius:4px;flex:none;background:var(--line)}
.pv-m span{flex:1}
.pv-m b{font-size:11px;font-weight:700;line-height:1}
/* 选中项：边框 / 色块 / 勾全走客户主色（真机收银台同款） */
.pv-m-on{border-color:var(--pv-primary)}
.pv-m-on i{background:var(--pv-primary)}
.pv-m-on b{color:var(--pv-primary)}
.pv-amt{margin-top:4px;text-align:center;font-size:20px;font-weight:700;letter-spacing:.4px;color:var(--pv-primary)}
.pv-btn{margin-top:2px;padding:9px;text-align:center;color:#fff;font-size:12px;font-weight:600;
  background:var(--pv-primary);border-radius:var(--pv-r)}
.pv-qr{display:flex;flex-direction:column;align-items:center;gap:8px;padding:4px 0}
.pv-qr-box{
  width:104px;height:104px;display:flex;align-items:center;justify-content:center;
  background:var(--qr-paper);border:1px solid var(--line);
}
.pv-qr-ico{width:86px;height:86px;color:var(--text)}
.pv-qr-am{font-size:18px;font-weight:700;color:var(--pv-primary)}
.pv-qr-tip{font-size:10px;color:var(--text-mute)}
.pv-foot{padding:0 12px 12px;text-align:center;font-size:9px;color:var(--text-mute);line-height:1.4}

/* ★★ r975 模板选择器：5 张卡一排，每张是「抬头 + 白卡」的微缩（配色真值来自后端 tokens） */
.tpl-pick{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:8px;margin-bottom:10px}
.tpl-card{
  border:2px solid var(--line);border-radius:10px;padding:0;overflow:hidden;background:var(--card);
  cursor:pointer;transition:.16s;text-align:center;font:inherit;
}
.tpl-card:hover{border-color:var(--brand-2,var(--line));transform:translateY(-1px)}
.tpl-card.on{border-color:var(--brand,var(--line));box-shadow:0 0 0 3px var(--line-soft)}
/* 微缩：上半是抬头渐变，左下角一枚印章，下半压一条白卡 —— 一眼看出「这版长什么样」 */
.tpl-sw{display:block;position:relative;height:40px;background:#F0F2F5}
.tpl-sw-top{display:block;position:absolute;inset:0 0 44% 0}
.tpl-sw-seal{display:block;position:absolute;left:7px;top:7px;width:11px;height:11px;border-radius:3px}
.tpl-sw-body{display:block;position:absolute;left:6px;right:6px;bottom:5px;height:10px;border-radius:2px;
  background:#fff;box-shadow:0 1px 3px rgba(0,0,0,.16)}
.tpl-nm{display:block;padding:5px 2px 6px;font-size:11px;font-weight:600;color:var(--text);line-height:1.2;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tpl-card.on .tpl-nm{color:var(--brand)}
.tpl-desc{margin:0 0 10px;font-size:11.5px;color:var(--text-mute);line-height:1.45;min-height:17px}
@media (max-width:640px){.tpl-pick{grid-template-columns:repeat(3,minmax(0,1fr))}}
.diy-prev-tip{margin-top:6px;font-size:11px}
@media (max-width:1100px){
  .diy-cols{grid-template-columns:1fr}
  .diy-prev{max-width:250px;margin:0 auto}
}

/* ★★★ r972（大人令 2026-10-28）：「所有的 IP 后面再加个地区」
   · 表格里 IP 与地区**竖着排两行** —— 横排会把「顾客 IP」那列撑到 210px，
     而这张表已经有 13 列（min-width:1720px），横向滚动条会再加长；
   · 地区永远比 IP 短，两行的高度差由 `.ip-cell` 吃掉，行高不跳；
   · `nowrap` 只加在地区上：IP 本身短，允许它在极窄屏断成两截也不好看。 */
.ip-cell { display: flex; flex-direction: column; gap: 1px; line-height: 1.35; }
.ip-cell > code { white-space: nowrap; }
.ip-geo { font-size: var(--fs-12); color: var(--text-dim); white-space: nowrap; }

/* ============================================================================
 * ★★ r979 · 台一「可用余额管理」—— 真数据台面
 * ----------------------------------------------------------------------------
 * 设计意图（资金页面，视觉必须服务于「看懂 + 不出错」）：
 *   ① **主格只有一个数字**：可动用余额。其余（可用/冻结/保证金）降为副格小字
 *      —— 钱类页面最怕并排四个大数字，用户不知道该信哪个。
 *   ② **未查询 = `****`，样式比数字更弱**（虚线边框 + 灰字）：
 *      让人一眼看出「这不是 0，是还没查」。
 *   ③ **风险条在余额之上**：先看到「这页数据可不可信」，再看数字。
 *   ④ 全部引令牌（--card/--line/--text/--ok/--warn/--bad），深浅色自动跟随。
 * ========================================================================== */

/* ---------------- 页头右区 ---------------- */
.bd-hd-r { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.bd-pick { display: flex; align-items: center; gap: 8px; }
.bd-pick select { min-width: 240px; }
.bd-plat { font-size: var(--fs-12); color: var(--text-dim); padding: 4px 10px;
  border: 1px solid var(--line); border-radius: 999px; background: var(--card); }
.bd-mode { font-size: var(--fs-12); font-weight: 700; padding: 4px 10px; border-radius: 999px; border: 1px solid; }
.bd-mode.real { color: var(--ok); border-color: var(--ok); background: var(--ok-soft); }
.bd-mode.mock { color: var(--bad); border-color: var(--bad); background: var(--bad-soft); }
.bd-mch { display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 10px 16px; margin-bottom: 12px; border-radius: var(--r-8);
  background: var(--line-soft); border: 1px solid var(--line); }
.bd-mch b { font-size: var(--fs-14); }
.bd-mch code { font-size: var(--fs-12); }

/* ---------------- 风险条 ---------------- */
.bd-alerts { display: flex; flex-direction: column; gap: 8px; margin-bottom: 14px; }
.bd-alert { display: flex; gap: 12px; padding: 12px 16px; border-radius: var(--r-8);
  border: 1px solid; align-items: flex-start; }
.bd-alert.bad { border-color: var(--bad); background: var(--bad-soft); }
.bd-alert.warn { border-color: var(--warn); background: var(--warn-soft); }
.bd-alert-i { flex: 0 0 20px; width: 20px; height: 20px; border-radius: 50%;
  display: grid; place-items: center; font-size: 12px; font-weight: 900;
  color: var(--on-brand); margin-top: 1px; }
.bd-alert.bad .bd-alert-i { background: var(--bad); }
.bd-alert.warn .bd-alert-i { background: var(--warn); }
/* 🔴 只对**标题那一层**生效（`> b`）—— 否则正文里的 <b> 也被撑成块级，一句话被拆成三行 */
.bd-alert-b > b { display: block; font-size: var(--fs-14); margin-bottom: 2px; }
.bd-alert-b p b { display: inline; font-weight: 700; }
.bd-alert-b p { font-size: var(--fs-12); color: var(--text-dim); line-height: 1.6; }
.bd-alert-b code { font-size: var(--fs-12); padding: 1px 5px; border-radius: 4px;
  background: rgba(0,0,0,.06); }

/* ---------------- 余额真相区 ---------------- */
.bd-bal { display: grid; grid-template-columns: minmax(260px, 1fr) minmax(360px, 1.15fr);
  gap: 0; border: 1px solid var(--line); border-radius: var(--radius-lg);
  background: var(--card); overflow: hidden; }
.bd-bal-main { padding: 22px 24px 18px; border-right: 1px solid var(--line-soft); }
.bd-bal-k { display: flex; align-items: center; gap: 8px;
  font-size: var(--fs-12); color: var(--text-dim); letter-spacing: .04em; }
.bd-bal-v { font-size: 40px; font-weight: 800; line-height: 1.15; margin: 6px 0 4px;
  letter-spacing: -.01em; color: var(--text); font-variant-numeric: tabular-nums; }
.bd-bal:not(.known) .bd-bal-v { color: var(--text-mute); letter-spacing: .18em; font-size: 32px; }
.bd-bal-sub { font-size: var(--fs-12); color: var(--text-dim); }
.bd-bal-src { margin-top: 10px; display: flex; align-items: center; gap: 6px;
  font-size: var(--fs-12); color: var(--text-mute); }
.bd-bal-err { margin-top: 8px; font-size: var(--fs-12); color: var(--bad);
  padding: 6px 10px; border-radius: 6px; background: var(--bad-soft); }
.bd-src { font-size: var(--fs-12); font-weight: 700; padding: 2px 8px; border-radius: 999px;
  border: 1px solid var(--line); }
.bd-src.ok { color: var(--ok); border-color: var(--ok); background: var(--ok-soft); }
.bd-src.bad { color: var(--bad); border-color: var(--bad); background: var(--bad-soft); }
.bd-src.none { color: var(--text-mute); background: var(--line-soft); }

.bd-eye { display: inline-grid; place-items: center; width: 26px; height: 26px;
  border-radius: 7px; border: 1px solid var(--line); background: var(--card);
  color: var(--text-mute); cursor: pointer; padding: 0; transition: .16s; }
.bd-eye svg { width: 15px; height: 15px; }
.bd-eye:hover { color: var(--brand); border-color: var(--brand); background: var(--brand-soft); }
.bd-eye.on { color: var(--brand); border-color: var(--brand); }
.bd-eye.busy { opacity: .45; pointer-events: none; }
.bd-eye.busy svg { animation: bdSpin 1s linear infinite; }
@keyframes bdSpin { to { transform: rotate(360deg); } }

/* 副格数量按子元素自然分列（`grid-auto-columns`）—— 不写死 3，加一格不用改 CSS */
.bd-bal-side { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; }
.bd-mini { padding: 20px 16px; display: flex; flex-direction: column; gap: 3px;
  border-left: 1px solid var(--line-soft); }
.bd-mini:first-child { border-left: 0; }
.bd-mini span { font-size: var(--fs-12); color: var(--text-dim); }
.bd-mini b { font-size: 21px; font-weight: 700; color: var(--text); font-variant-numeric: tabular-nums; }
.bd-bal:not(.known) .bd-mini b { color: var(--text-mute); letter-spacing: .12em; }
.bd-mini em { font-size: 11px; color: var(--text-mute); font-style: normal; }
.bd-bal-foot { display: flex; justify-content: space-between; align-items: center;
  gap: 12px; padding: 9px 16px; margin-bottom: 14px; flex-wrap: wrap;
  font-size: var(--fs-12); color: var(--text-dim);
  border: 1px solid var(--line); border-top: 0;
  border-radius: 0 0 var(--r-8) var(--r-8); background: var(--line-soft); }

/* ---------------- 两栏面板 ---------------- */
.bd-two { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 14px; }
.bd-panel { padding: 16px 18px; }
.bd-panel-h { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.bd-panel-h b { font-size: var(--fs-14); }
.bd-lrow { display: grid; grid-template-columns: 84px 1fr auto; align-items: baseline;
  gap: 10px; padding: 6px 0; border-bottom: 1px dashed var(--line-soft); }
.bd-lrow:last-of-type { border-bottom: 0; }
.bd-lrow span { font-size: var(--fs-12); color: var(--text-dim); }
.bd-lrow b { font-size: var(--fs-14); font-variant-numeric: tabular-nums; }
.bd-lrow em { font-size: 11px; color: var(--text-mute); font-style: normal; }
.bd-panel-note { margin-top: 10px; font-size: 11px; color: var(--text-mute); line-height: 1.6; }
.bd-grow { display: flex; justify-content: space-between; align-items: center; gap: 10px;
  padding: 6px 0; border-bottom: 1px dashed var(--line-soft); font-size: var(--fs-12); }
.bd-grow:last-of-type { border-bottom: 0; }
.bd-grow span { color: var(--text-dim); }
.bd-grow b { font-size: var(--fs-12); font-weight: 700; }
.bd-hard { color: var(--warn); }
.bd-pill { font-size: 11px; font-weight: 800; padding: 2px 8px; border-radius: 999px; border: 1px solid; }
.bd-pill.on { color: var(--ok); border-color: var(--ok); background: var(--ok-soft); }
.bd-pill.off { color: var(--bad); border-color: var(--bad); background: var(--bad-soft); }

/* ---------------- 出款区 ---------------- */
.bd-out { margin-bottom: 14px; }
.bd-out-h { display: flex; align-items: baseline; gap: 10px; margin-bottom: 10px; }
.bd-out-h b { font-size: var(--fs-15); }
.bd-out > .fd-steps { margin-bottom: 10px; }

/* 收款人卡片 */
.bd-payees { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 10px; }
.bd-payee { padding: 12px 14px; border-radius: var(--r-8);
  border: 1px solid var(--line); background: var(--card); transition: .16s;
  display: flex; flex-direction: column; gap: 8px; }
.bd-payee:hover { border-color: var(--brand); background: var(--brand-soft); }
/* 卡片主体（点它=选用），动作条单独一排 —— 不能把按钮套进按钮里 */
.bd-payee-body { text-align: left; cursor: pointer; display: flex; flex-direction: column; gap: 4px; }
.bd-payee-acts { display: flex; gap: 6px; padding-top: 8px; border-top: 1px dashed var(--line); }
.bd-payee-acts .mini { flex: 0 0 auto; }
.bd-payee-l { display: flex; align-items: center; gap: 8px; }
.bd-payee-l b { font-size: var(--fs-13); }
.bd-payee-m { font-size: var(--fs-12); color: var(--text-dim); font-variant-numeric: tabular-nums; }
.bd-payee-s { font-size: 11px; color: var(--text-mute); }
.bd-bin-hint { font-size: 11px; color: var(--brand); font-style: normal; min-height: 15px; line-height: 1.4; }
/* 删除是「危险但轻」的操作 ⇒ 描边红，别用整块实心红去抢注意力 */
button.mini.danger { background: transparent; border-color: var(--bad); color: var(--bad); }
button.mini.danger:hover:not(:disabled) { background: var(--bad); border-color: var(--bad); color: #fff; }
.bd-newpayee { margin-top: 12px; }
.bd-newform { margin-top: 10px; padding: 16px; }
.bd-newform-r { margin-top: 12px; display: flex; justify-content: flex-end; }
.bd-form2 { display: grid; grid-template-columns: 1fr 1fr; gap: 12px 16px; }
.bd-form2 > .fd-fld:nth-child(2) { grid-row: span 1; }
.bd-more-h { margin: 14px 0 8px; font-size: var(--fs-13); font-weight: 700; }

/* 预检 */
.bd-pre-bar { display: flex; align-items: center; gap: 12px; margin-top: 16px; flex-wrap: wrap; }
.bd-pre { margin-top: 14px; border: 1px solid var(--line); border-radius: var(--r-8); overflow: hidden; }
.bd-pre-h { padding: 10px 14px; font-size: var(--fs-13); font-weight: 800; }
.bd-pre-h.ok { color: var(--ok); background: var(--ok-soft); border-bottom: 1px solid var(--ok); }
.bd-pre-h.bad { color: var(--bad); background: var(--bad-soft); border-bottom: 1px solid var(--bad); }
.bd-pre-h.warn { color: var(--warn); background: var(--warn-soft); border-bottom: 1px solid var(--warn); }
.bd-pre-list { padding: 4px 0; }
.bd-pre-row { display: grid; grid-template-columns: 22px 150px 1fr; gap: 10px;
  padding: 7px 14px; align-items: baseline; font-size: var(--fs-12); }
.bd-pre-row + .bd-pre-row { border-top: 1px dashed var(--line-soft); }
.bd-pre-row b { font-weight: 700; color: var(--text); }
.bd-pre-row em { font-style: normal; color: var(--text-dim); line-height: 1.6; }
.bd-pre-i { width: 18px; height: 18px; border-radius: 50%; display: grid; place-items: center;
  font-size: 11px; font-weight: 900; color: var(--on-brand); }
.bd-pre-row.ok .bd-pre-i { background: var(--ok); }
.bd-pre-row.bad .bd-pre-i { background: var(--bad); }
.bd-pre-row.warn .bd-pre-i { background: var(--warn); }
.bd-pre-row.info .bd-pre-i { background: var(--text-mute); }
.bd-pre-row.warn em { color: var(--warn); }
.bd-pre-row.bad em { color: var(--bad); }
.bd-pre-foot { display: flex; align-items: center; gap: 14px; padding: 12px 14px;
  border-top: 1px solid var(--line-soft); background: var(--line-soft); flex-wrap: wrap; }
.bd-sum-hard { margin-top: 12px; padding-top: 10px; border-top: 1px dashed var(--line-soft);
  font-size: 11px; color: var(--text-mute); line-height: 1.6; }

/* ---------------- 流水 ---------------- */
.bd-td-msg { font-size: 11px; color: var(--text-mute); padding: 4px 10px 8px !important;
  background: var(--line-soft); }

/* ---------------- 二次确认弹层 ---------------- */
.bd-confirm { max-width: calc(400px * var(--ui-s)); }
.bd-cf-amt { font-size: 32px; font-weight: 800; text-align: center; margin: 14px 0 16px;
  color: var(--text); font-variant-numeric: tabular-nums; }
.bd-cf-rows { display: flex; flex-direction: column; gap: 6px; }
.bd-cf-rows > div { display: flex; justify-content: space-between; gap: 12px; font-size: var(--fs-12); }
.bd-cf-rows span { color: var(--text-dim); }
.bd-cf-warn { margin: 14px 0 10px; font-size: var(--fs-12); color: var(--bad);
  padding: 8px 10px; border-radius: 6px; background: var(--bad-soft); line-height: 1.6; }
.bd-confirm input { width: 100%; text-align: center; font-size: var(--fs-15); }
.bd-cf-r { display: flex; gap: 10px; margin-top: 14px; }
.bd-cf-r button { flex: 1; }

/* ---------------- 窄屏 ---------------- */
@media (max-width: 1100px) {
  .bd-bal { grid-template-columns: 1fr; }
  .bd-bal-main { border-right: 0; border-bottom: 1px solid var(--line-soft); }
  .bd-two { grid-template-columns: 1fr; }
  .bd-form2 { grid-template-columns: 1fr; }
  .bd-pre-row { grid-template-columns: 22px 1fr; }
  .bd-pre-row em { grid-column: 2; }
}
