/* 聚宽信号中转站 · 全站样式
   刻意不使用任何构建链，宝塔上传即可运行。 */

:root {
  color-scheme: light;
  /* —— 基础色板（对齐 v2board/antd 中性灰阶；主题色由 JS 按所选主题覆写）—— */
  --bg: #f5f5f5;              /* 页面底：antd 中性浅灰 */
  --surface: #ffffff;         /* 面板 / 卡片 */
  --surface-2: #fafafa;       /* 次级面板 / 表头 */
  --line: #d9d9d9;
  --line-soft: #f0f0f0;
  --text: rgba(0, 0, 0, .85);   /* 标题 */
  --text-2: rgba(0, 0, 0, .65); /* 正文 */
  --text-3: rgba(0, 0, 0, .45); /* 次要 */

  /* —— 主题色（默认 v2board「default 蓝」；JS 切主题 / 切亮暗时整体覆写这一组）—— */
  --brand: #0665d0;
  --brand-2: #2a84de;         /* hover 亮端 */
  --brand-dark: #004aab;      /* active */
  --brand-soft: #e6f6ff;
  --brand-rgb: 6, 101, 208;   /* 供 rgba() 通道使用 */
  --brand-ink: #0665d0;       /* 主色当文字用（对比足够，不必调深） */
  --on-brand: #ffffff;        /* 压在主色上的文字 */

  /* —— 涨跌与语义（对齐 antd 语义色；涨红跌绿仍保持 A 股惯例）—— */
  --up: #f5222d;      /* 涨 —— 红 */
  --down: #52c41a;    /* 跌 —— 绿 */
  --warn: #faad14;
  --ok: #52c41a;
  --danger: #f5222d;
  --info: #1890ff;
  --up-rgb: 245, 34, 45;
  --down-rgb: 82, 196, 26;
  --up-soft: #fff1f0;
  --down-soft: #f6ffed;

  --radius: 4px;
  --radius-sm: 2px;
  --shadow: 0 2px 8px rgba(0, 0, 0, .15);

  /* —— 设计令牌（v6 组件专用）：反向引用基础令牌，改一处全站联动 —— */
  --v6-navy: #0b1626;         /* 深色强调底（暗色模式另给值） */
  --v6-navy2: #13243a;
  --v6-navy3: #1d3553;        /* 实际多用于文字色 */
  --v6-orange: var(--brand);
  --v6-orange2: var(--brand-2);
  --v6-blue: var(--info);
  --v6-blue2: #e6f6ff;
  --v6-bg: var(--bg);
  --v6-white: #fff;           /* 纯白语义，勿用于面板底 */
  --v6-ink: var(--text);
  --v6-text: var(--text-2);
  --v6-muted: var(--text-3);
  --v6-line: var(--line);
  --v6-soft: var(--surface-2);
  --v6-green: var(--down);
  --v6-red: var(--up);
  --v6-amber: var(--warn);
  --v6-shadow: 0 2px 8px rgba(0, 0, 0, .15);
  --v6-shadow2: 0 6px 16px rgba(0, 0, 0, .08);
  --v6-max: 1180px;

  /* —— v3 扩展令牌（--q-* 前缀，与存量令牌零冲突）—— */
  --q-panel-a: #ffffff;
  --q-panel-b: #fafafa;
  --q-sub: #fafafa;
  --q-sub2: #f5f5f5;
  --q-hover: #f5f5f5;
  --q-track: #f0f0f0;
  --q-badge-bg: #f0f0f0;
  --q-badge-fg: rgba(0, 0, 0, .45);
  --q-muted: rgba(0, 0, 0, .45);
  --q-dim: rgba(0, 0, 0, .45);
  --q-shine: rgba(0, 0, 0, .06);
  --q-grid-rgb: 0, 0, 0;
  --q-grid-a: .04;
  --q-glow-a: rgba(var(--brand-rgb), .07);
  --q-glow-b: rgba(24, 144, 255, .07);
  --q-topbar: rgba(255, 255, 255, .82);
  --q-side-a: #ffffff;
  --q-side-b: #fafafa;
  --q-side-shadow: 1px 0 0 #f0f0f0;
  --q-shadow-sm: 0 2px 8px rgba(0, 0, 0, .08);
  --q-dot-ring: #ffffff;
  --q-nav-on-bg: rgba(var(--brand-rgb), .17);
  --q-nav-on-bd: rgba(var(--brand-rgb), .34);
  /* 知识库代码块。刻意单独给令牌而不复用 --v6-navy：暗色模式下
     页面底本身就是深蓝，再用深色底代码块会糊成一片、看不出边界。 */
  --q-code-bg: #fafafa;
  --q-code-fg: rgba(0, 0, 0, .65);
}

/* ============================================================
   暗色模式：整体覆写令牌即可，存量组件零改动自动跟随。
   html[data-mode="dark"] 由 base.html 的初始化脚本写入（防 FOUC）。
   主题色同样被 JS 覆写，这里给出的只是「JS 未运行」时的兜底值。
   ============================================================ */
html[data-mode="dark"] {
  color-scheme: dark;
  --bg: #141414;
  --surface: #1f1f1f;
  --surface-2: #1a1a1a;
  --line: #303030;
  --line-soft: #262626;
  --text: rgba(255, 255, 255, .85);
  --text-2: rgba(255, 255, 255, .65);
  --text-3: rgba(255, 255, 255, .45);

  --brand: #177ddc;
  --brand-2: #4095e0;
  --brand-dark: #095cb5;
  --brand-soft: #111d2c;
  --brand-rgb: 23, 125, 220;
  --brand-ink: #3c9be8;
  --on-brand: #ffffff;

  --up: #ff4d4f;
  --down: #52c41a;
  --warn: #faad14;
  --ok: #52c41a;
  --danger: #ff4d4f;
  --info: #177ddc;
  --up-rgb: 255, 77, 79;
  --down-rgb: 82, 196, 26;
  --up-soft: #2a1215;
  --down-soft: #162312;

  --shadow: 0 2px 8px rgba(0, 0, 0, .45);

  --v6-navy: #0a0a0a;
  --v6-navy2: #141414;
  --v6-navy3: rgba(255, 255, 255, .85);        /* 文字色用途，暗底要变亮 */
  --v6-blue2: #111d2c;
  --v6-white: #fff;
  --v6-shadow: 0 2px 8px rgba(0, 0, 0, .45);
  --v6-shadow2: 0 6px 16px rgba(0, 0, 0, .45);

  --q-panel-a: #1f1f1f;
  --q-panel-b: #1a1a1a;
  --q-sub: #1a1a1a;
  --q-sub2: #1f1f1f;
  --q-hover: #262626;
  --q-track: #303030;
  --q-badge-bg: #262626;
  --q-badge-fg: rgba(255, 255, 255, .65);
  --q-muted: rgba(255, 255, 255, .45);
  --q-dim: rgba(255, 255, 255, .45);
  --q-shine: rgba(255, 255, 255, .12);
  --q-grid-rgb: 255, 255, 255;
  --q-grid-a: .04;
  --q-glow-a: rgba(var(--brand-rgb), .15);
  --q-glow-b: rgba(23, 125, 220, .12);
  --q-topbar: rgba(20, 20, 20, .86);
  --q-side-a: #1f1f1f;
  --q-side-b: #1a1a1a;
  --q-side-shadow: 1px 0 0 #303030;
  --q-shadow-sm: 0 2px 8px rgba(0, 0, 0, .45);
  --q-dot-ring: #141414;
  --q-code-bg: #1a1a1a;
  --q-code-fg: rgba(255, 255, 255, .85);
}
/* 语义混用的针对性修补：--v6-navy 既当深底又当标题文字色，
   暗色下深底要保持，标题文字必须换成亮色。 */
html[data-mode="dark"] .service-setup-card-v3 h3 { color: var(--text); }
html[data-mode="dark"] .v6-badge.is-navy { background: var(--q-badge-bg); color: var(--v6-navy3); }
html[data-mode="dark"] .cs-dock-qq { color: var(--text-2); }
html[data-mode="dark"] .brand-mark { box-shadow: 0 4px 14px rgba(var(--brand-rgb), .45); }


* { box-sizing: border-box; }

html, body {
  margin: 0; padding: 0;
  background: var(--bg);
  color: var(--text);
  font-family: system-ui, -apple-system, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--brand); text-decoration: none; }
a:hover { text-decoration: underline; }
h1, h2, h3, h4 { margin: 0 0 .5em; font-weight: 600; line-height: 1.3; }
h1 { font-size: 28px; }
h2 { font-size: 20px; }
h3 { font-size: 16px; }
p { margin: 0 0 1em; }
ul, ol { margin: 0 0 1em; padding-left: 1.3em; }
code, pre, .mono { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }

/* ---------- 布局 ---------- */
.container { max-width: 1120px; margin: 0 auto; padding: 0 20px; }
.container-narrow { max-width: 760px; margin: 0 auto; padding: 0 20px; }
.page { padding: 28px 0 72px; }
.page-head { margin-bottom: 22px; }
.page-head .sub { color: var(--text-2); font-size: 14px; }
.section { margin-bottom: 32px; }
.grid { display: grid; gap: 16px; }
.grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.row { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
.row-between { display: flex; gap: 10px; justify-content: space-between; align-items: center; flex-wrap: wrap; }
.spacer { flex: 1; }
.stack > * + * { margin-top: 14px; }

@media (max-width: 860px) {
  .grid-2, .grid-3, .grid-4 { grid-template-columns: 1fr; }
  h1 { font-size: 23px; }
}

/* ---------- 顶栏（v3 亮色：半透明白 + 深字，随主题色联动） ---------- */
.topbar {
  background: var(--q-topbar);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--line-soft);
  position: sticky; top: 0; z-index: 50;
  color: var(--text-2);
}
.topbar .inner {
  max-width: var(--v6-max); margin: 0 auto; padding: 0 20px;
  height: 64px; display: flex; align-items: center; gap: 22px;
}
.brand { font-weight: 700; font-size: 16px; color: var(--text); letter-spacing: .2px; display: flex; align-items: center; gap: 9px; }
.brand:hover { text-decoration: none; }
.brand span { color: var(--brand); }
.brand-mark {
  width: 32px; height: 32px; border-radius: var(--radius-sm); flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  overflow: hidden; box-shadow: 0 4px 12px rgba(var(--brand-rgb), .3);
}
.brand-mark img { width: 100%; height: 100%; display: block; object-fit: cover; }
.nav { display: flex; gap: 4px; align-items: center; flex-wrap: wrap; }
.nav a {
  color: var(--text-3); font-size: 14px; padding: 8px 12px; border-radius: var(--radius-sm);
  display: inline-flex; align-items: center; gap: 6px;
}
.nav a:hover { color: var(--text); background: var(--q-hover); text-decoration: none; }
.nav a.active { color: var(--brand-ink); background: var(--q-nav-on-bg); }
.topbar .right { margin-left: auto; display: flex; gap: 10px; align-items: center; }
.topbar .btn.ghost { background: var(--surface); color: var(--text-2); border-color: var(--line); }
.topbar .btn.ghost:hover { background: var(--q-hover); color: var(--text); }
.topbar .btn { background: var(--brand); color: var(--on-brand); }
.nav-burger {
  display: none; background: var(--surface); border: 1px solid var(--line);
  color: var(--text-2); border-radius: var(--radius-sm); padding: 6px 10px; cursor: pointer; font-size: 16px;
}
/* 积分 chip */
.points-chip {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 6px 12px; border-radius: 999px;
  background: rgba(var(--brand-rgb), .12); border: 1px solid rgba(var(--brand-rgb), .3);
  color: var(--brand-ink); font-size: 13px;
}
.points-chip strong { color: var(--brand-ink); font-weight: 800; }
.points-chip:hover { text-decoration: none; background: rgba(var(--brand-rgb), .2); }
/* 用户下拉 */
.nav-user-menu { position: relative; }
.nav-user-menu > summary {
  list-style: none; cursor: pointer; display: inline-flex; align-items: center; gap: 8px;
  padding: 5px 11px 5px 5px; border-radius: 999px;
  background: var(--surface); border: 1px solid var(--line);
  color: var(--text-2); font-size: 13.5px;
}
.nav-user-menu > summary::-webkit-details-marker { display: none; }
.v6-avatar {
  width: 26px; height: 26px; border-radius: 50%; flex: none;
  background: linear-gradient(140deg, var(--brand), var(--brand-2));
  color: var(--on-brand); font-weight: 800; font-size: 13px;
  display: inline-flex; align-items: center; justify-content: center;
  overflow: hidden;
}
.v6-avatar img { width: 100%; height: 100%; display: block; object-fit: cover; }
.nav-user-dropdown {
  position: absolute; right: 0; top: calc(100% + 8px); z-index: 60;
  min-width: 176px; padding: 7px; border-radius: var(--radius); background: var(--surface);
  border: 1px solid var(--line); box-shadow: var(--v6-shadow);
}
.nav-user-dropdown a {
  display: block; padding: 9px 12px; border-radius: var(--radius-sm);
  color: var(--text-2); font-size: 13.5px;
}
.nav-user-dropdown a:hover { background: var(--q-hover); color: var(--text); text-decoration: none; }
.nav-user-dropdown a.dropdown-logout { color: var(--v6-red); }
/* 管理后台与上面九模块不是一回事，用一条极淡的分隔线断开 */
.nav-user-dropdown .dropdown-sep {
  height: 1px; margin: 6px 8px; background: var(--line-soft);
}
/* 退出登录是 <form><button>（必须是 POST，见 base.html 注释），
   这里把它调成和上面几个 <a> 完全一致的观感，避免露出原生按钮灰底。 */
.nav-user-dropdown .dropdown-form { margin: 0; }
.nav-user-dropdown button.dropdown-logout {
  display: block; width: 100%; text-align: left; cursor: pointer;
  padding: 9px 12px; border-radius: var(--radius-sm);
  background: none; border: 0; font-family: inherit; font-size: 13.5px;
  line-height: inherit; color: var(--v6-red);
}
.nav-user-dropdown button.dropdown-logout:hover {
  background: var(--q-hover); color: var(--v6-red);
}

/* ---------- 主题切换器（顶栏胶囊 + 浮层） ---------- */
.theme-pop { position: relative; }
.theme-pop > summary {
  list-style: none; cursor: pointer; display: inline-flex; align-items: center; gap: 7px;
  padding: 6px 11px; border-radius: 999px;
  background: var(--surface); border: 1px solid var(--line);
  color: var(--text-2); font-size: 13px;
}
.theme-pop > summary::-webkit-details-marker { display: none; }
.theme-pop > summary:hover { background: var(--q-hover); color: var(--text); }
.theme-pop .tdot-mini { width: 9px; height: 9px; border-radius: 50%; background: var(--brand); display: inline-block; flex: none; }
.theme-pop-card {
  position: absolute; right: 0; top: calc(100% + 8px); z-index: 60;
  width: 238px; padding: 13px 14px; border-radius: var(--radius);
  background: var(--surface); border: 1px solid var(--line); box-shadow: var(--v6-shadow);
}
.theme-pop-card .tp-h { font-size: 10.5px; letter-spacing: .1em; font-weight: 800; color: var(--q-dim); margin-bottom: 9px; }
.theme-pop-card .tp-row { display: flex; gap: 8px; flex-wrap: wrap; }
.theme-pop-card .tp-h + .tp-row + .tp-h { margin-top: 13px; }
.tdot {
  width: 22px; height: 22px; border-radius: 50%; border: 2px solid transparent;
  padding: 0; cursor: pointer; transition: transform .16s;
}
.tdot:hover { transform: scale(1.14); }
.tdot.is-on { border-color: var(--q-dot-ring); box-shadow: 0 0 0 3px rgba(var(--brand-rgb), .3); }
.mbtn {
  flex: 1; padding: 6px 9px; border-radius: var(--radius-sm); cursor: pointer; font: inherit; font-size: 12.5px;
  border: 1px solid var(--line); background: var(--surface-2); color: var(--text-2);
}
.mbtn:hover { background: var(--q-hover); color: var(--text); }
.mbtn.is-on { background: var(--brand); border-color: var(--brand); color: var(--on-brand); font-weight: 700; }
.tp-foot { margin-top: 12px; font-size: 11.5px; color: var(--q-dim); line-height: 1.6; }
@media (max-width: 980px) {
  .nav-burger { display: inline-block; }
  .topbar .nav { display: none; }
  .topbar .nav.open {
    display: flex; flex-direction: column; align-items: stretch;
    position: absolute; left: 0; right: 0; top: 64px;
    background: var(--surface); padding: 10px 16px 16px; gap: 2px;
    border-bottom: 1px solid var(--line-soft); box-shadow: var(--v6-shadow);
  }
  .topbar .inner { position: relative; }
  .theme-pop-card { width: 214px; }
}

/* ---------- 卡片 ---------- */
.card {
  background: var(--surface);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  padding: 20px;
  box-shadow: var(--shadow);
}
.card.plain { box-shadow: none; }
.card h2, .card h3 { margin-top: 0; }
.card-sub { color: var(--text-2); font-size: 13px; margin: -6px 0 14px; }

/* ---------- 按钮 ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  padding: 9px 16px; border-radius: var(--radius-sm);
  border: 1px solid transparent; background: var(--brand); color: var(--on-brand);
  font-size: 14px; font-family: inherit; cursor: pointer; line-height: 1.2;
  transition: opacity .15s, background .15s;
}
.btn:hover { background: var(--brand-2); border-color: var(--brand-2); text-decoration: none; }
.btn:active { background: var(--brand-dark); border-color: var(--brand-dark); }
.btn:disabled { opacity: .45; cursor: not-allowed; }
.btn.ghost { background: var(--surface); color: var(--text); border-color: var(--line); }
.btn.ghost:hover { color: var(--brand); border-color: var(--brand); background: var(--surface); }
.btn.ghost:active { color: var(--brand-dark); border-color: var(--brand-dark); }
.btn.danger { background: var(--danger); }
.btn.sm { padding: 5px 11px; font-size: 12.5px; }
.btn.block { width: 100%; }
.btn.link { background: none; color: var(--brand); padding: 0; border: 0; }
.btn-group { display: inline-flex; gap: 8px; flex-wrap: wrap; }

/* ---------- 表单 ---------- */
label { display: block; font-size: 13.5px; color: var(--text-2); margin-bottom: 6px; }
input[type=text], input[type=email], input[type=password], input[type=number],
input[type=date], select, textarea {
  width: 100%; padding: 10px 12px; font-size: 14px; font-family: inherit;
  color: var(--text); background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  outline: none; transition: border-color .15s, box-shadow .15s;
}
input:focus, select:focus, textarea:focus {
  border-color: var(--brand); box-shadow: 0 0 0 2px rgba(var(--brand-rgb), .2);
}
textarea { min-height: 90px; resize: vertical; }
.field { margin-bottom: 16px; }
.field .hint { font-size: 12px; color: var(--text-3); margin-top: 4px; }
.field-row { display: flex; gap: 12px; }
.field-row > * { flex: 1; }

/* ---------- 表格 ---------- */
.table-wrap { overflow-x: auto; }
table.tbl { width: 100%; border-collapse: collapse; font-size: 13.5px; }
table.tbl th, table.tbl td {
  text-align: left; padding: 10px 12px; border-bottom: 1px solid var(--line-soft);
  white-space: nowrap; vertical-align: middle;
}
table.tbl th { color: var(--text-2); font-weight: 500; font-size: 12.5px; background: var(--surface-2); }
table.tbl tr:hover td { background: var(--surface-2); }
table.tbl td.wrap { white-space: normal; }
table.tbl .num { font-family: ui-monospace, monospace; }

/* ---------- 徽章 / 标签 ---------- */
.pill {
  display: inline-block; padding: 2px 9px; border-radius: 99px;
  font-size: 11.5px; line-height: 1.7; white-space: nowrap;
}
.pill.gray { background: #f0f0f0; color: var(--text-2); }
.pill.blue { background: #e6f7ff; color: #1890ff; }
.pill.green { background: #f6ffed; color: var(--ok); }
.pill.amber { background: #fffbe6; color: var(--warn); }
.pill.red { background: #fff1f0; color: var(--danger); }
.pill.brand { background: var(--brand-soft); color: var(--brand-dark); }
.tag {
  display: inline-block; padding: 2px 9px; border-radius: var(--radius-sm);
  background: var(--surface-2); border: 1px solid var(--line-soft);
  font-size: 12px; color: var(--text-2);
}
.p-pending { background: #fffbe6; color: var(--warn); }
.p-processing { background: #e6f7ff; color: #1890ff; }
.p-acked { background: #f6ffed; color: var(--ok); }
.p-failed, .p-rejected { background: #fff1f0; color: var(--danger); }
.p-dead_letter { background: #fff1f0; color: #a8071a; }

.up { color: var(--up); }
.down { color: var(--down); }
.muted { color: var(--text-2); }
.dim { color: var(--text-3); }
.small { font-size: 12.5px; }
.mono { font-size: 12.5px; }

/* ---------- 提示条 ---------- */
.alert { padding: 11px 14px; border-radius: var(--radius-sm); margin-bottom: 16px; font-size: 14px; }
.alert.ok { background: #f6ffed; color: #237804; border: 1px solid #b7eb8f; }
.alert.err { background: #fff1f0; color: #a8071a; border: 1px solid #ffa39e; }
.alert.info { background: #e6f7ff; color: #0958d9; border: 1px solid #91d5ff; }
.alert.warn { background: #fffbe6; color: #ad6800; border: 1px solid #ffe58f; }

/* ---------- 统计块 ---------- */
.stat { text-align: left; }
.stat .label { font-size: 12.5px; color: var(--text-2); }
.stat .value { font-size: 24px; font-weight: 600; line-height: 1.25; margin-top: 2px; }
.stat .value.sm { font-size: 18px; }

.kv-list { display: grid; gap: 10px; }
.kv-list .item { display: flex; gap: 12px; font-size: 13.5px; }
.kv-list .item .k { color: var(--text-2); min-width: 110px; }
.kv-list .item .v { flex: 1; word-break: break-all; }

/* ---------- 空状态 ---------- */
.empty { text-align: center; color: var(--text-3); font-size: 14px; padding: 36px 16px; }
.empty .big { font-size: 15px; color: var(--text-2); margin-bottom: 6px; }

/* ---------- 首页 Hero ---------- */
.hero { padding: 64px 0 44px; text-align: center; }
.hero h1 { font-size: 38px; letter-spacing: -.4px; }
.hero .lead { font-size: 17px; color: var(--text-2); max-width: 720px; margin: 0 auto 26px; }
.hero .cta { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; }
.chips { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; margin-top: 22px; }
.chip { font-size: 12.5px; color: var(--text-2); background: var(--surface); border: 1px solid var(--line-soft);
        border-radius: 99px; padding: 5px 13px; }

.section-title { text-align: center; margin-bottom: 26px; }
.section-title .eyebrow { font-size: 12px; letter-spacing: 1.6px; color: var(--brand); font-weight: 600; text-transform: uppercase; }
.section-title h2 { font-size: 26px; margin-top: 6px; }
.section-title p { color: var(--text-2); max-width: 640px; margin: 6px auto 0; font-size: 14.5px; }

.step { display: flex; gap: 14px; }
.step .idx {
  flex: none; width: 30px; height: 30px; border-radius: 50%;
  background: var(--brand-soft); color: var(--brand-dark);
  display: flex; align-items: center; justify-content: center;
  font-size: 13px; font-weight: 600;
}

.plan { position: relative; display: flex; flex-direction: column; }
.plan .price { font-size: 30px; font-weight: 700; line-height: 1.15; }
.plan .price .unit { font-size: 14px; font-weight: 400; color: var(--text-2); margin-left: 4px; }
.plan .feature { display: flex; gap: 8px; font-size: 13.5px; padding: 4px 0; color: var(--text-2); }
.plan .feature::before { content: "✓"; color: var(--ok); flex: none; }
.plan.highlight { border-color: var(--brand); box-shadow: 0 0 0 1px var(--brand), var(--shadow); }
.plan .ribbon {
  position: absolute; top: -11px; right: 16px; background: var(--brand); color: var(--on-brand);
  font-size: 11.5px; padding: 3px 10px; border-radius: 99px;
}

.risk-note { font-size: 12.5px; color: var(--text-3); line-height: 1.7; }
.footer { border-top: 1px solid var(--line-soft); background: var(--surface); padding: 26px 0; margin-top: 40px; }
.footer .inner { max-width: 1120px; margin: 0 auto; padding: 0 20px; color: var(--text-3); font-size: 12.5px; }
.footer .links { display: flex; gap: 16px; flex-wrap: wrap; margin-bottom: 10px; }

/* ---------- 侧栏布局（用户中心 / 后台） ---------- */
.shell { display: grid; grid-template-columns: 200px minmax(0, 1fr); gap: 24px; align-items: start; }
@media (max-width: 900px) { .shell { grid-template-columns: 1fr; } }
.side { background: var(--surface); border: 1px solid var(--line-soft); border-radius: var(--radius); padding: 10px; position: sticky; top: 76px; }
.side a { display: block; padding: 8px 12px; border-radius: var(--radius-sm); color: var(--text-2); font-size: 14px; }
.side a:hover { background: var(--surface-2); text-decoration: none; }
.side a.active { background: var(--brand-soft); color: var(--brand-dark); font-weight: 500; }
.side .group { font-size: 11.5px; color: var(--text-3); padding: 12px 12px 4px; letter-spacing: .6px; }

/* ---------- 迷你图表 ---------- */
.spark { width: 100%; height: 140px; display: block; }
.spark path.line { fill: none; stroke: var(--brand); stroke-width: 2; }
.spark path.area { fill: var(--brand-soft); opacity: .6; }
.spark line.axis { stroke: var(--line-soft); stroke-width: 1; }

/* ---------- 代码块 ---------- */
pre.code {
  background: #28282a; color: #e8e8e6; padding: 14px 16px; border-radius: var(--radius-sm);
  overflow-x: auto; font-size: 12.5px; line-height: 1.65; margin: 0 0 14px;
}
pre.code .c { color: #8f8f8a; }
.token-box {
  font-family: ui-monospace, monospace; font-size: 12.5px;
  background: var(--surface-2); border: 1px dashed var(--line);
  padding: 8px 11px; border-radius: var(--radius-sm); word-break: break-all;
}

/* ---------- 后台 ---------- */
.badge-dot { display: inline-block; width: 7px; height: 7px; border-radius: 50%; margin-right: 6px; }
.badge-dot.red { background: var(--danger); }
.badge-dot.amber { background: var(--warn); }
.badge-dot.green { background: var(--ok); }

.tabs { display: flex; gap: 6px; border-bottom: 1px solid var(--line-soft); margin-bottom: 18px; flex-wrap: wrap; }
.tabs a { padding: 8px 14px; font-size: 14px; color: var(--text-2); border-bottom: 2px solid transparent; }
.tabs a:hover { text-decoration: none; color: var(--brand); }
.tabs a.active { color: var(--brand); border-bottom-color: var(--brand); font-weight: 500; }

/* ================= 通道工作台（阶段四 · 工作台信息架构） ================= */

.wb-head { padding: 22px 24px; }
.wb-eyebrow {
  font-size: 11.5px; letter-spacing: 1.4px; text-transform: uppercase;
  color: var(--brand); font-weight: 600; margin-bottom: 6px;
}
.wb-title { font-size: 26px; margin: 0 0 6px; display: flex; align-items: center; gap: 10px; }
.wb-title .pill { font-size: 12px; }

.wb-h2 { font-size: 20px; margin: 28px 0 4px; }
.wb-lead { color: var(--text-2); font-size: 14px; margin: 0 0 16px; }

.wb-status { padding: 16px 18px; }
.wb-status .label { font-size: 12.5px; color: var(--text-2); }
.wb-status .v { font-size: 17px; font-weight: 600; margin-top: 6px; line-height: 1.4; }
.wb-status .v.sm { font-size: 15px; font-weight: 500; }
.wb-status .hint { font-size: 12px; color: var(--text-3); margin-top: 6px; }

.wb-step { position: relative; padding: 20px 20px 16px; }
.wb-step-no {
  position: absolute; top: 18px; right: 18px;
  width: 26px; height: 26px; border-radius: 50%;
  background: var(--text); color: #fff; font-size: 13px; font-weight: 600;
  display: flex; align-items: center; justify-content: center;
}
.wb-step-title { margin: 0 40px 8px 0; font-size: 17px; }
.wb-step .btn { margin-top: 14px; }
.wb-step-foot {
  display: flex; gap: 8px; align-items: center; flex-wrap: wrap;
  margin-top: 12px; font-size: 12.5px;
}
.wb-step-foot .dot { color: var(--text-3); }
.wb-filename {
  background: var(--surface-2); border: 1px solid var(--line-soft);
  border-radius: var(--radius-sm); padding: 7px 10px; margin: 0 0 4px;
}

.wb-verify { padding: 20px 22px; border-style: dashed; }
.wb-verify .wb-testform { margin-top: 14px; }
.wb-testform {
  display: flex; gap: 12px; align-items: flex-end; flex-wrap: wrap;
  padding: 14px; background: var(--surface-2);
  border: 1px solid var(--line-soft); border-radius: var(--radius-sm);
}
.wb-testform .f { display: flex; flex-direction: column; gap: 5px; }
.wb-testform .f > span { font-size: 12px; color: var(--text-2); }
.wb-testform .f input, .wb-testform .f select { min-width: 130px; }
.wb-testform .f input[name="symbol"] { min-width: 150px; }
.wb-testform .f input[name="quantity"] { min-width: 90px; }

.wb-settings .field { margin-bottom: 12px; }
.wb-settings .field .lbl { display: block; font-size: 12.5px; color: var(--text-2); margin-bottom: 5px; }

.wb-more { padding: 0; }
.wb-more > summary {
  cursor: pointer; padding: 16px 22px; font-size: 15px; font-weight: 600;
  list-style: none; user-select: none;
}
.wb-more > summary::-webkit-details-marker { display: none; }
.wb-more > summary::before { content: "▸ "; color: var(--brand); }
.wb-more[open] > summary::before { content: "▾ "; }
.wb-more[open] > summary { border-bottom: 1px solid var(--line-soft); }
.wb-more-body { padding: 22px; }
.wb-more-body h3 { margin-top: 0; font-size: 16px; }
hr.sep { border: 0; border-top: 1px solid var(--line-soft); margin: 26px 0; }

/* ---------- 代码弹层 ---------- */
.modal { position: fixed; inset: 0; z-index: 80; display: flex; align-items: center; justify-content: center; padding: 24px; }
.modal[hidden] { display: none; }
.modal-mask { position: absolute; inset: 0; background: rgba(20, 20, 18, .45); }
.modal-box {
  position: relative; background: var(--surface); border-radius: var(--radius);
  box-shadow: 0 24px 60px -20px rgba(0, 0, 0, .45);
  width: min(920px, 100%); max-height: 88vh; display: flex; flex-direction: column;
}
.modal-head {
  display: flex; gap: 14px; justify-content: space-between; align-items: flex-start;
  padding: 16px 20px; border-bottom: 1px solid var(--line-soft);
}
.modal-actions {
  display: flex; gap: 8px; align-items: center; flex-wrap: wrap;
  padding: 12px 20px; background: var(--surface-2);
  border-bottom: 1px solid var(--line-soft);
}
.ok-text { color: var(--ok); }
.code-box {
  margin: 0; padding: 16px 20px; overflow: auto; flex: 1;
  font-size: 12.5px; line-height: 1.6; background: #fbfbf9;
  border-bottom: 1px solid var(--line-soft);
}
.code-help { padding: 12px 20px 18px; }
.code-help > summary { cursor: pointer; font-size: 13.5px; color: var(--brand); }
.code-help-body {
  margin: 10px 0 0; white-space: pre-wrap; font-size: 12.5px;
  color: var(--text-2); background: var(--surface-2);
  border: 1px solid var(--line-soft); border-radius: var(--radius-sm); padding: 12px;
}

@media (max-width: 760px) {
  .wb-title { font-size: 22px; }
  .modal { padding: 0; }
  .modal-box { max-height: 100vh; border-radius: 0; height: 100%; width: 100%; }
}

/* ==================================================================
   组件库 v6 —— 与站点主视觉对齐
   ================================================================== */

.v6-wrap { max-width: var(--v6-max); margin: 0 auto; padding: 22px 20px 60px; }

/* ---------- 卡片 / 区块头 ---------- */
.v6-card {
  border: 1px solid var(--v6-line); border-radius: var(--radius);
  background: var(--surface); box-shadow: var(--v6-shadow); padding: 20px;
}
.v6-card + .v6-card, .v6-section + .v6-section { margin-top: 16px; }
.v6-section { margin-top: 18px; }
.v6-section-head {
  display: flex; gap: 14px; justify-content: space-between;
  align-items: flex-start; flex-wrap: wrap; margin-bottom: 12px;
}
.v6-section-head h2 { font-size: 19px; margin: 0 0 2px; }
.v6-section-head p { margin: 0; color: var(--v6-muted); font-size: 13px; }
.v6-kicker {
  display: block; font-size: 11px; letter-spacing: 1.5px; text-transform: uppercase;
  color: var(--v6-orange); font-weight: 800; margin-bottom: 4px;
}
.v6-sub-note { color: var(--v6-muted); font-size: 13.5px; margin: 0 0 14px; }

/* ---------- 徽章 ---------- */
.v6-badge {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 5px 9px; border-radius: 999px;
  background: var(--v6-soft); color: var(--v6-muted);
  font-size: 11px; font-weight: 800; white-space: nowrap;
}
.v6-badge.is-green { background: #f6ffed; color: var(--v6-green); }
.v6-badge.is-red { background: #fff1f0; color: var(--v6-red); }
.v6-badge.is-blue { background: #e6f7ff; color: var(--v6-blue); }
.v6-badge.is-amber { background: #fffbe6; color: var(--v6-amber); }
.v6-badge.is-gray { background: var(--v6-soft); color: var(--v6-muted); }
.v6-badge.is-navy { background: var(--surface-2); color: var(--v6-navy3); }

/* ---------- 按钮 ---------- */
.v6-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  padding: 10px 17px; border-radius: var(--radius); border: 1px solid transparent;
  background: var(--v6-soft); color: var(--v6-navy3);
  font-size: 14px; font-family: inherit; font-weight: 600; line-height: 1.2;
  cursor: pointer; transition: opacity .15s, background .15s, border-color .15s;
}
.v6-btn:hover { opacity: .92; text-decoration: none; }
.v6-btn:disabled { opacity: .45; cursor: not-allowed; }
.v6-btn.is-primary { background: var(--v6-orange); color: var(--on-brand); }
.v6-btn.is-primary:hover { background: var(--v6-orange2); }
.v6-btn.is-primary:active { background: var(--brand-dark); }
.v6-btn.is-navy { background: var(--v6-navy); color: #fff; }
.v6-btn.is-outline { background: var(--surface); border-color: var(--v6-orange); color: var(--v6-orange); }
.v6-btn.is-outline:hover { background: var(--brand-soft); }
.v6-btn.is-ghost { background: var(--surface); border-color: var(--v6-line); color: var(--v6-text); }
.v6-btn.is-ghost:hover { background: var(--v6-soft); }
.v6-btn.is-danger { background: var(--surface); border-color: #ffa39e; color: var(--v6-red); }
.v6-btn.is-danger:hover { background: #fff1f0; }
.v6-btn.is-sm { padding: 6px 12px; font-size: 12.5px; border-radius: var(--radius-sm); }
.v6-btn.is-block { width: 100%; }
.v6-btn-row { display: flex; gap: 9px; flex-wrap: wrap; }

.v6-icon-button {
  border: 0; background: none; cursor: pointer; color: var(--v6-muted);
  font-size: 15px; line-height: 1; padding: 4px 6px; border-radius: var(--radius-sm);
}
.v6-icon-button:hover { background: var(--v6-soft); color: var(--v6-orange); }

.v2-back-link {
  display: inline-flex; align-items: center; gap: 6px; margin-bottom: 12px;
  color: var(--v6-muted); font-size: 13.5px;
}
.v2-back-link:hover { color: var(--v6-orange); text-decoration: none; }

/* ---------- 提示条 ---------- */
/* ⚠️ 必须是 block，不能是 flex：站内每一条提示条装的都是「成段文字 +
   行内 <b>/<a>」，flex 会把每段行内内容变成独立的 flex 项，于是整句
   被拆成几栏、在几十像素宽里换行 —— 制动横幅与安装指引页都栽过。
   要加「图标 + 文字」那种横排，请另开一个修饰类，别改这里。 */
.v6-notice {
  display: block; padding: 13px 15px; border: 1px solid #91d5ff;
  border-radius: var(--radius); background: var(--v6-blue2); color: #0958d9; font-size: 13px;
  margin: 12px 0;
}
.v6-notice.is-danger { border-color: #ffa39e; background: #fff1f0; color: #a8071a; }
.v6-notice.is-success { border-color: #b7eb8f; background: #f6ffed; color: #237804; }
.v6-notice.is-warn { border-color: #ffe58f; background: #fffbe6; color: #ad6800; }
/* 公告广播（v0.7.50 P3-1）：标题+正文纵排，正文里的段落/列表别撑出大间距 */
/* block 布局下标题/正文天然纵排；原来 flex 的 gap:3px 改用 margin 补回。 */
.notice-broadcast .notice-body { margin-top: 3px; }
.notice-broadcast .notice-title { font-weight: 700; }
.notice-broadcast .notice-body p { margin: 0; }
.notice-broadcast .notice-body ul, .notice-broadcast .notice-body ol { margin: 4px 0 0; padding-left: 18px; }
.v6-inline-message { font-size: 13px; color: var(--v6-green); margin: 10px 0 0; }
.v6-inline-message.is-error { color: var(--v6-red); }

/* ---------- 服务页头卡 ---------- */
.v6-service-page { max-width: var(--v6-max); margin: 0 auto; padding: 20px 20px 56px; }
.service-summary-v2 {
  display: flex; gap: 18px; justify-content: space-between;
  align-items: flex-start; flex-wrap: wrap; padding: 20px 22px;
}
.service-summary-v2 h1 { font-size: 24px; margin: 0; }
.service-title-v2 { display: flex; align-items: center; gap: 8px; margin: 4px 0 6px; }
.service-summary-v2 p { margin: 0; color: var(--v6-muted); font-size: 13.5px; }
.service-summary-v2 p strong { color: var(--v6-ink); }
.service-summary-actions-v2 { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.service-summary-meta-v2 {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0; margin: 14px 0 0; padding: 0; border: 1px solid var(--v6-line);
  border-radius: var(--radius); background: var(--surface); overflow: hidden;
}
.service-summary-meta-v2 > div { padding: 13px 18px; border-right: 1px solid var(--v6-line); }
.service-summary-meta-v2 > div:last-child { border-right: 0; }
.service-summary-meta-v2 dt { font-size: 12px; color: var(--v6-muted); margin-bottom: 3px; }
.service-summary-meta-v2 dd { margin: 0; font-size: 15px; font-weight: 700; color: var(--v6-ink); }
.service-summary-meta-v2 dd small { display: block; font-weight: 400; font-size: 11.5px; color: var(--v6-muted); margin-top: 2px; }
@media (max-width: 720px) { .service-summary-meta-v2 { grid-template-columns: 1fr; } .service-summary-meta-v2 > div { border-right: 0; border-bottom: 1px solid var(--v6-line); } }

/* ---------- 两步配置卡 ---------- */
.service-setup-v3 { margin-top: 22px; }
.service-setup-v3 > h2 { font-size: 19px; margin: 0 0 4px; }
.service-setup-v3 > p { color: var(--v6-muted); font-size: 13.5px; margin: 0 0 14px; }
.service-setup-grid-v3 { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
@media (max-width: 760px) { .service-setup-grid-v3 { grid-template-columns: 1fr; } }
.service-setup-card-v3 {
  position: relative; padding: 18px 18px 16px;
  /* 原来是硬编码的 #dfe5ed。亮色下能看，暗色下就是一道比底色还亮的白边，
     在深色卡堆里像没加载完。换成分区变量，亮/暗两套自动跟随。 */
  border: 1px solid var(--line-soft);
  border-radius: var(--uc-radius); background: var(--q-panel-a);
  display: flex; flex-direction: column;
}
.service-setup-card-v3 h3 {
  /* ⚠️ 原来是 var(--v6-navy)。这个令牌的**语义是深色底**（亮 #0b1626 / 暗 #0a1220），
     当文字色用它就等于「深字压深底」—— 亮色下正常，一到暗色模式标题直接看不见。
     这正是「令牌混用」的典型后果：值是对的，用途是错的。 */
  font-size: 17px; color: var(--text); margin: 0 0 6px; padding-right: 34px;
}
.service-setup-card-v3 p { color: var(--text-3); font-size: 13.5px; margin: 0 0 12px; }
.service-setup-card-v3 .v6-btn, .service-setup-card-v3 .svc-dl-btn { margin-top: auto; }
.service-setup-num-v3 {
  position: absolute; top: 16px; right: 16px;
  width: 26px; height: 26px; border-radius: 50%;
  /* 原来也是 --v6-navy + 白字。那对组合在两种模式下都能看，但跟新体系
     不在一个色系里；改用主题强调色，顺带让序号跟着「红色方案」走
     （--on-accent 是强调色上的前景色，换主题时不会出现红底白字变红底红字）。 */
  background: var(--accent); color: var(--on-accent);
  font-size: 13px; font-weight: 700;
  display: flex; align-items: center; justify-content: center;
}
.service-file-name-v2 {
  font-family: ui-monospace, monospace; font-size: 12.5px; word-break: break-all;
  background: var(--v6-soft); border: 1px solid var(--v6-line);
  border-radius: var(--radius-sm); padding: 7px 10px; color: var(--v6-text);
}
.service-help-link-v2 { font-size: 12.5px; color: var(--v6-blue); margin-top: 10px; display: inline-block; }

/* ---------- 验证 QMT 连接 ---------- */
.service-test-v3 { margin-top: 22px; }
.service-test-v3 > h2 { font-size: 19px; margin: 0 0 4px; }
.service-test-v3 > p { color: var(--v6-muted); font-size: 13.5px; margin: 0 0 14px; }
.service-test-form-v3 {
  /* 同上：硬编码的 #d3dde8 虚线框 + #fcfdff 白底在暗色下会亮成一块。
     这里换成「虚线框 + 下沉一级的面」，语义不变、两套模式都对。 */
  border: 1px dashed var(--line); border-radius: var(--uc-radius);
  padding: 16px 18px; background: var(--q-sub);
}
.service-test-row-v3 { display: flex; flex-wrap: wrap; gap: 12px; align-items: flex-end; }
.service-test-field-v3 { display: flex; flex-direction: column; gap: 5px; }
.service-test-field-v3 > label { font-size: 12px; color: var(--v6-muted); margin: 0; }
.service-test-field-v3 input, .service-test-field-v3 select { min-width: 128px; }
.service-test-field-v3 input#ct-amount, .service-test-field-v3 input[name="quantity"] { min-width: 96px; }
.service-test-row-v3 > .v6-btn { align-self: flex-end; }
.service-test-result-v2 { display: block; margin: 12px 0 0; font-size: 13px; color: var(--v6-muted); }
/* 测试信号回显三态：绿=已收到 / 红=没收到 / 琥珀=还在等。
   颜色必须显式给，别只靠文字 —— 客户扫一眼就该知道通没通。 */
.service-test-result-v2.is-ok { color: var(--v6-green); font-weight: 700; }
.service-test-result-v2.is-fail { color: var(--v6-red); font-weight: 700; }
.service-test-result-v2.is-wait { color: var(--v6-amber); }
.service-test-result-v2.is-ok .st-detail,
.service-test-result-v2.is-fail .st-detail { color: var(--v6-muted); font-weight: 400; }
.service-test-result-v2 .st-pill {
  display: inline-block; margin-left: 8px; padding: 1px 8px; border-radius: 999px;
  /* 原来底色写死 #e6f4ee（浅绿）。暗色模式下这一小块会亮得突兀，
     换成「下行色的低透明度」—— 深色底上是暗绿、浅色底上是浅绿，自动适配。 */
  font-size: 12px; font-weight: 700;
  background: rgba(var(--down-rgb), .14); color: var(--v6-green);
}
@media (max-width: 640px) { .service-test-row-v3 { flex-direction: column; align-items: stretch; } }

/* ---------- 全链路时间轴（聚宽 → 中转站 → QMT） ----------
   三跳逐条列出，每跳自带颜色：绿=通 / 红=断 / 琥珀=还在等。
   「断在哪一跳」必须一眼看出来 —— 这是这个区块存在的唯一理由。 */
.link-timeline { display: flex; flex-direction: column; gap: 8px; margin: 14px 0 0; }
.link-timeline-empty { color: var(--v6-muted); font-size: 13px; }
.link-hop {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 9px 13px; border-radius: var(--radius-sm); border: 1px solid var(--v6-line);
  background: var(--surface); font-size: 13.5px;
}
.link-hop .hop-idx {
  flex: 0 0 auto; width: 22px; height: 22px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 12px; font-weight: 700; background: var(--v6-soft); color: var(--v6-muted);
}
.link-hop .hop-label { flex: 1 1 auto; color: var(--v6-text); font-weight: 600; }
.link-hop .hop-note { color: var(--v6-muted); font-size: 12.5px; }
.link-hop .hop-state { flex: 0 0 auto; font-weight: 700; font-size: 12.5px; }

/* ⚠️ 下面三组「通/断」配色的浅底（#f4fbf8 / #fdf6f6 / #e6f4ee / #fdecec）原本是
   写死的亮色值。这个区块是「链路断在哪一跳」的唯一可视信号，暗色模式下
   如果底色还是一块浅色，三跳会亮成三块白斑，比不加底色还糟。
   统一改成「语义色的低透明度」：亮色底上=浅绿/浅红，深色底上=暗绿/暗红。
   边框一并跟着语义色走，避免出现「底跟上了、边还是浅色」。 */
.link-hop.is-ok { border-color: rgba(var(--down-rgb), .38); background: rgba(var(--down-rgb), .07); }
.link-hop.is-ok .hop-idx { background: rgba(var(--down-rgb), .16); color: var(--v6-green); }
.link-hop.is-ok .hop-state { color: var(--v6-green); }

.link-hop.is-fail { border-color: rgba(var(--up-rgb), .38); background: rgba(var(--up-rgb), .07); }
.link-hop.is-fail .hop-idx { background: rgba(var(--up-rgb), .16); color: var(--v6-red); }
.link-hop.is-fail .hop-state { color: var(--v6-red); }

.link-hop.is-wait .hop-state { color: var(--v6-amber); }
.link-hop.is-skip { opacity: .6; }
.link-hop.is-skip .hop-state { color: var(--v6-muted); }

.link-verdict { margin: 12px 0 0; font-size: 13.5px; font-weight: 700; }
.link-verdict.is-ok { color: var(--v6-green); }
.link-verdict.is-fail { color: var(--v6-red); }
.link-verdict.is-wait { color: var(--v6-amber); }
.link-verdict .verdict-hint {
  display: block; margin-top: 6px; color: var(--v6-muted);
  font-weight: 400; font-size: 12.5px; line-height: 1.7;
}
.link-err {
  margin: 8px 0 0; padding: 8px 12px; border-radius: var(--radius-sm);
  /* 同上：原来是写死的浅红底 #fdf6f6，暗色下会亮成一块。 */
  background: rgba(var(--up-rgb), .1); color: var(--v6-red); font-size: 12.5px;
}
.link-meta { margin: 10px 0 0; color: var(--v6-muted); font-size: 12.5px; }

/* ---------- 信号表 ---------- */
.v6-table-wrap { overflow: auto; border: 1px solid var(--v6-line); border-radius: var(--radius); background: var(--surface); }
table.v6-table { width: 100%; border-collapse: collapse; font-size: 13.5px; }
table.v6-table th, table.v6-table td {
  text-align: left; padding: 11px 14px; border-bottom: 1px solid var(--v6-line);
  white-space: nowrap; vertical-align: middle;
}
table.v6-table th { background: var(--v6-soft); color: var(--v6-text); font-weight: 700; font-size: 12.5px; }
table.v6-table tbody tr:last-child td { border-bottom: 0; }
table.v6-table tbody tr:hover td { background: #fafafa; }
table.v6-table .is-buy { color: var(--up); font-weight: 800; }
table.v6-table .is-sell { color: var(--down); font-weight: 800; }
.v6-signal-table { min-width: 760px; }
.channel-refresh-label { font-size: 12px; color: var(--v6-muted); margin-left: 10px; }

.v6-empty { padding: 42px 22px; text-align: center; }
.v6-empty h3 { margin: 0 0 6px; font-size: 16px; color: var(--v6-text); }
.v6-empty p { margin: 0; color: var(--v6-muted); font-size: 13.5px; }

/* ---------- 弹层 ---------- */
.v6-dialog-overlay {
  position: fixed; inset: 0; z-index: 130; display: flex;
  align-items: center; justify-content: center; padding: 18px;
  background: rgba(0, 0, 0, .45);
}
.v6-dialog-overlay[hidden] { display: none; }
body.v6-dialog-open { overflow: hidden; }
.v6-dialog {
  position: relative; width: min(520px, 100%); max-height: 90vh; overflow: auto;
  background: var(--surface); border-radius: var(--radius); box-shadow: var(--v6-shadow2);
  display: flex; flex-direction: column;
}
.v6-dialog.is-wide { width: min(680px, 100%); }
.v6-dialog-head {
  display: flex; gap: 12px; justify-content: space-between; align-items: flex-start;
  padding: 18px 20px 12px;
}
.v6-dialog-head h3 { margin: 0 0 3px; font-size: 17px; }
.v6-dialog-head p { margin: 0; color: var(--v6-muted); font-size: 12.5px; }
.v6-dialog-body { padding: 4px 20px 16px; }
.v6-dialog-foot {
  display: flex; gap: 9px; justify-content: flex-end; align-items: center;
  padding: 14px 20px 18px; flex-wrap: wrap;
}
.v6-dialog-close {
  border: 0; background: none; font-size: 20px; line-height: 1; cursor: pointer;
  color: var(--v6-muted); padding: 2px 6px; border-radius: var(--radius-sm);
}
.v6-dialog-close:hover { background: var(--v6-soft); color: var(--v6-ink); }
.v6-dialog .field { margin-bottom: 14px; }
.v6-dialog .field > label { display: block; font-size: 12.5px; color: var(--v6-muted); margin-bottom: 6px; }

/* ---------- 套餐 chip ---------- */
.sub-plan-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(112px, 1fr)); gap: 9px; }
.sub-plan-chip {
  position: relative; display: grid; gap: 1px; place-content: center;
  min-height: 58px; padding: 8px 6px; border: 1px solid #dfe3e8; border-radius: var(--radius-sm);
  background: var(--surface); text-align: center; cursor: pointer; font: inherit; box-shadow: none;
}
.sub-plan-chip.selected { border-color: var(--v6-orange); background: var(--brand-soft); box-shadow: 0 0 0 1px rgba(var(--brand-rgb), .08); }
.sub-plan-chip strong { font-size: 14px; color: var(--v6-ink); }
.sub-plan-chip small { font-size: 11.5px; color: var(--v6-muted); }
.sub-plan-chip .rib {
  position: absolute; top: -8px; right: 6px; font-size: 10px; font-weight: 800;
  background: var(--v6-orange); color: var(--on-brand); padding: 2px 7px; border-radius: 999px;
}
/* 积分结算 */
.quote-list { border: 1px solid var(--v6-line); border-radius: var(--radius); overflow: hidden; margin-top: 14px; }
.quote-list .q {
  display: flex; justify-content: space-between; gap: 12px;
  padding: 9px 14px; font-size: 13px; border-bottom: 1px solid var(--v6-line);
}
.quote-list .q:last-child { border-bottom: 0; }
.quote-list .q span { color: var(--v6-muted); }
.quote-list .q strong { color: var(--v6-ink); }
.quote-list .q strong.is-danger { color: var(--v6-red); }
.quote-list .q.is-total { background: var(--v6-soft); }

/* ---------- 权益清单 ---------- */
.v6-feature-list { display: grid; gap: 7px; margin: 12px 0 0; }
.v6-feature-list .f { display: flex; gap: 8px; font-size: 13px; color: var(--v6-text); }
.v6-feature-list .f::before { content: "✓"; color: var(--v6-green); font-weight: 800; flex: none; }

/* ---------- 通道卡片网格 ---------- */
.jq-channel-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 14px; }
.jq-channel-card { display: flex; flex-direction: column; gap: 10px; padding: 18px; }
.jq-channel-card h3 { margin: 0; font-size: 16.5px; }
.jq-channel-card .meta { display: grid; gap: 5px; font-size: 12.5px; color: var(--v6-muted); }
.jq-channel-card .meta b { color: var(--v6-text); font-weight: 600; }
.jq-channel-card .acts { display: flex; gap: 8px; flex-wrap: wrap; margin-top: auto; padding-top: 4px; }
.jq-channel-card.is-expired { border-color: #f0d7d7; }

/* ---------- 悬浮客服 / 返回顶部 ---------- */
.cs-float { position: fixed; right: 18px; bottom: 26px; z-index: 90; display: flex; flex-direction: column; gap: 9px; }
.cs-float a, .cs-float button {
  width: 46px; height: 46px; border-radius: 50%; border: 1px solid var(--v6-line);
  background: var(--surface); color: var(--v6-navy3); cursor: pointer;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  font-size: 10.5px; gap: 1px; box-shadow: var(--v6-shadow); text-decoration: none;
}
.cs-float a:hover, .cs-float button:hover { color: var(--v6-orange); border-color: var(--v6-orange); }
.cs-float .ic { font-size: 16px; line-height: 1; }

/* ---------- 页脚 ---------- */
.footer { border-top: 1px solid var(--v6-line); background: var(--surface); padding: 28px 0 34px; margin-top: 46px; }
.footer .inner { max-width: var(--v6-max); margin: 0 auto; padding: 0 20px; color: var(--v6-muted); font-size: 12.5px; }
.footer .links { display: flex; gap: 18px; flex-wrap: wrap; margin-bottom: 12px; }
.footer .links a { color: var(--v6-text); }
.footer .links a:hover { color: var(--v6-orange); }

/* ---------- 表格在窄屏展开 ---------- */
@media (max-width: 760px) {
  table.v6-table.v6-signal-table { min-width: 0; border: 0; }
  table.v6-table.v6-signal-table thead { display: none; }
  table.v6-table.v6-signal-table tr { display: block; border: 1px solid var(--v6-line); border-radius: var(--radius); margin-bottom: 9px; padding: 6px 10px; }
  table.v6-table.v6-signal-table td { display: flex; justify-content: space-between; gap: 12px; border: 0; padding: 6px 0; white-space: normal; }
  table.v6-table.v6-signal-table td::before { content: attr(data-label); color: var(--v6-muted); font-size: 12px; }
}

/* ---------- 教程 / 工具 / 商城 卡片 ---------- */
.v6-card-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 16px; }
.v6-link-card { display: flex; flex-direction: column; gap: 8px; padding: 20px; }
.v6-link-card h3 { margin: 0; font-size: 17px; }
.v6-link-card p { margin: 0; color: var(--v6-muted); font-size: 13.5px; }
.v6-link-card .go { margin-top: auto; color: var(--v6-orange); font-size: 13px; font-weight: 600; }
.v6-steps { display: grid; gap: 12px; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); margin: 18px 0; }
.v6-steps .s { border: 1px solid var(--v6-line); border-radius: var(--radius); padding: 14px; background: var(--surface); }
.v6-steps .s .n { font-size: 11px; font-weight: 800; color: var(--v6-orange); letter-spacing: 1px; }
.v6-steps .s p { margin: 4px 0 0; font-size: 13px; color: var(--v6-text); }
.v6-check-list { display: grid; gap: 8px; }
.v6-check-list label { display: flex; gap: 10px; align-items: flex-start; font-size: 13.5px; color: var(--v6-text); margin: 0; }
.v6-check-list input { margin-top: 2px; flex: none; }
.v6-metric-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 14px; }
.v6-metric { border: 1px solid var(--v6-line); border-radius: var(--radius); padding: 14px; background: var(--surface); }
.v6-metric .k { font-size: 12px; color: var(--v6-muted); }
.v6-metric .v { font-size: 22px; font-weight: 800; color: var(--v6-ink); margin-top: 3px; }
.v6-metric .v.up { color: var(--up); }
.v6-metric .v.down { color: var(--down); }

/* ---------- 代码块（深色） ---------- */
.v6-code { background: var(--v6-navy); color: #dbe6f3; border-radius: var(--radius); padding: 14px 16px; overflow: auto; font-size: 12.5px; line-height: 1.65; margin: 0; }
.v6-token { font-family: ui-monospace, monospace; font-size: 12.5px; background: var(--v6-soft); border: 1px dashed var(--v6-line); padding: 8px 11px; border-radius: var(--radius-sm); word-break: break-all; }

/* ============================================================
   悬浮联系窗（右侧常驻胶囊按钮 + 点击弹窗）
   ============================================================ */
.cs-dock { position: fixed; right: 0; top: 56%; transform: translateY(-50%); z-index: 92; display: flex; flex-direction: column; gap: 10px; }
.cs-dock-btn {
  display: flex; align-items: center; gap: 9px;
  border: 0; cursor: pointer; padding: 9px 13px 9px 11px;
  border-radius: var(--radius) 0 0 var(--radius);
  font-family: inherit; text-align: left;
  box-shadow: -2px 6px 20px rgba(11, 22, 38, .16);
  transition: transform .16s ease, box-shadow .16s ease;
}
.cs-dock-btn:hover { transform: translateX(-3px); box-shadow: -4px 9px 26px rgba(11, 22, 38, .22); }
.cs-dock-ic { font-size: 17px; line-height: 1; width: 18px; text-align: center; }
.cs-dock-tx { display: flex; flex-direction: column; line-height: 1.15; }
.cs-dock-tx b { font-size: 13px; font-weight: 700; }
.cs-dock-tx i { font-size: 10.5px; font-style: normal; opacity: .82; letter-spacing: .06em; }
.cs-dock-wechat { background: linear-gradient(135deg, var(--v6-orange2), var(--v6-orange)); color: var(--on-brand); }
.cs-dock-qq { background: var(--surface); color: var(--v6-navy3); border: 1px solid var(--v6-line); }

.cs-modal { position: fixed; inset: 0; z-index: 200; display: flex; align-items: center; justify-content: center; padding: 20px; }
.cs-modal[hidden] { display: none; }
.cs-modal-mask { position: absolute; inset: 0; background: rgba(0, 0, 0, .45); }
.cs-modal-card {
  position: relative; z-index: 1; width: 100%; max-width: 340px;
  background: var(--surface); border-radius: var(--radius); padding: 22px 20px 18px;
  box-shadow: var(--v6-shadow2); text-align: center;
  animation: csPop .18s ease-out;
}
@keyframes csPop { from { opacity: 0; transform: translateY(8px) scale(.97); } to { opacity: 1; transform: none; } }
.cs-modal-x {
  position: absolute; top: 8px; right: 10px; width: 30px; height: 30px;
  border: 0; background: transparent; color: var(--v6-muted);
  font-size: 21px; line-height: 1; cursor: pointer; border-radius: var(--radius-sm);
}
.cs-modal-x:hover { background: var(--v6-soft); color: var(--v6-ink); }
.cs-modal-title { font-size: 17px; font-weight: 700; color: var(--v6-ink); }
.cs-modal-desc { font-size: 12.5px; color: var(--v6-muted); margin-top: 5px; line-height: 1.6; }
.cs-copy {
  display: flex; align-items: center; gap: 8px; margin-top: 14px;
  background: var(--v6-soft); border: 1px dashed var(--v6-line);
  border-radius: var(--radius); padding: 8px 10px;
}
.cs-copy-label { font-size: 11.5px; color: var(--v6-muted); white-space: nowrap; }
.cs-copy-val { flex: 1; font-family: ui-monospace, monospace; font-size: 14px; color: var(--v6-ink); word-break: break-all; text-align: left; }
.cs-qr { margin-top: 14px; }
.cs-qr img { width: 200px; height: 200px; max-width: 100%; object-fit: contain; border-radius: var(--radius); border: 1px solid var(--v6-line); background: var(--surface); }
.cs-modal-foot { margin-top: 12px; font-size: 12px; color: var(--v6-muted); line-height: 1.6; }
body.cs-modal-open { overflow: hidden; }

/* ============================================================
   通用数据列表（后台用户管理等 2 万行量级）：紧凑表格 + 分页条
   ============================================================ */
.tbl-wrap { overflow-x: auto; border: 1px solid var(--v6-line); border-radius: var(--radius); background: var(--surface); }
table.data-tbl { width: 100%; border-collapse: collapse; font-size: 13px; min-width: 880px; }
table.data-tbl th, table.data-tbl td { padding: 9px 12px; text-align: left; border-bottom: 1px solid var(--line-soft); vertical-align: middle; }
table.data-tbl thead th {
  background: var(--surface-2); color: var(--text-2); font-weight: 600;
  font-size: 12px; letter-spacing: .02em; white-space: nowrap;
}
table.data-tbl thead th a { color: inherit; display: inline-flex; align-items: center; gap: 4px; }
table.data-tbl thead th a:hover { color: var(--brand); }
table.data-tbl tbody tr:hover { background: #fafcfe; }
table.data-tbl tbody tr:last-child td { border-bottom: 0; }
table.data-tbl td.nowrap { white-space: nowrap; }
table.data-tbl .col-num { text-align: right; font-variant-numeric: tabular-nums; }

.filter-bar { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.filter-bar input, .filter-bar select { padding: 7px 10px; font-size: 13px; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--surface); }
.filter-bar input[type="text"] { min-width: 200px; }
.filter-bar .spacer { flex: 1; }

/* ★ v0.7.59：`.filter-bar` 一直是「一控件一行」的假单行。
   根因在**本文件顶部**那条全局规则：
       input[type=text], select, textarea { width: 100% }
   而 `.filter-bar` 是 `display:flex; flex-wrap:wrap`。flex 换行是按
   **假设主轴尺寸**（这里就是 width:100% = 容器整宽）来分行的 ⇒ 每个控件
   都"刚好占满一行"，后面所有兄弟只能另起一行。
   实测（1440 视口）：输入框 w=730、下拉 w=730、按钮独占第三行，
   那个筛选卡高 ~110px，其中大半是空的 —— 圆总 2026-10-03 报的「大量空白」主因。
   修法：在 flex 容器内部把宽度交还 flex 布局 —— 输入框可伸展、下拉与按钮按内容宽。
   只影响 `.filter-bar` 内部；非 flex 场景的全宽表单（.field 那一套）仍是 width:100%。 */
.filter-bar input[type="text"], .filter-bar input[type="search"],
.filter-bar input[type="email"], .filter-bar input[type="number"] {
  flex: 1 1 200px; width: auto; min-width: 0;
}
.filter-bar select { flex: 0 1 auto; width: auto; max-width: 100%; }
.filter-bar .btn, .filter-bar button { flex: 0 0 auto; }


.pager { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-top: 12px; font-size: 13px; }
.pager .pages { display: flex; gap: 5px; align-items: center; flex-wrap: wrap; }
.pager .pages a, .pager .pages span {
  min-width: 32px; height: 32px; padding: 0 9px; border-radius: var(--radius-sm);
  border: 1px solid var(--line); background: var(--surface); color: var(--text-2);
  display: inline-flex; align-items: center; justify-content: center; text-decoration: none; font-size: 12.5px;
}
.pager .pages a:hover { border-color: var(--brand); color: var(--brand); }
.pager .pages .cur { background: var(--brand); border-color: var(--brand); color: var(--on-brand); font-weight: 600; }
.pager .pages .off { opacity: .42; }

@media (max-width: 760px) {
  .cs-dock { top: auto; bottom: 96px; transform: none; gap: 8px; }
  .cs-dock-btn { padding: 8px 10px 8px 9px; }
  .cs-dock-tx b { font-size: 12px; }
  .cs-float { right: 12px; bottom: 16px; }
}

/* ============================================================
   用户中心 · v6 组件补全（2026-09-25）
   ------------------------------------------------------------
   问题：用户中心原来混用两套类名 —— 一部分页面写 .card / .tbl /
   .pill / .tabs（旧体系），另一部分写 .v6-card / .v6-table（新体系）。
   结果同一个板块里卡片圆角、表头底色、按钮风格都不统一。

   做法：把用户中心需要的组件**全部按 v6 令牌补齐**，模板统一改用
   v6-*。旧类（.card / .tbl / .pager / .tabs）原样保留，继续服务
   后台管理页（admin/*），两边互不干扰。

   注意：table.v6-table 与 .v6-table-wrap、.v6-metric、.v6-steps、
   .v6-badge、.v6-btn 等已在上方定义，此处不重复。
   ============================================================ */

/* ---------- 页头 ---------- */
.v6-page-head {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 16px; flex-wrap: wrap; margin-bottom: 16px;
}
.v6-page-head h1 { margin: 0 0 3px; font-size: 22px; color: var(--v6-ink); }
.v6-page-head p { margin: 0; color: var(--v6-muted); font-size: 13.5px; }

/* ---------- 用户中心顶部 tab ---------- */
.v6-tabs {
  display: flex; gap: 3px; flex-wrap: wrap;
  border-bottom: 1px solid var(--v6-line); margin-bottom: 18px;
}
.v6-tabs a {
  padding: 9px 13px; border-radius: var(--radius-sm) var(--radius-sm) 0 0; margin-bottom: -1px;
  color: var(--v6-muted); font-size: 13.5px; font-weight: 600;
  text-decoration: none; border: 1px solid transparent; border-bottom: 0;
  white-space: nowrap;
}
.v6-tabs a:hover { color: var(--v6-orange); background: var(--v6-soft); }
.v6-tabs a.active {
  color: var(--v6-orange); background: var(--surface); border-color: var(--v6-line);
}

/* ---------- 表单 ---------- */
.v6-field { margin-bottom: 14px; }
.v6-field > label {
  display: block; font-size: 12.5px; color: var(--v6-muted); margin-bottom: 6px;
}
.v6-field .hint { font-size: 12px; color: var(--v6-muted); margin-top: 4px; }
.v6-input, .v6-select, .v6-textarea {
  width: 100%; box-sizing: border-box; padding: 9px 11px;
  font-size: 13.5px; font-family: inherit; color: var(--v6-ink);
  border: 1px solid var(--v6-line); border-radius: var(--radius-sm); background: var(--surface);
}
.v6-input:focus, .v6-select:focus, .v6-textarea:focus {
  outline: 0; border-color: var(--v6-orange);
  box-shadow: 0 0 0 3px rgba(var(--brand-rgb), .12);
}
.v6-input[readonly], .v6-input:disabled { background: var(--v6-soft); color: var(--v6-muted); }
.v6-form-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 14px; }
.v6-form-narrow { max-width: 460px; }

/* ---------- 键值网格（基本资料这类纯展示） ---------- */
.v6-kv { display: grid; grid-template-columns: repeat(auto-fit, minmax(185px, 1fr)); gap: 14px; }
.v6-kv > div { background: var(--v6-soft); border-radius: var(--radius); padding: 12px 14px; }
.v6-kv dt { font-size: 11.5px; color: var(--v6-muted); margin: 0 0 4px; }
.v6-kv dd {
  margin: 0; font-size: 14px; font-weight: 600; color: var(--v6-ink);
  word-break: break-all;
}

/* ---------- 键值行（报价 / 核对这类单列） ---------- */
.v6-quote-list { display: grid; gap: 2px; margin: 12px 0 0; }
.v6-quote-list .q {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: 12px; font-size: 13.5px; padding: 7px 0;
  border-bottom: 1px dashed var(--v6-line);
}
.v6-quote-list .q:last-child { border-bottom: 0; }
.v6-quote-list .q > span { color: var(--v6-muted); }
.v6-quote-list .q > strong { color: var(--v6-ink); }
.v6-quote-list .q.is-total {
  margin-top: 6px; padding-top: 10px; font-size: 15px;
  border-top: 1px solid var(--v6-line); border-bottom: 0;
}
.v6-quote-list .q.is-total > strong { color: var(--v6-orange); font-size: 17px; }

/* ---------- 分页 ---------- */
.v6-pager {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap; margin-top: 12px;
  font-size: 13px; color: var(--v6-muted);
}
.v6-pager .pages { display: flex; gap: 5px; align-items: center; flex-wrap: wrap; }
.v6-pager .pages a, .v6-pager .pages span {
  min-width: 32px; height: 32px; padding: 0 9px; border-radius: var(--radius-sm);
  border: 1px solid var(--v6-line); background: var(--surface); color: var(--v6-text);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 12.5px; text-decoration: none;
}
.v6-pager .pages a:hover { border-color: var(--v6-orange); color: var(--v6-orange); }
.v6-pager .pages .cur {
  background: var(--v6-orange); border-color: var(--v6-orange);
  color: #fff; font-weight: 600;
}
.v6-pager .pages .off { opacity: .42; }

/* ---------- 布局小工具 ---------- */
.v6-row-between {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap;
}
.v6-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.v6-sep { border: 0; border-top: 1px solid var(--v6-line); margin: 18px 0; }

/* ---------- 状态点 ---------- */
.v6-status { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; }
.v6-status::before {
  content: ""; flex: none; width: 7px; height: 7px;
  border-radius: 50%; background: var(--v6-muted);
}
.v6-status.is-ok::before { background: var(--v6-green); }
.v6-status.is-warn::before { background: var(--v6-amber); }
.v6-status.is-bad::before { background: var(--v6-red); }

@media (max-width: 640px) {
  .v6-page-head h1 { font-size: 19px; }
  .v6-tabs a { padding: 8px 10px; font-size: 12.5px; }
}

/* ============================================================
   v3 设计体系 · 用户中心增强件（2026-09-25）
   —— 与上面的 v6 组件并存：v6 服务存量模板，uc-* / --q-* 服务新增强件。
   全部类名带 uc- 前缀，不触碰任何存量类名。
   ============================================================ */

/* ---------- 页面底：网格 + 双色光晕（随主题色联动） ---------- */
body::before {
  content: ""; position: fixed; inset: 0; pointer-events: none; z-index: 0;
  background:
    radial-gradient(920px 520px at 10% -12%, var(--q-glow-a), transparent 62%),
    radial-gradient(780px 500px at 100% -4%, var(--q-glow-b), transparent 62%),
    linear-gradient(rgba(var(--q-grid-rgb), var(--q-grid-a)) 1px, transparent 1px) 0 0 / 100% 34px,
    linear-gradient(90deg, rgba(var(--q-grid-rgb), var(--q-grid-a)) 1px, transparent 1px) 0 0 / 34px 100%;
}
/* 内容层必须抬到网格之上（.topbar 自带 z-index:50，无需处理） */
main, .footer { position: relative; z-index: 1; }
/* 内容不足一屏时把页脚推到底，避免页脚下面拖出一大片空白
   （64 顶栏 + ~180 页脚 + 46 页脚上边距 ≈ 290） */
main { min-height: calc(100vh - 290px); }
.v6-wrap, .container, .container-narrow { position: relative; z-index: 1; }

/* ---------- 侧栏（用户中心 / 后台）· v3 视觉 ---------- */
.shell { display: grid; grid-template-columns: 232px minmax(0, 1fr); gap: 22px; align-items: start; }
.side {
  background: linear-gradient(180deg, var(--q-side-a), var(--q-side-b));
  border: 1px solid var(--line-soft); border-radius: var(--radius);
  padding: 12px; position: sticky; top: 82px; box-shadow: var(--q-shadow-sm);
}
.side .group {
  font-size: 10.5px; letter-spacing: .16em; color: var(--q-dim); font-weight: 800;
  padding: 13px 9px 6px;
}
.side a {
  position: relative; display: flex; align-items: center; gap: 9px;
  padding: 9px 11px; border-radius: var(--radius); color: var(--text-2); font-size: 13.5px;
  border: 1px solid transparent; transition: background .16s, color .16s, border-color .16s;
}
.side a:hover { background: var(--q-hover); color: var(--text); text-decoration: none; }
.side a.active {
  background: linear-gradient(90deg, rgba(var(--brand-rgb), .17), rgba(var(--brand-rgb), .03));
  color: var(--brand-ink); border-color: var(--q-nav-on-bd); font-weight: 600;
}
.side a.active::before {
  content: ""; position: absolute; left: -12px; top: 9px; bottom: 9px; width: 3px;
  border-radius: 0 3px 3px 0; background: var(--brand);
  box-shadow: 0 0 14px rgba(var(--brand-rgb), .85);
}
.side a .badge {
  margin-left: auto; font-size: 10.5px; font-weight: 800; padding: 2px 7px;
  border-radius: 999px; background: var(--q-badge-bg); color: var(--q-badge-fg);
}
.side a.active .badge { background: rgba(var(--brand-rgb), .22); color: var(--brand-ink); }
.side .side-foot {
  margin-top: 12px; padding: 11px 12px; border-radius: var(--radius);
  background: var(--q-sub); border: 1px solid var(--line-soft);
  font-size: 11.5px; color: var(--q-dim); line-height: 1.7;
}
.side .side-foot b { color: var(--text-2); }
@media (max-width: 900px) {
  .shell { grid-template-columns: 1fr; }
  .side {
    position: static; top: auto; display: flex; gap: 6px;
    overflow-x: auto; padding: 9px; -webkit-overflow-scrolling: touch;
  }
  .side .group, .side .side-foot { display: none; }
  .side a { white-space: nowrap; border-radius: 999px; padding: 7px 13px; }
  .side a.active::before { display: none; }
}

/* ---------- 眉标（uc-kicker） ---------- */
.uc-kicker { display: block; font-size: 10.5px; letter-spacing: .18em; font-weight: 900; color: var(--brand); margin-bottom: 7px; }

/* ---------- 用户中心 · 模块内切换条 ----------
   v0.7.33 起：侧栏是「九大模块」的一级入口，本条只在一级入口内部
   细分视角（聚宽信号 = 通道管理 / 信号记录，购买套餐 = 通道服务 /
   官方策略 / 积分与充值 / 权益兑换 …），所以不写死数量。
   整条不折行、溢出横向滚动 —— 折行会把内容区推得很低。
   分隔线目前仅作视觉分隔，留 CSS 备用。 */
.uc-tabs {
  display: flex; align-items: center; gap: 3px; flex-wrap: nowrap;
  overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none;
  padding: 7px 9px; margin-bottom: 18px;
  background: var(--surface); border: 1px solid var(--line-soft);
  border-radius: 999px; box-shadow: var(--q-shadow-sm);
}
.uc-tabs::-webkit-scrollbar { display: none; }
.uc-tabs a {
  white-space: nowrap; padding: 8px 15px; border-radius: 999px;
  font-size: 13.5px; font-weight: 600; color: var(--text-2);
  border: 1px solid transparent;
  transition: background .16s, color .16s, border-color .16s;
}
.uc-tabs a:hover { background: var(--q-hover); color: var(--text); text-decoration: none; }
.uc-tabs a.active {
  background: rgba(var(--brand-rgb), .13); color: var(--brand-ink);
  border-color: rgba(var(--brand-rgb), .42);
}
/* 组间细分隔线：宽度固定不参与收缩，否则会被 flex 压成 0 而消失 */
.uc-tab-sep {
  flex: 0 0 auto; width: 1px; height: 17px;
  background: var(--line-soft); margin: 0 6px;
}
@media (max-width: 760px) {
  .uc-tabs { border-radius: var(--radius); padding: 6px 7px; }
  .uc-tabs a { padding: 7px 12px; font-size: 13px; }
  .uc-tab-sep { margin: 0 4px; }
}

/* ---------- KPI 卡（含 sparkline） ---------- */
.uc-kpis { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 13px; }
.uc-kpis.c3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.uc-kpi {
  position: relative; overflow: hidden; padding: 15px 16px 14px;
  border-radius: var(--radius); border: 1px solid var(--line-soft);
  background: linear-gradient(158deg, var(--q-panel-a), var(--q-panel-b) 64%);
  box-shadow: var(--q-shadow-sm);
}
.uc-kpi .k { font-size: 12px; color: var(--text-3); }
.uc-kpi .v {
  margin-top: 7px; font-size: 25px; font-weight: 800; color: var(--text);
  font-variant-numeric: tabular-nums; letter-spacing: -.6px; line-height: 1.2;
}
.uc-kpi .v small { font-size: 13px; font-weight: 600; color: var(--text-3); margin-left: 3px; }
.uc-kpi .d { margin-top: 5px; font-size: 11.5px; color: var(--q-dim); }
.uc-kpi .sparkwrap { position: absolute; right: 10px; bottom: 8px; opacity: .95; }
.uc-kpi.is-accent { border-color: var(--q-nav-on-bd); }
.uc-kpi.is-accent::after {
  content: ""; position: absolute; inset: 0 0 auto; height: 2px;
  background: linear-gradient(90deg, transparent, var(--brand), transparent);
}
.uc-kpi.is-accent .v { color: var(--brand-ink); }
.uc-spark { display: block; }
.uc-spark .ln { fill: none; stroke: var(--brand); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.uc-spark .ar { fill: rgba(var(--brand-rgb), .12); stroke: none; }
.uc-spark.s-up .ln { stroke: var(--up); }
.uc-spark.s-up .ar { fill: rgba(var(--up-rgb), .12); }
.uc-spark.s-down .ln { stroke: var(--down); }
.uc-spark.s-down .ar { fill: rgba(var(--down-rgb), .12); }
@media (max-width: 900px) { .uc-kpis, .uc-kpis.c3 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px) { .uc-kpis, .uc-kpis.c3 { grid-template-columns: 1fr; } }

/* ---------- 环形进度 ---------- */
.uc-ring { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }
.uc-ring svg { flex: none; }
.uc-ring .rt .big { font-size: 23px; font-weight: 800; color: var(--text); font-variant-numeric: tabular-nums; line-height: 1.2; }
.uc-ring .rt .cap { font-size: 12px; color: var(--text-3); margin-top: 3px; }
.ring-track { stroke: var(--q-track); fill: none; }
.ring-bar { stroke: var(--brand); fill: none; stroke-linecap: round; transition: stroke-dashoffset .6s ease; }

/* ---------- 进度条 ---------- */
.uc-bar { height: 7px; border-radius: 99px; background: var(--q-track); overflow: hidden; }
.uc-bar > i { display: block; height: 100%; border-radius: 99px; background: linear-gradient(90deg, var(--brand), var(--brand-2)); }
.uc-bar.is-cool > i { background: linear-gradient(90deg, var(--v6-blue), var(--v6-blue2)); }

/* ---------- 标签（带状态点） ---------- */
.uc-tag {
  display: inline-flex; align-items: center; gap: 6px; padding: 3px 9px;
  border-radius: 999px; font-size: 11px; font-weight: 800;
  border: 1px solid transparent; white-space: nowrap;
}
.uc-tag::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.uc-tag.is-ok { color: var(--down); background: rgba(var(--down-rgb), .12); border-color: rgba(var(--down-rgb), .3); }
.uc-tag.is-warn { color: var(--warn); background: rgba(184, 120, 15, .12); border-color: rgba(184, 120, 15, .3); }
.uc-tag.is-bad { color: var(--up); background: rgba(var(--up-rgb), .12); border-color: rgba(var(--up-rgb), .3); }
.uc-tag.is-info { color: var(--v6-blue); background: rgba(47, 111, 224, .12); border-color: rgba(47, 111, 224, .3); }
.uc-tag.is-mute { color: var(--text-3); background: var(--q-badge-bg); border-color: var(--line-soft); }
html[data-mode="dark"] .uc-tag.is-warn { color: var(--warn); background: rgba(245, 181, 68, .14); border-color: rgba(245, 181, 68, .32); }
html[data-mode="dark"] .uc-tag.is-info { color: var(--info); background: rgba(75, 143, 245, .14); border-color: rgba(75, 143, 245, .32); }

/* ---------- 时间线 ---------- */
.uc-tl { position: relative; padding-left: 20px; }
.uc-tl::before { content: ""; position: absolute; left: 5px; top: 6px; bottom: 6px; width: 1px; background: var(--line-soft); }
.uc-tl .it { position: relative; padding: 0 0 15px; }
.uc-tl .it:last-child { padding-bottom: 0; }
.uc-tl .it::before {
  content: ""; position: absolute; left: -19px; top: 5px; width: 9px; height: 9px;
  border-radius: 50%; background: var(--surface); border: 2px solid var(--q-track);
}
.uc-tl .it.is-on::before { border-color: var(--brand); box-shadow: 0 0 0 3px rgba(var(--brand-rgb), .16); }
.uc-tl .t { font-size: 13px; color: var(--text); font-weight: 600; }
.uc-tl .m { font-size: 11.5px; color: var(--q-dim); margin-top: 2px; }

/* ---------- 网格工具 ---------- */
.uc-g2 { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 14px; }
.uc-g3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; }
.uc-g-main { display: grid; grid-template-columns: minmax(0, 1.55fr) minmax(0, 1fr); gap: 14px; align-items: start; }
.uc-stack > * + * { margin-top: 14px; }
@media (max-width: 900px) { .uc-g2, .uc-g3, .uc-g-main { grid-template-columns: 1fr; } }

/* ---------- 卡片微调（v3 观感：更轻的描边 + 渐变面） ---------- */
.card {
  background: linear-gradient(180deg, var(--q-panel-a), var(--q-panel-b));
  border-color: var(--line-soft);
}
.card-hd { border-bottom-color: var(--line-soft); }
.v6-table-wrap { border-color: var(--line-soft); }

/* =====================================================================
   量化知识库（原「量化教程」，2026-09-25 改名并改为数据库驱动）
   ---------------------------------------------------------------------
   正文是 Markdown 渲染出来的**裸语义标签**（h2 / p / ul / pre /
   blockquote / table），没有 class 可挂 —— 所以排版规则只能写成
   .kb-body 的后代选择器。这恰恰是要的效果：后台只吐语义标签，
   排版全在这一处统一控制，管理员在编辑器里换什么写法都不会破坏版式。
   ===================================================================== */

/* ---------- 列表页：卡片 ---------- */
.kb-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 14px; }
.kb-card {
  display: flex; flex-direction: column; gap: 9px; padding: 18px 19px;
  background: linear-gradient(180deg, var(--q-panel-a), var(--q-panel-b));
  border: 1px solid var(--line-soft); border-radius: var(--radius);
  box-shadow: var(--q-shadow-sm); text-decoration: none; color: inherit;
  transition: border-color .16s, transform .16s;
}
.kb-card:hover {
  text-decoration: none; color: inherit;
  border-color: rgba(var(--brand-rgb), .45); transform: translateY(-2px);
}
.kb-card-top { display: flex; justify-content: space-between; align-items: center; gap: 10px; }
.kb-cat {
  display: inline-block; font-size: 11px; font-weight: 800; letter-spacing: .04em;
  padding: 2.5px 9px; border-radius: 999px; white-space: nowrap;
  background: rgba(var(--brand-rgb), .12); color: var(--brand-ink);
}
.kb-views { font-size: 11.5px; color: var(--q-dim); white-space: nowrap; }
.kb-card h3 {
  margin: 0; font-size: 16.5px; line-height: 1.45; color: var(--text);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
.kb-card p {
  margin: 0; font-size: 13px; line-height: 1.7; color: var(--text-3);
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
  overflow: hidden;
}
.kb-card-foot {
  margin-top: auto; padding-top: 10px; border-top: 1px solid var(--line-soft);
  display: flex; justify-content: space-between; align-items: center;
  font-size: 12px; color: var(--q-dim);
}
.kb-go { color: var(--brand-ink); font-weight: 600; }

/* ---------- 详情页：头部 ---------- */
.kb-article { padding: 26px 30px 30px; }
.kb-meta {
  display: flex; gap: 12px; align-items: center; flex-wrap: wrap;
  font-size: 12.5px; color: var(--q-dim); margin-bottom: 13px;
}
.kb-title { margin: 0 0 10px; font-size: 26px; line-height: 1.35; color: var(--text); letter-spacing: -.3px; }
.kb-sub { margin: 0; font-size: 14px; line-height: 1.75; color: var(--text-3); }
.kb-cta {
  margin-top: 22px; display: flex; gap: 16px;
  justify-content: space-between; align-items: center; flex-wrap: wrap;
}

/* v0.7.44：列表页把引导卡从页底挪到「分类条之后、文章网格之前」。
   .v6-tabs 自己已有 18px 下边距，这里只补卡片与网格之间的间距，
   所以把默认的 margin-top: 22px 归零 —— 否则两条边距叠成 40px，
   在页顶会显得卡片凭空悬着。详情页那张仍走 kb-cta 原样。 */
.kb-cta-top { margin: 0 0 20px; }

/* ---------- 详情页：正文排版 ---------- */
.kb-body { margin-top: 20px; font-size: 14.5px; line-height: 1.85; color: var(--text); }
.kb-body > *:first-child { margin-top: 0; }
.kb-body h1, .kb-body h2, .kb-body h3,
.kb-body h4, .kb-body h5, .kb-body h6 {
  margin: 30px 0 10px; line-height: 1.4; color: var(--text); font-weight: 700;
}
.kb-body h1 { font-size: 22px; }
/* h2 带下划线：长文里最实用的一个视觉锚点，扫读时能立刻分段 */
.kb-body h2 { font-size: 20px; padding-bottom: 8px; border-bottom: 1px solid var(--line-soft); }
.kb-body h3 { font-size: 17px; }
.kb-body h4, .kb-body h5, .kb-body h6 { font-size: 15px; }
.kb-body p { margin: 12px 0; }
.kb-body ul, .kb-body ol { margin: 12px 0; padding-left: 24px; }
.kb-body li { margin: 6px 0; }
.kb-body a { color: var(--brand-ink); text-decoration: underline; text-underline-offset: 3px; }
.kb-body strong { font-weight: 700; color: var(--text); }
.kb-body del { color: var(--q-dim); }
.kb-body hr { margin: 26px 0; border: 0; border-top: 1px solid var(--line-soft); }
.kb-body img {
  max-width: 100%; height: auto; border-radius: var(--radius);
  border: 1px solid var(--line-soft);
}
.kb-body blockquote {
  margin: 16px 0; padding: 12px 16px; border-left: 3px solid var(--brand);
  background: var(--q-sub); border-radius: 0 10px 10px 0;
  color: var(--text-2); font-size: 14px;
}
.kb-body blockquote > *:first-child { margin-top: 0; }
.kb-body blockquote > *:last-child { margin-bottom: 0; }
.kb-body code {
  font-family: ui-monospace, "JetBrains Mono", Consolas, Menlo, monospace;
  font-size: 13px; padding: 2px 6px; border-radius: var(--radius-sm);
  background: var(--q-sub); color: var(--brand-ink);
  border: 1px solid var(--line-soft);
}
.kb-body pre.kb-code {
  margin: 16px 0; padding: 15px 17px; overflow-x: auto;
  background: var(--q-code-bg); border: 1px solid var(--line-soft);
  border-radius: var(--radius); line-height: 1.7;
}
/* 代码块内部的 code 不能再带自己的底色与边框，否则一块套一块 */
.kb-body pre.kb-code code {
  background: none; border: 0; padding: 0;
  font-size: 13px; color: var(--q-code-fg);
}
.kb-table-wrap {
  margin: 16px 0; overflow-x: auto;
  border: 1px solid var(--line-soft); border-radius: var(--radius);
}
.kb-table { width: 100%; border-collapse: collapse; font-size: 13.5px; }
.kb-table th, .kb-table td {
  padding: 10px 13px; text-align: left;
  border-bottom: 1px solid var(--line-soft);
}
.kb-table th { background: var(--q-sub); font-weight: 700; color: var(--text); white-space: nowrap; }
.kb-table tbody tr:last-child td { border-bottom: 0; }
.kb-table tbody tr:hover td { background: var(--q-hover); }

@media (max-width: 640px) {
  .kb-article { padding: 20px 17px 22px; }
  .kb-title { font-size: 21px; }
  .kb-body { font-size: 14px; }
  .kb-grid { grid-template-columns: 1fr; }
}

/* =====================================================================
   v7 用户中心 · 「量化指挥舱」设计系统（2026-09-25）
   ---------------------------------------------------------------------
   来源：本工作区设计稿 ui-A-quant-terminal-v3.html（方案 A · v3，亮/暗双模）。
   两条硬约束，改之前先读：

     ① 全部规则限定在 body.uc 作用域内。
        公开页 / 帮助页 / 管理后台既有样式一行都不受影响 ——
        特别注意 .shell / .side / .side-foot 那套是**后台在用的**，
        裸改会直接打坏 admin/base_admin.html。

     ② 组件类统一带 uc- 前缀，与已有的 uc-kpi / uc-tag / uc-bar /
        uc-ring / uc-tl / uc-g2 系列同一约定。原稿里的裸类名
        （.card / .btn / .tag / .field / .chip / .empty / .mono…）
        本站早已有主，绝不能直接搬。

   颜色令牌继续走 --q-* 前缀（见文件顶部 :root 的「v3 扩展令牌」），
   这里只补设计稿有、本站尚未定义的那几个；主题色与底色仍由 base.html
   的 JS 覆写 --brand* 驱动，本段不做任何硬编码主题值。
   ===================================================================== */

body.uc {
  /* —— 设计稿补充令牌（暗色值见下方 html[data-mode="dark"] body.uc）—— */
  --q-line-3: #e5ecf6;
  --q-line-4: #d9e3f2;
  --q-line-4-h: #c3d3ea;
  --q-field: #f8fafd;
  --q-field-ro: #f1f5fa;
  --q-row-line: #eff4fa;
  --q-ink-hover: #16233a;
  --q-ink-soft: #5a6c8b;
  --q-muted-2: #8497ae;
  --q-dim-2: #7e91a8;
  --q-up-2: #c43832;
  --q-up-3: #a82a25;
  --q-blue: #2f6fe0;
  --q-blue-2: #3f83e8;
  --q-blue-2-rgb: 63, 131, 232;
  --q-amber-rgb: 184, 120, 15;
  --q-blue-soft: #6fa4ee;
  --q-amber-soft: #d9be86;
  --q-down-soft2: #8fd9c5;
  --q-avatar-a: #2563a7;
  --q-avatar-b: #4b8ff5;

  /* —— 主题色别名 ——
     设计稿通篇用 --accent / --accent2 / --accent-ink / --accent-rgb /
     --on-accent / --grad-a / --grad-b，本站是 --brand 一系。
     这里做一层**别名字面量**（而不是改原稿的 CSS），好处是：
     原稿的组件 CSS 可以近乎逐行照抄，而「切主题 / 切亮暗」依然由
     base.html <head> 里那一套 JS 统一驱动，不存在第二份配色表。
     因为 var() 是延迟求值的，JS 之后覆写 --brand* 这里会自动跟随。 */
  --accent: var(--brand);
  --accent2: var(--brand-2);
  --accent-ink: var(--brand-ink);
  --accent-rgb: var(--brand-rgb);
  --on-accent: var(--on-brand);
  --grad-a: var(--brand);
  --grad-b: var(--brand-dark);
  --uc-radius: 14px;
}
html[data-mode="dark"] body.uc {
  --q-line-3: #2a3f5e;
  --q-line-4: #35496b;
  --q-line-4-h: #46618c;
  --q-field: #131f33;
  --q-field-ro: #101b2c;
  --q-row-line: #1e2f47;
  --q-ink-hover: #e4ecfa;
  --q-ink-soft: #a9bdd9;
  --q-muted-2: #7f94b3;
  --q-dim-2: #61769a;
  --q-up-2: #ff8b8b;
  --q-up-3: #ffa5a5;
  --q-blue: #4b8ff5;
  --q-blue-2: #5aa2ff;
  --q-blue-2-rgb: 90, 162, 255;
  --q-amber-rgb: 245, 181, 68;
  --q-blue-soft: #a9c9f5;
  --q-amber-soft: #f0cf8e;
  --q-down-soft2: #9fe3c7;
}

/* 用户中心的内容层要压过全站那道网格 + 光晕背景（body::before，z-index:0） */
body.uc .uc-shell, body.uc .uc-col { position: relative; z-index: 1; }
body.uc .uc-main { position: relative; z-index: 1; }

/* ============================ 骨架 ============================ */
body.uc .uc-shell {
  display: grid; grid-template-columns: 240px minmax(0, 1fr);
  align-items: start; min-height: 100vh;
}
body.uc .uc-side {
  position: sticky; top: 0; z-index: 30;
  height: 100vh; overflow: hidden;
  display: flex; flex-direction: column; gap: 12px;
  padding: 16px 14px 20px;
  background: linear-gradient(180deg, var(--q-side-a), var(--q-side-b));
  border-right: 1px solid var(--line-soft);
  box-shadow: var(--q-side-shadow);
}
body.uc .uc-col { min-width: 0; display: flex; flex-direction: column; min-height: 100vh; }

/* ★ v0.7.41（圆总报「网站整体缩放后出现大量空白，布局没自适应填充」）：
   原来这里是 `max-width: 1260px` 而且**没有 margin 自动居中** —— 视口一旦超过
   240+1260=1500，主区就固定 1260 死贴左边、右边晾一条空白，且空白随视口线性增长。
   无头 Chrome 实测（本文件同目录外的工作区脚本 _v0741_geom.py 可复现）：

       视口 1280 → 主区 1007（铺满），右空白   15px
       视口 1920 → 主区 1260（封顶），右空白  402px
       视口 2866 → 主区 1260（封顶），右空白 1348px   ← 67% 缩放就是这一幕

   多出来那 402 / 1348px 是**单侧**的，看上去像页面画歪了，比两侧对称留白更刺眼。
   ⇒ 工作台型版面（行情表 / 卡片 / 通道矩阵）本就该吃满屏幕，改成跟随视口。
     只有真正难读的长文保留窄栏：
       · `.container-narrow`（760px，风险提示 / 帮助 / 论坛帖）—— 刻意不动；
       · `.kb-article` 正文列单独限宽（见下方 v0.7.41 那段）。
   `clamp()` 让左右内边距随视口缓增，超宽屏下正文不至于贴到屏幕边。 */
body.uc .uc-main {
  flex: 1 1 auto; width: 100%; min-width: 0;
  max-width: none; margin: 0;
  padding: 24px clamp(20px, 1.8vw, 40px) 40px;
}

/* ★ v0.7.41：弹层必须盖住顶栏与侧栏（否则弹层头部被顶栏压住 = 又一个「显示不全」）
   ------------------------------------------------------------------
   病因在**层叠上下文**，不在弹层自己的 z-index：
     `.uc-main` 自己带 `position: relative; z-index: 1`（见上方骨架那段），
     而固定定位**逃不出祖先的层叠上下文**。
     `.uc-topbar`（sticky, z-index 20）与 `.uc-side`（sticky, z-index 30）
     是它的上级/兄弟节点 ⇒ 两者都被画在遮罩**之上**：
       · 弹层头部（标题「测试台」+ 关闭键）被顶栏压掉 —— 弹层越高越明显；
       · 侧栏与顶栏在弹层打开时**仍然可点**（点得到 = 弹层没真正拦住）。
   实测：100% 缩放下带一份回执时弹层被撑到上限，top 只剩 ~18px，
   标题整块落在顶栏（0–44px）后面。圆总看到的「测试模块显示不全」含这一条。
   修法：弹层打开期间（body.v6-dialog-open）把外壳抬到顶栏/侧栏/悬浮件之上 ——
   遮罩本来就该盖住整个视口。用 body.v6-dialog-open 限定，平时层叠完全不变。 */
body.uc.v6-dialog-open .uc-shell { z-index: 96; }   /* > .cs-dock(92) / .cs-float(90) */
body.uc.v6-dialog-open .uc-col { z-index: 40; }     /* > .uc-side 的 30 */
body.uc.v6-dialog-open .uc-main { z-index: 40; }    /* > .uc-topbar 的 20 */

/* --------- 站内内容页嵌入用户中心外壳（v0.7.31） ---------
   官方策略 / 知识库 / 交流论坛这批页面原本按公开页排版，自己带一层
   .container(20px) / .v6-wrap(20px) 的居中留白。搬进 .uc-main（已有
   26px 内边距）后会叠成 ~46px，正文明显偏窄、左右还各空一条。
   这里把**外壳已经提供**的那份横向留白收掉，保留页面自己的
   max-width 与居中（否则长文章会被拉成一整屏宽，更难读），
   纵向节奏也只压掉顶部那段重复的 28px。 */
body.uc .uc-main > .container-narrow,
body.uc .uc-main > .v6-wrap { padding-left: 0; padding-right: 0; }

/* v0.7.41：`.v6-wrap` 自带 `max-width: 1180px; margin: 0 auto`，上面那条只归零了
   内边距、没动限宽 —— 于是 /kb、/kb/<slug>、/help/... 这批页面在超宽屏上照样是
   「中间一条 1180 + 两侧成片空白」。跟 `.container` 一样把限宽放开。
   知识库文章是长文，正文列另给上限（下一段），避免超宽屏一行两百字。 */
body.uc .uc-main > .v6-wrap {
  max-width: none;
  margin-left: 0;
  margin-right: 0;
}
body.uc .uc-main .kb-article { max-width: 1080px; }

/* 页脚与主内容同宽同基线：主区已铺满，页脚如果还居中在 1180 上，
   拉到底部会看到「正文到边、页脚缩在中间」，像是两块拼错的东西。 */
body.uc .footer .inner {
  max-width: none;
  margin: 0;
  padding-left: clamp(20px, 1.8vw, 40px);
  padding-right: clamp(20px, 1.8vw, 40px);
}

/* ★ 2026-09-26（圆总报）：在「通道服务 ↔ 官方策略」之间切换时，主体内容
   会「窄一截 + 整体右移」。量出来就是这一层 .container 造成的 ——
   .uc-main 的内容盒是 1190px，而 .container 是 `max-width:1120px; margin:0 auto`，
   ⇒ 切进 /official 后内容窄 70px、左边界从 266 挪到 301（凭空多 35px 缩进）。
   上一轮只归零了左右 padding，没动限宽与居中，所以「页头修好了、主体还是不对」。
   用户中心是「工作台」型版面：/me/* 二十来个页面一律直接铺在 .uc-main 里。
   站内容页搬进这套外壳后，就该与它们**等宽、同一条左基线** ——
   所以让 .container 在这里退化为透明 wrapper。
   ⚠️ 刻意**不动** `.container-narrow`：760px 那个窄栏是给长文
   （/terms、/help/*）设的，铺满反而难读；`.v6-wrap` 是 1180px，与 1190 只差
   10px（居中后左右各 5px），肉眼已对齐，也不必改。 */
body.uc .uc-main > .container {
  max-width: none;
  margin-left: 0;
  margin-right: 0;
  padding-left: 0;
  padding-right: 0;
}
body.uc .uc-main > .container.page { padding-top: 0; }
/*  ↑ 原来是 4px。2026-09-26：/official 的页内切换条因此比同组的 /me 页低 4px，
       切过去整行会轻微「跳」一下。.uc-main 自己已有 24px 上内边距，
       这 4px 属于重复留白，收掉即对齐（游客态不受影响，规则带 body.uc 前缀）。 */

/* ============================ 品牌 ============================ */
body.uc .uc-brand {
  display: flex; align-items: center; gap: 10px;
  padding: 2px 6px 14px; border-bottom: 1px solid var(--line-soft);
}
body.uc .uc-brand:hover { text-decoration: none; }
body.uc .uc-brand .lg {
  width: 34px; height: 34px; flex: 0 0 34px; border-radius: var(--radius);
  overflow: hidden; box-shadow: 0 6px 18px rgba(var(--accent-rgb), .36);
}
body.uc .uc-brand .lg img { display: block; width: 34px; height: 34px; object-fit: cover; }
body.uc .uc-brand .tx b { display: block; color: var(--text); font-size: 14.5px; line-height: 1.3; }
body.uc .uc-brand .tx span { font-size: 10.5px; color: var(--q-dim); letter-spacing: .1em; }

/* ============================ 导航 ============================ */
body.uc .uc-nav { display: flex; flex-direction: column; gap: 2px; flex: 1; overflow-y: auto; }
body.uc .uc-nav::-webkit-scrollbar { width: 5px; }
body.uc .uc-nav::-webkit-scrollbar-thumb { background: var(--q-line-4); border-radius: 99px; }
body.uc .uc-grp {
  font-size: 10px; letter-spacing: .16em; font-weight: 800;
  color: var(--q-dim-2); padding: 14px 9px 6px;
}
body.uc .uc-navi {
  position: relative; display: flex; align-items: center; gap: 10px;
  padding: 9px 11px; border-radius: var(--radius);
  font-size: 13.5px; color: var(--q-ink-soft);
  border: 1px solid transparent;
  transition: background .16s, color .16s, border-color .16s;
}
body.uc .uc-navi:hover { background: var(--q-hover); color: var(--q-ink-hover); text-decoration: none; }
body.uc .uc-navi.is-on {
  background: linear-gradient(90deg, rgba(var(--accent-rgb), .17), rgba(var(--accent-rgb), .03));
  color: var(--accent-ink); font-weight: 600;
  border-color: rgba(var(--accent-rgb), .34);
}
body.uc .uc-navi.is-on::before {
  content: ""; position: absolute; left: -14px; top: 9px; bottom: 9px; width: 3px;
  border-radius: 0 3px 3px 0; background: var(--accent);
  box-shadow: 0 0 14px rgba(var(--accent-rgb), .85);
}
body.uc .uc-navi svg { width: 16px; height: 16px; flex: 0 0 16px; opacity: .8; }
body.uc .uc-navi.is-on svg { opacity: 1; }
body.uc .uc-navi .bd {
  margin-left: auto; font-size: 10.5px; font-weight: 800;
  padding: 2px 7px; border-radius: 999px;
  background: var(--q-badge-bg); color: var(--q-badge-fg);
}
body.uc .uc-navi.is-on .bd { background: rgba(var(--accent-rgb), .22); color: var(--accent-ink); }

/* ==================== 顶栏主题按钮（原「侧栏主题条」） ====================
   v0.7.31：侧栏底部那条主题色条已移除，控件整体搬到顶栏右上角的
   .theme-pop 浮层里（见 me/base_me.html）。所以这里删掉了旧的
   .uc-themebar / .uc-dots / .uc-mode 三段样式 —— 留着就是一份
   「看着像功能还在、实际没有任何元素命中」的死代码。
   浮层本身复用 base.html 的 .theme-pop 组件（样式在本文件前段），
   触发按钮靠 .uc-chip 拿视觉，不需要额外规则。 */

body.uc .uc-side-foot {
  margin-top: 10px; padding: 11px 12px; border-radius: var(--radius);
  background: var(--q-sub); border: 1px solid var(--line-soft);
  font-size: 11.5px; color: var(--q-dim); line-height: 1.7;
}
body.uc .uc-side-foot b { color: var(--text-2); }

/* ============================ 顶栏 ============================ */
body.uc .uc-topbar {
  position: sticky; top: 0; z-index: 20;
  display: flex; align-items: center; justify-content: space-between;
  gap: 14px; flex-wrap: wrap; padding: 12px 26px;
  background: var(--q-topbar); backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line-soft);
  box-shadow: 0 1px 0 var(--line-soft), 0 6px 18px -14px rgba(16, 26, 44, .2);
}
body.uc .uc-topbar .tb-l, body.uc .uc-topbar .tb-r { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
body.uc .uc-topbar .tb-r { margin-left: auto; }
body.uc .uc-sdot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--down); animation: uc-pulse 2.2s infinite;
}
/* 同一个状态点在「有需要注意的事」时换成琥珀并停止呼吸动画：
   闪烁适合表达「活着」，不适合表达「有问题」—— 一直闪会让人忽略它。 */
body.uc .uc-sdot.is-warn {
  background: var(--warn); animation: none;
  box-shadow: 0 0 0 3px rgba(var(--q-amber-rgb), .18);
}
@keyframes uc-pulse {
  0% { box-shadow: 0 0 0 0 rgba(var(--down-rgb), .55); }
  70% { box-shadow: 0 0 0 9px rgba(var(--down-rgb), 0); }
  100% { box-shadow: 0 0 0 0 rgba(var(--down-rgb), 0); }
}
body.uc .uc-chip {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 6px 11px; border-radius: var(--radius-sm);
  border: 1px solid var(--q-line-3); background: var(--q-sub);
  font-size: 12px; color: var(--q-ink-soft);
}
body.uc .uc-chip.is-mono, body.uc .uc-chip .mono {
  font-family: ui-monospace, Consolas, monospace;
  font-variant-numeric: tabular-nums;
}
/* 可点击的 chip（用户中心顶栏那个「退出」）。
   button 自带 UA 样式：字体不回继承（会掉成系统 UI 字体，跟旁边几个 chip 不同款）、
   光标也不是 pointer。chip 的视觉全在 .uc-chip 上，这里只补这两处差异。 */
body.uc .uc-chip.is-btn {
  cursor: pointer; font-family: inherit; font-weight: 600;
}
body.uc .uc-chip.is-btn:hover {
  border-color: var(--q-line-4-h); background: var(--q-hover); color: var(--text);
}
body.uc .uc-plabel {
  padding: 4px 10px; border-radius: 999px;
  font-size: 11px; font-weight: 900; letter-spacing: .1em;
  color: var(--on-accent);
  background: linear-gradient(135deg, var(--grad-a), var(--grad-b));
}
body.uc .uc-avatar {
  width: 32px; height: 32px; border-radius: var(--radius-sm); flex: 0 0 32px;
  overflow: hidden; display: grid; place-items: center;
  background: linear-gradient(140deg, var(--q-avatar-a), var(--q-blue));
  color: #fff; font-weight: 800; font-size: 13px;
  box-shadow: 0 0 0 1px var(--q-line-4);
}
body.uc .uc-avatar img { display: block; width: 100%; height: 100%; object-fit: cover; }
/* 「基本资料」头像卡里的大尺寸。设计稿那里是写死的内联样式
   （width:64px;height:64px;border-radius:16px;font-size:24px），
   这里收成一个类，免得同一个尺寸在模板里散成四行 style。 */
body.uc .uc-avatar.is-xl {
  width: 64px; height: 64px; border-radius: 16px; flex: 0 0 64px; font-size: 24px;
}
body.uc .uc-who b { display: block; font-size: 13px; color: var(--text); line-height: 1.25; }
body.uc .uc-who span { font-size: 11px; color: var(--q-dim); }

/* 移动端：侧栏折成一条横向可滚动的胶囊条 */
@media (max-width: 900px) {
  body.uc .uc-shell { grid-template-columns: 1fr; }
  body.uc .uc-side {
    position: static; height: auto; flex-direction: row; align-items: center;
    gap: 8px; padding: 10px 12px; overflow-x: auto;
    border-right: 0; border-bottom: 1px solid var(--line-soft);
  }
  body.uc .uc-brand { border-bottom: 0; padding: 0 6px 0 0; flex: 0 0 auto; }
  body.uc .uc-brand .tx, body.uc .uc-grp, body.uc .uc-side-foot { display: none; }
  body.uc .uc-nav { flex-direction: row; gap: 6px; flex: 0 0 auto; overflow: visible; }
  body.uc .uc-navi { white-space: nowrap; padding: 8px 12px; border-radius: 999px; }
  body.uc .uc-navi.is-on::before { display: none; }
  body.uc .uc-navi svg { display: none; }
  body.uc .uc-main { padding: 18px 16px 32px; }
  body.uc .uc-topbar { padding: 10px 16px; }
}

/* 表格行 hover 用的中性蓝（设计稿的 --blue-rgb，本站原先没有） */
body.uc { --q-blue-rgb: 47, 111, 224; }
html[data-mode="dark"] body.uc { --q-blue-rgb: 75, 143, 245; }

/* ============================ 页头 ============================ */
body.uc .uc-phead {
  display: flex; justify-content: space-between; align-items: flex-end;
  gap: 18px; flex-wrap: wrap; margin-bottom: 18px;
}
body.uc .uc-phead h1 {
  font-size: 23px; font-weight: 800; letter-spacing: -.2px;
  color: var(--text); margin: 0; line-height: 1.3;
}
body.uc .uc-phead .sub { margin: 6px 0 0; color: var(--text-3); font-size: 13px; }
body.uc .uc-phead .uc-kicker {
  display: block; font-size: 10.5px; letter-spacing: .18em;
  font-weight: 900; color: var(--accent); margin-bottom: 7px;
}

/* 登录态下的公开页页头（.page-head）。
   /kb、/forum、/help/*、/pricing、/terms 这些内容页登录后会套上用户中心外壳
   （见 templating._layout_for），但页头仍是公开页那一套 28px/600。
   于是从 /me 的某个模块切过去时，标题会"跳"一下变大 —— 2026-09-26
   圆总反馈的「切换页面有违和感」。
   这里在 body.uc 作用域内把 .page-head 收敛到与 .uc-phead 同口径；
   加 body.uc 前缀是关键：公开页（游客态）完全不受影响。
   注：kicker 是**内容**不是样式，能对齐的只有字号/字重/字距/颜色/间距。 */
body.uc .page-head { margin-bottom: 18px; }
body.uc .page-head h1 {
  font-size: 23px; font-weight: 800; letter-spacing: -.2px;
  color: var(--text); margin: 0; line-height: 1.3;
}
body.uc .page-head .sub { margin: 6px 0 0; color: var(--text-3); font-size: 13px; }

/* ============================ 卡片 ============================ */
body.uc .uc-card {
  border: 1px solid var(--line-soft); border-radius: var(--uc-radius);
  background: linear-gradient(180deg, var(--q-panel-a), var(--q-panel-b));
  box-shadow: var(--q-shadow-sm);
}
body.uc .uc-card + .uc-card { margin-top: 14px; }
body.uc .uc-card-hd {
  display: flex; justify-content: space-between; align-items: center;
  gap: 14px; flex-wrap: wrap;
  padding: 15px 18px; border-bottom: 1px solid var(--line-soft);
}
body.uc .uc-card-hd h2 { font-size: 15.5px; font-weight: 800; letter-spacing: -.2px; margin: 0; color: var(--text); }
body.uc .uc-card-hd h3 { font-size: 14px; font-weight: 800; margin: 0; color: var(--text); }
body.uc .uc-card-hd p { margin: 3px 0 0; font-size: 12.5px; color: var(--text-3); }
body.uc .uc-card-bd { padding: 16px 18px; }
body.uc .uc-card-bd.is-tight { padding: 8px 10px; }
body.uc .uc-card-bd.is-foot {
  border-top: 1px solid var(--line-soft);
  display: flex; justify-content: space-between; align-items: center;
  flex-wrap: wrap; gap: 10px;
}

/* ============================ KPI 卡 ============================ */
body.uc .uc-kpi {
  border-color: var(--line-soft);
  background: linear-gradient(158deg, var(--q-panel-a), var(--q-panel-b) 64%);
}
/* 顶部那道高光：普通卡 1px，强调卡 2px 并换成主题色 */
body.uc .uc-kpi::after {
  content: ""; position: absolute; inset: 0 0 auto; height: 1px;
  background: linear-gradient(90deg, transparent, var(--q-shine), transparent);
}
body.uc .uc-kpi.is-accent::after {
  height: 2px;
  background: linear-gradient(90deg, transparent, var(--brand), transparent);
}
/* ⚠️ 类名必须叫 .uc-spark，**绝不能叫 .spark**：
     本文件第 504 行早有一条 `.spark { width: 100%; height: 140px }`（旧版大图表
     留下的死规则，全站已无人使用）。用 .spark 会被它按 100%×140px 撑开，
     走势线直接盖住整张 KPI 卡 —— 2026-09-25 实测过，症状是「数字上压着一条线」。
     同理这里把宽高写死，不再依赖 width/height 呈现属性（它们优先级低于任何 CSS）。 */
body.uc .uc-kpi .uc-spark {
  position: absolute; right: 11px; bottom: 9px;
  width: 66px; height: 24px; display: block; opacity: .95;
}
body.uc .uc-kpi .uc-spark polyline { fill: none; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
/* 带走势线的卡片，说明文字要给右下角那块让位：
   走势线虽然绝对定位在 bottom:9px，但它的顶端和 .d 的基线在同一横带上，
   说明文字一长（例如「聚宽跟单服务 · 年费 · 至 2027-03-31」）就会插进线里。
   由模板按「这一格有没有走势线」加 has-spark，不去用 :has()，兼容性没风险。
   顺带 nowrap + 省略号：宁可截断，也不要折行后压到走势线上。 */
body.uc .uc-kpi.has-spark .d {
  padding-right: 72px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* ============================ 表格 ============================ */
body.uc .uc-tbl-wrap { overflow-x: auto; }
body.uc .uc-tbl { width: 100%; border-collapse: collapse; font-size: 13px; }
body.uc .uc-tbl th {
  text-align: left; font-size: 10.5px; letter-spacing: .1em;
  color: var(--q-dim); font-weight: 800;
  padding: 0 12px 10px; border-bottom: 1px solid var(--line-soft); white-space: nowrap;
}
body.uc .uc-tbl td {
  padding: 12px; border-bottom: 1px solid var(--q-row-line);
  color: var(--text-2); vertical-align: middle;
}
body.uc .uc-tbl tbody tr:hover { background: rgba(var(--q-blue-rgb), .06); }
body.uc .uc-tbl tr:last-child td { border-bottom: 0; }
body.uc .uc-tbl .r, body.uc .uc-tbl th.r { text-align: right; }
body.uc .uc-tbl td b { color: var(--text); }

/* ============================ 工具类 ============================ */
body.uc .uc-mono {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-variant-numeric: tabular-nums;
}
body.uc .uc-sm { font-size: 12px; }
body.uc .uc-dim { color: var(--q-dim); }
body.uc .uc-nowrap { white-space: nowrap; }
body.uc .uc-r { text-align: right; }
body.uc .uc-t-up { color: var(--up) !important; }
body.uc .uc-t-down { color: var(--down) !important; }
body.uc .uc-t-acc { color: var(--accent-ink) !important; }
body.uc .uc-t-warn { color: var(--warn) !important; }
body.uc .uc-t-dim { color: var(--q-dim) !important; }
body.uc .uc-t-blue { color: var(--q-blue) !important; }

/* ============================ 按钮 ============================ */
body.uc .uc-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  padding: 9px 15px; border-radius: var(--radius-sm);
  border: 1px solid var(--q-line-4); background: var(--q-sub2);
  color: var(--text-2); font: inherit; font-size: 13px; font-weight: 600;
  cursor: pointer; transition: .15s;
  /* 按钮标签永远不折行。`.uc-card-hd` 是 flex 行，右侧按钮在标题长了之后
     会被压窄 —— 「换一个邀请码」会断成「换一个邀请 / 码」两行，看着像坏掉。
     按钮文案本来就短，nowrap 不占额外宽度，只是不许它在字中间断。 */
  white-space: nowrap;
}
body.uc .uc-btn:hover {
  border-color: var(--q-line-4-h); background: var(--q-hover);
  color: var(--text); text-decoration: none;
}
body.uc .uc-btn.is-primary {
  background: linear-gradient(135deg, var(--grad-a), var(--grad-b));
  border-color: transparent; color: var(--on-accent);
  box-shadow: 0 8px 22px rgba(var(--accent-rgb), .26);
}
body.uc .uc-btn.is-primary:hover { filter: brightness(1.07); color: var(--on-accent); }
body.uc .uc-btn.is-ghost { background: transparent; }
body.uc .uc-btn.is-danger { background: transparent; border-color: rgba(var(--up-rgb), .4); color: var(--q-up-2); }
body.uc .uc-btn.is-danger:hover { background: rgba(var(--up-rgb), .1); border-color: rgba(var(--up-rgb), .6); color: var(--q-up-3); }
body.uc .uc-btn.sm { padding: 6px 11px; font-size: 12px; border-radius: var(--radius-sm); }
body.uc .uc-btn.is-block { width: 100%; }
body.uc .uc-btn[disabled] { opacity: .4; cursor: not-allowed; }
body.uc .uc-btn-row { display: flex; gap: 9px; flex-wrap: wrap; align-items: center; }

/* ============================ 表单 ============================ */
body.uc .uc-field { margin-bottom: 15px; }
body.uc .uc-field.is-narrow { max-width: 460px; }
body.uc .uc-label { display: block; font-size: 12.5px; color: var(--text-2); margin-bottom: 6px; font-weight: 700; }
body.uc .uc-input, body.uc .uc-select, body.uc .uc-ta {
  width: 100%; padding: 10px 12px; border-radius: var(--radius-sm);
  border: 1px solid var(--q-line-4); background: var(--q-field);
  color: var(--text); font: inherit; font-size: 13.5px; outline: none; transition: .15s;
}
body.uc .uc-input:focus, body.uc .uc-select:focus, body.uc .uc-ta:focus {
  border-color: var(--accent); box-shadow: 0 0 0 3px rgba(var(--accent-rgb), .16);
}
body.uc .uc-input[readonly] { color: var(--q-dim); background: var(--q-field-ro); }
body.uc .uc-ta { min-height: 84px; resize: vertical; }
body.uc .uc-hint { font-size: 11.5px; color: var(--q-dim); margin-top: 6px; line-height: 1.6; }
body.uc .uc-kv {
  display: grid; grid-template-columns: 132px minmax(0, 1fr);
  gap: 11px 16px; font-size: 13.5px; margin: 0;
}
body.uc .uc-kv dt { color: var(--text-3); }
body.uc .uc-kv dd { margin: 0; color: var(--text-2); font-weight: 600; }
body.uc .uc-kv dd.uc-mono { font-weight: 400; }

/* ---- 邀请链接：只读长输入框 + 复制按钮 ----
   输入框必须能吃掉剩余宽度（flex:1 + min-width:0），否则长链接会把
   按钮挤出容器。`uc-input` 自带 max-width 之类的约束，这里不复用、
   单开一个类，免得调宽窄时把全站输入框一起改了。 */
body.uc .uc-invite-row { display: flex; gap: 10px; align-items: stretch; }
body.uc .uc-invite-input {
  flex: 1 1 auto; min-width: 0;
  padding: 10px 13px; font-size: 13px; line-height: 1.5;
  color: var(--text); background: var(--q-field-ro);
  border: 1px solid var(--line-soft); border-radius: var(--radius);
  overflow-x: auto; white-space: nowrap; text-overflow: ellipsis;
}
body.uc .uc-invite-input:focus {
  outline: 0; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(var(--accent-rgb), .16);
}
@media (max-width: 640px) {
  body.uc .uc-invite-row { flex-direction: column; }
}

/* ---- 规则清单 ---- */
body.uc .uc-rule-list { margin: 0; padding-left: 18px; font-size: 12.5px; color: var(--text-2); line-height: 1.85; }
body.uc .uc-rule-list li + li { margin-top: 2px; }
body.uc .uc-rule-list b { color: var(--text); }

/* ---- 单选胶囊（工单类型） ----
   用 radio + label 而不是 <select>：三个类型是要一眼看全的并列选项，
   下拉框得点开才知道有哪些。radio 保留原生语义（键盘、无障碍、表单提交），
   只是把外观换掉 —— `position:absolute;opacity:0` 而不是 display:none，
   因为 display:none 会让它拿不到焦点，键盘用户就选不了了。 */
body.uc .uc-pick-row { display: flex; flex-wrap: wrap; gap: 8px; }
body.uc .uc-pick { position: relative; cursor: pointer; }
body.uc .uc-pick input { position: absolute; opacity: 0; width: 1px; height: 1px; margin: 0; }
body.uc .uc-pick span {
  display: inline-block; padding: 7px 15px; border-radius: 999px;
  font-size: 13px; font-weight: 600; color: var(--text-2);
  background: var(--q-sub); border: 1px solid var(--line-soft);
  transition: background .16s, color .16s, border-color .16s;
}
body.uc .uc-pick:hover span { background: var(--q-hover); color: var(--text); }
body.uc .uc-pick input:checked + span {
  background: rgba(var(--brand-rgb), .13); color: var(--brand-ink);
  border-color: rgba(var(--brand-rgb), .42);
}
body.uc .uc-pick input:focus-visible + span { box-shadow: 0 0 0 3px rgba(var(--accent-rgb), .28); }

/* ---- 工单会话 ----
   左右分栏只是**辅助**，每条上头都写了「我 / 站长」的文字署名：
   靠颜色区分身份的话，截图转发出去、或色觉障碍用户就分不出来了。 */
body.uc .uc-thread { display: flex; flex-direction: column; gap: 12px; }
body.uc .uc-msg { border-radius: var(--radius); padding: 12px 14px; border: 1px solid var(--line-soft); max-width: 92%; }
body.uc .uc-msg.is-me { background: var(--q-sub); align-self: flex-end; }
body.uc .uc-msg.is-staff { background: rgba(var(--q-blue-rgb), .07); border-color: rgba(var(--q-blue-rgb), .26); align-self: flex-start; }
body.uc .uc-msg-hd { display: flex; align-items: baseline; gap: 8px; margin-bottom: 7px; }
body.uc .uc-msg-hd .who { font-size: 12.5px; font-weight: 800; color: var(--text); }
body.uc .uc-msg-bd {
  font-size: 13.5px; line-height: 1.75; color: var(--text-2);
  white-space: pre-wrap;      /* 用户输入的换行要保留 —— 复现步骤靠它分段 */
  word-break: break-word;     /* 长 URL / 长报错串不能把卡片撑破 */
}
@media (max-width: 640px) {
  body.uc .uc-msg { max-width: 100%; align-self: stretch; }
}

/* ============================ 通道行 ============================ */
body.uc .uc-chan {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 13px 15px; border: 1px solid var(--line-soft);
  border-radius: var(--radius); background: var(--q-sub);
}
body.uc .uc-chan + .uc-chan { margin-top: 10px; }
body.uc .uc-chan .nm { font-weight: 800; color: var(--text); font-size: 14px; }
body.uc .uc-chan .meta { font-size: 12px; color: var(--text-3); margin-top: 3px; }
body.uc .uc-chan .meta.uc-mono { font-weight: 400; }
/* 操作组：允许换行 + 右对齐。四个按钮在一行里挤不下时（窄屏 / 长通道名）
   会整组掉到下一行并保持右对齐，而不是把按钮压变形。 */
body.uc .uc-chan .sp {
  margin-left: auto; display: flex; align-items: center; gap: 9px;
  flex-wrap: wrap; justify-content: flex-end;
}
/* 危险操作与其它操作之间的竖线分隔（删除按钮前 / 实盘报单前），防手滑连点。
   不锁在 .uc-chan 里 —— 工作台测试台的「不下单 / 真报单」也用它。 */
body.uc .sp-sep {
  width: 1px; height: 18px; flex: 0 0 auto; align-self: center;
  background: var(--line-soft);
}
body.uc .uc-icobox {
  width: 38px; height: 38px; flex: 0 0 38px; border-radius: var(--radius);
  display: grid; place-items: center; font-size: 15px;
  background: var(--q-sub2); border: 1px solid var(--q-line-4);
}
/* 「添加一条通道」那种虚线占位行 */
body.uc .uc-chan.is-dashed { border-style: dashed; background: transparent; }
body.uc .uc-chan.is-dashed .uc-icobox { background: transparent; }
/* 虚线行本身是 <a>，要显式去下划线 + 给 hover 反馈 */
body.uc a.uc-chan { text-decoration: none; }
body.uc a.uc-chan:hover {
  text-decoration: none; border-color: var(--q-line-4-h); background: var(--q-hover);
}
body.uc a.uc-chan:hover .nm { color: var(--accent-ink); }
body.uc a.uc-chan.is-dashed:hover { background: rgba(var(--accent-rgb), .05); border-color: var(--q-nav-on-bd); }
/* 订阅记录里把通道行竖排（名称/到期/进度条/按钮） */
body.uc .uc-chan.is-col { flex-direction: column; align-items: flex-start; gap: 8px; }

/* ============================ 充值档位 ============================ */
body.uc .uc-pk-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 13px; }
body.uc .uc-pk {
  position: relative; padding: 16px; border-radius: var(--radius);
  border: 1px solid var(--line-soft); background: var(--q-sub);
  cursor: pointer; transition: .16s;
}
body.uc .uc-pk:hover { border-color: var(--q-line-4-h); }
body.uc .uc-pk.is-on {
  border-color: var(--accent);
  background: linear-gradient(170deg, rgba(var(--accent-rgb), .14), rgba(var(--accent-rgb), .02));
}
body.uc .uc-pk .amt { font-size: 24px; font-weight: 800; color: var(--text); font-variant-numeric: tabular-nums; }
body.uc .uc-pk .amt small { font-size: 12px; font-weight: 600; color: var(--text-3); margin-left: 4px; }
body.uc .uc-pk .price { margin-top: 6px; color: var(--accent-ink); font-weight: 800; font-size: 15px; }
body.uc .uc-pk .tagline { margin-top: 7px; font-size: 11.5px; color: var(--q-dim); }
body.uc .uc-pk .pick {
  position: absolute; top: 12px; right: 12px;
  width: 16px; height: 16px; border-radius: 50%;
  border: 1px solid var(--q-line-4-h);
}
body.uc .uc-pk.is-on .pick { border-color: var(--accent); background: var(--accent); box-shadow: inset 0 0 0 3px var(--q-sub); }
@media (max-width: 1120px) { body.uc .uc-pk-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 620px) { body.uc .uc-pk-grid { grid-template-columns: 1fr; } }

/* ============================ 提示条 ============================
   ⚠️ 这里曾经是 `display: flex; gap: 10px`（为 `.ic` 图标列服务）。那个写法是错的：
   裸文本放进 flex 容器会被拆成一个个**匿名 flex item**，默认 nowrap 下每个 item
   被压到只剩一两个字宽 ⇒ 整段中文逐字竖排，看上去就是乱码
   （2026-09-30 实测：通道工作台「卖单测试」那张红框告警整段错乱）。
   flex 只在「正文被包成唯一子元素」时才安全，而全站 20 处 uc-note 里绝大多数是
   裸文本 + <b>/<code>/<br> 混排，还有 loadSignals() 那种直接 innerHTML 塞纯文本的。
   退回 block 后 `.ic` 退回行内、用 margin 顶开间距 —— 对「有 .ic」「没有 .ic」
   两种写法都正确。改回去之前先想清楚这一条。 */
body.uc .uc-note {
  display: block; padding: 12px 14px; border-radius: var(--radius);
  font-size: 12.8px; line-height: 1.65;
  border: 1px solid var(--q-line-4); background: var(--q-sub); color: var(--text-2);
}
body.uc .uc-note .ic { display: inline-block; margin-right: 8px; font-weight: 900; }
body.uc .uc-note.is-info { border-color: rgba(var(--q-blue-rgb), .34); background: rgba(var(--q-blue-rgb), .08); color: var(--q-blue-soft); }
body.uc .uc-note.is-warn { border-color: rgba(var(--q-amber-rgb), .34); background: rgba(var(--q-amber-rgb), .08); color: var(--q-amber-soft); }
body.uc .uc-note.is-ok { border-color: rgba(var(--down-rgb), .32); background: rgba(var(--down-rgb), .08); color: var(--q-down-soft2); }
body.uc .uc-note b { color: inherit; }

/* ==================== 测试台（v0.7.39） ====================
   通道工作台把「发送测试信号 / 买卖预检 / 实盘报单」收进一个对话框后的配套样式。
   卡上：三张强度说明 + 执行端持仓可见性 + 持仓表；
   弹层里：方向切换 + 标的/数量/价格 + 三个动作 + 一个统一回执区。
   回执区的四步流程条颜色语义与 .uc-tag 保持一致：
   绿=已通过 · 琥珀=进行中/等待 · 红=失败或会被拒 · 灰=尚未到达。 */
/* v0.7.40：从三档强度收敛成两步 —— 列数必须同步从 3 改 2，
   否则第三列空着、两张卡各占 1/3 宽、右边吊着一块空白。 */
body.uc .uc-tg-strip { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
@media (max-width: 820px) { body.uc .uc-tg-strip { grid-template-columns: 1fr; } }
body.uc .uc-tg-lvl {
  display: flex; flex-direction: column; gap: 4px;
  padding: 11px 13px; border-radius: var(--radius);
  border: 1px solid var(--line-soft); background: var(--q-sub);
}
body.uc .uc-tg-lvl.is-danger { border-color: rgba(var(--up-rgb), .32); background: rgba(var(--up-rgb), .05); }
body.uc .uc-tg-lvl-tag {
  font-size: 10.5px; font-weight: 800; letter-spacing: .5px;
  color: var(--q-dim); text-transform: uppercase;
}
body.uc .uc-tg-lvl b { font-size: 13.5px; color: var(--text); }
body.uc .uc-tg-lvl > span:last-child { font-size: 12.2px; line-height: 1.6; color: var(--text-3); }

body.uc .uc-tg-row { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; }
@media (max-width: 640px) { body.uc .uc-tg-row { grid-template-columns: 1fr; } }
body.uc .uc-tg-row .field { margin-bottom: 8px; min-width: 0; }
body.uc .uc-tg-row .field input { width: 100%; box-sizing: border-box; }

/* 方向切换：两个互斥按钮。卖出态用红（A 股「涨红」约定下，卖出动作沿用危险色更醒目）。 */
body.uc .uc-tg-dir {
  display: inline-flex; gap: 3px; padding: 3px;
  border-radius: var(--radius-sm); border: 1px solid var(--line-soft); background: var(--q-sub);
}
body.uc .uc-tg-dir button {
  appearance: none; -webkit-appearance: none; border: 0; cursor: pointer;
  padding: 6px 20px; border-radius: var(--radius-sm); font: inherit;
  font-size: 13px; font-weight: 700; color: var(--text-3); background: transparent;
}
body.uc .uc-tg-dir button:hover { background: var(--q-hover); }
body.uc .uc-tg-dir button.is-on { background: var(--accent); color: var(--on-accent); }
body.uc .uc-tg-dir button.is-on[data-dir="sell"] { background: var(--q-up-2); color: #fff; }

/* 回执区：流程条 + 结论 + 处理建议，三段合一 —— 用户只需要盯着一处看 */
body.uc .uc-tg-out {
  margin-top: 14px; padding: 12px 13px; border-radius: var(--radius);
  border: 1px solid var(--line-soft); background: var(--q-sub);
}
body.uc .uc-tg-steps { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
/* 步骤之间的连接箭头（v0.7.40）：四个孤立胶囊看不出「先后」，
   中间插一个 → 之后它才是一条**流程**而不是四个并列标签。由 tgSteps() 生成。 */
body.uc .uc-tg-sep { color: var(--q-dim); font-style: normal; font-size: 11px; line-height: 1; user-select: none; }
body.uc .uc-tg-step {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 10px; border-radius: 999px; font-size: 12px;
  border: 1px solid var(--line-soft); color: var(--text-3); background: transparent;
}
body.uc .uc-tg-step .d { width: 7px; height: 7px; border-radius: 50%; background: var(--q-line-4-h); flex: 0 0 auto; }
body.uc .uc-tg-step.is-ok { color: var(--down); border-color: rgba(var(--down-rgb), .38); }
body.uc .uc-tg-step.is-ok .d { background: var(--down); }
body.uc .uc-tg-step.is-wait { color: var(--warn); border-color: rgba(var(--q-amber-rgb), .42); }
body.uc .uc-tg-step.is-wait .d { background: var(--warn); }
body.uc .uc-tg-step.is-bad { color: var(--q-up-2); border-color: rgba(var(--up-rgb), .38); }
body.uc .uc-tg-step.is-bad .d { background: var(--up); }

body.uc .uc-tg-concl { margin-top: 10px; font-size: 13.5px; font-weight: 700; line-height: 1.6; color: var(--text-2); }
body.uc .uc-tg-concl.is-ok { color: var(--down); }
body.uc .uc-tg-concl.is-wait { color: var(--warn); }
body.uc .uc-tg-concl.is-bad { color: var(--q-up-2); }
/* 空态弱化：未触发时它只是一句操作指引，不该和「结论」一样重。 */
body.uc .uc-tg-concl.is-idle { font-weight: 400; color: var(--text-3); }
/* 原始回报（执行端回的统一 k=v 串）作为结论的**附属**呈现：
   左侧一道细竖线，比另起一行同色文字更容易看出从属关系；
   文字仍走灰色，不与结论争视觉权重。 */
body.uc .uc-tg-concl .st-detail {
  display: block; margin-top: 6px; padding-left: 9px;
  border-left: 2px solid var(--line-soft);
  font-weight: 400; font-size: 12.3px;
  color: var(--text-3); word-break: break-word;
}

body.uc .uc-tg-fix {
  margin-top: 10px; padding: 9px 12px; border-radius: var(--radius-sm);
  font-size: 12.4px; line-height: 1.65;
  border-left: 3px solid var(--warn);
  background: rgba(var(--q-amber-rgb), .08); color: var(--text-2);
}
body.uc .uc-tg-fix b { color: var(--text); }
body.uc .uc-tg-fix code {
  padding: 1px 5px; border-radius: var(--radius-sm); background: var(--q-hover);
  font-size: 11.6px;
}

/* ★ v0.7.41（圆总报「100% 缩放下测试模块无法完整显示，部分内容被截断」）
   ------------------------------------------------------------------
   病因在 .v6-dialog 的 `max-height: 90vh; overflow: auto`（见文件上方那条通用规则）。
   无头 Chrome 实测（_v0741_probe2.py）——**跑过一次失败回执**之后：

       视口 1525×680 → 弹层自然高 677px，被压到 612px，**底部 65px 被裁**
       视口 1280×604 → 弹层 544px，**被裁 133px**
       1525×680 下把「执行流程 / 结果怎么读 / 异常怎么处理」展开 → **被裁 828px**

   而 1525×680 正是 100% 缩放 + 1080p/125% 屏的常见可视区；被裁掉的恰好是
   结论下方的**处置建议**与折叠说明 —— 用户最需要的那一段。
   （不跑测试只开弹层时量到 543px，能放下 —— 所以「空态没问题」是个假象，
     真实使用一定带一份回执。）

   两条修法：
     ① 用满纵向空间：`90vh` 白扔 10%，换成 `calc(100vh - 36px)`（给遮罩留 18px×2）；
     ② 滚动的职责从「整个弹层」下移到「内容区」——头部的标题与关闭键固定，
        滚动条只出现在正文里。原来滚的是整个 .v6-dialog，标题会跟着滚走，
        看起来就像「整块被截断」。
   再配合下面那段矮窗口收紧，让常见尺寸下**不需要滚动**即可看全。 */
body.uc #test-dialog .v6-dialog {
  width: min(880px, 100%);
  max-height: calc(100vh - 36px);
  overflow: hidden;                 /* 滚动交给 .v6-dialog-body */
}
body.uc #test-dialog .v6-dialog-head { flex: 0 0 auto; padding: 13px 20px 10px; }
body.uc #test-dialog .v6-dialog-head h3 { font-size: 16.5px; margin: 0 0 2px; }
body.uc #test-dialog .v6-dialog-body {
  flex: 1 1 auto; min-height: 0;
  overflow-y: auto; overscroll-behavior: contain;
  padding: 2px 20px 13px;
}
/* 弹层内部收紧一点：这一步是为了让「失败回执 + 建议」也塞得进 680px 的可视高。
   只动 #test-dialog，不碰其它弹层。 */
body.uc #test-dialog .field { margin-bottom: 11px; }
body.uc #test-dialog .uc-tg-row .field { margin-bottom: 6px; }
body.uc #test-dialog .uc-tg-out { margin-top: 10px; }
/* 窗口一矮（100% 缩放的笔记本就是这个区间），头部那句副标题先让位给结论区 ——
   它只是「怎么用」的引导，而下面那段是「刚才发生了什么」。 */
@media (max-height: 780px) {
  body.uc #test-dialog .v6-dialog-head p { display: none; }
}

/* 结果区在窄屏下按钮要能换行（三个动作并排会挤） */
@media (max-width: 560px) { body.uc .v6-dialog .uc-btn-row { flex-direction: column; align-items: stretch; } }

/* ============================ 空状态 ============================ */
body.uc .uc-empty { padding: 36px 20px; text-align: center; color: var(--text-3); }
body.uc .uc-empty h3 { font-size: 15px; font-weight: 800; margin: 0 0 6px; color: var(--text-2); }
body.uc .uc-empty p { margin: 0 0 14px; font-size: 13px; }

/* ============================ 时间线（补两个变体） ============================ */
body.uc .uc-tl .it.is-ok::before { border-color: var(--down); }
body.uc .uc-tl .it.is-mute::before { border-color: var(--q-line-4-h); }
body.uc .uc-tl .it.is-warn::before { border-color: var(--warn); }
body.uc .uc-tl .it.is-bad::before { border-color: var(--up); }
body.uc .uc-tl .it .tt { font-size: 11.5px; color: var(--q-dim); }
body.uc .uc-tl .it .cc { font-size: 13.5px; color: var(--text-2); margin-top: 2px; }

/* ============================ 环形进度（补文字色） ============================ */
body.uc .uc-ring .rt .big { font-weight: 800; color: var(--text); font-variant-numeric: tabular-nums; }
body.uc .uc-ringtext-big { fill: var(--text); }
body.uc .uc-ringtext-cap { fill: var(--text-3); }
/* 设计稿「服务有效期」是环形 + 右侧两行说明，比默认的 18px 间距更紧凑 */
body.uc .uc-ring.is-tight { gap: 14px; }

/* ============================ v7.1 工作台补件 ============================ */

/* 「权益与到期」那种「左标题 + 右（标签/日期/进度条）」的宽版 kv */
body.uc .uc-kv.is-wide { grid-template-columns: 150px minmax(0, 1fr); align-items: center; }
body.uc .uc-kv.is-wide dt { color: var(--text-2); font-weight: 700; }
body.uc .uc-kv.is-wide dd .uc-bar { margin-top: 8px; }

/* KPI 里的「运行中通道」不分走势线，改用一条分段状态条：
   走势线需要历史数据，而通道数是**快照**，硬凑一条假曲线不如如实画状态。
   每段一段颜色代表一条通道，宽度等分。 */
body.uc .uc-seg { display: flex; gap: 3px; margin-top: 9px; }
body.uc .uc-seg > i {
  flex: 1; height: 4px; border-radius: 99px; background: var(--q-track);
}
body.uc .uc-seg > i.is-on { background: var(--down); }
body.uc .uc-seg > i.is-paused { background: var(--warn); }
body.uc .uc-seg > i.is-off { background: var(--q-line-4-h); }

/* 卡头右侧的「小字 + 链接」组合（如「清空」「全部通道」） */
body.uc .uc-card-hd .hd-r { display: flex; align-items: center; gap: 10px; }

/* KPI 迷你走势线的色调（设计稿 .spk-* 一系）。 */
body.uc .uc-kpi .uc-spark .spk-accent { stroke: var(--accent); }
body.uc .uc-kpi .uc-spark .spk-blue { stroke: var(--q-blue); }
body.uc .uc-kpi .uc-spark .spk-down { stroke: var(--down); }
body.uc .uc-kpi .uc-spark .spk-amber { stroke: var(--warn); }
body.uc .uc-kpi .uc-spark .spk-dim { stroke: var(--q-line-4-h); }

/* ============================ v7.2 列表页补件 ============================ */

/* 分页。与 .v6-pager 的区别只在配色：旧的写死 --v6-orange，
   用户中心要跟随 --accent。两套并存，公开页（知识库）继续用旧的。 */
body.uc .uc-pager {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap; margin-top: 12px;
  font-size: 12.5px; color: var(--q-dim);
}
body.uc .uc-pager .pages { display: flex; gap: 5px; align-items: center; flex-wrap: wrap; }
body.uc .uc-pager .pages a, body.uc .uc-pager .pages span {
  min-width: 32px; height: 32px; padding: 0 9px; border-radius: var(--radius-sm);
  border: 1px solid var(--q-line-4); background: var(--q-sub2); color: var(--text-2);
  display: inline-flex; align-items: center; justify-content: center;
  transition: border-color .15s, color .15s;
}
body.uc .uc-pager .pages a:hover {
  border-color: var(--accent); color: var(--accent-ink); text-decoration: none;
}
body.uc .uc-pager .pages .cur {
  background: var(--accent); border-color: var(--accent);
  color: var(--on-accent); font-weight: 700;
}
body.uc .uc-pager .pages .off { opacity: .42; }

/* 计数胶囊的「当前项」态（订单状态筛选那一组） */
body.uc .uc-chip.is-on {
  border-color: rgba(var(--accent-rgb), .5);
  background: rgba(var(--accent-rgb), .1); color: var(--accent-ink);
}

/* 兑换预览的键值行。这行 HTML 是 JS 拼出来的 —— 类名必须自带布局，
   靠不了父选择器的结构，所以给它一套独立的 .uc-q。 */
body.uc .uc-q {
  display: flex; justify-content: space-between; gap: 14px;
  padding: 9px 0; border-bottom: 1px solid var(--q-row-line); font-size: 13.5px;
}
body.uc .uc-q:last-child { border-bottom: 0; }
body.uc .uc-q span { color: var(--text-3); }
body.uc .uc-q strong { color: var(--text); font-weight: 700; }

/* AJAX 结果提示（兑换码预览 / 核销） */
body.uc .uc-inline-msg { margin: 12px 0 0; font-size: 13px; color: var(--q-dim); }
body.uc .uc-inline-msg.is-error { color: var(--q-up-2); }

/* 流程步骤条（充值流程）。
   刻意不叫 .steps：app.css 的历史命名里 .s/.n 这类单字母类太容易被别处撞上，
   uc- 前缀 + 复合选择器是唯一安全的写法。 */
body.uc .uc-steps {
  display: grid; grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 10px; margin-top: 4px;
}
body.uc .uc-steps .s {
  position: relative; padding: 11px 7px 10px; text-align: center;
  border: 1px solid var(--q-line-4); border-radius: var(--radius);
  background: var(--q-sub); font-size: 12px; color: var(--text-3);
}
body.uc .uc-steps .s .n {
  display: grid; place-items: center; width: 21px; height: 21px; margin: 0 auto 7px;
  border-radius: 50%; font-size: 11.5px; font-weight: 800;
  background: rgba(var(--accent-rgb), .12); color: var(--accent-ink);
}
body.uc .uc-steps .s.is-last {
  border-color: var(--q-nav-on-bd);
  background: rgba(var(--accent-rgb), .05); color: var(--text-2);
}
@media (max-width: 900px) { body.uc .uc-steps { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 560px) { body.uc .uc-steps { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* 卡内小节标题 + 卡内分隔线。
   设计稿的每张卡只有一节内容，所以它没有这组类 —— 这里是为「选择档位」
   （充值积分页）补的：那一张卡把原来两张卡（档位套餐 + 在线支付）并成了
   一节，**必须**有条分隔，否则「档位价」和「费率价」两套口径连成一片，
   用户会以为能按档位价直接付款。
   .uc-sub 刻意不做成 .uc-card-hd 的样子：那是卡头的层级，卡内再用一次
   会出现「卡里套卡」的错觉，而且 uc-card-hd 自带 18px 左右内边距，
   会让小节标题跟卡头对不齐。 */
body.uc .uc-sub {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; flex-wrap: wrap;
  font-size: 13px; font-weight: 800; color: var(--text);
}
body.uc .uc-hr { height: 1px; margin: 18px 0 16px; background: var(--line-soft); }

/* 空态。站点原有的 .empty 是给旧版卡片用的（居中大图标），
   这里的空态要嵌在 .uc-card-bd 里，尺寸得收一档。 */
body.uc .uc-empty { padding: 18px 4px; text-align: center; }
body.uc .uc-empty .et { font-size: 14px; font-weight: 700; color: var(--text-2); }
body.uc .uc-empty .es { margin-top: 5px; font-size: 12.5px; color: var(--q-dim); }

/* 竖向卡片栈（右栏、"rows" 语义）。
   .uc-card + .uc-card 已经能盖住纯卡片串，这里再兜一层是为了
   「卡片之间夹了个 note / 分页条」的情况 —— 那种时候相邻选择器会失效。 */
body.uc .uc-rows > * + * { margin-top: 14px; }

/* 通道内的「接收范围」补充行：设计稿的 .chan 只有两行 meta，
   这里第三行要跟 meta 同字号但颜色更淡，避免抢主地址的注意力。 */
body.uc .uc-chan .meta.is-soft { color: var(--q-dim); }

/* 订阅矩阵表（推送设置）。
   通用 .uc-tbl 允许换行 —— 那对「订单号 + 说明」这种表是对的，但矩阵表
   是**交叉表**：行名一换行，整行的勾就跟列头对不上了，一眼看不出是哪一格。
   所以矩阵表强制单行 + 横向滚动（外层已有 .uc-tbl-wrap 的 overflow-x）。
   第一列给个下限宽度，避免长策略名把标签列压成一条。 */
body.uc .uc-tbl.is-matrix th, body.uc .uc-tbl.is-matrix td { white-space: nowrap; }
body.uc .uc-tbl.is-matrix th:first-child, body.uc .uc-tbl.is-matrix td:first-child {
  min-width: 132px; text-align: left;
}
body.uc .uc-tbl.is-matrix td { vertical-align: middle; }

/* =====================================================================
   弹层（续费 / 新建通道 / 删除通道）
   ---------------------------------------------------------------------
   ⚠️ 这里只**覆写样式**，不新造一套 `.uc-dialog-*` 去替换 `.v6-dialog-overlay`
   / `.v6-dialog` 这些结构类。理由：
     ① 结构类同时被 channels.html 与 channel_detail.html 的 JS 引用
        （openDlg/closeDlg 按 id 取元素、`body.v6-dialog-open` 锁滚动），
        改名等于同时改两个模板的脚本，风险远大于收益；
     ② 弹层是覆盖层，视觉上只需要「底色、边框、圆角、阴影」跟主题走，
        不值得为它复制一遍定位/动画。
   所以：结构态用 v6 的，配色与按钮回到 uc 体系。
   ===================================================================== */
body.uc .v6-dialog-overlay { background: rgba(12, 15, 22, .46); }
body.uc .v6-dialog {
  border: 1px solid var(--q-line-4); border-radius: var(--uc-radius);
  background: var(--q-panel-a); box-shadow: var(--q-shadow);
}
body.uc .v6-dialog-head { border-bottom: 1px solid var(--line-soft); }
body.uc .v6-dialog-head h3 { color: var(--text); }
body.uc .v6-dialog-head p { color: var(--text-3); }
body.uc .v6-dialog-foot { border-top: 1px solid var(--line-soft); }
body.uc .v6-dialog-close { color: var(--text-3); }
body.uc .v6-dialog-close:hover { background: var(--q-hover); color: var(--accent-ink); }

/* 上面的覆写只管到「外壳」（遮罩 / 面板 / 头 / 脚 / 关闭键）。弹层**内部**还有
   一组内件，跟外壳一样必须处理 —— 典型例子是 base.html 的全局「QMT 跟单包
   下载前确认」（`#global-dl-confirm`）：它挂在所有页面共用的 base.html 上，
   用户中心里点「下载跟单包」就会弹出来，里面的 kicker / 勾选列表 / 提示条 /
   按钮全是 v6 体系。不改的话，用户中心里会突然冒出一个「按钮圆角、字号、
   提示条底色都跟隔壁不一样」的弹层。

   ⚠️ 依然只能**覆写、不能改名**（同上一段的理由，但更硬）：
   `.v6-btn / .v6-notice / .v6-kicker` 不止这一处在用 —— 公开页的
   kb / kb_article / help_qmt_install / download_test_client / forum* 与后台的
   orders / settings / forum 都在用。把 base.html 的 markup 换成 `.uc-btn`
   的话，这些页面拿到的是一组**只在 `body.uc` 下才有定义**的类，
   结果是公开页按钮全部掉回浏览器默认样式 —— 而改造范围明确是「只改用户中心」。
   所以选择器锁死在 `body.uc .v6-dialog` 里：改的只是用户中心这一侧。
   （特异性 0,3,1 已高过 `.v6-btn.is-primary` 这类 0,2,0 的旧规则，无需 !important） */
body.uc .v6-dialog .v6-kicker {
  font-size: 10.5px; letter-spacing: .18em; font-weight: 900;
  color: var(--brand); margin-bottom: 7px;
}
body.uc .v6-dialog .v6-check-list { display: grid; gap: 8px; }
body.uc .v6-dialog .v6-check-list label {
  display: flex; gap: 10px; align-items: flex-start; margin: 0;
  font-size: 13px; color: var(--text-2);
}
body.uc .v6-dialog .v6-check-list input {
  margin-top: 2px; flex: none; accent-color: var(--accent);
}
body.uc .v6-dialog .v6-notice {
  display: flex; gap: 10px; padding: 12px 14px; border-radius: var(--radius);
  font-size: 12.8px; line-height: 1.65;
  border: 1px solid var(--q-line-4); background: var(--q-sub); color: var(--text-2);
}
body.uc .v6-dialog .v6-notice.is-warn {
  border-color: rgba(var(--q-amber-rgb), .34);
  background: rgba(var(--q-amber-rgb), .08); color: var(--q-amber-soft);
}
body.uc .v6-dialog .v6-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  padding: 9px 15px; border-radius: var(--radius-sm);
  border: 1px solid var(--q-line-4); background: var(--q-sub2);
  color: var(--text-2); font: inherit; font-size: 13px; font-weight: 600;
  cursor: pointer; transition: .15s;
}
body.uc .v6-dialog .v6-btn:hover {
  border-color: var(--q-line-4-h); background: var(--q-hover);
  color: var(--text); text-decoration: none;
}
body.uc .v6-dialog .v6-btn.is-primary {
  background: linear-gradient(135deg, var(--grad-a), var(--grad-b));
  border-color: transparent; color: var(--on-accent);
  box-shadow: 0 8px 22px rgba(var(--accent-rgb), .26);
}
body.uc .v6-dialog .v6-btn.is-primary:hover { filter: brightness(1.07); color: var(--on-accent); }
body.uc .v6-dialog .v6-btn.is-ghost { background: transparent; }
body.uc .v6-dialog .v6-btn.is-sm { padding: 6px 11px; font-size: 12px; border-radius: var(--radius-sm); }
body.uc .v6-dialog .v6-btn[disabled] { opacity: .4; cursor: not-allowed; }

/* 代码块 / 令牌块（通道工作台的「聚宽接入代码」弹层）。
   `.v6-code` 的底色是 `--v6-navy`，而这个令牌在**暗色模式下是 #0a1220**，
   跟暗色页面底 #0e1626 几乎一模一样 —— 两个深蓝叠在一起，代码块会跟页面
   糊成一片、只剩文字浮在半空（这正是 --q-code-bg 这组令牌单独存在的理由，
   见文件上方它的注释）。这里把用户中心里的这两块换成设计系统的代码底色，
   顺带把换主题时的边框 / 圆角一并对齐。
   markup 依旧不动：`.v6-code` 还被公开页 help_qmt_install.html 用着。
   只覆写「底 / 字 / 边 / 圆角」，padding 与字号沿用原规则，避免两处维护。 */
body.uc .v6-code {
  background: var(--q-code-bg); color: var(--q-code-fg);
  border: 1px solid var(--line-soft); border-radius: var(--radius);
}
body.uc .v6-token {
  background: var(--q-sub); border: 1px dashed var(--q-line-4);
  color: var(--text-2); border-radius: var(--radius-sm);
}

/* 周期档位（续费弹层）。对应设计稿 `.pk` 的小尺寸版本：
   这里只需要「选中/未选中」两态，所以不做 .uc-pk 那套价格大字号。 */
body.uc .uc-plan-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(118px, 1fr)); gap: 9px;
}
body.uc .uc-plan {
  position: relative; text-align: left; padding: 11px 12px; cursor: pointer;
  font: inherit; color: var(--text-2);
  border: 1px solid var(--q-line-4); border-radius: var(--radius); background: var(--q-sub);
  transition: .15s;
}
body.uc .uc-plan:hover { border-color: var(--q-line-4-h); }
body.uc .uc-plan.is-on {
  border-color: var(--accent); background: rgba(var(--accent-rgb), .08);
  box-shadow: 0 0 0 1px rgba(var(--accent-rgb), .12);
}
body.uc .uc-plan strong { display: block; font-size: 14px; color: var(--text); }
body.uc .uc-plan small { display: block; font-size: 11.5px; color: var(--q-dim); margin-top: 2px; }
body.uc .uc-plan .rib {
  position: absolute; top: -8px; right: 9px; font-size: 10px; font-weight: 800;
  padding: 1px 6px; border-radius: 99px; background: var(--accent); color: var(--on-accent);
}

/* 打勾清单（弹层里的「包含什么」）。
   同时支持 li 和 .f 两种子元素：新写的用 <ul><li>，工作台那处是
   历史留下的 <div class="f">，为它改标记不值当，让样式两种都认更省事。 */
body.uc .uc-feats { display: grid; gap: 7px; margin: 12px 0 0; padding: 0; list-style: none; }
body.uc .uc-feats li, body.uc .uc-feats > .f {
  display: flex; gap: 8px; font-size: 13px; color: var(--text-2);
}
body.uc .uc-feats li::before, body.uc .uc-feats > .f::before {
  content: "✓"; flex: none; font-weight: 800; color: var(--down);
}

/* 危险态提示条。uc-note 原本只有 info / warn / ok，
   删除确认这类不可逆操作需要一条明确的红色。 */
body.uc .uc-note.is-danger {
  border-color: rgba(var(--up-rgb), .38); background: rgba(var(--up-rgb), .08);
  color: var(--q-up-2);
}

/* 自适应卡片阵（通道卡）。不用 .uc-g3 是因为它是**固定 3 列**：
   只有 1 个通道时会留下两列空白，看起来像加载失败。
   auto-fill 让 1 张卡占满、4 张卡自动折行。 */
body.uc .uc-cards {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(292px, 1fr)); gap: 14px;
}
body.uc .uc-cards .uc-card + .uc-card { margin-top: 0; }
@media (max-width: 640px) { body.uc .uc-cards { grid-template-columns: 1fr; } }

/* ==================== v0.7.36 卡片阵（v0.7.53 限宽 / v0.7.54 三列）=============
   购买套餐页（/me/subscribe）v0.7.53 起摆**三类**套餐：跟单工具 / 策略源码 /
   官方策略信号；v0.7.54 起三类各一张卡、**并排三列**（.is-triple）。

   为什么从 grid 换成 flex：
     v0.7.36 用的是 auto-fit + minmax(232px, 1fr)，四档时刚好一行 —— 但
     **只剩一张卡**时（2026-10-02 圆总截图：跟单工具就一张聚合卡），
     1fr 会把它拉满整宽，配 8 行功能点，看着又大又空。
     v0.7.53 改成 flex + max-width 封顶 360px：单张卡就是一张正常尺寸的卡，
     多张从 280px 起步自动折行，一行大约 3~4 张，窄屏自动掉成一列。
     v0.7.54 的 .is-triple 把上限放宽到 400px，让三张卡把整行 1:1:1 填满
     （约 380px/张）—— 三张卡等高、等宽、底注对齐，就是圆总要的「并排三卡」。 */
body.uc .uc-plancards {
  display: flex; flex-wrap: wrap; align-items: stretch; gap: 14px;
}
body.uc .uc-plancard {
  flex: 1 1 280px; max-width: 360px; min-width: 240px;
  display: flex; flex-direction: column;
  border: 1px solid var(--line-soft); border-radius: var(--uc-radius);
  background: linear-gradient(180deg, var(--q-panel-a), var(--q-panel-b));
  box-shadow: var(--q-shadow-sm);
  padding: 14px 14px 12px;
  position: relative;
}
/* v0.7.54：三列版。flex-basis 300 + 上限 400 ⇒ 宽屏下三张各约 380px 填满整行；
   窄屏按 300 起步收缩，低于 260 才折行 —— 保证「并排」一直成立。 */
body.uc .uc-plancards.is-triple .uc-plancard {
  flex: 1 1 300px; max-width: 400px; min-width: 260px;
}
/* 推荐档 / 当前档：**只靠左边框与角标**区分，不整块换底色 ——
   整块高亮会让四张卡看起来不是同一类商品，而是「两个不同的东西」。 */
body.uc .uc-plancard.is-rec { border-color: rgba(var(--brand-rgb), .42); }
body.uc .uc-plancard.is-cur {
  border-color: rgba(var(--brand-rgb), .55);
  box-shadow: 0 0 0 1px rgba(var(--brand-rgb), .18), var(--q-shadow-sm);
}
body.uc .uc-plancard .pc-top {
  display: flex; align-items: center; gap: 8px; min-height: 20px;
}
body.uc .uc-plancard .pc-period {
  margin: 0;
  font-size: 13.5px; font-weight: 800; color: var(--text); letter-spacing: -.2px;
}
body.uc .uc-plancard .pc-price {
  display: flex; align-items: baseline; gap: 5px; margin: 8px 0 3px;
}
body.uc .uc-plancard .pc-price b {
  font-size: 23px; font-weight: 800; letter-spacing: -.6px;
  color: var(--brand-ink); line-height: 1.05;
}
body.uc .uc-plancard .pc-price span { font-size: 12.5px; color: var(--text-3); }
body.uc .uc-plancard .pc-sub { font-size: 12.5px; color: var(--text-3); }
/* v0.7.54 卡片文案两件套：lead 在档位表上方（一句「是什么」），
   note 放进 .pc-foot（margin-top:auto）钉在卡底（一句「注意什么」）——
   三张卡的字数不同，但底注因此对齐在同一条水平线上。 */
body.uc .uc-plancard .pc-lead {
  margin: 6px 0 0; font-size: 12px; color: var(--text-3); line-height: 1.6;
}
body.uc .uc-plancard .pc-note {
  margin: 0; font-size: 11.5px; color: var(--text-3); line-height: 1.6;
}
body.uc .uc-plancard .pc-feats { margin-top: 10px; font-size: 12.5px; }
/* 卡脚钉在底部：四张卡特性条数不同时按钮要对齐在同一水平线上，
   否则一行里四个按钮高低错落，看着像布局坏了。 */
body.uc .uc-plancard .pc-foot { margin-top: auto; padding-top: 12px; }
body.uc .uc-plancard .pc-foot .uc-btn { width: 100%; justify-content: center; }

/* v0.7.51 多周期聚合：卡内周期切换（一张商品卡，切换 7 天/月度/年度/永久） */
body.uc .uc-plancard .pc-periods {
  display: flex; flex-wrap: wrap; gap: 6px; margin: 12px 0 0;
}
body.uc .uc-plancard .pc-period-btn {
  padding: 4px 11px; font-size: 12px; line-height: 1.5;
  border: 1px solid var(--line-soft); border-radius: var(--radius-sm);
  background: var(--surface-2); color: var(--text-2); cursor: pointer;
  transition: color .15s, border-color .15s, background .15s;
}
body.uc .uc-plancard .pc-period-btn:hover { border-color: var(--brand-2); color: var(--brand); }
body.uc .uc-plancard .pc-period-btn.is-on {
  border-color: var(--brand); color: var(--brand); background: var(--brand-soft);
  font-weight: 600;
}

/* ==================== v0.7.54 购买套餐页：一档一行的档位表 ====================
   三张卡共用同一种「一行一档」：左边档位名 + 一行小字，右边价格 + 按钮。
   行容器统一是 .pc-row，两种形态：
     · 能直接下单的档 → <form class="pc-row">（POST 到各自原有的端点）
     · 只能进详情页选的档 → <div class="pc-row">（右侧换成 <a> 按钮）
   两种吃同一条规则，所以三张卡的行**长得一模一样**，不会一张是表单按钮、
   另一张是纯文字 —— 圆总 2026-10-03 的「统一卡片格式与样式」。

   v0.7.53 的 .uc-sec / .uc-sec-hd（三段纵向分节头）与 .pc-metrics（回测指标行）
   在这版一并删掉：三列并排之后不再有「段」，指标行属于策略详情页，不属于货架。 */
body.uc .uc-plancard .pc-plans {
  list-style: none; margin: 10px 0 0; padding: 0; display: grid; gap: 6px;
}
/* 后台若把跟单工具拆成多组商品，组名占一行小标题（单组时不渲染）。 */
body.uc .uc-plancard .pc-grp {
  font-size: 11.5px; font-weight: 700; color: var(--text-3);
  letter-spacing: .04em; margin-top: 2px;
}
body.uc .uc-plancard .pc-row {
  display: flex; align-items: center; gap: 8px;
  padding: 5px 8px; border: 1px solid var(--line-soft);
  border-radius: var(--radius-sm); background: var(--surface-2);
}
body.uc .uc-plancard .pc-row .pn {
  flex: 1 1 auto; min-width: 0;
  display: flex; flex-direction: column; gap: 1px;
  font-size: 12.5px; color: var(--text-2);
}
body.uc .uc-plancard .pc-row .pn a {
  color: var(--text); font-weight: 600;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
body.uc .uc-plancard .pc-row .pn a:hover { color: var(--brand); }
body.uc .uc-plancard .pc-row .pn i { font-style: normal; font-size: 11.5px; }
body.uc .uc-plancard .pc-row .pp {
  font-size: 13px; font-weight: 700; color: var(--brand-ink); white-space: nowrap;
}
body.uc .uc-plancard .pc-row .uc-btn { flex: none; }

/* ==================== v0.7.36 策略订阅两段式 ====================
   /official 是双态页（游客/登录共用同一张模板），用的是公开页那套
   .card / .grid-2 类，所以这两条**不能**加 body.uc 前缀 —— 
   加了游客态就完全失效，而游客态恰恰是这一页的第一屏。 */
.st-sec + .st-sec { margin-top: 30px; }
.st-hd { margin-bottom: 14px; }
.st-hd h2 {
  font-size: 17px; font-weight: 800; letter-spacing: -.2px;
  color: var(--text); margin: 0 0 5px;
}
body.uc .st-hd h2 { font-size: 16px; }
.st-hd p { margin: 0; font-size: 13px; color: var(--text-3); line-height: 1.65; }

/* ==================== v0.7.52 P3-3 公开页套餐卡 ====================
   首页 PRICING 段 与 /pricing 定价页共用 partials/public_plan_cards.html。
   数据来自 public_plan_cards()（plan_groups 聚合），一「商品」一张卡，
   卡内切周期。单商品时居中、多商品自动并排。不带 body.uc 前缀 ——
   这是公开页（base.html 外壳），游客态正是第一屏。 */
.pricing-cards { display: flex; justify-content: center; flex-wrap: wrap; gap: 16px; }
.pcard {
  flex: 1 1 300px; max-width: 360px; min-width: 260px;
  background: var(--surface);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  padding: 22px 22px 20px;
  box-shadow: var(--shadow);
  display: flex; flex-direction: column;
  position: relative;
}
.pcard.is-rec { border-color: rgba(var(--brand-rgb), .42); }
.pcard .pc-top { display: flex; align-items: center; gap: 8px; min-height: 22px; }
.pcard .pc-name { font-size: 15px; font-weight: 800; color: var(--text); letter-spacing: -.2px; }
.pcard .pc-price { display: flex; align-items: baseline; gap: 5px; margin: 12px 0 4px; }
.pcard .pc-price b {
  font-size: 30px; font-weight: 800; letter-spacing: -.6px;
  color: var(--brand-ink); line-height: 1.05;
}
.pcard .pc-price span { font-size: 13px; color: var(--text-3); }
.pcard .pc-sub { font-size: 12.5px; color: var(--text-3); }
.pcard .pc-feats {
  list-style: none; margin: 14px 0 0; padding: 0;
  font-size: 13px; color: var(--text-2); display: grid; gap: 7px;
}
.pcard .pc-feats li { display: flex; gap: 8px; }
.pcard .pc-feats li::before { content: "✓"; color: var(--ok); flex: none; }
.pcard .pc-foot { margin-top: auto; padding-top: 18px; }
.pcard .pc-foot .btn { width: 100%; justify-content: center; }
.pcard .pc-periods { display: flex; flex-wrap: wrap; gap: 6px; margin: 14px 0 0; }
.pcard .pc-period-btn {
  padding: 4px 11px; font-size: 12px; line-height: 1.5;
  border: 1px solid var(--line-soft); border-radius: var(--radius-sm);
  background: var(--surface-2); color: var(--text-2); cursor: pointer;
  transition: color .15s, border-color .15s, background .15s;
}
.pcard .pc-period-btn:hover { border-color: var(--brand-2); color: var(--brand); }
.pcard .pc-period-btn.is-on {
  border-color: var(--brand); color: var(--brand); background: var(--brand-soft);
  font-weight: 600;
}

/* ==================== v0.7.52 P3-3 官网策略卡指标行 ====================
   /official 是双态页（游客/登录共用），同样**不能**加 body.uc 前缀。 */
.st-card { display: flex; flex-direction: column; }
.st-card-hd { display: flex; justify-content: space-between; gap: 10px; align-items: flex-start; }
.st-name { font-size: 18px; margin: 0 0 4px; }
.st-metrics {
  display: flex; gap: 18px; flex-wrap: wrap;
  margin: 12px 0 0; padding: 12px 14px;
  background: var(--surface-2); border: 1px solid var(--line-soft);
  border-radius: var(--radius-sm);
}
.st-metric { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.st-metric b { font-size: 17px; font-weight: 800; color: var(--text); letter-spacing: -.2px; }
.st-metric b.st-text { font-size: 13px; font-weight: 600; line-height: 1.5; }
.st-metric span { font-size: 11.5px; color: var(--text-3); }
.st-metrics.is-text { display: block; }
.st-edition {
  font-size: 12px; color: var(--text-2);
  background: var(--surface-2); border: 1px solid var(--line-soft);
  border-radius: 999px; padding: 4px 11px;
}
.st-edition:first-child { color: var(--brand-ink); background: var(--brand-soft); border-color: rgba(var(--brand-rgb), .3); }

/* ==================== 管理后台外壳（v0.7.47 P1） ====================
   body.adm 前缀，与用户中心 body.uc、公开页完全隔离。
   复用全局 --q-* 令牌（:root / html[data-mode=dark] 已定义），
   主题色直接引用 --brand* 系列 —— 不依赖 body.uc 里的 --accent 别名。
   内容区刻意**不套** .container（max-width:1120px）：后台是工作台型
   版面，吃满屏幕比居中更省眼；左右留白用 clamp 随视口缓增。 */
body.adm { --adm-side-w: 224px; }

body.adm .adm-shell {
  display: grid; grid-template-columns: var(--adm-side-w) minmax(0, 1fr);
  align-items: start; min-height: 100vh;
}
body.adm .adm-side {
  position: sticky; top: 0; z-index: 30;
  height: 100vh; overflow: hidden;
  display: flex; flex-direction: column;
  background: linear-gradient(180deg, var(--q-side-a), var(--q-side-b));
  border-right: 1px solid var(--line-soft);
  box-shadow: var(--q-side-shadow);
}
body.adm .adm-col { min-width: 0; display: flex; flex-direction: column; min-height: 100vh; }

body.adm .adm-brand {
  display: flex; align-items: center; gap: 10px;
  padding: 14px 16px; border-bottom: 1px solid var(--line-soft);
}
body.adm .adm-brand:hover { text-decoration: none; }
body.adm .adm-brand .lg {
  width: 32px; height: 32px; flex: 0 0 32px; border-radius: var(--radius-sm);
  overflow: hidden; box-shadow: 0 6px 16px rgba(var(--brand-rgb), .3);
}
body.adm .adm-brand .lg img { display: block; width: 32px; height: 32px; object-fit: cover; }
body.adm .adm-brand .tx { min-width: 0; }
body.adm .adm-brand .tx b { display: block; color: var(--text); font-size: 14.5px; line-height: 1.3; }
body.adm .adm-brand .tx span { font-size: 10px; color: var(--q-dim); letter-spacing: .1em; }

body.adm .adm-nav { flex: 1; overflow-y: auto; overflow-x: hidden; padding: 6px 10px 12px; }
body.adm .adm-nav::-webkit-scrollbar { width: 5px; }
body.adm .adm-nav::-webkit-scrollbar-thumb { background: var(--q-line-4); border-radius: 99px; }
body.adm .adm-grp {
  font-size: 10px; letter-spacing: .15em; font-weight: 800;
  color: var(--q-dim-2); padding: 15px 11px 6px;
}
body.adm .adm-navi {
  position: relative; display: flex; align-items: center; gap: 10px;
  padding: 8px 11px; border-radius: var(--radius-sm);
  font-size: 13.5px; color: var(--q-ink-soft); white-space: nowrap;
  border: 1px solid transparent;
  transition: background .16s, color .16s, border-color .16s;
}
body.adm .adm-navi:hover { background: var(--q-hover); color: var(--q-ink-hover); text-decoration: none; }
body.adm .adm-navi.is-on {
  background: linear-gradient(90deg, rgba(var(--brand-rgb), .17), rgba(var(--brand-rgb), .03));
  color: var(--brand-ink); font-weight: 600;
  border-color: rgba(var(--brand-rgb), .34);
}
body.adm .adm-navi.is-on::before {
  content: ""; position: absolute; left: -10px; top: 8px; bottom: 8px; width: 3px;
  border-radius: 0 3px 3px 0; background: var(--brand);
  box-shadow: 0 0 12px rgba(var(--brand-rgb), .7);
}
body.adm .adm-navi svg { width: 16px; height: 16px; flex: 0 0 16px; opacity: .8; }
body.adm .adm-navi.is-on svg { opacity: 1; }

body.adm .adm-foot { padding: 12px 16px; border-top: 1px solid var(--line-soft); font-size: 11px; color: var(--q-dim); line-height: 1.7; }
body.adm .adm-foot b { color: var(--text-2); }
body.adm .adm-foot .mono { font-family: ui-monospace, Consolas, monospace; }

body.adm .adm-topbar {
  position: sticky; top: 0; z-index: 20;
  display: flex; align-items: center; gap: 14px;
  padding: 10px 26px; background: var(--q-topbar); backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line-soft);
  box-shadow: 0 1px 0 var(--line-soft), 0 6px 18px -14px rgba(16, 26, 44, .2);
}
body.adm .adm-topbar .tb-l, body.adm .adm-topbar .tb-r { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
body.adm .adm-topbar .tb-r { margin-left: auto; }
body.adm .adm-burger {
  cursor: pointer; font-family: inherit; font-size: 16px; line-height: 1;
  width: 32px; height: 32px; border-radius: var(--radius-sm);
  border: 1px solid var(--q-line-3); background: var(--q-sub); color: var(--q-ink-soft);
}
body.adm .adm-burger:hover { background: var(--q-hover); color: var(--text); }
body.adm .adm-crumb { font-size: 13px; color: var(--q-dim); }
body.adm .adm-crumb.is-cur { color: var(--text); font-weight: 600; }
body.adm .adm-crumb-sep { color: var(--q-line-4-h); }
body.adm .adm-chip {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 6px 11px; border-radius: var(--radius-sm);
  border: 1px solid var(--q-line-3); background: var(--q-sub);
  font-size: 12px; color: var(--q-ink-soft); text-decoration: none;
}
body.adm .adm-chip:hover { border-color: var(--q-line-4-h); background: var(--q-hover); color: var(--text); }
body.adm .adm-chip.is-btn { cursor: pointer; font-family: inherit; font-weight: 600; }
body.adm .adm-who b { display: block; font-size: 12.5px; color: var(--text); line-height: 1.25; }
body.adm .adm-who span { font-size: 10.5px; color: var(--q-dim); }

body.adm .adm-main {
  flex: 1 1 auto; width: 100%; min-width: 0;
  max-width: none; margin: 0;
  padding: 24px clamp(20px, 1.8vw, 40px) 40px;
}

/* 折叠态：只留图标（64px） */
body.adm.is-folded { --adm-side-w: 64px; }
body.adm.is-folded .adm-brand { justify-content: center; padding: 14px 8px; }
body.adm.is-folded .adm-brand .tx { display: none; }
body.adm.is-folded .adm-grp { display: none; }
body.adm.is-folded .adm-navi { justify-content: center; padding: 9px 8px; }
body.adm.is-folded .adm-navi > :not(svg) { display: none; }
body.adm.is-folded .adm-foot { display: none; }

/* 移动端：侧栏折成顶部横向胶囊条（与用户中心同思路） */
@media (max-width: 900px) {
  body.adm .adm-shell { grid-template-columns: 1fr; }
  body.adm .adm-side {
    position: static; height: auto; flex-direction: row; align-items: center;
    gap: 8px; padding: 8px 12px; overflow-x: auto;
    border-right: 0; border-bottom: 1px solid var(--line-soft);
  }
  body.adm .adm-brand { border-bottom: 0; padding: 0 8px 0 0; flex: 0 0 auto; }
  body.adm .adm-brand .tx, body.adm .adm-grp, body.adm .adm-foot { display: none; }
  body.adm .adm-nav { flex-direction: row; gap: 6px; flex: 0 0 auto; overflow: visible; padding: 0; }
  body.adm .adm-navi { white-space: nowrap; padding: 7px 12px; border-radius: 999px; }
  body.adm .adm-navi.is-on::before { display: none; }
  body.adm .adm-navi svg { display: none; }
  body.adm .adm-main { padding: 18px 16px 32px; }
  body.adm .adm-topbar { padding: 10px 16px; }
  body.adm .adm-burger { display: none; }
  body.adm .adm-who span { display: none; }
}

/* ==================== 仪表盘（v0.7.47 P1） ==================== */
body.adm .adm-quick { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 14px; margin-bottom: 18px; }
body.adm .adm-qk {
  display: flex; align-items: center; gap: 14px;
  padding: 16px 18px; border-radius: var(--radius);
  background: var(--surface); border: 1px solid var(--line-soft);
  text-decoration: none; transition: border-color .16s, transform .16s, box-shadow .16s;
}
body.adm .adm-qk:hover { border-color: var(--q-line-4-h); box-shadow: var(--v6-shadow); transform: translateY(-1px); }
body.adm .adm-qk .ic {
  width: 40px; height: 40px; flex: 0 0 40px; border-radius: var(--radius);
  display: grid; place-items: center;
  background: var(--brand-soft); color: var(--brand-ink);
  font-size: 19px; font-weight: 800;
}
body.adm .adm-qk .tx { min-width: 0; }
body.adm .adm-qk .tx b { display: block; font-size: 14px; color: var(--text); }
body.adm .adm-qk .tx i { display: block; font-style: normal; font-size: 12px; color: var(--text-3); margin-top: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
body.adm .adm-qk .arr { margin-left: auto; color: var(--q-dim); font-size: 18px; }

body.adm .adm-kpis { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; margin-bottom: 14px; }
body.adm .adm-kpi { display: block; padding: 18px 20px; border-radius: var(--radius); background: var(--surface); border: 1px solid var(--line-soft); text-decoration: none; }
body.adm .adm-kpi:hover { border-color: var(--q-line-4-h); }
body.adm .adm-kpi .k { font-size: 12.5px; color: var(--text-2); }
body.adm .adm-kpi .v { font-size: 32px; font-weight: 800; letter-spacing: -.6px; line-height: 1.15; margin-top: 4px; color: var(--text); font-variant-numeric: tabular-nums; }
body.adm .adm-kpi .v .unit { font-size: 15px; font-weight: 600; color: var(--text-3); margin-left: 4px; letter-spacing: 0; }

body.adm .adm-subkpis { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 14px; margin-bottom: 18px; }
body.adm .adm-subkpi { padding: 12px 16px; border-radius: var(--radius); background: var(--surface-2); border: 1px solid var(--line-soft); }
body.adm .adm-subkpi .k { font-size: 11.5px; color: var(--text-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
body.adm .adm-subkpi .v { font-size: 17px; font-weight: 700; margin-top: 3px; color: var(--text); font-variant-numeric: tabular-nums; }
body.adm .adm-subkpi .d { font-size: 11px; color: var(--text-3); margin-top: 2px; }

body.adm .adm-duo { display: grid; grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); gap: 14px; align-items: start; margin-bottom: 18px; }
body.adm .adm-trend, body.adm .adm-todo { background: var(--surface); border: 1px solid var(--line-soft); border-radius: var(--radius); padding: 18px 20px; }
body.adm .adm-trend .lg { display: flex; gap: 16px; font-size: 12px; color: var(--text-2); margin-bottom: 8px; }
body.adm .adm-trend .lg span { display: inline-flex; align-items: center; gap: 6px; }
body.adm .adm-trend .lg i { width: 10px; height: 10px; border-radius: 3px; display: inline-block; }
body.adm .adm-todo-item { display: flex; align-items: center; gap: 10px; padding: 9px 0; border-bottom: 1px solid var(--line-soft); }
body.adm .adm-todo-item:last-child { border-bottom: 0; }
body.adm .adm-todo-item .nm { font-size: 13px; color: var(--text-2); flex: 1; }
body.adm .adm-todo-item .n { font-size: 13px; font-weight: 700; text-decoration: none; font-variant-numeric: tabular-nums; }
body.adm .adm-todo-item .n.bad { color: var(--up); }
body.adm .adm-todo-item .n.ok { color: var(--down); }

@media (max-width: 1400px) { body.adm .adm-subkpis { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 1100px) { body.adm .adm-quick { grid-template-columns: repeat(2, minmax(0, 1fr)); } body.adm .adm-duo { grid-template-columns: 1fr; } }
@media (max-width: 640px) { body.adm .adm-kpis { grid-template-columns: 1fr; } body.adm .adm-subkpis { grid-template-columns: 1fr 1fr; } }

/* ===== 设置页顶部 Tab（v0.7.48 P2） ===== */
body.adm .adm-tabs { display: flex; gap: 2px; flex-wrap: wrap; margin: 0 0 16px; border-bottom: 1px solid var(--line-soft); }
body.adm .adm-tab { padding: 9px 16px; font-size: 13.5px; font-weight: 600; color: var(--text-2); border-bottom: 2px solid transparent; text-decoration: none; cursor: pointer; margin-bottom: -1px; }
body.adm .adm-tab:hover { color: var(--brand); }
body.adm .adm-tab.is-on { color: var(--brand); border-bottom-color: var(--brand); }

/* v0.7.60：执行端缩量标记（工作台「目标数量/仓位」列）。
   缩量不是错误 —— 它是跟单端按可用资金 / 可卖持仓做的正确风控；
   错的只是它过去不留痕迹。用 --warn 系而不是 danger 系，就是为了
   让人「看见并核对」，而不是「以为出错了来报障」。 */
.is-capped {
  margin-left: 6px; padding: 1px 6px; border-radius: 10px;
  font-size: 12px; font-weight: 600; white-space: nowrap;
  color: var(--warn); background: rgba(250, 170, 20, .12);
}
/* 信号卡标题旁的「今日 N 条 · M 条失败」 */
.signal-tally {
  margin-left: 8px; font-size: 12px; font-weight: 400;
  color: var(--v6-muted);
}
.signal-tally b { color: var(--danger); font-weight: 600; }

/* Report fixes: explicit hidden state must win over component display rules. */
[hidden] { display: none !important; }
.uc-mobile-menu, .cs-mobile-tools { display: none; }
body.v6-dialog-open .cs-float, body.v6-dialog-open .cs-dock,
body.v6-dialog-open .cs-mobile-tools { display: none; }
@media (max-width: 900px) {
  body.uc .uc-side { overflow: visible; justify-content: space-between; position: relative; z-index: 35; }
  body.uc .uc-mobile-menu { display: block; margin-left: auto; }
  .uc-mobile-menu summary, .cs-mobile-tools summary {
    cursor: pointer; padding: 10px 14px; border: 1px solid var(--line-soft);
    border-radius: 12px; color: var(--text); background: var(--bg, #fff);
    list-style: none;
  }
  .uc-mobile-menu summary::-webkit-details-marker, .cs-mobile-tools summary::-webkit-details-marker { display: none; }
  body.uc .uc-mobile-nav {
    position: absolute; right: 12px; top: 100%; width: min(280px, calc(100vw - 24px));
    max-height: 70vh; overflow: auto; padding: 10px; border-radius: 12px;
    background: var(--bg, #fff); border: 1px solid var(--line-soft); box-shadow: 0 8px 24px #0002;
  }
  body.uc .uc-mobile-nav .uc-nav { flex-direction: column; gap: 4px; }
  .cs-mobile-tools { display: block; position: relative; margin: 12px; width: max-content; z-index: 90; }
  body.uc .uc-side > .cs-mobile-tools { margin: 0; }
  body.uc .uc-side > .cs-mobile-tools .cs-mobile-panel { top: calc(100% + 8px); bottom: auto; }
  .cs-mobile-panel {
    position: absolute; right: 0; bottom: calc(100% + 8px); width: 110px;
    padding: 8px; border-radius: 12px; background: var(--bg, #fff);
    border: 1px solid var(--line-soft); box-shadow: 0 8px 24px #0002;
  }
  .cs-mobile-panel .cs-dock, .cs-mobile-panel .cs-float {
    position: static; display: flex; flex-direction: column; gap: 6px; transform: none; margin: 0;
  }
  .cs-mobile-panel .cs-dock { margin-bottom: 6px; }
  .cs-mobile-panel .cs-dock button, .cs-mobile-panel .cs-float a, .cs-mobile-panel .cs-float button { width: 100%; }
}
