/* auto-qb 新版 WEB UI · 视图层: 辅种页 / 设置页 / 历史流量
 * 布局契约(与 app.js 耦合, 勿改名): .sticky-head(--head-h 量测) / .statusbar(--statusbar-h 底部预留) /
 * .bulk-inline(批量段, FIX-06 起并入筛选行, 不再是独立吸顶条) /
 * .group-head/.detail-head(列宽拖拽 + TBL-05 拖动重排) / gridStyle 内联列模板 / .search-hit/.ctx-menu。
 * 记忆点 = 底部状态栏: 全站速度与流量摘要常显, 其余视觉保持安静。
 */

/* ---------------- 限速浮层(SPD-04; FX-08 改为就近弹出) ----------------
 * 无遮罩 anchored popover: 宽度 380px 与 app.js 的 W 常量单点对齐; 纵向由 CSS 锚在状态栏上缘
 * (bottom: --statusbar-h + 8px), 横向由 JS 写 inline left 并夹取到视口内。
 * 层级 131 = 与确认框同层但无遮罩 —— 高于 toast(120), 低于不去遮罩的状态栏(30)不冲突。 */
.speed-pop { position: fixed; z-index: 131; width: 380px; padding: 14px 16px 12px;
  bottom: calc(var(--statusbar-h, 34px) + 8px);
  display: flex; flex-direction: column; gap: 10px;
  background: var(--bg-card); border: 1px solid var(--border-strong); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-3); animation: drop-in .12s var(--ease-out); }
.speed-pop .add-dialog-body { display: flex; flex-direction: column; gap: 10px; overflow: visible; }
.speed-pop .speed-dialog-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.speed-pop .modal-field input { width: 100%; }

/* ---------------- 列头拖动虚影(FX-25) ----------------
 * 跟随光标的列名胶囊。**不用 HTML5 draggable 的原生拖影**(它会与点击排序/列宽拖拽互相干扰),
 * 与已有的 mousedown 阈值手势完全解耦; pointer-events: none 不吃事件。
 * 必须渲染在 #app 层(不能放进 .group-head: 它的 will-change/transform 会另建包含块,
 * fixed 定位会相对表头而非视口)。 */
.col-ghost { position: fixed; z-index: 120; pointer-events: none; transform: translate(10px, 12px);
  padding: 3px 10px; border-radius: var(--radius-sm);
  background: var(--bg-elev); border: 1px solid var(--accent-line); box-shadow: var(--shadow-2);
  color: var(--fg); font-family: var(--font-mono); font-size: 11.5px; font-weight: 600; white-space: nowrap; }

/* ---------------- 辅种页布局 ---------------- */
/* TBL-08: 左栏"舵台"信息栏退役 -> 底部状态栏(.statusbar); 布局改单列全宽。
 * TBL-07: 不再 2560px 居中限宽, 两侧只留最小 12px 内边距(横向滚动内容不再被两侧页底色裁切) */
.layout { display: grid; grid-template-columns: minmax(0, 1fr); align-items: start;
  padding: 16px 12px calc(28px + var(--statusbar-h, 34px)); }
.layout, .ce-page { animation: page-in .2s var(--ease-out); }
/* overflow-x: clip(2026-09-17): 表头 .group-head 脱离 .group-table 滚动容器做纵向 sticky,
 * 列多/拖宽时它会比 .content 宽 —— 不裁切就把整页撑出**第二条**横向滚动条。
 * clip 不建立滚动容器, 不影响 sticky 顶贴与它的 transform 跟随。 */
.content { min-width: 0; overflow-x: clip; }
/* ---------------- 底部状态栏(TBL-08 修订) ----------------
 * 原左栏"舵台"(.rail*)整块退役: 左 = 常显统计摘要 + 完整统计入口, 右 = 速度摘要 + 限速入口。
 * 高度用 --statusbar-h 令牌锁定(不随内容变化, 与内容区底部预留共用同一值, 避免取整透缝);
 * z-index 30 与吸顶条同层 —— 低于列选择器弹层/右键菜单/toast/modal。
 * R10-02: 底色从 --glass 换专用令牌 --statusbar-bg —— 暗主题下 --glass 与页底 --bg 明度差不足 2%,
 * 状态栏"与背景色一致"看不出来。不用 --glass 是因为它同时管顶栏, 改它会把顶栏一起带偏。
 * 同步去掉 backdrop-filter: 底色已不透明, 模糊无效; 少一层层叠上下文也少一类遮挡问题。 */
.statusbar { position: fixed; left: 0; right: 0; bottom: 0; z-index: 30; display: flex; align-items: center;
  gap: 16px; height: var(--statusbar-h, 34px); padding: 0 18px; overflow: hidden; white-space: nowrap;
  background: var(--statusbar-bg, var(--bg-card)); border-top: 1px solid var(--border);
  box-shadow: inset 0 1px 0 var(--hairline); }
.sb-speed { display: flex; align-items: center; gap: 14px; min-width: 0; overflow: hidden; }
/* FX-08: 速度与限速配对 —— "下载速度 12.3 MiB/s · 限制速度 不限" 是一个不可断开的组合,
 * 同组内距离小于组间距离, 读起来才是一个整体。 */
.sb-sep { width: 1px; height: 14px; background: var(--border); flex: 0 0 auto; }
/* 2026-09-20: 「[方向图标] 速度 / 限速」合成按钮 —— 整组可点(点图标 / 速度 / 限速任一处都就近弹出限速浮层);
 * 不再单独给限速配图标(仪表盘 i-gauge 退役); "不限"只弱化限速值, 方向图标保持语义色 */
.sb-spd { display: inline-flex; align-items: center; gap: 5px; padding: 1px 7px;
  border: 1px solid transparent; border-radius: var(--radius-sm); background: transparent;
  color: var(--fg-muted); font: inherit; font-size: 11.5px; cursor: pointer; flex: 0 0 auto;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease), color var(--dur) var(--ease); }
.sb-spd:hover { background: var(--surface-2); border-color: var(--border-soft); color: var(--fg); }
.sb-spd .val { color: var(--fg); font-weight: 600; font-size: 12.5px; font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.sb-spd .slash { color: var(--fg-dim); }
.sb-spd .lim { color: var(--fg); font-weight: 600; font-size: 12px; font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.sb-spd.off .lim { color: var(--fg-dim); font-weight: 500; }
/* 今日流量(FX-07): 数据源与连接/剩余不同(Traffic Monitor dat), 用竖线与右侧摘要区分。
 * R10-05: 历史入口已并入本组作子元素 -> 不再需要右边框与额外间距: 原先那道 1px 竖线
 * 正好在两者之间, 读作"两个不相干的块"(用户: "中间有隔断")。 */
/* 2026-09-20: 选择器要比后面的 `.sb-item .val` 更"重" —— 两者特异性同为 (0,2,0), 后者靠顺序赢,
   棱镜侧数值(及其箭头图标)就掉回 --fg 变白; 用 .sb-item.sb-today 抬到 (0,3,0), 与书写顺序解耦 */
.sb-item.sb-today .v-down { color: var(--today-down); }
.sb-item.sb-today .v-up { color: var(--today-up); }
/* 2026-09-20: 数值自带方向箭头图标(取代字面量 ↓/↑) —— 图标继承 .val 的字色, 与数值同族 */
.sb-today .val { display: inline-flex; align-items: center; gap: 3px; }
/* R10-05: 历史入口(今日流量组的子元素) —— 轻量按钮, 与块内数值同排只留图标间距 */
.sb-hist { display: inline-flex; align-items: center; gap: 4px; margin-left: 2px; padding: 1px 8px;
  border: 1px solid var(--border-soft); border-radius: var(--radius-sm); background: var(--surface-1);
  color: var(--fg-muted); font: inherit; font-size: 11.5px; cursor: pointer; flex: 0 0 auto;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease), color var(--dur) var(--ease); }
.sb-hist:hover { background: var(--surface-2); border-color: var(--border); color: var(--fg); }
/* 历史入口(2026-09-17): 文字已移除, 只剩图标 -> 图标自己有色(与今日流量图标同族 --today-ico) */
.sb-hist .ico { color: var(--today-ico, var(--lime)); }
.sb-hist:hover .ico { color: var(--accent-hi); }
/* 左侧统计摘要: 指标项紧凑排列(标签暗 + 数值亮), 空间不足时整体裁切而不换行 */
.sb-stats { display: flex; align-items: center; gap: 14px; min-width: 0; overflow: hidden; }
/* "今日" 与 "连接/剩余" 的标签同格式(2026-09-20): 两条同族, 别再各写一套 */
.sb-stats .lbl, .sb-today .lbl { color: var(--fg-dim); font-size: 11.5px; }
.sb-empty { color: var(--fg-dim); font-size: 11.5px; }
.sb-item { display: inline-flex; align-items: center; gap: 6px; }
.sb-item .val { color: var(--fg); font-weight: 600; font-size: 12.5px; font-family: var(--font-mono); }
.sb-item .ico-down { color: var(--blue); }
.sb-item .ico-up { color: var(--green); }
.sb-item .ico-flow { color: var(--blue); }
.sb-item .ico-alltime { color: var(--accent-hi); }
.sb-item .ico-peers { color: var(--green); }
.sb-item .ico-dht { color: var(--teal, var(--accent)); }
/* 空间剩余: 磁盘图标原先继承 --fg-dim(观感"没有颜色"), 改用存储中性色 indigo */
.sb-item .ico-disk { color: var(--indigo); }
.sb-spacer { flex: 1; }
.sb-btn { display: inline-flex; align-items: center; gap: 5px; padding: 2px 10px; border-radius: 999px;
  border: 1px solid var(--border-soft); background: var(--surface-1); color: var(--fg-muted);
  font-size: 12px; font-family: inherit; cursor: pointer; flex: 0 0 auto;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease), color var(--dur) var(--ease); }
.sb-btn:hover { background: var(--surface-2); color: var(--fg); }

/* ---------------- 分组表 ---------------- */
.group-table { display: flex; flex-direction: column; gap: 5px; overflow-x: auto; padding-bottom: 2px; }
/* 行宽口径: 数据行与表头一律 **fit-content + min-width: 100%** —— 行底色/边框必须覆盖**内容**宽度
 * (定宽 100% 时一旦内容宽于容器, 横向滚到右侧就没有行底色/边框)。
 * 假滚动条的真因在单元格: 默认 `min-width: auto` + 表格层 `white-space: nowrap` => 自动最小宽 = 文本全长,
 * 累加后把行的最小宽顶到容器之上, 于是 fit-content 恒宽几像素 => 列没溢出却常驻横滚动条。
 * 解决法 = 行内单元格统一 `min-width: 0`, 行最小宽回到 `minmax(Xpx,·)` 之和。
 * 明细与外层共用**同一条**横向滚动(原先 .detail 自带 overflow-x: auto 会形成第二条, 见下方)。 */
.group-row, .detail, .detail-head, .member-row { width: fit-content; min-width: 100%; }
.group-row > *, .group-head > *, .detail-head > *, .member-row > * { min-width: 0; }
.g-stat, .g-count, .g-hr, .m-stat { overflow: hidden; text-overflow: ellipsis; }
/* 表头: 脱离滚动容器做纵向 sticky; 横向位移由 app.js 写 transform 跟随。
 * FIX-03 配色: 底色从 --bg-card 改为 --bg 页底色 —— 之前与顶栏 --glass 玻璃底明度相近,
 * 吸顶时像"第二根导航"; 改用不透明页底色读作"页面面板", 权重更低且不透滚动内容。
 * FIX-03 防透缝: --head-h 是 JS Math.round(实测高度), 顶栏行高含小数时取整可偏差 ±0.5px,
 * 叠加设备像素取整仍可能现 1px 竖缝 —— top 在齐平值上多压 1px, 重叠部分藏在上方 .sticky-head
 * (z-index 更高)之下且与页底同色, 不遮挡内容也不产生横向滚动。 */
.group-head { display: grid; gap: 10px; padding: 7px 14px; color: var(--fg-dim);
  font-family: var(--font-mono); font-size: 11px; font-weight: 600; letter-spacing: .06em;
  width: fit-content; min-width: 100%;
  position: sticky; top: calc(var(--head-h, 100px) - 1px); z-index: 5;
  background: var(--bg); border-bottom: 1px solid var(--border);
  box-shadow: var(--shadow-1); will-change: transform; }
.group-head.sticky-head { border-radius: 0; }
.h-cell { position: relative; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; padding-right: 10px; }
/* R10-08: 列对齐不再在这里硬编码名单 —— 口径唯一来源是 app.js 的列模型 `align`,
 * 由 colAlignCss 按**当前可见列**生成 :nth-child 规则注入 <head>(表头与单元格同源)。
 * 这样加/删/换序列都只改列模型一处, 不会再出现"表头左、值右"的错位。
 * 旧规则(.hc-dlspeed…右对齐名单 + .hc-count/.hc-hr 居中)已删。 */
.h-cell.sortable { cursor: pointer; user-select: none; transition: color var(--dur) var(--ease); }
.h-cell.sortable:hover { color: var(--fg); }
.h-cell .arrow { color: var(--accent); display: inline-block; animation: arrow-in .14s var(--ease-out); }
.h-cell .arrow .ico { width: 11px; height: 11px; stroke-width: 2; }
.h-cell .resizer { position: absolute; right: 0; top: 0; width: 10px; height: 100%; cursor: col-resize; z-index: 2; }
.h-cell .resizer::after { content: ""; position: absolute; left: 4px; top: 15%; width: 2px; height: 70%;
  background: transparent; border-radius: 2px; }
.h-cell:hover .resizer::after { background: var(--accent); }


/* P0-3 乐观 UI: pending 行 = 本地已按预期改过、还没拿到服务端确认。
   半透明 + 轻微动效表示"进行中"; 回执失败会回滚原值(见 app.js resolveOptimistic),
   3s 未确认也会回落真值 —— 绝不允许停在假状态上。 */
.is-pending { opacity: .55; transition: opacity .18s ease; }
/* P1-2 行窗口化占位: 撑住"窗口外的行"所占的高度(滚动条长度/滚到底与全量渲染一致)。
   空盒 + 不吃事件: 只提供高度, 不参与行内 :nth-child 列对齐, 也不该被 hover/右键命中。 */
.row-pad { flex: 0 0 auto; pointer-events: none; }
.group-row { position: relative; display: grid; gap: 10px; align-items: center; background: var(--bg-row);
  border: 1px solid var(--border-soft); border-radius: var(--radius); padding: 10px 14px;
  cursor: pointer; user-select: none;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease), transform var(--dur) var(--ease); }
.group-row:hover { background: var(--bg-hover); border-color: var(--border-strong); transform: translateY(-1px); }
/* 展开态 = 结构语言(下沉底色 + 底角取直与明细相连); 选中态 = accent 语言(左条 + 柔底) —— 分家 */
.group-row.expanded { background: var(--bg-sunken); border-color: var(--border);
  border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
.group-row.expanded + .detail { margin-top: -6px; border-top-left-radius: 0; border-top-right-radius: 0; }
.group-row.expanded:hover { transform: none; }
.g-name { display: flex; align-items: center; gap: 7px; font-weight: 600; overflow: hidden; white-space: nowrap; }
.g-name-text { overflow: hidden; text-overflow: ellipsis; }
.g-name .caret { color: var(--fg-dim); transition: transform var(--dur) var(--ease-spring), color var(--dur) var(--ease); }
.group-row:hover .caret { color: var(--accent); }
.group-row.expanded .caret { transform: rotate(90deg); color: var(--accent); }
.g-status { display: inline-grid; place-items: center; width: 20px; height: 20px; flex: 0 0 auto;
  border-radius: var(--radius-sm); background: var(--surface-2); }
.g-status.k-seeding { background: var(--green-soft); }
.g-status.k-downloading, .g-status.k-checking { background: var(--blue-soft); }
.g-status.k-error { background: var(--error-soft); }
/* FX-06(D8-B): 暂停/其它芯片此前没有背景修饰符, 落回 .g-status 的 --surface-2(暗主题 = 白 6%)
 * 读作"太白/没颜色"; 改为不铺底 + 中性描边 + 中性中间调字色 —— 与其它四色并列时"有色/无色"
 * 的层次反而更清楚, 且不抢眼。 */
.g-status.k-paused, .g-status.k-other { background: var(--paused-soft); color: var(--paused);
  box-shadow: inset 0 0 0 1px var(--paused-line); }
.g-stat, .member-row span { white-space: nowrap; }
.g-stat, .m-stat { text-align: right; }
.g-stat.zero, .m-stat.zero { text-align: center; }
.zero { color: var(--fg-dim); opacity: .35; }
.risk-mark { color: var(--warn); cursor: help; }
.g-sites { display: flex; flex-wrap: wrap; gap: 4px; min-width: 0; }
.site-chip { display: inline-flex; align-items: center; gap: 4px; padding: 2px 8px; border-radius: var(--radius-sm);
  background: var(--surface-2); color: var(--fg-muted); font-size: 11px; white-space: nowrap;
  transition: background var(--dur) var(--ease); }
.site-chip.seeding { background: var(--green-soft); color: var(--green); }
.site-chip.downloading, .site-chip.checking { background: var(--blue-soft); color: var(--blue); }
.site-chip.paused, .site-chip.other { background: var(--paused-soft); color: var(--paused);
  box-shadow: inset 0 0 0 1px var(--paused-line); }  /* FX-06: 同 .g-status.k-paused(去白高光底) */
.site-chip.error { background: var(--error-soft); color: var(--error); }
.site-chip.search-hit { background: var(--accent-soft); color: var(--accent-hi); font-weight: 600;
  box-shadow: inset 0 0 0 1px var(--accent-line); }
.g-tags, .m-tags { display: flex; align-items: center; gap: 4px; min-width: 0; overflow: hidden; }
.g-cat, .m-cat { display: flex; align-items: center; gap: 4px; min-width: 0; overflow: hidden; }
.tag-chip { display: inline-flex; align-items: center; padding: 1px 7px; border-radius: var(--radius-sm);
  background: var(--surface-2); color: var(--fg-muted); font-size: 11px; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; }
/* HR 标签语义色: pending 最醒目, done 镇静对照 */
.tag-chip.hr-pending { background: var(--hr-pending-soft); color: var(--hr-pending); font-weight: 600;
  box-shadow: inset 0 0 0 1px var(--hr-pending-line); }
.tag-chip.hr-done { background: var(--hr-done-soft); color: var(--hr-done);
  box-shadow: inset 0 0 0 1px var(--hr-done-line); }
.cat-chip { display: inline-flex; align-items: center; padding: 1px 7px; border-radius: var(--radius-sm);
  background: var(--surface-2); color: var(--fg-muted); font-size: 11px; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; }
/* 标签/分类芯片改"状态色"(2026-09-17 用户要求): 原先分类永远蓝、普通标签永远灰 —— 颜色不带语义,
 * 蓝色分类 chip 还会和"下载中"撞色。改为跟随**所在行的状态语义色**(与 .site-chip 同口径);
 * HR 标签(hr-pending/hr-done)自带 HR 语义, 用 :not() 排除不受影响; paused/other 保持中性灰。 */
.group-row.s-seeding .tag-chip:not(.hr-pending):not(.hr-done),
.group-row.s-seeding .cat-chip,
.member-row.seeding .tag-chip:not(.hr-pending):not(.hr-done),
.member-row.seeding .cat-chip { background: var(--green-soft); color: var(--green); }
.group-row.s-downloading .tag-chip:not(.hr-pending):not(.hr-done),
.group-row.s-downloading .cat-chip,
.group-row.s-checking .tag-chip:not(.hr-pending):not(.hr-done),
.group-row.s-checking .cat-chip,
.member-row.downloading .tag-chip:not(.hr-pending):not(.hr-done),
.member-row.downloading .cat-chip,
.member-row.checking .tag-chip:not(.hr-pending):not(.hr-done),
.member-row.checking .cat-chip { background: var(--blue-soft); color: var(--blue); }
.group-row.s-error .tag-chip:not(.hr-pending):not(.hr-done),
.group-row.s-error .cat-chip,
.member-row.error .tag-chip:not(.hr-pending):not(.hr-done),
.member-row.error .cat-chip { background: var(--error-soft); color: var(--error); }
.tag-more { font-size: 11px; color: var(--fg-dim); flex: 0 0 auto; }
.diff-mark { flex: 0 0 auto; padding: 0 5px; border-radius: var(--radius-sm); background: var(--surface-2);
  color: var(--fg-dim); font-size: 11px; white-space: nowrap; }
.g-count { text-align: center; color: var(--fg-dim); font-size: 12.5px; }

/* 展开明细 */
/* 不再自建滚动容器(2026-09-17): 原先 overflow-x: auto 会让明细区出现第二条横向滚动条,
 * 改为可见溢出 -> 明细内容并入外层 .group-table 滚动区, 全局只保一条横滚动。 */
.detail { margin: -2px 0 6px; padding: 4px 14px 8px;
  background: var(--bg-sunken); border: 1px solid var(--border); border-radius: var(--radius);
  animation: drop-in .16s var(--ease); }
.detail-head { display: grid; gap: 10px; padding: 7px 4px; color: var(--fg-dim);
  font-family: var(--font-mono); font-size: 11px; font-weight: 600; letter-spacing: .06em;
  border-bottom: 1px solid var(--border); }
.member-row { display: grid; gap: 10px; padding: 7px 4px; border-bottom: 1px dashed var(--border-soft);
  transition: background var(--dur) var(--ease); }
.member-row:hover { background: var(--surface-2); }
.member-row:last-child { border-bottom: 0; }
.member-row span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.m-site { display: inline-flex; align-items: center; gap: 6px; font-weight: 600; }
.m-site .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--fg-dim); flex: 0 0 auto; }
.member-row.seeding .m-site .dot { background: var(--green); }
.member-row.downloading .m-site .dot, .member-row.checking .m-site .dot { background: var(--blue); }
.member-row.error .m-site .dot { background: var(--error); }
.m-state { display: inline-flex; align-items: center; gap: 6px; color: var(--fg-muted); }
.m-state .dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; flex: 0 0 auto; }
.member-row.seeding .m-state { color: var(--green); }
.member-row.downloading .m-state, .member-row.checking .m-state { color: var(--blue); }
.member-row.error .m-state { color: var(--error); }
.member-row.paused .m-state, .member-row.other .m-state { color: var(--paused); }  /* FX-06: 与状态芯片同族(不再是 dim 灰) */
.member-row.paused .m-site .dot, .member-row.other .m-site .dot { background: var(--paused); }
.m-hash { color: var(--fg-dim); font-size: 12px; }

/* 进度条 */
.m-progress { display: flex; align-items: center; gap: 7px; min-width: 0; }
.m-progress .bar { flex: 1 1 auto; height: 4px; min-width: 22px; border-radius: 999px;
  background: var(--surface-2); overflow: hidden; }
.m-progress .bar > i { display: block; height: 100%; border-radius: inherit; background: var(--accent);
  transition: width var(--dur-slow) var(--ease-out); }
.m-progress .val { flex: 0 0 auto; font-size: 12px; color: var(--fg-muted); }

/* 搜索命中: 左侧渐层 + 柔底(不整框描边) */
.group-row.search-hit { border-color: var(--accent-line);
  background: linear-gradient(90deg, var(--accent-soft), transparent 46%), var(--bg-row); }
.member-row.search-hit { background: linear-gradient(90deg, var(--accent-soft), transparent 42%); }

/* 多选选中态(R10-07): 改用**选中态专用令牌族**(--sel-bg/--sel-line/--sel-bar)。
 * 原先选中态引用 --accent-soft/--accent, 而品牌主题(orbit)的 --accent 与"做种中"的 --green
 * 同属绿族且明度接近 -> 用户反馈"不好分辨"。现在五主题统一给非绿值(靖蓝族),
 * 与状态色彻底分家; 换主题不再撞色。 */
.group-row.selected { background: var(--sel-bg, var(--accent-soft)); border-color: var(--sel-line, var(--accent-line)); }
.group-row.selected::before { content: ""; position: absolute; left: 0; top: 14%; bottom: 14%;
  width: 3px; border-radius: 0 3px 3px 0; background: var(--sel-bar, var(--accent)); }
.member-row.selected { background: var(--sel-bg, var(--accent-soft)); }
/* FX-12 半选态(indeterminate): 派生集合只命中该行**部分**成员 —— 例如在种子页选了某辅种组的
 * 2 个种子后回辅种页, 该组应显示"半选"而不是"没选"。视觉 = 同款左色条但降透明 + 柔底,
 * 与全选明确区分。 */
.group-row.partial, .member-row.partial { background: var(--sel-bg, var(--accent-soft));
  border-color: var(--sel-line, var(--accent-line)); }
.member-row { position: relative; }
.group-row.partial::before, .member-row.partial::before { content: ""; position: absolute; left: 0;
  top: 14%; bottom: 14%; width: 3px; border-radius: 0 3px 3px 0; background: var(--sel-bar, var(--accent)); opacity: .42; }
.member-row.partial::before { top: 18%; bottom: 18%; }

/* 限速对照 */
.pill-limit .ico { opacity: .9; }
.pill-limit.mismatch .lbl, .pill-limit.mismatch .val { color: var(--warn); }
.pill-limit.mismatch .val { font-weight: 700; }
.pill-limit.mismatch .ico { color: var(--warn); }
.pill-limit.manual .lbl, .pill-limit.manual .val { color: var(--accent-hi); }
.pill-limit.manual .ico { color: var(--accent-hi); }

/* HR 栏(居中) + 时长/分享率对 */
.g-hr { display: flex; align-items: center; justify-content: center; gap: 5px; }
.g-hr .hr-num { font-weight: 600; }
.g-hr.pending { color: var(--hr-pending); }
.g-hr.done { color: var(--green); }
.g-hr .ico { opacity: .85; }
.m-pair { display: inline-flex; align-items: baseline; gap: 3px; }
.m-pair .req { color: var(--fg-dim); font-size: 11.5px; }
.m-pair.m-dur { color: var(--teal); }
.m-pair.m-ratio { color: var(--violet); }
.m-pair.pending { color: var(--hr-pending); }
.m-pair.reached { color: var(--green); }

/* 校验中呼吸 */
.g-status.k-checking .ico, .member-row.checking .m-state .dot { animation: pulse-soft 1.6s ease-in-out infinite; }

/* ---------------- 批量操作段(FIX-06: 并入筛选行) ----------------
 * 原为独立吸顶浮条(.bulk-bar, top 跟随 --head-h), 选中/取消选中时会插入或抽出表格上方,
 * 造成整页跳动; 现改为 .status-strip 行首的同行段 —— 无独立 top/z-index/margin,
 * 无选中时完全不渲染, 有选中时在行内出现(同排不改变行高)。
 * FX-09: 高度必须 ≤ 26px(与 .dist-chip 齐平) —— 它是靠"自然高度不超"来实现同排不改变行高,
 * 只靠 ① 压按钮不够: 段自身的 padding+border 也会超出, 所以两处都锁死。 */
.bulk-inline { display: flex; flex-wrap: nowrap; align-items: center; gap: 0 9px; height: 26px;
  padding: 0 9px 0 8px; border: 1px solid var(--accent-line); border-radius: var(--radius);
  background: linear-gradient(180deg, var(--accent-soft), transparent 70%), var(--bg-card); }
.bulk-inline .bulk-count { font-size: 11.5px; line-height: 1; color: var(--fg-muted); white-space: nowrap; }
.bulk-inline .bulk-count b { color: var(--accent-hi); font-variant-numeric: tabular-nums; }
.bulk-sep { width: 1px; height: 16px; background: var(--border); }
.bulk-btn { display: inline-flex; align-items: center; gap: 5px; height: 20px; padding: 0 9px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border-soft); background: var(--surface-1); color: var(--fg-muted);
  font-size: 11.5px; line-height: 1; cursor: pointer;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease), color var(--dur) var(--ease); }
.bulk-btn:hover { background: var(--surface-2); color: var(--fg); }
.bulk-btn .ico-play { color: var(--green); }
.bulk-btn .ico-pause { color: var(--warn); }
.bulk-btn .ico-sync { color: var(--blue); }
.bulk-btn.danger { color: var(--error); border-color: var(--error-line); }
.bulk-btn.danger:hover { background: var(--error-soft); }
.bulk-btn.ghost { border-color: transparent; background: transparent; color: var(--fg-dim); }
.bulk-enter-active, .bulk-leave-active { transition: opacity var(--dur) var(--ease-out), transform var(--dur) var(--ease-out); }
.bulk-enter-from, .bulk-leave-to { opacity: 0; transform: translateY(-5px); }

/* ---------------- 设置页(图形化配置编辑器) ----------------
 * RFB-02: 字段行栅格令牌化(label 宽/列间距/行内边距/控件最大宽单点声明), 全部 .ce-field 行
 * 与嵌套容器共用同一套 -> 同层输入框左缘逐级严格对齐; 控件最大宽放开到 --ce-input-max,
 * 宽屏下不再「页面很宽、内容只占一窄条」。TBL-07: 不再 2560px 居中限宽。 */
.ce-page { padding: 16px 12px calc(24px + var(--statusbar-h, 34px)); display: flex; flex-direction: column;
  --ce-label-w: 200px;    /* 字段标签列宽(全部层级一致) */
  --ce-ctl-gap: 12px;     /* 标签列与控件列的间距 */
  --ce-row-pad-x: 12px;   /* 字段行左右内边距(与容器内边距折算后同层对齐) */
  --ce-input-max: 720px;  /* 输入控件/说明文字的最大宽度(页面利用率) */ }
.ce-grid { display: grid; grid-template-columns: 216px minmax(0, 1fr); gap: 18px; align-items: start; }
.ce-placeholder { display: flex; flex-direction: column; align-items: center; gap: 12px;
  text-align: center; color: var(--fg-dim); padding: 56px 20px; }
.ce-placeholder.loading { animation: loading-glow 1.8s ease-in-out infinite; }

.ce-side { position: sticky; top: 74px; display: flex; flex-direction: column; gap: 3px; padding: 6px;
  border-radius: var(--radius); background: var(--surface-1); border: 1px solid var(--border-soft); }
.ce-master-title { display: flex; align-items: center; gap: 6px; padding: 6px 10px 8px;
  font-size: 11.5px; font-weight: 600; letter-spacing: .06em; color: var(--fg-dim); text-transform: uppercase; }
.ce-master-title .ce-spacer { flex: 1; }
.ce-master-title .ce-icon, .ce-master-title .ce-icon:hover { color: var(--green); }
.ce-side-item { display: flex; align-items: center; gap: 9px; text-align: left;
  background: transparent; border: 0; border-radius: var(--radius-sm); color: var(--fg-muted);
  padding: 9px 12px; font-size: 13px; cursor: pointer;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease); }
.ce-side-item .ico { opacity: .9; transition: opacity var(--dur) var(--ease); }
.ce-side-label { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ce-side-item:hover { background: var(--surface-2); color: var(--fg); }
.ce-side-item:hover .ico { opacity: 1; }
.ce-side-item.active { background: var(--accent-soft); color: var(--fg); font-weight: 600;
  box-shadow: inset 2px 0 0 var(--accent); }
.ce-side-item.active .ico { opacity: 1; }
.icog-basic { color: var(--blue); }
.icog-logging { color: var(--indigo); }
.icog-web { color: var(--cyan); }
.icog-notify { color: var(--warn); }
.icog-maintenance { color: var(--green); }
.icog-speed { color: var(--violet); }
.icog-trackers { color: var(--teal); }
.icog-rules { color: var(--pink); }
.ce-side-badge { font-size: 11px; padding: 1px 7px; border-radius: var(--radius-sm);
  background: var(--surface-2); color: var(--fg-muted); }
.ce-side-item.active .ce-side-badge { background: var(--accent-soft); color: var(--accent-hi); }

.ce-main { min-width: 0; display: flex; flex-direction: column; gap: 14px; padding-bottom: 8px; }
.ce-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.ce-head h2 { display: flex; align-items: center; gap: 8px; margin: 0;
  font-size: 18px; font-weight: 600; letter-spacing: .01em; }
.ce-head h2 .ico { opacity: .95; }
.ce-sub { margin: 4px 0 0; color: var(--fg-dim); font-size: 12.5px; }
.ce-head-actions { display: flex; align-items: center; gap: 10px; flex-shrink: 0; }
.ce-sync { display: inline-flex; align-items: center; gap: 5px; padding: 3px 10px; border-radius: var(--radius-sm);
  background: var(--green-soft); color: var(--green); font-size: 11.5px; white-space: nowrap; }
.ce-sync.on { background: var(--warn-soft); color: var(--warn); }
.ce-sub-head { display: flex; align-items: center; gap: 8px; padding: 2px 2px 0; }
.ce-sub-title { font-size: 13px; font-weight: 600; color: var(--fg); }

.ce-card { display: flex; flex-direction: column; gap: 6px; padding: 12px 14px;
  border-radius: var(--radius); background: var(--bg-card); border: 1px solid var(--border);
  box-shadow: var(--shadow-1);
  transition: border-color var(--dur) var(--ease); }
.ce-card:hover { border-color: var(--border-strong); }
.ce-detail-title { font-size: 14.5px; letter-spacing: .01em; }

.ce-banner { padding: 10px 14px; border-radius: var(--radius); font-size: 13px; border: 1px solid transparent; }
.ce-banner.ok { background: var(--green-soft); color: var(--green); border-color: var(--green-line); }
.ce-banner.warn { background: var(--warn-soft); color: var(--warn); border-color: var(--warn-line); }
.ce-banner.error { background: var(--error-soft); color: var(--error); border-color: var(--error-line); }

.ce-fields { display: flex; flex-direction: column; gap: 2px; }
.ce-field { display: grid; grid-template-columns: var(--ce-label-w) minmax(0, 1fr); gap: var(--ce-ctl-gap); align-items: start;
  padding: 7px var(--ce-row-pad-x); border-radius: var(--radius); background: transparent; border: 1px solid transparent;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease),
    opacity var(--dur) var(--ease); }
.ce-field:hover { background: var(--surface-2); border-color: var(--border-soft); }
.ce-field-block { grid-template-columns: 1fr; }
.ce-label { display: flex; align-items: center; gap: 6px; min-height: 34px; font-size: 13px; color: var(--fg); }
.ce-field.ce-inactive { opacity: .45; }
.ce-field.ce-inactive:hover { opacity: .8; }
.ce-ctl { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; min-width: 0; }

/* RFB-02 件4 展开/折叠密度: 头部内边距与段间距统一(折叠头行高一致);
 * 段间距 8px 与 .ce-main 的卡片间距 14px 拉开层级: 段内 < 段间 < 卡间 */
.ce-group { margin: 8px 0; border-radius: var(--radius); border: 1px solid var(--border-soft);
  background: var(--surface-1); border-left: 3px solid var(--accent);
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease); }
.ce-group:hover { border-color: var(--border); box-shadow: var(--shadow-1); }
.ce-group.ceg-0 { border-left-color: var(--blue); }
.ce-group.ceg-1 { border-left-color: var(--violet); }
.ce-group.ceg-2 { border-left-color: var(--teal); }
.ce-group.ceg-3 { border-left-color: var(--pink); }
.ce-group.ceg-4 { border-left-color: var(--indigo); }
.ce-group.ceg-5 { border-left-color: var(--cyan); }
.ce-group-head { display: flex; align-items: center; gap: 8px; padding: 8px 12px; cursor: pointer;
  user-select: none; transition: background var(--dur) var(--ease); }
.ce-group-head:hover { background: var(--surface-2); }
.ce-group-head .caret { color: var(--accent); opacity: .55; transform: rotate(0deg);
  transition: transform var(--dur) var(--ease-spring), opacity var(--dur) var(--ease); }
.ce-group-head:hover .caret { opacity: 1; }
.ce-group-head .caret.open { transform: rotate(90deg); }
/* RFB-02 件4 标题分级(由大到小): 卡片题 14.5 > group 段 13.5 > section 段 13 > subcard 12 */
.ce-group-title { font-size: 13.5px; font-weight: 600; color: var(--fg); }
.ce-group-sum { font-size: 11.5px; color: var(--fg-dim); overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
.ce-group-body { overflow: hidden; padding: 2px 12px 8px; }
.ce-group-body[style*="display: none"] { padding: 0; }
.ce-inline-help { font-weight: 400; font-size: 12px; color: var(--fg-dim); }
/* ⚠ 本行的选择器头曾被波次三的批量编辑吞掉(连同下面那条漏闭合的 .ce-subcard .ce-field 规则一起),
 * 留下孤立声明段与一个多余闭合符, 浏览器从这条起把后续规则整段丢弃 —— 已按星图同名规则还原。 */
.ce-subcard { margin: 6px 0 10px; padding: 6px 10px 8px; border-radius: var(--radius);
  background: var(--bg-sunken); border: 1px solid var(--border-soft); border-left: 2px solid var(--teal); }
.ce-subcard-head { display: flex; align-items: center; gap: 6px; padding: 2px 2px 4px;
  font-size: 12px; font-weight: 500; color: var(--fg-muted); }
.ce-subcard-head .ico { color: var(--teal); transform: rotate(90deg); }
/* 相关设置子卡内的字段栅格: 固定标签列宽(prism 用 160px, 星图用令牌 --ce-label-w)。
 * ⚠ 这里原本有一条**未闭合**的 `.ce-subcard .ce-field { grid-template-columns: var(--ce-label-w) …; padding: 7px 0`
 * (波次三批量编辑丢掉了 `; }`), 被浏览器当作未结束的声明块 → 其后约 200 条规则被整段丢弃
 * (棱镜缺样式的真凶)。与被下面这条完全同选择器/同属性, 属冗余行, 直接删除。 */
.ce-subcard .ce-field { grid-template-columns: 160px minmax(0, 1fr); padding: 6px 8px; }
.ce-subcard .ce-field .ce-help { margin-top: -2px; }

.ce-section { margin: 8px 0; border-radius: var(--radius); border: 1px solid var(--border-soft);
  background: var(--surface-1); border-left: 3px solid var(--violet);
  transition: border-color var(--dur) var(--ease), opacity var(--dur) var(--ease),
    box-shadow var(--dur) var(--ease); }
.ce-section:hover { border-color: var(--border); box-shadow: var(--shadow-1); }
.ce-section-head { display: flex; align-items: center; gap: 8px; padding: 8px 12px; }
.ce-section-head .caret { color: var(--violet); opacity: .55; transform: rotate(0deg);
  transition: transform var(--dur) var(--ease-spring), opacity var(--dur) var(--ease); }
.ce-section:hover .ce-section-head .caret { opacity: 1; }
.ce-section-title { font-size: 13px; font-weight: 600; color: var(--fg); }
.ce-section-sum { font-size: 11.5px; color: var(--fg-dim); overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
.ce-section-body { padding: 2px 10px 8px 14px; }
/* 段内展开后的行奇偶区隔: 偶数行叠加极淡表面色, 长列表更容易横向跟行;
 * 容器自身保留分组底色, hover 仍以描边浮出 —— 两种提示并存不冲突 */
.ce-group-body > .ce-item:nth-child(even) > .ce-field,
.ce-section-body > .ce-item:nth-child(even) > .ce-field { background: var(--surface-2); }

/* 统一注记(RFB-02 件2): 段级/字段级警告与提示 = 行内小字 + 色点, 不再用大框横幅。
 * 网格双列(色点列 + 文本列): 换行时文字悬挂缩进; 字段行内独占一行(宽度与输入区对齐) */
.ce-note { display: inline-grid; grid-template-columns: auto minmax(0, 1fr); column-gap: 7px; align-items: start;
  font-size: 12px; line-height: 1.5; color: var(--fg-muted); max-width: var(--ce-input-max); }
.ce-note::before { content: ""; width: 6px; height: 6px; margin-top: 6px; border-radius: 50%;
  background: var(--fg-dim); }
.ce-note.warn { color: var(--warn); }
.ce-note.warn::before { background: var(--warn); }
.ce-note.error { color: var(--error); }
.ce-note.error::before { background: var(--error); }
.ce-ctl .ce-note { flex: 1 1 100%; }

.ce-master-detail { display: grid; grid-template-columns: 200px minmax(0, 1fr); gap: 16px; align-items: start; }
.ce-master { position: sticky; top: 74px; display: flex; flex-direction: column; gap: 3px; padding: 6px;
  border-radius: var(--radius); background: var(--surface-1); border: 1px solid var(--border-soft); }
.ce-master-item { text-align: left; background: transparent; border: 0; border-radius: var(--radius-sm);
  color: var(--fg-muted); padding: 8px 11px; font-size: 13px; cursor: pointer;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease); }
.ce-master-item:hover { background: var(--surface-2); color: var(--fg); }
.ce-master-item.active { background: var(--accent-soft); color: var(--fg); font-weight: 600; }
.ce-detail { min-width: 0; display: flex; flex-direction: column; gap: 10px; }
.ce-detail-bar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

.ce-rule-card { position: relative; display: flex; flex-direction: column; gap: 8px;
  padding: 10px 14px 12px 17px; border-radius: var(--radius);
  background: var(--bg-card); border: 1px solid var(--border); }
.ce-rule-card::before { content: ""; position: absolute; left: 0; top: 10px; bottom: 10px; width: 3px;
  border-radius: 999px; background: var(--accent); }
.ce-rule-card.collapsed::before { background: var(--border-strong); }
.ce-rule-card.collapsed { padding-bottom: 10px; }
.ce-rule-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ce-rule-head .caret { color: var(--fg-dim); transition: transform var(--dur) var(--ease); }
.ce-rule-card:not(.collapsed) .ce-rule-head .caret { transform: rotate(90deg); color: var(--accent); }
.ce-rule-name { font-size: 14px; letter-spacing: .01em; }
.ce-rule-meta { font-size: 11.5px; color: var(--fg-dim); }
.ce-rule-body { display: flex; flex-direction: column; gap: 8px; }
.ce-plugins { display: flex; flex-direction: column; gap: 8px; margin-top: 4px;
  border-top: 1px dashed var(--border); padding-top: 10px; }
.ce-plugins-head { display: flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--fg-dim); }
.ce-plugins-title { display: flex; align-items: baseline; gap: 8px; flex: 1; color: var(--fg); font-weight: 600; }
.ce-plugin-card { display: flex; flex-direction: column; gap: 4px; padding: 9px 11px;
  border: 1px solid var(--border-soft); border-radius: var(--radius-sm); background: var(--surface-1); }
.ce-plugin-bar { display: flex; align-items: center; gap: 8px; }
.ce-ord { flex: 0 0 auto; display: inline-grid; place-items: center; width: 20px; height: 20px;
  border-radius: var(--radius-sm); background: var(--accent-soft); color: var(--accent-hi);
  font-family: var(--font-mono); font-size: 11px; font-weight: 600; }

.ce-curve { display: flex; flex-direction: column; gap: 12px; }
.ce-curve-off { flex-direction: row; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap; }
.ce-curve-off .ce-help { flex: 1 1 320px; }
.ce-curve-card { gap: 10px; }
.ce-curve-card.collapsed { background: var(--bg-sunken); }
.ce-curve-card .caret { color: var(--accent); opacity: .65; transform: rotate(0deg);
  transition: transform var(--dur) var(--ease-spring), opacity var(--dur) var(--ease); }
.ce-curve-card .caret.open { transform: rotate(90deg); }
.ce-curve-card .ce-icon.flat { padding: 2px; border-radius: var(--radius-sm); }
.ce-curve-card .ce-icon.flat:hover { background: var(--surface-2); }
.ce-curve-badge { flex: 0 0 auto; display: inline-grid; place-items: center; width: 22px; height: 22px;
  border-radius: var(--radius-sm); background: var(--accent-soft); color: var(--accent-hi);
  font-family: var(--font-mono); font-size: 12px; font-weight: 600; }
.ce-curve-dir { display: flex; flex-direction: column; gap: 8px; padding: 10px;
  border-radius: var(--radius); background: var(--bg-sunken); border: 1px solid var(--border-soft); }
.ce-curve-dir-head { display: flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--fg); font-weight: 600; }
.ce-curve-dir.d-up .ce-curve-dir-head > .ico { color: var(--green); }
.ce-curve-dir.d-down .ce-curve-dir-head > .ico { color: var(--blue); }
.ce-curve-points { display: flex; flex-direction: column; gap: 5px; }
.ce-curve-point-head, .ce-curve-point { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) 30px;
  gap: 8px; align-items: center; }
.ce-curve-point-head { font-size: 11.5px; color: var(--fg-dim); }
.ce-curve-point .ce-input { flex: 1 1 auto; max-width: none; }

.ce-chart { position: relative; margin: 4px 0; padding: 10px 12px 6px; border-radius: var(--radius);
  background: var(--bg); border: 1px solid var(--border-soft); cursor: crosshair; }
.ce-chart-svg { display: block; width: 100%; height: auto; aspect-ratio: 560 / 210; }
.ce-chart-line { fill: none; stroke: var(--accent); stroke-width: 2; stroke-linejoin: round;
  vector-effect: non-scaling-stroke; }
.ce-chart-area { fill: var(--accent-soft); stroke: none; }
.ce-curve-dir.d-up .ce-chart-line { stroke: var(--green); }
.ce-curve-dir.d-up .ce-chart-area { fill: var(--green-soft); }
.ce-curve-dir.d-down .ce-chart-line { stroke: var(--blue); }
.ce-curve-dir.d-down .ce-chart-area { fill: var(--blue-soft); }
.ce-grid-lines line { stroke: var(--border-soft); stroke-width: 1; vector-effect: non-scaling-stroke; }
.ce-chart-tick { stroke: var(--border); stroke-width: 1; stroke-dasharray: 2 3;
  vector-effect: non-scaling-stroke; }
.ce-chart-cross { stroke: var(--fg-dim); stroke-width: 1; stroke-dasharray: 3 3;
  vector-effect: non-scaling-stroke; opacity: .85; }
.ce-chart-dot { fill: var(--fg); stroke: var(--bg); stroke-width: 2; vector-effect: non-scaling-stroke; }
.ce-chart-svg .ce-axis-labels text { fill: var(--fg-dim); font-size: 10px; }
.ce-chart-tip { position: absolute; transform: translate(10px, -50%); display: flex; flex-direction: column;
  gap: 1px; padding: 6px 9px; border-radius: var(--radius-sm); background: var(--bg-elev);
  border: 1px solid var(--border-strong); box-shadow: var(--shadow-2); pointer-events: none;
  font-size: 11.5px; color: var(--fg-soft); white-space: nowrap; z-index: 2; }
.ce-chart-tip.flip { transform: translate(calc(-100% - 10px), -50%); }
.ce-chart-tip b { color: var(--fg); font-size: 12px; }
.ce-chart-legend { display: flex; gap: 12px; padding: 4px 2px 0; font-size: 11px; color: var(--fg-dim); }
.ce-chart-legend .ce-lg-x, .ce-chart-legend .ce-lg-y { white-space: nowrap; }
.ce-chart-legend .ce-lg-note { margin-left: auto; }

.ce-preview { margin-top: 8px; display: flex; flex-direction: column; gap: 8px; align-items: flex-start; }
.ce-preview-body { width: 100%; max-height: 440px; overflow: auto; margin: 0; padding: 14px 16px;
  border-radius: var(--radius); border: 1px solid var(--border); background: var(--bg-sunken);
  font: 12.5px/1.65 var(--font-mono); color: var(--fg-soft);
  white-space: pre; tab-size: 2; }

.ce-actions { position: sticky; bottom: 0; z-index: 6; display: flex; align-items: center;
  justify-content: flex-end; gap: 10px; margin-top: 14px; padding: 12px 4px;
  background: linear-gradient(transparent, var(--bg) 42%); }

/* ---------------- 历史流量弹层 ---------------- */
.hist-modal { width: var(--modal-w-add); max-width: 100%; }
.hist-modal .modal-title { margin-bottom: 12px; }
.hist-tabs { display: inline-flex; gap: 2px; padding: 2px; border-radius: var(--radius-sm);
  background: var(--bg-sunken); border: 1px solid var(--border-soft); }
.hist-tabs button { padding: 3px 12px; border: 0; border-radius: var(--radius-sm); background: transparent;
  color: var(--fg-muted); font-size: 12px; cursor: pointer;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease); }
.hist-tabs button:hover { color: var(--fg); }
.hist-tabs button.active { background: var(--accent-soft); color: var(--accent-hi);
  box-shadow: inset 0 0 0 1px var(--accent-line); }
.hist-loading, .hist-empty { padding: 44px 0; text-align: center; color: var(--fg-dim); font-size: 13px; }
.hist-chart { position: relative; }
.hist-svg { display: block; width: 100%; height: auto; aspect-ratio: 920 / 380; }
.hist-grid line { stroke: var(--hairline); }
.hist-axis text { fill: var(--fg-dim); font-size: 10px; font-family: var(--font-mono); }
.hist-area.up { fill: var(--today-up); opacity: .08; }
.hist-area.down { fill: var(--today-down); opacity: .08; }
.hist-line { fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
  vector-effect: non-scaling-stroke; stroke-dasharray: 1000; stroke-dashoffset: 1000;
  animation: hist-draw .7s var(--ease-out) forwards; }
.hist-line.up { stroke: var(--today-up); }
.hist-line.down { stroke: var(--today-down); }
.hist-cross line { stroke: var(--fg-dim); stroke-width: 1; stroke-dasharray: 3 3;
  vector-effect: non-scaling-stroke; opacity: .8; }
.hist-dot { stroke: var(--bg); stroke-width: 2; vector-effect: non-scaling-stroke; }
.hist-dot.up { fill: var(--today-up); }
.hist-dot.down { fill: var(--today-down); }
.hist-tip { position: absolute; transform: translateX(-50%); display: flex; flex-direction: column; gap: 1px;
  padding: 7px 11px; border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  background: var(--bg-elev); box-shadow: var(--shadow-2); font-size: 11.5px; color: var(--fg-muted);
  pointer-events: none; white-space: nowrap; z-index: 2; }
.hist-tip.flip { transform: translateX(-100%); }
.hist-tip b { color: var(--fg); font-size: 12px; }
.hist-tip .h-up { color: var(--today-up); }
.hist-tip .h-down { color: var(--today-down); }
.hist-legend { display: flex; align-items: center; gap: 16px; margin-top: 8px; font-size: 12px; color: var(--fg-muted); }
.hist-legend .sw { display: inline-block; width: 9px; height: 9px; border-radius: 2px; margin-right: 6px; }
.hist-legend .sw.up { background: var(--today-up); }
.hist-legend .sw.down { background: var(--today-down); }
.hist-hint { margin-left: auto; color: var(--fg-dim); font-size: 11.5px; }
.hist-summary { display: flex; flex-wrap: wrap; gap: 6px 18px; margin-top: 10px; padding-top: 10px;
  border-top: 1px solid var(--border-soft); font-size: 12px; color: var(--fg-dim); }
.hist-summary b { color: var(--fg); font-weight: 600; font-variant-numeric: tabular-nums; }
.hist-summary .h-up { color: var(--today-up); }
.hist-summary .h-down { color: var(--today-down); }

/* ---------------- 响应式 ---------------- */
@media (max-width: 1320px) {
  .top-search input { width: 168px; }
  .top-search input:focus { width: 208px; }
}
@media (max-width: 1200px) {
  .layout { padding: 12px 12px calc(24px + var(--statusbar-h, 34px)); }
}
@media (max-width: 900px) {
  .topbar { flex-wrap: wrap; gap: 10px; padding: 10px 12px; }
  .topbar .spacer { display: none; }
  .layout { padding: 12px 12px calc(24px + var(--statusbar-h, 34px)); }
  .statusbar { padding: 0 12px; gap: 10px; }
  .ce-page { padding: 12px 12px 24px; }
  .status-strip { padding: 7px 12px; overflow-x: auto; align-items: flex-start; }
  .dist-bar { flex-basis: 120px; }
  .ce-grid, .ce-master-detail { grid-template-columns: 1fr; }
  .ce-side, .ce-master { position: static; flex-direction: row; flex-wrap: wrap; }
  .group-head, .group-row { min-width: 1180px; }
}

/* ============ 种子页(R1A): 种子行专属单元格 ============ */

/* 视图开关样式已随元素退役(2026-09-17): 三态视图升为顶栏一级导航后, 页内第二套切换器删除 */

/* 种子行: 状态文字弱化 / 保存路径与 tracker 列省略号(title 兜底) */
/* 状态文案在错误状态下是**具体原因**("文件丢失" / tracker 报错原文, 可能很长): 一律省略号
 * 截断 + title 悬停给全文, 不撑破状态列(行内单元格 min-width:0 见 .member-row > * 规则)。
 * .m-state 内的文本必须包一层 .state-text 才能拿到省略号 —— flex 容器的匿名文本项不可压缩。 */
.state-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.torrent-row .state-text { font-size: 12px; color: var(--fg-muted); }
.g-save-path { color: var(--fg-muted); font-size: 12px; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }

/* ==================== 种子详情抽屉(R1B) ====================
 * 层级: 抽屉 80 < 右键菜单 100 < toast 120 < 确认框 130; 表面/描边与 modal 同族(--bg-card/--border-strong) */
.drawer-mask { position: fixed; inset: 0; z-index: 80; display: flex; justify-content: flex-end;
  background: rgba(0, 0, 0, .38); backdrop-filter: blur(2px); animation: fade-in .14s var(--ease); }
.drawer { width: min(780px, 94vw); height: 100%; display: flex; flex-direction: column;
  background: var(--bg-card); border-left: 1px solid var(--border-strong); box-shadow: var(--shadow-3);
  animation: drawer-in .18s var(--ease); }
@keyframes drawer-in { from { transform: translateX(24px); opacity: 0; } }
.drawer-enter-active, .drawer-leave-active { transition: opacity .15s var(--ease); }
.drawer-enter-from, .drawer-leave-to { opacity: 0; }
/* 离场中的遮罩立刻停止接收指针(与星图同款双保险): 全屏 fixed 遮罩若因过渡未触发
 * (后台标签页不跑 CSS 过渡 -> transitionend 不来 -> Vue 不移除元素)而滞留, 会以 opacity:0
 * 拦截整页点击; 模板另加 :duration 兜底 */
.drawer-mask.drawer-leave-active { pointer-events: none; }
.drawer-head { display: flex; align-items: flex-start; gap: 12px; padding: 14px 16px 10px; border-bottom: 1px solid var(--border); }
.drawer-title { flex: 1; min-width: 0; display: flex; gap: 8px; align-items: flex-start; }
.drawer-title strong { font-size: 14px; line-height: 1.45; overflow-wrap: anywhere; }
.drawer-actions { display: flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }
.drawer-tabs { display: flex; gap: 2px; padding: 8px 16px 0; border-bottom: 1px solid var(--border); }
.drawer-tabs button { padding: 7px 14px; border: 0; background: transparent; color: var(--fg-muted);
  cursor: pointer; font-size: 13px; border-bottom: 2px solid transparent; }
.drawer-tabs button.active { color: var(--accent-hi); border-bottom-color: var(--accent-line); }
.drawer-body { flex: 1; overflow: auto; padding: 14px 16px 24px; }
.drawer-hr { border: 1px solid var(--border); border-left: 2px solid var(--hr-pending, #c56a1a); padding: 8px 12px;
  margin: 0 0 16px; font-size: 13px; display: flex; gap: 10px; flex-wrap: wrap; align-items: baseline; }
.drawer-hr.done { border-left-color: var(--hr-done, #0e8574); }
.drawer-sec { margin: 0 0 18px; }
.drawer-sec h4 { margin: 0 0 8px; font: 600 11px/1 var(--font-mono);
  letter-spacing: .1em; text-transform: uppercase; color: var(--fg-muted); }
.drawer-rows { display: grid; grid-template-columns: 150px minmax(0, 1fr); gap: 4px 14px; font-size: 13px; }
.drawer-rows .k { color: var(--fg-muted); }
.drawer-rows .v { overflow-wrap: anywhere; min-width: 0; }
.drawer-rows .v.mono { font-family: var(--font-mono); font-size: 12px; }
.drawer-table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.drawer-table th { text-align: left; font: 600 11px/1.4 var(--font-mono); letter-spacing: .08em;
  text-transform: uppercase; color: var(--fg-muted); padding: 6px 8px; border-bottom: 1px solid var(--border); white-space: nowrap; }
.drawer-table td { padding: 6px 8px; border-bottom: 1px solid var(--border); vertical-align: top; }
.drawer-table td.wrap { white-space: normal; overflow-wrap: anywhere; }
.drawer-table tr.virtual td { color: var(--fg-muted); }
.drawer-table .mono-cell { font-family: var(--font-mono); font-size: 12px; }
.drawer-table .dir-name { color: var(--fg-muted); }
/* R10-15: 内容页目录/文件分色 —— 目录是**结构**(亮一档 + 加粗), 文件是内容(中间调),
 * 只引既有令牌族不散写色值; skipped(优先级=跳过)仍由 tr.skipped 统一弱化 */
.drawer-table .dir-name.dir { color: var(--fg-soft); font-weight: 600; }
.drawer-table tr.skipped td { color: var(--fg-muted); }
.drawer-raw { margin-top: 6px; }
.drawer-raw summary { cursor: pointer; color: var(--fg-muted); font-size: 12.5px; margin-bottom: 8px; }

/* ================= 运行日志(W4) —— 原顶层日志页整体迁入设置页 [运行日志] 章节 =================
 * 不再是顶层 page; 作为 .ce-main 内的一个特殊章节渲染, 无自动轮询(仅引用 tokens)。
 * mono 等宽原始行; 章节头含等级/行数选择与手动刷新, 正文独立滚动。
 */
.logs-embed { display: flex; flex-direction: column; flex: 1; min-height: 0;
  height: calc(100vh - var(--head-h, 100px) - var(--statusbar-h, 34px) - 250px); }
.logs-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: 12px; }
.logs-head-text h2 { display: flex; align-items: center; gap: 8px; margin: 0; font-size: 15px; font-weight: 600; }
.logs-head-text h2 .ico { color: var(--accent); }
.logs-head-text .ce-sub { max-width: 56vw; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.logs-actions { display: flex; align-items: center; gap: 10px; flex: 0 0 auto; }
.logs-ctl { display: inline-flex; align-items: center; gap: 6px; color: var(--fg-dim); font-size: 12px; }
.logs-ctl select { padding: 5px 8px; border-radius: var(--radius-sm); border: 1px solid var(--border);
  background: var(--bg-card); color: var(--fg); font: inherit; font-size: 12px; cursor: pointer; }
.logs-ctl select:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--ring); }
.logs-body { display: flex; flex-direction: column; flex: 1; min-height: 0; overflow: hidden;
  border: 1px solid var(--border); border-radius: var(--radius); background: var(--bg-sunken); }
.logs-body .ce-placeholder { flex: 1; }
.logs-pre { flex: 1; margin: 0; padding: 10px 12px; overflow: auto;
  font-family: var(--font-mono); font-size: 11.5px; line-height: 1.6;
  color: var(--fg-muted); white-space: pre-wrap; word-break: break-all; }

/* ================= 限速修改弹窗(SPD-04; 仅引用 tokens) =================
 * 交互改为 qB 式「点击限速 -> 弹窗修改」; 原左栏"限速对照卡 + 临时覆盖表单"随 .rail 一并退役。
 * 表单两方向都必填(后端语义: 两方向都设置, 0 = 不限); 曲线启用时为临时覆盖, 下一档位恢复。
 */
.speed-dialog .add-dialog-body { display: flex; flex-direction: column; gap: 12px; }
.speed-mode-line { display: flex; align-items: center; gap: 7px; padding: 8px 10px;
  border-radius: var(--radius-sm); background: var(--surface-1); border: 1px solid var(--border-soft);
  color: var(--fg-muted); font-size: 12px; }
.speed-dialog-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.add-dialog-hint { margin: 0; color: var(--fg-dim); font-size: 11.5px; line-height: 1.5; }

/* ================= 追剧视图(R10): 剧→季→集 层级(prism 移植自星图, 令牌同名族) =================
 * 复用 .group-row/.detail/.member-row 的既有样式; 这里只补层级结构件:
 * 剧行(剧名加重) / 季子标题 / 集行(集号 chip + 版本徽标) / 缺集提示 / 未识别折叠区 */
.show-row .show-name-text { font-weight: 600; }

.season-head {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 14px 7px; margin-top: 2px;
  border-bottom: 1px solid var(--border-soft);
  font-size: 12px; letter-spacing: .06em;
  color: var(--fg-muted); font-weight: 600;
  position: sticky; top: 0; background: var(--bg-sunken);
}
.season-name { font-family: var(--font-mono); }

.gap-badge {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 1px 8px; border-radius: 999px;
  background: var(--warn-soft); color: var(--warn);
  font-size: 11.5px; font-weight: 600; cursor: help;
}

.ep-row .g-name .caret { opacity: .55; }
.ep-row.expanded .caret { opacity: 1; }
.ep-key {
  font-family: var(--font-mono); font-size: 12.5px; font-weight: 600;
  padding: 1px 7px; border-radius: 4px;
  background: var(--surface-1); border: 1px solid var(--border-soft);
}
.ep-pack {
  font-size: 10.5px; padding: 0 5px; border-radius: 3px;
  background: var(--surface-1); color: var(--fg-muted); border: 1px solid var(--border-soft);
}
.ep-site-count { font-size: 11.5px; color: var(--fg-dim); }
.ep-row .state-text { font-size: 12px; color: var(--fg-muted); }

.unrecognized { margin-top: 14px; border-top: 1px dashed var(--border); padding-top: 8px; }
.unrecognized-head {
  display: flex; align-items: center; gap: 7px; width: 100%;
  padding: 6px 14px; border: 0; background: none; cursor: pointer;
  color: var(--fg-muted); font-size: 12.5px; font-weight: 600;
  font-family: inherit; text-align: left;
}
.unrecognized-head:hover { color: var(--accent); }
.unrecognized-head .caret { transition: transform var(--dur) var(--ease); }
.unrecognized-head .caret.open { transform: rotate(90deg); }
.unrecognized-hint { font-weight: 400; font-size: 11.5px; color: var(--fg-dim); }
.unrecognized-body { padding: 2px 0 6px; }
.unrecognized-row {
  display: grid; grid-template-columns: 110px minmax(200px, 2.2fr) 76px 92px 92px;
  gap: 10px; align-items: center; padding: 5px 14px;
}
.unrecognized-row .m-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--fg); font-size: 12.5px; }

/* ================= 波次三 W1/W5 棱镜移植 · 表格呈现层与详情抽屉 ================= */

/* TBL-05 表头拖动重排: 源列半透明; 落点指示线是 head 容器的绝对定位子元素(不占 grid 轨道,
 * app.js 读 gridTemplateColumns 计列宽时不受影响)。.group-head 自带 sticky 定位上下文,
 * .detail-head 非 sticky, 需补 relative 作指示线包含块 */
.detail-head { position: relative; }
.h-cell.drag-src { opacity: .45; }
.group-head.col-dragging .h-cell, .detail-head.col-dragging .h-cell { cursor: col-resize; }
.col-drop-line { position: absolute; top: 0; height: 100%; width: 2px; border-radius: 1px;
  background: var(--accent); box-shadow: 0 0 6px var(--accent-line); pointer-events: none; z-index: 3; }

/* TBL-03 行状态**文字色** + 数值色阶(用户 2026-09-17: 要的是**文字颜色**而非背景色)。
 * 棱镜此前只有 .g-status 徽标底色, 缺行级状态色 —— 本次与星图对齐: 名称/数值列文字染语义色;
 * 0 值(.zero)与"—"占位不染; 数值色阶 tone-* 写在状态色之后 -> 同权重时源顺序胜出。
 *
 * R10-06: 覆盖面从"名称 + 数值格子"扩到**文本型格子** —— 保存路径 / Hash v1 / Hash / Tracker /
 * 站数。芯片类(站点/标签/分类)按决策 D6-A **不跟随**行状态色: 芯片表达的是**成员级**语义
 * (组内不同站点状态可不同), 强行覆盖会把这层信息抹平。
 *
 * R12(用户要求, 与星图同口径): ① 进度/状态两列文字纳入同一套规则(此前恒为 --fg-muted 灰);
 * ② paused/other 不再保持默认前景(近白), 改用中性中间调 --paused —— 即"已暂停"状态文字那支色,
 * 与 FX-06 的徽标/站点芯片同一族。 */
.group-row.s-seeding .g-name-text, .group-row.s-seeding .g-stat:not(.zero),
.group-row.s-seeding .g-save-path, .group-row.s-seeding .m-hash, .group-row.s-seeding .g-count,
.group-row.s-seeding .m-progress .val, .group-row.s-seeding .state-text { color: var(--green); }
.group-row.s-downloading .g-name-text, .group-row.s-downloading .g-stat:not(.zero),
.group-row.s-checking .g-name-text, .group-row.s-checking .g-stat:not(.zero),
.group-row.s-downloading .g-save-path, .group-row.s-downloading .m-hash, .group-row.s-downloading .g-count,
.group-row.s-checking .g-save-path, .group-row.s-checking .m-hash, .group-row.s-checking .g-count,
.group-row.s-downloading .m-progress .val, .group-row.s-checking .m-progress .val,
.group-row.s-downloading .state-text, .group-row.s-checking .state-text { color: var(--blue); }
.group-row.s-error .g-name-text, .group-row.s-error .g-stat:not(.zero),
.group-row.s-error .g-save-path, .group-row.s-error .m-hash, .group-row.s-error .g-count,
.group-row.s-error .m-progress .val, .group-row.s-error .state-text { color: var(--error); }
.group-row.s-paused .g-name-text, .group-row.s-paused .g-stat:not(.zero),
.group-row.s-paused .g-save-path, .group-row.s-paused .m-hash, .group-row.s-paused .g-count,
.group-row.s-paused .m-progress .val, .group-row.s-paused .state-text,
.group-row.s-other .g-name-text, .group-row.s-other .g-stat:not(.zero),
.group-row.s-other .g-save-path, .group-row.s-other .m-hash, .group-row.s-other .g-count,
.group-row.s-other .m-progress .val, .group-row.s-other .state-text { color: var(--paused); }
/* 成员行(展开明细/追剧集明细)同口径: 行类名是 m.kind 而非 s-*, 故单独一组 */
.member-row.seeding .m-stat:not(.zero), .member-row.seeding .m-hash, .member-row.seeding .g-save-path,
.member-row.seeding .m-progress .val, .member-row.seeding .state-text { color: var(--green); }
.member-row.downloading .m-stat:not(.zero), .member-row.checking .m-stat:not(.zero),
.member-row.downloading .m-hash, .member-row.checking .m-hash,
.member-row.downloading .g-save-path, .member-row.checking .g-save-path,
.member-row.downloading .m-progress .val, .member-row.checking .m-progress .val,
.member-row.downloading .state-text, .member-row.checking .state-text { color: var(--blue); }
.member-row.error .m-stat:not(.zero), .member-row.error .m-hash, .member-row.error .g-save-path,
.member-row.error .m-progress .val, .member-row.error .state-text { color: var(--error); }
.member-row.paused .m-stat:not(.zero), .member-row.paused .m-hash, .member-row.paused .g-save-path,
.member-row.paused .m-progress .val, .member-row.paused .state-text,
.member-row.other .m-stat:not(.zero), .member-row.other .m-hash, .member-row.other .g-save-path,
.member-row.other .m-progress .val, .member-row.other .state-text { color: var(--paused); }

/* TBL-03 数值色阶: tone-low 压暗(偏弱) / tone-high 品牌强调色(接近满档) */
.group-row .g-stat.tone-low, .member-row .m-stat.tone-low { color: var(--fg-muted); }
.group-row .g-stat.tone-high, .member-row .m-stat.tone-high { color: var(--accent-hi); }

/* W5-RFB-01 详情抽屉纯展示化: 抽屉头只留 标题 + 状态徽章 + 关闭(操作走行右键/批量条) */
.drawer-close { display: inline-flex; align-items: center; justify-content: center; width: 26px; height: 26px; padding: 0;
  border: 0; border-radius: var(--radius-sm); background: transparent; color: var(--fg-dim); cursor: pointer;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease); }
.drawer-close:hover { background: var(--bg-hover); color: var(--fg); }
/* 字段行: 图标 + 小字字段名 + 等宽值(超长值看下方 .wide 块行)
 * FX-22 重构三件: ① 长值行升格为**块行**(标签一行, 值独占下一行) —— 旧写法所有行都是
 * "16px / 112px / 1fr" 三列 + anywhere 硬断, 长路径被切成两行且与邻行参差; ② 图标按语义着色
 * (.ico-t-*, 不再是 48 行全灰); ③ 值区右侧可挂操作按钮(复制/打开目录)。 */
.f-rows { display: flex; flex-direction: column; font-size: 13px; }
.f-row { display: grid; grid-template-columns: 16px 112px minmax(0, 1fr) auto; gap: 10px;
  align-items: flex-start; padding: 6px 0; border-bottom: 1px solid var(--hairline); }
.f-row:last-child { border-bottom: 0; }
.f-row .ico { margin-top: 2px; color: var(--fg-dim); }
.f-row .k { color: var(--fg-muted); font-size: 11.5px; line-height: 1.7; }
.f-row .v { min-width: 0; font-family: var(--font-mono); font-size: 12px; line-height: 1.55;
  overflow-wrap: anywhere; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
/* 长值块行(路径 / 哈希 / 备注): 图标+键一行, 值独占下一行, 3 行上限 + break-word 断行 */
.f-row.wide { grid-template-columns: 16px minmax(0, 1fr) auto; grid-template-areas:
  "ico k act" "v v v"; row-gap: 2px; }
.f-row.wide > .ico { grid-area: ico; }
.f-row.wide > .k { grid-area: k; line-height: 1.5; }
.f-row.wide > .v { grid-area: v; -webkit-line-clamp: 3; overflow-wrap: break-word; word-break: normal; }
.f-row > .f-row-act { grid-area: act; align-self: center; width: 22px; height: 22px; }
.f-row-act { width: 22px; height: 22px; opacity: .55;
  transition: opacity var(--dur) var(--ease), background var(--dur) var(--ease), color var(--dur) var(--ease); }
.f-row:hover .f-row-act { opacity: 1; }
/* FX-22 图标语义色: 与右键菜单 CTX-01 彩图标集同语言(色值一律走主题令牌, 改色只改令牌) */
.f-row .ico-t-io { color: var(--blue); }      /* 传输: 下载/上传/箭头 */
.f-row .ico-t-cap { color: var(--teal); }     /* 容量: 大小/总大小/分块 */
.f-row .ico-t-time { color: var(--indigo); }  /* 时间: 日历/时钟/计时/ETA */
.f-row .ico-t-site { color: var(--cyan); }    /* 站点与连接: 地球/链接 */
.f-row .ico-t-sw { color: var(--green); }     /* 开关与设置族 */
.f-row .ico-t-id { color: var(--violet); }    /* 标识: 哈希/信息/标签/备注 */
.f-row .ico-t-path { color: var(--accent-hi); }  /* 路径: 文件夹 */
.f-row .ico-t-state { color: var(--pink); }   /* 状态与比率: 进度/分享率/校验/警示 */
/* FX-22 分组层级: 组标题行右侧给一句汇总(组间节奏 + 一眼看重点); 卡片化与设置页 .ce-section 同语言 */
.drawer-sec { padding: 10px 12px 6px; margin: 0 0 12px; border-radius: var(--radius);
  background: var(--surface-1); border: 1px solid var(--border-soft); }
.drawer-sec h4 { display: flex; align-items: baseline; gap: 10px; }
.drawer-sec h4 .s-sum { margin-left: auto; font-family: var(--font-mono); font-size: 11px;
  letter-spacing: 0; text-transform: none; color: var(--fg-dim); }
