/* ==========================================================================
   达播工作台 — pages.css
   数据看板 / 登录 / 回调
   ========================================================================== */

/* ============================ 数据看板 ============================ */

.dashboard-overview {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  flex-wrap: wrap;
  margin-top: var(--space-5);
  margin-bottom: var(--space-4);
}

.dashboard-overview__title {
  font-size: var(--font-size-2xl);
  font-weight: var(--font-weight-semibold);
  letter-spacing: var(--font-letter-spacing-display);
}

.dashboard-overview__date {
  margin-top: var(--space-1);
  font-size: var(--font-size-sm);
  color: var(--color-muted);
}

.kpi-row {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-4);
  margin-bottom: var(--space-6);
}

/* 3 张 KPI 卡（经营总览）：必须恒为 3 列，否则复用默认 4 列会让右侧空出一格
   （2026-09-12 乐哥反馈「右边留白」的根因即此）。
   ⚠️ 用 .kpi-row.kpi-row--three 双类提高权重：页面下方还有一组 `.kpi-row` 的媒体查询
      （1400px→4列 / 1100px→3列 / ≤1099px→2列），它们的权重相同但位置更靠后，
      只写单类会被它们翻掉（实测：单类写法下网格仍是 4 列、留白照旧）。
      双类写法与文件顺序无关，稳。 */
.kpi-row.kpi-row--three { grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (min-width: 1100px) and (max-width: 1399px) {
  .kpi-row.kpi-row--three { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 1099px) {
  .kpi-row.kpi-row--three { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 699px) {
  .kpi-row.kpi-row--three { grid-template-columns: minmax(0, 1fr); }
}

/* 经营总览三卡：作为页面结论，用更足的间距与下方明细拉开层级。
   （字号不用改：.kpi-card__value 本身已是 --font-size-3xl=30px。）
   预估态不再整卡套黄框（那会让重点指标看着像警告卡），见下方 .kpi-card--estimate 覆盖。 */
.kpi-row--overview { margin-bottom: var(--space-5); gap: var(--space-5); }
.kpi-row--overview .kpi-card { padding: var(--space-5) var(--space-5) var(--space-4); }

/* 5 张 KPI 卡（达人经营）：默认 4 列会变成 4+1、右侧空三格 —— 必须显式给 5 列；
   窄屏依次退到 3 / 2 / 1 列（与 --three 的断点保持同一套节奏）。
   ⚠️ 不复用 .kpi-row--six：那套规则的 nth-child 跨列是按「6 张 + 特定列数」推的，
      5 张套进去会在 1100~1399 区间留白（2026-09-13 复核其媒体查询时发现）。 */
.kpi-row.kpi-row--five { grid-template-columns: repeat(5, minmax(0, 1fr)); }
@media (max-width: 1399px) {
  .kpi-row.kpi-row--five { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 899px) {
  .kpi-row.kpi-row--five { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 599px) {
  .kpi-row.kpi-row--five { grid-template-columns: minmax(0, 1fr); }
}

/* 6 张 KPI 卡（经营看板）：宽屏下让「利润 / 利润率」各跨 2 列，把第二行铺满。
   不做的话 4+2 会在右侧留出两格空白（2026-09-11 扫图发现）。 */
.kpi-row--six > :nth-child(5),
.kpi-row--six > :nth-child(6) { grid-column: span 2; }

@media (min-width: 1100px) and (max-width: 1399px) {
  /* 3 列时：第 6 张跨 2 列，第二行 1 + 2 刚好铺满 */
  .kpi-row--six > :nth-child(5) { grid-column: span 1; }
  .kpi-row--six > :nth-child(6) { grid-column: span 2; }
}
@media (max-width: 1099px) {
  .kpi-row--six > :nth-child(5),
  .kpi-row--six > :nth-child(6) { grid-column: span 1; }
}

/* 经营看板 · 成本大类行内标记（「公共」等）。
   必须不可折行 —— 否则窄列下「公共」会被拆成「公 / 共」两行（2026-09-11 扫图发现）。 */
.an-tag {
  display: inline-block;
  white-space: nowrap;
  font-size: var(--font-size-xs);
  line-height: 18px;
  padding: 0 6px;
  margin-left: 4px;
  color: var(--color-muted);
  background: var(--color-surface-2);
  border: 1px solid var(--color-border-soft);
  border-radius: var(--radius-sm);
  vertical-align: 1px;
}

/* 「预估」标记（经营看板：T+35 口径下含未满 35 天订单时）——
   橙色 = 提示「这个数还会变」，与红色的错误态区分开。
   同时给整张 KPI 卡换橙色描边，扫一眼就知道这一屏不是最终结算数。
   ⚠️ 选择器必须写成 .kpi-card.kpi-card--estimate（双类）：
      .kpi-card 的单类定义在本文件**更后面**（第 79 行起），单类写法同优先级下会被它覆盖，
      描边看起来像没生效（实测踩过：算出 rgb(237,239,241) 默认灰）。 */
.an-tag--warn {
  color: var(--color-warning-text);
  background: var(--color-warning-bg);
  border-color: var(--color-warning);
}
.kpi-card.kpi-card--estimate,
.kpi-card.kpi-card--estimate:hover {
  border-color: var(--color-warning);
}
/* 经营总览的预估态：不套黄框（重点指标不该看着像警告），改用标签上的小 pill 提示口径。
   乐哥 2026-09-12：三张 KPI 卡是页面结论，视觉上要「亮」而不是「告警」。 */
.kpi-row--overview .kpi-card--estimate,
.kpi-row--overview .kpi-card--estimate:hover { border-color: var(--color-border-soft); }

/* ==========================================================================
   （已删除）盈亏公式条 .an-formula 系列 —— 2026-09-13 清理死 CSS
   背景：这一组共 9 条规则（.an-formula / __item / __item--result / __item--in /
   __item--out / __op / --empty 等）是「盈亏板块」的公式条样式。
   该板块在 2026-09-13 的「达人维度整合」中**已整体搬到「达人经营」页**，
   而公式条的渲染代码同时被移除 → 全项目（public/js + index.html）**零引用**，
   属确认死 CSS（grep 双向核对过）。留着会让「这组类到底谁在用」反复产生误判，
   故整组删除。**若将来要用，从 git 历史取回即可。**
   ========================================================================== */

/* 7 张 KPI 卡：宽屏 4 列，中等屏 3 列，窄屏 2 列 */
@media (min-width: 1400px) {
  .kpi-row { grid-template-columns: repeat(4, 1fr); }
}
@media (min-width: 1100px) and (max-width: 1399px) {
  .kpi-row { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 1099px) {
  .kpi-row { grid-template-columns: repeat(2, 1fr); }
}

.kpi-card {
  min-width: 0;
  padding: var(--space-5);
  background: var(--color-surface);
  border: 1px solid var(--color-border-soft);
  border-radius: var(--radius-lg);
  box-shadow: none;
  transition: border-color var(--motion-fast) var(--motion-ease-standard),
    transform var(--motion-fast) var(--motion-ease-standard);
}

.kpi-card:hover {
  border-color: var(--color-accent);
  box-shadow: none;
  transform: translateY(-1px);
}

/* 强调卡片（如「成本总金额」总览项）：主色浅底 + 主色边框，突出关键数字 */
.kpi-card--accent {
  background: var(--color-primary-50);
  border-color: var(--color-primary-200);
}
.kpi-card--accent .kpi-card__label { color: var(--color-accent-text); }

/* KPI 卡「语义柔底」（乐哥 2026-09-15 起用于工作台首页）
   动机：首页四张卡原本全白底，只能靠读文字分辨指标性质；用底色区分后可一眼分辨
        （蓝=成交 / 绿=净成交 / 橙=排期 / 紫=达人规模）。
   实现：把 `dashboard.js` 里**原本就有的 tone 语义**（原先只染右上角图标）延伸到卡片底色 ——
        不新增概念，只是让已有色调换个位置呈现。
   ⚠️ 为什么做成**修饰类**而不是直接改 `.kpi-card` 的 background：
      `.kpi-card` 被 **14 个页面共用**（见 grep kpi-card public/js/pages），
      直接改 = 全站换底，属结构性改动。加类 → 只有显式加类的页面生效，其余页零影响。
   ⚠️ 类名 `--tone-*` 与 JS 侧 `UI.kpiTones()` 的键一一对应（blue/teal/orange/green/purple）；
      写错键名不会报错、只会**静默退回白底**，故只允许用这 5 个键。
   ⚠️ `border-color: transparent` 是本设计的组成部分：柔底卡片再描一圈边会显脏。
      悬停高亮仍生效 —— 但**靠的不是书写顺序**：`.kpi-card:hover`（特异性 0,2,0）
      高于 `.kpi-card--tone-*`（0,1,0），故它实际写在本段**之前**也能覆盖回来。
      （别按"后面覆盖前面"的直觉判断，本项目已多次踩特异性陷阱，见上方 estimate 段注释。） */
.kpi-card--tone-blue   { background: var(--color-tone-blue-bg);   border-color: transparent; }
.kpi-card--tone-teal   { background: var(--color-tone-teal-bg);   border-color: transparent; }
.kpi-card--tone-orange { background: var(--color-tone-orange-bg); border-color: transparent; }
.kpi-card--tone-green  { background: var(--color-tone-green-bg);  border-color: transparent; }
.kpi-card--tone-purple { background: var(--color-tone-purple-bg); border-color: transparent; }

/* 经营总览行（.kpi-row--overview）里的柔底卡：描边必须也是透明
   ⚠️ 为什么单独写一条、且要写成「.kpi-row--overview .kpi-card.kpi-card--tone-x」三重选择器：
      该行有 `.kpi-row--overview .kpi-card--estimate { border-color: var(--color-border-soft) }`
      —— 它是 **0,2,0**，而上面的 `.kpi-card--tone-*` 只有 **0,1,0** → **会被它盖掉**，
      结果就是「柔底上又描了一圈灰边」，正是本设计要避免的「脏」。
      所以这里必须凑到 **0,3,0**（多带一个 `.kpi-card`）才能稳定压过它 ——
      **不要**简化成 `.kpi-row--overview .kpi-card--tone-x`（那是 0,2,0，与它同权重，
      只能靠书写顺序分胜负，属于本项目已反复踩过的隐性依赖）。
   ⚠️ 另一个边界：`--result` 卡片（利润来源链条）**不在这里管** —— 它是 `.an-src-card`，
      不是 `.kpi-card`，走自己那套规则。 */
.kpi-row--overview .kpi-card.kpi-card--tone-blue,
.kpi-row--overview .kpi-card.kpi-card--tone-teal,
.kpi-row--overview .kpi-card.kpi-card--tone-orange,
.kpi-row--overview .kpi-card.kpi-card--tone-green,
.kpi-row--overview .kpi-card.kpi-card--tone-purple { border-color: transparent; }

/* 售后分析三页（售后总览 / 达人售后 / 商品售后）的柔底卡：同样要保证描边透明。
   ⚠️ 先说清这条的**真实作用**（实测过，别误以为它是"新加透明"）：
      `.kpi-card--tone-*`（第 185 行起）**自身已经写了 `border-color: transparent`**，
      而 `.kpi-card`（147 行）的基础边框与它**同为 (0,1,0)** → 目前是**靠书写顺序**让 tone 胜出。
      本组 (0,3,0) 规则的价值是**去掉这个顺序依赖**：将来谁把 `.kpi-card` 挪到 tone 类之后、
      或在该行加一条 (0,2,0) 的边框规则（`--overview` 行就有这种情况，见上方 191 行注释），
      柔底卡都不会突然长出灰边。
   ⚠️ 行类名必须是 `--grid6` / `--grid5`（**不是** `--overview`）——
      售后三页用的是这两个行类，选择器对不上就完全不生效。 */
.kpi-row--grid6 .kpi-card.kpi-card--tone-blue,
.kpi-row--grid6 .kpi-card.kpi-card--tone-teal,
.kpi-row--grid6 .kpi-card.kpi-card--tone-orange,
.kpi-row--grid6 .kpi-card.kpi-card--tone-green,
.kpi-row--grid6 .kpi-card.kpi-card--tone-purple,
.kpi-row--grid5 .kpi-card.kpi-card--tone-blue,
.kpi-row--grid5 .kpi-card.kpi-card--tone-teal,
.kpi-row--grid5 .kpi-card.kpi-card--tone-orange,
.kpi-row--grid5 .kpi-card.kpi-card--tone-green,
.kpi-row--grid5 .kpi-card.kpi-card--tone-purple { border-color: transparent; }

.kpi-card__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: var(--space-3);
}

.kpi-card__label {
  font-size: var(--font-size-sm);
  color: var(--color-muted);
}

.kpi-card__icon {
  width: 32px;
  height: 32px;
  border-radius: var(--radius-md);
  background: var(--color-primary-50);
  color: var(--color-accent-text);
  display: flex;
  align-items: center;
  justify-content: center;
}

/* ⚠️ 盈亏正负色必须在这里再声明一次：`.kpi-card__value`（本文件、特异性 0,1,0）
   与 table.css 的 `.num-pos`（0,1,0）**特异性相同**，而本文件**后加载** → 会把正负色覆盖掉。
   2026-09-13 实测：KPI 卡上的「月最终盈亏 -¥13.3万」显示为深灰，而表格里同值已是绿色 —— 两处不一致。
   故用 0,2,0 显式覆盖（全站约定：盈利=红、亏损=绿）。 */
.kpi-card__value.num-pos,
.card__value.num-pos { color: var(--color-danger); }
.kpi-card__value.num-neg,
.card__value.num-neg { color: var(--color-success); }

.kpi-card__value {
  font-size: var(--font-size-3xl);
  font-weight: var(--font-weight-semibold);
  letter-spacing: var(--font-letter-spacing-display);
  font-feature-settings: "tnum", "lnum";
  font-variant-numeric: tabular-nums;
  color: var(--color-fg);
  line-height: var(--font-line-height-tight);
}

.kpi-card__delta {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  margin-top: var(--space-2);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-medium);
}

.kpi-card__delta.is-up { color: var(--color-success); }
.kpi-card__delta.is-down { color: var(--color-danger); }
/* 一张卡上有**多个环比**时的容器（如总盈亏卡：盈亏涨跌幅 + 利润率百分点差）。
   ⚠️ 必须 column 排：`.kpi-card__delta` 自身是 inline-flex，两个直接相邻会挤在同一行
      连成一串（"↑721.8% 较上月 ↑5.08 个百分点 利润率较上月"），读不出这是两组数据
      —— 乐哥 2026-09-16 报障的「文字内容挤压」就是这处。
   容器内单个 delta 不再各自留上边距（间距统一由 gap 控制）。 */
.kpi-card__moms { display: flex; flex-direction: column; align-items: flex-start; gap: 3px; margin-top: var(--space-2); }
.kpi-card__moms > .kpi-card__delta { margin-top: 0; }
/* 「无环比可算」态（全部月份 / 预估口径 / 上月无数据）：灰色说明，不用涨跌色 ——
   否则灰色的「不与上月对比」配上红绿色会被误读成"持平"。 */
.kpi-card__delta.is-none { color: var(--color-muted); font-weight: var(--font-weight-regular); }
/* 「较上月」后缀小字：与涨跌数字同排，弱化以免抢数字的注意力 */
.kpi-card__delta-label { color: var(--color-muted); font-weight: var(--font-weight-regular); }

.kpi-card__sub {
  margin-top: var(--space-2);
  font-size: var(--font-size-xs);
  color: var(--color-muted);
  line-height: 1.5;
}

/* 净实收卡按渠道（微信小店/抖音）拆分 */
.kpi-src {
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: var(--font-size-xs);
  color: var(--color-fg);
}
.kpi-src + .kpi-src { margin-top: 3px; }
.kpi-src__dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
}

/* 成本构成横向条形 */
.cost-bar-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
.cost-bar-item__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-2);
  font-size: var(--font-size-sm);
}
.cost-bar-item__head span:first-child { color: var(--color-fg); }
.cost-bar-item__head .num { color: var(--color-fg-2); font-variant-numeric: tabular-nums; }
.cost-bar-item__track {
  height: 8px;
  border-radius: 999px;
  background: var(--color-gray-100);
  overflow: hidden;
}
.cost-bar-item__fill {
  height: 100%;
  border-radius: 999px;
  background: var(--color-accent-text);
  transition: width var(--motion-base) var(--motion-ease-standard);
}

.chart-grid {
  display: grid;
  grid-template-columns: 1.6fr 1fr;
  gap: var(--space-4);
  margin-bottom: var(--space-4);
}

.chart-grid--bottom {
  grid-template-columns: 1fr 1fr;
}

.chart-card {
  min-width: 0;
  overflow: hidden;
  background: var(--color-surface);
  border: 1px solid var(--color-border-soft);
  border-radius: var(--radius-lg);
}

.chart-card__body {
  padding: var(--space-5);
  min-height: 240px;
  position: relative;
  min-width: 0;
}

.chart-card__body canvas {
  max-width: 100%;
  display: block;
}

.chart-fallback {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 240px;
  color: var(--color-muted);
  font-size: var(--font-size-sm);
}

/* 排行条形 */
.ranking-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.ranking-item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.ranking-item__rank {
  width: 20px;
  flex-shrink: 0;
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  color: var(--color-meta);
  text-align: center;
  font-feature-settings: "tnum", "lnum";
  font-variant-numeric: tabular-nums;
}

.ranking-item__name {
  width: 96px;
  flex-shrink: 0;
  font-size: var(--font-size-sm);
  color: var(--color-fg-2);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ranking-item__bar {
  flex: 1;
  height: 8px;
  border-radius: var(--radius-pill);
  background: var(--color-surface-2);
  overflow: hidden;
}

.ranking-item__bar-fill {
  height: 100%;
  border-radius: var(--radius-pill);
  background: var(--color-accent);
}

.ranking-item__value {
  width: 88px;
  flex-shrink: 0;
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-fg);
  font-feature-settings: "tnum", "lnum";
  font-variant-numeric: tabular-nums;
  text-align: right;
}

/* 快捷入口（卡片内横排 4 个） */
.quick-links {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-3);
}

.quick-link {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-4);
  border-radius: var(--radius-md);
  background: var(--color-surface-2);
  border: 1px solid transparent;
  color: var(--color-fg-2);
  cursor: pointer;
  text-align: center;
  transition: border-color var(--motion-fast) var(--motion-ease-standard),
    background var(--motion-fast) var(--motion-ease-standard);
}

.quick-link:hover {
  border-color: var(--color-border);
  background: var(--color-surface);
}

/* 高亮快捷入口（排期日历）：主色浅底 + 主色图标，克制不抢眼 */
.quick-link--highlight {
  background: var(--color-primary-50);
}
.quick-link--highlight .quick-link__icon {
  background: var(--color-accent);
  color: var(--color-accent-on);
  box-shadow: none;
}
.quick-link--highlight .quick-link__label {
  color: var(--color-fg);
}
.quick-link--highlight .quick-link__desc {
  color: var(--color-muted);
}
.quick-link--highlight:hover {
  border-color: var(--color-accent);
  background: var(--color-primary-50);
}

.quick-link__icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: var(--radius-md);
  background: var(--color-surface-2);
  color: var(--color-accent-text);
}

.quick-link__text {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.quick-link__label {
  font-size: var(--font-size-base);
  font-weight: var(--font-weight-semibold);
  color: var(--color-fg);
}

.quick-link__desc {
  font-size: var(--font-size-xs);
  color: var(--color-muted);
}

/* 移动端：快捷入口降为两列；高亮的「排期日历」占满整行更醒目 */
@media (max-width: 768px) {
  .quick-links {
    grid-template-columns: repeat(2, 1fr);
  }
  .quick-link--highlight {
    grid-column: 1 / -1;
  }
}

/* 首页底部备案号（合规：主页底部中央位置，滚动到底部才出现，非悬浮） */
.site-footer {
  margin-top: var(--space-8);
  padding: var(--space-6) 0;
  text-align: center;
  font-size: var(--font-size-xs);
  color: var(--color-muted);
}
.site-footer a {
  color: var(--color-muted);
  text-decoration: none;
}
.site-footer a:hover {
  color: var(--color-fg-2);
}

/* ============================ 登录（split-screen，参考 Arco Pro） ============================ */

.login-root {
  min-height: 100vh;
  display: flex;
  background: var(--color-bg);
}

/* 左侧品牌视觉区 */
.login-hero {
  position: relative;
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  padding: var(--space-10);
  overflow: hidden;
  background:
    radial-gradient(1200px 900px at 80% 20%, rgba(255,255,255,0.18), transparent 55%),
    linear-gradient(135deg, var(--color-primary-500) 0%, var(--color-primary-600) 45%, var(--color-primary-400) 100%);
  color: #fff;
}

/* 左侧装饰网格 */
.login-hero::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(rgba(255,255,255,0.06) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,0.06) 1px, transparent 1px);
  background-size: 48px 48px;
  pointer-events: none;
}

/* 左侧装饰圆环 */
.login-hero__ring {
  position: absolute;
  z-index: 0;
  border: 1px solid rgba(255,255,255,0.15);
  border-radius: 50%;
  pointer-events: none;
}
.login-hero__ring--1 { width: 320px; height: 320px; top: 12%; right: 15%; }
.login-hero__ring--2 { width: 180px; height: 180px; bottom: 22%; left: 12%; border-color: rgba(255,255,255,0.10); }
.login-hero__ring--3 { width: 80px; height: 80px; top: 28%; left: 18%; background: rgba(255,255,255,0.08); border: none; }

/* 左侧装饰方块/数据条
   ⚠️⚠️ 这里**刻意不用 `backdrop-filter`**（原来有 blur(4px)）：
      `backdrop-filter` 会把元素提升为**独立合成层**，Chrome 合成时会按 DOM 顺序
      叠在文字之上 —— 即使文字的 z-index(1) 比它高也压不住
      （实测：装饰横条压在副标题文字上，蓝底时只是隐约可见，换成金色门面后非常明显）。
      ⇒ 去掉 blur 并把层级显式降到 0。背景本来就是纯色渐变，"糊不糊"肉眼无差别，
        去掉它零视觉损失、却治好了压字。 */
.login-hero__shape {
  position: absolute;
  z-index: 0;
  border-radius: var(--radius-md);
  background: rgba(255,255,255,0.10);
  pointer-events: none;
}
.login-hero__shape--1 { width: 120px; height: 80px; top: 18%; left: 10%; transform: rotate(-12deg); }
.login-hero__shape--2 { width: 80px; height: 120px; bottom: 18%; right: 10%; transform: rotate(8deg); }
/* ⚠️⚠️ 这两条装饰横条原来是 `top:55% / 60%` + `right:20% / 24%` ——
   而品牌文字块是**垂直居中**的（logo + 标题 + 两行副标题大约占 40%~65% 高度），
   ⇒ 横条正好穿过副标题，把文字压花（蓝底时只是隐约、金色门面下很明显，实测截图可见）。
   ⇒ 移到**顶部左侧空白区**（那里只有细线圆环，装饰叠装饰不影响可读性）。
   ⚠️ 这是"装饰与内容抢位置"的典型：装饰块用百分比定位、内容用居中定位，
      两者在不同视口下必然在某个尺寸撞上。改装饰的位置，不改内容的居中。 */
.login-hero__shape--3 { width: 160px; height: 12px; top: 11%; left: 6%; border-radius: var(--radius-pill); }
.login-hero__shape--4 { width: 100px; height: 10px; top: 14.5%; left: 10%; border-radius: var(--radius-pill); opacity: 0.6; }

.login-hero__brand {
  position: relative;
  /* ⚠️ 2 而不是 1：装饰块统一是 0（见上面的说明），留出明确层级差，
     避免将来有人插一个 z-index:1 的装饰元素又把文字压住。 */
  z-index: 2;
  text-align: center;
}
.login-hero__logo {
  width: 72px;
  height: 72px;
  margin: 0 auto var(--space-5);
  display: flex;
  align-items: center;
  justify-content: center;
  /* ⚠️⚠️ 底衬必须是**接近不透明的白**，不能是半透明玻璃（原值 rgba(255,255,255,0.16)）。
     用可计算的证据说明为什么（2026-09-20 换公司标识时实测；2026-09-21 标识改用主色蓝后**重算**）：
       公司标识自身是「**主色蓝 #0064E0** + 青 #0FEAE4 + 白 + 深灰描边 #595757」，
       而两个门面的 hero 底色是**蓝系 / 金系**（蓝系就是 primary 渐变，
        金系 #A8741A→#8A5C0E→#C08F24），与标识抢色 —— 实测对比度（vs 渐变 45% 处）：
         · 主色蓝 #0064E0 vs 蓝底(primary-500/600/400) **1.00 / 1.21 / 1.93**、
                             vs 金底 1.33          （WCAG 要 ≥3 才不糊）
         · 青       vs 蓝底 3.57、vs 金底 3.84
         · 描边     vs 蓝底 **1.33**
       ⇒ 直接压在底色上，标识的每个颜色**都糊**（只是形状轮廓还能认出来，
          属于"看着有点脏、但说不上哪不对"的那种问题，最容易被放过）。
       换成近白底衬后：主色蓝 **5.39** ✅、描边 **7.18** ✅、青/白靠自带描边分隔 ✅
       （标识**自带深灰描边**正是为浅底设计的，白角不会消失）。
     ⭐⭐ 2026-09-21 改主色蓝后，这一条从"必要"升级为"**绝对必须**"：
        登录页 hero 的渐变**起点就是 primary-500**，与新蓝**完全相同 ⇒ 对比度 1.00**。
        也就是说，标识的蓝块压在 hero 左下部时会**与底色融为一体、完全看不见**
        （改色前是 1.32，虽也糊但还能看出"有块蓝色"）。
        ⇒ 白底衬不能省、也不能调暗；调成半透明玻璃会让 logo 在门面上直接缺一块。
     ⚠️ 顺带把 `backdrop-filter` 去掉了：它会把元素提升为**独立合成层**，
        在 Chrome 下按 DOM 顺序叠在文字之上 —— 即使文字 z-index 更高也压不住
        （登录页装饰块那次就是这么把副标题压花的，见 .login-hero__shape 的说明）。
        底衬改成不透明后，模糊也没有意义了。 */
  background: rgba(255, 255, 255, 0.95);
  border-radius: var(--radius-xl);
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.10);
}
/* ⚠️ 选择器同时管 `svg` 与 `img`：标识 2026-09-20 从内联 SVG 换成了 `<img>`（见 icons.js），
   只写 svg 的话新标识会**失去尺寸限制**、撑到容器满格（看着就是"logo 变大了"）。
   ⚠️⚠️ 用 `width:auto; height:44px` 而不是 `44px×44px + object-fit`：
      后者元素框仍是正方形、图形在框内等比缩放居中，**看起来等比但量不出来**
       （`getBoundingClientRect()` 返回的是元素框 44×44，会让人误判成"被压扁了"，
        实测核验脚本就误报过一次）。按高定尺后元素框本身就等于图形尺寸，一眼可验。 */
.login-hero__logo svg,
.login-hero__logo img {
  width: auto;
  height: 44px;
  object-fit: contain;
}
.login-hero__title {
  font-size: var(--font-size-3xl);
  font-weight: var(--font-weight-semibold);
  letter-spacing: 1px;
  margin-bottom: var(--space-3);
  /* 轻阴影：门面底色可能是蓝（通用）也可能是金（财务），
     加一层极淡暗影保证两种底色下文字边缘都清楚 —— 0.22 以下几乎看不出"有阴影"，
     但能明显提升压在浅色装饰上的可读性。 */
  text-shadow: 0 1px 10px rgba(0, 0, 0, 0.22);
}
.login-hero__subtitle {
  font-size: var(--font-size-base);
  opacity: 0.85;
  /* ⚠️ 360px 是原来按旧文案（3 个词）定的宽度；文案扩到 5 个词后
     「一站式管理」被挤到第 3 行、只剩"管理"两字孤零零一行（实测截图）。
     ⇒ 放宽到 440px，两行排满。⚠️ 两个门面**共用**这个宽度，
        财务门面的文案更短、放宽后仍是 2 行，不受影响。 */
  max-width: 440px;
  line-height: 1.7;
  text-shadow: 0 1px 8px rgba(0, 0, 0, 0.20);
}

/* 右侧表单区 */
.login-form-wrap {
  flex: 0 0 480px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-6);
  background: var(--color-bg);
}

.login-card {
  width: 400px;
  max-width: 100%;
  background: var(--color-surface);
  border: 1px solid var(--color-border-soft);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-raised);
  padding: var(--space-8) var(--space-8);
}

.login-card__header {
  text-align: center;
  margin-bottom: var(--space-6);
}
.login-card__title {
  font-size: var(--font-size-xl);
  font-weight: var(--font-weight-semibold);
  color: var(--color-fg);
}
.login-card__desc {
  margin-top: var(--space-2);
  font-size: var(--font-size-sm);
  color: var(--color-muted);
}

/* 登录方式切换标签 */
.login-tabs {
  display: flex;
  gap: var(--space-1);
  background: var(--color-surface-2);
  border-radius: var(--radius-pill);
  padding: 4px;
  margin-bottom: var(--space-6);
}
.login-tab {
  flex: 1;
  padding: 7px var(--space-3);
  font-size: var(--font-size-sm);
  color: var(--color-fg);
  text-align: center;
  border-radius: var(--radius-pill);
  cursor: pointer;
  transition: color var(--motion-fast) var(--motion-ease-standard),
    background var(--motion-fast) var(--motion-ease-standard);
}
.login-tab:hover {
  background: color-mix(in srgb, var(--color-surface) 60%, transparent);
}
.login-tab.is-active {
  background: var(--color-accent);
  color: var(--color-accent-on);
  font-weight: var(--font-weight-medium);
}

.login-card__btn {
  width: 100%;
}
.login-card__btn + .login-card__btn {
  margin-top: var(--space-3);
}

.login-card__footer {
  margin-top: var(--space-5);
  font-size: var(--font-size-xs);
  color: var(--color-meta);
  text-align: center;
}

/* 登录页小屏：隐藏品牌区，表单占满（否则左侧 hero 被压没、480px 表单溢出） */
@media (max-width: 768px) {
  .login-hero { display: none; }
  .login-form-wrap { flex: 1 1 100%; }
  .login-card { width: 100%; }
}

/* 密码输入框小眼睛 */
.input--password {
  position: relative;
}
.input--password .input {
  width: 100%;
  padding-right: 40px;
}
.pwd-toggle {
  position: absolute;
  right: 12px;
  top: 50%;
  transform: translateY(-50%);
  background: transparent;
  border: none;
  color: var(--color-muted);
  cursor: pointer;
  padding: 4px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.pwd-toggle:hover {
  color: var(--color-fg);
}

/* 回调加载页 */
.callback-box {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-12) 0;
}

.spinner {
  width: 28px;
  height: 28px;
  border-radius: var(--radius-pill);
  border: 3px solid var(--color-border);
  border-top-color: var(--color-accent-text);
  animation: spin 0.8s linear infinite;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

@media (max-width: 1024px) {
  .kpi-row {
    grid-template-columns: repeat(2, 1fr);
  }
  .chart-grid,
  .chart-grid--bottom {
    grid-template-columns: 1fr;
  }
}

/* === 排期时间轴（详情抽屉内）=== */
.timeline {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  padding: var(--space-2) 0 var(--space-2) var(--space-1);
}
.timeline__item {
  display: flex;
  gap: var(--space-3);
  position: relative;
}
.timeline__item::before {
  content: '';
  position: absolute;
  left: 4px;
  top: 14px;
  bottom: -18px;
  width: 2px;
  background: var(--color-border-soft);
}
.timeline__item:last-child::before { display: none; }
.timeline__dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--color-accent);
  flex-shrink: 0;
  margin-top: 4px;
  z-index: 1;
}
.timeline__body { flex: 1; min-width: 0; }
.timeline__head {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
}
.timeline__time {
  font-size: var(--font-size-sm);
  color: var(--color-muted);
}
.timeline__detail {
  font-size: var(--font-size-sm);
  color: var(--color-fg-2);
  margin-top: 2px;
}

/* === 排期时间轴节点卡片（表单内动态节点）=== */
.node-card {
  border: 1px solid var(--color-border-soft);
  border-radius: var(--radius-lg);
  padding: var(--space-4);
  margin-top: var(--space-3);
  background: var(--color-surface);
}
.node-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-2);
}
.node-title {
  font-weight: var(--font-weight-semibold);
  font-size: var(--font-size-base);
  color: var(--color-fg);
}
.form-actions {
  position: sticky;
  bottom: 0;
  z-index: 10;
  display: flex;
  justify-content: flex-end;
  gap: var(--space-3);
  padding: var(--space-4) 0;
  background: var(--color-bg);
  border-top: 1px solid var(--color-border-soft);
}

/* ---- 套餐商品选择器 ---- */
.bundle-picker {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  max-height: 220px;
  overflow-y: auto;
  padding: var(--space-2);
}
.bundle-pick-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-md);
}
.bundle-pick-row:hover {
  background: var(--color-surface-2);
}

/* ---- 样品发放记录：发放样品列（小字，超长折叠） ---- */
.s-prod-summary {
  font-size: var(--font-size-xs);
  color: var(--color-fg-2);
  line-height: 1.5;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  word-break: break-all;
}
.bundle-pick-name {
  font-size: var(--font-size-base);
  font-weight: var(--font-weight-medium);
  color: var(--color-fg);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ---- 商品选择器（全站统一）：PC 一行（表格式对齐），手机两行 ---- */
.product-picker {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  max-height: 220px;
  overflow-y: auto;
  padding: var(--space-2);
}
.product-pick-row {
  display: grid;
  grid-template-columns: 40px minmax(0, 1fr) 130px 80px 90px auto;
  grid-template-areas: "img name code stock price action";
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-md);
  cursor: pointer;
}
.product-pick-row:hover { background: var(--color-surface-2); }
.pp-img { grid-area: img; width: 40px; height: 40px; border-radius: 6px; object-fit: cover; }
.pp-img--empty { display: inline-flex; align-items: center; justify-content: center; background: var(--color-surface-2); color: var(--color-meta); }
.pp-name {
  grid-area: name;
  display: flex; align-items: center; gap: var(--space-2);
  min-width: 0;
}
.pp-name-text {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-weight: var(--font-weight-medium); color: var(--color-fg);
}
/* PC：meta 用 display:contents 不占位，让编码/库存/价格各自独立成列、像表格一样对齐 */
.pp-meta { display: contents; }
.pp-code { grid-area: code; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--font-size-sm); color: var(--color-fg-2); }
.pp-code--missing { color: var(--color-warning); }
.pp-stock { grid-area: stock; white-space: nowrap; font-size: var(--font-size-sm); color: var(--color-fg-2); }
.pp-price { grid-area: price; color: var(--color-price); font-weight: var(--font-weight-semibold); white-space: nowrap; }
.pp-action { grid-area: action; justify-self: end; }
.pp-picked { color: var(--color-accent); font-size: var(--font-size-sm); font-weight: var(--font-weight-semibold); }

@media (max-width: 640px) {
  .product-pick-row {
    grid-template-columns: 48px minmax(0, 1fr) auto;
    grid-template-areas: "img name action" "img meta action";
    row-gap: 2px;
  }
  .pp-img { width: 48px; height: 48px; }
  /* 手机：meta 恢复占位，编码/库存/价格合并到一行 */
  .pp-meta {
    display: flex; align-items: center; gap: var(--space-3);
    grid-area: meta; min-width: 0; overflow: hidden;
    font-size: var(--font-size-sm); color: var(--color-fg-2);
  }
  .pp-code, .pp-stock, .pp-price { grid-area: auto; }
}

/* ---- 排期横向时间轴 ---- */
.sch-timeline {
  position: relative;
  padding: var(--space-4) var(--space-2);
  overflow-x: auto;
}
.sch-tl {
  position: relative;
}

/* 住宿泳道：块左右边界对齐事项节点（圆心到圆心） */
.sch-tl-acc {
  position: relative;
  height: 56px;
  margin-bottom: var(--space-3);
}
.sch-tl-acc__block {
  position: absolute;
  top: 0;
  height: 100%;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 0 var(--space-2);
  border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--acc, var(--color-muted)) 14%, #fff);
  border: 1px solid color-mix(in srgb, var(--acc, var(--color-muted)) 38%, #fff);
  overflow: hidden;
}
.sch-tl-acc__dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--acc, var(--color-muted));
  flex-shrink: 0;
}
.sch-tl-acc__body {
  display: flex;
  flex-direction: column;
  min-width: 0;
  line-height: 1.35;
}
.sch-tl-acc__hotel {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-fg);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sch-tl-acc__sub {
  font-size: var(--font-size-xs);
  color: var(--color-fg-2);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 节点容器 + 虚线（虚线从首个节点圆心到末个节点圆心） */
.sch-tl-nodes-wrap {
  position: relative;
}
.sch-tl-line {
  position: absolute;
  left: 85px;   /* NODE_W/2：对齐首节点圆心 */
  right: 85px;  /* 对齐末节点圆心 */
  top: 6px;     /* dot 高 14 → 圆心 7，线高 2 → top 6 */
  height: 2px;
  background: var(--color-gray-400);
  z-index: 0;
}
.sch-timeline__nodes {
  display: flex;
  gap: 24px;
  position: relative;
}
.sch-timeline__node {
  position: relative;
  width: 170px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  z-index: 1;
}
.sch-timeline__dot {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 2px solid #fff;
  box-shadow: 0 0 0 1px rgba(0,0,0,0.08);
  flex-shrink: 0;
}
.sch-timeline__date {
  margin-top: var(--space-2);
  font-size: var(--font-size-xs);
  color: var(--color-fg-2);
}
.sch-timeline__time {
  margin-top: 2px;
  font-size: var(--font-size-xs);
  color: var(--color-muted);
}
.sch-timeline__label {
  margin-top: 2px;
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--color-fg);
}
.sch-timeline__card {
  margin-top: var(--space-2);
  width: 100%;
  border: 1px solid var(--color-border-soft);
  border-radius: var(--radius-md);
  padding: var(--space-2);
  font-size: var(--font-size-sm);
  color: var(--color-fg);
  line-height: 1.5;
}
/* 时间轴卡片信息行：图标固定 + 标签 + 头像 + 文字，尺寸统一 */
.tl-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  min-height: 20px;
}
.tl-row-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 14px;
  color: var(--color-muted);
  flex-shrink: 0;
}
.tl-row-label {
  color: var(--color-muted);
  flex-shrink: 0;
}
.tl-avatar {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--color-primary-100);
  color: var(--color-accent-text);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  font-weight: var(--font-weight-medium);
  flex-shrink: 0;
  overflow: hidden;
}
.tl-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.tl-row-text {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sch-timeline__session {
  margin-top: 4px;
  padding-top: 4px;
  border-top: 1px dashed var(--color-border-soft);
}
.sch-timeline__session-title {
  font-weight: var(--font-weight-medium);
}
.sch-timeline__session-date {
  font-size: var(--font-size-xs);
  color: var(--color-fg-2);
}
.sch-timeline__session-time {
  font-size: var(--font-size-xs);
  color: var(--color-muted);
}

/* ---- 列表展开行 ---- */
.row-expand {
  background: var(--color-surface-2);
}
/* 主播业绩：展开明细按「大类」着色（乐哥 2026-09-11 定：不同大类不同颜色）。
   刻意避开左侧色条——项目铁律明确「不存在左侧色条这类通用强调手法」，改用整行淡底 + 名称前小圆点。 */
.ip-sub--live {
  background: var(--color-primary-50);
}
.ip-sub--private {
  background: var(--color-warning-bg);
}
.ip-dot {
  display: inline-block;
  width: 6px;
  height: 6px;
  border-radius: var(--radius-pill);
  margin-right: 8px;
  flex: 0 0 auto;
}
.ip-dot--live {
  background: var(--color-accent);
}
.ip-dot--private {
  background: var(--color-warning-text);
}
.row-expand__inner {
  padding: var(--space-4);
}
/* 已结束的排期（列表）：整行淡化，悬停恢复，仍可查看/编辑 */
.table tr.is-past {
  opacity: 0.55;
  transition: opacity var(--motion-fast) var(--motion-ease-standard);
}
.table tr.is-past:hover {
  opacity: 1;
}
/* 订单业绩天维度展开子表：去掉内缩，让子表列与主表对齐 */
.row-expand__inner.so-expand {
  padding: var(--space-2) 0;
}

/* ---- 展开详情网格 ---- */
.detail-grid {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-6);
}
.detail-grid > div {
  min-width: 120px;
}

/* ---- 佣金商品选择器 ---- */
.cm-picker {
  margin-top: var(--space-2);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  max-height: 220px;
  overflow-y: auto;
}
.cm-pick {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  cursor: pointer;
  font-size: var(--font-size-sm);
}
.cm-pick:hover {
  background: var(--color-surface-2);
}
.chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  /* 上 3 下 1：补偿中文字面偏上，视觉居中（总高不变） */
  padding: 3px 8px 1px;
  margin: 2px;
  border-radius: var(--radius-pill);
  background: var(--color-surface-2);
  font-size: var(--font-size-sm);
}
/* 表格内紧凑胶囊（费用构成等）：高度对齐 .tag(22)，文字视觉居中 */
.cell-chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 22px;
  padding: 1px 8px 0;
  margin: 1px 4px 1px 0;
  border-radius: var(--radius-pill);
  background: var(--color-surface-2);
  color: var(--color-fg-2);
  font-size: var(--font-size-xs);
  white-space: nowrap;
}
.chip__x {
  border: none;
  background: none;
  cursor: pointer;
  color: var(--color-muted);
  display: inline-flex;
  padding: 0;
}
.chip__x:hover {
  color: var(--color-danger);
}

/* ---- 费用列表：原始数据展开（横向网格排列，字段卡片式） ---- */
.raw-data {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: var(--space-2);
}
.raw-row {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: var(--space-2) var(--space-3);
  background: var(--color-surface-2);
  border-radius: var(--radius-sm);
  min-width: 0;
}
.raw-row--wide {
  grid-column: 1 / -1; /* 长字段（用途/备注等）横跨整行 */
}
.raw-row__key {
  font-size: var(--font-size-xs);
  color: var(--color-muted);
  line-height: 1.3;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.raw-row__val {
  font-size: var(--font-size-sm);
  color: var(--color-fg);
  word-break: break-all;
  line-height: 1.5;
}

/* 订单业绩「直播·私域」维度的区块标题 */
.so-section-title {
  font-size: var(--font-size-sm);
  font-weight: 500;
  color: var(--color-fg);
  margin: 4px 0 10px;
}

/* ---- 工作台首页（对齐设计稿） ---- */
/* 卡片头右侧「查看全部」 */
.card-more {
  margin-left: auto;
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-accent-text);
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
}
.card-more:hover { color: var(--color-accent-hover); }

/* 卡片标题内的「口径」小字（乐哥 2026-09-15 加）
   动机：首页两块图口径不同（达人业绩=GMV、业绩占比=GSV），而标题都不写口径 ——
        两图合计分别是 89.4 万与 80.3 万，数字都对，但并排看容易被误读成
        "同一份数据画了两遍"。把口径贴在标题旁，是成本最低的解法。
   ⚠️ 必须**弱化**（小一号 + muted + 常规字重）：它是标题的限定词、不是标题主体，
      抢视觉就本末倒置了（标题是 --font-size-lg / semibold）。 */
.card__unit {
  margin-left: var(--space-2);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-regular);
  color: var(--color-muted);
  white-space: nowrap;
}

/* 平台分布：横向条形列表 */
.plat-list { display: flex; flex-direction: column; gap: var(--space-4); }
.plat-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}
.plat-row__name {
  width: 56px;
  flex-shrink: 0;
  font-size: var(--font-size-sm);
  color: var(--color-fg-2);
}
.plat-row__bar {
  flex: 1;
  height: 8px;
  border-radius: var(--radius-pill);
  background: var(--color-surface-2);
  overflow: hidden;
}
.plat-row__fill {
  display: block;
  height: 100%;
  border-radius: var(--radius-pill);
  transition: width var(--motion-base) var(--motion-ease-standard);
}
.plat-row__pct {
  width: 40px;
  flex-shrink: 0;
  text-align: right;
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-fg);
  font-variant-numeric: tabular-nums;
}

/* 今日排期列表 */
.today-list { display: flex; flex-direction: column; }
.today-item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3);
  border-radius: var(--radius-md);
  background: var(--color-surface-2);
}
.today-item + .today-item { margin-top: var(--space-2); }
.today-item__time {
  flex-shrink: 0;
  width: 92px;
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--color-fg-2);
  font-variant-numeric: tabular-nums;
}
.today-item__name {
  flex: 1;
  min-width: 0;
  font-size: var(--font-size-sm);
  color: var(--color-fg);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 待办提醒列表 */
.todo-list { display: flex; flex-direction: column; gap: var(--space-3); }
.todo-item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}
.todo-item__dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
}
.todo-item__text {
  flex: 1;
  font-size: var(--font-size-sm);
  color: var(--color-fg-2);
}
.todo-item__count {
  min-width: 24px;
  height: 20px;
  padding: 0 8px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-pill);
  background: var(--color-surface-2);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-medium);
  color: var(--color-fg-2);
  font-variant-numeric: tabular-nums;
}
.todo-empty {
  padding: var(--space-6) 0;
  text-align: center;
  font-size: var(--font-size-sm);
  color: var(--color-muted);
}

/* ---- 移动端：看板/首页紧凑适配 ---- */
@media (max-width: 768px) {
  .chart-card__body {
    padding: var(--space-3);
  }
  .today-item {
    flex-wrap: wrap;
  }
  .today-item__time {
    width: auto;
  }
}
/* 超小屏（手机竖屏）：KPI 卡单列，一眼扫一个指标 */
@media (max-width: 480px) {
  .kpi-row {
    grid-template-columns: 1fr;
    gap: var(--space-3);
  }
  .dashboard-overview {
    margin-top: var(--space-3);
    margin-bottom: var(--space-3);
  }
}

/* ============================ 业绩总表（/performance） ============================ */
/* 卡片统一留白 + Tab 栏与筛选工具栏之间留出呼吸
   （原来 .card 本身没有内边距，一级 Tab 与搜索工具栏直接贴在一起） */
.pf-card {
  padding: var(--space-5);
}
.pf-card > .tabs {
  margin-bottom: var(--space-5);
  /* ⚠️ padding 必须清零（2026-09-18 修，全站对齐普查发现）：
     `.card > .tabs`（components.css）给了 `padding: 0 20px`，
     而 `.pf-card` 自身也有 `padding: 20px` → **叠成 40px 双重缩进**，
     导致本页 TAB 文字落在 **313px**，而同页的搜索框在 293px（差 20px，TAB 明显偏右）。
     全站其他 12 个有 TAB 的页面都在 293（它们的 TAB 在 `.toolbar` 内、且 `.table-tabs`
     的 padding 已在 2026-09-14 清零）→ 本页是唯一的例外。
     ⚠️ 只改本页：`.card > .tabs` 那条规则对"卡片本身无内边距"的页面是**正确**的
        （如排期表单 `card sf-card`、达人详情），不能全局去掉。
     ⚠️ 加载顺序保证了本规则生效：pages.css 在 components.css **之后**（见 index.html），
        特异性同为 (0,2,0) → 后者胜。 */
  padding: 0;
}

/* ============================ 经营看板（/analytics） ============================ */
/* 板块标题：照 7 月版参照看板的「一、二、三」编号 + 副标题（2026-09-11 重做） */
.an-sec {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: var(--space-6) 0 var(--space-4);
  padding-bottom: var(--space-2);
  border-bottom: 1px solid var(--color-border-soft);
}
.an-sec:first-of-type { margin-top: var(--space-4); }
.an-sec__no {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  flex: none;
  border-radius: var(--radius-sm);
  background: var(--color-accent-bg);
  color: var(--color-accent-text);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  align-self: center;
}
.an-sec__title {
  font-size: var(--font-size-lg, 18px);
  font-weight: var(--font-weight-semibold);
  color: var(--color-fg);
}
.an-sec__sub {
  font-size: var(--font-size-xs);
  color: var(--color-muted);
}

/* 板块目录条（#an-nav）：常驻吸顶、点击平滑滚动、滚动高亮。
   定位：贴在全局顶栏（.topbar，sticky top:0，高 --header-height）下沿。
   z-index 900 < 顶栏 --z-sticky(1100)：顶栏始终压在其上，层叠不打架。
   底色取页面底 --color-bg（与 .page 留白同色）→ 视觉最轻，只靠底部细线区分内容；
   当前项用主色字 + 浅主色胶囊，未选中用 muted —— 刻意弱于一级口径 Tab（下划线式），不抢风头。
   结构拆「固定区 + 可滚动区」：overflow 只挂在滚动区，固定区（口径徽章）不被横向滚动带走，
   且固定区自身无 overflow，故徽章的下拉不会被裁剪。 */
.an-nav {
  position: sticky;
  top: var(--header-height);
  z-index: 900;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  height: 46px;
  margin: 0 0 var(--space-4);
  background: var(--color-bg);
  border-bottom: 1px solid var(--color-border-soft);
}

/* 固定区：口径徽章，不参与横向滚动（flex:none —— 窄屏不被压扁也不被滚走） */
.an-nav__fixed {
  flex: 0 0 auto;
  position: relative;
  display: flex;
  align-items: center;
  height: 100%;
  padding-right: var(--space-2);
  border-right: 1px solid var(--color-border-soft);
}

/* 可滚动区：右侧目录项独立横滚，窄屏不换行挤成两行；滚动条隐藏，避免吸顶时高度抖动 */
.an-nav__scroll {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: var(--space-1);
  height: 100%;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.an-nav__scroll::-webkit-scrollbar { display: none; }

.an-nav__item {
  flex: 0 0 auto;
  height: 30px;
  padding: 0 var(--space-3);
  border: none;
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--color-muted);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-regular);
  line-height: 30px;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color var(--motion-fast) var(--motion-ease-standard),
              color var(--motion-fast) var(--motion-ease-standard);
}
.an-nav__item:hover { background: var(--color-surface-2); color: var(--color-fg); }
.an-nav__item.is-active {
  background: var(--color-accent-bg);
  color: var(--color-accent-text);
  font-weight: var(--font-weight-medium);
}
.an-nav__item:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }

/* 口径徽章：胶囊 + 主色描边 + 浅主色底，明显区别于目录项（纯文字无边框）——
   一眼看出是「状态」而非「跳转项」，也不与一级口径 Tab（下划线式）撞脸。 */
.an-caliber { position: relative; display: flex; align-items: center; height: 100%; }
.an-caliber__btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  height: 30px;
  padding: 0 var(--space-3);
  border: 1px solid var(--color-accent);
  border-radius: var(--radius-pill);
  background: var(--color-accent-bg);
  color: var(--color-accent-text);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color var(--motion-fast) var(--motion-ease-standard),
              border-color var(--motion-fast) var(--motion-ease-standard);
}
.an-caliber__btn:hover { background: var(--color-surface-2); }
.an-caliber__btn:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }
.an-caliber__label { line-height: 1; }
.an-caliber__caret {
  display: inline-flex;
  align-items: center;
  color: var(--color-accent-text);
  transition: transform var(--motion-fast) var(--motion-ease-standard);
}
.an-caliber__btn[aria-expanded="true"] .an-caliber__caret { transform: rotate(180deg); }

/* 静态口径指示（2026-09-17：经营看板收起口径 tab 栏后，目录条上只剩一个口径）。
   形态与上面的「胶囊按钮」一致（同色同尺寸），但**去掉了按钮感**：
     · 无 caret（不可下拉）、无 :hover 变色（不可点）—— 点击光标会是「坏了的下拉」的错觉；
     · 用 <span> 而不是 <button> —— 屏幕阅读器不该把它报成可操作控件（可访问性，不是样式问题）。
   ⚠️ 必须自己写 `line-height:1`：胶囊按钮里有 `.an-caliber__label{line-height:1}`，
      静态版把文字直接放外层，漏了就比按钮版高 2px（目录条里一眼看出不齐）。 */
.an-caliber__static {
  display: inline-flex;
  align-items: center;
  height: 30px;
  padding: 0 var(--space-3);
  border: 1px solid var(--color-accent);
  border-radius: var(--radius-pill);
  background: var(--color-accent-bg);
  color: var(--color-accent-text);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  line-height: 1;
  white-space: nowrap;
}

/* 下拉：相对徽章绝对定位（.an-caliber 已 position:relative）→ 目录条吸顶时位置依然正确。
   z-index 950 > 目录条 900、< 顶栏 --z-sticky(1100)：不会盖住顶栏。 */
.an-caliber__menu {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  min-width: 168px;
  padding: var(--space-1);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  z-index: 950;
}
.an-caliber__menu[hidden] { display: none; }
.an-caliber__opt {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  width: 100%;
  padding: var(--space-2) var(--space-3);
  border: none;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--color-fg-2);
  font-size: var(--font-size-sm);
  line-height: 1.4;
  text-align: left;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color var(--motion-fast) var(--motion-ease-standard);
}
.an-caliber__opt:hover { background: var(--color-surface-2); color: var(--color-fg); }
.an-caliber__opt:focus-visible { outline: 2px solid var(--color-accent); outline-offset: -2px; }
.an-caliber__opt.is-active { color: var(--color-accent-text); font-weight: var(--font-weight-medium); }
.an-caliber__opt-check { display: inline-flex; align-items: center; color: var(--color-accent); opacity: 0; }
.an-caliber__opt.is-active .an-caliber__opt-check { opacity: 1; }

/* 滚动补偿：走 scrollIntoView / 锚点跳转时，标题不被吸顶条（顶栏 56 + 目录条 46 + 8 呼吸）盖住。
   主路径用 JS 的 window.scrollTo 精确补偿，此处作为兜底，值须与 JS 的 NAV_GAP 保持一致。 */
#an-body .an-sec { scroll-margin-top: calc(var(--header-height) + 54px); }

/* 口径提示条：info（订单归档）/ warn（快照兜底）
   ⚠️ 2026-09-14 乐哥「警示提醒方式没有微信小店的好」→ 去色块，改**细左边框**形态
   ----------------------------------------------------------------------------
   改前：`--color-accent-bg`(#EDF4FE) 或 `--color-warning-bg`(#FEF5E7) 整条铺底 +
         1px 边框 + 圆角，宽 1456px —— 一块 12 万+ 像素的色块。
   为什么要改：与 `.st-cover` 同理（见该处注释）—— 大色块与表格内状态色抢注意力，
       且满屏黄条会导致「警示疲劳」。实测微信小店全图彩色像素只占 0.72%。
   为什么**这条保留左边框**（而 `.st-cover` 是下细线）：
       内容性质不同 —— `.st-cover` 是**单行 + 需要行动**（有按钮），去掉边界仍读得通；
       本 banner 是**多行口径说明**（3~5 行），完全没有边界会被读成正文的一部分。
       左边框是"引文/注释"的通用形态，既轻量又保留"这是一段说明"的语义。
   ⚠️ 文字色改为常规色（--color-fg-2）：原来整条用 warning-text 橙字，
      在**有底色**时靠底色衬托尚可；去掉底色后整段橙字会过抢。
      现在层次是：正文灰 → `<b>` 深色加粗（口径关键值）→ `.an-warn-text` 橙字（真需注意）。
      即「说明用深色、警示用橙色」，与微信小店「正文灰 + 关键橙」同一逻辑。 */
/* 提示条 · 统一形态（2026-09-14 乐哥定稿：浅底 + 圆角 + 左侧图标，**不带关闭叉**）
   ---------------------------------------------------------------
   改前：透明底 + 左侧 3px 竖线（"引文"观感），与提成总览页的"近白底"又是两套。
   改后：与全站统一 —— 引用 --notice-* 那组规格（浅蓝底 + 8px 圆角 + 蓝图标）。
   ⚠️ 字号 12px → 14px：对齐 --font-size-sm（项目规范：中文 12px 以下发虚），
      也与 .st-rule__inner / .alert 同档，全站提示条只有一种字号。 */
.an-banner {
  display: flex;
  align-items: flex-start;
  gap: var(--notice-gap);
  padding: var(--notice-pad-y) var(--notice-pad-x);
  margin-bottom: var(--space-4);
  border-radius: var(--notice-radius);
  border: 1px solid var(--notice-border);
  background: var(--notice-bg);
  font-size: var(--font-size-sm);
  line-height: 1.6;
  color: var(--notice-fg);
}
/* 提示条图标 · 垂直对齐（2026-09-14 乐哥：「刚刚做的警示提醒，那个图标没有上下居中」）
   ────────────────────────────────────────────────────────────────────────────
   改前：每条提示条各写一个 `margin-top`（1/2/3px 共 5 个魔数），而且**全都算得不对**：
         实测 .st-rule__inner 偏上 2.0px；.an-banner 更隐蔽 —— 它的 <span> 里 svg 是
         inline 元素，按 baseline「当字符」排版，位置由字体度量决定（恰好只差 1px 是巧合，
         换个字号就会歪）。
   机制：图标中心必须对齐**首行行盒中心**（提示条可能多行 → 不能 align-items:center，
         那会让多行时图标跑到整块中间）。
         · 有包裹容器 → 「盒子法」：容器高 = 首行行高，svg 在容器内 align-items:center。
           单行时视觉居中、多行时对齐首行，两种情况都对。
         · 裸 svg → 用可推导的 margin：⌈(行高 − 图标高) / 2⌉（16px 是提示条图标的统一尺寸）。
           用 em 表达行高 → 字号一变 margin 自动跟随，不再是手算魔数。 */
.an-banner__ico {
  flex: none;
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  height: 1.6em;          /* = 本条的 line-height:1.6，即首行行高（22.4px @14px） */
  color: var(--notice-ico);
}
.an-banner b { color: var(--color-fg); font-weight: var(--font-weight-semibold); }
.an-banner--info {
  border-color: var(--notice-border);
  background: var(--notice-bg);
}
.an-banner--info .an-banner__ico { color: var(--notice-ico); }
/* 警示类**保留橙色语义**（只统一形态）——全改蓝会让"警告"失去辨识度 */
.an-banner--warn {
  border-color: var(--notice-warn-border);
  background: var(--notice-warn-bg);
}
.an-banner--warn .an-banner__ico { color: var(--notice-warn-ico); }

/* 图卡片标题行（参照看板是 13px / 次要字色 + 右侧 hint）
   ==========================================================================
   2026-09-17 乐哥统一图表标题版式（「标题字号大一点」「和上面留一点行间距」）：
     · 字号 14px → **16px**（`--font-size-lg`，与经营看板的 `.cb-sub` 同档）
     · 字重 500 → **600**（16px 用 medium 仍偏软，标题要能从正文里跳出来）
     · 左 padding 16px → **20px**（原比 `.chart-card__body` 的 20px 少 4px，
       标题左边界与图表左边界**对不齐** —— 这是实测发现的额外瑕疵）
     · bottom 0 → **12px**（原为 0，标题底边紧贴图表顶边，"挨在一起"正是如此）
     · 字色 fg-2 → **fg**（标题是主信息，不该用次级色）
   ⚠️ 本类被 3 个页面共用（analytics / aftersale / influencer-profit）→ 改一处三处生效。 */
.an-chart-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-5) var(--space-5) var(--space-3);
  font-size: var(--font-size-lg);
  font-weight: var(--font-weight-semibold);
  color: var(--color-fg);
}
.an-chart-head__h {
  font-size: var(--font-size-xs);
  font-weight: 400;
  color: var(--color-muted);
  /* ⚠️ 不再 `nowrap`（2026-09-16 修）：这类小字常是一整句说明（如
     「数据自 2026-06 起（此前月份无订单，不补零）」），窄屏下 nowrap 会让它
     以单行 502px 的宽度**越出卡片 215px**。改成可换行 + 允许收缩。 */
  white-space: normal;
  min-width: 0;
  overflow-wrap: anywhere;
}
/* ⚠️ 已弃用（2026-09-11）：图表高度改由 JS 侧 chartCard() 传像素 + 内联 style 控制
   （之前是「tall 布尔 + 这里的 340px」隐式耦合，改一个图要同时翻 JS 和 CSS 两处）。
   保留此规则只为兜底，当前没有任何元素使用。 */
.an-chart--tall { height: 340px; }

/* 单列铺满 / 三列分类型 网格 */
.an-grid-1 { grid-template-columns: 1fr; }
.an-type-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-4);
}
@media (max-width: 1099px) {
  .an-type-grid { grid-template-columns: 1fr; }
}

/* 分类型对比卡（专场 / 私域 / 混播）：标题行加一个语义色点 + 主色标题字（乐哥 2026-09-15）
   动机：三张卡是同质并列项，需要一个「一眼分成三块」的标识。
   ⚠️ 为什么只在标题行上色、**不给整卡上色**：
      ① 数字区保持白底 → 不影响盈亏红绿的可读性。实测「混播」当前是亏的（绿字），
         绿字放到彩色底上对比度会下降，读数字更费劲；
      ② 三张卡装的是同一类指标、只是分类不同，整卡铺色的视觉分量过重。
   ⚠️ 用**具名修饰类** `--special/--private/--mixed`（由 JS 按 TYPE_META 的 key 挂上），
      不用 `:nth-child(N)` —— 卡片顺序一变，nth-child 会**静默错配颜色**且很难被发现。
   ⚠️ 色点用 `::before` 伪元素而不是新增 `<span>`：卡内容是 innerHTML 拼的，
      加一个真实节点就要同步改渲染代码，纯样式能解决就不动 DOM。
   ⚠️ 颜色一律走令牌（本文件禁止硬编码 hex），这三个正是 `UI.kpiTones()` 用的同族色，
      与 KPI 柔底同源 —— 将来换主色只需改 design-tokens 一处。 */
.an-type-card--special .an-card-title { color: var(--color-tone-blue-fg); }
.an-type-card--private .an-card-title { color: var(--color-tone-teal-fg); }
.an-type-card--mixed   .an-card-title { color: var(--color-tone-purple-fg); }
.an-type-card--special .an-card-title::before,
.an-type-card--private .an-card-title::before,
.an-type-card--mixed   .an-card-title::before {
  content: ''; display: inline-block; width: 8px; height: 8px; border-radius: 50%;
  margin-right: 8px; vertical-align: 1px;
}
.an-type-card--special .an-card-title::before { background: var(--color-tone-blue-fg); }
.an-type-card--private .an-card-title::before { background: var(--color-tone-teal-fg); }
.an-type-card--mixed   .an-card-title::before { background: var(--color-tone-purple-fg); }
/* 「N 个场次」副标题仍用中性灰 —— 它是量词不是分类标识，跟着主色走会喧宾夺主 */
.an-type-card--special .an-card-title__sub,
.an-type-card--private .an-card-title__sub,
.an-type-card--mixed   .an-card-title__sub { color: var(--color-muted); }

/* 分类型卡内的小统计 */
.an-card-title {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-fg);
  margin-bottom: var(--space-3);
}
.an-card-title__sub {
  font-size: var(--font-size-xs);
  font-weight: 400;
  color: var(--color-muted);
  margin-left: 6px;
}
.an-stat-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-2);
}
.an-stat__label { font-size: var(--font-size-xs); color: var(--color-muted); }
.an-stat__value { font-size: var(--font-size-sm); font-weight: var(--font-weight-medium); margin-top: 2px; }
.an-card-foot {
  margin-top: var(--space-3);
  font-size: var(--font-size-xs);
  color: var(--color-muted);
}

/* 成本大类下钻行 */
.an-cat-grid {
  display: grid;
  grid-template-columns: 150px 1fr 110px 72px;
  gap: 10px;
  align-items: center;
  font-size: var(--font-size-sm);
}
.an-cat-grid--head {
  margin-bottom: var(--space-2);
  font-size: var(--font-size-xs);
  color: var(--color-muted);
}
.an-cat-grid--head > :nth-child(3),
.an-cat-grid--head > :nth-child(4) { text-align: right; }
.an-cat-track { background: var(--color-surface-2); border-radius: var(--radius-sm); height: 16px; }
.an-cat-fill { height: 16px; border-radius: var(--radius-sm); }
.an-cat-num { text-align: right; font-variant-numeric: tabular-nums; }
.an-cat-num--muted { color: var(--color-muted); }

/* 面包屑 */
.an-crumb { margin-bottom: var(--space-3); font-size: var(--font-size-xs); }
.an-crumb a { color: var(--color-accent-text); text-decoration: none; }
.an-crumb__sep { color: var(--color-muted); margin: 0 6px; }

.an-flex-between { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-3); }
.an-link { color: var(--color-accent-text); text-decoration: none; }
.an-warn-text { color: var(--color-warning-text); }

/* ---------------- 盈亏状态标记（圆点 + 文字） ----------------
   状态标记「圆点 + 文字」：圆点取 currentColor，颜色由 JS 内联写在元素上，
   与该行「盈亏」数字用**同一套色规**（正=红 / 负=绿）。
   ⚠️ 刻意不用 .badge 上色：badge 的色是语义色（success=绿），与本系统「涨红跌绿」的数值色相反 ——
      一个绿底 badge 写「亏损」会同时发出两个相反信号，读者不知道该信哪个。

   使用方（两处，同一语义共用同一套样式，不各造一个类）：
     · 达人经营 · 明细表「状态」列 + 页头「本月有 N 位达人在亏」
     · 达人结算 · 展开区（若后续用到）
   2026-09-13：原属经营看板「三、达人盈亏」，该板块并入「达人经营」后样式与语义一并迁移。 */
.pnl-flag { display: inline-flex; align-items: center; gap: 6px; font-size: var(--font-size-xs); white-space: nowrap; }
.pnl-flag::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: none; }
.pnl-flag--muted { color: var(--color-muted); }

/* 合计行底色。不复用 .so-subtotal：它只在 .table--sub / .table--zebra 下才有样式，
   挂在普通 .table 上其实是"裸"的（看着像没有合计），这里显式给一条本表专用规则。 */
.an-pnl-table tbody tr.an-pnl-total { background: var(--color-surface-2); }
.an-pnl-table tbody tr.an-pnl-total td { font-weight: var(--font-weight-medium); }

/* ---------------- 一、利润来源：公式链 + 展开面板（2026-09-12 新增） ----------------
   视觉参照乐哥给的示例图：横向链条、加粗深色描边的圆角卡片、标签在上金额在下、`=` 与 `−` 连接。
   描边用 1.5px（比常规卡片粗）+ 深色（--color-fg），这是示例图的关键特征，不是笔误；
   描边色通过 --chain-border 间接引用 token，不写裸色值。 */
:root { --chain-border: var(--color-border-soft); }   /* 乐哥 2026-09-12：原为 --color-fg（近黑），与全站卡片浅灰描边不一致，改为统一 */

.an-src-chain-wrap { overflow-x: auto; padding-bottom: 2px; }
/* ⚠️ 2026-09-16 修（乐哥报障「公式是不是漏减了项目成本」）：
   原来是 `display:flex; min-width:150px/卡 + overflow-x:auto`。
   公式在 2026-09-16 从 5 张卡增加到 7 张（总盈亏 / 收入 / 投流 / 达人佣金 /
   达人招待费用 / 提成&人力成本 / 项目成本）后，**实测视口 ≤1512px 时
   最后一张「项目成本」正好被裁出可视区**：
     视口 1512 → 溢出 86px ｜ 1440 → 158px ｜ 1366 → 232px ｜ 1280 → 318px
   而 macOS 的滚动条默认隐藏、容器也没给任何提示 → 用户完全看不出右边还有内容，
   会以为「公式里漏了这项」。**内容被裁掉等于没写**，这是必须修的可用性问题。
   → 改用 grid auto-fit：容器够宽就一行、不够就自动折行，**永不裁切**，且各卡等宽。
   实测修复后：1512/1440/1366/1280 全部完整可见（一行或两行）。 */
.an-src-chain {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(158px, 1fr));
  gap: var(--space-2);
  align-items: stretch;
}
/* 每一项 = 「操作符 + 卡片」打包成一个 grid 单元。
   为什么要包：折行时保证减号**跟着卡片走**，不会出现
   「减号留在上一行末尾、卡片孤零零掉到下一行」的割裂观感。

   ── 分组配色（乐哥 2026-09-16：「用颜色区分达人侧 / 公司侧」）────────────
   双通道设计，两个信息各走一路、互不抢占：
     · 左侧色条 = **分组色** → 回答"这笔钱算谁头上"
     · 标题前色点 = **类目色** → 回答"这是哪一项"，**与成本看板同色**
   ⚠️ 为什么只能走"色条 + 色点"、不能整卡上淡底（2026-09-16 实测否决）：
      人力橙底与结果卡暖底、达人蓝底与展开态浅底，**各是同一个 token**（实测色差 0.0）
      → 整卡上底会同时"分不出结果 vs 过程"和"卡片日常就像被点开"，且点开只剩描边反馈。 */
.an-src-term { display: flex; align-items: stretch; gap: var(--space-2); min-width: 0; --grp-c: transparent; }
.an-src-term[data-grp="talent"] { --grp-c: var(--color-chart-1); }   /* 达人侧（投流 / 佣金 / 招待） */
.an-src-term[data-grp="hr"] { --grp-c: var(--color-chart-5); }       /* 提成&人力 */
/* ⚠️ 公司侧**刻意不用绿**（乐哥 2026-09-16：「绿这个色换掉」）：
   绿 --color-chart-3(#2BA471) 与「亏损绿」--color-success(#31A24C) 同色系（色差仅 21），
   而本系统红涨绿跌、**绿 = 亏** → 绿出现在成本卡上容易被读成"这一项亏了"。
   改用靛紫：与达人组的蓝明显区分，也不会与「结果卡暖橙」「展开态浅蓝」撞色。 */
.an-src-term[data-grp="project"] { --grp-c: var(--color-tone-purple-fg); }

/* 组与组之间加宽一格间距 → 5 张成本卡自然聚成 3 簇（达人侧 3 张 / 人力 1 张 / 公司 1 张）。
   只在**每组首项**加左间距，故二、三组各加一次。 */
.an-src-term[data-grp="hr"], .an-src-term[data-grp="project"] { margin-left: 12px; }

/* 「多链共用一个网格」时的强制换行点（2026-09-16 新增，达人经营页的利润构成用它）
   --------------------------------------------------------------------------
   场景：一个页面有**两条公式链**（上面算达人利润、下面算最终盈亏），它们必须
   **卡片同宽、左右对齐**，否则一眼能看出"上下两行不是一套"。
   为什么不能各用一个 `.an-src-chain`：那是 `repeat(auto-fit, …)`，而 **auto-fit 会折叠
   没有项目的空轨道** → 项目少的那条链每张卡被拉伸摊满容器。
   实测（容器均 1414px）：第一条链 5 项 → 276px/卡；第二条链 4 项 → 348px/卡，差 72px。
   → 把两条链放进**同一个** `.an-src-chain`（列宽只由容器决定），第二条链的首项用本类
     强制回到第 1 列开新行。
   ⚠️ 用"强制换行"而不是"靠正好排满"：列数随视口变化，靠数量的边界是脆的（一变就串行）；
      `grid-column: 1` 在任何列数下都成立（列数 5 → 链 1 占整行、链 2 从下一行首列起；
      列数 3 时也可用）。
   ⚠️ `grid-column: 1` 不能配合 `margin-left`（本类的组间距走 padding/无外边距），
      否则第 1 列会被外距推出网格线、与上方卡片对不齐。 */
/* ⚠️ `grid-column: 1` 时**必须把 margin-left 归零**：本类的组间距（data-grp）是 margin-left，
   而网格的第 1 列若带上外边距，卡片会被推出网格线、与上方卡片左边界错开 12px
   （肉眼就是"没对齐"）。
   ⚠️⚠️ `margin-top` **不能只加在换行那一项上**：实测那样只有它自己下移 8px，
      与**同一行的其他项差一行高**（y=788 vs 780），比不加还难看。
      必须用兄弟选择器把整行一起下移 —— `~` 覆盖它后面的所有项，
      换行后即使再折行也在同一行里保持一致。
   （只靠 grid 的 row-gap 8px 读不出"这是两个不同的算式"，两条链会糊成一整片。） */
.an-src-term--brk { grid-column: 1; margin-left: 0; }
.an-src-term--brk, .an-src-term--brk ~ .an-src-term { margin-top: var(--space-2); }
.an-src-card {
  /* 宽度由父级 grid 列宽决定；`.an-src-term` 内用 flex 撑满。
     ⚠️ 不要在这里写 min-width —— 那会重新把链条撑出容器、又变成"最后一张被裁掉"。 */
  flex: 1 1 auto; min-width: 0; display: block; text-align: left;
  /* 1px 浅灰 + 12px 圆角 —— 与 .kpi-card 完全对齐（乐哥 2026-09-12 统一；原为 1.5px 深色 + 8px） */
  background: var(--color-surface); border: 1px solid var(--chain-border);
  /* 左侧 3px 分组色条（方案 F 的"通道一"）。用 inset box-shadow 而不是 border-left：
     ① 不改变盒模型宽度 → 与 grid 列宽、折行计算无冲突（改 border 会挤掉内容宽度）
     ② 描边（border）留给 hover / 选中态用，两个通道互不覆盖
     ⚠️ 只有"成本项"用分组色；结果卡与收入卡不是成本项，--grp-c 未定义 → 回落成 --chain-border，
        视觉上等于没有色条（正是想要的：它们不属于任何费用组）。 */
  box-shadow: inset 3px 0 0 0 var(--grp-c, transparent);
  border-radius: var(--radius-lg); padding: 11px 15px;
  font-family: inherit; cursor: pointer;
  transition: border-color .12s, background .12s;
}
.an-src-card:hover { border-color: var(--color-accent); }
.an-src-card[aria-pressed="true"] { border: 2px solid var(--color-accent); background: var(--color-accent-bg); padding: 10px 14px; }
.an-src-card__n { display: block; font-size: var(--font-size-sm); color: var(--color-muted); margin-bottom: 5px; }
/* 类目色点（方案 F 的"通道二"）：回答"这是哪一项"。
   ⚠️ 色值**必须与成本看板同色**（cost-board.js 的 BIG_COLOR → --color-chart-*），
      否则同一个「投流」在公式链与成本看板是两种颜色 ——
      乐哥 2026-09-16 明确："每个费用都用固定颜色，不要不同地方不一致"。
      改动时两边要一起改（这也是 5/5 一致性断言的依据）。 */
.an-src-card[data-src="ad"] .an-src-card__n::before,
.an-src-card[data-src="commission"] .an-src-card__n::before,
.an-src-card[data-src="ent_talent"] .an-src-card__n::before,
.an-src-card[data-src="hr_all"] .an-src-card__n::before,
.an-src-card[data-src="project_all"] .an-src-card__n::before {
  content: ''; display: inline-block; width: 8px; height: 8px; border-radius: 2px;
  margin-right: 6px; vertical-align: 1px;
}
.an-src-card[data-src="ad"] .an-src-card__n::before { background: var(--color-chart-1); }
.an-src-card[data-src="commission"] .an-src-card__n::before { background: var(--color-chart-2); }
.an-src-card[data-src="ent_talent"] .an-src-card__n::before { background: var(--color-chart-5); }
.an-src-card[data-src="hr_all"] .an-src-card__n::before { background: var(--color-chart-3); }
.an-src-card[data-src="project_all"] .an-src-card__n::before { background: var(--color-chart-4); }
.an-src-card__v {
  display: block; font-size: var(--font-size-2xl); font-weight: 500; line-height: 1.15;
  color: var(--color-fg); font-variant-numeric: tabular-nums;
}
/* ⚠️⚠️ 这里曾有一个「亏损显示成红色」的真 bug，2026-09-15 修 —— 别改回去：
   原写法是一条 `.an-src-card--result .an-src-card__v { color: var(--color-danger) }`（0,2,0），
   本意只是「结果卡默认给个突出的红色」，但它**盖过了** table.css 的 `.num-neg`（0,1,0）。
   而 JS（analytics.js）明明按盈亏正负挂了 `num-pos` / `num-neg` ——
   于是 `num-neg` 那条**永远不生效**：**亏损月的结果卡也显示红色**。
   实测（生产库快照）：2026-06 总盈亏 −¥2.0万、2026-08 为亏损，卡片却都是红色
   （`-¥2.0万` 颜色 = rgb(228,30,63) 红，应为绿）→ 会让人把亏损看成盈利，属会误导决策的那类错。
   → 正确写法：**让符号决定颜色**，按正负各写一条并凑到 0,3,0 压过基类。
      （基类 `.an-src-card__v`（0,1,0）与 `.num-pos`（0,1,0）同权重，而 **pages.css 后加载**，
        所以只写 `.num-pos` 也会被基类的 `color: var(--color-fg)` 盖掉 —— 必须显式写复合选择器。） */
.an-src-card--result .an-src-card__v.num-pos { color: var(--color-danger); }   /* 盈利 = 红 */
.an-src-card--result .an-src-card__v.num-neg { color: var(--color-success); }  /* 亏损 = 绿 */
/* 结果卡加一层暖底，和右边三组成本卡分开（乐哥 2026-09-15）
   用途：现在链条上五张卡长得一模一样，只能靠 = / − 符号判断谁是结果、谁是过程。
   为什么只用 1 个颜色、且只给结果卡：三组成本是**同质并列项**，多色只是噪音；
       而这张卡点一下会展开明细 —— 展开态是「主色描边 + 主色浅底」（见下方 aria-pressed 规则），
       若成本卡也上固定底色，常态色与选中色就会糊在一起，分不出点开了哪张。 */
.an-src-card--result { background: var(--color-tone-orange-bg); border-color: transparent; }
.an-src-card__h { display: block; font-size: var(--font-size-xs); color: var(--color-meta); margin-top: 5px; }
/* 「邀请点击」的副标题用主色蓝（2026-09-19 乐哥：「利润公式里那个点击展开要不要用蓝色字？
   不然很多人都不知道」）。
   ⚠️⚠️ 判据是**副标题在不在邀请动作**，不是**卡片能不能点** ——
      实测 7 张卡**全都可点**（含写着「本月无支出」的两张：点开下方联动画板照样切到
      该项分析、画布正常渲染）。所以用"可点/不可点"来决定颜色是分不出来的，
      而且会让「本月无支出」配着蓝字自相矛盾。
      ⇒ 只有「点击展开 / 点击看走势」这类**动作词**才变蓝；
        「本月无支出 / 口径不支持」是**陈述状态**，没有动作可做，保持灰。
   ⚠️ 颜色复用 `--color-accent-text`（= primary-500 钴蓝）—— 与全站同一套"蓝=可操作"语言：
      `.an-caliber__btn`（蓝色胶囊=可下拉）与 `.an-caliber__static`（刻意去蓝=不可点）就是这对。
      不新造颜色。
   ⚠️ 卡片本身 hover 时**边框**已变蓝（`.an-src-card:hover`），所以副标题用同色是呼应、
      不是冲突（两者一起构成"这张卡活着"的反馈）。 */
.an-src-card__h.is-clickable { color: var(--color-accent-text); font-weight: var(--font-weight-medium); }
/* 选中的卡（aria-pressed）已有蓝底蓝框，副标题若还是蓝会糊在一起 —— 保持蓝但不再加粗 */
.an-src-card[aria-pressed="true"] .an-src-card__h.is-clickable { font-weight: var(--font-weight-regular); }
/* 本月无支出的组：卡片仍展示（否则链条缺一段、看不出「这组没花钱」），但弱化处理，
   避免它和可点的卡长一样、让人白点一下却发现没东西可看 */
.an-src-card.is-zero { border-color: var(--color-border); }
.an-src-card.is-zero .an-src-card__v { color: var(--color-muted); }
.an-src-op { flex: 0 0 auto; align-self: center; font-size: var(--font-size-2xl); font-weight: 500; color: var(--color-fg); padding: 0 2px; }
.an-src-ladder {
  margin-top: var(--space-4); padding-top: var(--space-3);
  border-top: 1px solid var(--color-border-soft);
  font-size: var(--font-size-xs); color: var(--color-muted); line-height: 1.8;
}
.an-src-ladder b { color: var(--color-fg-2); font-weight: 600; }

/* 展开面板 */
.an-src-panel__title { font-size: var(--font-size-lg); font-weight: 600; color: var(--color-fg); }
.an-src-panel__total { font-size: var(--font-size-sm); color: var(--color-muted); }
.an-src-pg { display: grid; grid-template-columns: 300px minmax(0, 1fr); gap: var(--space-4); }
.an-src-cap { font-size: var(--font-size-xs); color: var(--color-muted); margin-bottom: 6px; }
.an-chart-src--ring { height: 230px; }
.an-chart-src--line { height: 220px; }
.an-chart-src--rank { height: 320px; }
.an-src-item {
  display: grid; grid-template-columns: minmax(0, 1fr) 96px 56px; gap: var(--space-2);
  align-items: center; padding: 8px 10px;
  border: 1px solid transparent; border-radius: var(--radius-md);
}
.an-src-item[role="button"] { cursor: pointer; }
.an-src-item[role="button"]:hover { background: var(--color-surface-2); }
.an-src-item.is-on { background: var(--color-accent-bg); border-color: var(--color-primary-200); }
.an-src-item__n { font-size: var(--font-size-sm); color: var(--color-fg-2); }
.an-src-item__v { font-size: var(--font-size-sm); color: var(--color-fg-2); text-align: right; font-variant-numeric: tabular-nums; }
.an-src-item__p { font-size: var(--font-size-xs); color: var(--color-meta); text-align: right; }
.an-src-note { margin-top: var(--space-3); line-height: 1.8; }
.an-src-note-line {
  font-size: var(--font-size-xs); color: var(--color-muted); line-height: 1.9;
  background: var(--color-surface-2); border-radius: var(--radius-md); padding: 10px 12px;
}
.an-src-block { margin-top: var(--space-4); padding-top: var(--space-4); border-top: 1px solid var(--color-border-soft); }
.an-src-block__t { font-size: var(--font-size-sm); font-weight: 500; color: var(--color-fg); margin-bottom: 10px; }
.an-src-empty {
  display: flex; align-items: center; justify-content: center; min-height: 92px;
  padding: 14px 16px; border: 1px dashed var(--color-primary-200);
  border-radius: var(--radius-md); background: var(--color-surface-2);
  color: var(--color-meta); font-size: var(--font-size-xs); line-height: 1.7; text-align: center;
}

@media (max-width: 900px) {
  .an-src-pg { grid-template-columns: minmax(0, 1fr); }
}

/* ==========================================================================
   粉丝体验装（pages/fan-experience.js）
   明细的商品全名很长（含「达人专属」「规格」），必须在单元格内截断，否则表格会被撑爆
   ========================================================================== */
.fe-prod {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* 达人维度看板：达人分组行（可点折叠）+ 组内排期行 */
.fe-group td {
  background: var(--color-surface-2);
  font-weight: var(--font-weight-medium);
}
.fe-child td { background: var(--color-surface); }
.fe-child td:first-child { box-shadow: inset 2px 0 0 var(--color-border); }
/* 折叠箭头与达人胶囊之间留口气，否则箭头像贴在名字上 */
.fe-caret { display: inline-flex; vertical-align: middle; margin-right: 6px; color: var(--color-muted); }
/* KPI 行与表格同处一个 card：#fe-body 里的 .kpi-row 拿不到 .card > .kpi-row 的样式，
   用这个类补上与表头左右对齐的内边距（比行内 margin 拼间距可控） */
.kpi-row.fe-board-kpi {
  padding: var(--space-4) var(--space-5) var(--space-3);
  margin-bottom: 0;
}
/* 达人维度表尾说明：与表格左对齐 */
.fe-foot-note { margin: var(--space-3) var(--space-5) var(--space-5); }

/* --------------------------------------------------------------------------
   粉丝体验装 · 导入页（pages/fan-experience-import.js）
   替代原弹窗：三步式「选排期 → 传清单 → 核对明细」
   -------------------------------------------------------------------------- */
.fei-step {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-2);
}
.fei-step__no {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--color-accent-bg);
  color: var(--color-accent-text);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  line-height: 1;
}
.fei-step__label {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-fg);
}
/* 排期选择器在页面里占满整行会太宽，收一收；下拉是文档流内的，不会被卡片裁切 */
.fei-sched-wrap { max-width: 520px; }

/* --------------------------------------------------------------------------
   导入页 · 第 3 步「按商品设置成本」
   从文件里提取去重商品，一个商品设一次单价（同商品成本相同）；
   与下方明细表拉开层次，让人一眼看到「哪里是花钱的地方」
   -------------------------------------------------------------------------- */
.fei-cost-block {
  margin: var(--space-3) 0 0;
  padding: var(--space-4);
  border: 1px solid var(--color-border-soft);
  border-radius: var(--radius-md);
  background: var(--color-surface-2);
}
.fei-cost-block .table-wrap {
  background: var(--color-surface);
  border-radius: var(--radius-sm);
  overflow: hidden;
}
.fei-cost-head {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
  margin-bottom: var(--space-3);
}
.fei-cost-head .fei-step__label { display: inline-flex; align-items: center; gap: 5px; }
.fei-cost-foot {
  display: flex;
  align-items: baseline;
  margin-top: var(--space-3);
  padding-top: var(--space-3);
  border-top: 1px solid var(--color-border-soft);
  font-size: var(--font-size-sm);
  color: var(--color-fg-2);
}
.fei-cost-foot b { color: var(--color-fg); font-size: var(--font-size-base); }
/* 商品下拉：窄一点，避免把「文件货品名」一列挤没 */
.fei-sel { width: 100%; max-width: 260px; }

/* ==========================================================================
   售后分析 · 页内下钻（达人售后：点达人名 → 整页切成该达人下钻页）
   2026-09-11 乐哥选定「页内切换视图」：像进入一个页面，但不换路由、筛选不丢。
   ========================================================================== */
.af-crumb {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
  margin-bottom: var(--space-4);
}
.af-back {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 4px 10px 4px 6px;
  font-size: var(--font-size-sm);
  color: var(--color-accent-text);
  background: var(--color-accent-bg);
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: background-color var(--motion-fast) var(--motion-ease-standard);
}
.af-back:hover { background: var(--color-primary-100); }
.af-back:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 1px; }
.af-crumb__path { font-size: var(--font-size-sm); color: var(--color-muted); }
.af-crumb__path b { color: var(--color-fg); font-weight: var(--font-weight-medium); }
.af-crumb__sep { padding: 0 2px; color: var(--color-muted); }

/* ==========================================================================
   售后分析 · 核算明细清单（乐哥 2026-09-11 要求：每个指标都要能自己核算）
   把所有「分子 ÷ 分母 = 结果」连同数据来源摊开成表，主指标行浅底凸显。
   ========================================================================== */
.af-audit {
  border: 1px solid var(--color-border-soft);
  border-radius: var(--radius-lg);
  background: var(--color-surface);
  padding: var(--space-4);
  margin-bottom: var(--space-4);
}
.af-audit__head {
  font-size: var(--font-size-base);
  font-weight: var(--font-weight-medium);
  color: var(--color-fg);
  margin-bottom: var(--space-3);
}
.af-audit__sub {
  font-size: var(--font-size-sm);
  font-weight: 400;
  color: var(--color-muted);
}
.af-audit__table { width: 100%; }
.af-audit__table th { font-size: var(--font-size-xs); color: var(--color-muted); font-weight: var(--font-weight-medium); }
.af-audit__name { white-space: nowrap; color: var(--color-fg-2); }
.af-audit__calc { color: var(--color-fg-2); font-variant-numeric: tabular-nums; }
.af-audit__note { margin-top: 2px; font-size: var(--font-size-xs); color: var(--color-muted); }
.af-audit__res {
  text-align: right;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  color: var(--color-fg);
}
/* 主指标行（能直接与上方 KPI 卡对上）：浅底 + 名称/结果加重，一眼区分于参考项 */
.af-audit__main { background: var(--color-surface-2); }
.af-audit__main .af-audit__name { font-weight: var(--font-weight-medium); color: var(--color-fg); }
.af-audit__main .af-audit__res { font-weight: var(--font-weight-medium); }
.af-audit__foot {
  margin-top: var(--space-3);
  padding-top: var(--space-3);
  border-top: 1px solid var(--color-border-soft);
  font-size: var(--font-size-xs);
  color: var(--color-muted);
  line-height: 1.7;
}

/* 售后分析 · 表头口径标注（如「退款率 / 金额口径」两行）
   两个率口径不同，不标出来会被误以为可直接比较。 */
.af-th-sub {
  display: inline-block;
  margin-top: 1px;
  font-size: var(--font-size-xs);
  font-weight: 400;
  color: var(--color-muted);
}

/* ==========================================================================
   售后分析 · 口径定义说明（乐哥 2026-09-11 提供电商标准口径，作为页面注释依据）
   退货率＝衡量「货有没有回来」；退款率＝衡量「钱有没有出去」；两者口径不同。
   ========================================================================== */
.af-def {
  border: 1px solid var(--color-border-soft);
  border-radius: var(--radius-lg);
  background: var(--color-surface);
  padding: var(--space-4);
  margin-bottom: var(--space-4);
}
.af-def__head {
  font-size: var(--font-size-base);
  font-weight: var(--font-weight-medium);
  color: var(--color-fg);
  margin-bottom: var(--space-3);
}
.af-def__sub { font-size: var(--font-size-sm); font-weight: 400; color: var(--color-muted); }
/* 两个指标上下排列，各自一块 */
.af-def__item {
  padding: var(--space-3) 0;
  border-top: 1px solid var(--color-border-soft);
}
.af-def__title {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
  font-size: var(--font-size-base);
  font-weight: var(--font-weight-medium);
  color: var(--color-fg);
}
/* 口径徽标：单数口径 / 金额口径 —— 一眼区分两个指标的口径类型 */
.af-def__badge {
  padding: 1px 8px;
  font-size: var(--font-size-xs);
  font-weight: 400;
  border-radius: 999px;
  background: var(--color-info-bg);
  color: var(--color-info);
}
.af-def__meaning { font-size: var(--font-size-sm); font-weight: 400; color: var(--color-muted); }
/* 公式行：等宽数字、浅底，像「公式」 */
.af-def__formula {
  margin: var(--space-2) 0;
  padding: 6px 10px;
  font-size: var(--font-size-sm);
  font-variant-numeric: tabular-nums;
  background: var(--color-surface-2);
  border-radius: var(--radius-md);
  color: var(--color-fg);
}
.af-def__points {
  margin: 0 0 var(--space-2);
  padding-left: 1.2em;
  font-size: var(--font-size-sm);
  color: var(--color-fg-2);
  line-height: 1.8;
}
.af-def__points li { list-style: disc; }
/* 退款率的三类来源：紧凑两列（名称 + 单数） */
.af-def__bd {
  margin: 0 0 var(--space-2);
  padding: 0;
  font-size: var(--font-size-sm);
}
.af-def__bd li {
  display: flex;
  justify-content: space-between;
  gap: var(--space-3);
  padding: 3px 0 3px 1.2em;
  color: var(--color-fg-2);
}
.af-def__bd-label { min-width: 0; }
.af-def__bd-num { color: var(--color-fg); font-variant-numeric: tabular-nums; white-space: nowrap; }
/* 本页实测算式 —— 最关键的复核依据，浅主色底强调 */
.af-def__calc {
  margin-top: var(--space-2);
  padding: 6px 10px;
  font-size: var(--font-size-sm);
  font-variant-numeric: tabular-nums;
  background: var(--color-accent-bg);
  border-radius: var(--radius-md);
  color: var(--color-fg-2);
}
.af-def__calc b { color: var(--color-fg); }
.af-def__rel {
  padding-top: var(--space-3);
  border-top: 1px solid var(--color-border-soft);
  font-size: var(--font-size-sm);
  color: var(--color-fg-2);
  line-height: 1.8;
}
.af-def__warn {
  margin-top: var(--space-2);
  padding: 6px 10px;
  font-size: var(--font-size-xs);
  background: var(--color-warning-bg);
  color: var(--color-warning-text);
  border-radius: var(--radius-md);
}

/* 售后分析 · 退款率分子构成（三类来源 + 在途，互斥相加 = 退款单数） */
.af-bd {
  border: 1px solid var(--color-border-soft);
  border-radius: var(--radius-lg);
  background: var(--color-surface);
  padding: var(--space-4);
  margin-bottom: var(--space-4);
}
.af-bd__head {
  font-size: var(--font-size-base);
  font-weight: var(--font-weight-medium);
  color: var(--color-fg);
  margin-bottom: var(--space-3);
}
.af-bd__sub { font-size: var(--font-size-sm); font-weight: 400; color: var(--color-muted); }
.af-bd__idx { color: var(--color-muted); font-variant-numeric: tabular-nums; }
.af-bd__total { background: var(--color-surface-2); }
.af-bd__foot {
  margin-top: var(--space-3);
  padding-top: var(--space-3);
  border-top: 1px solid var(--color-border-soft);
  font-size: var(--font-size-xs);
  color: var(--color-muted);
}

/* ==========================================================================
   售后分析 · KPI 一行 6 个（乐哥 2026-09-11）
   与 .kpi-row--six 的区别：--six 是「4 列 + 第5/6张跨2列」的 4+2 布局；
   --grid6 是**强制一行 6 等分**（售后分析三处卡片都用它）。
   窄屏逐级降列，避免字被挤爆。
   ========================================================================== */
/* 默认 3 列（窄屏安全），≥1440px 才升到一行 6 个。
   实测：6 列时每格约 186px（1440）~ 213px（1600）；「¥1,052,382.50」在 28px 字号下需 194px，
   1400px 下会溢出（实测 194>167），故 6 列模式下把数值字号降到 24px，并把换行阈值提到 1440px。 */
.kpi-row--grid6 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (min-width: 1440px) {
  .kpi-row--grid6 { grid-template-columns: repeat(6, minmax(0, 1fr)); }
  .kpi-row--grid6 .kpi-card__value { font-size: var(--font-size-2xl); }
}
@media (max-width: 899px) { .kpi-row--grid6 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
/* 6 列时卡片更窄：副标题收紧行高，长数字不允许撑破卡片 */
.kpi-row--grid6 .kpi-card__sub { line-height: 1.45; }
.kpi-row--grid6 .kpi-card__value { white-space: nowrap; }

/* 售后分析 · 商品页 KPI 一行 5 个（乐哥 2026-09-12 去掉「未匹配商品行」后）
   与 --grid6 同源，列数从 6 降到 5。
   ⚠️ 5 不能被 3 整除也不能被 2 整除 → 若不管，中窄屏最后一行会留空格
   （实测：3 列时留 384px、2 列时留 376px）。
   故默认（3 列）与窄屏（2 列）都让**第 5 张跨 2 列**，保证每行都铺满：
     3 列：3 + (1+2) 铺满   ／  2 列：2 + 2 + 2 铺满
   ≥1440px 用 5 列一行铺满（每格约 224px，比 6 列的 186px 更宽松，数值字号无需下调）。 */
.kpi-row--grid5 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.kpi-row--grid5 > :nth-child(5) { grid-column: span 2; }
@media (min-width: 1440px) {
  .kpi-row--grid5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
  .kpi-row--grid5 > :nth-child(5) { grid-column: span 1; }
}
@media (max-width: 899px) {
  .kpi-row--grid5 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .kpi-row--grid5 > :nth-child(5) { grid-column: span 2; }
}
.kpi-row--grid5 .kpi-card__sub { line-height: 1.45; }
.kpi-row--grid5 .kpi-card__value { white-space: nowrap; }

/* ==========================================================================
   售后分析 · 口径解释入口 + 弹窗（2026-09-12 乐哥改造）

   原先「核算明细 / 退款率分子构成 / 指标口径说明」是三个各自独立的 <details> 折叠条目，
   要分三次点开才看得全（乐哥：「这种展开折叠不直观」）。
   现改为 **一个入口 → 弹窗**：弹窗内三块全部展开 + 顶部锚点跳转定位。
   ⚠️ 弹窗内刻意不再用折叠/Tab —— 折叠的毛病就是「内容被藏起来」，
      换弹窗后再套一层隐藏等于没改。
   ========================================================================== */
/* 提示条 · 统一形态 + 保留可点击（2026-09-14 乐哥定稿）
   ---------------------------------------------------------------
   本类特殊：它是个**可点击的入口**（点开看「指标口径与核算明细」）→
   统一成浅蓝底 + 同规格圆角，但**保留右侧 `>` 箭头**（那是"可展开"的指示，不能去掉）。
   改前是**白底卡**（--color-surface + 边框），正是乐哥说的"白底的"那一类。 */
.af-explain {
  display: flex;
  align-items: center;
  gap: var(--notice-gap);
  width: 100%;
  text-align: left;
  padding: var(--notice-pad-y) var(--notice-pad-x);
  margin-bottom: var(--space-4);
  background: var(--notice-bg);
  border: 1px solid var(--notice-border);
  border-radius: var(--notice-radius);
  cursor: pointer;
  font-family: inherit;
  /* ⚠️ 必须显式声明字号（2026-09-14 门禁抓出）：
     本元素是 `<button>`，只继承 font-family 时**字号仍取浏览器默认的 13.3333px**
     （不是全站的 14px）→ 实测提示条比其它页小半号，视觉不一致。
     门禁 probe-notice-standard.js 会断言 14px，不要删。 */
  font-size: var(--font-size-sm);
  transition: border-color var(--motion-fast) var(--motion-ease-standard),
              background var(--motion-fast) var(--motion-ease-standard);
}
.af-explain:hover { border-color: var(--color-primary-300); background: var(--color-primary-100); }
.af-explain:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }
.af-explain__ico { display: inline-flex; color: var(--color-primary-500); flex: none; }
.af-explain__main { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.af-explain__t { font-size: var(--font-size-base); font-weight: var(--font-weight-medium); color: var(--color-fg); }
.af-explain__s { font-size: var(--font-size-xs); color: var(--color-muted); }
/* 右箭头：明确提示「点了会打开新东西」（比折叠三角更指向"弹出"） */
.af-explain__chev { display: inline-flex; color: var(--color-meta); flex: none; }

/* ---- 弹窗内容 ---- */
.af-ex__nav {
  position: sticky;   /* 锚点条吸顶：滚动长内容时始终能跳转 */
  top: calc(-1 * var(--space-5));
  z-index: 2;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  padding: var(--space-2) 0 var(--space-3);
  margin: calc(-1 * var(--space-2)) 0 var(--space-3);
  background: var(--color-surface);
  border-bottom: 1px solid var(--color-border-soft);
}
.af-ex__navbtn {
  height: 30px;
  padding: 0 var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-full);
  background: var(--color-surface);
  color: var(--color-fg-2);
  font-family: inherit;
  font-size: var(--font-size-sm);
  cursor: pointer;
  transition: border-color var(--motion-fast) var(--motion-ease-standard),
              color var(--motion-fast) var(--motion-ease-standard),
              background var(--motion-fast) var(--motion-ease-standard);
}
.af-ex__navbtn:hover { border-color: var(--color-primary-300); color: var(--color-primary-500); }
.af-ex__navbtn.is-on {
  border-color: var(--color-primary-500);
  background: var(--color-primary-50);
  color: var(--color-primary-600);
}
.af-ex__sec + .af-ex__sec { margin-top: var(--space-5); padding-top: var(--space-5); border-top: 1px solid var(--color-border-soft); }
.af-ex__head { display: flex; align-items: baseline; flex-wrap: wrap; gap: var(--space-2); margin-bottom: var(--space-3); }
.af-ex__no {
  display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; flex: none;
  border-radius: var(--radius-sm);
  background: var(--color-primary-500); color: #fff;
  font-size: var(--font-size-xs); font-weight: var(--font-weight-medium);
}
.af-ex__t { font-size: var(--font-size-base); font-weight: var(--font-weight-semibold); color: var(--color-fg); }
.af-ex__h { font-size: var(--font-size-xs); color: var(--color-muted); }
.af-ex__body { min-width: 0; }

/* 口径标记（乐哥 2026-09-12）：KPI 副标题里把「金额口径 / 单数口径」做成蓝色小标记，
   与后面的算式（灰色）区分开。蓝色 = info 语义，与弹窗内 .af-def__badge 同色，全页一致。
   目的：本页退款率（看钱）与退货率（看单数）口径不同，副标题原先一片灰色、扫读会混。 */
.af-caliber {
  display: inline-block;
  padding: 0 6px;
  border-radius: var(--radius-sm);
  background: var(--color-info-bg);
  color: var(--color-info);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-medium);
  line-height: 1.6;
  vertical-align: baseline;
}

/* ==========================================================================
   售后分析 · 列头口径提示（乐哥 2026-09-11）
   表头里的「金额口径 / 单数口径」文字太长 → 改成圆圈感叹号图标，悬停显示说明。
   ⚠️ 关键约束：表格外层 .table-wrap 是 overflow-x: auto，按 CSS 规范该方向的 visible
      会被计算成 auto → **tooltip 上下左右都可能被裁**。故：
      · 向右不溢出：tip 用 right:0 定位（贴着图标右缘向左展开）
      · 向下不溢出：tip 向下弹，落在表头下方的表格内容区（仍在容器高度内）
      实测（无头浏览器）确认可见后才上线；若某天表头变成最后一行元素，需改为向上弹。
   ========================================================================== */
.af-hint {
  position: relative;
  display: inline-flex;
  align-items: center;
  vertical-align: -2px;
  margin-left: 3px;
  color: var(--color-muted);
  cursor: help;
}
.af-hint:hover,
.af-hint:focus-visible { color: var(--color-accent-text); }
.af-hint:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 1px; border-radius: 2px; }
.af-hint__tip {
  display: none;
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 60;
  width: max-content;
  max-width: 240px;
  padding: 6px 10px;
  font-size: var(--font-size-xs);
  font-weight: 400;
  line-height: 1.55;
  text-align: left;
  white-space: normal;
  color: var(--color-accent-on);
  background: var(--color-fg);
  border-radius: var(--radius-md);
  box-shadow: 0 2px 8px rgba(0, 0, 0, .18);
}
.af-hint:hover .af-hint__tip,
.af-hint:focus-visible .af-hint__tip { display: block; }

/* ==========================================================================
   售后分析 · 金额「万」展示（乐哥 2026-09-12）
   过万的金额显示为 ¥160.2万，鼠标悬停（或键盘聚焦）浮出精确值。
   复用 .af-hint 的定位策略（向下弹 + right:0 对齐）—— 表格外层是 overflow-x:auto，
   浮层必须落在容器内，否则会被裁（已实测同策略可行）。
   注意：**不加虚线下划线**（乐哥 2026-09-12：到万的那些数字下面不用加虚线，没必要）——
        数字本身就是可读的，加下划线反而让整列显得毛糙。
        「可悬停」的提示由 cursor: help（鼠标移到数字上变问号光标）承担，无静态视觉噪音。
   ========================================================================== */
.af-money {
  position: relative;
  cursor: help;
}
.af-money:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 1px; border-radius: 2px; }
.af-money__tip {
  display: none;
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 60;
  width: max-content;
  padding: 6px 10px;
  font-size: var(--font-size-xs);
  font-weight: 400;
  line-height: 1.5;
  letter-spacing: normal;
  white-space: nowrap;
  color: var(--color-accent-on);
  background: var(--color-fg);
  border-radius: var(--radius-md);
  box-shadow: 0 2px 8px rgba(0, 0, 0, .18);
}
.af-money:hover .af-money__tip,
.af-money:focus-visible .af-money__tip { display: block; }

/* ==========================================================================
   表格隔行底色（斑马纹）· 乐哥 2026-09-12
   「这些表格为了看的清楚，错行用很浅的背景色做区分」
   ⚠️ 三个必须处理的冲突（都靠"写在后面 + 特异性不低"来压制）：
     1. hover 高亮：table.css 里的 .table tbody tr:hover 与本规则**同特异性**，
        且 table.css 先加载 → 若只写斑马纹会盖掉 hover。故这里**重写一次 hover** 并放在其后。
     2. 特殊行底色：.af-audit__main（核算清单主指标行）、.af-bd__total（构成合计行）、
        .so-subtotal（交叉表合计行）本就用 --color-surface-2 标出，斑马纹不得盖掉 →
        同等特异性、写在斑马纹之后。
     3. 斑马纹色选 --color-bg(#F5F6F8) 而非 --color-surface-2(#FAFBFC)：后者已被特殊行占用，
        两者若同色则"特殊行"与"普通偶数行"看起来一样，反而更乱。
   作用域：只在显式加了 .table--zebra 的表上生效（默认不动全站表格）。
   ========================================================================== */
.table--zebra tbody tr:nth-child(even) { background: var(--table-row-alt); }
/* 特殊行优先于斑马纹（必须写在斑马纹之后） */
.table--zebra tbody tr.af-audit__main,
.table--zebra tbody tr.af-bd__total,
.table--zebra tbody tr.so-subtotal { background: var(--color-surface-2); }
/* hover 优先于一切（重写以压过上面的斑马纹规则） */
.table--zebra tbody tr:hover { background: var(--table-row-hover); }

/* ==========================================================================
   提成页面（2026-09-12）——「我的提成」方案 1 模块卡堆叠式 +「提成总览」方案 2 侧栏主从式
   依据：docs/UI方案-提成与结算确认.md、.render-check/ui-plan-1.png / -2.png（乐哥拍板）
   铁律：容器一律 .module-card 体系（不新造模块容器）；颜色全走 CSS 变量（零裸 hex）；
        相邻卡片 24px 由 .module-card + .module-card 保证；工具栏控件 44px。
   ⚠️ 类名用 .cm-*（产品类）；对比页专用的 .cmp-* 不进产品代码。
   ========================================================================== */

/* —— 方案 1：金额头 + 类目拆解条 —— */
.cm-hero {
  display: grid;
  grid-template-columns: 300px minmax(0, 1fr);
  gap: var(--space-8);
  align-items: center;
}
.cm-hero__label { font-size: var(--font-size-sm); color: var(--color-muted); }
.cm-hero__value {
  margin-top: var(--space-1);
  font-size: var(--font-size-4xl);
  font-weight: var(--font-weight-semibold);
  letter-spacing: var(--font-letter-spacing-display);
  line-height: var(--font-line-height-tight);
  color: var(--color-fg);
  font-variant-numeric: tabular-nums;
}
.cm-hero__sub {
  margin-top: var(--space-3);
  display: flex; flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
  font-size: var(--font-size-sm);
  color: var(--color-muted);
}
.cm-cat__sub { margin-top: var(--space-1); font-size: var(--font-size-xs); color: var(--color-meta); font-variant-numeric: tabular-nums; }

/* 类目分组头（明细卡内每组一行） */
.cm-grouphead { display: flex; align-items: baseline; gap: var(--space-3); margin-bottom: var(--space-3); }
.cm-grouphead__name {
  display: inline-flex; align-items: center; gap: var(--space-2);
  font-size: var(--font-size-sm); font-weight: var(--font-weight-semibold); color: var(--color-fg);
}
.cm-grouphead__meta { font-size: var(--font-size-xs); color: var(--color-muted); }
.cm-grouphead__amt { margin-left: auto; font-size: var(--font-size-sm); font-weight: var(--font-weight-semibold); color: var(--color-fg); font-variant-numeric: tabular-nums; }
.cm-more { margin-top: var(--space-2); display: flex; justify-content: flex-end; }
/* 窄屏专用副行（桌面隐藏）：把被折叠的「计算基数 · 点位」并进达人单元格，保证 AC-04 三项不缺 */
.cm-narrow-sub { display: none; }
/* 金额列禁止折行（窄屏下必须整串完整显示） */
.cm-table td:last-child, .cm-table th:last-child { white-space: nowrap; }

/* —— 方案 2：侧栏主从式 —— */
.cm-master {
  display: grid;
  grid-template-columns: 340px minmax(0, 1fr);
  gap: var(--space-6);
  align-items: start;
}
.cm-plist { display: flex; flex-direction: column; gap: 2px; max-height: 460px; overflow-y: auto; }
.cm-plist__hd { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); margin-bottom: var(--space-3); }
.cm-plist__count { font-size: var(--font-size-xs); color: var(--color-meta); font-variant-numeric: tabular-nums; }
.cm-pitem {
  display: flex; align-items: center; gap: var(--space-3);
  width: 100%; padding: var(--space-2) var(--space-3);
  border: none; border-radius: var(--radius-md);
  background: transparent; text-align: left; cursor: pointer;
  transition: background-color var(--motion-fast) var(--motion-ease-standard);
}
.cm-pitem:hover { background: var(--color-surface-2); }
.cm-pitem:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.cm-pitem.is-active { background: var(--color-primary-50); }
.cm-pitem__meta { flex: 1; min-width: 0; }
.cm-pitem__name { display: block; font-size: var(--font-size-sm); font-weight: var(--font-weight-medium); color: var(--color-fg); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cm-pitem__roles { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 3px; }
.cm-pitem__amt { font-size: var(--font-size-sm); font-weight: var(--font-weight-semibold); color: var(--color-fg); font-variant-numeric: tabular-nums; white-space: nowrap; }

.cm-heroline { display: flex; align-items: center; gap: var(--space-3); }
.cm-heroline__meta { min-width: 0; }
.cm-heroline__name { font-size: var(--font-size-lg); font-weight: var(--font-weight-semibold); color: var(--color-fg); }
.cm-heroline__sub { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: 3px; }
.cm-heroline__amt { margin-left: auto; text-align: right; }
.cm-heroline__amt-label { font-size: var(--font-size-xs); color: var(--color-muted); }
.cm-heroline__amt-val {
  font-size: var(--font-size-2xl); font-weight: var(--font-weight-semibold); color: var(--color-fg);
  font-variant-numeric: tabular-nums; letter-spacing: var(--font-letter-spacing-display);
}
.cm-catgrid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-3); }
.cm-catbox { padding: var(--space-3); border: 1px solid var(--color-border-soft); border-radius: var(--radius-md); background: var(--color-surface-2); }
.cm-catbox__label { font-size: var(--font-size-xs); color: var(--color-muted); }
.cm-catbox__val { margin-top: var(--space-1); font-size: var(--font-size-lg); font-weight: var(--font-weight-semibold); color: var(--color-fg); font-variant-numeric: tabular-nums; }
.cm-catbox__sub { margin-top: 2px; font-size: var(--font-size-xs); color: var(--color-meta); font-variant-numeric: tabular-nums; }
.cm-catbox--total { background: var(--color-accent-bg); border-color: var(--color-primary-200); }
.cm-catbox--total .cm-catbox__label { color: var(--color-accent-text); }

/* 可点的类目卡 = 提成明细页的**类目筛选器**（2026-09-15 乐哥：「点某个类目 → 只看它 → 快速核对」）。
   ⚠️ 新增 `--pick` 修饰类承载"可点"三态，**不动 .cm-catbox 本体** ——
      达人结算页也用同一套类名，在本体上加 cursor:pointer 会让那页的纯展示卡"看着能点"（假可点）。
   三态都要给反馈：默认（能点）/ hover（即将生效）/ is-active（当前生效）。
   只做 hover 不做 active 的话，用户切完看不出"现在是哪一个在生效"，表格少了一半行会以为漏数。 */
.cm-catbox--pick { cursor: pointer; transition: border-color var(--motion-fast) var(--motion-ease-standard), box-shadow var(--motion-fast) var(--motion-ease-standard); }
/* hover 用**边框 + 阴影**而不是换底色：卡片默认底就是 `--color-surface-2`（项目里当 hover 底用的那一档），
   两者同色 → 改背景等于没反馈。 */
.cm-catbox--pick:hover { border-color: var(--color-primary-200); box-shadow: var(--shadow-sm); }
.cm-catbox--pick:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.cm-catbox--pick.is-active { border-color: var(--color-accent); background: var(--color-accent-bg); }
.cm-catbox--pick.is-active .cm-catbox__label { color: var(--color-accent-text); }
/* 「筛选中」小字：给当前生效的那张卡一个明确标记（只靠边框色差，在浅色屏上不够醒目） */
.cm-catbox__on { font-size: var(--font-size-xs); color: var(--color-accent-text); }
.cm-catgrid__tip { margin-top: var(--space-2); }
/* 标题行的筛选态胶囊（含取消按钮）：滚动到表格时卡片已出视野，必须在这儿再写一次"已筛选" */
.cm-filter-tag {
  display: inline-flex; align-items: center; gap: var(--space-1);
  padding: 2px var(--space-2); border-radius: 999px;
  background: var(--color-accent-bg); color: var(--color-accent-text);
  font-size: var(--font-size-xs); font-variant-numeric: tabular-nums;
}
.cm-filter-tag__x {
  display: inline-flex; align-items: center; justify-content: center;
  width: 16px; height: 16px; padding: 0; border: 0; border-radius: 50%;
  background: transparent; color: inherit; cursor: pointer;
}
.cm-filter-tag__x:hover { background: var(--color-primary-200); }
/* 总览页「可下钻」的角色金额：默认与其它数字同观感（不做成蓝链接，财务表格里满屏蓝会乱），
   但 hover 变主色 + 虚线下划线 —— 既保持扫读性，又让人发现"这里能点"。 */
.co-drill { cursor: pointer; border-bottom: 1px dashed transparent; transition: color var(--motion-fast) var(--motion-ease-standard); }
.co-drill:hover { color: var(--color-accent-text); border-bottom-color: var(--color-accent); }

/* rebuild dry_run 影响面报告（方案 2 顶部「重建人员明细」弹窗） */
.cm-report { display: flex; flex-direction: column; gap: var(--space-4); }
.cm-report__kpis { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-3); }
.cm-report__kpi { padding: var(--space-3); border: 1px solid var(--color-border-soft); border-radius: var(--radius-md); background: var(--color-surface-2); }
.cm-report__kpi-label { font-size: var(--font-size-xs); color: var(--color-muted); }
.cm-report__kpi-val { margin-top: 2px; font-size: var(--font-size-lg); font-weight: var(--font-weight-semibold); color: var(--color-fg); font-variant-numeric: tabular-nums; }
.cm-report__sec { font-size: var(--font-size-sm); font-weight: var(--font-weight-semibold); color: var(--color-fg); }

/* —— 工作台首页「我的提成」卡片 —— */
.my-comm-card { cursor: pointer; transition: box-shadow var(--motion-fast) var(--motion-ease-standard); }
.my-comm-card:hover { box-shadow: var(--shadow-md); }
.my-comm-card:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.my-comm-card__title { display: inline-flex; align-items: center; gap: var(--space-2); color: var(--color-fg); }
.my-comm-card__amount { font-size: var(--font-size-3xl); font-weight: var(--font-weight-semibold); color: var(--color-fg); font-variant-numeric: tabular-nums; letter-spacing: var(--font-letter-spacing-display); line-height: var(--font-line-height-tight); }
.my-comm-card__label { margin-top: var(--space-1); font-size: var(--font-size-xs); color: var(--color-muted); }
.my-comm-card__cats { margin-top: var(--space-3); font-size: var(--font-size-sm); color: var(--color-fg-2); }

/* —— 排期表单：每人点位（三类角色）—— */
.member-rate-list { display: flex; flex-direction: column; gap: var(--space-2); }
.member-rate-row { display: flex; align-items: center; gap: var(--space-3); min-height: 44px; }
.member-rate-row__name { flex: 1; min-width: 0; display: flex; align-items: center; gap: var(--space-2); font-size: var(--font-size-sm); color: var(--color-fg); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.member-rate-row__input { flex: 0 0 132px; }
.member-rate-row__state { flex: 0 0 auto; font-size: var(--font-size-xs); }
.member-rate-hint { margin-top: var(--space-2); display: flex; align-items: flex-start; gap: var(--space-2); font-size: var(--font-size-xs); line-height: 1.7; }
.member-rate-hint--warn { color: var(--color-warning-text); }
.member-rate-hint--info { color: var(--color-muted); }

/* —— 窄屏（≤768px）：方案 1 / 2 统一的收缩策略 —— */
@media (max-width: 768px) {
  .cm-hero { grid-template-columns: minmax(0, 1fr); gap: var(--space-5); }
  .cm-master { grid-template-columns: minmax(0, 1fr); gap: var(--space-4); }
  /* 左栏人员列表 → 横向可滑的人员条 */
  .cm-plist { flex-direction: row; overflow-x: auto; overflow-y: hidden; max-height: none; padding-bottom: var(--space-1); }
  .cm-pitem { flex: 0 0 auto; width: auto; padding-right: var(--space-4); }
  .cm-pitem__roles { display: none; }
  .cm-catgrid { grid-template-columns: minmax(0, 1fr); }
  /* 明细细表渐进披露：隐去 直播时间 / 计算基数 / 点位，语义折进达人单元格副行（AC-04 三项仍在） */
  .cm-c-time, .cm-c-base, .cm-c-rate { display: none; }
  .cm-narrow-sub { display: block; }
  .cm-table th, .cm-table td { padding-left: var(--space-2); padding-right: var(--space-2); }
  .cm-table td { overflow-wrap: break-word; }
  .cm-table td:first-child .mono, .cm-table th:first-child { font-size: var(--font-size-xs); }
  .cm-table td:first-child { width: 118px; }
  .cm-table td:last-child { min-width: 78px; }
  .cm-heroline { flex-wrap: wrap; row-gap: var(--space-3); }
  .cm-heroline__amt { margin-left: 0; width: 100%; text-align: left; }
  .cm-plist__count { white-space: nowrap; }
  .cm-report__kpis { grid-template-columns: minmax(0, 1fr); }
  .member-rate-row { flex-wrap: wrap; }
  .member-rate-row__input { flex: 1 1 132px; }
}

/* ⚠️ 已废弃（2026-09-15 晚）：`.member-rate-group`（每人点位分组壳）随
   「按人配点位（助播 / 商务助理）」一起下线 —— 它只被已删除的 `rateGroupHtml()` 使用。
   商务侧的逐人点位是**平铺列表**，只用下面的 `.member-rate-list` / `.member-rate-row`。 */

/* 人员成本页 tab 条：窄屏 6 个 tab 排一行会撑出横向溢出 → 允许换行。
   只作用于本页（#ps-tabs），不动全局 .seg（其他页 tab 数少、行为不变）。 */
@media (max-width: 768px) {
  #ps-tabs { flex-wrap: wrap; padding: 4px; }
  #ps-tabs .seg__btn { flex: 1 1 auto; }
}

/* ==========================================================================
   提成总览：人员表格（2026-09-12 乐哥要求「一行一行」替代原左右分栏）
   · .co-row 整行可点展开（所以 cursor:pointer + hover 反馈要明显）
   · .co-expand 是展开区容器：用 surface-2 与表体区分，避免与相邻行视觉粘连
   ========================================================================== */
.co-row { cursor: pointer; }
.co-row.is-open { background: var(--color-surface-2); }
.co-toggle { color: var(--color-muted); }
.co-ops { white-space: nowrap; }
.co-ops .btn + .btn { margin-left: var(--space-2); }
.co-expand { padding: var(--space-4); background: var(--color-surface-2); }
/* 手动校准弹窗的「校准范围」提示条（2026-09-15 乐哥：「校准是校准那个岗位、那一场，
   还是所有的提成」）—— 校准的实际粒度是「人 × 月」，会把该人该月**全部岗位、全部场次**
   的提成合在一起改。不写清楚，财务会以为是按岗位/按场校准（那两者都不存在）。
   用浅主色底 + 左侧主色竖条：一眼可见、但不与弹窗里的输入区抢注意力。 */
.co-adj-scope {
  margin-top: var(--space-3);
  padding: var(--space-3);
  border: 1px solid var(--color-primary-200);
  border-left-width: 3px;
  border-radius: var(--radius-md);
  background: var(--color-accent-bg);
  color: var(--color-accent-text);
  font-size: var(--font-size-sm);
  line-height: 1.6;
}

/* ==========================================================================
   达人结算：行内展开「业绩构成」（2026-09-12 乐哥需求）
   关联直播的按场次一行、未关联的归当月私域一行；系数只在展开层展示。
   ========================================================================== */
.st-row { cursor: pointer; }
/* 展开中的主行：底色与展开区一致 + 去掉下边框 → 主行与展开块**读成一个整体**（不是两块） */
.st-row.is-open,
.st-row.is-open:hover { background: var(--color-bg); }
.st-row.is-open > td { border-bottom-color: transparent; }
/* （已删除）.st-toggle —— 首列「展开箭头」单元格已随「点行跳结算明细页」一并移除（乐哥 2026-09-13），
   这两条（.st-toggle 与展开态点亮）不再匹配任何元素。 */

/* ==========================================================================
   展开区（乐哥 2026-09-12 二次优化：要"显眼、好扫读"）
   三条视觉手段，都在既有 token 内：
     ① 分界：底色下沉到页面底（--color-bg）+ 2px 上边界线 → 与上方白表格明确分开
     ② 主次：汇总从"一行平铺 14px"改为「标签在上 / 数字在下的 KPI 格」，合计基数放大加粗
     ③ 顺序：表头用 .th-sub 标出 计算基础 → 各维度之和 → 乘积结果，引导从左到右读
   ========================================================================== */
.st-drill {
  padding: var(--space-4) var(--space-4) var(--space-4);
  background: var(--color-bg);                 /* 下沉一档（原 surface-2 太接近白色，看不出展开） */
  border-top: 2px solid var(--color-border);   /* 明确上边界：一眼看出"从这里开始是展开内容" */
}
/* ⚠️ 桌面端把展开面板宽度**钳到卡片可见宽**（实测踩过，必须保留这条）：
   主表 13 列的内容宽度是 1379px，比卡片可见宽 1134px 宽 → `.table-wrap` 会横向滚动；
   展开行 `<td colspan=13>` 实测宽 1205px，若面板跟着撑满，
   最关键的「合计基数」KPI 格与「该行佣金」列会**落到可见区之外**（实测右侧还差 43px），
   财务得先横向滚动才看得到金额 —— 正是乐哥说的"看不出重点"的元凶之一。
   宽度算式全部用既有 token：视口 − 侧边栏 − 页面左右留白 − 展开行左右内边距 − 卡片边框。
   sticky left 让面板在横向滚动时钉在可见区左侧，不会跟着跑出去。 */
@media (min-width: 1024px) {
  .st-drill {
    position: sticky;
    left: 0;
    width: calc(100vw - var(--sidebar-width) - var(--page-padding) * 2 - var(--space-3) * 2 - 2px);
    max-width: 100%;
  }
}
/* 展开区标题条：给这块内容一个"名字"，扫读时先看到它 */
.st-drill-head {
  display: flex; align-items: center; gap: var(--space-2);
  margin-bottom: var(--space-3);
}
.st-drill-head svg { flex: none; color: var(--color-muted); }
.st-drill-head__t { font-size: var(--font-size-sm); font-weight: var(--font-weight-semibold); color: var(--color-fg); }
.st-drill-head__meta { margin-left: auto; font-size: var(--font-size-xs); color: var(--color-meta); }
.st-drill-hint {
  display: flex; align-items: flex-start; gap: var(--space-2);
  padding: var(--space-3); margin-bottom: var(--space-3);
  border-radius: var(--radius-md);
  background: var(--color-warning-bg); color: var(--color-warning-text);
  font-size: var(--font-size-sm);
}
/* 汇总：KPI 格（标签在上、数字在下）——「合计基数」为主，放大一级 + 主文字色
   ⚠️ 2026-09-14 与提成明细的 `.cm-catbox` 统一（乐哥反馈「达人结算二级页和提成总览不一样」）：
      原本这里是 `surface 底 + 阴影无边框`，提成那边是 `surface-2 底 + 1px 边框`，
      同为「二级页顶部的 3 格类目汇总」，两套皮 → 看着不是一套东西。
      现统一取提成那套（乐哥拍板「统一为有边框」）：浅底 + 1px 细边框、去掉阴影。
      边框比阴影在浅色底上边界更清晰，也更接近全站卡片的统一语言。
   ⚠️ 改这里会**同时影响**达人结算列表页的行内展开区（同一个 .st-drill 组件）——
      这是有意的：同一个组件只该有一套皮。 */
.st-drill-kpis {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-3); margin-bottom: var(--space-4);
}
.st-drill-kpi {
  padding: var(--space-3);
  background: var(--color-surface-2);
  border: 1px solid var(--color-border-soft);
  border-radius: var(--radius-md);
}
.st-drill-kpi__k { font-size: var(--font-size-xs); color: var(--color-muted); }
.st-drill-kpi__v {
  margin-top: var(--space-1);
  font-size: var(--font-size-lg); font-weight: var(--font-weight-semibold); color: var(--color-fg-2);
  font-variant-numeric: tabular-nums;
}
/* 主数字：合计 —— 财务最关心的那个，放大到 20px + 主文字色。
   底色/边框对齐提成明细的 `.cm-catbox--total`（强调底 + 强调边框），
   使两页的「合计格」在整套格子里以同样方式跳出来。 */
.st-drill-kpi--main {
  background: var(--color-accent-bg);
  border-color: var(--color-primary-200);
}
.st-drill-kpi--main .st-drill-kpi__v {
  font-size: var(--font-size-xl); color: var(--color-fg);
}
.st-drill-diff { color: var(--color-warning-text); }
.st-drill-tag {
  display: inline-block; padding: 0 var(--space-2); border-radius: var(--radius-sm);
  background: var(--color-surface); color: var(--color-fg-2); font-size: var(--font-size-xs, 12px);
  /* nowrap 必须加：「当月私域」4 字在固定列宽里会被折成两行（实测踩过），
     标签一旦换行就把整行撑高、看着像坏了 */
  white-space: nowrap;
}
.st-drill-tag--priv { background: var(--color-warning-bg); color: var(--color-warning-text); }
/* ---- 展开区「分列展示」：线上佣金 / 线下应结（乐哥 2026-09-12）----
   原来在一个单元格里纵向堆叠各维度，线上金额往往占大头、把"我方要付的线下额"淹没了。
   改为横向分列：一列线上、一列线下应结 → 老板一眼看出"还要给这个达人结多少钱"。
   · 线上佣金：平台直付，我方不付 → **次要色弱化**
   · 线下应结：**我方实际要付的** → **主色加粗**，该行的重点读数
   每列下方 .st-col-sub 给构成（如「线下 2% + 年框 3%」），细分金额放 title 悬停看。 */
.st-col-on {
  color: var(--color-muted);            /* 弱化：不是我们要付的钱 */
  font-feature-settings: "tnum", "lnum";
}
.st-col-off {
  /* ⭐ 「线下应结」是全表最重要的读数：本期我方要付给达人的钱（乐哥 2026-09-13 要求更突出）
     → 主色蓝 + 字号升一档 + 加粗。
     与左侧可跳转的场次编号（.cell-link，主色 500、常规字重、小字号）靠"更深 + 更大 + 更粗"区分，
     一个是"能点"，一个是"要付的钱"，不会混。 */
  color: var(--color-primary-600);
  font-size: var(--font-size-base);
  font-weight: var(--font-weight-semibold);
  font-feature-settings: "tnum", "lnum";
}
.st-col-off--zero { color: var(--color-muted); font-weight: var(--font-weight-regular); }
.st-col-sub {
  margin-top: 1px;
  color: var(--color-muted);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-regular);
  line-height: 1.35;
  white-space: nowrap;
}
/* 展开区里两列的单元格：不再参与"行高撑开"，让小字紧贴金额 */
.st-drill .table--sub tbody td.st-col-online,
.st-drill .table--sub tbody td.st-col-offline { vertical-align: top; padding-top: var(--space-2); }

/* ⚠️ 2026-09-14 乐哥拍板「所有列表统一标准」→ **删除本块的表头皮覆盖**（第四套皮）。
   原设计与注释：
     「展开区明细表：与主表拉开差异 —— 表头更弱、行更高、佣金列加重
      （主表表头 44px 灰底；这里表头透明、行高更大，避免"两处表头长得一样"看串行）」
     → 实测：`transparent 底 + 34px 高 + 底对齐`。
   为什么删：乐哥的原话是「列与列之间的间隔、列头的高度和颜色，很多表格都不一致」、
   「你要不统一定一个标准，所有列表页面都按照这个标准改」——
   项目里因此累计了**四套表头皮**（主表 44px 灰底 / 子表 28px 透明 / st-comp 34px 透明 /
   本块 34px 透明底对齐）。统一优于局部区分：展开区与主表的层次现在由**容器边界 + 缩进**承担
   （`.st-drill` 自身的内边距与左侧留白），不再靠"表头长得不一样"。
   保留 `vertical-align: bottom` 已无意义（主表未设、两行表头本就是居中），一并移除。 */
.st-drill .table--sub tbody td {
  padding-top: var(--space-3);
  padding-bottom: var(--space-3);
  background: transparent;
}
.st-drill .table--sub tbody tr:hover td { background: var(--color-surface-2); }
/* 场次编号：字号略小、等宽，作为"行标签"；其下的人员小字弱化 */
.st-drill .table--sub tbody td:first-child { font-size: var(--font-size-sm); }
.st-drill .table--sub tbody td:first-child .cell-sub { margin-top: var(--space-1); color: var(--color-meta); }
/* 佣金列：整块最重的数字 —— 加粗 + 主文字色 + 稍大一号 */
.st-drill .table--sub tbody td.st-drill-amt {
  font-weight: var(--font-weight-semibold);
  font-size: var(--font-size-base);
  color: var(--color-fg);
}
/* 私域行：与直播场次行区分（浅黄底，与「当月私域」标签同源） */
.st-drill .table--sub tbody tr.st-drill-row--priv td { background: var(--color-warning-bg); }
.st-drill .table--sub tbody tr.st-drill-row--priv:hover td { background: var(--color-warning-bg); }

/* ==========================================================================
   达人结算：业绩归属「取数规则」备注（乐哥 2026-09-12）
   文案来自服务端 /shop-orders/attribution-rule，前端原样渲染。
   ========================================================================== */
.st-rule { margin-bottom: var(--space-3); }
/* 提示条 · 统一形态（2026-09-14 乐哥：「不要做成现在提成总览里这种**白底**的」）
   ---------------------------------------------------------------
   改前：`background: --color-surface-2`（#FAFBFC，几乎与卡片同色）+ 4px 圆角 + 左竖线
        → 看着就是"白底"，不够醒目。这正是乐哥点名要改的那一条。
   改后：浅蓝底（--notice-bg）+ 8px 圆角 + 蓝图标，与 .an-banner / .alert 完全同规格。
   ⚠️ 去掉左侧竖线：图片里那种是"整块浅底"，没有色条。 */
.st-rule__inner {
  display: flex; align-items: flex-start; gap: var(--notice-gap);
  padding: var(--notice-pad-y) var(--notice-pad-x);
  border-radius: var(--notice-radius);
  border: 1px solid var(--notice-border);
  background: var(--notice-bg);
  color: var(--notice-fg);
  font-size: var(--font-size-sm);
  line-height: 1.6;
}
/* 图标垂直对齐：16px 图标在首行行盒（1.6em = 22.4px @14px）内居中
   → 下移 (1.6em − 16px) / 2 = 3.2px。用 em 表达行高，字号一变自动跟随。
   ⚠️ 必须用 align-self: flex-start（对齐首行）而不是容器的 align-items:center，
      提示条常是多行，整体居中会让图标跑到段落中间。 */
.st-rule__inner svg { flex: none; align-self: flex-start; margin-top: calc((1.6em - 16px) / 2); color: var(--notice-ico); }

/* 表头副标题：用于在列名下方标注口径（如「无需结算」「不含线上」）—— 2026-09-12
   2026-09-12 二次：改 10.5px 太小不可读 → 用 --font-size-xs，并在展开区表头里兼作"读法引导" */
.th-sub {
  display: block;
  font-weight: var(--font-weight-regular);
  font-size: var(--font-size-xs);
  color: var(--color-muted);
  white-space: nowrap;
  line-height: 1.35;
}
/* 表头旁的「口径提示」图标：圆圈感叹号，**说明只在悬停时以浏览器原生气泡显示**
   （乐哥 2026-09-12：不要把说明文字摊在表头占地方）。
   ⚠️ 用原生 title 而非 CSS 气泡：表格外层 .table-wrap{overflow-x:auto} 会裁掉自定义气泡。
   这里只做视觉：图标与列名同行对齐、悬停时有颜色反馈表示"可查看说明"。 */
.th-note {
  display: inline-flex;
  align-items: center;
  vertical-align: middle;
  margin-left: 3px;
  color: var(--color-muted);
  cursor: help;              /* 提示可悬停查看 */
  transition: color var(--motion-fast) var(--motion-ease-standard);
}
.th-note:hover { color: var(--color-accent-text); }
.th-note svg { flex: none; }
/* 该列不参与应付（如线上佣金由平台直付）→ 金额用次要色，从视觉上"退出主读数" */
.st-col-muted { color: var(--color-muted); }
/* 展开区表头副标题：承接「计算基础 → 各维度之和 → 乘积结果」的读法引导，语气更明确 */
.st-drill .table--sub thead .th-sub { color: var(--color-meta); }

/* 窄屏：KPI 三格 → 单列；展开区左右内边距收紧（表格交给 .table-wrap 横向滚动） */
@media (max-width: 768px) {
  .st-drill { padding: var(--space-3); }
  .st-drill-kpis { grid-template-columns: minmax(0, 1fr); gap: var(--space-2); }
  .st-drill-kpi { display: flex; align-items: baseline; gap: var(--space-2); padding: var(--space-2) var(--space-3); }
  .st-drill-kpi__v { margin-top: 0; }
  .st-drill-head { flex-wrap: wrap; }
}


/* 展开区「线下应结」列的年框未计原因提示（资格被拦时出现）：
   写明是「未签年框 / 合同日期未填 / 不在合同期」，避免看到 0 以为算错 */
.st-col-note {
  margin-top: 2px;
  color: var(--color-warning-text);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-regular);
  line-height: 1.35;
  white-space: nowrap;
}

/* 展开区「合计」行（乐哥 2026-09-12）：各行的线上/线下应结必须能加总，
   且「线下应结」合计要与顶部结算单的「应付总额」对得上 */
.st-drill .table--sub tbody tr.st-drill-sumrow td {
  border-top: 2px solid var(--color-border);
  background: var(--color-surface-2);
  font-weight: var(--font-weight-semibold);
  white-space: nowrap;
}
.st-drill .table--sub tbody tr.st-drill-sumrow td:first-child {
  color: var(--color-muted);
  font-weight: var(--font-weight-regular);
}

/* 展开区：该行「未满 T+35」金额（暂不计入结算）—— 灰色提示，避免与已计金额混淆 */
.st-col-pending {
  margin-top: 2px;
  color: var(--color-warning-text);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-regular);
  line-height: 1.35;
  white-space: nowrap;
}

/* 展开区底部：「未满 T+35」合计提示条 —— 醒目（财务给达人结算前必须看到） */
.st-pending-bar {
  display: flex;
  align-items: flex-start;
  gap: var(--notice-gap);
  margin-top: var(--space-3);
  padding: var(--notice-pad-y) var(--notice-pad-x);
  /* 与全站提示条同规格（2026-09-14）：圆角 4→8px、描边用更柔和的 warning-border
     （原来是 --color-warning 实色，#F2A918 太跳）。**橙色语义保留**（这是警示不是说明）。 */
  border: 1px solid var(--notice-warn-border);
  border-radius: var(--notice-radius);
  background: var(--notice-warn-bg);
  color: var(--color-warning-text);
  font-size: var(--font-size-sm);
  line-height: 1.5;
}
/* 图标垂直对齐（首行行高 1.5em = 21px @14px → 下移 (1.5em − 16px) / 2 = 2.5px，原手写 2px 偏上 0.5px） */
.st-pending-bar svg { flex: none; align-self: flex-start; margin-top: calc((1.5em - 16px) / 2); }
.st-pending-bar b { font-weight: var(--font-weight-semibold); }

/* 展开区「非福利款 GSV」列（= GSV − 福利款，线下四类的基数）—— 乐哥 2026-09-12 独立成列，
   不再挤在线下应结格里。颜色与 GSV 列一致（都是基数），靠副标题区分用途。 */
.st-col-ns { font-feature-settings: "tnum", "lnum"; }
.st-drill .table--sub tbody td.st-col-nscol { vertical-align: top; padding-top: var(--space-2); }
.st-drill .table--sub tbody tr.st-drill-sumrow td:nth-child(6) { font-feature-settings: "tnum", "lnum"; }

/* 展开区「未满35天」列（下期再结）—— 乐哥 2026-09-12 独立成列。
   它是**业绩**（本期未计入），故用 warning 色提示；与左侧「本期」各列之间加分隔线，
   避免误读成"本期也算过它"。 */
.st-col-pendcol {
  vertical-align: top;
  padding-top: var(--space-2);
  border-left: 1px dashed var(--color-border);
  border-right: 1px dashed var(--color-border);
}
.st-drill .table--sub thead th.st-col-pendhead {
  border-left: 1px dashed var(--color-border);
  border-right: 1px dashed var(--color-border);
}
.st-col-pending { font-feature-settings: "tnum", "lnum"; }
.st-col-none { color: var(--color-muted); }

/* 页顶归属规则条里的「规则」入口（2026-09-13）：
   完整规则收进 hover 气泡，常驻只留精简一句 → 用下划虚线提示"可悬停/聚焦查看"。 */
.st-rule__more {
  margin-left: var(--space-2);
  color: var(--color-primary-500);
  border-bottom: 1px dashed currentColor;
  cursor: help;
  transition: color var(--motion-fast) var(--motion-ease-standard);
}
.st-rule__more:hover { color: var(--color-primary-600); }

/* ==========================================================================
   提成总览：合计行 + 月度合计突出（乐哥 2026-09-13 要求对齐达人结算页的做法）
   ========================================================================== */
/* 月度合计：财务最关心的数 → 主色 + 加粗（与达人结算页「线下应结」同一套视觉语言）
   ⚠️ 选择器必须带 .cm-table td（特异性 0,2,1）：单类 `.cm-co-total` 会被
      pages.css **之后**加载的 pages-influencer.css / pages-schedule.css 里的表格规则覆盖，
      实测表现为"class 加上了、颜色却没变"（2026-09-13 踩过）。 */
.cm-table td.cm-co-total {
  color: var(--color-primary-600);
  font-weight: var(--font-weight-semibold);
  font-feature-settings: "tnum", "lnum";
}
/* 表尾合计行：与数据行区分（上边框 + 浅底 + 加粗），且不可点、不参与展开 */
.cm-foot-row td {
  border-top: 2px solid var(--color-border);
  background: var(--color-surface-2);
  font-weight: var(--font-weight-semibold);
  white-space: nowrap;
}
/* 「合计（N 人 / N 行）」这一个标签格：置灰、不加粗 —— 它是**说明**，不是数字。
   ⚠️ 2026-09-17 从 `td:nth-child(2)` 改成 `td:first-child`：
   原来绑第 2 格，是因为当时两处合计行（华大对账 / 提成总览）多写了一个空 `<td>`，
   让标签落在了第 2 格；而那两处本身是**错的**（表头 9 列、合计行 10 格 → 整行右移一列，
   数字会显示在错误的列下）。现已把它们改成标签落第 1 格（与其它 3 处合计行一致：
   排期明细 colspan=2、提成总览展开区 colspan=6、带货明细 colspan=3 —— 都用 colspan 合并首格）。
   绑 `:first-child` 后三种写法都能命中，不再依赖"首格是不是空的"。 */
.cm-foot-row td:first-child {
  color: var(--color-muted);
  font-weight: var(--font-weight-regular);
}
/* 同理：合计行里的总额也要保证生效（同上，提高特异性） */
.cm-table td.cm-co-sumtotal,
.cm-foot-row td.cm-co-sumtotal {
  color: var(--color-primary-600);
  font-size: var(--font-size-base);
}

/* 达人结算 · KPI 卡里的「无权查看」占位（金额为 null 时显示「—」）：
   用 muted 而不是 0 —— 0 会被读成"确实没有这笔钱"，与"看不到"是两回事。 */
.st-kpi-hidden { color: var(--color-muted); }

/* ============================================================================
   达人结算 · 结算单覆盖提示条（乐哥 2026-09-13）
   「达人结算，8月里为啥只有2个达人」—— 因为列表只装已生成结算单的达人。
   这条提示把「本月有 N 位做过直播、M 位还没结算单」摆出来并给一键补齐入口。
   警示色：这不是错误，但是**该处理的事**（不补生成，这些达人这个月就看不到）。
   ============================================================================ */
/* ⚠️ 2026-09-14 乐哥：「警示提醒方式没有微信小店的好」→ 改**行内强调**（去色块）
   ----------------------------------------------------------------------------
   改前：`#FEF5E7` 浅黄底 + 1px 边框 + 圆角，整条 1456px 通栏色块（12 万+ 像素）。

   为什么改（像素级对比微信小店参考图）：
     · 微信小店全图彩色像素只占 **0.72%**，唯一强调色是橙色 rgb(251,157,59)，
       且**只用在「待发货」这类几个字**上；信息层级靠**文字深浅**，不用色块。
     · 我们的大色块会与表格内的状态色（红「否」#E41E3F、橙「未授权」#F2A918）**抢注意力**；
       而且一旦哪页都有黄条，用户就"看不见"了（**警示疲劳**）。

   改后：透明底 + 只留下方 1px 细线；**关键数字用橙字**挑出；按钮改文字链。
   保留「警示」语义靠三处：图标色 + 关键数字橙字 + 与内容之间那条细线。
   ⚠️ 橙色文字用的是 --color-warning-text（#B25C0C），白底对比度 **4.73** > 4.5 达标；
      不能用 --color-warning（#FF8C42），那个对比度只有 2.4，做正文色不合格。
   ⚠️ 不要改回"有底色"：那种做法已被验证会与表内状态色打架（见上）。 */
/* 提示条 · 统一形态 + 保留操作按钮（2026-09-14 乐哥定稿）
   ---------------------------------------------------------------
   乐哥：「统一色底，保留按钮」
   本类特殊：**带「一键生成」操作按钮**（不是纯说明）→ 统一底色/圆角/图标，
   但按钮照旧右对齐（用 margin-left:auto 推过去）。
   改前是「透明底 + 底部细线」——与提成总览那条又不一样。 */
.st-cover {
  display: flex; align-items: center; gap: var(--notice-gap); flex-wrap: wrap;
  padding: var(--notice-pad-y) var(--notice-pad-x); margin-bottom: var(--space-4);
  border: 1px solid var(--notice-warn-border); border-radius: var(--notice-radius);
  background: var(--notice-warn-bg);
  font-size: var(--font-size-sm);
  color: var(--color-fg-2);
}
/* 右侧按钮推到最右（原来是靠 justify/内容撑，统一后固定住） */
.st-cover > .btn, .st-cover > button:last-child { margin-left: auto; }
.st-cover:empty { display: none; }
.st-cover__ic { flex: none; display: inline-flex; align-items: center; color: var(--notice-warn-ico); }
.st-cover__txt { flex: 1; min-width: 260px; line-height: 1.7; }
/* 关键数字/关键词用橙字（对齐微信小店「待发货」的做法）——它是本条里唯一的强调手段 */
.st-cover__txt b { color: var(--color-warning-text); font-weight: var(--font-weight-semibold); }
.st-cover .btn { flex: none; }

/* ============================================================================
   品牌佣金 · 通用佣金条 + 待维护（乐哥 2026-09-13）
   需求：「增加个待维护佣金的筛选（我导入订单导入的商品，但是系统里没维护上游佣金的）」
        「或者设置个通用佣金……通用佣金所有商品都是这个佣金率，我特殊维护的除外」
   ============================================================================ */

/* 通用佣金条：已设置用主色（正常态），未设置用警示色（因为没设时待维护商品会算成 0% → 负数） */
/* 提示条 · 统一形态（2026-09-14）：色底/圆角/内边距对齐 --notice-* 规格；
   本条**带「设置通用佣金」按钮**（保留，右对齐）。 */
.cm-general {
  display: flex; align-items: center; gap: var(--notice-gap); flex-wrap: wrap;
  padding: var(--notice-pad-y) var(--notice-pad-x); margin-bottom: var(--space-3);
  border: 1px solid var(--notice-border); border-radius: var(--notice-radius);
  background: var(--notice-bg);
}
.cm-general--warn { border-color: var(--notice-warn-border); background: var(--notice-warn-bg); }
/* 图标（原本**没有图标**，2026-09-14 补上以与全站一致） */
.cm-general__ico { flex: none; display: inline-flex; align-items: center; color: var(--notice-ico); }
.cm-general--warn .cm-general__ico { color: var(--notice-warn-ico); }
/* 右侧按钮推到最右 */
.cm-general > .btn, .cm-general > button:last-child { margin-left: auto; }
/* 未设置时隐藏空壳（还没加载完数据时不该闪一条空框） */
.cm-general:empty { display: none; }
.cm-gb__label { font-size: var(--font-size-sm); font-weight: 600; color: var(--color-primary-700); flex: none; }
.cm-gb__label--warn { color: var(--color-warning-text); }
.cm-gb__v {
  font-size: 22px; font-weight: 700; color: var(--color-primary-700);
  font-variant-numeric: tabular-nums; flex: none;
}
.cm-gb__v--warn { color: var(--color-warning-text); font-size: 18px; }
.cm-gb__d { font-size: var(--font-size-sm); color: var(--color-fg-2); line-height: 1.7; flex: 1; min-width: 220px; }
.cm-gb__d b { color: var(--color-fg); }
.cm-general .btn { flex: none; }
/* 弹窗里的影响面说明块 */
.cm-gb-note {
  grid-column: 1 / -1; margin-top: var(--space-2); padding: var(--space-3);
  border-radius: var(--radius-md); background: var(--color-surface-2);
  border: 1px solid var(--color-border);
  font-size: var(--font-size-sm); color: var(--color-fg-2); line-height: 1.8;
}
.cm-gb-note b { color: var(--color-fg); }

/* 「待维护」徽标：这不是错误、是需要处理的缺口 —— 用警示色（与"未开票"同一档语义） */
.cm-pend-badge {
  display: inline-block; font-size: 11px; line-height: 16px; padding: 0 6px;
  border-radius: var(--radius-sm); white-space: nowrap; font-weight: var(--font-weight-semibold);
  background: var(--color-warning-bg); color: var(--color-warning-text);
  border: 1px solid var(--color-warning-border);
}
/* 待维护行整行浅底纹：一屏扫过去能直接看出"这几行还没配" */
.table tbody tr.cm-pend-row > td { background: var(--color-warning-bg-soft); }
.table tbody tr.cm-pend-row:hover > td { background: var(--color-warning-bg-hover); }
/* 已卖出的金额：红色（已经在算错、最紧急） */
.cm-pend-sold { color: var(--color-danger-strong); font-weight: var(--font-weight-semibold); font-size: var(--font-size-sm); }

/* 提成总览：身份来源标记（2026-09-13，「兼职助播」专用）。
   刻意与角色 badge **视觉区分**：角色 badge 说的是「在直播里担任什么」（商务/助播/商助），
   这个说的是「以什么身份参与」（成员账号 / 兼职助播）。两者若用同一种 badge 样式，
   并排会出现「助播」+「兼职助播」两个看起来同类的标签，容易误读成"身兼两个角色"。
   虚线边框 = "另一维度"的视觉语言，与实心 badge 拉开。 */
.co-src {
  display: inline-flex;
  align-items: center;
  padding: 0 6px;
  height: 18px;
  font-size: var(--font-size-xs);
  color: var(--color-fg-2);
  border: 1px dashed var(--color-border);
  border-radius: var(--radius-sm);
}
.co-src + .pnl-flag { margin-left: 4px; }

/* 提成「待补」标记（2026-09-13）：已确认发放后，又到期进来的提成 = 要补给本人的钱。
   用**橙色**（与"预估"同一套 warning 语义）：都是"钱还没落定"的状态。
   ⚠️ 不用红色：红色在本系统是"涨/正数"的数值色，借来表达"待办"会与金额色冲突。 */
.co-carry {
  margin-top: 3px;
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  color: var(--color-warning-text);
  white-space: nowrap;
  cursor: help;
}
/* 页头汇总徽标：进页面第一眼就要看到「有几笔钱要补」 */
.co-carry-head__badge {
  display: inline-flex;
  align-items: center;
  height: 22px;
  padding: 0 var(--space-2);
  margin-right: var(--space-2);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  color: var(--color-warning-text);
  background: var(--color-warning-bg);
  border: 1px solid var(--color-warning);
  border-radius: var(--radius-sm);
  cursor: help;
}

/* ==========================================================================
   排期盈亏（schedule-detail 的「盈亏」tab）—— 乐哥 2026-09-13
   结论卡最显眼（盈利/亏损一眼看到），其次收入/成本两侧，再逐笔明细。
   ========================================================================== */
.pf-hero {
  display: flex;
  align-items: center;
  gap: var(--space-6);
  padding: var(--space-4);
  border-radius: var(--radius-md);
  margin: var(--space-3) 0;
}
/* ⚠️ 着色遵循项目统一约定（table.css 的 .num-pos / .num-neg）：
   **盈利=红、亏损=绿**（国内红涨绿跌习惯）。2026-09-13 修正 ——
   原来我用「盈利=绿」写反了，与「经营看板」「主播业绩」的红绿语义冲突
   （同一系统里绿色既表示亏损又表示盈利，看的人会误判）。 */
.pf-hero.is-win { background: var(--color-danger-bg); }
.pf-hero.is-loss { background: var(--color-success-bg); }
.pf-hero__main { flex: none; min-width: 220px; }
.pf-hero__k {
  font-size: var(--font-size-sm);
  color: var(--color-muted);
  margin-bottom: var(--space-1);
}
.pf-hero__v {
  font-size: var(--font-size-3xl);
  font-weight: var(--font-weight-semibold);
  font-feature-settings: "tnum", "lnum";
  line-height: 1.2;
}
.pf-hero.is-win .pf-hero__v { color: var(--color-danger); }
.pf-hero.is-loss .pf-hero__v { color: var(--color-success); }
.pf-hero__sub {
  font-size: var(--font-size-sm);
  color: var(--color-muted);
  margin-top: var(--space-1);
}
.pf-hero__side { flex: 1; display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--space-2) var(--space-5); }

/* 收入 / 成本 两侧并排 */
.pf-sides { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-4); margin-bottom: var(--space-4); }
.pf-side {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-4);
}
.pf-side__t {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--color-muted);
  margin-bottom: var(--space-3);
}
.pf-kv {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-1) 0;
  font-size: var(--font-size-sm);
}
.pf-kv span { color: var(--color-muted); }
.pf-kv b { font-feature-settings: "tnum", "lnum"; font-weight: var(--font-weight-medium); }
.pf-kv--strong b { color: var(--color-primary-600); font-size: var(--font-size-base); font-weight: var(--font-weight-semibold); }
.pf-note {
  margin-top: var(--space-3);
  padding-top: var(--space-2);
  border-top: 1px dashed var(--color-border);
  font-size: var(--font-size-xs);
  color: var(--color-muted);
  line-height: 1.5;
}

/* 逐笔费用记录：类目分组行 */
.pf-cat td {
  background: var(--color-surface-2);
  font-weight: var(--font-weight-semibold);
  color: var(--color-fg-2);
}

@media (max-width: 900px) {
  .pf-hero { flex-direction: column; align-items: flex-start; }
  .pf-sides { grid-template-columns: 1fr; }
}

/* 展开区「预估应结」列（本期 + 未满35天预估）—— 乐哥 2026-09-13
   这是财务跟达人核对"总共要结多少"的数，故给一个浅底与左侧「本期」区隔开。
   颜色用主色（与「线下应结」同族），但加浅底让它更醒目；副标题说明差额来自未满部分。 */
.st-col-fcast {
  color: var(--color-primary-600);
  font-weight: var(--font-weight-semibold);
  font-feature-settings: "tnum", "lnum";
}
/* 主表（达人结算列表页）也用「预估应结」列了 —— 乐哥 2026-09-13 要求提到列表页，不必只能展开看。
   ⚠️ 必须写成 `.table tbody td.st-col-fcast`（0,2,2）：上面那条 `.st-col-fcast`（0,1,0）
      会被全局 `.table tbody td`（0,1,2）压过 → 主色**静默失效**，数字仍是默认近黑。
      实测：改前 getComputedStyle(...).color === rgb(28, 30, 33)。
      这是本项目反复踩的同一个坑（`.num-pos` / `.cm-co-total` / `.kpi-card__value` 都中过），
      **规则：给表格单元格上色 / 加粗，选择器里至少要带上 `.table tbody td` 这一层。**
      （展开区那侧不需要：它的规则是 `.st-drill .table--sub tbody tr.st-drill-sumrow td.st-col-fcast`，
        权重 (0,3,3) 本来就压得住。） */
.table tbody td.st-col-fcast {
  color: var(--color-primary-600);
  font-weight: var(--font-weight-semibold);
}
/* 列表页「线下应结」列（乐哥 2026-09-13：「颜色也改下，不要黑色」）。
   与展开区 `.st-col-off` 是**同一个数**（settleTotal 四类之和），故用**同一套视觉**：
   主色蓝 + 半粗，两处看起来一致，不会让人以为是两个不同的值。
   （此前列表页这格只挂了 `is-num num` + 内联 font-weight，没挂颜色类 → 默认近黑。） */
.table thead th.st-col-payable,
.table tbody td.st-col-payable {
  color: var(--color-primary-600);
  font-weight: var(--font-weight-semibold);
}
/* 「本期 | 预估」的分界线：两列同色同粗，靠这条竖线区分主次（本期 = 现在付，预估 = 含未满）。
   与展开区表头 `th.st-col-fcasthead` 的 border-left 同一种处理，两处观感一致。 */
.table thead th.st-col-fcast,
.table tbody td.st-col-fcast {
  border-left: 1px solid var(--color-border);
}

/* ==========================================================================
   T+35 数值展示规范（2026-09-13 乐哥定：全系统统一，不然很乱）
   核心：**一个数 + 状态标签**。含未满 35 天时挂橙色「预估」标签，全满了不挂任何标签
        （标签的出现本身就是信号：没标签 = 这个数已经定了）。
   三类列的处理：
     · 看业绩/看赚亏（GSV、收入、利润）→ 一列（含未满）+「预估」标签
     · 要结算的钱（应结给达人/员工）    → 两列：截止目前应结 ／ 预估应结
     · 结算依据（结算基数、提成基数）    → 一列（**不含**未满）+ 下面这个灰色小字提示
   ⚠️ 结算依据类**不能用**橙色「预估」标签：它的语义与「预估」相反（这列不含未满），
      而且它乘费率就是应结金额 —— 用同一种橙色标签会让人以为两列是一回事。
      所以另立一种视觉：灰色小字，说明"未满多少没算进来"。
   ========================================================================== */
.t35-hint {
  display: block;
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-regular);
  color: var(--color-muted);
  white-space: nowrap;
  cursor: help;
}
/* 金额格里的标签不吃掉小数点的对齐：标签是 inline 的，跟在小字后面不换行 */
td .t35-hint { margin-top: 1px; }

/* 表格单元格里的「预估」标签：比 KPI 卡上的小一号，避免在密集表格里抢视线。
   ⚠️ 用 `.table tbody td .an-tag` 带上表格层：`.an-tag` 本体权重 (0,1,0)，
      会被 `.table tbody td`（0,1,2）的字号压回表格默认值（本项目反复踩的同一个坑）。 */
.table tbody td .an-tag {
  font-size: 11px;
  line-height: 16px;
  padding: 0 5px;
  vertical-align: 1px;
}
.st-drill .table--sub tbody td.st-col-forecast {
  vertical-align: top;
  padding-top: var(--space-2);
  background: var(--color-primary-50);
}
.st-drill .table--sub thead th.st-col-fcasthead {
  background: var(--color-primary-50);
  border-left: 1px solid var(--color-border);
}
.st-drill .table--sub tbody tr.st-drill-sumrow td.st-col-fcast {
  background: var(--color-primary-50);
  font-size: var(--font-size-base);
}

/* ============================================================================
   华大营养对账（应收 / 开票台账）— 2026-09-13
   与「达人结算」同构：分达人主表 + 点行展开商品明细；多一块开票/回款台账。
   ============================================================================ */
.hs-ledger { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-4); }
@media (max-width: 900px) { .hs-ledger { grid-template-columns: 1fr; } }
.hs-ledger__col {
  border: 1px solid var(--color-border); border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4); background: var(--color-surface);
}
.hs-ledger__t {
  font-size: var(--font-size-sm); font-weight: var(--font-weight-semibold); color: var(--color-fg);
  margin-bottom: var(--space-2); padding-bottom: var(--space-2); border-bottom: 1px solid var(--color-border);
}
.hs-ledger__row {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
  padding: 6px 0; font-size: var(--font-size-sm);
}
.hs-ledger__k { color: var(--color-muted); flex: none; }
.hs-ledger__v { color: var(--color-fg); text-align: right; font-variant-numeric: tabular-nums; }

/* 对账金额变了（又有订单满 35 天）：提示「票面要不要跟着改」，用警示色但不做成按钮态 */
.hs-warn {
  display: flex; align-items: flex-start; gap: 6px; margin-top: var(--space-3);
  padding: var(--space-2) var(--space-3); border-radius: var(--radius-sm);
  background: var(--color-warning-bg); color: var(--color-warning-text);
  font-size: var(--font-size-sm); line-height: 1.7;
}
/* 图标垂直对齐（首行行高 1.7em = 23.8px @14px → 下移 (1.7em − 16px) / 2 = 3.9px，原手写 3px 偏上 0.9px） */
.hs-warn svg { flex: none; align-self: flex-start; margin-top: calc((1.7em - 16px) / 2); }

.hs-row:hover { background: var(--color-surface-2); }
.hs-drill { padding: var(--space-2) 0 var(--space-2) var(--space-3); background: var(--color-surface-2); }
.hs-drill .table--sub { background: var(--color-bg); }
/* ⚠️ 2026-09-14 二级明细页去灰底（乐哥：「华大对账明细的 UI 也不一样，列表怎么有灰色底？」）
   上面两行的灰底是**列表页行内展开区**的设计意图（用浅灰把"展开的明细"和"主表"分层）。
   但二级明细页复用了同一套 HTML（detail.js 渲染 `.detail-drill > .hs-drill > table`），
   于是整个表格区域被铺成灰底、看着像"整块禁用/只读"。
   修法：**只在二级页作用域内**改回白底（transparent 露出白卡片），
         列表页展开区的灰底分层**原样保留**（那里是有意的，改了会破坏主表/明细的层次）。
   ⚠️ 不能直接删上面两行 —— 那会连带改掉列表页展开区的观感。 */
.detail-drill .hs-drill,
.detail-drill .hs-drill .table--sub {
  background: transparent;
}
.hs-sub-sep td {
  font-size: var(--font-size-xs); color: var(--color-muted);
  background: var(--color-surface-2); padding: var(--space-2) var(--space-3);
}

/* 合计行（tfoot 是**独立的行组**，thead/tbody 的规则一律覆盖不到它，必须单独写）：
   · 「应收」主色：本条与上文 `.cm-foot-row td.cm-co-sumtotal` 都能给它上色，
     特异性上**本条胜出**（0,2,2 vs 0,2,1）—— 所以改颜色时两条都要看，
     只改一条会出现「改了不生效」的错觉（2026-09-13 反向验证实测踩到：
     只抹掉 cm-co-sumtotal 时合计行仍是主色，排查后才发现本条在管它）。
   · 分界线：tbody/th 的规则覆盖不到 tfoot，漏写合计行那条竖线会断掉。 */
.table tfoot td.st-col-payable { color: var(--color-primary-600); font-weight: var(--font-weight-semibold); }
.table tfoot td.st-col-fcast { border-left: 1px solid var(--color-border); }

/* 「本月订单都还没满 35 天」的行内提示：用警示色而不是 muted —— 它解释的是"为什么这里是 0"，
   muted 会读成"没数据"，而实际是"数据还没到期"。 */
.hs-pend-note { color: var(--color-warning-text); }

/* ---- 分店铺（2026-09-13 追加：华大分店铺结算）---- */

/* 店铺标签：主表每行、展开区标题、台账卡片标题都用它标出「这是哪个店」。
   用主色系而不是中性灰 —— 分店铺是本页的核心区分维度，扫读时要一眼抓得到。 */
.hs-store {
  display: inline-block; font-size: var(--font-size-xs); line-height: 18px; padding: 0 6px;
  border-radius: var(--radius-sm); white-space: nowrap;
  background: var(--color-primary-50); color: var(--color-primary-700);
  border: 1px solid var(--color-primary-200);
}

/* 台账：按店铺各一张卡片（原来是一张卡片两个列，现在外层再套一层店铺分组） */
.hs-led-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-4); }
@media (max-width: 1200px) { .hs-led-grid { grid-template-columns: 1fr; } }
.hs-led-card {
  border: 1px solid var(--color-border); border-radius: var(--radius-lg);
  padding: var(--space-3); background: var(--color-bg);
}
.hs-led-card__hd {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
  padding-bottom: var(--space-2); margin-bottom: var(--space-2); border-bottom: 1px solid var(--color-border);
}
.hs-led-card__amt {
  font-size: var(--font-size-sm); font-weight: var(--font-weight-semibold);
  color: var(--color-fg); text-align: right; font-variant-numeric: tabular-nums;
}
.hs-led-card__amt .cell-sub { display: block; font-weight: var(--font-weight-regular); }
.hs-led-card__actions {
  display: flex; justify-content: flex-end; gap: var(--space-2);
  margin-top: var(--space-3); padding-top: var(--space-3); border-top: 1px solid var(--color-border);
}
/* 卡片内的台账两列在窄卡里要能塌成单列（卡片本身只有半屏宽） */
.hs-led-card .hs-ledger { grid-template-columns: 1fr; gap: var(--space-2); }
@media (min-width: 1500px) { .hs-led-card .hs-ledger { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.hs-led-card .hs-ledger__col { border: none; padding: 0; background: transparent; }

/* 展开区标题：店铺标签 + 达人说明 + 右侧合计（合计靠右、要显眼 —— 财务对的就是这个数） */
.hs-drill__head {
  display: flex; align-items: center; gap: var(--space-2);
  padding: var(--space-1) 0 var(--space-2);
}
.hs-drill__sum { margin-left: auto; font-size: var(--font-size-sm); color: var(--color-fg-2); }
.hs-drill__sum b { color: var(--color-primary-700); font-variant-numeric: tabular-nums; }

/* 展开区分段标题（乐哥 2026-09-13：明细分「已满 35 天」+「未满 35 天」两段）——
   一段是已经能开票的、一段是要等订单满期的，视觉上必须一眼能分开。 */
.hs-drill__sec {
  display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap;
  margin: var(--space-3) 0 var(--space-2); padding-top: var(--space-2);
  border-top: 1px solid var(--color-border);
  font-size: var(--font-size-sm); font-weight: var(--font-weight-semibold); color: var(--color-fg);
}
.hs-drill__sec:first-of-type { margin-top: var(--space-1); }
/* 「未满」段用暖色：不是错误，但必须让人意识到"这批钱还没到账期" */
.hs-drill__sec--pend { color: var(--color-warning-text); }
.hs-drill__sec-tag {
  font-size: 11px; line-height: 17px; padding: 0 7px; border-radius: var(--radius-sm);
  background: var(--color-surface-2); color: var(--color-fg-2); border: 1px solid var(--color-border);
  font-weight: var(--font-weight-regular); white-space: nowrap;
}
.hs-drill__sec--pend .hs-drill__sec-tag {
  background: var(--color-warning-bg); color: var(--color-warning-text); border-color: var(--color-warning-border);
}
.hs-drill__sec-num { margin-left: auto; font-size: var(--font-size-sm); font-weight: var(--font-weight-regular); color: var(--color-fg-2); }
.hs-drill__sec-num b { color: var(--color-fg); font-variant-numeric: tabular-nums; }
.hs-drill__sec--pend .hs-drill__sec-num b { color: var(--color-warning-text); }

/* 分段合计行：两段各有一行合计，用来跟主表「截止目前 / 预估」对账 */
/* ⚠️ 必须带 `.table tbody` 层（0,1,2）—— 单类选择器（0,1,0）会被 .table tbody td 压过 */
.table tbody tr.hs-drill__sum-row > td {
  background: var(--color-surface-2); font-weight: var(--font-weight-semibold); color: var(--color-fg);
}

/* 福利款标记（2026-09-13）：福利款的线上佣金按「福利款对外佣金率」算、不按达人常规线上率，
   所以那一行线上率会明显更低（10% vs 40%）。不打标记会被当成"线上率填错了"。
   用暖色（与"需要注意的特例"语义一致）而不是警示红 —— 它本身不是错误。 */
.hs-wel {
  display: inline-block; margin-left: 6px; font-size: var(--font-size-xs); line-height: 16px;
  padding: 0 5px; border-radius: var(--radius-sm); vertical-align: middle; white-space: nowrap;
  background: var(--color-warning-bg); color: var(--color-warning-text);
  border: 1px solid var(--color-warning-border); font-weight: var(--font-weight-semibold);
}
/* 应付星盟为负的行：标记原因（多半是上游佣金率没配）。用警示红 —— 这确实是需要处理的问题。 */
.hs-neg-tag {
  display: inline-block; margin-left: 6px; font-size: var(--font-size-xs); line-height: 16px;
  padding: 0 5px; border-radius: var(--radius-sm); vertical-align: middle; white-space: nowrap;
  background: var(--color-danger-bg, #FDECEA); color: var(--color-danger-strong);
  border: 1px solid var(--color-danger-border); font-weight: var(--font-weight-semibold);
}

/* 福利款行的整行底纹：让它在明细里成片可辨（一屏多行时比逐行找标签快） */
.table tbody tr.hs-prod-wel > td { background: var(--color-warning-bg); }
.table tbody tr.hs-prod-wel > td:first-child { box-shadow: inset 3px 0 0 var(--color-warning-accent); }

/* 自定义 SKU：等宽字体（编码类内容用等宽更好逐位核对），过长时省略号 + 悬停看全 */
.hs-sku {
  display: inline-block; max-width: 140px; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; vertical-align: bottom;
  font-family: var(--font-family-mono); font-size: var(--font-size-xs); color: var(--color-fg);
}

/* 弹窗里的只读信息块（店铺 + 该店铺应收），与输入框区分开 */
.hs-static {
  display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap;
  padding: 8px var(--space-3); border-radius: var(--radius-sm);
  background: var(--color-surface-2); border: 1px solid var(--color-border);
  min-height: 38px;
}

/* 发票文件选择器（支持 PDF，故不复用只收图片的 .img-upload） */
.hs-file { display: flex; align-items: center; gap: var(--space-3); }
.hs-file__box {
  flex: 1; min-width: 0; padding: 8px var(--space-3);
  border: 1px dashed var(--color-border); border-radius: var(--radius-sm);
  font-size: var(--font-size-sm); color: var(--color-fg-2); cursor: pointer;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.hs-file__box:hover { border-color: var(--color-primary-400); color: var(--color-primary-600); }

/* ==========================================================================
   排期详情 · 订单明细页签（乐哥 2026-09-13）
   点排期编号从提成总览/达人结算下钻过来对数用。规格：订单 + 商品 + 两口径对照 + 自检。
   ========================================================================== */
.sdo-filters { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; }

/* 口径说明条：左侧主色竖线，与页面其他"口径提示"一致（st-pending-bar / hs-tip 同风格） */
.sdo-tip {
  display: flex; gap: var(--space-2); align-items: flex-start;
  background: var(--color-accent-bg); border: 1px solid var(--color-border-soft);
  border-left: 3px solid var(--color-accent);
  border-radius: var(--radius-sm);
  padding: var(--space-3) var(--space-4);
  margin-bottom: var(--space-3);
  font-size: var(--font-size-xs); line-height: 1.9; color: var(--color-fg-2);
}
.sdo-tip b { color: var(--color-fg); }
.sdo-em { color: var(--color-fg); font-weight: var(--font-weight-semibold); }

/* 订单状态构成 */
.sdo-chips { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; margin-bottom: var(--space-3); }
.sdo-chips__k { font-size: var(--font-size-xs); color: var(--color-meta); }
.sdo-chip {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: var(--font-size-xs); color: var(--color-meta);
  border: 1px solid var(--color-border-soft); border-radius: var(--radius-lg, 12px);
  padding: 3px 10px; background: var(--color-surface);
}
.sdo-chip b { color: var(--color-fg); }

/* 商品单元格：多商品单一行内纵向排列，行间虚线分隔 */
.sdo-prod { line-height: 1.5; padding: 2px 0; }
.sdo-prod + .sdo-prod { border-top: 1px dashed var(--color-border-soft); margin-top: 4px; padding-top: 4px; }
/* 商品第 1 行 = 商品名 +（售后状态标签）。
   ── 三次演进（都记着，避免以后来回改）──
   ① 最初：标签放在第 2 行（.sdo-prod__meta）里 → 那一行被挤爆，标签断成两行、该行 90px。
   ② 2026-09-13 上午：标签移到第 1 行，配 `.sdo-prod__head{display:flex}` + 商品名 `nowrap + ellipsis`。
      挤压解决了，但埋下新问题：商品名 nowrap 会把列撑到 **459px**、整表横向滚 **106px**
      （搜「畅」这类长套餐名时，「净额」「状态」列要左右拖才看得到）。
   ③ 2026-09-13 傍晚（乐哥拍板「商品名可折两行」）：商品名**允许折行**、取消截断。
      商品名既已能折行，就不需要 flex + ellipsis 那套了 → head 改回普通流式布局，
      售后标签改成 inline 紧跟文字（折行时自然跟在**末行之后**，不会孤零零浮在右边）。 */
.sdo-prod__head { line-height: 1.45; }
.sdo-prod__head .sdo-after { white-space: nowrap; margin-left: 4px; }
/* 商品名：**允许折行**（乐哥 2026-09-13 傍晚拍板，订单明细表 / 商品汇总表 两处统一）。
   原来是 `max-width:420px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap` —— 单行截断，
   两个表都被它坑过：
     · 商品汇总表：nowrap 把富余宽度霸住不放 → 窄列（自定义SKU / 类型）被压到断行 / 竖排；
     · 订单明细表：nowrap 使该列的 min-content = 全文宽（实测 344px）→ 列被撑到 459px，整表横向滚。
   改成折行后：窄列可以锁死单行、表格不再横向滚动，长名也能看全（占几行由内容自然决定）。
   `overflow-wrap: break-word` 是兜底 —— 万一出现超长且无断点的片段（长英文串 / 长编码）也不会溢出。 */
.sdo-prod__nm {
  white-space: normal; overflow-wrap: break-word; line-height: 1.45;
}
/* 第 2 行（SKU · 类型 · 数量）：子项**一律不许被压缩**（`flex: 0 0 auto` + nowrap）。
   背景（乐哥 2026-09-13 修）：这一行原来是 `flex-wrap:nowrap` 且子项可压缩，
   当总宽超出单元格时子项会被挤扁 →「套餐」竖排、文字在盒内断行、行高被撑高（实测 90px vs 72px）。
   `flex-wrap: wrap` 作为兜底：万一将来又有超宽内容，它会整块换到第二行，而不是挤成一团。 */
.sdo-prod__meta {
  display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap;
  font-size: var(--font-size-xs); color: var(--color-meta); margin-top: 2px;
}
.sdo-prod__meta > * { flex: 0 0 auto; white-space: nowrap; }
/* SKU / 类型 胶囊：**必须显式给字号**（乐哥 2026-09-13 统一）。
   原来不写字号 → 跟着父级走：在「订单明细表」里它们位于 .sdo-prod__meta（12px）内 → 12px；
   在「商品汇总表」里直接放在 td 里（14px）→ 14px。**同一个胶囊在同一页出现两种字号**。
   标签/胶囊按项目惯例统一 12px（与 .st-drill-tag 等一致），改这里两表一起生效。 */
/* ⚠️ 这一行必须 `white-space: nowrap`（乐哥 2026-09-13 修）。
   它是个 15~16 位、带连字符的编码（如 YY013501-0000005）：`normal` 下浏览器会**在连字符处断行**，
   于是「商品汇总」表里每格变 2 行（实测高 35px），11 行累计多占近 300px。
   nowrap 之后它的 min-content = 整串宽（约 115px），表格再也压不动它，只能去压商品名列。 */
.sdo-sku {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: var(--font-size-xs);
  background: var(--color-surface-2); padding: 0 5px; border-radius: var(--radius-sm);
  white-space: nowrap;
}
/* ⚠️ 同样必须 `white-space: nowrap`（乐哥 2026-09-13 修）。
   中文**任意两个字之间都允许断行** → `normal` 下「套餐」被拆成竖排的「套 / 餐」（实测高 40px、2 行），
   这是本次「商品维度 UI 有问题」里最难看的一处。
   注：在「订单明细表」里它位于 .sdo-prod__meta（`> * { white-space:nowrap }`）→ 本来就正常；
   只有「商品汇总表」里它是 td 的直接子元素，才暴露了这个缺陷。 */
.sdo-kind {
  font-size: var(--font-size-xs); border: 1px solid var(--color-border-soft);
  padding: 0 5px; border-radius: var(--radius-sm); white-space: nowrap;
}
.sdo-after { color: var(--color-warning, #B8860B); }
.sdo-unmatched { color: var(--color-danger); font-size: var(--font-size-xs); }

/* ── 「商品汇总」表：把宽度精确让给唯一可换行的商品名列（乐哥 2026-09-13）──────────────
   问题：`table-layout: auto` 下所有列都参与"分配剩余宽度"，商品名列虽然是弹性列却没优先权，
        结果只有 302px（最长的商品名要 344px）→ 长名折成双行、同表行高 46/66 不一致。
   修法：让**除商品名以外的所有列锁死单行**（`nowrap`）。这样它们的 min-content == max-content，
        浏览器压不动它们，只能把富余宽度全部让给唯一还能换行的商品名列。
   ⚠️ 为什么不直接改全站的 `.is-num`：那是 `table.css` 里的公共类，全站几十张表都在用，
      本项目铁律「改公共类前先查复用范围」—— 所以这里**新开一个只给本表用的作用域类**，
      原 `.num` / `.is-num` 一字未动。 */
.sdo-sumtbl thead th.is-num,
.sdo-sumtbl tbody td.is-num,
.sdo-sumtbl tfoot td.is-num { white-space: nowrap; }
/* ⚠️ 这里**不需要**给表头单独写 nowrap —— 全站 `.table thead th` 本来就是 `nowrap`（table.css:27）。
   曾误加过 `.sdo-sumtbl thead th { white-space: nowrap }`，既冗余、配套断言也恒真（假绿），已一并删除。 */

/* 订单号：该列的主信息 → 与其它主信息列同为正常字号（原 12px 与全表 14px 不齐）。
   19 位数字 + 等宽字体，配合加宽后的列宽（190px）刚好一行放下（乐哥 2026-09-13）。 */
.sdo-no { font-size: var(--font-size-sm); }
.sdo-rf { color: var(--color-danger); }
.sdo-ses {
  font-size: var(--font-size-xs); white-space: nowrap;
  background: var(--color-accent-bg); color: var(--color-accent-text);
  padding: 1px 7px; border-radius: var(--radius-lg, 12px);
}
.sdo-st {
  font-size: var(--font-size-xs); white-space: nowrap;
  background: var(--color-surface-2); color: var(--color-fg-2);
  padding: 1px 7px; border-radius: var(--radius-sm);
}
.sdo-st--cancel { background: var(--color-danger-bg); color: var(--color-danger); }

/* 对账自检条：通过=绿框（让财务一眼确认对得上）；异常=红框（口径被破坏，必须显眼） */
.sdo-chk {
  margin-top: var(--space-3); padding: var(--space-3) var(--space-4);
  border: 1px solid var(--color-border-soft);
  border-left: 3px solid var(--color-success);
  background: var(--color-success-bg);
  border-radius: var(--radius-sm);
  font-size: var(--font-size-xs); line-height: 1.95; color: var(--color-fg-2);
}
.sdo-chk b { color: var(--color-fg); }
.sdo-chk--bad { background: var(--color-danger-bg); border-color: var(--color-danger); }

/* 口径说明里的「当前范围」（全部场次 / PQ000009-1）——用底色胶囊，与正文区分开 */
.sdo-scope {
  display: inline-block; margin-left: 8px;
  font-size: var(--font-size-xs); font-weight: var(--font-weight-regular);
  background: var(--color-accent); color: var(--color-accent-on);
  padding: 1px 8px; border-radius: var(--radius-lg, 12px);
}

/* ==========================================================================
   KPI 卡内的可点提示（乐哥 2026-09-13）
   --------------------------------------------------------------------------
   用于「N 张单数据有变化，重新计算」这类"看到问题就能顺手解决"的提示。
   刻意做成**文字链**而不是按钮：4 张卡里通常只有 1 张会出现它，
   做成按钮会显得突兀、也抢了卡片主数字的注意力。
   ========================================================================== */
.kpi-card__act {
  display: block; width: 100%; margin-top: var(--space-1); padding: 0;
  border: 0; background: none; text-align: left; cursor: pointer;
  font-size: var(--font-size-xs); line-height: 1.5;
  color: var(--color-warning-text);
}
.kpi-card__act:hover { text-decoration: underline; }
.kpi-card__act-go { font-weight: var(--font-weight-medium); text-decoration: underline; }
.kpi-card__act:disabled { opacity: 0.6; cursor: default; text-decoration: none; }

/* ==========================================================================
   口径说明条：「完整口径」点击展开（乐哥 2026-09-13）
   --------------------------------------------------------------------------
   改前是 hover 气泡装一整段长文（华大那页 1191 字）—— 读长文别扭、读到一半会消失、
   也没法复制。改成按钮展开：默认只占一行，展开后按主题分小节（小标题 + 要点列表）。
   ⚠️ 与原 .st-rule__more（气泡版）并存：三页改造是分批做的，另一页改造完可一并清掉。
   ========================================================================== */
.st-rule__toggle {
  margin-left: var(--space-2); padding: 0; border: 0; background: none; cursor: pointer;
  font-size: inherit; font-family: inherit; line-height: inherit;
  color: var(--color-primary-500); border-bottom: 1px dashed currentColor;
}
.st-rule__toggle:hover { color: var(--color-primary-600); }
.st-rule__full {
  margin-top: var(--space-2); padding: var(--space-3) var(--space-4);
  background: var(--color-surface-2); border: 1px solid var(--color-border-soft);
  border-radius: var(--radius-sm);
  font-size: var(--font-size-xs); line-height: 1.9; color: var(--color-fg-2);
}
.st-rule__sec + .st-rule__sec {
  margin-top: var(--space-3); padding-top: var(--space-3);
  border-top: 1px dashed var(--color-border-soft);
}
.st-rule__sec-t { font-weight: var(--font-weight-medium); color: var(--color-fg); margin-bottom: 2px; }
.st-rule__list { margin: 0; padding-left: 18px; }
.st-rule__list li { margin: 0; }

/* ==========================================================================
   结算单展开区 · 「未满 35 天」分段（乐哥 2026-09-13）
   --------------------------------------------------------------------------
   背景：8 月 13 张结算单里 11 张是「全未满」（最大 ¥1,212,806.22 / 2094 单），
   而展开区此前直接返回一句「无业绩明细」—— 未满的钱、单数、场次全都看不到。
   现在把未满部分也**按场次列进同一张表**，用一条分段标题行与已满部分隔开。
   设计要求：既要在视觉上明确"这批还没到期"，又不能让它比"现在能付的钱"还抢眼
   → 用浅灰底 + 左侧虚线，不用红/黄警告色（那是异常的颜色，未满是正常业务状态）。
   ========================================================================== */

/* 分段标题行：跨全表宽的一条小标题 */
.st-drill .table--sub tbody tr.st-drill-segrow td {
  background: var(--color-surface-2);
  border-top: 2px solid var(--color-border);
  border-bottom: 1px solid var(--color-border-soft);
  padding-top: var(--space-2);
  padding-bottom: var(--space-2);
  white-space: nowrap;
}
.st-drill-segrow__t {
  font-weight: var(--font-weight-semibold);
  color: var(--color-fg-2);
  margin-right: var(--space-3);
}
.st-drill-segrow__d { color: var(--color-meta); font-size: var(--font-size-xs); }

/* 未满行：浅灰底 + 首列左侧虚线，表明"这一段的性质与上面不同"（还没到期） */
.st-drill .table--sub tbody tr.st-drill-pendrow td {
  background: var(--color-surface);
  color: var(--color-fg-2);
}
.st-drill .table--sub tbody tr.st-drill-pendrow td:first-child {
  border-left: 2px dashed var(--color-border);
}
.st-drill .table--sub tbody tr.st-drill-pendrow:hover td { background: var(--color-surface-2); }

/* 未满合计行：比正常合计更弱（它是"还没到期的预估"，不是现在能付的钱） */
.st-drill .table--sub tbody tr.st-drill-sumrow--pend td {
  border-top: 1px dashed var(--color-border);
  color: var(--color-meta);
}
.st-drill .table--sub tbody tr.st-drill-sumrow--pend td:first-child { color: var(--color-meta); }

/* ==========================================================================
   「本期佣金构成」—— 达人结算展开区（乐哥 2026-09-13）
   原话：「线上佣金/线下·机构/年框/线下·返点/激励佣金 怎么都是空的，我都不知道每个项目
         佣金多少；展开明细只有应结佣金，但结算的是哪个项目的佣金、什么点数结算，我都看不到」
   实测根因：某达人**配了年框 3%** 却没计入（未签合同），页面只有静默的 ¥0.00 + 「无适用维度」，
   一个字都不解释。本区块把五个项目逐项摊开（费率 / 基数 / 金额 / **为什么是这个数**）。
   放在业绩构成表**之前**：先给结论（该付多少、什么点数），再给依据（哪几场算出来的）。
   ========================================================================== */
.st-comp { margin-bottom: var(--space-4); }
/* 与「业绩构成」标题条同款，但用分隔线把两个区块分开，避免看成一整块 */
.st-comp__head {
  display: flex; align-items: center; gap: var(--space-2);
  margin-bottom: var(--space-3);
  padding-bottom: var(--space-2);
  border-bottom: 1px solid var(--color-border-soft);
}
.st-comp__head svg { flex: none; color: var(--color-accent); }
.st-comp__t { font-size: var(--font-size-sm); font-weight: var(--font-weight-semibold); color: var(--color-fg); }
.st-comp__meta { margin-left: auto; font-size: var(--font-size-xs); color: var(--color-meta); }
.st-comp__empty {
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  background: var(--color-surface-2);
  font-size: var(--font-size-sm); color: var(--color-fg-2);
}
.st-comp__empty b { color: var(--color-fg); }

/* 表格：表头弱化（与业绩构成表保持一致，避免两块表头抢注意力） */
/* ⚠️ 2026-09-14 删除表头皮覆盖（乐哥「所有列表统一标准」）：
   原为 `.st-comp__tbl thead th { background: transparent; color: var(--color-meta);
   font-weight: medium; }` —— 这是**第三套表头皮**（项目里共三套：
   主表 `.table thead th` 浅灰底 44px / 子表 `.table--sub thead th` 透明 28px /
   本表 透明 34px），三者并存就是乐哥反馈的「表头高度和颜色很多表格不一致」。
   现全部并入主表那套，此处不再覆盖任何表头样式。
   注意：tbody 的 `vertical-align: top` 保留（那是内容对齐，与表头无关）。 */
.st-comp__tbl tbody td { vertical-align: top; }

/* 项目名：这一列是"主角"，给主文字色 + 中等字重 */
.st-comp__nm { color: var(--color-fg); font-weight: var(--font-weight-medium); }
/* 「平台直付」小标签：说明这一项不是我方掏钱，避免被误算进应付 */
.st-comp__tag {
  display: inline-block; margin-left: 6px; padding: 0 5px;
  border-radius: var(--radius-sm);
  background: var(--color-surface-2); color: var(--color-meta);
  font-size: var(--font-size-xs); font-weight: var(--font-weight-regular);
}
/* 费率：乐哥要的"什么点数结算"，加粗；「—」表示未配置 */
.st-comp__rate { font-weight: var(--font-weight-semibold); color: var(--color-fg); }
.st-comp__na { color: var(--color-muted); font-weight: var(--font-weight-regular); }
/* 金额：有值时用主色（与「截止目前应结」同色系，一眼认出"这是我方要付的"） */
.st-comp__amt { font-weight: var(--font-weight-semibold); }
.st-comp__amt.is-on { color: var(--color-accent-text); }
/* 状态说明：三种语义各有颜色 —— 未配置=灰（无需行动）、已计入=绿（正常）、
   未计=警示（**这是最需要看的一类**：配了费率却没算出钱，必须显眼） */
.st-comp__st { font-size: var(--font-size-xs); line-height: 1.5; }
.st-comp__st.is-off { color: var(--color-muted); }
.st-comp__st.is-on { color: var(--color-success-text); }
.st-comp__st.is-warn { color: var(--color-warning-text); }
.st-comp__st b { font-weight: var(--font-weight-semibold); }
/* 合计行：与展开区其它合计行同款（上方虚线、次要底色） */
.st-comp__sumrow td {
  border-top: 1px dashed var(--color-border);
  color: var(--color-meta);
}
.st-comp__sumrow td:first-child { font-size: var(--font-size-xs); }
.st-comp__sumrow b { color: var(--color-fg); }

/* 「本表与列表金额不一致」提示条（生成草稿后费率/订单/合同又变过）
   —— 构成表用实时费率，主表用单上快照，两者不等时**必须显式说明**，
   否则用户看到两个不同的数会直接判定"算错了"。配色用警示（不是错误，是"需留意"）。 */
.st-comp__drift {
  display: flex; align-items: flex-start; gap: var(--space-2);
  padding: var(--space-3); margin-bottom: var(--space-3);
  border-radius: var(--radius-md);
  background: var(--color-warning-bg); color: var(--color-warning-text);
  font-size: var(--font-size-xs); line-height: 1.7;
}
/* 图标垂直对齐（首行行高 1.7em，本条字号是 xs=12px → 20.4px → 下移 (1.7em − 16px) / 2 = 2.2px，原手写 1px 偏上 1.2px）
   ⚠️ 用 em 而非 px：本条 font-size 是 --font-size-xs，与其它提示条不同档，px 会写错。 */
.st-comp__drift svg { flex: none; align-self: flex-start; margin-top: calc((1.7em - 16px) / 2); }
.st-comp__drift b { font-weight: var(--font-weight-semibold); }

/* ==========================================================================
   统一「明细页」—— 2026-09-13（乐哥：行展开统一改为下级页面）
   ---------------------------------------------------------------------------
   9 处「详情类」展开改为独立明细页（detail.js 承载），这些样式是它的统一外壳。
   与列表页的关系：点行进明细 → 点「返回」回列表（保留筛选与滚动位置）。
   ⚠️ 全部走设计 token，无硬编码色值；间距用 --space-* 保持全站节奏。
   ========================================================================== */

/* 页头：返回按钮 + 标题（+ 右侧操作区） */
.detail-head {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}
/* 返回：做成明确的"按钮"形态（不是裸文字）—— 技能 §9 要求返回可预测且显眼 */
.detail-back {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  flex: none;
  height: 32px;
  padding: 0 var(--space-3) 0 var(--space-2);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  color: var(--color-fg-2);
  font-family: inherit;
  font-size: var(--font-size-sm);
  cursor: pointer;
  transition: background-color var(--motion-fast) var(--motion-ease-standard),
    color var(--motion-fast) var(--motion-ease-standard),
    border-color var(--motion-fast) var(--motion-ease-standard);
}
.detail-back:hover { background: var(--color-surface-2); color: var(--color-fg); border-color: var(--color-gray-400); }
.detail-back:active { background: var(--color-gray-100); }
.detail-back:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.detail-head__main { flex: 1; min-width: 0; }
.detail-head__act { flex: none; }

/* 内容堆叠：多张卡片之间统一间距 */
.detail-stack > * + * { margin-top: var(--space-4); }

/* 键值网格（成本明细）：两列自适应，长值横跨整行避免被截断 */
.dt-kv { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-2) var(--space-5); }
.dt-kv__row { display: flex; gap: var(--space-2); min-width: 0; font-size: var(--font-size-sm); line-height: 1.7; }
.dt-kv__row--wide { grid-column: 1 / -1; }
.dt-kv__k { flex: none; width: 88px; color: var(--color-muted); }
.dt-kv__v { min-width: 0; color: var(--color-fg); word-break: break-word; }
/* 窄屏收敛为单列，避免两列挤压 */
@media (max-width: 760px) {
  .dt-kv { grid-template-columns: minmax(0, 1fr); }
}

/* 明细页里的「展开区同款内容」（结算 / 华大对账）：
   这两块原本是列表内的展开区（自带 `.st-drill` / `.hs-drill` 的标题条与内边距），
   直接搬进明细页即可，只需去掉它作为"表格内嵌行"时的多余外边距。 */
.detail-drill .st-drill,
.detail-drill .hs-drill { margin-bottom: 0; }

/* ==========================================================================
   工作台首页改造（乐哥 2026-09-13）
   --------------------------------------------------------------------------
   新增：.chart-grid--three（投流消耗 / 今日排期 / 待办 三列）、.adcost（投流消耗展示）
   ========================================================================== */

/* 三列网格：底栏三块（投流消耗 / 今日排期 / 待办提醒）
   ⚠️ 窄屏必须降级为单列，否则每列 ~380px 会把「今日排期」的表格挤到换行。 */
.chart-grid--three { grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 1279px) {
  .chart-grid--three { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 899px) {
  .chart-grid--three { grid-template-columns: minmax(0, 1fr); }
}

/* 投流消耗：主金额大号 + 占 GSV 比的细进度条
   ⚠️ 2026-09-20 删掉「投产比 ROI」那一格（乐哥：「roi 这个整体都不要了」）后，
      以下四条变成死样式、一并移除：
        .adcost__grid（两列 grid）/ .adcost__cell（格子）/ .adcost__k / .adcost__v
      原布局是「两个格子（投产比 / 投流占 GSV）+ 进度条」，现在只剩
      「进度条 + 一行占比说明」—— 占比不再重复呈现两次。
      若将来要再加指标格，从 git 历史里取回这四条即可（当时就是两列布局）。 */
.adcost__main {
  font-size: 26px;
  font-weight: var(--font-weight-semibold);
  color: var(--color-fg);
  font-variant-numeric: tabular-nums;
  line-height: 1.2;
}
.adcost__label { margin-top: 2px; font-size: var(--font-size-xs); color: var(--color-muted); }
/* 占比条：投流 ÷ 净成交 —— 用主色填充，直观表达"投流占多少" */
.adcost__bar {
  margin-top: var(--space-4);
  height: 6px;
  border-radius: 999px;
  background: var(--color-surface-2);
  overflow: hidden;
}
.adcost__bar > span {
  display: block; height: 100%;
  background: var(--color-accent);
  border-radius: 999px;
  transition: width var(--motion-base) var(--motion-ease-standard);
}
.adcost__hint { margin-top: var(--space-2); font-size: var(--font-size-xs); color: var(--color-muted); }

/* 「待维护」行的区分标识（2026-09-14 乐哥选：给页面加区分标识）
   ----------------------------------------------------------------------------
   待维护行有两类，成因与优先级完全不同，但长相相似：
     · 有归属订单 → 订单已成交、只是没人维护业绩（编号要维护后才生成）→ **该尽快补维护**
     · 无归属订单 → 多半是订单还没导入（实测订单库只到 8-29，9 月为 0）→ 暂时不用管
   所以有订单的那类用**警示色**把它挑出来（"这是要处理的"），
   无订单的保持 `.cell-sub` 默认弱化灰（"不用管"）。 */
.perf-pend-note {
  color: var(--color-warning-text);
}

/* ==========================================================================
   月度利润明细表（乐哥 2026-09-14 需求）
   --------------------------------------------------------------------------
   结构：一个月一行 × 收入(2 列) + 支出(三大组动态 N 列) + 总成本/盈亏/盈亏率
   ⚠️ 全部用 `.pl-` 前缀新开作用域类，**不动** .table / .is-num 等公共类
      （项目铁律：改公共类前先查复用范围；新页面新开类最稳）。
   ========================================================================== */
.pl-table { font-variant-numeric: tabular-nums; }
/* 分组表头（"成本 · 达人相关"这一行）：浅底 + 加粗 + 居中，
   与下面一行的细项列名形成层级 —— 不加底色时两级表头看着是一整片，分不清哪个管哪几列。 */
.pl-grouphd {
  text-align: center;
  background: var(--color-surface-2);
  font-weight: var(--font-weight-semibold);
  color: var(--color-fg-2);
  border-bottom: 1px solid var(--color-border);
}
/* 细项表头：比分组头弱一档（字号小、常规字重），层级才立得住 */
.pl-table thead tr:last-child th {
  font-weight: var(--font-weight-regular);
  color: var(--color-fg-2);
}
/* 可下钻单元格：虚线下划线（不用实线，避免与链接/正文混淆）+ hover 变色。
   可点但看着不像按钮，是刻意的 —— 整表几十个可点格，全做成按钮会非常吵。 */
.pl-link {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px dashed var(--color-border);
  cursor: pointer;
  transition: color var(--motion-fast) var(--motion-ease-standard),
              border-color var(--motion-fast) var(--motion-ease-standard);
}
.pl-link:hover,
.pl-link:focus-visible {
  color: var(--color-accent-text);
  border-bottom-color: var(--color-accent-text);
}
.pl-link:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; border-radius: 2px; }
/* 总成本 / 盈亏：整表最该被一眼看到的两列，加重 */
.pl-strong { font-weight: var(--font-weight-semibold); }
/* 月份列：不折行（"2026-08" 断成两行会让每行高度不齐） */
.pl-table tbody td:first-child { white-space: nowrap; }
/* 月份格：可点进「当月达人明细」二级页（乐哥 2026-09-15）
   ──────────────────────────────────────────────────────────────────────────
   乐哥原话：「不要虚线，改成蓝色（就是可以跳转那种，这样更显眼）」
   改前走全站 .pl-link（继承文字色 + 虚线下划线），在整表一堆下钻格里不突出。
   改后 = 表格内可跳转链接的标准形态（`.cell-link` 那套：蓝 #0064E0、无下划线、hover 加下划线）。

   ⚠️ **必须保留 `pl-link` 类**（不是换成 `cell-link`）：本页的下钻事件是
      `box.querySelectorAll('.pl-link')` 统一绑定的，类名一换**点击就失效**（且不报错）。
      故这里用「双类 + 提高特异性」覆盖样式，不动 HTML 上的类名。
   ⚠️ 为什么月份要与其他下钻格（虚线条）不同：两者是**不同层级的入口** ——
      月份去的是**页面级二级页**，其他格是**就地弹层下钻**。
      用两种视觉区分层级，比整表清一色虚线更清楚。
   ⚠️ 特异性说明：`.pl-link.pl-month`(0,2,0) 胜过 `.pl-link`(0,1,0)；
      `.pl-link.pl-month:hover`(0,3,0) 胜过 `.pl-link:hover`(0,2,0) —— 不依赖书写顺序。 */
.pl-link.pl-month {
  color: var(--color-primary-500);
  border-bottom: none;
  font-weight: var(--font-weight-semibold);
}
.pl-link.pl-month:hover,
.pl-link.pl-month:focus-visible {
  color: var(--color-primary-600);
  border-bottom: none;
  text-decoration: underline;
}

/* ==========================================================================
   月度利润明细 · 点月份进的「当月达人明细」二级页（乐哥 2026-09-15）
   --------------------------------------------------------------------------
   结构：本月合计 KPI → 达人明细（**行内展开场次**）→ 项目公共成本 → 底部验算条。
   ⚠️ 展开用「行内子表」而不是弹窗/新页面 —— 乐哥原话「不要跳来跳去，其实不直观」，
      想看某位达人这个月播了哪几场，就地展开即可（数据后端已一并返回，无额外请求）。
   ========================================================================== */
.pmd-table { font-variant-numeric: tabular-nums; }
/* 主行可点展开：必须有 hover 反馈，否则用户不知道这一行能点 */
.pmd-table tbody tr.pmd-row { cursor: pointer; }
/* 斑马纹：本表主行后紧跟**隐藏的展开行**，两者交替 →
   全站斑马纹的 `tbody tr:nth-child(even)` 会全落在隐藏行上、主行一条纹都没有（实测踩到）。
   故由页面按**主行序号**交替加 .is-alt，这里给底色。
   特异性 (0,2,2) > 全站斑马纹 (0,1,2) → 稳胜，且高于它即可不依赖书写顺序。 */
.pmd-table tbody tr.pmd-row.is-alt { background: var(--table-row-alt); }
.pmd-table tbody tr.pmd-row:hover > td { background: var(--color-surface-2); }
.pmd-table tbody tr.pmd-row.is-open > td { background: var(--color-surface-2); }
/* 展开箭头：默认朝右，展开后转 90°（用 transition，不用弹跳缓动——全站禁用弹性缓动） */
.pmd-caret {
  display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; color: var(--color-muted);
  transition: transform var(--motion-fast) var(--motion-ease-standard);
}
.pmd-table tbody tr.pmd-row.is-open .pmd-caret { transform: rotate(90deg); }

/* 展开区 = **主表的兄弟行**（不再是嵌套子表）
   --------------------------------------------------------------------------
   ⚠️⚠️ 为什么展开行不能嵌一张子表（2026-09-17 乐哥第二次报同一条 bug）：
      子表是**另一张表**，列宽由它自己的内容独立计算，与外层表头列宽毫无关系 →
      逐格错开。实测（1900px 视口 · 2026-09 数据）外层 13 列宽
      = 50/150/82/132/132/140/138/130/119/117/131/134/99，
      而嵌套子表 13 格全都是 ≈116px（内容相近 → 浏览器平均分），
      「第 1 场」因此落在 **T+35 GSV** 表头下、GSV 值落在「未满 35 天」下，最多偏 92px。
      ⇒ 展开行做兄弟行后，列宽由同一张表统一分配，**对齐是布局的自然结果**，
        不再需要任何"手工同步宽度"（那种做法改一列就会漂，且改一处漏一处）。
   ⚠️ `tr[hidden]` 显式声明 display:none：UA 的 `[hidden]{display:none}` 优先级低于
      任何作者样式，一旦将来有人给 tbody tr 设 display，收起态就会静默失效 —— 多这一行是保险。 */
.pmd-table tbody tr.pmd-sub[hidden] { display: none; }
/* 子行视觉：浅底 + 小一号字 + 更紧凑的上下留白（替代原 `.table--sub` 的「紧凑子表」角色）
   ⚠️ 底色设在 **td** 而不是 tr：全站斑马纹/悬浮是设在 tr 上的，
      设 td 的特异性更高、稳定压过它们（与 table.css 里 `tr.is-sum > td` 同一套做法）。 */
.pmd-table tbody tr.pmd-sub > td {
  background: var(--color-surface-2);
  font-size: var(--font-size-sm);
  padding-top: var(--space-2); padding-bottom: var(--space-2);
}
.pmd-table tbody tr.pmd-sub:hover > td { background: var(--color-surface-2); }
/* 「从属关系」用 inset 阴影表达，**不用 border-left**：本项目 border-left 已被若干
   语义线占用（见 table.css 的 .col-sep 注释），同属性会互相覆盖且极难排查。
   只画在首格（它贴着表格左边缘），视觉上就是那条"这些行属于上面那位达人"的竖线。 */
.pmd-table tbody tr.pmd-sub > td:first-child { box-shadow: inset 3px 0 0 var(--color-border-soft); }

/* 「该场无订单数据」标记（2026-09-17）
   --------------------------------------------------------------------------
   起因：乐哥问「艺芯怎么少了第二场直播」—— 那场确实一笔订单都没有，
   引擎从订单枚举场次导致整行不出现，用户只看到"少了一场"却不知原因。
   现在后端补出这类场次（金额恒为 0），这里给它一个**克制但一眼可辨**的标记：
   不用红色（不是错误、不影响任何金额），用中性警示色，避免看到就以为账错了。 */
.pmd-noorder {
  display: inline-block; margin-left: 6px; padding: 0 6px; border-radius: 4px;
  font-size: var(--font-size-xs); line-height: 1.6;
  background: var(--color-warning-bg); color: var(--color-warning-text);
}
.pmd-noorder-row > td { opacity: 0.85; }

/* 展开行下方的**附注行**（跨整行）：排期级成本未计入 / 无订单数据的原因
   --------------------------------------------------------------------------
   ⚠️ 为什么不放在表格最后一格（2026-09-17 实测数据说话）：
      放进「状态」列后，那格文字会参与列宽分配 → 展开一下整表列宽就跳：
        1440px 视口 · 2026-09：状态列 75→163px，其余 12 列各缩约 9%；
        2026-08 那条长说明更糟 —— 被挤在 97px 宽里折成 **199px 高**，竖着排一长条。
      跨整行（colspan=全列数）后，其最小宽度被摊到所有列上（每列十几像素），
      实测展开前后列宽几乎不变，文案也能用满整行。
   ⚠️ 附注行与场次行**同一组**显隐（都带 data-detail-of），由 bindRowToggle 按组切换；
      `tr[hidden]` 同样显式声明 display:none（理由同 .pmd-sub）。 */
.pmd-table tbody tr.pmd-note[hidden] { display: none; }
.pmd-table tbody tr.pmd-note > td {
  background: var(--color-surface-2);
  font-size: var(--font-size-xs);
  color: var(--color-meta);
  padding-top: 2px; padding-bottom: var(--space-2);
  /* 跨列格**不能**设 white-space:nowrap —— 那会让它的最小宽度无法被摊薄，
     整表会被撑宽（本项目"nowrap + 长文案把表格撑破"踩过一次，见 table.css 的注释）。 */
  white-space: normal;
}
/* 附注左侧的从属竖线：与场次行同一条（否则看着像两条线） */
.pmd-table tbody tr.pmd-note > td:first-child { box-shadow: inset 3px 0 0 var(--color-border-soft); }
/* 说明文案在附注行里可以用满整行，不再限制 360px（那个上限是为"塞在窄格里"设的） */
.pmd-table tbody tr.pmd-note .pmd-noorder-tip { display: inline; margin-top: 0; max-width: none; white-space: normal; }
/* ⚠️ 徽标现在放在附注行**句首**（2026-09-17 从"场次"格移过来）：
   那一列实测只有 91px 宽，徽标"无订单数据"会被挤成两行（"无订单 / 数据"）。
   改到跨整行的附注行后一行放得下，也顺了"徽标 + 解释"挨着读的直觉。
   ⇒ 原来的 `margin-left: 6px`（跟在"第 N 场"后面的场景）改成只留右侧间距。 */
.pmd-table tbody tr.pmd-note .pmd-noorder { margin-left: 0; margin-right: var(--space-2); }
/* 徽标与「排期级成本未计入」两段说明之间留出间距（都是 inline，需要显式 margin） */
.pmd-table tbody tr.pmd-note .cell-sub + .cell-sub { margin-top: 0; }
.pmd-table tbody tr.pmd-note .pmd-noorder-tip + .cell-sub { margin-left: var(--space-3); }

/* ==========================================================================
   达人结算单 · 卡片底部口径块（乐哥 2026-09-15：「列表里面少了个底块」）
   --------------------------------------------------------------------------
   参照华大对账那张卡：它在表格下方挂一块口径说明，而达人结算表格下面直接就是分页、没有这块。
   ⚠️ 视觉规格**用全站统一的提示条 token（--notice-*）**：浅底 + 8px 圆角 + info 图标。
      不复用 `.st-rule__inner` 类名（那是"页面级规则条"的语义），但共用同一组 token，
      保证同一屏里两个说明块视觉完全一致；`probe-notice-standard.js` 也会一并覆盖到。
   ⚠️ 左右 margin 用 --space-5：与 .card__header / .pagination 的水平内边距对齐，
      否则这个块会比卡片里的表格"缩进不齐"。
   ========================================================================== */
.st-foot {
  display: flex;
  align-items: flex-start;
  gap: var(--notice-gap);
  margin: 0 var(--space-5) var(--space-5);
  padding: var(--notice-pad-y) var(--notice-pad-x);
  border: 1px solid var(--notice-border);
  border-radius: var(--notice-radius);
  background: var(--notice-bg);
  color: var(--notice-fg);
  font-size: var(--font-size-sm);
  line-height: 1.6;
}
/* 图标垂直对齐：沿用全站提示条的推导法（16px 图标在 1.6em 行盒内居中） */
.st-foot svg { flex: none; align-self: flex-start; margin-top: calc((1.6em - 16px) / 2); color: var(--notice-ico); }
.st-foot b { color: var(--color-fg); font-weight: var(--font-weight-semibold); }

/* ==========================================================================
   角色权限页 · 权限目录（2026-09-17 重构）
   --------------------------------------------------------------------------
   改造前：44 个复选框平铺在 8 个**旧业务域**分组里，与侧栏菜单对不上号 ——
   用户看到「commission:rebate:read」只有一个光秃秃的中文名，不知道：
     ① 它属于侧栏哪个菜单   ② 它是"看不见菜单"还是"看不到某个金额"
   现在：分组 = 侧栏一级分组；组头一行小字列出该组的二级菜单；
        每个权限带**性质角标**（菜单可见 / 页面内操作 / 字段脱敏）+「管什么」说明。
   ⚠️ 角标三色语义必须稳定（与图例逐字对应），改色会让图例变成假的：
         menu   → 主色（蓝）：控制"能不能看到入口"，最重
         action → 中性灰：页面内的按钮级操作
         field  → 橙色：只影响某些金额显示为「—」，最容易被误解，故用警示色
   ========================================================================== */
.perm-group { padding: var(--space-4) 0; border-bottom: 1px solid var(--color-border-soft); }
.perm-group:last-child { border-bottom: 0; }
.perm-group__head { display: flex; align-items: baseline; gap: var(--space-3); flex-wrap: wrap; margin-bottom: var(--space-3); }
/* ⚠️ 用 --font-size-lg（16px）而不是 --font-size-md —— 令牌表里**没有 md**（只有 xs/sm/base/lg/xl…），
   写错的表现是**整条声明被浏览器丢弃**且不报错（本项目 check-css-tokens.js 抓到的）。 */
.perm-group__title { font-size: var(--font-size-lg); font-weight: var(--font-weight-semibold); color: var(--color-fg); }
/* 组头那行菜单摘要：它是"权限 ↔ 菜单"的锚点，不能省 —— 省了就退回改造前那种"对不上号"的状态 */
.perm-group__menus { font-size: var(--font-size-xs); color: var(--color-muted); }

.perm-list { display: flex; flex-direction: column; gap: var(--space-1); }
/* 每个权限一行：整行可点（label 包住 checkbox），避免只能点 12px 的小方块 */
.perm-item { display: flex; align-items: flex-start; gap: var(--space-2); padding: var(--space-2) var(--space-2);
  border-radius: var(--radius-sm); cursor: pointer; font-size: var(--font-size-sm); }
.perm-item:hover { background: var(--color-surface-2); }
.perm-item input[type="checkbox"] { margin-top: 2px; flex: none; }
.perm-item__body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.perm-item__top { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.perm-item__label { color: var(--color-fg); }
/* 权限码本身也给出来（等宽字体、弱化）：排查"某个权限没生效"时要能直接对上后端日志 */
.perm-item__code { font-size: var(--font-size-xs); color: var(--color-muted); font-family: var(--font-mono, monospace); }
.perm-item__scope { font-size: var(--font-size-xs); color: var(--color-muted); line-height: 1.5; }

/* 性质角标（三色，与图例一一对应） */
.perm-kind { display: inline-flex; align-items: center; height: 18px; padding: 0 var(--space-2);
  border-radius: var(--radius-pill); font-size: var(--font-size-xs); font-weight: var(--font-weight-medium);
  white-space: nowrap; }
.perm-kind--menu { color: var(--color-accent-text); background: var(--color-accent-bg); }
.perm-kind--action { color: var(--color-muted); background: var(--color-surface-2); }
.perm-kind--field { color: var(--color-warning-text); background: var(--color-warning-bg); }

/* 图例：常驻在「全选/清空」同一行右侧（不折叠），否则角标成了没人懂的符号 */
.perm-legend { display: flex; align-items: center; gap: var(--space-2); margin-left: auto; flex-wrap: wrap; }
.perm-legend__t { font-size: var(--font-size-xs); color: var(--color-muted); margin-right: var(--space-2); }

/* ==========================================================================
   经营看板 · 本期洞察（2026-09-17）
   --------------------------------------------------------------------------
   放在 #an-body 最顶部，KPI 卡之上 —— 一进页面先看到"这个月怎么样"。
   设计约束（来自乐哥：「不用很啰嗦，但是很关键」）：
     · 一行一条结论，左标签 + 中结论 + 右行动提示，**扫读三列对齐**
     · 只给"需要注意"的行加底色（risk/warn），正常的行不加 —— 全是底色等于没有重点
     · 数字用页面统一的「万」格式，盈利红/亏损绿与全站一致
   ⚠️ `.an-ins-label` 用固定 56px 宽度：三条以上时标签列必须对齐，
      否则「规模 / 亏损达人 / 口径」长短不一会让结论列参差，扫读时眼睛要来回找。
   ========================================================================== */
.an-ins { margin-bottom: var(--space-6); }
.an-ins-headline {
  font-size: var(--font-size-base);
  color: var(--color-fg);
  line-height: 1.7;
  padding: var(--space-3) var(--space-4);
  background: var(--color-surface-2);
  border-radius: var(--radius-md);
  margin-bottom: var(--space-3);
}
.an-ins-list { display: flex; flex-direction: column; }
.an-ins-row {
  display: grid;
  grid-template-columns: 56px 1fr auto;
  gap: var(--space-3);
  align-items: baseline;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-md);
  font-size: var(--font-size-sm);
  line-height: 1.7;
}
.an-ins-row + .an-ins-row { border-top: 1px solid var(--color-border-soft); }
/* 需处理：整行浅警示底（比只染标签更能"跳出来"，但不至于像报错） */
.an-ins-row.is-risk { background: var(--color-warning-bg-soft); }
.an-ins-row.is-warn { background: var(--color-warning-bg-soft); }
.an-ins-label { font-size: var(--font-size-sm); color: var(--color-muted); white-space: nowrap; }
.an-ins-row.is-risk .an-ins-label { color: var(--color-warning-text); font-weight: var(--font-weight-medium); }
.an-ins-row.is-warn .an-ins-label { color: var(--color-warning-text); }
.an-ins-text { color: var(--color-fg); min-width: 0; }
.an-ins-text b { font-weight: var(--font-weight-semibold); }
/* 数字：等宽数字（tabular）保证多行数字右边缘对齐，扫读时不会左右跳 */
.an-ins-num { font-variant-numeric: tabular-nums; font-feature-settings: "tnum"; font-weight: var(--font-weight-medium); }
.an-ins-note { font-size: var(--font-size-xs); color: var(--color-muted); white-space: nowrap; }
.an-ins-row.is-risk .an-ins-note,
.an-ins-row.is-warn .an-ins-note { color: var(--color-warning-text); }

/* AI 追问（2026-09-17）—— 默认收起，点「追问 AI」才展开。
   ⚠️ 输入行用 flex 而不是 grid：窄屏时按钮要能跟着输入框一起收缩，
      grid 的固定列在 375px 下会把"提问"按钮挤出容器。 */
.an-ask { margin-top: var(--space-4); padding-top: var(--space-4); border-top: 1px solid var(--color-border-soft); }
.an-ask__row { display: flex; gap: var(--space-2); align-items: center; }
.an-ask__row .input { flex: 1; min-width: 0; }
.an-ask__row .btn { flex: none; }
.an-ask__sug { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; margin-top: var(--space-2); }
/* 建议问题做成一排小胶囊：比空白输入框更好上手，也引导用户问"数据里有的东西" */
.an-ask__chip {
  border: 1px solid var(--color-border-soft);
  background: var(--color-surface);
  color: var(--color-fg);
  border-radius: var(--radius-pill);
  padding: 2px var(--space-3);
  font-size: var(--font-size-xs);
  cursor: pointer;
}
.an-ask__chip:hover { border-color: var(--color-accent); color: var(--color-accent-text); }
.an-ask__hint { font-size: var(--font-size-xs); color: var(--color-muted); }
.an-ask__out:not(:empty) { margin-top: var(--space-3); }
.an-ask__loading { font-size: var(--font-size-sm); color: var(--color-muted); display: flex; align-items: center; gap: 6px; }
.an-ask__q { font-size: var(--font-size-sm); color: var(--color-muted); margin-bottom: var(--space-2); }
.an-ask__a {
  font-size: var(--font-size-sm);
  line-height: 1.8;
  color: var(--color-fg);
  background: var(--color-surface-2);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
}
/* 来源标注：**必须可见** —— 用户要知道这是 AI 解释，权威数字在上方洞察卡（规则算的、可对账） */
.an-ask__src { font-size: var(--font-size-xs); color: var(--color-muted); margin-top: var(--space-2); }
.an-ask__err { font-size: var(--font-size-sm); color: var(--color-danger); }

/* ============================================================================
   权限配置页：按左侧菜单树布局（2026-09-18 乐哥拍板重构）
   四个区块：菜单名 | 页面可见 | 操作权限 | 金额可见
   ⚠️ 金额 chip 是**全局**的（同一个码在多个菜单下出现，勾一处联动其它处），
      因为打码按字段名判断、与页面无关 —— UI 上以「全局生效」提示。
   ============================================================================ */
.perm-toolbar { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; padding-bottom: var(--space-3); margin-bottom: var(--space-3); border-bottom: 1px solid var(--color-border-soft); }
.perm-head-row, .perm-menu-row { display: grid; grid-template-columns: minmax(150px, 1fr) 104px 210px 200px; gap: var(--space-2); align-items: center; }
.perm-head-row { padding: var(--space-2) var(--space-3); font-size: var(--font-size-xs); color: var(--color-muted); border-bottom: 1px solid var(--color-border-soft); }
.perm-menu-row { padding: var(--space-2) var(--space-3); border-bottom: 1px solid var(--color-border-soft); }
.perm-menu-row:last-child { border-bottom: 0; }
.perm-menu-row:hover { background: var(--color-surface-2); }
.perm-menu-row__name { color: var(--color-fg); display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.perm-menu-row__note { font-size: var(--font-size-xs); color: var(--color-muted); }
.perm-menu-row__read, .perm-menu-row__act, .perm-menu-row__money { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }
.perm-read { display: inline-flex; align-items: center; gap: 4px; font-size: var(--font-size-sm); color: var(--color-fg); cursor: pointer; }
.perm-muted { font-size: var(--font-size-xs); color: var(--color-muted); }
.perm-chip { display: inline-block; padding: 1px 7px; border-radius: var(--radius-sm); font-size: var(--font-size-xs); cursor: pointer;
  border: 1px solid var(--color-border-soft); color: var(--color-muted); background: transparent; user-select: none; }
.perm-chip:hover { border-color: var(--color-border); color: var(--color-fg); }
.perm-chip.is-on { background: var(--color-accent-bg, #EDF4FE); border-color: var(--color-accent-border, #BBD5F7); color: var(--color-accent-text, #0040A3); }
.perm-chip--money.is-on { background: var(--color-warning-bg, #FFF4E5); border-color: var(--color-warning-border, #FFD8A8); color: var(--color-warning-text, #8A5300); }
.perm-group__head--fold { cursor: pointer; user-select: none; align-items: center; }
.perm-fold { font-size: 11px; color: var(--color-muted); width: 12px; }
.perm-group.is-folded .perm-group__body { display: none; }
.perm-global { display: flex; flex-direction: column; gap: var(--space-2); padding: var(--space-2) 0; }
.perm-item--inline { align-items: center; }

/* ==========================================================================
   「我的报销」页（2026-09-19）
   新增：替票额度条 / 筛选行（tab + 月份 + 日期口径 + 状态）/ 汇总行 / 驳回原因
   ⚠️ 只用既有 design-tokens 变量，不新造颜色 —— 与全站观感一致（本项目已因"孤例颜色"返工过）
   ========================================================================== */

/* 替票额度条：报销的**前置条件**（选「没有发票」要够额度），故放页面顶部一眼可见。
   2026-09-19 改：原来它是个「灰底 + 30px 按钮」的独立条，与周围两套语言都不搭 ——
     ① 底色用 --color-surface-2（=表头灰），视觉重量接近工具栏，像"第二个工具栏"；
     ② 按钮 30px，而页头按钮 44px、工具栏控件 34px，三套尺寸。
   改成：白底 + 1px 边框（与卡片同一语言），按钮升到 34px（= 工具栏控件高度）。
   ⚠️ 不能把按钮写成 `.btn--sm` 就完事 —— 那样它永远 30px；要在自己的类里显式给高。 */
.tt-bar {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-4);
  padding: var(--space-3) var(--space-5);
  margin-bottom: var(--space-6);
  background: var(--color-surface);
  border: 1px solid var(--color-border-soft);
  border-radius: var(--radius-lg);
  flex-wrap: wrap;
}
.tt-bar__l { display: flex; align-items: baseline; gap: var(--space-3); flex-wrap: wrap; }
.tt-bar__k { font-size: var(--font-size-sm); color: var(--color-fg-2); }
.tt-bar__v { font-size: 20px; font-weight: var(--font-weight-medium); color: var(--color-accent-text); }
.tt-bar__hint { font-size: var(--font-size-sm); color: var(--color-muted); }
.tt-bar__r { display: flex; gap: var(--space-2); flex-shrink: 0; }
.tt-bar__r .btn { height: 34px; min-height: 34px; }

/* 状态笔数（工具栏右侧）：与 `.table-toolbar__total` 并排，故沿用同一套字号与颜色。
   2026-09-19 改：原来是一个占整行的自造 `.me-sum`（独立第三行、21px 高），
   现在并入工具栏右侧 —— 规范里统计属于工具栏，不该另占一行。 */
.me-counts { display: inline-flex; align-items: center; gap: var(--space-4); flex-wrap: wrap; }
.me-counts__item {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: var(--font-size-xs); color: var(--color-meta); white-space: nowrap;
}
.me-counts__item b { color: var(--color-fg); font-variant-numeric: tabular-nums; }
.me-counts__dot { width: 6px; height: 6px; border-radius: 50%; background: var(--color-muted); }
.me-counts__dot--warning { background: var(--color-warning); }
.me-counts__dot--success { background: var(--color-success); }
.me-counts__dot--danger  { background: var(--color-danger); }

/* 驳回原因（要让人知道改什么才能重提，否则只能干等） */
.me-reject { color: var(--color-danger); }

/* ---------- 手机端适配 ---------- */
@media (max-width: 768px) {
  .tt-bar { flex-direction: column; align-items: stretch; gap: var(--space-3); }
  .tt-bar__r { justify-content: stretch; }
  .tt-bar__r .btn { flex: 1; min-height: 40px; }
  .tt-bar__hint { display: none; }          /* 手机上省一行（额度本身已说明一切） */
  /* ⚠️ 手机上工具栏右侧必须能换行（2026-09-19 实测踩到）：
     统计并入工具栏后，`.table-toolbar__right` 是 `display:flex` **无 flex-wrap**、
     且其中 `.table-toolbar__total` 带 `white-space: nowrap`（公共类的防折行，不能动），
     于是 360px 下两者挤在同一行、总额被压掉尾数（截图实测：「合计 ¥2,705.0」被"审批中"盖住）。
     ⇒ 补 wrap + 让状态笔数独占一行。作用域限定在本页的工具栏上，不动公共类。 */
  .toolbar--join-card > .table-toolbar__right {
    flex-wrap: wrap;
    width: 100%;
    margin-left: 0;
    justify-content: flex-start;
  }
  .me-counts { width: 100%; gap: var(--space-3); }
}

/* ==========================================================================
   报销表单 · 分区单列布局（2026-09-19）
   乐哥：「报销提交那个页面，ui 整体调整下，现在做的一点都不直观」
   实测三个问题 → 三个改法：
     ① 因果链被打断（两列布局把「大类→类型→成本类目」拆散）→ **单列**
     ② 长说明占 2-3 行 → 收进每区一句「这一区在干什么」，长说明移进提示
     ③ 字段平铺无分组 → **3 个分区卡片**（带序号）
   ⚠️ 只用既有 design-tokens 变量；配色复用 module-card（全站模块卡的既有语言）
   ========================================================================== */

/* 报销人条：默认本人、不需要输入；点「帮他人报销」才展开下拉 */
.rf-who {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  margin-bottom: var(--space-4);
  background: var(--color-surface-2);
  border: 1px solid var(--color-border-soft);
  border-radius: var(--radius-lg);
}
.rf-who__l { display: flex; align-items: baseline; gap: var(--space-2); flex-wrap: wrap; }
.rf-who__k { font-size: var(--font-size-sm); color: var(--color-fg-2); }
.rf-who__me { font-size: var(--font-size-base); font-weight: var(--font-weight-medium); }
.rf-who__tag {
  font-size: 11px; color: var(--color-fg-2);
  background: var(--color-surface); border: 1px solid var(--color-border-soft);
  border-radius: 999px; padding: 1px 8px;
}
.rf-who__other { margin-bottom: var(--space-4); }

.rf-req { color: var(--color-danger); }

/* 分区卡片：序号圆点 + 标题 + 一句说明 */
.rf-sec { margin-bottom: var(--space-4); }
.rf-sec:last-child { margin-bottom: 0; }
.rf-sec__head { display: flex; gap: var(--space-3); align-items: flex-start; }
.rf-sec__no {
  flex: 0 0 auto; width: 22px; height: 22px; border-radius: 50%;
  background: var(--color-accent); color: var(--color-accent-on);
  font-size: 12px; line-height: 22px; text-align: center; margin-top: 1px;
}
.rf-sec__sub { font-size: var(--font-size-sm); color: var(--color-muted); margin-top: 3px; line-height: 1.5; }

/* 分区内字段：单列、纵向间距均匀 */
.rf-sec .module-card__body > div { margin-bottom: var(--space-4); }
.rf-sec .module-card__body > div:last-child { margin-bottom: 0; }

/* 成本类目：从"第 3 行右侧的一个只读框 + 一行说明"改成**紧跟类型的实时反馈条** ——
   它是「大类 + 类型」算出来的**结果**，必须贴着它的两个输入项，否则读不出因果关系。
   ⚠️ 容器 .rf-alloc-cell 里现在只放一个 hidden input（回传用）+ 这条反馈条。 */
.rf-alloc-cell { margin-top: calc(var(--space-2) * -1); }
.rf-alloc-cell > .field-label { display: none; }      /* 反馈条自带语义，不需要再顶一行标签 */
.rf-alloc {
  display: flex; align-items: center; gap: var(--space-2);
  padding: 9px 12px;
  border: 1px dashed var(--color-border-soft);
  border-radius: var(--radius-md);
  background: var(--color-accent-bg);
}
.rf-alloc__k { font-size: var(--font-size-sm); color: var(--color-fg-2); }
.rf-alloc__v { font-size: var(--font-size-base); font-weight: var(--font-weight-medium); color: var(--color-accent-text); }

/* ---------- 手机端（乐哥：「得适配 pc 和手机页面」）---------- */
@media (max-width: 768px) {
  /* 页头「返回 + 标题」在手机上占两行、且标题被挤成小字 —— 改成单行紧凑 */
  .rf-who { padding: var(--space-2) var(--space-3); }
  .rf-who__me { font-size: var(--font-size-sm); }
  /* 手机上分区之间留白收一半：两屏能看完整个表单 */
  .rf-sec { margin-bottom: var(--space-3); }
  .rf-sec .module-card__body > div { margin-bottom: var(--space-3); }
  .rf-sec__sub { display: none; }      /* 手机上一屏寸土寸金：分区说明省掉（标题已表意） */
}

/* ==========================================================================
   手机端独立页（/h5/expense 等）—— 从飞书工作台点进来时，整屏只放表单
   ⚠️ 用「隐藏」而不是「不渲染」：DOM 结构不动，"退出独立模式"只需去掉类；
      也避免为独立页另建一套骨架（那会带来两套要同步维护的布局）。
   ========================================================================== */
.app-shell.is-standalone .sidebar,
.app-shell.is-standalone .sidebar-backdrop,
.app-shell.is-standalone .page-tabs-bar {
  display: none !important;
}
.app-shell.is-standalone .app-main {
  margin-left: 0;          /* 没有侧栏了，内容列从左边开始 */
  width: 100%;
}
/* 独立页没有标签栏，页面顶部即是内容 —— 把 .page 的上内边距收掉，
   否则会出现一条"本应是标签栏"的空白（实测 24px）。 */
.app-shell.is-standalone .page { padding-top: var(--space-4); }

/* ⭐⭐ 财务模块（**2026-09-21 起 = 与达播同构**：有侧栏 + 有标签栏）
   ──────────────────────────────────────────────────────────────────────────
   这里是**第三次**改它的形态，别把某一版当成唯一答案（演进有价值，记下来）：
     · 2026-09-20 之前：无侧栏 + 无标签栏 —— "独立的一层"，自带模块头（`.fin-top`）
     · 2026-09-20：无侧栏 + **有**标签栏（乐哥「上面的标签该保留的也保留」）
       —— 彼时跨板块入口靠标签栏里那个「公司门户 / 达播工作台 / 星盟财务中心」切换器
     · **2026-09-21（现状）**：**有侧栏 + 有标签栏**
       —— 乐哥「不要这个」（删掉标签栏的切换器）+「财务的左上角也做的和现在达播台一样」
       ⇒ 侧栏回归：顶部品牌区 + 中部财务导航 + 底部「返回门户网站 / 我的」；
         跨板块入口改由**侧栏底部的「返回门户网站」**承担（进财务则走门户页的卡片）。
   ⚠️⚠️ 侧栏必须**显式加 `!important` 覆盖**：上面那条
      `.app-shell.is-standalone .sidebar { display: none !important }` 带 `!important`，
      不写就盖不过它。这是本轮最容易漏的一处 —— 漏了的现象是
      **"侧栏内容都渲染对了，屏幕上却什么也看不见"**（DOM 里有、样式上是 none）。
   ⚠️ 同时 `.app-main` 的左边距必须**还回去**：上面那条 is-standalone 规则把它设成
      `margin-left: 0`（前提是"没有侧栏"）。侧栏回来后要让出 `--sidebar-width`，
      否则内容列会被压在侧栏底下；且 `width: 100%` 要一并改成 `auto`，
      不然"240px 外边距 + 100% 宽"会横向撑出滚动条。
   ⚠️ 用 `.is-finance` 这个**显式标记类**（由 showAppShell 加），不用 `:has(.fin)`：
      后者靠"页面内容恰好带某个类"推断，隔了一层，后来者不易发现。 */
.app-shell.is-standalone.is-finance .sidebar {
  display: flex !important;
}
.app-shell.is-standalone.is-finance .app-main {
  margin-left: var(--sidebar-width);
  width: auto;
}
/* ⚠️⚠️ 移动端必须**显式收回**上面那条 `margin-left`。
   ──────────────────────────────────────────────────────────────────────────
   为什么：`@media` 查询**不改变选择器特异性**。上面那条是 3 个类的选择器，
   而移动端的基础规则只有 1 个类 —— 特异性能赢，于是**桌面的 240px 左边距在手机上照样生效**。
   实测（390×844 视口，本轮真踩）：`.app-main` 的 margin-left 被算成 240px
   ⇒ 财务内容只剩 **150px 宽**（屏宽 390），几乎不可用。
   ⚠️⚠️ 而且这个 bug **不报错、也不产生横向滚动条**（内容自适应收窄了）
      —— 只能靠"在窄视口下量宽度"才看得出来。不要只测桌面就宣布完成。
   ⚠️ 反过来 `.sidebar` 那条**不需要**在移动端收回：
      移动端侧栏抽屉是靠 `transform: translateX(-100%)` 移出屏幕的（见 layout.css），
      `display` 本来就是 flex ⇒ 我那条 `display:flex !important` 与它不冲突。
      （若哪天移动端改成用 `display:none` 隐藏侧栏，这里就必须同步补一条覆盖。） */
@media (max-width: 768px) {
  .app-shell.is-standalone.is-finance .app-main {
    margin-left: 0;
    width: auto;
  }
}
.app-shell.is-standalone.is-finance .page-tabs-bar {
  display: flex !important;
}
.app-shell.is-standalone.is-finance .page {
  padding-top: var(--page-padding);
}
/* 手机安全区：底部按钮不被 iPhone 的小黑条压住 */
body.is-standalone .sf-actions { padding-bottom: env(safe-area-inset-bottom, 0); }

/* 分区布局里的控件要撑满单列宽度。
   ⚠️ 必须显式写：`.form-grid .input{width:100%}` 那条只对 form-grid 生效，
      分区布局不是 form-grid → 金额这类原生 input 会退回默认宽度（实测 ~120px，
      与旁边的日期/下拉宽度不一致，看着像坏了）。 */
.rf-sec .input,
.rf-sec .select,
.rf-sec .textarea {
  width: 100%;
}

/* ==========================================================================
   个人替票页（2026-09-19 改版）—— 余额卡 + 上传替票弹窗
   依据：乐哥「上传替票这个页面，ui也整体优化下」（原截图：弹窗 880px 宽、4 个字段排两列、
        输入框被拉到 412px 宽右侧全空、票面金额填了会怎样没说、底部留白；
        余额卡只有「¥0.00 + 一行 14 字规则」，看不到额度是怎么来的）。
   铁律：容器一律走既有 .card / .module-card 体系（不新造模块容器）；
        颜色全走 CSS 变量（零裸 hex）；类名 .tu- 前缀，不改任何公共类。
   ========================================================================== */

/* —— 余额卡：左「能报多少」 / 右「额度怎么来的」 —— */
.tu-bal__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 260px;
  gap: var(--space-8);
  align-items: center;
}
.tu-bal__label { font-size: var(--font-size-sm); color: var(--color-muted); }
.tu-bal__value {
  margin-top: var(--space-1);
  font-size: var(--font-size-4xl);
  font-weight: var(--font-weight-semibold);
  line-height: var(--font-line-height-tight);
  letter-spacing: var(--font-letter-spacing-display);
  /* ⭐ 红色（乐哥 2026-09-19：「个人替票金额要不要用红色展示啊」）
     ────────────────────────────────────────────────────────────────────
     `--color-price` 是本项目全站既有的「金额语言」，不是新造色：
       · base.css 的 `.price`（货品售价/达播价）
       · components.css 的 `.rmk-hl--money`（备注里的金额）
       · pages.css 的 `.pp-price`、报销单底部合计 `.eb-total__v`
     三处结论性金额都是它 ⇒ 这个「可用替票余额」是同一性质（钱的口径），
     跟着走才一致。
     ⚠️ 它**不是**"错误色"：令牌注释写明「价格：与危险色同源，避免多一套红」，
        `--color-price` 就是 `--color-danger` 的语义别名，两者只是用途不同。
     ⚠️ 列表里的「票面金额」列**保持默认色**（不动）：全站 40+ 处表格的金额列
        都是默认色，整列涂红会成为孤例，且一列 20 个红数字会让人误以为"这些有问题"。 */
  color: var(--color-price);
  font-variant-numeric: tabular-nums;
}
.tu-bal__hint { margin-top: var(--space-2); font-size: var(--font-size-sm); color: var(--color-muted); }
/* 右侧明细用一条竖线与大数字分开：左右是「结论 / 依据」两层关系，不是两组并列数据 */
.tu-bal__side {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding-left: var(--space-6);
  border-left: 1px solid var(--color-border-soft);
}
.tu-bal__row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  font-size: var(--font-size-sm);
}
.tu-bal__row > span { color: var(--color-muted); }
.tu-bal__row > b {
  font-weight: var(--font-weight-medium);
  color: var(--color-fg);
  font-variant-numeric: tabular-nums;
}

/* —— 上传替票弹窗 —— */
/* 顶部提示条：进弹窗第一眼要知道「这张票会变成什么」，而不是先看到一串要填的框 */
.tu-note {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-1) var(--space-3);
  padding: var(--space-3) var(--space-4);
  margin-bottom: var(--space-5);
  border-radius: var(--radius-md);
  background: var(--color-accent-bg);
}
.tu-note__k { font-size: var(--font-size-sm); font-weight: var(--font-weight-medium); color: var(--color-accent-text); }
.tu-note__v { font-size: var(--font-size-sm); color: var(--color-fg-2); }

/* 分区复用 .rf-sec 的结构（数字圆标 + 标题 + 一句说明），与报销提交页同一套视觉语言。
   但弹窗内**不画分隔线**：弹窗自己已有 footer 分隔线，再画一条会像"这里少了一段内容"。 */
.tu-sec { margin-bottom: var(--space-5); }
.tu-sec--last { margin-bottom: 0; }
.tu-sec .module-card--bare { padding-bottom: 0; border-bottom: none; }

.tu-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-4) var(--space-5);
}
.tu-span2 { grid-column: 1 / -1; }
/* 字段说明可能是两行，行高按正文给，否则两行会挤在一起 */
.tu-grid .field-hint { line-height: var(--font-line-height-body); }

/* 金额 → 额度 反馈条：与报销提交页 .rf-alloc 同一视觉语言（虚线 + 淡底），
   全站"某字段会影响某个结果"统一长这样，员工一眼认得。 */
.tu-alloc {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  margin-top: var(--space-2);
  padding: 9px 12px;
  border: 1px dashed var(--color-border-soft);
  border-radius: var(--radius-md);
  background: var(--color-accent-bg);
}
.tu-alloc__k { font-size: var(--font-size-sm); color: var(--color-fg-2); }
.tu-alloc__v {
  font-size: var(--font-size-base);
  font-weight: var(--font-weight-medium);
  color: var(--color-accent-text);
  font-variant-numeric: tabular-nums;
}

/* ==========================================================================
   上传替票 · 「拍发票」大上传框（2026-09-19 第二次改版）
   ──────────────────────────────────────────────────────────────────────────
   改版前是一个 160×160 的小虚线框、文案只写「点击上传图片」，而且它在最下面
   （照片是"选填、收尾补一下"的定位）。现在照片成了**动线的第一步**
   （拍完自动识别 → 后面几项就不用打了），所以它必须：
     · 大（整宽、够高），一眼看出"这里是起点"
     · 文案说清拍了会发生什么（"会自动读出票面信息"）
     · 传完直接显示预览 —— 让人确认"拍的就是这张票"，而不是只留个文件名
   ⚠️ 颜色全走既有令牌：主色虚线框（与报销单的必传凭证同一语言 = "要你做动作"），
      完成后转成功色（"这一步做完了"）。
   ========================================================================== */
.tu-shot {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  width: 100%;
  min-height: 132px;
  padding: var(--space-4);
  border: 1.5px dashed var(--color-primary-200);
  border-radius: var(--radius-md);
  background: var(--color-accent-bg);
  color: var(--color-accent-text);
  font-family: inherit;
  cursor: pointer;
  transition: border-color var(--motion-fast) var(--motion-ease-standard),
    background var(--motion-fast) var(--motion-ease-standard);
}
.tu-shot:hover { border-color: var(--color-accent); }
.tu-shot__ico { display: flex; }
.tu-shot__t { font-size: var(--font-size-base); font-weight: var(--font-weight-medium); }
.tu-shot__s { font-size: var(--font-size-xs); color: var(--color-muted); }
/* 识别中：与普通框同高，避免"点完框突然变矮、下面的字段往上跳" */
.tu-shot--busy {
  flex-direction: row;
  gap: var(--space-2);
  cursor: default;
  border-style: solid;
  border-color: var(--color-border);
  background: var(--color-surface-2);
  color: var(--color-fg-2);
  font-size: var(--font-size-sm);
}
.tu-shot__spin {
  width: 14px; height: 14px; flex: 0 0 auto;
  border: 2px solid var(--color-border);
  border-top-color: var(--color-accent);
  border-radius: 50%;
  animation: tu-spin .8s linear infinite;
}
@keyframes tu-spin { to { transform: rotate(360deg); } }
/* 已上传：预览图 + 状态行 */
.tu-shot__wrap { width: 100%; }
.tu-shot__img {
  display: block;
  width: 100%;
  max-height: 200px;
  object-fit: contain;
  border: 1px solid var(--color-border-soft);
  border-radius: var(--radius-md);
  /* 白底：发票是白纸黑字，透明/深色底会让它看着像"缺了一块" */
  background: #fff;
}
.tu-shot__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-top: var(--space-2);
  font-size: var(--font-size-sm);
  color: var(--color-success-text);
}
.tu-shot__bar > span { flex: 1; }

/* 「自动识别」小标：挂在被识别出来的字段标签后面。
   ⚠️ 它的作用不是装饰，而是**告诉用户"这几项是机器填的，重点核对它们"** ——
      全填完却不说哪些是机器填的，用户会把整张表都当成"自己填的、肯定没错"。 */
.tu-auto {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 6px;
  border-radius: var(--radius-full, 999px);
  background: var(--color-success-bg);
  color: var(--color-success-text);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-regular);
  vertical-align: 1px;
}

/* —— 手机端（乐哥：「得适配 pc 和手机页面」）—— */
@media (max-width: 768px) {
  .tu-bal__grid { grid-template-columns: 1fr; gap: var(--space-4); }
  /* 竖线改横线：单列后"左/右"变成"上/下"，竖线留着会像一条没意义的竖杠 */
  .tu-bal__side {
    padding-left: 0;
    padding-top: var(--space-4);
    border-left: none;
    border-top: 1px solid var(--color-border-soft);
  }
  .tu-grid { grid-template-columns: 1fr; }
  .tu-shot { min-height: 116px; }
  .tu-shot__img { max-height: 160px; }
}

/* ==========================================================================
   多明细报销表单（2026-09-19 乐哥需求 2+3）
   「抬头 + 多笔明细」——填一遍提交多笔，不用一笔一笔分开报。
   铁律：容器走既有 .card / .dt 体系，颜色全走 token（零裸 hex）。

   ▸ 2026-09-19 第二次改版（乐哥：「ui优化下，看要不要参考新建达人那种（只是不要 tab），
     然后部分框加带颜色的框」）：
     骨架从「一整张大 .card」换成 **新建达人页同款** ——
       UI.headNav（返回 + 标题）+ .sf-shell--modules + .sf-body__content（1120 限宽）
       + 一列 .module-card（分区卡）+ 底部 .form-actions 操作条。
     与新建达人的唯一差别就是**没有 .sf-tabs**（报销单是一条纵向动线，不需要切分组）。
     ⚠️ 彩色框只在 4 处（语义化，不是装饰），全部走既有语义令牌：
       汇总条=主色 / 关联排期=主色 / 代报条=警示 / 必传凭证=主色虚线。
       依据 docs/UIUX设计-达播工作台.md 的「绝对禁令 #1」——
       彩色描边只能用于**语义块**（如 --color-warning-border 注释里写的"待结算卡片外框"），
       页面级卡片一律白底 + 中性描边。
   ========================================================================== */
/* 分区卡标题栏右侧那句补充说明（跟着标题走，不另起一行）
   ⚠️ 原来还有一条 `.eb-head__t`（大标题）—— 标题已改由 `.module-card__title` 承担，
      该条已无引用，本轮删掉（本项目踩过"用了不存在的类名"，反向的"定义了没人用的类名"
      同样是死代码，会让下次改版误以为它还有用）。 */
.eb-head__s { font-size: var(--font-size-sm); color: var(--color-muted); }
.eb-head__s--end { margin-left: auto; }

/* 报销人条（默认本人、不让人手输）。代报时切成警示色 —— 见 .eb-who--proxy */
.eb-who {
  display: flex; align-items: center; gap: var(--space-2);
  padding: var(--space-2) var(--space-3); margin-bottom: var(--space-4);
  border: 1px solid var(--color-border-soft); border-radius: var(--radius-md);
  background: var(--color-surface-2);
}
/* 「帮他人报销」展开后：这一条变成"你在替别人报"的提醒。
   用 --color-warning-border / --color-warning-bg-soft（设计规范里给"待结算卡片外框"的那对令牌），
   语义正好：这是一个"要注意"的状态，不是错误（所以不用红）。 */
.eb-who--proxy {
  border-color: var(--color-warning-border);
  background: var(--color-warning-bg-soft);
}
.eb-who__k { font-size: var(--font-size-sm); color: var(--color-fg-2); }
.eb-who__me { font-size: var(--font-size-base); font-weight: var(--font-weight-medium); }
.eb-who-other { margin-bottom: var(--space-4); }

/* 抬头字段网格：两列，长字段（排期）占满整行 */
.eb-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-4); }
.eb-fld { display: block; }
/* 「票面要素」那一行（2026-09-20）。
   ⚠️ 它**曾经是 3 个手填输入框**（号码/代码/开票日期），现已改成只读汇总 ——
      但仍用 auto-fit 而不是写死列数：窄屏时自动堆成一列，
      否则「票面金额 + 对不上 + 票面要素」三格挤在 375px 里会看不全
      （票号有 20 位）。 */
.eb-grid--inv { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
/* 票面金额那一行（2026-09-20）—— 原来这里是三个手填输入框，
   改成"只读的票面金额汇总 + 可展开的要素清单"（乐哥：「发票代码、发票号这些
   是不是可以不用填了？…用逗号隔开我觉得没意义」）。
   ⚠️ 只读值必须**看起来就不能填**（无边框、无输入框外观）——
      做成 input[readonly] 会让人以为要填、点了没反应。
   ⚠️ 高度与输入框**对齐**（min-height 44px）：它与「费用类型」等字段同处一个网格，
      矮一截会让整行歪掉（本项目对这 1~4px 错位一贯要求对齐）。 */
.eb-ro {
  display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap;
  min-height: 44px; padding: 0 var(--space-3);
  border: 1px dashed var(--color-border-soft); border-radius: var(--radius-md);
  background: var(--color-surface-2);
  font-size: var(--font-size-sm); color: var(--color-fg-2);
}
.eb-ro__v { font-size: var(--font-size-base); font-weight: var(--font-weight-semibold); color: var(--color-fg); }
.eb-ro__n { font-size: var(--font-size-xs); color: var(--color-meta); }
.eb-ro__empty { color: var(--color-meta); }
.eb-ro__why { font-size: var(--font-size-xs); color: var(--color-meta); }
/* 报销金额 > 票面金额的提醒（只提醒不拦）—— 用警告色，但要能一眼看出是"待核对"不是"报错" */
.eb-ro--warn {
  border-style: solid; border-color: var(--color-warning-text);
  background: var(--color-warning-bg); color: var(--color-fg-2);
}
.eb-ro--warn .eb-ro__why { color: var(--color-warning-text); }
.eb-ro__lnk {
  border: none; background: transparent; padding: 0; cursor: pointer;
  color: var(--color-accent-text); font-size: var(--font-size-sm);
}
.eb-ro__lnk:hover { text-decoration: underline; }

/* 票面要素清单（默认 hidden，点「点开查看」才展开）——
   三栏从界面上拿掉了，但要素必须**有地方能看**（财务核对要用）。
   ⚠️ 默认收起而不是展开：它是"给财务核对用"的明细，
      填单的人不需要天天看到 20 位的票号（那是纯噪音）。 */
.eb-invpanel {
  margin-top: var(--space-2); padding: var(--space-3);
  border: 1px solid var(--color-border-soft); border-radius: var(--radius-md);
  background: var(--color-surface-2);
}
.eb-invpanel__row {
  display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap;
  padding: 5px 0; border-bottom: 1px solid var(--color-border-soft);
  font-size: var(--font-size-xs);
}
.eb-invpanel__row:last-of-type { border-bottom: none; }
.eb-invpanel__n {
  flex: 0 0 auto; width: 18px; height: 18px; line-height: 18px; text-align: center;
  border-radius: 50%; background: var(--color-surface); color: var(--color-meta);
  font-size: 11px;
}
.eb-invpanel__src { flex: 0 0 auto; max-width: 180px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--color-meta); }
.eb-invpanel__f { color: var(--color-meta); }
.eb-invpanel__f b { color: var(--color-fg-2); font-weight: var(--font-weight-medium); font-variant-numeric: tabular-nums; }
.eb-invpanel__amt { margin-left: auto; font-weight: var(--font-weight-medium); color: var(--color-fg); }
.eb-invpanel__tip { margin-top: 8px; font-size: var(--font-size-xs); color: var(--color-meta); line-height: 1.6; }

.eb-fld .input, .eb-fld .select { width: 100%; }
.eb-fld--full { grid-column: 1 / -1; }

/* 关联排期块：整块套一层主色浅底框。
   为什么单独上色：它是**只有「达人溯源直播」才出现**的必填项，也是这张单
   "钱算到哪场"的唯一依据 —— 漏选会把达人成本错记成项目成本（不报错、只错账）。
   给它一圈主色，是为了让它在一屏字段里一眼被看见。 */
.eb-schedbox {
  border: 1.5px solid var(--color-primary-200);
  border-radius: var(--radius-md);
  background: var(--color-accent-bg);
  padding: var(--space-3) var(--space-4);
}

/* ⚠️ 已删除（2026-09-19 晚，改版后无引用，属于"定义了没人用的类名"）：
   · `.eb-sum` / `.eb-sum__k` / `.eb-sum__v` / `.eb-sum__auto`
     —— 汇总条从卡片内移到了底部固定条，见下面的 `.eb-total*`
   · `.eb-chips` / `.eb-chip[data-sid]` / `.eb-chip__d` / `.eb-chip__x` / `.eb-chip--add`
     —— 排期从"自绘胶囊 + 弹窗"换成了 `UI.schedulePicker`（它自带胶囊样式 `.fp-chip`）
   删而不留的理由：本项目踩过"用了不存在的类名"（卡片头挤成一坨），
   反向的"定义了没人用的类名"同样是负债 —— 下次改版会以为它还有用、照着改。 */

/* 报销人条上的「本人 / 代报」小标签 —— **仍在用**，所以保留 */
.eb-chip--tag { height: 22px; font-size: var(--font-size-xs); color: var(--color-muted); background: var(--color-surface); }

/* ==========================================================================
   底部固定操作条（合计 + 取消/提交）（2026-09-19 乐哥：
   「累计的这个报销费用，要不要一直放在页面右下角」）
   ─────────────────────────────────────────────────────────────────────────
   ⭐ 依据（调研 Expensify / Ramp / 飞书审批后定的）：
      Ramp 的官方说明原话是 "one row per purchase, then subtotals by category
      and a grand total" —— **总计在最后**；三家成熟系统都把合计与"提交"放在同一区。
      我们原来把合计夹在「整单信息」和「费用明细」之间 ⇒ 滚到明细区就完全看不见，
      而这恰恰是用户最需要看到合计的时刻（正在一笔一笔加钱）。

   ⚠️ 用 `position: sticky; bottom: 0`，**不是** `fixed`：
      fixed 脱离文档流，页面短时会浮在半空、窄屏会压住内容；
      sticky 只在"它自己那一行可见"时才粘住，页尾自然落位。全站首次用这个形态，
      已单独验证过（不遮内容、不盖侧栏、手机端正常）。
   ⚠️ `z-index` 要低于侧栏遮罩与弹层（它们用 --z-modal），
      否则日历弹窗会被这条压住。 */
/* ⚠️ sticky / 白底 / 上边线放在**外层**（整宽），限宽放在内层 ——
   两者不能合成一层：合了之后白条只有 1120 宽，两侧会透出页面灰底、
   "条"就不贯穿了（达人表单的 .form-actions 正是这个两层结构）。
   ⚠️ 覆盖达人表单那条公共规则（`.sf-shell > .form-actions` 自带 border-top + 白底），
      用 `--total` 变体精确作用于本页，**不动达人表单**。 */
.sf-shell > .form-actions--total {
  display: block;
  padding: 0;
  position: sticky;
  bottom: 0;
  z-index: 5;
  background: var(--color-surface);
  border-top: 1px solid var(--color-border);
  /* 顶部一点投影，让它"浮"在明细之上，暗示下面还有内容 */
  box-shadow: 0 -2px 10px color-mix(in srgb, var(--color-gray-900) 6%, transparent);
}
/* 内层限宽 1120 居中 —— 合计靠左、按钮靠右，两端都与内容列对齐 */
.sf-shell > .form-actions--total .eb-total__inner {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  max-width: 1120px;
  margin: 0 auto;
  padding: var(--space-3) var(--space-6);
}
.eb-total__k { font-size: var(--font-size-sm); color: var(--color-fg-2); }
.eb-total__v {
  font-size: var(--font-size-xl);
  font-weight: var(--font-weight-semibold);
  font-variant-numeric: tabular-nums;
  /* ⭐ 红色（乐哥定的）：--color-price 是本项目全站既有的"金额语言"
     （货品价格 .price、备注里的金额 .rmk-hl--money 都用它），
     与主营业务里"金额用红"的习惯一致。它不是"错误色"——
     --color-price 在令牌里就是 --color-danger 的语义别名，注释写着"价格：与危险色同源"。 */
  color: var(--color-price);
}
.eb-total__n { font-size: var(--font-size-xs); color: var(--color-muted); }
/* 按钮组推到最右（与"合计在最左"形成两端对齐） */
.eb-total__btns { display: flex; gap: var(--space-3); margin-left: auto; }

/* --------------------------------------------------------------------------
   住宿的「入住 → 离店」：**一个字段分区内**并排两个日期（乐哥：
   「住宿的开始入住和离店，要不要也放同一行，这样填起来更直观」）
   ⚠️ 关键：合成一格（而不是让两个独立单元格"凑"到同一行）。
      在 CSS Grid 里，两个单元格能否同行取决于它前面有几格 ——
      住宿时前面只有"费用类型"1 格 ⇒ 两个日期各占 1 格正好被推到两行；
      以后往前加一个字段又会被打散。合成一格就与"前面有几个字段"无关。
   -------------------------------------------------------------------------- */
.eb-range { display: flex; align-items: center; gap: var(--space-2); }
.eb-range__item { flex: 1 1 0; min-width: 0; }
.eb-range__sep { flex: 0 0 auto; color: var(--color-muted); font-size: var(--font-size-sm); }

/* ⚠️⚠️ 日期控件高度必须对齐标准输入框（44px）。
   `DateTimePicker` 的触发按钮默认 40px（见 datetime-picker.css 的 .dtp-trigger），
   而全站 `.input` / `.select` 是 44px ⇒ 不补这条，日期框会比旁边的输入框**矮 4px**，
   一行里两个框高低不齐（本项目对这类 1~4px 错位一贯要求对齐）。 */
.eb-fld .dtp-trigger { height: 44px; }

/* 明细区：明细卡直接坐在分区卡里，不再需要独立的分区标题行
   （标题已由 .module-card__head 承担） */
.eb-dt .dt__bd { padding: var(--space-4); }
.eb-dt .eb-grid { gap: var(--space-4) var(--space-4); }

/* 「再加一笔」——放在明细分区卡的底部，整宽虚线按钮 */
.eb-add {
  width: 100%; margin-top: var(--space-3); height: 44px;
  border: 1px dashed var(--color-border); border-radius: var(--radius-lg);
  background: transparent; color: var(--color-accent-text);
  font-size: var(--font-size-base); font-family: inherit; cursor: pointer;
}
.eb-add:hover { background: var(--color-accent-bg); border-color: var(--color-accent); }

/* 凭证上传格
   ⚠️ 必传的两格（支付凭证 / 发票）用**主色虚线**而不是原来的灰虚线 ——
      灰虚线看着像"选填的装饰位"，而这两格不传就提交不了。
      已传的仍是绿色实线（.eb-up--done），"传没传"一眼可辨。 */
.eb-grid--up { margin-top: var(--space-4); }
.eb-up {
  display: flex; align-items: center; gap: var(--space-2);
  min-height: 44px; padding: var(--space-2) var(--space-3);
  border: 1px dashed var(--color-primary-200); border-radius: var(--radius-md);
  background: var(--color-accent-bg); color: var(--color-accent-text);
  font-size: var(--font-size-sm); cursor: pointer;
}
.eb-up:hover { border-color: var(--color-accent); }
/* 走替票时发票那格是"不用传"的说明 —— 退回中性灰，别让它看着还能点 */
.eb-up--na {
  border-style: solid; border-color: var(--color-border-soft);
  background: var(--color-surface-2); color: var(--color-muted);
  cursor: default; font-size: var(--font-size-sm);
}
.eb-up--done { border-style: solid; border-color: var(--color-success); background: var(--color-success-bg); color: var(--color-success-text); cursor: default; }
.eb-up__img { width: 32px; height: 32px; object-fit: cover; border-radius: var(--radius-sm); flex: 0 0 auto; }
.eb-up__pdf {
  flex: 0 0 auto; padding: 2px 6px; border-radius: var(--radius-sm);
  background: var(--color-danger-bg); color: var(--color-danger); font-size: var(--font-size-xs);
}
.eb-up__name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--font-size-xs); }
.eb-up__del { border: none; background: transparent; color: var(--color-danger); font-size: var(--font-size-xs); cursor: pointer; }
/* ⚠️ `.eb-up` / `.eb-up--done` 等**单文件时代**的样式已无引用（2026-09-19 深夜改多文件）——
   被下面 `.eb-files` 系列取代。这里**不删**这两个已无引用的类：
   `.eb-up--na`（走替票时发票那格的"不用传"说明）**仍在用**，它与 `.eb-up` 同族、
   删掉基类会让下一条规则无从参照。留着只占几行、不产生视觉效果。 */
.eb-opt { color: var(--color-muted); font-weight: var(--font-weight-regular); font-size: var(--font-size-xs); }

/* ==========================================================================
   多文件上传区（2026-09-19 深夜，乐哥：「需要支持多个文件上传」「支持拖入、粘贴」）
   ──────────────────────────────────────────────────────────────────────────
   形态：已传的文件排成一行 54px 方块（缩略图），末尾一个「＋」追加格。
   ⭐ 为什么横排而不是"一行一个"（实测数据支撑）：
      这块可用宽 **474px** ⇒ 一排能放 **7 个**（54 格 + 8 间距 = 62px/格，474÷62=7）。
      而"一行一个"3 个文件就 185px（比旁边「发票」格高 84px），明细卡跟着变高。
      放不下时会自动折行（flex-wrap 的自然行为）。
      ⚠️⚠️ 实测数据（2026-09-20 逐档探针，**方块的尺寸改过，数据要跟着重测**）：
          · 方块 44px 时：每格占 52px ⇒ 一排 8 个；0/3/6 个 = 46px，8/10 个 = 98px（两行）
          · 方块 **54px 时（当前）**：每格占 62px ⇒ 一排 **7 个**；
            实测 9 个文件 = **118px**（7 + 3 两行）
          ⚠️ 两次都踩过同一件事：**把估算值当实测值写进注释**（44 那版写成"10 个也只占 44px"）。
             ⇒ 凡"能放几个 / 多高"的结论，一律**改完后用探针逐档重量一遍**再写。
   ⚠️ 还有一个"乘数效应"要记住：**方块尺寸 → 每行容量 → 折行阈值 → 上传格高度 → 明细卡高度**。
      所以以后调方块大小时，上面这串数据全都要重测（不是只改一个数就完事）。

   ⚠️ 高度锁在一档固定值（`min-height`），**两格必须等高、且各状态下不变**：
      它要和右列「发票」那格永远顶部对齐 —— 两格高度不同会让整个明细卡的网格歪掉
      （本项目对这 1~4px 错位一贯要求对齐，见 .eb-range 上方那段）。
      ⚠️ 2026-09-20 起空态引导（"点击选择、拖入或粘贴截图"）放进了框**里面**、
         与「＋」**同一行** —— 是行内元素、不新起一行，所以不影响高度。
         （曾经的做法是把这句并进框下面的 field-hint 那一行；那样「发票」那格
          底下空着、用的人完全不知道能拖能粘，见 .eb-guide 上方那段。）
   ⚠️⚠️ 2026-09-20 **再次调高**（乐哥：「上传支付凭证，还有发票的框框要不要高一点，
       现在太矮了」）。量化了"矮"在哪：原来是方块 44px 塞进 46px 容器，
       **上下各只剩 1px** —— 几乎顶到虚线边框，所以显局促
       （对比其他输入框也是 44px，但里面是文字、居中后显得饱满）。
       ⇒ 改为容器 **68px** + 方块 **54px**（上下各留 7px），空态和已传文件都宽松，
         缩略图同时放大约 23%（看发票照片更容易分辨）。
       ⚠️ 代价是每笔明细卡 +22px（5 笔多 110px）—— 这是当时对比三档后乐哥选的档位，
          将来若要再调，别只改容器高度而不改方块（那就退回"只有留白变多"的 A 档观感）。
   ⚠️ 颜色全部走既有 token：主色虚线 + 主色浅底（与旧的单文件上传格同一套语言），
      拖入高亮复用全站既有的 `.upload-drop.is-dragover` 配色（主色实边）。
   ========================================================================== */
.eb-files {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  /* 68px（2026-09-20 调高，乐哥「框框要不要高一点，现在太矮了」）——
     原先 44px 时方块 44px 上下只剩 1px，顶着边框显局促。 */
  min-height: 68px; padding: 0 var(--space-3);
  border: 1px dashed var(--color-primary-200); border-radius: var(--radius-md);
  background: var(--color-accent-bg);
  cursor: pointer;
  transition: border-color var(--motion-fast) var(--motion-ease-standard),
              background var(--motion-fast) var(--motion-ease-standard);
}
.eb-files:hover { border-color: var(--color-accent); }
.eb-files:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }
/* 拖入高亮（复用全站 .is-dragover 语言：主色实边 + 稍深底） */
.eb-files.is-dragover { border-style: solid; border-color: var(--color-accent); background: var(--color-primary-50); }
/* 粘贴目标：点过这一格之后才标出来 —— 让"Ctrl+V 会粘到哪"一眼可见。
   ⚠️ 用**实线 + 主色**与"拖入中"区分不开也没关系：两者都是"这一格是当前目标"，
      而且拖入时用户手上有鼠标、粘贴时看的是边框，不会同时发生。 */
.eb-files.is-paste-target { border-style: solid; border-color: var(--color-accent); }
/* 上传中：降低不透明度，让"正在传"有反馈（不转圈 —— 这一格太矮，圈会挤掉方块） */
.eb-files.is-uploading { opacity: .6; pointer-events: none; }

/* ── 空态引导（2026-09-20 乐哥「UI 升级下」）────────────────────────────────
   改前：框里空态只有一个「＋」，右边一大片空白 —— 看不出这格能放几个、
        更看不出可以拖入或粘贴；说明还躲在框**下面**的小字里，且只有「支付凭证」
        那格有。改后引导语进框、与「＋」同一行。
   ⚠️ 是**行内元素、不新起一行** ⇒ 高度仍是 44px（+边框=46），
      与「发票」那格永远对齐 —— 这是这块最不能破的不变量。 */
.eb-guide { font-size: var(--font-size-xs); color: var(--color-meta); white-space: nowrap; }
.eb-guide b { color: var(--color-accent-text); font-weight: var(--font-weight-medium); }

/* 三种状态同一时刻只显示一条；默认只留 idle。
   ⚠️ 用 CSS 切而不是在回调里改 textContent：dragover 每秒触发几十次，
      重建文本节点既浪费、文案还会闪；切类名则由浏览器合成，零抖动。 */
.eb-guide__drop, .eb-guide__paste { display: none; }
.eb-files.is-dragover .eb-guide__idle { display: none; }
.eb-files.is-dragover .eb-guide__drop { display: inline; }
.eb-files.is-paste-target:not(.is-dragover) .eb-guide__idle { display: none; }
.eb-files.is-paste-target:not(.is-dragover) .eb-guide__paste { display: inline; }
/* 已有文件时**不显示任何引导文字**（连拖入/粘贴的实时提示也不显示）：
   ⚠️⚠️ 这里踩过一个边缘问题：文件多到快占满一行时（例如 8 个 ⇒ 已占 424px、
      只剩 47px），那条提示文字（约 112~144px）放不下就会**折行**，
      于是"点一下这一格"会让整格从 46px 跳到 92px、点别处又跳回来 —— 明显的抖动。
   ⭐ 取舍：有文件时不靠文字确认，改靠**边框变实线 + 主色**（空间反馈仍然明确：
      换另一格会立刻看到实线边框移过去）。用户此时已经用过这一格，
      不需要再读一遍"点击选择、拖入或粘贴"；而**高度恒定**比多一句提示更值。
   ⚠️ 隐藏的是**整条 `.eb-guide`**、不是里面的子元素：子元素 display:none 后
      外层 span 仍是 flex item、仍占一个 8px 的 gap，会在「＋」后留出像 bug 的空隙。 */
.eb-files.has-files .eb-guide { display: none; }

/* 单个文件方块（54×54）—— ⚠️ 比上传格（68px）矮 14px，上下各留 7px 的呼吸；
   ⚠️ 这两个数要**成对**改：只改容器高度会让方块重新贴边（退回"只有留白变多"的观感）。 */
.eb-file {
  position: relative; width: 54px; height: 54px; flex: 0 0 auto;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--color-border); border-radius: var(--radius-md);
  background: var(--color-surface); overflow: visible;
}
.eb-file__img { width: 100%; height: 100%; object-fit: cover; border-radius: var(--radius-md); display: block; }
/* PDF 没有缩略图 → 显示 PDF 标签（不要留空白，否则看着像没传成功） */
.eb-file__t {
  /* 方块 44→54 后，只靠原来的 xs 字号会显得空 —— 提到 sm */
  font-size: var(--font-size-sm); font-weight: var(--font-weight-semibold);
  color: var(--color-danger);
}
.eb-file--pdf { background: var(--color-danger-bg); border-color: var(--color-border); }
/* 已满上限时末尾那个数字格 */
.eb-file--full { font-size: var(--font-size-xs); color: var(--color-muted); background: var(--color-surface-2); }

/* 移除按钮：贴在方块右上角（负偏移）—— 方块只有 44px，放里面会盖住缩略图 */
.eb-file__x {
  /* 方块变大后按钮也略放大（16→18），否则在一个 54px 的方块上显得过小、不好点 */
  position: absolute; top: -6px; right: -6px; width: 18px; height: 18px; padding: 0;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--color-border); border-radius: 50%;
  background: var(--color-surface); color: var(--color-muted);
  cursor: pointer; line-height: 1;
  transition: background var(--motion-fast) var(--motion-ease-standard),
              color var(--motion-fast) var(--motion-ease-standard);
}
/* ⚠️ 白字用 `var(--color-surface)`（= #FFFFFF）而不是裸 `#fff` ——
   本页有门禁"报销表单样式里不许出现裸十六进制颜色"，且全站既有惯例也是这么写的
   （见 components.css 的 .link-btn 区域）。 */
.eb-file__x:hover { background: var(--color-danger); border-color: var(--color-danger); color: var(--color-surface); }

/* 「＋」追加格：与文件方块同尺寸，虚线 → 一眼看出"这里还能加" */
.eb-file-add {
  width: 54px; height: 54px; flex: 0 0 auto; padding: 0;
  display: flex; align-items: center; justify-content: center;
  border: 1px dashed var(--color-primary-200); border-radius: var(--radius-md);
  background: var(--color-surface); color: var(--color-accent-text);
  cursor: pointer;
}
.eb-file-add:hover { border-color: var(--color-accent); background: var(--color-accent-bg); }

/* 手机端：方块收到 40px（一行能多放一个），移除按钮稍微往内收一点防出界 */
@media (max-width: 768px) {
  .eb-file, .eb-file-add { width: 40px; height: 40px; }
  .eb-file__x { top: -4px; right: -4px; }
}

/* 排期选择弹窗 */
.eb-ps-list { max-height: 320px; overflow-y: auto; margin-top: var(--space-3); }
.eb-ps-row {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-2) var(--space-3); border-radius: var(--radius-md); cursor: pointer;
}
.eb-ps-row:hover { background: var(--color-surface-2); }
.eb-ps-row.is-on { background: var(--color-accent-bg); }
.eb-ps-inf { flex: 1; font-size: var(--font-size-sm); }
.eb-ps-d { font-size: var(--font-size-xs); color: var(--color-muted); font-variant-numeric: tabular-nums; }
.eb-ps-empty { padding: var(--space-6); text-align: center; color: var(--color-muted); font-size: var(--font-size-sm); }

/* 手机端：单列 + 汇总不换行截断 */
@media (max-width: 768px) {
  .eb-grid { grid-template-columns: 1fr; }
  .eb-sum { flex-direction: column; align-items: flex-start; gap: var(--space-1); }
  .eb-chip { height: 32px; }
}

/* 明细卡片头（.dt__*）—— 2026-09-19 补：
   ⚠️ 这几个类名我先在原型里用了、也在产品代码里直接用了，但**产品 CSS 里从没定义过**
      （原型是独立文件、自带样式，所以原型看着正常）。实测截图发现卡片头变成
      「1交通出行¥860.00删除」全挤成一坨 —— 典型的"用了不存在的类名却不报错"。 */
.eb-dt .dt__hd {
  display: flex; align-items: center; gap: var(--space-2);
  padding: var(--space-3) var(--space-4);
  background: var(--color-surface-2);
  border-bottom: 1px solid var(--color-border-soft);
}
.eb-dt .dt__no {
  flex: 0 0 auto; width: 22px; height: 22px; border-radius: 50%;
  background: var(--color-accent); color: var(--color-accent-on);
  font-size: 12px; line-height: 22px; text-align: center;
}
.eb-dt .dt__kind { font-size: var(--font-size-sm); font-weight: var(--font-weight-medium); }
.eb-dt .dt__amt {
  margin-left: auto; padding-left: var(--space-3);
  font-size: var(--font-size-sm); font-weight: var(--font-weight-medium);
  font-variant-numeric: tabular-nums;
}
.eb-dt .dt__del {
  flex: 0 0 auto; border: none; background: transparent;
  color: var(--color-danger); font-size: var(--font-size-sm);
  cursor: pointer; padding: 0 var(--space-1);
}
.eb-dt { border: 1px solid var(--color-border-soft); border-radius: var(--radius-lg); background: var(--color-surface); }
.eb-dt + .eb-dt { margin-top: var(--space-3); }

/* ==========================================================================
   「我的报销」列表按单折叠（2026-09-19，配合多明细报销单）
   ─────────────────────────────────────────────────────────────────────────────
   一张报销单含多笔明细 → 列表折叠成一行摘要（几笔 · 合计 · 事由 · 日期范围 · 状态），
   点击展开看每笔。**单笔的单不折叠**（直接是普通行）—— 库里 260 条多为历史单笔，
   一律折叠等于给所有人凭空多一次点击。

   ⚠️ 展开/收起只切 class（`tr.me-item--child.is-open`），不重新渲染：
      重渲染会丢滚动位置，还会把"正在看第 5 笔"变成"回到列表顶部"。
   ========================================================================== */
.me-sheet > td {
  padding: 0;                             /* 内边距交给内部 .me-sheet__in，避免 td 直接做 flex */
  background: var(--color-surface-2);
  cursor: pointer;
}
.me-sheet:hover > td { background: var(--table-row-hover); }   /* 与全站表格 hover 同一色，别自造 */
.me-sheet__in {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-2) var(--space-4);
  flex-wrap: wrap;
}
.me-sheet__caret { color: var(--color-muted); font-size: var(--font-size-sm); width: 12px; }
.me-sheet__n { font-weight: var(--font-weight-medium); }
.me-sheet__amt { font-weight: var(--font-weight-medium); font-variant-numeric: tabular-nums; }
.me-sheet__reason { color: var(--color-fg); }
.me-sheet__range { color: var(--color-muted); font-size: var(--font-size-sm); }
.me-sheet__st { margin-left: auto; }

/* 折叠的子明细行：默认收起；展开只在"有 .is-open"时出现 */
tr.me-item--child { display: none; }
tr.me-item--child.is-open { display: table-row; }
/* 缩进一小格 + 左侧竖线，让人一眼看出"这几行属于上面那张单" */
tr.me-item--child > td:first-child {
  padding-left: var(--space-6);
  box-shadow: inset 2px 0 0 var(--color-border-soft);
}

/* 凭证/发票缩略图（约 2KB 的本地小图，原图在飞书） */
.me-thumb {
  display: block; float: left; width: 28px; height: 28px; margin: 0 var(--space-2) 0 0;
  object-fit: cover; border: 1px solid var(--color-border-soft);
  border-radius: var(--radius-sm); cursor: zoom-in;
}
/* 「+N」（2026-09-19 深夜，多文件附件）：跟着缩略图一起 float: left，
   尺寸与缩略图一致（28px）—— 让它读起来是"这一排里的一个"，而不是另一段文字。 */
.me-thumb-more {
  display: flex; float: left; align-items: center; justify-content: center;
  width: 28px; height: 28px; margin: 0 var(--space-2) 0 0;
  border: 1px solid var(--color-border-soft); border-radius: var(--radius-sm);
  background: var(--color-surface-2); color: var(--color-muted);
  font-size: var(--font-size-xs); cursor: default;
}

/* 明细卡片「说明（备注）」尾行（2026-09-19 乐哥指定字段顺序）
   顺序：费用类型 → 类型相关（交通方式/出发到达/日期）→ 金额 → 发票类型
        → 支付凭证 → 发票 → **说明**（这里）
   ⚠️ 独立成一段而不是塞进上面的两列网格：备注可能写得较长（"汉庭王府井店 3 晚"），
      挤在半列里看不全；也与"钱的字段"分开，扫一眼不会混。 */
.eb-grid--tail { margin-top: var(--space-3); }
.eb-fld--full { grid-column: 1 / -1; }

/* ==========================================================================
   登录页 · 财务门面（2026-09-20）
   乐哥：「登录页面的名字，图啥的换下，财务相关的，弄金钱相关符号吧」
        +「我觉得登录也，财务和达播台的，是不是得分开？」

   ⭐ 分的是**门面**，不是账号：从 `/finance` 进来的人看到这一套（金币 ¥ + 金色调），
      其它来路看到保留达播主体的通用门面。底层 users / 权限 / 会话完全共用。
      （机制说明见 public/js/pages/login.js 顶部的 entryKind / FACADE）

   ⚠️ 下面三个金色是**财务标识专用色**，与 js/icons.js 的 financeLogo 渐变同色系。
      它们只出现在登录门面（和模块页头徽标）上，**:不加入设计令牌**——
      写进 tokens 就会有人拿去做按钮/标签/图表，金色一旦铺开就廉价了。
   ⚠️ 白字压在金色上必须够深：实测 #A8741A → #8A5C0E 这段与 #fff 的对比度
      在 4.6:1 以上（AA 合格）；换成更亮的金（如 #F5BA18）会掉到 2:1 以下、看不清。
   ========================================================================== */
.login-root--fin .login-hero {
  background:
    radial-gradient(1200px 900px at 80% 20%, rgba(255,255,255,0.20), transparent 55%),
    linear-gradient(135deg, #A8741A 0%, #8A5C0E 45%, #C08F24 100%);
}
/* ⚠️ 这条覆盖**已删除**（2026-09-20）：它原本是"金币标识在金色底上太糊、把底衬提亮一档"
   （金币是金色、压在金色 hero 上确实糊）。现在标识统一成公司图，
   而 `.login-hero__logo` 的通用底衬已经是近不透明的白（见该处说明），
   两个门面用同一个底衬即可 —— 留着这条反而会把财务门面的底衬又改成半透明、重新变糊。 */
