/* ==========================================================================
   达播工作台 — pages-influencer.css
   达人列表 / 达人详情
   ========================================================================== */

/* ============================ 达人列表 ============================ */

.batch-bar {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-4);
  margin-bottom: var(--space-4);
  background: var(--color-primary-50);
  border: 1px solid var(--color-primary-100);
  border-radius: var(--radius-md);
  font-size: var(--font-size-sm);
}

.batch-bar__count {
  font-weight: var(--font-weight-medium);
  color: var(--color-accent-text);
}

.platform-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  height: 20px;
  padding: 0 var(--space-2);
  border-radius: var(--radius-sm);
  border: 1px solid var(--color-border);
  color: var(--color-fg-2);
  font-size: var(--font-size-xs);
  background: var(--color-surface);
}

.platform-dot {
  width: 6px;
  height: 6px;
  border-radius: var(--radius-pill);
  background: var(--color-accent);
}

/* 达人列表：平台+机构竖排列表（上下排列，机构彩色徽章） */
.cell-agency-list {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-top: 4px;
}
.cell-agency-row {
  display: flex;
  align-items: center;
  gap: 5px;
  max-width: 100%;
  min-width: 0;
  font-size: var(--font-size-xs);
  color: var(--color-fg-2);
}
.cell-agency-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--color-accent);
  flex-shrink: 0;
}
.cell-agency-platform {
  flex-shrink: 0;
  color: var(--color-fg-2);
}
/* 机构标签（统一 .tag 风格）在列表/详情行内超长截断 */
.cell-agency-row .tag,
.platform-detail-row .tag {
  flex-shrink: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}

/* 展开卡片：平台账号/机构行 */
.platform-detail-row {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 4px 0;
  min-width: 0;
}
.platform-detail-platform {
  color: var(--color-fg);
  font-weight: var(--font-weight-medium);
  flex-shrink: 0;
}
.platform-detail-account {
  color: var(--color-muted);
  font-size: var(--font-size-xs);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ============================ 达人详情 ============================ */

/* 达人详情内容区与编辑页统一：整体包在 .sf-shell 单卡片内，居中限宽 */
.detail-shell {
  max-width: var(--form-max-width);
  margin-left: auto;
  margin-right: auto;
}

/* 通用：外壳不再是一整张大白卡，改为「Tab 栏 + 一列模块卡」
   达人详情页用 .detail-shell--modules，达人表单页用 .sf-shell--modules，共用同一套规则 */
.detail-shell--modules,
.sf-shell--modules {
  background: transparent;
  border: none;
  box-shadow: none;
  overflow: visible;
}
/* ⚠️⚠️ `overflow: visible` 必须**单独写一条高特异性规则**（2026-09-19 修 bug）。
   ─────────────────────────────────────────────────────────────────────────────
   上面那条 `.sf-shell--modules { ... overflow: visible }` 特异性是 (0,1,0)，
   而文件后面（371 行）的 `.sf-shell { overflow: hidden }` **特异性相同、位置更靠后**
   ⇒ 后者胜出 ⇒ **`--modules` 的 `overflow: visible` 从来没有生效过**。
   实测证据（浏览器 computed）：`<div class="sf-shell sf-shell--modules">` 的
   `overflow-y` 是 `hidden` 而不是 `visible`。

   为什么这次必须修（不只是"洁癖"）：`overflow: hidden` 会**创建新的滚动容器**，
   于是 `position: sticky` 元素的"粘附参照"从视口变成那个容器 ⇒
   报销单新加的底部固定汇总条**完全粘不住**（实测：粘附目标算错，元素被推到视口下方）。
   ⇒ sticky 的祖先链上**一个 overflow != visible 的祖先都不能有**（`clip` 除外，它不建滚动容器）。

   为什么这样修是安全的：`.sf-shell--modules` 的整个意图就是"去掉外壳"
   （background/border/box-shadow 全清），**没有圆角、没有需要裁切的东西**；
   而真正需要 `hidden`（为了让内容跟随圆角裁切）的是**有边框圆角**的 `.sf-shell` 本身。
   受影响的是 3 个用该变体的表单页（达人表单 / 签约公司表单 / 报销单），
   均为「Tab 或分区卡」结构、内部无通栏宽表 ⇒ 已逐一验证无横向溢出。
   用 `.detail-shell--modules` 的两个详情页不受影响（`.detail-shell` 本就没设 overflow）。 */
/* ⚠️⚠️ 这条必须**高特异性**（`.sf-shell.sf-shell--modules` = (0,2,0)），
   因为文件后面（496 行）的 `.sf-shell { background/border/overflow/... }` 特异性 (0,1,0)——
   看似"--modules 更具体"其实**同源单类、平手**，此时**位置靠后者胜**。
   ─────────────────────────────────────────────────────────────────────────────
   🐞 2026-09-19 只发现了 `overflow` 中招（见下方注释），修了它一条；
   🐞 2026-09-28 乐哥报「二级页卡片里面又套了一层卡片，2 层」（本项目的坑**第二次发作**）：
      同一条规则里的 **`background` / `border` / `box-shadow` 也全部没生效** ——
      实测 computed：`<div class="sf-shell sf-shell--modules">` 仍是
      `background: rgb(255,255,255)` + `border: 1px` + `border-radius: 16px`（1064×1324 的大白卡），
      里面再套 2 张 `.module-card` ⇒ **卡套卡（2 层背景）**。
   ⇒ 修法：把当年漏掉的 background / border / box-shadow 一起收进高特异性规则。
      修完该元素四个属性全部归零，内容区只剩模块卡（1 层）。 */
.sf-shell.sf-shell--modules,
.detail-shell.detail-shell--modules {
  background: transparent;
  border: none;
  box-shadow: none;
  overflow: visible;
}
.detail-shell--modules .sf-body,
.sf-shell--modules .sf-body {
  background: transparent;
}
/* hero 与 Tab 栏、Tab 栏与内容之间也要留足呼吸（原来分别是 12px / 16px，显挤） */
.detail-shell--modules .detail-hero {
  margin-bottom: var(--space-5);
}
.detail-shell--modules .sf-body__content,
.sf-shell--modules .sf-body__content {
  /* ⭐ 2026-09-28 上内边距 24 → **16**（乐哥：「二级页面 tab 栏和下面内容模块间距太大了，
     这些间距你全局都排查一遍，要一致」）——改前 tab 行 → 首个内容卡 24px，
     比卡片之间的 16px 大 8px、明显空；改后与全站卡片间距同档（16），节奏一致。
     ⚠️ 这是"唯一的间距来源"（详情页）；表单页的间距由外层 padding-bottom + 本值合成，
        see `.sf-tabs` 的 padding-bottom 归零说明。 */
  padding-top: var(--space-4);
  padding-bottom: var(--space-6);
  /* ⭐ 2026-09-28 左右 padding 24 → 0（乐哥：排期详情上面和下面宽度不一致）——
     改前：页头卡/hero 贴满 shell（宽 1063），而内容卡被这 24px 左右 padding 内缩成 1015，
     上下差 48px。该 padding 是「白色大卡外壳」时代的遗产（卡嵌壳内要留呼吸），
     2026-09-28 卡套卡修复后外壳透明，module-card 自己就是卡，不再需要内缩。
     去掉后内容卡与页头/hero **完全同宽**（1063），且卡内文字(x=332)与 Tab 栏左缘天然对齐。 */
  padding-left: 0;
  padding-right: 0;
}

/* 详情页 hero：头部信息区
   ⭐ 2026-09-28 包盒（乐哥：「排期详情还得优化」）——
      改前是 `background: transparent`（当年设计是"嵌在白色大卡内"），
      2026-09-28 修复卡套卡后外壳透明，hero 失去白底衬托 ⇒ 头像+信息裸摊在灰底上。
      现与 .detail-head 同规格包成白卡：白底 + 1px 边框 + 圆角 16。 */
.detail-hero {
  display: flex;
  align-items: center;
  gap: var(--space-5);
  padding: var(--space-5) var(--space-6);
  background: var(--color-surface);
  border: 1px solid var(--color-frame-border);
  border-radius: var(--radius-lg);
  margin-bottom: var(--space-5);
}

/* 详情页 「内容分组 Tab」：与内容列左右对齐
   ⚠️⚠️ 2026-09-26 托盘化：本条有**两个**必须改的点 ——
     ① **不能再设 `background: transparent`**（原值）：托盘底色画在 `.tabs` 自己身上
        （`--tab-tray-bg`，见上文 `.tabs` 段），清掉就退化成"没有托盘的散排文字"，
        与一级 Tab 又分不开了。
     ② **不能再设 `padding`**（原值 `0 24px`）：padding 特异性高于 `.tabs` 自身的
        `padding: 4px`，会把托盘内边距一起清掉（白块紧贴托盘边、无呼吸）。
        缩进一律用 margin 表达。
   ⭐⭐ 2026-09-28 悬浮吸顶 + 胶囊化（乐哥拍板，三轮原型定稿）：
     · 通栏白底细边框（灰托盘浮在灰底上显脏 ⇒ 白底；贴左缘与卡片对齐，不再缩进 24）
     · 选中项 = 渐变蓝胶囊（白底上白指示块不可见 ⇒ ink 隐藏）
     · sticky 吸顶 top = 侧栏白岛同公式（tabs-bar-height + frame-gap + 4px）
     · 滚动后（.sf-shell.is-scrolled）半透明毛玻璃 + 阴影 =「悬浮」
     · 右侧 `.detail-head__act`（编辑等操作按钮）随 Tab 一起悬浮 */
.sf-shell .tabs {
  margin-left: 0;
  margin-right: 0;
  width: 100%;                        /* 半截托盘 → 通栏（乐哥：右边空太多） */
  justify-content: space-between;     /* 胶囊左、操作按钮右 */
  align-items: center;
  background: var(--color-surface);
  /* ⭐ 2026-09-28 边框加深（乐哥：「达人详情页 tab 没有边框，我记得刚刚沟通过」）——
     原用 `--color-frame-border`(#EBECEF)——那是**卡片留白用的极浅灰**，在白底 tab 行上
     与白卡片几乎融成一片（Δ 仅 20 阶，截图里看不出框）。tab 行是**控件容器**
     （语义同输入框），边界应比卡片更明确 ⇒ 改用 `--color-gray-300`(#DDDDDD，Δ 34)。
     ⚠️ 只加深 Tab 行这一处，不动卡片族（卡片保持 frame-border 的弱边界）。 */
  border: 1px solid var(--color-gray-300);
  /* ⭐ 2026-09-28 二次修：左右内边距 4 → 24（乐哥：「tab 模块的位置当前几乎是完全贴着
     左边的，不合理」）—— 基类 padding:4px 是"灰托盘"时代的紧凑值（托盘是独立小控件）；
     现在是**白底卡**形态，首个胶囊距容器左缘只有 5px（4px + 1px 边框，实测），
     与下方内容卡的文字缩进（24px）差一大截，读起来"贴边不成体"。
     改 24px 后：胶囊距左缘 25px ≈ 内容卡文字（333）、hero 文字——三层对齐成一条竖线。
     ⚠️ 垂直保持 4px（选中胶囊上下贴容器内缘的紧凑感是刻意的，不许一起放大）。 */
  /* ⭐ 2026-09-28 三次修订（乐哥：「底框高度还是贴着胶囊」）—— 垂直 6 → **8px**
     （胶囊距框上下 9px，明显不贴）；水平保持 24（与 `.tabs` 基类同值，胶囊距框左统一 25px）。
     ⭐⭐ 2026-09-28 第五次修订（全站 tab 统一）：**改为 12px 上下** ——
     因为本层现在是"白卡"（里面还要装内层小框 44px），
     12 + 44 + 12 + 2(边框) = **70px**，与一级页白卡（`.page-header--has-tabs`）**逐像素一致**。 */
  /* ⭐⭐ 2026-09-28 垂直内边距 12 → **9px**（乐哥：「这个 tab…感觉有一点点高了，要不矮个 10%」）——
     容器高 = 9×2 + 内层框44 + 2(边框) = **64**（原 70，矮 8.6%）；
     无内层框的页面（编辑排期）60 → **54**（正好 −10%，命中乐哥给的幅度）。
     ⚠️ 12 → 9 是**全站四处同改**（`.tabs` / `.sf-shell .tabs` / `.sf-tabs__track` /
        `.page-header--has-tabs`）——只改一处会让"tab 栏高度"重新分叉。
     ⚠️ 9px 不是 `--space-*` 档位值（令牌里没有 9）—— 它由"矮 10%"倒推得到，
        不是随手写的；改它之前先看这句注释。
     ⚠️ 胶囊（34）**不动**：乐哥当天上午刚要求过"胶囊太矮了"提到 34（见该处注释），
        这次说的"高"是**容器**厚，不该再把胶囊压回去。 */
  padding: 9px var(--space-6);
  position: sticky;
  top: calc(var(--tabs-bar-height) + var(--frame-gap) + 4px);   /* 与侧栏白岛顶同公式（90px） */
  z-index: 60;                        /* 高于内容卡，低于顶栏(1100)/下拉(1000) */
  transition: box-shadow var(--motion-base) var(--motion-ease-standard),
              background-color var(--motion-base) var(--motion-ease-standard),
              border-color var(--motion-base) var(--motion-ease-standard);
}
.sf-shell .tabs .detail-head__act {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: var(--space-2);
}
/* 悬浮态：**克制玻璃**（乐哥 2026-09-28 拍板：「玻璃用克制玻璃」）——
   透光渐变 + 饱和度提升 + 上缘高光：比原「白 82%」透（能看出底下内容在动），
   又比全液态玻璃克制（文字区仍清晰可读）。
   ⚠️ 边框**保留**（乐哥：「这个页面tab不需要边框吗？」）——基类的
      `border: 1px solid var(--color-frame-border)` 继续生效，玻璃只换底与阴影；
      ⛔ 不许把边框改成白色/透明（白边框在白卡上等于没有框，实测过）。 */
/* ⭐⭐⭐ 2026-09-28 第五次修订：**贴顶才变「液态玻璃」**（乐哥拍板两条）
   ──────────────────────────────────────────────────────────────────────────
   乐哥：「这个标签，我如果不滑动，刚进来的时候应该没那么重的阴影吧，
         是不是和其他内容叠加才有」+「这个透白毛玻璃不行，做能液态玻璃那种」
         + 三档里选了 **L3**。
   ⛔ 改前挂 `.is-scrolled`（滚 50px 就触发）——见 app.js `updateStuck` 的实测说明：
      各页 tab 的初始 y 不同（228 / 249 / 322），贴顶发生在滚 138~232px，
      固定 50px 会在"还没贴顶、下面还有 88px 空档"时就变玻璃 ⇒ 玻璃下面没有内容可透，
      只显得"莫名糊了一块"；等真贴顶时玻璃反而"用旧了"。
   ✅ 改挂 `.is-stuck`（js 用 `rect.top <= stickyTop` 判定，与页面/屏高无关）。 */
.sf-shell .tabs.is-stuck {
  background: var(--liquid-bg);
  backdrop-filter: var(--liquid-blur);
  -webkit-backdrop-filter: var(--liquid-blur);
  border-color: var(--liquid-edge);
  box-shadow: var(--liquid-shadow);
}
/* 内层小框**一起**做玻璃（乐哥：「内层小框要不要一起做玻璃」→ 做）——
   ⛔ 不做的后果（已实测）：白卡变成玻璃后，小框若仍是**不透明白底**，
      看上去就是"玻璃上贴了一张白纸"，层次全乱。
   ✅ 给它更透的白 + 更亮的边，与外壳形成**两层玻璃**的层次。 */
.sf-shell .tabs.is-stuck .tabs__tray {
  background: var(--liquid-tray-bg);
  border-color: var(--liquid-tray-edge);
}
/* 胶囊项尺寸（与 `.tab` 基类同值；选中态由基类统一定义 ——
   ⭐ 2026-09-28 全站胶囊化后，原 scoped 选中态规则（含压 transparent 的 :has 分支）已删：
   基类 `.tab.is-active` 现在直接给渐变 + 白字，无需在此重复/提权）。
   ⚠️ 本规则特异性(0,3,0)高于基类 `.tab`(0,1,0) ⇒ 基类改了这里**必须同步改**
      （本次实测：只改基类 34px，本页仍显 32px —— 就是被这条压住的）。 */
.sf-shell .tabs .tab {
  padding: 0 16px;
  border-radius: var(--radius-seg);
  height: 34px;
}
/* Tab 行里的操作按钮：浅蓝轻按钮（乐哥 2026-09-28 拍板）——比 ghost 醒目、
   不与选中胶囊抢注意力；主按钮（如「佣金配置」）保持原样 */
.sf-shell .tabs .detail-head__act .btn {
  /* ⭐ 2026-09-28 行内按钮降档（乐哥：「右边编辑、佣金配置按钮太大了，不协调」）——
     原为 btn--lg 的 44px（标准档），比同行 tab 项(32px)高一大截，且把整行撑到 54px。
     降到 **34px（紧凑档）**：与同站"列表工具栏控件"同档，行高随之回到 44px
     （34 + 内边距 4×2 + 边框 1×2），与胶囊 tab 的紧凑感一致。
     ⚠️ 只降尺寸、不动颜色/语义（浅蓝轻按钮 + 主按钮的层级保持）。 */
  height: var(--control-height-sm);
  min-height: var(--control-height-sm);
  padding: 0 var(--space-4);
}
.sf-shell .tabs .detail-head__act .btn--ghost {
  background: var(--color-primary-50);
  border-color: transparent;
  color: var(--color-accent-text);
  font-weight: var(--font-weight-semibold);
}
.sf-shell .tabs .detail-head__act .btn--ghost:hover:not(:disabled) {
  background: var(--color-primary-100);
  border-color: transparent;
  color: var(--color-accent-text);
}
/* 信息卡收缩（滚动后一行：头像 64→36，高度 ~127→60，过渡动画）
   ⚠️ 只动 height/padding（不用 transform + fill both —— 会静默创建层叠上下文遮下拉面板） */
.sf-shell .detail-hero {
  transition: height var(--motion-fast) var(--motion-ease-standard),
              padding var(--motion-fast) var(--motion-ease-standard);
  overflow: hidden;
}
.sf-shell .detail-hero .detail-avatar {
  transition: width var(--motion-fast) var(--motion-ease-standard),
              height var(--motion-fast) var(--motion-ease-standard);
  flex: none;
}
.sf-shell.is-scrolled .detail-hero {
  height: 60px;
  padding-top: var(--space-2);
  padding-bottom: var(--space-2);
  margin-bottom: var(--space-2);
}
.sf-shell.is-scrolled .detail-hero .detail-avatar {
  width: 36px;
  height: 36px;
}

.detail-avatar {
  width: 64px;
  height: 64px;
  border-radius: var(--radius-pill);
  background: var(--color-primary-100);
  color: var(--color-accent-text);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--font-size-xl);
  font-weight: var(--font-weight-semibold);
  flex-shrink: 0;
  overflow: hidden;
}

.detail-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.detail-name {
  font-size: var(--font-size-xl);
  font-weight: var(--font-weight-semibold);
  color: var(--color-fg);
}

.detail-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-2);
}

/* 所属商务（关联人员）头像列表 */
.detail-bd-list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

/* 达人列表「所属商务」列：带头像 chip */
.bd-cell-list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
}
.bd-cell-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: 1px var(--space-1) 1px 1px;
  border: 1px solid var(--color-border-soft);
  border-radius: var(--radius-pill);
  background: var(--color-surface-2);
  font-size: var(--font-size-xs);
  color: var(--color-fg);
}
.bd-cell-avatar {
  padding-top: 1px; /* 补偿中文字面偏上 */
  width: 20px;
  height: 20px;
  border-radius: var(--radius-pill);
  background: var(--color-primary-100);
  color: var(--color-accent-text);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-medium);
  flex-shrink: 0;
  overflow: hidden;
}
.bd-cell-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.bd-cell-name {
  max-width: 140px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.detail-bd-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: 1px var(--space-1) 1px 1px;
  border: 1px solid var(--color-border-soft);
  border-radius: var(--radius-pill);
  background: var(--color-surface-2);
  font-size: var(--font-size-xs);
  color: var(--color-fg);
}
.detail-bd-avatar {
  width: 20px;
  height: 20px;
  border-radius: var(--radius-pill);
  background: var(--color-primary-100);
  color: var(--color-accent-text);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-medium);
  flex-shrink: 0;
  overflow: hidden;
}
.detail-bd-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* 详情页字段：无线布局，靠字号、行间距、留白区分层级（label 上 + value 下） */
.info-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-5) var(--space-4);
  padding: var(--space-2) 0;
}

.info-item {
  padding: 0;
  background: transparent;
  border: none;
  border-radius: 0;
}

.info-item__label {
  font-size: var(--font-size-xs);
  color: var(--color-muted);
  line-height: 1.4;
  margin-bottom: var(--space-1);
}

.info-item__value {
  font-size: var(--font-size-base);
  color: var(--color-fg);
  line-height: 1.5;
  word-break: break-all;
}

/* 详情页区块小标题（佣金配置 / 开票豁免 / 平台账号 等） */
.detail-section__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  flex-wrap: wrap;
  margin-bottom: var(--space-3);
}

.detail-section__title {
  font-size: var(--font-size-lg);   /* ⭐ 2026-09-28：14(sm) → 16(lg) —— 板块标题与正文(14)同号会淹没，
                                       提到「卡片标题」档；字重同步 500 → 600（与 pages-schedule 对齐） */
  font-weight: var(--font-weight-semibold);
  color: var(--color-fg);
  margin-bottom: var(--space-3);
}

.detail-section__head .detail-section__title {
  margin-bottom: 0;
}

/* ══════════════════════════════════════════════════════════════════════════════
   「内容分组 Tab」—— 灰托盘 + 白块（2026-09-26 全站统一）
   ──────────────────────────────────────────────────────────────────────────────
   ⭐ 为什么改（乐哥 2026-09-26）：「部分页面的二级 tab，样子是不是得改改，
      当前名字下加下划线那种，和一级的冲突了」。
     冲突是真实的：业绩总表这一页，顶部「全部｜待维护｜已维护」（一级：表格视图切换）
     和卡内「直播业绩｜私域业绩」（二级：内容分组）**是同一种视觉语言** ——
     都是「文字 + 名字下一条主色下划线」，只差高度（32 / 44px）—— 用户得靠位置猜层级；
     而且二级还多一条横贯基线，比一级更"重"，反而更像主 tab。

   ✅ 解法：两级各用一套语言，靠**有没有容器**一眼区分 ——
     · 一级（表格视图切换，`.table-tabs--in-header`）＝ **散排文字 + 下划线**（页面级导航）
     · 二级（本段，`.tabs`）＝ **灰托盘 + 选中白块**（组内切换）
     这也是主流后台（TDesign / Ant Design 的 segmented）最通用的二级切换语言。

   ⚠️⚠️ 这是 `.tabs` / `.tab` 的**唯一定义处**（原来它也叫「一级 Tab（全局通用）」，
      注释已按 2026-09-26 的命名纠正：它承载的是"页面内内容分组"，不是页面级导航）。
      全站 7 处在用：业绩总表、达人详情、达人表单（新增/编辑）、签约公司详情/表单、
      新建排期/排期详情，外加两个弹窗内（成本下钻、新增用户）。
      ⇒ 将来改尺寸/配色**只改这里**。（本项目反复吃亏的一条：同一件事两套实现必然漂移。）

   ⚠️ 尺寸从 44px/16px 降到 **32px/14px**：托盘方案的项是"块"不是"栏"，
      44px 会让托盘高到 52px（44+8）盖过页面标题行；32px 是紧凑档（与表格内 TAB 项同高）。
      字号跟着降到 14px —— 且**一级反而更大（16px）**，层级方向变正确了
      （原来二级 16px 比一级的 16px 同级、只靠高度区分，本末倒置）。
   ══════════════════════════════════════════════════════════════════════════════ */
.tabs {
  display: flex;
  align-items: center;
  gap: 2px;                              /* 项间距 24 → 2（容器内项是紧邻的块，不是散排文字） */
  /* ⭐ 2026-09-28 三次修订（乐哥：「底框高度还是贴着胶囊」+「胶囊和底框左边间距没统一」）——
     实测改前：胶囊距框 左 25px(详情) vs 7px(表单/卡内) —— **左边距三处不一**；垂直 7px 仍偏贴。
     统一为 **8px 24px**：垂直 8（胶囊距框上下 9px，有明显呼吸）；
     水平 24（**三处同值** —— 胶囊距框左统一 25px，与详情页对齐）。
     ⚠️ 垂直 8 是"先给一档"的保守值；若乐哥仍觉贴可提到 10。
     ⚠️ 水平 24 是三处**统一口径**（`.tabs` 基类 / `.sf-shell .tabs` / `.sf-tabs__track` 同值）。 */
  /* ⭐⭐ 2026-09-28 垂直内边距 12 → **9px**（乐哥：「这个 tab…感觉有一点点高了，要不矮个 10%」）——
     容器高 = 9×2 + 内层框44 + 2(边框) = **64**（原 70，矮 8.6%）；
     无内层框的页面（编辑排期）60 → **54**（正好 −10%，命中乐哥给的幅度）。
     ⚠️ 12 → 9 是**全站四处同改**（`.tabs` / `.sf-shell .tabs` / `.sf-tabs__track` /
        `.page-header--has-tabs`）——只改一处会让"tab 栏高度"重新分叉。
     ⚠️ 9px 不是 `--space-*` 档位值（令牌里没有 9）—— 它由"矮 10%"倒推得到，
        不是随手写的；改它之前先看这句注释。
     ⚠️ 胶囊（34）**不动**：乐哥当天上午刚要求过"胶囊太矮了"提到 34（见该处注释），
        这次说的"高"是**容器**厚，不该再把胶囊压回去。 */
  padding: 9px 24px;                    /* ⭐ 2026-09-28 四修订：垂直 8 → 10（乐哥拍板「改到 10px」）/ 水平 24 保持
                                           ⭐⭐ 第五次修订（全站 tab 统一）：**10 → 12px** ——
                                           本层现在是"白卡"（装上内层小框后 4+34+4+2=44），
                                           12 + 44 + 12 + 2(边框) = **70px**，与一级页
                                           `.page-header--has-tabs` 逐像素一致（三处同值）。 */
  background: var(--tab-tray-bg);        /* 白底（2026-09-28 令牌已升级，见 design-tokens） */
  /* ⭐ 2026-09-28 补外框（乐哥：「有的有外框，有的没有，需要补进去」）——
     白底容器必须有完整 1px 边框才是"一张卡"；缺框时它在白卡/页头内彻底隐形。
     ⚠️ 原 `border-bottom: 0`（当年为清掉继承来的下划线基线）已删 —— 现在本块自己
        定义了完整边框，再写 border-bottom:0 会把底边打掉（三边有框、底边缺口）。 */
  border: 1px solid var(--color-frame-border);
  border-radius: var(--tab-tray-radius);
  /* ⭐ 2026-09-26：指示块（.tabs__ink）的定位参照 —— 它必须 `position: relative`。 */
  position: relative;
  /* ⚠️ 托盘要**收缩到内容宽**（不是通栏）：
     通栏的灰底会变成一条"分区横条"，与页面标题行、下方工具栏撞语言。
     ⚠️ 用 `width: fit-content` 而不是 `display: inline-flex`：inline 级元素会被父级的
        `text-align: center` 影响（达人详情页 `.detail-shell` 内就有居中上下文），
        `fit-content` 在 block 容器里恒定左对齐，不受 text-align 干扰。 */
  width: fit-content;
  max-width: 100%;
  flex-wrap: wrap;                       /* 窄屏/项多时换行，不出横向滚动条
                                            （⚠️ 不用 overflow-x: auto —— 它会让 overflow-y
                                             也变成 auto，托盘高度恰好 40px 时可能长出竖滚动条，
                                             本项目 2026-09-14 已在 .table-tabs 踩过同一个坑） */
}

/* ══════════════════════════════════════════════════════════════════════════════
   Tab 托盘的「指示块」—— 选中白块**滑过去**，不再"重新贴一次"
   ──────────────────────────────────────────────────────────────────────────────
   ⭐ 2026-09-26 动效（乐哥：「轻盈灵动」）—— 这是最"灵"的一处：
     改前：选中项自己长白底（`background` 直接切换），**换个 tab 就是"啪"地换位置**，
           用户看不出"我从哪个切到了哪个"。
     改后：托盘里只有**一个**白块，切换时它从旧位置滑到新位置 ⇒ 位移本身就是"从哪到哪"的说明。

   ⚠️⚠️ 白块由 JS 注入（app.js 的 paintTabInk），因为"哪个 tab 是选中的、它在什么位置"
      只有运行时才知道。**CSS 必须能优雅降级**：JS 没跑/跑失败时，回退成"选中项自己长白底"
      （见下面的 `:not(:has(.tabs__ink))` 那条）—— 没有这层兜底，JS 一挂就是"看不出哪个被选中"。
   ⚠️ 用 `:has()` 判"有没有装指示块"，而不是给 `.tabs` 加一个 `.has-ink` 类：
      类名要 JS 维护，而 JS 注入 ink 和加类**可能不同步**（本项目反复踩"两处状态"）。
      用结构判据 `:has()` 天然同步。
   ══════════════════════════════════════════════════════════════════════════════ */
.tabs__ink {
  position: absolute;
  /* ⭐ 2026-09-26：位置与尺寸**全量由 JS 给**（width / height / translate(x, y)，
     见 app.js 的 paintTabInk）。原实现是 CSS 固定 `top:4px; bottom:4px; left:0` + JS 只给 x ——
     那要求"托盘永远单行、且每个 tab 都恰好 托盘高−8"；托盘是 `flex-wrap: wrap`，
     窄屏换行后第二行的 tab 会拿到第一行的 y（x 对、y 错）。
     改成 JS 量 active 的 offset* 后：单行结果与原来**逐像素一致**
     （4px 内缩 = offsetTop 4 / 高度 32），换行也正确。
     ⚠️ 这条与两个托盘的 `position: relative` 是**配对**的：一个负责"参照对了"，
        一个负责"位置对了"，缺任一条白块都会跑偏（乐哥 09-26 实报过一次）。 */
  top: 0;
  left: 0;
  border-radius: var(--tab-tray-item-radius);
  background: var(--tab-tray-active-bg);
  box-shadow: var(--shadow-sm);
  pointer-events: none;                  /* 纯装饰：不拦截点击，下面照常点得到 tab */
  /* ⚠️ 曲线用 in-out（两端缓）：位移类变化两端缓才"起停不吃力"。
      用进场的 easeOut 会出现"唰地一下滑到位然后停住"——也是"傻快"的一种。 */
  transition: transform var(--motion-base) var(--motion-ease-in-out),
              width var(--motion-base) var(--motion-ease-in-out),
              height var(--motion-base) var(--motion-ease-in-out),
              opacity var(--motion-fast) var(--motion-ease);
}
/* ⭐⭐ 2026-09-28 全站胶囊化（乐哥：「所有页面 tab 胶囊这个 ui 不统一，有的有外框，
   有的没有，需要补进去」）——「白底容器 + 1px 边框 + 渐变蓝选中胶囊」成为**唯一形态**。
   白色滑动指示块（ink）全站隐藏：白块在白底容器上不可见（详情页改白底后实测选中态
   完全消失）。选中态统一定义在下方 `.tab.is-active` / `.sf-tab.is-active`（不再依赖 ink，
   也不再有「有 ink / 无 ink」两分支 —— 降级天然成立：没有 ink 也照样正确显示选中）。
   ⚠️ 本条必须放在基类 .tabs__ink **之后**：motion-system 门禁取「第一条匹配规则」检测
   position:absolute，若本条的 display:none 被先取到会误报"ink 不是绝对定位"。 */
.tabs .tabs__ink,
.sf-tabs__track .tabs__ink { display: none; }
/* 未选中项 hover：浅灰块（白底容器上可见；原半透明白块在白底上不可见） */
.tab:not(.is-active):hover { background: var(--tab-tray-hover-bg); }
.sf-tab:not(.is-active):hover { background: var(--tab-tray-hover-bg); }

.tab {
  position: relative;
  /* ⭐ 2026-09-28 32 → **34**（乐哥拍板全站 tab 统一）：与一级页胶囊同高。
     一级页 `.table-tabs--in-header .pill-filter__item` 一直是 34 —— 统一时以它为准。 */
  height: 34px;
  padding: 0 16px;                       /* 14 → 16：与一级页胶囊同值（横向留白也统一） */
  background: transparent;
  border: none;
  border-radius: var(--radius-seg);      /* 8 → 6：与一级页胶囊同值 */
  color: var(--color-fg-2);              /* 未选中：正文色（原 --color-muted 偏浅，
                                            在浅灰托盘上对比度更低） */
  font-size: var(--font-size-sm);        /* 16 → 14（令牌 sm） */
  font-weight: var(--font-weight-medium);
  white-space: nowrap;
  cursor: pointer;
  transition: color var(--motion-fast) var(--motion-ease-standard),
    background-color var(--motion-fast) var(--motion-ease-standard);
}

/* ⚠️ 下划线指示条的 `::after` 规则**已整条删除**（不是置空）。
   原因：托盘方案里"选中"由白块 + 轻投影表达，若沿用老的 `::after` 下划线描边，
   选中态会同时出现"白块 + 下划线"两个指示 —— 一个控件两种"选中"表达。
   保留一条永不生效的空规则（如 `content: none`）只会让后来者以为它还在用，故直接删。 */

/* ⚠️ 2026-09-26：hover 底色**排除选中项**（选中项已是当前项，不需要"可点"暗示）。
   ⭐ 2026-09-28：选中态改**渐变蓝胶囊**（全站统一，白底容器上唯一可见的选中表达）。 */
.tab:not(.is-active):hover {
  color: var(--color-accent-text);
  background: var(--tab-tray-hover-bg);
}

.tab.is-active {
  background: var(--gradient-brand);
  color: var(--color-accent-on);          /* 白字（渐变蓝底上） */
  font-weight: var(--font-weight-semibold);
  box-shadow: none;                       /* 原白块投影已随灰托盘方案退役 */
}

/* 达人表单/详情统一：外壳限宽 1120 居中（详情页 .detail-shell 与表单页 .sf-shell 同一宽度） */
.sf-shell {
  background: var(--color-surface);
  border: 1px solid var(--color-border-soft);
  border-radius: var(--radius-lg);
  box-shadow: none;
  overflow: hidden;
  max-width: var(--form-max-width);
  margin-left: auto;
  margin-right: auto;
}

/* 达人表单 Tab 栏：**灰托盘 + 白块**（2026-09-26，与 `.tabs` 同款 —— 见上文 `.tabs` 的说明）
   ----------------------------------------------------------------------------
   ⚠️ 与 `.tabs` 的关系：**同一套视觉、两份 DOM 结构**。
      `.tabs` 直挂按钮；`.sf-tabs` 多两层（`__inner` 限宽 1120 居中 + `__track` 托盘）。
      托盘画在 `__track` 上，`.sf-tab` 的项样式与 `.tab` 逐项对齐。
   ⚠️ 历史教训（2026-09-22 已栽过）：这两套曾经尺寸不一致（44 vs 40），
      根因就是"同一个东西两份实现、只改了一处"。⇒ 将来改尺寸**两边一起改**
      （`.tab` / `.sf-tab` 的 height / padding / font-size 必须同值）。 */
.sf-tabs {
  display: flex;
  align-items: center;
  /* ⭐ 2026-09-28 三次修订（乐哥：「胶囊和底框左边的间距，我看没统一」）——
     **水平 padding 16/24 → 0**：让框（track）贴内容列左缘，与详情页的 tab 行**同一起点**；
     框内 24px（见 `.sf-tabs__track`）⇒ 胶囊距内容列左 = 25px，与详情页完全一致。
     ⛔ 改前外层留 24px + 框内 6px ⇒ 胶囊落在 49px，比详情页(25) 右 24px —— 这就是"没统一"。
     下 0（间距由内容区 padding-top 唯一承担）。
     ⭐⭐ 2026-09-28 第五次修订：**上内边距 → 上外边距**（padding-top → margin-top）——
     为让"表单页 tab 吸顶"生效，sticky 必须挂在本层（原因见下），
     而**内边距会跟着吸顶一起固定在顶上**（玻璃条会离顶 16px）；
     外边距在 sticky 元素的框外，吸顶时**不占位**，玻璃条正好贴顶。 */
  margin-top: var(--space-4);
  padding: 0;
  border-bottom: 0;                      /* 去基线（同 .tabs：托盘的灰底已表达分组边界） */
  /* ⭐ 2026-09-28 外层白底 → 透明（乐哥：「tab 这个背景没圆角」）——
     改前本层铺一条**通栏直角白条**，把内层圆角胶囊"包"在直角白底里 ⇒ 看起来背景是方的。
     改透明后，视觉载体只剩内层 `.sf-tabs__track`（白底 + 圆角 16 + 1px 边框），
     胶囊圆角直接落在页面灰底上，一眼是"圆角容器"。 */
  background: transparent;
  overflow-x: visible;                   /* 托盘自己 flex-wrap，不需要横向滚动 */
  /* ⭐⭐ 2026-09-28 第五次修订：**表单页 tab 吸顶**（乐哥：「所有页面的 tab …
     然后悬浮，透白，整个逻辑和一级页面的一致」）。
     ⛔⛔ **sticky 必须挂在本层，不能挂 `.sf-tabs__track`**（先挂错了一次，实测抓到）：
        sticky 元素只能在**其父容器的盒子范围内**吸附 ——
        `.sf-tabs__track` 的父级是 `.sf-tabs__inner`，而那个 inner 的高度**恰好等于 track**
        （实测两者都是 60px）⇒ 父容器没有可吸附的余量 ⇒ sticky 形同虚设
        （实测：滚动 600px 后 track 的 top 直接变成 **-407**，跟着页面滚走了）。
        挂到本层后父级是 `.sf-shell`（实测高 1621）⇒ 吸附余量充足。
     ⚠️ 吸顶位置与一级页 / 二级页**同一条公式**（90px），三处必须同值。 */
  position: sticky;
  top: calc(var(--tabs-bar-height) + var(--frame-gap) + 4px);
  z-index: 60;
  transition: box-shadow var(--motion-base) var(--motion-ease-standard);
}

.sf-tabs__inner {
  display: flex;
  align-items: center;
  width: 100%;
  /* ⭐⭐ 2026-09-28 硬编码 1120 → **跟随令牌 var(--form-max-width)**。
     ───────────────────────────────────────────────────────────────────────────
     🐞 漏项事故（乐哥下午追问 `新建排期 tab 与新增达人不一样` 时才查出来）：
        上一轮把 `--form-max-width` 从 1120 放宽到 **1280**，验证时量的是
        **`.sf-shell`（透明外层容器）**＝1280 就宣布"内容区 1280 生效"——
        但用户**看不见**那个容器：表单页真正的限宽在更内层的 4 处**硬编码 1120**：
          ① `.sf-tabs__inner`（本处，tab 内层）          ✅ 生效中（computed 1280）
          ② `.sf-body__content`（内容列）                ✅ 生效中（computed 1280）
          ③ `.sf-shell > .form-actions .form-actions__inner`（底部按钮）
                ⚠️ **实测为死规则**：被 `#page-root .form-actions > .form-actions__inner`
                   `{ max-width: none }`（ID 选择器，特异性更高）覆盖 ⇒ computed = none。
                   底部按钮是**浮岛**（fit-content + 右对齐到卡片内缘 1696），**本就该贴合内容**、
                   不是"限宽 1280 的容器"。本处保留 `var(...)` 仅作防御（若将来浮岛规则移除，
                   这里仍能限制按钮行），**不要把它当成在生效的限宽**。
          ④ `.sf-shell > .form-actions--total .eb-total__inner`（多明细提单页的合计条）
                ✅ 生效中（computed 1280，实测 440→1720，与内容列同宽）
        实测后果：新增达人内容列仍是 **1120**（改前 1064，实际只 +56px，而非所报的 +216px）。
        ⇒ **这是一次假验证**：验了"外层容器"，没验"用户真正看到的元素"。
     ⚠️ 教训（已记入技能库）：
        ① 验宽度必须量**最内层的可见载体**（首张内容卡 / 输入框 / tab 托盘），不是外层包装容器；
        ② 报告"某规则生效"之前，必须读**该元素的 computed 值** —— 写过的规则可能被更特异的选择器
           覆盖（本处 ③ 就是：三处真限宽、一处死规则，只看源码分不出来）。
     ⚠️ ①②④ 三处**必须同值**（tab 内层 / 内容列 / 合计条）—— 两端要对齐成一条竖线；
        改一处不改其余会立刻左右错位。 ③ 不在其中（见上）。 */
  max-width: var(--form-max-width);
  margin: 0 auto;
  padding: 0;
}

/* 胶囊容器（与 `.tabs` 同款，2026-09-28 起为**白底 + 1px 边框**，令牌见 design-tokens） */
.sf-tabs__track {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  /* ⭐ 2026-09-28 三次修订：垂直 6 → 8、水平 6 → **24**（与 `.tabs` / `.sf-shell .tabs` 统一）
     —— 乐哥：「胶囊和底框左边的间距，我看没统一」（实测本处 7px vs 详情页 25px）。 */
  /* ⭐ 2026-09-28 四修订：垂直 8 → 10（同 .tabs，三处一致）
     ⭐⭐ 2026-09-28 第五次修订（全站 tab 统一）：**10 → 12px** ——
     本层现在是"白卡"（里面还装内层小框 44px），12 + 44 + 12 + 2(边框) = **70px**，
     与一级页 `.page-header--has-tabs`、二级页 `.sf-shell .tabs` **逐像素一致**。 */
  /* ⭐⭐ 2026-09-28 垂直内边距 12 → **9px**（乐哥：「这个 tab…感觉有一点点高了，要不矮个 10%」）——
     容器高 = 9×2 + 内层框44 + 2(边框) = **64**（原 70，矮 8.6%）；
     无内层框的页面（编辑排期）60 → **54**（正好 −10%，命中乐哥给的幅度）。
     ⚠️ 12 → 9 是**全站四处同改**（`.tabs` / `.sf-shell .tabs` / `.sf-tabs__track` /
        `.page-header--has-tabs`）——只改一处会让"tab 栏高度"重新分叉。
     ⚠️ 9px 不是 `--space-*` 档位值（令牌里没有 9）—— 它由"矮 10%"倒推得到，
        不是随手写的；改它之前先看这句注释。
     ⚠️ 胶囊（34）**不动**：乐哥当天上午刚要求过"胶囊太矮了"提到 34（见该处注释），
        这次说的"高"是**容器**厚，不该再把胶囊压回去。 */
  padding: 9px 24px;
  background: var(--tab-tray-bg);
  /* ⭐ 2026-09-28 补外框（同 `.tabs`：白底容器必须有边框，否则在白卡里隐形）；
     边框色与详情页 Tab 行**同源**（gray-300）—— 乐哥要求"两种 tab 一个样"。 */
  border: 1px solid var(--color-gray-300);
  border-radius: var(--tab-tray-radius);
  flex-wrap: wrap;
  /* ⭐⭐ 2026-09-28 第五次修订：**表单页 tab 吸顶**（乐哥：「所有页面的 tab …
     然后悬浮，透白，整个逻辑和一级页面的一致」）。
     ⛔⛔ sticky 挂在**外层 `.sf-tabs`**（不是本层）—— 原因见 `.sf-tabs` 的注释：
        本层的父级 `.sf-tabs__inner` 高度恰好等于本层 ⇒ **没有可吸附余量**，
        sticky 会形同虚设（实测：滚动 600px 后本层 top 直接 -407，跟着页面滚走）。
     ⚠️ 本层保留定位上下文（`position: relative`）—— 它是 `.tabs__ink`（绝对定位）的参照。 */
  position: relative;
}

/* ⭐⭐⭐ 2026-09-28 第五次修订：表单页 tab「贴顶才变液态玻璃」（乐哥拍板，同二级页）
   —— 判定逻辑见 app.js updateStuck；强度 = L3 档（乐哥选定），令牌见 design-tokens。 */
.sf-tabs.is-stuck .sf-tabs__track {
  background: var(--liquid-bg);
  backdrop-filter: var(--liquid-blur);
  -webkit-backdrop-filter: var(--liquid-blur);
  border-color: var(--liquid-edge);
  box-shadow: var(--liquid-shadow);
}
/* 内层小框一起做玻璃（乐哥：「内层小框要不要一起做玻璃」→ 做） */
.sf-tabs.is-stuck .tabs__tray {
  background: var(--liquid-tray-bg);
  border-color: var(--liquid-tray-edge);
}

/* 表单页「内容分组 Tab」的项（达人表单 / 签约公司表单用；报销单刻意没有 .sf-tabs）
   ----------------------------------------------------------------------------
   ⚠️ 与 `.tab` **逐项同值**（height / padding / font-size / 圆角 / 三态）——
      见上文 `.tabs` 段的说明。历史教训：2026-09-22 因为"同一个东西两份实现
      只改了一处"，出现「达人详情页 tab 44px、达人编辑页 tab 40px」（乐哥实报
      「达人列表查看，和编辑的整体 ui 有些差异」）。⇒ 改尺寸必须两边一起改。
   ⚠️ `line-height` 不再写死 44px：托盘方案的项高 32px，写死行高会把文字顶偏；
      用 flex 居中（`.sf-tabs__track` 是 align-items:center）。 */
.sf-tab {
  position: relative;
  /* ⭐ 2026-09-28 32 → **34**（全站 tab 统一）：与 `.tab` / 一级页胶囊同高。
     ⚠️ 这两套是"同一个东西的两份实现"，改一处必须同时改另一处 ——
        `tests/tab-size-consistency.test.js` 会当场报红（本次就是它抓出来的）。 */
  height: 34px;
  padding: 0 16px;                     /* 与 .tab 对齐（14 → 16，同一批统一） */
  border: none;
  border-radius: var(--radius-seg);    /* 8 → 6：与 .tab / 一级页胶囊同值 */
  background: transparent;
  color: var(--color-fg-2);
  font-size: var(--font-size-sm);      /* 与 .tab 对齐：16 → 14（令牌 sm） */
  font-weight: var(--font-weight-medium);
  white-space: nowrap;
  cursor: pointer;
  transition: color var(--motion-fast) var(--motion-ease-standard),
    background-color var(--motion-fast) var(--motion-ease-standard);
}

.sf-tab:not(.is-active):hover {
  color: var(--color-accent-text);
  background: var(--tab-tray-hover-bg);
}

.sf-tab.is-active {
  background: var(--gradient-brand);
  color: var(--color-accent-on);          /* ⭐ 2026-09-28：选中态改渐变蓝胶囊（全站统一） */
  font-weight: var(--font-weight-semibold);
  box-shadow: none;
}

/* 内容区 */
.sf-body {
  background: var(--color-surface);
}

/* 内容列统一限宽（跟随 --form-max-width，含左右 24px padding），与 Tab 栏内层、底部操作区对齐
   ⭐ 2026-09-28 硬编码 1120 → var(--form-max-width)：它是「对齐链」四环之一，
      详见 `.sf-tabs__inner` 的漏项说明（改一处必须四处同改）。 */
.sf-body__content {
  padding: var(--space-5) var(--space-6);
  max-width: var(--form-max-width);
  margin: 0 auto;
}

.sf-panel-body {
  width: 100%;
}

/* 达人表单 · 平台相关：一行一个平台 —— 左列「平台名 + 开通开关」，右列配置内容。
   左列平台名按 4 个中文字符预留宽度，长短不齐的平台名也能对齐。 */
.platform-group {
  border: 1.5px solid var(--color-border-soft);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  margin-bottom: var(--space-2);
}
.platform-group:last-child {
  margin-bottom: 0;
}
/* 第一行：平台名 + 开通开关 + 平台账号ID + 达人类型，**全部同一行**。
   踩坑（2026-09-10 乐哥反馈"UI 布局有问题"）：上一版把「平台名 + 开关」做成 132px 的
   独立左列且 align-items:center + align-self:stretch —— 它会在这块区域的整体高度里
   垂直居中，于是看着跟右边的「平台账号ID」不在同一行。现在改为第一行内联。 */
.platform-group__main {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  min-height: 44px;
}
.platform-group__head {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  align-self: stretch;
  padding-right: var(--space-4);
  border-right: 1px solid var(--color-border-soft);
}
.platform-group__name {
  min-width: 56px;   /* 按 4 个中文字符预留 */
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-fg);
}
.platform-group__head .switch { margin: 0; flex-shrink: 0; }
/* 未开通：第一行右侧给一行灰提示，避免"右边空着"的错觉 */
.platform-group__off {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  font-size: var(--font-size-xs);
  color: var(--color-fg-3);
}
/* 字段行：标签在左、控件在右（标签定宽对齐），不再各占一行 */
.pg-field {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-width: 0;
}
.pg-field__label {
  flex: 0 0 76px;
  font-size: var(--font-size-xs);
  color: var(--color-fg-2);
  text-align: right;
}
.pg-field__ctl { flex: 1; min-width: 0; }
/* 行内右侧的字段区：固定两列网格 —— 这样第一行「平台账号ID / 达人类型」与下面
   「签约机构」行的「机构名称 / 机构编码」列宽、起点完全一致（乐哥要求"输入框宽度和第一行对齐"）。
   列用 minmax(0, 1fr) 才能在内容过长时正常收缩。 */
.platform-group__fields {
  flex: 1 1 auto;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-3) var(--space-5);
  min-width: 0;
}
/* 区块内第二行起：上缘一条浅线分隔（第一行不带线） */
.platform-group__line {
  border-top: 1px solid var(--color-border-soft);
  margin-top: var(--space-3);
  padding-top: var(--space-3);
}
/* 该行右侧没有内容的行（如「腾讯互选」）：不画右侧竖线，名称 + 开关仍与其他行左对齐 */
.platform-group__head--bare {
  padding-right: 0;
  border-right: none;
}
/* 「签约机构」开关打开后展开的字段区：JS 用这个类做显隐钩子（关闭时置 display:none），
   布局沿用 .platform-group__fields 的两列网格，这里给出"展开"时的默认 display */
.platform-agency-box {
  display: grid;
}

/* 窄屏（手机）：第一行改上下堆叠、平台名与开关占满整行，
   字段区收成一列，否则同一行里塞不下 */
@media (max-width: 768px) {
  .platform-group__main {
    flex-direction: column;
    align-items: stretch;
    gap: var(--space-3);
  }
  .platform-group__head {
    align-self: auto;
    padding-right: 0;
    padding-bottom: var(--space-3);
    border-right: none;
    border-bottom: 1px solid var(--color-border-soft);
  }
  .platform-group__head--bare {
    padding-bottom: 0;
    border-bottom: none;
  }
  .platform-group__fields { grid-template-columns: 1fr; }
  .pg-field__label { flex: 0 0 64px; }
}

/* 二级胶囊筛选已收敛为全局通用组件 .pill-filter（见 components.css），达人表单不再使用 */

/* 底部操作区：外层整宽（分隔线贯穿），内层限宽、按钮右对齐到内容列右边缘 */
.sf-shell > .form-actions {
  display: block;
  padding: 0;
  border-top: 1px solid var(--color-border-soft);
  background: var(--color-surface);
}

.sf-shell > .form-actions .form-actions__inner {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-3);
  width: 100%;
  /* ⭐ 2026-09-28 硬编码 1120 → var(--form-max-width)（「对齐链」第 ③ 环，
     详见 `.sf-tabs__inner`）：否则内容列放宽后按钮组会比内容窄 160px、右缘对不齐。 */
  max-width: var(--form-max-width);
  margin: 0 auto;
  padding: var(--space-4) var(--space-6);
}

@media (max-width: 1024px) {
  .sf-tabs__inner {
    padding: 0 var(--space-4);
  }
  .sf-tab {
    margin-right: var(--space-4);
  }
  .sf-body__content {
    padding: var(--space-4);
  }
  .sf-shell > .form-actions .form-actions__inner {
    padding: var(--space-4);
  }
}

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

/* ⭐ 2026-09-27 乐哥需求：佣金历史弹窗里的**合并时间轴**
   （达人通用佣金 ＋ 排期单独维护合并切分："这个达人的费率随时间怎么变"）。
   排期覆盖行用左侧竖条 + 浅色底强调 —— 它是"例外"，与普通配置段要一眼可分。 */
.comm-timeline {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--color-border-soft);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.comm-timeline__row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  font-size: var(--font-size-sm);
  border-top: 1px solid var(--color-border-soft);
}
.comm-timeline__row:first-child { border-top: none; }
.comm-timeline__row.is-sched {
  background: var(--color-warning-bg);
  box-shadow: inset 3px 0 0 var(--color-warning);
}
.comm-timeline__when {
  flex: none;
  min-width: 150px;
  color: var(--color-fg-2);
  font-variant-numeric: tabular-nums;
}
.comm-timeline__rate { flex: 1; color: var(--color-fg); font-weight: var(--font-weight-medium); }
.comm-timeline__src { flex: none; color: var(--color-muted); font-size: var(--font-size-xs); }

/* 佣金配置：渠道分组（白底 + 渠道色边框，视频号绿框 / 抖音蓝框）+ 场景开关 */
.comm-channel {
  margin-bottom: var(--space-4);
  padding: var(--space-3);
  border-radius: var(--radius-lg);
  background: var(--color-surface);
  border: 1.5px solid var(--color-success);
}
.comm-channel--dy {
  border-color: var(--color-info);
}
.comm-channel:last-child { margin-bottom: 0; }
.comm-channel-title {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-fg);
  margin-bottom: var(--space-2);
}
/* ⭐ 2026-09-27（乐哥：「有些乱、内容有些多，排期里佣金那个展示方式就非常好」）：
   块头右侧的「当前佣金摘要」—— 学排期详情 .sd-comm-ch__note 的信息架构，
   不展开就能扫到这个渠道当前用的是多少（不必在输入框/历史行之间来回找）。
   ⚠️ 必须显式写 color：.comm-channel-title--dy 会给整个 title 上蓝色（--color-info），
      摘要继承下来会变成"蓝色强调"，抢占渠道名的视觉权重。 */
.comm-channel-sum {
  margin-left: auto;
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-regular);
  color: var(--color-muted);
  font-variant-numeric: tabular-nums;
}
.comm-channel-sum--none { color: var(--color-fg-2); opacity: .65; }
.comm-channel-title::before {
  content: '';
  width: 4px;
  height: 14px;
  border-radius: 2px;
  background: var(--color-success);
  flex-shrink: 0;
}
.comm-channel-title--dy {
  color: var(--color-info);
}
.comm-channel-title--dy::before {
  background: var(--color-info);
}
.comm-channel-warn {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 8px;
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-medium);
  line-height: 1.4;
  color: var(--color-warning);
  background: var(--color-warning-bg);
  border-radius: var(--radius-pill);
  vertical-align: middle;
}
/* 混播/私域开关关闭时，整行置灰禁用 */
.comm-off {
  opacity: 0.5;
}

/* 佣金配置卡片式：场景块（白底，与渠道淡底区分）+ 附加佣金（摘要常显 + 展开编辑） */
.comm-scene {
  border: 1px solid var(--color-border-soft);
  border-radius: var(--radius-md);
  padding: var(--space-3);
  margin-bottom: var(--space-2);
  background: var(--color-surface);
}
.comm-scene:last-child { margin-bottom: 0; }
.comm-scene-head {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
  margin-bottom: var(--space-3);
}
.comm-scene-name { font-weight: var(--font-weight-medium); font-size: var(--font-size-sm); }
.comm-scene-period {
  font-size: var(--font-size-xs);
  color: var(--color-muted);
  margin-left: 6px;
}
/* 当前生效佣金一行蓝色字（时间段 + 佣金内容），放在场次下方 */
/* ⭐ 2026-09-27：改前是蓝字（--color-info）且内容是"生效期 + 完整佣金摘要"——
   摘要与输入框/块头重复。改后**只留生效期**、改灰字：它是辅助信息，不是强调项。
   （强调项 = 输入框的值 + 块头摘要） */
.comm-current {
  margin-top: var(--space-2);
  font-size: var(--font-size-xs);
  line-height: 1.5;
  color: var(--color-muted);
}
/* ⭐ 2026-09-27 **结构改版**（乐哥：「我以为你是有做结构上的调整啊，原来也没有啊」）
   ─────────────────────────────────────────────────────────────────────────
   改前：每个场景 = 一个输入框 + 一个「附加佣金」折叠区 ⇒ 这是**表单结构**，
         一眼看不出"这个场景总共几个点、分别多少"。
   改后：学排期详情「本场佣金」——**指标格**（线上/线下/年框/其他），
         标签在上、数值在下、等分 4 列，**先看后改**；输入区收进「编辑佣金」。
   ⚠️ 与排期页 .sd-comm-ch__grid 保持同一视觉语言（等分 + tabular-nums 对齐），
      但类名独立，避免动到排期详情/排期编辑共用的样式。 */
.comm-rate-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--space-3);
  padding: var(--space-2) 0 var(--space-2);
}
.comm-rate-lbl {
  display: block;
  font-size: var(--font-size-xs);
  color: var(--color-muted);
  margin-bottom: 2px;
}
.comm-rate-val {
  font-size: var(--font-size-lg);
  font-weight: var(--font-weight-semibold);
  color: var(--color-fg);
  font-variant-numeric: tabular-nums;
  line-height: 1.4;
}
.comm-rate-val--off { color: var(--color-muted); font-weight: var(--font-weight-regular); }
/* ⭐ 2026-09-27：未配置时不铺 4 个「—」（一片空白比没数字更难看），给一行灰字 */
.comm-rate-empty {
  padding: var(--space-1) 0 var(--space-2);
  font-size: var(--font-size-xs);
  color: var(--color-muted);
}
.comm-rate-inc {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: var(--font-size-xs);
  color: var(--color-fg-2);
  padding-bottom: var(--space-1);
}
/* 场景头/展开区里的「编辑佣金」按钮靠右（不抢场景名视线） */
.comm-scene-head-act { margin-left: auto; }
.comm-scene-edit-act { display: flex; justify-content: flex-end; margin-top: var(--space-2); }
/* 编辑层：默认收起（.comm-edit-panel 由 JS 控制 display），展开后与展示层用虚线分隔 */
.comm-edit-panel {
  margin-top: var(--space-3);
  padding-top: var(--space-3);
  border-top: 1px dashed var(--color-border-soft);
}
/* 开票与税点：豁免标记（橙色标签） */
.comm-exempt-tag {
  display: inline-block;
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-medium);
  color: var(--color-warning);
  background: var(--color-warning-bg);
  padding: 1px 8px;
  border-radius: var(--radius-pill);
  line-height: 1.4;
}
/* 「开票与税点」卡内的两个板块（① 佣金开票豁免 / ② 佣金税点）：
   板块标题行（名称靠左、新增按钮靠右）+ 说明文字 + 各自的表格
   —— 概念优先：渠道降级成表格里的一列，不再拿渠道当外框（那样会把两件事挤在一起） */
.it-blk-head {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}
.it-blk-head__name {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--color-fg);
}
.it-blk-head .btn {
  margin-left: auto;
}
.it-blk-desc {
  margin-top: var(--space-2);
  font-size: var(--font-size-xs);
  line-height: 1.7;
  color: var(--color-fg-2);
}
.it-blk-desc b {
  font-weight: var(--font-weight-semibold);
  color: var(--color-fg);
}
/* 专场单独维护：一致/不一致状态标签 + 差异数字标红 */
.lock-ok, .lock-diff {
  display: inline-block;
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-medium);
  padding: 1px 8px;
  border-radius: var(--radius-pill);
  line-height: 1.4;
}
.lock-ok { color: var(--color-success); background: var(--color-success-bg); }
.lock-diff { color: var(--color-warning); background: var(--color-warning-bg); }
.lock-diff-num { color: var(--color-danger); font-weight: var(--font-weight-medium); }
.comm-scene-tag {
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-medium);
  color: var(--color-accent-text);
  background: var(--color-primary-100);
  padding: 1px 8px;
  border-radius: var(--radius-pill);
  line-height: 1.4;
}
.comm-follow {
  font-size: var(--font-size-xs);
  color: var(--color-success);
  margin-left: auto;
  background: var(--color-success-bg);
  padding: 2px 10px;
  border-radius: var(--radius-pill);
  line-height: 1.4;
}
.comm-channel--dy .comm-follow {
  color: var(--color-info);
  background: var(--color-info-bg);
}
.comm-scene-fields {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  flex-wrap: wrap;
}
.comm-scene-body {
  margin-top: var(--space-3);
  padding-top: var(--space-3);
  border-top: 1px dashed var(--color-border);
  /* ⚠️ 2026-09-27 修（乐哥截图：「你觉得你改的好看吗？」）：
     原来是 `display:flex; align-items:center` 横排 —— 那是给「输入框 + 附加佣金按钮」两件套用的。
     塞进**指标格**后，格子 / 编辑按钮 / 输入框被挤在同一行（截图里的乱象）。
     ⇒ 改**竖排**：指标格一行、按钮一行、输入区一行，各占各的。 */
  display: block;
}
.comm-field {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}
.comm-field-label { font-size: var(--font-size-xs); color: var(--color-fg-2); }
.comm-input-suffix {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.comm-input-suffix input { width: 80px; }
.comm-unit { font-size: var(--font-size-xs); color: var(--color-fg-2); }
.comm-more-wrap {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
}
/* ⚠️ .comm-extra-summary 仍被排期编辑页（schedule-form.js）使用 —— **不能删**。
   达人页已改为把摘要并进「附加佣金」按钮文案（.comm-more-sum，见下），
   原因是独立胶囊与右侧「跟随专场」胶囊**同款样式**（绿底绿字/蓝底蓝字），
   一个是"已配置的值"、一个是"跟随状态"，视觉上分不清（乐哥说的"乱"之一）。 */
.comm-extra-summary {
  font-size: var(--font-size-xs);
  color: var(--color-success);
  line-height: 1.6;
  background: var(--color-success-bg);
  padding: 2px 10px;
  border-radius: var(--radius-pill);
}
/* ⭐ 2026-09-27 新增：「附加佣金」按钮内的已配置摘要（中性灰，与绿色状态胶囊区分） */
.comm-more-sum {
  margin-left: 6px;
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-regular);
  color: var(--color-muted);
  font-variant-numeric: tabular-nums;
}
.comm-more-ico { display: inline-flex; align-items: center; margin-right: 2px; }
.comm-channel--dy .comm-extra-summary {
  color: var(--color-info);
  background: var(--color-info-bg);
}
.comm-extra {
  margin-top: var(--space-3);
  padding-top: var(--space-3);
  border-top: 1px dashed var(--color-border);
  width: 100%;
}
.comm-extra-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: var(--space-3);
}
.comm-extra-item { display: flex; flex-direction: column; gap: 6px; }
.comm-extra-item > label { font-size: var(--font-size-xs); color: var(--color-fg-2); }
.comm-extra-item .comm-input-suffix { width: 100%; }
.comm-extra-item .comm-input-suffix input { flex: 1; width: auto; }
.comm-extra-hint { margin-top: var(--space-2); }

/* 下游佣金：达人列表（表头按场景分列：专场/混播/私域，场景列内按渠道分行） */
.dc-table {
  table-layout: fixed;
}
.dc-table thead th.dc-th-scene {
  position: relative;
  border-left: 1px solid var(--color-border-soft);
}
.dc-scene-cell {
  padding: var(--space-2) var(--space-3);
  border-left: 1px solid var(--color-border-soft);
}
.dc-cell-line {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 2px 0;
  min-height: 24px;
}
.dc-cell-line--off { opacity: 0.55; }
.dc-cell-text {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  font-size: var(--font-size-sm);
}
/* 达人佣金：线上 / 线下 / 年框 三行分色（仅数字用彩色，标签/日期用默认灰） */
.dc-rates {
  display: flex;
  /* ⚠️ 原来是 `flex-direction: column` —— 同一平台的多个费率项（线上 + 返点 + 年框…）
     会**逐项堆叠**，一个达人配 3 项就把该格撑到 147px（乐哥 2026-09-13 排查「明显高行」）。
     改为横向排列 + 自动换行：列宽放得下就并排（省一半高度），放不下自动折行——
     最坏情况与原来一致，不会更差。 */
  flex-direction: row;
  flex-wrap: wrap;
  gap: 3px 10px;
  min-width: 0;
  flex: 1;
}
.dc-rate-row {
  display: flex;
  align-items: center;
  gap: 5px;
  flex-wrap: nowrap;      /* 一个费率项内部不再折行（外层 .dc-rates 负责换行） */
  font-size: var(--font-size-sm);
  line-height: 1.35;      /* 1.5 → 1.35：密集表格里的多行费率，行距略收更耐看 */
}
/* 分色：线上=主色钴蓝 / 线下=橙 / 年框=绿 / 返点=紫 / 激励=红 */
.dc-rate--online { color: var(--color-accent-text); }
.dc-rate--offline { color: var(--color-warning); }
.dc-rate--yearly { color: var(--color-success); }
.dc-rate--rebate { color: var(--color-chart-7); }
.dc-rate--incentive { color: var(--color-danger); }
.dc-rate-row .dc-rate-label {
  font-size: var(--font-size-xs);
  color: var(--color-fg-2);
  white-space: nowrap;
}
.dc-rate-row .dc-rate-num {
  font-weight: var(--font-weight-semibold);
  color: inherit;
  font-variant-numeric: tabular-nums;
}
.dc-rate-row .dc-rate-period {
  font-size: var(--font-size-xs);
  color: var(--color-fg-2);
  white-space: nowrap;    /* 「2026-09-10 起」不能被拆成两行 */
}
.dc-extra-chips {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  flex-wrap: wrap;
}
.dc-extra-chip {
  font-size: var(--font-size-xs);
  color: var(--color-fg-2);
  background: var(--color-gray-100);
  padding: 2px 8px;
  border-radius: var(--radius-pill);
  white-space: nowrap;
  line-height: 1.4;
}
.dc-chip-tag {
  display: inline-block;
  font-weight: var(--font-weight-medium);
  color: var(--color-success);
  background: var(--color-success-bg);
  padding: 2px 9px;
  border-radius: var(--radius-pill);
  flex-shrink: 0;
  font-size: var(--font-size-xs);
  line-height: 1.5;
  white-space: nowrap;
}
.dc-chip-tag--dy {
  color: var(--color-info);
  background: var(--color-info-bg);
}
.dc-follow {
  font-size: var(--font-size-xs);
  color: var(--color-fg-2);
  background: var(--color-gray-100);
  padding: 2px 10px;
  border-radius: var(--radius-pill);
  white-space: nowrap;
}
/* 上游佣金：卡片网格（货架式），按单品/套餐分两块，佣金率大字突出 */
.up-grid { display: flex; flex-direction: column; gap: var(--space-4); }
.up-section-head {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-fg);
  margin-bottom: var(--space-2);
}
.up-section-count {
  font-size: var(--font-size-xs);
  color: var(--color-fg-2);
}
.up-cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: var(--space-2);
}
.up-card {
  border: 1px solid var(--color-border-soft);
  border-radius: var(--radius-lg);
  background: var(--color-surface);
  padding: var(--space-3);
}
.up-card-top {
  display: flex;
  align-items: center;
  gap: 10px;
}
.up-card-img {
  width: 40px;
  height: 40px;
  border-radius: var(--radius-md);
  object-fit: cover;
  flex-shrink: 0;
  background: var(--color-gray-100);
}
.up-card-img--empty {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--color-fg-2);
}
.up-card-name {
  flex: 1;
  min-width: 0;
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.up-card-rate {
  font-size: var(--font-size-lg);
  font-weight: var(--font-weight-semibold);
  color: var(--color-accent-text);
  flex-shrink: 0;
  font-variant-numeric: tabular-nums;
}
.up-card-bottom {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: var(--space-2);
}
.up-card-type {
  font-size: var(--font-size-xs);
  color: var(--color-fg-2);
}
.up-card-actions {
  margin-left: auto;
  display: flex;
  gap: 2px;
}

/* 结算单：达人单元格多渠道标签（视频号/抖音 + 应付小计，点标签切渠道） */
.st-ch-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: 4px;
}
.st-ch-tag {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 8px;
  border-radius: var(--radius-pill);
  border: 1px solid transparent;
  background: var(--color-success-bg);
  color: var(--color-success);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-medium);
  cursor: pointer;
  transition: color var(--motion-fast) var(--motion-ease-standard),
    background-color var(--motion-fast) var(--motion-ease-standard),
    border-color var(--motion-fast) var(--motion-ease-standard);
}
.st-ch-tag--dy {
  background: var(--color-info-bg);
  color: var(--color-info);
}
.st-ch-tag:hover {
  border-color: var(--color-border);
}
.st-ch-tag.is-active {
  background: var(--color-primary-50);
  border-color: var(--color-primary-200);
  color: var(--color-accent-text);
  font-weight: var(--font-weight-medium);
}
.st-ch-tag__amt {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum", "lnum";
}

/* 静态渠道标签（单渠道行，乐哥 2026-09-15：渠道从独立列挪到达人名下）
   ⚠️ 与可点标签用同一个 .st-ch-tag 基类（保证 pill 外观/配色一致），
      只覆盖"可交互"的三处视觉暗示 —— 否则单渠道标签看着能点、点了却没反应。
      它**不带 data-ch**，绑定侧也据此跳过（见 influencer-settlement.js 的渠道标签事件）。 */
.st-ch-tag--static {
  cursor: default;
}
.st-ch-tag--static:hover {
  border-color: transparent;   /* 去掉"悬停高亮"这个可点暗示 */
}

/* 达人佣金：历史生效版本（对应佣金下一条条展示） */
.comm-history {
  margin-top: var(--space-2);
}
.comm-history-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--font-size-xs);
}
.comm-history-table td {
  padding: 4px 8px;
  border-bottom: 1px solid var(--color-border-soft);
  vertical-align: top;
  color: var(--color-fg-2);
}
/* 最新 3 段：整行蓝色 */
.comm-history-row--cur td {
  color: var(--color-info);
  font-weight: var(--font-weight-medium);
}
.comm-history-period {
  width: 38%;
  white-space: nowrap;
  color: var(--color-muted);
}
.comm-history-row--cur .comm-history-period {
  color: var(--color-info);
}
.comm-history-toggle {
  margin-top: 6px;
  padding: 0;
  color: var(--color-fg-2);
}
.comm-history-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

/* 特殊结算佣金（达人 × 渠道×场景 × 商品/套餐） */
.spc-section .spc-group { margin-bottom: var(--space-3); }
.spc-group__head {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-fg);
  margin-bottom: var(--space-2);
}
.spc-group__head::before {
  content: '';
  width: 3px;
  height: 14px;
  border-radius: 2px;
  background: var(--color-accent);
}
.spc-table { margin: 0; }
.spc-lock-tag {
  display: inline-flex;
  align-items: center;
  padding: 4px 10px;
  border-radius: var(--radius-sm);
  background: var(--color-surface-2);
  color: var(--color-fg-2);
  font-size: var(--font-size-xs);
}
.spc-toggle { gap: 6px; }

/* 排期佣金覆盖确认：排期编号链接 + 时间 */
.spc-sched-row { display: flex; align-items: center; gap: var(--space-3); }
.spc-sched-link { color: var(--color-info); font-weight: var(--font-weight-medium); text-decoration: none; cursor: pointer; }
.spc-sched-link:hover { text-decoration: underline; }
.spc-sched-time { color: var(--color-fg-2); }

/* 排期佣金覆盖确认：佣金对比（当前 → 覆盖后） */
.spc-sched-card { padding: var(--space-1) 0 var(--space-2); }
.spc-sched-card + .spc-sched-card { border-top: 1px solid var(--color-border-soft); }
.spc-sched-comm { display: flex; gap: var(--space-2); align-items: baseline; color: var(--color-fg-2); margin-top: 2px; }
.spc-sched-comm-label { color: var(--color-muted); font-size: var(--font-size-xs); flex-shrink: 0; }

/* 覆盖确认弹窗：前后佣金差异红色高亮 */
.spc-comm-diff { color: var(--color-danger); font-weight: var(--font-weight-semibold); }

/* 佣金配置板块卡片：板块之间清晰分隔（佣金配置 / 开票与税点 / 特殊佣金） */
.commission-section {
  border: 1px solid var(--color-border-soft);
  border-radius: var(--radius-lg);
  padding: var(--space-4);
  margin-bottom: var(--space-4);
  background: var(--color-surface);
}
.commission-section:last-child { margin-bottom: 0; }
.commission-section__sub {
  margin-top: var(--space-4);
  padding-top: var(--space-4);
  border-top: 1px solid var(--color-border-soft);
}

/* ==========================================================================
   达人经营 · 明细表：数值单元格禁止断行（2026-09-17）
   --------------------------------------------------------------------------
   问题：`-¥15,280.55` 会在负号后断成两行 —— 第一行只有 "-"、第二行是 "¥15,280.55"。
        视觉上像两个内容，且**负号与数字分离有误读成正数的风险**（老板要念数出去）。
   实测（1900px）：成本类目列与「利润（预估）」列都有此现象。
   修法：数值单元格禁止换行 + 同步加宽列（见 influencer-profit.js 的 W_MONEY/W_CAT）。
   ⚠️ 只作用于本页明细表（`#ip-body table`），不动全站 .table ——
      其他表列宽预算不同，全局 nowrap 会让那些表的内容溢出单元格。
   ========================================================================== */
#ip-body table.table tbody td.is-num {
  white-space: nowrap;
}

/* 达人明细表：窄屏**不压缩列宽**，改为整体横向滚动（2026-09-17）
   --------------------------------------------------------------------------
   本表是 13 列的数据密集表，宽度由「金额列要放得下六位数」决定（见 W_MONEY）。
   不加 min-width 时，窄屏会把**唯一的弹性列（达人/明细项）**压到 101px，
   达人名 + 编号 + 场次 + 「其中未满 35 天 GSV ¥169,930.04」折成 7~8 行
   （实测 1600px 屏平均 7.1 行）—— 比横向滚动难读得多。
   1560px = 固定列合计（箭头 32 + 金额 4×118 + 类目 5×110 + 利润率 86 + 状态 96）
            + 达人列最小可读宽 ≈ 260px。
   1920px 屏不受影响（实测表格自然宽 1614px > 1560）。
   ========================================================================== */
#ip-body table.table { min-width: 1560px; }

/* ==========================================================================
   签约公司 · 「添加旗下达人」弹窗的达人选择行（2026-09-22）
   --------------------------------------------------------------------------
   乐哥：「我们之前做的『达人公司』功能…UI 界面也跟我们系统的不一样，整体调整一下」。

   改前：裸的 `<label><input type=checkbox><span>名字</span></label>` 一行 ——
        没有头像、没有行悬停/选中态、复选框极小不好点，明显不是本系统的观感。
   改后：与全站达人选择器（`.fp-*`）同一套语言 ——
        圆形头像 + 名字 + 编号右对齐 + 整行可点 + 选中态高亮。
   ⚠️ 颜色一律走 design-tokens，不写死色值（改主题时这里要跟着变）。
   ⚠️ 本块只作用于 `.co-pick-list`（弹窗内），不动全站 label / input 的任何样式。
   ========================================================================== */
.co-pick-list {
  max-height: 360px;
  overflow: auto;
  border: 1px solid var(--color-border-soft);
  border-radius: var(--radius-md);
}
.co-pick-item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  cursor: pointer;
  border-bottom: 1px solid var(--color-border-soft);
  transition: background-color .12s ease;
}
.co-pick-item:last-child { border-bottom: 0; }
.co-pick-item:hover { background: var(--color-surface-2); }
/* 选中态：淡主色底 + 左侧主色条，一眼看出勾了哪几行 */
.co-pick-item.is-picked {
  background: var(--color-primary-50);
  box-shadow: inset 3px 0 0 var(--color-primary-500);
}
.co-pick-item__name {
  font-size: var(--font-size-sm);
  color: var(--color-fg);
}

/* ══════════════════════════════════════════════════════════════════════════
   达人详情页 / 编辑页 —— 信息层级（2026-09-27）
   ──────────────────────────────────────────────────────────────────────────
   乐哥：「主次模块之间感觉还是分得不清楚」
   ⭐ 实测诊断（改动前，两页共 6 张卡）——**每一个视觉维度都完全相同**：
        底色 rgb(255,255,255) ｜ 边框 1px rgb(235,236,239) ｜ 圆角 16px
        内边距 20px ｜ 标题 14px/500 ｜ 卡片间距一律 32px
      ⇒ 视觉上是一坨"平级的卡"：读不出哪个重要、哪几张属于一组。
   解法（三层，全部只用**既有令牌**；⛔ 不动骨架、不动 .module-card 基础规格）：
      ① 组标题 —— 模块按"组"组织，标题说明这组是什么
      ② 组内紧 / 组间松 —— 组内 16px、组间 40px（邻近性原则：距离表达从属关系）
      ③ 卡片两档 —— 主卡（白底 + 边框）｜次卡（浅底、无边框、更轻）
   ⛔ 约束：主次**不许**用"彩色描边 / 外发光"表达（全站明令禁止，见 components.css 顶部）；
      只能用「底色深浅 + 边框有无 + 间距」。
   ══════════════════════════════════════════════════════════════════════════ */

/* ── ⓪ 字号层级（2026-09-27 第二批：乐哥「文字标题是不是可以大一点？跟上面的正文重叠了」）
   ─────────────────────────────────────────────────────────────────────────
   实测（改动前）：组标题 14px / 卡片标题 14px / 正文 14px —— **三档完全同号** ⇒ 标题淹没在正文里。
   按设计令牌的既定语义恢复层级（令牌注释里本来就写着"卡片标题 = lg"）：
     · 组标题   --font-size-lg (16px) + semibold(600) + 主色竖条   ← 最重
     · 卡片标题 --font-size-lg (16px) + medium(500) + 标题栏分隔线 ← 中
     · 正文     --font-size-base (14px)                            ← 轻
     · 注释     --font-size-xs (12px)                              ← 最轻
   ⚠️ `.module-card__title` 原为**全站共用**（66 页），2026-09-27 时只能 scoped 到 `.ia-page`；
      2026-09-28 全站统一提档为 lg（components.css 同值）⇒ 本 scoped 规则已成冗余，已移除。 */
/* ── ① 分组容器与组标题 ───────────────────────────────────────────────── */
/* ⭐ 2026-09-28 组卡化（乐哥：「概览里合作与平台、经营数据这两个标题为什么在卡片外面？
   之前说了要放卡片里面」）——
   分组 = **一张白卡**，组标题嵌在卡内当卡头；组内原 module-card 去卡化降为平铺板块。
   与 2026-09-28 看板页拍板的「一个模块一张白卡、标题嵌在卡内」同一条设计语言，
   也与页头包盒（.detail-head / .page-header--has-tabs）同规格：白底 + 1px 边框 + 圆角 16。
   ⚠️ 只作用 .ia-page（达人详情页 + 编辑页，全站仅此两页用 iaGroup）。 */
.ia-group {
  margin-top: var(--space-4);   /* ⭐ 2026-09-28：20 → 16（全站卡片间距收一档，乐哥：「小一点点」） */
  background: var(--color-surface);
  border: 1px solid var(--color-frame-border);
  border-radius: var(--radius-lg);
  padding: var(--space-6);
}
.ia-group:first-child { margin-top: 0; }

.ia-group__title {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-4);
  font-size: var(--font-size-lg);
  font-weight: var(--font-weight-semibold);
  color: var(--color-fg);
}
/* 分区编号方块（⭐ 2026-09-27：乐哥给 PMS「新建项目」参考图 ——
   「整个 UI 的二级页面应该按照项目管理系统那个模型去做」。该模型第一眼线索就是这个编号：
   `① 基础信息` `② 业务与计费` —— 给出"一共几部分、现在在哪一部分"的顺序感。
   原实现是一条 3px 竖条，信息量只有"这里是一组的开头"，没有顺序。 */
.ia-group__no {
  width: 18px;
  height: 18px;
  border-radius: 5px;
  background: var(--color-primary-50);
  color: var(--color-primary-500);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-medium);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  font-variant-numeric: tabular-nums;
}
.ia-group__hint {
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-regular);
  color: var(--color-muted);
}

/* ── ② 组内卡片收紧 + 去卡化 + 首卡标题接管（⭐ 2026-09-28 B 方案）────────────
   ⚠️ 必须用后代选择器限定在 .ia-group 内 —— 直接改 `.module-card + .module-card`
      会波及全站 66 个页面。 */
.ia-group .module-card + .module-card { margin-top: var(--space-4); }  /* ⭐ 2026-09-28：同全站口径 20 → 16 */

/* 组内板块去卡化：原 .module-card（白底+边框+padding）在组白卡内降为平铺板块 ——
   否则「白卡套白卡」，与昨晚修掉的卡套卡是同一个毛病。 */
.ia-page .ia-group > .module-card {
  background: transparent;
  border: 0;
  border-radius: 0;
  padding: 0;
}

/* 首卡标题由组标题接管（乐哥：「b，标题重复了」）——
   组标题与首卡标题近义（「合作与平台」vs「合作信息」、「经营数据」vs「业绩概览」、
   「基础信息」vs「基本信息」…共 10 组全重复），两行并排是噪音。
   ⚠️ 只藏标题**文字**、不藏 head 本身：head 里可能还有控件
      （编辑页「收货地址」的「添加地址」按钮就在 head 里，margin-left:auto 靠右），
      整块藏会把控件一起弄丢。 */
.ia-page .ia-group > .ia-group__title + .module-card > .module-card__head > .module-card__title {
  display: none;
}
/* head 里除标题外别无内容（无控件）→ 整个 head 收缩，不留空 padding / 分隔线。
   ⚠️ 判据 `:has(> :not(.module-card__title))` = 「head 的直接子级里存在非标题元素」：
      判假 ⇒ 只有标题 ⇒ 藏整个 head；判真 ⇒ 有控件 ⇒ 保留 head（上一行已藏标题文字）。 */
.ia-page .ia-group > .ia-group__title + .module-card > .module-card__head:not(:has(> :not(.module-card__title))) {
  display: none;
}

/* ── ③ 次模块卡：降一档（附属信息）───────────────────────────────────────
   用途：本身是"上面那张主卡的细节/附属"的模块 ——
     详情页「平台账号 / 机构」＝「合作信息」的明细；
     编辑页「带货小号」＝「平台相关」的附属。
   用全站既有的"次级底"令牌 --color-surface-2，不新造颜色、不加阴影
   （柔底已有色彩区分度，加阴影反而发闷 —— 见 KPI 柔底卡的做法）。 */
.module-card--sub {
  background: var(--color-surface-2);
  border-color: transparent;
}
/* ⭐ 2026-09-28 组内次卡（浅底分区）：去卡化的 `padding: 0` 与本条同特异性(0,3,0)，
   靠**源码顺序**取胜 —— 本条写在去卡化之后（下文位置）⇒ 内边距生效。
   ⚠️ 若将来把本条上移，次卡会变"浅底块内容贴边"（静默、不报错）。 */
.ia-page .ia-group > .module-card--sub {
  background: var(--color-surface-2);
  border-radius: var(--radius-md);
  padding: var(--space-4) var(--space-5);   /* 16/20：卡内分区比外层卡（24）收一档 */
}
/* 次卡的头必须透明，否则 .module-card__head--plain 的白色底会"贴"在浅底上 */
.module-card--sub > .module-card__head { background: transparent; }
/* ⚠️ 次卡内的表头也要透明 —— 全站表头底是**白色**，比次卡底(#F1F5F9)更亮，
   留着会变成"一张白表头浮在灰卡上"（实测踩到：次卡底 rgb(241,245,249) vs 表头 rgb(255,255,255)）。
   透明后由卡片底色统一承载，整卡是一块柔和的浅底。 */
.module-card--sub .table thead th { background: transparent; }

/* ── 表单行：标签在左、右对齐成一列（⭐ 2026-09-27 照 PMS「新建项目」模型）
   ──────────────────────────────────────────────────────────────────────────
   原实现（标签在上、控件在下）的问题：每个标签各贴各的控件，**不成列** ——
   扫读时标签与正文混在一个层级里（乐哥：「标题跟上面的正文重叠了」）。
   改后：标签固定宽 + 右对齐 + 垂直居中，控件占满剩余宽 ⇒ 标签成一条整齐竖线。
   ⚠️ `.field-label` 是全站公共类，故新规则一律限定在 `.form-row` 内。 */
.form-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-width: 0;
}
.form-row > .field-label {
  flex: none;
  width: 112px;               /* ⭐ 2026-09-27：84 → 112。84px 只能放 6 个汉字，
                                 实测「是否沿用公司口径 / 达人基础信息备注 / 年框合同开始时间」
                                 等 8 字标签需要 112px —— 全被**裁剪**（scrollWidth 112 > 84）。
                                 标签被裁 = 信息丢失，比换行更糟。 */
  margin-bottom: 0;          /* 覆盖 .field-label 的 margin-bottom: 8px（那是"标签在上"用的） */
  text-align: right;
  white-space: nowrap;
}
.form-row__ctrl { flex: 1; min-width: 0; }
/* 多行控件（textarea / 备注）不适合垂直居中，改为顶对齐 */
.form-row:has(> .form-row__ctrl > textarea) { align-items: flex-start; }
.form-row:has(> .form-row__ctrl > textarea) > .field-label { padding-top: 10px; }
/* 窄屏：标签在左会挤压控件宽度 ⇒ 退回"标签在上"（与全站默认一致） */
@media (max-width: 900px) {
  .form-row { display: block; }
  .form-row > .field-label { width: auto; text-align: left; margin-bottom: var(--space-2); }
}
