/* ============================================================================
   批量洗剧工作台 — style.css
   深色专业工具界面（Soft-UI）。无外部依赖，除 Google Fonts 的 Inter。
   ========================================================================= */

/* ===== design tokens ===== */
:root {
  --bg: #0F172A;
  --surface: #161F35;
  --surface-2: #1D2742;
  --muted: #201A32;
  --border: rgba(255, 255, 255, .08);
  --border-strong: rgba(255, 255, 255, .16);
  --fg: #FFFFFF;
  --fg-muted: #94A3B8;
  --fg-dim: #64748B;
  --primary: #EC4899;
  --primary-hover: #DB2777;
  /* 承白色文字的实心面用更深一档：#DB2777 对白字 4.60:1，达 WCAG AA。
     --primary 保留给描边/焦点环/图标/进度条等非文字场景。 */
  --primary-solid: #DB2777;
  --primary-solid-hover: #BE185D;
  --on-primary: #FFFFFF;
  --accent: #2563EB;
  --success: #10B981;
  --warn: #F59E0B;
  --danger: #DC2626;
  --ring: #EC4899;
  --radius: 12px;
  --radius-lg: 16px;
  --shadow-soft: 0 4px 16px rgba(0, 0, 0, .28), 0 1px 2px rgba(0, 0, 0, .24);

  --sp-1: 4px;
  --sp-2: 8px;
  --sp-3: 12px;
  --sp-4: 16px;
  --sp-5: 20px;
  --sp-6: 24px;
  --sp-8: 32px;

  --dur-fast: 150ms;
  --dur: 200ms;
  --dur-slow: 250ms;
  --ease: cubic-bezier(.32, .72, 0, 1);

  --z-topbar: 40;
  --z-drawer: 60;
  --z-console: 50;
  --z-toast: 100;

  --font: Inter, system-ui, -apple-system, "PingFang SC", "Microsoft YaHei", sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;

  /* --- 主题语义 token ---
     深色值写在 :root，浅色值在文件末尾 html[data-theme="light"] 里整体重定义。
     组件 CSS 只用这些 token，不直接写「某个主题下的颜色」。 */
  --code-bg: rgba(255, 255, 255, .05);
  --subtle-bg: rgba(255, 255, 255, .05);
  --subtle-bg-strong: rgba(255, 255, 255, .06);
  --subtle-bg-strong-hover: rgba(255, 255, 255, .16);
  --hover-bg: rgba(255, 255, 255, .04);
  --hover-bg-faint: rgba(255, 255, 255, .015);
  --row-hover: rgba(255, 255, 255, .03);
  --hover-bg-strong: #24304F;
  --border-hover: rgba(255, 255, 255, .24);
  --border-hover-strong: rgba(255, 255, 255, .28);
  --spinner-track: rgba(255, 255, 255, .25);
  --scroll-thumb: rgba(255, 255, 255, .14);
  --scroll-thumb-hover: rgba(255, 255, 255, .26);

  /* 状态文字色（浅色主题下要整体压深，否则白底上看不见） */
  --danger-fg: #FCA5A5;
  --danger-fg-strong: #F87171;
  --warn-fg: #FCD34D;
  --success-fg: #6EE7B7;
  --info-fg: #93C5FD;
  --primary-fg: #F9A8D4;

  /* 光晕 / 遮罩 / 阴影 */
  --glow-primary: rgba(236, 72, 153, .18);
  --glow-primary-strong: rgba(236, 72, 153, .55);
  --glow-accent: rgba(37, 99, 235, .18);
  --selection-bg: rgba(236, 72, 153, .32);
  --scrim: rgba(4, 8, 20, .62);
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, .32);
  --shadow-card: 0 6px 18px rgba(0, 0, 0, .22);
  --shadow-pop: 0 18px 40px rgba(0, 0, 0, .48), 0 2px 8px rgba(0, 0, 0, .38);
  --shadow-modal: 0 24px 60px rgba(0, 0, 0, .5), 0 2px 8px rgba(0, 0, 0, .4);
  --shadow-drawer: -16px 0 40px rgba(0, 0, 0, .42);
  --shadow-auth: 0 24px 60px rgba(0, 0, 0, .38);
}

/* ===== reset ===== */
*, *::before, *::after { box-sizing: border-box; }

html, body {
  height: 100%;
  margin: 0;
  padding: 0;
}

body {
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font);
  font-size: 14px;
  line-height: 1.5;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow: hidden;
}

h1, h2, h3, h4, p, dl, dd, dt, figure { margin: 0; }
ul, ol { margin: 0; padding: 0; list-style: none; }
button, input, select, textarea { font: inherit; color: inherit; }
code { font-family: var(--mono); font-size: .92em; color: var(--fg-muted); background: var(--code-bg); padding: 1px 5px; border-radius: 6px; }
svg { display: block; flex: none; }
[hidden] { display: none !important; }
/* 平台级入口（LLM 设置 / 适配器配置）：普通租户直接不显示。
   角色由 user-menu.js 写在 <html data-user-role> 上，四个页面共用一条规则。 */
html[data-user-role="user"] .admin-only { display: none !important; }

:focus { outline: none; }
:focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: 2px;
  border-radius: 6px;
}

::selection { background: var(--selection-bg); }

/* scrollbars */
* { scrollbar-width: thin; scrollbar-color: var(--scroll-thumb) transparent; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--scroll-thumb); border-radius: 8px; border: 2px solid transparent; background-clip: content-box; }
::-webkit-scrollbar-thumb:hover { background: var(--scroll-thumb-hover); background-clip: content-box; }

.tabular, .data-table, .kv, .stat, .job-card__meta, .mini-job, .mono { font-variant-numeric: tabular-nums; }
.mono { font-family: var(--mono); }

/* ===== app shell ===== */
.app {
  display: grid;
  grid-template-rows: auto auto minmax(0, 1fr) auto;
  height: 100dvh;
  overflow: hidden;
}

/* ===== topbar ===== */
.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  min-height: 56px;
  padding: var(--sp-2) var(--sp-5);
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  /* 顶栏钉在窗口顶部：中间内容再长、滚动的也只有中间那一块。
     （曾经因为右栏 scrollIntoView 把整个文档滚了一下，顶栏整条跑到屏幕外） */
  position: sticky;
  top: 0;
  z-index: var(--z-topbar);
  flex: none;
}

.topbar__left { display: flex; align-items: center; gap: var(--sp-3); min-width: 0; }
.topbar__right { display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; justify-content: flex-end; }

.brand { display: flex; align-items: center; gap: var(--sp-3); min-width: 0; }
.brand__mark {
  display: grid;
  place-items: center;
  width: 32px; height: 32px;
  border-radius: 10px;
  background: linear-gradient(140deg, rgba(236,72,153,.22), rgba(37,99,235,.22));
  border: 1px solid var(--border-strong);
  color: var(--primary);
}
.brand__mark svg { width: 18px; height: 18px; }
.brand__text { display: flex; flex-direction: column; min-width: 0; }
.brand__title { font-size: 14px; font-weight: 600; letter-spacing: .01em; white-space: nowrap; }
.brand__sub {
  font-size: 12px;
  color: var(--fg-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 280px;
}

.status-pill {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  height: 28px;
  padding: 0 var(--sp-3);
  border-radius: 999px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  font-size: 12px;
  color: var(--fg-muted);
  white-space: nowrap;
}
.status-pill__dot { width: 8px; height: 8px; border-radius: 50%; background: var(--fg-dim); flex: none; }
.status-pill__dot.is-ok { background: var(--success); box-shadow: 0 0 0 3px rgba(16,185,129,.16); }
.status-pill__dot.is-bad { background: var(--danger); box-shadow: 0 0 0 3px rgba(220,38,38,.16); }
.status-pill__text { font-variant-numeric: tabular-nums; }

.control { display: flex; align-items: center; gap: var(--sp-2); }
.control__label { font-size: 12px; color: var(--fg-muted); white-space: nowrap; }

.mini-job {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-width: 180px;
  max-width: 280px;
}
.mini-job__track {
  position: relative;
  flex: 1;
  height: 6px;
  min-width: 60px;
  border-radius: 999px;
  background: var(--surface-2);
  overflow: hidden;
}
.mini-job__fill {
  height: 100%;
  width: 0%;
  border-radius: 999px;
  background: var(--primary);
  transition: width var(--dur-slow) var(--ease);
}
.mini-job__text {
  font-size: 12px;
  color: var(--fg-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 130px;
}

/* ===== connection banner ===== */
.conn-banner {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-5);
  background: rgba(245, 158, 11, .12);
  border-bottom: 1px solid rgba(245, 158, 11, .28);
  color: var(--warn);
  font-size: 13px;
}
.conn-banner svg { width: 16px; height: 16px; }

/* ===== layout ===== */
.layout {
  display: grid;
  grid-template-columns: 260px minmax(0, 1fr);
  min-height: 0;
  overflow: hidden;
}

/* ===== sidebar ===== */
.sidebar {
  display: flex;
  flex-direction: column;
  min-height: 0;
  background: var(--surface);
  border-right: 1px solid var(--border);
}
.sidebar__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-2);
  padding: var(--sp-3) var(--sp-4);
  border-bottom: 1px solid var(--border);
}
.sidebar__title { font-size: 12px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--fg-muted); }
.sidebar__foot { padding: var(--sp-3) var(--sp-4); font-size: 11px; color: var(--fg-muted); border-top: 1px solid var(--border); word-break: break-all; }

.project-list { flex: 1; overflow-y: auto; padding: var(--sp-2); display: flex; flex-direction: column; gap: var(--sp-1); }

.project-item {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  width: 100%;
  min-height: 56px;
  padding: var(--sp-2);
  border-radius: var(--radius);
  border: 1px solid transparent;
  background: transparent;
  cursor: pointer;
  text-align: left;
  transition: background var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.project-item:hover { background: var(--surface-2); border-color: var(--border); }
.project-item.is-selected { background: var(--surface-2); border-color: var(--border-strong); box-shadow: inset 2px 0 0 var(--primary); }
.project-item__cover {
  position: relative;
  width: 40px; height: 40px;
  flex: none;
  border-radius: 10px;
  overflow: hidden;
  background: var(--surface-2);
  border: 1px solid var(--border);
  display: grid;
  place-items: center;
  color: var(--fg-muted);
}
.project-item__cover img { width: 100%; height: 100%; object-fit: cover; }
.project-item__cover svg { width: 18px; height: 18px; }
.project-item__main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.project-item__name { font-size: 13px; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.project-item__meta { display: flex; align-items: center; gap: var(--sp-2); font-size: 11px; color: var(--fg-muted); white-space: nowrap; }
.project-item__del { opacity: 0; transition: opacity var(--dur-fast) var(--ease); }
.project-item:hover .project-item__del,
.project-item:focus-within .project-item__del { opacity: 1; }

/* ===== main ===== */
.main { display: flex; flex-direction: column; min-width: 0; min-height: 0; overflow: hidden; }
.main__scroll { flex: 1; min-height: 0; overflow-y: auto; overflow-x: hidden; padding: var(--sp-5); }
.mobile-bar { display: none; padding: var(--sp-2) var(--sp-4) 0; }

.workspace { display: flex; flex-direction: column; gap: var(--sp-5); min-width: 0; }
.workspace__head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--sp-4); flex-wrap: wrap; }
.workspace__title { font-size: 20px; font-weight: 600; letter-spacing: -.01em; }
.workspace__meta { font-size: 12px; color: var(--fg-muted); margin-top: 2px; }

/* ===== section / panel ===== */
.panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-soft);
  min-width: 0;
  overflow: hidden;
}
.panel__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  padding: var(--sp-4);
  border-bottom: 1px solid var(--border);
  flex-wrap: wrap;
}
.panel__title { font-size: 14px; font-weight: 600; }
.panel__sub { font-size: 12px; color: var(--fg-muted); }
.panel__body { padding: var(--sp-4); }

.section-label { font-size: 12px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--fg-muted); margin-bottom: var(--sp-3); }

/* ===== pipeline stepper ===== */
.pipeline {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: var(--sp-2);
  padding: var(--sp-3);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-soft);
}
.pipeline__step {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: 62px;
  padding: 10px 12px;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: var(--surface-2);
  cursor: pointer;
  text-align: left;
  transition: border-color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
}
.pipeline__step:hover:not(:disabled) { border-color: var(--border-strong); background: var(--hover-bg-strong); }
.pipeline__step:active:not(:disabled) { transform: translateY(1px); }
.pipeline__step:disabled { cursor: not-allowed; opacity: .55; }
.pipeline__step.is-current { border-color: var(--primary); box-shadow: 0 0 0 3px rgba(236,72,153,.14); }
.pipeline__step.is-current .step__num { background: var(--primary-solid); color: var(--on-primary); border-color: transparent; }
.pipeline__step.is-done .step__num { background: rgba(16,185,129,.16); color: var(--success); border-color: rgba(16,185,129,.4); }
.pipeline__step.is-error .step__num { background: rgba(220,38,38,.16); color: var(--danger-fg); border-color: rgba(220,38,38,.4); }
.pipeline__step.is-running .step__num { background: rgba(37,99,235,.16); color: var(--info-fg); border-color: rgba(37,99,235,.4); }

.step__num {
  display: grid;
  place-items: center;
  width: 26px; height: 26px;
  flex: none;
  border-radius: 50%;
  border: 1px solid var(--border-strong);
  background: var(--surface);
  font-size: 12px;
  font-weight: 600;
  color: var(--fg-muted);
}
.step__body { display: flex; flex-direction: column; min-width: 0; gap: 1px; }
.step__name { font-size: 13px; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* 「当前参数」那一行：让用户看得出这一步有东西可配 */
/* 卡片只有 ~180px 宽，一行放不下，所以允许折成两行——截断等于白显示 */
.step__settings {
  font-size: 11px; line-height: 1.35; color: var(--fg-dim);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; overflow-wrap: anywhere;
}
.pipeline__step:hover:not(:disabled) .step__settings { color: var(--fg-muted); }
.step__meta { font-size: 11px; color: var(--fg-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: flex; align-items: center; gap: 4px; }
.step__icon { display: inline-flex; align-items: center; color: var(--fg-muted); }
/* 齿轮：把「可以点开设置」这件事显式说出来（之前只有一个看不见的 hover title） */
.step__gear {
  flex: none; display: grid; place-items: center;
  width: 24px; height: 24px; margin-left: auto; border-radius: 7px;
  color: var(--fg-dim);
  transition: color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease);
}
.pipeline__step:hover:not(:disabled) .step__gear { color: var(--fg); background: var(--surface-2); }
.pipeline__step.is-current .step__gear { color: var(--primary); }

/* ===== buttons ===== */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  min-height: 40px;
  padding: 0 var(--sp-4);
  border-radius: var(--radius);
  border: 1px solid var(--border-strong);
  background: var(--surface-2);
  color: var(--fg);
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease), opacity var(--dur-fast) var(--ease);
}
.btn svg { width: 16px; height: 16px; }
.btn:hover:not(:disabled) { background: var(--hover-bg-strong); border-color: var(--border-hover); }
.btn:active:not(:disabled) { transform: translateY(1px); }
.btn:disabled { opacity: .45; cursor: not-allowed; }

.btn--primary { background: var(--primary-solid); border-color: transparent; color: var(--on-primary); }
.btn--primary:hover:not(:disabled) { background: var(--primary-solid-hover); border-color: transparent; }
.btn--ghost { background: transparent; border-color: var(--border); color: var(--fg-muted); }
.btn--ghost:hover:not(:disabled) { background: var(--surface-2); color: var(--fg); border-color: var(--border-strong); }
.btn--danger { background: var(--danger); border-color: transparent; color: #fff; }
.btn--danger:hover:not(:disabled) { background: #B91C1C; border-color: transparent; }
.btn--sm { min-height: 32px; padding: 0 var(--sp-3); font-size: 12px; border-radius: 10px; }
.btn--sm svg { width: 14px; height: 14px; }
.btn--block { width: 100%; }
.btn.is-busy { cursor: progress; }

.icon-btn {
  display: inline-grid;
  place-items: center;
  width: 40px; height: 40px;
  flex: none;
  border-radius: 10px;
  border: 1px solid transparent;
  background: transparent;
  color: var(--fg-muted);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.icon-btn svg { width: 18px; height: 18px; }
.icon-btn:hover:not(:disabled) { background: var(--surface-2); color: var(--fg); border-color: var(--border); }
.icon-btn:active:not(:disabled) { transform: translateY(1px); }
.icon-btn:disabled { opacity: .38; cursor: not-allowed; }
.icon-btn--sm { width: 32px; height: 32px; }
.icon-btn--sm svg { width: 15px; height: 15px; }
.icon-btn--danger:hover:not(:disabled) { color: var(--danger-fg); border-color: rgba(220,38,38,.4); background: rgba(220,38,38,.12); }

.spinner { display: inline-block; width: 16px; height: 16px; border-radius: 50%; border: 2px solid var(--spinner-track); border-top-color: currentColor; animation: spin 800ms linear infinite; }
.spin { animation: spin 900ms linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

/* ===== form controls ===== */
.input, .select, .textarea {
  width: 100%;
  min-height: 40px;
  padding: var(--sp-2) var(--sp-3);
  border-radius: 10px;
  border: 1px solid var(--border-strong);
  background: var(--muted);
  color: var(--fg);
  font-size: 13px;
  transition: border-color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease);
}
.input::placeholder, .textarea::placeholder { color: var(--fg-muted); }
.input:hover, .select:hover, .textarea:hover { border-color: var(--border-hover); }
.input:focus-visible, .select:focus-visible, .textarea:focus-visible { border-color: var(--primary); outline: 2px solid var(--ring); outline-offset: 1px; }
.input:disabled, .select:disabled, .textarea:disabled { opacity: .5; cursor: not-allowed; }
.textarea { min-height: 76px; resize: vertical; line-height: 1.5; font-family: var(--font); }
.select {
  appearance: none;
  padding-right: 30px;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2394A3B8' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 10px center;
  cursor: pointer;
}
.select--sm { min-height: 32px; padding: 0 28px 0 var(--sp-3); font-size: 12px; border-radius: 10px; }

/* 适配器自检结果 */
.dialog__spacer { flex: 1 1 auto; }
.adapter-test {
  margin: var(--sp-4) 0 0;
  padding: 10px 12px;
  border-radius: var(--radius);
  border: 1px solid var(--border-strong);
  background: var(--surface-2);
  font-size: 13px;
  line-height: 1.55;
  white-space: pre-wrap;
  word-break: break-word;
  color: var(--fg);
}
.adapter-test.is-ok { border-color: rgba(16, 185, 129, .5); background: rgba(16, 185, 129, .1); color: var(--success-fg); }
.adapter-test.is-bad { border-color: rgba(220, 38, 38, .5); background: rgba(220, 38, 38, .1); color: var(--danger-fg); }
.adapter-test__detail {
  display: block;
  margin-top: 6px;
  font-family: var(--mono);
  font-size: 11px;
  color: var(--fg-muted);
  max-height: 120px;
  overflow: auto;
  white-space: pre-wrap;
}

.field { display: flex; flex-direction: column; gap: var(--sp-2); min-width: 0; }
.field__label { font-size: 12px; font-weight: 500; color: var(--fg-muted); display: flex; align-items: center; gap: var(--sp-2); }
.field__value { font-size: 12px; color: var(--primary); font-weight: 600; font-variant-numeric: tabular-nums; }
.field__hint { font-size: 11px; color: var(--fg-muted); line-height: 1.5; }
.field__error { font-size: 12px; color: var(--danger-fg); }
.field__error::before { content: "! "; font-weight: 700; }
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-3); }
.row { display: flex; align-items: center; gap: var(--sp-2); min-width: 0; }
.row > .input { flex: 1; }

.range { width: 100%; height: 24px; appearance: none; background: transparent; cursor: pointer; }
.range::-webkit-slider-runnable-track { height: 4px; border-radius: 999px; background: var(--surface-2); }
.range::-webkit-slider-thumb { appearance: none; width: 16px; height: 16px; margin-top: -6px; border-radius: 50%; background: var(--primary); border: 2px solid var(--bg); }
.range::-moz-range-track { height: 4px; border-radius: 999px; background: var(--surface-2); }
.range::-moz-range-thumb { width: 16px; height: 16px; border-radius: 50%; background: var(--primary); border: 2px solid var(--bg); }

.segmented { display: inline-flex; padding: 3px; gap: 3px; border-radius: 10px; background: var(--muted); border: 1px solid var(--border); }
.segmented__item {
  min-height: 32px;
  padding: 0 var(--sp-4);
  border: none;
  border-radius: 8px;
  background: transparent;
  color: var(--fg-muted);
  font-size: 12px;
  font-weight: 500;
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.segmented__item:hover:not(.is-active) { color: var(--fg); background: var(--hover-bg); }
.segmented__item.is-active { background: var(--surface-2); color: var(--fg); box-shadow: var(--shadow-sm); }

.switch { display: inline-flex; align-items: center; gap: var(--sp-3); min-height: 40px; cursor: pointer; user-select: none; }
.switch--sm { min-height: 32px; }
.switch__input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.switch__track {
  position: relative;
  width: 38px; height: 22px;
  flex: none;
  border-radius: 999px;
  background: var(--surface-2);
  border: 1px solid var(--border-strong);
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.switch__thumb {
  position: absolute;
  top: 2px; left: 2px;
  width: 16px; height: 16px;
  border-radius: 50%;
  background: var(--fg-muted);
  transition: transform var(--dur) var(--ease), background var(--dur) var(--ease);
}
.switch__input:checked + .switch__track { background: var(--primary); border-color: transparent; }
.switch__input:checked + .switch__track .switch__thumb { transform: translateX(16px); background: #fff; }
.switch__input:focus-visible + .switch__track { outline: 2px solid var(--ring); outline-offset: 2px; }
.switch__input:disabled + .switch__track { opacity: .45; }
.switch__label { font-size: 12px; color: var(--fg-muted); }
.switch--sm .switch__track { width: 32px; height: 18px; }
.switch--sm .switch__thumb { width: 12px; height: 12px; }
.switch--sm .switch__input:checked + .switch__track .switch__thumb { transform: translateX(14px); }

.checkbox { width: 16px; height: 16px; accent-color: var(--primary); cursor: pointer; }
.checkbox:disabled { cursor: not-allowed; opacity: .45; }
.row-check { cursor: pointer; }

/* ===== badges / pills / dots ===== */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 1px 8px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--surface-2);
  font-size: 11px;
  font-weight: 500;
  color: var(--fg-muted);
  white-space: nowrap;
}
.badge--ok { color: var(--success-fg); border-color: rgba(16,185,129,.35); background: rgba(16,185,129,.12); }
.badge--warn { color: var(--warn-fg); border-color: rgba(245,158,11,.35); background: rgba(245,158,11,.12); }
.badge--danger { color: var(--danger-fg); border-color: rgba(220,38,38,.35); background: rgba(220,38,38,.12); }
.badge--info { color: var(--info-fg); border-color: rgba(37,99,235,.35); background: rgba(37,99,235,.12); }
.badge--primary { color: var(--primary-fg); border-color: rgba(236,72,153,.4); background: rgba(236,72,153,.14); }

.status-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; flex: none; background: var(--fg-dim); }
.status-dot--pending { background: var(--fg-dim); }
.status-dot--running { background: var(--accent); animation: pulse 1.4s ease-in-out infinite; }
.status-dot--done { background: var(--success); }
.status-dot--error { background: var(--danger); }
.status-dot--skipped { background: var(--warn); }
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }

/* ===== toolbar ===== */
.toolbar {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 6px;
  padding: var(--sp-3) var(--sp-4);
  border-bottom: 1px solid var(--border);
}
/* 每条线自己排一行：统计/并发一行，选择操作 + 导入导出一行。
   靠 flex-wrap 自己撞会撞出三行，把表格顶下去。 */
.toolbar__line { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }
.toolbar__group { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }
.toolbar__spacer { flex: 1; min-width: var(--sp-2); }
.toolbar__divider { width: 1px; height: 24px; background: var(--border); }

.stats { display: flex; align-items: center; gap: var(--sp-4); flex-wrap: wrap; }
.stat { display: inline-flex; align-items: baseline; gap: 5px; font-size: 12px; color: var(--fg-muted); }
.stat__num { font-size: 14px; font-weight: 600; color: var(--fg); }
.stat__num.is-ok { color: var(--success-fg); }
.stat__num.is-bad { color: var(--danger-fg); }

/* ===== table ===== */
.table-wrap { width: 100%; max-width: 100%; overflow-x: auto; overflow-y: visible; }
.data-table { width: 100%; min-width: 940px; border-collapse: collapse; font-size: 13px; }
.data-table thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--surface-2);
  border-bottom: 1px solid var(--border-strong);
  padding: var(--sp-2) var(--sp-3);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--fg-muted);
  text-align: left;
  white-space: nowrap;
}
.data-table tbody td {
  padding: var(--sp-2) var(--sp-3);
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
  color: var(--fg);
}
.data-table tbody tr { transition: background var(--dur-fast) var(--ease); }
.data-table tbody tr:hover { background: var(--row-hover); }
.data-table tbody tr.is-selected { background: rgba(236,72,153,.07); }
.data-table tbody tr.is-disabled { opacity: .5; }
.data-table tbody tr.is-running { background: rgba(37,99,235,.08); }
.data-table tbody tr:last-child td { border-bottom: none; }

.col-check { width: 44px; }
.col-idx { width: 52px; }
.col-thumb { width: 96px; }
.col-time { width: 130px; }
.col-dur { width: 84px; }
.col-face { width: 130px; }
.col-status { width: 150px; }
.col-actions { width: 148px; }

/* ===== 分镜表格：密集操作台，不是报表 =====
   列宽固定（table-layout: fixed）。默认的 auto 布局会把宽屏剩下的空间全给
   「提示词」一列，于是中间一大片空白、状态/操作挤在角落 —— 看着就是不整齐。
   固定后每一列拿自己该拿的宽度，提示词列拿剩下的全部并两行截断。
   min-width 620 是「还能读」的下限：右栏出现时左列约 640px，再窄就让
   .table-wrap 横向滚，总比把列压成两个字强。 */
.data-table--shots { min-width: 620px; table-layout: fixed; }
.data-table--shots thead th,
.data-table--shots tbody td { padding: var(--sp-2); }
.data-table--shots tbody td { overflow: hidden; }
.data-table--shots .col-check { width: 36px; }
.data-table--shots .col-idx { width: 36px; }
.data-table--shots .col-thumb { width: 82px; }
.data-table--shots .col-mode { width: 74px; }
.data-table--shots .col-face { width: 78px; }
.data-table--shots .col-status { width: 92px; }
.data-table--shots .col-actions { width: 108px; }
/* 这一列只回答「有没有、是哪张」：缩略图（多张带 +N）。文件名在这个宽度里
   只能截成噪音，完整列表走 title，细节在右栏的参考图列表里 */
.data-table--shots .refcell__path { display: none; }
.data-table--shots .refcell { cursor: text; }
/* 例外：这一格的「点一下填路径」会把一个 150px+ 的输入框塞进来，比列宽得多，
   必须让它盖到右边去 —— 裁掉就等于没法看自己填的路径（旧版 130px 列也是这样） */
.data-table--shots td.col-face { overflow: visible; position: relative; }
.data-table--shots td.col-face .input { position: absolute; left: var(--sp-2); top: 50%; transform: translateY(-50%); width: 230px; z-index: 4; }
/* 提示词最多两行，超出省略号：行高稳定，表格不会因为某条长提示词突然变胖 */
.data-table--shots .prompt-cell__inner {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
/* 行内编辑用 textarea：它不能比格子宽，否则固定布局下会顶出横向滚动条 */
.data-table--shots .prompt-edit { min-width: 0; }

.td-num { font-variant-numeric: tabular-nums; color: var(--fg-muted); white-space: nowrap; }

.thumb {
  position: relative;
  width: 64px; height: 36px;
  border-radius: 6px;
  overflow: hidden;
  background: var(--muted);
  border: 1px solid var(--border);
  display: grid;
  place-items: center;
  flex: none;
}
.thumb__img { width: 100%; height: 100%; object-fit: cover; display: block; }
.thumb__ph { color: var(--fg-muted); display: grid; place-items: center; width: 100%; height: 100%; }
.thumb__ph svg { width: 14px; height: 14px; }

.prompt-cell {
  display: block;
  width: 100%;
  min-height: 32px;
  padding: 6px 8px;
  border-radius: 8px;
  border: 1px solid transparent;
  background: transparent;
  color: var(--fg);
  font-size: 13px;
  line-height: 1.45;
  cursor: text;
  text-align: left;
  overflow-wrap: anywhere;
  transition: background var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.prompt-cell:hover { background: var(--muted); border-color: var(--border); }
.prompt-cell__inner { display: block; overflow-wrap: anywhere; }
.prompt-cell__empty { color: var(--fg-muted); font-style: normal; }
.prompt-edit {
  width: 100%;
  min-width: 220px;
  min-height: 62px;
  padding: 6px 8px;
  border-radius: 8px;
  border: 1px solid var(--primary);
  background: var(--muted);
  color: var(--fg);
  font-family: var(--font);
  font-size: 13px;
  line-height: 1.45;
  resize: vertical;
}
.prompt-cell__saved { display: inline-flex; align-items: center; gap: 4px; font-size: 11px; color: var(--success); margin-top: 2px; }

.refcell { display: flex; align-items: center; gap: var(--sp-2); min-width: 0; }
.refcell__thumb { width: 24px; height: 24px; border-radius: 6px; object-fit: cover; border: 1px solid var(--border); flex: none; }
.refcell__path {
  font-size: 12px;
  color: var(--fg-muted);
  font-family: var(--mono);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 78px;
  cursor: text;
}

.status-cell { display: flex; align-items: center; gap: var(--sp-2); min-width: 0; }
.status-cell__text { font-size: 12px; white-space: nowrap; }
.status-cell__text.is-error { color: var(--danger-fg); }
.status-cell__text.is-done { color: var(--success-fg); }
.status-cell__text.is-muted { color: var(--fg-muted); }
.row-bar { position: relative; width: 100%; height: 4px; margin-top: 5px; border-radius: 999px; background: var(--surface-2); overflow: hidden; }
.row-bar__fill { height: 100%; width: 40%; border-radius: 999px; background: var(--accent); transition: width .25s var(--ease); }
.row-bar--indeterminate .row-bar__fill { animation: slide 1.2s var(--ease) infinite; }
.row-bar__pct { display: block; margin-top: 3px; font-size: 11px; line-height: 1; color: var(--fg-muted); font-variant-numeric: tabular-nums; }
@keyframes slide { 0% { transform: translateX(-110%); } 100% { transform: translateX(260%); } }

.row-actions { display: flex; align-items: center; gap: 2px; }

.pager { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); padding: var(--sp-3) var(--sp-4); border-top: 1px solid var(--border); flex-wrap: wrap; }
.pager__info { font-size: 12px; color: var(--fg-muted); font-variant-numeric: tabular-nums; }
.pager__pages { display: flex; align-items: center; gap: var(--sp-1); flex-wrap: wrap; }
.pager__btn {
  min-width: 32px; height: 32px;
  padding: 0 var(--sp-2);
  border-radius: 8px;
  border: 1px solid var(--border);
  background: transparent;
  color: var(--fg-muted);
  font-size: 12px;
  cursor: pointer;
  font-variant-numeric: tabular-nums;
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.pager__btn:hover:not(:disabled) { background: var(--surface-2); color: var(--fg); }
.pager__btn.is-active { background: var(--primary-solid); border-color: transparent; color: var(--on-primary); }
.pager__btn:disabled { opacity: .4; cursor: not-allowed; }

/* ===== empty / fatal states ===== */
.empty-state, .fatal-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--sp-3);
  text-align: center;
  padding: var(--sp-8) var(--sp-5);
  min-height: 60vh;
}
.empty-state__art { color: var(--fg-dim); margin-bottom: var(--sp-2); }
.empty-state__art svg { width: 132px; height: 108px; }
.empty-state__title, .fatal-state__title { font-size: 18px; font-weight: 600; }
.empty-state__text, .fatal-state__text { font-size: 13px; color: var(--fg-muted); max-width: 460px; line-height: 1.6; }
.fatal-state { border: 1px solid var(--border); border-radius: var(--radius-lg); background: var(--surface); box-shadow: var(--shadow-soft); min-height: 50vh; }
.fatal-state__icon { color: var(--danger); }
.fatal-state__icon svg { width: 40px; height: 40px; }
.fatal-state__detail { font-family: var(--mono); font-size: 11px; color: var(--fg-muted); max-width: 620px; white-space: pre-wrap; word-break: break-word; }

.empty-inline { padding: var(--sp-6); text-align: center; color: var(--fg-muted); font-size: 13px; }

/* ===== import panel / dropzone ===== */
.import-panel { display: grid; gap: var(--sp-4); }
.dropzone {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--sp-3);
  min-height: 180px;
  padding: var(--sp-6);
  border-radius: var(--radius-lg);
  border: 1.5px dashed var(--border-strong);
  background: var(--surface);
  color: var(--fg-muted);
  cursor: pointer;
  text-align: center;
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.dropzone:hover { border-color: var(--primary); color: var(--fg); }
.dropzone.is-over { border-color: var(--primary); background: rgba(236,72,153,.08); color: var(--fg); }
.dropzone.is-busy { cursor: progress; opacity: .8; }
.dropzone__icon { color: var(--primary); }
.dropzone__icon svg { width: 32px; height: 32px; }
.dropzone__title { font-size: 15px; font-weight: 600; color: var(--fg); }
.dropzone__hint { font-size: 12px; color: var(--fg-muted); }

.progress { display: flex; flex-direction: column; gap: var(--sp-2); }
.progress__track { width: 100%; height: 6px; border-radius: 999px; background: var(--surface-2); overflow: hidden; }
.progress__fill { height: 100%; width: 0%; border-radius: 999px; background: var(--primary); transition: width var(--dur) var(--ease); }
.progress__text { font-size: 12px; color: var(--fg-muted); font-variant-numeric: tabular-nums; }

.path-form { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }
.path-form > .input { flex: 1; min-width: 240px; }
.hint-list { display: flex; flex-direction: column; gap: var(--sp-1); font-size: 12px; color: var(--fg-muted); }
.hint-list li { display: flex; gap: var(--sp-2); align-items: flex-start; }

/* ===== result card ===== */
.result-card {
  display: grid;
  gap: var(--sp-4);
  grid-template-columns: minmax(220px, 340px) minmax(0, 1fr);
  align-items: start;
}
.result-card__video { width: 100%; border-radius: var(--radius); border: 1px solid var(--border); background: #000; aspect-ratio: 9 / 16; max-height: 420px; object-fit: contain; }
.result-card__rows { display: flex; flex-direction: column; gap: var(--sp-3); }
.kv { display: grid; grid-template-columns: auto 1fr; gap: var(--sp-2) var(--sp-4); font-size: 13px; }
.kv dt { color: var(--fg-muted); font-size: 12px; }
.kv dd { color: var(--fg); word-break: break-all; }

/* ===== adapter form ===== */
.dialog__lead { font-size: 13px; color: var(--fg-muted); line-height: 1.6; }
.adapter-head { display: flex; align-items: flex-end; gap: var(--sp-4); flex-wrap: wrap; }
.adapter-head > .field { min-width: 260px; flex: 1; }
.adapter-meta { display: flex; gap: var(--sp-2); flex-wrap: wrap; padding-bottom: var(--sp-2); }
.adapter-form { display: flex; flex-direction: column; gap: var(--sp-4); }
.adapter-field__row { display: flex; align-items: center; gap: var(--sp-2); }
.adapter-field__row .input { flex: 1; }

/* ===== toasts ===== */
.toasts {
  position: fixed;
  right: var(--sp-5);
  bottom: var(--sp-5);
  z-index: var(--z-toast);
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  width: min(360px, calc(100vw - 32px));
  pointer-events: none;
}
.toast {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-3);
  border-radius: var(--radius);
  border: 1px solid var(--border-strong);
  background: var(--surface-2);
  box-shadow: var(--shadow-soft);
  pointer-events: auto;
  animation: toast-in var(--dur-slow) var(--ease);
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.toast.is-leaving { opacity: 0; transform: translateY(8px); }
.toast__icon { flex: none; margin-top: 1px; }
.toast__msg { flex: 1; font-size: 13px; line-height: 1.5; word-break: break-word; }
.toast__close { margin: -6px -6px 0 0; }
.toast--success { border-color: rgba(16,185,129,.4); }
.toast--success .toast__icon { color: var(--success); }
.toast--error { border-color: rgba(220,38,38,.45); }
.toast--error .toast__icon { color: var(--danger-fg-strong); }
.toast--warn { border-color: rgba(245,158,11,.45); }
.toast--warn .toast__icon { color: var(--warn); }
.toast--info .toast__icon { color: var(--info-fg); }
@keyframes toast-in { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }

/* ===== dialogs ===== */
.dialog {
  width: min(560px, calc(100vw - 32px));
  max-height: min(86vh, 900px);
  padding: 0;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-lg);
  background: var(--surface);
  color: var(--fg);
  box-shadow: var(--shadow-modal);
  overflow: hidden;
}
.dialog--wide { width: min(720px, calc(100vw - 32px)); }
.dialog--sm { width: min(440px, calc(100vw - 32px)); }
.dialog::backdrop { background: var(--scrim); backdrop-filter: blur(2px); }
.dialog[open] { animation: dialog-in var(--dur-slow) var(--ease); }
@keyframes dialog-in { from { opacity: 0; transform: translateY(10px) scale(.99); } to { opacity: 1; transform: none; } }

.dialog__form { display: flex; flex-direction: column; max-height: min(86vh, 900px); }
.dialog__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-4) var(--sp-3);
  border-bottom: 1px solid var(--border);
}
.dialog__title { font-size: 15px; font-weight: 600; }
.dialog__body { padding: var(--sp-4); display: flex; flex-direction: column; gap: var(--sp-4); overflow-y: auto; }
.dialog__message { font-size: 13px; color: var(--fg); line-height: 1.6; }
.dialog__detail { margin: 0; font-family: var(--mono); font-size: 11px; color: var(--fg-muted); background: var(--muted); border: 1px solid var(--border); border-radius: 10px; padding: var(--sp-3); max-height: 180px; overflow: auto; white-space: pre-wrap; word-break: break-word; }
.dialog__foot {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--sp-2);
  padding: var(--sp-3) var(--sp-4);
  border-top: 1px solid var(--border);
  background: var(--surface);
}

/* ===== drawer (preview) ===== */
.drawer {
  position: fixed;
  top: 0; right: 0; bottom: 0;
  z-index: var(--z-drawer);
  width: min(400px, 92vw);
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border-left: 1px solid var(--border-strong);
  box-shadow: var(--shadow-drawer);
  animation: drawer-in var(--dur-slow) var(--ease);
}
@keyframes drawer-in { from { transform: translateX(24px); opacity: 0; } to { transform: none; opacity: 1; } }
.drawer__head { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); padding: var(--sp-3) var(--sp-4); border-bottom: 1px solid var(--border); }
.drawer__title { font-size: 14px; font-weight: 600; }
.drawer__body { flex: 1; min-height: 0; overflow-y: auto; padding: var(--sp-4); display: flex; flex-direction: column; gap: var(--sp-4); }
.preview__stage { width: 100%; border-radius: var(--radius); overflow: hidden; background: #000; border: 1px solid var(--border); aspect-ratio: 9 / 16; max-height: 52vh; display: grid; place-items: center; }
.preview__stage video { width: 100%; height: 100%; object-fit: contain; background: #000; }
.preview__switch { display: flex; gap: var(--sp-2); }
.preview__actions { display: flex; flex-wrap: wrap; gap: var(--sp-2); }

/* ===== console (job drawer) ===== */
.console {
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border-top: 1px solid var(--border);
  min-height: 48px;
  /* 任务控制台钉在窗口底部：常驻可见（点标题栏展开任务列表），
     不会被中间内容顶走，删项目 / 切阶段都不影响它 */
  position: sticky;
  bottom: 0;
  z-index: var(--z-console);
  flex: none;
}
.console__head { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); padding: var(--sp-1) var(--sp-3) var(--sp-1) var(--sp-2); flex-wrap: wrap; }
.console__toggle {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: 40px;
  padding: 0 var(--sp-2);
  border: none;
  border-radius: 10px;
  background: transparent;
  color: var(--fg);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease);
}
.console__toggle:hover { background: var(--surface-2); }
.console__chev { color: var(--fg-muted); transition: transform var(--dur) var(--ease); }
.console__toggle[aria-expanded="true"] .console__chev { transform: rotate(180deg); }
.console__title { font-size: 13px; font-weight: 600; }
.console__summary { font-size: 12px; color: var(--fg-muted); font-variant-numeric: tabular-nums; }
.console__actions { display: flex; align-items: center; gap: var(--sp-3); }
.console__body { border-top: 1px solid var(--border); max-height: 320px; overflow-y: auto; }
.job-list { display: flex; flex-direction: column; gap: var(--sp-2); padding: var(--sp-3); }

.job-card {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface-2);
  overflow: hidden;
}
.job-card.is-running { border-color: rgba(37,99,235,.4); }
.job-card.is-error { border-color: rgba(220,38,38,.4); }
.job-card__head { display: flex; align-items: center; gap: var(--sp-3); padding: var(--sp-2) var(--sp-3); flex-wrap: wrap; }
.job-card__title { font-size: 13px; font-weight: 500; display: flex; align-items: center; gap: var(--sp-2); min-width: 0; }
.job-card__meta { font-size: 12px; color: var(--fg-muted); display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; }
.job-card__spacer { flex: 1; min-width: var(--sp-2); }
.job-card__progress { padding: 0 var(--sp-3) var(--sp-3); }
.job-card__body { border-top: 1px solid var(--border); padding: var(--sp-3); background: var(--muted); }
.job-log {
  margin: 0;
  max-height: 220px;
  overflow-y: auto;
  font-family: var(--mono);
  font-size: 11.5px;
  line-height: 1.6;
  color: var(--fg-muted);
  white-space: pre-wrap;
  word-break: break-word;
}
.job-log__line { display: block; }
.job-log__line.is-error { color: var(--danger-fg); }
.job-log__line.is-warn { color: var(--warn-fg); }
.job-log__empty { color: var(--fg-muted); }

/* ===== noscript ===== */
.noscript { padding: var(--sp-6); color: var(--warn); text-align: center; }

/* ===== responsive ===== */
@media (max-width: 1180px) {
  .pipeline { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .result-card { grid-template-columns: 1fr; }
  .result-card__video { max-height: 320px; }
}

@media (max-width: 900px) {
  .layout { grid-template-columns: minmax(0, 1fr); }
  .sidebar { display: none; }
  .mobile-bar { display: block; }
  .mobile-bar .field { max-width: none; }
  .main__scroll { padding: var(--sp-4) var(--sp-3); }
  .pipeline { grid-template-columns: 1fr; }
  .topbar { padding: var(--sp-2) var(--sp-3); }
  .topbar__right { gap: var(--sp-2); }
  .brand__title { font-size: 13px; }
  .mini-job { order: 3; width: 100%; max-width: none; }
  .console__body { max-height: 46vh; }
  .drawer { width: 100%; }
}

@media (max-width: 560px) {
  .toolbar { padding: var(--sp-2) var(--sp-3); }
  .grid-2 { grid-template-columns: 1fr; }
  .adapter-head > .field { min-width: 0; }
  .toasts { right: var(--sp-3); left: var(--sp-3); bottom: var(--sp-3); width: auto; }
}

/* ===== reduced motion ===== */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
  .spinner, .spin { animation: none !important; border-top-color: currentColor; }
  .row-bar--indeterminate .row-bar__fill { width: 100%; opacity: .5; }
}

/* ============================================================================
   分镜生成页（story.html / story.js）
   本段是**纯追加**：不修改上方任何既有规则，只新增 .appnav 与 story-* 系列。
   ========================================================================= */

/* ===== 顶部主导航（两个页面共用） ===== */
.appnav {
  display: flex;
  align-items: center;
  gap: 3px;
  padding: 3px;
  margin-left: var(--sp-2);
  border-radius: 10px;
  background: var(--muted);
  border: 1px solid var(--border);
  flex: none;
}
.appnav__item {
  display: inline-flex;
  align-items: center;
  min-height: 34px;
  padding: 0 var(--sp-4);
  border-radius: 8px;
  border: 1px solid transparent;
  border-left: 2px solid transparent;
  color: var(--fg-muted);
  font-size: 12px;
  font-weight: 500;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.appnav__item:hover { background: var(--hover-bg); color: var(--fg); }
.appnav__item:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; }
.appnav__item.is-active {
  background: var(--surface-2);
  color: var(--fg);
  border-color: var(--border-strong);
  border-left-color: var(--primary);
  box-shadow: var(--shadow-sm);
}

/* ===== 右栏（项目参数 / 组合成片） ===== */
.rail {
  display: flex;
  flex-direction: column;
  gap: var(--sp-5);
  min-height: 0;
  overflow-y: auto;
  padding: var(--sp-5);
  background: var(--bg);
  border-left: 1px solid var(--border);
}
.rail__block { flex: none; }
.rail__empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-2);
  text-align: center;
  padding: var(--sp-5) var(--sp-3);
  color: var(--fg-muted);
  font-size: 12px;
  line-height: 1.55;
}
.rail__empty svg { color: var(--fg-dim); }
.rail__empty--sm { padding: var(--sp-4) var(--sp-2); }

/* ===== 项目工具条（吸顶） ===== */
.story-toolbar {
  position: sticky;
  top: 0;
  z-index: 5;
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  flex-wrap: wrap;
  padding: var(--sp-3) var(--sp-5);
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  box-shadow: var(--shadow-card);
}
.toolbar__count { font-size: 12px; color: var(--fg-muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
.toolbar__count b { color: var(--fg); font-weight: 600; }

/* ===== 面板 ===== */
.story-panel { flex: none; }
.main__scroll > .story-panel + .story-panel { margin-top: var(--sp-5); }
.story-panel__headline { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.story-panel__headline .panel__title { display: flex; align-items: center; gap: var(--sp-2); }
.story-panel__headline .panel__title svg { color: var(--fg-muted); }
.panel__body--flush { padding: 0; }
.panel__body--sep { border-top: 1px solid var(--border); }
.is-warn { color: var(--warn-fg); }

.search {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding: 0 var(--sp-2);
  min-height: 32px;
  border-radius: 10px;
  border: 1px solid var(--border-strong);
  background: var(--muted);
  color: var(--fg-muted);
  transition: border-color var(--dur-fast) var(--ease);
}
.search:focus-within { border-color: var(--primary); }
.search .input { border: none; background: transparent; min-height: 28px; padding: 0 2px; width: 150px; }
.search .input:focus-visible { outline: none; }
.input--sm { min-height: 32px; padding: 0 var(--sp-2); font-size: 12px; border-radius: 10px; }
.visually-hidden { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* ===== 人物素材网格 ===== */
.char-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(215px, 1fr));
  gap: var(--sp-3);
  border-radius: var(--radius);
  transition: background var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.char-grid.is-over { background: rgba(236, 72, 153, .07); box-shadow: inset 0 0 0 1.5px var(--primary); }

.char-card {
  display: grid;
  grid-template-columns: 72px minmax(0, 1fr);
  grid-template-rows: auto auto;
  gap: var(--sp-2) var(--sp-3);
  padding: var(--sp-3);
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: var(--surface-2);
  transition: border-color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease);
}
.char-card:hover { border-color: var(--border-strong); }
.char-card.is-missing { border-color: rgba(245, 158, 11, .35); }
.char-card__thumb {
  position: relative;
  grid-row: 1 / span 2;
  width: 72px; height: 72px;
  border-radius: 10px;
  overflow: hidden;
  background: var(--muted);
  border: 1px solid var(--border);
  display: grid;
  place-items: center;
}
.char-card__thumb > .badge { position: absolute; left: 4px; bottom: 4px; }
.char-card__img { width: 100%; height: 100%; object-fit: cover; display: block; }
.char-card__ph { display: flex; flex-direction: column; align-items: center; gap: 3px; color: var(--fg-muted); }
.char-card__ph-text { font-size: 10.5px; line-height: 1.2; }
.char-card__body { min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.char-card__name {
  border: 1px solid transparent;
  border-radius: 8px;
  background: transparent;
  color: var(--fg);
  font-size: 13px;
  font-weight: 500;
  line-height: 1.35;
  text-align: left;
  padding: 4px 6px;
  margin: -4px -6px;
  cursor: text;
  overflow-wrap: anywhere;
  transition: background var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.char-card__name:hover { background: var(--muted); border-color: var(--border); }
.char-card__meta { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; font-size: 11px; color: var(--fg-muted); font-variant-numeric: tabular-nums; }
.char-card__refs { display: inline-flex; align-items: center; gap: 4px; }
.char-card__up { display: flex; align-items: center; gap: var(--sp-2); }
.char-card__up .progress__track { flex: 1; }
.char-card__up .progress__text { font-size: 10.5px; white-space: nowrap; }
.char-card__actions { grid-column: 2; display: flex; align-items: center; gap: 2px; }

/* ===== 分镜卡片 ===== */
.shot-list { display: flex; flex-direction: column; }
.shot-card { border-bottom: 1px solid var(--border); transition: background var(--dur-fast) var(--ease); }
.shot-card:last-child { border-bottom: none; }
.shot-card:hover { background: var(--hover-bg-faint); }
.shot-card.is-dragging { opacity: .45; }
.shot-card.drop-before { box-shadow: inset 0 3px 0 var(--primary); }
.shot-card.drop-after { box-shadow: inset 0 -3px 0 var(--primary); }

.shot-card__head {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-4);
  min-height: 48px;
  cursor: grab;
}
.shot-card__head:active { cursor: grabbing; }
.shot-card__head > * { cursor: auto; }
.shot-card__grip { color: var(--fg-dim); display: inline-flex; align-items: center; }
.shot-card__check { display: inline-flex; align-items: center; padding: 4px; cursor: pointer; }
.shot-card__idx {
  font-size: 12px;
  font-weight: 600;
  color: var(--fg-muted);
  font-variant-numeric: tabular-nums;
  min-width: 30px;
}
.shot-card__title {
  flex: 1;
  min-width: 0;
  min-height: 32px;
  border: 1px solid transparent;
  border-radius: 8px;
  background: transparent;
  color: var(--fg);
  font-size: 14px;
  font-weight: 600;
  text-align: left;
  padding: 0 var(--sp-2);
  cursor: text;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  transition: background var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.shot-card__title:hover { background: var(--muted); border-color: var(--border); }
.shot-card__title-edit { flex: 1; min-width: 120px; max-width: 420px; }
.shot-card__headright { display: flex; align-items: center; gap: var(--sp-2); flex: none; }
.shot-card__bar { display: flex; flex-direction: column; gap: 2px; padding: 0 var(--sp-4) var(--sp-2); }
.shot-card__error {
  margin: 0 var(--sp-4) var(--sp-2);
  padding: 8px 10px;
  border-radius: 10px;
  border: 1px solid rgba(220, 38, 38, .4);
  background: rgba(220, 38, 38, .1);
  color: var(--danger-fg);
  font-size: 12px;
  line-height: 1.5;
  word-break: break-word;
}

.shot-card__body { padding: 0 var(--sp-4) var(--sp-4); }
.shot-grid {
  display: grid;
  grid-template-columns: minmax(190px, 240px) minmax(0, 1fr) minmax(200px, 250px);
  grid-template-areas: "cast prompt params" "versions versions versions";
  gap: var(--sp-4);
  padding-top: var(--sp-2);
}
.shot-sec { display: flex; flex-direction: column; gap: var(--sp-3); min-width: 0; }
.shot-sec[data-sec="cast"] { grid-area: cast; }
.shot-sec[data-sec="prompt"] { grid-area: prompt; }
.shot-sec[data-sec="params"] { grid-area: params; }
.shot-sec[data-sec="versions"] { grid-area: versions; }
.shot-sec--params { padding-left: var(--sp-4); border-left: 1px solid var(--border); }
.shot-sec__label {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--fg-muted);
}
.shot-sec__hint { font-size: 11px; font-weight: 400; letter-spacing: 0; text-transform: none; color: var(--fg-dim); }
.shot-sec__row { align-items: center; gap: var(--sp-3); flex-wrap: wrap; }
.shot-sec__warn {
  display: flex;
  align-items: flex-start;
  gap: 6px;
  padding: 7px 10px;
  border-radius: 10px;
  font-size: 11.5px;
  line-height: 1.5;
}
.shot-sec__warn.is-warn { border: 1px solid rgba(245, 158, 11, .4); background: rgba(245, 158, 11, .1); color: var(--warn-fg); }
.shot-sec__warn.is-error { border: 1px solid rgba(220, 38, 38, .4); background: rgba(220, 38, 38, .1); color: var(--danger-fg); }

/* ===== 人物 chip（顺序徽章 ①②③） ===== */
.chips { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.chip {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 40px;
  max-width: 100%;
  padding: 3px 8px 3px 4px;
  border-radius: 999px;
  border: 1px solid var(--border-strong);
  background: var(--surface-2);
  color: var(--fg-muted);
  font-size: 12px;
  cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
}
.chip:hover { border-color: var(--border-hover-strong); color: var(--fg); }
.chip.is-on {
  border-color: var(--primary);
  background: rgba(236, 72, 153, .12);
  color: var(--fg);
  box-shadow: 0 0 0 3px rgba(236, 72, 153, .1);
}
.chip.is-ghost { border-style: dashed; }
.chip__order {
  display: grid;
  place-items: center;
  flex: none;
  width: 20px; height: 20px;
  border-radius: 50%;
  font-size: 12px;
  font-weight: 700;
  line-height: 1;
  color: var(--fg-dim);
  background: var(--muted);
  border: 1px solid var(--border);
}
.chip.is-on .chip__order { background: var(--primary-solid); border-color: transparent; color: var(--on-primary); }
.chip__img { width: 24px; height: 24px; border-radius: 50%; object-fit: cover; flex: none; border: 1px solid var(--border); }
.chip__img--ph { display: grid; place-items: center; background: var(--muted); color: var(--fg-dim); }
.chip__name {
  max-width: 150px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.chip__tools { display: inline-flex; align-items: center; gap: 1px; }
.chip__tool {
  display: grid;
  place-items: center;
  width: 22px; height: 22px;
  border-radius: 50%;
  border: 1px solid transparent;
  background: var(--subtle-bg-strong);
  color: var(--fg-muted);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.chip__tool:hover { background: var(--subtle-bg-strong-hover); color: var(--fg); }

/* ===== 参数区 ===== */
.param-grid { display: flex; flex-direction: column; gap: var(--sp-4); }
.tag {
  display: inline-flex;
  align-items: center;
  padding: 0 6px;
  border-radius: 999px;
  border: 1px solid var(--border);
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  white-space: nowrap;
}
.tag--inherit { color: var(--fg-muted); background: var(--hover-bg); }
.tag--override { color: var(--primary-fg); border-color: rgba(236, 72, 153, .4); background: rgba(236, 72, 153, .14); }

/* ===== 自检标签 ===== */
.lint-row { display: flex; flex-wrap: wrap; gap: 6px; }
.lint-tag {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 9px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--surface-2);
  font-size: 11.5px;
  line-height: 1.5;
  color: var(--fg-muted);
  max-width: 100%;
}
.lint-tag b { font-weight: 600; }
.lint-tag span { overflow-wrap: anywhere; }
.lint-tag--error { color: var(--danger-fg); border-color: rgba(220, 38, 38, .45); background: rgba(220, 38, 38, .12); }
.lint-tag--warn { color: var(--warn-fg); border-color: rgba(245, 158, 11, .45); background: rgba(245, 158, 11, .12); }
.lint-tag--ok { color: var(--success-fg); border-color: rgba(16, 185, 129, .45); background: rgba(16, 185, 129, .12); }
.lint-tag--info { color: var(--info-fg); border-color: rgba(37, 99, 235, .45); background: rgba(37, 99, 235, .12); }
.lint-tag--muted { color: var(--fg-muted); }

/* ===== 折叠区 / 只读预览 ===== */
.fold { border: 1px solid var(--border); border-radius: var(--radius); background: var(--muted); overflow: hidden; }
.fold__sum {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: 40px;
  padding: 0 var(--sp-3);
  font-size: 12px;
  color: var(--fg-muted);
  cursor: pointer;
  list-style: none;
  user-select: none;
}
.fold__sum::-webkit-details-marker { display: none; }
.fold__sum:hover { color: var(--fg); background: var(--row-hover); }
.fold[open] .fold__sum { border-bottom: 1px solid var(--border); color: var(--fg); }
.fold__pre {
  margin: 0;
  padding: var(--sp-3);
  max-height: 260px;
  overflow: auto;
  font-family: var(--mono);
  font-size: 11.5px;
  line-height: 1.65;
  color: var(--fg-muted);
  white-space: pre-wrap;
  word-break: break-word;
}
.textarea--mono { font-family: var(--mono); font-size: 12.5px; line-height: 1.65; }
.textarea.is-flash, .fold__pre.is-flash { animation: flash-update 880ms var(--ease); }
@keyframes flash-update {
  0% { box-shadow: 0 0 0 2px rgba(236, 72, 153, .55); }
  100% { box-shadow: 0 0 0 2px rgba(236, 72, 153, 0); }
}

/* ===== 操作区 ===== */
.shot-card__actions {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  flex-wrap: wrap;
  margin-top: var(--sp-4);
  padding-top: var(--sp-3);
  border-top: 1px solid var(--border);
}
.danger-ghost:hover:not(:disabled) { color: var(--danger-fg); border-color: rgba(220, 38, 38, .45); background: rgba(220, 38, 38, .1); }

/* ===== 历史版本 ===== */
.versions { display: flex; gap: var(--sp-3); overflow-x: auto; padding-bottom: var(--sp-2); }
.ver-card {
  flex: none;
  width: 186px;
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  padding: var(--sp-2);
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: var(--surface-2);
  transition: border-color var(--dur-fast) var(--ease);
}
.ver-card:hover { border-color: var(--border-strong); }
.ver-card.is-current { border-color: var(--primary); box-shadow: 0 0 0 3px rgba(236, 72, 153, .12); }
.ver-card__thumb {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  border-radius: 8px;
  overflow: hidden;
  border: 1px solid var(--border);
  background: var(--muted);
  display: grid;
  place-items: center;
  cursor: pointer;
  padding: 0;
}
.ver-card__img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ver-card__ph { color: var(--fg-dim); }
.ver-card__play {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  color: #fff;
  background: rgba(4, 8, 20, .38);
  opacity: 0;
  transition: opacity var(--dur-fast) var(--ease);
}
.ver-card__thumb:hover .ver-card__play, .ver-card__thumb:focus-visible .ver-card__play { opacity: 1; }
.ver-card__thumb > .badge { position: absolute; top: 5px; right: 5px; }
.ver-card__meta { display: flex; flex-direction: column; gap: 2px; font-size: 11px; color: var(--fg-muted); font-variant-numeric: tabular-nums; }
.ver-card__meta > span { display: flex; align-items: center; gap: 4px; min-width: 0; overflow-wrap: anywhere; }
.ver-card__v { font-size: 12px; font-weight: 600; color: var(--fg); }
.ver-card__note { color: var(--warn-fg); }
.ver-card__actions { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }
.ver-card__actions .btn { flex: 1; min-width: 92px; }

/* ===== 组合成片列表 ===== */
.compose-list { display: flex; flex-direction: column; gap: var(--sp-2); max-height: 42vh; overflow-y: auto; }
.compose-row {
  /* 右侧栏很窄，一行塞不下「复选框+序号+缩略图+标题+版本下拉+上下移」。
     排成两行：第一行看画面与标题，第二行选版本、调顺序。 */
  display: grid;
  grid-template-columns: auto auto auto 44px minmax(0, 1fr);
  grid-template-areas:
    "grip check idx thumb main"
    "meta meta  meta meta meta";
  align-items: center;
  column-gap: var(--sp-2);
  row-gap: 3px;
  padding: var(--sp-2);
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: var(--surface-2);
  transition: border-color var(--dur-fast) var(--ease), opacity var(--dur-fast) var(--ease);
}
.compose-row__grip { grid-area: grip; }
.compose-row__check { grid-area: check; }
.compose-row__idx { grid-area: idx; }
.compose-row__thumb { grid-area: thumb; }
.compose-row__main { grid-area: main; }
.compose-row__meta { grid-area: meta; }
.compose-row.is-off { opacity: .5; }
.compose-row.is-dragging { opacity: .35; }
.compose-row.drop-before { box-shadow: inset 0 3px 0 var(--primary); }
.compose-row.drop-after { box-shadow: inset 0 -3px 0 var(--primary); }
.compose-row__grip { color: var(--fg-dim); cursor: grab; display: inline-flex; align-items: center; }
.compose-row__check { display: inline-flex; align-items: center; padding: 4px; cursor: pointer; }
.compose-row__idx {
  min-width: 20px;
  font-size: 12px;
  font-weight: 600;
  color: var(--fg-muted);
  font-variant-numeric: tabular-nums;
}
.compose-row__thumb {
  width: 44px; height: 28px;
  flex: none;
  border-radius: 6px;
  overflow: hidden;
  border: 1px solid var(--border);
  background: var(--muted);
  display: grid;
  place-items: center;
}
.compose-row__img { width: 100%; height: 100%; object-fit: cover; display: block; }
.compose-row__ph { color: var(--fg-dim); }
.compose-row__main { min-width: 0; }
.compose-row__title { font-size: 12.5px; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.compose-row__meta { display: flex; align-items: center; gap: 6px; font-size: 11px; color: var(--fg-muted); font-variant-numeric: tabular-nums; min-width: 0; }
.compose-row__dur { flex: none; }
/* 逐镜挑版本：抽卡后同一镜会有好几版。让它吃掉第二行的剩余宽度 */
.compose-row__ver {
  flex: 1 1 auto; min-width: 0; max-width: none;
  min-height: 24px; height: 24px; padding: 0 22px 0 8px; font-size: 11px;
  border-radius: 8px; color: var(--fg); background-position: right 6px center;
}
.compose-row__vertext { display: inline-flex; align-items: center; gap: 3px; flex: none; }
.compose-row__vertext.is-warn { color: var(--warn); }
.compose-row__tools { display: flex; align-items: center; gap: 1px; flex: none; margin-left: auto; }
.compose-actions { margin-top: var(--sp-3); }
.compose-opts { margin-top: var(--sp-3); align-items: end; }
.result-card--rail {
  grid-template-columns: minmax(0, 108px) minmax(0, 1fr);
  align-items: stretch;
  gap: var(--sp-3);
  flex: 1;
  min-height: 0;
}
/* 短剧是竖屏（9:16）：左列固定 108px，视频按**高度**撑满整张卡（右列规格多高
   它就多高），contain 兜住横屏素材 —— 不用 aspect-ratio 定高是因为卡片高度
   本身就是弹性的，按高度走才不会在卡里留一大块空白。 */
.result-card--rail .result-card__video {
  width: 100%;
  height: 100%;
  min-height: 132px;
  max-height: 420px;
  aspect-ratio: auto;
  object-fit: contain;
}
.result-card--rail .kv { grid-template-columns: auto minmax(0, 1fr); gap: 1px var(--sp-2); font-size: 11px; }
.result-card--rail .kv dt { font-size: 11px; }
.result-card--rail .kv dd { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.result-card--rail .result-card__rows { gap: var(--sp-2); justify-content: space-between; }
.result-card--rail .toolbar__group { gap: 6px; flex-wrap: nowrap; }
.result-card--rail .toolbar__group > * { flex: 1; min-width: 0; justify-content: center; padding: 0 6px; }

/* 成片历史版本：意图和分镜的抽卡版本一样（每次重拼都留一版），
   但右栏窄，做成紧凑的竖排列表而不是卡片网格。 */
.final-vers {
  margin-top: var(--sp-2);
  padding-top: var(--sp-2);
  border-top: 1px solid var(--border);
}
.final-vers__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 11px;
  color: var(--fg-dim);
  margin-bottom: var(--sp-1);
}
.final-vers__head > span { display: inline-flex; align-items: center; gap: 4px; }
.final-vers__list { display: flex; flex-direction: column; gap: 2px; max-height: 128px; overflow-y: auto; }
.final-vers__row {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 3px 4px;
  border-radius: var(--radius);
}
.final-vers__row.is-current { background: var(--surface-2); }
.final-vers__pick {
  flex: none;
  min-width: 36px;
  padding: 2px 6px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  background: transparent;
  color: var(--fg);
  font-size: 11px;
  font-weight: 600;
  cursor: pointer;
}
.final-vers__pick:hover:not(:disabled) { border-color: var(--primary); color: var(--primary); }
.final-vers__pick:disabled { cursor: default; }
.final-vers__row.is-current .final-vers__pick { border-color: var(--primary); color: var(--primary); }
.final-vers__meta {
  flex: 1;
  min-width: 0;
  font-size: 11px;
  color: var(--fg-dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ===== 播放弹窗 / H3 规范 ===== */
.dlg-video__stage {
  width: 100%;
  aspect-ratio: 16 / 9;
  max-height: 60vh;
  border-radius: var(--radius);
  overflow: hidden;
  border: 1px solid var(--border);
  background: #000;
  display: grid;
  place-items: center;
}
.dlg-video__stage video { width: 100%; height: 100%; object-fit: contain; background: #000; }
.skill-fold { border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; background: var(--muted); }
.skill-fold__sum {
  display: flex;
  align-items: center;
  min-height: 40px;
  padding: 0 var(--sp-3);
  font-size: 12px;
  color: var(--fg-muted);
  cursor: pointer;
  list-style: none;
  user-select: none;
}
.skill-fold__sum::-webkit-details-marker { display: none; }
.skill-fold[open] .skill-fold__sum { border-bottom: 1px solid var(--border); color: var(--fg); }
.skill-pre {
  margin: 0;
  padding: var(--sp-3);
  max-height: min(56vh, 560px);
  overflow: auto;
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.7;
  color: var(--fg-muted);
  white-space: pre-wrap;
  word-break: break-word;
}
.sidebar__error { padding: var(--sp-4); font-size: 12px; color: var(--danger-fg); line-height: 1.6; }

/* ===== 响应式 ===== */
/* 分镜页（story.html）在常见桌面宽度上要三栏：侧栏 + 主区 + 右侧栏。
   注意三点（都踩过坑）：
   1) 三栏网格必须挂在 min-width 上——挂成 max-width 会让 rail 掉到第二行，
      把主区高度压掉一半；
   2) .sidebar/.rail 被 display:none 后，grid 自动布局会把 .main 放回第 1 列
      （于是主区被压成 240px）。所以每档都显式指定各栏的 grid-column；
   3) 三栏是 story 页专属的，选择器必须写成 .layout--story —— 之前写成裸 .layout，
      于是工作台（index.html 的 .layout 里只有 .sidebar + .main，没有 .rail 子节点）
      也被套上「260px + 1fr + 320px」，第三栏永远空着：屏幕上就是右边一条
      320px 的死区，同时主区被压窄到 780px、940px 的表格放不下只能横向滚。 */
/* 三栏：侧栏 260 + 主区 + 右栏（参数 / 组合成片 / 任务）。
   右栏是「组合成片」的唯一入口，所以只要放得下就别收 —— 原来 1181px 以下
   直接 display:none，1064px 的笔记本上用户根本找不到合并在哪。 */
@media (min-width: 1181px) {
  .layout--story { grid-template-columns: 260px minmax(0, 1fr) 320px; }
  .layout--story > .sidebar { grid-column: 1; }
  .layout--story > .main { grid-column: 2; }
  .layout--story > .rail { grid-column: 3; }
}

/* 1001–1180px：主区先让位，右栏缩到 296px 保住组合成片 */
@media (min-width: 1001px) and (max-width: 1180px) {
  .layout--story { grid-template-columns: 236px minmax(0, 1fr) 296px; }
  .layout--story > .sidebar { grid-column: 1; }
  .layout--story > .main { grid-column: 2; }
  .layout--story > .rail { grid-column: 3; }
}

/* 901–1000px：真的放不下三栏了，右栏收起（组合成片改在主区里） */
@media (min-width: 901px) and (max-width: 1000px) {
  .layout--story { grid-template-columns: 236px minmax(0, 1fr); }
  .layout--story > .sidebar { grid-column: 1; }
  .layout--story > .main { grid-column: 2; }
  .layout--story > .rail { display: none; }
}

@media (max-width: 1500px) {
  .shot-grid {
    grid-template-columns: minmax(0, 1fr) minmax(200px, 250px);
    grid-template-areas: "prompt params" "cast cast" "versions versions";
  }
  .shot-sec--params { padding-left: var(--sp-4); }
}

@media (max-width: 1180px) {
  .shot-grid {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "prompt" "params" "cast" "versions";
  }
  .shot-sec--params { padding-left: 0; border-left: none; border-top: 1px solid var(--border); padding-top: var(--sp-4); }
}

/* 980px 以下：右侧栏收起，并让导航换到顶栏第二行。
   这里**不写** .layout 的单列规则——留给下面的 900px 档，避免源码顺序把它覆盖掉。 */
@media (max-width: 980px) {
  /* 注意：这里**不再**写 .rail { display: none } —— 三栏的收起阈值由上面
     1001px 那一档统一决定。两处都写会互相打架：980 档在后面，
     会把 1001–1180 档显式打开的右栏又盖掉（组合成片就找不到了）。 */
  .topbar { flex-wrap: wrap; }
  .topbar__left { flex-wrap: wrap; order: 1; }
  .topbar__right { order: 2; }
  .appnav { order: 3; width: 100%; margin-left: 0; }
  .appnav__item { flex: 1; justify-content: center; }
}

/* 900px 以下：侧栏也收起，主区独占一行。
   必须放在 980px 档之后：原文件更靠前的 @media (max-width:900px) 单列规则
   会被中间任意一条 .layout 规则按源码顺序覆盖。 */
@media (max-width: 900px) {
  .layout { grid-template-columns: minmax(0, 1fr); }
  .main { grid-column: 1; }
  .story-toolbar { padding: var(--sp-2) var(--sp-3); }
  .char-grid { grid-template-columns: minmax(0, 1fr); }
  .shot-card__head { flex-wrap: wrap; padding: var(--sp-2) var(--sp-3); }
  .shot-card__body { padding: 0 var(--sp-3) var(--sp-3); }
  .shot-card__bar, .shot-card__error { padding-left: var(--sp-3); padding-right: var(--sp-3); }
  .shot-card__error { margin-left: var(--sp-3); margin-right: var(--sp-3); }
  .versions { gap: var(--sp-2); }
  .ver-card { width: 160px; }
}

@media (max-width: 560px) {
  .char-card { grid-template-columns: 60px minmax(0, 1fr); }
  .char-card__thumb { width: 60px; height: 60px; }
  .topbar__left .brand__sub { max-width: 180px; }
  .compose-opts { grid-template-columns: 1fr; }
}

/* ===== LLM 提示词模板（system / user） ===== */
.tpl {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  padding-top: var(--sp-4);
  border-top: 1px solid var(--border);
}
.tpl__title { font-size: 13px; font-weight: 600; }
.tpl-field { display: flex; flex-direction: column; gap: var(--sp-2); }
.tpl-field__head { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); flex-wrap: wrap; }
.tpl-field__head .field__label { margin: 0; }
.tpl-field__head code { font-size: 11px; }
.tpl-field__foot { align-items: center; gap: var(--sp-2); }
.textarea--tpl { min-height: 180px; font-size: 12.5px; line-height: 1.6; }
.field__hint.is-override { color: var(--primary-fg); }

.tpl-vars { display: flex; flex-wrap: wrap; align-items: center; gap: 5px; }
.tpl-vars__label {
  font-size: 11px;
  color: var(--fg-muted);
  letter-spacing: .04em;
  padding-right: 2px;
}
.tpl-var {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  min-height: 28px;
  padding: 0 8px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--surface-2);
  color: var(--fg-muted);
  cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.tpl-var code { background: transparent; padding: 0; color: var(--fg); font-size: 11px; }
.tpl-var:hover { border-color: var(--primary); background: rgba(236, 72, 153, .12); color: var(--fg); }
.tpl-var:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; }
.tpl-vars__hint {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 11px;
  color: var(--fg-dim);
}
.tpl-preview__head {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-3) var(--sp-3) 0;
}
.tpl-preview__tag {
  display: inline-flex;
  align-items: center;
  padding: 0 8px;
  min-height: 22px;
  border-radius: 999px;
  border: 1px solid rgba(37, 99, 235, .45);
  background: rgba(37, 99, 235, .14);
  color: var(--info-fg);
  font-family: var(--mono);
  font-size: 11px;
}
.tpl-preview__foot { padding: 0 var(--sp-3) var(--sp-3); align-items: center; gap: var(--sp-2); }
.fold__body { display: flex; flex-direction: column; gap: var(--sp-2); padding-bottom: var(--sp-2); }
.fold__body .fold__pre { max-height: 220px; border: 1px solid var(--border); border-radius: 8px; margin: 0 var(--sp-3); }

/* ============================================================================
   多用户部署（登录页 / 后台管理页 / 顶栏用户菜单）
   本段同样是**纯追加**：不修改上方任何既有规则，只新增 .usermenu / .auth-* /
   .admin-* / .settings-* / .stepper / .pwd-meter / .holder / .chip--var 系列。
   ========================================================================= */

/* ===== 顶栏用户菜单（index.html / story.html / admin.html 共用） ===== */
.usermenu { position: relative; flex: none; }

.usermenu__btn {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: 40px;
  padding: 0 var(--sp-2) 0 5px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--surface-2);
  color: var(--fg);
  font-size: 13px;
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.usermenu__btn:hover { background: var(--hover-bg-strong); border-color: var(--border-strong); }
.usermenu__btn[aria-expanded="true"] { border-color: var(--primary); background: var(--surface-2); }

.usermenu__avatar {
  display: grid;
  place-items: center;
  width: 28px; height: 28px;
  flex: none;
  border-radius: 50%;
  background: linear-gradient(140deg, rgba(236, 72, 153, .26), rgba(37, 99, 235, .26));
  border: 1px solid var(--border-strong);
  color: var(--primary);
}
.usermenu__name {
  max-width: 140px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 500;
}
.usermenu__chev { color: var(--fg-muted); transition: transform var(--dur) var(--ease); }
.usermenu__btn[aria-expanded="true"] .usermenu__chev { transform: rotate(180deg); }

.usermenu__pop {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 70;
  width: 236px;
  padding: 5px;
  border-radius: var(--radius);
  border: 1px solid var(--border-strong);
  background: var(--surface);
  box-shadow: var(--shadow-pop);
  animation: usermenu-in var(--dur) var(--ease);
}
@keyframes usermenu-in { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }

.usermenu__meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 4px;
  padding: 8px var(--sp-3) 10px;
  margin-bottom: 4px;
  border-bottom: 1px solid var(--border);
  font-size: 11px;
  color: var(--fg-muted);
}
.usermenu__meta-name { color: var(--fg); font-weight: 600; font-size: 12px; }
.usermenu__meta-sep { color: var(--fg-dim); }
.usermenu__conc { color: var(--fg); font-variant-numeric: tabular-nums; }

.usermenu__item {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  width: 100%;
  min-height: 40px;
  padding: 0 var(--sp-3);
  border: none;
  border-radius: 8px;
  background: transparent;
  color: var(--fg-muted);
  font-size: 13px;
  text-align: left;
  text-decoration: none;
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.usermenu__item svg { color: var(--fg-dim); }
.usermenu__item:hover { background: var(--subtle-bg); color: var(--fg); }
.usermenu__item:hover svg { color: var(--fg); }
.usermenu__item--danger:hover { background: rgba(220, 38, 38, .14); color: var(--danger-fg); }
.usermenu__item--danger:hover svg { color: var(--danger-fg); }
.usermenu__sep { height: 1px; margin: 5px var(--sp-2); background: var(--border); }

/* ===== 密码强度计（登录页 / 用户菜单 / 后台共用） ===== */
.pwd-meter {
  display: inline-block;
  vertical-align: middle;
  width: 84px; height: 5px;
  border-radius: 999px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  overflow: hidden;
}
.pwd-meter__bar {
  display: block;
  width: 0%; height: 100%;
  border-radius: 999px;
  background: var(--fg-dim);
  transition: width var(--dur) var(--ease), background var(--dur) var(--ease);
}
.pwd-meter.is-bad .pwd-meter__bar { background: var(--danger); }
.pwd-meter.is-warn .pwd-meter__bar { background: var(--warn); }
.pwd-meter.is-ok .pwd-meter__bar { background: var(--success); }
.pwd-meter__text { font-size: 11px; color: var(--fg-muted); font-variant-numeric: tabular-nums; }
.pwd-meter__text.is-bad { color: var(--danger-fg); }
.pwd-meter__text.is-warn { color: var(--warn-fg); }
.pwd-meter__text.is-ok { color: var(--success-fg); }

/* ===== 登录页 / 初始化页 ===== */
/* 布局：≥981px 左侧品牌叙述 + 右侧表单卡片；更窄压成单列，品牌只留标题。
   两团品牌光晕挂在 .auth 上；深浅两套主题共用同一份结构，只换 token。 */
.auth-body { overflow: auto; }

.auth {
  position: relative;          /* ::before/::after 的品牌光晕挂在它上面 */
  min-height: 100dvh;          /* 内容不足一屏时也要垂直居中 */
  display: grid;
  place-items: center;
  gap: 0;
  padding: clamp(24px, 5vh, 56px) clamp(16px, 4vw, 48px);
}
.auth::before,
.auth::after {
  content: "";
  position: absolute;
  z-index: 0;
  border-radius: 50%;
  filter: blur(80px);
  pointer-events: none;
}
.auth::before {
  width: clamp(280px, 34vw, 460px);
  height: clamp(280px, 34vw, 460px);
  left: -4%; top: -8%;
  background: radial-gradient(circle, var(--glow-primary), transparent 70%);
}
.auth::after {
  width: clamp(300px, 38vw, 520px);
  height: clamp(300px, 38vw, 520px);
  right: -6%; bottom: -12%;
  background: radial-gradient(circle, var(--glow-accent), transparent 70%);
}

.auth__grid {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: minmax(0, 1.06fr) minmax(0, .94fr);
  align-items: center;
  gap: clamp(28px, 5vw, 76px);
  width: min(1140px, 100%);
}

/* ---- 左栏：品牌与技术卖点 ---- */
.auth-brand { display: flex; flex-direction: column; gap: clamp(20px, 3.4vh, 34px); min-width: 0; }
.auth-brand__head { display: flex; align-items: center; gap: var(--sp-3); }
.auth-brand__mark {
  display: grid;
  place-items: center;
  width: 46px; height: 46px;
  flex: none;
  border-radius: 14px;
  background: linear-gradient(140deg, var(--primary), var(--accent));
  color: #fff;
  box-shadow: 0 12px 28px -10px var(--glow-primary-strong);
}
.auth-brand__mark svg { width: 24px; height: 24px; }
.auth-brand__name { font-size: 19px; font-weight: 650; letter-spacing: .01em; color: var(--fg); }

.auth-brand__copy { display: flex; flex-direction: column; }
.auth-brand__eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .04em;
  color: var(--primary-fg);
}
.auth-brand__eyebrow::before {
  content: "";
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--primary);
  box-shadow: 0 0 0 4px var(--glow-primary);
}
.auth-brand__headline {
  margin-top: var(--sp-3);
  font-size: clamp(30px, 3.5vw, 44px);
  font-weight: 700;
  line-height: 1.16;
  letter-spacing: -.02em;
  color: var(--fg);
}
.auth-brand__headline span { color: var(--primary); }
.auth-brand__lead {
  margin-top: var(--sp-3);
  max-width: 44ch;
  font-size: 14px;
  line-height: 1.7;
  color: var(--fg-muted);
}

.auth-brand__feats { display: flex; flex-direction: column; gap: var(--sp-3); }
.auth-brand__feats li { display: flex; align-items: flex-start; gap: var(--sp-3); }
.auth-brand__feat-icon {
  display: grid;
  place-items: center;
  width: 34px; height: 34px;
  flex: none;
  border-radius: 10px;
  border: 1px solid var(--border-strong);
  background: var(--surface);
  color: var(--primary);
  box-shadow: var(--shadow-soft);
}
.auth-brand__feat-icon svg { width: 17px; height: 17px; }
.auth-brand__feat-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.auth-brand__feat-text b { font-size: 13px; font-weight: 600; color: var(--fg); }
.auth-brand__feat-text em { font-style: normal; font-size: 12px; line-height: 1.55; color: var(--fg-muted); }

/* 分镜条：一条静态时间轴 + 一道很淡的扫描光，点题「视频流水线」 */
.auth-brand__timeline {
  position: relative;
  display: flex;
  gap: 4px;
  height: 36px;
  padding: 5px;
  border-radius: 12px;
  border: 1px solid var(--border);
  background: var(--surface);
  overflow: hidden;
}
.auth-brand__timeline span { flex: 1; border-radius: 5px; background: var(--surface-2); }
.auth-brand__timeline span:nth-child(2),
.auth-brand__timeline span:nth-child(7) {
  background: linear-gradient(180deg, var(--primary), var(--accent));
  opacity: .9;
}
.auth-brand__timeline::after {
  content: "";
  position: absolute;
  top: 0; bottom: 0;
  width: 30px;
  background: linear-gradient(90deg, transparent, var(--glow-primary-strong), transparent);
  animation: auth-scan 5s var(--ease) infinite;
}
@keyframes auth-scan {
  0% { transform: translateX(-30px); }
  55%, 100% { transform: translateX(520px); }
}

/* ---- 右栏：表单卡片 ---- */
.auth-panel {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-4);
  min-width: 0;
}

.auth-card {
  position: relative;
  width: 100%;
  border-radius: var(--radius-lg);
  border: 1px solid var(--border-strong);
  background: var(--surface);
  box-shadow: var(--shadow-soft), var(--shadow-auth);
  overflow: hidden;
}
.auth-card::before { /* 顶部品牌发丝线 */
  content: "";
  display: block;
  height: 3px;
  background: linear-gradient(90deg, var(--primary), var(--accent));
}
.auth-card__head {
  display: block;
  padding: var(--sp-6) var(--sp-6) 0;
  border-bottom: none;
}
.auth-card__title { font-size: 20px; font-weight: 650; letter-spacing: -.01em; color: var(--fg); }
.auth-card__sub { margin-top: 4px; font-size: 12.5px; color: var(--fg-muted); }
.auth-card__body { padding: var(--sp-5) var(--sp-6) var(--sp-6); }

.auth-form { display: flex; flex-direction: column; gap: var(--sp-4); }
.auth-loading {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-4) 0;
  font-size: 13px;
  color: var(--fg-muted);
}
.auth-note { font-size: 11px; color: var(--fg-muted); line-height: 1.6; }
.auth-foot {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--sp-2);
  font-size: 11px;
  color: var(--fg-dim);
}
.auth-foot__brand { color: var(--fg-muted); }

/* 登录页的字段错误要显眼一点 */
.auth-form .field__error {
  padding: 8px 10px;
  border-radius: 10px;
  border: 1px solid rgba(220, 38, 38, .45);
  background: rgba(220, 38, 38, .1);
}
.auth-form .field__error:empty { display: none; }

/* 大写锁定提示：只在真的开着时出现 */
.auth-caps {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  line-height: 1.5;
  color: var(--warn-fg);
}
.auth-caps svg { width: 13px; height: 13px; }

/* 入场：只动 opacity / transform，150–250ms，尊重 reduced-motion */
@media (prefers-reduced-motion: no-preference) {
  .auth-brand { animation: auth-rise var(--dur-slow) var(--ease) both; }
  .auth-card { animation: auth-rise var(--dur-slow) var(--ease) both; animation-delay: 70ms; }
  .auth-panel .auth-foot { animation: auth-rise var(--dur-slow) var(--ease) both; animation-delay: 140ms; }
}
@keyframes auth-rise {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .auth-brand__timeline::after { display: none; }
}

/* ---- 窄屏：单列，品牌只留标题 ---- */
@media (max-width: 980px) {
  .auth__grid { grid-template-columns: minmax(0, 1fr); width: min(460px, 100%); gap: var(--sp-6); }
  .auth-brand { gap: var(--sp-4); }
  .auth-brand__lead,
  .auth-brand__feats,
  .auth-brand__timeline { display: none; }
  .auth-brand__headline { margin-top: var(--sp-2); font-size: 26px; }
  .auth-panel { width: 100%; }
}
@media (max-width: 560px) {
  .auth { padding: var(--sp-5) var(--sp-3); }
  .auth-brand__headline { font-size: 22px; }
}

/* ===== 后台管理页 ===== */
.app--admin { grid-template-rows: auto minmax(0, 1fr); }
.admin-gate {
  display: grid;
  place-items: center;
  padding: var(--sp-6);
  overflow: auto;
}
.admin {
  min-height: 0;
  overflow-y: auto;
  padding: var(--sp-5);
}
.admin__inner {
  display: flex;
  flex-direction: column;
  gap: var(--sp-5);
  max-width: 1500px;
  margin: 0 auto;
}
.admin-loading {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  grid-column: 1 / -1;
  color: var(--fg-muted);
  font-size: 13px;
  padding: var(--sp-4) 0;
}
.admin-muted { color: var(--fg-muted); font-size: 12px; }
.admin-overview__body { display: flex; flex-direction: column; gap: var(--sp-4); }
.admin-cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: var(--sp-4); }
/* 后台的空状态别占满整屏：这里是「一块区域暂时是空的」，不是首屏落地页 */
.admin .empty-state { min-height: 220px; padding: var(--sp-5) var(--sp-4); }
.admin .empty-state__art svg { width: 84px; height: 68px; }
.admin .empty-state__title { font-size: 15px; }
.admin .empty-state__text { font-size: 12px; max-width: 420px; }
.admin-subcard {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface-2);
  padding: var(--sp-3) var(--sp-4);
  min-width: 0;
}
.admin-subcard__title {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--fg-muted);
  margin-bottom: var(--sp-3);
}
.admin-subcard__hint { font-size: 11px; font-weight: 400; letter-spacing: 0; text-transform: none; color: var(--fg-dim); }

/* 闸门状态条 */
.gate-card {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: linear-gradient(180deg, rgba(236, 72, 153, .07), rgba(37, 99, 235, .05));
  padding: var(--sp-4);
}
.gate-card__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  flex-wrap: wrap;
  margin-bottom: var(--sp-3);
}
.gate-card__title { font-size: 13px; font-weight: 600; }
.gate-card__stat { font-size: 14px; font-weight: 600; font-variant-numeric: tabular-nums; }
.gate-card__legend { margin-top: var(--sp-3); font-size: 12px; color: var(--fg-muted); font-variant-numeric: tabular-nums; }
#gate-track { height: 10px; }
.gate-card #gate-fill.is-full { background: var(--warn); }

.holder-list { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.holder {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding: 5px 10px 5px 5px;
  border-radius: 999px;
  border: 1px solid var(--border-strong);
  background: var(--surface);
  font-size: 12px;
}
.holder__avatar {
  display: grid;
  place-items: center;
  width: 22px; height: 22px;
  border-radius: 50%;
  background: rgba(16, 185, 129, .16);
  color: var(--success-fg);
}
.holder__name { font-weight: 500; }
.holder__slots { color: var(--fg-muted); font-variant-numeric: tabular-nums; }

.kv--wide { grid-template-columns: minmax(90px, auto) minmax(0, 1fr); }
.kv--wide dd { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }

/* 任务 / 用户表格 */
.data-table--users { min-width: 1060px; }
.data-table--jobs { min-width: 920px; }
.col-role { width: 132px; }
.col-conc { width: 132px; }
.col-storage { width: 150px; }
.col-running { width: 118px; }
.col-login { width: 148px; }
.col-useracts { width: 150px; }
.col-owner { width: 132px; }
.col-progress { width: 190px; }
.col-status { width: 110px; }

.user-cell { display: flex; align-items: center; gap: var(--sp-2); min-width: 0; }
.user-cell__avatar {
  display: grid;
  place-items: center;
  width: 26px; height: 26px;
  flex: none;
  border-radius: 8px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  color: var(--fg-muted);
}
.user-cell__name { font-weight: 500; }
.user-cell__edit { max-width: 200px; }

.cell-sub { display: block; font-size: 11px; color: var(--fg-muted); margin-top: 2px; font-variant-numeric: tabular-nums; }

.job-title { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.job-title__name { font-weight: 500; }
.job-title__msg {
  font-size: 11px;
  color: var(--fg-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 320px;
}
.status-cell__bar { min-width: 120px; }
.status-cell__pct {
  font-size: 11px;
  color: var(--fg-muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  gap: 5px;
}
.status-cell__pct .td-num { font-size: 11px; }

/* ===== 数字步进器（用户并发槽 / 全局设置数字项共用） ===== */
.stepper {
  display: inline-flex;
  align-items: stretch;
  border-radius: 10px;
  border: 1px solid var(--border-strong);
  background: var(--surface);
  overflow: hidden;
  transition: border-color var(--dur-fast) var(--ease);
}
.stepper:focus-within { border-color: var(--primary); box-shadow: 0 0 0 2px rgba(236, 72, 153, .22); }
.stepper.is-disabled { opacity: .5; }
.stepper__btn {
  display: grid;
  place-items: center;
  width: 32px; height: 34px;
  flex: none;
  border: none;
  background: transparent;
  color: var(--fg-muted);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.stepper__btn:hover:not(:disabled) { background: var(--surface-2); color: var(--fg); }
.stepper__btn:disabled { opacity: .35; cursor: not-allowed; }
.stepper__input {
  width: 50px;
  min-height: 34px;
  padding: 0 2px;
  border: none;
  border-left: 1px solid var(--border);
  border-right: 1px solid var(--border);
  background: transparent;
  color: var(--fg);
  text-align: center;
  font-size: 13px;
  font-variant-numeric: tabular-nums;
}
.stepper__input:focus-visible { outline: none; }
.stepper__input::-webkit-outer-spin-button,
.stepper__input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.stepper__input[type="number"] { -moz-appearance: textfield; appearance: textfield; }
.stepper--settings .stepper__btn { width: 42px; height: 40px; }
.stepper--settings .stepper__input { width: 104px; min-height: 40px; font-size: 14px; }
.settings-field .stepper { align-self: flex-start; }
/* 用户表里的并发步进器：窄列里也放得下四位数 */
.data-table--users .stepper__input { width: 46px; }

/* ===== 全局设置 ===== */
.settings-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(330px, 1fr));
  gap: var(--sp-4);
  align-items: start;
  margin-top: var(--sp-4);
}
.settings-card {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface-2);
  overflow: hidden;
  min-width: 0;
}
.settings-card__head {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
  padding: var(--sp-4);
  border-bottom: 1px solid var(--border);
}
.settings-card__icon {
  display: grid;
  place-items: center;
  width: 32px; height: 32px;
  flex: none;
  border-radius: 10px;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  color: var(--primary);
}
.settings-card__titles { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.settings-card__title { font-size: 14px; font-weight: 600; }
.settings-card__note { font-size: 11px; color: var(--fg-muted); line-height: 1.55; }
.settings-card__group {
  grid-column: 1 / -1;
  margin: var(--sp-2) 0 0;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--fg-muted);
}
.settings-card__body { padding: var(--sp-4); flex: 1; }
.settings-fields { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: var(--sp-4); }
.settings-field--wide { grid-column: 1 / -1; }
/* 开关类字段：标签与开关同一行，说明文字换行到下一行 */
.settings-field--switch { gap: 4px var(--sp-3); }
.settings-field--switch .field__label { flex: 1; }
.settings-field--switch .switch { flex: none; }
.settings-card__foot {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  flex-wrap: wrap;
  padding: var(--sp-3) var(--sp-4);
  border-top: 1px solid var(--border);
  background: var(--surface);
}
.settings-card__msg { font-size: 12px; color: var(--fg-muted); line-height: 1.5; max-width: 100%; word-break: break-word; }
.settings-card__msg.is-ok { color: var(--success-fg); }
.settings-card__msg.is-bad { color: var(--danger-fg); }
.settings-card__msg .adapter-test__detail { margin-top: 4px; }

.chip--var {
  display: inline-flex;
  align-items: center;
  min-height: 26px;
  padding: 0 8px;
  border-radius: 999px;
  border: 1px solid var(--border-strong);
  background: var(--surface);
  color: var(--fg-muted);
  font-size: 11px;
  cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease);
}
.chip--var:hover { border-color: var(--primary); color: var(--fg); background: rgba(236, 72, 153, .1); }
.chip--var code { background: transparent; padding: 0; color: inherit; font-size: 11px; }

/* ===== 后台窄屏 ===== */
@media (max-width: 900px) {
  .admin { padding: var(--sp-4) var(--sp-3); }
  .settings-grid { grid-template-columns: 1fr; }
  .admin-cols { grid-template-columns: 1fr; }
  .usermenu__name { max-width: 84px; }
}
@media (max-width: 560px) {
  .usermenu__pop { right: 0; width: min(260px, calc(100vw - 24px)); }
  .settings-fields { grid-template-columns: 1fr; }
  .auth-card__head,
  .auth-card__body { padding: var(--sp-4); }
}

/* ============================================================================
   剧本智能拆分（story.html / story.js）—— 智能生成分镜
   本段是**纯追加**：不修改上方任何既有规则，只新增 .dlg-script__* 系列。
   契约见 docs/SCRIPT_IMPORT_API.md。
   ========================================================================= */

/* ===== 工具条入口：项目里没有分镜时呼吸一下，提示新手从这儿开始 ===== */
.btn.dlg-script__cta-glow { box-shadow: 0 0 0 0 rgba(219, 39, 119, .5); animation: dlg-script-glow 2.6s var(--ease) infinite; }
.btn.dlg-script__cta-glow:hover:not(:disabled) { animation-play-state: paused; }
@keyframes dlg-script-glow {
  0%   { box-shadow: 0 0 0 0 rgba(219, 39, 119, .5); }
  60%  { box-shadow: 0 0 0 7px rgba(219, 39, 119, 0); }
  100% { box-shadow: 0 0 0 0 rgba(219, 39, 119, 0); }
}

/* ===== 对话框骨架：body 自己滚，窄屏不溢出 ===== */
.dlg-script { width: min(780px, calc(100vw - 32px)); }
.dlg-script .dialog__form { max-height: min(86vh, 900px); }
.dlg-script__body { gap: var(--sp-4); overflow-y: auto; overscroll-behavior: contain; }
.dlg-script__step { display: flex; flex-direction: column; gap: var(--sp-4); }

/* ===== 对话框内错误条 ===== */
.dlg-script__error {
  margin: 0;
  padding: var(--sp-3);
  border-radius: var(--radius);
  border: 1px solid rgba(220, 38, 38, .4);
  background: rgba(220, 38, 38, .1);
  color: var(--danger-fg);
  font-size: 13px;
  line-height: 1.6;
  word-break: break-word;
}
.dlg-script__error::before { content: "! "; font-weight: 700; }

/* ===== 第一步：剧本输入 ===== */
.dlg-script__fieldhead { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); }
.dlg-script__count { font-size: 12px; color: var(--fg-muted); white-space: nowrap; }
.dlg-script__count.is-short { color: var(--warn-fg); }

.dlg-script__area { position: relative; display: flex; }
.dlg-script__text {
  width: 100%;
  min-height: 240px;
  max-height: 46vh;
  padding: var(--sp-3);
  resize: vertical;
  font-family: var(--mono);
  font-size: 13px;
  line-height: 1.7;
  tab-size: 2;
}
.dlg-script__area.is-over .dlg-script__text { border-color: var(--primary); background: rgba(236, 72, 153, .06); }

.dlg-script__dropmask {
  position: absolute;
  inset: 2px;
  display: none;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  border-radius: var(--radius);
  border: 1.5px dashed var(--primary);
  background: rgba(15, 23, 42, .88);
  color: var(--fg);
  font-size: 13px;
  pointer-events: none;
  text-align: center;
}
.dlg-script__dropmask svg { width: 28px; height: 28px; color: var(--primary); }
.dlg-script__area.is-over .dlg-script__dropmask { display: flex; }

.dlg-script__dropbar { display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; }
.dlg-script__fname { color: var(--fg); font-weight: 500; }

/* ===== 第一步：两个 switch ===== */
.dlg-script__switches { display: flex; flex-direction: column; gap: var(--sp-2); }
.dlg-script__switches .switch {
  align-items: flex-start;
  padding: var(--sp-2) var(--sp-3);
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: var(--surface-2);
}
.dlg-script__switches .switch__label { color: var(--fg); font-size: 13px; }
.dlg-script__switches .field__hint { display: block; margin-top: 2px; }
.dlg-script__switches .switch__track { margin-top: 2px; }
.switch__track--danger { border-color: rgba(220, 38, 38, .5); }
.switch__input:checked + .switch__track--danger { background: var(--danger); border-color: transparent; }
.is-danger { color: var(--danger-fg) !important; }

/* ===== 第二步：摘要条 ===== */
.dlg-script__summary {
  margin: 0;
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: var(--surface-2);
  font-size: 14px;
  color: var(--fg-muted);
}
.dlg-script__summary b { color: var(--fg); font-weight: 600; }
.dlg-script__mock {
  display: inline-flex;
  align-items: center;
  margin-left: var(--sp-2);
  padding: 1px 8px;
  border-radius: 999px;
  border: 1px solid rgba(245, 158, 11, .4);
  background: rgba(245, 158, 11, .12);
  color: var(--warn-fg);
  font-size: 11px;
  font-weight: 500;
}

/* ===== 第二步：警告区 ===== */
.dlg-script__warns {
  padding: var(--sp-3);
  border-radius: var(--radius);
  border: 1px solid rgba(245, 158, 11, .4);
  background: rgba(245, 158, 11, .1);
  color: var(--warn-fg);
  font-size: 12px;
}
.dlg-script__warn-head { display: flex; align-items: center; gap: var(--sp-2); font-weight: 600; font-size: 13px; }
.dlg-script__warn-list { margin: var(--sp-2) 0 0; padding-left: 22px; list-style: disc; display: flex; flex-direction: column; gap: 3px; line-height: 1.6; }

/* ===== 第二步：分区标题 ===== */
.dlg-script__block { display: flex; flex-direction: column; gap: var(--sp-2); min-width: 0; }
.dlg-script__blockhead { display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-3); flex-wrap: wrap; }
.dlg-script__blocktitle { font-size: 13px; font-weight: 600; color: var(--fg); }
.dlg-script__blocksub { font-size: 12px; color: var(--fg-muted); }
.dlg-script__empty { margin: 0; font-size: 12px; color: var(--fg-muted); padding: var(--sp-3); border: 1px dashed var(--border-strong); border-radius: var(--radius); }

/* ===== 第二步：角色 chip 网格 ===== */
.dlg-script__chars {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(226px, 1fr));
  gap: var(--sp-2);
  max-height: 210px;
  overflow-y: auto;
  padding: 2px;
}
.dlg-script__char {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-2);
  min-width: 0;
  padding: var(--sp-3);
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: var(--surface-2);
}
.dlg-script__avatar {
  display: grid;
  place-items: center;
  flex: none;
  width: 26px; height: 26px;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: var(--muted);
  color: var(--fg-dim);
}
.dlg-script__char-main { display: flex; flex-direction: column; gap: 3px; min-width: 0; flex: 1; }
.dlg-script__char-top { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }
.dlg-script__char-name { font-size: 13px; font-weight: 600; color: var(--fg); overflow-wrap: anywhere; }
.dlg-script__badge { flex: none; }
.dlg-script__char-desc {
  font-size: 11px;
  color: var(--fg-muted);
  line-height: 1.5;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.dlg-script__char-used { font-size: 11px; color: var(--fg-dim); }

/* ===== 第二步：分镜列表 ===== */
.dlg-script__shots {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  max-height: 300px;
  overflow-y: auto;
  padding: 2px;
}
.dlg-script__shot {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
  padding: var(--sp-3);
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: var(--surface-2);
}
.dlg-script__shot-idx {
  display: grid;
  place-items: center;
  flex: none;
  min-width: 24px; height: 24px;
  padding: 0 5px;
  border-radius: 8px;
  background: var(--muted);
  border: 1px solid var(--border);
  font-size: 12px;
  font-weight: 600;
  color: var(--fg-muted);
}
.dlg-script__shot-main { display: flex; flex-direction: column; gap: 4px; min-width: 0; flex: 1; }
.dlg-script__shot-title { font-size: 13px; font-weight: 600; color: var(--fg); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dlg-script__shot-chars { display: flex; flex-wrap: wrap; gap: var(--sp-1); }
.dlg-script__shot-prompt {
  font-size: 12px;
  color: var(--fg-muted);
  line-height: 1.6;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dlg-script__shot-dur { flex: none; font-size: 12px; color: var(--fg-muted); }
.chip.chip--static {
  min-height: 22px;
  padding: 0 8px;
  font-size: 11px;
  cursor: default;
  border-color: var(--border);
  background: var(--muted);
}
.chip.chip--static:hover { border-color: var(--border); color: var(--fg-muted); }
.dlg-script__nochar {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 11px;
  color: var(--warn-fg);
}

/* ===== 窄屏 ===== */
@media (max-width: 640px) {
  .dlg-script .dialog__body { padding: var(--sp-3); }
  .dlg-script__chars { grid-template-columns: 1fr; max-height: 180px; }
  .dlg-script__shots { max-height: 240px; }
  .dlg-script__text { min-height: 180px; max-height: 36vh; }
  .dlg-script__shot-prompt { white-space: normal; display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; }
  .dlg-script__shot-dur { align-self: flex-start; }
}

/* ===== reduced motion：关掉强调动画 ===== */
@media (prefers-reduced-motion: reduce) {
  .btn.dlg-script__cta-glow { animation: none !important; box-shadow: none; }
  /* 跨页淡入淡出对前庭敏感的人不友好，一并关掉 */
  html.is-leaving .app, html.is-entering .app { opacity: 1 !important; transform: none; }
  .app { transition: none; }
}

/* ============================================================================
 * ===== 右栏：成片 + 分镜详情 + 常驻任务控制台 =====
 *
 * 宽屏（≥1280px）把工作台切成两段：
 *   第一行是「页头 + 模式说明」，横跨整幅（`.workspace__top`）；
 *   第二行起左右分栏 —— 左边流水线 + 分镜表格，右边 320px 放三件随时要看的
 *   东西：成片预览（做完就要看，不该埋在页面最底下）、当前分镜详情、
 *   任务控制台。底部那条折叠抽屉在宽屏上收进右栏，纵向空间还给表格。
 * 窄屏整栏隐藏：成片回主区最下面、控制台回底部抽屉，用的是同一份 DOM。
 *
 * 右栏高度是「100vh 减掉头顶那些」算出来的，所以头顶每多占一行，都是从右栏
 * 的预算里扣：流水线因此留在左列并紧凑化（见文件末尾的 ≥1280 那条），
 * 宁可让它在左列窄一点，也不让右栏的控制台被挤出去。
 *
 * 阈值必须和 app.js 的 RAIL_BREAKPOINT 配对（那边 1280 → 这边 max-width 1279），
 * ui_test 的 [G] 段盯着这一对。
 * ========================================================================= */
.workspace {
  display: grid;
  /* 右栏已经搬到 .layout（见 .layout--work），主区独占整行 */
  grid-template-columns: minmax(0, 1fr);
  align-items: start;
  gap: var(--sp-5);
}
.workspace > * { min-width: 0; }
/* 第一行整条横跨：页头 + 模式说明 */
.workspace__top {
  grid-column: 1 / -1;
  display: flex;
  flex-direction: column;
  gap: var(--sp-5);
  min-width: 0;
}
/* 左列是**一个** grid 子项（里面再用 flex 排版）：右栏要跟整列并排，就不能让
   左列占很多行 —— 跨行的每一行之间都有 20px 的 gap，跨 20 行 = 19×20 = 380px
   的假高度，页面明明没内容也要往下滚一大截（之前就是这个症状）。
   一行放完，右栏只需要 grid-row: 2。 */
.workspace__main {
  grid-column: 1;
  display: flex;
  flex-direction: column;
  gap: var(--sp-5);
  min-width: 0;
}
.workspace > .rail {
  grid-column: 2;
  grid-row: 2;
  /* 外层 .main__scroll 已经给了 20px；story 页那套 .rail 的 padding 会继承下来，
     这里必须清掉 —— 右栏一共 581px 高，白扔 40px 就是从成片卡身上扣 */
  padding: 0;
  position: sticky;
  top: 0;
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  height: calc(100vh - 190px);
  min-height: 320px;
  /* 右栏自己**不滚**：里面分成「成片 + 详情（自己滚）+ 控制台（固定）」。这样
     任务控制台的主按钮永远在视口里 —— 详情再长也不用先滚到底才能开始干活。 */
  overflow: hidden;
}

.railcard {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  padding: var(--sp-4);
  /* 详情吃掉剩余高度，内容超出时自己滚；成片卡和控制台固定在上下两头 */
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-soft);
  min-width: 0;
}
/* 成片卡和详情卡是同一个位置的两个 tab：谁显示谁独占这段高度（见 railTabsSync） */
.railcard--final { padding: var(--sp-3); gap: var(--sp-2); }
.rail__tabs { display: flex; flex: none; }
.rail__tabs .segmented__item { flex: 1; padding: 0 var(--sp-2); min-height: 30px; }
.railcard__head { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2); }
/* 卡片内容比卡片高时，默认 flex-shrink: 1 会把每一块**压扁**去迁就高度：
   视频那一格（overflow: hidden）直接被压成 0 高 —— 右栏里就能看到「分镜没有
   预览」这种假象。改成谁都不许缩，让 .railcard 自己滚。 */
.railcard > * { flex: none; }
/* 例外：成片卡里的 result-card 要吃满整张卡，左边那列视频才撑得起来 */
.railcard > .result-card { flex: 1; min-height: 0; }
.railcard__title { font-size: 14px; font-weight: 600; }
.railcard__block { display: flex; flex-direction: column; gap: var(--sp-2); }
.railcard__label { font-size: 12px; font-weight: 600; color: var(--fg-muted); }
.railcard__row { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }
.railcard--empty { color: var(--fg-muted); }
.rail__empty { font-size: 12px; color: var(--fg-muted); line-height: 1.6; }
.rail__hint { font-size: 11px; color: var(--fg-muted); }
.rail__hint b { color: var(--fg); font-weight: 600; }
.rail__error { display: inline-flex; align-items: center; gap: 4px; font-size: 11px; color: var(--danger-fg); }
.rail__error-text { font-size: 11px; color: var(--danger-fg); line-height: 1.5; overflow-wrap: anywhere; }
.rail__textarea {
  width: 100%;
  min-height: 56px;
  padding: var(--sp-2);
  border-radius: 10px;
  border: 1px solid var(--border-strong);
  background: var(--muted);
  color: var(--fg);
  font-family: var(--font);
  font-size: 13px;
  line-height: 1.5;
  resize: vertical;
}
.rail__textarea:focus { outline: none; border-color: var(--primary); }

/* 预览：9:16 竖屏短剧为主，给一个固定的舞台避免加载时跳高 */
.railcard__stage { border-radius: 12px; overflow: hidden; background: #000; }
.railplayer { display: block; width: 100%; max-height: 216px; background: #000; }
.railplayer--empty {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--sp-2);
  height: 150px; color: rgba(255,255,255,.55); font-size: 12px; background: var(--surface-2);
}

/* 参考图列表 */
.refpills { display: flex; flex-direction: column; gap: var(--sp-2); }
.refpill {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: 4px 6px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface-2);
  min-width: 0;
}
.refpill.is-primary { border-color: rgba(236,72,153,.4); background: rgba(236,72,153,.08); }
.refpill__thumb {
  display: grid; place-items: center;
  width: 28px; height: 28px; flex: none;
  border-radius: 7px; overflow: hidden;
  background: var(--muted); color: var(--fg-muted);
}
.refpill__thumb img { width: 100%; height: 100%; object-fit: cover; }
.refpill__path {
  flex: 1; min-width: 0;
  font-family: var(--mono); font-size: 11px; color: var(--fg-muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.refpill__tag { font-size: 10px; padding: 1px 5px; border-radius: 999px; background: rgba(236,72,153,.16); color: var(--primary-fg); }

.railmeta { display: grid; grid-template-columns: 72px minmax(0, 1fr); gap: 2px var(--sp-2); font-size: 11px; }
.railmeta dt { color: var(--fg-muted); }
.railmeta dd { color: var(--fg); font-variant-numeric: tabular-nums; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* 控制台住进右栏：这里它是常驻面板，不再是可折叠的底部抽屉 */
.console--rail {
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-soft);
  background: var(--surface);
  overflow: hidden;
  min-height: 200px;
  flex: none;
}
.console--rail .console__head {
  border-bottom: 1px solid var(--border);
  background: var(--surface);
  padding: var(--sp-1) var(--sp-2);
  flex-wrap: nowrap;
  gap: var(--sp-2);
}
/* 右栏里标题行只有 290px：badge 和摘要都收着点，摘要超出打省略号，别折成三行 */
.console--rail .console__toggle { min-height: 32px; padding: 0 6px; gap: 6px; }
.console--rail .console__title,
.console--rail .switch__label { white-space: nowrap; }
/* 右栏里只有 290px 宽：标题 + 计数 + 「隐藏已结束」开关 + 刷新，摘要再挤进来
   就折成三行的头部（比没有摘要更难看）。摘要说的那点事，下面的统计里都有。 */
.console--rail .console__summary { display: none; }
.console--rail .switch__label { font-size: 11px; }
.console--rail .console__cta { padding: var(--sp-2); gap: 6px; }
.console--rail .console__chev { display: none; }
.console--rail .console__toggle { cursor: default; }
.console--rail .console__body {
  border-top: none;
  /* CTA（统计 + 主按钮）固定，任务列表自己滚：任务再多也不会把主按钮顶出视口 */
  display: flex;
  flex-direction: column;
  /* 任务多的时候列表自己滚，别把主按钮顶出视口；这里封顶也是为了给上面的
     成片卡和分镜详情留出高度（右栏总共只有一屏高） */
  max-height: 150px;
  overflow: hidden;
}
.console--rail .console__cta { flex: none; }
.console--rail .job-list { flex: 1; min-height: 0; overflow-y: auto; padding: var(--sp-2); gap: 6px; }
/* 任务卡在右栏里压成一行（标题 + 状态 + 细进度条）：原来那张卡自带 meta 行和
   日志区，66px 的可视高度里只能露出一道边，看着像个空框 */
.console--rail .job-card__head { padding: 6px var(--sp-2); gap: var(--sp-2); flex-wrap: nowrap; }
.console--rail .job-card__title { font-size: 12px; min-width: 0; }
.console--rail .job-card__title > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.console--rail .job-card__meta { display: none; }
.console--rail .job-card__progress { padding: 0 var(--sp-2) 6px; }
.console__cta { display: flex; flex-direction: column; gap: var(--sp-2); padding: var(--sp-3); border-bottom: 1px solid var(--border); }
.console__stats { display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; }
.btn--block { width: 100%; }

/* 项目头：模式开关 + 一行说明 */
.workspace__head-main { min-width: 0; }
.workspace__head-actions { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }
.workspace__hint {
  display: flex; align-items: flex-start; gap: 6px;
  font-size: 12px; color: var(--fg-muted); line-height: 1.5;
}
.workspace__hint svg { flex: none; margin-top: 2px; color: var(--fg-dim); }

/* ===== 流水线卡片：状态语义 ===== */
.pipeline__step { align-items: flex-start; padding: 10px; }
.step__top { display: flex; align-items: center; gap: 6px; min-width: 0; }
.step__name { flex: 1; min-width: 0; }
.step__chip {
  display: inline-flex; align-items: center; gap: 4px;
  flex: none;
  padding: 1px 6px;
  border-radius: 999px;
  border: 1px solid var(--border);
  font-size: 10px;
  font-weight: 600;
  color: var(--fg-muted);
  background: var(--surface);
  white-space: nowrap;
}
.step__chip.is-running { color: var(--info-fg); border-color: rgba(37,99,235,.35); background: rgba(37,99,235,.12); }
.step__chip.is-error { color: var(--danger-fg); border-color: rgba(220,38,38,.35); background: rgba(220,38,38,.12); }
.step__chip.is-done { color: var(--success-fg); border-color: rgba(16,185,129,.35); background: rgba(16,185,129,.12); }
.step__chip.is-current { color: var(--on-primary); border-color: transparent; background: var(--primary-solid); }
.step__chip .spinner { width: 10px; height: 10px; }
.step__sub { font-size: 11px; color: var(--fg-muted); font-variant-numeric: tabular-nums; }
.meta--num { font-variant-numeric: tabular-nums; }

/* ===== 表格：方式列 + 更宽的可读列 ===== */
.col-mode { width: 92px; }
.mode-chip {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 1px 7px;
  border-radius: 999px;
  font-size: 11px;
  border: 1px solid var(--border-strong);
  background: var(--surface-2);
  color: var(--fg-muted);
  white-space: nowrap;
}
.mode-chip.is-face { color: var(--fg); border-color: var(--border-strong); }
.mode-chip.is-character { color: var(--primary-fg); border-color: rgba(236,72,153,.4); background: rgba(236,72,153,.12); }
.mode-chip__dot { width: 5px; height: 5px; border-radius: 50%; background: currentColor; opacity: .55; }
.refcell__count { font-size: 10px; color: var(--fg-muted); border: 1px solid var(--border); border-radius: 999px; padding: 0 5px; }
.data-table tbody tr { cursor: pointer; }
.data-table tbody tr.is-active { box-shadow: inset 2px 0 0 var(--primary); }
.data-table tbody tr:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }
/* 行内次要按钮平时压暗、当前行/悬停/键盘聚焦时点亮。
   以前是 opacity: 0 —— 那一列在静态截图里就是三个空格子，既不知道能点什么，
   也让整张表看着缺一块；压暗（.45）保留了收敛的观感，但一直是可发现的。 */
.data-table tbody .row-actions { opacity: .45; transition: opacity var(--dur-fast) var(--ease); }
.data-table tbody tr:hover .row-actions,
.data-table tbody tr.is-active .row-actions,
.data-table tbody tr:focus-within .row-actions { opacity: 1; }
.segmented--sm .segmented__item { min-height: 30px; padding: 0 var(--sp-3); font-size: 12px; }
.segmented--mode .segmented__item { min-height: 32px; padding: 0 var(--sp-3); font-size: 12px; }

/* 窄屏：右栏和右栏里的控制台一起收掉，控制台回到底部抽屉 */
/* 工作台的右栏是「宽屏专属」（≥1280px，和 app.js 的 RAIL_BREAKPOINT 配对），
   窄了收成单列、成片回主区最下面、控制台回到底部那条。
   注意选择器必须限定在 .workspace 下：story 页的 .rail 是另一套（三栏，
   1001px 起就显示），两条规则同名同时生效的话会把 story 的右栏一起关掉。 */
@media (max-width: 1279px) {
  .workspace { display: flex; flex-direction: column; gap: var(--sp-5); }
  .workspace > .rail { display: none; }
}

/* 人物卡图片加载失败：给出可读的提示，而不是一片空白（看着像「没传图」） */
.char-card.is-imgbroken .char-card__thumb::after {
  content: '图片加载失败';
  position: absolute; inset: auto 0 0 0;
  padding: 2px 4px;
  font-size: 10px; text-align: center;
  color: var(--danger-fg);
  background: rgba(0, 0, 0, .45);
}
/* ===== 只读读数（并发这类由管理员设定的值） ===== */
.readout {
  display: inline-flex;
  align-items: center;
  min-height: 36px;
  padding: 0 var(--sp-3);
  border-radius: var(--radius);
  border: 1px dashed var(--border-strong);
  background: var(--surface-2);
  color: var(--fg);
  font-size: 13px;
  font-variant-numeric: tabular-nums;
}
.readout--sm { min-height: 28px; padding: 0 var(--sp-2); font-size: 12px; }
.status-pill--quiet { background: transparent; border-color: var(--border); }
/* ===== 编剧对话框（左：prompt 库 / 右：生成与成稿） ===== */
.dlg-writer__body {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--sp-4);
  align-items: start;
}
.dlg-writer .writer-col { display: flex; flex-direction: column; gap: var(--sp-3); min-width: 0; }
.dlg-writer .field--grow { display: flex; flex-direction: column; min-height: 0; }
.dlg-writer__system, .dlg-writer__out {
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.55;
  min-height: 260px;
  max-height: 46vh;
  resize: vertical;
}
.dlg-writer__meta { font-size: 11px; color: var(--fg-muted); }
@media (max-width: 900px) {
  .dlg-writer__body { grid-template-columns: minmax(0, 1fr); }
}
/* ===== 素材分组（人物 / 场景） ===== */
.asset-group { display: flex; flex-direction: column; gap: var(--sp-3); }
.asset-group + .asset-group { margin-top: var(--sp-5); padding-top: var(--sp-5); border-top: 1px solid var(--border); }
.asset-group__head { display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; }
.asset-group__title { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; font-weight: 600; }
.asset-group__title svg { color: var(--fg-muted); }

/* 场景卡：空间描述 + 英文锚那两行 */
.char-card--scene { border-color: rgba(236, 72, 153, .28); }
.char-card__scene { display: flex; flex-direction: column; gap: 4px; margin-top: 2px; }
.scene-line {
  display: flex; align-items: center; gap: 4px;
  width: 100%;
  padding: 3px 6px;
  border: 1px dashed var(--border-strong);
  border-radius: 8px;
  background: transparent;
  color: var(--fg-muted);
  font-size: 11px;
  line-height: 1.4;
  text-align: left;
  cursor: text;
  transition: border-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.scene-line:hover { border-color: var(--primary); color: var(--fg); }
.scene-line__text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.scene-line__empty { font-style: italic; opacity: .8; }
.scene-line.is-anchored { border-style: solid; border-color: rgba(16,185,129,.4); color: var(--success-fg); }
/* ============================================================================
 * ===== 编剧页（writers.html）：编剧库 / 编辑器 / 试写 =====
 *
 * 交互约定（这一页就是为了把「创作规范写在哪」讲清楚）：
 *   左 = 编剧库（人名 + 有没有写规范）  中 = 规范编辑器  右 = 试写与导出
 * ========================================================================= */
.layout--writers { grid-template-columns: 280px minmax(0, 1fr) 360px; }

.writer-list { flex: 1; overflow-y: auto; padding: var(--sp-2); display: flex; flex-direction: column; gap: var(--sp-1); }
.writer-item {
  display: flex; align-items: flex-start; gap: var(--sp-2);
  width: 100%; padding: var(--sp-2);
  border: 1px solid transparent; border-radius: var(--radius);
  background: transparent; color: var(--fg);
  text-align: left; cursor: pointer;
  transition: background var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.writer-item:hover { background: var(--surface-2); border-color: var(--border); }
.writer-item.is-selected { background: var(--surface-2); border-color: var(--border-strong); box-shadow: inset 2px 0 0 var(--primary); }
.writer-item__mark { display: grid; place-items: center; width: 26px; height: 26px; flex: none; border-radius: 8px; background: var(--muted); color: var(--fg-muted); }
.writer-item__main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.writer-item__name { display: flex; align-items: center; gap: 6px; font-size: 13px; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.writer-item__meta { font-size: 11px; color: var(--fg-muted); }
.writer-item.is-empty .writer-item__mark { color: var(--warn); }

.writers-rail {
  display: flex; flex-direction: column; gap: var(--sp-3);
  padding: var(--sp-4);
  background: var(--bg);
  border-left: 1px solid var(--border);
  overflow-y: auto;
  min-height: 0;
}
.writers-rail__out { font-family: var(--mono); font-size: 12px; line-height: 1.55; min-height: 180px; resize: vertical; }

.writer-editor { display: flex; flex-direction: column; gap: var(--sp-4); }
.writer-editor__head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--sp-4); flex-wrap: wrap; }
.writer-editor__title { font-size: 20px; font-weight: 600; letter-spacing: -.01em; }
.writer-editor__sub { font-size: 12px; color: var(--fg-muted); margin-top: 2px; }
.writer-editor__field { display: flex; flex-direction: column; }
.writer-editor__system {
  font-family: var(--mono);
  font-size: 12.5px;
  line-height: 1.6;
  min-height: 320px;
  resize: vertical;
}
.writer-editor__foot { display: flex; align-items: center; gap: var(--sp-3); }
.writer-editor__state { font-size: 12px; color: var(--fg-muted); }
.writer-editor__state.is-dirty { color: var(--warn); }

@media (max-width: 1180px) {
  .layout--writers { grid-template-columns: 240px minmax(0, 1fr); }
  .writers-rail { grid-column: 2; border-left: none; border-top: 1px solid var(--border); }
}
@media (max-width: 900px) {
  .layout--writers { grid-template-columns: minmax(0, 1fr); }
  .layout--writers .sidebar { display: none; }
  .writers-rail { grid-column: 1; }
}
/* 编剧页：空规范时的三步指引（回答「这东西怎么用」） */
.writer-guide {
  display: flex; flex-direction: column; gap: var(--sp-2);
  padding: var(--sp-4);
  border: 1px solid rgba(236, 72, 153, .28);
  border-radius: var(--radius-lg);
  background: rgba(236, 72, 153, .06);
}
.writer-guide__title { display: flex; align-items: center; gap: 6px; font-size: 13px; font-weight: 600; }
.writer-guide__title svg { color: var(--primary); }
.writer-guide__steps { display: flex; flex-direction: column; gap: 6px; margin: 0; padding-left: 20px; font-size: 12.5px; line-height: 1.65; color: var(--fg-muted); }
.writer-guide__steps b { color: var(--fg); font-weight: 600; }
.writer-guide__note { font-size: 11.5px; color: var(--fg-muted); }
/* ============================================================================
   ===== 跨页切换：不让它「一闪一闪」 =====
   四个页面是四个真实文档，点导航就是一次文档切换。浏览器在新文档画出来之前
   会一直显示旧画面，但默认中间可能露出底色，观感就是闪一下。这里做两件事：
     1) 旧页面点击后主动淡出一点（is-leaving），把注意力带走
     2) 新页面首帧透明（is-entering），下一帧去掉 → 按 .app 的 transition 淡入
   两者都只动 opacity/transform，且尊重 prefers-reduced-motion（见文件末尾）。
   ========================================================================= */
.app { opacity: 1; transition: opacity .14s var(--ease), transform .14s var(--ease); }
html.is-leaving .app { opacity: .55; transform: scale(.995); }
/* 首帧透明：由各页 <head> 里的内联脚本在解析 body 之前把 is-entering 摘掉。
   `.app` 默认是 opacity:1，只有在 is-entering 期间才透明 —— 于是「有 JS 正常淡入、
   没有 JS 也照样看得见」，不需要额外兜底规则。 */
html.is-entering .app { opacity: 0; }

/* 顶栏导航：切页时不要重排（高度固定，避免新页面先把内容顶一下） */
.appnav { min-height: 34px; }
.appnav__item { min-height: 30px; }

/* 编剧弹窗里的只读规范预览（编辑在「编剧」页，这里只给看） */
.writer-preview {
  display: flex; flex-direction: column; gap: 6px;
  padding: var(--sp-3);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--muted);
  min-height: 0;
}
.writer-preview__head { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2); }
.writer-preview__name { font-size: 12.5px; font-weight: 600; }
.writer-preview__body {
  margin: 0;
  max-height: 40vh;
  overflow-y: auto;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  font-family: var(--mono);
  font-size: 11px;
  line-height: 1.55;
  color: var(--fg-muted);
}
.writer-preview__body.is-empty { color: var(--warn); font-family: var(--font); font-size: 12px; }
.field__hint.is-warn { color: var(--warn-fg); }
/* ============================================================================
   主题系统（web/theme.js）
   <html data-theme="light"> → 下面这组 token 覆盖 :root 的深色值。
   选色约束：正文/次要文字对底 4.5:1 起，状态色对白底 ≥4.5:1，边框在两种主题
   下都能看清；浅色不用纯白做页面底（避免大面积高亮刺眼）。
   ========================================================================= */
html[data-theme="light"] {
  color-scheme: light;

  --bg: #F5F7FB;
  --surface: #FFFFFF;
  --surface-2: #F1F4FA;
  --muted: #F3F5FB;
  --border: rgba(15, 23, 42, .10);
  --border-strong: rgba(15, 23, 42, .17);
  --fg: #0F172A;
  --fg-muted: #4B5670;   /* 白底 7.3:1 */
  --fg-dim: #64708C;     /* 白底 5.0:1 */

  --primary: #DB2777;
  --primary-hover: #BE185D;
  --primary-solid: #DB2777;
  --primary-solid-hover: #BE185D;
  --on-primary: #FFFFFF;
  --accent: #1D4ED8;
  --success: #059669;
  --warn: #D97706;
  --danger: #DC2626;
  --ring: #DB2777;

  --code-bg: rgba(15, 23, 42, .05);
  --subtle-bg: rgba(15, 23, 42, .045);
  --subtle-bg-strong: rgba(15, 23, 42, .06);
  --subtle-bg-strong-hover: rgba(15, 23, 42, .13);
  --hover-bg: rgba(15, 23, 42, .04);
  --hover-bg-faint: rgba(15, 23, 42, .022);
  --row-hover: rgba(15, 23, 42, .03);
  --hover-bg-strong: #E6EAF4;
  --border-hover: rgba(15, 23, 42, .26);
  --border-hover-strong: rgba(15, 23, 42, .34);
  --spinner-track: rgba(15, 23, 42, .18);
  --scroll-thumb: rgba(15, 23, 42, .18);
  --scroll-thumb-hover: rgba(15, 23, 42, .32);

  /* 状态文字色：白底上必须压深，粉彩系在白底等于看不见 */
  --danger-fg: #B91C1C;   /* 6.5:1 */
  --danger-fg-strong: #DC2626;
  --warn-fg: #B45309;     /* 5.1:1 */
  --success-fg: #047857;  /* 5.5:1 */
  --info-fg: #1D4ED8;     /* 6.8:1 */
  --primary-fg: #BE185D;  /* 6.5:1 */

  --glow-primary: rgba(219, 39, 119, .10);
  --glow-primary-strong: rgba(219, 39, 119, .32);
  --glow-accent: rgba(29, 78, 216, .10);
  --selection-bg: rgba(219, 39, 119, .18);
  --scrim: rgba(15, 23, 42, .45);

  --shadow-soft: 0 2px 10px rgba(15, 23, 42, .06), 0 1px 2px rgba(15, 23, 42, .05);
  --shadow-sm: 0 1px 2px rgba(15, 23, 42, .10);
  --shadow-card: 0 6px 18px rgba(15, 23, 42, .08);
  --shadow-pop: 0 16px 36px rgba(15, 23, 42, .14), 0 2px 8px rgba(15, 23, 42, .08);
  --shadow-modal: 0 24px 60px rgba(15, 23, 42, .18), 0 2px 8px rgba(15, 23, 42, .08);
  --shadow-drawer: -12px 0 32px rgba(15, 23, 42, .12);
  --shadow-auth: 0 20px 50px rgba(15, 23, 42, .12);
}

/* ---- 浅色下的零散修正（不能只靠 token 表达的部分） ---- */
/* select 的箭头是内联 SVG data URI，得单独换一版描边色 */
html[data-theme="light"] .select {
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2364708C' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
}
/* 危险实心按钮 hover：深色下用更深的红，浅色下反而要浅一点才不会显脏 */
html[data-theme="light"] .btn--danger:hover:not(:disabled) { background: #B91C1C; }
/* 光晕在浅色底上要收敛，否则整页发灰 */
html[data-theme="light"] .auth::before,
html[data-theme="light"] .auth::after { filter: blur(90px); }

/* ===== 主题切换按钮（顶栏 / 登录页共用） ===== */
.theme-toggle svg { transition: transform var(--dur) var(--ease); }
.theme-toggle:hover svg { transform: rotate(-18deg) scale(1.06); }

.auth-theme {
  position: fixed;
  top: var(--sp-4);
  right: var(--sp-4);
  z-index: 30;
  border-color: var(--border);
  background: var(--surface);
  box-shadow: var(--shadow-soft);
}
@media (max-width: 560px) {
  .auth-theme { top: var(--sp-3); right: var(--sp-3); }
}









/* ============================================================================
 * ===== 工作台右栏模式（≥1280px）：左列变窄了，零件跟着紧凑一档 =====
 * 阈值和 app.js 的 RAIL_BREAKPOINT 一致（见文件开头那条注释）。
 * ========================================================================= */
@media (min-width: 1280px) {
  /* 流水线留在左列（~740px），五张卡各 ~140px：
     字号、内边距、行数都收一档，保留「名称 + 状态 chip + 一行元信息」，
     多出来的第三行（明细数字）让位——它在 title 和步骤弹窗里都有。 */
  .workspace__main > .pipeline { gap: 6px; padding: var(--sp-2); }
  .workspace__main > .pipeline .pipeline__step {
    min-height: 0;
    padding: 8px;
    gap: 6px;
    align-items: center;
  }
  .workspace__main > .pipeline .step__name { font-size: 12.5px; }
  .workspace__main > .pipeline .step__meta {
    font-size: 11px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .workspace__main > .pipeline .step__sub { display: none; }
  .workspace__main > .pipeline .step__gear { display: none; }
  /* 140px 的卡里「名称 + 状态 chip」挤不下（名称会被截成「导…」）。
     状态本来就是三重表达：序号圈（✓/spinner/序号）、卡片配色、title 提示，
     chip 让位给名称，进度数字留在下面那行 meta 里。 */
  .workspace__main > .pipeline .step__chip { display: none; }
}


/* ============================================================================
 * ===== 右栏里的阶段面板：把 <dialog> 当内联卡片用 =====
 * 点流水线卡片 → 对应 dialog 的**节点**被搬进右栏（见 app.js selectStage），
 * 所以表单联动、校验和「开始切分 / 开始合并」这些按钮全都原样复用，
 * 不是另写一套。这里只负责把它从「浮层」变成「卡片」。
 * ========================================================================= */
dialog.dlg-inline {
  position: static;
  /* ⚠️ 这里**不能**直接写 display: block：那样会把「关闭的 dialog 默认 display:none」
     这条 UA 规则顶掉，于是住在右栏里的四个阶段面板**全都显示出来**（用户看到的
     「切分镜参数 + 生成脚本 同时列在右边」就是这个 —— 四个都在，只是滚动条下面
     还有两个）。必须让它跟着 open 走。 */
  display: none;
  width: 100%;
  max-width: none;
  max-height: none;
  margin: 0;
  padding: 0;
  border: none;
  background: transparent;
  box-shadow: none;
  overflow: visible;
}
dialog.dlg-inline[open] { display: block; }
dialog.dlg-inline::backdrop { display: none; }
dialog.dlg-inline .dialog__form {
  max-height: none;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-soft);
}
dialog.dlg-inline .dialog__body {
  overflow-y: auto;
  max-height: calc(100vh - 380px);
  padding: var(--sp-4);
}
dialog.dlg-inline .dialog__head { padding: var(--sp-3) var(--sp-4); }
dialog.dlg-inline .dialog__foot { padding: var(--sp-3) var(--sp-4); }


/* ============================================================================
 * ===== 工作台右栏：住在 .layout 里（主区之外）的阶段参数 =====
 * 主区每次整段重建都碰不到它 —— 阶段面板只切 open 属性，不搬节点。
 * ========================================================================= */
@media (min-width: 1280px) {
  /* 三栏：侧栏 | 主区 | 阶段参数。阈值和 app.js 的 RAIL_BREAKPOINT 配对 */
  .layout--work { grid-template-columns: 260px minmax(0, 1fr) 400px; }
  .layout--work > .sidebar { grid-column: 1; }
  .layout--work > .main { grid-column: 2; }
  .layout--work > .rail { grid-column: 3; }
}
@media (max-width: 1279px) {
  .layout--work { grid-template-columns: minmax(0, 1fr); }
  .layout--work > .sidebar { display: none; }
  .layout--work > .main { grid-column: 1; }
  /* 窄屏右栏收起：阶段参数回到弹窗（dialog 被搬回 body，仍然是同一份表单） */
  .layout--work > .rail { display: none; }
}
.layout--work > .rail {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  min-width: 0;
  min-height: 0;
  padding: 0;
  overflow: hidden;
}
.rail__stage,
.rail__cards { display: flex; flex-direction: column; gap: var(--sp-3); min-height: 0; }
.rail__stage { flex: 1 1 auto; overflow-y: auto; }
.rail__cards { flex: none; }

/* 回看已完成阶段时的提示条（在右栏，阶段面板之前） */
.rail__stage-back {
  gap: var(--sp-2);
  padding: var(--sp-3);
  border-style: dashed;
  color: var(--fg-muted);
}
.rail__stage-back-text { font-size: 12px; line-height: 1.5; }
.rail__stage-back .btn { align-self: flex-start; }
