/* ============ 设计令牌：深空科幻主题 ============ */
:root {
  --primary: #6C8CFF;
  --primary-hover: #5B7BFF;
  --primary-light: rgba(108, 140, 255, 0.16);
  --accent: #22D3EE;
  --accent-2: #A78BFA;
  --success: #34D399;
  --success-light: rgba(52, 211, 153, 0.16);
  --warning: #FBBF24;
  --warning-light: rgba(251, 191, 36, 0.16);
  --danger: #F87171;
  --danger-light: rgba(248, 113, 113, 0.16);
  --info: #60A5FA;
  --info-light: rgba(96, 165, 250, 0.16);
  --bg: #0A0F1E;
  --card: #0F1629;
  --card-2: #131B30;
  --card-2-hover: #182238;
  --text: #E5EDF8;
  --text-1: #E5EDF8;
  --text-2: #93A3BC;
  --text-3: #5C6C8C;
  --text-muted: #5C6C8C;
  --border: #1E2A44;
  --border-light: #2C3D63;
  --bg-hover: rgba(108, 140, 255, 0.1);
  --shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
  --shadow-lg: 0 10px 40px rgba(0, 0, 0, 0.55);
  --glow: 0 0 16px rgba(108, 140, 255, 0.28);
  --radius: 10px;
  --radius-sm: 6px;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

html, body { height: 100%; overflow: hidden; }
body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
    "Microsoft YaHei", sans-serif;
  background:
    radial-gradient(1100px 520px at 85% -10%, rgba(108, 140, 255, 0.13), transparent 60%),
    radial-gradient(900px 460px at -10% 0%, rgba(167, 139, 250, 0.09), transparent 55%),
    radial-gradient(700px 380px at 55% 120%, rgba(34, 211, 238, 0.07), transparent 55%),
    var(--bg);
  background-attachment: fixed;
  color: var(--text);
  font-size: 14px;
  line-height: 1.6;
}

.hidden { display: none !important; }

/* ============ 应用骨架：固定视口高度，顶栏 + 导航固定，仅主内容区内部滚动 ============ */
#app {
  display: grid;
  grid-template-rows: auto 1fr;
  grid-template-columns: 120px 1fr;
  height: 100vh;
  overflow: hidden;
}
.topbar { grid-column: 1 / -1; grid-row: 1; flex-shrink: 0; }
.navbar { grid-column: 1; grid-row: 2; flex-shrink: 0; }

/* ============ 顶部栏 ============ */
.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 56px;
  padding: 0 20px;
  background: rgba(15, 22, 41, 0.72);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--border);
}
.brand { display: flex; align-items: center; gap: 8px; }
.brand-logo {
  font-size: 22px;
  filter: drop-shadow(0 0 8px rgba(108, 140, 255, 0.55));
}
.brand-name {
  font-size: 17px; font-weight: 700;
  background: linear-gradient(90deg, #6C8CFF, #A78BFA);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}
.brand-tag {
  font-size: 12px; color: var(--text-3);
  margin-left: 6px; padding-left: 10px;
  border-left: 1px solid var(--border);
}
.topbar-right { display: flex; align-items: center; gap: 16px; }
.sys-status {
  display: flex; align-items: center; gap: 6px;
  font-size: 12px; color: var(--text-2);
  padding: 4px 10px; border-radius: 999px;
  background: var(--bg);
}
.sys-status .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--text-3); }
.sys-status.ok .dot { background: var(--success); }
.sys-status.err .dot { background: var(--danger); }

/* ============ 导航栏 ============ */
.navbar {
  overflow-y: auto;
  display: flex; flex-direction: column; gap: 2px;
  background: rgba(15, 22, 41, 0.6);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  padding: 12px 10px;
  border-right: 1px solid var(--border);
  border-bottom: none;
}
.nav-btn {
  border: none; background: transparent;
  padding: 10px 14px; font-size: 14px; color: var(--text-2);
  cursor: pointer; text-align: left;
  border-radius: var(--radius-sm);
  border-left: 3px solid transparent;
  position: relative;
  transition: color 0.2s, background 0.2s;
}
.nav-btn:hover { color: var(--text); background: var(--primary-light); }
.nav-btn.active {
  color: #fff; font-weight: 600;
  background: linear-gradient(90deg, rgba(108, 140, 255, 0.22), rgba(108, 140, 255, 0.05));
  border-left-color: var(--accent);
  box-shadow: inset 0 0 18px rgba(108, 140, 255, 0.1);
}
.nav-btn.ghost { border-left: 3px solid transparent; }
.nav-spacer { flex: 1; }

/* ============ 主内容区 ============ */
#main {
  grid-column: 2; grid-row: 2;
  padding: 0;
  max-width: none;
  width: 100%;
  min-width: 0;
  min-height: 0;
  overflow-y: auto;
}
/* 页面左右留白固定 30px：不设 max-width 居中（否则窗口一宽两侧留白就变大，用户要求"固定不随窗口/缩放变化"） */
#main .page { max-width: none; margin: 0; padding: 30px; }
#main #page-storyboards { padding-top: 0; }
.page { display: none; }
.page.active { display: block; animation: fadeIn 0.18s ease; }
@keyframes fadeIn { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }

/* ============ 页面头部 ============ */
.page-head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 18px; gap: 12px; flex-wrap: wrap;
}
.page-title { font-size: 20px; font-weight: 700; }
.page-sub { font-size: 13px; color: var(--text-3); margin-top: 2px; }
.page-actions { display: flex; gap: 8px; align-items: center; }
.crumb {
  font-size: 12px; color: var(--text-3);
  margin-left: 10px; padding-left: 10px;
  border-left: 1px solid var(--border);
}
.crumb b { color: var(--primary); font-weight: 600; }

/* ============ 按钮 ============ */
.btn {
  border: 1px solid var(--border); background: var(--card-2); color: var(--text);
  padding: 7px 14px; font-size: 13px; border-radius: var(--radius-sm);
  cursor: pointer; transition: all 0.15s;
  display: inline-flex; align-items: center; gap: 5px;
}
.btn:hover { border-color: var(--primary); color: var(--primary); }
.btn.primary {
  background: linear-gradient(135deg, #6C8CFF, #8B7CF6);
  border: none; color: #fff;
  box-shadow: 0 2px 12px rgba(108, 140, 255, 0.35);
}
.btn.primary:hover { background: linear-gradient(135deg, #5B7BFF, #7C6AF0); color: #fff; box-shadow: 0 2px 18px rgba(108, 140, 255, 0.5); }
.btn.danger { background: var(--danger); border-color: var(--danger); color: #fff; }
.btn.danger:hover { opacity: 0.9; }
.btn.danger-ghost { color: var(--danger); border-color: var(--danger-light); }
.btn.danger-ghost:hover { background: var(--danger-light); color: var(--danger); border-color: var(--danger); }
.btn.sm { padding: 4px 10px; font-size: 12px; }
.btn:disabled { opacity: 0.5; cursor: not-allowed; }
.btn.loading { pointer-events: none; opacity: 0.7; }

/* ============ 卡片 ============ */
.card {
  background: linear-gradient(180deg, rgba(19, 27, 48, 0.9), rgba(15, 22, 41, 0.95));
  border-radius: var(--radius);
  border: 1px solid var(--border); box-shadow: var(--shadow);
  backdrop-filter: blur(8px);
}
.card-hover { cursor: pointer; transition: transform 0.2s, box-shadow 0.2s, border-color 0.2s; }
.card-hover:hover { transform: translateY(-3px); box-shadow: var(--glow); border-color: var(--border-light); }

/* ============ 项目页 ============ */
.project-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 18px;
}
.project-card { padding: 18px; position: relative; overflow: hidden; }
.project-card .p-cover {
  height: 120px; border-radius: var(--radius-sm); margin-bottom: 12px;
  background: linear-gradient(135deg, rgba(108, 140, 255, 0.18), rgba(167, 139, 250, 0.08));
  display: flex; align-items: center; justify-content: center;
  font-size: 36px; background-size: cover; background-position: center;
}
.project-card .p-name { font-size: 15px; font-weight: 600; margin-bottom: 4px; }
.project-card .p-desc {
  font-size: 12px; color: var(--text-2);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; min-height: 36px;
}
.project-card .p-meta {
  display: flex; justify-content: space-between; align-items: center;
  margin-top: 12px; font-size: 12px; color: var(--text-3);
}
.p-status { font-size: 11px; padding: 2px 8px; border-radius: 999px; }
.p-status.draft { background: var(--bg); color: var(--text-2); }
.p-status.generating { background: var(--warning-light); color: var(--warning); }
.p-status.done { background: var(--success-light); color: var(--success); }
.project-card .p-actions {
  position: absolute; top: 12px; right: 12px;
  display: flex; gap: 6px; opacity: 0; transition: opacity 0.15s;
}
.project-card:hover .p-actions { opacity: 1; }
.icon-btn {
  width: 28px; height: 28px; border-radius: var(--radius-sm);
  border: 1px solid var(--border); background: var(--card-2); cursor: pointer;
  font-size: 13px; display: flex; align-items: center; justify-content: center;
  transition: all 0.2s;
}
.icon-btn:hover { border-color: var(--primary); color: var(--primary); box-shadow: 0 0 8px rgba(108, 140, 255, 0.25); }
.icon-btn.danger:hover { border-color: var(--danger); color: var(--danger); box-shadow: 0 0 8px rgba(248, 113, 113, 0.3); }
.icon-btn.warn:hover { border-color: var(--warning); color: var(--warning); }
.empty-state {
  text-align: center; padding: 60px 20px; color: var(--text-3);
}
.empty-state .empty-icon { font-size: 48px; margin-bottom: 12px; }

/* ============ 项目页 = 登入式独立首页（body.landing） ============
   未选择项目时：隐藏顶栏与左侧导航栏；顶行左侧放「🎬 星野短剧」标志（一行横排）、
   右侧放「＋ 新建项目」；下方项目列表整体左对齐（不再居中）。
   选择项目进入工作台后由 app.js 的 syncLanding() 摘掉 body.landing 恢复外壳。 */
body.landing #app { grid-template-columns: 1fr; grid-template-rows: 1fr; }
body.landing .topbar,
body.landing .navbar { display: none; }
body.landing #main { grid-column: 1 / -1; grid-row: 1; }
body.landing #main .page { max-width: none; margin: 0; padding: 0; }
/* 顶行：品牌在左上、新建项目在右上（仅登入态显示，避免与顶栏标志/页头按钮重复） */
.landing-head { display: none; }
body.landing .landing-head {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 18px 30px;
  animation: fadeIn 0.28s ease;
}
.landing-brand { display: flex; align-items: center; gap: 10px; }
.landing-logo {
  font-size: 26px; line-height: 1;
  filter: drop-shadow(0 0 12px rgba(108, 140, 255, 0.55));
}
.landing-title {
  font-size: 22px; font-weight: 800; letter-spacing: 1px;
  background: linear-gradient(90deg, #6C8CFF, #A78BFA 60%, #22D3EE);
  -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent;
}
/* 列表主体：登入态左对齐（原来居中会显得卡片悬在中间） */
body.landing .landing-body { max-width: none; margin: 0; padding: 0 30px 60px; }
/* 「点击项目卡片即可进入创作工作台」：只在没有项目时显示（见 projects.js refresh 空列表分支） */
.landing-hint { margin-top: 14px; font-size: 12px; color: var(--text-3); }

/* ============ 剧本页 ============ */
#page-script.page.active { display: flex; flex-direction: column; height: 100%; }
#page-script .page-head { flex-shrink: 0; }
.script-layout {
  display: flex; gap: 18px;
  flex: 1; min-height: 0;
}
.chapter-list {
  width: 220px; flex-shrink: 0; background: var(--card);
  border: 1px solid var(--border); border-radius: var(--radius);
  padding: 10px; display: flex; flex-direction: column; gap: 6px;
  align-self: stretch; min-height: 0; overflow-y: auto;
}
.chapter-item {
  padding: 10px 12px; border-radius: var(--radius-sm);
  cursor: pointer; font-size: 13px; color: var(--text-2);
  display: flex; justify-content: space-between; align-items: center; gap: 6px;
  transition: background 0.12s;
}
.chapter-item:hover { background: var(--bg); }
.chapter-item.active { background: var(--primary-light); color: var(--primary); font-weight: 600; }
.chapter-item .ch-del { opacity: 0; border: none; background: none; cursor: pointer; color: var(--text-3); font-size: 14px; }
.chapter-item:hover .ch-del { opacity: 1; }
.chapter-item .ch-del:hover { color: var(--danger); }
.script-editor {
  flex: 1; min-width: 0; min-height: 0;
  display: flex; flex-direction: column;
}
/* 章节剧本体检状态条（场次/台词/动作拍/预估时长/质量门）——
   2026-10-03 按用户批注「这个也不需要显示」整块删除（模板、`core.js::_refreshStats` 一起删）。
   样式的 `.stat-chip*` 还留着：别处（若还有引用）不至于塌掉，也没有多余占位。 */
.script-toolbar {
  display: flex; gap: 8px; margin-bottom: 10px; flex-wrap: wrap;
  align-items: center; flex-shrink: 0;
}
.script-title {
  width: 100%; border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: 10px 14px; font-size: 16px; font-weight: 600; outline: none;
  margin-bottom: 10px; background: var(--card-2); color: var(--text);
  flex-shrink: 0;
}
.script-title:focus { border-color: var(--primary); }
#chapter-content {
  width: 100%; flex: 1; min-height: 120px; resize: vertical;
  border: 1px solid var(--border); border-radius: var(--radius);
  padding: 14px; font-size: 14px; line-height: 1.9; outline: none;
  background: var(--card-2); color: var(--text); font-family: inherit;
}
#chapter-content:focus { border-color: var(--primary); }
.save-hint { font-size: 12px; color: var(--text-3); margin-left: auto; }
.save-hint.saving { color: var(--warning); }
.save-hint.saved { color: var(--success); }

/* ============ 角色/场景页 ============ */
.asset-toolbar {
  display: flex; gap: 10px; margin-bottom: 16px; flex-wrap: wrap;
  align-items: center;
}
/* 「工作流 / API 模型」内联选择器（2026-10-12，static/js/gen-picker.js）——
   角色/场景/资产页的 `.asset-toolbar` 与全能参考页的 `.sb-toolbar` 里都用这一套。
   类名全带 `gen-picker-` 前缀，避免与别处撞车（`tools/check_css_collision.py` 会查）。
   194 轮：原生 select → 自绘下拉（收起态按钮 + 挂 body 的浮层列表）。
   原生下拉弹层是浏览器原生 UI，点 option 不派发 DOM 事件 → "点当前项也弹窗"做不到。
   197 轮：**视觉重心从容器移到按钮本身** —— 用户（截图："⚡ qwen2.1 ▾"）：
   "这个下拉框的按钮要求明显一些，现在这个不明显"。以前只有外层 `.gen-picker-row`
   有个淡边框、按钮本身完全透明（看着就是一行普通文字 + 一个小到看不见的 ▾）。
   现在：容器只当排布壳（透明无边框），按钮自带底/边框/阴影/加粗字号，
   hover 与展开态都用主题色，▾ 用主题色且加大。 */
.gen-picker-row {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 0; border: none; background: transparent;
}
.gen-picker-row .gen-picker-label {
  font-size: 12px; color: var(--text-3); white-space: nowrap;
}
.gen-picker-row .gen-picker-sel {
  border: none; outline: none; background: transparent; color: var(--text);
  font-size: 12px; max-width: 260px; cursor: pointer;
}
.gen-picker-row .gen-picker-sel option { background: var(--card-2); color: var(--text); }
/* ↓ 收起态按钮本身（197 轮：明显化） */

.gen-picker-row .gen-picker-btn {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 6px 11px; border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--card-2); color: var(--text); box-shadow: var(--shadow);
  font-size: 13px; font-weight: 600; font-family: inherit; line-height: 1.2;
  max-width: 300px; cursor: pointer;
  transition: border-color 0.15s, background 0.15s, color 0.15s, box-shadow 0.15s;
}
.gen-picker-row .gen-picker-btn .gen-picker-cur {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.gen-picker-row .gen-picker-caret {
  font-size: 12px; line-height: 1; color: var(--primary); flex: none;
}
.gen-picker-row .gen-picker-btn:hover {
  border-color: var(--primary); color: var(--primary); background: var(--card);
  box-shadow: 0 0 0 2px var(--bg-hover);
}
.gen-picker-row .gen-picker-btn:active { transform: translateY(1px); }
.gen-picker-row .gen-picker-btn[aria-expanded="true"] {
  border-color: var(--primary); color: var(--primary);
  box-shadow: 0 0 0 2px var(--bg-hover);
}
.gen-picker-pop {
  position: fixed; z-index: 10000; min-width: 180px; max-height: 320px; overflow: auto;
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lg); padding: 4px; display: flex; flex-direction: column; gap: 2px;
}
.gen-picker-pop .gen-picker-item {
  display: block; width: 100%; text-align: left; border: none; outline: none; cursor: pointer;
  background: transparent; color: var(--text); font-size: 13px; font-family: inherit;
  padding: 7px 11px; border-radius: 4px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.gen-picker-pop .gen-picker-item:hover { background: var(--card-2); }
.gen-picker-pop .gen-picker-item.gp-on { color: var(--primary); font-weight: 600; }
.search-box {
  display: flex; align-items: center; gap: 6px;
  background: var(--card-2); border: 1px solid var(--border);
  border-radius: var(--radius-sm); padding: 6px 12px; flex: 1; max-width: 320px;
  transition: border-color 0.2s, box-shadow 0.2s;
}
.search-box:focus-within { border-color: var(--primary); box-shadow: 0 0 10px rgba(108, 140, 255, 0.2); }
.search-box input { border: none; outline: none; font-size: 13px; flex: 1; background: transparent; color: var(--text); }
.view-toggle { display: flex; border: 1px solid var(--border); border-radius: var(--radius-sm); overflow: hidden; background: var(--card-2); }
.view-toggle button {
  border: none; background: transparent; padding: 6px 12px; font-size: 12px; cursor: pointer; color: var(--text-2);
  transition: all 0.2s;
}
.view-toggle button:hover { color: var(--text); }
.view-toggle button.active {
  background: linear-gradient(135deg, #6C8CFF, #8B7CF6); color: #fff;
  box-shadow: 0 0 10px rgba(108, 140, 255, 0.4);
}
.asset-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: 14px;
}
.asset-card { padding: 14px; }
.asset-card .a-avatar {
  width: 100%; aspect-ratio: 16/9; border-radius: var(--radius-sm);
  background: linear-gradient(135deg, rgba(108, 140, 255, 0.15), rgba(167, 139, 250, 0.06));
  display: flex; align-items: center; justify-content: center;
  font-size: 42px; margin-bottom: 10px; background-size: cover; background-position: center;
  position: relative; overflow: hidden;
}
.asset-card .a-name { font-weight: 600; font-size: 14px; display: flex; align-items: center; gap: 6px; }
.asset-card .a-tags { font-size: 11px; color: var(--text-3); margin-top: 2px; display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.asset-card .a-tag { font-size: 10px; color: var(--primary); background: var(--primary-light); padding: 1px 6px; border-radius: 999px; }
.asset-card .a-desc {
  font-size: 12px; color: var(--text-2); margin-top: 6px;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.asset-card .a-single { margin-top: 8px; }
.asset-card .a-single-img {
  width: 100%; height: 110px; object-fit: cover; object-position: top;
  border: 1px solid var(--border); border-radius: 6px; cursor: zoom-in;
  transition: border-color 0.2s;
}
.asset-card .a-single-img:hover { border-color: var(--primary); }
/* 角色卡双图：四视图(16:9 横版)在左 + 单人图(3:4 竖版)在右，等高并排 */
#char-content .asset-grid { grid-template-columns: repeat(auto-fill, minmax(min(400px, 100%), 1fr)); }
.a-img-row { display: flex; gap: 8px; align-items: stretch; margin-bottom: 10px; }
.a-img-box {
  position: relative; overflow: hidden; border-radius: var(--radius-sm);
  background: linear-gradient(135deg, rgba(108, 140, 255, 0.15), rgba(167, 139, 250, 0.06));
  display: flex; align-items: center; justify-content: center;
  font-size: 40px; min-width: 0;
}
.a-img-box img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.a-img-box.sheet-box { flex: 2.4 1 0; aspect-ratio: 16/9; }
.a-img-box.single-box { flex: 1 1 0; }
.a-img-box .a-img-tag {
  position: absolute; left: 6px; bottom: 6px; z-index: 2;
  font-size: 10px; line-height: 16px; padding: 0 6px; border-radius: 999px;
  background: rgba(0, 0, 0, 0.45); color: #fff; pointer-events: none;
}
.a-img-box .a-img-pending { position: absolute; top: 6px; left: 6px; z-index: 2; pointer-events: none; }
.a-img-box:hover .img-menu-btn { display: flex; }
.asset-card .a-actions { display: flex; gap: 6px; margin-top: 10px; }
.asset-card .a-actions .btn { flex: 1; justify-content: center; }
.asset-card .a-voice { display: flex; align-items: center; gap: 6px; margin-top: 10px; }
.asset-card .a-voice .btn { flex: none; padding: 4px 10px; }
.asset-card .a-voice-player { height: 30px; flex: 1; min-width: 0; }
.asset-card .a-voice-err { font-size: 11px; color: var(--danger); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tag {
  display: inline-block; font-size: 11px; padding: 2px 8px;
  border-radius: 999px; background: var(--primary-light); color: var(--primary);
}
.tag.amber { background: var(--warning-light); color: var(--warning); }

/* 列表视图 */
.asset-table { width: 100%; border-collapse: collapse; background: var(--card); border-radius: var(--radius); overflow: hidden; border: 1px solid var(--border); }
.asset-table th, .asset-table td { padding: 10px 14px; text-align: left; border-bottom: 1px solid var(--border); font-size: 13px; }
.asset-table th { background: var(--card-2); color: var(--text-2); font-weight: 600; white-space: nowrap; }
.asset-table tr:last-child td { border-bottom: none; }
.asset-table tr:hover td { background: rgba(108, 140, 255, 0.06); }

/* ============ 表单 ============ */
.form-group { margin-bottom: 14px; }
.form-group label { display: block; font-size: 13px; font-weight: 600; margin-bottom: 6px; color: var(--text); }
.form-group label .req { color: var(--danger); margin-left: 2px; }
.form-group input[type="text"], .form-group input[type="number"], .form-group input[type="password"],
.form-group textarea, .form-group select {
  width: 100%; border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: 8px 12px; font-size: 13px; outline: none; background: var(--card-2);
  color: var(--text); font-family: inherit;
  transition: border-color 0.2s, box-shadow 0.2s;
}
select option { background: var(--card-2); color: var(--text); }
::placeholder { color: var(--text-3); opacity: 1; }
.form-group input:focus, .form-group textarea:focus, .form-group select:focus { border-color: var(--primary); box-shadow: 0 0 10px rgba(108, 140, 255, 0.18); }
.form-group textarea { resize: vertical; min-height: 64px; }
.form-row { display: flex; gap: 12px; }
.form-row .form-group { flex: 1; }
.form-hint { font-size: 11px; color: var(--text-3); margin-top: 4px; }
.voice-pick-row { display: flex; gap: 8px; align-items: center; }
.voice-pick-row select { flex: 1; min-width: 0; }
.voice-pick-row .btn { flex-shrink: 0; white-space: nowrap; }
.upload-box {
  border: 1.5px dashed var(--border-light); border-radius: var(--radius-sm);
  padding: 14px; text-align: center; font-size: 12px; color: var(--text-2);
  cursor: pointer; transition: all 0.2s; background: var(--card-2);
}
.upload-box:hover { border-color: var(--primary); color: var(--primary); box-shadow: 0 0 12px rgba(108, 140, 255, 0.15); }
.upload-box:hover { border-color: var(--primary); color: var(--primary); }
.upload-box .up-preview { max-width: 120px; max-height: 120px; border-radius: var(--radius-sm); margin: 0 auto 8px; display: block; object-fit: cover; }
.upload-box .up-text { display: block; }

/* ============ 实体图片上传框（角色定妆照 / 场景背景图 / 资产图）============
   用户 2026-10-04："要求用户能够自己上传自己做过的图片，要求这个明显一些" ——
   原来那个 12px 灰字的小虚线框（"点击上传头像图片（可选）"）太不显眼，资产页连框都没有。
   现在三处统一用 `EntityImage.html()` 画的这个大框：图标 + 主文案 + 说明，
   点选 / 拖入都能传，拖到框上会亮起来。⚠ 三条规则都排在旧 `.upload-box` 之后（同权重靠后赢）。 */
.upload-box-lg {
  min-height: 148px; padding: 18px 14px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 7px;
  border-width: 2px; border-color: rgba(108, 140, 255, 0.45);
  background: rgba(108, 140, 255, 0.05);
}
.upload-box-lg .up-inner { display: flex; flex-direction: column; align-items: center; gap: 5px; pointer-events: none; }
.upload-box-lg .up-ico { font-size: 30px; line-height: 1; }
.upload-box-lg .up-main { font-size: 13.5px; font-weight: 600; color: var(--text); }
.upload-box-lg .up-sub { font-size: 11px; color: var(--text-3); }
.upload-box-lg .up-preview {
  max-width: 240px; max-height: 168px; object-fit: contain;
  border-radius: var(--radius-sm); margin: 0 auto 10px; display: block;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.25);
}
.upload-box-lg.has-img { min-height: 0; }
/* 拖拽悬停 / 上传中 */
.upload-box.drag-over {
  border-color: var(--primary); background: rgba(108, 140, 255, 0.14);
  box-shadow: 0 0 0 3px rgba(108, 140, 255, 0.18);
}
.upload-box.busy { opacity: 0.6; pointer-events: none; }

/* ============ 分镜页 ============ */
/* 分镜卡片上方的分页器 + 工具栏：滚动时固定吸顶不随内容滚动 */
.sb-sticky {
  position: sticky;
  top: 0;
  z-index: 20;
  background: rgba(10, 15, 30, 0.88);
  backdrop-filter: blur(10px);
  margin: 0 -30px;
  padding: 12px 30px 12px;
  border-bottom: 1px solid var(--border);
}
.sb-sticky::after {
  content: '';
  position: absolute;
  left: 0; right: 0; top: 100%;
  height: 4px;
  pointer-events: none;
  background: linear-gradient(to bottom, rgba(108, 140, 255, 0.15), rgba(108, 140, 255, 0));
}
.sb-toolbar { display: flex; gap: 10px; margin-bottom: 14px; flex-wrap: wrap; align-items: center; }
.sb-stats { display: flex; gap: 8px; flex-wrap: wrap; }
/* 「一键导入分镜」弹窗（2026-10-08）：格式说明 + 解析预览 */
.sb-fmt { border: 1px solid var(--border); border-radius: var(--radius); background: var(--card); padding: 8px 12px; }
.sb-fmt > summary { cursor: pointer; font-size: 13px; color: var(--text-2); }
.sb-fmt pre {
  margin: 8px 0; padding: 10px; max-height: 210px; overflow: auto;
  background: var(--bg); border: 1px solid var(--border); border-radius: 8px;
  font-family: ui-monospace, Consolas, monospace; font-size: 12px; line-height: 1.6; white-space: pre-wrap;
}
.sb-fmt-actions { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.sb-import-bar { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-bottom: 6px; }
.sb-import-preview { margin-top: 10px; }
.sb-import-ok { font-size: 13px; color: #4ade80; margin-bottom: 8px; }
.sb-import-err {
  font-size: 13px; color: #f87171; background: rgba(248, 113, 113, .08);
  border: 1px solid rgba(248, 113, 113, .35); border-radius: 8px; padding: 8px 10px; margin-bottom: 8px;
}
.sb-import-err ul, .sb-import-warn ul { margin: 6px 0 0; padding-left: 18px; }
.sb-import-err li, .sb-import-warn li { font-size: 12px; line-height: 1.7; }
.sb-import-warn { font-size: 12px; color: var(--text-2); margin-bottom: 8px; }
.sb-import-table-wrap { max-height: 260px; overflow: auto; }
.sb-import-sum { max-width: 420px; color: var(--text-2); }
.stat-chip {
  background: var(--card); border: 1px solid var(--border); border-radius: 999px;
  padding: 4px 12px; font-size: 12px; color: var(--text-2);
}
.stat-chip b { color: var(--text); }
.sb-table-wrap { overflow-x: auto; }
.sb-table { width: 100%; border-collapse: collapse; background: var(--card); border-radius: var(--radius); overflow: hidden; border: 1px solid var(--border); min-width: 860px; }
.sb-table th, .sb-table td { padding: 9px 12px; text-align: left; border-bottom: 1px solid var(--border); font-size: 13px; vertical-align: middle; }
.sb-table th { background: var(--card-2); color: var(--text-2); font-weight: 600; white-space: nowrap; }
.sb-table tr:hover td { background: rgba(108, 140, 255, 0.06); }
.sb-table .sb-no { width: 40px; text-align: center; color: var(--text-3); }
.sb-table .sb-prompt { max-width: 220px; }
.sb-table .sb-meta { margin: 2px 0; display: flex; gap: 4px; flex-wrap: wrap; }
.sb-table .shot-chip {
  display: inline-block; padding: 0 6px; line-height: 18px; font-size: 11px;
  border-radius: 4px; background: var(--primary-light); color: var(--primary); white-space: nowrap;
}
.sb-table .ellipsis {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%;
}
.sb-table .sb-thumb img { width: 56px; height: 56px; object-fit: cover; border-radius: var(--radius-sm); cursor: pointer; border: 1px solid var(--border); }
.sb-table .sb-thumb .no-img {
  width: 56px; height: 56px; border-radius: var(--radius-sm);
  background: var(--bg); display: flex; align-items: center; justify-content: center;
  font-size: 18px; color: var(--text-3); border: 1px dashed var(--border);
}
.sb-status { font-size: 11px; padding: 2px 8px; border-radius: 999px; white-space: nowrap; }
.sb-status.draft { background: var(--bg); color: var(--text-2); }
.sb-status.image_ready { background: var(--success-light); color: var(--success); }
.sb-status.video_ready { background: var(--primary-light); color: var(--primary); }
.sb-status.failed { background: var(--danger-light); color: var(--danger); }
.sb-actions { display: flex; gap: 4px; }
.sb-actions .icon-btn { width: 26px; height: 26px; font-size: 12px; }
.sb-actions .icon-btn.gen { border-color: var(--primary-light); color: var(--primary); }
.sb-actions .icon-btn.gen:hover { background: var(--primary-light); }
/* 优化提示词：浅蓝描边 + 浅蓝文字（次要操作，视觉轻） */
.sb-actions .icon-btn.op { border-color: var(--primary-light); color: var(--primary); background: transparent; opacity: .85; }
.sb-actions .icon-btn.op:hover { background: var(--primary-light); opacity: 1; }
/* 生成视频：主色实心填充（核心操作，视觉最重） */
.sb-actions .icon-btn.vid { border-color: var(--primary); color: #fff; background: linear-gradient(135deg, #4F7CFF, #6D5CFF); box-shadow: 0 2px 8px rgba(79, 124, 255, .35); }
.sb-actions .icon-btn.vid:hover { background: linear-gradient(135deg, #3D6AFF, #5A4AFF); border-color: var(--primary); color: #fff; box-shadow: 0 3px 12px rgba(79, 124, 255, .5); transform: translateY(-1px); }
.sb-actions .icon-btn.dl { border-color: var(--success-light, #d1f5e6); color: var(--success, #10B981); }
.sb-actions .icon-btn.dl:hover { background: var(--success-light, #d1f5e6); }
/* v6.2 一键超清：主色描边，悬停点亮 */
.sb-actions .icon-btn.up { border-color: var(--primary-light, #d6e1ff); color: var(--primary, #4F7CFF); }
.sb-actions .icon-btn.up:hover { background: var(--primary-light, #d6e1ff); }
.sb-actions .icon-btn.warn { border-color: var(--warning-light); color: var(--warning); }
.sb-actions .icon-btn.warn:hover { background: var(--warning-light); }
.sb-actions .icon-btn:disabled { opacity: 0.35; cursor: not-allowed; }
/* 生视频 Prompt 的 AI 优化按钮：绝对定位在提示词框右上角（不依赖会被隐藏的 field-label） */
.field-ai-opt {
  position: absolute; top: 4px; right: 8px; z-index: 5;
  padding: 2px 10px; font-size: 11px; line-height: 18px;
  border: 1px solid var(--primary-light); border-radius: 999px;
  background: var(--card); color: var(--primary); cursor: pointer;
  transition: all .15s; white-space: nowrap; box-shadow: 0 1px 4px rgba(0,0,0,.25);
}
.field-ai-opt:hover { background: var(--primary-light); color: var(--primary); box-shadow: 0 0 8px rgba(108, 140, 255, .3); }
/* 提示词框（field-row--prompt）需要相对定位，让右上角按钮落在框内 */
.field-row--prompt { position: relative; }
.sb-pager { display: flex; align-items: center; justify-content: flex-end; gap: 10px; margin: 0 0 14px; font-size: 13px; color: var(--text-2); }
.sb-pager button { min-width: 30px; }
.sb-status.running {
  background: var(--warning-light); color: var(--warning);
  animation: pulse 1.2s ease-in-out infinite;
}
@keyframes pulse { 50% { opacity: 0.55; } }
.sb-table tr.generating td { background: rgba(251, 191, 36, 0.08); }
.sb-table .sb-thumb video {
  width: 56px; height: 56px; object-fit: cover; border-radius: var(--radius-sm);
  border: 1px solid var(--border); background: #000;
}

/* ---- 分镜卡片视图（全能参考改造，已迁移到表格视图 .sb-cols） ---- */
.sb-card {
  background: linear-gradient(180deg, var(--card-2), var(--card));
  border: 1px solid var(--border); border-radius: var(--radius);
  overflow: hidden; display: flex; flex-direction: column;
  height: auto; /* 自适应高度：卡片随内容自然撑开，不再固定等高 */
  transition: box-shadow .18s, border-color .18s;
}
.sb-card:hover { box-shadow: 0 4px 20px rgba(108, 140, 255, 0.15); border-color: var(--border-light); }
.sb-card.generating { border-color: var(--warning); box-shadow: 0 0 0 3px var(--warning-light); }
.sb-media { position: relative; aspect-ratio: 16/9; background: #0B1220; display: flex; align-items: center; justify-content: center; overflow: hidden; }
.sb-media img, .sb-media video { width: 100%; height: 100%; object-fit: cover; display: block; }
.sb-media.empty { aspect-ratio: auto; height: 44px; background: var(--bg); border-bottom: 1px solid var(--border); }
.sb-media .sb-empty-hint { display: inline-flex; align-items: center; gap: 6px; color: var(--text-3); font-size: 12px; }
.sb-media .progress { position: absolute; left: 0; right: 0; bottom: 0; height: 4px; background: rgba(255,255,255,.15); }
.sb-media .progress div { height: 100%; width: 60%; background: linear-gradient(90deg, var(--primary), var(--warning)); animation: sb-slide 1.4s ease-in-out infinite; }
@keyframes sb-slide { 0% { margin-left: -60%; } 100% { margin-left: 100%; } }
.sb-media .sb-status { position: absolute; top: 8px; right: 8px; z-index: 2; }
/* 任务类型差异化：生成视频 / 优化提示词 / 视频超清 */
.sb-status.optimizing { background: #EDE9FE; color: #7C3AED; animation: pulse 1.2s ease-in-out infinite; }
.sb-status.upscaling { background: #D1FAE5; color: #059669; animation: pulse 1.2s ease-in-out infinite; }
.sb-card.generating--video { border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-light); }
.sb-card.generating--optimize { border-color: #7C3AED; box-shadow: 0 0 0 3px rgba(124, 58, 237, .18); }
.sb-card.generating--upscale { border-color: #10B981; box-shadow: 0 0 0 3px rgba(16, 185, 129, .18); }
.sb-media .progress--video div { background: linear-gradient(90deg, var(--primary), #6D5CFF); }
.sb-media .progress--optimize div { background: linear-gradient(90deg, #8B5CF6, #D946EF); animation-duration: 1.1s; }
.sb-media .progress--upscale div { background: linear-gradient(90deg, #10B981, #34D399); animation-duration: 1.6s; }
.sb-progress-label {
  position: absolute; left: 8px; bottom: 8px; z-index: 2;
  font-size: 11px; padding: 2px 8px; border-radius: 999px;
  background: rgba(10, 14, 22, .72); color: #fff; pointer-events: none;
}
.sb-progress-label.progress-label--optimize { color: #D8B4FE; }
.sb-progress-label.progress-label--upscale { color: #6EE7B7; }

/* ---- 分镜模式切换（全能参考 / 首尾帧） ---- */
.sb-mode-switch {
  display: inline-flex; align-items: center; gap: 4px; padding: 3px;
  background: var(--bg); border: 1px solid var(--border); border-radius: 999px;
}
.sb-mode-btn {
  border: none; background: transparent; color: var(--text-3);
  padding: 6px 14px; border-radius: 999px; font-size: 13px; cursor: pointer;
  transition: background .18s, color .18s;
}
.sb-mode-btn:hover { color: var(--text-1); background: var(--bg-hover); }
.sb-mode-btn.active { background: var(--primary); color: #fff; font-weight: 600; }

/* ---- 首尾帧模式：首帧/尾帧双图位 ---- */
.sb-frames { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; padding: 10px 12px 4px; border-bottom: 1px solid var(--border); }
.sb-frame { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.sb-frame-label { font-size: 12px; font-weight: 600; color: var(--text-2); display: flex; align-items: center; gap: 4px; }
.sb-frame-body {
  aspect-ratio: 1/1; border-radius: var(--radius-sm); overflow: hidden; background: #0B1220;
  display: flex; align-items: center; justify-content: center; min-height: 120px;
}
.sb-frame-body img.frame-img { width: 100%; height: 100%; object-fit: cover; display: block; cursor: zoom-in; }
.sb-frame-body .sb-empty-hint { display: inline-flex; align-items: center; gap: 6px; color: var(--text-3); font-size: 12px; }
.sb-frame-actions { display: flex; gap: 6px; }
.sb-frame-actions .btn { flex: 1; padding: 5px 6px; font-size: 12px; }

/* ---- 自定义播放器（替代原生 controls：⋮ 下载强制选文件夹） ---- */
.sb-player { position: relative; width: 100%; height: 100%; background: #000; overflow: hidden; }
.sb-player video { width: 100%; height: 100%; object-fit: contain; cursor: pointer; display: block; }
.sb-p-play {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: 52px; height: 52px; border-radius: 50%; border: none;
  background: rgba(15, 23, 42, .55); color: #fff; font-size: 20px;
  display: flex; align-items: center; justify-content: center; cursor: pointer;
  opacity: 0; transition: opacity .18s; pointer-events: none; z-index: 2;
}
.sb-player:hover .sb-p-play { opacity: 1; pointer-events: auto; }
.sb-p-play:hover { background: rgba(15, 23, 42, .75); }
.sb-p-bar {
  position: absolute; left: 0; right: 0; bottom: 0;
  display: flex; align-items: center; gap: 6px;
  padding: 6px 8px; background: linear-gradient(transparent, rgba(15, 23, 42, .8));
  opacity: 0; transition: opacity .18s; z-index: 3;
}
.sb-player:hover .sb-p-bar { opacity: 1; }
.sb-p-btn {
  background: none; border: none; color: #fff; font-size: 14px; line-height: 1;
  width: 26px; height: 26px; cursor: pointer; padding: 0;
  display: inline-flex; align-items: center; justify-content: center; flex: none;
}
.sb-p-btn:hover { background: rgba(255, 255, 255, .18); border-radius: 6px; }
.sb-p-progress { flex: 1; height: 4px; cursor: pointer; accent-color: var(--primary, #4F7CFF); min-width: 40px; }
.sb-p-time { color: #fff; font-size: 11px; white-space: nowrap; flex: none; }
.sb-p-menu-wrap { position: relative; flex: none; }
.sb-p-menu {
  position: absolute; right: 0; bottom: 30px;
  background: var(--card-2); border: 1px solid var(--border-light); border-radius: 8px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.6), 0 0 12px rgba(108, 140, 255, 0.12);
  padding: 4px; min-width: 150px; display: none; z-index: 5;
}
.sb-p-menu-wrap.open .sb-p-menu { display: block; }
.sb-p-menu button {
  display: block; width: 100%; text-align: left; border: none; background: none;
  padding: 7px 10px; font-size: 12px; color: var(--text-1, #E5EDF8);
  border-radius: 6px; cursor: pointer; white-space: nowrap;
}
.sb-p-menu button:hover { background: var(--primary-light); }
.sb-p-menu .dl-color { color: var(--success, #10B981); }
/* ---- 首尾帧模式：参考图片区（角色/场景/资产） ---- */
.sb-refimgs { display: flex; align-items: flex-start; gap: 8px; padding: 6px 12px 2px; border-bottom: 1px solid var(--border); }
.sb-refimgs .ref-label { padding-top: 3px; width: auto; min-width: 64px; }
.sb-refimgs .ref-items { display: flex; gap: 6px; flex-wrap: wrap; flex: 1; min-height: 24px; align-content: flex-start; }
.sb-refimgs .ref-chip { max-width: 200px; }
/* ---- 首尾帧模式：生成首尾帧提示词 ---- */
.sb-frame-prompt { padding: 6px 12px 10px; border-bottom: 1px solid var(--border); }
.sb-frame-prompt .field-row { align-items: flex-start; }
.sb-frame-prompt .field-row + .field-row { margin-top: 4px; }
.sb-frame-prompt .field-row .field-label { width: auto; flex: none; padding-top: 2px; }
.sb-frame-prompt .field-val { flex: 1; white-space: pre-wrap; word-break: break-word; }
.ref-zone { padding: 8px 12px 4px; border-top: 1px solid var(--border); display: flex; flex-direction: column; gap: 4px; }
.ref-group { display: flex; align-items: flex-start; gap: 8px; padding: 4px 0; }
.ref-label { font-size: 11px; color: var(--text-3); width: 76px; flex: none; padding-top: 3px; }
.ref-items { display: flex; gap: 6px; flex-wrap: wrap; flex: 1; min-height: 24px; align-content: flex-start; }
.ref-chip {
  display: inline-flex; align-items: center; gap: 5px;
  border: 1px solid var(--border); border-radius: 6px; padding: 2px 7px;
  font-size: 11px; color: var(--text-2); background: var(--bg);
  max-width: 150px;
}
.ref-chip .ref-th { width: 20px; height: 20px; border-radius: 4px; background: linear-gradient(135deg, #8fb0e8, #4F7CFF); flex: none; object-fit: cover; display: block; }
.ref-chip .ref-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ref-x { width: 14px; height: 14px; border-radius: 50%; background: var(--danger); color: #fff; font-size: 9px; line-height: 14px; text-align: center; border: none; cursor: pointer; padding: 0; flex: none; }
.ref-empty { font-size: 11px; color: var(--text-3); padding-top: 3px; }
/* 提示词优化结果预览：参考图缩略图行 */
.ppo-refs { display: flex; flex-wrap: wrap; gap: 8px; }
.ppo-ref-img { width: 56px; height: 56px; border-radius: 6px; object-fit: cover; border: 1px solid var(--border); background: linear-gradient(135deg, #8fb0e8, #4F7CFF); }
.ppo-ref-empty { font-size: 12px; color: var(--text-3); }
.ref-add {
  flex: none; border: 1.5px dashed var(--border-light); border-radius: 6px;
  padding: 3px 10px; font-size: 11px; color: var(--text-3); cursor: pointer;
  background: var(--card-2); white-space: nowrap;
}
.ref-add:hover { border-color: var(--primary); color: var(--primary); background: var(--primary-light); }
.sb-body { padding: 10px 12px 12px; display: flex; flex-direction: column; gap: 8px; flex: none; }
.sb-name { font-size: 14px; font-weight: 600; color: var(--text); line-height: 1.4; }
.sb-meta { display: flex; gap: 5px; flex-wrap: wrap; }
.sb-meta .shot-chip { display: inline-block; padding: 0 6px; line-height: 18px; font-size: 11px; border-radius: 4px; background: var(--primary-light); color: var(--primary); white-space: nowrap; }
.sb-meta .shot-chip.line { background: rgba(167, 139, 250, 0.18); color: var(--accent-2); }
.field-zone { border: 1px dashed var(--border-light); border-radius: 8px; padding: 8px 10px; display: flex; flex-direction: column; gap: 6px; background: var(--card-2); }
.field-row { display: flex; align-items: flex-start; gap: 8px; }
.field-row .field-label { font-size: 11px; color: var(--text-3); width: 86px; flex: none; padding-top: 2px; }
/* 生视频 Prompt：标签在上、内容在下，内容占满整行 */
.field-row--prompt { flex-direction: column; gap: 3px; }
.field-row--prompt .field-label { width: auto; padding-top: 0; }
.field-val {
  flex: 1; font-size: 12px; color: var(--text-2); cursor: text;
  border: 1px solid transparent; border-radius: 4px; padding: 2px 6px;
  white-space: pre-wrap; word-break: break-all; min-height: 20px;
}
.field-val:hover { background: var(--card-2); border-color: var(--primary); color: var(--text); }
/* 生视频 Prompt 默认最小化：只显示约 3 行（60px），超高折叠 + 底部渐隐 + "展开"按钮，避免撑高卡片；点击可放大查看全部 */
.field-val--prompt {
  display: block;
  position: relative;
  max-height: 60px;
  overflow: hidden;
  padding-right: 12px;
  transition: max-height .18s ease;
}
.field-val--prompt.open { max-height: none; overflow: visible; }
.field-val--prompt:not(.open)::after {
  content: '';
  position: absolute; left: 0; right: 0; bottom: 0; height: 18px;
  background: linear-gradient(to bottom, rgba(15,22,41,0), rgba(15,22,41,1));
  pointer-events: none;
}
.sb-prompt-toggle {
  position: absolute; right: 4px; bottom: 3px; z-index: 2;
  font-size: 11px; line-height: 1.4; color: var(--primary);
  background: var(--card-2); border: 1px solid var(--border-light);
  border-radius: 4px; padding: 1px 5px; cursor: pointer;
  user-select: none; white-space: nowrap;
}
/* ---- 提示词里的参考图内联显示（2026-10-18）：`素材名参考图N` → 缩略图 + 素材名 ----
   用户："我要求全能参考提示词中是这样显示参考图片的"（贴图：正文里每个素材名前带一张小图）。
   口径：图 = 该分镜 reference_urls 里图片类的第 N 张；点图放大（data-act="refzoom"）。
   用 inline-flex + baseline，让缩略图跟着行内文字走、不破行距。 */
.field-val--prompt .pm-ref {
  display: inline-flex; align-items: center; gap: 3px;
  margin: 0 2px; padding: 0 3px 0 2px;
  border: 1px solid var(--border-light); border-radius: 5px;
  background: var(--card-2); vertical-align: middle;
  max-width: 160px; line-height: 1.5;
}
.field-val--prompt .pm-ref-img {
  width: 20px; height: 20px; border-radius: 4px; object-fit: cover;
  flex: none; display: block; cursor: zoom-in;
  background: linear-gradient(135deg, #8fb0e8, #4F7CFF);
}
.field-val--prompt .pm-ref-name {
  font-size: 12px; color: var(--text-2);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.field-val--prompt .pm-ref:hover { border-color: var(--primary); }
.field-val--prompt .pm-ref:hover .pm-ref-name { color: var(--text); }
/* 首尾帧页的提示词框：同一个内联参考图观感（2026-10-18 第七批，用户："要求和全能参考一样"）。
   ⚠ 那两个框是 contenteditable 直接编辑，所以 chip 带 `contenteditable=false`（整体不可拆），
   它的 textContent 就是名字本身 → 保存时不会掉字。 */
.flf-vp-textarea .pm-ref,
.flf-frame-prompt .pm-ref {
  /* ⚠⚠ 必须 `display:inline`（**不能用 inline-flex / inline-block**）：Chromium 的 `innerText` 会把
     inline-flex 当**块边界**，contenteditable 存库时前后各塞一个空行 —— 2026-10-18 真事故：
     `0-2s，特写，缓推，昏暗\n\n\n土坯房内\n\n\n，阳光…`（用户看到"句子被拆成好几行"）。 */
  display: inline; margin: 0 2px; padding: 0 3px 0 2px;
  border: 1px solid var(--border-light); border-radius: 5px;
  background: rgba(255,255,255,.04); line-height: 1.5; user-select: none;
  white-space: nowrap;
}
.flf-vp-textarea .pm-ref-img,
.flf-frame-prompt .pm-ref-img {
  width: 18px; height: 18px; border-radius: 3px; object-fit: cover;
  display: inline-block; vertical-align: -4px; margin-right: 3px;
  background: linear-gradient(135deg, #8fb0e8, #4F7CFF);
}
.flf-vp-textarea .pm-ref-name,
.flf-frame-prompt .pm-ref-name {
  font-size: 12px; color: var(--text-2);
}
.flf-vp-textarea .pm-ref:hover,
.flf-frame-prompt .pm-ref:hover { border-color: var(--primary); }
.sb-prompt-toggle:hover { background: var(--primary-light); border-color: var(--primary); }
/* 参考素材 chip 可点击：点击把 <Picture N> 加入生视频 Prompt */
.ref-chip.pickable { cursor: pointer; transition: border-color .15s, color .15s, background .15s; }
.ref-chip.pickable:hover { border-color: var(--primary); color: var(--primary); background: var(--primary-light); }
/* 参考图拖拽换位（2026-10-19）：拖动中的那张半透明、落点描边 */
.ref-chip.drag-src { opacity: .45; }
.ref-chip.drop-target { border-color: var(--primary); box-shadow: 0 0 0 2px var(--primary-light); }
.ref-chip[data-drag="img"] { cursor: grab; touch-action: none; }
.ref-chip[data-drag="img"]:active { cursor: grabbing; }
.field-input {
  flex: 1; font-size: 12px; color: var(--text); border: 1px solid var(--primary);
  border-radius: 4px; padding: 4px 6px; outline: none; resize: vertical;
  min-width: 0; background: var(--card-2);
}
.field-input:focus { box-shadow: 0 0 0 3px var(--primary-light); }
/* 生视频 Prompt 编辑态：随内容自适应高度 */
.field-input--prompt { height: auto; min-height: 60px; resize: vertical; }
/* 生视频 Prompt 直接原位编辑：无"专门输入框"外观，淡绿背景提示可编辑，内容自适应 */
.field-input--prompt[contenteditable] {
  display: block;
  width: 100%;
  border-color: transparent;
  background: rgba(52, 211, 153, .07);
  box-shadow: none;
  padding: 4px 6px;
  white-space: pre-wrap;
  word-break: break-all;
}
.field-input--prompt[contenteditable]:focus {
  border-color: var(--primary);
  box-shadow: none;
}
.field-input--prompt[contenteditable]:empty::before {
  content: '点击修改，点击其他位置保存';
  color: var(--text-3);
  pointer-events: none;
}
/* 参考素材标记插入后的即时反馈：边框绿色闪一下（与成功色 #10B981 一致） */
.field-input.chip-insert {
  border-color: var(--success);
  box-shadow: 0 0 0 3px rgba(52, 211, 153, .25);
  animation: chip-pop .9s ease-out;
}
@keyframes chip-pop { 0% { background: rgba(52, 211, 153, .18); } 100% { background: var(--card-2); } }
.field-val.flash { animation: sb-flash .9s ease-out; }
@keyframes sb-flash { 0% { background: rgba(52, 211, 153, .4); } 100% { background: transparent; } }
.sb-body .sb-actions { margin-top: 2px; justify-content: flex-end; }
.tag-select { display: flex; flex-wrap: wrap; gap: 6px; max-height: 120px; overflow-y: auto; }
.tag-check {
  display: inline-flex; align-items: center; gap: 4px;
  border: 1px solid var(--border); border-radius: 999px;
  padding: 3px 10px; font-size: 12px; cursor: pointer; background: var(--card-2);
  color: var(--text-2);
}
.tag-check:hover { border-color: var(--primary); }
.tag-check input { display: none; }
.tag-check:has(input:checked) { background: var(--primary-light); border-color: var(--primary); color: var(--primary); font-weight: 600; }
.sb-toolbar .search-box { width: 240px; }

/* ============ 弹窗 ============ */
.modal-overlay {
  position: fixed; inset: 0; z-index: 100;
  background: rgba(4, 8, 18, 0.65);
  backdrop-filter: blur(6px);
  display: flex; align-items: center; justify-content: center;
  overflow: hidden;
}
.modal-overlay.closing { animation: fadeOut 0.12s ease forwards; }
@keyframes fadeOut { to { opacity: 0; } }
.modal {
  background: linear-gradient(180deg, #141C33, #0F1629);
  border: 1px solid var(--border-light); border-radius: 14px;
  box-shadow: 0 24px 80px rgba(0, 0, 0, 0.6), 0 0 30px rgba(108, 140, 255, 0.08);
  display: flex; flex-direction: column; max-height: 88vh;
  animation: popIn 0.16s ease;
}
@keyframes popIn { from { opacity: 0; transform: scale(0.96) translateY(6px); } to { opacity: 1; transform: none; } }
.modal-sm { width: 420px; max-width: 92vw; }
.modal-md { width: 660px; max-width: 94vw; }
.modal-lg { width: 900px; max-width: 94vw; }
.modal-xl { width: 1180px; max-width: 96vw; height: 92vh; max-height: 92vh; }
.modal-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 16px 20px; border-bottom: 1px solid var(--border);
}
.modal-head h3 { font-size: 16px; }
.modal-head-actions { display: flex; gap: 8px; margin-left: auto; margin-right: 12px; }
.modal-close {
  border: none; background: none; font-size: 22px; color: var(--text-3);
  cursor: pointer; line-height: 1; width: 28px; height: 28px;
  border-radius: var(--radius-sm);
}
.modal-close:hover { background: var(--primary-light); color: var(--text); }
.modal-body { padding: 20px; overflow-y: auto; min-height: 0; }
/* ============ 生成视频弹窗：工作流卡片选择 ============ */
.vg-title {
  display: flex; align-items: center; gap: 10px;
  font-size: 13px; font-weight: 600; color: var(--text); margin: 2px 0 10px;
}
.vg-title:not(:first-child) { margin-top: 18px; }
.vg-title::after { content: ''; flex: 1; height: 1px; background: var(--border); }
/* 生成弹窗顶部提示：本次几张图 → 自动匹配几图工作流（避免"我传了 3 张，它用了哪份"） */
.vg-cards-hint {
  font-size: 12px; line-height: 1.6; color: var(--text-3);
  background: rgba(108, 140, 255, 0.08); border: 1px solid rgba(108, 140, 255, 0.25);
  border-radius: 8px; padding: 7px 10px; margin-bottom: 10px;
}
.wf-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 10px; }
.wf-card {
  display: flex; align-items: flex-start; gap: 10px;
  border: 1.5px solid var(--border); border-radius: 10px;
  padding: 12px 14px; background: var(--card); cursor: pointer;
  transition: border-color 0.15s, background 0.15s, box-shadow 0.15s;
}
.wf-card:hover { border-color: var(--primary); box-shadow: 0 0 12px rgba(108, 140, 255, 0.15); }
.wf-card.active {
  border-color: var(--primary);
  background: var(--primary-light);
  box-shadow: 0 0 0 3px rgba(108, 140, 255, 0.12), 0 0 16px rgba(108, 140, 255, 0.2);
}
.wf-radio {
  width: 16px; height: 16px; flex-shrink: 0; margin-top: 2px;
  border-radius: 50%; border: 2px solid var(--border);
  position: relative; transition: border-color 0.15s;
}
.wf-card.active .wf-radio { border-color: var(--primary); }
.wf-card.active .wf-radio::after {
  content: ''; position: absolute; inset: 2px;
  border-radius: 50%; background: var(--primary);
}
.wf-card-main { flex: 1; min-width: 0; }
.wf-card-name { font-size: 13px; font-weight: 600; color: var(--text); line-height: 1.3; }
.wf-card-meta { font-size: 11px; color: var(--text-3); margin-top: 3px; }
.vg-grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.vg-field { display: flex; flex-direction: column; gap: 6px; }
.vg-field .form-label { font-size: 12px; color: var(--text-2); }
/* ============ 设置弹窗分区卡片 ============ */
.settings-card {
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--card);
  margin-bottom: 14px;
  overflow: hidden;
}
.settings-card:last-child { margin-bottom: 0; }
.settings-card-head {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 16px;
  background: var(--card-2);
  border-bottom: 1px solid var(--border);
}
.settings-card-head .sc-icon { font-size: 18px; line-height: 1; }
.settings-card-head h4 { font-size: 14px; color: var(--text); margin: 0; }
.settings-card-head p { font-size: 11px; color: var(--text-3); margin: 2px 0 0; line-height: 1.4; }
.settings-card-head .btn { margin-left: auto; }
.settings-card-body { padding: 14px 16px; }
.settings-card-body .form-group { margin-bottom: 12px; }
.settings-card-body .form-group:last-child { margin-bottom: 0; }
.sc-effective {
  display: flex; flex-direction: column; gap: 6px;
  padding: 10px 12px; margin-bottom: 14px;
  background: var(--bg); border: 1px dashed var(--border);
  border-radius: var(--radius-sm);
  font-size: 12px; color: var(--text-2); line-height: 1.6;
  word-break: break-all;
}
.sc-effective span { color: var(--text-3); margin-right: 8px; white-space: nowrap; }

/* ============ 配置弹窗（v2 精简版：一行一项） ============ */
.cfg-card {
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--card);
  margin-bottom: 12px;
  overflow: hidden;
}
.cfg-card:last-child { margin-bottom: 0; }
.cfg-head {
  display: flex; align-items: center; gap: 10px;
  padding: 11px 14px;
  background: var(--card-2);
  border-bottom: 1px solid var(--border);
}
.cfg-head .cfg-icon { font-size: 17px; line-height: 1; }
.cfg-head-text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.cfg-head-text strong { font-size: 13px; color: var(--text); font-weight: 600; }
.cfg-head-text span { font-size: 11px; color: var(--text-3); line-height: 1.4; }
.cfg-head .btn { margin-left: auto; }
.cfg-body { padding: 12px 14px; display: flex; flex-direction: column; gap: 10px; }
.cfg-row { display: flex; align-items: flex-start; gap: 12px; }
.cfg-row > label {
  flex: 0 0 84px; padding-top: 8px;
  font-size: 12px; color: var(--text-2); text-align: right;
}
.cfg-ctl { flex: 1 1 auto; min-width: 0; }
.cfg-input {
  width: 100%; box-sizing: border-box;
  padding: 7px 10px; font-size: 13px;
  color: var(--text); background: var(--bg);
  border: 1px solid var(--border); border-radius: 8px;
  outline: none;
}
.cfg-input:focus { border-color: var(--primary); }
select.cfg-input { cursor: pointer; }
.cfg-textarea { resize: vertical; font-size: 12px; line-height: 1.6; font-family: inherit; }
.cfg-inline { display: flex; gap: 8px; align-items: center; }
.cfg-inline .cfg-input { flex: 1 1 auto; }
.cfg-inline .btn { flex: 0 0 auto; white-space: nowrap; }
/* 模型管理式表单（192 二改，参考用户的「模型管理」界面）：标签在上、字段通栏、按钮右对齐 */
.cfg-frow { display: flex; flex-direction: column; gap: 5px; margin-bottom: 12px; }
.cfg-frow > label { font-size: 12px; color: var(--text-2); }
.cfg-frow .cfg-hint { margin-top: 0; }
.cfg-f2col { display: flex; gap: 14px; margin-bottom: 12px; }
.cfg-f2col > .cfg-frow { flex: 1 1 0; min-width: 0; margin-bottom: 0; }
.cfg-fbtns { display: flex; justify-content: flex-end; gap: 8px; margin: 2px 0 14px; }
.cfg-fsaved { margin-top: 2px; }
/* 已保存的模型列表（192 二改）：一条一行 —— 左圆点（当前=紫点+紫边）+ 加粗名称 + 小字 模型ID·地址 + 右侧 编辑/删除 */
.cfg-profs { display: flex; flex-direction: column; gap: 10px; }
.cfg-prof {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 14px;
  border: 1px solid var(--border); border-radius: 12px;
  background: var(--bg); cursor: pointer;
}
.cfg-prof:hover { border-color: var(--primary); }
.cfg-prof.active { border-color: var(--primary); }
.cfg-prof-dot { flex: 0 0 auto; width: 9px; height: 9px; border-radius: 50%; background: var(--text-3); }
.cfg-prof.active .cfg-prof-dot { background: var(--primary); }
.cfg-prof-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.cfg-prof-name { font-size: 13px; font-weight: 700; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cfg-prof-sub { font-size: 11px; color: var(--text-3); word-break: break-all; }
.cfg-prof-ops { flex: 0 0 auto; display: flex; gap: 8px; }
.cfg-hint { font-size: 11px; color: var(--text-3); margin-top: 4px; line-height: 1.5; }
.cfg-advanced { margin-top: 2px; }
.cfg-advanced summary {
  cursor: pointer; font-size: 12px; color: var(--text-2);
  padding: 4px 0; user-select: none;
}
.cfg-advanced summary:hover { color: var(--primary); }
.cfg-advanced textarea { margin-top: 6px; }
.test-result {
  font-size: 12px; margin-top: 12px; padding: 8px 10px;
  border-radius: var(--radius-sm); line-height: 1.5; display: none;
  word-break: break-all;
}
.test-result.ok { display: block; background: var(--success-light); color: var(--success); }
.test-result.fail { display: block; background: var(--danger-light); color: var(--danger); }
.test-result.loading { display: block; background: var(--primary-light); color: var(--primary); }

.modal-foot {
  display: flex; justify-content: flex-end; gap: 10px;
  padding: 14px 20px; border-top: 1px solid var(--border);
}

/* 视频生成模式选择卡片 */
#video-mode-body { display: flex; flex-direction: column; gap: 12px; }
.mode-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; }
@media (max-width: 720px) { .mode-grid { grid-template-columns: 1fr; } }
.mode-card {
  display: flex; flex-direction: column; gap: 2px; text-align: left;
  padding: 12px 14px; border: 1px solid var(--border); border-radius: 10px;
  background: var(--card-2); cursor: pointer; transition: border-color .2s, box-shadow .2s;
}
.mode-card:hover:not(:disabled) { border-color: var(--primary); box-shadow: 0 2px 12px rgba(108, 140, 255, 0.2); }
.mode-card:disabled { cursor: not-allowed; }
.mode-card.active { border-color: var(--primary); box-shadow: 0 0 0 2px var(--primary-light); }
.mode-card .mode-icon { font-size: 15px; font-weight: 600; color: var(--primary); }
.mode-card .mode-name { font-size: 14px; font-weight: 600; }
.mode-card .mode-desc { font-size: 12px; color: var(--text-muted); }
.mode-tag {
  display: inline-block; margin-left: 4px; padding: 0 6px; border-radius: 999px;
  font-size: 10px; font-weight: 600; line-height: 16px; vertical-align: 1px;
}
.mode-tag.rec { background: var(--primary-light); color: var(--primary); }
.mode-state { margin-top: 6px; }
.vg-state { font-size: 11px; font-weight: 600; }
.vg-state.ok { color: var(--success); }
.vg-state.warn { color: var(--warning); }
.btn.ghost { background: transparent; color: var(--text-2); border-color: var(--border); }

/* 视频生成弹窗：分镜信息 + 尾帧图选择 */
.vg-info {
  padding: 10px 12px; border: 1px solid var(--border); border-radius: 10px;
  background: var(--bg); display: flex; flex-direction: column; gap: 4px;
}
.vg-info-title { font-size: 13px; font-weight: 600; color: var(--text-1); }
.vg-info-auto { font-size: 12px; color: var(--success); }
.vg-info-auto b { font-weight: 600; }
.vg-info-prompt { font-size: 12px; color: var(--text-3); word-break: break-all; }
/* 生成工作流选择 */
.vg-workflow { display: flex; flex-direction: column; gap: 6px; }
.vg-wf-row { display: flex; align-items: center; gap: 8px; }
.vg-wf-select {
  flex: 1; min-width: 0; padding: 8px 10px; font-size: 13px;
  border: 1px solid var(--border); border-radius: 8px; background: var(--card-2); color: var(--text);
}
.vg-lastframe { display: flex; flex-direction: column; gap: 8px; }
.vg-lf-title { font-size: 13px; font-weight: 600; color: var(--text-2); }
.vg-lf-tools { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.vg-lf-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(72px, 1fr));
  gap: 8px; max-height: 180px; overflow-y: auto;
}
.lf-item {
  position: relative; border: 1px solid var(--border); border-radius: 8px;
  overflow: hidden; cursor: pointer; padding: 0; background: var(--card-2);
}
.lf-item:hover { border-color: var(--primary); }
.lf-item.active { border-color: var(--primary); box-shadow: 0 0 0 2px var(--primary-light); }
.lf-item img { width: 100%; height: 64px; object-fit: cover; display: block; }
.lf-item span {
  position: absolute; left: 2px; bottom: 2px; padding: 0 5px; border-radius: 4px;
  font-size: 10px; font-weight: 600; background: rgba(0,0,0,.55); color: #fff;
}

/* 全能参考：参考素材列表 */
.vg-refs { display: flex; flex-direction: column; gap: 8px; }
.vg-ref-list {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 8px; max-height: 180px; overflow-y: auto;
}
.vg-ref-item {
  display: flex; align-items: center; gap: 8px;
  border: 1px solid var(--border); border-radius: 8px; padding: 6px 8px;
  background: var(--card-2); min-width: 0;
}
.vg-ref-item img {
  width: 44px; height: 44px; object-fit: cover; border-radius: 6px; flex-shrink: 0;
  border: 1px solid var(--border);
}
.vg-ref-icon {
  width: 44px; height: 44px; border-radius: 6px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: 20px; background: var(--bg); border: 1px solid var(--border);
}
.vg-ref-name {
  flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: 12px; color: var(--text-2);
}
.vg-ref-del {
  flex-shrink: 0; width: 20px; height: 20px; border: none; border-radius: 50%;
  background: var(--danger-light); color: var(--danger); font-size: 14px; line-height: 1;
  cursor: pointer; display: flex; align-items: center; justify-content: center;
}
.vg-ref-del:hover { background: rgba(248, 113, 113, 0.28); }

/* ============ 参考素材选择弹窗（从角色/场景/资产/已生成分镜导入） ============ */
.picker-upload-row { display: flex; align-items: center; gap: 10px; padding: 10px 20px 0; }
.picker-group { margin-bottom: 16px; }
.picker-group:last-child { margin-bottom: 0; }
.picker-group-title {
  font-size: 13px; font-weight: 600; color: var(--text-1);
  margin-bottom: 8px; display: flex; align-items: center; gap: 6px;
}
.picker-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(108px, 1fr));
  gap: 10px; max-height: 260px; overflow-y: auto; padding-right: 4px;
}
.picker-item {
  position: relative; border: 1px solid var(--border); border-radius: 10px;
  overflow: hidden; cursor: pointer; background: var(--card-2);
  transition: border-color .2s, box-shadow .2s;
}
.picker-item:hover { border-color: var(--primary); box-shadow: 0 2px 12px rgba(108, 140, 255, 0.2); }
.picker-item.on { border-color: var(--success); box-shadow: 0 0 0 2px rgba(52, 211, 153, .3); }
/* 已添加的参考图：置灰 + 不可再次添加（点按提示已在卡片中） */
.picker-item.added { opacity: .72; cursor: default; }
.picker-item.added:hover { border-color: var(--border); box-shadow: none; }
.picker-item.added .picker-check { background: var(--success); }
.picker-item img {
  width: 100%; height: 84px; object-fit: cover; display: block;
  background: var(--bg);
}
.picker-item video { width: 100%; height: 84px; object-fit: cover; display: block; background: var(--bg); }
.picker-item audio { width: 100%; height: 36px; display: block; padding: 6px; box-sizing: border-box; }
.picker-item .picker-media { position: relative; }
.picker-item .picker-media .picker-kind { position: absolute; left: 6px; top: 6px; font-size: 10px; background: rgba(15,23,42,.65); color: #fff; padding: 2px 6px; border-radius: 999px; }
.picker-name {
  display: block; padding: 6px 8px 10px; font-size: 12px; color: var(--text-2);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.picker-check {
  position: absolute; top: 6px; right: 6px; min-width: 22px; height: 22px;
  padding: 0 6px; border-radius: 999px; font-size: 12px; font-weight: 600;
  background: var(--primary); color: #fff; line-height: 22px; text-align: center;
  box-shadow: 0 1px 4px rgba(0,0,0,.2);
}
.picker-item.on .picker-check { background: var(--success); }

/* 编辑弹窗：尾帧图行 */
.lf-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.lf-thumb {
  width: 64px; height: 40px; object-fit: cover; border-radius: 6px;
  border: 1px solid var(--border);
}

/* 角色/场景生成状态角标 */
.gen-badge {
  display: inline-block; padding: 1px 8px; border-radius: 999px;
  font-size: 11px; font-weight: 600; line-height: 18px;
}
.gen-badge.ok { background: rgba(52, 211, 153, .14); color: #34D399; }
.gen-badge.running { background: rgba(251, 191, 36, .16); color: #FBBF24; }
.gen-badge.fail { background: rgba(248, 113, 113, .16); color: #F87171; }

/* ============ Toast ============ */
#toast-container {
  position: fixed; top: 16px; left: 16px; z-index: 200;
  display: flex; flex-direction: column; gap: 10px;
}
.toast {
  padding: 10px 16px; border-radius: var(--radius-sm);
  font-size: 13px; box-shadow: var(--shadow-lg);
  display: flex; align-items: center; gap: 8px; max-width: 320px;
  animation: slideIn 0.2s ease;
}
@keyframes slideIn { from { opacity: 0; transform: translateX(-16px); } to { opacity: 1; transform: none; } }
.toast.success { background: var(--success); color: #fff; }
.toast.error { background: var(--danger); color: #fff; }
.toast.info { background: #1E2A44; color: #fff; border: 1px solid var(--border-light); }
.toast.warn { background: var(--warning); color: #0A0F1E; border: 1px solid var(--warning-light); }
.toast .t-close { cursor: pointer; margin-left: 6px; font-size: 15px; opacity: 0.8; }
.toast .t-close:hover { opacity: 1; }

/* ============ 任务中心 ============ */
.task-list { display: flex; flex-direction: column; gap: 10px; }
.task-item { border: 1px solid var(--border); border-radius: var(--radius); padding: 12px 14px; }
.task-item .t-head { display: flex; justify-content: space-between; align-items: center; gap: 10px; }
.task-item .t-label { font-weight: 600; font-size: 13px; }
.task-item .t-meta { font-size: 12px; color: var(--text-3); margin-top: 2px; }
.task-item .t-progress { display: flex; align-items: center; gap: 10px; margin-top: 8px; }
.progress-bar { flex: 1; height: 6px; background: var(--bg); border-radius: 999px; overflow: hidden; }
.progress-bar > i { display: block; height: 100%; background: var(--primary); border-radius: 999px; transition: width 0.3s; }
.task-item .t-error { font-size: 12px; color: var(--danger); margin-top: 6px; word-break: break-all; }
.task-item .t-result { font-size: 12px; color: var(--text-3); margin-top: 6px; word-break: break-all; }
.t-status { font-size: 11px; padding: 2px 8px; border-radius: 999px; white-space: nowrap; }
.t-status.pending { background: var(--bg); color: var(--text-2); }
.t-status.running { background: var(--warning-light); color: var(--warning); }
.t-status.success { background: var(--success-light); color: var(--success); }
.t-status.failed { background: var(--danger-light); color: var(--danger); }
.t-actions { display: flex; gap: 6px; margin-top: 8px; }

/* ============ 角色页头像 / 衣橱 ============ */
.asset-card .a-avatar img,
.asset-card .a-avatar span {
  width: 100%; height: 100%; object-fit: cover; border-radius: var(--radius-sm);
}
.asset-card .a-avatar span { display: flex; align-items: center; justify-content: center; font-size: 40px; }
.asset-table .t-avatar {
  width: 40px; height: 40px; border-radius: var(--radius-sm); object-fit: cover;
  background: var(--bg); display: inline-flex; align-items: center; justify-content: center;
  font-size: 18px; border: 1px solid var(--border); vertical-align: middle;
}
.wardrobe-empty {
  text-align: center; padding: 26px 0; color: var(--text-3); font-size: 13px;
}
.wardrobe-item {
  display: flex; align-items: center; gap: 10px;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: 10px 12px; margin-bottom: 8px; background: var(--card-2);
}
.wardrobe-item .w-thumb {
  width: 44px; height: 44px; border-radius: var(--radius-sm); object-fit: cover;
  background: var(--bg); display: flex; align-items: center; justify-content: center;
  font-size: 20px; border: 1px solid var(--border); flex-shrink: 0;
}
.wardrobe-item .w-info { flex: 1; min-width: 0; }
.wardrobe-item .w-name { font-size: 13px; font-weight: 600; }
.wardrobe-item .w-desc {
  font-size: 12px; color: var(--text-3); margin-top: 2px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.wardrobe-item .w-del {
  border: none; background: none; cursor: pointer; color: var(--text-3);
  font-size: 16px; line-height: 1; padding: 4px; border-radius: var(--radius-sm);
}
.wardrobe-item .w-del:hover { background: var(--danger-light); color: var(--danger); }
.wardrobe-add { margin-top: 12px; border-top: 1px dashed var(--border); padding-top: 12px; }
.wardrobe-add .btn { width: 100%; justify-content: center; }

/* ============ 生成历史（选择/删除） ============ */
.history-empty {
  text-align: center; padding: 32px 0; color: var(--text-3); font-size: 13px;
}
.history-item {
  display: flex; align-items: center; gap: 12px;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: 10px 12px; margin-bottom: 8px; background: var(--card-2);
}
.history-item.current { border-color: var(--primary); background: var(--primary-light); box-shadow: 0 0 12px rgba(108, 140, 255, 0.12); }
.history-thumb-wrap { position: relative; flex-shrink: 0; }
.history-thumb {
  width: 64px; height: 64px; border-radius: var(--radius-sm); object-fit: cover;
  background: var(--bg); border: 1px solid var(--border); display: block;
}
.history-tag {
  position: absolute; top: -6px; right: -6px;
  background: var(--primary); color: #fff; font-size: 10px;
  border-radius: 8px; padding: 1px 6px;
}
.history-info { flex: 1; min-width: 0; }
.history-time { font-size: 12px; color: var(--text-3); }
.history-note { font-size: 12px; color: var(--primary); margin-top: 3px; }
.history-actions { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
.history-current-hint { font-size: 12px; color: var(--primary); font-weight: 600; }
.history-hint {
  margin-top: 10px; font-size: 12px; color: var(--text-3);
  border-top: 1px dashed var(--border); padding-top: 10px;
}

/* 提示词优化方式选择（API / ComfyUI 工作流） */
.opt-mode-cards { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.opt-mode-card {
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: 14px 12px; cursor: pointer; text-align: center;
  background: var(--card-2); transition: border-color 0.15s, background 0.15s;
}
.opt-mode-card:hover { border-color: var(--primary); background: var(--primary-light); }
.opt-mode-icon { font-size: 26px; margin-bottom: 6px; }
.opt-mode-name { font-size: 13px; font-weight: 600; color: var(--text-1); }
.opt-mode-desc { font-size: 11px; color: var(--text-3); margin-top: 4px; line-height: 1.4; }

/* 分镜视频历史版本（v2 首尾帧页 / 全能参考页，点击预览） */
.vh-preview-wrap {
  position: relative; width: 100%; aspect-ratio: 16 / 9;
  background: var(--bg); border: 1px solid var(--border);
  border-radius: var(--radius-sm); overflow: hidden; margin-bottom: 10px;
}
.vh-preview {
  width: 100%; height: 100%; object-fit: contain; display: block;
}
.vh-item { cursor: pointer; transition: border-color 0.15s, background 0.15s; }
.vh-item:hover:not(.current) { border-color: var(--primary); }
.vh-item.current { cursor: default; }
.vh-item.vh-selected { border-color: var(--primary); box-shadow: 0 0 8px rgba(108, 140, 255, 0.25); }
.vh-item .history-thumb { pointer-events: none; }

/* ============ AI 拆解分镜 ============ */
.ai-warn {
  font-size: 12px; color: var(--warning); background: var(--warning-light);
  border: 1px solid rgba(251, 191, 36, 0.4); border-radius: var(--radius-sm);
  padding: 8px 12px; margin-bottom: 10px;
}
.ai-item-sub.muted { color: var(--text-3); }

/* ============ AI 提取角色/场景 ============ */
.badge {
  display: inline-block; padding: 1px 8px; border-radius: 999px;
  background: var(--primary-light); color: var(--primary);
  font-size: 11px; margin-left: 6px; vertical-align: 1px;
}
.badge-ok { background: var(--success-light); color: var(--success); }
.badge-gray { background: var(--bg); color: var(--text-2); }

/* ============ 工作流管理 ============ */
.table-wrap { overflow-x: auto; }
.table {
  width: 100%; border-collapse: collapse; font-size: 13px;
}
.table th, .table td {
  text-align: left; padding: 8px 10px; border-bottom: 1px solid var(--border);
  vertical-align: middle;
}
.table th {
  color: var(--text-2); font-weight: 500; font-size: 12px;
  background: var(--card-2); white-space: nowrap;
}
.table tbody tr:hover { background: rgba(108, 140, 255, 0.06); }
.wf-placeholders {
  font-size: 11px; color: var(--text-3); font-family: monospace;
  word-break: break-all;
}
.wf-editor {
  background: var(--bg);
  border-top: 1px solid var(--border);
  padding: 12px 14px 14px;
}
.wf-editor-head {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-bottom: 8px;
}
.wf-editor-head strong { font-size: 13px; color: var(--text-1); }
.wf-editor .wf-name-input,
.wf-editor textarea.wf-textarea {
  width: 100%; border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: 8px 10px; font-size: 13px; color: var(--text-1);
  background: var(--card-2); box-sizing: border-box;
}
.wf-editor textarea.wf-textarea {
  margin-top: 8px; font-family: Consolas, Menlo, monospace; font-size: 12px;
  resize: vertical; line-height: 1.5;
}
.wf-editor .wf-name-input::placeholder,
.wf-editor textarea.wf-textarea::placeholder { color: var(--text-3); }
.wf-editor .wf-name-input:focus,
.wf-editor textarea.wf-textarea:focus {
  outline: none; border-color: var(--primary);
}
.wf-editor-foot { display: flex; gap: 10px; justify-content: flex-end; margin-top: 10px; }
/* 工作流行内改名（名称单元格切换成输入框） */
.wf-name-cell .wf-rename-input {
  width: 100%; min-width: 160px; border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: 6px 8px; font-size: 13px; color: var(--text-1); background: var(--card-2);
  box-sizing: border-box;
}
.wf-name-cell .wf-rename-input:focus { outline: none; border-color: var(--primary); }
.wf-rename-actions { display: flex; gap: 6px; margin-top: 6px; }
.wf-view-pre {
  margin: 0; max-height: 60vh; overflow: auto;
  font-size: 12px; line-height: 1.6; color: var(--text-1);
  background: var(--bg); border: 1px solid var(--border);
  padding: 12px; border-radius: 8px;
  white-space: pre-wrap; word-break: break-all;
  font-family: Consolas, Menlo, 'Courier New', monospace;
}
/* AI 提取：流式输出区 */
.ai-stream {
  margin-top: 10px; border: 1px solid var(--border); border-radius: 8px;
  background: var(--bg); overflow: hidden;
}
.ai-stream-head {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 12px; font-size: 12px; color: var(--text-2);
  background: var(--card-2); border-bottom: 1px solid var(--border);
}
.ai-stream-head .dot-run {
  width: 7px; height: 7px; border-radius: 50%; background: var(--primary);
  animation: pulse 1s infinite;
}
.ai-stream-body {
  max-height: 240px; overflow: auto; margin: 0; padding: 10px 12px;
  font-family: Consolas, Menlo, monospace; font-size: 12px; line-height: 1.6;
  color: var(--text-2); white-space: pre-wrap; word-break: break-all;
}
/* 工作流管理：按四大生成分类卡片 */
.wf-cat { margin-bottom: 16px; border: 1px solid var(--border); border-radius: 10px; overflow: hidden; background: var(--card); }
.wf-cat-head {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 12px 14px; border-bottom: 1px solid var(--border);
  background: var(--card-2);
}
.wf-cat-icon { font-size: 18px; }
.wf-cat-titles { display: flex; flex-direction: column; gap: 2px; }
.wf-cat-title { font-size: 14px; color: var(--text-1); }
.wf-cat-desc { font-size: 11px; color: var(--text-3); }
.wf-state { font-size: 11px; font-weight: 600; padding: 3px 10px; border-radius: 999px; white-space: nowrap; }
.wf-state.ok { background: var(--success-light); color: var(--success); }
.wf-state.none { background: var(--bg); color: var(--text-3); }
.wf-cat-empty {
  padding: 14px; font-size: 12px; color: var(--text-3);
  border-bottom: 1px solid var(--border);
}
.wf-cat-subs { border-bottom: 1px solid var(--border); }
.wf-sub {
  display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap;
  padding: 10px 14px; border-bottom: 1px dashed var(--border);
}
.wf-sub:last-child { border-bottom: none; }
.wf-sub-info { display: flex; flex-direction: column; gap: 2px; }
.wf-sub-info strong { font-size: 13px; color: var(--text-1); }
.wf-sub-note { font-size: 11px; color: var(--text-3); }
.wf-sub-right { display: flex; align-items: center; gap: 10px; }
.wf-cat .table-wrap { border-bottom: 1px solid var(--border); }
/* 窄弹窗里别把表格压扁：宁可横向滚动，也别让工作流名竖排、操作按钮挤成两行
   （2026-09-25：用户报「工作流弹窗样式坏了」时，窄窗口下这几个列被压到 60~90px） */
.wf-cat .table-wrap > table.table { min-width: 620px; }
.btn.danger-ghost {
  background: var(--card-2); color: var(--danger); border-color: var(--danger);
}
.btn.danger-ghost:hover { background: var(--danger-light); color: var(--danger); }
.ai-section { margin-bottom: 18px; }
.ai-section h4 { font-size: 13px; margin: 0 0 8px; color: var(--text-2); }
.ai-item {
  display: flex; align-items: flex-start; gap: 10px;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: 10px 12px; margin-bottom: 8px; background: var(--card-2);
  cursor: pointer; transition: border-color 0.2s, box-shadow 0.2s;
}
.ai-item:hover { border-color: var(--primary); box-shadow: 0 0 10px rgba(108, 140, 255, 0.12); }
.ai-item:has(input:checked) { border-color: var(--primary); background: var(--primary-light); box-shadow: 0 0 14px rgba(108, 140, 255, 0.15); }
.ai-item input[type="checkbox"] { margin-top: 3px; accent-color: var(--primary); flex-shrink: 0; }
.ai-item-main { flex: 1; min-width: 0; }
.ai-item-title { font-size: 13px; font-weight: 600; }
.ai-item-sub {
  font-size: 12px; color: var(--text-3); margin-top: 3px;
  overflow: hidden; text-overflow: ellipsis; display: -webkit-box;
  -webkit-line-clamp: 2; -webkit-box-orient: vertical;
}
.ai-detail { margin-top: 6px; }
.ai-detail summary {
  font-size: 12px; color: var(--primary); cursor: pointer;
  user-select: none;
}
.ai-prompt {
  margin: 6px 0 0; padding: 8px 10px; font-size: 11px; line-height: 1.6;
  color: var(--text-2); background: var(--bg); border: 1px solid var(--border);
  border-radius: var(--radius-sm); white-space: pre-wrap; word-break: break-all;
  max-height: 160px; overflow: auto;
}

/* ============ AI 智能拆解预览卡片（v2.0） ============ */
.ai-preview-count {
  font-size: 12px; color: var(--text-2); margin-bottom: 10px;
  padding: 8px 12px; background: var(--primary-light);
  border-radius: var(--radius-sm);
}
.ai-card {
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: 12px; margin-bottom: 10px; background: var(--card-2);
  transition: border-color 0.2s, box-shadow 0.2s;
}
.ai-card:hover { border-color: var(--primary); box-shadow: 0 0 12px rgba(108, 140, 255, 0.14); }
.ai-card-head { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.ai-card-no {
  font-size: 12px; font-weight: 700; color: var(--primary);
  background: var(--primary-light); border-radius: 6px;
  padding: 2px 8px; flex-shrink: 0;
}
.ai-card-title { font-size: 13px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ai-card-meta { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 6px; }
.ai-card-meta .tag {
  font-size: 11px; color: var(--text-2); background: var(--bg);
  border: 1px solid var(--border); border-radius: 999px; padding: 1px 8px;
}
.ai-card-desc { font-size: 12px; color: var(--text); line-height: 1.7; margin-bottom: 4px; }
.ai-text-block {
  margin: 0 0 8px; padding: 10px 12px; font-size: 12px; line-height: 1.8;
  color: var(--text); background: var(--card); border: 1px solid var(--border);
  border-radius: var(--radius-sm); white-space: pre-wrap; word-break: break-all;
}
.ai-card-line { font-size: 12px; color: var(--text-3); margin-bottom: 3px; }
.ai-card-edit { margin-top: 8px; }
.btn-sm {
  padding: 3px 10px; font-size: 12px; border-radius: 6px;
  border: 1px solid var(--border); background: var(--card-2); color: var(--primary);
  cursor: pointer;
}
.btn-sm:hover { border-color: var(--primary); background: var(--primary-light); }

/* ============ 微调抽屉 ============ */
.drawer-overlay {
  position: fixed; inset: 0; z-index: 60; background: rgba(4, 8, 18, 0.6);
  backdrop-filter: blur(4px);
  display: flex; justify-content: flex-end; overflow: hidden;
}
.drawer-overlay.hidden { display: none; }
.drawer {
  width: 400px; max-width: 92vw; height: 100%;
  background: linear-gradient(180deg, #141C33, #0F1629);
  border-left: 1px solid var(--border-light);
  box-shadow: -8px 0 40px rgba(0, 0, 0, 0.55);
  display: flex; flex-direction: column;
}
.drawer-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 16px 20px; border-bottom: 1px solid var(--border);
}
.drawer-head h4 { margin: 0; font-size: 15px; }
.drawer-body { flex: 1; min-height: 0; overflow-y: auto; padding: 20px; }
.drawer-label {
  display: block; font-size: 12px; color: var(--text-2); margin-bottom: 14px;
}
.drawer-label textarea,
.drawer-label input[type="text"],
.drawer-label input[type="number"],
.drawer-label select {
  display: block; width: 100%; margin-top: 6px; box-sizing: border-box;
  padding: 8px 10px; font-size: 13px; font-family: inherit;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--card-2); color: var(--text);
}
.drawer-label textarea:focus,
.drawer-label input:focus,
.drawer-label select:focus {
  outline: none; border-color: var(--primary);
}
.drawer-row { display: flex; gap: 12px; }
.drawer-row .drawer-label { flex: 1; }
.drawer-foot {
  display: flex; justify-content: flex-end; gap: 10px;
  padding: 14px 20px; border-top: 1px solid var(--border);
}

/* ============ 提示词库（pl-*：分类折叠 / 提示词卡片 / 内置折叠块 / 自定义列表） ============ */
/* `margin: 0 auto` 是必须的：页面容器 `#main .page` 是 `max-width:none; margin:0`（全宽左对齐，见 L146），
   这里只写 max-width 的话宽屏下整块贴在左边、右侧空一大片（用户："这个提示词页面没有居中显示"）。 */
.pl-page { max-width: 1200px; margin: 0 auto; }
.pl-head {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 16px;
  margin-bottom: 12px;
}
.pl-title { font-size: 18px; color: var(--text); margin: 0; }
.pl-sub { font-size: 12px; color: var(--text-2); margin-top: 4px; max-width: 680px; line-height: 1.7; }
.pl-head-actions { display: flex; gap: 8px; flex-shrink: 0; align-items: center; }
.pl-reset-all:hover { border-color: var(--danger); color: var(--danger); }
.pl-summary {
  display: inline-flex; gap: 14px; padding: 6px 14px; margin-bottom: 16px;
  background: var(--card); border: 1px solid var(--border); border-radius: 999px;
  font-size: 12px; color: var(--text-2);
}
.pl-cat {
  margin-bottom: 14px; background: var(--card);
  border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden;
}
.pl-cat-title {
  display: flex; align-items: center; gap: 8px; cursor: pointer; user-select: none;
  font-size: 15px; font-weight: 700; color: var(--text);
  padding: 12px 14px; transition: background .15s;
}
.pl-cat-title:hover { background: var(--card-2); }
.pl-cat-arrow {
  width: 8px; height: 8px; flex-shrink: 0;
  border-right: 2px solid var(--text-3); border-bottom: 2px solid var(--text-3);
  transform: rotate(45deg); transition: transform .2s; margin-right: 2px;
}
.pl-cat.collapsed .pl-cat-arrow { transform: rotate(-45deg); }
.pl-cat-name { flex: 1; }
.pl-cat-count {
  font-size: 11px; font-weight: 400; color: var(--text-3);
  background: var(--card-2); border: 1px solid var(--border);
  padding: 2px 8px; border-radius: 999px;
}
.pl-cat-body { border-top: 1px solid var(--border); padding: 14px; display: block; }
.pl-cat.collapsed .pl-cat-body { display: none; }
.pl-card {
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius);
  padding: 14px 16px; display: flex; flex-direction: column; gap: 10px;
  margin-bottom: 12px;
}
.pl-card-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.pl-card-name { font-size: 14px; color: var(--text); margin: 0; }
.pl-flag {
  font-size: 11px; padding: 2px 8px; border-radius: 999px; white-space: nowrap;
  background: var(--card-2); color: var(--text-3); border: 1px solid var(--border);
}
.pl-flag.custom { background: var(--warning-light); color: var(--warning); border-color: transparent; }
.pl-flag.modified { background: var(--info-light); color: var(--info); border-color: transparent; }
.pl-desc { font-size: 12px; color: var(--text-2); line-height: 1.7; }
.pl-format {
  background: var(--card-2); border: 1px dashed var(--border-light);
  border-radius: var(--radius-sm); padding: 8px 10px;
}
.pl-format-label { font-size: 11px; font-weight: 700; color: var(--accent); }
.pl-format p { font-size: 12px; color: var(--text-2); line-height: 1.7; margin: 4px 0 0; }
.pl-block { display: flex; flex-direction: column; gap: 6px; }
.pl-block-label { font-size: 12px; font-weight: 600; color: var(--text); }
.pl-block-tip { font-weight: 400; color: var(--text-3); margin-left: 4px; }
/* 内置提示词折叠块 */
.pl-builtin {
  border: 1px solid var(--border); border-radius: var(--radius-sm); overflow: hidden;
}
.pl-builtin-head {
  display: flex; align-items: center; gap: 8px; width: 100%; cursor: pointer;
  padding: 8px 10px; background: var(--card-2); border: none;
  font-size: 12px; font-weight: 600; color: var(--text); text-align: left;
  transition: background .15s;
}
.pl-builtin-head:hover { background: var(--card-2-hover, var(--card-2)); }
.pl-builtin-head .pl-cat-arrow { transform: rotate(-45deg); }
.pl-builtin.open .pl-builtin-head .pl-cat-arrow { transform: rotate(45deg); }
.pl-builtin-hint { font-weight: 400; color: var(--text-3); font-size: 11px; }
.pl-builtin-badge {
  font-size: 10px; font-weight: 400; color: var(--info);
  background: var(--info-light); border: 1px solid transparent;
  padding: 1px 6px; border-radius: 999px; white-space: nowrap;
}
.pl-builtin-body { display: none; padding: 10px; background: var(--bg); flex-direction: column; gap: 8px; }
.pl-builtin.open .pl-builtin-body { display: flex; }
.pl-builtin-edit {
  width: 100%; border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: 8px 10px; font-size: 12px; line-height: 1.7; color: var(--text-2);
  font-family: Consolas, Monaco, 'Courier New', monospace;
  background: var(--card); outline: none; resize: vertical; box-sizing: border-box;
}
.pl-builtin-edit:focus { border-color: var(--primary); box-shadow: 0 0 10px rgba(108, 140, 255, 0.18); }
/* 用户自定义提示词列表 */
.pl-custom-list { display: flex; flex-direction: column; gap: 8px; }
.pl-custom-item {
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--card-2); overflow: hidden;
}
.pl-custom-item.active { border-color: var(--primary); box-shadow: 0 0 0 1px var(--primary); }
.pl-custom-item-head {
  display: flex; align-items: center; gap: 8px; padding: 8px 10px; cursor: pointer;
}
.pl-custom-item-head:hover { background: var(--card-2-hover, var(--card-2)); }
.pl-custom-radio {
  display: inline-flex; align-items: center; gap: 4px; flex-shrink: 0; cursor: pointer;
  font-size: 12px; color: var(--text-2);
}
.pl-custom-radio input { accent-color: var(--primary); cursor: pointer; }
/* 规则名称（2026-10-15）：胶囊样式与「AI 优化提示词」弹窗里那块保持一致 */
.pl-custom-name {
  flex: 0 0 auto; max-width: 24ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: 11.5px; font-weight: 600; color: var(--primary);
  background: var(--primary-light); border-radius: 4px; padding: 1px 6px;
}
.pl-custom-name-edit {
  width: 100%; box-sizing: border-box; border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: 6px 10px; font-size: 12px; outline: none; background: var(--card); color: var(--text);
}
.pl-custom-name-edit:focus { border-color: var(--primary); }
.pl-add-box { display: flex; flex-direction: column; gap: 6px; margin-top: 2px; }
.pl-custom-new-name {
  width: 100%; box-sizing: border-box; border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: 6px 10px; font-size: 12px; outline: none; background: var(--bg); color: var(--text);
}
.pl-custom-new-name:focus { border-color: var(--primary); }
.pl-custom-new-name::placeholder { color: var(--text-3); }
.pl-custom-summary {
  flex: 1; min-width: 0; font-size: 12px; color: var(--text-2); line-height: 1.6;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.pl-custom-badge {
  flex-shrink: 0; font-size: 11px; color: var(--text-3);
  background: var(--card); border: 1px solid var(--border); padding: 1px 6px; border-radius: 999px;
}
.pl-custom-item-body { padding: 8px 10px 10px; border-top: 1px solid var(--border); display: flex; flex-direction: column; gap: 8px; }
.pl-custom-item-body[hidden] { display: none; }
.pl-custom-edit {
  width: 100%; border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: 8px 10px; font-size: 12px; line-height: 1.7; outline: none; resize: vertical;
  background: var(--card); color: var(--text); font-family: Consolas, Monaco, 'Courier New', monospace;
}
.pl-custom-edit:focus { border-color: var(--primary); box-shadow: 0 0 10px rgba(108, 140, 255, 0.18); }
.pl-add-row { display: flex; align-items: flex-start; gap: 8px; }
.pl-custom-new {
  flex: 1; border: 1px dashed var(--border); border-radius: var(--radius-sm);
  padding: 8px 10px; font-size: 12px; line-height: 1.7; outline: none; resize: vertical;
  background: var(--bg); color: var(--text); font-family: Consolas, Monaco, 'Courier New', monospace;
}
.pl-custom-new:focus { border-color: var(--primary); border-style: solid; }
.pl-area {
  width: 100%; border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: 8px 10px; font-size: 12px; line-height: 1.7; outline: none;
  background: var(--card-2); color: var(--text); font-family: Consolas, Monaco, 'Courier New', monospace;
  resize: vertical; min-height: 96px;
}
.pl-area.readonly { background: var(--bg); color: var(--text-2); border-style: dashed; }
.pl-custom-area {
  width: 100%; border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: 8px 10px; font-size: 12px; line-height: 1.7; outline: none;
  background: var(--card-2); color: var(--text); font-family: Consolas, Monaco, 'Courier New', monospace;
  resize: vertical; min-height: 84px;
}
.pl-custom-area:focus, .pl-area:focus { border-color: var(--primary); box-shadow: 0 0 10px rgba(108, 140, 255, 0.18); }
.pl-actions { display: flex; align-items: center; gap: 8px; }
.pl-actions .btn:disabled { opacity: 0.5; cursor: not-allowed; }
.pl-status { font-size: 12px; margin-left: auto; }
.pl-status.ok { color: var(--success); }
.pl-status.err { color: var(--danger); }
@media (max-width: 768px) {
  .pl-head { flex-direction: column; }
}

/* ============ 滚动条 ============ */
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-thumb { background: var(--border-light); border-radius: 4px; }
::-webkit-scrollbar-thumb:hover { background: var(--primary); box-shadow: 0 0 6px rgba(108, 140, 255, 0.5); }
::-webkit-scrollbar-track { background: transparent; }

/* ============ 响应式 ============ */
@media (max-width: 768px) {
  .brand-tag { display: none; }
  #app { grid-template-columns: 100px 1fr; }
  .nav-btn { padding: 9px 10px; font-size: 13px; }
  .script-layout { flex-direction: column; }
  .chapter-list { width: 100%; max-height: 180px; position: static; flex-direction: row; overflow-x: auto; }
  .chapter-item { white-space: nowrap; }
  #main .page { padding: 14px 30px; }
  .sb-sticky { margin-left: -30px; margin-right: -30px; padding-left: 30px; padding-right: 30px; }
}

/* ============ 图片双击放大 ============ */
.lightbox {
  position: fixed; inset: 0; z-index: 9999;
  overflow: hidden;
}
.lightbox-mask { position: absolute; inset: 0; background: rgba(10, 14, 25, 0.85); }
.lightbox-img {
  /* 不限制尺寸：由 JS 按原始像素布局，保证完整分辨率解码，放大不糊。
     绝对定位 + left/top 50%，以视口中心为锚点，JS 用 transform 控制缩放与平移 */
  position: absolute; left: 50%; top: 50%;
  transform-origin: 0 0;
  max-width: none; max-height: none;
  border-radius: 10px;
  box-shadow: 0 10px 48px rgba(0, 0, 0, 0.55);
  cursor: grab; user-select: none;
  animation: lightbox-in 0.18s ease-out;
  will-change: transform;
}
.lightbox-img.grabbing { cursor: grabbing; }
.lightbox-tip {
  position: absolute; bottom: 22px; left: 50%; transform: translateX(-50%);
  background: rgba(255, 255, 255, 0.14); color: #fff; font-size: 12px;
  padding: 6px 14px; border-radius: 999px; pointer-events: none;
  white-space: nowrap; z-index: 1;
}
.lightbox-close {
  position: absolute; top: 16px; right: 20px; z-index: 1;
  width: 38px; height: 38px; border-radius: 50%; border: none;
  background: rgba(255, 255, 255, 0.15); color: #fff;
  font-size: 22px; line-height: 1; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.lightbox-close:hover { background: rgba(255, 255, 255, 0.32); }
@keyframes lightbox-in {
  from { opacity: 0.4; }
  to { opacity: 1; }
}

/* ============ AI 一键写剧本 ============ */
/* 参数配置表单：label 在上、控件在下，统一对齐 */
.gen-form { display: flex; flex-direction: column; gap: 14px; }
.gen-field { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.gen-field .form-label { margin: 0; }
.gen-field .field-hint { margin-top: 2px; }
.gen-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
@media (max-width: 640px) {
  .gen-grid { grid-template-columns: 1fr; }
}
.gen-form .style-chips { gap: 8px; }
.step-tag {
  display: inline-block; font-size: 11px; font-weight: 400;
  color: var(--primary); background: var(--primary-light);
  border-radius: 999px; padding: 2px 10px; margin-left: 8px;
  vertical-align: 2px;
}
.form-grid { display: flex; gap: 20px; }
.form-col { flex: 1; display: flex; flex-direction: column; gap: 6px; }
.form-col .form-label { margin-bottom: 0; }
.form-grid .form-col + .form-col { border-left: 1px solid var(--border); padding-left: 20px; }
.form-label { font-size: 13px; font-weight: 600; color: var(--text); display: block; margin: 14px 0 6px; }
.form-label .req { color: var(--danger); margin-left: 2px; }
.form-input {
  width: 100%; box-sizing: border-box;
  background: var(--card-2); border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: 9px 12px; font-size: 13px; color: var(--text); outline: none;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.form-input:focus { border-color: var(--primary); box-shadow: 0 0 10px rgba(108, 140, 255, 0.18); }
textarea.form-input { font-family: inherit; resize: vertical; line-height: 1.7; }
.field-hint { font-size: 11px; color: var(--text-3); margin-top: 4px; }

/* 风格芯片 */
.style-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.style-chip {
  padding: 5px 14px; border-radius: 999px; cursor: pointer;
  font-size: 12px; color: var(--text-2);
  background: var(--card-2); border: 1px solid var(--border);
  transition: all 0.15s; user-select: none;
}
.style-chip:hover { border-color: var(--primary); color: var(--text); }
.style-chip.on {
  background: var(--primary-light); border-color: var(--primary);
  color: var(--primary); font-weight: 600;
}
/* 「题材 / 风格」最后一格：用户自己写（打字即覆盖上面的芯片选择） */
.gen-style-custom {
  flex: 1 1 200px; min-width: 160px;
  padding: 5px 14px; border-radius: 999px;
  background: var(--card-2); border: 1px dashed var(--border);
  color: var(--text); font-size: 12px; outline: none;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.gen-style-custom:focus {
  border-color: var(--primary); border-style: solid;
  box-shadow: 0 0 10px rgba(108, 140, 255, 0.18);
}
.gen-style-custom::placeholder { color: var(--text-3); }

/* 大纲页（卷）：只显示每卷的卷名 + 大概内容，其余一律不显示。
   卡片可以点开：上面是卷内容框，下面是**这一卷专属的讨论框**（气泡样式与讨论页一致）。 */
.volume-item {
  background: var(--card); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 12px 14px; margin-bottom: 12px;
  transition: border-color .15s, box-shadow .15s;
}
.volume-item:hover { border-color: var(--border-light); }
.volume-item.open {
  border-color: var(--primary); box-shadow: 0 0 0 1px rgba(108, 140, 255, 0.25);
}
.volume-top { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.volume-top .outline-no { flex-shrink: 0; }
.volume-top .vol-title { flex: 1 1 auto; min-width: 0; font-weight: 600; }
.volume-top .vol-toggle { flex-shrink: 0; }
.volume-top .vol-del { flex-shrink: 0; }
.vol-summary { line-height: 1.8; }
/* 点开后内容框给足高度（12 行）：卷内容一般 200~400 字，要能一眼看全、直接在上面改 */
.volume-item.open .vol-summary { min-height: 260px; }

/* 单卷讨论框：只出现在点开的卡片里，样式跟讨论页的聊天框一套口径 */
.vol-chat {
  margin-top: 10px; display: flex; flex-direction: column;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: rgba(0, 0, 0, 0.16); overflow: hidden;
}
.vol-chat-log {
  max-height: 360px; min-height: 200px; overflow-y: auto; padding: 10px 12px;
  display: flex; flex-direction: column; gap: 10px;
}
.vol-chat-log .gen-msg { font-size: 12.5px; }
.vol-chat-input {
  flex-shrink: 0; border-top: 1px solid var(--border); padding: 8px 10px;
  display: flex; gap: 8px; align-items: flex-end;
}
.vol-chat-input .vol-chat-ta { flex: 1 1 auto; resize: none; min-height: 52px; }
.vol-chat-input .vol-chat-send,
.vol-chat-input .ep-chat-send,
.vol-chat-input .script-chat-send {
  flex-shrink: 0; white-space: nowrap;
  height: 36px; padding: 0 16px; align-self: flex-end;   /* 别让它被输入行拉得老高（用户：「高度太高」） */
}

/* ---------- 内容区 ↔ 讨论区之间的**可上下拖动**的分隔条 ----------
   用户批注：「加一个可以上下拖动」（箭头指着卷内容框和讨论框之间那块）。
   上下拖 = 改讨论记录区的高度，内容区吃剩下的高度。
   大纲页卷卡片 / 细纲详情 / 正文详情**共用这一套**（`Script._bindSplitter` 绑事件）。 */
.gen-splitter {
  flex: 0 0 auto; height: 12px; margin: 4px 0 2px;
  display: flex; align-items: center; justify-content: center;
  cursor: row-resize; user-select: none; touch-action: none;
}
.gen-splitter::before {
  content: ''; width: 48px; height: 3px; border-radius: 2px;
  background: var(--border); transition: background 0.15s, width 0.15s;
}
.gen-splitter:hover::before { background: var(--primary); width: 72px; }
body.gen-dragging { cursor: row-resize; user-select: none; }
/* 拖动时讨论记录区的 min/max 都不要掺和（高度由拖出来的像素值说了算） */
body.gen-dragging .vol-chat-log { transition: none; }

/* ⚠ 2026-10-03（用户批注）：「点开之后只显示这个卷，不能滚动……点开第 2 卷会出现这个显示框显示不完整，
   所以要求固定这个显示框」。所以：
   ① 点开某一卷时**只渲染那一卷**（`_renderVolumes` 里做的），不再"一长条卡片往下堆"；
   ② 这一张卡撑满弹窗正文，**卷内容框吃掉剩余高度**（框自己滚，页面不滚）、讨论框固定在小高度 ——
      这样不管点第几卷，内容框和讨论框的位置、大小都一模一样，不会出现"显示不完整"。 */
#gen-step-volumes > .modal-body { display: flex; flex-direction: column; min-height: 0; }
#gen-volume-list { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.volume-item.open {
  flex: 1 1 auto; min-height: 0; margin-bottom: 0;
  display: flex; flex-direction: column;
}
.volume-item.open .vol-summary { flex: 1 1 auto; min-height: 120px; resize: none; }
.volume-item.open .vol-chat { flex: 0 0 auto; }
/* 讨论记录区默认别太高（用户批注「高度太高」）；拖动分隔条会写死内联 height，那个说了算 */
.volume-item.open .vol-chat-log { flex: 0 0 auto; min-height: 72px; max-height: 120px; }

/* 细纲页：外层"卷细纲卡片" → 点进去左边章节、右边细纲内容 */
.vol-outline-card { cursor: pointer; }
.vol-outline-card.empty { border-style: dashed; }
.vol-outline-card .vol-outline-title { flex: 1 1 auto; min-width: 0; font-weight: 600; color: var(--text); }
.vol-outline-card .vol-outline-range { font-size: 12px; color: var(--text-3); flex-shrink: 0; }
.vol-outline-summary { font-size: 12px; line-height: 1.7; color: var(--text-3); }
.ep-split { display: flex; gap: 14px; align-items: flex-start; min-height: 0; }
.ep-side {
  flex: 0 0 220px; max-height: 52vh; overflow-y: auto;
  border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--card-2);
}
.ep-side-head {
  padding: 8px 10px; font-size: 12px; color: var(--text-2); border-bottom: 1px solid var(--border);
  display: flex; justify-content: space-between; gap: 6px;
}
.ep-side-head span { color: var(--text-3); }
.ep-side-item {
  padding: 8px 10px; cursor: pointer; border-bottom: 1px solid var(--border);
  display: flex; flex-direction: column; gap: 2px; font-size: 12px; color: var(--text-3);
}
.ep-side-item b { color: var(--primary); font-size: 11px; }
.ep-side-item span { color: var(--text-2); }
.ep-side-item:hover { background: rgba(108, 140, 255, 0.08); }
.ep-side-item.on { background: rgba(108, 140, 255, 0.16); border-left: 2px solid var(--primary); }
.ep-main { flex: 1 1 auto; min-width: 0; }
.ep-main .outline-field textarea { min-height: 150px; }
/* 细纲详情 / 正文详情右栏那个讨论框：和卷卡片里那个是同一套（复用 .vol-chat*），只是容器不同。
   ⚠ 2026-10-03 补丁 17（用户批注：「正文的弹窗页面，要求这个讨论框的高度和下面的对话发送位置固定，
   不要随滚动不见」）——**布局定型为：内容区固定高度、自己滚；讨论框（记录 + 输入行）钉在下面不动**。
   所以 `.ep-main` 不滚（`overflow: hidden`），让内容卡吃剩余高度、内容框内部滚；
   `.ep-chat` 是 `flex: 0 0 auto`。⚠ 别再改回"内容按高度撑开整页、整列一起滚"——
   那样一往上翻，讨论框和发送键就滚出屏幕了（用户实测就是这么报的）。 */
#gen-step-outline > .modal-body,
#gen-step-script > .modal-body { display: flex; flex-direction: column; min-height: 0; }
#gen-outline-detail,
#gen-script-detail { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
#gen-outline-detail .ep-split,
#gen-script-detail .ep-split { flex: 1 1 auto; min-height: 0; align-items: stretch; }
#gen-outline-detail .ep-side,
#gen-script-detail .ep-side { max-height: none; }
#gen-outline-detail .ep-main,
#gen-script-detail .ep-main {
  display: flex; flex-direction: column; min-height: 0;
  overflow: hidden;              /* 滚的是内容框，不是这一列 */
}
#gen-outline-detail .ep-main > .outline-item,
#gen-script-detail .ep-main > .outline-item {
  flex: 1 1 auto; min-height: 0; margin-bottom: 10px;
  display: flex; flex-direction: column;
}
#gen-outline-detail .ep-chat,
#gen-script-detail .ep-chat { flex: 0 0 auto; }
#gen-outline-detail .ep-chat .vol-chat-log,
#gen-script-detail .ep-chat .vol-chat-log { flex: 0 0 auto; min-height: 72px; max-height: 120px; }
#gen-outline-detail .ep-chat .vol-chat-ta,
#gen-script-detail .ep-chat .vol-chat-ta { min-height: 52px; }
.ep-chat { margin-top: 0; }
.ep-chat .vol-chat-log { min-height: 140px; }
.ep-chat .vol-chat-ta { min-height: 66px; }

/* 细纲/正文内容本身：卡片的底/边框/内边距就够了，框内不再套一层边框。
   高度交给 flex（吃掉内容卡的剩余高度），**框内滚动**——见上面那条布局说明。 */
.script-doc-ta {
  width: 100%; flex: 1 1 auto; min-height: 0; resize: none; overflow-y: auto;
  background: transparent; border: none; outline: none; padding: 0;
  color: var(--text-2); font-size: 12.5px; line-height: 1.85; font-family: inherit;
  transition: color 0.15s;
}
.script-doc-ta:focus { color: var(--text); }
.script-doc-ta::placeholder { color: var(--text-3); }

/* 大纲预览 */
.outline-head {
  display: flex; align-items: center; gap: 18px; flex-wrap: wrap;
  padding: 10px 14px; margin-bottom: 12px;
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-sm);
  font-size: 12px; color: var(--text-2);
}
.outline-head .stat b { color: var(--primary); font-size: 15px; margin: 0 2px; }
.outline-head .hint-stat { color: var(--text-3); margin-left: auto; }
.outline-item {
  background: var(--card); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 12px 14px; margin-bottom: 12px;
}
.outline-item-top { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.outline-no {
  font-size: 12px; font-weight: 700; color: var(--primary);
  background: var(--primary-light); border-radius: 4px; padding: 2px 8px;
  flex-shrink: 0;
}
.outline-title-input {
  flex: 1; background: transparent; border: 1px solid transparent; border-radius: 4px;
  font-size: 14px; font-weight: 600; color: var(--text); padding: 4px 6px; outline: none;
  transition: all 0.15s;
}
.outline-title-input:hover { border-color: var(--border-light); }
.outline-title-input:focus { border-color: var(--primary); background: var(--card-2); }
.outline-regen-btn {
  flex-shrink: 0; font-size: 11px; padding: 3px 10px;
  border: 1px solid var(--border); border-radius: 999px; background: var(--card-2);
  color: var(--text-2); cursor: pointer; transition: all 0.15s;
}
.outline-regen-btn:hover { border-color: var(--primary); color: var(--primary); }
.outline-regen-btn:disabled { opacity: 0.5; cursor: not-allowed; }
/* 正文页要和细纲页长得一样：标题那一行撑满、右侧状态右对齐 */
.outline-item-top .vol-outline-title {
  flex: 1 1 auto; min-width: 0; font-size: 14px; font-weight: 600; color: var(--text);
  padding: 4px 6px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.outline-item-top .vol-outline-range { flex-shrink: 0; font-size: 12px; color: var(--text-3); }
.outline-fields { display: flex; flex-direction: column; gap: 6px; }
.outline-field { display: flex; gap: 6px; align-items: flex-start; }
.outline-field-label {
  flex-shrink: 0; font-size: 11px; font-weight: 700; color: var(--text-3);
  padding-top: 6px; width: 42px;
}
.outline-field textarea {
  flex: 1; background: var(--card-2); border: 1px solid var(--border);
  border-radius: 6px; padding: 6px 8px; font-size: 12px; line-height: 1.7;
  color: var(--text-2); outline: none; resize: vertical; font-family: inherit;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.outline-field textarea:focus { border-color: var(--primary); box-shadow: 0 0 10px rgba(108, 140, 255, 0.18); color: var(--text); }
.foot-note { margin-right: auto; font-size: 11px; color: var(--text-3); align-self: center; }
.gen-start-bar { display: flex; align-items: center; gap: 8px; padding: 10px 18px; border-top: 1px solid var(--border); background: var(--card-2); }
.gen-start-bar .gen-start-label { font-size: 13px; color: var(--text-2); white-space: nowrap; }
.gen-start-bar .gen-start-no { width: 64px; text-align: center; }
.gen-start-bar .foot-note { margin-left: auto; }
/* 一键写剧本：模型/思考模式下拉要放得下文字（.gen-start-no 默认只有 64px 给数字框用） */
.gen-start-bar select#gen-model { width: auto; min-width: 180px; max-width: 320px; padding: 6px 10px; border: 1px solid var(--border); border-radius: 6px; background: var(--card-2); color: var(--text); font-size: 13px; outline: none; }
.gen-start-bar select#gen-thinking { width: auto; min-width: 150px; padding: 6px 10px; border: 1px solid var(--border); border-radius: 6px; background: var(--card-2); color: var(--text); font-size: 13px; outline: none; }
/* 一键写剧本「四步流程」：访谈 / 设定 / 大纲 / 正文 */
/* ⚠ 步骤容器是 .modal 的**直接子元素**，必须自己撑成 flex 列。
   否则它在 .modal（flex column）里是 flex:0 1 auto、min-height:auto，
   会被内容顶开、体撑出弹窗边界，而且底部的 footer（返回上一步的按钮）被推到看不见。 */
#modal-gen-script .modal > [id^="gen-step-"] {
  display: flex; flex-direction: column;
  flex: 1 1 auto; min-height: 0;
}
#modal-gen-script .modal > [id^="gen-step-"] > .modal-body {
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
}
#modal-gen-script .modal > [id^="gen-step-"] > .modal-foot { flex-shrink: 0; }
/* 常驻的模型条与头部不参与收缩 */
#modal-gen-script .modal > .modal-head,
#modal-gen-script .modal > .gen-start-bar { flex-shrink: 0; }

/* 步骤指示器（可点回上一步） */
.gen-steps { display: flex; align-items: center; gap: 6px; margin-left: 14px; flex-wrap: wrap; }
.gen-step-item {
  font-size: 12px; line-height: 20px; padding: 2px 10px; border-radius: 10px;
  border: 1px solid var(--border); background: var(--card-2); color: var(--text-3);
  cursor: default; white-space: nowrap;
}
.gen-step-item.done { color: var(--text-2); cursor: pointer; }
.gen-step-item.done:hover { border-color: var(--primary); color: var(--text); }
.gen-step-item.cur { color: #fff; border-color: var(--primary); background: rgba(108, 140, 255, 0.18); }
.gen-step-sep { color: var(--text-3); font-size: 11px; }
/* 访谈题的候选答案（点一下即填；下方 textarea 仍可自由写） */
/* 「大纲是按旧设定写的」警告条 */
.gen-stale {
  margin-bottom: 12px; padding: 10px 12px; font-size: 12px; line-height: 1.8;
  border: 1px solid rgba(251, 191, 36, 0.45); border-radius: var(--radius-sm);
  background: rgba(251, 191, 36, 0.08); color: #fbbf24;
}
.gen-stale b { color: #fcd34d; }
.gen-stale-inline { margin-top: 6px; color: #fbbf24; }
.gen-note {
  font-size: 12px; line-height: 1.8; color: var(--text-2);
  background: var(--card-2); border: 1px solid var(--border);
  border-radius: var(--radius-sm); padding: 10px 12px; margin-bottom: 12px;
}
.gen-note a { color: var(--primary); cursor: pointer; text-decoration: underline; }
/* 访谈页的「聊天框」：用户的话靠左、AI 的回复靠右（微信式气泡）。
   布局：聊天框吃掉弹窗剩下的高度；记录区自己滚，输入框钉在框底 —— 全框只有一个滚动条。 */
#gen-step-interview { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
#gen-step-interview > .modal-body { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
#gen-step-interview > .modal-foot { flex-shrink: 0; }
#gen-step-interview #gen-interview-form { flex: 1 1 auto; min-height: 0; }
.gen-chat-field { flex: 1 1 auto; min-height: 0; }
/* 模型条右侧：当前步骤的统计 + 写作参数开关（把原来单独占一行的统计并进来） */
.gen-bar-right { margin-left: auto; display: flex; align-items: center; gap: 10px; }
.gen-bar-stats { font-size: 12px; color: var(--text-2); }
.gen-bar-stats b { color: var(--primary); font-size: 14px; margin: 0 2px; }
/* 聊天框标题行：左边标题 + 右边的「多轮对话」下拉框 */
.gen-chat-head { display: flex; align-items: center; gap: 10px; }
.gen-chat-head .form-label { margin: 0; }
.gen-conv {
  margin-left: auto; max-width: 46%;
  background: var(--card-2); border: 1px solid var(--border); border-radius: var(--radius-sm);
  color: var(--text-2); font-size: 12px; padding: 4px 8px; outline: none; cursor: pointer;
}
.gen-conv:hover, .gen-conv:focus { border-color: var(--primary); color: var(--text); }
.gen-chat {
  position: relative; flex: 1 1 auto; min-height: 130px;
  display: flex; flex-direction: column; overflow: hidden;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: rgba(0, 0, 0, 0.16);
}
.gen-chat-log {
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
  display: flex; flex-direction: column; gap: 12px; padding: 12px;
}
.gen-chat-input { flex-shrink: 0; border-top: 1px solid var(--border); padding: 8px 10px;
  display: flex; gap: 8px; align-items: flex-end; }
.gen-chat-input textarea { resize: none; flex: 1 1 auto; min-height: 52px; }
/* 讨论页的「发送」现在在这条输入行里（2026-10-03 用户要求：底栏的发送/取消/历史版本都去掉，
   发送挪进对话栏）——和卷卡片/详情页那个发送同一套尺寸口径。 */
.gen-chat-input .btn { flex-shrink: 0; white-space: nowrap; height: 36px; padding: 0 16px; align-self: flex-end; }
.gen-typing { color: var(--text-3); }
.gen-msg {
  position: relative; max-width: 82%;
  padding: 9px 12px; border-radius: 12px;
  font-size: 12.5px; line-height: 1.75; color: var(--text-2);
  word-break: break-word;
}
.gen-msg::before {
  content: attr(data-who);
  display: block; font-size: 10px; line-height: 1; margin-bottom: 5px;
  color: var(--text-3); letter-spacing: 0.5px;
}
/* 用户 = 左边；AI = 右边（尾巴朝向各自那一侧） */
.gen-msg-user {
  align-self: flex-start; background: var(--primary-light);
  border: 1px solid var(--primary); color: var(--text);
  border-top-left-radius: 4px; white-space: pre-wrap;
}
.gen-msg-user::before { color: var(--primary); }
.gen-msg-ai {
  align-self: flex-end; background: var(--card);
  border: 1px solid var(--border); border-top-right-radius: 4px;
}
/* 大纲页顶部那排参数：要能换行，否则窄窗口会挤成一坨 */
.gen-start-bar.gen-wrap-bar { flex-wrap: wrap; row-gap: 6px; }
.gen-start-bar.gen-wrap-bar .style-chips { flex-wrap: wrap; }

/* 一键写剧本：历史版本面板（第 1 步 footer 上方展开） */.gen-hist-empty { padding: 12px 18px; font-size: 12px; color: var(--text-3); border-top: 1px solid var(--border); }
.gen-hist-head { display: flex; align-items: center; justify-content: space-between; padding: 8px 18px; border-top: 1px solid var(--border); background: var(--card-2); font-size: 12px; color: var(--text-2); }
.gen-hist-list { max-height: 220px; overflow-y: auto; }
.gen-hist-row { display: flex; align-items: center; gap: 10px; padding: 8px 18px; border-top: 1px solid var(--border); font-size: 12px; }
.gen-hist-row:hover { background: var(--primary-light); }
.gen-hist-time { color: var(--text-2); white-space: nowrap; }
.gen-hist-meta { flex: 1; min-width: 0; color: var(--text-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gen-start-bar select#ai-split-chapter { width: auto; min-width: 220px; max-width: 340px; padding: 6px 10px; border: 1px solid var(--border); border-radius: 6px; background: var(--card-2); color: var(--text); font-size: 13px; outline: none; }
.gen-start-bar select#ai-split-chapter:focus { border-color: var(--primary); box-shadow: 0 0 10px rgba(108, 140, 255, 0.18); }
/* AI 提取弹窗顶栏下拉（提取范围 / 模型 / 思考模式）统一暗色主题，
   之前只有 #ai-split-chapter 有样式，其余浏览器默认白底显得突兀 */
.gen-start-bar select {
  padding: 6px 10px; border: 1px solid var(--border); border-radius: 6px;
  background: var(--card-2); color: var(--text); font-size: 13px; outline: none;
  appearance: none; -webkit-appearance: none; cursor: pointer;
}
.gen-start-bar select:focus { border-color: var(--primary); box-shadow: 0 0 10px rgba(108, 140, 255, 0.18); }
.gen-start-bar select option { background: var(--card-2); color: var(--text); }
.gen-start-bar select#ai-extract-chapter { width: auto; min-width: 200px; max-width: 320px; }
/* 模型名比较长（如 minimax_h3_fl2v_turbo_8step_v1.0_comfyui_bf16.safetensors），
   下拉要够宽，否则选项文字被截断看不全 */
.gen-start-bar select#ai-extract-model,
.gen-start-bar select#ai-split-model { width: auto; min-width: 260px; max-width: 430px; }
.gen-start-bar select#ai-extract-thinking,
.gen-start-bar select#ai-split-thinking { width: auto; min-width: 160px; }
/* AI 拆解弹窗顶栏（2026-10-12 二修）：**两行式**布局 ——
   第一行 集数/模型/思考模式（单行放得下），第二行 每段时长 + 右侧说明。
   一修的"容器换行"版参差不齐（说明挤在一起、折行位置随内容漂），用户反馈不好看，
   改为显式两行：容器 flex column，每行一个 .gen-start-row（行内仍可换行兜底）。 */
#ai-split-subbar { flex-direction: column; align-items: stretch; gap: 8px; }
#ai-split-subbar .gen-start-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
/* 「每段时长」输入对：装进一个连体小胶囊 —— 边框在胶囊上，两个数字框自身无边框，
   中间 "～" 作分隔条；聚焦时整颗胶囊亮边（和 select 的 focus 语言一致）。 */
.dur-pair {
  display: inline-flex; align-items: stretch;
  border: 1px solid var(--border); border-radius: 6px; background: var(--card-2);
  overflow: hidden; transition: border-color .15s, box-shadow .15s;
}
.dur-pair:focus-within { border-color: var(--primary); box-shadow: 0 0 10px rgba(108, 140, 255, 0.18); }
.dur-pair input[type="number"] {
  width: 56px; padding: 6px 4px; border: none; background: transparent;
  color: var(--text); font-size: 13px; text-align: center; outline: none;
  -moz-appearance: textfield; appearance: textfield;
}
.dur-pair input[type="number"]::-webkit-outer-spin-button,
.dur-pair input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.dur-pair .dur-sep {
  display: flex; align-items: center; padding: 0 4px;
  font-size: 12px; color: var(--text-3);
  border-left: 1px solid var(--border); border-right: 1px solid var(--border);
}
/* 第二行右侧的说明文字：贴右缘，窄屏时随行换行不挤压控件 */
.gen-start-hint { margin-left: auto; font-size: 12px; color: var(--text-3); white-space: nowrap; }
/* AI 优化提示词弹窗头部：模型 / 思考模式 */
.po-head-selects { display: flex; align-items: center; gap: 12px; margin-left: auto; margin-right: 10px; }
.po-head-selects label {
  display: flex; align-items: center; gap: 6px;
  font-size: 12px; color: var(--text-3); white-space: nowrap;
}
.po-head-selects select {
  padding: 5px 8px; border: 1px solid var(--border); border-radius: 6px;
  background: var(--card-2); color: var(--text); font-size: 12px; outline: none;
}
.po-head-selects select#po-model { min-width: 220px; max-width: 320px; }
.po-head-selects select:focus { border-color: var(--primary); }
.po-head-selects select option { background: var(--card-2); color: var(--text); }
/* 画面比例：宽 × 高 一行两个输入 */
.wf-pair { display: flex; align-items: center; gap: 8px; }
.wf-pair .wf-param-input { flex: 1 1 0; }
.wf-pair-x { color: var(--text-3); font-size: 13px; flex: 0 0 auto; }

/* AI 提取画风：卡片（大图·网格换行）+ 自定义画风面板 —— 2026-10-11 第一百七十二/一百七十四轮**整体重做**。
   用户："样式太丑，还有加上这个上传风格图片" + "这个风格的整体页面都优化，参考图大一下"
   + "这个画风再放大一些，还有这个画风不用挤在一排，可以两排、三排"。
   以前：卡片 76px、缩略图 68px 太小；自定义那块的输入区被塞进卡片那一排（`flex:1 1 320px`），
   被压成一条缝、输入框只剩十几像素宽。
   现在：**CSS 网格 + 自动换行**（不再横向滚动，加自定义画风就自然排到第二、三排），
   缩略图跟着列宽走，实测 **147px**（原来的 68px 的两倍多）。
   `minmax(148px,1fr)` 是量出来的：弹窗内容宽 862px → **每行 5 张**（卡片 162×186、缩略图 147），
   7 张卡（6 预设 + ＋新建）排成 `[5,2]`、10 张 `[5,5]`、13 张三排 `[5,5,3]`。 */
#ai-extract-style-bar { display: block; border-top: none; padding-top: 2px; padding-bottom: 12px; }
/* 标签**单独一行**：卡片要占满弹窗内容宽（和标签挤一行会少掉 ~100px，一排就放不下 6 张）。 */
#ai-extract-style-bar .gen-start-label { display: block; padding: 0 0 6px; }
.extract-style-cards {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(148px, 1fr));
  gap: 12px; padding: 4px 2px 10px;
  /* 兜底：画风太多时让**画风区自己内部滚**，别把底部按钮/结果区顶没（`.modal` 是 max-height:88vh）。
     ⚠ 46vh 是量出来的：这个卡片尺寸下**两排正好 394px**，44vh（385）会差 9px 就冒出一条多余滚动条；
     46vh（402）两排不滚、三排起才内部滚。改卡片尺寸（上面那个 minmax）就要重新量这个数。 */
  max-height: 46vh; overflow-y: auto;
}
.extract-style-cards::-webkit-scrollbar { width: 8px; }
.extract-style-cards::-webkit-scrollbar-track { background: transparent; }
.extract-style-cards::-webkit-scrollbar-thumb { background: var(--border); border-radius: 999px; }
.extract-style-card {
  position: relative; width: auto; cursor: pointer; text-align: center;
  border: 2px solid var(--border); border-radius: 14px; padding: 6px 6px 8px;
  background: var(--card-2);
  transition: border-color .15s, background .15s, transform .15s, box-shadow .15s;
}
/* 图跟着**列宽**走（正方形）—— 这样"放大卡片"只要改上面的 minmax 一个数，不用同时改一堆像素值 */
.extract-style-card img {
  width: 100%; height: auto; aspect-ratio: 1 / 1; object-fit: cover;
  border-radius: 10px; display: block; background: var(--card);
}
.extract-style-card > span:last-child {
  display: block; margin-top: 6px; font-size: 12px; color: var(--text-2); line-height: 1.3;
}
.extract-style-card:hover { transform: translateY(-2px); box-shadow: 0 6px 16px rgba(0, 0, 0, .28); }
.extract-style-card.active {
  border-color: var(--primary); background: rgba(108, 140, 255, .12);
  box-shadow: 0 0 0 3px rgba(108, 140, 255, .16);
}
.extract-style-card.active > span:last-child { color: var(--primary); font-weight: 600; }
/* 选中的角标（右上角的小勾）—— 光靠边框在深色底上不够显眼 */
.extract-style-card.active::after {
  content: '✓'; position: absolute; right: 8px; top: 8px; width: 18px; height: 18px;
  border-radius: 50%; background: var(--primary); color: #fff;
  font-size: 12px; line-height: 18px; text-align: center;
}
/* 自定义卡：没上传图时是虚线占位（✏️），上传后就是一张真图 */
.extract-style-card.custom .extract-style-ph,
.extract-style-card.add .extract-style-ph {
  width: 100%; height: auto; aspect-ratio: 1 / 1;
  display: flex; align-items: center; justify-content: center;
  font-size: 26px; border-radius: 10px; background: var(--card); border: 1px dashed var(--border);
}
/* 「＋ 新建」那张卡（2026-10-11 第一百七十三轮：自定义画风可以加很多个） */
.extract-style-card.add .extract-style-ph { font-size: 30px; color: var(--text-3); }
.extract-style-card.add:hover .extract-style-ph { border-color: var(--primary); color: var(--primary); }
.extract-style-card.add > span:last-child { color: var(--text-3); }
/* 面板里的「🗑 删除」（删掉当前这个自定义画风） */
.extract-custom .ec-del {
  flex: 0 0 auto; height: 32px; padding: 0 12px; font-size: 12px; cursor: pointer;
  color: var(--danger, #ff6b6b); background: transparent;
  border: 1px solid var(--border); border-radius: 8px;
}
.extract-custom .ec-del:hover { border-color: var(--danger, #ff6b6b); background: rgba(255, 107, 107, .10); }
/* ── 自定义画风面板（整宽，两栏：左缩略图 + 右输入）──
   ⚠ 面板高度是**算着留的**：这上面"画风区 + 面板"越长，下面那个显示提取结果的 `.modal-body` 就越矮
   （实测：画风 3 排 + 老面板 142px 时，结果区只剩 **40px**）。所以名称/描述**并到一行**、说明压成一行。 */
#modal-ai-extract .modal { max-height: 94vh; }   /* 这个弹窗内容比别的多，比通用的 88vh 再放宽一点 */
.extract-custom {
  display: flex; gap: 16px; align-items: flex-start;
  margin: 0 0 12px; padding: 10px 14px;
  border: 1px solid var(--border); border-radius: 14px; background: var(--card-2);
}
.extract-custom.hidden { display: none; }
.extract-custom .ec-thumb { flex: 0 0 auto; }
.extract-custom .ec-tile {
  position: relative; width: 96px; height: 96px; border-radius: 12px; cursor: pointer;
  border: 1px dashed var(--border); background: var(--card); overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  transition: border-color .15s, background .15s;
}
.extract-custom .ec-tile:hover { border-color: var(--primary); background: var(--card-2); }
.extract-custom .ec-tile img { width: 100%; height: 100%; object-fit: cover; display: block; }
.extract-custom .ec-tile-ph {
  font-size: 11.5px; line-height: 1.5; color: var(--text-3); text-align: center; padding: 0 8px;
}
.extract-custom .ec-tile-x {
  position: absolute; top: 4px; right: 4px; width: 20px; height: 20px; border-radius: 50%;
  background: rgba(0, 0, 0, .62); color: #fff; font-size: 12px; line-height: 20px; text-align: center;
}
.extract-custom .ec-fields { flex: 1 1 auto; min-width: 0; }
.extract-custom .ec-row { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.extract-custom .ec-lbl { flex: 0 0 auto; font-size: 12px; color: var(--text-2); }
.extract-custom .ec-in {
  min-width: 0; height: 32px; padding: 0 10px; font-size: 13px;
  color: var(--text); background: var(--card); border: 1px solid var(--border); border-radius: 8px;
}
.extract-custom .ec-in-name { flex: 0 1 210px; }
.extract-custom .ec-in-desc { flex: 1 1 auto; }
.extract-custom .ec-in:focus { outline: none; border-color: var(--primary); }
.extract-custom .ec-hint {
  font-size: 11.5px; line-height: 1.55; color: var(--text-3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* 逐集生成进度弹窗 */
.progress-wrap { display: flex; flex-direction: column; gap: 10px; }
.progress-top { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.progress-title { font-size: 14px; color: var(--text); display: flex; align-items: center; gap: 6px; }
.progress-title .cur { color: var(--primary); font-weight: 600; }
.progress-pct { font-size: 20px; font-weight: 700; color: var(--primary); }
.progress-bar { height: 8px; background: var(--card-2); border-radius: 999px; overflow: hidden; }
.progress-bar .fill {
  height: 100%; background: linear-gradient(90deg, var(--primary), var(--accent));
  border-radius: 999px; transition: width 0.3s; width: 0;
}
.progress-sub {
  display: flex; align-items: center; gap: 8px;
  font-size: 12px; color: var(--text-2); flex-wrap: wrap;
}
.spinner {
  width: 13px; height: 13px; flex-shrink: 0;
  border: 2px solid var(--primary-light); border-top-color: var(--primary);
  border-radius: 50%; animation: spin 0.8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
.ep-list {
  display: flex; flex-direction: column; gap: 6px;
  max-height: 56vh; overflow-y: auto; margin-top: 4px;
  padding-right: 4px;
}
.ep-item {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 12px; border-radius: var(--radius-sm);
  background: var(--card); border: 1px solid var(--border);
  transition: all 0.2s;
}
.ep-item.done { border-color: var(--success); background: var(--success-light); }
.ep-item.error { border-color: var(--danger); background: var(--danger-light); }
.ep-no {
  font-size: 11px; font-weight: 700; color: var(--text-3);
  background: var(--card-2); border: 1px solid var(--border);
  border-radius: 4px; padding: 2px 6px; flex-shrink: 0;
}
.ep-title { flex: 1; min-width: 0; font-size: 12px; color: var(--text-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ep-status { font-size: 11px; flex-shrink: 0; }
.ep-status.waiting { color: var(--text-3); }
.ep-status.generating { color: var(--primary); }
.ep-status.done { color: var(--success); }
.ep-status.error { color: var(--danger); }
.final-box {
  margin-top: 4px; padding: 12px 14px;
  background: var(--success-light); border: 1px solid var(--success);
  border-radius: var(--radius-sm); font-size: 13px; color: var(--success);
  line-height: 1.7;
}

/* 高亮渐变按钮（AI 一键写剧本） */
.btn.glow {
  position: relative;
  background: linear-gradient(135deg, #6c8cff, #a06cff);
  background-size: 200% 200%;
  animation: glowShift 3s ease infinite;
  border: none;
  box-shadow: 0 4px 16px rgba(108, 140, 255, 0.35);
  color: #fff;
}
.btn.glow:hover {
  box-shadow: 0 6px 22px rgba(108, 140, 255, 0.5);
  transform: translateY(-1px);
}
@keyframes glowShift {
  0% { background-position: 0% 50%; }
  50% { background-position: 100% 50%; }
  100% { background-position: 0% 50%; }
}

/* 新生成章节高亮动画 */
.chapter-item.new-chapter {
  animation: newChapter 2.2s ease-out;
  border-color: var(--primary);
}
@keyframes newChapter {
  0% { background: rgba(108, 140, 255, 0.28); }
  60% { background: rgba(108, 140, 255, 0.28); }
  100% { background: transparent; }
}


/* ===== 图片卡 ⋮ 三点菜单（角色/场景/资产图片下载） ===== */
/* 按钮与下拉菜单叠加在 .a-avatar 内（position:relative），不包装图片本身 */
.img-menu-btn {
  position: absolute; top: 6px; right: 6px;
  width: 24px; height: 24px; line-height: 20px;
  border: none; border-radius: 6px; cursor: pointer;
  background: rgba(0,0,0,0.45); color: #fff; font-size: 16px;
  display: none; align-items: center; justify-content: center;
  z-index: 3;
}
.a-avatar:hover .img-menu-btn { display: flex; }
.img-menu {
  position: absolute; top: 34px; right: 6px; z-index: 5;
  background: var(--card, #0F1629); border: 1px solid var(--border, #1E2A44);
  border-radius: 8px; box-shadow: 0 6px 20px rgba(0,0,0,0.45);
  overflow: hidden; min-width: 132px;
}
.img-menu-item {
  display: block; width: 100%; padding: 9px 14px; text-align: left;
  border: none; background: none; color: var(--text, #E5EDF8);
  font-size: 13px; cursor: pointer; white-space: nowrap;
}
.img-menu-item:hover { background: rgba(255,255,255,0.08); }
.img-menu.hidden { display: none; }


/* ===== 全能参考页表格视图（#小行 + **两列**：分镜视频 | 右侧上下（参考素材 / 视频提示词）） =====
   2026-10-18 用户："这个分镜卡改成两列，左侧是分镜视频，右侧的上面是参考素材，下面只视频提示词，
   高度变成现在的1.5倍"。
   ⚠ 高度为什么自动就是 1.5 倍：视频区是 `aspect-ratio: 16/9`，高度 = 列宽 × 9/16；列宽从 1/3 变成 1/2
   就正好 ×1.5（不需要写死像素，换分辨率/换窗口都不会错位）。右列是"参考素材 + 提示词"竖排，
   提示词吃掉剩余高度 → 整行高度由左侧视频决定。 */
.sb-grid { display: block; width: 100%; overflow-x: auto; }
.sb-table-head.sb-cols {
  display: grid; grid-template-columns: 1fr 1fr; gap: 16px; align-items: stretch;
  width: 100%;
}
/* 每行：左侧视频在文档流里（决定行高），右侧「参考素材 + 提示词」**绝对定位**铺满右半
   ⚠ 为什么用绝对定位：右列的内容（提示词全文）参与格子尺寸计算的话，行高会被它撑到 1.9 倍，
   左边 16:9 的视频就和右边对不齐了。绝对定位后行高**只由左侧视频决定** = 稳定 1.5 倍。 */
.sb-card .sb-cols {
  display: block; position: relative;
  padding: 12px 14px;
  width: 100%;
}
.sb-table-head.sb-cols { padding: 8px 14px; }
/* 网格子项禁止撑破列（视频/长内容不溢出侵占相邻列） */
.sb-cols > * { min-width: 0; overflow: hidden; }
.sb-card .sb-col-media { width: calc(50% - 8px); display: flex; flex-direction: column; gap: 10px; }
/* 右列：只剩视频提示词（参考素材已搬到左列视频框下方，2026-10-19） */
.sb-card .sb-col-side {
  position: absolute; top: 12px; bottom: 12px;
  left: calc(50% + 8px); right: 14px;
  display: flex; flex-direction: column; gap: 10px;
  border-left: 1px solid var(--border); padding-left: 14px;
  min-width: 0; min-height: 0; overflow: hidden;
}
/* 参考素材块（2026-10-19 从右列搬到**视频框下面**）：竖排四行，行高自然、不滚动、不压缩。
   ⚠ 行高由左列决定（视频 16:9 + 这四行），右列的提示词靠绝对定位铺满同高。 */
.sb-card .sb-col-media .sb-col-refs { flex: 0 0 auto; min-height: 0; }
.sb-card .sb-col-refs .ref-zone { display: grid; grid-template-columns: 1fr; gap: 4px; }
/* 首帧图 / 尾帧图 合到**一排**（2026-10-19 用户："把这个首尾帧图的显示改成一排"） */
.sb-card .ref-pair { display: flex; gap: 16px; align-items: center; flex-wrap: wrap; }
.sb-card .ref-pair .ref-group { flex: 1 1 0; min-width: 0; }
.sb-card .sb-col-prompt { flex: 1 1 auto; min-height: 90px; }
.sb-head-sep { color: var(--text-3); opacity: .6; margin: 0 4px; }
.sb-table-head {
  padding: 8px 14px; background: var(--bg); border: 1px solid var(--border);
  border-bottom: none; border-radius: var(--radius) var(--radius) 0 0;
  font-size: 12px; color: var(--text-3); font-weight: 600;
}
/* 每个分镜一行：# 单独小行 + 三列内容 */
.sb-card {
  display: block;
  background: linear-gradient(180deg, var(--card-2), var(--card));
  border: 1px solid var(--border); border-top: none;
  border-radius: 0; transition: background .15s;
}
.sb-card:last-child { border-radius: 0 0 var(--radius) var(--radius); }
.sb-card:hover { background: rgba(108,140,255,0.05); }
.sb-card.generating { box-shadow: inset 0 0 0 1px var(--warning); }
.sb-no-row {
  padding: 5px 14px; font-size: 12px; font-weight: 600; color: var(--text-3);
  background: var(--bg); border-bottom: 1px solid var(--border);
}
.sb-card .sb-cols { padding: 12px 14px; }
/* 第一列：视频（满列高、16:9、状态叠加右上角） */
.sb-col-media {
  overflow: hidden;
}
.sb-col-media .sb-media {
  position: relative; width: 100%; aspect-ratio: 16/9;
  background: #0B1220; display: flex; align-items: center; justify-content: center;
  overflow: hidden; border-radius: var(--radius-sm);
}
/* 视频 contain：保持 16:9 完整显示，不拉成正方形 */
.sb-col-media .sb-media video { object-fit: contain !important; }
.sb-col-media .sb-media img, .sb-col-media .sb-media video { width: 100%; height: 100%; object-fit: cover; display: block; }
.sb-col-media .sb-media .sb-empty-ico { font-size: 30px; opacity: .4; }
.sb-col-media .sb-media .sb-status { position: absolute; top: 6px; right: 6px; z-index: 2; }
.sb-col-media .sb-media .progress { position: absolute; left: 0; right: 0; bottom: 0; height: 4px; background: rgba(255,255,255,.15); }
.sb-col-media .sb-media .progress div { height: 100%; width: 60%; background: linear-gradient(90deg, var(--primary), var(--warning)); animation: sb-slide 1.4s ease-in-out infinite; }
/* 任务类型差异化（覆盖上面的默认进度条样式） */
.sb-col-media .sb-media .progress--video div,
.sb-media .progress--video div { background: linear-gradient(90deg, var(--primary), #6D5CFF); }
.sb-col-media .sb-media .progress--optimize div,
.sb-media .progress--optimize div { background: linear-gradient(90deg, #8B5CF6, #D946EF); animation-duration: 1.1s; }
.sb-col-media .sb-media .progress--upscale div,
.sb-media .progress--upscale div { background: linear-gradient(90deg, #10B981, #34D399); animation-duration: 1.6s; }
.sb-col-media .sb-media .sb-progress-label,
.sb-media .sb-progress-label {
  position: absolute; left: 8px; bottom: 8px; z-index: 2;
  font-size: 11px; padding: 2px 8px; border-radius: 999px;
  background: rgba(10, 14, 22, .72); color: #fff; pointer-events: none;
}
.sb-col-media .sb-progress-label.progress-label--optimize,
.sb-progress-label.progress-label--optimize { color: #D8B4FE; }
.sb-col-media .sb-progress-label.progress-label--upscale,
.sb-progress-label.progress-label--upscale { color: #6EE7B7; }
/* 第二列：参考素材 */
.sb-col-refs .ref-zone { padding: 0; border: none; gap: 2px; }
/* 第三列：提示词 + 按钮 */
.sb-col-prompt .field-zone { margin-bottom: 10px; }
.sb-col-prompt .sb-actions { flex-wrap: wrap; justify-content: flex-start; }
/* 全能参考表格：表头的列分割线（卡片里的分割线在 `.sb-card .sb-col-side` 上，两列版） */
.sb-table-head.sb-cols > div + div {
  border-left: 1px solid var(--border); padding-left: 14px;
}

/* 提示词块：**填满右列剩余高度**（2026-10-18 两列版：不再是 16:9，而是 flex 吃满），操作按钮在最下方 */
.sb-col-prompt { display: flex; flex-direction: column; min-width: 0; min-height: 0; }
.sb-col-prompt .field-zone {
  flex: 1 1 auto; min-height: 0; width: 100%;
  display: flex; flex-direction: column; overflow: hidden; margin-bottom: 0;
}
.sb-col-prompt .field-row--prompt { flex: 1; display: flex; flex-direction: column; min-height: 0; }
.sb-col-prompt .field-val--prompt,
.sb-col-prompt .field-val--prompt.open {
  flex: 1; min-height: 0; max-height: none; overflow-y: auto;
}
.sb-col-prompt .field-val--prompt:not(.open)::after { display: none; }
.sb-col-prompt .sb-prompt-toggle { display: none; }
.sb-col-prompt .sb-actions { margin-top: 10px; flex: none; }

/* 隐藏提示词列顶部标签文字（📝 生视频 Prompt） */
.sb-col-prompt .field-row--prompt .field-label { display: none; }
/* 提示词编辑态与查看态一致：同样撑满 16:9 盒、内容可滚动 */
.sb-col-prompt .field-input--prompt,
.sb-col-prompt .field-input--prompt[contenteditable] {
  flex: 1; height: 100%; min-height: 0; max-height: none;
  overflow-y: auto; resize: none;
}
/* 首帧图红叉：叠在图片右上角，点击直接删除 */
.ff-chip { position: relative; padding-right: 18px; }
.ff-chip .ff-ref-del {
  position: absolute; top: -5px; right: -5px;
  width: 16px; height: 16px; line-height: 16px; font-size: 10px;
  box-shadow: 0 0 4px rgba(0,0,0,.5);
}
.ff-chip .ff-ref-del:hover { transform: scale(1.15); }

/* ===== 存储空间（素材清理） ===== */
.storage-summary{font-size:13px;color:var(--text-1);margin-bottom:10px}
.storage-summary b{color:var(--primary)}
.storage-rows{display:flex;flex-direction:column;gap:6px;margin-bottom:12px}
.storage-row{display:flex;align-items:center;gap:10px;padding:8px 10px;background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-sm);font-size:13px}
.storage-row .sr-name{flex:1;font-weight:600}
.storage-row .sr-meta{color:var(--text-2);font-size:12px}
.storage-row .sr-check{width:16px;height:16px;accent-color:var(--primary);cursor:pointer}
.storage-row .sr-check:disabled{opacity:.35;cursor:not-allowed}
.storage-options{display:flex;align-items:center;gap:8px;margin-bottom:12px;font-size:13px}
.storage-actions{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-bottom:8px}
.storage-hint{font-size:12px;color:var(--text-2);line-height:1.6}

/* ===== 插件系统（左栏插件入口 + 插件页容器） ===== */
.nav-slot{display:flex;flex-direction:column;gap:2px}
.nav-slot:empty{display:none}
/* 插件入口：左栏只有 100px 内容宽，图标 + 文字的按钮需要收紧内边距，否则文字被截断 */
.plugin-nav-btn{display:flex;align-items:center;gap:6px;padding:10px 14px;font-size:14px}
.plugin-nav-btn .nav-ico{font-size:14px;line-height:1;flex:none}
.plugin-nav-btn .nav-txt{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.nav-sep{height:1px;background:var(--border);margin:6px 4px}

/* 插件页：默认沿用宿主卡片布局（1280px 限宽 + 24px 内边距） */
.plugin-iframe-wrap{width:100%;height:100%;min-height:420px;display:flex;flex-direction:column}
.plugin-iframe{width:100%;height:100%;min-height:420px;border:1px solid var(--border);border-radius:var(--radius);background:var(--card);display:block}

/* 铺满模式（iframe 模式默认开启；module 模式用 page.fullscreen:true 开启）：
   纵向撑满主显示区（不产生外层滚动条）；**横向与内置页面完全一致**——
   限宽 1280px 居中 + 左右 24px 内边距，所以宽屏下左右留白与项目/剧本等页面一模一样。
   需要更宽/铺满：清单里写 page.maxWidth（如 "none" 或 "1600px"）；
   需要更大留白：page.padding（如 "0 40px"）。 */
#main .page.plugin-fullscreen{
  max-width:none;margin:0;
  padding:0 30px;
  height:100%;min-height:0;
}
#main .page.plugin-fullscreen.plugin-fullscreen-iframe{overflow:hidden}
#main .page.plugin-fullscreen .plugin-iframe-wrap{height:100%;min-height:0}
#main .page.plugin-fullscreen .plugin-iframe{
  height:100%;min-height:0;border:0;border-radius:0;
}
/* 插件页可复用的骨架（插件自己的 CSS 也可以完全自定义） */
.plugin-page-head{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;margin-bottom:16px}
.plugin-page-title{font-size:20px;font-weight:700}
.plugin-page-sub{font-size:13px;color:var(--text-3);margin-top:2px}
.plugin-card{background:var(--card);border:1px solid var(--border);border-radius:var(--radius);padding:16px}
.plugin-error{color:var(--danger)}

/* ===== 插件管理弹窗（在界面里添加 HTML 文件） ===== */
.plg-drop{
  border:1px dashed var(--border-light); border-radius:var(--radius);
  background:var(--bg); padding:22px 16px; text-align:center; cursor:pointer;
  transition:border-color .2s, background .2s;
}
.plg-drop:hover,.plg-drop.dragover{border-color:var(--primary);background:var(--primary-light)}
.plg-drop-inner{font-size:13px;color:var(--text-2)}
.plg-drop-inner code{color:var(--accent)}
.plg-drop-hint{font-size:11px;color:var(--text-3);margin-top:6px}
.plg-pick-row{display:flex;align-items:center;gap:8px;margin-top:10px;flex-wrap:wrap}
.plg-or{font-size:12px;color:var(--text-3)}
.plg-path-input{flex:1;min-width:240px;box-sizing:border-box}
.plg-form{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:10px;margin-top:12px}
.plg-form-checks{grid-template-columns:1fr 1fr;align-items:center}
.plg-field{display:flex;flex-direction:column;gap:4px;font-size:12px;color:var(--text-2)}
.plg-field .form-input{width:100%;box-sizing:border-box}
.plg-check{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--text-2);cursor:pointer}
.plg-check input{accent-color:var(--primary);width:15px;height:15px;cursor:pointer}
.plg-actions{display:flex;align-items:center;gap:12px;margin-top:14px;flex-wrap:wrap}
.plg-list-title{font-size:13px;font-weight:700;margin:20px 0 10px;padding-top:14px;border-top:1px solid var(--border)}
.plg-list{display:flex;flex-direction:column;gap:8px}
.plg-row{
  display:grid;grid-template-columns:34px 1fr auto;gap:10px;align-items:center;
  background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-sm);padding:10px 12px;
}
.plg-row.off{opacity:.6}
.plg-ico{font-size:20px;text-align:center}
.plg-noicon{color:var(--text-3);font-size:14px}
.plg-main{min-width:0}
.plg-name{font-size:13px;font-weight:600;display:flex;align-items:center;gap:6px}
.plg-badge{font-size:11px;font-weight:400;color:var(--warning);background:var(--warning-light);padding:1px 6px;border-radius:999px}
.plg-meta{font-size:11px;color:var(--text-3);margin-top:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.plg-meta code{color:var(--text-2)}
.plg-err{color:var(--danger)}
.plg-ops{display:flex;gap:6px;flex-wrap:wrap;justify-content:flex-end}
/* 行内「设置」面板：标题 + 四列字段 + 底部提示与按钮，独立成块不再挤在一行 */
.plg-edit{grid-column:1/-1;border-top:1px dashed var(--border);margin-top:8px;padding-top:12px}
.plg-edit-title{font-size:12px;font-weight:700;color:var(--text-2);margin-bottom:10px}
.plg-edit-grid{display:grid;grid-template-columns:1.6fr 1fr 0.8fr 1.2fr;gap:12px}
@media (max-width:820px){.plg-edit-grid{grid-template-columns:1fr 1fr}}
.plg-edit .plg-field .form-input{height:32px;padding:0 8px}
.plg-edit-foot{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-top:14px;flex-wrap:wrap}
.plg-edit-tip{font-size:11px;color:var(--text-3)}
.plg-edit-ops{display:flex;gap:8px;margin-left:auto}

/* ============================================================
   首尾帧页（i2v）样式 —— 从 git HEAD 恢复
   该页此前只删了入口、连 JS 与样式一起删了；页面与样式已一并回填。
   来源：tools/restore_firstlastframe_css.py（HEAD 原文，仅补缺失规则）
   ============================================================ */

/* ============ 首尾帧 v2：表格式行布局 ============ */

/* ---- 工具栏 ---- */
.flf-toolbar {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  position: sticky; top: 0; z-index: 10;
  background: var(--bg); margin: 0 -30px 12px;
  padding: 12px 30px 12px;
  border-bottom: 1px solid var(--border);
}
.flf-toolbar-title {
  font-size: 16px; font-weight: 700; color: var(--text); margin-right: auto;
  display: flex; align-items: center; gap: 10px;
}
.flf-toolbar-title .ep-name { font-size: 13px; font-weight: 400; color: var(--text-2); }
/* ---- 工具栏里的两颗工作流下拉（2026-10-17）：图生图 / 首尾帧视频 ----
   下拉本体复用 `.gen-picker-row`（gen-picker.js 自绘按钮 + 浮层列表），这里只管
   "标签 + 下拉"排成一组、标签用小号灰字，两颗并排时不挤在一起。 */
.flf-gen-pick { display: inline-flex; align-items: center; gap: 6px; }
.flf-gen-pick-label { font-size: 12px; color: var(--text-3); white-space: nowrap; }
/* ---- 统计栏 ---- */
.flf-stats-bar {
  display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
  padding: 8px 12px; margin-bottom: 12px;
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-sm);
  font-size: 12px; color: var(--text-2);
}
.flf-stat { display: flex; align-items: center; gap: 4px; }
.flf-stat-val { font-weight: 700; color: var(--text); }
/* ---- 分镜表容器 ---- */
.flf-shot-table {
  display: flex; flex-direction: column; gap: 14px;
}
/* ---- 单行分镜 ---- */
.flf-shot-row {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 14px;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 14px;
  height: 580px;
  overflow: hidden;
  transition: box-shadow 0.18s, border-color 0.18s;
}
.flf-shot-row:hover { box-shadow: 0 4px 20px rgba(108, 140, 255, 0.14); border-color: var(--border-light); }
.flf-shot-row.generating { border-color: var(--warning); }
/* ---- 左栏：视频提示词区 ---- */
.flf-prompt-col {
  display: flex; flex-direction: column; gap: 8px;
  min-width: 0; overflow: hidden;
}
/* --- 视频预览区 --- */
.flf-video-preview {
  aspect-ratio: 16/9; background: #0B1220;
  border: 2px dashed var(--border-light); border-radius: 6px;
  display: flex; align-items: center; justify-content: center;
  position: relative; overflow: hidden;
  cursor: pointer; transition: border-color 0.2s, box-shadow 0.2s;
  flex-shrink: 0;
}
.flf-video-preview:hover { border-color: var(--primary); box-shadow: 0 0 14px rgba(108, 140, 255, 0.2); }
.flf-video-preview img,
.flf-video-preview video { width: 100%; height: 100%; object-fit: cover; display: block; border-radius: 4px; }
.flf-video-preview .flf-preview-placeholder {
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  color: var(--text-3); font-size: 12px;
}
.flf-video-preview .flf-preview-placeholder svg { width: 28px; height: 28px; opacity: 0.4; }
/* 视频生成进度条 */
.flf-video-progress {
  position: absolute; bottom: 0; left: 0; right: 0; height: 4px;
  background: rgba(0,0,0,0.4); z-index: 1;
}
.flf-video-progress-bar {
  height: 100%; background: var(--primary); transition: width 0.3s;
}
/* --- 分镜头部 --- */
.flf-shot-header {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  flex-shrink: 0;
}
.flf-shot-no {
  font-size: 12px; font-weight: 700; color: var(--primary);
  background: var(--primary-light); border-radius: 4px;
  padding: 2px 8px; flex-shrink: 0;
}
.flf-meta-chip {
  font-size: 11px; color: var(--text-2);
  background: var(--bg); border: 1px solid var(--border);
  border-radius: 999px; padding: 1px 8px;
}
.flf-meta-chip .chip-label { color: var(--text-3); margin-right: 2px; }
/* --- 视频提示词可编辑区 --- */
.flf-vp-textarea {
  width: 100%; flex: 1;
  background: var(--card-2); border: 1px solid var(--border); border-radius: 6px;
  padding: 8px 10px; font-size: 12px; color: var(--text); line-height: 1.7;
  font-family: inherit; outline: none; resize: none; overflow-y: auto;
  word-break: break-word; white-space: pre-wrap;
  transition: border-color 0.2s, box-shadow 0.2s;
}
.flf-vp-textarea:focus { border-color: var(--primary); box-shadow: 0 0 10px rgba(108, 140, 255, 0.18); }
.flf-vp-textarea[data-placeholder]:empty::before {
  content: attr(data-placeholder); color: var(--text-3);
}
.flf-vp-textarea:not(:focus):empty::before { content: attr(data-placeholder); color: var(--text-3); }
/* 视频提示词结构化显示：中英文段名高亮、时间戳高亮、帧对齐高亮 */
.flf-vp-textarea .flf-pp-label { color: var(--accent); font-weight: 600; }
.flf-vp-textarea .flf-pp-ts { color: var(--warn); font-weight: 600; }
.flf-vp-textarea .flf-pp-frame { color: var(--info); font-weight: 600; }
/* ---- 中间 & 右侧：首帧/尾帧卡片 ---- */
.flf-frame-card {
  display: flex; flex-direction: column; gap: 8px;
  background: var(--card-2); border: 1px solid var(--border); border-radius: 8px;
  padding: 10px; min-width: 0; overflow: hidden;
  transition: border-color 0.2s, box-shadow 0.2s;
}
.flf-frame-card:hover { border-color: var(--border-light); box-shadow: 0 0 12px rgba(108, 140, 255, 0.1); }
/* --- 帧预览区 --- */
.flf-frame-preview {
  aspect-ratio: 16/9; background: var(--bg);
  border: 2px dashed var(--border-light); border-radius: 6px;
  display: flex; align-items: center; justify-content: center;
  position: relative; overflow: hidden;
  flex-shrink: 0;
}
.flf-frame-preview img { width: 100%; height: 100%; object-fit: contain; display: block; }
.flf-frame-preview .flf-preview-placeholder {
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  color: var(--text-3); font-size: 12px;
}
.flf-frame-preview .flf-frame-label {
  position: absolute; top: 6px; left: 6px;
  font-size: 10px; font-weight: 700; padding: 2px 8px; border-radius: 4px;
  color: #fff; z-index: 1;
  box-shadow: 0 0 8px rgba(0, 0, 0, 0.4);
}
.flf-frame-label.first { background: rgba(108, 140, 255, 0.9); }
.flf-frame-label.last { background: rgba(167, 139, 250, 0.9); }
/* --- 帧预览上的操作按钮 --- */
.flf-frame-actions {
  position: absolute; top: 6px; right: 6px;
  display: flex; gap: 4px; z-index: 1;
}
/* --- 参考图行：三列并排 --- */
.flf-ref-row { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 6px; flex-shrink: 0; }
.flf-ref-item { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.flf-ref-item-title {
  font-size: 10px; font-weight: 600; color: var(--text-3);
  display: flex; align-items: center; gap: 2px;
}
.flf-ref-thumbs { display: flex; gap: 3px; flex-wrap: wrap; min-height: 32px; }
.flf-ref-thumb {
  width: 32px; height: 32px; border-radius: 4px; object-fit: cover;
  border: 1px solid var(--border); cursor: pointer; background: var(--bg);
  transition: border-color 0.2s, box-shadow 0.2s;
}
.flf-ref-thumb:hover { border-color: var(--primary); box-shadow: 0 0 8px rgba(108, 140, 255, 0.3); }
.flf-ref-thumb.placeholder {
  display: flex; align-items: center; justify-content: center;
  font-size: 14px; color: var(--text-3); cursor: default;
}
.flf-ref-thumb.add-ref {
  display: flex; align-items: center; justify-content: center;
  font-size: 14px; color: var(--text-3);
  border: 1px dashed var(--border); cursor: pointer;
}
.flf-ref-thumb.add-ref:hover { border-color: var(--primary); color: var(--primary); }
.flf-ref-thumb-wrap { position: relative; display: inline-flex; }
.flf-ref-x {
  position: absolute; top: -6px; right: -6px; width: 15px; height: 15px;
  line-height: 13px; text-align: center; font-size: 10px; padding: 0;
  background: var(--danger); color: #fff; border: 1px solid rgba(255,255,255,0.6); border-radius: 50%;
  cursor: pointer; opacity: 0; transition: opacity 0.2s; box-shadow: 0 1px 4px rgba(0,0,0,0.5);
}
.flf-ref-thumb-wrap:hover .flf-ref-x { opacity: 1; }
.flf-ref-x:hover { background: #F87171; }
/* --- 图片位置编号角标：「图N」= 工作流图位序号（第 N 张参考图进第 N 个图位）--- */
.flf-ref-num {
  position: absolute; left: -2px; bottom: -2px;
  padding: 0 3px; border-radius: 3px; font-size: 9px; line-height: 12px;
  background: rgba(79, 124, 255, 0.92); color: #fff; pointer-events: none;
}
/* 视频参考图行里「首帧/尾帧专用」素材的角标：只读展示，增删到对应帧卡片 */
.flf-ref-frame-tag {
  position: absolute; left: -2px; top: -2px;
  padding: 0 3px; border-radius: 3px; font-size: 9px; line-height: 12px;
  background: rgba(167, 139, 250, 0.92); color: #fff; pointer-events: none;
}
/* --- 图片位置一览行（场景/角色/资产三列下方的「有几张显示几张 + ＋」）--- */
.flf-ref-imgs { display: flex; flex-direction: column; gap: 2px; flex-shrink: 0; }
.flf-ref-imgs .flf-ref-item-title { flex-wrap: wrap; }
.flf-ref-imgs .form-hint { font-size: 10px; }
/* --- 尾帧参考图默认提示 --- */
.flf-ref-inherit {
  font-size: 10px; color: var(--text-3); font-style: italic;
  padding: 2px 0;
}
/* --- 帧提示词可编辑区 --- */
.flf-frame-prompt {
  background: var(--card); border: 1px solid var(--border); border-radius: 6px;
  padding: 6px 8px; font-size: 11px; color: var(--text-2); cursor: text;
  flex: 1; overflow-y: auto; min-height: 28px; word-break: break-word;
  white-space: pre-wrap; line-height: 1.7;
  outline: none; transition: border-color 0.2s, box-shadow 0.2s;
}
/* 帧提示词结构化显示：段名高亮、图N编号弱化、层级标题高亮 */
.flf-frame-prompt .flf-pp-label { color: var(--accent); font-weight: 600; }
.flf-frame-prompt .flf-pp-level { color: var(--info); font-weight: 600; }
.flf-frame-prompt .flf-pp-tag { color: var(--text-3); opacity: .55; font-size: 10px; }
.flf-frame-prompt .flf-pp-body { color: var(--text); }
.flf-frame-prompt:focus { border-color: var(--primary); box-shadow: 0 0 10px rgba(108, 140, 255, 0.18); }
.flf-frame-prompt[data-placeholder]:empty::before {
  content: attr(data-placeholder); color: var(--text-3);
}
/* --- 负面提示词（首尾帧页帧卡片；只用于生成该帧图） --- */
.flf-neg-head {
  display: flex; align-items: center; gap: 6px; flex-shrink: 0;
  font-size: 10px; color: var(--text-3); margin-top: 2px;
}
.flf-frame-neg {
  flex: 0 0 auto;                /* 不跟正面提示词抢空间 */
  min-height: 24px; max-height: 72px;
  font-size: 10px; color: var(--text-3);
  border-style: dashed; background: transparent;
}
.flf-frame-neg:focus { color: var(--text-2); border-style: solid; }
/* --- 帧卡片底部按钮行 --- */
.flf-row-bottom {
  display: flex; align-items: center; gap: 6px;
  padding-top: 8px; border-top: 1px solid var(--border);
  flex-shrink: 0;
}
/* --- 提示词列底部按钮 --- */
.flf-prompt-col .flf-row-bottom { border-top: 1px solid var(--border); padding-top: 8px; flex-wrap: wrap; }
/* 响应式：窄屏退化为单列 */
@media (max-width: 1024px) {
  .flf-shot-row { grid-template-columns: 1fr; height: auto; }
  .flf-frame-card { min-height: 300px; }
}

/* ================= 「⬇ 下载软件」弹窗（2026-10-07） =================
   用户："把这个打包和导入备份的按钮删除，改成下载软件，下载的时候要下载这个软件本身，
   还有下载所有的依赖…依赖直接从镜像上面下载"。逻辑在 static/js/software-download.js，
   后端在 routers/software.py（云端侧提供清单与打包，本机侧下载并解包）。
   类名统一 `sw-` 前缀，避免和宿主通用类撞车。 */
.sw-tip {
  font-size: 12.5px; line-height: 1.7; color: var(--text-2);
  background: var(--primary-light); border: 1px solid var(--border);
  border-radius: 8px; padding: 10px 12px; margin-bottom: 14px;
}
.sw-row { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; flex-wrap: wrap; }
.sw-lab { flex: none; width: 64px; font-size: 12.5px; color: var(--text-2); }
.sw-in {
  flex: 1 1 240px; min-width: 0; height: 32px; padding: 0 10px; border-radius: 8px;
  font: inherit; font-size: 12.5px; color: var(--text);
  background: var(--bg); border: 1px solid var(--border);
}
.sw-free { flex: none; font-size: 11.5px; color: var(--text-3); }
.sw-parts-head { display: flex; align-items: center; gap: 6px; margin: 14px 0 6px; font-size: 12.5px; color: var(--text-2); }
.sw-parts-head .sw-spacer { flex: 1 1 auto; }
.sw-parts { max-height: 38vh; overflow-y: auto; border: 1px solid var(--border); border-radius: 8px; }
.sw-parts:empty { border: 0; }
.sw-part {
  display: flex; align-items: flex-start; gap: 9px; padding: 9px 11px;
  border-bottom: 1px solid var(--border); cursor: pointer;
}
.sw-part:last-child { border-bottom: 0; }
.sw-part:hover { background: var(--primary-light); }
.sw-part.off { opacity: .5; cursor: not-allowed; }
.sw-part input { margin-top: 3px; flex: none; }
.sw-pmain { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.sw-pmain b { font-size: 12.5px; font-weight: 600; color: var(--text); }
.sw-pmain i { font-style: normal; font-size: 11.5px; color: var(--text-3); }
.sw-pmain em { font-style: normal; font-size: 11px; color: var(--text-3); }
.sw-empty { padding: 14px; font-size: 12.5px; color: var(--text-3); line-height: 1.7; }
.sw-prog { margin-top: 14px; }
.sw-bar { height: 8px; border-radius: 6px; overflow: hidden; background: var(--border); }
.sw-bar i { display: block; height: 100%; width: 0; background: var(--primary); transition: width .3s; }
.sw-pmsg { margin-top: 6px; font-size: 12px; color: var(--text-2); word-break: break-all; }
.sw-log {
  margin-top: 8px; max-height: 22vh; overflow: auto; padding: 8px 10px; border-radius: 8px;
  background: var(--bg); border: 1px solid var(--border);
  font: 11px/1.6 ui-monospace, Consolas, monospace; color: var(--text-2); white-space: pre-wrap;
}
.sw-foot-note { flex: 1 1 auto; font-size: 11.5px; color: var(--text-3); line-height: 1.6; }
.sw-link { color: var(--primary); text-decoration: underline; margin-left: 8px; }
.btn.sm { padding: 4px 9px; font-size: 11.5px; }
/* 「① 打成一个完整包」那张卡片 + 分区小标题（2026-10-07 用户："下载之后就能够直接使用，不用再安装任何依赖"） */
.sw-card { border: 1px solid var(--border); border-radius: 10px; padding: 12px 13px; margin-bottom: 14px; background: var(--bg); }
.sw-card-t { font-size: 13.5px; font-weight: 700; color: var(--text); margin-bottom: 8px; }
.sw-badge { font-size: 10.5px; font-weight: 600; color: #fff; background: var(--primary); border-radius: 6px; padding: 1px 6px; margin-left: 6px; vertical-align: 2px; }
.sw-tag { font-size: 10px; font-weight: 600; color: var(--primary); border: 1px solid var(--primary); border-radius: 5px; padding: 0 4px; margin-left: 6px; vertical-align: 1px; }
.sw-tag.opt { color: var(--text-3); border-color: var(--border); }
.sw-sep { height: 1px; background: var(--border); margin: 12px 0 10px; }
.sw-note { font-size: 11.5px; line-height: 1.7; color: var(--text-3); }
.sw-bundle-msg { flex: 1 1 auto; font-size: 12px; color: var(--text-2); }
.sw-bundle-bar { margin-top: 10px; }
.sw-bundle-log { max-height: 18vh; }

/* ============================================================
   入口选择层（云端实例打开软件时的两张卡片：云端使用 / 微信加入·本地端）
   2026-10-08 第一百七十轮新增，前端 static/js/entry-choice.js（只云端弹）。
   整层是**不透明全屏覆盖**（用户："只有这三个卡片"），z-index 压过所有弹窗。
   ============================================================ */
body.ec-locked { overflow: hidden; }
.ec-layer {
  position: fixed; inset: 0; z-index: 99999; overflow: auto;
  background: radial-gradient(1100px 620px at 18% -8%, rgba(108, 140, 255, 0.20), transparent 62%),
              radial-gradient(900px 560px at 92% 4%, rgba(167, 139, 250, 0.16), transparent 60%),
              var(--bg);
  padding: 40px 22px 34px;
}
.ec-wrap { max-width: 1220px; margin: 0 auto; }
.ec-head { display: flex; align-items: center; gap: 14px; margin-bottom: 26px; }
.ec-logo {
  width: 54px; height: 54px; flex: 0 0 auto; border-radius: 15px;
  display: flex; align-items: center; justify-content: center; font-size: 28px;
  background: linear-gradient(145deg, rgba(108, 140, 255, 0.28), rgba(34, 211, 238, 0.16));
  border: 1px solid var(--border-light);
}
.ec-brand { font-size: 23px; font-weight: 800; color: var(--text); letter-spacing: 0.5px; }
.ec-slogan { font-size: 13px; color: var(--text-2); margin-top: 3px; }

.ec-grid {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px; align-items: stretch;
  max-width: 1020px; margin: 0 auto;        /* 两卡版：限定宽度居中，别把两张卡拉成一整屏宽 */
}
@media (max-width: 1080px) { .ec-grid { grid-template-columns: 1fr; } .ec-layer { padding: 26px 14px; } }

.ec-card {
  display: flex; flex-direction: column; gap: 10px;
  background: var(--card); border: 1px solid var(--border); border-radius: 16px;
  padding: 20px 19px 18px; box-shadow: var(--shadow);
  border-top: 3px solid var(--border-light);
}
.ec-card-cloud { border-top-color: var(--primary); }
.ec-card-qr { border-top-color: var(--accent); }
.ec-icon { font-size: 30px; line-height: 1; }
.ec-title { font-size: 18px; font-weight: 800; color: var(--text); margin: 0; }
.ec-desc { font-size: 13px; line-height: 1.75; color: var(--text-2); margin: 0; }
.ec-desc strong { color: var(--text); }

.ec-warn {
  background: var(--danger-light); border-left: 3px solid var(--danger);
  border-radius: 0 9px 9px 0; padding: 10px 12px;
}
.ec-warn-t { font-size: 12.5px; font-weight: 700; color: var(--danger); margin-bottom: 6px; }
.ec-warn ul { margin: 0; padding-left: 17px; }
.ec-warn li { font-size: 12px; line-height: 1.72; color: var(--text-2); margin-bottom: 5px; }
.ec-warn li:last-child { margin-bottom: 0; }
.ec-warn b { color: var(--text); }

.ec-ok {
  font-size: 11.5px; line-height: 1.7; color: var(--text-2);
  background: var(--success-light); border-left: 3px solid var(--success);
  border-radius: 0 9px 9px 0; padding: 8px 11px;
}
.ec-muted { font-size: 11.5px; line-height: 1.7; color: var(--text-3); }
.ec-muted code {
  background: var(--bg); border: 1px solid var(--border); border-radius: 5px;
  padding: 0 5px; font-size: 11px; color: var(--text-2);
}
.ec-steps { margin: 0; padding-left: 18px; }
.ec-steps li { font-size: 12.5px; line-height: 1.8; color: var(--text-2); }

.ec-btn {
  width: 100%; flex: 0 0 auto; padding: 10px 14px; border-radius: 10px;
  border: 1px solid var(--border-light); background: var(--card-2); color: var(--text);
  font-size: 13.5px; font-weight: 700; cursor: pointer; transition: all 0.15s;
}
.ec-btn:hover { background: var(--card-2-hover); border-color: var(--primary); }
.ec-btn:disabled { opacity: 0.6; cursor: default; }
.ec-btn-primary {
  background: linear-gradient(135deg, var(--primary), var(--accent-2));
  border-color: transparent; color: #fff;
}
.ec-btn-primary:hover { filter: brightness(1.08); }
.ec-btn-ghost { background: transparent; }

/* 卡片内这些块要能被"顶"到最下面，卡片按钮才齐（`.ec-card-local` 已随「本地下载」卡撤掉） */
.ec-card-qr .ec-btn, .ec-card-cloud .ec-btn { margin-top: auto; }
.ec-card-cloud .ec-warn { margin-bottom: 4px; }

.ec-prog { margin-top: 2px; }
.ec-bar { height: 6px; border-radius: 99px; background: var(--bg); border: 1px solid var(--border); overflow: hidden; }
.ec-bar i { display: block; height: 100%; width: 4%; border-radius: 99px;
  background: linear-gradient(90deg, var(--primary), var(--accent)); transition: width 0.35s; }
.ec-prog-msg { font-size: 11.5px; color: var(--text-2); margin-top: 6px; }
.ec-fine { font-size: 11.5px; color: var(--text-3); line-height: 1.7; }
.ec-fine a { color: var(--primary); text-decoration: underline; }

.ec-qr-box {
  flex: 0 0 auto; display: flex; align-items: center; justify-content: center;
  min-height: 168px; padding: 10px; border-radius: 12px;
  background: #fff;                       /* 二维码要白底才扫得动 */
  border: 1px solid var(--border);
}
.ec-qr-empty {
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  color: #64748b; font-size: 12px; text-align: center; line-height: 1.7;
  background: var(--card); border: 1px dashed var(--border-light);
  border-radius: 10px; padding: 16px 18px; width: 100%;
}
.ec-qr-empty span { font-size: 11px; color: #94a3b8; }
.ec-qr-ph { font-size: 26px; color: var(--text-3); }
.ec-qr-img { max-width: 100%; max-height: 210px; border-radius: 8px; cursor: zoom-in; display: block; }
.ec-qr-ops { display: flex; align-items: center; gap: 10px; }
/* ⚠ 这里必须把 .ec-btn 的 width:100% 收回来：整行按钮 + 旁边那颗「清除」链接在 flex 行里，
   不收回来「清除」会被挤出卡片、整层横向溢出（2026-10-08 真机截图实测踩到）。 */
.ec-qr-ops .ec-btn { margin-top: 0; width: auto; flex: 1 1 auto; }
.ec-qr-clear { font-size: 11.5px; color: var(--text-3); text-decoration: underline; cursor: pointer; }
.ec-card-qr .ec-muted { margin-top: auto; }

/* 「本地端必须先扫码进群」这条硬要求（二维码上方那条，2026-10-14 两卡版新增） */
.ec-qr-req {
  font-size: 12.5px; font-weight: 700; line-height: 1.7; color: var(--warning);
  background: var(--warning-light); border-left: 3px solid var(--warning);
  border-radius: 0 9px 9px 0; padding: 9px 12px;
}

.ec-zoom {
  position: fixed; inset: 0; z-index: 100000; background: rgba(3, 7, 18, 0.86);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px; cursor: zoom-out;
}
.ec-zoom img { max-width: min(86vw, 520px); max-height: 74vh; background: #fff;
  border-radius: 14px; padding: 14px; box-shadow: var(--shadow-lg); }
.ec-zoom-tip { font-size: 12.5px; color: #cbd5e1; }

.ec-foot { margin-top: 22px; text-align: center; font-size: 12px; color: var(--text-3); line-height: 1.8; }
.ec-foot a { color: var(--primary); text-decoration: underline; }

/* ===== AI 优化提示词弹窗「用户自定义提示词」清单（2026-10-15，按用户给的参考界面） =====
   结构：带标题的边框盒子 → 每行（勾选「生效」+ 正文摘要单行省略 + #N）→ 底部虚线粘贴框 + 「添加」。
   ⚠ 行内正文必须 nowrap+ellipsis：规则正文动辄几千字，不省略整页会被撑爆。 */
.po-rule-box { border: 1px solid var(--border); border-radius: 8px; padding: 8px 10px 10px; background: var(--bg); }
.po-rule-head { font-size: 12px; font-weight: 600; color: var(--text-2); margin-bottom: 8px; }
.po-rule-item {
  display: flex; align-items: center; gap: 8px;
  border: 1px solid transparent; border-radius: 6px;
  padding: 5px 8px; margin-bottom: 4px; background: var(--card-2);
}
.po-rule-item.on { border-color: var(--border); }
/* ⚠ 类名不能用裸的 `.editing`（插件里也有这个通用类，宿主元素会被插件样式污染 ——
   check_css_collision.py 会拦），所以带 po- 前缀。 */
.po-rule-item.po-rule-editing { border-color: var(--primary); box-shadow: 0 0 8px rgba(108, 140, 255, 0.25); }
.po-rule-main { display: flex; align-items: center; gap: 8px; flex: 1 1 auto; min-width: 0; cursor: pointer; }
.po-rule-main input[type="checkbox"] { flex: 0 0 auto; cursor: pointer; }
.po-rule-on { flex: 0 0 auto; font-size: 12px; color: var(--text-2); }
/* 名称（用户自己起的 or 正文自动截取的头 16 字）：做成小胶囊，太长就省略号 */
.po-rule-name {
  flex: 0 0 auto; max-width: 24ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: 11.5px; font-weight: 600; color: var(--primary);
  background: var(--primary-light); border-radius: 4px; padding: 1px 6px;
}
.po-rule-text {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: 12.5px; color: var(--text);
}
.po-rule-act { flex: 0 0 auto; font-size: 12px; color: var(--text-3); text-decoration: none; }
.po-rule-act:hover { color: var(--text); }
.po-rule-no { flex: 0 0 auto; font-size: 11.5px; color: var(--text-3); min-width: 22px; text-align: right; }
.po-rule-add { display: flex; flex-direction: column; gap: 6px; margin-top: 8px; }
.po-rule-add-row { display: flex; align-items: center; gap: 8px; }
.po-rule-name-input {
  width: 100%; box-sizing: border-box; padding: 6px 10px; font-size: 12.5px;
  border: 1px solid var(--border); border-radius: 6px; background: transparent;
  color: var(--text); font-family: inherit; outline: none;
}
.po-rule-name-input:focus { border-color: var(--primary); }
.po-rule-name-input::placeholder { color: var(--text-3); }
.po-rule-add textarea {
  flex: 1 1 auto; min-width: 0; height: 46px; resize: vertical;
  border: 1px dashed var(--border); border-radius: 6px; background: transparent;
  color: var(--text); font-size: 12.5px; font-family: inherit; padding: 6px 10px; outline: none;
}
.po-rule-add textarea:focus { border-color: var(--primary); }
.po-rule-add textarea::placeholder { color: var(--text-3); }
.po-rule-add .btn { flex: 0 0 auto; align-self: stretch; height: auto; margin: 0; }
.po-rule-cancel { flex: 0 0 auto; cursor: pointer; margin-top: 0; }


/* ============ 剧本导入弹窗（2026-10-17 新增）============
   用户："这个软件的导入txt剧本是解析不出来的。要求能够导入这个txt,word,json等多种格式" —— 
   解析与切章在后端 `services/script_import.py`，这里只负责预览清单的排版。 */
.import-meta { font-size: 13px; color: var(--text-1); display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.import-note { width: 100%; font-size: 12px; color: var(--text-3); }
.import-mode { margin-top: 12px; display: flex; flex-direction: column; gap: 6px; font-size: 13px; }
.import-mode label { display: flex; align-items: center; gap: 6px; cursor: pointer; color: var(--text-1); }
.import-mode label input:disabled + span { color: var(--text-3); }
.import-mode-hint { font-size: 12px; color: var(--text-3); }
.import-list {
  margin-top: 12px; max-height: 46vh; overflow: auto;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--card-2); padding: 4px 12px;
}
.import-row {
  display: flex; justify-content: space-between; align-items: center; gap: 12px;
  padding: 7px 0; border-bottom: 1px dashed var(--border); font-size: 13px;
}
.import-row:last-child { border-bottom: none; }
.import-row-title { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text-1); }
.import-row-num { flex: 0 0 auto; font-size: 12px; color: var(--text-3); }
.import-row-more { justify-content: center; color: var(--text-3); font-size: 12px; }
/* 剧本导入：失败原因（留在弹窗里）+ 粘贴兜底区（2026-10-17 第二版） */
.import-error { color: var(--danger); font-weight: 600; }
.import-paste { margin-top: 14px; border-top: 1px dashed var(--border); padding-top: 10px; }
.import-paste > summary { cursor: pointer; font-size: 13px; color: var(--text-2); }
.import-paste > summary:hover { color: var(--text-1); }
.import-paste textarea {
  width: 100%; margin-top: 8px; resize: vertical;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--card-2); color: var(--text-1); font-family: inherit;
  font-size: 13px; line-height: 1.6; padding: 8px 10px; outline: none;
}
.import-paste textarea:focus { border-color: var(--primary); }
.import-paste-foot { display: flex; align-items: center; gap: 10px; margin-top: 8px; }
/* ============ AI 写剧本：⚡ 一键生成（快捷模式，2026-10-17）============
   模式芯片在顶部模型条里；快捷面板复用四步模式的题材芯片与写作参数条（DOM 搬家，不复制状态）。 */
.gen-quick-sub { margin-left: 8px; font-size: 12px; font-weight: 400; color: var(--text-3); }
.gen-chip-slot { min-height: 0; }
.gen-chip-slot .gen-wrap-bar,
.gen-chip-slot#gen-quick-params-slot > .gen-wrap-bar { margin: 0; padding: 0; border: 0; background: transparent; }
#gen-quick-idea { width: 100%; resize: vertical; min-height: 84px; line-height: 1.7; }
#gen-mode-chips .style-chip { font-size: 12.5px; }
/* ============ ⚡ 一键生成：两栏排版（2026-10-17 第二版）============
   左栏写故事设定（想法/人设/走向/禁忌），右栏选题材与剧本规格；
   题材芯片与写作参数条是从四步模式「搬」过来的同一份 DOM（`_mountGenControls`），
   所以这里只管容器与行的排版，不复制任何控件。 */
.quick-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.06fr) minmax(0, 1fr);
  gap: 20px 26px;
  align-items: start;
}
.quick-col { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
.quick-col .gen-field { margin: 0; }
.quick-col .form-label { display: block; margin-bottom: 6px; }
.quick-col textarea.form-input { line-height: 1.7; }
.gen-quick-sub { margin-left: 8px; font-size: 12px; font-weight: 400; color: var(--text-3); }

/* 写作参数条搬进右栏后：一张卡片里 6 行，标签固定宽度对齐，控件在右 */
.gen-chip-slot { min-width: 0; }
.gen-chip-card .gen-wrap-bar {
  display: flex; flex-direction: column; gap: 9px;
  margin: 0; padding: 12px 14px;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--card-2);
}
.gen-opt-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; min-width: 0; }
.gen-opt-row > .gen-start-label { flex: 0 0 62px; margin: 0; white-space: nowrap; }
.gen-opt-row > .gen-start-no,
.gen-opt-row > input.form-input { width: 74px; }
.gen-opt-row .style-chips { gap: 6px; flex-wrap: wrap; }
.gen-opt-row .style-chip { padding: 4px 9px; font-size: 12.5px; }
.gen-start-label-sm { flex: 0 0 auto !important; color: var(--text-3); }
/* 题材芯片搬进来时，与上方标签留一点空隙 */
#gen-quick-style-slot .style-chips { gap: 6px; }
#gen-quick-style-slot .gen-style-custom { width: 100%; }

@media (max-width: 1080px) {
  .quick-grid { grid-template-columns: minmax(0, 1fr); gap: 14px; }
}
/* ============ ⚡ 一键生成：v2 排版（2026-10-17 第三次调） ============
   要解决的三件事（截图实测）：
     ① 弹窗固定 92vh，一键模式内容少 → 下方一大片空白；
     ② 右栏「剧本规格」那几行被 `align-items:center` 在纵向 flex 里**水平居中**了，看着像错位；
     ③ 两栏没有分组感，芯片大小和间距不统一。 */
#modal-gen-script.qm-quick .modal { height: auto; max-height: 92vh; }
#modal-gen-script.qm-quick .modal-body { padding: 16px 18px 8px; }

.quick-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  gap: 16px;
  align-items: stretch;
}
.quick-col {
  display: flex; flex-direction: column; gap: 12px; min-width: 0;
  padding: 14px 16px 16px;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: linear-gradient(180deg, rgba(108,140,255,0.05), rgba(108,140,255,0) 42%);
}
.quick-col-head {
  display: flex; align-items: baseline; gap: 10px;
  padding-bottom: 10px; margin-bottom: 2px;
  border-bottom: 1px solid var(--border);
}
.quick-col-title { font-size: 14px; font-weight: 700; color: var(--text-1); letter-spacing: .2px; }
.quick-col-sub { font-size: 12px; color: var(--text-3); }
.quick-col .gen-field { margin: 0; gap: 6px; }
.quick-col .form-label { margin: 0; font-size: 12.5px; font-weight: 600; color: var(--text-2); }
.quick-col textarea.form-input { line-height: 1.7; }
.gen-quick-sub { margin-left: 6px; font-size: 11.5px; font-weight: 400; color: var(--text-3); }

/* 右栏：题材 / 卷数 芯片统一尺码，别一大一小 */
.quick-col .style-chips { gap: 7px; }
.quick-col .style-chip { padding: 5px 11px; font-size: 12.5px; line-height: 1.2; }
#gen-quick-style-slot .gen-style-custom { width: 100%; margin-top: 2px; }

/* 写作参数条搬进右栏：一张卡片 6 行，**左对齐**（之前纵向 flex 的 center 把它整片推右了） */
.gen-chip-slot { min-width: 0; }
.gen-chip-card .gen-wrap-bar {
  display: flex; flex-direction: column; align-items: stretch; gap: 8px;
  margin: 0; padding: 10px 12px 12px;
  border: 1px solid var(--border); border-radius: 10px;
  background: var(--card-2);
}
.gen-chip-card .gen-wrap-bar .foot-note { margin-left: 0; }
.gen-opt-row {
  display: flex; align-items: center; justify-content: flex-start;
  gap: 10px; flex-wrap: wrap; min-width: 0;
}
.gen-opt-row > .gen-start-label { flex: 0 0 60px; margin: 0; white-space: nowrap; font-size: 12.5px; }
.gen-opt-row > .gen-start-no,
.gen-opt-row > input.form-input { width: 66px; padding: 4px 8px; font-size: 12.5px; }
.gen-opt-row .style-chips { flex: 1 1 auto; gap: 6px; }
.gen-opt-row .style-chip { padding: 4px 9px; font-size: 12px; }
.gen-start-label-sm { flex: 0 0 auto !important; color: var(--text-3); }

/* 底部：说明别占满整行，按钮给固定宽度更稳 */
#gen-quick-hint { flex: 1 1 auto; max-width: 60%; line-height: 1.6; }
#gen-quick-start { flex: 0 0 auto; min-width: 168px; }

@media (max-width: 1080px) {
  .quick-grid { grid-template-columns: minmax(0, 1fr); }
}
/* ============ ⚡ 一键生成：v3 细节打磨 ============
   v2 截图复核后剩下的问题：左栏底部空一截、说明文字太淡太小、模型下拉在快捷模式下太宽、没有副标题。 */
#modal-gen-script.qm-quick #gen-model { min-width: 150px; max-width: 240px; }
.gen-head-sub { font-size: 12px; color: var(--text-3); font-weight: 400; letter-spacing: .2px; }
#modal-gen-script.qm-quick .gen-head-sub { display: inline; }
#modal-gen-script:not(.qm-quick) .gen-head-sub { display: none; }

/* 左栏：主字段（一句话想法）给更高的输入区，其余按内容；整列用更大行距填满高度 */
.quick-col { gap: 14px; }
.quick-col .gen-field { gap: 7px; }
#gen-quick-idea { min-height: 92px; }
.gen-quick-sub { font-size: 12px; color: var(--text-2); opacity: .85; }
.quick-col .form-label { color: var(--text-1); }

/* 右栏规格卡：6 行之间松一点，标签与控件基线对齐 */
.gen-chip-card .gen-wrap-bar { gap: 10px; padding: 12px 13px; }
.gen-opt-row > .gen-start-label { color: var(--text-2); }
.gen-opt-row > input.form-input { text-align: center; }
/* ============ ⚡ 一键生成：v4 分组与留白收尾 ============ */
/* 规格卡里「写作口径」（视角/节奏/基调）与前 3 行用一条虚线分开，小标题只在快捷模式显示 */
.gen-opt-sep { display: none; }
.gen-chip-card .gen-opt-sep {
  display: block; margin-top: 2px; padding-top: 9px;
  border-top: 1px dashed var(--border);
  font-size: 11.5px; color: var(--text-3); letter-spacing: .4px;
}
/* 左栏底部提示：margin-top:auto 把两栏的空白吃掉，视觉上更平衡 */
.quick-col-tip {
  margin-top: auto; padding-top: 4px;
  font-size: 12px; line-height: 1.7; color: var(--text-3);
}
#gen-quick-hint { color: var(--text-2); }
/* ============ 角色「音色描述」展示（2026-10-17）：AI 提取的 音色：… 落 voice_desc ============ */
.a-voice-desc {
  margin-top: 2px; font-size: 12px; line-height: 1.55; color: var(--text-2);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.ai-item-voice { color: var(--text-2); }
.ai-voice-tag {
  display: inline-block; margin-right: 6px; padding: 0 6px; border-radius: 4px;
  background: var(--primary-light); color: var(--primary); font-size: 11.5px;
}
/* ============ 一键生成全部角色声音（2026-10-17）============
   ⚠ 原来的弹窗（`.vb-list/.vb-row/.vb-name/.vb-desc/.vb-st`）在「第三版：不要弹窗」时整段删掉了，
   现在只剩页内进度条 + 卡片状态这两组样式（弹窗 DOM 与那套 CSS 都已移除）。 */
/* ============ 一键生成声音：页内进度条（不弹窗，2026-10-17）============ */
.voice-strip {
  display: flex; align-items: center; gap: 10px;
  margin: 0 0 10px; padding: 8px 12px;
  border: 1px solid var(--border); border-radius: 8px; background: var(--card-2);
  font-size: 12.5px; color: var(--text-2);
}
.voice-strip-text { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.voice-strip-bar { flex: 0 0 180px; height: 6px; border-radius: 3px; background: var(--border); overflow: hidden; }
.voice-strip-bar > i { display: block; height: 100%; width: 0; background: var(--primary); transition: width .25s ease; }
.a-voice-hint { font-size: 12px; color: var(--text-3); }

/* ============================================================================
   工作流节点图预览（宿主版 static/js/wf-preview.js，2026-10-18）
   与导演台插件里的节点图是同一套外观，类名统一 wf-pv-*（宿主全局 CSS，别用 cv- 前缀）。
   入口：🧩 工作流 → 每一行右侧的「🕸」按钮。
   ============================================================================ */
/* ============================================================================
   工作流节点图预览（dd-wfpreview.js，2026-10-18，插件 2.9.253）
   入口：🧩 工作流 → 「参数 / JSON」→「工作流 JSON（可编辑）」标题右边那颗
   「🕸 预览节点图」。用 API 格式 JSON 画成 ComfyUI 风格的节点图：
   看连线 / 删节点（Delete）/ 双击或右键空白加节点（节点清单来自本机全部已导入工作流）。
   类名统一 wf-pv-*；宿主全局 CSS，改完跑 tools/check_css_collision.py。
   ============================================================================ */
/* 工作流弹窗里的「工作流 JSON」标题行：左边标题 + 右边预览按钮 */

/* ---------- 遮罩 / 面板 ---------- */
.wf-pv-mask {
  position: fixed; inset: 0; z-index: 10050;
  background: rgba(5, 8, 16, .66);
  display: flex; align-items: center; justify-content: center;
}
.wf-pv {
  width: min(96vw, 1500px); height: min(92vh, 940px);
  display: flex; flex-direction: column; overflow: hidden;
  background: #0B1020; border: 1px solid #26314d; border-radius: 14px;
  box-shadow: 0 26px 70px rgba(0, 0, 0, .55);
  color: #E5EDF8; font: 13px/1.5 "Microsoft YaHei", system-ui, sans-serif;
}
.wf-pv-head {
  flex: none; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; row-gap: 6px;
  padding: 9px 12px; border-bottom: 1px solid #1c2740;
  background: linear-gradient(180deg, #121b30, #0d1424);
}
.wf-pv-ico { font-size: 16px; }
.wf-pv-title { font-weight: 700; font-size: 13.5px; max-width: 320px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wf-pv-stat { font-size: 11px; color: #8ea0be; white-space: nowrap; }
.wf-pv-stat.dirty { color: #ffc861; }
.wf-pv .btn {
  flex: none; background: rgba(255, 255, 255, .08); border-color: rgba(255, 255, 255, .16); color: #E5EDF8;
}
.wf-pv .btn:hover { background: rgba(124, 92, 255, .22); border-color: rgba(167, 139, 250, .55); color: #fff; }
.wf-pv .btn.primary {
  background: linear-gradient(135deg, #8b5cf6, #7c5cff); border-color: transparent; color: #fff; font-weight: 600;
}
.wf-pv .btn.primary:hover { filter: brightness(1.08); color: #fff; }
/* 窗口窄（工坊弹窗本身只有 ~670px 宽时）：顶部按钮只留图标，保存按钮保留文字 */
@media (max-width: 1180px) {
  .wf-pv .wf-pv-lbl { display: none; }
  .wf-pv .wf-pv-save .wf-pv-lbl { display: inline; }
  .wf-pv .wf-pv-save { margin-left: auto; }
}

/* ---------- 画布（点阵底 + 可平移） ---------- */
.wf-pv-stage {
  position: relative; flex: 1 1 auto; min-height: 0; overflow: hidden;
  background-color: #0e1424; cursor: grab;
  background-image: radial-gradient(rgba(255, 255, 255, .085) 1px, transparent 1px);
  background-size: 18px 18px;
}
.wf-pv-stage.panning { cursor: grabbing; }
.wf-pv-world {
  position: absolute; left: 0; top: 0; width: 1px; height: 1px;
  transform-origin: 0 0;
}
.wf-pv-svg { position: absolute; left: 0; top: 0; width: 1px; height: 1px; overflow: visible; pointer-events: none; }
.wf-pv-edge { fill: none; stroke-width: 2.4; stroke-linecap: round; opacity: .95; }
.wf-pv-edge.on { stroke: #fff !important; stroke-width: 3.4; filter: drop-shadow(0 0 5px rgba(255, 255, 255, .9)); }
.wf-pv-edge-hit { fill: none; stroke: transparent; stroke-width: 16; pointer-events: stroke; cursor: pointer; }

/* ---------- 节点 ---------- */
.wf-pv-node {
  position: absolute; width: 236px; box-sizing: border-box;
  background: #1a2337; border: 1px solid #2b3957; border-radius: 8px;
  box-shadow: 0 8px 22px rgba(0, 0, 0, .45);
  user-select: none; cursor: move;
}
.wf-pv-node.on {
  border-color: #a78bfa;
  box-shadow: 0 0 0 2px rgba(167, 139, 250, .5), 0 10px 26px rgba(0, 0, 0, .5);
}
.wf-pv-nh {
  display: flex; align-items: center; gap: 6px; height: 26px; box-sizing: border-box;
  padding: 0 8px; border-radius: 7px 7px 0 0; background: var(--c, #3f4859);
}
.wf-pv-nt { font-size: 11.5px; font-weight: 600; color: #fff; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wf-pv-nc {
  margin-left: auto; flex: none; max-width: 46%;
  font-size: 9.5px; color: rgba(255, 255, 255, .68);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.wf-pv-nb { padding: 3px 0 6px; }
.wf-pv-in { position: relative; display: flex; align-items: center; gap: 6px; height: 19px; padding: 0 8px; box-sizing: border-box; }
.wf-pv-k {
  flex: none; max-width: 58%; font-size: 10.5px; color: #a9b8d2;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.wf-pv-v {
  margin-left: auto; min-width: 0; max-width: 60%;
  font-family: ui-monospace, Consolas, monospace; font-size: 10px; color: #e7eefc;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* 模型 / LoRA 文件名：点一下出候选菜单（2026-10-18） */
.wf-pv-pick { cursor: pointer; text-decoration: underline dotted rgba(167, 139, 250, .65); text-underline-offset: 2px; }
.wf-pv-pick:hover { color: #c9b8ff; }
.wf-pv-dot {
  position: absolute; left: -5px; top: 50%; width: 9px; height: 9px; margin-top: -4.5px;
  box-sizing: border-box; border-radius: 50%; background: #0e1424; border: 2px solid #7c8fb5;
}
.wf-pv-outs { position: absolute; right: -5px; top: 32px; display: flex; flex-direction: column; gap: 6px; }
.wf-pv-dot.out { position: static; margin: 0; border-color: #8ea0be; }

/* ---------- 提示 / 缩放 ---------- */
.wf-pv-hint {
  position: absolute; left: 10px; bottom: 9px; z-index: 3; max-width: min(60%, 720px);
  font-size: 10px; line-height: 1.6; color: #93a3bc;
  background: rgba(10, 16, 30, .72); border: 1px solid rgba(255, 255, 255, .08);
  border-radius: 8px; padding: 4px 8px; pointer-events: none;
}
.wf-pv-zoom {
  position: absolute; right: 12px; bottom: 10px; z-index: 3;
  display: flex; align-items: center; gap: 5px;
  background: rgba(10, 16, 30, .82); border: 1px solid rgba(255, 255, 255, .10); border-radius: 9px; padding: 3px 5px;
}
.wf-pv-zbtn {
  border: 1px solid rgba(255, 255, 255, .14); background: rgba(255, 255, 255, .06); color: #E5EDF8;
  border-radius: 6px; width: 22px; height: 22px; line-height: 1; font-size: 13px; cursor: pointer; padding: 0;
}
.wf-pv-zbtn.wide { width: auto; padding: 0 8px; font-size: 11px; }
.wf-pv-zbtn:hover { background: rgba(124, 92, 255, .28); border-color: rgba(167, 139, 250, .5); }
.wf-pv-zval { font-size: 10.5px; color: #b9c6dd; min-width: 38px; text-align: center; }

/* ---------- 添加节点面板（ComfyUI Add Node） ---------- */
.wf-pv-pl {
  position: absolute; z-index: 5; width: 330px; max-height: 430px;
  display: flex; flex-direction: column; overflow: hidden;
  background: #111a2e; border: 1px solid #2b3957; border-radius: 10px;
  box-shadow: 0 16px 40px rgba(0, 0, 0, .55);
}
.wf-pv-pl.hidden { display: none; }
.wf-pv-pl-head { flex: none; display: flex; align-items: center; gap: 6px; padding: 7px 8px; border-bottom: 1px solid #1e2a44; }
.wf-pv-pl-ico { color: #a78bfa; font-weight: 700; }
.wf-pv-pl-q {
  flex: 1; min-width: 0; background: rgba(255, 255, 255, .07); border: 1px solid rgba(255, 255, 255, .16);
  color: #E5EDF8; border-radius: 7px; padding: 5px 8px; font: inherit; font-size: 12px;
}
.wf-pv-pl-q:focus { outline: none; border-color: var(--cv-accent, #7c5cff); }
.wf-pv-pl-list { flex: 1 1 auto; min-height: 0; overflow: auto; padding: 4px 5px 8px; }
.wf-pv-pcat { font-size: 10px; color: #7f90ad; padding: 6px 6px 3px; letter-spacing: .5px; }
.wf-pv-pi {
  display: flex; align-items: center; gap: 7px; width: 100%; text-align: left;
  border: 1px solid transparent; background: transparent; color: #E5EDF8;
  border-radius: 7px; padding: 5px 7px; cursor: pointer; font: inherit;
}
.wf-pv-pi:hover { background: rgba(124, 92, 255, .18); border-color: rgba(167, 139, 250, .4); }
.wf-pv-pidot { flex: none; width: 8px; height: 8px; border-radius: 50%; }
.wf-pv-pin { font-size: 11.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 46%; }
.wf-pv-pic {
  margin-left: auto; flex: none; max-width: 48%; font-size: 9.5px; color: #8ea0be;
  font-family: ui-monospace, Consolas, monospace; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.wf-pv-pempty { font-size: 11px; color: #93a3bc; line-height: 1.7; padding: 10px 8px; }
/* 从输出口拖线松手后弹出的节点面板：顶部说明「这根线会接到你选的节点」 */
.wf-pv-pl-tip {
  font-size: 10.5px; line-height: 1.6; color: #cdc3ff;
  background: rgba(124, 92, 255, .18); border: 1px solid rgba(167, 139, 250, .45);
  border-radius: 7px; padding: 5px 8px; margin: 2px 4px 6px;
}

/* ---------- 右键菜单 ---------- */
.wf-pv-menu {
  position: absolute; z-index: 6; width: 190px; padding: 4px; max-height: 360px; overflow: auto;
  background: #111a2e; border: 1px solid #2b3957; border-radius: 9px;
  box-shadow: 0 14px 36px rgba(0, 0, 0, .55);
}
.wf-pv-menu.hidden { display: none; }
.wf-pv-mi {
  display: block; width: 100%; text-align: left; font: inherit; font-size: 12px;
  color: #E5EDF8; background: transparent; border: none; border-radius: 6px; padding: 6px 9px; cursor: pointer;
}
.wf-pv-mi:hover { background: rgba(124, 92, 255, .22); }
.wf-pv-mi.danger { color: #ffb4b4; }
.wf-pv-mi.danger:hover { background: rgba(239, 68, 68, .22); }

/* 连线（2026-10-18）：输出口拖到输入口 */
.wf-pv-dot.in, .wf-pv-dot.out { cursor: crosshair; }
.wf-pv-dot.empty { border-style: dashed; border-color: #5c6f92; background: #131c2f; }
.wf-pv-dot:hover { border-color: #c9b8ff; background: #2a3350; }
.wf-pv-edge.temp { stroke: #c9b8ff; stroke-dasharray: 6 5; pointer-events: none; }
.wf-pv-stage.linking .wf-pv-edge,
.wf-pv-stage.linking .wf-pv-edge-hit { pointer-events: none; }
.wf-pv-in.drop { background: rgba(167, 139, 250, .20); }
.wf-pv-in.drop .wf-pv-dot { background: #a78bfa; border-color: #d9cfff; box-shadow: 0 0 8px rgba(167, 139, 250, .8); }

/* ── 内置 harness（右侧「🤖 AI 助手」侧栏，2026-10-18）─────────────────────
   结构见 static/js/manju-dock.js；harness 本体由 plugins/harness/backend.py
   随软件启动自动拉起（127.0.0.1:3082，profile=manju）。改这里要同时看那个 js。 */
.harness-btn { position: relative; }
.harness-btn.active { background: var(--primary-light); color: var(--text); border-color: var(--primary); }
.harness-dot {
  display: inline-block; width: 7px; height: 7px; border-radius: 50%;
  margin-left: 6px; vertical-align: middle; background: var(--text-3);
}
.harness-dot.on { background: var(--success); box-shadow: 0 0 6px var(--success); }
.harness-dot.off { background: var(--danger); }
.harness-dot.wait { background: var(--warning); animation: hd-pulse 1.1s ease-in-out infinite; }
@keyframes hd-pulse { 0%, 100% { opacity: .35; } 50% { opacity: 1; } }

/* AI 助手 = **右侧固定分栏**（不是浮窗、不是遮罩）：
   - 面板贴死右边、通到底，宽度默认 900（最小 760）
   - 打开时给 #app 让出同样的宽度（body.harness-dock-open #app），软件内容**不会被盖住**
   宽度写在 CSS 变量 --hd-w 上，由 manju-dock.js 更新（拖左边缘可调）。 */
.harness-dock {
  position: fixed; top: 0; right: 0; bottom: 0; z-index: 900;
  width: 600px; min-width: 300px; max-width: 600px;
  display: none; flex-direction: column;
  background: var(--card); border-left: 1px solid var(--border-light);
  box-shadow: -16px 0 40px rgba(4, 8, 20, .45);
}
.harness-dock.open { display: flex; }

/* 打开时把软件布局压窄：右侧那一条归 AI 助手，软件不占用 */
body.harness-dock-open #app { width: calc(100% - var(--hd-w, 600px)); }
body.harness-dock-open.hd-resizing #app { transition: none; }

.hd-head {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 8px 10px 8px 12px; border-bottom: 1px solid var(--border); flex: 0 0 auto;
}
.hd-title { display: flex; align-items: center; gap: 8px; color: var(--text); font-size: 13px; font-weight: 600; }
.hd-logo { font-size: 15px; }
.hd-status { color: var(--text-3); font-size: 11px; font-weight: 400; margin-left: 2px; }
.hd-tools { display: flex; align-items: center; gap: 4px; }
.hd-icon {
  border: 1px solid transparent; background: transparent; color: var(--text-2);
  width: 26px; height: 26px; border-radius: 6px; cursor: pointer; font-size: 13px; line-height: 1;
}
.hd-icon:hover { background: var(--bg-hover); color: var(--text); border-color: var(--border-light); }

.hd-badge {
  display: none; flex: 0 0 auto; margin: 6px 10px 0; padding: 6px 10px;
  border-radius: 6px; cursor: pointer; font-size: 12px; text-align: left;
  color: #0a1220; background: var(--accent); border: none; font-weight: 600;
}
.hd-badge.show { display: block; }

.hd-body { position: relative; flex: 1 1 auto; min-height: 0; display: flex; }
.hd-frame { flex: 1 1 auto; width: 100%; height: 100%; border: none; background: var(--bg); }
.hd-hint {
  position: absolute; inset: 0; display: none; flex-direction: column; gap: 12px;
  align-items: center; justify-content: center; padding: 24px; text-align: center;
  background: var(--card); color: var(--text-2); font-size: 13px; line-height: 1.7;
}
.hd-hint-text { max-width: 380px; word-break: break-word; }

/* 左边缘：拖宽（软件那侧跟着让位）。
   抓手做成 18px 宽、跨在分界线上（一半在面板外），中间一条亮线 + 三个点，
   鼠标靠近就好抓；拖动时显示当前宽度。 */
.hd-grip {
  position: absolute; left: -9px; top: 0; bottom: 0; width: 18px;
  cursor: col-resize; touch-action: none; z-index: 5;
  background: transparent;
}
.hd-grip::before {
  content: ''; position: absolute; left: 8px; top: 0; bottom: 0; width: 2px;
  background: var(--border-light); transition: background .15s, box-shadow .15s;
}
.hd-grip::after {
  content: ''; position: absolute; left: 6px; top: 50%; width: 6px; height: 34px;
  transform: translateY(-50%); border-radius: 3px;
  background:
    radial-gradient(circle, var(--text-3) 1.2px, transparent 1.4px) center/100% 10px repeat-y;
  opacity: 0; transition: opacity .15s;
}
.hd-grip:hover::before { background: var(--primary); box-shadow: 0 0 0 1px rgba(108, 140, 255, .35); }
.hd-grip:hover::after { opacity: 1; }
/* ⚠ 2026-10-18：把裸的 `.dragging` 加上 `.harness-dock` 锚点。
   原来写 `.dragging .hd-grip::before`（裸类当祖先）→ 与导演台插件的 `.cv-refs.dragging`
   **同名撞车**（`tools/check_css_collision.py --strict` 报 1 个）。宿主那条本来就只作用于
   侧栏自己的 `.hd-grip`，加锚点后行为完全不变（`panel` 同时带 `harness-dock` + `dragging`），
   但宿主类名集合里不再出现裸 `dragging`。 */
.harness-dock.hd-dragging .hd-grip::before { background: var(--primary); box-shadow: 0 0 0 1px rgba(108, 140, 255, .5); }
.harness-dock.hd-dragging .hd-grip::after { opacity: 1; }

/* 拖动时跟在鼠标旁边的宽度提示 */
.hd-width-tip {
  position: fixed; z-index: 950; pointer-events: none;
  padding: 3px 8px; border-radius: 6px; font-size: 12px; line-height: 1.4;
  color: #0a1220; background: var(--accent); font-weight: 600;
  transform: translate(-50%, -50%); box-shadow: 0 4px 14px rgba(4, 8, 20, .4);
}
body.hd-resizing { cursor: col-resize; user-select: none; }

/* 首页（登入页）没有顶栏 → 右下角悬浮按钮兜底 */
.harness-float {
  position: fixed; right: 22px; bottom: 22px; z-index: 880;
  width: 46px; height: 46px; border-radius: 50%; border: 1px solid var(--border-light);
  background: var(--card-2); color: var(--text); font-size: 20px; cursor: pointer;
  display: none; align-items: center; justify-content: center;
  box-shadow: 0 10px 26px rgba(4, 8, 20, .55);
}
.harness-float:hover { background: var(--card-2-hover); border-color: var(--primary); }
