/* ═══════════════════════════════════════════════════════════
   繁星智绘 · 影视 Agent
   ★ v2578：视觉语言换成与「电商 Studio」同一套 ——
     暖灰底 + 纸白卡 + 墨黑字 + 苔绿强调；基准字阶 13px、圆角 3~8px；
     卡片靠 **1px 细线**拉开层级，阴影只留给浮层。
   为什么统一：这两件工具在同一个站里、同一批人在用，
     上一页学会的「什么颜色代表什么」（绿 = 可推进 / 已通过，红 = 会被卡住）
     不该在下一页重新学一遍。紫调 + 大圆角 + 大投影那是 landing page 的语言，
     不是一件要长时间盯着看的工作台的语言。
   ⚠ token **名**沿用旧名（--brand-p / --grad-p / --brand-light-p）——
     它们在这个文件里被引用 80 多次，改名要动的地方太多、漏一处就掉色。
     但**指向的含义已经换了**：--brand-p 现在是苔绿，不再是品牌紫。
   ═══════════════════════════════════════════════════════════ */
:root{
  /* ── 复古名：旧 token 指向新配色 ─────────────────────────────── */
  --bg:#f6f6f7; --card:#fff; --ink:#202122; --sub:#777b80; --faint:#8d969b;
  --brand:#1c1e20; --brand-light:#f1f1f3; --grad:linear-gradient(135deg,#2a2c2e,#4a4d50);
  --brand-p:#166b50; --brand-light-p:#eaf3ee; --grad-p:linear-gradient(135deg,#17553f,#2f8a68);
  --line:#e5e6e8; --radius:6px;
  --shadow:0 1px 3px #0000000a;
  --ok:#287457; --warn:#8a6218; --err:#a4392f;
  --p0:#a4392f; --p1:#8a6218; --p2:#6b7276;

  /* ── 电商 Studio 那套 token：本文件新写的规则直接用它们 ─────────── */
  --paper:#fff; --sunken:#f1f1f3; --sunken-2:#f9f9fa;
  --ink-2:#3f474a; --muted:#777b80; --faint-2:#91969a;
  --line-2:#eceef0; --line-3:#dfe1e4;
  --green:#166b50; --green-2:#287457; --green-soft:#eaf3ee; --green-soft-2:#e9f2ec;
  --green-line:#abcbb8; --green-line-2:#bdd9cb;
  --green-btn:#d2edb4; --green-btn-ink:#213720;
  --dark:#1c1e20; --dark-btn:#252728; --dark-btn-h:#45484a;
  --err-soft:#fbeeec; --err-line:#e6c4bf;
  --warn-soft:#fdf4e3; --warn-line:#e8d6ad;
  --r:6px; --r-sm:5px; --r-xs:3px;
  --railw:205px; --insw:312px; --h-top:64px;
}
*{margin:0;padding:0;box-sizing:border-box;letter-spacing:0}
/* 一屏锁死：整页不滚，高度由 .dr-app 独占 100vh。窄屏/矮屏在文件末尾解锁。 */
html,body{height:100%;overflow:hidden}
body{
  font:13px/1.5 -apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Noto Sans SC","Microsoft YaHei",sans-serif;
  background:var(--bg); color:var(--ink); -webkit-font-smoothing:antialiased;
  display:flex; height:100%;
}
button{font-family:inherit;cursor:pointer;border:none;background:none;color:inherit}
button:disabled{cursor:not-allowed;opacity:.45}
input,textarea,select{font-family:inherit;outline:none;color:inherit}
a{color:inherit;text-decoration:none}
button:focus-visible,a:focus-visible,[tabindex]:focus-visible{outline:2px solid #258165;outline-offset:3px;border-radius:3px}
/* 图标基线：JS 里生成的内联 SVG 只写 viewBox、不写宽高；没有这条兜底，
   落在「没单独指定尺寸」容器里的图标会退回 SVG 默认的 300×150（占半屏）。 */
svg{flex-shrink:0}
svg:not([width]){width:17px;height:17px}
::-webkit-scrollbar{width:8px;height:8px}
::-webkit-scrollbar-thumb{background:#d3d6d9;border-radius:4px}
::-webkit-scrollbar-thumb:hover{background:#c2c6c9}
::-webkit-scrollbar-track{background:transparent}

/* ── 按钮（与电商 .btn 同一套尺寸与配色）── */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:7px;white-space:nowrap;
  padding:9px 13px;border:1px solid var(--line-3);border-radius:var(--r);background:#fff;
  font-size:12px;color:var(--ink-2);transition:background .16s,border-color .16s,color .16s}
.btn:hover{background:#eceef0}
.btn svg{width:14px;height:14px}
.btn-sm{padding:7px 11px;font-size:11.5px}
.btn:disabled{opacity:.45;cursor:not-allowed}
.btn-primary{background:var(--dark-btn);border-color:var(--dark-btn);color:#fff}
.btn-primary:hover{background:var(--dark-btn-h);border-color:var(--dark-btn-h)}
.btn-ghost{border-color:var(--line-3);background:#fff;color:var(--muted)}
.btn-ghost:hover{background:#f1f2f4;color:var(--ink-2)}
/* ⚠ 旧类名 `.btn-purple` 必须留着：drama.js 里还有几处在用它。
   含义已经从「品牌紫」改成「可推进的绿」—— 名字过时，但语义现在是统一的。 */
.btn-purple{background:var(--green-btn);border-color:transparent;color:var(--green-btn-ink);font-weight:600}
.btn-purple:hover{background:#c4e5a1}
.btn-danger{background:var(--err-soft);border-color:var(--err-line);color:var(--err)}
.btn-danger:hover{background:#f7e2de}

/* ══════════ 外壳：左窄栏 + 右列 ══════════
   与电商 Studio（.ec-app / .ec-rail / .ec-col）同一套骨架。
   ★ 一屏锁死能成立的关键：**每一层都要 `min-height:0`** ——
     任何一层漏了，grid/flex 子项就会被内容顶开、把整页撑出滚动条。 */
.dr-app{display:grid;grid-template-columns:var(--railw) minmax(0,1fr);height:100vh;width:100%;overflow:hidden}

/* ── 左栏 ── */
.dr-rail{
  background:var(--sunken); border-right:1px solid var(--line);
  padding:22px 16px 16px; display:flex; flex-direction:column;
  height:100%; min-height:0; overflow-y:auto;
}
.brand{display:flex;gap:10px;align-items:center;padding:0 6px 20px;flex-shrink:0}
.brandmark{width:31px;height:31px;background:#242526;color:#fff;border-radius:5px;display:grid;place-items:center;flex-shrink:0}
.brandmark svg{width:16px;height:16px}
.brandtext strong{font-size:15px;font-weight:600;display:block;line-height:1.25}
.brandtext small{font-size:9px;color:#73777b;display:block;margin-top:3px;letter-spacing:.02em}

.dr-projcard{
  display:flex; gap:9px; align-items:center; border:1px solid #dcdee0; border-radius:var(--r);
  padding:10px; margin-bottom:16px; background:var(--sunken-2); flex-shrink:0;
}
.dr-projcard .avatar{width:25px;height:25px;background:#dfe6e2;border-radius:5px;display:grid;place-items:center;font-weight:600;font-size:11px;flex-shrink:0}
.dr-projcard .pt{flex:1;min-width:0}
.dr-projcard .pt b{font-size:11.5px;font-weight:500;display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.dr-projcard .pt span{font-size:10px;color:var(--faint-2);display:block;margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

.rail-label{font-size:10px;color:#888d91;margin:0 10px 9px}
.dr-nav{display:flex;align-items:center;gap:11px;padding:10px 11px;width:100%;text-align:left;
  margin:2px 0;border-radius:var(--r);color:#656a6f;font-size:12.5px;background:none;border:0}
.dr-nav svg{width:16px;height:16px;opacity:.85}
.dr-nav:hover{background:#e9eaec}
.dr-nav.on{background:#fff;color:#232729;box-shadow:0 1px 3px #0000000a}
.dr-rail .spacer{flex:1}
.dr-railfoot{font-size:11px;color:#898d91;border-top:1px solid #dddfe1;padding:15px 8px 0;
  display:flex;align-items:center;gap:8px}
.dr-railfoot a{display:flex;align-items:center;gap:6px;color:#898d91}
.dr-railfoot a:hover{color:var(--ink)}
.dr-railfoot .dot{width:6px;height:6px;border-radius:50%;background:#428c6d;flex-shrink:0}

/* ── 顶栏（面包屑 + 星光 + 新建）──
   不再是 sticky：列自己已经 `overflow:hidden` 不滚了，留在里面的 sticky 没有参照物。 */
.dr-col{min-width:0;display:flex;flex-direction:column;height:100vh;min-height:0;overflow:hidden}
.dr-top{
  height:var(--h-top); padding:0 26px; display:flex; align-items:center; justify-content:space-between;
  gap:14px; background:#fff; border-bottom:1px solid var(--line);
  position:relative; z-index:30; flex-shrink:0;
}
.dr-crumb{display:flex;align-items:center;gap:9px;font-size:12px;color:#909497;min-width:0}
.dr-crumb i{color:#c2c6c9;font-style:normal}
.dr-crumb b{color:#363a3d;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.dr-topact{display:flex;align-items:center;gap:10px;flex-shrink:0}
.dr-credits{display:inline-flex;align-items:center;gap:6px;font-size:10px;border:1px solid #e1e2e5;
  border-radius:4px;padding:5px 8px;color:#81868a;font-variant-numeric:tabular-nums}
.dr-credits svg{width:12px;height:12px}
.dr-credits .num{color:var(--ink);font-weight:600}

/* ── 页面：标题区 / 步骤条 / 工作区 三行栅格 ──
   工作区是 `minmax(0,1fr)` —— 「吃掉剩下的高度」写进栅格，不靠 `flex:1` 碰运气。
   间距统一由 `gap` 给：子块**都不自带 margin-bottom**（自带就会跟 gap 叠加）。 */
.dr-page{
  padding:18px 26px 16px; flex:1; min-width:0; min-height:0;
  display:grid; grid-template-rows:auto auto minmax(0,1fr); gap:14px;
}
.dr-thead{display:flex;align-items:flex-start;justify-content:space-between;gap:20px;min-height:0}
.dr-eyebrow{font-size:10px;color:#8a8f94;margin-bottom:5px}
.dr-title{
  font-size:22px;font-weight:600;line-height:1.25;margin:0 0 7px;padding:0;border:0;background:none;
  color:var(--ink);width:100%;max-width:620px;border-radius:4px;
}
.dr-title:hover:not(:disabled){box-shadow:0 0 0 1px var(--line)}
.dr-title:focus{outline:none;box-shadow:0 0 0 3px rgba(22,107,80,.10)}
.dr-title:disabled{color:#b8bdc1;cursor:default}
.dr-title::placeholder{color:#b8bdc1;font-weight:600}
.dr-meta{display:flex;gap:11px;align-items:center;color:#8a8e92;font-size:11px;flex-wrap:wrap}
.dr-meta .dot{width:3px;height:3px;border-radius:50%;background:#bdc0c4;flex-shrink:0}
.dr-meta b{font-weight:600;color:var(--ink-2)}
.dr-cost{color:#8a8e92;font-variant-numeric:tabular-nums}
.dr-cost b{font-weight:600;color:var(--ink-2)}
.dr-theadact{display:flex;align-items:center;gap:9px;flex-wrap:wrap;justify-content:flex-end}

/* ── 六个环节：横向编号步骤条 ──
   ★ 与电商 `.ec-steps` 同形态。血条不再铺在按钮底下当背景，而是**压在步骤条那条
     底线上**（bottom:-2px 正好盖住 border-bottom）—— 横排只有三十来像素高，
     背景层铺宽会直接把文字压糊。`.pct` 收成行尾的小字。
   ⚠ `.fill` / `.pct` 两个 class 名由 drama.js 的 renderRail() 直接操作，不许改名。 */
.dr-steps{display:flex;align-items:stretch;gap:24px;border-bottom:1px solid var(--line);
  min-height:0;overflow-x:auto;overflow-y:hidden;scrollbar-width:none}
.dr-steps::-webkit-scrollbar{display:none}
.dr-step{
  display:flex;align-items:center;gap:8px;padding:0 0 12px;flex-shrink:0;
  border-bottom:2px solid transparent;color:#898e92;font-size:12px;text-align:left;
  position:relative;background:none;border-radius:0;cursor:pointer;
}
.dr-step:hover{color:#5c6266}
.dr-step i{
  width:20px;height:20px;flex:none;border:1px solid #dcdee1;border-radius:50%;
  display:grid;place-items:center;font-style:normal;font-size:10px;
  font-variant-numeric:tabular-nums;background:none;color:inherit;
}
.dr-step .tx{display:flex;align-items:center;gap:7px;min-width:0}
.dr-step b{font-weight:500;white-space:nowrap;font-size:12px}
.dr-step em{font-style:normal;font-size:10px;color:var(--faint-2);white-space:nowrap;display:none}
.dr-step.on{color:#282e30;border-bottom-color:#282e30}
.dr-step.on i{background:#252a2b;color:#fff;border-color:#252a2b}
.dr-step:disabled{opacity:.5;cursor:not-allowed}

/* 血条 = 这一步的进度，压在底线上的 2px 绿线。宽度由 renderRail() 铺。 */
.dr-step > .fill{
  position:absolute;left:0;bottom:-2px;height:2px;width:0;
  background:var(--green-2);transition:width .5s ease;pointer-events:none;
}
/* 行尾百分比：只有「在跑」与「中断」才露出来 —— 其余时候它只是噪音。 */
.dr-step > .pct{
  font-size:9px;color:var(--faint-2);font-variant-numeric:tabular-nums;
  white-space:nowrap;display:none;
}
.dr-step > .pct.run{display:inline;color:var(--green-2);font-weight:600;animation:breathe 1.6s ease-in-out infinite}
.dr-step > .pct.done{display:inline}
.dr-step > .pct.fail{display:inline;color:var(--err);font-weight:600}
@keyframes breathe{0%,100%{opacity:1}50%{opacity:.45}}
@keyframes pulse{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.45;transform:scale(1.35)}}

/* 推进方式（半托管 / 全托管）：横排分段控件，与电商 .ec-mode 同形 */
.dr-mode{display:inline-flex;background:#eaecee;border-radius:var(--r-sm);padding:3px;gap:2px}
.dr-mode button{
  border-radius:var(--r-xs);padding:6px 11px;text-align:left;color:#85898e;
  line-height:1.3;background:none;border:0;display:block;
}
.dr-mode button b{font-size:11px;font-weight:500;display:block}
.dr-mode button em{font-style:normal;font-size:9px;display:none;color:inherit}
.dr-mode button:hover{color:#5c6266}
.dr-mode button.on{background:#fff;color:#202628;box-shadow:0 1px 3px #0000000b}
.dr-mode button.on b{font-weight:600}

/* 开拍 / 停止。绿 =「可推进」，与电商的开跑按钮同一个绿。 */
.dr-run{display:inline-flex;align-items:center;gap:7px;padding:9px 14px;border-radius:var(--r-sm);
  background:var(--green-btn);color:var(--green-btn-ink);font-size:12px;font-weight:600;
  border:0;transition:background .16s}
.dr-run:hover{background:#c4e5a1}
.dr-run svg{width:13px;height:13px}
.dr-run.stop{background:var(--dark-btn);color:#fff}
.dr-run.stop:hover{background:var(--dark-btn-h)}
.dr-run.stop>svg{display:none}
.dr-run.is-busy{opacity:1;cursor:progress}
.dr-run.is-busy:hover{background:var(--green-btn)}
#drRunSpin{display:none}
.dr-run.is-busy #drRunSpin{display:block}
.dr-run.is-busy>svg{display:none}
.bspin{width:12px;height:12px;flex:none;border-radius:50%;
  border:2px solid #00000024;border-top-color:currentColor;
  animation:drspin .8s linear infinite}
.btn.is-busy .bspin{border-color:#ffffff59;border-top-color:#fff}
@keyframes drspin{to{transform:rotate(360deg)}}

/* ── 工作区两栏：内容 + 检视栏 ──
   `align-items:stretch` 让两栏同高（`start` 会让检视栏比正文矮一截，视觉上就「散」）。
   ⚠ `.dr-main{overflow-y:auto}` 是**最后一道保险**，不是「锁死失败」：
     极端窗口下宁可让工作区自己滚，也不能把正文裁掉 —— `overflow:hidden`
     会把内容**静默吃掉**，那比滚动糟得多。 */
.dr-studio{display:grid;grid-template-columns:minmax(0,1fr) var(--insw);gap:20px;
  align-items:stretch;min-height:0}
.dr-main{min-width:0;min-height:0;overflow-y:auto;overflow-x:hidden;overscroll-behavior:contain;
  scrollbar-width:thin;scrollbar-color:#d3d6d9 transparent;padding-right:3px}
.dr-main::-webkit-scrollbar{width:8px}
.dr-main::-webkit-scrollbar-thumb{background:#d3d6d9;border-radius:4px}
.dr-main::-webkit-scrollbar-track{background:transparent}

.dr-insp{background:var(--paper);border:1px solid var(--line);border-radius:var(--r);
  display:flex;flex-direction:column;min-height:0;overflow:hidden}
.dr-insp-h{display:flex;align-items:center;justify-content:space-between;gap:10px;flex-shrink:0;
  padding:14px 17px 12px;border-bottom:1px solid var(--line-2);font-size:12px;font-weight:600}
.dr-insp-h svg{width:14px;height:14px;color:#8b9297}
.dr-insp-b{padding:14px 17px 132px;flex:1;min-height:0;overflow-y:auto;
  scrollbar-width:thin;scrollbar-color:#dcdfe1 transparent}
/* 底部多留 132px：右下角是固定定位的客服浮标（.kefu-fab，52px + bottom 22px）。
   留 92px 原本以为够了，但「余额不足」警示框一出现就把侧栏撑长，
   浮标正好压住警示的最后一行 —— 而那行恰恰是「该怎么做」，不能被挡。 */
.dr-insp-b::-webkit-scrollbar{width:8px}
.dr-insp-b::-webkit-scrollbar-thumb{background:#dcdfe1;border-radius:4px}

.side-head{display:flex;align-items:center;gap:8px;font-size:10px;font-weight:400;
  letter-spacing:0;color:#7c8388;margin:0 2px 11px}
/* 区块之间用一条细线分开，而不是靠大间距 —— 间距一松，右栏就装不下了 */
.side-head:not(:first-child){margin-top:16px;padding-top:15px;border-top:1px solid var(--line-2)}
/* 「设置」小入口：放在区块标题右侧，跟标题同高，不占额外行 */
.side-edit{margin-left:auto;font-size:10px;color:var(--green);border-bottom:1px solid var(--green-line);
  padding:0;border-radius:0;background:none;transition:color .16s}
.side-edit:hover{color:var(--green-2);background:none}
.side-note{font-size:11px;color:var(--faint);line-height:1.6;margin:6px 2px 0}
.side-note b{color:var(--sub)}
.side-row{display:flex;justify-content:space-between;gap:8px;font-size:11.5px;
  padding:5px 0;border-bottom:1px solid var(--line-2)}
.side-row:last-child{border-bottom:none}
.side-row span{color:var(--muted)}
.side-row b{font-weight:600;text-align:right;font-variant-numeric:tabular-nums}
.side-row b.p{color:var(--green)}
/* 余额不够跑完时的提示。必须显眼：这是「钱花了剧没成」的唯一预警点。
   用暖红底 + 左侧色条，和普通 side-note（灰色小字）拉开层级，避免被当说明文字略过。 */
.side-warn{
  font-size:11.5px;line-height:1.65;color:var(--err);background:var(--err-soft);
  border-left:3px solid var(--err);border-radius:4px;
  padding:8px 10px;margin:8px 2px 0;
}
.side-warn b{color:var(--err)}
.side-warn ul{margin:6px 0 0;padding-left:16px}
.side-warn li{margin-bottom:5px}
.side-warn li:last-child{margin-bottom:0}
.side-row b.short{color:var(--err)}

/* ── 通用卡片 ── */
/* v2578：卡片**去掉投影**，改用 1px 细线 —— 与电商 .card 一致。
   投影版本在满屏十几张卡时会互相叠出一层灰雾，工作台里那是噪音；
   层级靠「线」表达已经足够，投影只留给真正浮起来的东西（弹层 / 抽屉）。 */
.card{background:var(--paper);border:1px solid var(--line);border-radius:var(--r);
  margin-bottom:12px;overflow:hidden}
.card:last-child{margin-bottom:0}
.card-h{display:flex;align-items:center;gap:10px;padding:13px 17px;border-bottom:1px solid var(--line-2)}
.card-h h3{font-size:13px;font-weight:600;flex:1;min-width:0}
.card-h .sub{font-size:11px;color:var(--faint);font-weight:400}
.card-b{padding:16px 17px}
.card-b+.card-b{border-top:1px solid var(--line)}
.card.pad0 .card-b{padding:0}

.hint{font-size:12.5px;color:var(--faint);line-height:1.65}
.badge{display:inline-flex;align-items:center;gap:4px;font-size:11px;font-weight:700;padding:3px 9px;border-radius:8px}
.badge.ok{background:#e9f2ec;color:var(--ok)}
.badge.run{background:var(--brand-light-p);color:var(--brand-p)}
.badge.wait{background:#f1f1f3;color:var(--faint)}
.badge.fail{background:#f7e2de;color:var(--err)}
.badge.warn{background:#fdf4e3;color:#8a6218}
.badge.done{background:#e9f2ec;color:var(--ok)}

.empty{text-align:center;padding:52px 24px;color:var(--faint)}
.empty .ico{font-size:38px;margin-bottom:12px;opacity:.5}
.empty h3{font-size:15px;font-weight:600;color:var(--ink);margin-bottom:6px}
.empty p{font-size:13px;line-height:1.7;max-width:440px;margin:0 auto}

/* ── 立项表单 ── */
.form-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(168px,1fr));gap:12px}
.fld{display:flex;flex-direction:column;gap:6px}
.fld label{font-size:12px;font-weight:600;color:var(--sub)}
.fld input,.fld select,.fld textarea{
  border:1px solid var(--line);border-radius:5px;padding:9px 11px;font-size:13px;background:#fff;transition:all .18s;
}
.fld input:focus,.fld select:focus,.fld textarea:focus{border-color:var(--brand-p);box-shadow:0 0 0 3px rgba(22,107,80,.1)}
.dr-idea{
  width:100%;min-height:132px;resize:vertical;border:1px solid var(--line);border-radius:6px;
  padding:13px 15px;font-size:13.5px;line-height:1.72;background:#fff;transition:all .18s;
}
.dr-idea:focus{border-color:var(--brand-p);box-shadow:0 0 0 3px rgba(22,107,80,.1)}
.src-switch{display:inline-flex;background:var(--brand-light);border-radius:5px;padding:3px;gap:2px}
.src-switch button{font-size:12.5px;font-weight:600;padding:6px 14px;border-radius:5px;color:var(--sub);transition:all .18s}
.src-switch button.on{background:#fff;color:var(--brand-p);box-shadow:0 1px 4px rgba(0,0,0,.08)}
.checks{display:flex;flex-wrap:wrap;gap:8px}
.chk{display:flex;align-items:center;gap:7px;font-size:12.5px;padding:8px 13px;border:1px solid var(--line);border-radius:5px;cursor:pointer;transition:all .18s;user-select:none}
.chk:hover{border-color:rgba(22,107,80,.3)}
.chk.on{background:var(--brand-light-p);border-color:var(--brand-p);color:var(--brand-p);font-weight:600}
.chk input{display:none}

/* ── 角色 / 道具卡 ── */
/* 两个网格，用途不同，**别共用一个规则**（v2540-B 在这里踩过）：
   ① `.grid-cards` = 项目页的资产区（角色三视图 / 道具 / 分集）。张数不定（可能只有
      3 个角色），所以 auto-fill + 固定 230px 卡宽：有 3 张就排 3 列，右边自然空着。
   ② `.grid-pipe` = 新建页「这台流水线在做什么」的 8 张卡。张数恒定，要**铺满且等宽**，
      所以按断点给显式列数。
      为什么不能沿用 auto-fill：它的语义就是「先铺满轨道、多出来的空着」——
      2560px 屏上铺出 8 条 242px 轨道而卡只有 4 张，后 4 条空轨白着、卡片挤在左半边
      （2026-09-17 老板实拍报的问题）。auto-fit 也不行：塌缩空轨只对最后一行生效，
      8 张卡落在 3 列宽度时最后 2 张被拉宽，与上面的卡片不等宽。
      断点按**每档实测卡宽**定，让卡宽全程落在 220~460px 的可读区间。注意
      **容器宽 = 视口 − 626**（v2578 新外壳：左栏 205 + 右栏 312 + 栏间距 20 +
      页面左右内边距 52 + 主区右内边距 3 + 卡片左右内边距 34；
      ⚠ 旧外壳那套是 228/312、合计 620 —— 换成新外壳后容器宽了 6px，
        这几档断点因此整体偏保守一点点，但相邻档位相隔几百像素，不会错档）。
      视口 ≤920 时左栏收成图标条（≈ 视口 − 483），≤820 右栏落到底下（≈ 视口 − 340），
      ≤700 左栏变成顶部横条（≈ 视口 − 68）。
      曾经写成 `≥2300 → 8` / 基础 4 /
      `≤1500 → 2`，结果 1500 处出现悬崖：1600 视口是 4 列 ×236px，1500 视口掉成
      2 列 ×434px，而 1440 / 1366 这些主流笔电分辨率全在错的一侧（8 张卡要滚 4 行）。
      根因是缺了 3 列这一档（v2540-G 修）：
        ≥2500px（容器 ≥1880）→ 8 列，卡 224~232px（2560 屏一行铺满，不用滚）
        1580~2499（容器 960~1879）→ 4 列，卡 231~437px
        1340~1579（容器 720~959）→ 3 列，卡 232~312px
        641~1339（容器 ~576~719）→ 2 列，卡 256~350px
        ≤640（导轨已隐藏）→ 1 列
      8 张卡落 3 列时是 3+3+2，末行不满属正常网格行为，不算留白；要避免的只有
      **空轨道**（auto-fill 的老毛病）与**卡宽失衡**（auto-fit 的老毛病）。 */
.grid-cards{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:12px}
.grid-cards>.mini{min-width:0}
.grid-pipe{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}
.grid-pipe>.mini{min-width:0}
@media(min-width:1340px){.grid-pipe{grid-template-columns:repeat(3,minmax(0,1fr))}}
@media(min-width:1580px){.grid-pipe{grid-template-columns:repeat(4,minmax(0,1fr))}}
@media(min-width:2500px){.grid-pipe{grid-template-columns:repeat(8,minmax(0,1fr))}}
@media(max-width:640px){.grid-pipe{grid-template-columns:1fr}}
.mini{border:1px solid var(--line);border-radius:6px;padding:13px 14px;transition:all .18s;background:#fff}
.mini:hover{border-color:rgba(22,107,80,.28);box-shadow:0 2px 8px rgba(0,0,0,.05)}
.mini h4{font-size:13.5px;font-weight:700;margin-bottom:3px;display:flex;align-items:center;gap:7px}
.mini h4 .role{font-size:10.5px;font-weight:600;color:var(--brand-p);background:var(--brand-light-p);padding:2px 8px;border-radius:8px}
.mini dl{font-size:12px;line-height:1.66;margin-top:7px}
.mini dt{color:var(--faint);font-size:11px;font-weight:600;margin-top:6px}
.mini dd{color:var(--ink);word-break:break-word}

/* ── 分镜表 ── */
.shot{border:1px solid var(--line);border-radius:6px;margin-bottom:11px;overflow:hidden;background:#fff;transition:all .18s}
.shot:hover{border-color:rgba(22,107,80,.24)}
.shot-h{display:flex;align-items:center;gap:9px;padding:11px 14px;background:#f6f6f7;border-bottom:1px solid var(--line);flex-wrap:wrap}
.shot-no{width:23px;height:23px;border-radius:5px;background:var(--grad-p);color:#fff;font-size:11.5px;font-weight:800;display:flex;align-items:center;justify-content:center;flex:none}
.shot-h .tag{font-size:11px;font-weight:600;padding:3px 9px;border-radius:8px;background:#fff;border:1px solid var(--line);color:var(--sub)}
.shot-h .tag.beat{background:var(--brand-light-p);border-color:transparent;color:var(--brand-p)}
.shot-h .sp{margin-left:auto}
.shot-b{padding:13px 14px;display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:10px}
.shot-b .w{display:flex;flex-direction:column;gap:5px}
.shot-b .w.full{grid-column:1/-1}
.shot-b label{font-size:11px;font-weight:700;color:var(--faint);letter-spacing:.3px}
.shot-b textarea,.shot-b input{
  border:1px solid var(--line);border-radius:5px;padding:8px 10px;font-size:12.5px;line-height:1.62;
  background:#fff;resize:vertical;width:100%;transition:all .18s;
}
.shot-b textarea:focus,.shot-b input:focus{border-color:var(--brand-p);box-shadow:0 0 0 3px rgba(22,107,80,.08)}
.shot-b textarea.en{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11.5px;background:#f6f6f7;line-height:1.58}
details.pwrap{margin-top:4px}
details.pwrap>summary{font-size:11.5px;font-weight:700;color:var(--brand-p);cursor:pointer;padding:4px 0;list-style:none}
details.pwrap>summary::-webkit-details-marker{display:none}
details.pwrap>summary::before{content:"▸ ";font-size:10px}
details.pwrap[open]>summary::before{content:"▾ "}

/* v2542：两层结构 —— 「段」是出片单位，「拍」是叙事单位，版式要把两者分开。
   一拍一段（老项目、或选了 5 秒档）时不画 .seghead，画面与改前一致。 */
.seghead{display:flex;align-items:center;gap:9px;margin:18px 0 9px;padding:0 2px}
.seghead:first-child{margin-top:0}
.seghead b{font-size:12.5px;font-weight:800;color:var(--brand-p);white-space:nowrap}
.seghead span{font-size:11.5px;font-weight:600;color:var(--faint)}
.seghead::after{content:"";flex:1;height:1px;background:var(--line)}
.segbox{border:1px solid rgba(22,107,80,.22);background:var(--brand-light-p);border-radius:6px;margin-bottom:11px;overflow:hidden}
.segbox-h{display:flex;align-items:center;gap:9px;padding:10px 14px;flex-wrap:wrap;border-bottom:1px solid rgba(22,107,80,.16)}
.segbox-h .tag{font-size:11px;font-weight:700;padding:3px 9px;border-radius:8px;background:#fff;border:1px solid rgba(22,107,80,.22);color:var(--brand-p)}
.segbox>.w{padding:12px 14px 13px;display:flex;flex-direction:column;gap:5px}
.segbox>.w label{font-size:11px;font-weight:700;color:var(--faint);letter-spacing:.3px}
.segbox textarea{
  border:1px solid var(--line);border-radius:5px;padding:8px 10px;font-size:12.5px;line-height:1.62;
  background:#fff;resize:vertical;width:100%;transition:all .18s;
}
.segbox textarea.en{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11.5px;background:#f6f6f7;line-height:1.58}
.segbox textarea:focus{border-color:var(--brand-p);box-shadow:0 0 0 3px rgba(22,107,80,.08)}

/* ── 质检 ── */
.qc-top{display:flex;gap:18px;align-items:center;flex-wrap:wrap}
.qc-total{
  width:104px;height:104px;border-radius:50%;flex:none;display:flex;flex-direction:column;
  align-items:center;justify-content:center;background:var(--brand-light-p);color:var(--brand-p);
}
.qc-total b{font-size:33px;line-height:1;font-weight:800}
.qc-total em{font-size:10.5px;font-style:normal;margin-top:4px;font-weight:600;opacity:.8}
.qc-total.pass{background:#e9f2ec;color:var(--ok)}
.qc-total.revise{background:#fdf4e3;color:#8a6218}
.qc-dims{flex:1;min-width:230px;display:flex;flex-direction:column;gap:7px}
.dim{display:flex;align-items:center;gap:10px;font-size:12.5px}
.dim span{width:74px;color:var(--sub);flex:none}
.dim .track{flex:1;height:7px;border-radius:6px;background:#EFEFF3;overflow:hidden}
.dim .fill{height:100%;border-radius:6px;background:var(--grad-p);transition:width .5s}
.dim b{width:32px;text-align:right;font-weight:700}

/* ── 表演体检（v2610）───────────────────────────────────────────────
   复用质检那套 .dim / .track / .fill 维度条，这里只补容器与状态药丸。
   ★ 刻意**不新造一套进度条样式**：同一页面上两个看起来不一样的同义控件，
     读起来像两个不同的东西（其中一个还会被误当成没生效）。 */
.perfbox{border-top:1px solid var(--line-2)}
.perfbox-h{display:flex;align-items:center;gap:10px;margin-bottom:10px;flex-wrap:wrap}
.perfbox-h .pill{
  font-size:11px;font-weight:700;padding:3px 10px;border-radius:8px;
  background:var(--brand-light-p);border:1px solid transparent;color:var(--brand-p);
}
.perfbox-h .pill.warn{background:var(--warn-soft);border-color:var(--warn-line);color:var(--warn)}
.perfgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:8px 20px}
.issue{border-left:3px solid var(--p2);background:#f6f6f7;border-radius:0 12px 12px 0;padding:11px 14px;margin-bottom:9px}
.issue.p0{border-left-color:var(--p0);background:#FEF5F5}
.issue.p1{border-left-color:var(--p1);background:#FFFAF0}
.issue-h{display:flex;align-items:center;gap:8px;margin-bottom:5px;flex-wrap:wrap}
.issue-h .lv{font-size:10.5px;font-weight:800;padding:2px 8px;border-radius:6px;background:var(--p2);color:#fff}
.issue.p0 .lv{background:var(--p0)}
.issue.p1 .lv{background:var(--p1)}
.issue-h .wh{font-size:12px;font-weight:700}
.issue p{font-size:12.5px;line-height:1.68;color:var(--ink)}
.issue p+p{margin-top:3px}
.issue p.k{color:var(--sub)}
.issue p.k b{color:var(--ink);font-weight:600}

/* ── 图片网格 / 抽卡 ── */
.imgs{display:grid;grid-template-columns:repeat(auto-fill,minmax(168px,1fr));gap:12px}

/* ── 资产卡网格（v2549）──
   角色 / 道具这类**同类资产横向从左到右排列**：一张卡 = 一个资产，卡自己换行。
   原先是「一个资产占一整行、纵向堆叠」—— 三个角色要滚三屏，同类之间既没法
   一眼比对，也看不出到底有几个。auto-fill + minmax(300px)：张数不定
   （1~8 个角色都可能），宽度自适应，窄屏自然降成一列，不需要写断点。
   ⚠ `.assetc .imgs` 是**两个 class**的覆盖规则：通用 `.imgs` 是 168px 底线，
      一张卡里可能横排 2~4 张抽卡候选，照抄 168px 会直接溢出卡片。
      按本项目的铁律 —— 覆盖规则必须比被覆盖的多一个 class（1 → 2）。 */
/* 底线给 240px 而不是 300px：主区宽 = 视口 − 540（左 rail 228 + 右栏 312），
   1440 主流笔电下只有 900px —— 300px 底线只排得下 2 列，3 个角色就要换行，
   「同类横着从左到右一眼看全」这件事就打了折。240px 下 1440 能排 3 列、
   1920 能排 5 列。资产图是 16:9 横版设定稿，240px 宽仍有 ~135px 高，
   「正/侧/背」并排看得清。 */
.asset-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:14px}
.assetc{border:1px solid var(--line);border-radius:6px;padding:11px;background:#fff;min-width:0}
.assetc-h{display:flex;align-items:baseline;gap:7px;margin-bottom:9px;flex-wrap:wrap}
.assetc-h b{font-size:12.5px;font-weight:700;color:var(--ink)}
/* auto-fit（不是 auto-fill）：只出一张图时（绝大多数资产都只抽一张），
   空轨道会被折叠，那张图就**铺满整张卡**；出 2~4 张抽卡候选时才并排。
   auto-fill 会保留空轨，单张图只占 1/2 卡宽、右边空一块，看着像没加载完。 */
.assetc .imgs{grid-template-columns:repeat(auto-fit,minmax(96px,1fr));gap:8px}
.assetc .pickbar{padding-top:8px}
.imgc{position:relative;border:1px solid var(--line);border-radius:6px;overflow:hidden;background:#fff;transition:all .18s}
.imgc.picked{border-color:var(--brand-p);box-shadow:0 0 0 3px rgba(22,107,80,.14)}
.imgc .ph{width:100%;aspect-ratio:9/16;background:#f1f1f3;display:block;object-fit:cover;cursor:zoom-in}
/* 资产图（风格锚 / 三视图 / 道具）后端固定出 16x9 横版设定稿。
   用 contain 而不是 cover：老项目里可能存着竖版资产图，cover 会把正/侧/背裁掉。 */
.imgc.wide .ph{aspect-ratio:16/9;object-fit:contain}
.imgc .cap{padding:8px 10px;font-size:11.5px;color:var(--sub);line-height:1.5;display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.imgc .cap b{color:var(--ink);font-weight:600}
/* v2552：出了图的那一格也要能换（老板报的是失败格，但「我不喜欢这一张」
   更常发生，而整集「重新生成」会把满意的那些一起毁掉）。
   **放在图片上的浮层、hover 才现**：塞进 `.cap` 会让宽 tag 那几格折行 ——
   实测同一网格 37px / 60px 两种卡高。浮层不占布局，卡高恒定。
   隐藏时 `pointer-events:none`，避免「看不见却点得到」。
   `.pickbar` 是普通流式元素，不受这里的 absolute 影响。 */
.imgc .redos{position:absolute;top:7px;right:7px;z-index:3;display:flex;gap:5px;
  opacity:0;transition:opacity .15s;pointer-events:none}
.imgc:hover .redos,.imgc:focus-within .redos{opacity:1;pointer-events:auto}
.imgc .redos button{font-family:inherit;font-size:11px;line-height:1;
  padding:5px 8px;border-radius:7px;border:1px solid var(--line);background:rgba(255,255,255,.94);
  color:var(--sub);cursor:pointer;transition:all .15s;backdrop-filter:blur(3px)}
.imgc .redos button:hover{border-color:var(--brand-p);color:var(--brand-p);
  background:#fff}
.pickbar{display:flex;gap:5px;padding:7px 10px;border-top:1px solid var(--line);flex-wrap:wrap}
.pickbar button{
  font-size:11px;font-weight:700;padding:4px 10px;border-radius:5px;border:1px solid var(--line);
  color:var(--sub);transition:all .16s;
}
.pickbar button.on{background:var(--grad-p);color:#fff;border-color:transparent}
.pickbar button:hover:not(.on){border-color:var(--brand-p);color:var(--brand-p)}
.pickbar .lb{font-size:10.5px;color:var(--faint);align-self:center;margin-right:2px}

/* ── 视频 ── */
.vids{display:grid;grid-template-columns:repeat(auto-fill,minmax(186px,1fr));gap:12px}
.vidc{border:1px solid var(--line);border-radius:6px;overflow:hidden;background:#fff}
.vidc .ph{width:100%;aspect-ratio:9/16;background:#141417;display:block;object-fit:cover}
.vidc.wide .ph{aspect-ratio:16/9}
.vidc .st{padding:8px 10px;font-size:11.5px;display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.vidc .st .dot{width:7px;height:7px;border-radius:50%;background:#D8D8DE;flex:none}
.vidc .st .dot.run{background:var(--brand-p);animation:pulse 1.1s infinite}
.vidc .st .dot.done{background:var(--ok)}
.vidc .st .dot.fail{background:var(--err)}
.skin{width:100%;aspect-ratio:9/16;background:linear-gradient(135deg,#F6F6F8,#ECECF1);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:9px;color:var(--faint);font-size:12px}
.skin.wide{aspect-ratio:16/9}
.spin{width:22px;height:22px;border:2.5px solid rgba(22,107,80,.18);border-top-color:var(--brand-p);border-radius:50%;animation:sp .8s linear infinite}
@keyframes sp{to{transform:rotate(360deg)}}
.pbar{width:66%;height:4px;border-radius:4px;background:rgba(0,0,0,.08);overflow:hidden}
.pbar i{display:block;height:100%;background:var(--grad-p);transition:width .4s}

/* ── 日志 ── */
.logs{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11.5px;line-height:1.8;color:var(--sub);max-height:216px;overflow-y:auto}
.logs div{display:flex;gap:9px}
.logs em{color:var(--faint);font-style:normal;flex:none}

/* ── 底部进度条：v2549 已删除 ──
   原来这里有一条 fixed 的整条流水线进度条（.dr-bar / -in / -txt / -track /
   -fill / -pct）。它只有一个数字，说不出「六步里哪一步做到几成」，跨步骤时
   还会走满一格又跳回个位数。现改为**左侧制作流程每一步自己的血条**：
   .dr-step > .fill（半透明，按进度铺宽）+ .dr-step > .pct（右上角百分比）。
   DOM 与 JS 引用也一并删了 —— 留个 display:none 的空壳只会让人以为它还在。 */

/* ── 抽屉 / 弹层 ── */
.mask{position:fixed;inset:0;background:rgba(20,20,23,.42);z-index:200;display:none;align-items:center;justify-content:center;padding:24px}
.mask.show{display:flex}
.sheet{background:#fff;border-radius:8px;max-width:600px;width:100%;max-height:82vh;display:flex;flex-direction:column;overflow:hidden;box-shadow:0 24px 70px rgba(0,0,0,.22)}
.sheet-h{display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding:14px 17px;border-bottom:1px solid var(--line-2)}
.sheet-h h3{font-size:13px;font-weight:600;flex:1}
.sheet-b{padding:14px 17px;overflow-y:auto}
.sheet .row{display:flex;align-items:center;gap:10px;padding:11px 12px;border-radius:var(--r);
  transition:background .16s;cursor:pointer}
.sheet .row:hover{background:var(--brand-light)}
.sheet .row b{font-size:13px;font-weight:500}
/* 删除：默认是普通灰（不该跟「打开」抢注意力），只有**指上去**才变红 ——
   一个常驻的红按钮会让人以为「这一行有问题」，而那只是「你可以删它」。 */
.sheet .row .del{flex:none;font-size:11px;padding:4px 9px;border-radius:var(--r-sm);
  border:1px solid var(--line-3);background:#fff;color:var(--muted);white-space:nowrap;
  transition:background .16s,border-color .16s,color .16s}
.sheet .row .del:hover{border-color:var(--err);color:var(--err);background:var(--err-soft)}
.sheet .row .meta{font-size:11.5px;color:var(--faint);margin-top:2px}
.sheet .row .go{margin-left:auto;color:var(--faint);font-size:18px}
/* ── 设置抽屉 ──
   为什么是抽屉而不是继续放右侧栏：右侧栏在 <1180px 是 display:none 的，
   设置放那儿小屏就改不了模型；而且它只在「没开项目」时显示模型选择。 */
.mask.aside{align-items:stretch;justify-content:flex-end;padding:0}
.drw{width:min(468px,100vw);background:#fff;display:flex;flex-direction:column;
  box-shadow:-18px 0 60px rgba(0,0,0,.14);animation:drwIn .22s cubic-bezier(.22,1,.36,1)}
@keyframes drwIn{from{transform:translateX(26px);opacity:.5}to{transform:none;opacity:1}}
.drw-h{flex:none;display:flex;align-items:center;gap:8px;padding:16px 20px;border-bottom:1px solid var(--line)}
.drw-h h3{font-size:15px;font-weight:700;white-space:nowrap}
.drw-h .sub{font-size:11.5px;color:var(--faint);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.drw-x{margin-left:auto;flex:none;width:30px;height:30px;border-radius:5px;font-size:13px;color:var(--sub);transition:all .16s}
.drw-x:hover{background:var(--brand-light);color:var(--ink)}
.drw-b{flex:1;overflow-y:auto;padding:0 20px 22px}
.drw-f{flex:none;border-top:1px solid var(--line);background:#f6f6f7;padding:14px 20px calc(14px + env(safe-area-inset-bottom,0px))}
.drw-act{display:flex;gap:10px;margin-top:14px}
.drw-act .btn{flex:1;padding:11px;font-size:13.5px}
.cfg-g{padding:15px 0;border-bottom:1px dashed var(--line)}
.cfg-g:first-child{padding-top:18px}
.cfg-g:last-child{border-bottom:none}
.cfg-t{display:flex;flex-direction:column;gap:3px;margin-bottom:9px}
.cfg-t b{font-size:13px;font-weight:700}
.cfg-t span{font-size:11.5px;color:var(--faint);line-height:1.55}
.cfg-sel{width:100%;padding:10px 12px;border:1px solid var(--line);border-radius:5px;
  background:#fff;font-size:13px;font-weight:600;transition:all .16s}
.cfg-sel:focus{border-color:var(--brand-p);box-shadow:0 0 0 3px rgba(22,107,80,.1)}
.cfg-g .side-note{margin-top:8px}
/* 底栏里的警示：紧贴预估上方，不占太大高度（抽屉总高有限） */
.drw-f .side-warn{margin:0 0 12px;max-height:26vh;overflow-y:auto}

/* ── 设置抽屉 · 卡片版（版式参照站内「偏好设置」） ──
   为什么从「分组标题 + 一堆 select」改成卡片：
     · 每一项都要能挂一句「改了会怎样」，分组标题里塞不下；
     · 题材/规格、模型、抽卡三类性质完全不同，卡片边界就是安全边界；
     · 底栏固定 —— 滚动区再长，预估与主按钮也始终在视野里。 */
.drw2{width:min(524px,100vw)}
.drw2 .drw-h{gap:11px;padding:15px 18px}
.drw-ico{flex:none;width:34px;height:34px;border-radius:5px;background:var(--brand-light-p);color:var(--brand-p);display:flex;align-items:center;justify-content:center}
.drw-ico svg{width:18px;height:18px}
.drw-ht{flex:1;min-width:0;display:flex;flex-direction:column;gap:1px}
.drw-ht h3{font-size:15px;font-weight:700;line-height:1.3;white-space:nowrap}
.drw-ht .sub{font-size:11.5px;color:var(--faint);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.drw2 .drw-x{margin-left:0}
/* 关键：column flex 的子项默认 flex-shrink:1。抽屉滚动区高度受限时，
   卡片会被**压扁**去迁就容器（于是 scrollHeight == clientHeight，根本不滚动），
   而卡片自带 overflow:hidden —— 结果是内容被静默裁掉，用户看不到「单次出片秒数」
   和「画幅」两组控件还以为它们不存在。必须 flex:none 让它们保持自然高度。 */
.drw2 .drw-b{padding:16px 18px 18px;display:flex;flex-direction:column;gap:14px}
.drw2 .drw-b>*{flex:none}

.cfg-card{border:1px solid var(--line);border-radius:6px;background:#fff;overflow:hidden}
.cfg-card-h{display:flex;align-items:center;gap:10px;padding:13px 14px;background:#f9f9fa;border-bottom:1px solid var(--line)}
.cfg-ico{flex:none;width:28px;height:28px;border-radius:5px;background:var(--brand-light-p);color:var(--brand-p);display:flex;align-items:center;justify-content:center}
.cfg-ico svg{width:16px;height:16px}
.cfg-ht{flex:1;min-width:0;display:flex;flex-direction:column;gap:1px}
.cfg-ht b{font-size:13px;font-weight:700}
.cfg-ht em{font-size:11px;color:var(--faint);font-style:normal;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cfg-rule{flex:none;font-size:11.5px;font-weight:600;color:var(--brand-p);padding:5px 10px;border-radius:5px;background:var(--brand-light-p);transition:all .16s}
.cfg-rule:hover{background:#eaf3ee}
.cfg-rule.on{background:var(--brand-p);color:#fff}
.cfg-card-b{padding:14px}
.cfg-rulebox{padding:12px 14px 14px;border-top:1px dashed var(--line);background:#f6f6f7;font-size:11.5px;color:var(--sub);line-height:1.75}
.cfg-rulebox b{color:var(--ink)}

.cfg-lab{display:flex;align-items:baseline;gap:8px;margin-bottom:8px}
.cfg-lab span{font-size:12.5px;font-weight:700}
.cfg-lab em{font-size:11px;color:var(--faint);font-style:normal}
.cfg-inline{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.cfg-inline>.cfg-chips{flex:1;min-width:0}
.cfg-in{width:100%;margin-top:10px;padding:10px 12px;border:1px solid var(--line);border-radius:5px;background:#fff;font-size:13px;transition:all .16s}
.cfg-in:focus{border-color:var(--brand-p);box-shadow:0 0 0 3px rgba(22,107,80,.1)}
.cfg-in:disabled{background:var(--brand-light);color:var(--faint);cursor:not-allowed}
.cfg-mrow{display:flex;align-items:center;gap:8px;margin:12px 0 6px}
.cfg-mrow:first-child{margin-top:0}
.cfg-mrow span{font-size:12px;font-weight:600;color:var(--sub)}
.cfg-list{margin:10px 0 0;padding-left:17px;font-size:11.5px;color:var(--sub);line-height:1.8}
.cfg-list li{margin-bottom:4px}
.cfg-list li:last-child{margin-bottom:0}
.cfg-list b{color:var(--ink)}

.cfg-chips{display:flex;gap:7px;flex-wrap:wrap}
.cfg-chips button{padding:7px 12px;border-radius:5px;border:1px solid var(--line);background:#fff;font-size:12px;font-weight:600;color:var(--sub);transition:all .16s}
.cfg-chips button:hover:not(:disabled){border-color:rgba(22,107,80,.4);color:var(--brand-p)}
.cfg-chips button.on{background:var(--brand-light-p);border-color:var(--brand-p);color:var(--brand-p)}
.cfg-chips button:disabled{cursor:not-allowed;opacity:.55;background:#f6f6f7;border-style:dashed}
.cfg-chips button.on:disabled{opacity:1}

.cfg-step{flex:none;display:flex;align-items:center;border:1px solid var(--line);border-radius:5px;overflow:hidden;background:#fff}
.cfg-step button{width:34px;height:36px;font-size:15px;font-weight:600;color:var(--sub);transition:all .16s}
.cfg-step button:hover:not(:disabled){background:var(--brand-light-p);color:var(--brand-p)}
.cfg-step button:disabled{color:#D2D2D7;cursor:not-allowed}
.cfg-step>span{min-width:76px;text-align:center;font-size:13px;border-left:1px solid var(--line);border-right:1px solid var(--line);padding:8px 6px}
.cfg-step>span b{font-weight:700}
.cfg-step>span em{font-size:10.5px;color:var(--faint);font-style:normal;margin-left:2px}

/* 分段方案条：浅紫底 + 一行大字。数字全部来自后端，前端不复算。 */
.cfg-spec{margin-top:12px;padding:11px 13px;border-radius:6px;background:var(--brand-light-p);border:1px solid rgba(22,107,80,.16)}
.cfg-specline{font-size:12px;color:var(--green);line-height:1.7}
.cfg-specline b{color:var(--brand-p);font-weight:800}

.cfg-sw{display:flex;align-items:center;gap:12px}
.cfg-swt{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.cfg-swt b{font-size:12.5px;font-weight:600}
.cfg-swt em{font-size:11px;color:var(--faint);font-style:normal;line-height:1.5}
.sw{flex:none;width:44px;height:25px;border-radius:6px;background:#E4E4E9;transition:background .2s}
.sw i{display:block;width:19px;height:19px;border-radius:50%;background:#fff;margin:3px;box-shadow:0 1px 3px rgba(0,0,0,.18);transition:transform .2s}
.sw.on{background:var(--grad-p)}
.sw.on i{transform:translateX(19px)}
.sw:disabled{cursor:not-allowed;opacity:.55}

/* ── 整集合成状态条（出片页顶部） ── */
.stitch-box{display:flex;align-items:center;gap:11px;padding:12px 14px;border-radius:6px;border:1px solid var(--line);background:#f9f9fa;margin-bottom:12px}
.stitch-box b{font-size:13px;font-weight:700;display:inline-flex;align-items:center;gap:7px}
.stitch-box .hint{margin-top:3px}
.stitch-box.ok{border-color:rgba(40,116,87,.28);background:#eaf3ee}
.stitch-box.fail{border-color:rgba(164,57,47,.26);background:#FFF7F7}

/* ── 半托管「确认进入下一步」条 ──
   半托管的心智是「一步一确认」：每一步跑完，先看成果，再决定要不要往下走
   （下一步要花星光）。所以它要比普通按钮显眼：绿底 = 上一步已妥，
   右侧那颗主色按钮是唯一的下一步出口。
   全托管不渲染它 —— 一条道跑到底，问「是否继续」没有意义。 */
.nextbar{
  display:flex;align-items:center;gap:12px;
  padding:12px 15px;margin-bottom:12px;
  border:1px solid rgba(40,116,87,.3);border-radius:6px;background:#eaf3ee;
  animation:nextIn .22s cubic-bezier(.22,1,.36,1);
}
@keyframes nextIn{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}
.nextbar .nb-ico{
  flex:none;width:30px;height:30px;border-radius:5px;
  background:#e9f2ec;color:var(--ok);font-weight:700;font-size:15px;
  display:flex;align-items:center;justify-content:center;
}
.nextbar .nb-txt{flex:1;min-width:0}
.nextbar .nb-txt b{display:block;font-size:13px;font-weight:700}
.nextbar .nb-txt .hint{margin-top:2px}
.nextbar .btn{flex:none}
.nextbar.done{border-color:var(--line);background:#f9f9fa;animation:none}
.nextbar.done .nb-ico{background:#f1f1f3;color:var(--faint)}

/* ── 「补充要求」对话框 ──
   每次确认都先弹它：用户常常有一句「我还想要…」憋着没地方说，
   不说出来就会在成片出来之后才发现不对，那时重跑已经花了星光。 */
.askn{align-items:center}
.askn-box{width:min(524px,100%);background:#fff;border-radius:8px;overflow:hidden;box-shadow:0 24px 70px rgba(0,0,0,.22);animation:asknIn .2s cubic-bezier(.22,1,.36,1)}
@keyframes asknIn{from{transform:translateY(12px) scale(.98);opacity:.6}to{transform:none;opacity:1}}
.askn-h{display:flex;align-items:center;gap:11px;padding:15px 18px;border-bottom:1px solid var(--line)}
.askn-ico{flex:none;width:32px;height:32px;border-radius:5px;background:var(--brand-light-p);color:var(--brand-p);display:flex;align-items:center;justify-content:center;font-size:15px}
.askn-h b{display:block;font-size:14px;font-weight:700}
.askn-h em{font-size:11.5px;color:var(--faint);font-style:normal}
.askn-b{padding:14px 18px}
.askn-ta{width:100%;resize:vertical;min-height:88px;padding:11px 13px;border:1px solid var(--line);border-radius:6px;background:#f6f6f7;font-size:13px;line-height:1.7;font-family:inherit;transition:all .16s}
.askn-ta:focus{border-color:var(--brand-p);background:#fff;box-shadow:0 0 0 3px rgba(22,107,80,.1)}
.askn-tips{display:flex;gap:7px;flex-wrap:wrap;margin-top:10px}
.askn-tips button{padding:6px 11px;border-radius:5px;background:var(--brand-light);font-size:11.5px;color:var(--sub);transition:all .16s}
.askn-tips button:hover{background:var(--brand-light-p);color:var(--brand-p)}
.askn-hint{font-size:11px;color:var(--faint);line-height:1.7;margin-top:10px}
.askn-f{display:flex;gap:10px;padding:14px 18px calc(14px + env(safe-area-inset-bottom,0px));border-top:1px solid var(--line);background:#f6f6f7}
.askn-f .btn{flex:1;padding:11px;font-size:13.5px}

@media(max-width:560px){
  .drw2{width:100vw}
  .cfg-step>span{min-width:62px}
  .cfg-inline{gap:8px}
  .askn{padding:16px}
  .askn-box{width:100%}
}

.lbbox{width:100%;aspect-ratio:9/16;max-height:66vh;object-fit:contain;background:#141417;border-radius:6px}

#toast{
  position:fixed;left:50%;bottom:76px;transform:translate(-50%,14px);background:#1C1C1E;color:#fff;
  font-size:13px;padding:11px 20px;border-radius:6px;opacity:0;pointer-events:none;
  transition:all .25s;z-index:300;max-width:88vw;text-align:center;line-height:1.55;
}
#toast.show{opacity:1;transform:translate(-50%,0)}

/* ══════════ v2540：立项页输入条（composer） ══════════
   版式照参考图（即梦的 composer）：输入框在上，一行参数在下；
   参数只显示当前值、档位收进弹出面板；右端是计数 + 圆形主按钮。
   配色也照参考图 —— **浅灰胶囊**（实测参考图取色 #F1F2F3~#F4F4F4，
   这里用站内已有的 --brand-light #f1f1f3 同一个色），深色字；
   整行没有深色容器，就落在白色卡片上。

   为什么 .cm-pill.ghost（直出那枚）没有底色：参考图里 `⏱ 5s` 就是无底色的纯文字，
   只有第一枚「比例·画质·数量」有浅灰底。主次靠底色区分，而不是靠边框。
   悬浮/展开时才给浅灰底，保证仍然看得出可点。 */
.cm-box{position:relative}
.cm-src-wrap{display:flex;margin-bottom:10px}
.cm-ta{min-height:118px;background:#f6f6f7}
.cm-ta:focus{background:#fff}
.cm-bar{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-top:10px}
.cm-grp{position:relative;display:flex;min-width:0}
.cm-pill{display:flex;align-items:center;gap:7px;height:34px;padding:0 11px;min-width:0;
  border:none;border-radius:5px;background:transparent;color:var(--ink);
  font-size:12.5px;font-weight:600;font-family:inherit;letter-spacing:.2px;
  cursor:pointer;transition:background .14s,box-shadow .14s}
.cm-pill>span{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:left}
.cm-pill.main{background:var(--brand-light)}
.cm-pill.main:hover,.cm-pill.on{background:rgba(28,28,30,.07)}
.cm-pill.on{box-shadow:inset 0 0 0 1px rgba(28,28,30,.16)}
.cm-pill.ghost{color:var(--sub)}
.cm-pill.ghost:hover,.cm-pill.ghost.on{background:var(--brand-light);color:var(--ink)}
.cm-caret{flex:none;width:12px;height:12px;opacity:.5;transition:transform .16s,opacity .16s}
.cm-pill.on .cm-caret{transform:rotate(180deg);opacity:.85}
/* 浮层 = fixed + JS 定位（placeCmPop）。**不能用 absolute 挂在胶囊上**：
   立项页的 composer 在 .card 里，而 .card{overflow:hidden} 与 #drMain{overflow:auto}
   会把绝对定位的浮层整块裁掉（实测面板 409px 高、向上展开后 bbox.y=-96，
   只剩十几像素漏在卡内）—— 面板看着打开了，档位一个都点不到。
   fixed 脱离裁剪链，方向与左右边界交给 JS。 */
.cm-pop{position:fixed;left:0;top:0;z-index:120;width:268px;
  max-width:calc(100vw - 32px);max-height:min(70vh,440px);overflow-y:auto;
  overscroll-behavior:contain;padding:13px 13px 2px;border-radius:6px;background:#fff;
  border:1px solid var(--line);box-shadow:0 18px 50px rgba(0,0,0,.14);display:none}
.cm-pop.open{display:block;animation:fadeIn .16s ease}
@keyframes fadeIn{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}
.cm-sec{margin-bottom:13px}
.cm-sec.last{margin-bottom:11px}
.cm-sec-t{font-size:11.5px;color:var(--faint);font-weight:600;margin-bottom:7px;letter-spacing:.2px}
.cm-segs{display:flex;flex-wrap:wrap;gap:6px}
.cm-seg{flex:1 1 auto;min-width:56px;display:flex;align-items:center;justify-content:center;
  gap:7px;height:33px;padding:0 8px;border-radius:5px;background:#fff;
  border:1px solid var(--line);color:var(--ink);font-size:12.5px;font-weight:500;
  cursor:pointer;white-space:nowrap;transition:all .14s}
.cm-seg:hover{border-color:rgba(28,28,30,.45)}
/* 选中态用站内**黑白**语言：--brand-light 浅灰底 + 近黑描边。
   不用品牌紫 —— 变量表写着「品牌紫仅用于 logo / 首页 / 生成按钮」。
   描边恒为 1px（与未选中同宽），因此选中不会引起任何布局位移。 */
.cm-seg.active{background:var(--brand-light);border-color:var(--ink);font-weight:700}
/* 模型不支持的档位（v2541-H）。必须真的不可点：以前点了会被就近取档，
   用户以为选了 5 秒、实际出 15 秒，而界面还理直气壮地显示 5 秒。 */
.cm-seg.off{background:#f6f6f7;color:var(--faint);border-style:dashed;cursor:not-allowed}
.cm-seg.off:hover{border-color:var(--line)}
.cm-tip{font-size:11px;color:var(--faint);line-height:1.6;margin-top:7px}
.cm-segs.cm-ratio .cm-seg{flex:1 1 0;min-width:0}
.cm-ratio-ico{flex:none;width:20px;height:20px;display:flex;align-items:center;justify-content:center;color:var(--faint)}
.cm-ratio-ico i{display:block;width:17px;height:11px;border:1.6px solid currentColor;border-radius:3px}
.cm-seg.active .cm-ratio-ico{color:var(--brand)}
.cm-seg[data-v="9:16"] .cm-ratio-ico i{width:11px;height:18px}
.cm-seg[data-v="16:9"] .cm-ratio-ico i{width:18px;height:11px}
.cm-input{width:100%;height:34px;padding:0 11px;border:1px solid var(--line);border-radius:5px;
  font-size:12.5px;font-family:inherit;background:#f6f6f7;transition:all .16s}
.cm-input:focus{border-color:var(--brand-p);background:#fff;box-shadow:0 0 0 3px rgba(22,107,80,.1)}
/* 集数自定义（v2541-A）：与档位同处一段，比再弹一层浮层更短更准 */
.cm-cust{display:flex;align-items:center;gap:7px;margin-top:7px}
.cm-cust>span{flex:none;font-size:11.5px;color:var(--faint)}
.cm-cust .cm-input{width:78px;flex:none;text-align:center;padding:0 6px;font-weight:600}
.cm-num.on{border-color:var(--ink);background:var(--brand-light)}
.cm-num{-moz-appearance:textfield}
.cm-num::-webkit-outer-spin-button,.cm-num::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
/* @：参考图里就是一枚**无底色**的纯图标，这里照做 */
.cm-at{flex:none;width:30px;height:34px;border:none;background:transparent;color:var(--sub);
  font-size:15px;font-weight:700;border-radius:5px;cursor:pointer;transition:all .15s;
  font-family:ui-monospace,SFMono-Regular,monospace;line-height:1}
.cm-at:hover{background:var(--brand-light);color:var(--ink)}
.cm-at.active{background:var(--brand);color:#fff}
.cm-gap{flex:1 1 auto;min-width:0}
.cm-refs{display:flex;align-items:center;gap:4px;font-size:12px;color:var(--faint);
  font-variant-numeric:tabular-nums;padding:0 2px;white-space:nowrap}
.cm-refs svg{width:14px;height:14px}
.cm-refs.on{color:var(--ink);font-weight:600}
.cm-cost{font-size:12.5px;color:var(--sub);white-space:nowrap;font-variant-numeric:tabular-nums}
.cm-cost.short{color:var(--err);font-weight:600}
/* 圆形主按钮：参考图右端就是一枚圆钮。品牌紫是站内规范允许的
   「生成按钮」用色，立项是这个页面唯一的主操作，用在这里正合适。 */
.cm-send{flex:none;width:38px;height:38px;border-radius:50%;border:none;cursor:pointer;
  background:var(--grad-p);color:#fff;font-size:15px;line-height:1;
  display:flex;align-items:center;justify-content:center;
  box-shadow:0 2px 6px rgba(22,107,80,.22);transition:all .16s}
.cm-send:hover{transform:translateY(-1px);box-shadow:0 2px 8px rgba(22,107,80,.26)}
.cm-send:disabled,.cm-send.busy{opacity:.55;cursor:progress;transform:none;box-shadow:none}
.cm-sub{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:12px}
.cm-count{margin-left:auto}
/* 四个参数的原生控件：留在 DOM 里给 mk() 用，视觉上收走。
   不用 display:none —— 某些浏览器上 display:none 的控件取值仍正常，
   但 clip 这套更稳，且不会被读屏软件当成「凭空出现的输入框」。 */
.cm-native{position:absolute;width:1px;height:1px;overflow:hidden;
  clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap}
/* @ 弹层 */
.cm-pop.at{width:296px;padding:12px 12px 2px}
.at-sec{margin-bottom:12px}
.at-h{display:flex;align-items:center;gap:8px;font-size:11.5px;color:var(--faint);
  font-weight:600;letter-spacing:.2px;margin-bottom:8px}
.at-up{margin-left:auto;font-size:11.5px;font-weight:700;color:var(--brand-p);
  padding:4px 9px;border-radius:5px;background:var(--brand-light-p);transition:all .15s}
.at-up:hover{box-shadow:0 0 0 1px rgba(22,107,80,.3)}
.at-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:7px}
.at-item{position:relative;border:1px solid var(--line);border-radius:5px;overflow:hidden;
  background:#f6f6f7;cursor:pointer;transition:all .15s}
.at-item:hover{border-color:var(--brand-p);box-shadow:0 2px 6px rgba(0,0,0,.06)}
.at-item img{display:block;width:100%;aspect-ratio:1/1;object-fit:cover}
.at-tag{display:block;font-size:10px;color:var(--sub);text-align:center;padding:5px 3px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;background:#fff}
.at-x{position:absolute;top:4px;right:4px;width:18px;height:18px;border-radius:50%;
  background:rgba(20,20,23,.62);color:#fff;font-size:10px;line-height:1;
  display:flex;align-items:center;justify-content:center;transition:background .15s}
.at-x:hover{background:var(--err)}
.at-empty{font-size:11.5px;color:var(--faint);line-height:1.65;margin:0}
.at-empty b{color:var(--sub)}
.at-foot{font-size:10.5px;color:var(--faint);line-height:1.6;margin:0 0 10px;
  padding-top:9px;border-top:1px dashed var(--line)}
@media(max-width:860px){
  .cm-bar{gap:5px}
  .cm-pill,.cm-at{height:32px}
  .cm-send{width:34px;height:34px}
  .cm-pop{width:min(268px,calc(100vw - 44px))}
  .cm-pop.at{width:min(296px,calc(100vw - 44px))}
}

/* ── 自适应：与电商 Studio 同一套断点阶梯（v2578）──
   每一档只做一件事：把**已经装不下**的那一栏收掉或换位。
   顺序是刻意的 —— 先保工作区（它是干活的地方），再保步骤条，
   最后才轮到右栏（它是参考资料，窄屏可以落到底下去）。 */
@media(min-width:1600px){
  .dr-page{padding:22px 40px 20px;max-width:1520px}
  .dr-studio{grid-template-columns:minmax(0,1fr) 336px;gap:28px}
}
@media(max-width:1240px){
  .dr-studio{grid-template-columns:minmax(0,1fr) 276px;gap:16px}
  .dr-page{padding:16px 20px 14px}
  .dr-top{padding:0 20px}
}
@media(max-width:1060px){
  :root{--railw:170px}
  .dr-rail{padding:22px 10px 16px}
  .dr-steps{gap:18px}
}
@media(max-width:920px){
  :root{--railw:62px}
  .dr-rail{padding:20px 9px}
  .brand{padding:0 5px 20px}
  .brandtext,.dr-projcard,.rail-label,.dr-nav span,.dr-railfoot a span{display:none}
  .dr-nav{justify-content:center;padding:11px}
  .dr-railfoot{justify-content:center;padding:13px 0 0}
  .dr-title{font-size:21px}
}
@media(max-width:820px){
  .dr-studio{grid-template-columns:1fr}
  .dr-insp{margin-top:6px}
  .dr-steps{gap:20px}
  .dr-step em{display:none}
  .dr-mode button em{display:none}
}
@media(max-width:700px){
  .dr-app{display:block}
  .dr-rail{height:54px;width:100%;position:sticky;top:0;z-index:40;flex-direction:row;
    align-items:center;gap:2px;padding:6px 10px;border-right:0;
    border-bottom:1px solid var(--line);overflow-x:auto}
  .brand{padding:0 8px 0 0}
  .dr-rail .spacer,.dr-railfoot,.dr-projcard{display:none}
  .dr-nav{width:38px;margin:0;padding:10px}
  .dr-top{height:52px;padding:0 14px;position:static}
  .dr-crumb{font-size:10px;gap:6px}
  .dr-page{padding:18px 14px 0}
  .dr-metahint{display:none}   /* 窄屏这行说明会把标题区撑成四行 */
  .dr-thead{gap:10px;flex-wrap:wrap}
  .dr-title{font-size:19px;max-width:100%}
  .dr-head-act{justify-content:flex-start}
  .card-b{padding:14px 15px}
}


/* ── 窄屏 / 矮屏解锁（v2578）──
   ★ 上面那套「一屏锁死」只在**装得下**的窗口上成立。窗口矮到 560px 时，
     锁死等于把正文裁掉 —— 而 `overflow:hidden` 裁内容是**静默**的，
     用户连滚动条都看不到，只会以为「内容就这么点」。
     所以这一档必须把 overflow 放回 auto、把整条高度链解开。
     ⚠ 这一档要在**所有**定高规则之后（CSS 后写的赢），别往上面挪。 */
@media(max-width:980px),(max-height:560px){
  html,body{overflow:auto}
  body{display:block;height:auto;min-height:100%}
  .dr-app{display:block;height:auto;min-height:100vh;overflow:visible}
  .dr-col{height:auto;min-height:0;overflow:visible}
  .dr-page{display:block;padding-bottom:26px}
  .dr-studio{margin-top:2px}
  .dr-main{overflow:visible;padding-right:0}
  .dr-insp{height:auto;overflow:visible}
  .dr-insp-b{overflow:visible}
}

/* ══════════ 客服（与站内其他页面一致） ══════════ */
.kefu-fab{position:fixed;right:22px;bottom:22px;width:52px;height:52px;border-radius:26px;background:var(--grad-p);color:#fff;display:flex;align-items:center;justify-content:center;box-shadow:0 4px 14px rgba(22,107,80,.26);z-index:90;transition:all .2s}
.kefu-fab:hover{transform:translateY(-2px) scale(1.04)}
.kefu-fab .dot{position:absolute;top:11px;right:11px;width:8px;height:8px;border-radius:50%;background:#bdd9cb;border:2px solid #fff}
.kefu-fab-tip{position:absolute;right:62px;top:50%;transform:translateY(-50%);background:#1C1C1E;color:#fff;font-size:12px;padding:7px 12px;border-radius:9px;white-space:nowrap;opacity:0;pointer-events:none;transition:all .2s}
.kefu-fab:hover .kefu-fab-tip{opacity:1;right:66px}
.kefu-mask{position:fixed;inset:0;background:rgba(20,20,23,.42);z-index:200;display:none;align-items:center;justify-content:center;padding:24px}
.kefu-mask.show{display:flex}
.kefu-modal{background:#fff;border-radius:8px;padding:26px;max-width:340px;width:100%;text-align:center;box-shadow:0 24px 70px rgba(0,0,0,.22)}
.kefu-modal .ico{width:56px;height:56px;border-radius:8px;background:var(--brand-light-p);display:flex;align-items:center;justify-content:center;margin:0 auto 14px}
.kefu-modal h3{font-size:16px;font-weight:700;margin-bottom:14px}
.kefu-qr{width:160px;height:160px;margin:0 auto;border-radius:6px;background:var(--brand-light);display:flex;align-items:center;justify-content:center;overflow:hidden}
.kefu-meta{display:flex;align-items:center;justify-content:center;gap:8px;margin-top:14px;font-size:13px;color:var(--sub)}
.kefu-meta b{color:var(--ink)}
.kefu-btn{font-size:12px;padding:4px 12px;border-radius:5px;background:var(--brand-light-p);color:var(--brand-p);font-weight:600}
.kefu-tip-line{font-size:11.5px;color:var(--faint);margin-top:12px;line-height:1.6}
.kefu-ok{margin-top:16px;width:100%;padding:11px;border-radius:6px;background:var(--grad-p);color:#fff;font-size:13.5px;font-weight:600}

/* ══ v2551：把「正在跑」做成一等状态 ══════════════════════════════════════
 *
 * 事故症状：立项 / 剧本 / 质检走的是**同步接口**（请求本身跑 60~120 秒），
 * 而在那段时间里页面上一行「正在…」都没有 —— 按钮还写着「开始立项」、
 * 卡头徽章写着「未开始」或「已完成」。用户的体感是「我点了，它没反应」。
 *
 * 这里只补视觉：文案与状态都由 drama.js 的 runningHere() / stepBtn() 给。
 * 新增的选择器全是**新 class**（.btn.busy / .skin-miss / .failbox / .donow），
 * 不覆盖既有规则 —— 覆盖式改动在这套样式里是查不出来的（CSS 不报错、
 * id 全在、字符数还可能恰好相同）。
 */
.spin-xs{width:11px;height:11px;border-width:2px;flex:none}
/* 跑起来的按钮：呼吸感，让人知道「它收到了」。禁用态是 .btn[disabled] 的透明度，
   这里不再叠加，避免和别处的禁用样式打架。 */
.btn.busy{animation:busebreathe 1.5s ease-in-out infinite;display:inline-flex;
  align-items:center;gap:6px}
@keyframes busebreathe{0%,100%{opacity:.62}50%{opacity:1}}

/* 分镜图「这一格没出来」的卡片。原来是和「未生成」共用一块灰皮，
   两者在视觉上分不开，用户也不知道该点哪里。 */
.skin.skin-miss{background:#FFFBF5;border:1px dashed #F3D6B0;padding:12px 10px;
  justify-content:flex-start;gap:7px;aspect-ratio:auto;min-height:132px}
.skin-miss .miss-tag{font-size:12.5px;font-weight:700;color:var(--ink)}
.skin-miss .miss-why{font-size:11.5px;color:#8a6218;font-weight:600}
.skin-miss .miss-err{font-size:11px;line-height:1.5;color:var(--sub);
  max-height:42px;overflow:hidden;text-align:center}
.skin-miss .redo{display:flex;flex-direction:column;gap:5px;width:100%;margin-top:2px}
.skin-miss .redo .btn{width:100%;justify-content:center}

/* 失败清单（资产 / 分镜图共用）。失败项必须**指名**列出来 ——
   只躺在数据里不显示，用户的体感是「一半东西没了，还不知道为什么」。 */
.failbox{background:#FFF8F5;border:1px solid #FBDCCB;border-radius:6px;padding:13px 15px}
.failbox>b{font-size:12.5px;color:#8a6218;display:block;margin-bottom:7px}
.failbox ul{margin:0 0 8px;padding-left:17px}
.failbox li{font-size:12px;line-height:1.75;color:var(--ink)}
.failbox li .who{font-weight:600}
.failbox li .why{color:var(--sub);margin-left:5px}
.failbox .why{font-size:11.5px;line-height:1.7;color:var(--sub);margin:0 0 6px}
.failbox .hint{font-size:11.5px;color:var(--faint);line-height:1.7;margin:0}
/* v2555：`.warnbox` = 资产换过、分镜图还是旧的（**提醒**，不是失败）。
   ⚠ 写成 `.failbox.warnbox`（两个 class）而不是单写 `.warnbox`：`.failbox` 那组
     规则是 `.failbox > b` / `.failbox .why` 这种两段式（0,1,1），单个 `.warnbox`
     只有 0,1,0 —— 压不住它们，颜色会被静默盖回橙红。本项目第 N 次栽在这个
     「少一个 class 就被覆盖」上，这里直接一次写对。 */
.failbox.warnbox{background:var(--brand-light-p);border-color:rgba(22,107,80,.18)}
.failbox.warnbox>b{color:var(--brand-p)}
.failbox.warnbox .hint{color:var(--green)}
.failbox.warnbox .btn{margin-top:10px}

/* 「已经够出片了」的出口条。缺的若是中间拍，就不该把人堵在分镜图页。 */
.donow{background:var(--brand-light-p);border:1px solid var(--green-line-2);border-radius:6px;
  padding:13px 15px;display:flex;align-items:center;gap:14px}
.donow>b{font-size:12.5px;color:var(--brand-p);display:block;margin-bottom:4px}
.donow .hint{font-size:11.5px;color:var(--sub);line-height:1.65;margin:0}
.donow .btn{flex:none}
