/* wemio-operator.css — extracted from operator.html inline <style> (2026-06-11 全系统重构 Phase4 Step3,
   字节级等价:cascade 原位 link 替换,渲染不变,仅可缓存+可维护) */
/* :root 色板已迁移到 claude-design-system.css */
    * { box-sizing: border-box; margin: 0; padding: 0; }
    html, body { height: 100%; }
    body {
      background: var(--bg);
      color: var(--text);
      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
                   "Microsoft YaHei", sans-serif;
      font-size: 14px;
      line-height: 1.65;
    }
    a { color: var(--accent); text-decoration: none; }
    a:hover { text-decoration: underline; }

    /* Header */
    header {
      background: var(--panel);
      border-bottom: 1px solid var(--line);
      padding: 10px 18px;
      display: flex;
      align-items: center;
      gap: 16px;
    }
    header .brand {
      font-weight: 700;
      letter-spacing: 0.04em;
      color: var(--accent);
    }
    header .crumb {
      color: var(--text-dim);
      font-size: 13px;
    }
    header .spacer { flex: 1; }
    header .auth-bar {
      display: flex; align-items: center; gap: 8px; font-size: 13px;
      color: var(--text-dim);
    }
    header button {
      background: var(--panel-2); color: var(--text);
      border: 1px solid var(--line);
      padding: 4px 10px; border-radius: 4px;
      font-size: 12px; cursor: pointer;
    }
    header button:hover { border-color: var(--accent); color: var(--accent); }

    /* Tabs */
    .tabs {
      display: flex;
      background: var(--panel);
      border-bottom: 1px solid var(--line);
      padding: 0 18px;
    }
    .tabs button {
      background: transparent;
      color: var(--text-dim);
      border: none;
      padding: 10px 18px;
      cursor: pointer;
      border-bottom: 2px solid transparent;
      font-size: 14px;
    }
    .tabs button.active {
      color: var(--accent);
      border-bottom-color: var(--accent);
    }
    .tabs button:hover { color: var(--text); }

    /* Layout */
    main {
      max-width: 1200px;
      margin: 0 auto;
      padding: 24px;
    }
    .panel {
      background: var(--panel);
      border: 1px solid var(--line);
      border-radius: 6px;
      padding: 20px 24px;
      margin-bottom: 16px;
    }
    .panel h2 {
      font-size: 17px;
      font-weight: 600;
      letter-spacing: -0.012em;
      margin-bottom: 12px;
      color: var(--text-strong);
    }
    .panel .hint {
      color: var(--text-dim);
      font-size: 12px;
      margin-bottom: 12px;
    }

    /* Forms */
    .grid {
      display: grid;
      grid-template-columns: 200px 1fr;
      gap: 8px 16px;
      align-items: center;
    }
    .grid .full { grid-column: 1 / -1; }
    .grid label {
      color: var(--text-dim);
      font-size: 13px;
    }
    input[type="text"], input[type="number"], input[type="email"],
    input[type="password"], select, textarea {
      width: 100%;
      background: var(--panel-2);
      color: var(--text);
      border: 1px solid var(--line);
      padding: 8px 12px;
      border-radius: 4px;
      font-size: 13px;
      font-family: inherit;
    }
    textarea {
      font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
      font-size: 12px;
      min-height: 100px;
      resize: vertical;
    }
    .checkbox-row {
      display: flex; gap: 18px; align-items: center; padding: 4px 0;
    }
    .checkbox-row label {
      color: var(--text); font-size: 13px;
      display: flex; align-items: center; gap: 6px; cursor: pointer;
    }

    button.primary {
      background: var(--accent); color: var(--accent-fg);
      border: none; padding: 8px 18px; border-radius: 4px;
      cursor: pointer; font-size: 13px; font-weight: 600;
    }
    button.primary:hover { background: var(--accent-2); }
    button.primary:disabled { opacity: 0.5; cursor: not-allowed; }
    button.secondary {
      background: transparent; color: var(--text);
      border: 1px solid var(--line); padding: 8px 12px; border-radius: 4px;
      cursor: pointer; font-size: 13px;
    }
    button.secondary:hover { border-color: var(--accent); color: var(--accent); }

    /* Episode rows (batch tab) */
    .ep-row {
      background: var(--panel-2);
      border: 1px solid var(--line);
      border-radius: 4px;
      padding: 12px;
      margin-bottom: 8px;
    }
    .ep-row .head {
      display: flex; align-items: center; gap: 10px;
      margin-bottom: 6px;
    }
    .ep-row .head .num {
      width: 50px; padding: 4px 6px;
    }
    .ep-row .head .path { flex: 1; }
    .ep-row textarea { min-height: 60px; }

    /* Status board */
    .badge {
      display: inline-block;
      padding: 2px 8px;
      border-radius: 3px;
      font-size: 11px;
      font-weight: 600;
      margin-left: 6px;
    }
    .badge-queued { background: var(--text-dim); color: var(--bg); }
    .badge-running { background: var(--warn); color: var(--bg); animation: ws-pulse 1.4s ease-in-out infinite; }
    @keyframes ws-pulse {
      0%, 100% { opacity: 1; }
      50% { opacity: 0.55; }
    }
    /* 2026-05-12 — autofill detect hack. Webkit/Blink apply
       `:-webkit-autofill` pseudo-class when browser autofills an input;
       a zero-effect CSS animation on that pseudo triggers JS
       `animationstart` event — the only robust DOM signal that autofill
       just happened. Used by _attachCanonicalAutofillScrubListener. */
    @keyframes onAutoFillStart { from {} to {} }
    input:-webkit-autofill { animation-name: onAutoFillStart; animation-duration: 1ms; }
    /* 2026-05-15 — SB-1/SB-2 daoai-x v1.15 (AP#35 Wilson floor / AP#27
       tail-truncation): even if JS scrub strips `.value` to "", Edge
       leaves the autofill yellow/grey overlay + grey text styling. The
       operator visually still sees their email in the canonical-name
       field (the dogfood symptom). Force overlay transparent with a
       very wide inset box-shadow trick + reset text fill colour, so
       even at the autofill instant before JS scrub the field renders
       in the page theme — not as a styled autofill match. Belt &
       suspenders with the JS scrubbers below. */
    #s-canonical:-webkit-autofill,
    #b-canonical:-webkit-autofill,
    #s-canonical:-webkit-autofill:hover,
    #b-canonical:-webkit-autofill:hover,
    #s-canonical:-webkit-autofill:focus,
    #b-canonical:-webkit-autofill:focus {
      box-shadow: 0 0 0 1000px var(--bg) inset !important;
      -webkit-box-shadow: 0 0 0 1000px var(--bg) inset !important;
      -webkit-text-fill-color: var(--text) !important;
      caret-color: var(--text) !important;
      transition: background-color 0s 1000000s, color 0s 1000000s;
    }
    .badge-complete { background: var(--high); color: var(--bg); }
    /* 2026-05-26 wave-D #5 — dry_run-ok variant of complete: neutral
       gray instead of success-green so operator's eye doesn't read
       "成片好了" when in fact no video was produced. Paired with the
       状态板 chip + truth-line on submit cards (defense in depth). */
    .badge-dry-run-ok {
      background: rgba(160, 150, 130, 0.85);
      color: var(--bg);
    }
    .badge-failed { background: var(--error); color: white; }
    .badge-cancelled { background: var(--text-dim); color: var(--bg); }
    /* SB-3 fix (daoai-x r1) — partial is only emitted by auto_batch
       terminal when SOME children completed but rest were cancelled.
       Visually we want it distinct from both 'complete' (all ok) and
       'failed' (real crash) so operators don't re-trigger work that
       actually finished. */
    .badge-partial { background: var(--warn); color: var(--bg); border: 1px solid var(--accent); }

    .status-row {
      background: var(--panel-2);
      border: 1px solid var(--line);
      border-radius: 4px;
      padding: 12px 16px;
      margin-bottom: 8px;
    }
    .status-row.is-failed {
      border-left: 3px solid var(--error);
    }
    .status-row.is-complete {
      border-left: 3px solid var(--high);
    }
    .status-row.is-running {
      border-left: 3px solid var(--warn);
    }
    /* 2026-05-14 v4 — retry chain visual grouping. Cards minted via
       /retry are visually indented + flagged with a leading ↳ marker
       so the operator can see at a glance "this card is a child of the
       one above". Lighter weight than full grouping (which would change
       iteration order + complicate polling). */
    .status-row.is-retry {
      margin-left: 24px;
      position: relative;
      background: var(--panel);
    }
    .status-row.is-retry::before {
      content: "↳";
      position: absolute;
      left: -20px;
      top: 12px;
      color: var(--text-dim);
      font-size: 16px;
      font-weight: 700;
    }
    .status-row.is-retry .id-line {
      opacity: 0.95;
    }
    .status-row .id-line {
      font-family: ui-monospace, monospace;
      font-size: 12px;
      color: var(--text);
    }
    .status-row .meta {
      color: var(--text-dim); font-size: 12px;
      margin-top: 4px;
    }
    .status-row .sub-runs {
      margin-top: 6px;
      padding-left: 12px;
      border-left: 2px solid var(--line);
      font-size: 12px;
    }

    /* ============= Redesigned chunk grid + retry actions (2026-05-14) ====
       User feedback: (1) 视频可在线预览 (2) 失败需原因+重试 (3) UI 不够友好
       Pre-fix: chunks were target=_blank links + plain red text on fail.
       Now: clear card per chunk with status pill, preview / retry CTAs. */
    .pl-actions {
      display: flex; flex-wrap: wrap; gap: 8px;
      margin-top: 12px;
    }
    .pl-actions button, .pl-actions a.btn-action {
      display: inline-flex; align-items: center; gap: 4px;
      padding: 8px 12px; border-radius: 4px; font-size: 12px;
      font-weight: 600; cursor: pointer; text-decoration: none;
      border: 1px solid var(--line); background: var(--panel);
      color: var(--text);
    }
    .pl-actions button:hover, .pl-actions a.btn-action:hover {
      border-color: var(--accent); color: var(--accent);
    }
    .pl-actions .btn-primary {
      background: var(--accent); color: var(--accent-fg); border-color: var(--accent);
    }
    .pl-actions .btn-primary:hover { opacity: 0.9; color: #fff; }
    .pl-actions .btn-retry {
      background: rgba(212,160,23,0.12);
      border-color: rgba(212,160,23,0.5);
      color: #a07b00;
    }
    .pl-actions .btn-retry:hover {
      background: rgba(212,160,23,0.22); color: #a07b00;
    }

    /* Failure reason banner inside a status-row */
    .pl-failure {
      margin-top: 8px;
      padding: 8px 12px;
      background: rgba(184, 58, 43, 0.08);
      border: 1px solid rgba(184, 58, 43, 0.30);
      border-radius: 4px;
      font-size: 13px;
      color: var(--text);
    }
    .pl-failure b { color: var(--error); }
    .pl-failure .hint {
      display: block; margin-top: 4px;
      font-size: 12px; color: var(--text-dim);
    }

    /* Multi-chunk grid */
    .chunk-grid {
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
      gap: 12px;
      margin-top: 12px;
    }
    .chunk-card {
      background: var(--panel);
      border: 1px solid var(--line);
      border-radius: 4px;
      padding: 12px;
      font-size: 12px;
      display: flex; flex-direction: column; gap: 8px;
    }
    .chunk-card.is-complete { border-left: 3px solid var(--high); }
    .chunk-card.is-failed { border-left: 3px solid var(--error); }
    .chunk-card.is-pending { border-left: 3px solid var(--text-dim); }
    .chunk-card .ch-head {
      display: flex; justify-content: space-between; align-items: center;
    }
    .chunk-card .ch-label { font-weight: 600; color: var(--text); }
    .chunk-card .ch-status {
      padding: 1px 6px; border-radius: 3px; font-size: 11px;
      font-weight: 600;
    }
    .chunk-card .ch-status.s-complete { background: var(--high); color: var(--bg); }
    .chunk-card .ch-status.s-failed { background: var(--error); color: #fff; }
    .chunk-card .ch-status.s-pending { background: var(--text-dim); color: var(--bg); }
    .chunk-card .ch-reason {
      color: var(--error); font-size: 11px;
      word-break: break-word;
    }
    .chunk-card .ch-actions {
      display: flex; gap: 6px; flex-wrap: wrap;
    }
    .chunk-card .ch-actions a, .chunk-card .ch-actions button {
      flex: 1 1 auto;
      text-align: center;
      padding: 4px 8px;
      border-radius: 3px;
      font-size: 11px;
      font-weight: 600;
      text-decoration: none;
      cursor: pointer;
      border: 1px solid var(--line);
      background: var(--panel-2);
      color: var(--text);
    }
    .chunk-card .ch-actions a.preview {
      background: rgba(201,100,66,0.12);
      border-color: rgba(201,100,66,0.5);
      color: var(--accent);
    }
    .chunk-card .ch-actions a:hover, .chunk-card .ch-actions button:hover {
      border-color: var(--accent); color: var(--accent);
    }

    /* Hero preview pill for the 60s master / single chunk */
    .pl-master {
      margin-top: 12px;
      padding: 12px 16px;
      background: rgba(201,100,66,0.10);
      border: 1px solid rgba(201,100,66,0.4);
      border-radius: 6px;
      display: flex; align-items: center; gap: 12px;
      flex-wrap: wrap;
    }
    .pl-master .ico { font-size: 18px; }
    .pl-master .label { font-weight: 600; color: var(--accent); flex: 1; min-width: 160px; }
    .pl-master .meta-line { color: var(--text-dim); font-size: 12px; }
    .pl-master a.preview-master {
      padding: 8px 16px; border-radius: 4px;
      background: var(--accent); color: var(--accent-fg);
      font-weight: 600; text-decoration: none; font-size: 13px;
    }
    .pl-master a.preview-master:hover { opacity: 0.9; text-decoration: none; }
    .pl-master a.dl-master {
      padding: 8px 12px; border-radius: 4px;
      border: 1px solid var(--accent); color: var(--accent);
      font-weight: 600; text-decoration: none; font-size: 13px;
      background: transparent;
    }

    /* Result/log panels */
    .result {
      background: var(--code-bg);
      border: 1px solid var(--line);
      border-radius: 4px;
      padding: 12px;
      font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
      font-size: 12px;
      white-space: pre-wrap;
      word-break: break-all;
      max-height: 320px;
      overflow-y: auto;
      margin-top: 12px;
    }
    .banner-warn {
      background: rgba(234, 179, 8, 0.12);
      border: 1px solid rgba(234, 179, 8, 0.4);
      color: var(--warn);
      padding: 8px 12px;
      border-radius: 4px;
      font-size: 12px;
      margin-bottom: 12px;
    }
    .banner-error {
      background: rgba(184, 58, 43, 0.12);
      border: 1px solid rgba(184, 58, 43, 0.4);
      color: var(--error);
      padding: 8px 12px;
      border-radius: 4px;
      font-size: 12px;
      margin-bottom: 12px;
    }
    .hidden { display: none !important; }

    .row-actions {
      display: flex; gap: 12px; align-items: center;
      margin-top: 12px;
    }
    .small-meta { font-size: 11px; color: var(--text-dim); }
    .cost-line { font-size: 13px; color: var(--accent); font-weight: 600; }

    /* ==========================================================
       8-step workflow stepper (W4.5 — 工作流可视化)
       ========================================================== */
    .stepper {
      display: flex;
      align-items: stretch;
      background: var(--panel);
      border-bottom: 1px solid var(--line);
      padding: 8px 18px;
      gap: 0;
      overflow-x: auto;
    }
    .stepper .step {
      display: flex;
      align-items: center;
      gap: 6px;
      padding: 6px 12px 6px 8px;
      font-size: 12px;
      color: var(--text-dim);
      cursor: pointer;
      position: relative;
      white-space: nowrap;
      border-radius: 4px;
      user-select: none;
      transition: background 0.12s, color 0.12s;
    }
    .stepper .step:hover { background: var(--panel-2); color: var(--text); }
    .stepper .step .num {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 20px;
      height: 20px;
      border-radius: 50%;
      background: var(--panel-2);
      color: var(--text-dim);
      font-weight: 700;
      font-size: 11px;
      border: 1px solid var(--line);
      flex-shrink: 0;
    }
    .stepper .step.done {
      color: var(--high);
    }
    .stepper .step.done .num {
      background: var(--high);
      color: var(--accent-fg);
      border-color: var(--high);
    }
    .stepper .step.active {
      color: var(--accent);
      font-weight: 600;
      background: var(--panel-2);
    }
    .stepper .step.active .num {
      background: var(--accent);
      color: var(--accent-fg);
      border-color: var(--accent);
    }
    .stepper .step.todo .num::after { content: ""; }
    .stepper .arrow {
      display: flex;
      align-items: center;
      color: var(--text-dim);
      padding: 0 2px;
      font-size: 10px;
      flex-shrink: 0;
    }
    .stepper .step.placeholder {
      opacity: 0.55;
      cursor: help;
    }
    .stepper .step.placeholder::after {
      content: "·待开发";
      font-size: 10px;
      color: var(--warn);
      margin-left: 4px;
    }

    /* UX-r4 (2026-05-27) — stepper compaction, mirror of the layer at
       end of /static/_step_shell.css. operator.html doesn't link
       _step_shell.css so the rules are duplicated here. Keep in lock-
       step manually (sentinel will fail if either drifts). Compaction:
         - Default desktop: tighter padding + smaller font + lighter
           arrows so 8 chips fit on a 1280px laptop without overflow
         - <1000px: hide step labels (keep number circles), arrows shrink
       Both layers MUST stay byte-identical (mod whitespace) — see
       backend/tests/test_augmenter_cache_writer_lockstep_v1.py
       test_stepper_compaction_lockstep. */
    .stepper { gap: 4px !important; padding: 6px 14px !important; }
    .stepper .step {
      font-size: 10px !important;
      letter-spacing: 0.12em !important;
      padding: 4px 8px !important;
    }
    .stepper .arrow {
      font-size: 9px !important;
      padding: 0 1px !important;
      opacity: 0.6;
    }
    @media (max-width: 1000px) {
      .stepper .step > span:not(.num) { display: none; }
      .stepper .step { padding: 4px 6px !important; }
      .stepper .arrow { padding: 0 !important; }
    }

    /* =====================================================================
       OPERATOR · 4-stage refactor (2026-05-26)
       Wraps the legacy flat-form into 4 visible stages with inline action
       panels. ALL legacy IDs preserved (s-show-id / s-shots-md / s-submit
       / s-one-click-produce / s-ack-unready / s-ack-garbage-shots) so the
       existing submit JS at L4880-4990 keeps working unchanged. The new
       cards just toggle the legacy hidden checkboxes + click the legacy
       submit buttons under the hood.
       ===================================================================== */
    .op-identity-bar {
      display: flex;
      align-items: center;
      justify-content: space-between;
      padding: 12px 16px;
      background: var(--panel-2);
      border: 1px solid var(--line);
      border-left: 4px solid var(--accent);
      border-radius: 6px;
      margin-bottom: 12px;
      font-size: 14px;
    }
    .op-identity-bar .identity-left { display: flex; align-items: center; gap: 8px; }
    .op-identity-bar .identity-icon { font-size: 18px; }
    .op-identity-bar strong { color: var(--accent); font-weight: 700; font-size: 15px; }
    .op-identity-bar .identity-sep { color: var(--text-dim); padding: 0 4px; }
    .op-identity-bar #s-identity-meta { color: var(--text-dim); font-size: 13px; }

    .op-stage-stepper {
      display: flex;
      align-items: center;
      gap: 4px;
      padding: 12px 16px;
      background: var(--panel);
      border: 1px solid var(--line);
      border-radius: 6px;
      margin-bottom: 16px;
      overflow-x: auto;
    }
    .op-stage-stepper .op-stage {
      display: flex;
      align-items: center;
      gap: 6px;
      padding: 4px 12px;
      font-size: 13px;
      color: var(--text-dim);
      white-space: nowrap;
      border-radius: 4px;
      transition: color 0.15s, background 0.15s;
    }
    .op-stage-stepper .op-stage .stage-num {
      font-size: 16px; font-weight: 700;
    }
    .op-stage-stepper .op-stage .stage-label { font-weight: 500; }
    .op-stage-stepper .op-stage .stage-status {
      font-size: 11px;
      color: var(--text-dim);
      padding: 2px 6px;
      border-radius: 10px;
      background: var(--panel-2);
    }
    .op-stage-stepper .op-stage.done {
      color: var(--high);
    }
    .op-stage-stepper .op-stage.done .stage-status {
      background: rgba(80, 180, 100, 0.15);
      color: var(--high);
    }
    .op-stage-stepper .op-stage.blocked {
      color: var(--error);
    }
    .op-stage-stepper .op-stage.blocked .stage-status {
      background: rgba(220, 80, 60, 0.12);
      color: var(--error);
    }
    .op-stage-stepper .op-stage.active {
      color: var(--accent);
      font-weight: 600;
    }
    .op-stage-stepper .op-stage.active .stage-status {
      background: rgba(220, 100, 60, 0.12);
      color: var(--accent);
    }
    .op-stage-stepper .op-stage-arrow {
      color: var(--text-dim);
      font-size: 14px;
      flex-shrink: 0;
    }

    /* ===== 2026-06-11 墨宗三栏工作台(operator 单条 tab)=====
       2026-06-12 版面美学重排:④提交 原挤在 348px 中栏 → 双卡每张 ~150px,
       标题/truth-line/按钮文字全断行,右栏下方大片空白(用户截图实锤)。
       重排为「两卡 + 两条全宽横带」节奏:
         row1: ②出片设置(中) | ①剧本(右)
         row2: ③资产准备(跨中+右全宽)
         row3: ④提交(跨中+右全宽 → 双卡横排各 ~480px,断行消失)
       面板零搬迁,纯 id 定位的 grid-column/grid-row。 */
    .op-wb {
      display: grid;
      grid-template-columns: 214px 400px minmax(0, 1fr);
      gap: 16px 20px;
      align-items: start;
    }
    .op-wb > .op-rail { grid-column: 1; grid-row: 1 / span 3; position: sticky; top: 16px; }
    .op-wb > #s-stage-2-panel { grid-column: 2; grid-row: 1; }            /* 中栏:出片设置 */
    .op-wb > #s-stage-1-panel { grid-column: 3; grid-row: 1; }            /* 右:剧本编辑器 */
    .op-wb > #s-stage-3-panel { grid-column: 2 / span 2; grid-row: 2; }   /* 全宽带:资产 */
    .op-wb > #s-stage-4-panel { grid-column: 2 / span 2; grid-row: 3; }   /* 全宽带:提交双卡 */
    /* 左竖轨外观 */
    .op-rail {
      background: #ffffff;
      border: 1px solid var(--line);
      border-radius: 18px;
      padding: 16px;
      display: flex;
      flex-direction: column;
      gap: 4px;
      margin-bottom: 0;
      box-shadow: 0 2px 12px rgba(0,0,0,.04);
    }
    .op-rail .rail-back {
      display: inline-block; font-size: 12px; color: var(--text-dim);
      text-decoration: none; margin-bottom: 8px;
    }
    .op-rail .rail-back:hover { color: var(--accent); }
    .op-rail .rail-proj { padding: 4px 6px 12px; border-bottom: 1px solid var(--line); margin-bottom: 8px; }
    .op-rail .rail-proj .rp-k { font-size: 11px; letter-spacing: .14em; text-transform: uppercase; color: var(--text-dim); }
    .op-rail .rail-proj .rp-name { font-size: 15px; font-weight: 600; color: var(--text-strong); margin-top: 4px; }
    .op-rail .rail-proj .rp-name strong { color: var(--accent); }
    .op-rail .rail-proj .rp-sub { font-size: 12px; color: var(--text-dim); margin-top: 4px; }
    /* rail 内的竖向 stepper:覆盖 .op-stage-stepper 的横向容器样式 */
    .op-rail .op-stage-stepper {
      flex-direction: column; align-items: stretch;
      background: none; border: 0; padding: 0; margin: 0; overflow: visible;
      gap: 2px;
    }
    .op-rail .op-stage-stepper .op-stage {
      width: 100%; padding: 12px; border-radius: 12px; gap: 8px;
      cursor: default; position: relative;
      transition: background .18s;
    }
    .op-rail .op-stage-stepper .op-stage .stage-label { flex: 1; }
    .op-rail .op-stage-stepper .op-stage.active { background: rgba(0,113,227,.07); }
    .op-rail .op-stage-stepper .op-stage.active::after {
      content: ""; position: absolute; left: 0; top: 9px; bottom: 9px;
      width: 3px; border-radius: 0 3px 3px 0; background: var(--grad);
    }

    @media (max-width: 1180px) {
      .op-wb { grid-template-columns: 200px minmax(0, 1fr); }
      .op-wb > .op-rail { grid-row: 1 / span 4; }
      .op-wb > #s-stage-1-panel { grid-column: 2; grid-row: 1; }
      .op-wb > #s-stage-2-panel { grid-column: 2; grid-row: 2; }
      .op-wb > #s-stage-3-panel { grid-column: 2; grid-row: 3; }
      .op-wb > #s-stage-4-panel { grid-column: 2; grid-row: 4; }
    }
    @media (max-width: 760px) {
      .op-wb { grid-template-columns: 1fr; }
      .op-wb > .op-rail { grid-row: auto; position: static; }
      .op-wb > section { grid-column: 1 !important; grid-row: auto !important; }
    }

    .op-stage-panel {
      background: #ffffff;
      border: 1px solid var(--line);
      border-radius: 16px;
      padding: 24px;
      margin-bottom: 20px;
      position: relative;
      overflow: hidden;
      box-shadow: 0 2px 12px rgba(0,0,0,.04);
      transition: border-color .22s, box-shadow .22s, transform .2s;
    }
    /* 状态左条改为渐变竖标(伪元素,不挤压内边距) */
    .op-stage-panel.is-blocked::before,
    .op-stage-panel.is-active::before,
    .op-stage-panel.is-done::before {
      content: ""; position: absolute; left: 0; top: 12px; bottom: 12px;
      width: 3px; border-radius: 0 3px 3px 0;
    }
    .op-stage-panel.is-blocked::before { background: var(--error); }
    .op-stage-panel.is-active::before { background: var(--grad); }
    .op-stage-panel.is-active {
      border-color: rgba(0,113,227,.35);
      box-shadow: 0 0 0 1px rgba(0,113,227,.15), 0 6px 20px rgba(0,0,0,.05);
    }
    .op-stage-panel.is-done::before { background: var(--high); }
    .op-stage-panel .stage-header {
      display: flex;
      align-items: baseline;
      justify-content: space-between;
      gap: 8px 16px;
      flex-wrap: wrap;            /* 2026-06-12 长 meta(③资产 21项统计)换行而非挤窄条 */
      margin-bottom: 16px;
      padding-bottom: 12px;
      border-bottom: 1px solid var(--line);
    }
    .op-stage-panel .stage-header h3 { flex: none; }
    .op-stage-panel .stage-header .stage-summary {
      margin-left: auto; text-align: right; max-width: 100%;
      line-height: 1.55;
    }
    .op-stage-panel .stage-header h3 {
      font-size: 17px;
      font-weight: 600;
      letter-spacing: -.012em;
      color: var(--text-strong);
      margin: 0;
      /* 对齐修复:长 summary 挤压时标题曾被迫词中换行(「③资/产准备」)。
         标题恒一行,空间不足让 summary 换行。 */
      flex: none;
      white-space: nowrap;
    }
    .op-stage-panel .stage-header .stage-summary {
      font-size: 12px;
      color: var(--text-dim);
      min-width: 0;
      text-align: right;
      line-height: 1.5;
    }

    /* Action panel (stage 2 — replaces flat banner) */
    .op-action-panel {
      background: var(--panel-2);
      border: 1px solid var(--line);
      border-left: 3px solid var(--med);
      padding: 16px;
      border-radius: 10px;
      margin-bottom: 16px;
    }
    .op-action-panel.is-green {
      border-left-color: var(--high);
      background: var(--high-soft);
    }
    .op-action-panel #s-readiness-text {
      font-size: 13px;
      line-height: 1.6;
    }
    .op-action-panel .op-action-btn-row {
      display: flex;
      gap: 12px;
      align-items: center;
      margin-top: 12px;
      flex-wrap: wrap;
    }
    .op-action-panel button.action-primary {
      background: var(--grad);
      color: var(--accent-fg);
      border: none;
      padding: 8px 16px;
      border-radius: 10px;
      cursor: pointer;
      font-size: 14px;
      font-weight: 600;
      box-shadow: none;
      transition: transform .15s, box-shadow .25s, filter .2s;
    }
    .op-action-panel button.action-primary:hover { transform: translateY(-1px); box-shadow: 0 4px 14px rgba(0,113,227,.22); filter: brightness(1.05); }
    .op-action-panel button.action-primary:disabled {
      opacity: 0.5; cursor: not-allowed; transform: none; box-shadow: none;
    }
    .op-action-panel button.action-secondary {
      background: #ffffff;
      color: var(--text);
      border: 1px solid var(--line);
      padding: 8px 16px;
      border-radius: 10px;
      cursor: pointer;
      font-size: 13px;
      transition: border-color .18s, color .18s, background .18s;
    }
    .op-action-panel button.action-secondary:hover {
      border-color: var(--accent); color: var(--accent); background: rgba(0,113,227,.06);
    }
    .op-action-panel .action-link {
      color: var(--accent);
      text-decoration: none;
      font-size: 13px;
      font-weight: 600;
    }
    .op-action-panel .action-link:hover { text-decoration: underline; }
    .op-action-panel #s-gen-progress {
      font-size: 12px;
      color: var(--text-dim);
      padding: 12px;
      background: var(--bg2);
      border-radius: 8px;
      margin-top: 12px;
    }
    .op-action-panel #s-unused-list,
    .op-action-panel #s-placeholder-list {
      margin-top: 12px;
      padding: 12px 16px;
      background: var(--bg2);
      border: 1px solid var(--line);
      border-radius: 10px;
      max-height: 240px;
      overflow-y: auto;
      font-size: 12px;
    }
    .op-action-panel .asset-entry {
      display: flex;
      align-items: center;
      gap: 8px;
      padding: 4px 0;
      border-bottom: 1px dotted var(--line);
    }
    .op-action-panel .asset-entry:last-child { border-bottom: none; }
    .op-action-panel .asset-entry .cat-icon { width: 18px; text-align: center; }
    .op-action-panel .asset-entry .name { flex: 1; font-weight: 600; }
    .op-action-panel .asset-entry .aliases {
      color: var(--text-dim); font-size: 11px;
    }
    .op-action-panel .asset-entry a.edit-link {
      color: var(--accent);
      text-decoration: none;
      font-size: 11px;
    }
    .op-action-panel .asset-entry a.edit-link:hover { text-decoration: underline; }

    /* Refs row (the 17 assets summary line) */
    .op-refs-row {
      display: flex;
      gap: 12px;
      align-items: baseline;
      padding: 12px 16px;
      background: var(--bg2);
      border: 1px solid var(--line);
      border-radius: 10px;
      font-size: 12px;
      color: var(--text-dim);
    }
    .op-refs-row strong { color: var(--accent); font-weight: 700; }

    /* Advanced collapsible */
    .op-advanced {
      margin-top: 16px;
      padding: 12px 16px;
      background: var(--bg2);
      border: 1px solid var(--line);
      border-radius: 10px;
    }
    .op-advanced summary {
      cursor: pointer;
      font-size: 13px;
      font-weight: 600;
      color: var(--text-dim);
      padding: 2px 0;
      user-select: none;
    }
    .op-advanced summary:hover { color: var(--accent); }
    .op-advanced[open] summary {
      color: var(--accent);
      margin-bottom: 10px;
      padding-bottom: 8px;
      border-bottom: 1px dashed var(--line);
    }
    .op-advanced .grid {
      margin-top: 8px;
    }

    /* Submit cards (stage 4) */
    .op-stage-prompt {
      font-size: 14px;
      color: var(--text);
      margin-bottom: 12px;
      font-weight: 500;
    }
    .op-submit-cards {
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: 20px;
      margin-bottom: 20px;
    }
    @media (max-width: 720px) {
      .op-submit-cards { grid-template-columns: 1fr; }
    }
    .op-submit-card {
      display: flex;
      flex-direction: column;
      align-items: flex-start;
      text-align: left;
      gap: 8px;
      padding: 24px;
      background: #ffffff;
      border: 1px solid var(--line);
      border-radius: 16px;
      cursor: pointer;
      transition: border-color .2s, transform .18s, box-shadow .22s;
      font-family: inherit;
      color: var(--text);
    }
    .op-submit-card:hover {
      border-color: var(--accent);
      transform: translateY(-3px);
      box-shadow: 0 0 0 1px rgba(0,113,227,.25), 0 10px 28px rgba(0,0,0,.08);
    }
    .op-submit-card:disabled {
      opacity: 0.5; cursor: not-allowed; transform: none; box-shadow: none;
    }
    .op-submit-card .card-icon { font-size: 32px; line-height: 1; }
    .op-submit-card .card-title {
      font-size: 17px;
      font-weight: 600;
      letter-spacing: -.012em;
      color: var(--text-strong);
    }
    .op-submit-card .card-desc {
      font-size: 13px;
      color: var(--text-dim);
      line-height: 1.6;
    }
    .op-submit-card .card-cta {
      margin-top: 8px;
      padding: 8px 16px;
      background: var(--grad);
      color: var(--accent-fg);
      border-radius: 10px;
      font-size: 14px;
      font-weight: 600;
      box-shadow: none;
    }
    .op-submit-card.op-submit-card-danger {
      border-color: rgba(220, 80, 60, 0.3);
    }
    .op-submit-card.op-submit-card-danger:hover {
      border-color: rgba(220, 80, 60, 0.7);
      box-shadow: 0 0 0 1px rgba(220,80,60,.3), 0 16px 40px rgba(220,80,60,.14);
    }
    .op-submit-card.op-submit-card-danger .card-title {
      color: #f87171;
    }
    .op-submit-card.op-submit-card-danger .card-cta {
      background: linear-gradient(135deg, #ef4444, #b91c1c);
      box-shadow: 0 4px 14px rgba(220,80,60,.28);
    }
    /* 2026-05-26 wave-C — truth-line.
       After 7 consecutive dogfood submissions all landed in dry_run
       (operator clicked 🧪 不烧钱 expecting real out片), the cards
       needed a more unmissable signal of "this DOES produce video"
       vs "this DOES NOT". The truth-line sits between title and desc,
       uses high-contrast colors + explicit symbol pairs (❌ vs ✅) so
       a quick glance distinguishes the two paths. */
    .op-submit-card .card-truth {
      font-size: 13px;
      font-weight: 700;
      line-height: 1.45;
      margin: 2px 0 4px;
      padding: 5px 10px;
      border-radius: 8px;
    }
    .op-submit-card .card-truth.is-no {
      color: var(--text-dim);
      background: rgba(0,0,0,.035);
      border-left: 3px solid var(--text-dim-2);
    }
    .op-submit-card.op-submit-card-danger .card-truth.is-yes {
      color: #f87171;
      background: rgba(239, 68, 68, 0.12);
      border-left: 3px solid #ef4444;
    }

    /* Danger zone (folded ack-bypass with ▸ indicator) */
    .op-danger-zone {
      margin-top: 16px;
      padding: 12px 16px;
      background: rgba(220, 80, 60, 0.04);
      border: 1px dashed rgba(220, 80, 60, 0.3);
      border-radius: 10px;
    }
    .op-danger-zone summary {
      cursor: pointer;
      font-size: 12px;
      font-weight: 500;
      color: rgba(180, 80, 60, 0.85);
      padding: 4px 0;
      user-select: none;
    }
    .op-danger-zone summary:hover { color: rgba(200, 70, 55, 1); }
    .op-danger-zone[open] summary {
      margin-bottom: 10px;
      padding-bottom: 6px;
      border-bottom: 1px dashed rgba(220, 80, 60, 0.3);
    }
    .op-danger-zone .danger-warn {
      font-size: 12px;
      color: var(--text);
      background: rgba(220, 80, 60, 0.08);
      padding: 8px 12px;
      border-radius: 9px;
      margin-bottom: 10px;
    }
    .op-danger-zone .danger-card {
      background: var(--bg2);
      border: 1px solid var(--line);
      padding: 12px;
      border-radius: 9px;
      margin-bottom: 10px;
    }
    .op-danger-zone .danger-card label {
      display: flex; align-items: center; gap: 8px;
      font-size: 13px;
      cursor: pointer;
    }
    .op-danger-zone .danger-card .danger-detail {
      margin-top: 8px;
      padding-top: 8px;
      border-top: 1px dotted var(--line);
      font-size: 12px;
      color: var(--text-dim);
      line-height: 1.6;
    }
    .op-danger-zone .danger-card ul {
      margin: 6px 0 0 18px;
      padding: 0;
    }
    .op-danger-zone .danger-card .danger-state {
      font-size: 12px;
      color: var(--text);
      margin-bottom: 6px;
    }

    /* =====================================================================
       OPERATOR · cinematic amp v1 (2026-05-19)
       Minimal layer: header + panel-head + buttons + modal + toast +
       stepper polish. Does NOT restructure W3.5/W3.6 tabs or internal
       sections. Contract preserved: all IDs untouched, behavior pure
       cosmetic. Light footprint (~6KB CSS) to keep risk low on 433KB
       file with active LP-016 + axis-7 integrations.
       ===================================================================== */
    header {
      padding: 16px 24px !important;
      background: linear-gradient(180deg, var(--surface) 0%, var(--surface-2) 100%) !important;
      border-bottom: 1px solid var(--border) !important;
      position: relative;
    }
    header::after {
      content: "";
      position: absolute;
      left: 24px; bottom: -1px;
      width: 64px; height: 2px;
      background: var(--accent);
    }
    header .brand,
    header > span:first-child {
      font-family: var(--font-sans) !important;
      font-weight: 600 !important;
      font-size: 17px !important;
      letter-spacing: -0.012em !important;
      color: var(--text-strong) !important;
    }
    header .crumb {
      font-family: var(--font-mono) !important;
      font-size: 11px !important;
      letter-spacing: 0.16em !important;
      text-transform: uppercase;
      color: var(--accent) !important;
      font-weight: 600;
    }
    header a.nav-link, header > button {
      font-family: var(--font-mono) !important;
      font-size: 11px !important;
      letter-spacing: 0.12em !important;
      text-transform: uppercase;
      padding: 4px 12px !important;
      border-radius: var(--radius-pill) !important;
      background: transparent !important;
      border: 1px solid var(--border) !important;
      color: var(--muted) !important;
      transition: all var(--transition-fast);
    }
    header a.nav-link:hover, header > button:hover {
      background: var(--accent-soft) !important;
      border-color: var(--accent) !important;
      color: var(--accent) !important;
    }

    /* Panel head treatment */
    .panel > h2,
    .panel-head h2,
    section > h2 {
      font-family: var(--font-sans) !important;
      font-weight: 600 !important;
      font-size: 17px !important;
      letter-spacing: -0.012em !important;
      color: var(--text-strong) !important;
    }

    /* Stepper — turn into mono uppercase film-slate look */
    .stepper {
      gap: 8px !important;
    }
    .stepper .step {
      font-family: var(--font-mono) !important;
      font-size: 11px !important;
      letter-spacing: 0.14em !important;
      text-transform: uppercase;
      padding: 4px 12px !important;
      border-radius: 3px !important;
      font-weight: 600;
    }
    .stepper .step.active {
      background: var(--accent) !important;
      color: var(--accent-fg) !important;
      box-shadow: 0 2px 8px var(--accent-soft);
    }

    /* Primary CTA pill treatment (consistent with other surfaces) */
    button.primary,
    .modal-actions button.primary,
    .row button.primary,
    .btn-primary {
      font-family: var(--font-sans) !important;
      font-size: 14px !important;
      letter-spacing: 0.01em !important;
      text-transform: none;
      padding: 8px 20px !important;
      border-radius: var(--radius-pill) !important;
      font-weight: 600 !important;
      background: var(--accent) !important;
      color: var(--accent-fg) !important;
      border: 0 !important;
      box-shadow: 0 4px 12px var(--accent-soft);
      transition:
        background var(--transition-fast),
        box-shadow var(--transition-fast),
        transform var(--transition-fast);
    }
    button.primary:hover:not(:disabled) {
      background: var(--accent-hover) !important;
      box-shadow: 0 6px 18px var(--accent-soft);
      transform: translateY(-1px);
    }

    /* Modal cinematic entrance */
    .modal-bg {
      background: rgba(15, 14, 11, 0.6) !important;
      backdrop-filter: blur(6px);
      -webkit-backdrop-filter: blur(6px);
      opacity: 0;
      transition: opacity 0.32s ease-out;
    }
    .modal-bg.visible,
    .modal-bg:not(.hidden) { opacity: 1; }
    .modal {
      background: var(--surface) !important;
      border: 1px solid var(--border) !important;
      border-radius: var(--radius-lg) !important;
      box-shadow: var(--shadow-lg) !important;
      transform: scale(0.94) translateY(8px);
      opacity: 0;
      transition:
        transform 0.38s cubic-bezier(0.2, 0.8, 0.2, 1),
        opacity 0.28s ease-out;
    }
    .modal-bg.visible .modal,
    .modal-bg:not(.hidden) .modal {
      transform: scale(1) translateY(0);
      opacity: 1;
    }

    /* Toast — magazine notice */
    .toast {
      background: var(--surface) !important;
      border: 1px solid var(--border) !important;
      border-left-width: 4px !important;
      padding: 12px 16px !important;
      border-radius: var(--radius-sm) !important;
      font-family: var(--font-sans) !important;
      font-size: 13px !important;
      letter-spacing: 0 !important;
      text-transform: none;
      box-shadow: var(--shadow-md) !important;
    }
    .toast.ok { border-left-color: var(--high) !important; }
    .toast.err,
    .toast.error { border-left-color: var(--low) !important; color: var(--low) !important; }
    .toast.warn { border-left-color: var(--med) !important; }

    /* =====================================================================
       OPERATOR · cinematic amp v2 polish (2026-05-19)
       W3.5/W3.6 tabs + stepper hover state + form-field accent ring +
       panel-enter on tab content. Lighter than v2 of small surfaces
       because operator's panels are stateful (dispatching, log streams).
       ===================================================================== */
    .tabs {
      background: linear-gradient(180deg, var(--surface) 0%, var(--surface-2) 100%) !important;
      gap: 6px !important;
      padding: 8px 18px 0 !important;
      border-bottom: 1px solid var(--border) !important;
    }
    .tabs button {
      font-family: var(--font-sans) !important;
      font-size: 13px !important;
      letter-spacing: 0 !important;
      text-transform: none;
      font-weight: 600 !important;
      padding: 12px 16px !important;
      border-radius: var(--radius-sm) var(--radius-sm) 0 0 !important;
      border-bottom: 2px solid transparent !important;
      color: var(--muted) !important;
      background: transparent !important;
      transition: all var(--transition-fast);
    }
    .tabs button:hover {
      color: var(--text-strong) !important;
      background: var(--surface) !important;
    }
    .tabs button.active {
      color: var(--accent) !important;
      background: var(--surface) !important;
      border-bottom-color: var(--accent) !important;
      font-weight: 700 !important;
    }

    /* Stepper hover state — accent-soft fade-in on each step */
    .stepper .step {
      transition: background var(--transition-fast), color var(--transition-fast);
    }
    .stepper .step:not(.active):hover {
      background: var(--accent-soft) !important;
      color: var(--accent) !important;
    }
    .stepper .arrow {
      color: var(--border-strong) !important;
    }

    /* Form input accent focus ring (anywhere in operator) */
    input[type="text"], input[type="email"], input[type="password"],
    input[type="number"], input[type="search"],
    textarea, select {
      background: var(--surface) !important;
      border: 1px solid var(--border) !important;
      border-radius: var(--radius-sm) !important;
      transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
    }
    input:focus, textarea:focus, select:focus {
      border-color: var(--accent) !important;
      box-shadow: 0 0 0 3px var(--accent-soft) !important;
      outline: none !important;
    }

    @media (prefers-reduced-motion: reduce) {
      .modal-bg, .modal-bg .modal { transition: none; transform: none; opacity: 1; }
      button.primary, .tabs button, .stepper .step { transition: none; }
    }
