  /* Vue 挂载前隐藏未编译的 {{ }} 模板（避免慢网/资源加载期看到原始花括号）；本地 /vendor 托管依赖，不走境外 CDN */
  [v-cloak] { display: none !important; }
  /* 表格加载中（切页/刷新）不显示「暂无数据」空状态，只留 loading 转圈——避免切换时空状态与转圈同时闪现 */
  .arco-spin:has(.arco-spin-mask) .arco-table-tr-empty { visibility: hidden; }
  html, body, #app { height: 100%; margin: 0; overflow: hidden; }  /* 外层框架锁死不滚动：只有 .sb-menu 与表格 body 内部滚动，页头/工具条/分页栏固定 */
  body { font-family: -apple-system, "PingFang SC", "Microsoft YaHei", sans-serif; }
  /* 泰语字形自带一份（vendor/ 在投放集内，随代码上线）：白底主图的文字要印进成品，
     靠系统字体会出现"同一张画布在 Mac 和 Windows 上字形不同"，甚至没装泰文字体时是一片豆腐块。
     Google 把 Noto Sans Thai 发成**可变字体**，一个文件覆盖 400~700，故只放一份。 */
  @font-face { font-family:'Noto Sans Thai'; src:url('vendor/NotoSansThai.woff2') format('woff2');
               font-weight:400 700; font-display:swap; }
  /* 侧栏宽度 184 → 244px（2026-08-01 规 5 改名同批）：三级菜单最长项「界面（梦羊马仓）运费汇总表」
     实测需 237px（13px 字宽 169 + l3 缩进 42 + 右内边距 10 + 左右外边距 16），
     184px 下被硬裁成「界面（梦羊马仓）运费」——看上去像另一个页面名。改名后名字更长，故一并放宽。
     宽度是**按实测最长项定的，不是拍脑袋**；将来再加更长的名字，走 .menu-item 的省略号 + title 兜底。 */
  :root { --sb-w:244px; --sb-cw:64px; --sb-bg:#1e293b; --sb-fg:#cbd5e1; --sb-accent:#165dff; --top-h:56px; }

  /* ===== 登录/注册页（照 fba LoginView 左右分栏） ===== */
  .login-wrap { position:fixed; inset:0; display:flex; z-index:2000; }
  .brand-panel { flex:1.15; background:linear-gradient(135deg,#0f172a 0%,#1e293b 55%,#28415e 100%); color:#e2e8f0; display:flex; align-items:center; justify-content:center; position:relative; overflow:hidden; }
  .brand-panel::after { content:''; position:absolute; width:420px; height:420px; border-radius:50%; background:radial-gradient(circle,rgba(22,93,255,.28),transparent 70%); top:-120px; right:-120px; }
  .brand-inner { max-width:400px; padding:0 40px; position:relative; z-index:1; }
  .brand-logo { width:52px; height:52px; border-radius:12px; margin-bottom:22px; display:block; }
  .brand-inner h1 { font-size:28px; margin:0 0 10px; color:#fff; }
  .brand-inner p { color:#94a3b8; margin:0 0 26px; }
  .brand-points { list-style:none; padding:0; margin:0; color:#cbd5e1; font-size:14px; }
  .brand-points li { padding:7px 0 7px 24px; position:relative; }
  .brand-points li::before { content:'✓'; position:absolute; left:0; color:var(--sb-accent); font-weight:700; }
  .login-panel { flex:1; background:#fff; display:flex; align-items:center; justify-content:center; }
  .login-box { width:340px; }
  .login-box h2 { margin:0 0 4px; color:#1d2129; }
  .login-switch { margin-top:14px; font-size:13px; color:#86909c; text-align:center; }
  .login-switch a { color:var(--sb-accent); cursor:pointer; }
  /* 已有 token 不等于应用已经可用：刷新时还要等账号、权限、菜单、店铺与列元数据一起回来。
     这层门控刻意独立于登录页和主布局——如果直接让主布局先出来，data() 的默认
     active=fund_raw 会拿空 meta/shops 画出一张「0 行」假空表，正是用户 2026-09-18 实拍。 */
  .boot-wrap { position:fixed; inset:0; z-index:2000; display:flex; align-items:center; justify-content:center;
               background:linear-gradient(135deg,#f7f9fc 0%,#eef3fa 100%); }
  .boot-card { width:390px; max-width:calc(100vw - 48px); box-sizing:border-box; padding:30px 32px;
               background:#fff; border:1px solid #e5e6eb; border-radius:12px;
               box-shadow:0 18px 55px rgba(15,23,42,.10); text-align:center; }
  .boot-logo { width:44px; height:44px; border-radius:10px; display:block; margin:0 auto 16px; }
  .boot-title { color:#1d2129; font-size:17px; font-weight:600; margin-bottom:8px; }
  .boot-desc { color:#86909c; font-size:13px; line-height:1.7; }
  .boot-actions { display:flex; justify-content:center; gap:10px; margin-top:18px; }
  @media (max-width: 760px) { .brand-panel { display:none; } }

  /* ===== 顶部模块条（照 Claude Design 稿：深色全宽，logo + 模块 tab + 用户；刻意不加 transition） ===== */
  .apptop { position:fixed; top:0; left:0; right:0; height:var(--top-h); background:var(--sb-bg); display:flex; align-items:center; gap:18px; padding:0 16px; z-index:200; }
  .apptop-brand { display:flex; align-items:center; gap:10px; color:#fff; font-weight:600; font-size:15px; white-space:nowrap; }
  .apptop-brand .dot { width:26px; height:26px; border-radius:7px; flex:none; display:block; }
  .apptop-mods { display:flex; align-items:stretch; height:100%; }
  .mod-tab { display:flex; align-items:center; gap:6px; padding:0 16px; cursor:pointer; font-size:14px; color:#94a3b8; border-bottom:3px solid transparent; border-top:3px solid transparent; user-select:none; }
  .mod-tab:hover { color:#fff; }
  .mod-tab.active { color:#fff; border-bottom-color:var(--sb-accent); }
  .apptop-user { margin-left:auto; }
  .user-chip { display:flex; align-items:center; gap:8px; cursor:pointer; color:#e2e8f0; padding:4px 8px; border-radius:6px; }
  .user-chip:hover { background:rgba(255,255,255,.08); }
  .avatar { width:30px; height:30px; border-radius:8px; background:var(--sb-accent); color:#fff; display:flex; align-items:center; justify-content:center; font-weight:600; flex:none; font-size:13px; }

  /* ===== 侧边栏（照设计稿浅色：分区标题 + 平台折叠组 + 圆角选中块；收缩 64px、刻意不加 transition 防大表 reflow） ===== */
  /* 收缩不加过渡动画：大表页面 width 动画会连续触发表格 reflow（用户实测"收缩很慢"），直接瞬时切换 */
  .sidebar { position:fixed; left:0; top:var(--top-h); bottom:0; width:var(--sb-w); background:#fff; border-right:1px solid #e5e6eb; color:#4e5969; display:flex; flex-direction:column; z-index:100; }
  .sidebar.collapsed { width:var(--sb-cw); }
  /* 侧栏拖宽手柄（2026-08-05 用户要求）：宽度存 localStorage，180~400px；收缩态不显示 */
  .sb-resize { position:absolute; top:0; right:-3px; width:7px; height:100%; cursor:col-resize; z-index:101; }
  .sb-resize:hover { background:rgba(22,93,255,.18); }
  .sb-menu { flex:1; overflow-y:auto; overflow-x:hidden; padding:8px 0 10px; }
  .sec-title { padding:16px 16px 6px; font-size:12px; color:#86909c; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  .menu-group { display:flex; align-items:center; gap:8px; padding:8px 10px; margin:2px 8px; border-radius:6px; cursor:pointer; font-size:13px; color:#4e5969; user-select:none; white-space:nowrap; overflow:hidden; }
  .menu-group:hover { color:#1d2129; background:#f2f3f5; }
  /* 🔴 `flex:none` + 标签自己截断（2026-08-13 探针实测）：分组名是 admin 可改的
     （管理 → 菜单显示名），改长一点就会把展开箭头顶出容器 —— 实测长名下箭头右边界
     超出 100px，而 `.menu-group` 是 overflow:hidden ⇒ 箭头**既看不见也点不到**，
     这一组看上去就是个不能展开的普通行，页面零报错。
     ⚠️ 省略号不能只写在 `.menu-group` 上：它是 flex 容器，文字在匿名 flex item 里，
     `text-overflow` 落不到那上面（`.menu-item` 那条能生效是因为它的文字确实是自己的行盒）。
     必须由**装标签的那个 span** 自己 `min-width:0` + 截断，箭头才有地方待。 */
  .menu-group > span:not(.brand-ico), .menu-sub > span {
    min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .menu-group .caret { margin-left:auto; color:#c9cdd4; flex:none; }
  .menu-group .caret.open { transform:rotate(180deg); }
  .menu-group.g-active { color:var(--sb-accent); }
  /* 菜单项超长时给省略号而不是硬裁（原来只有 overflow:hidden，「界面（梦羊马仓）运费账单」被切成
     「界面（梦羊马仓）运费」，看上去像是另一个页面名）。侧栏宽度已按最长项实测放宽，省略号是将来
     再加长名字时的兜底，配 title 悬停看全称。 */
  .menu-item { display:flex; align-items:center; gap:8px; padding:8px 10px; margin:2px 8px; border-radius:6px; cursor:pointer; font-size:14px; color:#4e5969; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  .menu-item.sub { padding-left:30px; font-size:13px; }
  .brand-ico { display:flex; align-items:center; flex:none; }
  .brand-ico svg { width:16px; height:16px; display:block; }
  .menu-sub { display:flex; align-items:center; gap:6px; padding:7px 10px 7px 28px; margin:1px 8px; border-radius:6px; cursor:pointer; font-size:12px; color:#86909c; user-select:none; white-space:nowrap; overflow:hidden; }
  .menu-sub:hover { color:#1d2129; background:#f2f3f5; }
  .menu-sub .caret { margin-left:auto; color:#c9cdd4; flex:none; }
  .menu-sub .caret.open { transform:rotate(180deg); }
  .menu-sub.s-active { color:var(--sb-accent); }
  .menu-item.l3 { padding-left:42px; font-size:13px; }
  .unm-badge { margin-left:6px; background:#f53f3f; color:#fff; border-radius:9px; font-size:11px; padding:0 6px; line-height:16px; display:inline-block; flex:none; }
  .menu-item:hover { color:#1d2129; background:#f2f3f5; }
  .menu-item.active { color:var(--sb-accent); background:#e8f3ff; font-weight:500; }
  .sidebar-footer { flex:none; border-top:1px solid #e5e6eb; padding:6px 8px; }
  .collapse-btn { text-align:center; cursor:pointer; color:#86909c; padding:6px; border-radius:6px; }
  .collapse-btn:hover { color:#1d2129; background:#f2f3f5; }

  /* ===== 主区域 ===== */
  .main-area { margin-left:var(--sb-w); margin-top:var(--top-h); height:calc(100vh - var(--top-h)); display:flex; flex-direction:column; min-height:0; background:#f7f8fa; }
  .main-area.collapsed { margin-left:var(--sb-cw); }
  /* ===== A 区页头（报表展示规范 规 2，2026-08-01）=====
     只放三样：报表名 / 一行口径芯片（点开进 F 区口径抽屉）/ 状态位。全部恒定单行。
     ⚠️ **高度刻意仍是 52px**：全站表格的 :scroll y 是 calc(100vh - Npx) 手算的，页头改高全都要重算（铁律 8）。
     旧写法把长口径整段塞进 a-tag，只能靠 white-space:normal 换行兜底 —— 2~3 行内容撑破 52px，
     标题被裁掉上半截（用户截图 3 就是这个）。2026-07-31 修的是同一根因的另一半（外壳被撑宽横滚），
     那次选择「允许换行」，这次改成「本来就只有一行」，故 overflow:hidden 可以放心加回来。 */
  .topbar { height:52px; flex:none; background:#fff; border-bottom:1px solid var(--color-border-2); display:flex; align-items:center; gap:12px; padding:0 20px; overflow:hidden; }
  .page-title { font-size:16px; font-weight:600; color:#1d2129; white-space:nowrap; flex:none; }
  .page-title .plat { font-weight:400; color:#86909c; }
  /* 口径芯片：一行截断，全文在抽屉。max-width + min-width:0 让它随窗口收缩而不是把外壳撑宽 */
  .cal-chip { flex:0 1 auto; min-width:0; max-width:52vw; display:inline-flex; align-items:center; gap:5px;
              background:#e8f3ff; color:#1a4fd6; border:1px solid #bedaff; border-radius:5px;
              padding:2px 9px; font-size:12px; line-height:1.7; cursor:pointer; }
  .cal-chip .t { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .cal-chip .more { flex:none; color:#165dff; font-weight:600; }
  .cal-chip:hover { background:#d4e8ff; }
  /* 状态位：唯一常驻的告警入口，点击直达待核对 tab。
     **全通过时不出绿色 pill**——那正是 2026-07 被否决的「恒绿标签＝虚假安全感」；
     「查过了而且是平的」这个证据在待核对 tab 里恒定列着（规 3），不需要在页头天天晃。 */
  .rv-pill { flex:none; margin-left:auto; cursor:pointer; border-radius:5px; padding:3px 10px;
             font-size:12px; font-weight:500; white-space:nowrap;
             background:#ffece8; border:1px solid #fdcdc5; color:#b71d1d; }
  .rv-pill.todo { background:#fff7e8; border-color:#ffcf8b; color:#7a4a00; }
  .rv-pill:hover { filter:brightness(0.97); }
  /* F 区口径抽屉：页面上全部长口径文案的唯一归宿（规 2「禁止游离灰字段落」） */
  .cal-sec { margin-bottom:20px; }
  .cal-sec h4 { margin:0 0 7px; font-size:13px; font-weight:600; color:#1d2129; }
  .cal-sec .cal-body { font-size:13px; line-height:1.9; color:#4e5969; word-break:break-word; }
  .content { flex:1; min-height:0; overflow:hidden; }


  /* ===== cig-in：单行化 textarea（澳洲项目删除后**唯一保留**的那一块，2026-09-09）=====
     🔴 模块 2026-09-01 迁去 au.aibuildr.cn、代码 09-09 物理删除，但**这个组件留着**：
        全站一百多处输入框在用它，而它顶着已退役模块的前缀 —— 按 `cig-` 前缀一扫就会
        被带走，表现是变成未注册组件 ⇒ Vue 当未知元素原样渲染 ⇒ 宽 0、看不见、打不了字，
        而 DOM 完整、console 零错误（那个从来没注册过的 search-box 组件是同一形状）。
        `verify_talent §40` 专门钉着「它还注册着」。
     ⚠️ 名字刻意不改：改前缀要同时动组件注册 + 全部用法 + 这几条 CSS，
        收益只是"名字好看"，而任何一处漏改都是上面那种静默失效。 */
  /* 🔴 **单行化 textarea 代替 input**（2026-08-27 第八轮，用户：那个很烦）——
     Chrome 密码管理器只认领 <input>，不认领 <textarea>。全站那个 `stampAutofill`
     （type=search / autocomplete=new-password / readonly-until-focus）2026-08-05 已被
     用户实拍**逐一证伪**，它还挂着只是无害兜底 —— 唯一有效的是换标签，这是结构性的。
     样式照 Arco small input 抄一份（灰底、无边框、聚焦转白 + 蓝框），肉眼看不出区别。 */
  .cig-in { display:block; width:100%; box-sizing:border-box; resize:none; overflow:hidden;
            white-space:pre; font-family:inherit; font-size:13px; line-height:20px;
            height:28px; padding:3px 8px; border:1px solid transparent; border-radius:2px;
            background:var(--color-fill-2, #f2f3f5); color:#1d2129; outline:none;
            transition:background-color .1s, border-color .1s; }
  .cig-in:hover:not(:disabled) { background:var(--color-fill-3, #e5e6eb); }
  .cig-in:focus { background:#fff; border-color:#165dff; }
  .cig-in:disabled { background:var(--color-fill-2, #f2f3f5); color:#c9cdd4; cursor:not-allowed; }
  .cig-in::placeholder { color:#c9cdd4; }
  /* mini：与 a-input size="mini" 对齐（列表里就地改那些格子） */
  .cig-in.mini { height:24px; line-height:16px; padding:3px 7px; font-size:12px; }
  .cig-in.right { text-align:right; }
  .cig-in.big { height:40px; line-height:30px; font-size:20px; font-weight:600; padding:4px 10px; }

  .cig-inw { position:relative; display:inline-block; vertical-align:middle; width:100%; }
  .cig-inx { position:absolute; right:6px; top:50%; transform:translateY(-50%); cursor:pointer;
             color:#c9cdd4; font-size:13px; line-height:1; width:14px; height:14px;
             display:flex; align-items:center; justify-content:center; border-radius:50%; }
  .cig-inx:hover { color:#4e5969; background:#e5e6eb; }
  /* ===== 列表页统一结构（照 fba：flex 链 min-height:0 + 表格卡片 + 外置分页栏） ===== */
  .page { height:100%; min-height:0; display:flex; flex-direction:column; padding:16px 20px 10px; box-sizing:border-box; }
  /* 取数配置是多卡片长页，交给页面本身自然纵向滚动；规则表只负责横向列宽。
     固定 flex 高度会把多条规则压成一行，内层又拿不到可滚高度。 */
  .tal-cfg-page { display:block; overflow-y:auto; overflow-x:hidden; }
  .tal-cfg-page > .table-card { height:auto; min-height:auto; overflow:visible; }
  .tal-rules-card { flex:none; }
  .tal-cfg-page .tal-rules-card > * { flex:0 0 auto; }
  .tal-cfg-page .tal-rules-card > .cf-rows { overflow-x:auto; overflow-y:visible; }
  /* 商务补数日清：这是运营读数面板，不是任务控制台。六个数字按“额度→在途→
     回执→候选池”排开，避免把“唤起已下发”或历史日志误读为“今日已经取完”。 */
  .tal-quota-grid { display:grid; grid-template-columns:repeat(auto-fit,minmax(290px,1fr)); gap:12px; }
  .tal-quota-card { min-width:0; padding:15px 16px 13px; background:linear-gradient(145deg,#fff 0%,#f7faff 100%);
                     border:1px solid #dbe8ff; border-radius:10px; box-shadow:0 3px 12px rgba(22,93,255,.045); }
  .tal-quota-head { display:flex; align-items:center; gap:8px; min-width:0; }
  .tal-quota-head b { font-size:15px; color:#1d2129; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .tal-quota-state { margin-left:auto; flex:none; padding:2px 7px; border-radius:10px; font-size:11px; line-height:18px;
                     color:#165dff; background:#e8f3ff; }
  .tal-quota-state.warn { color:#9a5b00; background:#fff3d9; }
  .tal-quota-state.bad { color:#c92a2a; background:#fff0f0; }
  .tal-quota-hero { display:flex; align-items:end; gap:8px; margin:16px 0 7px; }
  .tal-quota-hero span { color:#4e5969; font-size:12px; padding-bottom:4px; }
  .tal-quota-hero strong { color:#165dff; font-family:ui-rounded,"PingFang SC",sans-serif; font-size:34px; line-height:1; letter-spacing:-1px; }
  .tal-quota-hero em { color:#86909c; font-size:12px; font-style:normal; padding-bottom:4px; }
  .tal-quota-meter { height:6px; overflow:hidden; border-radius:6px; background:#e8f0ff; }
  .tal-quota-meter > i { display:block; height:100%; border-radius:inherit; background:linear-gradient(90deg,#165dff,#4080ff); transition:width .2s ease; }
  .tal-quota-counts { display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); margin-top:13px; border-top:1px solid #edf2fa; border-bottom:1px solid #edf2fa; }
  .tal-quota-counts span { min-width:0; padding:9px 5px 8px 0; display:flex; flex-direction:column; gap:2px; color:#86909c; font-size:11px; }
  .tal-quota-counts b { color:#1d2129; font-size:16px; line-height:1.2; }
  .tal-quota-counts .ok b { color:#00a870; }.tal-quota-counts .fail b { color:#f53f3f; }
  .tal-quota-foot { display:grid; grid-template-columns:1fr auto; gap:10px; margin-top:11px; color:#4e5969; font-size:12px; line-height:1.55; }
  .tal-quota-foot strong { color:#1d2129; }.tal-quota-foot i { color:#86909c; font-style:normal; text-align:right; }
  .tal-quota-explain { margin-top:10px; padding:7px 9px; border-radius:7px; background:#eef5ff; color:#165dff; font-size:12px; line-height:1.45; }
  .tal-quota-explain.warn { background:#fff7e8; color:#9a5b00; }.tal-quota-explain.bad { background:#fff0f0; color:#c92a2a; }
  .tal-quota-limit-edit { display:flex; align-items:center; gap:7px; margin-top:12px; padding-top:11px; border-top:1px dashed #dbe8ff; color:#4e5969; font-size:12px; }
  .tal-quota-limit-edit label { white-space:nowrap; }.tal-quota-limit-edit input { width:68px; height:27px; box-sizing:border-box; border:1px solid #c9d8ef; border-radius:5px; padding:0 7px; color:#1d2129; background:#fff; appearance:textfield; -moz-appearance:textfield; }.tal-quota-limit-edit input::-webkit-inner-spin-button,.tal-quota-limit-edit input::-webkit-outer-spin-button { -webkit-appearance:none; margin:0; }
  /* 历史事件可到 90 天；固定高度 page 若不自带纵滚，页码和底部记录会不可达。 */
  .tal-history-page { overflow-y:auto; overflow-x:hidden; }.tal-history-page > .table-card { flex:none; min-height:auto; }
  .tal-history-filters { display:flex; flex-wrap:wrap; align-items:center; gap:10px; margin-bottom:13px; }
  .tal-history-summary { display:flex; flex-wrap:wrap; gap:20px; padding:10px 12px; margin-bottom:12px; border-radius:8px; background:#f7faff; color:#4e5969; font-size:12px; }.tal-history-summary b { margin-right:4px; color:#165dff; font-size:17px; }.tal-history-summary .ok b { color:#00a870; }.tal-history-summary .fail b { color:#f53f3f; }
  .tal-history-table,.tal-plugin-pending,.tal-plugin-history { min-width:980px; border:1px solid var(--cf-page); border-radius:var(--r-lg); overflow:hidden; }
  .tal-history-head,.tal-history-row { display:grid; grid-template-columns:180px 205px 126px minmax(220px,1.1fr) minmax(160px,.8fr) 84px; gap:12px; align-items:start; padding:10px 12px; }
  .tal-history-head { background:var(--cf-page); color:#4e5969; font-size:12px; font-weight:600; }.tal-history-row { border-top:1px solid var(--cf-page); }.tal-history-row:hover { background:#fafcff; }
  .tal-plugin-ledger-row { display:grid; grid-template-columns:175px minmax(300px,1fr) 130px minmax(190px,.8fr); gap:12px; align-items:start; padding:9px 12px; border-top:1px solid var(--cf-page); font-size:12px; }.tal-plugin-pending .tal-plugin-ledger-row:first-child,.tal-plugin-history section:first-child .tal-plugin-day + .tal-plugin-ledger-row { border-top:0; }.tal-plugin-day { padding:8px 12px; background:var(--cf-page); font-weight:600; font-size:12px; }.tal-plugin-history { margin-top:12px; }
  @media (max-width:760px) { .tal-quota-foot { grid-template-columns:1fr; }.tal-quota-foot i { text-align:left; }.tal-history-summary { gap:12px; } }
  .muted { color:#86909c; font-size:12px; }
  /* 占位破折号 / 「还没有」那一类。🔴 **必须真有这条规则**：只写 class 不写规则时
     它会按默认样式渲染成加粗黑字，读起来像一个真值（`verify_dead_class` 抓的就是这个）。
     ⚠️ 2026-09-09 从已删除的澳洲项目 CSS 块里搬出来 —— 用它的是 API Key 配置页，
     跟那个模块没关系，只是当初写在了那一段里。 */
  .dash { color:#c9cdd4; }
  /* 店铺横向 tab（无汇总，必选一个店） */
  .shop-tabs { flex:none; display:flex; align-items:center; gap:14px; margin-bottom:10px; flex-wrap:wrap; }
  /* 界面运费账单：费用来源分类 tab（复刻 Excel sheet 分组配色：黄=快递账单，绿=异常费用） */
  .src-tabs { display:flex; align-items:center; gap:6px; flex-wrap:wrap; }
  .src-group { color:#86909c; font-size:12px; margin:0 2px 0 10px; }
  .src-tab { cursor:pointer; user-select:none; padding:4px 14px; border-radius:4px; font-size:13px;
             border:1px solid var(--color-border-2); background:#fff; color:#4e5969; }
  .src-tab.kd { background:#fffbe6; border-color:#ffe58f; }
  .src-tab.yc { background:#f0faf0; border-color:#b7eb8f; }
  .src-tab.nf { background:#f0f7ff; border-color:#a8c9f5; }  /* 订单表新表头店铺组（蓝） */
  .src-tab.on { color:#165dff; border-color:#165dff; font-weight:600; box-shadow:0 0 0 1px #165dff inset; }
  .filterbar { flex:none; background:#fff; border:1px solid var(--color-border-2); border-radius:6px; padding:12px 14px; margin-bottom:12px; display:flex; gap:10px; align-items:center; flex-wrap:wrap; }
  .filter-panel { flex:none; background:#fff; border:1px solid var(--color-border-2); border-radius:6px; padding:14px; margin:-4px 0 12px; display:flex; gap:12px; align-items:center; flex-wrap:wrap; box-shadow:0 2px 8px rgba(0,0,0,.06); }
  .table-card { position:relative; flex:1; min-height:0; display:flex; flex-direction:column; overflow:hidden; background:#fff; border:1px solid var(--color-border-2); border-radius:8px; box-shadow:0 1px 3px rgba(0,0,0,.04); }
  /* 切页骨架屏：切到还没数据的表时铺动效骨架条代替空白转圈（loading 且当前无行时显示，盖住 Arco 的空白+转圈） */
  .tbl-skel { position:absolute; left:0; right:0; top:41px; bottom:0; z-index:20; background:#fff; padding:10px 16px 0; overflow:hidden; }
  .tbl-skel::before { content:''; display:block; height:100%; background-image: repeating-linear-gradient(to bottom, #f2f3f5 0 22px, transparent 22px 52px); animation: skelPulse 1.2s ease-in-out infinite; }
  @keyframes skelPulse { 0%,100%{opacity:.5} 50%{opacity:1} }
  /* 商品图工厂（if-card 仍被 密钥/设置/运维 页使用） */
  /* 打法库正文预览（2026-09-10）。起名前 grep 过 .pb-body 未被占（铁律 10⑥）。 */
  .pb-body { margin:8px 0 0; padding:8px 10px; background:var(--color-fill-1,#f7f8fa);
             border-radius:4px; font-size:12.5px; line-height:1.6; white-space:pre-wrap;
             max-height:190px; overflow:auto; font-family:inherit; }
  .if-card { background:#fff; border:1px solid var(--color-border-2); border-radius:8px; padding:16px; margin-bottom:12px; }
  /* ===== 图片文案翻译 if2-（2026-08-04 Claude Design 稿：方角+细边线版式，刻意不用 Arco 组件） ===== */
  /* 设计稿自带全局 border-box，BL 没有——不带这条，flex 0 0 164px 的列加 padding 后实际占 184px，
     AI 结果列直接横向溢出卡片（2026-08-04 用户截图实证）。scoped 到 if2-page 不动 Arco 布局。 */
  .if2-page, .if2-page *, .if2-page *::before, .if2-page *::after { box-sizing: border-box; }
  .if2-page { font-size:13px; color:#1c1917; }
  /* 🔴 批量生成两页：**子元素一律不许收缩**（2026-08-15 用户实测「上下滑坏了 + 槽位没地方传图」）。
     `.page` 是 `display:flex; flex-direction:column; height:100%`，子元素默认 `flex-shrink:1`；
     内容超过一屏时它们**被按比例压扁而不是溢出** ⇒ 页面 scrollHeight == clientHeight
     ⇒ **滚不动**；而被压扁的那张卡若还带 `overflow:hidden`，里面的东西就直接**看不见了**
     （实测：任务行卡高 29px、内容 349px，槽位上传格连同「▤ 库」按钮整块被裁掉，
     表现成"槽位版没地方上传图片"——两个 bug 同一个根因）。
     ⚠️ 用 `> *` 的通配规则而不是逐个写 inline：以后往这两页加一个新区块，
     不会因为忘了写 flex-shrink 又复发一次。同族坑见 CLAUDE.md 铁律 10⑤。 */
  .if2-batpage > * { flex: 0 0 auto; }
  /* 任务行版式（2026-08-15 对齐 AITool）：输入在左、→、产物在右。
     ⚠️ `align-items:flex-start` 而不是 center：行高随提示词/槽位数变化，center 会让
     序号与产物格各自"浮"在中间，视线对不上。 */
  .if2-batrow { display:flex; gap:11px; align-items:flex-start; padding:12px;
                border-bottom:1px solid #f5f4f2; }
  .if2-batrow:hover { background:#fafaf9; }
  .if2-batrow-info { display:flex; align-items:center; gap:6px; flex:0 0 auto; padding-top:2px; }
  .if2-batrow-refs { display:flex; gap:7px; flex-wrap:wrap; flex:0 0 auto; max-width:420px; }
  .if2-batrow-main { flex:1; min-width:180px; }
  /* 箭头竖直居中：行高随提示词行数/槽位数变，写死 padding-top 只在某一种行高下对 */
  .if2-batrow-arrow { flex:0 0 auto; color:#c8c4c0; font-size:15px; align-self:center; }
  .if2-batrow-st { flex:0 0 92px; padding-top:2px; }
  .if2-batrow-act { flex:0 0 auto; display:flex; gap:3px; padding-top:2px; }
  .if2-batdot { width:6px; height:6px; border-radius:50%; display:inline-block; }
  /* 图格＝**一个整块**：外面一圈边框，里面上下两段（上＝图/上传区，下＝标签条）。
     🔴 上半段用**固定 px**不用 `calc(100% - 22px)`：`img-drop` 的 inline 变体套了两层
     `.imgdrop > .imgdrop-inline`，两层都没有高度 ⇒ 百分比算在 auto 上 ⇒ 标签条与素材库
     入口会**流到格子外面**去（用户实拍到的：三块各自为政、素材库条飘在外面）。
     所以这里也顺手把那两层撑成块级，让插槽内容规规矩矩待在格子里。 */
  .if2-batcell { position:relative; width:110px; flex:0 0 110px; border:1px solid #d6d3d1;
                 background:#fff; overflow:hidden; display:flex; flex-direction:column; }
  .if2-batcell .imgdrop, .if2-batcell .imgdrop-inline { display:block; }
  /* ⌘V 角标默认是 `top:-8px; right:-6px`（**戳出框外**，给大一点的上传区用的）。
     图格只有 110px 且 `overflow:hidden`，它会被裁掉半个（用户实拍）。
     这里把它收进框内——⚠️ 只在图格里改，不动 `.imgdrop.aim::after` 本体：
     那个类全站十几处上传位都在用，改它就是一次动全部。
     ⚠️ 不与 `.if2-batcell-x`（✕）撞：那个只在**有图**时渲染，而角标只在空位的 img-drop 上。 */
  .if2-batcell .imgdrop.aim::after { top:3px; right:3px; }
  .if2-batcell-body { position:relative; height:86px; background:#fafaf9; }
  .if2-batcell-res { width:100px; flex:0 0 100px; }
  .if2-batcell-res .if2-batcell-body { height:100px; }
  .if2-batcell-img { width:100%; height:86px; object-fit:cover; cursor:zoom-in; display:block; }
  .if2-batcell-res .if2-batcell-img { height:100px; }
  .if2-batcell-empty { height:86px; box-sizing:border-box; display:flex; flex-direction:column;
                       align-items:center; justify-content:center; gap:3px; font-size:10.5px;
                       color:#a8a29e; cursor:pointer; text-align:center; padding:0 4px;
                       background:repeating-linear-gradient(45deg,#fcfcfb 0 5px,#f7f6f4 5px 10px); }
  .if2-batcell-empty:hover { background:#f0f7f2; color:#1f7a37; }
  .if2-batcell-off { cursor:default; background:#fafaf9; }
  .if2-batcell-off:hover { background:#fafaf9; color:#a8a29e; }
  .if2-batcell-up { font-size:16px; line-height:1; }
  /* 底栏：标签 + 素材库入口在**同一条**里，不再是一个绝对定位飘着的条 */
  .if2-batcell-foot { height:22px; border-top:1px solid #eeeceb; display:flex; align-items:center;
                      gap:2px; padding:0 3px; background:#fff; }
  .if2-batcell-cap { flex:1; min-width:0; font-size:10px; color:#78716c; white-space:nowrap;
                     overflow:hidden; text-overflow:ellipsis; }
  .if2-batcell-lib { flex:0 0 auto; width:17px; height:17px; display:flex; align-items:center;
                     justify-content:center; font-size:10px; color:#78716c; cursor:pointer; }
  .if2-batcell-lib:hover { background:#f0efed; color:#1c1917; }
  .if2-batcell-x { position:absolute; right:2px; top:2px; width:16px; height:16px; background:#a92a1f;
                   color:#fff; font-size:10px; display:flex; align-items:center;
                   justify-content:center; cursor:pointer; }
  .if2-batcell-mk { position:absolute; left:2px; top:2px; height:16px; padding:0 4px;
                    background:rgba(31,122,55,.9); color:#fff; font-size:9px; display:flex;
                    align-items:center; cursor:pointer; }
  .if2-batcell-badge { position:absolute; left:2px; bottom:2px; background:rgba(194,98,10,.9);
                       color:#fff; font-size:9px; padding:0 4px; }
  /* 斜纹占位：产物还没出来时占住这个位子，人才知道图会出在哪儿 */
  .if2-batcell-hatch { width:100%; height:100%;
                       background:repeating-linear-gradient(45deg,#fafaf9 0 6px,#f0efed 6px 12px); }
  .if2-batcell-run { width:100%; height:100%;
                     background:linear-gradient(90deg,#f5f4f2 25%,#eceae8 37%,#f5f4f2 63%);
                     background-size:400% 100%; animation:if2batshim 1.4s ease infinite; }
  @keyframes if2batshim { 0% { background-position:100% 50%; } 100% { background-position:0 50%; } }
  .if2-batcell-fail { width:100%; height:100%; display:flex; align-items:center;
                      justify-content:center; color:#a92a1f; font-size:20px; background:#fdf4f2; }
  .if2-batcell-ok { position:absolute; right:3px; bottom:3px; width:15px; height:15px;
                    border-radius:50%; background:#fff; color:#1f7a37; font-size:11px;
                    display:flex; align-items:center; justify-content:center; }
  /* 槽位定义卡（照 AITool：编号徽标 + 名字 + 描述 + 共N张 + 批量上传） */
  .if2-batslot { border:2px dashed #b9ddc2; background:#f5faf6; padding:8px 10px;
                 min-width:172px; display:flex; flex-direction:column; gap:5px; }
  /* 历史提示词浮窗（2026-08-15 用户："用浮窗，简单一点"）。
     面板贴着触发器出现：壳 position:relative + 面板 absolute，不算坐标
     （算坐标那套在滚动/父容器 overflow 变化时必错位）。 */
  .if2-phwrap { position:relative; display:inline-flex; }
  .if2-phbtn { height:22px; padding:0 8px; font-size:10.5px; gap:3px; }
  .if2-phn { margin-left:2px; background:#1f7a37; color:#fff; font-size:9.5px; line-height:1;
             padding:2px 4px; border-radius:7px; font-weight:700; }
  .if2-phpop { position:absolute; top:26px; left:0; z-index:1400; width:330px;
               background:#fff; border:1px solid #d6d3d1; box-shadow:0 6px 20px rgba(28,25,23,.14); }
  .if2-phpop-r { left:auto; right:0; }
  .if2-phpop-h { display:flex; align-items:center; gap:6px; padding:7px 10px;
                 border-bottom:1px solid #f0efed; font-size:12px; font-weight:700; }
  .if2-phx { font-size:10.5px; font-weight:400; color:#78716c; cursor:pointer;
             border:1px solid #e7e5e4; padding:1px 6px; }
  .if2-phx:hover { background:#f5f4f2; color:#1c1917; }
  .if2-phpop-b { max-height:280px; overflow:auto; }
  .if2-phpop-f { padding:6px 10px; border-top:1px solid #f0efed; font-size:10.5px; color:#78716c; }
  .if2-phrow { display:flex; align-items:center; gap:7px; padding:6px 10px; cursor:pointer; }
  .if2-phrow:hover { background:#f0f7f2; }
  .if2-batslot-no { width:17px; height:17px; border-radius:50%; background:#1f7a37; color:#fff;
                    font-size:10.5px; display:flex; align-items:center; justify-content:center;
                    flex:0 0 auto; }
  .if2-mono { font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace; }
  .if2-head { display:flex; align-items:flex-end; justify-content:space-between; gap:20px; margin-bottom:14px; }
  .if2-title { font-size:19px; font-weight:700; letter-spacing:-.01em; }
  .if2-sub { font-size:12.5px; color:#57534e; margin-top:5px; }
  .if2-card { background:#fff; border:1px solid #d6d3d1; }
  .if2-btn { height:34px; padding:0 16px; border:1px solid #d6d3d1; background:#fff; color:#44403c; font-size:12.5px; font-weight:600; display:inline-flex; align-items:center; gap:7px; cursor:pointer; user-select:none; white-space:nowrap; }
  .if2-btn:hover { border-color:#1c1917; background:#fafaf9; }
  .if2-btn-pri { background:#1e5f9e; border-color:#12456f; color:#fff; }
  .if2-btn-pri:hover { background:#12456f; border-color:#12456f; }
  .if2-btn-dis { background:#f5f5f4 !important; border-color:#e7e5e4 !important; color:#a8a29e !important; cursor:not-allowed !important; }
  .if2-act { height:24px; padding:0 8px; border:1px solid #d6d3d1; background:#fff; color:#44403c; font-size:11.5px; display:inline-flex; align-items:center; cursor:pointer; user-select:none; white-space:nowrap; }
  .if2-act:hover { border-color:#1c1917; }
  /* 列表行的图标操作按钮（2026-08-10）。为什么要自己写一套而不是直接用 a-table 那套：
     Arco 的 text 按钮配色写在 `.table-card .arco-table-td` 选择器里（见本文件 ~288 行），
     而 if2 各列表页是**自绘 .if2-card**，选择器根本落不到，直接搬过来会是一片默认蓝。
     ⚠️ 等「批量任务」改成 a-table（需求③）后，这套可以连同 .if2-jrow 一起退役。 */
  .if2-ico { width:26px; height:24px; display:inline-flex; align-items:center; justify-content:center;
    border:1px solid transparent; color:#78716c; font-size:14px; cursor:pointer; user-select:none; }
  .if2-ico:hover { color:#1c1917; background:#f5f5f4; border-color:#d6d3d1; }
  .if2-ico-danger { color:#b0776f; }
  .if2-ico-danger:hover { color:#a92a1f; background:#fdf1f0; border-color:#e0aca7; }
  /* 裁切工作区（2026-08-08）。棋盘底＝"这是画布不是图"，否则浅色产物图与白底分不清边界 */
  .if2-cropstage { flex:1; min-width:0; position:relative; overflow:hidden; background:#44403c;
    background-image:linear-gradient(45deg,#4c4844 25%,transparent 25%),linear-gradient(-45deg,#4c4844 25%,transparent 25%),linear-gradient(45deg,transparent 75%,#4c4844 75%),linear-gradient(-45deg,transparent 75%,#4c4844 75%);
    background-size:18px 18px; background-position:0 0,0 9px,9px -9px,-9px 0; touch-action:none; user-select:none; }
  .if2-cropframe { position:absolute; outline-style:solid; outline-color:#fff; cursor:move; box-shadow:0 0 0 9999px rgba(0,0,0,.55); }
  .if2-cropgrip { position:absolute; background:#fff; border-style:solid; border-color:#44403c; box-sizing:border-box; }
  .if2-cropthird { position:absolute; background:rgba(255,255,255,.35); pointer-events:none; }
  /* 放大镜：1:1 背景 + 十字准星。pointer-events:none 免得它把光标从把手上抢走 */
  .if2-croploupe { position:absolute; width:150px; height:150px; border:2px solid #fff; pointer-events:none;
    box-shadow:0 6px 20px rgba(0,0,0,.45); background-repeat:no-repeat; z-index:5; }
  .if2-croploupe::after { content:''; position:absolute; inset:0; opacity:.85;
    background:linear-gradient(#fff,#fff) center/1px 100% no-repeat,linear-gradient(#fff,#fff) center/100% 1px no-repeat; }
  .if2-croploupe-tag { position:absolute; left:0; bottom:-20px; background:#1c1917; color:#fff; font-size:10.5px; padding:1px 6px; white-space:nowrap; }
  .if2-cropzoom { position:absolute; right:14px; bottom:9px; display:flex; align-items:center; gap:6px; background:rgba(28,25,23,.86); padding:6px 8px; z-index:6; }
  .if2-cropzb { width:26px; height:24px; display:flex; align-items:center; justify-content:center; background:#fff; border:1px solid #57534e; cursor:pointer; font-size:13px; }
  .if2-cropzb:hover { background:#f5f5f4; }
  .if2-cropkbd { font-size:10.5px; border:1px solid #d6d3d1; padding:0 4px; background:#fafaf9; }
  /* ---- 产物工作台（2026-08-09）---- */
  /* 覆盖层在**舞台坐标系**里，不随图层缩放：遮罩的 9999px 才是真的 9999px（见模板处注释）。
     它自己 pointer-events:none，只让里面的框/把手接事件，免得整层挡住画布的平移拖拽。 */
  .if2-wbolay { position:absolute; inset:0; pointer-events:none; }
  .if2-wbolay > * { pointer-events:auto; }
  .if2-wbedge { position:absolute; }                 /* 整条边都是热区，不用去对那个小方块 */
  .if2-wbmark { position:absolute; border:1.5px solid #1e5f9e; background:rgba(30,95,158,.20); }
  .if2-wbmark span { position:absolute; left:2px; top:2px; font-size:10px; font-weight:700; background:#1e5f9e; color:#fff; padding:0 4px; }
  .if2-wbmask { position:absolute; background:rgba(28,25,23,.6); outline:1px dashed #fff; }
  /* 加字（2026-08-10）：屏幕上这一层只是**所见即所得的预览**，真正的成品由 canvas 按
     原始像素重画一遍（if2WbTextApply）。两处都从同一份 texts 算，字号都按图宽百分比。 */
  .if2-wbtext { position:absolute; white-space:pre; cursor:move; line-height:1.25; user-select:none;
    transform:translateY(-50%); }
  .if2-wbtext-sel { outline:1px dashed #1e5f9e; outline-offset:2px; }
  .if2-wbhint { position:absolute; left:14px; bottom:9px; z-index:6; background:rgba(28,25,23,.82); color:#e7e5e4; font-size:11px; padding:5px 9px; max-width:58%; }
  .if2-wbpanel { border:1px solid #e7e5e4; background:#fafaf9; padding:10px; }
  .if2-wbchip { height:24px; padding:0 8px; border:1px solid #b9d3e8; background:#eaf2f9; color:#12456f; font-size:11px; display:inline-flex; align-items:center; gap:5px; cursor:pointer; }
  .if2-wbchip-o { border-color:#e6b781; background:#fdf7f0; color:#8a5a1f; }
  .if2-wbchip i { font-style:normal; opacity:.55; }
  .if2-wbchip i:hover { opacity:1; }
  .if2-wbref { position:relative; border-right:1px solid #e7e5e4; background:#fafaf9; padding:12px; display:flex; flex-direction:column; gap:9px; overflow:auto; }
  .if2-wbref-fold { padding:10px 4px; align-items:center; overflow:hidden; }
  .if2-wbref-fold > *:not(.if2-act) { display:none; }
  /* 拖宽手柄：照全站侧栏 .sb-resize 的成法（7px、col-resize、hover 才显色、宽度存 localStorage） */
  .if2-wbref-rs { position:absolute; top:0; right:-3px; width:7px; height:100%; cursor:col-resize; z-index:9; }
  .if2-wbref-rs:hover { background:rgba(30,95,158,.22); }
  .if2-wbrefbox { position:relative; width:100%; aspect-ratio:1; background:#fff; border:1px solid #d6d3d1; cursor:crosshair; touch-action:none; user-select:none; }
  .if2-wbrefmark { position:absolute; border:1.5px solid #c2620a; background:rgba(194,98,10,.18); }
  .if2-wbrefmark span { position:absolute; left:2px; top:2px; font-size:10px; font-weight:700; background:#c2620a; color:#fff; padding:0 4px; }
  .if2-tag { display:inline-flex; align-items:center; justify-content:center; height:22px; padding:0 8px; font-size:11.5px; font-weight:600; border:1px solid; white-space:nowrap; }
  .if2-input { border:1px solid #d6d3d1; outline:none; font-size:12.5px; padding:5px 7px; background:#fff; color:#1c1917; width:100%; }
  .if2-input:focus { border-color:#1e5f9e; }
  .if2-input:disabled { background:#fafaf9; color:#78716c; }
  /* 单行化 textarea（2026-08-05）：Chrome 密码管理器只认领 input、不认领 textarea——
     readonly/new-password/type=search 全被新版 Chrome 无视后的结构性根治。配 wrap="off" + 回车拦截。 */
  .if2-ta1 { display:block; height:30px; line-height:18px; resize:none; overflow:hidden; white-space:pre; font-family:inherit; }
  .if2-glossary-grid { display:flex; gap:10px; align-items:end; flex-wrap:wrap; }
  .if2-glossary-field { display:flex; flex-direction:column; gap:5px; min-width:150px; flex:1; }
  .if2-glossary-field label { font-size:11px; font-weight:600; color:#57534e; }
  .if2-glossary-table { width:100%; min-width:760px; border-collapse:collapse; }
  .if2-glossary-table th { text-align:left; font-size:11px; color:#78716c; font-weight:600; background:#f5f5f4; }
  .if2-glossary-table th, .if2-glossary-table td { padding:11px 14px; border-bottom:1px solid #e7e5e4; vertical-align:middle; }
  .if2-glossary-table tr:last-child td { border-bottom:0; }
  .if2-spin { width:14px; height:14px; border:2px solid #e7e5e4; border-top-color:#1e5f9e; border-radius:50%; animation:if2spin .8s linear infinite; }
  @keyframes if2spin { to { transform:rotate(360deg); } }
  .if2-bar { height:100%; background:#1e5f9e; background-image:linear-gradient(105deg,rgba(255,255,255,.34) 25%,transparent 25% 50%,rgba(255,255,255,.34) 50% 75%,transparent 75%); background-size:12px 12px; animation:if2flow .9s linear infinite; transition:width .5s linear; }
  @keyframes if2flow { from { background-position:0 0; } to { background-position:24px 0; } }
  /* 8 列：任务号 / 原图 / 底板 / 状态 / 进度 / 发起人 / 创建时间 / 操作。
     「底板」列 2026-08-05 加在原图与状态之间——套哪张底板决定成品长什么样，属于任务的身份信息，
     摆在原图旁边才能一眼横向对比"这批用的是米色、那批是浅紫"。素材库用 .if2-mrow 覆盖本行，不受影响。 */
  /* 末两列 2026-08-10 由 100/168 调成 108/148：操作改图标后 5 个 ≈142px 装得下，
     省下的宽度还给创建时间（`MM-DD HH:mm` 11 字符 mono ≈ 77px，原先 100px 本来够用，
     被溢出的操作列压住而已）。⚠️ 改这行务必同时数一遍上面的表头格子数，8 个不能变 */
  .if2-jrow { display:grid; grid-template-columns:170px 1fr 112px 96px 150px 74px 108px 148px; align-items:center; gap:12px; padding:11px 14px; }
  .if2-jhead { padding:9px 14px; border-bottom:1px solid #1c1917; background:#fafaf9; font-size:11.5px; font-weight:700; color:#57534e; }
  .if2-jline { border-bottom:1px solid #f0efed; cursor:pointer; }
  .if2-jline:hover { background:#fafaf9; }
  /* 素材库（2026-08-05）：行栅格与弹窗。沿用同一套 stone 色板与直角边框，不引入新视觉语言 */
  /* 2026-10-13 行首加两列（搜索/标签/分页那批）：序号 36px + 勾选 34px。
     勾选控件只在 canEdit 时渲染；列始终保留，非编辑账号的名称/状态不会错位 */
  .if2-mrow { grid-template-columns:36px 34px 62px minmax(180px,1fr) 96px 96px 70px 80px 110px 96px 104px; min-width:1220px; }   /* 创建人独立列，窄屏横向滚动，名称与状态不挤压 */
  .if2-mask { position:fixed; inset:0; background:rgba(28,25,23,.72); z-index:1200; display:flex; align-items:center; justify-content:center; padding:32px; }
  .if2-modal { background:#fff; border:1px solid #1c1917; display:flex; flex-direction:column; max-height:92vh; }
  .if2-modal-h { padding:12px 16px; border-bottom:1px solid #1c1917; background:#fafaf9; font-size:13.5px; font-weight:700; color:#1c1917; }
  .if2-modal-f { padding:12px 16px; border-top:1px solid #e7e5e4; background:#fafaf9; display:flex; justify-content:flex-end; gap:8px; }
  .if2-ghead { display:flex; background:#fafaf9; border-bottom:1px solid #1c1917; font-size:11.5px; font-weight:600; color:#57534e; }
  .if2-grow { display:flex; border-bottom:1px solid #d6d3d1; align-items:stretch; }
  .if2-crow { display:grid; grid-template-columns:96px 1fr 1.15fr .9fr 96px; border-bottom:1px solid #f5f5f4; align-items:stretch; }
  .if2-num { width:18px; height:18px; flex:0 0 18px; border:1px solid #b9d3e8; background:#eaf2f9; color:#1e5f9e; font-size:10.5px; font-weight:600; display:inline-flex; align-items:center; justify-content:center; }
  .table-card .arco-table { flex:1; min-height:0; width:100%; }
  .table-card .arco-table .arco-table-th { background:#f7f8fa; font-weight:600; white-space:nowrap; }
  .pagination-bar { flex:none; display:flex; align-items:center; justify-content:space-between; gap:12px; padding:9px 14px; border-top:1px solid var(--color-border-2); background:#fafbfc; font-size:13px; color:#4e5969; flex-wrap:wrap; }
  /* 财务 MCP 令牌页（2026-08-25，PRD §5.32）。类名前缀 mcp- 起名前已 grep 确认未被占用
     （铁律 10⑥：同名 class 后写的赢，会把别的模块的样式静默套到你的元素上）。 */
  /* 🔴 `.table-card` 自带 `flex:1 1 0%` + `overflow:hidden` —— 它是给**单表页**设计的
     （一个表撑满剩余高度）。本页放了**两张**卡，于是两张各分一半，MCP 那张的表格被压成
     7px 再被 overflow 裁掉：数据渲染出来了、DOM 完整、断言全绿，**只有截图上看得出**。
     这两张卡的高度应当由内容决定，故 flex:none。⚠️ 不改全局 .table-card，别的页面靠它撑满。 */
  /* 🔴 **这一页的布局模型与全站其它页不同**：别的页是「一张表撑满剩余高度、自己不滚」，
     所以 `.page` 是 `overflow:visible` + `.table-card` 是 `flex:1`。
     本页是「多块堆叠」（说明 + 两张表 + 配置片段），于是踩了同一族的三个坑：
       ① 两张 table-card 各分一半高度、第二张的表被压成 7px 再被 overflow 裁掉；
       ② alert 被 flex-shrink 压扁，101px 的内容只显示 44px；
       ③ 内容总高 870 > 可视 791，而 .page 不滚 ⇒ 底部 79px 看不见**也滚不到**。
     三个都是 DOM 完整、文字都在、console 零错误、断言全绿 —— **只有截图上看得出**。
     ⇒ 本页显式：自己能滚 + 里面的块都不压缩。⚠️ 不改全局 .page / .table-card。 */
  /* 复合页（表 + 参考卡）必须自己能滚：`.page` 默认 overflow:visible，内容一长
     下半截就**够不着**，而 DOM 完整、零报错（技能包页 2026-09-01 栽过一次，
     那一页 2026-09-10 已随技能包退役，规矩留给 `.mcp-page`）。 */
  .mcp-page { overflow-y:auto; }
  .skl-card { flex:none; }
  /* 令牌表按内容长、由页面滚：给它 flex:1 的话，下面那张 506px 的参考卡是定高的，
     被啃的永远是这张不定高的 —— 20 枚令牌时实测被压成 175px（≈2 行可见），
     而页面滚不动、DOM 完整、零报错（铁律 10⑤ 的竖向版）。
     ⛔ 别改成 min-height：那会让令牌只有一两枚时也凭空多一段滚动。 */
  .mcp-tkcard { flex:none; }
  /* 🔴 **签发成功那条 alert 也必须 flex:none**（2026-09-02 本地实测抓到）。
     上面那段注释里第 ② 条写的就是它（"alert 被 flex-shrink 压扁，101px 的内容只显示 44px"），
     而**这一行从来没写下来** —— 只写了 `.skl-card` 与 `.mcp-tkcard` 两条。
     文档写了不等于实现了；页面一长它就发作，实测 379px 的内容被压成 **32px**
     （Arco 的 alert 自带 overflow:hidden ⇒ min-content 高度是 0，能一路压到只剩标题行）。
     🔴 它裁掉的恰好是**令牌明文** —— 那串东西只显示这一次，关掉就再也拿不到。
     ⇒ 用户看到的是「令牌已生成，请立刻复制」而下面什么都没有。
     ⚠️ 用 `>` 直接子代：只管本页自己直接放着的 alert。 */
  .mcp-page > .arco-alert { flex:none; }
  .skl-h { padding:10px 14px; border-bottom:1px solid var(--color-border-2); font-weight:600;
           font-size:13px; color:#1d2129; background:#fafbfc; }
  .skl-h .muted { font-weight:400; }
  .mcp-plain { font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace; font-size:13px;
               background:#fff; border:1px solid var(--color-border-2); border-radius:4px;
               padding:8px 10px; margin-top:6px; word-break:break-all; user-select:all; }
  .mcp-conf { font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace; font-size:12px;
              background:#fff; border:1px solid var(--color-border-2); border-radius:4px;
              padding:8px 10px; margin:6px 0 0; overflow-x:auto; white-space:pre; user-select:all; }
  /* ── MCP 三页（2026-09-10 用户拍板：授权 / Skills 技能 / 调用记录 各成一页）──
     前缀 `mcp-` 是**既有一族**（`.mcp-page` / `.mcp-conf` / `.mcp-tkcard`），
     加之前逐个 grep 过全文件无同名（铁律 10⑥：同名类后写的赢，撞了页面坏而零报错）。
     ⚠️ 下面每一个 class 在模板里都真的用着、也都有规则命中（铁律 10⑥-1b：
        用了 class 却没有任何规则作用在它上面 ＝ 页面在替它许一个不存在的承诺）。 */
  /* 「怎么接」：左边四步、右边配置块。眼睛的路径是 读一步 → 看右边 → 复制，
     所以是并排不是上下。⚠️ 右栏必须 `min-width:0` —— 里面那个 `<pre>` 是
     `overflow-x:auto`，父级不给 0 下限的话它会把整行撑破（铁律 10⑯ 那族）。 */
  .mcp-how { display:flex; gap:18px; padding:12px 14px; align-items:flex-start; }
  .mcp-how-l { width:392px; flex:none; counter-reset:mcpstep; }
  .mcp-how-r { flex:1; min-width:0; }
  .mcp-step { position:relative; padding:0 0 11px 30px; font-size:13px;
              color:#1d2129; line-height:1.75; }
  .mcp-step:last-child { padding-bottom:0; }
  .mcp-step::before { counter-increment:mcpstep; content:counter(mcpstep);
    position:absolute; left:0; top:3px; width:19px; height:19px; border-radius:50%;
    background:#e8f3ff; color:#165dff; font-size:11px; font-weight:600;
    display:flex; align-items:center; justify-content:center; }
  /* 「Skills 技能」：一个技能一张卡。刻意**不用表格** —— 说明是这一页的主角，
     而 `.table-card .arco-table-td` 是 nowrap + ellipsis，表格里它只能显示一行、
     其余靠悬停（铁律 8 的房规）。写给人读的说明被折进 tooltip ＝ 等于没写。 */
  .mcp-sk { margin-bottom:12px; flex:none; }
  .mcp-sk-d { padding:11px 14px 0; font-size:13px; color:#1d2129;
              line-height:1.8; text-wrap:pretty; }
  /* 参数三列：名 / 必填 / 说明。说明本来就写在 schema 里给模型看，
     只列参数名的话运营看到的是一串英文键，等于没说。 */
  .mcp-sk-p { display:grid; grid-template-columns:180px 46px 1fr; gap:8px 14px;
              padding:12px 14px 14px; font-size:12.5px; align-items:baseline;
              color:#1d2129; }
  .mcp-sk-k { font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
              font-size:12px; color:#165dff; word-break:break-all; }
  .mcp-sk-r { font-size:11px; color:#f53f3f; }
  /* 「你可以这样问」：这一页的读者是财务与商务，不是开发 —— 只给
     `list_talents` 这种名字加一张参数表，等于让他读 API 文档。
     问法示例来自后端 `TOOLS[*].asks`（页面不写第二份）。 */
  .mcp-sk-ask { padding:10px 14px 0; display:flex; flex-direction:column; gap:5px; }
  .mcp-sk-ask .lab, .mcp-sk-note .lab { font-size:11.5px; color:#86909c; }
  .mcp-sk-q { font-size:13px; color:#4e5969; line-height:1.7; padding-left:11px;
              border-left:2px solid #165dff; }
  /* 「注意」：由 desc 里那些 🔴/⚠️ 行拆出来（后端 `_split`），刻意摆在参数表**之前** ——
     它们是"照着做会出错"的那几条，埋在参数表下面等于没写。 */
  .mcp-sk-note { padding:11px 14px 0; display:flex; flex-direction:column; gap:5px; }
  .mcp-sk-n { font-size:12.5px; line-height:1.7; color:#7a4a00; background:#fff7e8;
              border-radius:4px; padding:7px 10px; }
  /* 通道边界：先知道它做不了什么，比知道它能做什么更省事。 */
  .mcp-lim { display:grid; grid-template-columns:repeat(4,1fr); gap:1px;
             background:var(--color-border-2); }
  .mcp-lim > div { background:#fff; padding:11px 14px; }
  .mcp-lim b { display:block; font-size:12.5px; color:#1d2129; margin-bottom:3px; }
  .mcp-lim span { font-size:12px; color:#4e5969; line-height:1.65; }
  @media (max-width:1100px) { .mcp-lim { grid-template-columns:repeat(2,1fr); } }
  .pagination-bar b { color:#165dff; font-weight:600; margin:0 2px; }
  .pagination-bar .arco-pagination { margin-left:auto; }
  /* 越南 Shopee 财务报表（2026-08-17，PRD §5.23）。前缀 sp-，加之前 grep 过全文件无同名（铁律 10⑥） */
  .sp-pl, .sp-mx { width:100%; border-collapse:collapse; font-size:13px; font-variant-numeric:tabular-nums; }
  .sp-pl th, .sp-mx th { position:sticky; top:0; z-index:1; background:#f7f8fa; color:#4e5969; font-weight:600;
    text-align:left; white-space:nowrap; padding:8px 10px; border-bottom:1px solid var(--color-border-2); }
  .sp-pl td, .sp-mx td { padding:7px 10px; border-bottom:1px solid #f2f3f5; }
  .sp-pl .num, .sp-mx .num, .sp-pl th.num, .sp-mx th.num { text-align:right; }
  .sp-mx tbody tr:hover td { background:#fafbfc; }
  .sp-pl .sp-head td { background:#f7f8fa; font-weight:600; }
  .sp-pl .sp-calc td { background:#e8f3ff; font-weight:600; }
  .sp-mx .sp-calc td { background:#f7f8fa; font-weight:600; }
  .sp-pl .sp-sub td:first-child { color:#4e5969; }
  .sp-pl .sp-fx { font-size:12px; line-height:1.5; white-space:normal; }
  .sp-diff { flex:none; margin:0 0 10px; padding:9px 12px; background:#fff7e8; border:1px solid #ffcf8b;
    border-radius:6px; font-size:13px; color:#4e5969; line-height:1.6; }
  .sp-diff b { color:#ff7d00; }
  /* 月份组的竖分隔线（2026-08-17 用户实拍："按月份、总计要有明确的边界线，不然看不清"）。
     `.g0` 打在每组的**第一列**上；`.gt` 是合计组（加粗一点，它是另一种东西）。
     ⚠️ 用 border-left 而不是给整组包 <td colspan>：表格是逐格渲染的，包组会破坏列对齐。 */
  .sp-mx th.g0, .sp-mx td.g0 { border-left:1px solid var(--color-border-2); }
  .sp-mx th.gt, .sp-mx td.gt { border-left:2px solid #c9cdd4; }
  .sp-mx tbody td.gt { background:#fcfcfd; }
  /* 待核对：收进顶栏的紧凑标记（2026-08-17 用户实拍：面板别占版面，点开再看） */
  .sp-chk { cursor:pointer; user-select:none; }
  .sp-note-cell { display:flex; align-items:center; gap:6px; }
  .sp-note-cell .arco-input-wrapper { flex:1; min-width:0; }
  .table-card .arco-table-td { white-space:nowrap; }
  /* 规1：等宽数字 —— 比例字体里 "1" 比 "8" 窄，同一列的小数点即使位数相同也会左右错位。
     tabular-nums 让每个数字字形等宽，配合定长小数位，整列小数点在像素级对齐。
     合计栏（.pagination-bar）同享，否则合计数与列内数字字宽不一致、对不上眼。 */
  .table-card .arco-table-td, .pagination-bar { font-variant-numeric: tabular-nums; font-feature-settings:"tnum"; }
  .row-sub .arco-table-td { background:#f2f6ff !important; font-weight:600; }
  /* 店铺维度两级表头（2026-08-13 用户："名称居中一下，现在有点乱"）：
     数值列的 align:'right' 在 Arco 里**同时作用于表头**，于是组名居中、叶子名右对齐，
     两行头看起来是错位的。这里只把**表头**掰回居中，body 仍旧右对齐（金额必须右对齐）。
     挂在列的 headerCellClass 上，不是全局改 .arco-table-th —— 别的表的右对齐表头是对的。 */
  .th-mid .arco-table-cell { justify-content:center !important; text-align:center; }
  /* 泰国仓运费成本总表：人工录入的那几列（2026-08-31 用户「人工的部分需要在表头里面列出来」）。
     🔴 **底色跟着列一路铺到数据行**：只标表头的话，滚到第 3 行时又分不出来了 ——
        而这张表的读法就是横着扫一行。
     ⚠️ 用**蓝**不用橙（规 4 色彩闭集）：橙的唯一含义是「待人工处置：有钱挂账、有单待归属」，
        这里要说的是「这一列是人工填的」＝口径说明、中性信息 ⇒ 蓝。
     ⚠️ 只给 background 不动文字色：金额列右对齐竖着扫小数点（规 1），改字色会削弱那件事。 */
  .thw-man-th.arco-table-th { background:#e8f3ff; }
  .thw-man-td.arco-table-td { background:#f4f9ff; }
  .arco-table-tr:hover .thw-man-td.arco-table-td { background:#e8f3ff; }
  /* 组与组的竖分隔线（2026-08-31 用户「表头分割线需要清楚」）。挂在**每组第一列**上，
     组头 th / 叶子 th / 数据 td / 合计 td 四处同挂 ⇒ 从表头一路贯到合计行。
     ⚠️ 本表 `:bordered="false"`（没有竖向格线），所以这一条是页面上**唯一**的竖线，
        2px 才读得出是"块的边界"而不是"某一格的框"。
     ⚠️ 用灰（规 4：次要信息／结构线）—— 分隔线是版式不是状态，红橙都另有含义。 */
  .thw-gs.arco-table-th, .thw-gs.arco-table-td { border-left:2px solid #c9cdd4 !important; }
  /* 泰国仓「人工录入」弹窗：一块＝一笔，数与它的备注同一行（2026-08-31 重做）。
     ⚠️ 刻意不用 a-form-item：它的内容区是 flex row，控件与说明小字并排写会被挤到右边
        （铁律 10⑰），而这里每一块都要「一行控件 + 一行说明」，自绘比跟它较劲省事。 */
  .thw-adj-loc { display:flex; gap:12px; margin-bottom:14px; }
  .thw-adj-lab { font-size:12px; color:#4e5969; margin-bottom:4px; }
  .thw-adj-box { border:1px solid var(--color-border-2, #e5e6eb); border-radius:6px;
                 padding:12px 14px; margin-bottom:12px; }
  .thw-adj-head { font-size:13px; font-weight:600; color:#1d2129; margin-bottom:10px;
                  display:flex; align-items:center; gap:8px; }
  .thw-adj-row { display:flex; gap:10px; align-items:center; }
  .thw-adj-tip { font-size:11px; line-height:1.6; color:#86909c; margin-top:8px; }
  /* 待核对面板（规 3）：四档一形态，取代此前 a-alert/灰框/橙框/tag 组/常驻 tag 五种平行写法 */
  .rv-sum { display:flex; align-items:center; gap:9px; padding:9px 13px; border-radius:6px 6px 0 0;
            background:#e8ffea; border:1px solid #aff0b5; border-bottom:0; color:#0a7a22; font-size:13px; }
  .rv-sum.warn { background:#ffece8; border-color:#fdcdc5; color:#b71d1d; }
  .rv-list { border:1px solid var(--color-border-2); border-radius:0 0 6px 6px; overflow:hidden; }
  /* 🔴 `flex-wrap` 是 2026-08-21 加的：展开区（.rv-items）要跨整行摆，
     而它是这一行的第 N 个 flex 子项。不加 wrap 它会被挤在同一行里压成一条缝
     （铁律 10⑤ 那一族：换行容器里定宽元素与不定宽元素抢位）。
     配合 .rv-items 的 width:100% —— 两者缺一都不换行。 */
  /* 加载失败横幅（2026-09-08）：三张海外报表页共用。红底是刻意的 ——
   它要压过页面上那几个"看起来很正常"的 0，读起来必须比它们响亮。 */
.load-fail { display:flex; flex-wrap:wrap; align-items:center; gap:10px;
             margin-bottom:10px; padding:9px 12px; border:1px solid #e0b4ae;
             border-radius:4px; background:#fdf4f2; color:#a92a1f; font-size:12.5px; }
.load-fail-i { flex:none; font-size:14px; line-height:1; }
/* 下界是**正数**不是 0（铁律 10⑤ / 本套 §12 那条）：写 0 ⇒ flex-basis 恒 0 ⇒
   永远不换行，msg 一长就把「重试」按钮压成一条竖缝，而页面上什么都不报。 */
.load-fail-t { flex:1; min-width:240px; }
.load-fail-m { color:#8a6d68; font-size:11.5px; margin-top:2px; word-break:break-all; }
.rv-item { display:flex; align-items:center; flex-wrap:wrap; gap:11px; padding:9px 13px; font-size:13px;
             border-bottom:1px solid var(--color-border-2); }
  /* 展开看具体对象：跨整行、缩进对齐正文，与上面那行拉开一点 */
  .rv-items { width:100%; margin:2px 0 2px 18px; display:flex; flex-direction:column; gap:3px; }
  .rv-i { display:flex; align-items:baseline; gap:10px; font-size:12px; line-height:1.6;
          color:var(--color-text-2); }
  .rv-i > b { font-family:ui-monospace,Menlo,Consolas,monospace; color:var(--color-text-1); }
  .rv-more { font-size:12px; white-space:nowrap; }
  .rv-item:last-child { border-bottom:0; }
  .rv-item.pass { background:#fbfffc; }
  .rv-lv { width:7px; height:7px; border-radius:50%; flex:none; }
  .rv-lv.block { background:#f53f3f; } .rv-lv.todo { background:#ff7d00; }
  .rv-lv.known { background:#c9cdd4; } .rv-lv.pass { background:#00b42a; }
  .rv-t { font-weight:600; min-width:120px; flex:none; }
  .rv-amt { min-width:150px; flex:none; color:#4e5969; font-variant-numeric:tabular-nums; }
  .rv-det { color:#4e5969; flex:none; }
  /* 🔴 `min-width` 是 2026-08-29 加的，与上面 `.rv-item` 的 `flex-wrap` 是**一对**
     （铁律 10⑤：容器要 wrap，而那个不定宽的子项要有下界，否则放不下时被压瘪的
      永远是它）。原先写 `min-width:0` ⇒ 它的 flex-basis 是 0、**永远不会触发换行**，
     只会把剩下多少就占多少 —— `.rv-det` 一长（本页那条"费用科目对不上"的 detail
     实测 897px），它就被挤成 **27px 的一条竖缝、一行一个字往下淌 1131px**，
     而 DOM 完整、console 零错误、断言全绿，只有人眼看得出（浏览器实测抓到）。
     现在放不下就整条掉到下一行、再占满整行。⚠️ 别改回 0。 */
  .rv-act { color:#86909c; font-size:12px; flex:1; min-width:260px; }
  .rv-go { margin-left:auto; flex:none; white-space:nowrap; font-size:12px; }
  /* 待核对 tab 的徽标：block 亮红、只有 todo 亮橙、全通过不出徽标 */
  .rv-badge { display:inline-block; background:#f53f3f; color:#fff; font-size:10px; font-weight:700;
              line-height:1; padding:2px 5px; border-radius:8px; margin-left:5px; vertical-align:1px; }
  .rv-badge.todo { background:#ff7d00; }
  /* `block` 那一档的红**恰好就是 `.rv-badge` 的基线值**，所以它此前不需要规则也能对。
     写出来是把「block 亮红」从隐式继承基线变成显式声明：哪天有人把基线色改成中性、
     让每档各自给色，这 12 处静态写死 block 的徽标（全是挂账单数）不会静默跟着变色。
     ⚠️ 别为省事把基线的红删掉再靠这条撑 —— `.rv-badge` 单用的地方就没有兜底色了。 */
  .rv-badge.block { background:#f53f3f; }
  /* 快递费率规则：不在该方案内的格子（灰）/ 有历史价的角标 */
  .rate-off { background:#f7f8fa; }
  .rate-cell { cursor:pointer; display:flex; align-items:center; justify-content:flex-end; gap:4px; padding:2px 0 }
  .rate-cell:hover { background:#e8f3ff; border-radius:3px }
  .rate-hist { font-size:9px; color:#ff7d00 }
  /* 手工填写行（人可直接改报表数字的通道）：与自动汇总行视觉区分，照人工对账单里的高亮 */
  .date-native { height:32px; padding:0 10px; border:1px solid var(--color-neutral-3,#e5e6eb); border-radius:2px;
  background:#f2f3f5; font-size:14px; color:#1d2129; font-family:inherit; width:180px; box-sizing:border-box; }
.date-native:hover { background:#f2f3f5; border-color:#c9cdd4; }
.date-native:focus { background:#fff; border-color:#165dff; outline:none; }
.row-adj .arco-table-td { background:#fff7e8 !important; }
/* 阻断级异常行（规 4 红）：同一账期同一编码出现多个单价——"取哪一个"没有正确答案，
   必须一眼看见，而不是混在普通差异里 */
.row-alert .arco-table-td { background:#fff1f0 !important; }
  .arco-table-td.col-agg, .arco-table-td.col-agg .arco-table-cell { background:#f2f6ff; font-weight:600; }
  /* 抑制自动填充把 text 改成 search 后，隐藏 webkit 原生清除按钮，外观与原来一致 */
  input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration { -webkit-appearance:none; appearance:none; }
  .page .arco-table-tr-summary .arco-table-td { background:#e8f3ff !important; font-weight:700; color:#0e42d2; }
  /* 公式溯源芯片：公式里的【表·列】可点击直达原始表页，悬停(原生 title)看菜单路径+Excel 表头别名 */
  .src-chip { color:#165dff; cursor:pointer; border-bottom:1px dashed #94bfff; }
  .src-chip:hover { background:#e8f3ff; }
  .fx-pop { max-width:440px; line-height:1.7; }
  .page .arco-table-td, .page .arco-table-th, .arco-drawer-body { -webkit-user-select:text; user-select:text; }
  .table-card .arco-table-td .arco-btn-text { color:#86909c; }
  .table-card .arco-table-td .arco-btn-text:hover { color:#165dff; background:rgba(22,93,255,.06); }
  .table-card .arco-table-td .arco-btn-text.arco-btn-status-danger { color:#c9cdd4; }
  .table-card .arco-table-td .arco-btn-text.arco-btn-status-danger:hover { color:#f53f3f; background:rgba(245,63,63,.06); }
  .imp-modal .arco-table { box-shadow:none; }
  .colcfg-item { display:flex; align-items:center; gap:8px; padding:6px 4px; border-radius:4px; cursor:grab; }
  .colcfg-item:hover { background:#f7f8fa; }
  .colcfg-item.dragging { opacity:.4; }
  /* 出单渠道表的总计行（走 a-table 的 row-class；表格本身用全站统一的 a-table，不自造） */
  .arco-table tr.dyf-total td { font-weight: 600; background: #f7f8fa }
/* 「需核对」那一格的成因小字（2026-08-21）。加粗红的是**我们自己算少了钱**的两类
   （占位单号并组／编码不一致），灰的是解释性的两类（人工侧重复计／纯单价差）——
   两者该做的事完全不同，颜色上就要分得开。 */
.jm-why { margin-left:6px; font-size:12px; color:var(--color-text-3); cursor:help; white-space:nowrap; }
.jm-why.bad { color:rgb(var(--red-6)); }

/* 列表里的商品主图。
   ⛔ **这里 2026-08-21 写着"别改成横排"，2026-08-24 由用户拍板改了**（"商品图片放到
      红框位置去，占一整个行高"）。原注释的理由是对的 —— 改横排确实会啃商品名的宽度。
   ⇒ 代价怎么付的：商品那一列 110→146px（装 56px 图 + 8px 间距 + 名字），
      **从同一行的「来源切片」那列匀 36px 过来**（216→180），
      两张表（成品库 `.cf-rows-scr` / 裂变库 `.cf-rows-fis`）的列下限合计**一分不变**——
      那条「≤ 1098px」的不变量原样成立（`verify_cf` 的 `t_rows_grid_fit` 守着它）。
      代价仍在：商品名可用宽 110→82px，两行 clamp 下约 13 字，超了给省略号 + title。
   ⚠️ 行高不变：仍由 56×100 的来源缩略图定（约 119px）。商品主图多是方图，
      `object-fit:cover` 进 56×100 会裁掉两侧 —— 刻意与视频首帧同尺寸同形状，一行里两张图对齐。
   🔴 `.cf-prod-cell` **两张表共用**：改它就是同时改成品库与裂变库，两边列宽都要跟着匀。 */
.cf-lst-th { width:44px; height:44px; object-fit:cover; border-radius:3px; cursor:zoom-in;
             border:1px solid var(--color-border-2); }
.cf-prod-th { width:56px; height:100px; object-fit:cover; border-radius:4px; flex:none;
              border:1px solid var(--cf-surface); background:var(--cf-surface); }

/* ===== 内容工厂·商品主图字段（2026-08-21）=====
   ⚠️ 类名前缀 `cf-mainimg-` 起名前已 grep 过全文无同名规则（铁律 ⑥：19k 行单文件里
      后写的赢，撞名会让另一个模块的样式静默套过来，而 console 一个字都不报）。 */
/* 「左图右链」（2026-08-21 用户："和视频那个类似的布局"）：形状照 `.cf-film-src-cell` ——
   缩略图在左、内容一列在右。
   🔴 右侧那一列必须 `min-width:0`，否则里面的输入框撑着不让缩，窄屏下整块溢出
      （铁律 10⑤ 的老毛病：定宽的那个不让位，被啃的永远是不定宽的那个）。
   ⚠️ 主图是方的（800×800），不套用视频那边 56×100 的竖比例 —— 那会把商品图裁掉两边。 */
.cf-plink { display:flex; align-items:flex-start; gap:10px; }
.cf-plink-th { flex:0 0 auto; display:flex; flex-direction:column; align-items:center; gap:3px; }
.cf-plink-w { flex:1; min-width:0; }
.cf-plink-cap { font-size:11px; color:var(--color-text-3); line-height:1; }
.cf-plink-cap .on { color:rgb(var(--arcoblue-6)); }
.cf-mainimg { display:flex; align-items:flex-start; gap:10px; }
/* 56px：与 `.cf-film-srcth` 的宽度对齐（"和视频那个类似的布局"）。
   ⚠️ 高度取 56 不取 100 —— 商品主图是方的（800×800），套竖比例会把两边裁掉。 */
.cf-mainimg-th { width:56px; height:56px; object-fit:cover; border:1px solid var(--color-border-2);
                 border-radius:4px; cursor:zoom-in; flex:0 0 auto; }
.cf-mainimg-none { width:56px; height:56px; border:1px dashed var(--color-border-3); border-radius:4px;
                   display:flex; align-items:center; justify-content:center; flex:0 0 auto;
                   font-size:12px; color:var(--color-text-3); }
.cf-mainimg-act { display:flex; flex-wrap:wrap; align-items:center; gap:6px; min-width:0; }
.cf-mainimg-pick { display:flex; flex-wrap:wrap; gap:6px; margin-top:6px; }
.cf-mainimg-opt { width:44px; height:44px; object-fit:cover; border-radius:3px; cursor:pointer;
                  border:2px solid transparent; }
.cf-mainimg-opt:hover { border-color:var(--color-border-3); }
.cf-mainimg-opt.on { border-color:rgb(var(--arcoblue-6)); }

/* ===== 商品主图（2026-08-03）：四个备货页共用的缩略图 + 大图遮罩。
   图恒为本地 /static/jst/<url哈希>.jpg，缩略图同名带 _t（200px，列表只加载它：
   460 张缩略图 ≈ 7MB，原图 46MB）。外链直渲的方案已作废——用户国内浏览器
   打不开上游那两族图床（阿里云新加坡 OSS / 字节 TikTok CDN）。 ===== */
.jst-pic{width:36px;height:36px;border-radius:5px;object-fit:cover;background:#F2F3F5;border:1px solid #E3E5E9;cursor:zoom-in;display:block;flex:none}
.jst-pic-lg{width:64px;height:64px;border-radius:7px}
/* 无图占位：ERP 没配图 或 下载失败。刻意画成一个可分辨的灰块而不是留白——
   留白会让人以为"这列坏了"，灰块告诉人"这个品就是没图"。 */
.jst-pic-none{display:flex;align-items:center;justify-content:center;color:#B9BEC7;font-size:15px;cursor:default}
.jst-lb{position:fixed;inset:0;z-index:2000;background:rgba(0,0,0,.72);display:flex;flex-direction:column;
        align-items:center;justify-content:center;gap:14px;cursor:zoom-out}
.jst-lb img{max-width:82vw;max-height:78vh;border-radius:8px;background:#FFF;box-shadow:0 8px 40px rgba(0,0,0,.45)}
.jst-lb-tip{color:rgba(255,255,255,.72);font-size:12.5px}
/* 图表悬停浮层：fixed + translate(-50%,-100%) 让它悬在光标正上方；
   pointer-events:none 是关键——否则浮层会挡住下面的命中矩形，鼠标一移就闪。 */
/* 2026-08-06：原来是 white-space:nowrap + 恒向上，长文案贴到页面右边就整条溢出屏幕、
   贴到顶部就被裁掉。现在浮窗内容已收成"日期 · 数量"很短，但仍按最坏情况兜住：
   限宽 + 允许换行（换行优先于溢出），横向位置在 JS 里夹钳，顶部空间不够时翻到光标下方。 */
.jsku-tip{position:fixed;z-index:2200;transform:translate(-50%,-100%);pointer-events:none;
  background:rgba(20,22,26,.92);color:#FFF;font-size:11.5px;line-height:1.5;
  padding:5px 9px;border-radius:6px;white-space:normal;overflow-wrap:anywhere;
  max-width:min(300px,88vw);width:max-content;box-shadow:0 4px 14px rgba(0,0,0,.22);
  font-variant-numeric:tabular-nums}
.jsku-tip.flip{transform:translate(-50%,0)}

/* ===== 备货运营三页（今日备货单 / SKU 备货报表 / 数字怎么来的）—— 2026-08-03 Claude Design 稿移植。
   刻意不用 Arco 组件（设计稿自绘视觉），类名前缀 op-；只作用于这三页，不碰全站样式。 ===== */
.op-wrap{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Hiragino Sans GB','Microsoft YaHei',Helvetica,Arial,sans-serif;color:#14161A;background:#F2F3F5;min-height:100%;padding:0 0 56px;font-size:13px;}
.op-wrap a{color:#1B54D6;text-decoration:none;cursor:pointer}
.op-wrap a:hover{color:#123FA8;text-decoration:underline}
.op-head{display:flex;align-items:center;justify-content:space-between;gap:24px;padding:12px 24px;background:#FFF;border-bottom:1px solid #E3E5E9}
.op-card{background:#FFF;border:1px solid #E3E5E9;border-radius:10px}
.op-num{font-variant-numeric:tabular-nums}
.op-chip-blue{display:flex;align-items:center;gap:7px;padding:5px 10px;background:#EDF2FD;border:1px solid #D5E1FA;border-radius:6px;font-size:12px;color:#1B54D6;white-space:nowrap}
.op-btn{display:inline-block;padding:6px 12px;border:1px solid #D8DBE1;border-radius:6px;font-size:13px;color:#4B5259;background:#FFF;cursor:pointer;white-space:nowrap}
.op-btn:hover{border-color:#B9BEC7;color:#14161A}
.op-btn-dark{display:inline-block;padding:6px 12px;border-radius:6px;font-size:13px;font-weight:600;background:#14161A;color:#FFF;cursor:pointer;white-space:nowrap}
.op-btn-dark:hover{background:#2A3138}
.op-kpis{display:grid;grid-template-columns:repeat(5,1fr);gap:1px;background:#E3E5E9;border:1px solid #E3E5E9;border-radius:10px;overflow:hidden}
.op-kpi{background:#FFF;padding:13px 16px 14px}
.op-kpi .l{font-size:11.5px;color:#868D96;white-space:nowrap}
.op-kpi .v{font-size:27px;font-weight:690;letter-spacing:-.025em;font-variant-numeric:tabular-nums}
.op-kpi .u{font-size:11.5px;color:#9AA0A8}
.op-kpi .s{font-size:11px;color:#9AA0A8;margin-top:3px}
.op-tag{display:inline-flex;align-items:center;gap:5px;padding:3px 8px;border-radius:5px;font-size:11.5px;font-weight:600;white-space:nowrap;border:1px solid transparent}
.op-tag .d{width:5px;height:5px;border-radius:50%;display:inline-block;background:currentColor}
.op-tier{width:17px;height:17px;border-radius:4px;display:inline-flex;align-items:center;justify-content:center;font-size:10px;font-weight:700}
.op-seg{display:flex;border-radius:5px;overflow:hidden;height:22px}
.op-seg>div{display:flex;align-items:center;justify-content:center;font-size:10.5px;white-space:nowrap;overflow:hidden}
.op-orange{display:flex;gap:8px;padding:9px 11px;border-radius:7px;background:#FDF3E8;border:1px solid #F2DFC6}
.op-orange .t{font-size:11px;font-weight:700;color:#C25A00;flex:0 0 auto}
.op-orange .x{font-size:11.5px;color:#4B5259;line-height:1.6}
/* 今日备货单表格（2026-08-04：加「怎么理解」列 → 11 列变 12 列）。
   ⚠️ 列宽是压过的：最初 10 列版固定和 810 + 首列下限 180 = 990px，而 1280 视口下可用宽只有 ≈956
   （1280 − 侧栏 244 − padding 48 − 卡片边框 − 两层滚动条），**那时就已经横向溢出**。
   新列 64px 不是加出来的，是从各列匀 4~8px 挪出来的：固定和恒为 802 + 首列下限 150 = 952 ≤ 956。
   再加列必须重新算这笔账——已经没有余量，只能继续从别的列匀。

   2026-08-04 用户反馈「表头不要换行」：配 .op-th 的 nowrap，**在不动固定和 802 的前提下重新分配**
   （加宽会直接撑破上面那笔账）。做法是把余量从内容窄的两列匀给放不下的两列：
     状态 88→72（格内是个 ~52px 的标签）、建议备货量 106→92（「建议备货量」+右padding 约 81）
     → 匀出 30px 给 预测偏差 64→79、怎么理解 64→79（两者都需 ~73px）。
   同时把四个放不下的表头**缩短可见文案**，完整说法移进 title 悬停（本来就每个都有 title，不丢信息）：
     预计可售天数→可售天数 / 预计 20 天销量→20 天销量 / 预计 N 天销量→N 天销量 / 近 7 天偏差→7天偏差 */
.op-grid12{display:grid;grid-template-columns:minmax(150px,1fr) 30px 70px 88px 68px 84px 84px 84px 96px 79px 79px 40px;align-items:center}
.op-th{padding:8px;font-size:11px;color:#868D96;white-space:nowrap}
.op-row{border-bottom:1px solid #F5F6F7;background:#FFF}
.op-row:hover{background:#FAFBFC}
.op-pill{padding:4px 10px;border-radius:5px;font-size:12px;cursor:pointer;border:1px solid #DCDFE5;background:#FFF;color:#4B5259;white-space:nowrap}
.op-pill.on{background:#14161A;color:#FFF;border-color:#14161A}
.op-tabs{display:flex;border:1px solid #DCDFE5;border-radius:6px;overflow:hidden;flex:0 0 auto}
.op-tabs>div{padding:4px 9px;font-size:11.5px;cursor:pointer;background:#FFF;color:#4B5259}
.op-tabs>div+div{border-left:1px solid #DCDFE5}
.op-tabs>div.on{background:#14161A;color:#FFF}
.op-mini-th{display:grid;position:sticky;top:0;background:#FAFAFB;border-bottom:1px solid #EDEEF1}
.op-mini-th>div{padding:6px 10px;font-size:11px;color:#868D96}
.op-mini-tr{display:grid;border-bottom:1px solid #F5F6F7}
.op-mini-tr>div{padding:5px 10px;font-size:12px;font-variant-numeric:tabular-nums}
.op-sec-num{font-size:11px;font-weight:700;color:#FFF;background:#14161A;border-radius:4px;padding:2px 6px}
/* 首列 28px＝商品主图（2026-08-03 加）；其后 18px 层徽标 / 1fr 名称 / auto 建议量 为原设计稿三列 */
.op-rail-item{display:grid;grid-template-columns:28px 18px 1fr auto;gap:9px;align-items:center;padding:9px 14px 9px 11px;border-bottom:1px solid #F3F4F6;cursor:pointer;border-left:3px solid transparent;background:#FFF}
.op-rail-item .jst-pic{width:28px;height:28px;border-radius:4px}
.op-rail-item:hover{background:#F7F8FA}
.op-rail-item.on{background:#F4F7FE;border-left-color:#1B54D6}
.op-ybox{width:46px;display:flex;flex-direction:column;justify-content:space-between;text-align:right;font-size:10px;color:#A7ADB5;font-variant-numeric:tabular-nums}

/* ===== 内容工厂：暖色作用域（只在 .cf-scope 内生效，账单页零影响） ===== */
/* 🎨 设计令牌照 Claude Design 稿逐值抠出（2026-08-12）：Tailwind **stone** 中性阶
   + **orange-700** 主色。之前那套是我自己调的近似色，字号也偏大（Arco 默认 14px），
   而设计稿是 12px 为主（全稿 396 次）、圆角 7px 为主——两处叠起来就是"看着很像但哪儿都不对"。
   ⚠️ 变量名保持不变，下面几百行既有规则不用动；只换值 + 补新令牌。 */
.cf-scope {
  /* ── 中性：暖灰 stone，不要纯灰或蓝灰 ── */
  --cf-ink:#1C1917;        /* 一级文字 / 顶栏底 / 资产实底 */
  --cf-ink1:#292524;       /* 二级文字 */
  --cf-ink15:#44403C;      /* 正文弱化 */
  --cf-ink2:#57534E;       /* 说明文字 */
  --cf-ink3:#78716C;       /* 元信息 / 表头 */
  --cf-ink4:#A8A29E;       /* 占位 / 时间戳 / 空值 — */
  --cf-line2:#D6D3D1;      /* 强边框：输入框、次按钮 */
  --cf-line:#E7E5E4;       /* 标准边框 */
  --cf-page:#EFEDEB;       /* 弱分隔：侧栏、区块 */
  --cf-surface:#F5F5F4;    /* 表格行分隔 */
  --cf-ground:#FAFAF9;     /* 侧栏 / 表头 / 只读区 */
  --cf-work:#FBFAF9;       /* 详情页工作区底 */
  --cf-foot:#FCFCFB;       /* 卡片脚 / 抽屉脚 */
  --cf-dark:#292524;
  /* ── 主色 橙红：只给「要人动一下」和当前位置 ── */
  --cf-accent:#C2410C;
  --cf-accent-hover:#9A3412;
  --cf-accent2:#EA580C;    /* 计数、警示文字 */
  --cf-accent-line:#FDBA74;
  --cf-softline:#FED7AA;
  --cf-soft:#FFF1E8;       /* 选中态、标底 */
  --cf-soft2:#FFF7ED;      /* 待处置底 */
  --cf-soft3:#FFF9F4;
  --cf-row:#FFFCF9;        /* 待处置行底 */
  /* ── 进行中 蓝：只给进度与只读信息，不做主色 ── */
  --cf-info:#1D4ED8; --cf-info-line:#BFDBFE; --cf-info-bg:#EAF1FF; --cf-info-bg2:#F5F9FF;
  /* ── 成功 绿：只给「成了」，不给「可用」 ── */
  --cf-ok:#15803D; --cf-ok-line:#A7F3C4; --cf-ok-bg:#F0FDF4; --cf-ok-bg2:#F3FCF6;
  /* ── 异常 红：只给真失败与合规风险 ── */
  --cf-bad:#B91C1C; --cf-bad-line:#FECACA; --cf-bad-bg:#FEF2F2; --cf-bad-bg2:#FEF7F7;
  /* ── 提醒 琥珀：不是失败，但"你得去做点什么"（队列停摆 / 插件没在跑 / 数据取得不全）──
     🔴 2026-08-15 补：`var(--cf-warn)` 在模板里**被用了三次却从来没定义过** ——
     未定义的自定义属性会让整条 `color` 声明作废、回落到继承色，于是那三句告警
     一直和正文长得一模一样。**"样式表里写了"和"页面上有"是两件事**（同 nginx
     `add_header` 那条）。补的是定义不是用法：作者伸手要过三次，缺的只是这一行。 */
  --cf-warn:#B45309;
  /* ── 高光画面 琥珀：高光词（黄）长出来的那一族，视觉上同族 ──
     🔴 2026-08-24 补：这三个从 2026-08-22 起**被用了 19 处却从来没定义过**
     （`--cf-hl` 5 · `--cf-hl-bg` 8 · `--cf-hl-line` 6），与上面 `--cf-warn` 那次
     一字不差的同一种事故。未定义的自定义属性让整条声明作废：高光画面那一块的琥珀底
     变透明、边框回落成继承色的灰、台词里那个缩略图芯片的边框回落成主色橙红（于是
     "琥珀是内容标记、橙红是要人动一下"这条分工在页面上根本不成立）、时间条底部那道
     "这一段的范围"**压根不可见**——而它上面那行说明白纸黑字写着"底部那道琥珀线是这一段的范围"。
     ⚠️ **页面上没有报错、没有裂图、19 处全都安静地退化**，只有量 computed 才看得出来。
     防线也没看见：断言钉的是"那条 CSS 规则在不在"，而规则在、值不解析。
     现由 `verify_inline_template §18` 改钉规则本身：**凡 `var(--cf-*)` 用到的都必须定义**。
     取值按既有那两族的形状配：主色 accent `#C2410C` / line `#FDBA74` / soft `#FFF1E8`，
     琥珀这族同构。 */
  --cf-hl:#CA8A04; --cf-hl-line:#FDE68A; --cf-hl-bg:#FEFCE8;
  /* ── 内容标记：只出现在台词与拆解内容里，不做 UI 色 ── */
  --cf-hz:#FDE047;         /* 台词钩子词高亮底 */
  --cf-note-bg:#FEF9C3; --cf-note-t:#92400E;
  --cf-track:#F9A8D4;      /* 时间轴场景轨 */
  --cf-on-dark:#FDBA74;    /* 深色底上的强调字 */
  /* ── 圆角四档 / 阴影两种（规范 §1，不许有第五档）── */
  --r-sm:5px; --r-md:7px; --r-lg:10px; --r-xl:12px;
  --sh-drawer:-14px 0 34px rgba(28,25,23,.14);
  --sh-modal:0 12px 32px rgba(28,25,23,.08);
  font-size:13px; color:var(--cf-ink2);
}
/* 🔴 全作用域 border-box（2026-08-13）。2026-08-13 那两个「内容静默消失」的 bug **同一个根**：
   本作用域是 content-box，于是 `width:150px` + `padding:0 12px` + `1px` 边框 ＝ 实际 176px，
   而写的人以为是 150。全站只有 `.if2-page` 做过这个重置，`.cf-scope` 一直没有。
   挂在作用域根上而不是逐个类加 —— 逐个加必漏，而漏掉的那个正好就是会溢出的那个。
   ⚠️ 加它**不是零成本**：凡「定了 width 又有 padding/border」的规则都会变窄。
   全量扫过一遍，真受影响的只有三条，逐条处理见各自注释
   （`.cf-sgc-clip` 必须补回内边距——它的子元素是硬 150px 的视频；
     `.cf-why-col:last-child` 由 300 内容变 300 总宽，是文字列、可接受；
     `.cf-prev-img` 的 `width:100%`+1px 边框反而**不再**溢出 2px）。 */
.cf-scope, .cf-scope *, .cf-scope *::before, .cf-scope *::after { box-sizing:border-box; }
/* 规范 §1：**所有**数字、时间码、时间戳等宽，没有例外。
   挂在作用域根上而不是逐个类加——逐个加必漏，而漏掉的那个只是"看着抖"，没人会报 bug。 */
.cf-scope, .cf-scope .arco-table, .cf-scope .arco-drawer, .cf-scope .arco-modal {
  font-variant-numeric:tabular-nums; }
/* 规范 §1 行高：正文 1.6~1.85，台词 1.85，标题 1.4~1.5；长段落 pretty */
.cf-scope { line-height:1.7; }
.cf-scope .cf-hi, .cf-scope .cf-sc-srcbody { line-height:1.85; text-wrap:pretty; }

/* ═══ Arco 组件在内容工厂里的皮肤 ═══
   全部选择器都锁在 `.cf-scope` 内 —— 账单/备货那些页面一个像素不动。
   ⚠️ 抽屉与弹窗会被 teleport 到 body 外面，所以它们的根上要**自己带 cf-scope 类**
   （`<a-drawer class="cf-scope">` / `modal-class="cf-scope ..."`），
   不然这里的规则一条都够不着它们。 */
.cf-scope .arco-btn { border-radius:7px; font-size:13px; }
.cf-scope .arco-btn-primary { background:var(--cf-accent); font-weight:600; border-color:var(--cf-accent); }
.cf-scope .arco-btn-primary:hover { background:var(--cf-accent2); border-color:var(--cf-accent2); }
.cf-scope .arco-btn-secondary { background:#fff; border:1px solid var(--cf-line2); color:var(--cf-dark); }
.cf-scope .arco-btn-secondary:hover { background:var(--cf-ground); border-color:var(--cf-ink4); color:var(--cf-ink); }
.cf-scope .arco-btn-text { color:var(--cf-ink3); }
.cf-scope .arco-btn-text:hover { color:var(--cf-accent); background:var(--cf-soft); }
.cf-scope .arco-btn-size-mini { font-size:12px; border-radius:7px; }
.cf-scope .arco-btn-size-small { font-size:12px; }
.cf-scope .arco-input-wrapper, .cf-scope .arco-select-view, .cf-scope .arco-textarea-wrapper {
  border-radius:7px; border-color:var(--cf-line); background:#fff; font-size:12px; }
.cf-scope .arco-input-wrapper:hover, .cf-scope .arco-select-view:hover { border-color:var(--cf-line2); }
.cf-scope .arco-input-wrapper.arco-input-focus, .cf-scope .arco-select-view-focus,
.cf-scope .arco-textarea-wrapper:focus-within { border-color:var(--cf-accent); box-shadow:none; }
.cf-scope .arco-input::placeholder, .cf-scope .arco-textarea::placeholder { color:var(--cf-ink4); }
.cf-scope .arco-link, .cf-scope a { color:var(--cf-accent); }
.cf-scope .arco-link:hover, .cf-scope a:hover { color:#9A3412; }

/* 筛选页签：设计稿用的是**下划线 tab**（选中＝橙字 + 2px 橙下划线），
   不是 Arco 默认那种药丸。模板里仍是 a-radio-group type=button，只在这里换皮——
   改模板要动六处，而它们的语义（单选一档）本来就对。 */
.cf-scope .arco-radio-group-button { background:transparent; padding:0; border-radius:0;
  border-bottom:1px solid var(--cf-page); gap:18px; display:inline-flex; }
.cf-scope .arco-radio-group-button .arco-radio-button {
  background:transparent; border-radius:0; box-shadow:none; margin:0;
  font-size:13px; color:var(--cf-ink2); padding:0 0 9px; line-height:1.2; }
/* ⚠️ Arco 给选中项的类是 `arco-radio-checked`（**不是** `arco-radio-button-checked`）——
   第一版按后者写，规则一次都没匹配上，表现是"tab 看着像普通文字、选中态毫无反应"。
   分隔竖线是 ::before 画的，也要一起去掉（设计稿的 tab 之间没有竖线）。 */
.cf-scope .arco-radio-group-button .arco-radio-button::after,
.cf-scope .arco-radio-group-button .arco-radio-button::before { display:none; content:none; }
.cf-scope .arco-radio-group-button .arco-radio-button:hover { background:transparent; color:var(--cf-ink); }
.cf-scope .arco-radio-group-button .arco-radio-button.arco-radio-checked {
  background:transparent; color:var(--cf-accent); font-weight:600;
  border-bottom:2px solid var(--cf-accent); }
/* 行更紧一点（设计稿的表是 12px 字 + 克制的行距），缩略图别把行撑高 */
.cf-scope .arco-table-td .arco-table-cell { padding-top:8px; padding-bottom:8px; }
.cf-scope .arco-table-td img { max-height:44px; }

/* 状态徽标：设计稿是「浅底 + 同色描边 + 5px 圆角 + 600 字重」 */
.cf-scope .arco-tag { border-radius:5px; font-size:12px; font-weight:600; border:1px solid transparent; }
.cf-scope .arco-tag-green { color:var(--cf-ok); background:var(--cf-ok-bg); border-color:var(--cf-ok-line); }
.cf-scope .arco-tag-red { color:var(--cf-bad); background:var(--cf-bad-bg); border-color:var(--cf-bad-line); }
.cf-scope .arco-tag-orange { color:var(--cf-accent); background:var(--cf-soft); border-color:var(--cf-softline); }
.cf-scope .arco-tag-gray { color:var(--cf-ink3); background:var(--cf-surface); border-color:var(--cf-line); }
.cf-scope .arco-tag-blue { color:#1D4ED8; background:#EFF6FF; border-color:#BFDBFE; }

/* 表格：表头浅底、12px、行分隔线细。Arco 默认那套偏"重"，与这稿的克制不搭。 */
.cf-scope .arco-table-th { background:var(--cf-ground); font-size:11px; font-weight:500;
  color:var(--cf-ink3); border-color:var(--cf-line); }
.cf-scope .arco-table-td { font-size:12px; color:var(--cf-ink2); border-color:var(--cf-line); }
.cf-scope .arco-table-tr:hover .arco-table-td { background:var(--cf-ground); }
.cf-scope .arco-table-container, .cf-scope .arco-table-border { border-color:var(--cf-line); }
.cf-scope .arco-switch-checked { background:var(--cf-accent); }
.cf-scope .arco-pagination-item-active { background:var(--cf-soft); color:var(--cf-accent);
  border-color:var(--cf-softline); }

/* 抽屉与弹窗 */
.cf-scope.arco-drawer-container .arco-drawer-header,
.cf-scope .arco-modal-header { border-bottom:1px solid var(--cf-line); }
.cf-scope .arco-modal { border-radius:12px; }
.cf-scope .arco-drawer-body, .cf-scope .arco-modal-body { background:#fff; }

/* 页面外壳：标题更大、说明更弱，与设计稿的层级一致 */
.cf-scope .page-title { font-size:19px; font-weight:600; color:var(--cf-ink); }
.cf-scope .filterbar { gap:8px; }
.cf-scope .table-card { border-radius:12px; border-color:var(--cf-line); }
.cf-scope .muted { color:var(--cf-ink3); }
/* ═══ 复刻成品详情：左成品右对标（设计稿 H）═══ */
/* ═══════════ 成品库重构（2026-08-14，design_handoff_film_library）═══════════
   设计稿的 token 表与上面 `.cf-scope` 那份**逐值相同**（都是 stone + orange-700），
   所以这里一个新变量都不加，只写版式。新起的类名开工前已 grep 过零命中（铁律 10⑥）。
   ⚠️ 违规词底 #FEE2E2 是设计稿里唯一没有对应变量的值，就近写在 .cf-film-vio 里。 */
/* —— 扫雷三档页签（与 mode 下拉正交）—— */
.cf-film-tabs { display:flex; gap:18px; border-bottom:1px solid var(--cf-page); margin-bottom:10px; }
.cf-film-tabs > span { font-size:13px; padding-bottom:9px; cursor:pointer; color:var(--cf-ink2);
                       border-bottom:2px solid transparent; margin-bottom:-1px; }
.cf-film-tabs > span.on { color:var(--cf-accent); font-weight:600; border-bottom-color:var(--cf-accent); }
/* —— 列表主列：段数绿标 + 成品名 —— */
.cf-film-nseg { font-size:11px; font-weight:600; color:var(--cf-ok); background:var(--cf-ok-bg);
                border:1px solid var(--cf-ok-line); border-radius:4px; padding:1px 6px;
                font-variant-numeric:tabular-nums; flex:none; }
/* —— 详情：三卡 —— */
/* 🔴 `flex-wrap` + info 的 `min-width` 是一对，缺一不可（2026-08-17 本地量出来的）：
   加了第四张卡（裂变草稿）之后，1280 视口上「整片信息」被挤到 **178px，8 个值全部截断**——
   而它是这一行里唯一"内容量不定"的一格，其余三格都是定宽。不 wrap 的话 flex 只会
   一直压它；给了下限，放不下时最后那张卡会**掉到第二行**，而不是把中间那格压瘪。
   ⚠️ 这与铁律 10⑤ 记的是同一族（武汉运费页 `flex:1` 贪掉整行、成品页播放器被压成 263×104），
   只是方向相反：那次是某一格贪，这次是某一格被啃。判据都得靠**量**，看不出来。 */
.cf-film-cards { display:flex; flex-wrap:wrap; gap:12px; align-items:stretch; margin-bottom:14px; }
.cf-film-card { background:#fff; border:1px solid var(--cf-line); border-radius:10px;
                padding:13px 15px; display:flex; flex-direction:column; min-width:0; }
.cf-film-card.clip { width:172px; flex:none; padding:13px; gap:8px; }
.cf-film-card.info { flex:1; min-width:min(420px,100%); }
.cf-film-card.titles { width:340px; flex:none; gap:9px; }
.cf-film-lab { font-size:11px; color:var(--cf-ink4); }
.cf-film-thumb { width:100%; aspect-ratio:9/16; border-radius:7px; overflow:hidden;
                 position:relative; background:var(--cf-surface); cursor:pointer; }
.cf-film-thumb img { width:100%; height:100%; object-fit:cover; display:block; }
.cf-film-dur { position:absolute; left:0; right:0; bottom:0; padding:14px 8px 6px; color:#fff;
               font-size:10px; text-align:right; font-variant-numeric:tabular-nums;
               background:linear-gradient(transparent, rgba(0,0,0,.7)); }
.cf-film-play { position:absolute; inset:0; margin:auto; width:38px; height:38px; border-radius:50%;
                background:rgba(255,255,255,.9); display:flex; align-items:center;
                justify-content:center; color:var(--cf-ink); font-size:13px; }
.cf-film-plat { font-size:10px; font-weight:600; color:var(--cf-ink); background:var(--cf-surface);
                border:1px solid var(--cf-line); border-radius:4px; padding:1px 6px; flex:none; }
/* 字段网格。🔴 `align-content:start` 是硬要求（设计稿明写）：用 space-between 去填满
   高度会把 4 行拉出 80px 的行距，读不成一个信息块。**留白比拉开更可接受。** */
.cf-film-grid { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:11px 28px;
                align-content:start; }
.cf-film-f { display:flex; gap:12px; min-width:0; font-size:12px; line-height:1.6; }
.cf-film-f > i { width:76px; flex:none; color:var(--cf-ink4); font-style:normal; }
.cf-film-f > b { font-weight:400; color:var(--cf-ink); min-width:0; overflow:hidden;
                 text-overflow:ellipsis; white-space:nowrap; }
.cf-film-sub { margin-top:13px; padding-top:12px; border-top:1px dashed #F0EFEE; }
.cf-film-stats { display:grid; grid-template-columns:repeat(auto-fit,minmax(96px,1fr)); gap:8px;
                 margin:7px 0; }
.cf-film-stat { border:1px solid var(--cf-page); background:var(--cf-foot); border-radius:7px;
                padding:6px 9px; }
.cf-film-stat i { display:block; font-size:10px; color:var(--cf-ink4); font-style:normal; }
.cf-film-stat b { font-size:14px; font-weight:600; color:var(--cf-ink);
                  font-variant-numeric:tabular-nums; }
.cf-film-chip { font-size:11px; color:var(--cf-ink2); background:var(--cf-surface);
                border-radius:5px; padding:2px 8px; }
.cf-film-skip { border:1px dashed var(--cf-line2); background:var(--cf-foot); border-radius:7px;
                padding:5px 10px; font-size:12px; color:var(--cf-ink3);
                font-variant-numeric:tabular-nums; }
/* —— 标题三选一 —— */
.cf-film-t { font-size:12px; line-height:1.5; border-radius:7px; padding:7px 10px; cursor:pointer;
             border:1px solid var(--cf-line); color:var(--cf-ink15); background:#fff; }
.cf-film-t.on { color:var(--cf-ink); border-color:var(--cf-accent-line); background:var(--cf-soft3); }
.cf-film-t.ro { cursor:default; }
.cf-film-tag { font-size:12px; color:var(--cf-ink2); background:var(--cf-surface);
               border-radius:5px; padding:3px 9px; }
.cf-film-tag.add { background:#fff; border:1px dashed var(--cf-line2); color:var(--cf-ink4);
                   cursor:pointer; }
/* 「改」与「×」：常驻可见，不做 hover 才出现（UI 规范 §8 禁止 hover 才出现的主操作）。
   它们是**次级**动作，所以用最弱的灰，选中态下才跟着变主色。 */
.cf-film-tedit { float:right; margin-left:8px; font-size:11px; color:var(--cf-ink4); }
/* 就地编辑态：与段级台词「改一下」同一套观感（橙边 + 暖白底 + 同字号） */
.cf-film-t.edit { cursor:default; border-color:var(--cf-accent-line); background:var(--cf-soft3); }
.cf-film-tin { width:100%; box-sizing:border-box; font:inherit; font-size:12px; line-height:1.5;
               color:var(--cf-ink); border:1px solid var(--cf-accent-line); border-radius:6px;
               background:#fff; padding:6px 8px; resize:vertical; }
.cf-film-tbar { display:flex; align-items:center; gap:10px; margin-top:6px; }
.cf-film-tbar a { font-size:11px; color:var(--cf-ink3); cursor:pointer; }
.cf-film-tbar a.ok { color:var(--cf-accent); font-weight:600; }
.cf-film-tedit:hover { color:var(--cf-accent); }
.cf-film-t.on .cf-film-tedit { color:var(--cf-accent); }
.cf-film-tagx { margin-left:5px; color:var(--cf-ink4); font-size:12px; line-height:1; }
.cf-film-tagx:hover { color:var(--cf-bad); }
/* 列表「来源切片」列：缩略图 + 标题，两个热区分开 */
.cf-film-src-cell { display:flex; align-items:center; gap:8px; min-width:0; }
/* 来源那一格里的两条路：标题一行、「抖音 ↗」跟在下面（横排放不下，
   而把出站链接挤成省略号里的一截就等于没有）。 */
.cf-film-srcw { min-width:0; display:flex; flex-direction:column; gap:2px; align-items:flex-start; }
.cf-film-srcw > a:first-child { max-width:100%; }
/* 🔴 尺寸与另外四页的 `.cf-row-th` 统一（2026-08-19 用户："来源切片的高度需要和
   其它列表的保持一致"）：原先是 26×34，而候选/灵感/切片/案例都是 56×100 ——
   同一样东西（一条视频的封面）在六个页面里有两种大小，看着像两种东西。
   ⚠️ 行高会从 86 涨到 121，与那四页一致 —— 那正是"一致"的意思。 */
.cf-film-srcth { position:relative; width:56px; height:100px; border-radius:4px; overflow:hidden;
                 flex:none; background:var(--cf-surface); cursor:pointer; display:block; }
.cf-film-srcth img { width:100%; height:100%; object-fit:cover; display:block; }
.cf-film-srcth .ph { display:flex; align-items:center; justify-content:center; width:100%;
                     height:100%; font-size:10px; color:var(--cf-ink4); }
.cf-film-srcth .pl { position:absolute; inset:0; margin:auto; width:22px; height:22px;
                     border-radius:50%; background:rgba(255,255,255,.88); color:var(--cf-ink);
                     font-size:10px; display:flex; align-items:center; justify-content:center; }
.cf-film-tag.src { font-size:11px; color:var(--cf-ink3); background:#fff;
                   border:1px dashed var(--cf-line); border-radius:5px; padding:2px 7px; }
.cf-film-src2 { margin-top:auto; padding-top:11px; border-top:1px dashed #F0EFEE; }
.cf-film-src2 p { font-size:12px; color:var(--cf-ink2); line-height:1.55; margin:5px 0 7px;
                  display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical;
                  overflow:hidden; }
/* —— 逐段成品 —— */
.cf-film-segs { display:flex; flex-direction:column; gap:10px; }
.cf-film-seg { background:#fff; border:1px solid var(--cf-line); border-radius:10px; overflow:hidden; }
.cf-film-segh { display:flex; align-items:center; gap:9px; flex-wrap:wrap; padding:10px 14px;
                background:var(--cf-foot); border-bottom:1px solid var(--cf-surface); }
.cf-film-segno { font-size:13px; font-weight:600; color:var(--cf-accent);
                 font-variant-numeric:tabular-nums; }
.cf-film-segname { font-size:13px; font-weight:600; color:var(--cf-ink); }
.cf-film-srcno { font-size:11px; color:var(--cf-ink3); border:1px dashed var(--cf-line2);
                 border-radius:4px; padding:1px 6px; font-variant-numeric:tabular-nums; }
.cf-film-segb { display:flex; flex-wrap:wrap; align-items:stretch; }
.cf-film-segl { flex:1; min-width:min(420px,100%); padding:13px 15px; }
.cf-film-segr { width:360px; flex:none; border-left:1px solid var(--cf-surface);
                background:var(--cf-foot); padding:13px 15px; }
.cf-film-meta { display:flex; gap:8px; flex-wrap:wrap; align-items:center; font-size:11px;
                margin-bottom:8px; }
.cf-film-meta .ok { font-weight:600; color:var(--cf-ok); }
.cf-film-num { color:var(--cf-ink3); font-variant-numeric:tabular-nums; }
.cf-film-diff { font-size:11px; color:var(--cf-info); background:var(--cf-info-bg);
                border:1px solid var(--cf-info-line); border-radius:5px; padding:1px 7px; }
.cf-film-dirty { font-size:11px; color:var(--cf-accent); background:var(--cf-soft);
                 border:1px solid var(--cf-softline); border-radius:5px; padding:1px 7px; }
.cf-film-body { font-size:16px; color:var(--cf-ink); line-height:1.8; text-wrap:pretty;
                white-space:pre-wrap; }
.cf-film-fix { display:flex; align-items:center; gap:8px; flex-wrap:wrap; margin-top:9px;
               border:1px solid var(--cf-accent-line); background:var(--cf-soft3);
               border-radius:8px; padding:8px 11px; font-size:12px; }
.cf-film-srcline { font-size:13px; color:var(--cf-ink3); line-height:1.75; white-space:pre-wrap; }
/* 徽标：干净 / 有待改。两处（列表列与详情段头）**共用这一对类**，
   分开写必然在某次改色时只改一处，而"干净"与"待改"恰恰是最不该长得像的两个状态。 */
/* 🔴 2026-08-18：这条规则**曾经被插断过**，而且已经上线。
      `.cf-film-ok` 是跨两行写的（`background` 之后换行接 `border`），有人把「投放标记」
      与「加标签输入框」两段整个插进了这两行**中间** ⇒ `.cf-film-ok` 的 `{` 直到 20 行之后
      才闭合，中间那三族（`.cf-tg-in` / `.cf-tg-in:focus` / `.cf-pub` 全家）全被 CSS 解析器
      当成它的垃圾声明**整段丢弃**。
      表现：加标签弹窗里的输入框退化成浏览器裸 input（用户实拍），成品库的「已发布/已投放」
      标记也没有样式 —— 而 DOM 完整、console 零错误、43 套全绿，只有人眼看得出。
      ⇒ 现在 `.cf-film-ok` **写成一行闭合**，插进来的两段挪到它后面。
      由 `verify_cf §74`（声明块里不许再出现 `{`）机械钉住。 */
.cf-film-ok { font-size:12px; color:var(--cf-ok); background:var(--cf-ok-bg);
              border:1px solid var(--cf-ok-line); border-radius:5px; padding:2px 8px; }
/* 投放标记（2026-08-18）：两个独立小开关，灰＝没标、实心＝标了。
   ⚠️ 不用纯颜色区分（色弱看不出），实心底 + 加粗两重差别。 */
.cf-pub { display:inline-flex; gap:5px; }
.cf-pub a { display:inline-flex; align-items:center; justify-content:center;
            width:22px; height:22px; border-radius:5px; cursor:pointer;
            font-size:11.5px; line-height:1; border:1px solid var(--cf-line);
            color:var(--cf-ink4); background:#fff; user-select:none; }
.cf-pub a:hover { border-color:var(--cf-accent-line); }
.cf-pub a.on { background:var(--cf-accent); border-color:var(--cf-accent);
               color:#fff; font-weight:700; }
.cf-pub a.off { cursor:default; opacity:.75; }
.cf-pub a.off:hover { border-color:var(--cf-line); }
/* 裂变数：与那两个标记钮同排，但**不是同一类东西**（那两个是可切的状态、
   这个是一个计数入口）⇒ 用文字链的形状，不用方块钮。 */
.cf-pub-fis { font-size:11px; color:var(--cf-accent); cursor:pointer; white-space:nowrap;
              margin-left:2px; }
.cf-pub-fis:hover { text-decoration:underline; }
/* 加标签弹窗里的输入框。⚠️ `.cf-tg` / `.cf-tg-add`（切片库原来那套标签芯片）已于
   2026-08-18 删除 —— 切片库改用与灵感库同一套 `.cf-idtag` 之后没有任何模板引用了，
   而**死 CSS 是撞名的温床**（铁律 10⑥；`verify_cf §47` 对任何死 `.cf-*` 类判红）。 */
.cf-tg-in { width:100%; box-sizing:border-box; font-family:inherit; font-size:13.5px;
            padding:7px 10px; border:1px solid var(--cf-line); border-radius:7px;
            outline:none; color:var(--cf-ink); }
.cf-tg-in:focus { border-color:var(--cf-accent-line); }
.cf-film-todo { font-size:12px; color:var(--cf-accent2); background:var(--cf-soft2);
                border:1px solid var(--cf-accent-line); border-radius:5px; padding:2px 8px; }
/* ═══ 裂变（2026-08-17，PRD §5.19.14）═══
   刻意**复用** `.cf-film-seg*` 那一整套段卡与 `.cf-film-ok/-todo` 那对徽标：
   裂变的逐段对照与成品的逐段成品是同一种东西（左正文右只读对照），
   另起一套 CSS 就是同一个版式的第二份实现，改一处必漏一处。
   这里只加**裂变独有**的四组：锁定高亮 / 圈定面板 / 套次页签 / 草稿区。
   ⚠️ 锁定用**蓝**（--cf-info 一族）是刻意的：绿已经是「扫雷干净」、红是违禁词、
      橙是全模块的选中/强调色，再借用任何一个都会让两种状态在余光里分不开。 */
.cf-fis-lock { background:var(--cf-info-bg); border-bottom:2px solid var(--cf-info-line);
               color:var(--cf-ink); border-radius:2px; padding:1px 0; }
.cf-fis-lock.gone { background:var(--cf-bad-bg); border-bottom-color:var(--cf-bad-line);
                    color:var(--cf-bad); }
.cf-fis-pick { border:1px solid var(--cf-line); border-radius:8px; background:#fff;
               padding:10px 12px; margin-bottom:8px; }
.cf-fis-pick.all { background:var(--cf-ground); border-style:dashed; }
.cf-fis-pickh { display:flex; align-items:center; gap:8px; flex-wrap:wrap; margin-bottom:6px; }
/* 圈定区的正文：**纯文本 + 一层 <mark>**，没有别的嵌套 —— 拖选偏移量靠遍历
   childNodes 累加得出，容器里一旦有更深的结构，那个累加就得跟着改。
   `user-select:text` 显式写出来：抽屉里别处可能关掉了选中。 */
.cf-fis-src { font-size:14px; line-height:1.9; color:var(--cf-ink1); white-space:pre-wrap;
              user-select:text; cursor:text; }
.cf-fis-tabs { display:flex; gap:7px; flex-wrap:wrap; align-items:center; margin-bottom:10px; }
.cf-fis-tab { border:1px solid var(--cf-line); border-radius:20px; padding:4px 12px; font-size:12px;
              background:#fff; color:var(--cf-ink2); cursor:pointer; display:flex;
              align-items:center; gap:6px; }
.cf-fis-tab.on { border-color:var(--cf-accent); background:var(--cf-soft);
                 color:var(--cf-accent); font-weight:600; }
/* 🔴 `flex:none` 不许删（2026-08-17 本地真数据当场抓到）：`.table-card` 是
   `display:flex; flex-direction:column`，草稿区作为它的 flex 项默认 `flex-shrink:1`
   ⇒ 空间不够时被压成 **2px 的一条缝**（实测 selfH=2 而 scrollHeight=228）。
   最坏的是**文字还在 DOM 里**（innerText 读得到、断言也能过），只有人眼看得出这一区没了。
   同族先例：成品详情页主播放器被压成 263×104、武汉运费页 `flex:1` 贪掉整行。 */
/* 顶部第四张卡：只放概览与入口（2026-08-17 用户拍板从页面底部搬上来）。
   ⚠️ `flex:none` + 定宽：它是 `.cf-film-cards` 这个 row flex 的成员，
   不定宽会跟「整片信息」抢空间；而那一格是两列网格，被抢到 400px 以下就开始折行。 */
/* 放得下就 236px 站在第四格；放不下就自己掉到第二行并占满（`max-width` 防它变成一条长条） */
.cf-film-card.fis { flex:1 1 236px; min-width:236px; max-width:340px; gap:7px; }
.cf-fis-mini { display:flex; align-items:center; gap:6px; flex-wrap:wrap; cursor:pointer;
               border:1px solid var(--cf-line); border-radius:7px; padding:6px 8px;
               background:var(--cf-foot); }
.cf-fis-mini:hover { border-color:var(--cf-accent-line); background:var(--cf-soft3); }
.cf-fis-mini-t { flex:1; min-width:0; font-size:11px; color:var(--cf-ink2); overflow:hidden;
                 text-overflow:ellipsis; white-space:nowrap; }
/* 抽屉里的逐套一行 */
.cf-fis-row { display:flex; align-items:center; gap:9px; flex-wrap:wrap; padding:10px 12px;
              border:1px solid var(--cf-line); border-radius:8px; background:#fff;
              margin-bottom:7px; }
.cf-fis-row.on { border-color:var(--cf-accent-line); background:var(--cf-soft3); }
.cf-fis-sum { cursor:pointer; }
.cf-fis-sum { flex:1; min-width:180px; font-size:12px; color:var(--cf-ink1); overflow:hidden;
              text-overflow:ellipsis; white-space:nowrap; }
.cf-fis-badge { font-size:11px; border-radius:5px; padding:1px 7px; white-space:nowrap; }
.cf-fis-badge.lockok { color:var(--cf-info); background:var(--cf-info-bg);
                       border:1px solid var(--cf-info-line); }
.cf-fis-badge.lockbad { color:var(--cf-warn); background:var(--cf-note-bg); border:1px solid #FDE68A; }
.cf-fis-badge.miss { color:var(--cf-bad); background:var(--cf-bad-bg); border:1px solid var(--cf-bad-line); }
.cf-fis-miss { border:1px dashed var(--cf-bad-line); background:var(--cf-bad-bg2);
               border-radius:8px; padding:11px 14px; font-size:12px; color:var(--cf-bad);
               line-height:1.8; }
/* —— 新建拆解弹窗（2026-08-14 按设计稿重做）：左右两栏 + 脚部复述 —— */
.cf-up-modal .arco-modal-body { padding:0; }
.cf-up-sub { font-size:12px; font-weight:400; color:var(--cf-ink3); margin-left:10px; }
.cf-up { display:flex; flex-wrap:wrap; align-items:stretch; }
.cf-up-col { flex:1 1 380px; min-width:min(380px,100%); padding:16px 20px; }
.cf-up-col + .cf-up-col { border-left:1px solid var(--cf-line); background:var(--cf-work); }
.cf-up-h { display:flex; align-items:center; gap:8px; font-size:13px; font-weight:600;
           color:var(--cf-ink); margin-bottom:11px; }
.cf-up-h > i { width:17px; height:17px; border-radius:50%; background:var(--cf-accent); color:#fff;
               font-size:11px; font-style:normal; font-weight:600; display:flex;
               align-items:center; justify-content:center; flex:none; }
.cf-up-h > em { font-size:11px; font-weight:400; font-style:normal; color:var(--cf-ink4); }
.cf-up-tabs { display:inline-flex; background:var(--cf-surface); border-radius:7px; padding:2px;
              margin-bottom:11px; }
.cf-up-tabs > span { font-size:12px; color:var(--cf-ink2); padding:5px 16px; border-radius:5px;
                     cursor:pointer; }
.cf-up-tabs > span.on { background:#fff; color:var(--cf-ink); font-weight:600;
                        box-shadow:0 1px 2px rgba(28,25,23,.06); }
.cf-up-links { border:1px solid var(--cf-line); border-radius:7px; margin-top:9px;
               max-height:150px; overflow-y:auto; background:#fff; }
.cf-up-link { display:flex; align-items:center; gap:9px; padding:6px 10px; font-size:12px;
              border-bottom:1px solid var(--cf-surface); }
.cf-up-link:last-child { border-bottom:0; }
.cf-up-link .n { color:var(--cf-ink4); font-variant-numeric:tabular-nums; flex:none; }
.cf-up-link .u { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
                 color:var(--cf-ink2); }
.cf-up-link .k { flex:none; font-size:11px; border-radius:4px; padding:1px 7px; }
.cf-up-link .k.kl { color:var(--cf-accent); background:var(--cf-soft); }
.cf-up-link .k.lg { color:var(--cf-ok); background:var(--cf-ok-bg); }
.cf-up-link .k.sh { color:var(--cf-info); background:var(--cf-info-bg); }
.cf-up-foot { display:flex; align-items:center; gap:8px; font-size:11px; color:var(--cf-ink3);
              margin-top:8px; }
.cf-up-foot a { color:var(--cf-accent); cursor:pointer; }
.cf-up-tip, .cf-up-tip2 { font-size:11px; color:var(--cf-ink3); line-height:1.7; margin-top:7px; }
.cf-up-card { border:1px solid var(--cf-line); border-radius:8px; padding:11px 13px; cursor:pointer;
              background:#fff; margin-bottom:8px; }
.cf-up-card.on { border-color:var(--cf-accent); background:var(--cf-soft3); }
.cf-up-card .t { display:flex; align-items:center; font-size:13px; font-weight:600;
                 color:var(--cf-ink); }
.cf-up-card .t .cost { margin-left:auto; font-size:11px; font-weight:400; color:var(--cf-ink3); }
.cf-up-card .s { font-size:11px; color:var(--cf-ink3); margin-top:4px; }
.cf-up-src { display:flex; align-items:center; gap:7px; flex-wrap:wrap; margin-top:11px; }
.cf-up-chip { font-size:12px; color:var(--cf-ink2); border:1px solid var(--cf-line);
              border-radius:6px; padding:4px 11px; cursor:pointer; background:#fff; }
.cf-up-chip.on { color:var(--cf-accent); border-color:var(--cf-accent); background:var(--cf-soft); }
.cf-up-note { font-size:12px; color:var(--cf-ink2); line-height:1.7; border:1px solid var(--cf-line);
              border-radius:7px; background:#fff; padding:9px 11px; }
.cf-up-bar { display:flex; align-items:center; gap:10px; padding:12px 20px;
             border-top:1px solid var(--cf-line); background:var(--cf-foot); }
.cf-up-sum { flex:1; min-width:0; font-size:12px; color:var(--cf-ink1); line-height:1.6; }
.cf-up-sum .p { font-size:11px; color:var(--cf-ink4); }
/* —— 切片级「标题与 tag」（2026-08-14）：整片级、不分段，摆在段落列最上面 —— */
.cf-tt { border:1px solid var(--cf-accent-line); background:var(--cf-soft3); border-radius:10px;
         margin-bottom:14px; overflow:hidden; }
/* 🔴 `gap` 与 `padding` 必须与 `.cf-sgc-row` 逐项相同（2026-08-25）：
   对齐靠的是「左边那一格 392px」，而它右边那个 gap 也算在标题的左边缘里 ——
   卡头原来是 `gap:9px / padding:10px 14px`，段落行是 `10px / 11px 14px`，
   于是标题落在 959、台词落在 960，**差 1px**。
   这种"差一点点"正是最难被看出来的那一种：截图上完全看不出，只有量才知道。 */
.cf-tt-h { display:flex; align-items:center; gap:10px; flex-wrap:wrap; padding:11px 14px;
           background:#fff; border-bottom:1px solid var(--cf-line); cursor:pointer; }
.cf-tt-h:hover { background:var(--cf-ground); }
.cf-tt-h > b { font-size:13px; color:var(--cf-ink); }
/* 卡头左边那一格（2026-08-25）：收起态撑到 `--cf-lead-w`，让右边的标题与
   下面每一段的台词落在同一列上；展开态不撑（那时右边是徽标与元信息，撑开只留一个洞）。
   ⚠️ `--cf-lead-w` 与 `.cf-sgc-lead` 用的是**同一个变量**：对齐这件事只许有一个数。
   🔴 原来这里是 `.cf-tt-fsum` 一家六条（卡头下面单独一行的折叠摘要），2026-08-25 删掉 ——
      用户要的是把标题与 tag 放进卡头**那一行**，不是在下面新增一行。
      版式删了 CSS 就得跟着删（铁律 10⑥：死 CSS 是类名撞车最大的来源）。 */
.cf-tt-h-lead { display:flex; align-items:center; gap:9px; flex:none; }
.cf-tt-h-lead.ali { min-width:var(--cf-lead-w); }
.cf-tt-h-ttl { font-size:13px; color:var(--cf-ink1); font-weight:500; flex:1; min-width:0;
               overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.cf-tt-h-n { font-size:11.5px; color:var(--cf-ink4); flex:none; }
/* 「修辞手法」标签（2026-08-25 用户看过两案后选的 B）：形状、字号、内边距与段头那枚
   组徽标 `.cf-sgc-grp` **逐项相同**，只换成灰色那一档。
   🔴 刻意不与 `.cf-sgc-grp` 同色（那是 A 案，用户否掉）：「钩子」是一个**值**，
      「修辞手法」是一个**字段名** —— 长成同款之后那一行读起来像「钩子、修辞手法」
      是并列的两个类型，而它右边那几枚才是真正的手法值。走灰色与右边的手法芯片
      同色系，一眼看得出「这是那几个芯片的名字」。 */
.cf-skl-lab { font-size:11.5px; color:var(--cf-ink3); background:var(--cf-surface);
              border-radius:var(--r-sm); padding:2px 9px; flex:none; }
.cf-tt-body { display:flex; flex-wrap:wrap; align-items:stretch; background:#fff; }
.cf-tt-col { flex:1 1 320px; min-width:min(320px,100%); padding:12px 14px; }
.cf-tt-col.res { background:var(--cf-ok-bg2); border-left:1px solid var(--cf-line); }
.cf-tt-src { font-size:13px; line-height:1.7; color:var(--cf-ink1); border:1px solid var(--cf-line);
             border-radius:7px; background:var(--cf-ground); padding:9px 11px; margin-top:5px;
             white-space:pre-wrap; }
.cf-tt-tags { display:flex; gap:6px; flex-wrap:wrap; align-items:center; margin-top:5px; }
/* 空态：**带框的占位**，不是一段裸文字 —— 裸文字看起来像"这里本来就没东西"，
   带框看起来像"这一格等着被填"。文案说清它会拿什么去写。 */
.cf-tt-empty { font-size:12px; color:var(--cf-ink3); line-height:1.8; padding:12px 13px;
               border:1px dashed var(--cf-line2); border-radius:7px; background:#fff;
               margin-top:5px; }
.cf-tt-none { font-size:11px; color:var(--cf-accent); background:var(--cf-soft);
              border:1px solid var(--cf-softline); border-radius:5px; padding:1px 7px; }
.cf-hd-n { font-size:11px; color:var(--cf-ink4); font-variant-numeric:tabular-nums; }
.cf-tt-vers { display:flex; align-items:center; gap:7px; font-size:12px; color:var(--cf-ink2);
              margin:2px 0 8px; }
.cf-tt-vers a { color:var(--cf-accent); cursor:pointer; font-size:14px; line-height:1; }
.cf-tt-vers a.off { color:var(--cf-line2); pointer-events:none; }
.cf-tt-more-btn { color:var(--cf-ink4); font-size:15px; line-height:1; padding:0 4px;
                  cursor:pointer; }
.cf-tt-more-btn:hover { color:var(--cf-ink2); }
/* 结果卡：复用段级复刻那套 `.cf-saved-*`，两处观感一致 */
.cf-tt-res .cf-saved-h { display:flex; align-items:center; gap:8px; flex-wrap:wrap;
                         margin:5px 0 8px; }
.cf-tt-res .cf-saved-acts { margin-left:auto; display:flex; gap:10px; }
.cf-tt-res .cf-saved-acts a { font-size:11px; color:var(--cf-ink3); cursor:pointer; }
.cf-tt-res .cf-saved-acts a.hot { color:var(--cf-accent); }
.cf-tt-res .cf-saved-acts a.off { color:var(--cf-ink4); pointer-events:none; }
.cf-tt-meta { display:flex; align-items:center; gap:10px; font-size:11px; color:var(--cf-ink3);
              margin:6px 0 7px; }
.cf-tt-meta a, .cf-tt-mini { font-size:11px; color:var(--cf-accent); cursor:pointer; }
.cf-tt-mini { border:1px dashed var(--cf-accent-line); border-radius:5px; padding:2px 7px; }
.cf-tt-meta a.off, .cf-tt-mini.off { color:var(--cf-ink4); pointer-events:none; }
.cf-tt-row { display:flex; align-items:center; gap:8px; background:#fff;
             border:1px solid var(--cf-line); border-radius:7px; padding:5px 9px; margin-bottom:5px; }
.cf-tt-no { font-size:11px; color:var(--cf-ink4); font-variant-numeric:tabular-nums; flex:none; }
.cf-tt-in { flex:1; min-width:0; border:0; outline:0; background:transparent; resize:none;
            font:inherit; font-size:13px; line-height:1.5; color:var(--cf-ink); padding:0; }
.cf-tt-n { font-size:11px; color:var(--cf-ink4); font-variant-numeric:tabular-nums; flex:none; }
.cf-tt-more { text-align:center; font-size:12px; color:var(--cf-ok); cursor:pointer;
              border:1px solid var(--cf-ok-line); border-radius:7px; padding:5px; margin-top:4px;
              background:#fff; }
.cf-tt-foot { font-size:11px; color:var(--cf-ink3); line-height:1.7; margin-top:8px; }
/* —— 存到成品：选段面板（挂在切片详情页）—— */
.cf-film-pk { display:flex; gap:11px; align-items:flex-start; padding:10px 12px;
              border:1px solid var(--cf-line); border-radius:8px; margin-bottom:8px;
              cursor:pointer; background:#fff; }
.cf-film-pk.on { border-color:var(--cf-accent-line); background:var(--cf-soft3); }
.cf-film-pk.no { cursor:not-allowed; background:var(--cf-ground); }
.cf-film-pk .tx { font-size:12px; color:var(--cf-ink2); line-height:1.7; min-width:0; }
/* ═══ 结论层「这条为什么爆」（设计稿 F）═══
   深色卡是刻意的：它是**结论**，要和下面那一大片浅色的五轨明确分层，
   一眼看得出"上面是答案、下面是证据"。 */
/* ═════════ 详情页头部两行（handoff §1）═════════
   第一行＝这条视频是什么；第二行＝怎么看它。
   上一版把两件事挤进一条 filterbar，按钮换行、密度控件和视频信息混在一起。 */
.cf-hd1, .cf-hd2 { display:flex; align-items:center; gap:10px; min-width:0; flex-wrap:wrap; }
.cf-hd1 { padding-bottom:11px; }
.cf-hd2 { padding-bottom:12px; border-bottom:1px solid var(--cf-page); margin-bottom:14px; }
.cf-hd-back { font-size:12px; color:var(--cf-ink3); white-space:nowrap; cursor:pointer; flex:none; }
.cf-hd-back:hover { color:var(--cf-accent); }
/* 标题**单行截断**（用户 2026-08-12「控制所有的展示就两行」）：
   抖音标题动辄六七十字带一串话题标签，不截断就把 meta 与三个按钮全挤到第二行，
   头部从两行变三行。全文进 title 悬停看。 */
.cf-hd-title { font-size:17px; font-weight:600; color:var(--cf-ink); white-space:nowrap;
               cursor:pointer; flex:0 1 auto; min-width:0; max-width:min(560px, 38vw);
               overflow:hidden; text-overflow:ellipsis; }
.cf-hd-cat { font-size:12px; color:var(--cf-ink2); background:var(--cf-surface);
             border-radius:var(--r-sm); padding:3px 8px; flex:none; }
.cf-hd-meta { font-size:12px; color:var(--cf-ink3); font-variant-numeric:tabular-nums; flex:none; }
.cf-hd-src { font-size:12px; color:var(--cf-accent); cursor:pointer; flex:none; }
/* 右侧动作整组靠右。🔴 不能给单个按钮 `margin-left:auto`——
   换行的 flex 容器里那样会贪掉整行剩余空间，把后面的挤到第二行（report-ui-spec 规 7）。 */
.cf-hd-acts { margin-left:auto; display:flex; align-items:center; gap:8px; flex:none; }
/* 「⋯」里装低频动作（复制整篇台词 / 重新拆解）。收窄内边距：它只是个入口，
   与旁边两个真按钮不同重量。 */
.cf-scope .cf-hd-more { padding:0 9px; font-weight:600; letter-spacing:1px; }
/* 密度三档：自绘分段控件（规范 §7 说密度用 a-radio-group，但那套的高度与这一行的
   开关/文字链对不齐，自绘 22px 一致）。 */
.cf-den { display:inline-flex; border:1px solid var(--cf-line); border-radius:var(--r-md);
          overflow:hidden; flex:none; }
.cf-den > span { font-size:12px; padding:6px 11px; cursor:pointer; color:var(--cf-ink3);
                 background:#fff; border-left:1px solid var(--cf-line); }
.cf-den > span:first-child { border-left:none; }
.cf-den > span.on { color:var(--cf-ink); font-weight:600; background:var(--cf-surface); }
.cf-sw { display:flex; align-items:center; gap:7px; border:1px solid var(--cf-line);
         border-radius:var(--r-md); padding:5px 11px; font-size:12px; color:var(--cf-ink2);
         flex:none; cursor:pointer; }
/* 结论入口：**无边框纯文字**。做成按钮就会变成一屏里的第四个动作，
   而全页只允许三个橙红动作（规范 §2）。 */
/* 🔴 三列必须能换行（2026-08-13）：左右两列是定宽 flex:none，中间那列原先是
   `flex:1; min-width:0` ⇒ 容器一窄就只有它被挤，实测 980 视口下容器只有 664px
   ＝ 320+22+300+22 分毫不差，中间列被压成 **0px**，五个 beat 各剩 18px 的内边距、
   时间码可视宽 0 —— 整条结论横幅的中间列读不出来，而 DOM 完整、console 干净。
   与 68710a8 修的 `minmax(0,1fr)` 是同一族：**没有下限就塌成 0**（规 9.2）。 */
/* 🔴 三列的 flex-grow 是 1 : 1000 : 1，这个悬殊比例是**有意的**，两件事一起要：
   ① 三列同排时富余几乎全给中间的节奏条 —— 1680 实测 320.4/699.3/300.4，
      与改前的 320/700/300 只差 0.4px，宽屏版式原样保留；
   ② 某一列**独占一行**时它是那行唯一的 item，多大的 grow 都吃满整行。
   ②是必须的：换行后还杵在 320px，右边会空掉 344px，文案也白白多折几行 ——
   实测横幅从 359px 涨到 422px，把下面的段卡从 52px 挤成 **0 高**
   （`.cf-detail` 是 overflow:hidden ⇒ 整个段卡区连滚都滚不到）。
   **横向塌陷不许拿纵向空间去换**，那只是把同一族缺陷挪了个方向。
   ⚠️ 三列平分（都写 `flex:1`）实测会在 1680 把节奏条从 700 压到 462.7 ⇒ 五拍变两行，
   等于拿宽屏的好版式去换窄屏。别改回去。 */
/* 一拍最窄到多少还读得下去 ＝ 左右内边距 18px + 时间码一整行（11px tabular-nums，
   本页最长的「24.3—37.0s」实测 61.4px；视频超 100s 时 12 字符约 74px，
   都在 110-18=92px 的内容宽里）。区名 `.cf-beat-z` 有省略号会自己响亮降级，
   时间码没有 —— 一窄就折行，所以地板由**它**定。
   🔴 这是**可读性地板不是版式断点**：别为了"刚好放进 1280"去调它。 */
/* 🔴 原先是 `grid-auto-flow:column; grid-auto-columns:1fr` ＝ **强制一行塞下全部拍子、
   且没有下限**（段数由数据定，五段只是最常见的那个）。auto-fit + minmax 让它
/* 段级结构化标签（设计稿 F）：靠右贴在段头，不抢段名的位置 */
/* 密度三档：纯 CSS 收放，数据一条不少。
   ⚠️ 只收「轨」不收「台词」——台词是这一页的主语，任何一档都得在。 */
/* ═══ 规范 §3.1 状态徽标：七种语义各封一个，业务里不许传裸色 ═══
   规范 §2 的规则比任何 token 表都重要：
   橙红＝要人动一下 · 蓝＝正在跑/只读 · 绿＝成了 · 深色实底＝这是资产不是待办
   · 灰虚线＝不在流程里不催人 · 红＝真异常。 */
.cf-b { font-size:12px; font-weight:600; border-radius:var(--r-sm); padding:3px 8px;
        white-space:nowrap; display:inline-flex; align-items:center; gap:5px;
        border:1px solid transparent; }
.cf-b-idea { color:var(--cf-ink2); background:var(--cf-ground); border:1px dashed var(--cf-ink4); }
.cf-b-run  { color:var(--cf-info); background:var(--cf-info-bg); border-color:var(--cf-info-line); }
.cf-b-done { color:var(--cf-ok); background:var(--cf-ok-bg); border-color:var(--cf-ok-line); }
.cf-b-fail { color:var(--cf-bad); background:var(--cf-bad-bg); border-color:var(--cf-bad-line); }
/* 「还要人改一下」——扫雷有命中、商品资料缺项。**不是失败**（红只给真异常，规范 §2），
   也不是待办色橙红（那三个动作按钮才配）：用中间那档警示橙 --cf-accent2。 */
.cf-b-warn { color:var(--cf-accent2); background:var(--cf-soft2); border-color:var(--cf-accent-line); }
.cf-b-info { background:#e8f3ff; color:#165dff; }   /* 信息色：观众评论触发的回复（2026-09-05） */
.cf-b-dim  { color:var(--cf-ink3); background:var(--cf-surface); border-color:var(--cf-line); }
/* 正交小标「脚本」：与状态徽标**并存不互斥**，三个库里都是这一个标。radius 4px 是
   规范 §3.1 自己写明的例外档（token 表只有 5/7/10/12）。 */
.cf-b-script { font-size:11px; font-weight:600; color:var(--cf-accent); background:var(--cf-soft);
               border:1px solid var(--cf-softline); border-radius:4px; padding:1px 6px;
               white-space:nowrap; }
/* 分析中的脉冲圆点（规范 §3.1） */
.cf-b-dot { width:5px; height:5px; border-radius:50%; background:currentColor;
            animation:cfPulse 1.6s infinite; }
@keyframes cfPulse { 0%,100% { opacity:1 } 50% { opacity:.25 } }
.cf-b-bar { width:56px; height:4px; border-radius:var(--r-sm); background:var(--cf-info-line);
            overflow:hidden; display:inline-block; vertical-align:middle; }
.cf-b-bar > i { display:block; height:100%; background:var(--cf-info); }

/* ═══ 规范 §3.2 按钮四级 ═══
   🔴 **一个页面只许一个橙红实底**（规范 §8）。行内与卡上的三个动作
   （开拆 / ★存入案例库 / 复刻）一律用「主-描边」：白底 + 主色边 + 主色字。
   我上一版把卡上的动作也做成了实底，一页出现两个橙红——那三个动作就都不显眼了。 */
.cf-scope .cf-btn-act, .cf-scope .arco-btn.cf-btn-act {
  background:#fff; border:1px solid var(--cf-accent-line); color:var(--cf-accent);
  font-weight:600; border-radius:var(--r-md); }
.cf-scope .cf-btn-act:hover, .cf-scope .arco-btn.cf-btn-act:hover {
  background:var(--cf-soft); border-color:var(--cf-accent); color:var(--cf-accent-hover); }

/* 规范 §6.3：命中的违规词要**在正文里标出来**，不能只在下面列一张表——
   人改的是正文，而"哪一句里"才是他要找的东西。 */
.cf-vio { background:var(--cf-bad-bg); border-bottom:2px solid var(--cf-bad); padding:0 1px; }

/* 规范 §6.1：注册证号**单独用红框框住**，视觉上和其它字段彻底分开 */
.cf-certbox { border:1px solid var(--cf-bad-line); background:var(--cf-bad-bg2);
              border-radius:var(--r-md); padding:10px 12px; margin-top:10px; }
.cf-certbox .cf-p3-h { color:var(--cf-bad); margin-bottom:7px; }
.cf-cert-note { font-size:12px; line-height:1.7; color:var(--cf-bad); margin-top:8px; }
/* 成品正文的只读标记视图（点一下进编辑） */

/* 规范 §3.3：待处置行加底色，一眼看出哪几行等着人动 */
.cf-scope .arco-table-tr.cf-row-todo .arco-table-td { background:var(--cf-row); }

/* 新建复刻抽屉（设计稿 J）。四步编号 + 卡片式选择，商品与人设都在这里选。 */
/* ═════════ 复刻抽屉（760px，handoff §5）═════════
   三段固定：头（标题+副标 chip+来源卡）/ 体（三步 → 生成中 → 结果）/ 脚（复述+按钮）。 */
/* 🔴 三段固定（头/体/脚）必须用 **flex**，不能靠 `position:absolute; bottom:0` 钉脚。
   absolute 的 bottom 是相对**内容盒**的——内容一长（第 2 步三张人设卡就够了），
   脚就贴在内容底部、跟着一起滚，浮在人设卡中间挡住半屏。上一版正是这么坏的。 */
.cf-rd-drawer .arco-drawer-body { display:flex; flex-direction:column; padding:0; overflow:hidden; }
.cf-rd { flex:1; min-height:0; display:flex; flex-direction:column; }
.cf-rd-scroll { flex:1; min-height:0; overflow-y:auto; padding:15px 22px;
                display:flex; flex-direction:column; gap:4px; }
/* 灵感抽屉：备注吃掉剩余空高（那片空白原来闲在最底下），textarea 跟着长 */
.cf-idnote { flex:1; min-height:0; display:flex; flex-direction:column; }
.cf-scope .cf-idnote .arco-textarea-wrapper { flex:1; min-height:0; }
.cf-scope .cf-idnote textarea { height:100%; resize:none; min-height:118px; }
.cf-rd-sub { font-size:11px; color:var(--cf-ink3); background:var(--cf-surface);
             border-radius:var(--r-sm); padding:2px 8px; white-space:nowrap; font-weight:400; }
.cf-rd-head { background:var(--cf-ground); border:1px solid #F0EFEE; border-radius:9px;
              padding:10px 12px; }
.cf-rd-title { font-weight:600; font-size:14px; margin-bottom:4px;
               white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.cf-rd-hint { font-size:12px; color:var(--cf-accent); margin-top:6px; }
.cf-rd-srow { display:flex; align-items:center; gap:9px; }
.cf-rd-only { margin-left:auto; font-size:11px; color:var(--cf-ink4); }
.cf-rd-lab2 { font-size:11px; color:var(--cf-ink4); margin:9px 0 3px; }
.cf-rd-line { font-size:14px; color:var(--cf-ink); line-height:1.75; text-wrap:pretty; }
.cf-rd-meta { display:flex; gap:16px; margin-top:8px; font-size:11px; color:var(--cf-ink3); flex-wrap:wrap; }
/* 步骤徽章 */
.cf-rd-step { display:flex; align-items:center; gap:9px; margin:14px 2px 8px; }
.cf-rd-no { width:19px; height:19px; border-radius:4px; background:var(--cf-accent); color:#fff;
            font-size:11px; font-weight:600; display:flex; align-items:center; justify-content:center;
            flex:none; font-variant-numeric:tabular-nums; }
.cf-rd-lab { font-weight:600; font-size:13px; }
.cf-rd-must { font-size:11px; color:var(--cf-accent); }
/* 步骤 1 商品 */
.cf-rd-grid { display:grid; grid-template-columns:1fr 1fr; gap:9px; }
.cf-rd-opt { border:1px solid var(--cf-line); border-radius:9px; padding:10px 12px; cursor:pointer;
             background:#fff; min-width:0; }
.cf-rd-opt:hover { border-color:var(--cf-accent-line); }
.cf-rd-opt.on { border:2px solid var(--cf-accent); background:var(--cf-soft3); padding:9px 11px; }
.cf-rd-optname { font-weight:600; font-size:13px; min-width:0;
                 white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.cf-rd-fix { display:inline-block; margin-top:6px; font-size:11px; font-weight:600;
             color:var(--cf-accent); border:1px solid var(--cf-accent-line); border-radius:var(--r-sm);
             padding:2px 8px; background:#fff; cursor:pointer; }
/* 步骤 2 人设：整块高亮 */
.cf-rd-persona { border:2px solid var(--cf-accent-line); background:var(--cf-soft3);
                 border-radius:10px; padding:13px 15px; margin-top:14px; }
.cf-rd-swap { margin-left:auto; font-size:12px; font-weight:600; color:var(--cf-accent); cursor:pointer; }
.cf-rd-pempty { display:flex; align-items:center; gap:12px; background:#fff;
                border:1px dashed var(--cf-line2); border-radius:9px; padding:12px 14px;
                font-size:12px; color:var(--cf-ink3); }
.cf-rd-pempty > span { flex:1; }
/* ═══ 人设选择面板（handoff §6）═══ */
.cf-pp-modal .arco-modal { width:1240px; max-width:100%; }
.cf-pp-grid { display:grid; grid-template-columns:repeat(3,1fr); gap:14px; }
.cf-pp-card { border:1px solid var(--cf-line); border-radius:11px; overflow:hidden;
              background:#fff; cursor:pointer; }
.cf-pp-card:hover { border-color:var(--cf-accent-line); }
.cf-pp-card.on { border:2px solid var(--cf-accent); background:var(--cf-soft3); }
.cf-pp-head { display:flex; align-items:center; gap:8px; padding:12px 14px;
              border-bottom:1px solid var(--cf-surface); }
.cf-pp-card.on .cf-pp-head { border-bottom-color:var(--cf-softline); }
.cf-pp-head b { font-size:14px; }
.cf-pp-on { margin-left:auto; font-size:11px; font-weight:600; color:#fff;
            background:var(--cf-accent); border-radius:4px; padding:2px 7px; }
.cf-pp-body { padding:13px 14px; display:flex; flex-direction:column; gap:10px; }
.cf-pp-body > div { display:flex; flex-direction:column; gap:3px; }
.cf-pp-body label { font-size:11px; color:var(--cf-ink4); }
.cf-pp-body span { font-size:12px; line-height:1.65; color:var(--cf-ink); }
.cf-pp-body span.bad { color:var(--cf-bad); }
.cf-pp-foot { display:flex; align-items:center; gap:10px; margin-top:16px;
              padding-top:14px; border-top:1px solid var(--cf-page); }
.cf-rd-pcard { background:#fff; border:1px solid var(--cf-line); border-radius:9px;
               padding:12px 14px; cursor:pointer; }
.cf-rd-pcard:hover { border-color:var(--cf-accent-line); }
.cf-rd-pcard.on { border:2px solid var(--cf-accent); padding:11px 13px; }
.cf-rd-phead { display:flex; align-items:center; gap:8px; margin-bottom:9px; }
.cf-rd-phead b { font-size:14px; }
.cf-rd-pg { display:grid; grid-template-columns:60px 1fr; gap:7px 12px;
            font-size:12px; line-height:1.6; align-items:baseline; }
.cf-rd-pg > label { color:var(--cf-ink4); font-size:11px; }
.cf-rd-pg > span.bad { color:var(--cf-bad); }
.cf-rd-warn { margin-top:11px; border:1px solid var(--cf-bad-line); background:var(--cf-bad-bg2);
              border-radius:8px; padding:9px 12px; font-size:12px; color:var(--cf-bad); line-height:1.6; }
.cf-rd-warn b { display:block; font-weight:600; margin-bottom:2px; }
/* 步骤 3 范围 */
.cf-rd-segs { display:grid; grid-template-columns:repeat(auto-fill,minmax(140px,1fr)); gap:8px; }
.cf-rd-seg { border:1px solid var(--cf-accent-line); background:var(--cf-soft3);
             border-radius:var(--r-md); padding:7px 9px; }
.cf-rd-seg.dim { opacity:.45; cursor:pointer; border-color:var(--cf-line); background:var(--cf-ground); }
.cf-rd-sws { display:flex; gap:8px; flex-wrap:wrap; margin-top:10px; }
.cf-rd-sw { display:flex; align-items:center; gap:8px; border:1px solid var(--cf-line);
            border-radius:var(--r-md); padding:6px 10px; font-size:12px; color:var(--cf-ink2); }
.cf-rd-sw.done { color:var(--cf-ok); border-color:var(--cf-ok-line); background:var(--cf-ok-bg); }
.cf-rd-swon { font-weight:600; }
/* 生成中 */
.cf-rd-gen { display:flex; flex-direction:column; gap:14px; padding:6px 0; }
.cf-rd-genrow { display:flex; align-items:center; gap:9px; font-size:13px; font-weight:600;
                color:var(--cf-info); }
.cf-rd-pulse { width:7px; height:7px; border-radius:50%; background:var(--cf-info);
               animation:cfPulse 1.6s infinite; flex:none; }
@keyframes cfPulse { 0%,100% { opacity:1 } 50% { opacity:.25 } }
/* 结果 */
.cf-rd-res { display:flex; flex-direction:column; gap:13px; }
.cf-rd-resh { display:flex; align-items:center; gap:8px; }
.cf-rd-resh b { font-size:13px; color:var(--cf-ok); }
.cf-rd-rescard { border:1px solid var(--cf-line); border-radius:10px; padding:13px 15px; background:#fff; }
.cf-rd-resl { display:flex; align-items:center; font-size:11px; color:var(--cf-ink4); margin-bottom:7px; }
.cf-rd-resl a { font-size:12px; font-weight:600; color:var(--cf-accent); cursor:pointer; }
.cf-rd-resbody { font-size:16px; color:var(--cf-ink); line-height:1.8; text-wrap:pretty; }
.cf-rd-resed { width:100%; box-sizing:border-box; font-family:inherit; font-size:16px; line-height:1.8;
               background:#FFFDF9; border:1px solid var(--cf-accent-line); border-radius:8px;
               padding:10px 12px; resize:vertical; outline:none; color:var(--cf-ink); }
.cf-rd-restip { font-size:11px; color:var(--cf-ink4); margin-top:5px; }
.cf-rd-ressrc { margin-top:11px; padding-top:11px; border-top:1px dashed #F0EFEE;
                font-size:12px; color:var(--cf-ink3); line-height:1.6; }
.cf-rd-ressrc > span { font-size:11px; color:var(--cf-ink4); margin-right:8px; }
.cf-rd-scan { display:flex; align-items:center; gap:9px; border:1px solid var(--cf-accent-line);
              background:var(--cf-soft3); border-radius:9px; padding:11px 13px; flex-wrap:wrap; }
.cf-rd-kept { border:1px solid #EFEDEB; background:var(--cf-ground); border-radius:9px;
              padding:11px 13px; display:grid; grid-template-columns:44px 1fr; gap:5px 12px;
              font-size:12px; color:var(--cf-ink2); align-items:baseline; }
.cf-rd-kept > label { color:var(--cf-ink4); font-size:11px; }
/* 脚 */
.cf-rd-foot { flex:none; display:flex; align-items:center; gap:10px;
              padding:13px 22px; border-top:1px solid var(--cf-page); background:var(--cf-foot); }
/* 「保留这一版」是绿的：这一步是「确认成了」，不是「要人动一下」（规范 §2 的分工） */
.cf-scope .cf-btn-keep { background:var(--cf-ok); border-color:var(--cf-ok); color:#fff; font-weight:600; }
.cf-scope .cf-btn-keep:hover { background:#166534; border-color:#166534; color:#fff; }
/* 详情页视频按 9:16 预览（竖屏片在宽栏里会留出两条巨大黑边）。
   🔴 **比例约束不许再叠高度上限**：浏览器会优先满足 max-height，宽度仍是 100%，
   于是比例被悄悄改掉——案例库卡片就是这么变成横的（用户一眼看出"感觉不太对"）。
   要限高就限**外层容器**，别限这个带 aspect-ratio 的元素本身。 */
/* 🔴 `flex:none` 不能少：`.cf-left` 是 column flex 容器，`aspect-ratio` 只给出
   **首选**高度，而默认 `flex-shrink:1` 会在内容装不下时把它压扁——真数据下
   14 张缩略图 + 5 段跳转一撑满，播放器就从 263×467 塌成 263×104（比例 2.5:1）。
   桩数据里左栏内容少、不触发压缩，所以之前一直没暴露。 */
.cf-vwrap { width:100%; aspect-ratio:9/16; background:#000; flex:none;
            border-radius:var(--r-lg); overflow:hidden; display:flex; }
/* 列表缩略图：取不到首帧也**看得见**（占位底 + 播放键），点击播放原片 */
/* ⚠️ `.cf-tb` / `.cf-tb img` / `.cf-tb:hover` 已于 2026-08-18 删除：切片库的缩略图改用
   与灵感库共用的 `.cf-row-th`（56×100，行高也由它决定）之后，那三条没有引用了。
   `.cf-tb-play` 保留 —— 灵感卡与案例卡的播放键还挂着它（与 `.cf-ithumb-play` 同用，
   后者定义在后面、同特异性下赢，所以删掉那条 hover 揭示规则不影响它们）。 */
.cf-tb-play { position:absolute; left:50%; top:50%; transform:translate(-50%,-50%);
              font-size:11px; color:#fff; font-style:normal; opacity:0; transition:opacity .12s; }

/* ═══ 灵感卡：**横向**（左竖屏缩略图 88×156，右内容）═══
   竖屏封面配纵向卡片会让一屏只放得下三四条，而灵感库天生是"攒着的"，
   要一眼扫过很多条。 */
.cf-igrid { display:grid; grid-template-columns:repeat(auto-fill,minmax(340px,1fr)); gap:14px; }
/* ═══ 卡片 / 列表切换 + 列表视图（用户 2026-08-12）═══
   规范 §3.3：表格用 grid 自己写、不用 a-table；**表头与行共用同一份列定义**
   （写在 `.cf-rows-h` 与 `.cf-row` 的共同祖先上），两份列定义必然有一天对不上。 */
/* ── 排序 chip 与浮层（2026-08-19 单元 2）── */
.sortwrap { position:relative; flex:none; }
.sortchip { display:inline-flex; align-items:center; gap:6px; height:32px; padding:0 10px;
            border:1px solid var(--cf-line); border-radius:var(--r-md); background:#fff;
            font-size:12px; color:var(--cf-ink3); cursor:pointer; white-space:nowrap; }
.sortchip:hover { border-color:var(--cf-line2); color:var(--cf-ink2); }
.sortchip > i { font-style:normal; font-size:12px; border:0; background:transparent; font-family:inherit; color:var(--cf-ink4); }
.sortchip b { font-weight:600; color:var(--cf-ink2); }
.sortchip.on { border-color:var(--cf-softline); background:var(--cf-soft); color:var(--cf-accent); }
.sortchip.on > i, .sortchip.on b { color:var(--cf-accent); }
.sortchip .x { font-size:13px; color:var(--cf-accent-line); margin-left:1px; }
.sortchip .x:hover { color:var(--cf-accent); }
.sortpop { position:absolute; right:0; top:38px; z-index:20; width:314px; padding:13px 14px 14px;
           background:#fff; border:1px solid var(--cf-line); border-radius:var(--r-lg);
           box-shadow:0 8px 24px rgba(28,25,23,.12); }
.sortpop-h { font-size:11px; color:var(--cf-ink3); margin-bottom:7px; }
.sortpop-h + .sortpop-g + .sortpop-h { margin-top:13px; }
.sortpop-g { display:flex; flex-wrap:wrap; gap:6px; }
.sortpop .sf, .sortpop .sd { font-size:12px; padding:5px 11px; border-radius:var(--r-md);
           cursor:pointer; border:1px solid var(--cf-line); background:#fff;
           color:var(--cf-ink2); white-space:nowrap; }
.sortpop .sf:hover, .sortpop .sd:hover { border-color:var(--cf-line2); color:var(--cf-ink); }
.sortpop .sf.on, .sortpop .sd.on { border-color:var(--cf-accent); background:var(--cf-soft);
           color:var(--cf-accent); font-weight:600; }
.sortpop .sf .df { font-size:10px; color:var(--cf-ink4); margin-left:4px; font-style:normal; }
.sortpop .sf.on .df { color:var(--cf-accent2); }
.sortpop-f { margin-top:12px; padding-top:10px; border-top:1px solid var(--cf-surface);
             display:flex; align-items:center; gap:9px; font-size:11px; color:var(--cf-ink4); }
.sortpop-f a { font-size:11.5px; }

.cf-view { display:inline-flex; border:1px solid var(--cf-line); border-radius:var(--r-md);
           overflow:hidden; flex:none; }
.cf-view > span { font-size:12px; padding:5px 11px; cursor:pointer; color:var(--cf-ink3);
                  background:#fff; border-left:1px solid var(--cf-line); }
.cf-view > span:first-child { border-left:none; }
.cf-view > span.on { color:var(--cf-ink); font-weight:600; background:var(--cf-surface); }
/* 🔴 `overflow-x:auto` 而不是 `hidden`（2026-08-13，探针实测抓到）：本表是自绘 grid，
   列宽合计放不下时**整个操作列会被静默切掉** —— 1440 视口下少 17px（`⋯` 菜单整个没了，
   里面装着 复制链接/存原片/**删除**），1280 下少 177px（连 开拆/去拆片库 一起没）。
   而 `hidden` 让它既没有滚动条也没有任何报错，DOM 完整、console 干净，只有人眼看得出。
   `auto` 把"看不见且够不着"降级成"看得见的滚动条" —— 响亮失败优于静默错误。
   圆角照旧裁得住（auto 与 hidden 一样按 border-radius 裁）。 */
.cf-rows { border:1px solid var(--cf-page); border-radius:var(--r-lg); overflow-x:auto; }
.cf-rows-h, .cf-row { display:grid; gap:12px; align-items:center; padding:10px 14px; }
.cf-rows-h { background:var(--cf-ground); font-size:11px; color:var(--cf-ink3);
             border-bottom:1px solid var(--cf-page); }
.cf-row { border-bottom:1px solid var(--cf-surface); cursor:pointer; font-size:13px; }
.cf-row:last-child { border-bottom:none; }
.cf-row:hover { background:var(--cf-ground); }
/* 商务千川日志沿用 cf 列表皮肤；宽表可横向滚动，详情保留完整原文。 */
.qc-log-page .cf-rows-h, .qc-log-page .cf-row { min-width:1120px; }
.qc-log-page .cf-rows-h > span, .qc-log-page .cf-row > span {
  min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.qc-audit-text { white-space:pre-wrap; overflow-wrap:anywhere; font:inherit; line-height:1.7; }
.qc-log-json { white-space:pre-wrap; word-break:break-all; font-size:12px; line-height:1.65;
               padding:14px; border:1px solid var(--cf-line); border-radius:8px; background:var(--cf-ground); }
/* 列定义各写一处：表头与行都从这里继承 */
/* ⚠️ 两个 minmax 的**下限**是「压到多窄还读得下去」，不是版式断点：九个定宽列合计 668px，
   加 10 个 12px 间距，原来的下限 220/120 让整行最少要 1128px —— 而 1440 视口（侧栏展开）
   只给得出 1096px，**默认窗口下就已经放不下了**。下限降到 180/100（标题两行截断，
   180px 仍有 13 字左右）后最少 1068px，常见宽度都装得下；真装不下时由上面那条
   `overflow-x:auto` 出滚动条兜住，不再是切掉就算了。
   🔴 改这一行必须连着量一遍：`.cf-rows` 是 `overflow-x` 容器，列宽合计是**唯一**的溢出源。 */
/* 🔴 2026-08-18 用户拍板：勾选**独立成一列**（与候选库那一页一致），不再叠在缩略图上。
   加这一列要付 26 + 12 = 38px，而上面那段算过：11 列时合计已经 1080px，
   1440 视口只给 1098px。所以**从别处匀出这 38px**：
     标题 180→156（仍有 11 字左右）· 时长 52→46（"01:07" 够放）· 备注 90→82。
   改完合计仍是 1080px，一分没多 —— 这个数是量出来的，改这一行必须重算。
   ⚠️ 上一版把勾选叠在缩略图左上角正是为了省这 38px，但那样勾选区只有十几像素、
      还压着封面；候选库那种独立一列点起来明确得多，用户要的就是那个。 */
.cf-rows-insp .cf-rows-h, .cf-rows-insp .cf-row {
  grid-template-columns:26px 56px minmax(156px,1.6fr) 120px 82px 46px 58px 58px minmax(82px,1fr) 96px 72px 96px; }
/* 没有编辑权时不渲染那一格 ⇒ 退回 11 列（少一格会让整行错位一列，而页面不报错） */
.cf-rows-insp .cf-rows-h:not(:has(.cf-row-pick)),
.cf-rows-insp .cf-row:not(:has(.cf-row-pick)) {
  grid-template-columns:56px minmax(156px,1.6fr) 120px 82px 46px 58px 58px minmax(82px,1fr) 96px 72px 96px; }
.cf-row-pick { display:flex; align-items:center; justify-content:center; padding-top:2px; }
.cf-row-sel2 { background:#fff8f5; }
/* 罗盘榜单（2026-08-13，PRD §5.22）。⚠️ 新前缀 `cfr-` 是先 grep 过的（0 处占用）——
   本文件的 CSS 全在一个 <style> 里，同名后写的赢，撞了就是"另一个模块的样式静默套上来"
   （2026-08-12 一轮踩三次）。定宽列合计 516 + 8 个间距 96 + 两个 minmax 下限 276 = 888px。 */
/* 切片库（2026-08-18 用户拍板「展示逻辑参考灵感库，保持相同行高」）。
   🔴 **它此前是 `a-table`，灵感库是自绘 grid —— 两套实现**，于是行高、缩略图尺寸、
      单元格排布各调各的，永远对不齐。用户的原话是「避免反反复复的开发对齐」，
      所以修法不是再对齐一次，而是**收敛到同一套**（Archer 第 2 条：
      同类第二次出现就该收敛，不允许第三个平行实现）。
   ⇒ 行高由共用的 `.cf-row-th`（56×100）决定，与灵感库逐像素相同，不写死 height。
   🔴 **「榜单来源」不再单占一列**，并进切片名列的 `.cf-row-src` 徽标行 —— 与灵感库同一处、
      同一个渲染函数。它原先是 170px 一列，腾出来的宽度给了切片名与拆解规模。
   宽度预算（照 verify_cf 那条断言的量法，1440 视口下可用 1098px）：
     26+56+200+52+132+110+96+160 = 832，加 7 道 12px 间隙 = **916px** ⇒ 富余 182px。
   ⚠️ 无编辑权时勾选那一格整格不渲染（与灵感库同一个写法），所以要有 7 列的那一份。
   ⚠️ **序号列已于 2026-08-18 第二轮删除**（用户「把序号列给删除掉」）：
      灵感库本来就没有它，留着就是两页在最左边又差一格。腾出的 40px 给了切片名与拆解规模。 */
/* 末列 160 → 96（2026-08-19）。⚠️ **此处原注释说的「三个图标一行（3×24 + 2×10 gap = 92）」
   与实际 DOM 对不上**：这一列里是**文字链接**（存案例 / 移出案例库 / 重拆 / 删除），
   不是 24px 图标。按图标算出来的 96px 对文字来说不够，于是它们挤成一团、
   还会在「移出案例库」那种长文案上参差换行（用户 2026-08-20 实拍「排版太密」）。 */
.cf-rows-task .cf-rows-h, .cf-rows-task .cf-row {
  grid-template-columns:26px 56px minmax(200px,1.7fr) 52px 132px minmax(100px,1fr) 96px 92px 96px; }
.cf-rows-task .cf-rows-h:not(:has(.cf-row-pick)),
.cf-rows-task .cf-row:not(:has(.cf-row-pick)) {
  grid-template-columns:56px minmax(200px,1.7fr) 52px 132px minmax(100px,1fr) 96px 92px 96px; }
/* 操作列：**文字链接**，靠右，放不下就换行（用户 2026-08-20：「直接按钮换行就行了」）。
   `gap:2px` 是按"图标按钮"定的，对文字太挤 —— 改成 `行距 6px / 列距 10px`：
   横向回到 `.cf-row-a` 的通用值，纵向给换行留出可读的行距。
   ⚠️ **不收进「⋯」下拉**：用户明确选了换行这条路（删除仍是显式的一项，不藏）。 */
.cf-rows-task .cf-row-a { gap:6px 10px; align-items:center; }

.cf-rows-rank .cf-rows-h, .cf-rows-rank .cf-row {
  grid-template-columns:56px minmax(180px,1.6fr) 120px minmax(96px,0.7fr) 84px 84px 84px 88px; }
/* ═══ 商务 · 达人建联（2026-08-29，PRD §5.31）═══
   四张表各一份列定义，**各写一处**：列头 / 数据行都从这里继承。
   🔴 `.cf-rows` 是 overflow-x 容器，列宽合计是**唯一**的溢出源 —— 改这四行必须连着量一遍。
      **可用宽是量出来的**（不是算的）：1440 视口 `.cf-rows` 内容宽 **1096px**、
      1512 主力视口 1196px、1280 只有 966px（内容工厂那几页在 1280 下也是靠 overflow-x 兜的）。
      下面四行的最小合计（列宽 + 间距，不含行内边距）分别是
      **980 / 812 / 1178 / 946px**（2026-08-29 用户拿掉「曝光 · 千次成交 · 订单」那一列后
      各减 108px —— 那三个数在详情抽屉里照常看得到，只是不占列表的宽度了）。
      ⚠️ 这四个数 2026-08-29 逐个重算过 —— 上一版写的 1060 / 908 / 1018 / 946
         里有两个是错的（tal 与 tcfg），而**写错的数与量过的数在注释里长得一模一样**。
   🔴 只有 tlist 那一行**超过 1096**，是刻意的：用户要它的字段与达人库**逐列一致**
      （2026-08-29），前九列一个像素都没改 + 上榜日期 + 操作 ＝ 11 列。
      **横向滚多少是浏览器里量出来的**（不是拿列宽加出来的 —— scrollWidth 不含右内边距，
      我照算术写过两版，每次都偏大）：1660 视口 **0**、1512 视口 **0**、
      1440 视口 **68px** —— 由 `.cf-rows` 自带的 `overflow-x` 兜住
      （内容工厂那几页在 1280 下也这么兜）。**试过用 sticky 把操作列钉住，撤掉了**，
      理由见下面那段。
   新类名开工前已 grep 过零命中（铁律 10⑥：单文件 CSS 同名后写的赢）。 */
.cf-rows-tal .cf-rows-h, .cf-rows-tal .cf-row {
  grid-template-columns:40px minmax(216px,1.5fr) 76px minmax(96px,0.8fr)
                        minmax(96px,0.8fr) 80px 82px; }
.cf-rows-live .cf-rows-h, .cf-rows-live .cf-row {
  grid-template-columns:40px minmax(216px,1.5fr) 76px minmax(96px,0.8fr)
                        minmax(96px,0.8fr) 80px 82px; }
/* 2026-09-04：「数据源账号」换成「店铺」（账号跟着店走，并进第一列的小字里）。
   宽度不变 —— 店名比账号名短，100px 够；改宽会把规则名那一列压下去。
   ⚠️ 这段注释**不能写进下面那个规则块里**：verify_cf 抠表宽的判据是
      `{` 后紧跟 grid-template-columns，插进去就抠不出这张表（本次实测判红）。 */
.cf-rows-tcfg .cf-rows-h, .cf-rows-tcfg .cf-row {
  grid-template-columns:minmax(240px,1.6fr) 100px 92px 88px 80px 152px; }
/* 🔴 达标名单 ＝ 达人库那十列**逐列同宽**（用户 2026-08-29：「字段要和短视频达人库
   保持一致」）+ 上榜日期 + 操作。前十列一个数都不许改成"差不多"——
   两页是拿来对着翻的，差几像素就会看出错位。 */
.cf-rows-tlist .cf-rows-h, .cf-rows-tlist .cf-row {
  grid-template-columns:40px minmax(216px,1.5fr) 88px minmax(110px,1fr) 76px
                        minmax(96px,0.8fr) minmax(96px,0.8fr) 80px 82px 86px 88px; }
.cf-rows-tpick .cf-rows-h, .cf-rows-tpick .cf-row {
  grid-template-columns: minmax(216px,1.5fr) 76px minmax(96px,0.8fr)
                         minmax(96px,0.8fr) 72px 86px 78px 112px; }
.cf-stat-grid { display:grid; gap:10px; }
.cf-stat { padding:13px 15px; border:1px solid #e5e6eb; border-radius:8px; background:#fff; }
.cf-stat span { display:block; color:#86909c; font-size:12px; margin-bottom:5px; }
.cf-stat b { font-size:22px; color:#1d2129; }

/* 已建联达人库（2026-09-03，PRD §5.31.12）：十四列 ＝ 精选联盟「我的达人库」页面上
   那张表的全部列（用户明确要求「把列表上的所有数据都加上去」）。
   🔴 装不进 1098px 是**必然**的 —— 砍列就是把用户要的东西砍掉。由 .cf-rows 自带的
      overflow-x 兜住，并在 verify_cf 的 OVER 登记表里写明理由 + 此刻实测的上界。
   ⛔ 别用 position:sticky 去钉操作列：实测（§5.31.6.1）会把左邻那一列永久盖住。 */
.cf-rows-tcoop .cf-rows-h, .cf-rows-tcoop .cf-row {
  grid-template-columns: minmax(216px,1.4fr) 84px 104px 112px 88px 80px 88px 88px
                         96px 92px 88px 100px 84px 88px; }
/* 列头里的窗口小字（「近 30 天」）。用 <em> 而不是新起一个 class —— 标签选择器天然
   不会变成"用了却没规则"的那一类，而这个位置全站只有这一处需要小字。 */
.cf-rows-tcoop .cf-rows-h em {
  display: block; font-style: normal; font-weight: 400; font-size: 11px;
  color: var(--muted, #86909c); margin-top: 1px; }
/* ⛔ **操作列试过 `position:sticky; right:0`，撤掉了** —— 别再加回来。
   动机是对的（12 列在 1512 下要横向滚 110px，而滚出去的恰好是本页主操作），
   但**钉住的那一格会把它左边那一列永久盖住**：实测 1512 视口下「判定」整列
   （表头 + 每一行的达标/不达标徽标）**全被压在按钮底下看不见**，
   而「全部名单」这个 tab 里恰恰混着四种判定 ——
   为了少滚一下，换来一列永远看不见，这笔买卖是亏的。
   横向滚是 `.cf-rows` 自带的兜底（内容工厂那几页在 1280 下也这么兜），
   而用户自己的视口（约 1660）装得下这 1314px，压根不会滚。 */
/* 达人头像。图挂了不隐藏、露出底下那个首字兜底 —— 抖音 CDN 有防盗链，
   整列空白时「这个人没头像」与「图加载不出来」在页面上就分不开了。
   ⚠️ 直接用 `<img src>` 走浏览器加载，**服务端不去抓** —— 抓了就要落盘、进备份、
      还要进出网白名单（素材库那条链的代价），而这里只是列表上的一张小图。 */
/* 详情抽屉的字段表**复用内容工厂的 `.cf-idgrid`**（灵感库那个），这里只改两处：
   ① 键列 56px → 68px：本域的键是四个中文字（实测墨迹「带货商家」56px、
      「TOP 商品」61px），56px 下会换行、把右边整段顶下去；
   ② `align-items:start`：本域有几格的值是多行块（TOP 商品的图 + 名字），
      默认的 center 会让键飘在中间。
   ⚠️ 覆盖只作用在 `.tal-dt` 这个抽屉里 —— `.cf-idgrid` 是内容工厂共用的。 */
.tal-dt .cf-idgrid { grid-template-columns:68px 1fr; align-items:start; }
/* 🔴 2026-09-19 用户实报「不支持上下滑」：内容超出视口被 cf-rd-drawer 的 overflow:hidden
   整体裁掉，而内层 .cf-rd-scroll 没拿到有界高度（flex 链在真机上没立起来）。
   保险层：让 body 自己滚 —— 内层 auto 高度就不再产生第二个滚动容器，谁有界都是它滚。 */
.tal-dt .arco-drawer-body { overflow-y:auto; }
.tal-dt .cf-idgrid + .cf-idgrid { margin-top:12px; }
/* 抽屉头像比列表里那个大一圈 */
.tal-ava-lg { width:52px; height:52px; font-size:18px; }
.tal-ava { width:34px; height:34px; border-radius:50%; flex:none; position:relative;
           background:var(--cf-surface); display:flex; align-items:center;
           justify-content:center; font-size:13px; color:var(--cf-ink4); overflow:hidden; }
.tal-ava > img { position:absolute; inset:0; width:100%; height:100%; object-fit:cover; }
/* 带货 TOP 商品：三个小方图并排，悬停看名字与价 */
.tal-prods { display:flex; gap:4px; align-items:center; }
.tal-prods img { width:30px; height:30px; border-radius:5px; object-fit:cover;
                 border:1px solid var(--cf-line); background:var(--cf-surface); }
/* 达人身上的标 —— **复用内容工厂的 `.cf-row-tags` + `.cf-idtag`**（2026-08-29 用户：
   「UI 设计和内容工厂那边统一一下，别搞出来又一套不一样的」）。原先自造的
   `.tal-lb` / `.tal-chips` 把那套数字（11px / padding 1px 7px）手抄了一遍 ——
   手抄出来的一套迟早和被抄的那套漂开，而漂开的样子就是"这一页看着不像同一个系统"。
   这里只留**颜色修饰符**，尺寸/圆角/间距全从 `.cf-row-tags .cf-idtag` 继承。
   两种来源刻意分色，因为它们回答的是两个问题：
   · 蓝＝**我们是靠哪条规则找到他的**（销售额大涨）；
   · 灰＝**平台自己打在他身上的标**（销售额大涨 / 粉丝数大涨），实测 400 条里只有 5 条有；
   · 绿＝**插件在精选联盟详情页查到有联系方式**，并区分有手机号 / 有微信号；
   · 灰＝插件明确确认没有这一类联系方式。未采集保持未知，不挂“无”标签。
   三者都由后端 `_tal_row_tags` 算好逐行下发（按文案去重、命中标优先），前端只画。 */
.cf-row-tags .cf-idtag.hit { color:var(--cf-info); background:var(--cf-info-bg);
                             border:1px solid var(--cf-info-line); }
/* 绿＝插件在详情页查到**有联系方式**（2026-09-02）：它是查出来的事实，不是规则命中也不是平台标 */
.cf-row-tags .cf-idtag.contact { color:var(--cf-ok); background:var(--cf-ok-bg);
                                 border:1px solid var(--cf-ok-line); }
.cf-row-tags .cf-idtag.contact-none { color:var(--cf-ink3); background:var(--cf-surface);
                                      border:1px solid var(--cf-line); }
.cf-row-tags .cf-idtag.cat { color:var(--cf-accent); background:var(--cf-soft);
                             border:1px solid var(--cf-softline); }
/* 表下那段说明。⚠️ **不能叫 `.cf-note`** —— 那个名字 2584 行已经被内容工厂的留言条占了，
   而它是 `display:flex` ⇒ 整段文字会被排成竖条（铁律 10⑥，本次实测撞到）。 */
/* 表下那段常驻说明。**尺寸/颜色照内容工厂的 `.cf-note`**（12px / ink2 / 1.65），
   只是排版是块不是 flex —— `.cf-note` 那个名字已被内容工厂的留言条占着
   （它是 `display:flex`，套上去整段文字会被排成竖条，铁律 10⑥ 实测撞过）。
   ⚠️ 内容工厂把「口径说明」收进了页头 ⓘ 抽屉、页面上不留常驻条；这里留着的两处
      **不是口径而是运维警告**（自动更新已停用 / 平台状态第一期不自动更新），
      收进 ⓘ 里等于埋掉。 */
/* 来源分段控件（2026-08-31）。用户：「我需要两个部分…但是需要标注出来是来自于哪里」
   +「分开 tab 来看」。
   🔴 **刻意做成分段药丸而不是第二排 `.cf-film-tabs`**：内容工厂唯一那个 tab 类是
      下划线 tab，两排一模一样的下划线叠着，视觉上分不出哪排是外层 —— 而这两层
      本来就不同性质（来源＝这批人从哪来，判定桶＝他们处在什么状态）。
   ⚠️ 它落在 `.filterbar` 上而不是页头，因为它就是个筛选维度（`q.src` 那一条 WHERE）；
      判定桶留在最上那排不动。
   ⚠️ `> i` 而不是 `> span`：这一排在 `.filterbar` 里，而那里的 `> span` 另有规则。 */
/* 店铺关联那一行（2026-09-04 按店分）。⚠️ 这个类必须真有规则 ——
   「用了 class 却没有任何规则命中它」是 verify_dead_class 抓的那一类：
   DOM 完整、console 干净，而它宣称自己在管布局，其实靠的是浏览器默认值。 */
/* 弹窗里那个 ⓘ（说明收进它，别常驻占三行 —— 用户 2026-09-04：「旁边信息太多了」）。
   ⚠️ 这个类必须真有规则，否则 verify_dead_class 判红（它宣称自己在管样式，
   实际靠浏览器默认值）—— 当场抓到过一次。 */
.tal-q { width:13px; height:13px; border-radius:50%; border:1px solid var(--cf-ink4);
  color:var(--cf-ink3); font-size:9px; font-style:normal; display:inline-flex;
  align-items:center; justify-content:center; cursor:help; flex:none; }
.tal-srcs { display:inline-flex; gap:4px; background:var(--cf-page); border-radius:7px;
            padding:3px; flex:none; }
.tal-srcs > button { appearance:none; border:0; background:transparent; font:inherit;
                font-style:normal; font-size:12px; color:var(--cf-ink2); cursor:pointer;
                padding:3px 10px; border-radius:5px; line-height:1.5;
                font-variant-numeric:tabular-nums; white-space:nowrap; }
.tal-srcs > button:hover { color:var(--cf-ink); }
.tal-srcs > button.on { background:#fff; color:var(--cf-accent); font-weight:600;
                   box-shadow:0 1px 2px rgba(0,0,0,.06); }
.tal-judge-cell { display:flex; align-items:center; gap:6px; flex-wrap:wrap; }
.tal-judge-cell .arco-btn { padding:0 2px; min-height:24px; font-size:11px; }
.tal-judge-grid { display:grid; grid-template-columns:104px minmax(0,1fr); gap:10px 14px;
                  align-items:start; font-size:13px; line-height:1.65; }
.tal-judge-grid > b { color:var(--cf-ink3); font-weight:500; }
.tal-judge-rules { display:flex; flex-direction:column; gap:8px; }
.tal-judge-rule { padding:9px 11px; border:1px solid var(--cf-line); border-radius:7px;
                  background:var(--cf-page); overflow-wrap:anywhere; }
.tal-pick-tools { align-items:center; }
.tal-pick-tools .tal-srcs { max-width:100%; flex-wrap:wrap; }
@media (max-width: 980px) {
  .tal-pick-tools .tal-srcs { flex-basis:100%; }
  .tal-judge-grid { grid-template-columns:88px minmax(0,1fr); }
}
/* 行上那个来源小标。⚠️ 两条链都取到的人会有**两个**标 —— 这正是要让人看见的
   （`src_kinds` 存的是集合不是单值）。 */
.tal-src1 { font-size:11px; color:var(--cf-ink3); background:var(--cf-page);
            border-radius:4px; padding:1px 5px; white-space:nowrap; flex:none; }
.tal-note { margin-top:10px; font-size:12px; color:var(--cf-ink2); line-height:1.65; }
.tal-note b { color:var(--cf-ink); }
/* 排名徽标：前三名描金，其余素色——榜单的第一信息是名次 */
.cfr-rk { display:flex; flex-direction:column; align-items:center; gap:2px; font-weight:700; }
.cfr-rk > b { font-size:15px; color:var(--cf-ink); line-height:1; }
.cfr-rk.top > b { color:var(--cf-accent); }
.cfr-rk > i { font-style:normal; font-size:11px; font-weight:400; color:var(--cf-ink4); }
/* 指标格：上面一行数、下面一行"区间/精确"的口径标 —— 这一行是全页最容易被误读的地方，
   所以口径**贴在数字底下**，不放在表头的 ⓘ 里（放 ⓘ 里等于没人看见）。 */
.cfr-m { min-width:0; display:flex; flex-direction:column; gap:1px; }
.cfr-m > b { font-weight:600; font-size:13px; color:var(--cf-ink); white-space:nowrap;
             overflow:hidden; text-overflow:ellipsis; }
.cfr-m > i { font-style:normal; font-size:10px; color:var(--cf-ink4); }
.cfr-m > i.ex { color:var(--cf-ok); }
/* 页头「本场已发出」那一格的额度进度条（2026-09-06 设计稿「页头 A」）。
   ⚠️ 起名前查过 `^\.live-bar` 全文 0 命中（铁律 10⑥：单文件里同名后写的赢，
      而撞车的表现是"另一个模块的样式静默套到你的元素上"）。 */
.live-bar { height:5px; border-radius:3px; background:var(--cf-line); overflow:hidden; }
.live-bar > i { display:block; height:100%; background:var(--cf-accent); }
/* 双栏共用自然高度；底部记录区吸收余高，页面仍负责整体纵向滚动。 */
.live-board-columns { display:flex;gap:12px;align-items:stretch; }
.live-board-main { flex:1;min-width:0;display:flex;flex-direction:column;gap:12px; }
.live-board-side { width:352px;flex:none;display:flex;flex-direction:column;gap:12px; }
.live-board-columns > div > .table-card { flex:none; }
.live-board-columns > .live-board-main > .live-board-history,
.live-board-columns > .live-board-side > .live-board-comments { flex:1; }
.live-board-history-body { display:flex;flex-direction:column;flex:1;min-height:0; }
.live-board-history-body > .cf-rows { flex:1 1 0;min-height:520px;overflow-y:auto; }
.live-board-comment-rows { flex:1 1 0;min-height:420px;overflow-y:auto; }
/* 开播台顶部概况（2026-09-06）：四项仍在一张卡里，但每项改成「标题 + 主数」同行、
   解释贴在下一行，并用竖线分组。旧版每项各自从标题、数字、解释往下堆，宽屏时四组字
   散在一整条空白里，眼睛要来回找同一组信息。 */
.live-monitor { border-top:2px solid var(--cf-info-line); }
.live-monitor-head { display:flex;align-items:center;gap:10px;flex-wrap:wrap; }
.live-monitor-title,.live-monitor-link { color:var(--cf-info);white-space:nowrap; }
.live-monitor-sync { font-variant-numeric:tabular-nums;white-space:nowrap; }
.live-monitor-body { padding-top:12px; }
.live-monitor-toggle { display:inline-flex;align-items:center;gap:6px;padding:4px 10px;border:1px solid var(--cf-info-line);border-radius:6px;background:var(--cf-info-bg);color:var(--cf-info);font:inherit;cursor:pointer;white-space:nowrap; }
.live-monitor-toggle:hover { background:var(--cf-info-bg2); }
.live-monitor-toggle:focus-visible { outline:2px solid var(--cf-info);outline-offset:2px; }
.live-monitor-calc { display:grid;grid-template-columns:repeat(4,minmax(170px,1fr));gap:16px;padding:14px;background:var(--cf-info-bg2);border:1px solid var(--cf-info-line);border-radius:8px;overflow-x:auto; }
.live-monitor-calc > div { display:flex;flex-direction:column;gap:5px;white-space:nowrap; }
.live-monitor-calc label,.live-monitor-metrics label { color:var(--cf-ink3);font-size:12px;white-space:nowrap; }
.live-monitor-calc b { font-size:22px;font-variant-numeric:tabular-nums;white-space:nowrap; }
.live-monitor-calc span { color:var(--cf-ink3);font-size:12px;white-space:nowrap; }
.live-monitor-low { border-color:var(--cf-info-line); }
.live-monitor-low > div:first-child b { color:var(--cf-warn); }
.live-monitor-metrics { display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:14px;padding-top:16px; }
.live-monitor-metrics > div { display:flex;flex-direction:column;gap:5px; }
.live-monitor-value { display:flex;align-items:baseline;gap:10px;flex-wrap:wrap; }
.live-monitor-peer { display:inline-flex;align-items:baseline;gap:5px;white-space:nowrap;color:var(--cf-ink3);font-size:12px; }
.live-monitor-peer strong { color:var(--cf-ink2);font-size:12px;font-weight:600;font-variant-numeric:tabular-nums; }
.live-monitor-metrics b { font-size:16px;font-variant-numeric:tabular-nums;white-space:nowrap; }
@media(max-width:850px) { .live-monitor-calc { grid-template-columns:repeat(4,190px); } }
.live-overview { display:grid; grid-template-columns:1.2fr .9fr 1.25fr .8fr;
                 align-items:stretch; margin:0; border-top:1px solid var(--cf-page); }
.live-overview-item { min-width:0; padding:11px 16px 12px; }
.live-overview-item + .live-overview-item { border-left:1px solid var(--cf-page); }
.live-overview-main { min-width:0; min-height:25px; display:flex; align-items:baseline;
                      gap:7px; white-space:nowrap; }
.live-overview-main > label { margin-right:3px; font-size:11px; color:var(--cf-ink4); }
.live-overview-main > b { font-size:20px; line-height:1; font-weight:650; color:var(--cf-ink); }
.live-overview-main > span { min-width:0; overflow:hidden; text-overflow:ellipsis;
                             font-size:11.5px; color:var(--cf-ink3); }
.live-overview-sub { min-width:0; margin-top:5px; overflow:hidden; text-overflow:ellipsis;
                     white-space:nowrap; font-size:11px; color:var(--cf-ink4); }
.live-overview-sub.bad { color:var(--cf-bad); }
.live-overview-sub.warn { color:var(--cf-warn); }
/* 浏览器不支持 Document Picture-in-Picture 时的页内播放器。只在人点「小窗」后出现；
   支持的 Chrome 会直接把同一播放器放进系统小窗，不经过这一层。 */
.live-pip-dock { position:fixed; z-index:1200; right:22px; bottom:22px; width:390px;
                 height:min(700px,calc(100vh - 44px)); display:flex; flex-direction:column;
                 overflow:hidden; border:1px solid #31343a; border-radius:14px;
                 background:#0d0f12; box-shadow:0 18px 55px rgba(0,0,0,.38); }
.live-pip-head { height:44px; flex:none; display:flex; align-items:center; gap:8px;
                 padding:0 11px 0 14px; color:#f5f5f5; background:#191c21; font-size:12px; }
.live-pip-head > b { flex:1; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.live-pip-close { width:28px; height:28px; border:0; border-radius:7px; cursor:pointer;
                  color:#d8dadd; background:transparent; font-size:20px; line-height:26px; }
.live-pip-close:hover { background:#30343b; }
.live-pip-body { position:relative; flex:1; min-height:0; background:#000; }
.live-pip-body > video { width:100%; height:100%; display:block; object-fit:contain; background:#000; }
.live-pip-state { position:absolute; inset:0; display:flex; flex-direction:column; align-items:center;
                  justify-content:center; gap:12px; padding:24px; text-align:center;
                  color:#e7e8ea; background:rgba(8,9,11,.82); font-size:13px; line-height:1.6; }
.live-pip-actions { display:flex; gap:8px; }
/* 展开的视频面板：一行一条，缩略信息 + 打开 + 存灵感 */
.cfr-vp { padding:4px 14px 12px 70px; background:var(--cf-ground);
          border-bottom:1px solid var(--cf-surface); }
/* 勾选格 26px 是 2026-08-19 单元 5 加的（批量存灵感）。
   ⚠️ **没有编辑权时那一格不渲染** ⇒ 必须有第二份定义退回 5 列，
      少一格会让整行错位一列而页面不报错（同 `.cf-rows-*` 那几套的先例）。 */
.cfr-v { display:grid; grid-template-columns:26px 26px minmax(0,1fr) 140px 92px 128px; gap:10px;
         align-items:center; padding:6px 0; font-size:12px; }
.cfr-v:not(:has(.cfr-pick)) {
  grid-template-columns:26px minmax(0,1fr) 140px 92px 128px; }
.cfr-pick { display:flex; align-items:center; justify-content:center; }
.cfr-v + .cfr-v { border-top:1px dashed var(--cf-line); }
.cfr-v > .n { color:var(--cf-ink4); }
.cfr-v > .t { min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
              color:var(--cf-ink); }
.cfr-v > .a { min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
              color:var(--cf-ink3); }
.cfr-v > .d { color:var(--cf-ink4); }
.cfr-v > .ops { display:flex; gap:6px; justify-content:flex-end; }
/* 三条口径的常驻说明条。**不做成可关闭的**：关掉之后新同事看到的就是一张
   没有任何口径标注的榜单，而区间值与 Top10 这两件事一旦被当成精确值/全量，
   得出的结论会是反的。 */
/* API Key 页的 bridge 型 provider 说明块（2026-08-14，灰豚数据桥）。
   前缀 `ifb-` 起名前 grep 过，0 处占用（铁律 10⑥：单文件 CSS 同名后写的赢）。 */
.ifb-box { border:1px solid var(--cf-line, #e5e6eb); border-radius:8px; padding:10px 13px;
           margin-bottom:12px; background:#fafafa; font-size:12px; line-height:1.75; }
.ifb-row { display:flex; gap:10px; }
.ifb-row + .ifb-row { margin-top:7px; padding-top:7px; border-top:1px dashed #eceef0; }
.ifb-k { flex:0 0 44px; color:#86909c; font-weight:600; }
.ifb-row > span:last-child { flex:1; min-width:0; color:#4e5969; }
.ifb-shoprow { display:flex; align-items:center; gap:8px; flex-wrap:wrap; padding:5px 0; }
.ifb-shoprow + .ifb-shoprow { border-top:1px dashed #eceef0; }
/* ── 「抖音店铺」卡的店铺表格（2026-09-05 合并重构，PRD §5.31.18；照原型 .sbox）── */
.dsh-box { border:1px solid #e5e6eb; border-radius:8px; margin-bottom:12px; background:#fff;
           overflow:hidden; font-size:12px; line-height:1.75; }
.dsh-hd, .dsh-row { display:grid; gap:10px; align-items:center; padding:9px 13px;
           grid-template-columns:160px 300px 340px 1fr 84px; }
.dsh-hd { background:#fafafa; border-bottom:1px solid #eceef0; color:#86909c;
          font-weight:600; font-size:11.5px; padding:8px 13px; }
.dsh-row + .dsh-row { border-top:1px dashed #eceef0; }
.dsh-cell { display:flex; align-items:center; gap:8px; flex-wrap:wrap; min-width:0; }
.dsh-foot { font-size:11.5px; color:#86909c; padding:9px 13px; background:#fafafa;
            border-top:1px solid #eceef0; line-height:1.85; }
/* 三条口径已搬进**右侧口径抽屉**（2026-08-18 用户：「放到右侧抽屉里面去」），
   见 `PAGE_CALIBER_DETAIL.cf_rank`。页面上那块提示条与它的 CSS 一并删掉 ——
   删版式就要把 CSS 一起删，留着就是死 CSS，而死 CSS 正是本文件类名撞车的成因
   （铁律 10⑥；`verify_cf §47` 对任何死 CSS 判红）。 */
/* 自动取数总开关：关掉时整条变红底，因为"今晚一条都不抓"是个会被忘掉的状态，
   而罗盘的历史取不回来 —— 忘一周就永久少一周。 */
.cfr-auto { display:flex; align-items:center; gap:8px; padding:4px 11px 4px 8px;
            border:1px solid var(--cf-ok-line); background:var(--cf-ok-bg);
            border-radius:var(--r-md); font-size:12px; }
.cfr-auto > b { font-weight:600; color:var(--cf-ink); }
.cfr-auto > em { font-style:normal; color:var(--cf-ink3); }
.cfr-auto.off { border-color:var(--cf-bad-line); background:var(--cf-bad-bg); }
.cfr-auto.off > em { color:var(--cf-bad); }
/* 数据源账号 tab（2026-08-17，PRD §5.22.7）。照财务的 .src-tabs 形状，但用 --cf-* 令牌
   —— 内容工厂这几页整套是 cf 设计语言，套财务那份硬编码色会在这一页上显得是另一个系统。
   ⚠️ 容器 `flex-wrap` + 右侧提示 `margin-left:auto`：铁律 10⑤ 那条，
      不定宽的元素要么给 min-width 要么别让它参与抢空间。 */
/* 榜单页的筛选条：数据源 tab + 筛选 + 口径 + 按钮**同一行**（2026-08-18）。
   🔴 靠 `flex-wrap` 折行，不靠硬挤（铁律 10⑤ 与它反向的那一半）：
      宽屏一行；窄屏**折的是右侧那组**（它有 margin-left:auto），
      而不是把类目下拉压瘪 —— 被压瘪的那个恰好是最需要看全的那个。 */
.cfr-bar { row-gap:8px; }
/* 口径那一格：**这一行里唯一可伸缩的东西**。宽屏吃掉剩余空间把摘要显示全，
   窄屏自己截断成「…」，从而既"收成一行"又不牺牲"摘要看得见"。
   `min-width:0` 是 flex 子项能被压下去的前提（不写它 `text-overflow` 不生效）。 */
/* 右侧那组（重置 / 导出 / 立即抓一次）：`margin-left:auto` 靠右成组，
   折行时**整组一起掉下去**，不会出现"按钮掉了一半"，也不会去挤类目那一格
   （铁律 10⑤ 反向那一半：被啃的永远是不定宽的那个）。 */
.cfr-right { display:flex; align-items:center; gap:10px; flex:none; margin-left:auto; }
/* 「数据源」那个前缀标签。⚠️ 它曾被按 `.cfr-tab` 前缀批量删 CSS 时误删过一次
   （`.cfr-tabs-l` 也以 .cfr-tab 开头）—— 表现是"有 class 没样式"，页面不报错。
   按前缀批量删规则时，先把命中清单打出来看一眼。 */
.cfr-tabs-l { color:var(--cf-ink4); margin-right:4px; font-size:12px; flex:none; }
/* 数据源 tab（2026-08-18 从多选下拉退回）：与财务模块「店铺横向 tab」同形，
   但用 --cf-* 令牌 —— 内容工厂这几页整套是 cf 设计语言。 */
.cfr-tab { cursor:pointer; user-select:none; padding:4px 14px; border-radius:var(--r-md);
           font-size:13px; border:1px solid var(--cf-line); background:var(--cf-surface);
           color:var(--cf-ink2); flex:none; white-space:nowrap; }
.cfr-tab:hover { color:var(--cf-accent); }
.cfr-tab.on { color:var(--cf-accent); border-color:var(--cf-accent); font-weight:600;
              box-shadow:0 0 0 1px var(--cf-accent) inset; }
/* 数据源与筛选之间的竖线：让"选哪个号"和"筛什么"在视觉上仍是两件事 */
/* 数据源那一组：挂在页签行右端（2026-08-20）。`margin-left:auto` 靠右成组，
   `padding-bottom` 让它与页签的下边框对齐（页签自带 9px 的 padding-bottom）。 */
.cfr-src { margin-left:auto; display:flex; align-items:center; gap:8px; padding-bottom:6px; }
/* 动作组挪到页签行之后：不再靠 margin-left:auto 抢空间（那一行左边只有三个页签，
   .cfr-src 已经把自己推到右端了），它跟在数据源后面即可；padding-bottom 与页签对齐。 */
.cf-film-tabs > .cfr-right { padding-bottom:6px; margin-left:10px; }
/* 「不进候选」小标：这个类目跟的窗口不是回捞吃的那个 ⇒ 看榜正常但不产生候选 */
.cfr-nocand { font-style:normal; font-size:10px; color:var(--cf-ink4); margin-left:5px;
              padding:1px 5px; border:1px solid var(--cf-line); border-radius:3px;
              cursor:help; white-space:nowrap; }
/* 失败原因摊开写（Cookie 过期是最常见也最该被看见的失效） */
.cfr-errs { margin-top:10px; padding:9px 13px; border:1px solid var(--cf-bad-line);
            background:var(--cf-bad-bg); border-radius:var(--r-md); font-size:12px;
            color:var(--cf-ink2); line-height:1.7; }
.cfr-errs > b { display:block; color:var(--cf-bad); font-weight:600; margin-bottom:2px; }
.cfr-errs span { color:var(--cf-ink); font-weight:600; margin-right:6px; }
/* 可排序的表头：只有能点的那几个带手型，不能点的不带——
   全都带手型会让人以为「备注」也能排。 */
.cf-rows-h > .s { cursor:pointer; user-select:none; }
.cf-rows-h > .s:hover { color:var(--cf-accent); }
/* 标题两行 + 底下一行原链接 */
.cf-row-tt { min-width:0; display:flex; flex-direction:column; gap:2px; }
.cf-row-tt > b { font-weight:400; font-size:13px; color:var(--cf-ink); line-height:1.45;
                 display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical;
                 overflow:hidden; }
.cf-row-tt > a { font-size:11px; color:var(--cf-accent); align-self:flex-start; }
/* 「这条是哪来的」那一行（2026-08-18 用户需求）。
   🔴 **必须写在 `.cf-row-tt` 那一族之后**：第一版写在文件上方 840 行处，被这里
      `.cf-row-tt` 的 flex 规则接管，`white-space:nowrap` 根本没生效 ⇒ 来源摘要换成三行、
      行高从 81px 撑到 110px。**是量出来才知道的**，肉眼只觉得"有点挤"。
      同一个文件里 CSS 后写的赢 —— 位置本身就是语义（铁律 10⑥ 的同族）。
   一行内截断：来源摘要动辄三四十字，换行会让一屏看不到几条；全文在 title 里。 */
.cf-row-tt > em.cf-row-src { display:block; font-style:normal; font-size:11px;
              color:var(--cf-ink4); line-height:1.5; margin-top:1px; max-width:100%;
              overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
/* 裂变库主列的副行＝这一套的**首句**（2026-08-20）。形态与 `.cf-row-src` 一样是
   "主行底下一行淡字、单行截断"，但**另起一个类**：那个类专说"这条是哪来的"，
   语义不同，共用会让以后改其中一个时误伤另一个。
   🔴 同样**必须写在 `.cf-row-tt` 那一族之后**（后写的赢）—— 见上面那段的教训。 */
.cf-row-tt > em.cf-fis-first { display:block; font-style:normal; font-size:11px;
              color:var(--cf-ink4); line-height:1.5; max-width:100%;
              overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.cf-row-src > i { font-style:normal; display:inline-block; font-size:10px; line-height:1.5;
              padding:0 4px; border-radius:3px; margin-right:4px;
              background:var(--cf-ground); color:var(--cf-ink3); }
/* 店铺榜单（丽医生 / 红桃K）用强调色：它是"哪个号抓来的"，与来源类型不是一回事 */
.cf-row-src > i.cf-row-srca { background:var(--cf-soft); color:var(--cf-accent); font-weight:600; }
/* 标签那一行（2026-08-18 从备注列挪过来）：芯片形态 + 可就地加删，末尾跟着原链接。
   `flex-wrap` 让标签多时换行 —— 行高本来就跟着缩略图（100px），有余量。 */
.cf-row-tags { display:flex; align-items:center; gap:4px; flex-wrap:wrap; margin-top:3px; }
/* 列表行里的标签**复用 `.cf-idtag`**（与详情抽屉同一套），这里只把尺寸压小一档 ——
   抽屉那份是 12px / 3px 9px，一行 100px 高的列表塞不下。
   🔴 改的是"在这个容器里"的尺寸，不动 `.cf-idtag` 本身：那会把抽屉里的一起改小。 */
.cf-row-tags .cf-idtag { font-size:11px; padding:1px 7px; gap:4px; }
.cf-row-tags .cf-idtag i { font-size:11px; line-height:1; }
.cf-row-link { font-size:11px; color:var(--cf-accent); margin-left:2px; white-space:nowrap; }
/* 灰豚取数状态的行内标记（2026-08-18，从顶部横幅挪到出问题的那一行上） */
.cf-hu-bad { display:inline-block; margin-left:5px; font-size:10.5px; line-height:1.6;
             padding:0 5px; border-radius:4px; cursor:pointer; background:#fff2e8;
             color:#d4380d; border:1px solid #ffbb96; }
.cf-hu-bad:hover { background:#ffe7db; }
.cf-hu-wait { display:inline-block; margin-left:5px; font-size:10.5px; line-height:1.6;
              padding:0 5px; border-radius:4px; background:var(--cf-ground);
              color:var(--cf-ink4); }
/* 两行一格：主值 + 灰色小字（作者·粉丝 / 存的人·存入） */
.cf-row-au { min-width:0; display:flex; flex-direction:column; gap:1px; }
.cf-row-au > b { font-weight:400; font-size:12px; color:var(--cf-ink2);
                 white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.cf-row-au > i { font-size:11px; font-style:normal; color:var(--cf-ink4);
                 font-variant-numeric:tabular-nums; }
/* 🔴 标题列要有**下限**（2026-08-13 探针实测）：原来是 `minmax(0,1fr)`，而八个定宽列
   合计 596px、加 8 个 12px 间距共 692px —— 容器一旦窄于这个数，`1fr` 就被压成 **0px**，
   **整列标题凭空消失**（980 视口实测正是 0px），而点赞/评论那几列还好端端地显示着，
   页面零报错。给 180px 的下限后它不再塌，放不下就由 `.cf-rows` 的 `overflow-x:auto`
   出滚动条 —— 宁可滚，也不要让人对着一排没有标题的数字发呆。 */
/* 候选库（2026-08-19 单元 1c，cd-row → cf-rows）：四个数值各占一列。
   ⚠️ 此处原注释写的「866 + 120 = 986」是**旧数**，按当时的列串实算是 816 + 120 = 936。
   🔴 **「发布」不占一列，并进标题格**（2026-08-20 用户拍板，箭头指的就是那儿）。
   先做过一版独占一列（76px）—— 真浏览器量出来：1440 视口容器 1128px 只余 **14px**，
   1280 视口容器 968px **溢出 70px**（加这列之前 936 还装得下）。列预算本来就见底了，
   而"发布"属于"这一行是什么"，与足迹/来源徽标同一格最顺（同足迹那条并列的先例）。 */
.cf-rows-cand .cf-rows-h, .cf-rows-cand .cf-row {
  grid-template-columns:26px 56px minmax(180px,1.6fr) 116px 52px 52px 52px 52px 92px 62px 76px; }
.cf-rows-cand .cf-rows-h:not(:has(.cf-row-pick)),
.cf-rows-cand .cf-row:not(:has(.cf-row-pick)) {
  grid-template-columns:56px minmax(180px,1.6fr) 116px 52px 52px 52px 52px 92px 62px 76px; }
/* 候选行标题格里的「发布 YYYY-MM-DD」（2026-08-20）：与同一行的足迹/来源徽标同一档灰度，
   `tabular-nums` 让不同行的日期竖着对齐。它是"这条多新"的旁注，不该抢标题的注意力。 */
.cf-row-pub { font-size:11px; font-style:normal; color:var(--cf-ink4); white-space:nowrap;
              font-variant-numeric:tabular-nums; flex:none; }

/* 脚本档：成品库（`.cf-rows-scr`）与裂变库（`.cf-rows-fis`）。
   🔴 **2026-08-19 拆开了**：此前共用一份定义，理由是"两张表列数相同、宽度逐值相同"——
      而同日裂变库去掉了「锁定」列（用户："这个锁定列是没有用的"），**那个前提没了**。
      列数不同还共用一份，表现是其中一页整行错位一列而页面不报错。
      ⚠️ 拆开不是回到"各写各的"：两者仍逐值对齐，只是裂变少一格、并把那 88px
         还给了脚本列（它要摆首句，是全表最需要宽度的一列）。
   成品：勾选 · 成品 · 来源切片 · 商品 · 谁在说 · 扫雷 · 投放 · 创建 · 操作 = 9
   裂变：勾选 · 脚本 · 源成品 · 商品 · 谁在说 · 扫雷 · 创建 · 操作 = 8 */
/* 🔴 第 2/3 列的宽度 2026-08-19 重新分配（用户："可以往左移过去，让原标题展示更多出来"）。
   **量出来的**：成品名那一列 266px 而四行内容一条都没截（成品名都在 20 字以内），
   来源切片 150px 却**四行全截** —— 而它摆的是原视频标题，本来就是长的那一列。
   而且那一格里还有个 56px 的缩略图 + 8px gap，文字实际只剩 86px。
   ⇒ 成品名 1.7fr→1fr（下限 200→180），来源切片 150→minmax(216px,1.4fr)。
   列下限合计 980 + gap 96 = 1076 ≤ 1098（verify_cf 的 AVAIL），余 22px。 */
/* 🔴 2026-08-20 用户实拍：「来源切片列的标题太长了，缩短一下」「来源切片和成品列的
   间距太大了」。**两句说的是同一个结构性成因**，不是两处随手调数字：
   两个弹性列此前是 `1fr` / `1.4fr` ⇒ 宽屏下把富余**按比例**摊给它们俩，
   而成品名的内容根本用不了那么宽。1744 视口生产真数据实测：
     成品 300px（最长一条墨迹 236px ⇒ 右边空 64px，最短那条空 **172px**＝用户看到的"间距"）
     来源切片 420px（7 行 7 截 —— 它摆的是原视频标题，本来就长，给再多也是截）
     商品 110px（**3 行被截**，最长那条商品名 60 字）
   ⇒ 改成**每一列都有上界**：成品 ≤260（最长的成品名墨迹 236px，再宽就是纯空档）、
     来源切片 ≤330（文字 ≈266px，比 420 短但仍读得出前 20 字）、
     商品 ≤160（它 2026-08-20 起摆两行：商品名 + 「商品 ↗」出站 chip，
     而商品名自己**两行封顶**⇒160px 就读得出 26 字，见 `.cf-prod-n` 那段）。
   🔴 **富余落到末列（操作）而不是塞给某一个内容列** —— 这是本次最要紧的取舍：
      随便挑一列给 `1fr`，就只是把空档从"成品↔来源切片之间"挪到"那一列↔它右邻之间"，
      用户一样看得见（我第一版把富余给了商品，实测 240px 而短商品名只有 96px 墨迹 ⇒
      商品↔谁在说 之间凭空多出 144px，等于把刚修的毛病换了个位置犯一遍）。
      落在末列时它表现为**表格右边距**：`.cf-row-a` 是 `justify-content:flex-end`，
      「删除」照旧贴右边缘，中间那点空白读起来就是"这张表用不了这么宽"，而不是一个断层。
   ⚠️ 1440 视口下三个弹性列全在下限（180/216/110），与改前**逐像素相同** ——
      这一改**只在宽屏生效**，窄屏一个字节都没动。
   列下限合计 980 + 8×12 = 1076 ≤ 1098（verify_cf 的 AVAIL），与改前同值。 */
/* ⚠️ 2026-08-24：商品列 110→146（装整行高的商品图），从「来源切片」匀 36px 过来
   （216→180），列下限合计一分不变（1076px）。⛔ 别只加宽不匀（铁律 10⑤）。
   ⚠️ 注释只能写在规则**外面** —— 写在 `{` 与第一条声明之间虽然是合法 CSS，
      但 `verify_cf` 的列定义解析器按 `{\s*grid-template-columns:` 抠，当场抠不出来。 */
.cf-rows-scr .cf-rows-h, .cf-rows-scr .cf-row {
  grid-template-columns:26px minmax(180px,260px) minmax(180px,330px) minmax(146px,190px) 84px 88px 88px 92px minmax(96px,1fr); }
.cf-rows-scr .cf-rows-h:not(:has(.cf-row-pick)),
.cf-rows-scr .cf-row:not(:has(.cf-row-pick)) {
  grid-template-columns:minmax(180px,260px) minmax(180px,330px) minmax(146px,190px) 84px 88px 88px 92px minmax(96px,1fr); }
/* 裂变库同批（2026-08-20）：源成品那一格从**一行链接**变成「缩略图 + 标题 + 出站 chip」
   （用户："源成品列需要补上对应的成品的视频，且支持跳转，和成品页那个一样"）⇒
   150px 装不下（56px 缩略图 + 8px gap 之后只剩 86px，实测已经 3 行 3 截），
   与成品库「来源切片」那一列**取同一个档**（两格现在是同一样东西，同一套类渲染）。
   脚本列 2.2fr → 上界 420：它此前 670px，而主行现在是**脚本名**、副行才是首句，
   用不了那么宽。富余同样落到末列（理由见上面成品库那一段）。
   列下限合计 26+288+216+110+84+88+92+96 = 1000 + 7×12 = 1084 ≤ 1098。 */
/* ⚠️ 与成品库同一次改动（2026-08-24）：商品列 110→146（装整行高的商品图），
   从「来源切片」匀 36px 过来（216→180），列下限合计一分不变（1084px）。
   ⛔ 别只加宽不匀 —— 那会让 1440 默认宽度下右边几列被切掉（铁律 10⑤）。 */
.cf-rows-fis .cf-rows-h, .cf-rows-fis .cf-row {
  grid-template-columns:26px minmax(288px,420px) minmax(180px,330px) minmax(146px,190px) 84px 88px 92px minmax(96px,1fr); }
.cf-rows-fis .cf-rows-h:not(:has(.cf-row-pick)),
.cf-rows-fis .cf-row:not(:has(.cf-row-pick)) {
  grid-template-columns:minmax(288px,420px) minmax(180px,330px) minmax(146px,190px) 84px 88px 92px minmax(96px,1fr); }
.cf-rows-fis .cf-row { padding-top:9px; padding-bottom:9px; }
/* 这一档没有封面 ⇒ 行高由三行文本决定，不必给 100px 的缩略图留位 */
.cf-rows-scr .cf-row { padding-top:9px; padding-bottom:9px; }
/* 🔴 2026-08-20 用户实拍两条：「类型判断整段字符不要被挡住」「段+花字+音效 参考切片库」。
   ⇒ 10 列改 8 列：段/花字/音效三格并成一格「拆解规模」（与切片库同名同形，
     卡片视图那半本来就是这么写的 —— 两个视图此前一个合一个分）。
   量出来的（1744 视口、生产真数据）：
     · 类型判断 132px，最长那条「单品深度种草+用法教程型带货」14 字 ≈ 168px ⇒ **1 行被截**；
       给**定宽 184px**（＝那 168px 再留一点）：常见值一行放得下，更长的就换行
       （`.cf-row-w` 不截断，行高由 100px 的缩略图定、塞得下两三行）。
       🔴 **不给它 1fr、也不给上界很高的 minmax**：这一列一旦跟着窗口长，标题列就被它吃掉。
          第一版写的是 `minmax(180px,240px)`，1440 视口下它顶到 240 而内容只有 168 ——
          白占 72px，标题列从 ~370 被压到 258。**上界要按内容定，不是随手给一个大数。**
     · 拆解规模 150px：切片库同一串文字实测最宽墨迹 148px（「场景 5 · 花字 24 · 音效 40」）。
       三格并一格本来就占 42×3+12×2=150 —— **一分没多**。
     · 存入 88→96：这一格从"只有时间"变成「存入人 · 时间」两行（`.cf-row-au`），
       96 与切片库「创建人 · 创建」**同一个数**（同一样东西给同一个宽度）。
   🔴 **1280 视口要复量一遍**：这一版第一稿给了 156/110，合计 962px，而 1280 下
      这张表的可用内容宽实测只有 **936px** ⇒ 凭空多出一条横向滚动条，
      而改前（882px）是不滚的。**"≤1098"那条断言只管 1440，管不了 1280** ——
      窄屏是不是比改前更差，只能自己去量。现在 942px，仍留 -6px 余量。
   列下限合计 858 + 7×12 = **942px ≤ 1098**（verify_cf 那条上限），且 ≤ 1280 下的 936+ 余量。 */
/* 脚本库（2026-08-22，PRD §5.19.28）。两套网格跟着现有 .cf-rows-* 的形状走 ——
   内容工厂全域已经收敛到自绘 grid，这一页不许再引一张 a-table 回来（那是财务域的形态）。 */
.cf-rows-frame .cf-rows-h, .cf-rows-frame .cf-row {
  grid-template-columns:30px 38px minmax(200px,1.4fr) 92px 84px 72px 84px 104px; }
.cf-rows-ex .cf-rows-h, .cf-rows-ex .cf-row {
  grid-template-columns:30px minmax(180px,1.5fr) 86px 74px 74px 88px 78px; }
.cf-rows-ex .cf-row { cursor:default; }
.cf-rows-perf .cf-rows-h, .cf-rows-perf .cf-row {
  grid-template-columns:minmax(160px,1.4fr) 118px 78px 68px 62px 68px 96px; }
.cf-rows-perf .cf-row { cursor:default; }
.cf-fr-code { font-size:17px; font-weight:700; color:var(--cf-accent); line-height:1; }
.cf-fr-chain { display:flex; align-items:center; gap:6px; flex-wrap:wrap; min-width:0; }
/* 展开区：左侧那条竖线把「示例属于这个框架」画死，不靠缩进暗示 */
.cf-fr-open { background:var(--cf-row); border-bottom:1px solid var(--cf-surface);
  padding:0 0 8px 30px; }
.cf-fr-open > div { border-left:2px solid var(--cf-softline); }
.cf-fr-note { padding:8px 14px 4px; font-size:11px; color:var(--cf-ink4);
  display:flex; align-items:center; gap:10px; flex-wrap:wrap; }
.cf-fr-body { padding:2px 14px 12px; background:var(--cf-soft3); }
/* 框架展开里的两块聚合（2026-08-23）。用现有 token，不新造色值。 */
.cf-fr-agg { padding:10px 14px 2px; }
/* 示例展开：左右两栏（2026-08-23）。用现有 token，不新造色值。 */
.cf-fr-two { display:grid; grid-template-columns:minmax(0,1fr) 268px; gap:18px;
  align-items:start; padding:6px 0 4px; }
.cf-fr-left { min-width:0; }
.cf-fr-lab { font-size:10px; color:var(--cf-ink4); letter-spacing:.08em; margin-bottom:5px; }
.cf-fr-bts { display:grid; grid-template-columns:repeat(7, minmax(0,1fr)); gap:6px; }
.cf-fr-bt2 { display:flex; flex-direction:column; gap:2px; padding:6px 8px; min-width:0;
  border-radius:var(--r-md); background:var(--cf-soft); border:1px solid var(--cf-softline); }
.cf-fr-bt2 i { font-style:normal; font-size:10px; color:var(--cf-accent); white-space:nowrap;
  overflow:hidden; text-overflow:ellipsis; }
.cf-fr-bt2 em { font-style:normal; font-size:11px; color:var(--cf-ink15); white-space:nowrap;
  overflow:hidden; text-overflow:ellipsis; }
/* 没写的那一拍**用灰不用红**：红在本仓是「真失败与合规风险」专用，
   而"这一条没写收口"不是错误，是这条脚本的取舍。 */
.cf-fr-bt2.miss { background:var(--cf-ground); border-color:var(--cf-line); }
.cf-fr-bt2.miss i { color:var(--cf-ink4); }
.cf-fr-bt2.miss em { color:var(--cf-ink4); }
.cf-fr-tags { display:flex; flex-wrap:wrap; gap:5px; margin-top:10px; }
.cf-fr-tags span { font-size:11px; color:var(--cf-accent); background:var(--cf-soft);
  border:1px solid var(--cf-softline); border-radius:var(--r-sm); padding:1px 7px; }
.cf-fr-right { background:#fff; border:1px solid var(--cf-line); border-radius:var(--r-lg);
  padding:12px 14px; display:flex; flex-direction:column; gap:10px; }
.cf-fr-kv { display:grid; grid-template-columns:1fr 1fr; gap:9px 12px; }
.cf-fr-kv span { display:block; font-size:9.5px; color:var(--cf-ink4); letter-spacing:.06em; }
.cf-fr-kv b { font-size:15px; font-weight:600; color:var(--cf-ink); font-variant-numeric:tabular-nums; }
.cf-fr-kv b.hi { color:var(--cf-accent); }
.cf-fr-meta { border-top:1px dashed var(--cf-line); padding-top:9px; display:flex;
  flex-direction:column; gap:6px; }
.cf-fr-meta > div { display:flex; justify-content:space-between; gap:10px; font-size:12px; }
.cf-fr-meta span { color:var(--cf-ink4); }
.cf-fr-meta b { font-weight:400; color:var(--cf-ink15); }
.cf-fr-meta b.ok { color:var(--cf-ok); font-weight:600; }
.cf-fr-acts { display:flex; gap:7px; }
.cf-fr-acts .arco-btn { flex:1; }
/* 🔴 用 `<a>` 不用 `<a-button @click="window.open(...)">`：模板里没有 `window`
   （对着组件实例解析 ⇒ `_ctx.window` ⇒ 点了 TypeError）。同族见铁律 10⑮。 */
.cf-fr-a { flex:1; text-align:center; font-size:12px; padding:5px 10px; border-radius:var(--r-md);
  background:#fff; border:1px solid var(--cf-line2); color:var(--cf-dark); white-space:nowrap; }
.cf-fr-a:hover { background:var(--cf-ground); border-color:var(--cf-ink4); color:var(--cf-ink); }
@media (max-width: 1180px) {
  .cf-fr-two { grid-template-columns:minmax(0,1fr); }
  .cf-fr-bts { grid-template-columns:repeat(4, minmax(0,1fr)); }
}
.cf-fr-agg-h { font-size:11px; color:var(--cf-ink3); letter-spacing:.06em;
  display:flex; align-items:baseline; gap:8px; margin-bottom:7px; }
.cf-fr-agg-h em { font-style:normal; color:var(--cf-ink4); letter-spacing:0; }
.cf-fr-scenes { display:flex; flex-wrap:wrap; gap:6px; }
.cf-fr-sc { font-size:11.5px; padding:2px 9px; border-radius:var(--r-sm);
  background:var(--cf-surface); color:var(--cf-ink2); white-space:nowrap; }
.cf-fr-sc b { color:var(--cf-ink); font-weight:600; }
.cf-fr-sc.top { background:var(--cf-soft); color:var(--cf-accent); }
.cf-fr-sc.top b { color:var(--cf-accent); }
/* 七拍是**定长七格**：格数固定才看得出"缺的是哪一拍"。窄屏折行不换算法。 */
.cf-fr-beats { display:grid; grid-template-columns:repeat(7, minmax(0, 1fr)); gap:6px; }
.cf-fr-bt { display:flex; flex-direction:column; gap:2px; align-items:center;
  padding:6px 4px; border-radius:var(--r-md); min-width:0;
  background:var(--cf-soft); border:1px solid var(--cf-softline); }
.cf-fr-bt i { font-style:normal; font-size:10.5px; color:var(--cf-ink3);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; max-width:100%; }
.cf-fr-bt b { font-size:13px; font-weight:600; color:var(--cf-accent); }
/* 短板那几拍**不用红**：它不是错误，是"这个框架现在少写了这一拍"。
   红在本仓是「真失败与合规风险」专用（.cf-scope 那段 token 注释写着）。 */
.cf-fr-bt.weak { background:var(--cf-ground); border-color:var(--cf-line); }
.cf-fr-bt.weak b { color:var(--cf-ink4); }
@media (max-width: 1180px) { .cf-fr-beats { grid-template-columns:repeat(4, minmax(0,1fr)); } }
.cf-fr-script { font-size:14px; line-height:1.9; color:var(--cf-ink); background:#fff;
  border:1px solid var(--cf-line); border-radius:var(--r-lg); padding:12px 14px;
  max-width:66ch; white-space:pre-wrap; }
.cf-rows-case .cf-rows-h, .cf-rows-case .cf-row {
  grid-template-columns:26px 56px minmax(180px,1fr) 184px 46px 150px 96px 120px; }
/* 没有编辑权时不渲染勾选格 ⇒ 退回 7 列（少一格会让整行错位一列，而页面不报错） */
.cf-rows-case .cf-rows-h:not(:has(.cf-row-pick)),
.cf-rows-case .cf-row:not(:has(.cf-row-pick)) {
  grid-template-columns:56px minmax(180px,1fr) 184px 46px 150px 96px 120px; }
/* 🔴 2026-08-18 用户要求「每一行的高度和候选库保持一致」：候选库的封面是
   56px 宽 + `aspect-ratio:9/16`（≈100px 高），这里跟上。
   🔴 **2026-08-19 修**：上面那次只改了 `.cf-row-th` 的 width，**这一行的第一列忘了跟着改**
      （还是 34px）⇒ 56px 的封面塞进 34px 的格子里溢出 22px，**正好压住标题左边**，
      用户实拍才发现。注释里当时就写着「加宽 22px 会让列下限合计 1068→1090px」——
      **那句话描述的是没做的事**（真实合计一直是 872px）。
      「注释里承诺过的东西，不等于页面上有的东西」，这是同一条教训的第 N 次。
   ⚠️ 为什么既有断言没拦住：`verify_cf` 守的是「列下限合计 ≤ 1098」这个**上限**，
      而 34px 比 56px 更小、合计更小 ⇒ 照样绿。上限守不住「列宽配不上内容宽度」。
      现补 §84 钉住：凡行内有 `.cf-row-th` 的表，缩略图那一列必须 ≥ 它的实际宽度。
   ⚠️ 改后列下限合计 776→798，加 gap 12×8 = 894px ≤ 1098，仍有 204px 余量。 */
.cf-row-th { position:relative; width:56px; height:100px; border-radius:4px; overflow:hidden;
             background:linear-gradient(150deg,#78716C,#3F3B38); display:block; }
.cf-row-th img { width:100%; height:100%; object-fit:cover; display:block; }
.cf-row-th > i { position:absolute; left:50%; top:50%; transform:translate(-50%,-50%);
                 color:#fff; font-size:10px; font-style:normal; text-shadow:0 1px 3px rgba(0,0,0,.6); }
/* 长文本一律单行截断 + title 给全文（规范 §3.3） */
/* .cf-row-t 于 2026-08-19 单元 2 删除：案例库是它最后一个用处，那一列已改成
   与灵感库/切片库同构的 .cf-row-tt（两行封顶 + 标签行）。留着就是死 CSS，
   而死 CSS 正是类名撞车的温床（铁律 10⑥，verify_cf §47 判红）。 */
/* 🔴 **必须是 block 级**（2026-08-19 用户："源成本这里重叠了"）：
   `overflow:hidden` / `text-overflow:ellipsis` / `min-width` 对 `display:inline`
   的元素**统统无效** —— 而这个类挂在 `<a>` 与 `<span>` 上，两者默认都是 inline。
   实测：裂变库源成品那一格 150px，链接实际画了 208px、**溢到隔壁列 58px**，
   而 `text-overflow:ellipsis` 明明写着（computed 里读得到 `ellipsis`），只是永远轮不到生效。
   ⚠️ 它在 `.cf-film-src-cell`（flex 容器）里一直是好的 —— flex item 会被 block 化 ⇒
      **同一个类在两处表现不同**，这正是"我这边看着没问题"的由来。
   ⚠️ 用 `block` 不用 `inline-block`：后者宽度由内容撑开，`overflow` 依旧不裁。 */
.cf-row-e { display:block; min-width:0; max-width:100%;
            white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.cf-row-e { font-size:12px; color:var(--cf-ink3); }
/* 不截断、换行显示全文（2026-08-20 用户："类型判断整段字符不要被挡住"）。
   与 `.cf-row-e` 是**一对相反的选择**，用哪个取决于那一列的内容能不能有个上界：
   类型判断是一句结论（实测最长 14 字），换行两行就到头；而标题/来源切片是原视频标题
   （41~60 字），不截断会把行撑得没法扫。
   ⚠️ 行高不受影响：这几张表的行高由 56×100 的缩略图定，2~3 行文字塞得下。
   ⚠️ `word-break:break-word` 不能省 —— 长英文/长链接不给断点时会整段溢出到隔壁列，
      而 `white-space:normal` 一个人拦不住它（同 `.cf-row-e` 那条 display:block 的教训）。 */
.cf-row-w { display:block; min-width:0; max-width:100%; font-size:12px; color:var(--cf-ink3);
            white-space:normal; word-break:break-word; line-height:1.5; }
/* 商品那一格的两条路（2026-08-20 用户："商品这里支持直接跳转到商品详情页和商品资料详情页"）。
   形态与「来源切片」那一格的 `.cf-film-srcw` **刻意一致**：主文字进站内、chip 出站，
   全站一个规律（PRD §5.19.20）。
   ⚠️ 这里原先写着「横排放不下 —— 商品名本身就常年截断」：**那说的是文字与 chip 的横排**，
      2026-08-24 改成横排的是**图与文字块**（`.cf-prod-txt` 里面仍是竖排：名字一行、chip 跟在下面），
      所以那条结论没有被推翻，只是不再是这一格的全部形态。上面 `.cf-prod-th` 那段是权威。 */
.cf-prod-cell { min-width:0; display:flex; align-items:center; gap:8px; }
.cf-prod-txt { min-width:0; display:flex; flex-direction:column; gap:2px; align-items:flex-start; }
/* 商品名**两行封顶**而不是单行省略号（2026-08-20）。这一列的内容长度极不均匀：
   生产上短的 8 字（红桃K美颜口服液）、长的 60 字（丽医生医用硅酮疤痕凝胶…）——
   单行截断时，为了让长的那条读得出来就得把列开得很宽，而那会让**短的那几行**
   右边空出一大片（实测把列开到 220px 时，短名字那 4 行与「谁在说」之间凭空多出 140px，
   等于把刚修好的"间距太大"换个位置又犯一遍）。两行封顶之后 160px 就能读出 26 字，
   短名字也只多空 64px。
   ⚠️ 行高不受影响：这几张表的行高由 56×100 的缩略图定（119px），三行小字塞得下。 */
.cf-prod-txt > .cf-prod-n { display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical;
            overflow:hidden; min-width:0; max-width:100%; font-size:12px; line-height:1.45;
            color:var(--cf-ink3); }
.cf-prod-cell > a.cf-prod-n { color:var(--cf-accent); }
.cf-row-n { font-size:12px; color:var(--cf-ink2); font-variant-numeric:tabular-nums; }
/* 🔴 `flex-wrap` 是 2026-08-19 加的（用户："切片库的操作按钮和设计稿不一致"）：
   设计稿写的是「★⚡↻ 一行、🗑 掉到第二行」（用户第一轮那条"操作项保持在三个，
   超过三个就换行展示出来"），而实现里 `.cf-row-a` 不换行、四个图标硬挤在一行。
   ⚠️ 换行要与**列宽收窄**一起做：不收窄的话 160px 装得下四个，`flex-wrap` 就是
      一条永远不生效的规则 —— 而"写了没生效"比没写更难查。 */
.cf-row-a { display:flex; gap:10px; justify-content:flex-end; flex-wrap:wrap;
            row-gap:2px; align-content:center; }
.cf-row-a a { font-size:12px; color:var(--cf-ink3); white-space:nowrap; }
.cf-row-a a.hot { color:var(--cf-accent); font-weight:600; }
/* 空态写清该做什么（规范 §8） */
.cf-rows-empty { padding:36px 14px; text-align:center; font-size:12px;
                 color:var(--cf-ink4); line-height:1.9; }
/* 筛选下拉的空态（2026-08-18）：标签筛选**恒显示**，一个标签都没有时由它说出为什么是空的。
   🔴 空态必须解释自己 —— 一个"暂无数据"的空下拉与"这个功能没做"在页面上分不开，
      而用户报过来的正是「筛选项缺少标签」。 */
.cf-sel-empty { padding:12px 14px; font-size:12px; color:var(--cf-ink4); line-height:1.8;
                text-align:center; }
/* ═══ 候选库（2026-08-13）：一行一条视频 ═══
   ⚠️ 起名前 grep 过 `^\.cd-`，无撞车（铁律 10⑥ —— 19k 行单文件里同名后写的赢，
   而"另一个模块的样式静默套到你的元素上"是零报错的）。 */
/* 勾选列（2026-08-18）在最前，所以是五列。⚠️ 只有有编辑权时那一格才渲染，
   而 grid 的列数是写死的 —— 少一格会让后面全部左移一列。
   所以用 `:has()` 判：没有勾选格时回到原来的四列。
   （`:has()` 在当前 vendor 的 Chrome 上可用；退一步说，就算不支持也只是多一列
   56px 的空白，不会错位。） */
.cd-row { display:grid; grid-template-columns:34px 56px 1fr 208px 92px; gap:12px;
          border:1px solid var(--cf-line); border-radius:var(--r-lg); padding:8px 10px;
          align-items:start; background:#fff; }
.cd-row:not(:has(.cd-pick)) { grid-template-columns:56px 1fr 208px 92px; }
.cd-row + .cd-row { margin-top:8px; }
.cd-pick { display:flex; align-items:center; justify-content:center; padding-top:2px; }
.cd-row-sel { border-color:var(--cf-accent,#d4380d); background:#fff8f5; }
/* 「今天首上榜」标记：选题最关心的信号，给它一个与其余灰字不同的颜色 */
.cd-new { color:#d4380d !important; font-weight:600; }
/* 批量条：选中后才出现，横贯一行。idle 态只放一个「选中本页全部」的入口 */
.cf-batbar { display:flex; align-items:center; gap:8px; flex-wrap:wrap;
             padding:8px 12px; margin-bottom:8px; border-radius:var(--r-lg);
             background:#fff4ec; border:1px solid #ffd8bf; font-size:13px; }
.cd-cover { aspect-ratio:9/16; border-radius:var(--r-sm); background:var(--cf-ground);
            border:1px solid var(--cf-line); position:relative; overflow:hidden; cursor:pointer; }
.cd-cover img { width:100%; height:100%; object-fit:cover; display:block; }
.cd-dur { position:absolute; right:3px; bottom:3px; font-size:10px; background:rgba(0,0,0,.55);
          color:#fff; padding:0 3px; border-radius:2px; }
.cd-ttl { font-size:13.5px; font-weight:600; line-height:1.45; margin:0 0 5px; cursor:pointer;
          display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden; }
.cd-ttl:hover { color:var(--cf-accent); }
.cd-meta { font-size:12px; color:var(--cf-ink2); display:flex; flex-wrap:wrap; gap:2px 12px; }
.cd-meta s { text-decoration:none; color:var(--cf-ink4); }
/* 来源摘要：后端拼好存下来的一行，前端不 JOIN 任何来源表 */
.cd-src { margin-top:7px; display:inline-flex; align-items:center; gap:7px; max-width:100%;
          background:var(--cf-ground); border-radius:var(--r-sm); padding:4px 7px; }
.cd-badge { font-size:10.5px; font-weight:600; padding:1px 6px; border-radius:3px; flex:none;
            background:#e8f0ff; color:#165dff; }
/* 数据源账号徽标：与「来源类型」徽标形状一致、颜色区分开（一个答"哪种来源"、
   一个答"哪个店的号"，同色会让人以为是一件事的两半） */
.cd-acct { background:var(--cf-ground); color:var(--cf-ink2); }
.cd-src img { width:24px; height:24px; border-radius:3px; object-fit:cover; flex:none;
              border:1px solid var(--cf-line); }
.cd-srct { font-size:11.5px; color:var(--cf-ink2); overflow:hidden;
           text-overflow:ellipsis; white-space:nowrap; }
.cd-srcimg { width:56px; height:56px; border-radius:var(--r-sm); object-fit:cover;
              flex:none; border:1px solid var(--cf-line); }
.cd-srcl { color:var(--cf-accent); text-decoration:none; }
.cd-srcl:hover { text-decoration:underline; }
.cd-nums { display:grid; grid-template-columns:repeat(4,1fr); gap:4px; }
.cd-nums > div { text-align:center; }
.cd-nums span { display:block; font-size:10.5px; color:var(--cf-ink4); }
.cd-nums b { font-size:14px; font-weight:600; color:var(--cf-ink); }
.cd-acts { display:flex; flex-direction:column; gap:5px; }
.cd-skipped { font-size:11.5px; color:var(--cf-ink4); text-align:center; }
/* 2026-08-18 加了勾选角标 ⇒ 需要 `position:relative` 作定位上下文。
   ⚠️ 不给它的话角标会跑到最近的那个已定位祖先上（多半是整个页面），
   表现是"所有卡片的勾选框叠在页面左上角一处"。 */
.cf-icard { border:1px solid var(--cf-line); border-radius:var(--r-lg); background:#fff;
            display:flex; gap:12px; padding:12px; cursor:pointer; position:relative; }
/* 角标压在缩略图左上角。半透明白底：纯浮在图上会被深色封面吃掉。 */
.cf-icard-pick { position:absolute; left:6px; top:6px; z-index:2; line-height:1;
                 background:rgba(255,255,255,.86); border-radius:4px; padding:1px 2px; }
.cf-icard:hover { border-color:var(--cf-accent-line); }
.cf-ithumb { width:88px; height:156px; flex:none; border-radius:var(--r-md); overflow:hidden;
             position:relative; background:linear-gradient(150deg,#78716C,#3F3B38); }
.cf-ithumb img { width:100%; height:100%; object-fit:cover; display:block; }
.cf-ithumb-t { position:absolute; right:6px; bottom:6px; font-size:11px; color:#fff;
               background:rgba(0,0,0,.6); border-radius:4px; padding:1px 5px;  z-index:2;}
/* ═════════ 段落列（2026-08-12，按 handoff「拆片详情页」重建）═════════
   规矩三条，都是稿子里点名的：
   ① **同一时刻只开一段**，其余收成单行摘要 —— 一屏能看见全片节奏；
   ② 段体**两列**，台词是主角（16px，全页最大正文），拍摄那一栏单独在右；
   ③ 运营维度用 **chip** 不用下拉框，六个 a-select 会把段头和台词隔开一整行。 */
/* 🔴 横向用 `auto` 不用 `hidden`（2026-08-13）：`hidden` 正是把 2026-08-13 那个
   「`.cf-sgc-main` 裸 min-width:440px」从「难看」放大成「**「台词·屏幕字」整列被静默吃掉、
   连滚动条都没有**」的那一层。根因已在 `min(440px,100%)` 那处修掉，这里改的是**放大器**：
   将来再有谁把某个子元素撑出去，出滚动条比凭空少一列强。
   实测 sticky 不受影响（`.cf-sgc-clip` 的 position:sticky 在 hidden/auto 两种下位移都是 -42px）。 */
.cf-sgc { background:#fff; border:1px solid var(--cf-line); border-radius:11px;
          overflow-x:auto; flex:none; }

/* —— 收起态：一行 —— */
/* 🔴 台词列的左边缘由这一个数决定（2026-08-25）。**两处共用**：
      收起态段落行的前缀 `.cf-sgc-lead`，与「标题与 tag」折叠摘要的缩进。
      写两个数必分叉，而分叉出来的样子就是"差一点点没对齐"——最难被发现的那种。
   量法：把生产库 111 段的 (段名, 类型) 组合逐个塞进真的 `.cf-sgc-lead` 量 ——
   **不是挑一个看着最长的**：段名混着中英文（「解释Token计费与语言差异」），
   按字数排会挑错那一个（同铁律 10⑫「按像素排不按字数排」）。
   实测最宽 389px（段名「解释Token计费与语言差异」+ 类型「放大对比 · 想要」），
   取 392 留 3px。第二名 383、第三名 372 —— 原先拍的 372 恰好压在第三名上，
   最长那两行会各顶出去 7px 与 17px。
   ⚠️ 超出这个宽度的行会自己顶出去（`min-width` 不是 `width`）——**这是刻意的**：
      定死 `width` 要靠截断段名才能守住，而段名截了就读不出这一段在干嘛。
      宁可极少数超长行略微不齐，也不让每一行都少几个字。 */
.cf-scope { --cf-lead-w: 392px; }
/* 🔴 `flex-wrap` + 台词给 `min-width`（2026-08-25，铁律 10⑤ 那条的标准解法）：
   加上定宽前缀（392px）与修辞手法（最宽 170px）之后，这一行在**窄版面**下装不下了 ——
   而 flex 里被压瘪的永远是那个不定宽的，实测台词被挤到 **33px ＝ 两个字**，
   而代码里那条注释白纸黑字写着「台词摘要是收起态的关键」。
   给台词一个下限、让**修辞手法掉到第二行**，而不是把台词压没。
   下限取 180px（≈12 个中文字）：够认出是哪一段，又能让常见组合留在一行 ——
   实测收起行一行所需 ＝ 392(前缀)+180(台词)+170(手法最宽)+60(草稿)+30(展开)+gap/padding
   ≈ 900px 卡宽；详情页是左右分栏，1500 视口下卡宽 931 ⇒ 一行。
   ⚠️ 下限**不能取到让它一行装下最长台词**（那要 600px+）：台词本来就是带省略号的摘要，
      为它多占一行等于把"一屏看见全片节奏"这件事换掉。 */
.cf-sgc-row { display:flex; flex-wrap:wrap; align-items:center; gap:10px;
              padding:11px 14px; cursor:pointer; }
.cf-sgc-lead { display:flex; align-items:center; gap:10px; flex:none;
               min-width:var(--cf-lead-w); }

/* 收起态的修辞手法（2026-08-25）：摆在台词右边，芯片小一号。
   `flex:none` + `nowrap` —— 这一行不换行，让位的是台词（它有 ellipsis）。 */
.cf-sgc-skl { display:flex; align-items:center; gap:5px; flex:none; white-space:nowrap; }
.cf-skl-i.sm { font-size:11px; padding:1px 6px; }
.cf-sgc-row:hover { background:var(--cf-surface); }
.cf-sgc-no { font-size:13px; color:var(--cf-ink4); font-variant-numeric:tabular-nums; flex:none; }
.cf-sgc-no.big { font-size:15px; font-weight:600; color:var(--cf-accent); }
.cf-sgc-tt { font-size:13px; color:var(--cf-ink2); flex:none; }
.cf-sgc-ts { font-size:12px; color:var(--cf-ink3); font-variant-numeric:tabular-nums; flex:none; }
.cf-sgc-role { font-size:11px; color:var(--cf-ink2); background:var(--cf-surface);
               border-radius:4px; padding:2px 8px; flex:none; white-space:nowrap; }
.cf-sgc-role.hot { margin-left:auto; font-weight:600; color:var(--cf-accent);
                   background:var(--cf-soft); border:1px solid var(--cf-softline); }
/* 台词摘要：**这是收起态的关键**，没有它一行只剩「01 痛点开场 · 展开」，
   什么都没告诉人，只能挨个点开找。 */
.cf-sgc-teaser { font-size:12px; color:var(--cf-ink3); flex:1; min-width:min(180px, 100%);
                 white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.cf-sgc-open { font-size:12px; color:var(--cf-accent); flex:none; }

/* —— 展开态段头 —— */
/* 🔴 `flex-wrap:wrap`（2026-08-13）：这一行里「播放本段」「复刻这段」都是 `flex:none`，
   容器一窄就直接顶出去，而祖先 `.cf-sgc` 是 overflow-x:hidden ⇒ 按钮被切掉、点不到。
   实测 820px 视口下「复刻这段」溢出 89px —— 整个按钮不可达，且页面零异常。 */
.cf-sgc-head { display:flex; flex-wrap:wrap; align-items:center; gap:10px; padding:12px 16px;
               background:var(--cf-row); border-bottom:1px solid #F5F0EC; cursor:pointer; }
/* ⚠️ 段名**不设 flex-shrink**（2026-08-25 试过又撤回）：这一行是 `flex-wrap:wrap`，
   wrap 容器里 flex-shrink 只在同一行内起作用 —— 总宽超了它**先换行**而不是收缩，
   实测段名一个字都没被截、那一段照样两行。设了等于留一条不生效的规则。
   段头的宽度改由「播放只留图标 + 时间戳用秒数」让位，见模板里那两处。 */
.cf-sgc-name { font-size:14px; font-weight:600; color:var(--cf-ink); }
.cf-sgc-play { font-size:12px; color:var(--cf-accent); border:1px solid var(--cf-accent-line);
               border-radius:6px; padding:3px 9px; background:#fff; cursor:pointer; flex:none; }
.cf-sgc-play:hover { background:var(--cf-soft); }
.cf-sgc-btn { font-size:12px; font-weight:600; color:#fff; background:var(--cf-accent);
              border-radius:6px; padding:5px 13px; cursor:pointer; flex:none; }
.cf-sgc-btn:hover { background:var(--cf-accent-hover); }

/* —— 运营维度 chip —— */
/* Arco 的 select 换皮成 chip：去掉它自己的高度与内边距，字号跟 chip 走 */
.cf-scope .cf-dim .arco-select-view { min-height:0; height:22px; line-height:22px;
                                      padding:0 6px 0 8px; font-size:12px; background:transparent; }
.cf-scope .cf-dim .arco-select-view-input,
.cf-scope .cf-dim .arco-select-view-value { font-size:12px; color:var(--cf-ink); }
.cf-scope .cf-dim.empty .arco-select-view-value,
.cf-scope .cf-dim .arco-select-view-input::placeholder { color:var(--cf-ink4); }
.cf-scope .cf-dim .arco-select-view-suffix { padding-left:4px; }
/* 🔴 空 chip 会被撑到 161px：`.arco-select` 与 `.arco-select-view` 是**同一个元素**，
   `width:max-content` 拿的是里面那个 `<input>` 的固有宽（浏览器默认 size=20 ≈ 129px）。
   六个占位词都恰好四个字，所以给一个 4.4em 的定宽；聚焦时放宽到 9em 好打字。 */
.cf-scope .cf-dim .arco-select { width:max-content; min-width:0; }
.cf-scope .cf-dim .arco-select-view-input { width:4.4em; }
.cf-scope .cf-dim .arco-select-view-input:focus { width:9em; }

/* —— 主体两列 —— */
.cf-sgc-body { display:flex; flex-wrap:wrap; align-items:stretch; }
/* 🔴 `min-width:440px` + 父级 `flex-wrap:wrap` 缺一不可：
   少了它窄屏时右栏会把台词压到 100px 宽，16px 的字变成一列竖排。 */
/* 场景切片：9:16 竖条，跟台词并排。不给 `flex:none` 之外的伸缩——
   它是定宽的，让台词那列去吃剩余空间。 */
/* 右边留 4px：与 `.cf-sgc-main` 的 18px 左内边距合起来 22px。
   原来只有 18，9:16 的高占位块紧挨着台词框，看着像"碰上了"。 */
/* `align-self:flex-start` 不被拉伸（父级 stretch 会把这一列拉到和内容列等高，
   实测 267px 的视频下面被拉出 297px 的空）；`sticky` 让它在读长段落时跟着走——
   那段高度就从"空的"变成"视频一直在视野里"（用户 2026-08-12 方案 C）。 */
/* 🔴 作用域改 border-box 后这一列必须把内边距加回宽度里（2026-08-13 实测）：
   `width:150px` 在 border-box 下只剩 128px 内容，而下面的 video 与 `.cf-clip-none`
   都是硬 150px ⇒ 它们右溢 18px 压到台词列上 —— **正是 2026-08-13 那个 bug 的几何形状**。
   把 150 做成变量、外宽由它算出来，这样"切片多宽"仍然只有一处定义。 */
.cf-sgc-clip { --clip-w:150px; flex:none; width:calc(var(--clip-w) + 18px + 4px);
               padding:16px 4px 16px 18px;
               align-self:flex-start; position:sticky; top:0; z-index:1; background:#fff; }
.cf-sgc-clip video { width:var(--clip-w); aspect-ratio:9/16; border-radius:var(--r-md);
                     background:#000; display:block; object-fit:contain; }
/* 🔴 `box-sizing:border-box` 不是可有可无的（2026-08-13 修，用户两次实拍）：
   本页是 content-box，这里写 `width:150px` 却带着 `padding:0 12px` + `1px` 边框
   ⇒ 实际 **176px**，比旁边那个 `.cf-sgc-clip video { width:150px }` 宽出 26px，
   直接**溢出父容器、压到台词第一栏上面**。而父容器 `.cf-sgc-clip` 是
   `position:sticky; z-index:1` 且不透明白底 ⇒ 它**盖住**台词首字的左半边。
   表现：只提台词的任务（没有切片、所以才显示这个占位框）里，「台词·口播」
   每一行的第一个字都缺一块，而右边那栏好好的。
   ⚠️ 这类"被盖住"用 `getBoundingClientRect` 是量不出来的（几何没越界），
   得用 `document.elementFromPoint` 问"这个像素上最上面的是谁"——我第一次就是这么误判的。 */
/* `box-sizing` 已由作用域根统一重置，这里不再单写（写了也对，但会让人以为只有它特殊）。 */
.cf-clip-none { width:var(--clip-w,150px); aspect-ratio:9/16; border-radius:var(--r-md);
                border:1px dashed var(--cf-line2); background:var(--cf-ground);
                display:flex; flex-direction:column; align-items:center; justify-content:center;
                gap:6px; text-align:center; padding:0 12px; }
.cf-clip-none > span { font-size:12px; color:var(--cf-ink3); }
.cf-clip-none > em { font-size:11px; color:var(--cf-ink4); font-style:normal; line-height:1.6; }
/* `min-width:440px` + 父级 `flex-wrap:wrap` 缺一不可（handoff）：少了它窄屏时
   右栏会把台词压到 100px 宽。
   🔴 **限宽限的是文字不是这一列**（2026-08-12 修）：给列加 `max-width` 会在右边留
   一段怪异空白，而配 `margin-left:auto` 把空白推给右栏时，那个 auto 会**吃掉剩余空间
   当外边距**（实测 52.75px）——窄容器里正是它把右栏挤到了下一行。 */
/* 🔴 **`min-width` 必须夹住上限**（2026-08-13 修，生产真数据 + 窄视口实测）：
   原来是裸 `min-width:440px`。容器比 440 窄时（侧栏展开 + 窗口不大、或分屏），
   这一列**自己就成了溢出源**：它先换到下一行、再横向溢出 183px，
   而祖先 `.cf-sgc` 是 `overflow-x:hidden` ⇒ **「台词·屏幕字」整列被静默吃掉，
   连滚动条都没有**。屏幕上看不出任何异常，只是第二栏不见了。
   `min(440px, 100%)` 保留原意（有地方时不让台词被压成竖排），
   同时保证这一列永远不超过容器 —— 溢出源从根上消失，不靠 overflow 兜。
   ⚠️ 还要 `box-sizing:border-box`：本页是 content-box，`min-width:100%` **不含 padding**，
   36px 的左右内边距会照样把它顶出容器 35px —— 改完第一版实测才发现，
   差一点就当成修好了（这正是"改完要量一遍"而不是"看着对了"的理由）。 */
.cf-sgc-main { flex:1; min-width:min(440px, 100%); box-sizing:border-box; padding:16px 18px; }
/* 16px 中文一行 600px ≈ 36 字，再宽读起来要来回扫。
   ⚠️ 这条上限现在挂在 `.cf-sgc-work > *`（**每一列**各自 600），
   不再挂在两栏合起来的容器上 —— 挂在容器上时双轨每栏只剩 293px。 */

/* 去浅底，只留一条上分隔线：分区靠"线 + 标签 + 间距"就够，不必再糊一层底色 */

/* 四个字段各约 21 字：一行四列每列 200px 正好，窄屏自动退成两列一列 */
.cf-lab { font-size:11px; color:var(--cf-ink4); margin-bottom:8px; }
/* 台词两条轨：单轨时占满，双轨时**并排两栏**（合并会把差异抹平，而差异正是要看的） */
/* 操作日志「变更内容」收缩（2026-08-13）。折两行用 -webkit-line-clamp：
   它按**行**折而不是按字符截，多字节中文不会切在半个字上；渐隐那一层是给
   "下面还有"一个可见的提示——纯截断会让人以为内容就这么多。 */
.plog-chg.clamp { position:relative; max-height:3.4em; overflow:hidden; }
.plog-chg.clamp::after { content:''; position:absolute; left:0; right:0; bottom:0; height:1.3em;
  background:linear-gradient(180deg, rgba(255,255,255,0), #fff); pointer-events:none; }
.plog-more { display:flex; gap:10px; margin-top:2px; font-size:12px; }
/* 上游调用留档 · 图工厂侧（2026-08-18，PRD §5.6.9）。与内容工厂那套同构，
   但类名前缀不同（ifc- vs cf-）——🔴 单文件里同名 class 后写的赢，
   复用 cf 的前缀会让两边的样式互相盖（铁律 10⑥ 一轮踩三次的那条）。 */
.ifc-item { border:1px solid var(--line,#e5e6eb); border-radius:6px; margin-bottom:8px; overflow:hidden; }
.ifc-head { display:flex; align-items:center; gap:8px; padding:8px 10px; cursor:pointer; background:#fafafa; flex-wrap:wrap; }
.ifc-head:hover { background:#f2f3f5; }
.ifc-ep { font-size:12px; color:#4e5969; word-break:break-all; }
.ifc-meta { font-size:11px; color:#86909c; }
.ifc-err { padding:6px 10px; font-size:12px; color:#a92a1f; background:#fff2f0; word-break:break-all; }
.ifc-body { padding:10px; border-top:1px solid var(--line,#e5e6eb); }
.ifc-lb { font-size:12px; font-weight:600; color:#4e5969; margin:8px 0 4px; }
.ifc-lb:first-child { margin-top:0; }
.ifc-pre { margin:0; padding:8px; background:#f7f8fa; border-radius:4px; font-size:11.5px;
           line-height:1.7; white-space:pre-wrap; word-break:break-all; max-height:320px; overflow:auto; }
.ifc-media { font-size:11.5px; color:#4e5969; padding:3px 8px; background:#f7f8fa; border-radius:4px; margin-bottom:3px; word-break:break-all; }
/* 上游调用留档（2026-08-13）。折叠行 + 展开看提示词与响应；样式沿用段卡那一套的克制： */
.cf-apilog { margin-top:22px; padding-top:16px; border-top:1px solid var(--cf-line); }
.cf-al-row { border-bottom:1px solid var(--cf-line); }
.cf-al-h { display:flex; align-items:center; gap:10px; flex-wrap:wrap; padding:8px 0;
  cursor:pointer; font-size:12.5px; }
.cf-al-h:hover { background:var(--cf-surface); }
.cf-al-body { padding:4px 0 12px; }
.plog-raw { margin:0; padding:10px; background:#F7F8FA; border-radius:6px; font-size:12px;
  line-height:1.6; max-height:40vh; overflow:auto; white-space:pre-wrap; word-break:break-all;
  user-select:text; }
/* ═══ 段体工作区（2026-08-13 用户三条反馈）═══
   口播 / 屏幕字 / 画面解说 / 复刻 是**平级的阅读列**，排不下才换行。
   替掉了原来的「`.cf-tracks` 两栏网格 + 复刻纵向跟在它下面」——那套的两个毛病：
     ① 600px 的阅读上限是加在**两栏合起来**上的，于是双轨时每栏只有 293px（1440 实测），
        窄得每行只排得下 18 个字，段就被拉得很高；而右边空着 292px（1680 实测）。
     ② 复刻在台词**下面**，多复刻几版就一路往下叠。
   现在阅读上限 600px 加在**每一列**上：单列时仍是 600（口径没变），
   双列时各 444，三列时各 288 —— 空白被用掉，段高显著下降。
   🔴 **换行看的是 `flex-basis`，不是 `min-width`**：flex 按基准尺寸决定一行放几个，
      放下之后才把剩余空间分掉。基准写 280 时实测只排得下两列 —— 因为容器内容宽是
      **874**（910 减两侧 18px 内边距），而 280×3+22×2=884，差 10px，复刻就掉到下一行。
      基准取 240（下面那条已经立过的可读下限）：240×3+44=764 装得下，三列各得 276。
      ⚠️ 别为了"刚好排下"去调这个数 —— 它是「一列窄到多少还读得下去」，不是版式断点。
   刻意不用 `@container`：这里要的是「排不下就换行」，flex-wrap 本来就够，
   不需要知道容器有多宽（见 report-ui-spec 规 9.5）。 */
.cf-sgc-work { display:flex; flex-wrap:wrap; align-items:flex-start; gap:16px 22px; }
/* 每一列：至少 240（16px 中文一行 ~13 字，沿用双轨那版立的下限）、至多 600（阅读上限） */
.cf-sgc-work > * { flex:1 1 240px; min-width:min(240px, 100%); max-width:600px; }
/* 🔴 台词轨改名 `.cf-lntrack`：`.cf-track` 是左栏时间轴容器的类名（带灰底+边框），
   写在后面所以它赢，于是台词被套了个不该有的灰框。本轮第三次撞名了。 */
.cf-lntrack { min-width:0; }
.cf-lntrack > label { display:block; font-size:11px; color:var(--cf-ink4); margin-bottom:8px; }
/* 画面解说轨（2026-08-13）：与台词轨**视觉上必须分得开**——它是机器编的，
   而上面两栏是原片真有的。左边一条竖线 + 标签上的说明就是那道分界；
   同样不加底色（沿用「主角靠字号和位置说话，不靠框」那条），只用一条边。 */
/* margin-top 去掉了：它现在是工作区里的一列，纵向间距由 .cf-sgc-work 的 gap 给 */
.cf-vistrack { min-width:0; padding-left:12px; border-left:2px solid var(--cf-line); }
.cf-vistrack > label { display:flex; align-items:center; gap:8px; flex-wrap:wrap;
                       font-size:11px; color:var(--cf-ink4); margin-bottom:8px; }
.cf-vis-tag { font-size:10.5px; color:var(--cf-ink4); background:var(--cf-surface);
              border-radius:var(--r-sm); padding:1px 6px; }
.cf-lines.empty { color:var(--cf-ink4); }
.cf-saved-len { font-size:11px; color:var(--cf-ink3); font-variant-numeric:tabular-nums; flex:none; }
/* 台词＝全页最大正文。`text-wrap:pretty` 防止最后一行只剩一个字 */
/* 🔴 台词**不加底色**（用户 2026-08-12 方案 A）：一个段卡里原来有 27 个带底/带边的盒子，
   台词 16px 大字本该最显眼，被框起来之后和 13px 的「怎么拍」视觉权重差不多——
   主角靠字号和位置说话，不靠框。hover 时才给一层浅底提示"这里能点开改"。 */
.cf-lines { font-size:16px; color:var(--cf-ink); line-height:1.8; text-wrap:pretty;
            cursor:text; border-radius:var(--r-md); margin:0 -6px; padding:0 6px; }
.cf-lines:hover { background:var(--cf-surface); }
.cf-scope .cf-lines-ed textarea { font-size:16px; line-height:1.8; }

/* —— 为什么这么写：词级解读 —— */
/* 挪进右栏之后不再需要那条与台词分隔的虚线（上面没有台词了）；
   与下面的「怎么拍」之间用一条实线分隔。 */
.cf-why2 { display:flex; flex-direction:column; gap:7px;
           padding-bottom:14px; border-bottom:1px solid var(--cf-surface); }
.cf-note { font-size:12px; color:var(--cf-ink2); line-height:1.65;
            display:flex; align-items:baseline; gap:6px; }
.cf-note-b { flex:1; min-width:0; }
.cf-note-w { color:var(--cf-note-t); background:var(--cf-note-bg); border-radius:3px; padding:0 3px; margin-right:4px; }
/* 逐词时间码（2026-08-22，PRD §5.19.26）：点它跳到这几个字被说出来的那一刻。
   🔴 **取不到就不给**，绝不按字数在段里等分一个——等分算得出一个数、看起来完全合理，
      而没有任何人能发现它是假的（本仓头号形状）。取不到与"这条切片压根没有逐词时间轴"
      是两件事，各有各的说法：前者是这一行的灰「—」，后者是标题旁那个虚线徽标。 */
.cf-note-ts { flex:none; font-variant-numeric:tabular-nums; font-size:11px; cursor:pointer;
              color:var(--cf-accent); background:var(--cf-soft); border:1px solid var(--cf-softline);
              border-radius:4px; padding:0 4px; }
.cf-note-ts.off { color:var(--cf-ink4); background:var(--cf-surface);
                  border-color:var(--cf-line); cursor:default; }
.cf-hlbar { position:absolute; top:0; bottom:0; background:var(--cf-hl); border-radius:3px;
             cursor:pointer; }
.cf-legend i.lg-hl { background:var(--cf-hl); }
.cf-note-why { cursor:text; }
.cf-note-why.man { border-bottom:1px dotted var(--cf-line2); }
.cf-note-why.none { color:var(--cf-ink4); font-style:normal; }
.cf-note-ed { flex:1; min-width:0; font-size:12px; }
.cf-note-x { flex:none; color:var(--cf-ink4); font-size:12px; cursor:pointer; padding:0 2px; }
.cf-note-x:hover { color:var(--cf-bad); }
.cf-note-nots { margin-left:8px; font-size:10.5px; color:var(--cf-ink4);
                border:1px dashed var(--cf-line2); border-radius:4px; padding:0 5px; }

/* —— 保留下来的复刻结果：绿框，与台词**并排**成一列（2026-08-13 从"正下方"改过来）—— */
/* 版本条：`‹ v2 / 共 3 版 ›`。数字必须在，只显示一版而不说共有几版，
   用户会以为前几版被覆盖了。到头的那一侧变灰但**不隐藏**——按钮忽然消失比变灰更难懂。 */
.cf-repro-col { min-width:0; }
.cf-repro-col > label { display:flex; align-items:center; gap:8px; flex-wrap:wrap;
                        font-size:11px; color:var(--cf-ink4); margin-bottom:8px; }
.cf-rv { display:inline-flex; align-items:center; gap:5px; color:var(--cf-ink3);
         font-variant-numeric:tabular-nums; }
.cf-rv b { font-weight:600; color:var(--cf-ink2); }
.cf-rv a { cursor:pointer; color:var(--cf-accent); padding:0 3px; font-size:13px; line-height:1; }
.cf-rv a.off { color:var(--cf-line2); cursor:default; }
/* margin-top 去掉：它现在是一列的头一个块，纵向间距由 .cf-sgc-work 的 gap 给 */
.cf-saved { border:1px solid var(--cf-ok-line); background:#F5FDF8;
            border-radius:9px; padding:10px 12px; }
/* 🔴 `flex-wrap:wrap`（2026-08-13，探针实测）：这一行原来是给 600px 宽的列设计的，
   复刻挪进 277px 的工作列之后**放不下** —— 实测头部内容 327px、可视 251px，
   「复制 / 再来一版 / 删除」整组跑到列外 63px。同 `.cf-sgc-head` 那次：
   一行里全是 `flex:none` 的东西，容器一窄就直接顶出去，而按钮顶出去＝点不到。 */
.cf-saved-h { display:flex; flex-wrap:wrap; align-items:center; gap:6px 8px; margin-bottom:7px; }
.cf-saved-t { font-size:11px; font-weight:600; color:var(--cf-ok); flex:none; }
/* 基准给 140 而不是 0：`flex:1`（基准 0）在窄列里会把它压成五十来像素、
   省略号之后一个字都不剩，却仍占着第一行不肯换行。 */
.cf-saved-src { font-size:11px; color:var(--cf-ink3); flex:1 1 140px; min-width:0;
                white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.cf-saved-src b { color:var(--cf-ink2); font-weight:400; }
.cf-saved-acts { display:flex; gap:9px; flex:none; }
.cf-saved-acts a { font-size:11px; color:var(--cf-ink2); cursor:pointer; }
.cf-saved-acts a.hot { color:var(--cf-accent); }
/* 直接可编辑——不是"点一下才变成输入框"。改完 blur 即存、扫雷重算。 */
/* ⚠️ 换成 a-textarea 之后，`class` 落在**外层 wrapper** 上，字号/行高要单独打到里面那个
   `<textarea>`（与 `.cf-lines-ed` 同一个写法，见上面那条）。两处都写才是完整的一份样式。 */
/* 读态：与编辑框**同样的字号/行高/内边距**，点进去时字不许跳位置（跳一下就像"内容变了"）。
   边框留一条透明的占位，否则进编辑态时整块会往外涨 1px。 */
.cf-saved-read { font-size:16px; line-height:1.8; color:var(--cf-ink); background:#fff;
                 border:1px solid transparent; border-radius:var(--r-md); padding:6px 9px;
                 cursor:text; white-space:pre-wrap; word-break:break-word; }
.cf-saved-read:hover { border-color:#DCFCE7; }
.cf-saved-read.ro { cursor:default; }
.cf-saved-read.ro:hover { border-color:transparent; }
.cf-saved-when { font-size:11px; color:var(--cf-ok); flex:none; font-variant-numeric:tabular-nums; }
.cf-scope .cf-saved-body { width:100%; background:#fff; border:1px solid #DCFCE7;
                           border-radius:var(--r-md); padding:6px 9px; }
.cf-scope .cf-saved-body.arco-textarea-focus { border-color:var(--cf-ok-line); box-shadow:none; }
.cf-scope .cf-saved-body textarea { font-family:inherit; font-size:16px; line-height:1.8;
                                    color:var(--cf-ink); }
.cf-saved-hits { display:flex; align-items:center; gap:6px; margin-top:7px; flex-wrap:wrap; }
.cf-saved-tip { font-size:11px; color:var(--cf-ink4); }

/* —— 贴纸/花字 · 音效（2026-08-12 设计更新）——
   两块**上下堆叠各自全宽**。并排时每块只剩一半宽，音效那条「钉在哪句台词」
   会被压成 0px，而它是这一块最有信息量的字段。 */
.cf-cards { padding:0 18px 16px; display:flex; flex-direction:column; gap:12px; }
.cf-ovblk { border:1px solid #FEF08A; background:#FEFCE8; border-radius:9px; padding:11px 13px; }
.cf-sfxblk { border:1px solid #DBEAFE; background:#F6F9FF; border-radius:9px; padding:11px 13px; }
.cf-blk-h2 { display:flex; align-items:center; gap:8px; margin-bottom:9px; }
.cf-ovblk-t { font-size:12px; font-weight:600; color:#92400E; }
.cf-ovblk-n { font-size:11px; color:#A16207; font-variant-numeric:tabular-nums; }
.cf-ovblk-add { margin-left:auto; font-size:11px; color:#A16207; cursor:pointer; }
/* 空态一行：不占框，但「+ 补一条」的入口仍在（机器漏标是常态） */
.cf-ovline, .cf-sfxline { display:flex; align-items:baseline; gap:8px; font-size:12px;
                          padding:7px 13px; border-radius:var(--r-md); }
.cf-ovline { color:#A16207; background:#FEFCE8; border:1px solid #FEF08A; }
.cf-sfxline { color:var(--cf-info); background:var(--cf-info-bg2); border:1px solid #DBEAFE; }
.cf-ovline > b, .cf-sfxline > b { font-weight:600; flex:none; }
.cf-ovline > a, .cf-sfxline > a { margin-left:auto; font-size:11px; cursor:pointer; flex:none; }
.cf-ovline > a { color:#A16207; }
.cf-sfxline > a { color:var(--cf-info); }
.cf-sfxblk-t { font-size:12px; font-weight:600; color:var(--cf-info); }
.cf-sfxblk-n { font-size:11px; color:var(--cf-info); font-variant-numeric:tabular-nums; }
.cf-sfxblk-add { margin-left:auto; font-size:11px; color:var(--cf-info); cursor:pointer; }
/* `auto-fill` 不是 `auto-fit`：只有 1 条时不把它拉满整行 */
.cf-ovgrid { display:grid; grid-template-columns:repeat(auto-fill, minmax(260px,1fr)); gap:8px; }
.cf-sfxgrid { display:grid; grid-template-columns:repeat(auto-fill, minmax(300px,1fr)); gap:8px; }
.cf-ovi { border:1px solid #FDE68A; background:#fff; border-radius:var(--r-md);
          padding:7px 8px; display:flex; gap:9px; min-width:0; }
/* 🔴 52×92（9:16）的画面帧。**不能省**——花字长什么样、压在画面哪个位置，只有图能说清。
   后端存的就是该时刻的整帧（2026-08-07 起不再裁"刚好框住它"的横条）。 */
.cf-ovi-th { width:52px; height:92px; flex:none; border-radius:var(--r-sm); overflow:hidden;
             position:relative; background:linear-gradient(160deg,#57534E,#1C1917); cursor:pointer; }
.cf-ovi-th img { width:100%; height:100%; object-fit:cover; display:block; }
.cf-ovi-tht { position:absolute; left:0; right:0; bottom:0; background:rgba(0,0,0,.55);
              color:#fff; font-size:9px; text-align:center; padding:1px 0;
              font-variant-numeric:tabular-nums; }
.cf-ovi-b { flex:1; min-width:0; display:flex; flex-direction:column; gap:5px; }
.cf-ovi-r1 { display:flex; align-items:center; gap:6px; min-width:0; }
.cf-ovi-ts { font-size:11px; color:#A16207; font-variant-numeric:tabular-nums; min-width:0;
             overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.cf-ovi-del { margin-left:auto; font-size:11px; color:var(--cf-ink4); cursor:pointer; flex:none; }
.cf-ovi-del:hover { color:var(--cf-bad); }
.cf-ovi-txt { font-size:13px; font-weight:600; color:var(--cf-ink); cursor:text;
              white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
/* 样式与作用合成一句，截两行，全文进 title */
.cf-ovi-note { font-size:12px; color:var(--cf-ink2); line-height:1.5;
               display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical;
               overflow:hidden; }
.cf-ovi-jy { margin-top:auto; align-self:flex-start; max-width:100%;
             white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
/* Arco select 换皮成小标签，跟 chip 一个高度 */
.cf-scope .cf-ovi-kind, .cf-scope .cf-sfi-name { width:max-content; min-width:0; flex:none; }
.cf-scope .cf-ovi-kind .arco-select-view { min-height:0; height:19px; line-height:19px;
    padding:0 4px 0 6px; font-size:11px; background:#FEFCE8;
    border:1px solid #FDE68A; border-radius:4px; }
.cf-scope .cf-ovi-kind .arco-select-view-input { width:3.4em; }
.cf-scope .cf-ovi-kind .arco-select-view-value { color:#A16207; font-size:11px; }
.cf-sfi { border:1px solid #DBEAFE; background:#fff; border-radius:var(--r-md);
          padding:7px 9px; display:flex; flex-direction:column; gap:5px; min-width:0; }
.cf-sfi-r1 { display:flex; align-items:center; gap:8px; min-width:0; }
.cf-sfi-play { font-size:11px; color:var(--cf-info); cursor:pointer; flex:none; }
.cf-sfi-ts { font-size:11px; color:var(--cf-info); font-variant-numeric:tabular-nums; flex:none; }
.cf-scope .cf-sfi-name .arco-select-view { min-height:0; height:20px; line-height:20px;
    padding:0 2px; font-size:13px; background:transparent; }
.cf-scope .cf-sfi-name .arco-select-view-value { font-size:13px; font-weight:600; color:var(--cf-ink); }
.cf-scope .cf-sfi-name .arco-select-view-input { width:5em; }
.cf-sfi-cf { font-size:11px; color:var(--cf-info); background:#E5EDFF; border-radius:4px;
             padding:1px 6px; flex:none; }
.cf-sfi-cf.mid { color:var(--cf-ink3); background:var(--cf-surface); }
.cf-sfi-jy { margin-left:auto; min-width:0; white-space:nowrap; overflow:hidden;
             text-overflow:ellipsis; }
/* 🔴 「钉在哪句台词」**单独一行** —— 早期版本把它和剪映搜挤在一行，
   两列宽度下会被压成 0px 宽，而它是这一块最有信息量的字段。 */
.cf-sfi-r2 { font-size:12px; color:var(--cf-ink2); min-width:0;
             white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.cf-sfi-r2 > span { color:var(--cf-ink4); margin-right:5px; }
/* 「还有 N 条 · 全部展开」：整宽按钮，超过上限才出现 */
.cf-more { display:block; text-align:center; font-size:12px; border-radius:var(--r-md);
           padding:6px 0; margin-top:8px; cursor:pointer; }
.cf-more.ov { color:#92400E; background:#FEF9C3; border:1px solid #FDE68A; }
.cf-more.sfx { color:var(--cf-info); background:#EAF1FF; border:1px solid #DBEAFE; }
.cf-jy-k { font-size:11px; color:var(--cf-accent); background:var(--cf-soft);
           border:1px solid var(--cf-softline); border-radius:4px; padding:1px 7px;
           font-weight:400; }
/* ═══ 左栏段落跳转（设计稿：播放器/时间轴/段落跳转都在左栏）═══ */
.cf-navs { display:flex; flex-direction:column; gap:5px; }
.cf-nav { display:flex; align-items:center; gap:8px; padding:7px 9px; cursor:pointer;
          border:1px solid var(--cf-line); border-radius:var(--r-md); background:#fff; }
.cf-nav:hover { border-color:var(--cf-accent-line); }
.cf-nav.on { border-color:var(--cf-accent); background:var(--cf-soft); }
.cf-nav-no { font-size:11px; font-weight:600; color:var(--cf-ink4); flex:none; }
.cf-nav.on .cf-nav-no { color:var(--cf-accent); }
.cf-nav-t { font-size:12px; color:var(--cf-ink); min-width:0; overflow:hidden;
            text-overflow:ellipsis; white-space:nowrap; }
.cf-nav-d { margin-left:auto; font-size:11px; color:var(--cf-ink4); flex:none; font-variant-numeric:tabular-nums; }
.cf-nav-d2 { font-size:11px; color:var(--cf-ok); flex:none; }
.cf-nav-c { font-size:11px; color:var(--cf-accent); flex:none; }
/* 运营维度：**填过的实底、没填的虚线**——一眼看出哪几个还没标 */
.cf-scope .cf-dim-empty .arco-select-view { border-style:dashed; background:var(--cf-ground); }
/* 卡脚那个「原链接 ↗」：**幽灵级**（无底无边、只有字），不跟主动作抢。
   规范 §3.2 的「文字」级。 */
.cf-scope .cf-btn-ghost, .cf-scope .arco-btn.cf-btn-ghost {
  background:transparent; border:none; color:var(--cf-ink3); font-size:11px;
  padding:0 4px; height:auto; }
.cf-scope .cf-btn-ghost:hover { background:transparent; color:var(--cf-accent); }
/* 原片预览弹窗：**按视口高度定尺寸**，宽度由 9:16 算出来（用户 2026-08-12：
   「要刚好适配整个页面」）。原来写死 420px 宽 ⇒ 高 747px，加上弹窗头脚
   在 900 高的屏上直接顶出去。
   ⚠️ 这里**只给 height 不给 width**——两个都写死就把比例改掉了（第 40 组断言）。 */
/* ⚠️ 弹窗宽度**必须写死**：给 a-modal `width:auto` 会让它塌成内容宽（实测 194px），
   因为"宽由高算、高由 vh 算"对 inline-block 的弹窗是个解不开的循环。
   380px 是按 `620 × 9/16 = 349` 加左右留白定的——盒子在任何视口下都塞得进。 */
.cf-prevbox { height:min(68vh, 620px); aspect-ratio:9/16; background:#000;
              border-radius:var(--r-lg); overflow:hidden; display:flex; margin:0 auto; }
.cf-prevbox > video, .cf-prevbox > img { width:100%; height:100%; display:block; }
.cf-scope.cf-prev-modal .arco-modal { max-width:92vw; }
.cf-prev-nocover { width:100%; height:100%; display:flex; align-items:center;
                   justify-content:center; color:var(--cf-ink4); font-size:12px; }
/* 缩略图可点：常态给一个半透明播放键，hover 变实——不给的话没人知道它能点 */
.cf-ithumb { cursor:pointer; }
.cf-ithumb-play { position:absolute; left:50%; top:50%; transform:translate(-50%,-50%);
                  font-size:15px; color:#fff; font-style:normal; opacity:.55;
                  text-shadow:0 1px 6px rgba(0,0,0,.6); transition:opacity .12s; }
.cf-ithumb:hover .cf-ithumb-play { opacity:1; }
.cf-ithumb-m { position:absolute; left:6px; bottom:6px; font-size:11px; color:#fff;
               background:rgba(29,78,216,.85); border-radius:4px; padding:1px 5px; }
.cf-ibody { flex:1; min-width:0; display:flex; flex-direction:column; gap:7px; }
.cf-irow1 { display:flex; align-items:center; gap:6px; min-width:0; }
.cf-plat-chip { font-size:11px; font-weight:600; color:var(--cf-ink); background:var(--cf-surface);
                border:1px solid var(--cf-line); border-radius:4px; padding:1px 6px; flex:none; }
.cf-iauthor { font-size:12px; color:var(--cf-ink2); white-space:nowrap; overflow:hidden;
              text-overflow:ellipsis; }
.cf-ititle { font-size:13px; color:var(--cf-ink); line-height:1.5;
             display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden; }
.cf-istat { font-size:11px; color:var(--cf-ink3); }
.cf-inote { font-size:12px; color:var(--cf-ink3); line-height:1.45;
            white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.cf-ifoot { margin-top:auto; display:flex; align-items:center; gap:8px; }
.cf-iby { font-size:11px; color:var(--cf-ink4); white-space:nowrap; overflow:hidden;
          text-overflow:ellipsis; margin-right:auto; }
.cf-imore { font-size:12px; color:var(--cf-ink3); flex:none; padding:0 2px; cursor:pointer; }
.cf-iadd { border-style:dashed; align-items:center; justify-content:center; text-align:center;
           min-height:180px; background:var(--cf-ground); }
.cf-iadd-p { font-size:19px; color:var(--cf-ink4); }
.cf-iadd-t { font-size:13px; color:var(--cf-ink2); margin-top:6px; }
.cf-iadd-s { font-size:11px; color:var(--cf-ink4); margin-top:4px; }

.vnw-months { display:flex; flex-wrap:wrap; align-items:center; gap:0; }
/* 运费·产品明细的批次浮层小表（2026-09-04）。数字列右对齐 + tabular-nums，
   否则几千件与几件的位数对不齐，一眼看不出谁大。 */
/* 🔴 横向滑动不许触发浏览器的前进/后退手势（2026-08-12 用户："这个很烦"）。
   本站有大量横向滚动的宽表（41 列的订单表、13 列的库存最终表…），在 macOS 触控板上
   横滑到表格边界后继续滑，会被浏览器当成"上一页"手势 —— **整个站直接退出，填到一半的
   表单全没了**。overscroll-behavior-x:none 把这个手势关掉，纵向滚动不受影响。
   挂在 html/body 上是因为手势由最外层容器接管；表格容器上单独再挂一次兜底。 */
html, body { overscroll-behavior-x: none; }
.arco-table-body, .arco-table-content, .table-card { overscroll-behavior-x: contain; }
/* 待核对弹窗的「怎么核 / 怎么改」——兜底桶必须说得清出路，不能只给一个数字 */
.vnw-how { background:#f7f8fa; border:1px solid #e5e6eb; border-radius:6px;
           padding:12px 14px; margin-bottom:12px; font-size:13px; color:#4e5969; line-height:1.85; }
.vnw-how-t { font-weight:600; color:#1d2129; margin-bottom:4px; }
.vnw-how-t + .vnw-how-l { margin-top:0; }
.vnw-how-l { margin:0 0 10px 0; padding-left:20px; }
.vnw-how-l:last-child { margin-bottom:0; }
/* ═══ 灵感详情抽屉：左视频右字段（设计稿 G）═══ */
.cf-idtop { display:flex; gap:14px; }
/* 180×320 就是 9:16。写成 aspect-ratio 而不是写死高度：宽度改了比例自动跟上，
   两个值各写一处必然有一天对不上。 */
/* 🔴 `align-self:flex-start` 是必须的（2026-08-13 用户实拍「被拉长了」）：
   `.cf-idtop` 是 flex，默认 `align-items:stretch` —— **stretch 会覆盖 `aspect-ratio`**
   （aspect-ratio 只给"首选"高度，拉伸给的是"用定"高度）。备注/标签挪进右栏后右栏变高，
   封面就被拽着一起长：实测 180×**405**，而 9:16 应该是 180×320，竖屏封面平白拉高 85px。
   ⚠️ 我当时量的是「右栏高 405 ≡ 封面高 405」，看到相等就当成"正好齐平"——
   **该比的是封面自己的 180×16/9=320，不是隔壁那一栏**。比错了对象，等号就成了假证据。 */
.cf-idcover { width:180px; aspect-ratio:9/16; flex:none; align-self:flex-start;
              border-radius:var(--r-lg); overflow:hidden;
              position:relative; background:linear-gradient(160deg,#78716C,#292524); cursor:pointer; }
.cf-idcover video { width:100%; height:100%; object-fit:contain; background:#000; display:block; }
/* 没缓存原片：明说，别放播放键冒充"点了能播" */
.cf-idcover.nocache::after { content:''; position:absolute; inset:0; background:rgba(28,25,23,.42); }
.cf-idnc { position:absolute; left:0; right:0; top:50%; transform:translateY(-50%); z-index:1;
           display:flex; flex-direction:column; align-items:center; gap:5px; text-align:center;
           padding:0 12px; }
.cf-idnc > b { font-size:12px; font-weight:600; color:#fff; }
.cf-idnc > em { font-size:11px; font-style:normal; color:var(--cf-accent-line); }
.cf-idcover img { width:100%; height:100%; object-fit:cover; display:block; }
.cf-idmeta { flex:1; min-width:0; display:flex; flex-direction:column; gap:12px; }
.cf-idlab { font-size:11px; color:var(--cf-ink4); }
.cf-idtitle { font-size:13px; color:var(--cf-ink); line-height:1.7; text-wrap:pretty; margin-top:5px; }
.cf-idgrid { display:grid; grid-template-columns:56px 1fr; gap:7px 12px; align-items:center;
             font-size:13px; color:var(--cf-ink15); }
.cf-idstats { border:1px solid var(--cf-page); background:var(--cf-ground);
              border-radius:var(--r-lg); padding:12px 14px; }
.cf-idstats-h { display:flex; align-items:center; gap:8px; margin-bottom:10px;
                font-size:12px; color:var(--cf-ink1); }
.cf-idstats-n { display:flex; gap:26px; }
.cf-idstats-n span { display:block; font-size:11px; color:var(--cf-ink4); }
.cf-idstats-n b { font-size:14px; font-weight:600; color:var(--cf-ink); }
.cf-idstats-x { font-size:11px; color:var(--cf-ink4); margin-top:9px; }
/* 灰豚数据桥「装了两处」横幅（2026-08-14）。起名前已 grep 过没被占（铁律 10⑥）。 */
.cf-hubanner { display:flex; gap:8px; align-items:baseline; flex-wrap:wrap;
  margin:0 0 10px; padding:9px 12px; border-radius:6px; font-size:12px; line-height:1.7;
  background:#fff7e8; border:1px solid #ffcf8b; color:#7d4e00; }
.cf-hubanner b { flex:none; }
/* 灰豚概览（2026-08-13）：九项在 600 宽的抽屉里放不下一行，故三列换行。
   容器/表头/脚注三处**复用 `.cf-idstats*`**，只有这一格网格是新的（Archer 第 2 条）。
   ⚠️ 新类名前先 `grep -n "^\.cf-hu" 原型.html` 查过撞车（铁律 10⑥，一轮踩过三次）。 */
.cf-hu-n { display:grid; grid-template-columns:repeat(3, 1fr); gap:10px 8px; }
.cf-hu-n span { display:block; font-size:11px; color:var(--cf-ink4); }
.cf-hu-n b { font-size:14px; font-weight:600; color:var(--cf-ink); }
.cf-hu-chart { width:100%; height:150px; margin-top:10px; }
.cf-idtags { display:flex; gap:6px; flex-wrap:wrap; align-items:center; }
.cf-idtag { font-size:12px; color:var(--cf-ink2); background:var(--cf-surface);
            border-radius:var(--r-sm); padding:3px 9px; display:inline-flex; gap:5px; align-items:center; }
.cf-idtag i { font-style:normal; color:var(--cf-ink4); cursor:pointer; }
.cf-idtag i:hover { color:var(--cf-bad); }
/* ═══ 视频档案：足迹徽标 + 全链抽屉（2026-08-19，PRD §5.19.19）═══
   用户原话：「核心就是我需要能做到整体的数据回溯，从候选、灵感、切片、成品、裂变，
   一整体的视频信息数据回溯」。此前这条链只能一页一页人肉跳。
   🔴 徽标是**四个格子恒渲染**，走到的那格点亮 —— 只画走到的那几格会让
      「还没做成品」与「这一格我没画」在页面上分不开，而前者恰恰是运营要看的信息。 */
.cf-fp { display:inline-flex; align-items:center; gap:2px; cursor:pointer;
         vertical-align:middle; }
.cf-fp i { font-style:normal; font-size:10px; line-height:1; padding:2px 4px;
           border-radius:3px; border:1px solid var(--cf-line); color:var(--cf-ink4);
           background:#fff; letter-spacing:.02em; }
.cf-fp i.on { color:var(--cf-accent2); background:var(--cf-soft2);
              border-color:var(--cf-accent-line); font-weight:600; }
/* 「有但你看不见」：既不是走到了、也不是没走到 —— 第三种颜色，悬停说明 */
.cf-fp i.blk { color:var(--cf-ink4); background:var(--cf-surface);
               border-style:dashed; }
.cf-fp:hover i { border-color:var(--cf-accent-line); }
/* 🔴 **可点进去的那几格要看得出来**（2026-08-26）：整条 `.cf-fp` 一直是 pointer，
   但那时点哪一格都是同一个动作（开档案）。现在「切」「案」是直接跳到那条切片，
   而另外三格仍是开档案 —— 不给个区别的话，"点这里会发生什么"全靠猜。 */
.cf-fp i.go:hover { background:var(--cf-accent2); color:#fff;
                    border-color:var(--cf-accent2); }
/* 「已开拆」徽标可点时给个手型 + 悬停加深（不可点时就是个普通标签，别给假链接） */
.cf-b.cf-b-go { cursor:pointer; }
.cf-b.cf-b-go:hover { filter:brightness(.94); }
/* 新人培训：把已确认的工作台原型收进 BL 外壳，页面内仍沿用内容工厂色板。 */
.trn-shell { display:block; }
.trn-shell.plan-fixed,.trn-shell.plan-fixed .trn-main { height:100%; min-height:0; }
.trn-shell.plan-fixed .trn-main { display:flex; flex-direction:column; }
.trn-main { min-width:0; }
.trn-head { min-height:46px; display:flex; align-items:center; gap:10px; padding:7px 11px;
            background:#fff; border:1px solid var(--cf-line); border-radius:var(--r-lg); margin-bottom:10px; }
.trn-head > div:first-child { display:flex; align-items:baseline; gap:10px; min-width:0; }
.trn-head h2 { margin:0; font-size:14px; color:var(--cf-ink); white-space:nowrap; }
.trn-head p { margin:0; min-width:0; font-size:11px; color:var(--cf-ink3); white-space:nowrap;
              overflow:hidden; text-overflow:ellipsis; }
.trn-head-actions { margin-left:auto; display:flex; gap:8px; flex:none; }
.trn-metrics { display:grid; grid-template-columns:repeat(6,minmax(0,1fr)); gap:9px; margin-bottom:12px; }
.trn-metrics .cfr-m { min-height:68px; }
.trn-setup { display:grid; grid-template-columns:minmax(340px,.9fr) minmax(0,1.35fr); gap:12px; align-items:start; }
.trn-card { min-width:0; border:1px solid var(--cf-line); border-radius:var(--r-lg); background:#fff; padding:15px; }
.trn-bot-grid { display:grid; grid-template-columns:minmax(0,1fr) minmax(360px,.9fr); gap:12px; align-items:start; }
.trn-config-list { display:grid; gap:0; margin-top:10px; }
.trn-config-row { min-height:42px; display:grid; grid-template-columns:150px minmax(0,1fr); gap:14px;
  align-items:center; border-top:1px solid var(--cf-line); font-size:12px; }
.trn-config-row:first-child { border-top:0; }
.trn-config-label { color:var(--cf-ink3); }
.trn-config-value { min-width:0; color:var(--cf-ink); overflow-wrap:anywhere; }
.trn-strategy-row { min-height:54px; display:flex; align-items:center; gap:12px; border-top:1px solid var(--cf-line); }
.trn-strategy-row:first-child { border-top:0; }
.trn-strategy-row > div:first-child { flex:1; min-width:0; }
.trn-strategy-row b { display:block; font-size:12px; color:var(--cf-ink); }
.trn-strategy-row span { display:block; margin-top:3px; font-size:11px; color:var(--cf-ink3); }
.trn-time-input { width:112px; height:32px; box-sizing:border-box; border:1px solid var(--cf-line); border-radius:6px;
  padding:0 9px; color:var(--cf-ink); background:#fff; outline:none; }
.trn-time-input:focus { border-color:var(--cf-accent); }
.trn-chip-wrap { display:flex; flex-wrap:wrap; gap:5px; }
.trn-empty { min-height:250px; display:grid; place-items:center; text-align:center; color:var(--cf-ink4);
             border:1px solid var(--cf-line); background:#fff; border-radius:var(--r-lg); padding:28px; }
.trn-empty b { display:block; color:var(--cf-ink); font-size:15px; margin-bottom:6px; }
.trn-empty i { width:52px; height:52px; border-radius:14px; display:grid; place-items:center;
               margin:0 auto 12px; background:var(--cf-surface); color:var(--cf-accent2); font-style:normal; font-size:22px; }
.trn-plan { display:grid; grid-template-columns:184px minmax(0,1fr); gap:12px; }
.plan-fixed .trn-plan { flex:1; min-height:0; overflow:hidden; }
.trn-days { height:max-content; padding:7px; background:#fff; border:1px solid var(--cf-line); border-radius:var(--r-lg); }
.plan-fixed .trn-days { position:sticky; top:0; align-self:start; max-height:100%; overflow-y:auto; }
.trn-day { width:100%; border:0; background:transparent; border-radius:var(--r-md); padding:10px;
           display:grid; grid-template-columns:38px minmax(0,1fr); gap:8px; text-align:left; color:var(--cf-ink2); cursor:pointer; }
.trn-day:hover { background:var(--cf-surface); }
.trn-day.on { background:var(--cf-soft2); color:var(--cf-accent2); }
.trn-day strong { font-size:11px; padding-top:2px; }
.trn-day b { display:block; line-height:1.45; }
.trn-day span { display:block; color:var(--cf-ink4); font-size:10px; margin-top:3px; }
.trn-plan-main { min-width:0; }
.plan-fixed .trn-plan-main { min-height:0; display:flex; flex-direction:column; overflow:hidden; }
.trn-day-head { display:flex; align-items:center; gap:14px; min-height:82px; padding:13px 15px;
                background:#fff; border:1px solid var(--cf-line); border-radius:var(--r-lg); margin-bottom:10px; }
.trn-day-no { width:48px; height:48px; border-radius:12px; display:grid; place-items:center;
              flex:none; background:#182338; color:#fff; font-size:16px; font-weight:800; }
.trn-day-head h3 { margin:0 0 4px; font-size:17px; }
.trn-day-head p { margin:0; color:var(--cf-ink3); font-size:12px; }
.trn-day-stat { margin-left:auto; display:flex; gap:18px; text-align:right; flex:none; }
.trn-day-stat b { display:block; font-size:15px; }
.trn-day-stat span { color:var(--cf-ink4); font-size:10px; }
.trn-day-actions { display:flex; gap:7px; flex:none; }
.trn-course-scroll { overflow:auto; padding-bottom:5px; min-height:0; }
.plan-fixed .trn-course-scroll { flex:1; }
.trn-course-head,.trn-course { width:100%; min-width:880px; display:grid;
  grid-template-columns:32px 58px minmax(150px,1.25fr) minmax(190px,1.45fr)
    minmax(96px,.75fr) 130px; gap:8px; align-items:center; }
.trn-course-head { position:sticky; top:0; z-index:2; min-height:34px; margin-bottom:8px; padding:7px 13px;
                   background:#fff; border:1px solid var(--cf-line); border-radius:var(--r-md);
                   color:var(--cf-ink3); font-size:10.5px; font-weight:600; }
.trn-course { height:104px; padding:11px 13px; margin-bottom:8px; overflow:hidden; background:#fff; border:1px solid var(--cf-line); border-radius:var(--r-lg); }
.trn-course:hover { border-color:var(--cf-accent-line); box-shadow:0 4px 12px rgba(28,25,23,.04); }
.trn-course > * { min-width:0; }
.trn-seq { width:27px; height:27px; border-radius:7px; display:grid; place-items:center;
           background:var(--cf-surface); color:var(--cf-ink3); font-size:11px; font-weight:700; }
.trn-course b { display:block; overflow-wrap:anywhere; }
.trn-course em { display:block; margin-top:3px; color:var(--cf-ink4); font-size:10px; font-style:normal; }
.trn-main .cf-row { cursor:default; }
.trn-main .cf-row:hover { background:#fff; }
.trn-task-name b,.trn-task-name em { display:block; }
.trn-clamp1 { white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.trn-clamp2 { display:-webkit-box !important; -webkit-box-orient:vertical; -webkit-line-clamp:2;
              overflow:hidden; overflow-wrap:anywhere; }
.trn-row-actions { display:flex; gap:4px; white-space:nowrap; }
.trn-row-actions .arco-btn-size-mini { padding:0 6px; }
/* ══ 事项形态（2026-09-11）══════════════════════════════════════════════════
   「员工要做什么」原先藏在 `pass_standard` 那几个自由汉字里（多打一个空格就换档），
   现在它是一个闭集字段 `mode`，列表、编辑器、卡片预览三处都从它派生。
   ⚠️ 这四档的颜色只表达"要不要人做事"，不是难度排序：notice 灰（发完就完）、
      confirm/submit 蓝、exam 橙（要单独判卷 + 导师复核）。 */
.trn-chip { display:inline-flex; align-items:center; gap:4px; padding:2px 8px; border-radius:20px;
            font-size:11px; font-weight:600; white-space:nowrap;
            border:1px solid var(--cf-line); background:var(--cf-surface); color:var(--cf-ink2); }
.trn-chip.is-notice { color:var(--cf-ink3); }
.trn-chip.is-confirm { color:var(--cf-accent2); border-color:var(--cf-accent-line); background:var(--cf-soft2); }
.trn-chip.is-submit { color:#0e7490; border-color:#a5f3fc; background:#ecfeff; }
.trn-chip.is-exam { color:#ad4e00; border-color:#ffcf8b; background:#fff3e8; }
.trn-chip.is-warn { color:#b54708 !important; border-color:#fecd9b !important; background:#fff7e8 !important; }
.trn-do { display:flex; flex-direction:column; align-items:flex-start; gap:4px; }
.trn-do em { margin-top:0; }
.trn-item-res { display:flex; align-items:center; gap:7px; margin-top:3px; min-width:0; }
.trn-item-res a { color:var(--cf-accent2); font-size:10.5px; font-weight:600; text-decoration:none;
                  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; max-width:100%; }
.trn-item-res a:hover { text-decoration:underline; }
/* ══ 编辑事项工作台（2026-09-14 方案 A：左边五项、右边卡片预览）══════════════════ */
.trn-item-editor-page { position:fixed; inset:0; z-index:1000; min-height:0; height:100vh; display:flex; flex-direction:column; background:#f4f7fb; }
.trn-item-editor-head { height:76px; padding:0 38px; flex:none; display:flex; align-items:center; gap:14px;
                        background:#fff; border-bottom:1px solid #dbe3ee; }
.trn-item-editor-head h2 { margin:0; font-size:19px; color:#18263d; letter-spacing:-.25px; }
.trn-item-editor-head p { margin:3px 0 0; font-size:12px; color:#76859a; }
.trn-item-editor-actions { margin-left:auto; display:flex; align-items:center; gap:10px; }
.trn-item-editor-actions .arco-btn { height:38px; border-radius:9px; font-weight:600; }
.trn-item-editor-body { min-height:0; overflow-y:auto; padding:28px 26px 42px; }
.trn-editor { width:min(1480px,100%); margin:0 auto; display:grid; grid-template-columns:minmax(650px,1fr) 390px; gap:25px; align-items:start; }
.trn-editor-main { min-width:0; }
.trn-editor-side { position:sticky; top:0; }
/* 五行表单：标签一列 104px、内容一列；行与行之间一条细线（照设计稿 Main.dc.html 的数值）。 */
.trn-five { background:#fff; border:1px solid #dbe3ee; border-radius:15px; box-shadow:0 3px 12px rgba(36,59,101,.06); overflow:hidden; }
.trn-five-row { display:grid; grid-template-columns:104px minmax(0,1fr); column-gap:18px; padding:18px 23px; }
.trn-five-row + .trn-five-row { border-top:1px solid #edf0f4; }
.trn-five-label { color:#18263d; font-size:15px; font-weight:700; line-height:32px; white-space:nowrap; }
.trn-five-when { display:flex; align-items:center; gap:14px; flex-wrap:wrap; }
.trn-five-chips { display:flex; gap:6px; flex-wrap:wrap; }
.trn-five-chip { height:32px; min-width:54px; padding:0 10px; box-sizing:border-box; border:1px solid #dbe3ee; border-radius:8px;
                 background:#fff; color:#4e5969; font-size:13px; cursor:pointer; }
.trn-five-chip:hover:not(:disabled) { border-color:var(--cf-accent-line); }
.trn-five-chip.on { border-color:var(--cf-accent2); box-shadow:0 0 0 2px var(--cf-soft2); color:#C2410C; font-weight:700; }
.trn-five-chip:disabled { cursor:not-allowed; opacity:.55; }
.trn-five-sep { display:block; width:1px; height:20px; background:#dbe3ee; }
.trn-five-stack { display:flex; flex-direction:column; gap:10px; min-width:0; }
.trn-five-field { display:flex; flex-direction:column; gap:4px; min-width:0; }
.trn-five-field > span { color:#76859a; font-size:12px; }
/* 多行的两格（要员工做什么 / 考核要求）：沿用单行框的底色与聚焦样式，只把高度与换行放开。 */
.cig-in.trn-five-multi { height:auto; min-height:48px; white-space:pre-wrap; overflow-y:auto; resize:vertical; }
.trn-five-btnline { display:flex; align-items:center; gap:8px; flex-wrap:wrap; color:#76859a; font-size:12px; }
.trn-five-btntag { padding:2px 8px; border-radius:6px; background:#e8efff; color:#3370ff; font-weight:600; }
.trn-five-btntag.none { background:#f2f3f5; color:#86909c; }
.trn-five-warn { color:#b54708; font-size:12px; line-height:1.5; }
.trn-five-side-head { display:flex; align-items:baseline; gap:8px; margin:0 0 12px; }
.trn-five-side-head b { color:#18263d; font-size:15px; }
.trn-five-side-head span { color:#76859a; font-size:12px; }
.trn-five-test { display:flex; align-items:center; justify-content:space-between; gap:12px; margin-top:12px;
                 padding:11px 12px; border:1px solid #e5e9ef; border-radius:10px; background:#fff; }
.trn-five-test b { display:block; color:#18263d; font-size:13px; }
.trn-five-test span { display:block; margin-top:2px; color:#8290a0; font-size:11px; }
.trn-modes { display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:8px; }
.trn-mode { display:block; width:100%; text-align:left; cursor:pointer; padding:10px;
            border:1px solid #dbe3ee; border-radius:10px; background:#fff; }
.trn-mode:hover:not(:disabled) { border-color:var(--cf-accent-line); }
.trn-mode.on { border-color:var(--cf-accent2); box-shadow:0 0 0 2px var(--cf-soft2); }
.trn-mode:disabled { cursor:not-allowed; opacity:.55; }
.trn-mode b { display:block; font-size:13px; margin-bottom:4px; }
.trn-mode span { display:block; color:var(--cf-ink4); font-size:10.5px; line-height:1.5; }
.trn-note { padding:11px 13px; border-radius:8px; background:var(--cf-surface); border:1px solid var(--cf-line);
            color:var(--cf-ink3); font-size:11.5px; line-height:1.65; }
.trn-note.warn { background:#fff8e6; border-color:#ffcf8b; color:#8a5300; }
.trn-reqs { display:flex; flex-wrap:wrap; gap:4px 18px; }
.trn-material-editor { border:1px solid #c9d2df; border-radius:10px; overflow:hidden; background:#fff; box-shadow:0 1px 2px rgba(31,35,41,.04); }
.trn-material-toolbar { display:flex; align-items:center; gap:8px; padding:9px 10px; background:#f6f8fb; border-bottom:1px solid #e3e8ef; }
.trn-material-toolbar .arco-btn { color:#246bfd; }
.trn-material-rich { min-height:96px; padding:15px 16px; outline:none; font-size:14px; line-height:1.8; color:#1f2329; white-space:pre-wrap; overflow-wrap:anywhere; }
.trn-material-rich:empty:before { content:attr(data-placeholder); color:#9aa4b2; pointer-events:none; }
.trn-material-rich p { margin:0 0 10px; }.trn-material-rich a { color:#246bfd; text-decoration:underline; cursor:text; }.trn-material-rich img { display:block; max-width:220px; max-height:150px; object-fit:cover; border-radius:7px; margin:10px 0; border:1px solid #e3e8ef; }
.trn-material-tip { margin-left:auto; color:#8a95a5; font-size:11px; }
.trn-pv-card { overflow:hidden; border:1px solid #d9e1ec; border-radius:10px; background:#fff; box-shadow:0 4px 13px rgba(29,49,90,.06); }
.trn-pv-head { padding:15px 16px 13px; background:#e8efff; border-bottom:1px solid #dce6f7; }
.trn-pv-head b { color:#18263d; font-size:16px; display:block; overflow-wrap:anywhere; }
.trn-pv-head span { display:block; margin-top:3px; color:#7084a2; font-size:12px; }
.trn-pv-body { padding:16px; }
.trn-pv-text { margin:0 0 13px; font-size:14px; line-height:1.7; color:#26364a; overflow-wrap:anywhere; }
/* 预览里「对应课件」「考核」两块：灰字小标题 + 内容，上面一条细线（卡片上是 hr 分隔）。 */
.trn-pv-sec { display:flex; flex-direction:column; gap:2px; padding:9px 0; border-top:1px solid #edf0f4; font-size:13px; line-height:1.55; color:#26364a; }
.trn-pv-sec > span { color:#9aa0a6; }
.trn-pv-sec p { margin:0; white-space:pre-wrap; overflow-wrap:anywhere; }
.trn-pv-sec a { color:#C2410C; text-decoration:underline; overflow-wrap:anywhere; }
.trn-pv-sec .trn-pv-muted { color:#9aa0a6; }
.trn-pv-sec-img { display:block; width:min(100%,180px); max-height:150px; margin:3px 0; object-fit:contain; object-position:left top;
                  border:1px solid #eef0f4; border-radius:5px; background:#f7f8fa; }
.trn-pv-btn { display:block; width:calc(100% - 32px); margin:0 16px 16px; border:0; border-radius:6px; background:#3370ff; color:#fff; text-align:center;
              font-size:14px; font-weight:800; padding:10px; overflow-wrap:anywhere; box-sizing:border-box; }
.trn-pv-state { margin:-4px 12px 12px; padding:8px 9px; color:#647287; background:#f6f8fb; border-radius:6px; font-size:11px; line-height:1.55; }
.trn-pv-state b { color:#344256; }
.trn-exams { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:11px; }
.trn-exam { background:#fff; border:1px solid var(--cf-line); border-radius:var(--r-lg); padding:15px; }
.trn-exam-top { display:flex; gap:9px; align-items:flex-start; }
.trn-exam-no { width:34px; height:34px; border-radius:8px; flex:none; display:grid; place-items:center;
               background:var(--cf-soft2); color:var(--cf-accent2); font-weight:800; }
.trn-exam h3 { margin:0 0 4px; font-size:14px; }
.trn-exam-stats { display:grid; grid-template-columns:repeat(4,1fr); gap:6px; margin:13px 0; }
.trn-exam-stats div { padding:7px; background:var(--cf-surface); border-radius:6px; }
.trn-exam-stats b { display:block; }
.trn-exam-stats span { font-size:10px; color:var(--cf-ink4); }
.trn-exam-editor-page { height:100%; min-height:0; display:flex; flex-direction:column; background:var(--cf-page); }
.trn-exam-editor-head { position:sticky; top:0; z-index:4; display:flex; align-items:center; gap:10px;
                        min-height:58px; padding:9px 14px; border-bottom:1px solid var(--cf-line); background:#fff; }
.trn-exam-editor-head h2 { margin:0; font-size:17px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.trn-exam-editor-head .muted { white-space:nowrap; }
.trn-exam-editor-actions { margin-left:auto; display:flex; align-items:center; gap:7px; flex:none; white-space:nowrap; }
.trn-exam-editor-body { flex:1; min-height:0; overflow-y:auto; padding:14px; }
.trn-exam-editor-sheet { max-width:1180px; margin:0 auto; padding:16px 18px; border:1px solid var(--cf-line);
                         border-radius:var(--r-lg); background:#fff; }
.trn-exam-config { display:grid; grid-template-columns:minmax(220px,1.35fr) minmax(190px,1.15fr) 82px 105px 122px;
                   gap:0 12px; align-items:start; }
.trn-exam-config .arco-form-item-label-col { white-space:nowrap; }
.trn-exam-section-head { display:flex; align-items:center; gap:10px; margin:2px 0 10px; }
.trn-exam-section-head .cf-idlab { font-size:12px; color:var(--cf-ink2); }
.trn-exam-section-head > .arco-btn { margin-left:auto; }
.trn-question-card { display:block; min-width:0; margin-top:10px; padding:13px 14px 4px;
                     border:1px solid var(--cf-line); border-radius:var(--r-lg); background:var(--cf-ground); }
.trn-question-head { display:flex; align-items:center; gap:9px; margin-bottom:11px; }
.trn-question-no { width:26px; height:26px; flex:none; display:grid; place-items:center; border-radius:7px;
                   color:var(--cf-accent2); background:var(--cf-soft2); font-size:11px; font-weight:700; }
.trn-question-head b { font-size:13px; color:var(--cf-ink); }
.trn-question-head > .arco-btn { margin-left:auto; }
.trn-question-fields { display:grid; grid-template-columns:120px 90px minmax(0,1fr) minmax(220px,1fr);
                       gap:0 12px; align-items:start; }
.trn-question-fields > * { min-width:0; }
/* 🔴 题干与选项**各占整行**（2026-09-10 用户实报「应该是一个完整的题干去填写啊，
   然后，你的选项也很多」）。改之前题干是 `1 / 3` ＝ 被钉死在前两列（题型 120 + 分值 90
   + 间距 ＝ **约 222px**，屏幕再宽也不长），而它装的是一整句题干；选项挤在右半边，
   每个选项框也只有半屏宽。
   ⚠️ 第一行仍是 题型 / 分值权重 / 正确答案 三格并排——那三个都是短字段，并排是对的；
   只有"要写一段话"的题干和"会有好几条"的选项需要整行。 */
.trn-question-prompt { grid-column:1 / -1; }
.trn-question-options { grid-column:1 / -1; }
.trn-question-correct { grid-column:3 / 5; }
.trn-question-explanation { grid-column:1 / -1; }
.trn-question-images { grid-column:1 / -1; }
/* 同上：不给 width 的话它收缩到 262px ⇒ 这是个 wrap 的图片墙，窄了会**提前换行**
   （一行只放得下 2 张，而整行宽度能放 8 张）。 */
.trn-question-images-list { display:flex; flex-wrap:wrap; gap:10px; width:100%; }
.trn-question-images-list > div { width:126px; }
.trn-question-images-list img { width:126px; height:82px; object-fit:cover; border-radius:6px; border:1px solid var(--cf-page); cursor:zoom-in; }
/* 🔴 `width:100%` 不能省（2026-09-10）：Arco 的 `.arco-form-item-content` 是 **flex row**，
   放进去的块级元素成了 flex item、`flex:0 1 auto` ⇒ **按内容宽度收缩**。实测这一列
   撑满是 1060px，而选项列表只有 244px、单个选项输入框 **151px** —— 写不下一句话。
   这是铁律 10⑰ 那条（form-item 内容区是 flex row）的又一次发作，只是上次表现为
   「说明小字被挤到右边」，这次表现为「输入框莫名其妙地窄」。 */
.trn-option-list { display:flex; flex-direction:column; gap:7px; width:100%; }
.trn-option-row { display:grid; grid-template-columns:26px minmax(0,1fr) 54px; gap:7px; align-items:center; }
.trn-option-row > b { width:26px; height:26px; display:grid; place-items:center; border-radius:6px;
                      background:var(--cf-soft2); color:var(--cf-accent2); font-size:11px; }
.trn-option-add { margin-top:7px; }
.trn-exam-preview { max-width:900px; margin:0 auto; }
.trn-exam-preview-cover { padding:22px; border:1px solid var(--cf-line); border-radius:var(--r-lg); background:#fff; }
.trn-exam-preview-cover h1 { margin:0 0 8px; font-size:22px; }
.trn-exam-preview-meta { display:flex; gap:18px; color:var(--cf-ink3); font-size:12px; }
.trn-exam-preview-question { margin-top:12px; padding:16px 18px; border:1px solid var(--cf-line);
                             border-radius:var(--r-lg); background:#fff; }
.trn-exam-preview-qhead { display:flex; align-items:flex-start; gap:12px; }
.trn-exam-preview-qhead b { flex:1; font-size:14px; line-height:1.7; }
.trn-exam-preview-qhead span { flex:none; color:var(--cf-ink4); font-size:11px; white-space:nowrap; }
.trn-exam-preview-options > div { display:flex; align-items:flex-start; gap:8px; margin-top:7px; padding:9px 10px;
                                  border:1px solid var(--cf-line); border-radius:7px; background:var(--cf-ground); }
.trn-exam-preview-options i { width:22px; height:22px; flex:none; display:grid; place-items:center; border-radius:50%;
                              background:#fff; border:1px solid var(--cf-line); color:var(--cf-accent2); font-style:normal; font-weight:700; }
.trn-exam-preview-images { display:flex; flex-wrap:wrap; gap:8px; margin-top:10px; }
.trn-exam-preview-images img { width:150px; height:100px; object-fit:cover; border-radius:7px;
                               border:1px solid var(--cf-line); cursor:zoom-in; }
.trn-image-preview { display:block; max-width:100%; max-height:75vh; margin:auto; object-fit:contain; }
@media (max-width:1180px) {
  .trn-metrics { grid-template-columns:repeat(3,minmax(0,1fr)); }
  .trn-exams { grid-template-columns:repeat(2,minmax(0,1fr)); }
  .trn-shell.plan-fixed .trn-plan { grid-template-columns:1fr; grid-template-rows:auto minmax(0,1fr); }
  .trn-shell.plan-fixed .trn-days { position:static; display:flex; gap:5px; max-height:none;
                                    overflow-x:auto; overflow-y:hidden; padding:5px; }
  .trn-shell.plan-fixed .trn-day { min-width:150px; padding:7px 8px;
                                  grid-template-columns:34px minmax(0,1fr); }
}
@media (max-width:900px) {
  .trn-shell,.trn-plan,.trn-setup { grid-template-columns:1fr; }
  .trn-bot-grid { grid-template-columns:1fr; }
  .trn-exams { grid-template-columns:1fr; }
  .trn-editor { grid-template-columns:1fr; }
  .trn-editor-side { position:static; }
  .trn-item-editor-head { padding:0 16px; }
  .trn-five-row { grid-template-columns:1fr; row-gap:6px; }
  .trn-modes { grid-template-columns:repeat(2,minmax(0,1fr)); }
}
@media (max-width:900px) {
  .trn-exam-config { grid-template-columns:repeat(2,minmax(0,1fr)); }
  .trn-exam-editor-head .muted { display:none; }
  .trn-question-fields { grid-template-columns:1fr; }
  .trn-question-prompt,.trn-question-options,.trn-question-correct,
  .trn-question-explanation,.trn-question-images { grid-column:auto; }
}
/* 身份卡：封面 + 四行 kv（设计稿 `.dw-top`）。这是"这条视频是什么"，
   与下面那条链是两件事 —— 链回答"它走到哪了"。 */
/* 详情页里内联展开的档案头。默认收起 —— 这一页的主体是段落列。 */
.cf-archbox { border:1px solid var(--cf-line); border-radius:var(--r-lg); background:#fff;
              margin:0 0 12px; overflow:hidden; }
.cf-archbox-b { padding:13px 14px 15px; }
.cf-arch-sec { font-size:11.5px; color:var(--cf-ink3); margin:16px 0 8px;
               display:flex; align-items:center; gap:8px; }
.cf-arch-sec::after { content:''; flex:1; height:1px; background:var(--cf-surface); }
.cf-arch-top { display:flex; gap:13px; margin-bottom:4px; }
.cf-arch-cov { width:112px; height:199px; flex:none; border-radius:var(--r-md); overflow:hidden;
               position:relative; background:linear-gradient(150deg,#78716C,#3F3B38); cursor:pointer; }
.cf-arch-cov img { width:100%; height:100%; object-fit:cover; display:block; }
.cf-arch-cov .pl { position:absolute; inset:0; margin:auto; width:32px; height:32px; border-radius:50%;
                   background:rgba(255,255,255,.9); color:var(--cf-ink); font-size:12px;
                   display:flex; align-items:center; justify-content:center; }
.cf-arch-cov .t { position:absolute; right:5px; bottom:5px; font-size:10px; color:#fff;
                  background:rgba(0,0,0,.6); border-radius:4px; padding:1px 5px; }
.cf-arch-meta { min-width:0; flex:1; }
.cf-arch-ttl { font-size:13.5px; color:var(--cf-ink); line-height:1.5; margin-bottom:9px;
               display:-webkit-box; -webkit-line-clamp:3; -webkit-box-orient:vertical; overflow:hidden; }
.cf-arch-kv { display:grid; grid-template-columns:46px minmax(0,1fr); gap:5px 9px; font-size:12px; }
.cf-arch-kv > .k { color:var(--cf-ink4); }
.cf-arch-kv > .v { color:var(--cf-ink2); min-width:0; overflow:hidden; text-overflow:ellipsis;
                   white-space:nowrap; }
/* 数据回溯时间线（设计稿 `.tl`）：一行一个时刻，末列标出这个数出自哪一列 ——
   四个点来自四条不同的抓取链，不标出处的话两个数对不上时没人说得清该信哪个。 */
.cf-arch-tl { border:1px solid var(--cf-line); border-radius:var(--r-md); overflow:hidden; }
.cf-arch-tlr { display:grid; grid-template-columns:48px 82px minmax(0,1fr) auto; gap:9px;
               align-items:baseline; padding:8px 11px; font-size:12px;
               border-bottom:1px solid #F4F3F2; }
.cf-arch-tlr:last-child { border-bottom:none; }
.cf-arch-tlr.on { background:var(--cf-soft2); }
.cf-arch-tlr > .d { color:var(--cf-ink4); font-variant-numeric:tabular-nums; }
.cf-arch-tlr > .w { color:var(--cf-ink); font-weight:600; white-space:nowrap; }
.cf-arch-tlr > .v { color:var(--cf-ink2); min-width:0; }
.cf-arch-tlr > .v b { color:var(--cf-ink); font-variant-numeric:tabular-nums; }
.cf-arch-tlr > .v em { font-style:normal; color:var(--cf-ok); font-size:11px; margin-left:3px; }
.cf-arch-tlr > .s { font-size:10px; color:var(--cf-ink4); font-family:ui-monospace,Menlo,monospace;
                    white-space:nowrap; }
/* 趋势条：灰豚给的曲线。**只在真有数据时渲染** —— 空图与"这条没人看"长得一样。 */
.cf-arch-spark { display:flex; align-items:flex-end; gap:2px; height:44px; margin-top:9px;
                 padding:0 2px; }
.cf-arch-spark > i { flex:1; background:var(--cf-accent-line); border-radius:2px 2px 0 0;
                     min-height:2px; }
.cf-arch-spark > i.on { background:var(--cf-accent); }
.cf-arch-sx { display:flex; font-size:10px; color:var(--cf-ink4); margin-top:3px; }
/* 「中间取不回来」的说明（设计稿那个 ⚠️ 块）：四个点连成的线看着像日粒度数据，
   不说清楚就是在暗示我们有这份数据。 */
.cf-arch-warn { margin-top:10px; padding:9px 11px; border-radius:var(--r-md);
                background:var(--cf-soft2); border:1px solid var(--cf-accent-line);
                font-size:11.5px; color:var(--cf-ink2); line-height:1.75; }
.cf-arch-step { display:flex; gap:11px; padding:11px 0; border-bottom:1px solid var(--cf-line); }
.cf-arch-step:last-child { border-bottom:0; }
.cf-arch-k { flex:none; width:52px; font-size:11px; color:var(--cf-ink4); padding-top:2px; }
.cf-arch-b { flex:1; min-width:0; font-size:12.5px; color:var(--cf-ink); line-height:1.65; }
.cf-arch-b .m { font-size:11.5px; color:var(--cf-ink3); }
.cf-arch-b .none { font-size:12px; color:var(--cf-ink4); }
.cf-arch-sub { margin-top:5px; padding-left:9px; border-left:2px solid var(--cf-line); }
.cf-arch-sub > div { font-size:12px; color:var(--cf-ink2); padding:2px 0; }
/* 继承来的标签：比自有的更淡一档，且不给 hover 反馈 —— 它点不动，
   长得能点就是在骗人（PRD §5.19.18）。 */
/* 🔴 **不用虚线**（2026-08-19 用户："测试标签展示样式不对"）：虚线框在这一带
   已经是「+ 加标签」那个**空占位**的样子，继承标签也用虚线，两个完全不同的东西
   （一个是可点的入口、一个是只读的值）在余光里长得一模一样，看着像个没填的输入框。
   改成实线 + 更淡的底：仍与自有标签分得开（自有是深字实底），但一眼是"一个值"。 */
/* 继承来的标签（设计稿 `.cf-idtag.inh`）：淡一档 + 一个 `↑` —— `↑` 是"它的源头在上游"
   这件事的**可见记号**，不是装饰。点它去切片库改（`cursor:pointer`，因为它真的能点）。
   ⚠️ **不用虚线**（2026-08-19 用户："测试标签展示样式不对"）：虚线框在这一带已经是
   「+ 加标签」那个空占位的样子，两个完全不同的东西看着一模一样。 */
.cf-idtag.inh { color:var(--cf-ink3); background:transparent;
                border-color:var(--cf-line); cursor:pointer; }
.cf-idtag.inh > u { text-decoration:none; font-size:9px; color:var(--cf-ink4); margin-left:2px; }
.cf-idtag.inh:hover { border-color:var(--cf-accent-line); color:var(--cf-accent);
                      background:var(--cf-soft2); }
.cf-idtag.inh:hover > u { color:var(--cf-accent); }
/* 打标签浮层（2026-08-19，PRD §5.19.18）。芯片一族刻意**复用** `.cf-idtag`
   —— 浮层里的芯片与行上那些是同一种东西，另起一套就是同一个样子的第二份实现。
   这里只加浮层这个盒子自己的三段（当前 / 候选 / 输入）。 */
.tagwrap { position:relative; display:inline-flex; }
.tagpop { position:absolute; left:0; top:24px; z-index:20; width:300px;
          padding:11px 12px 12px; background:#fff; border:1px solid var(--cf-line);
          border-radius:var(--r-lg); box-shadow:0 8px 24px rgba(28,25,23,.12);
          cursor:default; }
.tagpop-h { font-size:11px; color:var(--cf-ink4); margin:0 0 6px; display:flex;
            align-items:center; letter-spacing:.02em; }
.tagpop-h:not(:first-child) { margin-top:11px; }
.tagpop-cur, .tagpop-g { display:flex; gap:6px; flex-wrap:wrap; align-items:center;
                         min-height:22px; }
.tagpop-g { max-height:104px; overflow:auto; }
.tagpop .cf-idtag { cursor:pointer; }
.tagpop .cf-idtag.on { background:var(--cf-soft2); border-color:var(--cf-accent-line);
                       color:var(--cf-accent2); }
.tagpop .cf-idtag.off { opacity:.45; cursor:not-allowed; }
.tagpop-in { display:flex; gap:8px; align-items:center; margin-top:11px; }
.tagpop-f { display:flex; align-items:center; gap:8px; margin-top:12px; padding-top:10px;
            border-top:1px solid var(--cf-line); font-size:11.5px; }
.tagpop-in .cf-tg-in { font-size:12.5px; padding:5px 9px; }
.tagpop-in .cf-tg-in:disabled { background:var(--cf-surface); color:var(--cf-ink4); }
.cf-idtag-add { color:var(--cf-ink4); background:transparent;
                border:1px dashed var(--cf-line2); cursor:pointer; }
/* 缩略图角标（规范 §3.4）：★左上。右下时长与左下脚本两档随旧卡片墙一起退役了 */
.cf-thumb { position:relative; }
.cf-thumb-tl { position:absolute; font-size:11px; font-weight:600;
  border-radius:var(--r-sm); padding:2px 6px; left:7px; top:7px;
  background:var(--cf-ink); color:var(--cf-on-dark); }
/* 🔴 长标题的三处收口（2026-08-10 用户实报"标题超出正常长度"）。根因不在数据在渲染：
   任务标题存的是抖音口令原文（含全部 #话题，`fetch_video_by_link` 截到 80 字符），而
   vendor/arco.css 里 `.arco-modal-header{height:48px;flex-shrink:0}` 是**定高**、
   `.arco-modal-title{display:flex;flex:1}` **没有 min-width:0 也没有 overflow:hidden** ——
   于是长标题在 48px 的盒子里折成三行、**溢出到弹窗外面画**，就是截图里那个样子。
   任务表格那一列反而没事，因为它单独写了 ellipsis+tooltip ——正说明问题是
   「每个展示位各自决定截不截」，所以这里按作用域一次收口，而不是再补第四处。
   刻意只作用于 .cf-scope：全站别的弹窗标题都是短文案，去动 arco 基础样式风险大于收益。 */
.cf-scope .arco-modal-title, .cf-modal-clamp .arco-modal-title {
  min-width:0; display:block; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
  text-align:left; }
/* 案例页头的标题：filterbar 是 flex，长标题会把后面的时长/尺寸/按钮全挤出去 */
/* 🔴 **此处原先写着「380 是量出来的，不是估的……标题给 460 时合计 1232 > 容器 1216
   会把按钮挤到第二行」——那段是 2026-08-11（17ccb0a）为一条 380px 的规则写的，
   而那条规则早已不在**：2026-08-19 审计把整份样式表搜过一遍，唯一的 380 是
   `.cf-up-col`（不相干）。下面这条 live 规则用的是 `min(34vw,460px)`，
   正是那段注释判为"会溢出"的那个值 ⇒ **注释与规则互相打架，且注释是孤儿。**
   ⚠️ 保留这段订正而不是直接删掉：380→460 是后来有人**主动放宽**的（不是笔误），
   但放宽的理由没留下来。1440 视口 / 尾部 772px 实测：460 时仍有 1 个元素掉到第二行
   （被吃掉那 7 天里标题 533px、掉 2 个）—— 所以**它比没有规则好，但没到"一个都不掉"**。
   要收紧就改这一处的 460；改之前先拿**真实**的尾部构成量一遍，
   上面那个 772 也是当年量的、现在页头元素已经变过。 */
/* 详情页标题：规范 §1 的 --f-17 那一档就是给它的（列表页 19px、详情页 17px）。
   上一版用 14px，和旁边的元信息几乎一样大，页面上看不出哪个是标题。
   ⚠️ 注释写在**规则之上**，不要插进选择器中间（插进去 CSS 里照样生效、注释算空白，
   但没人读得懂）。
   🔴 **本条注释自己踩过一次，2026-08-19 审计才发现 —— b261868 起在生产上活了 7 天**：
   上一版这里为了举例，在注释体内**原样写出了一对 CSS 注释的收口符**。而 **CSS 注释不嵌套**
   ⇒ 整条注释在那个内层收口符上**提前结束**，剩下的说明文字连着下面那条规则的选择器一起
   变成一个非法选择器 ⇒ 浏览器**静默丢弃整条规则**（实测 CSSOM 里查无此条，1278→1277）。
   于是 `.cf-head-title` 恒是 13px、不截断，而本注释上面第二段写的正是"长标题会把后面的
   时长/尺寸/按钮全挤出去"—— **警告"标题没截断"的那条注释，自己把防它的规则吃掉了**。
   ⇒ 规则：**注释里描述 CSS 注释时，一律不许写出收口符本身**（用文字说，如本段）。
   `verify_inline_template §13` 已钉住 —— 判据是「顶层规则的选择器里不许有注释残渣」，
   钉的是规则不是这一处。 */
.cf-scope .cf-head-title { max-width:min(34vw,460px); overflow:hidden; text-overflow:ellipsis;
                           white-space:nowrap; font-size:17px; font-weight:600;
                           color:var(--cf-ink); cursor:text; flex-shrink:0; }
/* 标题被弹窗头截断了，全文放正文里：想看全的人看得到，不想看的也不会被三行标题糊住脸。
   可选中复制——抖音口令原文里带话题词，运营常要拿去用。 */
.cf-modal-clamp .cf-prev-title { margin-top:10px; font-size:12px; line-height:1.6;
                                 color:#57534E; max-height:5.6em; overflow-y:auto;
                                 word-break:break-all; user-select:text; }
/* .page 是 flex column：这里必须自己声明宽度约束链，否则左栏会被内容（视频原始宽）撑爆、
   右栏被挤成几像素（首验实测 1462px vs 4px）。align-self:stretch 让本行吃满父宽。 */
.cf-detail { display:flex; gap:16px; flex:1; min-height:0; width:100%; align-self:stretch; overflow:hidden; }
.cf-bgm { border:1px solid var(--cf-line); border-radius:8px; padding:10px; margin-top:8px; background:var(--cf-paper,#fff); line-height:1.6; }
.cf-bgm-head { display:flex; align-items:center; justify-content:space-between; gap:8px; white-space:nowrap; }
.cf-bgm-track { display:flex; flex-direction:column; padding:6px 0; min-width:0; overflow-wrap:anywhere; }
/* 左栏：视频与它底下的时间轴**必须同宽**（用户 2026-08-12 实拍指出）。
   原来 `.cf-left` 固定 360px、而 `.cf-vwrap` 又被 52vh 折算限窄到 ~245px，
   于是视频一条边、时间轴另一条边，看着像两块没对齐的东西。
   改法：整栏宽度**由视频那条比例算出来**，栏内所有块都填满它——一个宽度只有一处定义。 */
.cf-left { flex:0 0 auto; width:min(360px, 52vh * 9 / 16); min-width:0;
           display:flex; flex-direction:column; gap:8px; overflow-y:auto; }
/* 🔴 **左栏所有直接子项一律 `flex-shrink:0`**（2026-08-12 真数据实证）：
   column flex 容器在内容装不下时会把每个子项按 shrink 压扁，于是播放器从
   263×467 塌成 263×104、时间轴与缩略图条一起变矮。左栏本来就是 `overflow-y:auto`，
   装不下该滚，不该压。**逐个挂 `flex:none` 必漏一个**——挂在父级的通配上。 */
.cf-left > * { flex-shrink:0; }
/* 🔴 左栏里的块一律 border-box：`.cf-track` 是 content-box，`width:100%` 之外
   还有 8/10px 内边距 + 1px 边框 ⇒ 实际 300px，而视频 278px——两条边差 22px，
   看着就是"没对齐"。全站没有统一的 box-sizing 重置，所以在这里显式指定。 */
.cf-left > * { width:100%; box-sizing:border-box; }
/* video 本体只管填满外层：比例与限高都由 .cf-vwrap 负责（见那条注释里的坑）。 */
.cf-video { width:100%; height:100%; object-fit:contain; background:#000; display:block; }
.cf-track { flex:none; background:var(--cf-surface); border:1px solid var(--cf-line); border-radius:7px; padding:8px 10px; }
.cf-track-row { position:relative; height:12px; margin-bottom:4px; }
.cf-track-dots { height:9px; }
.cf-seg { position:absolute; top:0; height:12px; background:#FECACA; border-radius:5px; cursor:pointer; }
.cf-seg.on { background:var(--cf-accent); }
.cf-ov { position:absolute; top:0; height:8px; background:#e8c85a; border-radius:5px; cursor:pointer; }
.cf-dot { position:absolute; top:1px; width:7px; height:7px; border-radius:50%; background:#57534E; cursor:pointer; }
.cf-legend { display:flex; gap:12px; font-size:11px; color:var(--cf-ink3); margin-top:2px; }
.cf-legend i { display:inline-block; width:10px; height:8px; border-radius:5px; margin-right:3px; vertical-align:middle; }
.cf-legend .lg-seg { background:#FECACA; } .cf-legend .lg-ov { background:#e8c85a; }
.cf-legend .lg-dot { background:#57534E; border-radius:50%; width:7px; height:7px; }
/* 镜头缩略图：**铺满换行，不横滑**（用户 2026-08-12）——
   横滑时后面几个镜头压根看不见，而"这条片一共切了几镜、都是什么"正是要一眼看全的。 */
/* 一行横滑：天然只占一行高，31 镜也不会把左栏撑爆（铺满两行那版会撑到 500px+）。
   滚动条做细一点，不喧宾夺主。 */
.cf-strip { display:flex; gap:6px; overflow-x:auto; background:var(--cf-surface);
            border:1px solid var(--cf-line); border-radius:7px; padding:8px;
            box-sizing:border-box; scrollbar-width:thin; }
.cf-strip::-webkit-scrollbar { height:6px; }
.cf-strip::-webkit-scrollbar-thumb { background:var(--cf-line2); border-radius:3px; }
.cf-strip img { width:44px; height:78px; object-fit:cover; border-radius:5px; cursor:pointer; flex:0 0 auto; }
.cf-strip img:hover { outline:2px solid var(--cf-accent); }
.cf-right { flex:1 1 0; min-width:0; overflow-y:auto; padding-right:4px; }
.cf-clip { flex:0 0 150px; max-width:150px; }
.cf-clip video { width:150px; aspect-ratio:9/16; border-radius:7px; background:#000; }
/* 收紧（用户 2026-08-12：「看下来太空了，信息密度有限」）：
   标签列 78→60px、行距 7→3px。收的是**空白**不是内容——每一行原样都在。 */
/* 区块里标题已经说了是什么，就不再摆一个重复的 label 占 78px */
/* ⚠️ 单列布局下，子元素身上任何 `grid-column:2` 都会**凭空造出一条隐式列**
   （表现是台词被挤成窄窄一条、复刻条跑到右边）。`.cf-repro` 的那条已随之删掉。 */
/* 台词里的重点词标黄——与词级拆解里「」引的词一一对应，看的时候不用来回找 */
.cf-kw { background:#ffe9a8; color:inherit; border-radius:5px; padding:0 3px; font-weight:600;
         cursor:pointer; }
.cf-kw:hover { outline:1px dashed #d48806; }
/* 人工标黄（2026-08-18 第二轮）：与模型标的**一眼分得开** —— 虚线下划线 + 后面跟一个「×」。
   🔴 用"下划线"而不是换个底色：底色已经被"标黄/已锁定"两态占满了，再加一种颜色
      会让三种状态在一眼之下分不清，而其中一种（已锁定）是会影响产出的。 */
.cf-kw-man { border-bottom:1px dashed var(--cf-ink4); }
.cf-kw-x { font-size:11px; color:var(--cf-ink4); cursor:pointer; margin:0 4px 0 1px;
           font-style:normal; }
.cf-kw-x:hover { color:var(--cf-bad); }
/* ═══ 选中文字后的浮框（2026-08-18 第三轮，用户「变成选中以后，类浮框的形式出现」）═══
   🔴 **一个浮框，动作按选区落在哪一侧给**（用户拍板 A 案）：
      左侧原文台词 → 标黄选中 / 加进卡审词库；右侧复刻产出 → 加进卡审词库 / 修改选中部分。
      不做"三个都摆出来、不适用的置灰" —— 那样人要对着一个灰按钮猜为什么不能点，
      而要解释的是"原文是事实快照、复刻才是可改写的产出"，一个 tooltip 说不清。
   ⚠️ `position:fixed` + 贴着选区矩形摆：跟着页面滚动会漂，而这个浮框的生命周期
      就是"这一次选中"，滚动时本来就该收起（见 `cfSelBarHide`）。
   ⚠️ 它**不能自己清掉选区** —— 整块 `mousedown` 都要 preventDefault（见模板）。 */
/* 2026-08-22 改轻（用户「这个现在感觉很重，参考飞书那种形态」）。拿掉三样：
   ① **不再把选中的字抄一遍**——它已经蓝底高亮在那儿了，抄一遍最长占掉浮框一半宽，
      而且让浮框宽度**随选区长度变化**，同一个浮框每次弹出来都不一样宽；
   ② **emoji 换单色线条图标**——🖍⛔✦ 三个 emoji 各带一套自己的颜色，
      在白色小浮框里就是三个最亮的点，比文字还抢眼；
   ③ **拿掉「取消」**——点别处 / Esc / 滚动都会收起（`cfSelBarHide` 三条早就实现了），
      再给一个按钮等于用一个常驻位置说一件本来就会发生的事。
   ⚠️ 字反而**调大**了（12.5→13.5）：轻不等于小，轻是"每个元素只说一件事"。 */
.cf-selbar { position:fixed; z-index:1200; display:inline-flex; align-items:center; gap:1px;
             padding:4px; border-radius:11px; background:#fff; flex-wrap:wrap;
             border:1px solid rgba(28,25,23,.08);
             box-shadow:0 1px 3px rgba(28,25,23,.06), 0 6px 20px rgba(28,25,23,.10);
             /* 🔴 `max-width` 不能省：`position:fixed` 只设了 `left`，不封顶的话它会一路
                拉到视口右边缘 —— 于是"量出来的宽度"本身就含着溢出，
                `cfSelBarAsk` 里那次回夹每次只能挪 12px、永远夹不回来（本次真点一遍量到的）。 */
             max-width:min(640px, calc(100vw - 24px)); }
.cf-selbar a { display:inline-flex; align-items:center; gap:6px; padding:7px 11px;
               border-radius:8px; color:var(--cf-ink1); cursor:pointer; white-space:nowrap;
               font-size:13.5px; line-height:1.2; }
.cf-selbar a:hover { background:var(--cf-surface); }
.cf-selbar a.on { background:var(--cf-soft); color:var(--cf-accent); }
.cf-selbar a.hot { color:var(--cf-accent); font-weight:600; }
.cf-selbar a.off { opacity:.45; cursor:default; }
.cf-selbar a.off:hover { background:transparent; }
.cf-selbar svg { width:16px; height:16px; flex:none; color:var(--cf-ink3); }
.cf-selbar a.on svg, .cf-selbar a.hot svg { color:var(--cf-accent); }
.cf-selbar a.sb-g:hover svg { color:var(--cf-ok); }
.cf-selbar a.sb-b:hover svg { color:var(--cf-warn); }
.cf-selbar .cf-selbar-sp { width:1px; height:18px; background:var(--cf-line); margin:0 4px;
                           flex:none; }
/* ⚠️ `.cf-selbar-q` / `.cf-selbar-rz` / `.cf-selbar-skip`（问原因那一态）
   已于 2026-08-26 随那一步一起删除 —— 模板里没人用了，留着就是死 CSS（铁律 10⑥）。 */
/* ⋯ 溢出：主态最多三个动作，多的收进来。复刻侧要放好/不好/改写，不收会挤成一条横幅 */
.cf-selbar-more { position:fixed; z-index:1201; background:#fff; padding:5px;
                  border:1px solid rgba(28,25,23,.08); border-radius:10px;
                  display:flex; flex-direction:column;
                  box-shadow:0 1px 3px rgba(28,25,23,.06), 0 6px 20px rgba(28,25,23,.10); }
.cf-selbar-more a { display:inline-flex; align-items:center; gap:6px; padding:7px 11px;
                    border-radius:8px; color:var(--cf-ink1); cursor:pointer;
                    white-space:nowrap; font-size:13.5px; }
.cf-selbar-more a:hover { background:var(--cf-surface); }
.cf-selbar-more svg { width:16px; height:16px; color:var(--cf-ink3); }
/* 复刻产出里的**卡审词命中**（2026-08-18 第二轮，需求④）。
   🔴 用红：绿已经是「扫雷干净」、黄是标黄/锁定词 —— 三种标记在一眼之下必须分得开，
      而这一种是"可能过不了审"，是三者里唯一需要人动手的。 */
.cf-ban { background:var(--cf-bad-bg, #FEF2F2); color:var(--cf-bad); border-radius:3px;
          padding:0 2px; text-decoration:underline wavy var(--cf-bad); text-underline-offset:3px; }
/* ═══ 高光画面（2026-08-22，PRD §5.19.28）═══
   🔴 颜色用**琥珀** `--cf-hl`：高光画面是从高光词（黄）长出来的，视觉上同族，
      一眼看得出这两件事是一件事。不用主色橙红（那是「要人动一下」和当前位置专用）。 */
.cf-kw-hl { display:inline-flex; align-items:center; gap:3px; margin-left:3px; vertical-align:2px;
            border:1px solid var(--cf-hl-line); background:var(--cf-hl-bg); color:#854D0E;
            border-radius:5px; padding:0 5px 0 3px; font-size:10.5px; line-height:16px;
            font-variant-numeric:tabular-nums; cursor:pointer; }
.cf-kw-hl img { width:12px; height:16px; object-fit:cover; border-radius:2px; flex:none; }
.cf-hlblk { margin-top:14px; border:1px solid var(--cf-hl-line); background:var(--cf-hl-bg);
            border-radius:10px; padding:11px 12px 13px; }
.cf-hlblk-h { display:flex; align-items:center; gap:9px; margin-bottom:10px; }
.cf-hlblk-h b { color:#854D0E; font-size:12.5px; }
.cf-hlblk-h .n { font-size:11px; color:#A16207; font-variant-numeric:tabular-nums; }
.cf-hlblk-h a { margin-left:auto; font-size:12px; color:var(--cf-accent); cursor:pointer; }
.cf-hlgrid { display:grid; grid-template-columns:repeat(auto-fill,minmax(132px,1fr)); gap:10px; }
.cf-hli { background:#fff; border:1px solid var(--cf-line); border-radius:8px; overflow:hidden; }
/* 竖屏片要看着像竖屏：深色信箱底 + 定宽缩略图，别把 9:16 拉成一条横带 */
.cf-hli-th { background:var(--cf-dark); display:grid; place-items:center; padding:7px 0;
             position:relative; cursor:pointer; }
.cf-hli-th img { width:70px; height:110px; object-fit:cover; border-radius:3px; display:block; }
.cf-hli-th .ph { width:70px; height:110px; border-radius:3px;
                 background:linear-gradient(155deg,#57534E,#292524); }
.cf-hli-b { padding:6px 8px 8px; }
.cf-hli-r1 { display:flex; align-items:center; gap:5px; font-size:10.5px; color:var(--cf-ink3);
             font-variant-numeric:tabular-nums; }
.cf-hli-r1 .d { margin-left:auto; color:#A16207; }
.cf-hli-w { font-size:12px; color:var(--cf-ink); margin-top:3px; overflow:hidden;
            text-overflow:ellipsis; white-space:nowrap; display:block; }
.cf-hli-k { font-size:11px; color:var(--cf-ink3); overflow:hidden; text-overflow:ellipsis;
            white-space:nowrap; display:block; }
/* 卡片底部＝「点开这一条」（2026-08-24）。整块可点，所以要有 hover 与手型 ——
   没有反馈的可点区域和不可点的说明文字长得一模一样。
   ⛔ 这里原先是「自动 · 待确认」两个角标的样式（`.cf-hli-auto` / `.cf-hlib-auto`），
      随那道确认一起删掉了；删版式要连 CSS 一起删（铁律 10⑥），留着就是死 CSS。 */
/* 「划一条」那个极简弹窗（2026-08-24）：两行时间码 + 一行名字，没有第三块。 */
.cf-hla-row { display:flex; align-items:center; gap:9px; margin-bottom:9px; }
.cf-hla-row label { width:30px; flex:none; font-size:12.5px; color:var(--cf-ink2); }
.cf-hla-tip { margin:8px 0 0 39px; font-size:11.5px; line-height:1.65; color:var(--cf-ink3); }
.cf-hli-b.act { cursor:pointer; }
.cf-hli-b.act:hover { background:var(--cf-hl-bg); }
.cf-hli-k.go { color:var(--cf-accent); }
/* 入库那颗星（2026-08-24）。**左上角** —— 删除的 ✕ 在右上角，两个动作分两个角。 */
.cf-hli-star { position:absolute; top:3px; left:4px; width:20px; height:20px; z-index:2;
               display:grid; place-items:center; border-radius:4px; cursor:pointer;
               color:#fff; opacity:.5; background:rgba(41,37,36,.5); }
.cf-hli-star svg { width:13px; height:13px; }
.cf-hli-star:hover { opacity:1; }
.cf-hli-star.on { opacity:1; color:#fff; background:var(--cf-hl); }
.cf-hli-star.off { opacity:.35; pointer-events:none; }
.cf-hlblk-h .n b { color:#854D0E; font-weight:600; }
.cf-hlblk-h .n b.zero { color:#A16207; font-weight:400; }
/* 「这个类型是机器标的」——纯出处不是待办：不拦事、没有确认按钮，人一改就消失。 */
.cf-hli-k .ai { font-style:normal; margin:0 3px 0 4px; font-size:9px; color:var(--cf-info);
                background:var(--cf-info-bg); border:1px solid var(--cf-info-line);
                border-radius:3px; padding:0 3px; }
.cf-hli-x { position:absolute; top:3px; right:4px; color:#fff; opacity:.55; font-size:12px;
            cursor:pointer; }
.cf-hli-x:hover { opacity:1; }
.cf-hli-zoom { position:absolute; left:4px; bottom:4px; color:#fff; opacity:.55; cursor:pointer;
               line-height:0; }
.cf-hli-zoom:hover { opacity:1; }
.cf-hli-zoom svg { width:13px; height:13px; }
.cf-hlline { margin-top:14px; font-size:12.5px; color:var(--cf-ink3); padding:9px 12px;
             background:var(--cf-ground); border:1px dashed var(--cf-line2); border-radius:8px; }
.cf-hlline b { color:var(--cf-ink2); }
.cf-hlline a { color:var(--cf-accent); margin-left:6px; cursor:pointer; }
/* ── 高光库（2026-08-22，PRD §5.19.28）──
   🔴 **卡片墙不做表格**：内容就是图，改表格后"看图选"会变成"看名字选"
      （图工厂那四个卡片墙页当年就是为这条理由保留的卡片形态）。 */
.cf-hlib-bar { display:flex; align-items:center; gap:9px; flex-wrap:wrap;
               padding-bottom:12px; border-bottom:1px solid var(--cf-line); }
.cf-hlib-k { border:1px solid var(--cf-line2); background:#fff; border-radius:6px;
             padding:2px 10px; font-size:12px; color:var(--cf-ink2); cursor:pointer;
             white-space:nowrap; }
.cf-hlib-k.on { border-color:var(--cf-hl); background:var(--cf-hl-bg); color:#854D0E;
                font-weight:600; }
.cf-hlib-k .n { color:var(--cf-ink4); margin-left:4px; font-variant-numeric:tabular-nums; }
.cf-hlib-k.on .n { color:#A16207; }
/* 竖屏片要看着像竖屏：深色信箱底 + 定宽缩略图（同段内那份，别把 9:16 拉成横带） */
/* 🔴 词摆在最上面，比来源和时间都靠上：翻这个库的人心里想的是
      「找一个『我家娃也是』这种共鸣画面」，不是「找 12 秒那条」。 */
/* ═══ 高光库：列表（2026-08-24 用户拍板，与切片库/灵感库同一套自绘 grid）═══
   ⛔ 这里原先是卡片墙（`.cf-hlib-grid` / `.cf-hlib-card` / `.cf-hlib-b` 那一族）。
      用户看过之后要"和别的菜单一样用列表" —— 缩略图那一列还在，"看图选"没丢，
      只是多了类型、来源、谁存的这几列，翻库时能横着比。
      删版式要连 CSS 一起删（铁律 10⑥），所以那几条一并去掉。 */
.cf-rows-hl .cf-rows-h, .cf-rows-hl .cf-row {
  grid-template-columns:26px 56px minmax(150px,1.3fr) 48px 116px minmax(180px,1.2fr) 88px 52px; }
/* 没有勾选列时（只读用户）少一列 —— 照成品库那条先例，`:has()` 判断 */
.cf-rows-hl .cf-rows-h:not(:has(.cf-row-pick)), .cf-rows-hl .cf-row:not(:has(.cf-row-pick)) {
  grid-template-columns:56px minmax(150px,1.3fr) 48px 116px minmax(180px,1.2fr) 88px 52px; }
/* 就地改类型：那一格得看得出能点 —— 不给反馈的可点区域和纯标签长得一模一样 */
.cf-hlib-kd.act { cursor:pointer; }
.cf-hlib-kd.act:hover { border-color:var(--cf-hl); background:var(--cf-hl-bg); color:#854D0E; }
.cf-hlib-kd.act.none:hover { color:var(--cf-accent); border-color:var(--cf-accent-line); }
.cf-hlr-w { font-size:13px; color:var(--cf-ink); font-weight:600; overflow:hidden;
            text-overflow:ellipsis; white-space:nowrap; display:block; }
.cf-hlr-w.none { color:var(--cf-ink4); font-weight:400; }
.cf-hlr-ts { font-style:normal; font-size:11px; color:var(--cf-ink4);
             font-variant-numeric:tabular-nums; }
.cf-hlr-d { font-size:12px; color:#A16207; font-variant-numeric:tabular-nums; }
.cf-hlr-src { font-size:12px; color:var(--cf-ink3); overflow:hidden; text-overflow:ellipsis;
              white-space:nowrap; display:block; cursor:pointer; flex:1; min-width:0; }
.cf-hlr-src:hover { color:var(--cf-accent); }
.cf-hlr-by { font-size:11.5px; color:var(--cf-ink2); overflow:hidden; text-overflow:ellipsis;
             white-space:nowrap; display:block; }
.cf-hlr-by i { font-style:normal; display:block; font-size:10.5px; color:var(--cf-ink4);
               font-variant-numeric:tabular-nums; }
.cf-hlr-by em { font-style:normal; color:var(--cf-line2); }
.cf-row-th .pl { position:absolute; left:50%; top:50%; transform:translate(-50%,-50%);
                 color:#fff; font-size:13px; font-style:normal; text-shadow:0 1px 3px rgba(0,0,0,.5); }
/* 「这个类型是机器标的」——**纯出处不是待办**：不拦事、没有确认按钮，
   人一改就永久消失。与 08-24 刚点掉的那个「自动 · 待确认」不是一回事。 */
.cf-hlib-kd .ai { font-style:normal; margin-left:4px; font-size:9px; color:var(--cf-info);
                  background:var(--cf-info-bg); border:1px solid var(--cf-info-line);
                  border-radius:3px; padding:0 3px; }
.cf-hlib-kd.none { color:var(--cf-ink4); border-style:dashed; }
.cf-hlib-empty { padding:38px 30px; text-align:center; display:flex; flex-direction:column;
                 align-items:center; gap:10px; border:1px dashed var(--cf-line2);
                 background:var(--cf-ground); border-radius:var(--r-lg); margin:14px; }
.cf-hlib-empty svg { width:34px; height:34px; color:var(--cf-ink4); }
.cf-hlib-empty b { font-size:14px; color:var(--cf-ink); }
.cf-hlib-empty p { max-width:440px; margin:0; font-size:12px; line-height:1.9;
                   color:var(--cf-ink3); }
.cf-hlib-empty p b { font-size:12px; }
.cf-hlib-empty i { font-style:normal; font-size:11.5px; color:var(--cf-ink4); }
/* 抽屉：三段从近到远 —— 这一段画面 / 在原片的哪儿 / 原片 */
/* 详情页（2026-08-24 从抽屉改成独立页）：左边这一段画面、右边它在原片的哪儿 + 原片。 */
.cf-hlv-cols { display:flex; gap:26px; align-items:flex-start; padding:16px 18px 20px; }
.cf-hlv-l { width:236px; flex:none; }
/* 🔴 `min-width:0` 缺一层，右栏里那些 ellipsis 的行就撑破整页（铁律 10⑯） */
.cf-hlv-r { flex:1; min-width:0; }
@media (max-width:900px){ .cf-hlv-cols { flex-direction:column; } .cf-hlv-l { width:100%; } }
.cf-hlv-sect { font-size:11px; color:var(--cf-ink4); letter-spacing:.04em; margin:18px 0 9px; }
.cf-hlv-sect:first-child { margin-top:0; }
.cf-hlv-l .cf-hlv-sect:first-child, .cf-hlv-r .cf-hlv-sect:first-child { margin-top:0; }
.cf-hlv-v { width:100%; aspect-ratio:9/16; border-radius:8px; display:block;
            background:var(--cf-dark); object-fit:cover; }
.cf-hlv-v.ph { background:linear-gradient(155deg,#57534E,#292524); }
.cf-hlv-kv { display:flex; gap:10px; font-size:12px; line-height:1.9; }
.cf-hlv-kv > i { font-style:normal; color:var(--cf-ink4); width:56px; flex:none; }
.cf-hlv-kv > span { color:var(--cf-ink); flex:1; min-width:0; }
.cf-hlv-kv .none { color:var(--cf-ink4); }
.cf-hlv-seg { margin-top:10px; border:1px solid var(--cf-hl-line); background:var(--cf-hl-bg);
              border-radius:8px; padding:9px 11px; }
.cf-hlv-seg .h { display:flex; align-items:baseline; gap:8px; flex-wrap:wrap; }
.cf-hlv-seg .h b { font-size:12.5px; color:#854D0E; }
.cf-hlv-seg .h .num { font-size:11px; color:#A16207; }
.cf-hlv-seg .h .st { font-size:10.5px; color:#854D0E; background:#fff;
                     border:1px solid var(--cf-hl-line); border-radius:4px; padding:0 6px; }
.cf-hlv-seg .l { font-size:12px; color:var(--cf-ink2); line-height:1.75; margin-top:6px; }
.cf-hlv-seg .l.none { color:var(--cf-ink4); }
.cf-hlv-t { font-size:13px; color:var(--cf-ink); line-height:1.6; font-weight:600;
            display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical;
            overflow:hidden; }
.cf-hlv-spec { font-size:11.5px; color:var(--cf-ink3); margin-top:5px; }
.cf-hlv-perf { margin-top:10px; border:1px solid var(--cf-line); background:var(--cf-ground);
               border-radius:8px; padding:9px 11px; }
.cf-hlv-perf .g { display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:4px; }
.cf-hlv-perf .g > div { text-align:center; }
.cf-hlv-perf .g b { display:block; font-size:14px; color:var(--cf-ink); }
.cf-hlv-perf .g i { font-style:normal; font-size:10.5px; color:var(--cf-ink4); }
/* 🔴 取数时刻**必须标出来**：不标的话「12.4 万赞」看着像实时的 */
.cf-hlv-perf .at { font-size:10.5px; color:var(--cf-ink4); margin-top:8px; text-align:center; }
/* 🔴 缺数与 0 分得开（报表页硬规 8）：没有战绩就说清为什么，不渲染一排 0 */
.cf-hlv-noperf { margin-top:10px; border:1px dashed var(--cf-line2); background:var(--cf-ground);
                 border-radius:8px; padding:9px 11px; font-size:11.5px; color:var(--cf-ink3);
                 line-height:1.75; }
.cf-hlv-noperf .none { color:var(--cf-ink4); }
.cf-hlib-kd { display:inline-block; margin-top:6px; border:1px solid var(--cf-line);
              background:var(--cf-surface); border-radius:5px; padding:0 6px; font-size:10.5px;
              color:var(--cf-ink2); }

/* ── 写法库（2026-08-23，PRD §5.19.27 · L1）── */
/* ── 说法库（2026-08-26，PRD §5.19.27）──
   上一版那整组 `.cf-wr*`（写法规则卡片）随页面一起删掉了 —— 类名留着而模板里没人用，
   就是铁律 10⑥ 说的死 CSS，而死 CSS 会让"钉住某条规则"的断言靠它自己通过。
   这里只剩两条：说法本体 + 它的原段落。 */
.cf-say-t { font-size:12.5px; color:var(--cf-ink); line-height:1.6;
            overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
/* 原段落两行封顶：一行看不全上下文（这一列存在的全部理由就是"这句话从哪来的"），
   三行会把每一行撑到 90px 高。超出的全文走 title 悬停。 */
.cf-say-b { margin-top:3px; font-size:11.5px; line-height:1.65; color:var(--cf-ink4);
            display:-webkit-box; -webkit-box-orient:vertical; -webkit-line-clamp:2;
            overflow:hidden; white-space:normal; }
/* 被标的那几个字在原段落里的位置：颜色与「判断」列同源（认可绿 / 否掉红）。
   ⚠️ 用下划线不用底色 —— 这一段本来就是灰字，加底色会糊成一团。 */
.cf-say-b .g { color:var(--cf-ok); text-decoration:underline; text-underline-offset:2px; }
.cf-say-b .b { color:var(--cf-bad); text-decoration:underline; text-underline-offset:2px; }

/* ── 设为高光词：词 / 解读 / 画面 一次做完（2026-08-23，用户「变成一整套」）──
   🔴 **必须是弹窗不能塞进选中浮框**：那个浮框整块挂着 `@mousedown.prevent`
      （不挡的话点它的瞬间浏览器就把选区折叠了），而 `preventDefault` 会**连带挡掉
      textarea 的聚焦** —— 输入框摆进去就是个点不动的框，而且零报错。 */
.cf-kwset { width:480px; }
.cf-kwset-w { display:flex; align-items:baseline; gap:9px; padding:10px 12px;
              border:1px solid var(--cf-hl-line); background:var(--cf-hl-bg);
              border-radius:9px; }
.cf-kwset-w b { background:var(--cf-hz); border-radius:4px; padding:1px 6px;
                color:var(--cf-ink); font-weight:600; }
.cf-kwset-w .ts { margin-left:auto; font-size:11.5px; color:#A16207;
                  font-variant-numeric:tabular-nums; }
.cf-kwset-l { font-size:12px; color:var(--cf-ink2); margin:14px 0 6px; }
.cf-kwset-l span { color:var(--cf-ink4); margin-left:6px; font-size:11.5px; }
.cf-kwset-hl { display:flex; align-items:flex-start; gap:8px; margin-top:14px;
               padding:10px 12px; border:1px solid var(--cf-line); border-radius:9px;
               background:var(--cf-ground); cursor:pointer; }
.cf-kwset-hl.off { opacity:.6; }
.cf-kwset-hl .t { flex:1; min-width:0; font-size:12.5px; color:var(--cf-ink1); line-height:1.7; }
.cf-kwset-hl .t i { display:block; font-style:normal; font-size:11.5px; color:var(--cf-ink3);
                    margin-top:2px; }
.cf-kwset-no { margin-top:14px; font-size:12px; line-height:1.7; color:var(--cf-warn);
               background:var(--cf-soft2); border:1px solid var(--cf-softline);
               border-radius:8px; padding:8px 11px; }

/* ── 划定台 ── */
.cf-hd-body { display:flex; flex-direction:column; }
/* ═══ 挑这几秒：画面 + 时间条（2026-08-24，组件 `hl-trim`）═══
   用户原话两句，其实是同一件事 —— **挑时间得看着画面挑**：
     图 1「就展示我选中的高光画面，然后支持移动对应的时间戳就可以了，现在搞得太复杂了」
     图 2「支持时间戳选中的时候，要有原来对应的视频画面才行」
   ⛔ 这里原先是 `.cf-hd-strip`/`.cf-hd-sh`（17 张镜头缩略图）+ `.cf-hd-snap`（吸附绿字）
      + `.cf-hd-io`（只读的起止显示）+ `.cf-hd-prev`（单独的预览位）。
      **能力一样没丢**，全落到这条时间条上了：切点＝条上细白线、把手靠近自动吸、
      两个数从只读变成可改。删版式要连 CSS 一起删（铁律 10⑥），所以那几条一并去掉。
   🔴 选中的**亮着**、外面**压暗**，不是给选中区上一层橙色 —— 一眼看得出"要的是这几秒"。 */
.hlt-top { display:flex; gap:18px; }
.hlt-top.solo { justify-content:center; }
/* 🔴 限高放在**外层容器**上（`verify_cf` 那条钉着的规则）：
   带 `aspect-ratio` 的元素同时写死 `width` 与 `max-height` 会把 9:16 压变形，
   而页面上只表现为"预览有点扁"，没人会报。高度由宽度算出来，比例照样成立。 */
.hlt-prev { width:min(186px, 46vh * 9 / 16); flex:none; }
.hlt-prev video { width:100%; aspect-ratio:9/16; border-radius:8px;
                  background:var(--cf-dark); display:block; }
.hlt-side { flex:1; min-width:0; }
.hlt-tl { position:relative; height:46px; margin-top:14px; border-radius:8px; overflow:hidden;
          background:var(--cf-dark); cursor:ew-resize; user-select:none; }
.hlt-film { position:absolute; inset:0; }
.hlt-film img { position:absolute; top:0; height:46px; object-fit:cover; }
.hlt-dim { position:absolute; top:0; bottom:0; background:rgba(24,22,20,.68);
           pointer-events:none; z-index:1; }
.hlt-band { position:absolute; top:0; bottom:0; pointer-events:none; z-index:2;
            box-shadow:inset 0 0 0 2px var(--cf-accent); }
.hlt-cut { position:absolute; top:0; bottom:0; width:1px; background:rgba(255,255,255,.45);
           pointer-events:none; z-index:3; }
.hlt-seg { position:absolute; bottom:0; height:3px; background:var(--cf-hl);
           pointer-events:none; z-index:3; }
.hlt-grip { position:absolute; top:0; bottom:0; width:16px; margin-left:-8px;
            cursor:ew-resize; z-index:4; }
.hlt-grip::after { content:''; position:absolute; left:5px; top:0; bottom:0; width:6px;
                   border-radius:3px; background:var(--cf-accent);
                   box-shadow:0 0 0 1px rgba(255,255,255,.6), 0 1px 3px rgba(0,0,0,.4); }
.hlt-grip::before { content:''; position:absolute; left:9px; top:50%; margin-top:-6px;
                    width:2px; height:12px; border-radius:1px;
                    background:rgba(255,255,255,.75); z-index:1; }
/* 吸附**要出声**：把手自己动了一下而不说话会像是 bug。 */
.hlt-lab { position:absolute; left:50%; transform:translateX(-50%); top:-23px; white-space:nowrap;
           background:var(--cf-ink); color:#fff; font-size:10.5px; padding:1px 7px;
           border-radius:5px; pointer-events:none; font-variant-numeric:tabular-nums;
           opacity:0; transition:opacity .12s; }
.hlt-grip.on .hlt-lab, .hlt-grip:hover .hlt-lab { opacity:1; }
.hlt-bar { display:flex; align-items:center; gap:9px; margin-top:9px; flex-wrap:wrap; }
.hlt-bar label { font-size:12.5px; color:var(--cf-ink2); }
.hlt-bar .ts { font-size:11.5px; color:var(--cf-ink3); font-variant-numeric:tabular-nums; }
.hlt-bar .dur { font-size:12.5px; color:#854D0E; font-weight:600;
                font-variant-numeric:tabular-nums; }
.hlt-bar .grow { flex:1; }
.hlt-note { margin-top:7px; font-size:11.5px; line-height:1.7; color:var(--cf-ink3); }
.hlt-note b { color:var(--cf-ink2); font-weight:600; }
.cf-hd-for { border:1px solid var(--cf-hl-line); background:var(--cf-hl-bg); border-radius:9px;
             padding:10px 12px; display:flex; gap:10px; align-items:flex-start; }
.cf-hd-for .w { background:var(--cf-hz); border-radius:4px; padding:1px 6px; color:var(--cf-ink);
                font-weight:600; flex:none; }
.cf-hd-for .t { flex:1; min-width:0; font-size:12.5px; color:#854D0E; line-height:1.7; }
.cf-hd-for .from { font-size:11px; color:#A16207; flex:none; text-align:right;
                   font-variant-numeric:tabular-nums; }
.cf-hd-tip { margin-top:11px; font-size:12px; line-height:1.72; color:var(--cf-warn);
             background:var(--cf-soft2); border:1px solid var(--cf-softline); border-radius:8px;
             padding:8px 11px; }
.cf-hd-tip b { color:#7C2D12; }
.cf-hd-lab { display:flex; align-items:baseline; gap:8px; margin:15px 0 7px; }
.cf-hd-lab b { font-size:12.5px; color:var(--cf-ink1); }
.cf-hd-lab span { font-size:11.5px; color:var(--cf-ink3); }
.cf-hd-cover { display:flex; align-items:center; gap:8px; margin-top:10px; }
.cf-hd-cover span { font-size:11.5px; color:var(--cf-ink3); }
.cf-hd-kinds { display:flex; flex-wrap:wrap; gap:5px; }
.cf-hd-kind { border:1px solid var(--cf-line2); background:#fff; border-radius:6px;
              padding:1.5px 9px; font-size:11.5px; color:var(--cf-ink2); cursor:pointer; }
.cf-hd-kind.on { border-color:var(--cf-hl); background:var(--cf-hl-bg); color:#854D0E;
                 font-weight:600; }
.cf-hd-foot { display:flex; align-items:center; gap:12px; }
.cf-hd-foot .grow { flex:1; }
@media (max-width:820px){ .hlt-top { flex-direction:column; } .hlt-prev { width:100%; } }

/* ═══ 复刻反馈的标记（2026-08-22，PRD §5.19.27）═══
   🔴 **只用下划线的形状与颜色，不碰底色**：这一页的底色已经被黄（高光词）与红（卡审词）
      占满了，而红是所有标记里唯一一个"不改就发不出去"的 —— 再拿红去表示"我觉得写得不好"，
      两件严重程度差着量级的事就长成了一样。
   🔴 「不好」用 `--cf-warn`：它的既有定义正好是这个语义——**不是失败，但你得去做点什么**。
   ⚠️ 反馈与底色天生要叠在同一批字上（一个锁住的高光词完全可以同时被标"好"），
      所以 `cfReproHtml` 是按字符累加类名而不是字符串替换，见那里的注释。 */
.cf-fb-g { border-bottom:2px solid var(--cf-ok); padding-bottom:1px; }
.cf-fb-b { border-bottom:2px dotted var(--cf-warn); padding-bottom:1px; }
/* 反馈栏：正文下面一份清单。**失效的灰掉但留着** —— 删了就没人知道这里曾被标过不好 */
.cf-fb { margin-top:11px; border-top:1px dashed var(--cf-line2); padding-top:9px; }
.cf-fb-h { display:flex; align-items:center; gap:9px; font-size:12px; color:var(--cf-ink3); }
.cf-fb-h b { color:var(--cf-ink1); }
.cf-fb-h .r { margin-left:auto; font-size:11.5px; color:var(--cf-ink4); }
.cf-fb-r { display:flex; align-items:center; gap:9px; padding:5px 2px; font-size:12.5px;
           border-bottom:1px solid var(--cf-surface); }
.cf-fb-r:last-child { border-bottom:0; }
.cf-fb-r .ic { flex:none; font-size:12px; width:16px; text-align:center; }
.cf-fb-r.g .ic { color:var(--cf-ok); }
.cf-fb-r.b .ic { color:var(--cf-warn); }
.cf-fb-r.d { color:var(--cf-ink4); }
.cf-fb-r .q { color:var(--cf-ink1); background:var(--cf-surface); border-radius:4px;
              padding:0 6px; max-width:290px; overflow:hidden; text-overflow:ellipsis;
              white-space:nowrap; }
.cf-fb-r.d .q { color:var(--cf-ink4); text-decoration:line-through; }
.cf-fb-r .why { color:var(--cf-ink4); font-size:11.5px; }
.cf-fb-r .x { margin-left:auto; color:var(--cf-ink4); cursor:pointer; font-size:12px; }
.cf-fb-r .x:hover { color:var(--cf-bad); }
/* ⚠️ `.cf-fb-rules`（「这一版带了哪几条写法规则」那一块）已于 2026-08-26 随写法规则
   那条链一起删除 —— 模板里没人用了，留着就是死 CSS（铁律 10⑥）。 */
/* ⚠️ `.cf-rp-selbar` / `.cf-rp-selw`（那条行内动作条）已于 2026-08-18 第三轮删除 ——
   动作收进 `.cf-selbar` 浮框之后没有任何模板引用了，而**死 CSS 是撞名的温床**
   （铁律 10⑥；`verify_cf §47` 对任何死 `.cf-*` 类判红）。 */
/* 已勾中＝复刻时原样保留（2026-08-18）。与"只是标黄"必须一眼分得开：
   实心边框 + 更深的底。⚠️ 不用颜色单独表意（色弱看不出），同时给了边框与底色两重差别。 */
.cf-kw-on { background:#ffd666; box-shadow:inset 0 0 0 2px #d46b08; }
.cf-kw-on::after { content:'锁'; font-size:9px; vertical-align:super; margin-left:1px;
                   color:#873800; font-weight:700; }
/* 剪映检索词：拆完得知道去哪儿找同款素材——音效在成片里已和人声混轨，原始素材只在作者的工程里 */
.cf-jy { font-size:11px; color:#a2621a; background:#fdf3e3; border:1px solid #f0dcc0;
         border-radius:5px; padding:2px 7px; margin-top:4px; display:inline-block; }
.cf-jy b { color:#8a4f0d; font-weight:600; }
.cf-link { color:var(--cf-primary,#C2410C); cursor:pointer; }
.cf-plat { display:inline-block; padding:1px 8px; border-radius:5px; font-size:11px;
           text-decoration:none; border:1px solid; white-space:nowrap; }
.cf-plat.dy { background:#fdf0f3; border-color:#eab8c6; color:#b0264a; }
.cf-plat.tk { background:#eef0f4; border-color:#b9bfc9; color:#2b3038; }
.cf-plat.other { background:var(--cf-surface); border-color:var(--cf-line); color:var(--cf-ink2); }
.cf-link:hover { text-decoration:underline; }
/* 空态与 .cf-val 同款内边距/行高：否则这几行比别的矮一截，左边标签列就参差不齐（用户实报） */
/* 五轨显隐开关（2026-08-10 需求③） */
/* 商品资料：左填资料 / 右页面预览（2026-08-11 重排）。
   预览列独立滚动 —— 填资料时图要一直在视野里，而不是滚到最底下才看得到。 */
.cf-p2 { display:grid; grid-template-columns:1fr 400px; gap:0 18px; align-items:start; }
.cf-p2-form { min-width:0; }
.cf-p2-cols { display:grid; grid-template-columns:1fr 1fr; gap:0 18px; align-items:start; }
.cf-p2-prev { border:1px solid var(--cf-line); border-radius:10px; background:var(--cf-ground);
              overflow:hidden; position:sticky; top:0; }
.cf-prev-h { display:flex; align-items:baseline; gap:8px; padding:9px 12px; font-weight:600;
             font-size:13px; border-bottom:1px solid var(--cf-line); background:var(--cf-surface); }
.cf-prev-h .muted { font-weight:400; font-size:11px; }
.cf-prev-body { max-height:calc(100vh - 240px); overflow-y:auto; padding:10px; }
.cf-prev-tag { font-size:11px; color:var(--cf-ink3); margin:6px 0 5px; }
.cf-prev-img { width:100%; display:block; border-radius:7px; margin-bottom:8px; cursor:zoom-in;
               border:1px solid var(--cf-line); }
@media (max-width:1400px) { .cf-p2 { grid-template-columns:1fr; }
                            .cf-p2-prev { position:static; } }
@media (max-width:1100px) { .cf-p2-cols { grid-template-columns:1fr; } }
/* 放大看图：长图动辄一万多像素高，弹窗里也要能滚 */
.cf-zoom-body { max-height:78vh; overflow-y:auto; }
.cf-zoom-body img { width:100%; display:block; }
/* （旧的三列样式保留：cf-p3-col 仍在用） */
.cf-p3 { display:grid; grid-template-columns:1fr 1fr 1fr; gap:0 18px; align-items:start; }
.cf-p3-col { min-width:0; }
.cf-p3-h { display:flex; align-items:center; gap:8px; font-weight:600; font-size:13px;
           margin-bottom:8px; color:var(--cf-ink); }
/* 抓回来的图文先摆出来给人看（2026-08-18）：覆盖 / 追加 / 扔掉三选一，不替人决定。
   正文限高 + 自己滚：抓回来常有几千字，不限高会把下面的输入框推到屏幕外。 */
/* ═══ 通篇对照（2026-08-18，用户需求⑨）═══
   左原片右复刻，连续排下来。与分段视图共用数据与渲染函数，只是版式不同。
   ⚠️ 两栏用 grid 而不是 flex：flex 下两边内容长短不一时会各自撑高、行与行对不齐，
      而"对照"这件事的全部意义就是同一段的左右在同一行上。 */
.cf-full { border:1px solid var(--cf-line); border-radius:var(--r-lg); background:#fff;
           overflow:hidden; }
/* 🔴 三列：序号 · 左 · 右（2026-08-19）。序号**独立成列**而不是塞在左栏正文上方 ——
   塞在上方时左栏比右栏多出一行的高度，同一段的左右第一行就错开，
   而"对照"这件事的全部意义就是两边在同一行上（用户："否则两边对不齐"）。 */
.cf-full-h { display:grid; grid-template-columns:36px 1fr 1fr; gap:0;
             background:var(--cf-ground); border-bottom:1px solid var(--cf-line); }
.cf-full-h > span { padding:9px 14px; font-size:12px; font-weight:600; color:var(--cf-ink3);
                    display:flex; align-items:baseline; gap:8px; }
.cf-full-h > span + span { border-left:1px solid var(--cf-line); }
.cf-full-hn { padding:9px 0 !important; }
.cf-full-h i { font-size:11px; font-style:normal; }
.cf-full-row { display:grid; grid-template-columns:36px 1fr 1fr; gap:0;
               border-bottom:1px solid #F4F3F2; }
.cf-full-row:last-child { border-bottom:none; }
.cf-full-l, .cf-full-r { padding:12px 14px; min-width:0; }
.cf-full-r { border-left:1px solid #F4F3F2; background:#FFFDFB; }
/* 序号那一格：与两栏正文**同一条基线**（padding-top 与它们一致） */
.cf-full-no { padding:12px 0 0; font-size:11px; color:var(--cf-ink4); font-weight:700;
              text-align:center; line-height:1.85; }
/* 字数：右栏顺带给出源字数 —— 复刻/裂变的长度约束贴着原文来，
   "改写后长了一倍"是这一屏最该一眼看出来的事。 */
.cf-full-n { margin-top:6px; font-size:11px; color:var(--cf-ink4); }
.cf-full-n i { font-style:normal; margin-left:4px; }
.cf-full-body { font-size:14.5px; line-height:1.85; color:var(--cf-ink); text-wrap:pretty; }
.cf-full-none { font-size:12.5px; color:var(--cf-ink4); padding-top:18px; }
.cf-gotbox { border:1px solid #ffd8bf; background:#fff7f0; border-radius:9px;
             padding:10px 12px; margin-bottom:9px; }
.cf-gotbox-h { display:flex; align-items:center; gap:8px; flex-wrap:wrap;
               font-size:12px; margin-bottom:7px; }
.cf-gotbox-b { max-height:180px; overflow:auto; font-size:12.5px; line-height:1.7;
               color:var(--cf-ink2); white-space:pre-wrap; background:#fff;
               border-radius:6px; padding:8px 10px; }
@media (max-width:1280px) { .cf-p3 { grid-template-columns:1fr 1fr; } }
/* ===== 人群画像与人设（2026-08-11） ===== */
.cf-aud-g { border:1px solid var(--cf-line); border-radius:10px; padding:10px 12px; margin-bottom:12px;
            background:var(--cf-ground); }
.cf-aud-h { display:flex; align-items:center; gap:8px; flex-wrap:wrap; margin-bottom:8px; font-size:13.5px; }
.cf-aud-cols { display:grid; grid-template-columns:1fr 1fr; gap:0 22px; }
.cf-aud-t { font-size:11.5px; color:var(--cf-ink3); margin-bottom:5px; }
.cf-aud-row { display:flex; align-items:center; gap:8px; font-size:12.5px; line-height:2; }
.cf-aud-tag { flex:0 0 130px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.cf-aud-bar { flex:1; height:8px; background:var(--cf-surface); border-radius:99px; overflow:hidden; }
.cf-aud-bar i { display:block; height:100%; background:var(--cf-accent); opacity:.72; }
.cf-aud-num { flex:0 0 62px; text-align:right; font-variant-numeric:tabular-nums; }
.cf-persona { border:1px solid var(--cf-line); border-radius:10px; padding:11px 13px; margin-bottom:12px;
              background:var(--cf-ground); }
.cf-persona.off { opacity:.55; }
.cf-persona-h { display:flex; align-items:center; gap:8px; margin-bottom:7px; }
.cf-persona-b > div { display:grid; grid-template-columns:78px 1fr; gap:10px; font-size:13px;
                      line-height:1.8; align-items:start; }
.cf-persona-b label { color:var(--cf-ink3); font-size:12px; }
/* 🔴 与 `.cf-film-ok` 同一个病的第二例（2026-08-18 一并修，两处都已上线）：
      `.cf-persona-ev` 也是跨两行写的，而「人设衍生弹窗」那一整段被插进了两行**中间**
      ⇒ `.cf-dv-*` 全家（草稿卡/卡名输入框/勾选态）被当成它的垃圾声明整段丢弃，
      人设衍生弹窗因此没有任何样式。同样是 DOM 完整、零报错、只有人眼看得出。 */
.cf-persona-ev { margin-top:7px; padding-top:7px; border-top:1px dashed var(--cf-line);
                 font-size:12px; color:var(--cf-ink2); }
.cf-persona-ev b { margin-right:6px; color:var(--cf-ink3); font-weight:600; }
/* ═══ 超高折叠（2026-08-19，用户需求③「超过一定版幅有折叠和展开按钮」）═══
   组件 `clamp-box`，四处摆人设五段文案的地方共用（见组件上方注释）。
   🔴 遮罩用 `mask-image` 而不是盖一层白色渐变 div：这四处的底色各不相同
      （人设卡白 / 换人设面板选中态是 `--cf-soft3` / 衍生草稿卡 `#FFFDFB`），
      盖白块会在有色底上留一道明显的白条。mask 只吃透明度，底色是什么都对。
   ⚠️ **写成一条一行的完整规则**：本文件大量规则跨两行写，而新 CSS 习惯性
      "插在相关注释后面"就会插进两行中间 ⇒ 浏览器静默丢弃整段
      （已有两条这样上过线，verify_inline_template §11 现在钉着这件事）。 */
.cf-clamp { position:relative; }
.cf-clamp-b.fold { overflow:hidden; -webkit-mask-image:linear-gradient(#000 62%, transparent); mask-image:linear-gradient(#000 62%, transparent); }
.cf-clamp-t { display:inline-block; margin-top:4px; font-size:12px; color:var(--cf-accent, #C2410C); cursor:pointer; user-select:none; }
.cf-clamp-t:hover { text-decoration:underline; }
/* 卡审词库 · 变更记录（2026-08-19，需求①）。一行一条，改前改后并排。
   ⚠️ 写成一条一行的完整规则（同 clamp 那组的理由）：本文件大量规则跨两行写，
      新 CSS 插进两行中间会让浏览器静默丢弃整段。 */
.cf-bl-row { border:1px solid var(--cf-line); border-radius:9px; padding:9px 11px; margin-bottom:9px; background:#fff; }
.cf-bl-h { display:flex; align-items:baseline; gap:8px; font-size:12.5px; margin-bottom:5px; }
.cf-bl-h b { color:var(--cf-accent); }
.cf-bl-t { color:var(--cf-ink3); font-size:12px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; max-width:210px; }
.cf-bl-h .muted { font-size:11.5px; }
.cf-bl-d { display:grid; grid-template-columns:82px 1fr; gap:8px; font-size:12.5px; line-height:1.7; }
.cf-bl-d label { color:var(--cf-ink4); font-size:11.5px; }
.cf-bl-d i { font-style:normal; color:var(--cf-ink4); text-decoration:line-through; }
.cf-bl-1 { display:block; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.cf-ban-cat { display:inline-block; margin:0 4px 2px 0; padding:0 6px; border-radius:4px; font-size:11px; background:var(--cf-soft, #FFF7ED); color:var(--cf-accent, #C2410C); border:1px solid var(--cf-softline, #FED7AA); }
/* 人设衍生弹窗（2026-08-18）：草稿卡，勾中的才存 */
.cf-dv-src { display:flex; align-items:baseline; gap:8px; font-size:12.5px;
             background:var(--cf-ground); border-radius:8px; padding:8px 11px; }
.cf-dv-src b { font-size:12px; color:var(--cf-ink3); font-weight:600; }
.cf-dv-card { border:1px solid var(--cf-line); border-radius:9px; padding:10px 12px;
              margin-bottom:9px; background:#fff; }
.cf-dv-card.on { border-color:var(--cf-accent-line); background:#FFFDFB; }
.cf-dv-h { display:flex; align-items:center; gap:8px; margin-bottom:7px; }
.cf-dv-name { flex:1; min-width:0; border:1px solid transparent; border-radius:6px;
              padding:3px 7px; font-size:13.5px; font-weight:600; color:var(--cf-ink);
              background:transparent; outline:none; font-family:inherit; }
.cf-dv-name:hover { border-color:var(--cf-line); }
.cf-dv-name:focus { border-color:var(--cf-accent-line); background:#fff; }
/* ===== 台词场景复刻（2026-08-10 需求④）：就地在台词栏下面，不跳去工作台 ===== */
.cf-set-block { padding:10px 0 16px; border-bottom:1px solid var(--cf-line); }
.cf-set-block > label { display:block; font-size:13px; font-weight:600; margin-bottom:6px; }
.cf-prompt textarea { font-family:ui-monospace,SFMono-Regular,Menlo,monospace; font-size:12.3px;
                      line-height:1.65; background:#fffdf9; }
.cf-flow { width:100%; border-collapse:collapse; font-size:12.5px; }
.cf-flow th { text-align:left; color:var(--cf-ink3); font-weight:600; font-size:11.5px;
              padding:5px 8px; border-bottom:1px solid var(--cf-line); }
.cf-flow td { padding:6px 8px; border-bottom:1px solid var(--cf-line); vertical-align:top; }
.cf-flow code { background:var(--cf-surface); padding:1px 6px; border-radius:4px; font-size:11.5px; }
.cf-flow tr.dim td { color:var(--cf-ink3); }
.cf-set-row { display:grid; grid-template-columns:400px 1fr; gap:14px; align-items:center;
              justify-items:start;   /* 不加这条 a-switch 会被拉满整行，点起来像个进度条 */ padding:7px 0;
              border-bottom:1px solid var(--cf-line); font-size:13px; }


.cf-drop { border:2px dashed var(--cf-line); border-radius:12px; padding:26px 18px; text-align:center;
           cursor:pointer; background:var(--cf-ground); transition:border-color .15s, background .15s; }
.cf-drop:hover, .cf-drop.on { border-color:var(--cf-accent); background:var(--cf-soft); }
.cf-drop.has { padding:14px; text-align:left; border-style:solid; }
.cf-drop-file { display:flex; align-items:center; gap:11px; }
.cf-drop-name { font-size:13.5px; font-weight:600; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.cf-drop-err { color:#b3261e; font-size:12.5px; margin-top:8px; }
.wfc-archived td { background:#f7f8fa !important; color:#86909c; }
.cf-drop-tip { font-size:12px; color:var(--cf-ink3); line-height:1.7; background:var(--cf-surface);
               border-radius:8px; padding:9px 12px; }

/* ============ 拆解配置（2026-08-24，PRD §5.19.30）============ */
/* 挂不到组上的类：这条要显眼 —— 它意味着那几个类在提示词里缺组名，
   而页面上它们和别的类长得一模一样。 */
.cf-zc-warn { margin:0 0 10px; padding:9px 12px; border-radius:8px; font-size:12px;
              line-height:1.7; background:var(--cf-note-bg); color:var(--cf-note-t); }
/* 编辑弹窗限高。段落类型有 8 个字段，不限高的话「确定」会掉到视口外面 ——
   1440x900 实测它落在 y=1021，人要滚整个页面才点得到，而弹窗自己看不出有下文。
   ⚠️ `cf-modal-clamp` 管的是**标题单行省略**，不是高度，别再拿它当限高用。 */
.cf-zc-modal .arco-modal-body { max-height:calc(100vh - 230px); overflow-y:auto; }

/* ═══ 01 这条片在讲什么（2026-08-24，PRD §5.19.30）═══
   逐值对着 design/Main.dc.html —— 那份稿是验收标准，调数值前先看它。 */
/* ⚠️ **不要 `overflow:hidden`**：它会把内容截掉半行（首验实测卖点第二行只露上半截），
   而这一块在定高分栏里本来就吃紧。圆角靠卡头自己那两个角实现。 */
.cf-doss { background:#fff; border:1px solid var(--cf-line); border-radius:var(--r-lg);
           margin:0 0 12px; flex:none; }

/* —— 「讲什么」/「档案」搬进右侧抽屉之后的外壳（2026-08-25）——
   抽屉本身已经是一张卡（有底、有边、有标题栏），里面那两块**再套一层卡**就是
   双层边框 + 双层圆角。故在抽屉里把它们的边框/圆角/外边距一起去掉，只留内容。
   ⚠️ 用 `.cf-doss-dv` / `.cf-archbox-dv` 两个附加类**限定在抽屉里**，
      不要直接改 `.cf-doss` 本体 —— 那个类将来若在别处内联使用，边框还是要的。 */
.cf-dv-body { flex:1; min-height:0; overflow-y:auto; padding:14px 20px 20px; }
.cf-dv-body .cf-doss-dv,
.cf-dv-body .cf-archbox-dv { border:none; border-radius:0; margin:0; background:transparent; }
/* 卡头在抽屉里是多余的：抽屉标题栏已经写着"这条片在讲什么"，
   而它的收起入口（▲）在抽屉里点了会把抽屉关掉 —— 一个东西两个关法。
   🔴 只隐藏**这一处**的卡头，`.cf-dos-head` 本身不动。 */
.cf-dv-body .cf-doss-dv > .cf-dos-head { display:none; }
.cf-dv-body .cf-doss-dv > .cf-dos-body { border-top:none; }
.cf-dos-head { display:flex; align-items:center; gap:10px; padding:11px 18px; flex-wrap:wrap;
               background:var(--cf-row); border-radius:var(--r-lg) var(--r-lg) 0 0; }
.cf-doss > .cf-dos-body { border-top:1px solid var(--cf-line); }
.cf-dos-x { font-size:11.5px; color:var(--cf-ink4); flex:none; }
.cf-dos-head b { font-size:14px; font-weight:600; color:var(--cf-ink); }
.cf-dos-no { font-size:10.5px; color:var(--cf-ink4); letter-spacing:.04em; }
.cf-dos-badge { font-size:11.5px; padding:2px 9px; border-radius:var(--r-sm); flex:none;
                cursor:default; }
.cf-dos-badge.bad { background:var(--cf-note-bg); border:1px solid #FDE68A; color:var(--cf-note-t); }
.cf-dos-badge.ok { background:#F0FDF4; border:1px solid #BBF7D0; color:#15803D; }
.cf-dos-body { padding:16px 18px; }
/* 三栏 → 窄屏塌成一栏。`auto-fit + minmax` 而不是写死 3 列：
   1280 视口下三栏各 330px 够用，再窄就该塌，写死 3 列会把「处境」那种长句压成一列字。 */
/* 🔴 340 是**量出来的**：卡内可用宽实测 1118px（1440 视口）。
   首版给 260 ⇒ 1118/260=4.3 ⇒ 排成 4 列，而稿上是 3 列 —— 三栏各自的标题
   （商品/目标用户/使用场景）会挤在一起读不出分组。
   340 ⇒ 1440 下 3 列、1280 下 2 列、再窄塌 1 列。 */
.cf-dos-grid { display:grid; grid-template-columns:repeat(auto-fit, minmax(340px, 1fr));
               gap:22px; }
/* 三栏徽标：2026-08-25 起**三个同色**（浅灰底深字）。
   原来是绿/蓝/棕三个色 class —— 分组靠的是文字（商品/目标用户/使用场景），
   颜色不是必需的区分手段，而它是整页「颜色太多」的一部分。 */
.cf-dos-grp { display:inline-block; margin-bottom:9px; font-size:11px; font-weight:600;
              color:var(--cf-ink2); background:var(--cf-surface); border-radius:var(--r-sm);
              padding:2px 9px; }
/* 标签列 56px 是稿上的值：四个中文字（「什么时候」）刚好放得下。 */
.cf-dos-row { display:grid; grid-template-columns:56px 1fr; gap:9px; padding:3px 0;
              align-items:start; font-size:12.5px; }
.cf-dos-lab { color:var(--cf-ink4); font-size:11px; }
.cf-dos-row .cf-dos-lab { padding-top:3px; }
.cf-dos-val { color:var(--cf-ink); line-height:1.5; }
/* 🔴 「台词里没有」是**要说出来的信息**，不是空白：留空与"模型没提取到"在页面上
   长得一样，而前者是这条片子真的没讲、后者是拆解漏了。稿上就是这么标的。 */
.cf-dos-none { color:var(--cf-ink4); font-size:12px; }
/* ═══ 结论区：三等分，与上面三栏之间一条分隔线（2026-08-25）═══
   为什么不再通栏：使用场景那一列排完就到底了而左中两列还在往下长，右下角空出 359×85px；
   卖点那块 64px 高只装 1 条。三处都量过。
   三格样式与三栏的字段行**同款** —— 标签 + 纯文本值，无底色无边框。 */
.cf-dos-concl { display:grid; grid-template-columns:repeat(auto-fit, minmax(230px, 1fr));
                gap:22px; margin-top:15px; padding-top:15px; border-top:1px solid var(--cf-line); }
.cf-dos-concl .cf-dos-val { font-size:12.5px; margin-top:6px; }
/* 痛点与解决的对照用**标签颜色**表达，不用整块底色（缩到 1/3 宽后色块显得碎）。 */
.cf-dos-lab.pain { color:var(--cf-accent); }
.cf-dos-lab.fix { color:var(--cf-ok); }
/* 卖点只显示第 1 条，其余折进「+N」。 */
.cf-dos-sell { display:flex; flex-wrap:wrap; align-items:baseline; gap:4px 7px; margin-top:6px; }
.cf-dos-sell > div { display:flex; gap:7px; align-items:baseline; font-size:12.5px;
                     color:var(--cf-ink2); min-width:0; }
.cf-dos-sell i { color:var(--cf-accent); font-weight:700; font-style:normal; flex:none; }
.cf-dos-more { font-size:11.5px; color:var(--cf-accent); cursor:pointer; flex:none; }
.cf-dos-more:hover { color:var(--cf-accent-hover); }
/* 用户层级：无边框下拉，视觉重量对齐同栏的纯文本值。 */
.cf-dos-lv { display:inline-flex; align-items:center; min-width:0; }
.cf-scope .cf-dos-lv .arco-select-view { min-height:0; height:22px; line-height:22px;
                                         font-size:12.5px; padding:0; background:transparent; }
/* 层级的台词依据：一行灰字，不再是带虚线框的块。 */
.cf-dos-why { font-size:12px; color:var(--cf-ink3); line-height:1.6; }
.cf-dos-why.none { color:var(--cf-ink4); }

/* ═══ 02 骨架（独立一块）═══ */
/* 骨架：2026-08-25 起并进 `.cf-hd1`，不再是独立一块卡（`.cf-skb` 容器样式已随之删掉）。
   🔴 三段**同色**：原来按组序号从六色调色板取（`cfSkbColor`），五个组就是五种颜色 ——
      那是整页「颜色太多」最大的来源。顺序由箭头表达，不需要颜色再说一遍。 */
.cf-hd-skb { display:inline-flex; align-items:center; gap:6px; flex:none; }
.cf-skb-i { font-size:12px; padding:2px 9px; border-radius:var(--r-sm); cursor:pointer;
            color:var(--cf-accent); background:var(--cf-soft); white-space:nowrap; }
.cf-skb-i:hover { background:var(--cf-softline); }
.cf-skb-ar { color:var(--cf-ink4); font-size:11px; }
/* 两块展开区的入口（讲什么 / 档案）。文案短是刻意的：这一行元素多，
   「这条片在讲什么 展开 ▼」那种长度会把标题挤没。 */
.cf-hd-open { font-size:11.5px; color:var(--cf-accent); cursor:pointer; flex:none; white-space:nowrap; }
.cf-hd-open:hover { color:var(--cf-accent-hover); }
/* 原链接收成图标（省 33px）。语义不变，全文进 title。 */
.cf-hd-srcico { display:inline-flex; align-items:center; flex:none; }

/* 段落手法：一排芯片 + 加手法（设计稿）。 */
.cf-skl { display:flex; flex-wrap:wrap; align-items:center; gap:6px; margin:0 0 7px; }
.cf-skl-i { font-size:11.5px; color:var(--cf-ink1); background:var(--cf-surface);
            border:1px solid var(--cf-line); border-radius:var(--r-sm); padding:2px 5px 2px 7px; }
.cf-skl-i a { color:var(--cf-ink4); margin-left:3px; cursor:pointer; font-size:12px; }
.cf-skl-i a:hover { color:var(--cf-accent); }
/* 段头的组徽标 + 类型下拉（2026-08-24 按设计稿）。 */
.cf-sgc-grp { font-size:11.5px; color:var(--cf-accent); background:var(--cf-soft);
              border-radius:var(--r-sm); padding:2px 9px; flex:none; }
.cf-sgc-zon { border:1px solid var(--cf-line2); border-radius:var(--r-sm); background:#fff;
              flex:none; }
/* min-width 120 → 96（2026-08-25）：手法进段头后要给它腾地方。
   最长的类名「对话情景剧」5 个字约 75px，加箭头与内边距 96 够用。 */
.cf-scope .cf-sgc-zon .arco-select-view { min-height:0; height:24px; line-height:24px;
                                          min-width:96px; font-size:12px; }

/* 旧框架拆的：灰底，说清为什么空 + 出路。 */
.cf-doss-old { background:var(--cf-surface); border-radius:8px; padding:9px 13px;
               margin:0 0 10px; font-size:12px; color:var(--cf-ink2); line-height:1.8; }

/* ============ 统一上传组件 img-drop（2026-08-08）============
   收敛前：10 处上传各写各的——只有 2 处能粘贴、3 处能拖；限额三套
   （20张/30MB · 20张5张一批 · 模板与装箱资料**完全没有前端校验**，超限只拿得到
   nginx 413 的「上传失败」）；错误两种呈现（内容工厂内联红字 / 图工厂 toast）。
   更要命的是粘贴/拖拽的收件人判据是**页面名 switch**（if2Paste 里硬写 if2_job/if2_matset），
   于是"新增一个上传位"必须有人记得回去改那两个函数——记忆里「给共享的东西加分支必漏一处」
   那个形状，10 个位只有 2 个被记得。改成组件注册表后，挂上组件即自动拥有三种方式。

   颜色刻意走 `var(--cf-*, 回退值)`：在 .cf-scope 内自动取内容工厂那套暖色，
   在别处回退到图工厂的蓝——一份 CSS 两种皮肤，不为换肤再复制一遍。 */
.imgdrop { position:relative; }
/* page 变体：页面上零占位（批量任务列表页要"能拖能粘但看不见框"，用户 2026-08-08 拍板）。
   刻意不用 display:none —— 整页拖拽的遮罩是这个组件渲染的，父节点隐掉遮罩就出不来了。 */
.imgdrop-bare { width:0; height:0; }
.imgdrop-zone { border:2px dashed var(--cf-line, #d6d3d1); border-radius:12px; padding:26px 18px;
                text-align:center; background:var(--cf-ground, #fafaf9);
                transition:border-color .15s, background .15s; }
.imgdrop-can .imgdrop-zone { cursor:pointer; }
.imgdrop-can:hover > .imgdrop-zone, .imgdrop.on > .imgdrop-zone {
                border-color:var(--cf-accent, #1e5f9e); background:var(--cf-soft, #f0f6fc); }
.imgdrop-zone.has { padding:14px; text-align:left; border-style:solid; }
.imgdrop-ico { font-size:26px; color:var(--cf-accent, #1e5f9e); margin-bottom:8px; }
.imgdrop-t { font-size:14px; margin-bottom:5px; color:var(--cf-ink, #1c1917); }
.imgdrop-t span { color:var(--cf-accent, #1e5f9e); font-weight:600; }
.imgdrop-s { font-size:12px; color:var(--cf-ink3, #a8a29e); }
/* inline 变体：包住调用方原有的那块 markup（缩略图+按钮 / 网格 / 一个按钮），
   外观零改动，只把整块变成拖放与粘贴的目标。故这里**不设 padding/border**——
   加了就会把装箱资料编辑弹窗那两列并排的表单项撑歪。 */
.imgdrop-inline { border-radius:8px; }
.imgdrop.on > .imgdrop-inline { outline:2px dashed var(--cf-accent, #1e5f9e); outline-offset:3px;
                background:var(--cf-soft, #f0f6fc); }
/* 拖拽悬停遮罩：pointer-events:none，否则鼠标"进入遮罩"会立刻触发 dragleave 导致闪烁 */
.imgdrop-over { position:absolute; inset:0; z-index:5; pointer-events:none; border-radius:10px;
                display:flex; align-items:center; justify-content:center; font-size:13px; font-weight:600;
                color:var(--cf-accent, #1e5f9e); background:var(--cf-soft, rgba(30,95,158,.07)); }
/* 「现在按 Ctrl+V 会贴到这里」——最近悬停过的那个目标。
   不给标记的话「最近悬停」这个判据对用户完全是隐形的，贴错了也不知道为什么。 */
.imgdrop.aim::after { content:'⌘V'; position:absolute; top:-8px; right:-6px; z-index:6;
                font-size:10px; font-weight:700; letter-spacing:.5px; line-height:1;
                padding:3px 5px; border-radius:5px; pointer-events:none;
                color:#fff; background:var(--cf-accent, #1e5f9e); opacity:.82; }
/* 校验错内联（用户 2026-08-08 拍板）：toast 3 秒就没了，拖 20 张有 2 张超限时
   根本来不及看清是哪两张。zone 变体占位排在下面；inline 变体走**不占位**的浮层，
   否则同样会把那两列表单撑歪。 */
.imgdrop-err { color:#b3261e; font-size:12.5px; margin-top:8px; line-height:1.6; }
.imgdrop-err-float { position:absolute; left:0; top:100%; z-index:7; margin-top:4px; width:max-content;
                max-width:320px; background:#fff5f5; border:1px solid #f3c9c5;
                border-radius:6px; padding:5px 8px; box-shadow:0 4px 14px rgba(0,0,0,.08); }
.imgdrop-note { color:#8a5a12; }
.imgdrop-note.imgdrop-err-float { background:#fdf7ec; border-color:#e6cfa8; }
/* ===== 复刻线（Phase 2） ===== */
.cf-blk { border:1px solid var(--cf-line); border-radius:10px; padding:12px; background:var(--cf-ground); }
/* 🔴 2026-08-20 审计：本条原先也叫 `.cf-ban`，与上面那条**行内命中高亮**撞名。
   同一个 <style> 里同名类**后写的赢** ⇒ 词库这条芯片样式把行内高亮整段盖掉：
   命中的卡审词在稿子正文里被套上 `padding:1px 7px; font-size:11.5px`，
   看着像一颗芯片嵌在句子中间。DOM 完整、console 零错误，只有人眼看得出（铁律 10⑥）。
   改名 `.cf-ban-pat` 与紧邻的 `.cf-ban-cat`（类目芯片）成一族。 */
.cf-ban-pat { font-size:11.5px; background:#fdeceb; color:#b3261e; border-radius:4px; padding:1px 7px; }
.cf-scan { font-size:12.5px; border-radius:8px; padding:7px 11px; margin-top:8px; }
.cf-scan.ok { background:#e7f3ec; color:#15803D; }
.cf-scan.bad { background:#fdeceb; color:#b3261e; }
.cf-hit { font-weight:700; text-decoration:underline; margin:0 5px; cursor:help; }
.cf-review { background:var(--cf-surface); border-radius:8px; padding:8px 11px; margin-top:8px; font-size:12.5px; line-height:1.7; }
.cf-review.ok { color:#15803D; }
.cf-tlist > div { padding:5px 8px; border-radius:6px; cursor:pointer; font-size:13.5px; }
.cf-tlist > div:hover { background:var(--cf-surface); }
.cf-tlist > div.bad { background:#fdeceb; }
.cf-tkind { font-size:11px; color:var(--cf-ink3); margin-right:8px; }

/* ═══ 浏览器插件：设备授权页（xtg-）与插件中心（xtc-），共用块 xte- ═══════════
   2026-09-05，任务文档 feat-ext-center-and-selfupdate.md 的 §5-C / §5-E。
   三个前缀起名前都 grep 过全站零命中（铁律 10⑥：同一个 style 里同名类后写的赢，
   撞了之后页面坏而零报错；同族的 ⑥-1b 反过来管"用了 class 却没有任何规则"）。 */
.xte-warn { background:#fdf7ec; border:1px solid #e6cfa8; color:#8a5a12; font-size:12.5px; line-height:1.75; padding:10px 12px; }
.xte-bad  { background:#fdf1f0; border:1px solid #e0aca7; color:#a92a1f; font-size:12.5px; line-height:1.75; padding:10px 12px; }
.xte-ok   { background:#eaf5ec; border:1px solid #b7ddc0; color:#1f7a37; font-size:12.5px; line-height:1.75; padding:10px 12px; }
/* 授权页是**整屏接管**：它不是主布局里的一页（扩展直接开一个地址进来），
   所以 z-index 要压过 Arco 弹窗(1001)与 .if2-mask(1200)。 */
.xtg-wrap { position:fixed; inset:0; z-index:3000; background:#f5f4f2; overflow:auto; display:flex; align-items:flex-start; justify-content:center; padding:46px 20px; }
.xtg-card { width:560px; max-width:100%; background:#fff; border:1px solid #d6d3d1; padding:24px 26px 20px; }
/* 短码是这条防线的**人做的那一半**（服务端那半是 180 秒 TTL + 失败计数 + 一次性）：
   它要能被一眼逐字符核对，所以等宽、大号、拉开字距、点一下整串选中。 */
.xtg-code { font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace; font-size:34px; font-weight:700; letter-spacing:7px; color:#1c1917; background:#faf9f7; border:1px dashed #a8a29e; padding:14px 10px 14px 17px; text-align:center; user-select:all; }
.xtg-r { display:flex; gap:10px; font-size:12.5px; color:#44403c; padding:6px 0; border-bottom:1px solid #f5f4f2; align-items:baseline; }
.xtg-k { flex:none; width:84px; color:#a8a29e; }
/* 插件中心：装机清单是**卡内的一张小表**（一个插件一张卡，同「插件下载」页的语言）。
   列宽写死是刻意的 —— 末列 1fr 让富余落在**右边距**上，不在中间开一个断层（铁律 10⑤ grid 版）。 */
.xtc-note { flex:none; background:#faf9f7; border:1px solid #e7e5e4; padding:10px 12px; font-size:12px; color:#57534e; line-height:1.85; margin-bottom:12px; }
/* 🔴 列宽 2026-09-05 第四轮重排过一次（第一列多了「名字」输入框、版本列改成
   `v旧 → v新`）：**下限合计只减不增** —— 改前 1030px（含 8 道 10px 的 gap），
   改后 1026px。装机 tab 的外壳是 `overflow:auto`，超了会横滚而不是把列切掉，
   但横滚一出现，最右那列「用的令牌」就得拖着才看得见。 */
.xtc-grid { display:grid; grid-template-columns:150px 150px 76px 110px 104px 130px 56px 74px minmax(96px,1fr); gap:0 10px; align-items:center; padding:7px 10px; font-size:12px; color:#44403c; font-variant-numeric:tabular-nums; }
.xtc-h { background:#f7f8fa; color:#78716c; font-weight:600; border-bottom:1px solid #e7e5e4; }
.xtc-row { border-bottom:1px solid #f5f4f2; }
.xtc-row:hover { background:#faf9f7; }
.xtc-sum { display:flex; gap:14px; align-items:center; font-size:12px; color:#57534e; flex-wrap:wrap; }

.rdy-page .filterbar{flex-wrap:nowrap!important;overflow-x:auto}.rdy-page .filterbar>*{flex-shrink:0}.rdy-page .filterbar button,.rdy-page .filterbar label{white-space:nowrap}.rdy-page .arco-table-th-title,.rdy-page .arco-table-td-content{white-space:nowrap}.rdy-content{display:flex;flex-direction:column;gap:4px;min-width:0;cursor:pointer}.rdy-content b,.rdy-content small{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.rdy-link{display:block;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--cf-accent);font-weight:600;text-decoration:none}.rdy-play-link{border:0;background:transparent;padding:0;text-align:left;font-family:inherit;font-size:inherit;cursor:pointer}.rdy-player-stage{display:flex;align-items:center;justify-content:center;background:#111;min-height:0;height:min(58vh,max(180px,calc(100dvh - 290px)));border-radius:8px;overflow:hidden}.rdy-player-stage video,.rdy-player-stage img{max-width:100%;max-height:100%;object-fit:contain}.rdy-player-files{display:flex;gap:8px;overflow-x:auto;padding:12px 0;white-space:nowrap}.rdy-player-files button{flex-shrink:0}.rdy-player-title{font-size:14px;line-height:1.6;margin:0 0 8px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.rdy-link:hover{text-decoration:underline}.rdy-link:focus-visible{outline:2px solid var(--cf-accent);outline-offset:2px}.rdy-content small{color:var(--cf-ink3);font-size:12px}.rdy-summary{display:flex;gap:28px;align-items:center;padding:4px 0 16px;overflow-x:auto;white-space:nowrap}.rdy-summary b{font-variant-numeric:tabular-nums;margin-left:6px}.rdy-source-summary{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:12px;margin-bottom:18px}.rdy-source-summary span{white-space:nowrap;color:var(--cf-ink3);font-size:12px}.rdy-source-summary b{display:block;color:var(--cf-ink);font-size:16px;margin-top:4px;font-variant-numeric:tabular-nums}.rdy-fields{width:100%;border-collapse:collapse}.rdy-fields th,.rdy-fields td{padding:10px 12px;border-bottom:1px solid var(--cf-border,#e8eaed);text-align:left;vertical-align:top}.rdy-fields th{width:220px;font-weight:500}.rdy-fields small{display:block;color:var(--cf-ink3);font-size:11px;margin-top:4px}.rdy-fields pre,.rdy-raw{white-space:pre-wrap;overflow-wrap:anywhere;font-size:12px;margin:0}.rdy-fields td{word-break:break-word}

  .cs-data-page{display:flex;flex-direction:column;flex:1;min-height:0;gap:10px;box-sizing:border-box;min-width:0}
  .cs-all-shops{flex:1;overflow:visible;gap:16px}.cs-all-toolbar{position:sticky;top:0;z-index:30;background:#fff;border:1px solid #e5e6eb;border-radius:6px;padding:10px 12px}.cs-shop-panel{flex:none;min-height:0;gap:8px;padding:12px;border:1px solid #e5e6eb;border-radius:8px;background:#f7f8fa;content-visibility:auto;contain-intrinsic-size:auto 760px}.cs-shop-panel .cs-table-card{flex:none}.cs-shop-heading{display:flex;align-items:center;gap:10px;min-height:32px;white-space:nowrap;overflow-x:auto}.cs-shop-heading b{font-size:16px;color:#1d2129}.cs-shop-heading span{font-size:12px;color:#86909c}.cs-shop-heading .arco-btn:last-child{margin-left:auto}
  .cs-account-stats{display:grid;grid-template-columns:repeat(6,minmax(145px,1fr));gap:10px;overflow-x:auto;flex:none}.cs-account-stat{border:1px solid #e5e6eb;border-radius:6px;background:#fff;padding:10px 14px;display:flex;flex-direction:column;gap:5px;white-space:nowrap}.cs-account-stat>span{color:#4e5969;font-size:12px}.cs-account-stat>b{font-size:22px;font-weight:600;font-variant-numeric:tabular-nums;line-height:1.2;color:#1d2129}.cs-account-stat>small{color:#86909c;font-size:12px}.cs-account-link{padding:0!important;font-weight:500}.cs-account-page .cs-table-heading>span{flex:none}
  .cs-account-config-actions{display:flex;align-items:center;gap:8px;margin:14px 0;white-space:nowrap;overflow-x:auto}.cs-account-options{display:flex;flex-direction:column;gap:0;width:100%}.cs-account-option{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:10px 0;border-bottom:1px solid #f2f3f5;min-width:0}.cs-account-option .arco-checkbox{white-space:nowrap;flex:none}.cs-account-option small{color:#86909c;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.cs-account-page .cs-table-heading button{margin-right:12px}
  .cs-shop-table th,.cs-shop-table td{white-space:nowrap}.cs-shop-note{margin:12px 0 0;font-size:12px;line-height:1.6;white-space:nowrap;overflow-x:auto}
  .cs-detail-controls{display:flex;align-items:center;flex-wrap:wrap;gap:8px 12px}.cs-detail-date{display:inline-flex;align-items:center;gap:6px;white-space:nowrap}.cs-detail-date .arco-picker{width:132px}.cs-detail-controls>.arco-btn{margin-left:auto}
@media(max-width:700px){.cs-shop-table .arco-table-col-fixed-left{position:static!important}.cs-shop-table .arco-table-col-fixed-left::after{display:none}}
  .cs-all-shops{flex:none;padding:12px 16px}.cs-data-page *{box-sizing:border-box}.cs-toolbar{flex-wrap:nowrap!important;overflow-x:auto;gap:8px;flex:none;margin:0}.cs-toolbar>*{flex-shrink:0}.cs-toolbar-tail{margin-left:auto;display:flex;gap:8px}
  .cs-filter-panel{display:flex;flex-direction:column;align-items:stretch;gap:0;padding:4px 14px!important;overflow:visible!important}.cs-filter-row{display:flex;align-items:center;flex-wrap:wrap;gap:8px 12px;min-width:0;padding:9px 0}.cs-filter-row+.cs-filter-row{border-top:1px solid #f2f3f5}.cs-filter-row>*{flex:none}.cs-filter-label{color:#4e5969;font-size:12px;white-space:nowrap}.cs-filter-actions{display:flex;align-items:center;flex-wrap:wrap;gap:8px;margin-left:auto}.cs-filter-shortcuts{display:flex;align-items:center;flex-wrap:wrap;gap:6px}.cs-filter-panel .arco-picker{max-width:100%}.cs-shop-heading .arco-btn:last-child{margin-left:auto}
  .cs-sync-stamp{margin-left:auto;color:#4e5969;font-size:12px;white-space:nowrap}.cs-sync-stamp strong{font-weight:500;color:#1d2129}.cs-sync-stamp small{color:#86909c}.cs-sync-stamp+.cs-filter-actions{margin-left:0}
  @media(max-width:700px){.cs-filter-panel{padding:4px 10px!important}.cs-filter-row{align-items:flex-start}.cs-filter-shortcuts{flex:1 1 100%;min-width:0}.cs-filter-actions{margin-left:0;width:100%}.cs-sync-stamp{margin-left:0;white-space:normal;flex:1 1 100%}.cs-filter-row .arco-picker,.cs-filter-row .arco-input-wrapper{max-width:100%}.cs-shop-heading{flex-wrap:wrap;overflow:visible;white-space:normal}.cs-shop-heading b{flex:1 1 100%;font-size:14px}}
  .cs-timeline:focus-visible{outline:2px solid #165dff;outline-offset:2px}
  .cs-table-card{display:flex;flex-direction:column;flex:1;min-height:0;padding:12px 14px}.cs-table-heading{display:flex;justify-content:space-between;gap:16px;white-space:nowrap;font-size:12px;color:#86909c;margin-bottom:10px;overflow-x:auto}.cs-table-heading>span:first-child{color:#1d2129;display:flex;gap:10px;align-items:center}.cs-data-page th,.cs-data-page td,.cs-data-page button,.cs-data-page .arco-tag{white-space:nowrap}.cs-alert-value{color:#f53f3f}.cs-empty{padding:36px;color:#86909c}.cs-checks{overflow:auto;padding:20px}.cs-legend{display:inline-flex;align-items:center;gap:6px;color:#4e5969}.cs-legend i{display:inline-block;width:8px;height:8px;border-radius:50%}.cs-state-1{background:#4bcbb3}.cs-state-0{background:#ffb65b}.cs-state-2{background:#d8dade}.cs-timeline{height:26px;position:relative;cursor:pointer;background:repeating-linear-gradient(to right,transparent 0,transparent calc(8.333% - 1px),#edf0f4 calc(8.333% - 1px),#edf0f4 8.333%);min-width:560px;outline-offset:2px}.cs-segment{position:absolute;top:9px;height:8px;min-width:1px}.cs-raw{white-space:pre-wrap;overflow-wrap:anywhere;background:#f7f8fa;padding:16px;font-size:12px;line-height:1.7;margin-top:16px}.cs-period-table{margin-top:16px}
.cs-core-strip {display:flex;gap:24px;overflow-x:auto;white-space:nowrap;padding:10px 14px;background:#fff;border:1px solid var(--border,#e5e6eb);border-radius:6px}.cs-core-strip span{flex:none;color:#86909c}.cs-core-strip b{color:#1d2129;margin-left:8px}
body:has(.cs-data-page) .apptop-mods{min-width:0;overflow-x:auto}body:has(.cs-data-page) .mod-tab{white-space:nowrap;flex:none}body:has(.cs-data-page) .apptop-user{flex:none}
.cs-mobile-nav{display:none}
@media(max-width:700px){body:has(.cs-data-page) .sidebar{display:none}body:has(.cs-data-page) .main-area{margin-left:0}.cs-mobile-nav{display:flex;align-items:center;gap:10px;flex:none;padding:8px 16px;background:#fff;border-bottom:1px solid #e5e6eb;color:#4e5969;font-size:12px}.cs-mobile-nav .arco-select{width:160px;max-width:calc(100vw - 120px)}.cs-data-page .pagination-bar{overflow-x:auto;white-space:nowrap;gap:16px}.cs-data-page .pagination-bar>*{flex:none}.cs-list-date-desktop{display:none!important}.cs-list-date-mobile{display:flex;align-items:center;gap:6px;padding:0 2px;flex:none;white-space:nowrap}.cs-list-date-mobile .arco-picker{width:132px}}
.exp-page{min-width:0}.exp-mobile-store{display:none}.exp-product-cell{display:flex;align-items:center;gap:8px;min-width:0}.exp-product-cell img{width:32px;height:32px;object-fit:cover;flex:none;border-radius:3px}.exp-product-cell>span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.exp-report-block{margin:12px 0}.exp-report-block h3{font-size:16px;margin:18px 0 10px}.exp-report-card{display:flex;gap:14px;padding:14px;border:1px solid #e5e6eb;border-radius:6px;white-space:normal}.exp-report-card>img{width:70px;height:70px;object-fit:cover;flex:none}.exp-report-card p{margin:4px 0}.exp-report-card small{font-size:12px;color:#4e5969}.exp-panel{border:1px solid #e5e6eb;border-radius:6px;background:#fff}.exp-stamp{margin-left:auto;white-space:nowrap;font-size:12px;color:#4e5969}.exp-body{overflow:auto;min-height:0;min-width:0;padding-bottom:12px}.exp-score-cards{display:grid;grid-template-columns:repeat(6,minmax(155px,1fr));gap:8px;overflow-x:auto;margin-bottom:12px}.exp-score-card{appearance:none;text-align:left;border:1px solid #e5e6eb;background:#fff;border-radius:6px;padding:14px;display:flex;flex-direction:column;gap:12px;color:#1d2129;cursor:pointer;white-space:nowrap;font:inherit}.exp-score-card strong{font-size:30px;font-weight:600;line-height:1.2;font-variant-numeric:tabular-nums}.exp-score-card small{font-size:12px;font-weight:400;margin-left:4px}.exp-score-card>span{font-size:13px}.exp-score-card.exp-total{background:#165dff;color:#fff;border-color:#165dff}.exp-score-change{font-size:12px!important;color:#4e5969}.exp-total .exp-score-change{color:#fff}.exp-score-change>span{margin-left:8px}.exp-context{display:flex;gap:20px;font-size:12px;align-items:flex-start;white-space:nowrap;overflow-x:auto;margin:12px 0;color:#4e5969}.exp-context details{min-width:120px}.exp-context .exp-fields{white-space:normal;min-width:500px}.exp-protect{background:#f2f7ff;border:1px solid #d4e3ff;border-radius:6px;padding:12px 16px;font-size:12px;margin-bottom:12px;color:#334b73}.exp-protect>div{display:flex;align-items:center;gap:12px;margin-bottom:6px;flex-wrap:wrap}.exp-protect details>div{line-height:2.2}.exp-diagnosis{display:flex;align-items:flex-start;gap:16px;padding:14px 16px;margin-bottom:14px;border-left:3px solid #165dff}.exp-summary-text{white-space:pre-wrap;line-height:1.8;font-size:13px;flex:1;min-width:0}.exp-diagnosis>.arco-btn{flex:none;white-space:nowrap}.exp-group{margin:16px 0}.exp-section-title{display:flex;align-items:center;gap:12px;margin-bottom:10px;font-size:14px;white-space:nowrap;overflow-x:auto}.exp-section-title>strong{font-size:16px}.exp-inline-note{font-size:12px;color:#165dff}.exp-metric-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}.exp-metric{appearance:none;display:block;text-align:left;min-width:0;border:1px solid #e5e6eb;border-radius:6px;padding:14px 16px;background:#fff;font:inherit;color:#1d2129;cursor:pointer}.exp-metric:hover,.exp-score-card:hover{border-color:#94bfff;box-shadow:0 2px 8px #165dff0a}.exp-metric:focus-visible,.exp-score-card:focus-visible{outline:2px solid #165dff;outline-offset:2px}.exp-metric-name{font-size:13px;display:flex;justify-content:space-between;gap:8px;white-space:nowrap;overflow-x:auto}.exp-metric-name>span{font-size:12px;color:#165dff}.exp-metric-main{display:flex;align-items:baseline;gap:6px;margin:10px 0;font-variant-numeric:tabular-nums;white-space:nowrap;overflow-x:auto}.exp-metric-main>strong{font-size:26px;font-weight:600}.exp-metric-main>span{font-size:12px}.exp-delta{margin-left:auto;color:#4e5969}.exp-metric-footer{display:flex;gap:12px;font-size:12px;line-height:1.7;white-space:nowrap;overflow-x:auto;min-height:20px}.exp-good{color:#16836b}.exp-below{color:#b65b00}.exp-chart-head{display:flex;align-items:center;justify-content:space-between;gap:12px;white-space:nowrap;overflow-x:auto;font-size:13px}.exp-chart-head small{margin-left:10px;color:#4e5969;font-size:12px}.exp-trend-tooltip{position:fixed;z-index:1100;pointer-events:none;width:260px;max-width:calc(100vw - 16px);box-sizing:border-box;padding:10px 12px;background:#fff;border:1px solid #e5e6eb;border-radius:6px;box-shadow:0 4px 16px #1d212926;font-size:12px;line-height:1.8;color:#1d2129;font-variant-numeric:tabular-nums}.exp-trend-tooltip>strong{font-size:13px}.exp-trend-tooltip-label{color:#4e5969;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.exp-trend-tooltip-row{display:flex;justify-content:space-between;gap:12px;white-space:nowrap}.exp-trend-tooltip-row>b{color:#165dff;font-weight:600}.exp-chart-scroll{overflow-x:auto}.exp-trend svg{display:block;width:100%;min-width:650px;max-height:220px}.exp-trend.compact svg{min-width:0;height:62px;width:100%}.exp-trend.compact circle{r:2}.exp-trend.compact text{display:none}.exp-trend.compact{margin-top:2px}.exp-day-values{max-height:400px;overflow:auto;margin-top:12px}.exp-day-values table{width:100%;border-collapse:collapse;font-variant-numeric:tabular-nums}.exp-day-values th,.exp-day-values td{padding:8px 12px;border-bottom:1px solid #e5e6eb;text-align:right;white-space:nowrap}.exp-day-values th:first-child,.exp-day-values td:first-child{text-align:left}.exp-source-copy{padding:14px 16px;margin-top:12px}.exp-source-copy>a{display:block;margin-top:10px}.exp-copy{white-space:pre-wrap;line-height:1.9;font-size:13px;color:#1d2129;overflow-wrap:anywhere}.exp-source-copy .exp-copy{margin-top:16px}.exp-fields{font-size:12px;line-height:1.9;overflow-wrap:anywhere;min-width:0}.exp-field{padding:6px 0;border-bottom:1px solid #f2f3f5}.exp-field-label{display:inline-block;min-width:160px;color:#4e5969;margin-right:16px}.exp-field details>.exp-fields{border-left:2px solid #e5e6eb;margin:8px 0 0 6px;padding-left:14px}.exp-fields summary,.exp-page summary{cursor:pointer}.exp-fields small{color:#4e5969;font-size:12px}.exp-detail-head{display:flex;flex-direction:column;gap:10px;margin-bottom:16px}.exp-detail-head>b{font-size:22px;font-variant-numeric:tabular-nums}.exp-detail-head>span{font-size:12px;color:#4e5969}.exp-table-panel{display:flex;flex-direction:column;min-height:0;gap:12px}.exp-table-panel th,.exp-table-panel td,.exp-table-panel button{white-space:nowrap}.exp-table-panel .pagination-bar{white-space:nowrap;overflow-x:auto;gap:16px}.exp-table-panel .pagination-bar>*{flex:none}.exp-logistics{display:flex;gap:10px;flex-wrap:wrap;margin:20px 0}.exp-logistics>b,.exp-logistics>details{width:100%}.exp-check{padding:20px}@media(max-width:700px){.exp-mobile-store{display:flex}.exp-metric-grid{grid-template-columns:minmax(300px,1fr)}.exp-diagnosis{padding:12px}.exp-score-cards{grid-template-columns:repeat(6,155px)}.exp-metric-footer{font-size:12px}.exp-stamp{margin-left:0}.exp-field-label{min-width:120px}}


.qc-audit-sr { position:absolute; width:1px; height:1px; padding:0; margin:-1px; overflow:hidden; clip-path:inset(50%); white-space:nowrap; }
.qc-audit-mobile-nav { display:none; }
@media(max-width:700px) { body:has(.qc-audit-page) .apptop-mods { min-width:0; overflow-x:auto; flex:1; } body:has(.qc-audit-page) .mod-tab { flex:none; white-space:nowrap; } body:has(.qc-audit-page) .apptop-brand { flex:none; } body:has(.qc-audit-page) .apptop-user { display:none; } body:has(.qc-audit-page) .sidebar { display:none; } body:has(.qc-audit-page) .main-area { margin-left:0; } .qc-audit-mobile-nav { display:flex; padding:8px 14px 0; flex:none; } .qc-audit-page .pagination-bar { overflow-x:auto; white-space:nowrap; gap:16px; } .qc-audit-page .pagination-bar>* { flex:none; } }
.qc-audit-filters { flex-wrap:nowrap; overflow-x:auto; }
.qc-audit-cell { display:flex; flex-direction:column; gap:4px; min-width:0; }
.qc-audit-cell>* { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-weight:normal; }
.qc-audit-cell small { color:var(--cf-ink3); font-size:12px; }
.qc-audit-status,.qc-audit-selected { flex:none; padding:8px 14px; font-size:12px; color:var(--cf-ink3); display:flex; gap:8px; align-items:center; overflow-x:auto; white-space:nowrap; }
.qc-audit-meta { display:grid; grid-template-columns:100px minmax(0,1fr); gap:10px; font-size:13px; }
.qc-audit-meta dt,.qc-audit-reason-fields dt { color:var(--cf-ink3); }
.qc-audit-meta dd,.qc-audit-reason-fields dd { margin:0; overflow-wrap:anywhere; }
.qc-audit-detail-name { font-size:16px; overflow-wrap:anywhere; }
.qc-audit-reason { border-top:1px solid var(--cf-line); padding:12px 0; }
.qc-audit-reason h3 { font-size:14px; line-height:1.7; }
.qc-audit-reason-fields { display:grid; gap:8px; font-size:13px; line-height:1.8; }
.qc-audit-reason-fields dd { margin-bottom:10px; }