/*
 * ============================================================================
 * 全站唯一色板（2026-10-31）
 *
 * 分镜台先试点，用户认可后铺到全部板块：写作 / 画布 / 管理端 / 工作台，
 * 连客户端窗口标题栏也读这一份（壳通过 IPC 拿 --page-bg 的当前值）。
 *
 * 所以**这里的每一个值都不许在别处再写一遍** —— 之前分镜台自己拷了一份放在
 * board.css 末尾，两份一改就飘。要调色只改这里。
 *
 * 三层背景是这套东西的骨架：
 *   ① --bg      页面底
 *   ② --panel   面板 / 卡片（浮在页面之上）
 *   ③ --sunken  内嵌面（剧本框、输入框、槽位）—— 凹进去的那一层
 * 只有两层的时候，输入框和它所在的容器同色，"这里能打字"根本读不出来。
 *
 * 白天不改成"科技黑"，那是另一个产品：只把暖纸底（#f5f5f2）冷半度，
 * 描边从实线换成半透明。暖灰配实线，凑近看是"打印纸"，不是"仪器"。
 * ============================================================================
 */
:root{
  --bg:#eef2f8;--panel:#fff;--panel2:#f5f8fc;--sunken:#eaf0f8;--soft:#f0f4fa;--hover:#e6edf8;
  --ink:#0d1522;--ink2:#4d5b70;--ink3:#7f8da4;
  /* hairline：半透明，压在底上会自己融进去，不切出一条硬边 */
  --line:rgba(20,45,85,.10);--line2:rgba(20,45,85,.18);
  --accent:#0b6fd0;--accent-soft:rgba(11,111,208,.07);--accent-line:rgba(11,111,208,.30);
  --ok:#12795a;--ok-soft:#e8f6f0;--warn:#a9690b;--warn-soft:#fdf3e2;--danger:#c23a2f;--danger-soft:#fdeceb;
  --bh:0px;
  --radius:14px;
  /* 顶面内高光 + 两段很淡的投影：白卡片才不会像贴了张纸 */
  --shadow:inset 0 1px 0 #fff,0 1px 2px rgba(16,34,66,.05),0 10px 26px rgba(16,34,66,.06);
  /* 卡片上沿那道 1px 亮线；夜晚换成青色 */
  --topline:linear-gradient(90deg,rgba(11,111,208,.32),rgba(11,111,208,.06) 46%,transparent 78%);
  /* 主按钮：全站唯一允许"发光"的元素 */
  --btn-main:linear-gradient(135deg,#1183e6,#0b5cc0);
  --btn-main-ink:#fff;
  --btn-main-glow:0 1px 2px rgba(11,92,192,.30);
  --bubbg:#fff;--bubline:rgba(20,45,85,.10);
  --sb:rgba(20,45,85,.16);
  /* 下拉箭头自绘：系统那个灰三角配立体阴影，深色底上尤其出戏 */
  --chev:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'><path d='M1 1l4 4 4-4' fill='none' stroke='%237f8da4' stroke-width='1.5' stroke-linecap='round'/></svg>");
}
*{box-sizing:border-box}
/* 等宽数字：token、集号、积分、耗时全部对齐。数字一歪，"精密工具"的感觉立刻没了 */
body{margin:0;background:var(--bg);color:var(--ink);font-family:system-ui,-apple-system,"Segoe UI","Microsoft YaHei",sans-serif;font-size:13px;min-height:100vh;font-variant-numeric:tabular-nums;font-feature-settings:"tnum" 1;-webkit-font-smoothing:antialiased}
header{display:flex;align-items:center;gap:14px;padding:0 18px;height:52px;background:var(--panel);border-bottom:1px solid var(--line);position:sticky;top:0;z-index:10}
.brand{font-size:15px;font-weight:600;display:flex;align-items:center;gap:8px}
/* 品牌小图：和文字基线对齐用 flex，别用 vertical-align —— 那个在 flex 行里没用 */
.brand .mark{width:22px;height:22px;border-radius:6px;display:block;flex:none}
.brand i{font-style:normal;font-size:11px;color:var(--ink3);margin-left:0;font-weight:400}
/* 壳的版本号：比品牌名小两号，只起「确认是哪一版」的作用，不抢注意力。
   只有客户端里有（页面拿得到 window.WF_UPD 才插），浏览器里不显示。 */
.brand .vertag{font-size:10px;font-weight:400;color:var(--ink3);opacity:.8;letter-spacing:.2px;margin-left:-2px;white-space:nowrap}
.spacer{flex:1}
.pill{font-size:11px;padding:4px 9px;border-radius:20px;border:1px solid var(--line2);color:var(--ink2);background:var(--panel2);white-space:nowrap}
.pill.on{color:var(--ok);border-color:#bfe0d3;background:var(--ok-soft)}
.pill.hot{color:var(--accent);border-color:#c5d5fb;background:var(--accent-soft)}
/* 积分刚被扣掉时闪一下：数字自己变了、用户却没看见是哪一步扣的，等于没反馈 */
.pill.dip{animation:cvdip .9s ease-out}
@keyframes cvdip{
  0%{background:var(--danger);border-color:var(--danger);color:#fff;transform:scale(1.06)}
  60%{transform:scale(1)}
  100%{transform:scale(1)}
}
.who{font-size:12px;color:var(--ink2)}
main{max-width:none;margin:0 auto;padding:14px 22px 24px}
.card{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow);padding:16px;margin-bottom:16px}
.card h2{font-size:13px;font-weight:600;margin:0 0 12px;display:flex;align-items:center;gap:8px}
.card h2 .hint{font-weight:400;font-size:11px;color:var(--ink3)}
.grid2{display:grid;grid-template-columns:400px 1fr;gap:16px;align-items:start}
/*
 * 左栏宽度：原来是写死的 286px。
 *
 * 2026-10-31 用户画了个框要「左边这么宽，右边留给对话」：在 1920 宽下红框是 26%。
 * 写死像素在这个比例下只有 15%，而且换分辨率就变形 —— 所以改成按比例给，
 * 上下用 clamp 兜住：小窗口不至于窄到折行（320），大屏不至于吃掉半个对话区（560）。
 * 收起左栏那条规则不受影响。
 */
.grid2.desk{grid-template-columns:clamp(320px,26%,560px) minmax(0,1fr)}
/* 收起左栏：网格要缩成「一列」。写成 0 + 1fr 是不行的 ——
   左栏 display:none 之后右栏会顶到第 1 列（宽 0），整个工作区塌成一条竖线 */
.grid2.desk.aside-off{grid-template-columns:minmax(0,1fr);gap:0}
.grid2.desk.aside-off>div:first-child{display:none}
@media(max-width:1100px){.grid2{grid-template-columns:1fr}}
label.field{display:block;margin-bottom:12px}
label.field>span{display:block;font-size:12px;color:var(--ink2);margin-bottom:5px}
input,select,textarea{width:100%;font-family:inherit;font-size:13px;color:var(--ink);background-color:var(--panel2);border:1px solid var(--line2);border-radius:8px;padding:8px 10px;outline:none}
/* 只能写 background-color：简写的 background 会把 select 的箭头图一起清掉 */
input:focus,select:focus,textarea:focus{border-color:var(--accent);background-color:var(--panel);box-shadow:0 0 0 3px var(--accent-soft)}
textarea{resize:vertical;line-height:1.7}
.btn{font-family:inherit;font-size:13px;padding:8px 14px;border-radius:8px;border:1px solid var(--line2);background:var(--panel);color:var(--ink);cursor:pointer;white-space:nowrap;transition:background .14s ease,border-color .14s ease,color .14s ease,box-shadow .16s ease}
.btn:hover{border-color:var(--ink3)}
/*
 * 主按钮是全站唯一"发光"的东西。
 * 之前那一版赛博方案把发光铺到卡片、按钮、标签上，到处亮等于哪里都不亮 ——
 * 光只给这一处，它才真的像"主"按钮。
 */
.btn.primary{background:var(--btn-main);border-color:transparent;color:var(--btn-main-ink);font-weight:600;letter-spacing:.02em;box-shadow:var(--btn-main-glow)}
.btn.primary:hover{background:var(--btn-main);filter:brightness(1.08)}
.btn.ghost{border-color:transparent;background:transparent;color:var(--ink2);padding:6px 8px}
.btn.ghost:hover{background:var(--hover);color:var(--ink)}
.btn.sm{font-size:11px;padding:4px 9px;border-radius:7px}
.btn:disabled{opacity:.5;cursor:not-allowed}
.tabs{display:flex;gap:4px;margin-bottom:16px}
.tabs button{padding:8px 14px;border:0;background:transparent;border-radius:8px;font-family:inherit;font-size:13px;color:var(--ink2);cursor:pointer}
.tabs button.active{background:var(--accent-soft);color:var(--accent);font-weight:500}
.slots{display:flex;flex-direction:column;gap:8px;min-height:56px}
.slot{display:flex;align-items:center;gap:10px;padding:9px 10px;border:1px solid var(--line);border-radius:8px;background:var(--panel2)}
.slot .idx{width:20px;height:20px;border-radius:50%;background:var(--accent-soft);color:var(--accent);font-size:11px;display:flex;align-items:center;justify-content:center;flex:none}
.slot .nm{font-size:13px;font-weight:500}
.slot .mt{font-size:11px;color:var(--ink3);margin-top:2px}
.slot .grow{flex:1;min-width:0}
.slot .ops{display:flex;gap:2px}
.empty{border:1px dashed var(--line2);border-radius:8px;padding:22px;text-align:center;color:var(--ink3);font-size:12px}
.addbar{display:flex;gap:8px;margin-top:12px}
.budget .bar{height:6px;background:var(--hover);border-radius:4px;overflow:hidden;margin-top:14px}
.budget .fill{height:100%;background:var(--accent);width:0;transition:width .25s}
.budget .fill.over{background:var(--danger)}
.budget .txt{font-size:11px;color:var(--ink3);margin-top:6px;display:flex;justify-content:space-between}
.out{margin-top:12px;border:1px solid var(--line);border-radius:8px;background:var(--panel2);padding:16px 18px;min-height:300px;max-height:58vh;overflow:auto;font-family:"Source Han Serif SC","Songti SC",SimSun,Georgia,serif;font-size:14.5px;line-height:1.9;white-space:pre-wrap;word-break:break-word;color:#24262b}
.out:empty::before{content:"生成的内容会出现在这里";color:var(--ink3);font-family:system-ui,sans-serif;font-size:12px}
.status{font-size:11px;color:var(--ink3);margin-top:8px;display:flex;gap:12px;flex-wrap:wrap}
.tag{font-size:11px;padding:2px 7px;border-radius:5px;background:var(--hover);color:var(--ink2)}
.tag.ok{background:var(--ok-soft);color:var(--ok)}
.tag.bad{background:var(--danger-soft);color:var(--danger)}
.tag.warn{background:var(--warn-soft);color:var(--warn)}
.issues{margin-top:10px;display:flex;flex-direction:column;gap:6px}
/* 以前这里写死 #7d241c / #7a4b06，深色主题下 --danger-soft 变成 #3a1f1d，
   深字压深底几乎看不见（和当年"白块"是同一类事故）。一律走变量 */
.issue{font-size:12px;padding:8px 10px;border-radius:7px;background:var(--danger-soft);color:var(--danger);line-height:1.6}
.issue.warn{background:var(--warn-soft);color:var(--warn)}
/* 审核模型返回原文的折叠口：只在它没按格式回答时出现，纯诊断用 */
.issraw{font-size:11px;color:var(--ink3)}
.issraw summary{cursor:pointer;padding:2px 0}
.issraw div{margin-top:6px;padding:8px 10px;border:1px solid var(--line);border-radius:7px;background:var(--soft);color:var(--ink2);line-height:1.7;white-space:pre-wrap;word-break:break-word;max-height:180px;overflow:auto}
.list-item{padding:9px 11px;border-radius:8px;cursor:pointer;font-size:13px;display:flex;align-items:center;gap:8px}
.list-item:hover{background:var(--hover)}
.list-item.active{background:var(--accent-soft);color:var(--accent);font-weight:500}
.list-item .d{font-size:11px;color:var(--ink3);margin-left:auto}
.tree .dir{font-size:11px;color:var(--ink3);font-family:"Cascadia Mono",Consolas,monospace;margin:10px 0 4px}
.tree .file{display:flex;align-items:center;gap:8px;padding:6px 9px;border-radius:7px;cursor:pointer;font-size:12px}
.tree .file:hover{background:var(--hover)}
.tree .file.active{background:var(--accent-soft);color:var(--accent)}
.tree .file .sz{margin-left:auto;font-size:10px;color:var(--ink3)}
.login{max-width:380px;margin:60px auto}
.login h1{font-size:18px;margin:0 0 6px}
.login p{color:var(--ink2);font-size:12.5px;line-height:1.8;margin:0 0 20px}
.login .switch{font-size:12px;color:var(--ink2);margin-top:14px;text-align:center}
.login .switch a{color:var(--accent);cursor:pointer;text-decoration:none}
.toast{position:fixed;bottom:22px;left:50%;transform:translateX(-50%);background:#22262c;color:#fff;font-size:12.5px;padding:10px 16px;border-radius:8px;z-index:90;opacity:0;transition:opacity .2s;pointer-events:none;max-width:80vw}
.toast.show{opacity:1}
.toast.bad{background:#8f2a22}
table{width:100%;border-collapse:collapse;font-size:12px}
th{text-align:left;color:var(--ink3);font-weight:500;padding:6px 8px;border-bottom:1px solid var(--line)}
/* 原先是写死的 #f1f1ee：浅色下没问题，深色主题里就是一条发白的横线 */
td{padding:7px 8px;border-bottom:1px solid var(--line)}

/* 这份用户列表读的是哪台库：本机测试库 / 线上库 */
.dbpill{font-size:10.5px;font-weight:400;padding:2px 8px;border-radius:20px;border:1px solid var(--line2);color:var(--ink2)}
.dbpill.loc{background:var(--warn-soft);color:var(--warn);border-color:transparent}
.dbpill.live{background:var(--ok-soft);color:var(--ok);border-color:transparent}

/* ── 管理端「用户与积分」：搜索条 + 注销 ───────────────────────── */
.ubar{display:flex;align-items:center;gap:8px;margin:-4px 0 12px;flex-wrap:wrap}
.trbar{display:flex;align-items:center;gap:8px;margin:-4px 0 10px;flex-wrap:wrap}
.ubarsplit{flex:1}
.usearch{width:280px;max-width:100%;padding:6px 10px;font-size:12.5px}
.udel{color:var(--danger)}
.udel:hover{background:var(--danger-soft);opacity:1}
.btn.danger{background:var(--danger);border-color:var(--danger);color:#fff}
.btn.danger:hover{opacity:.88}
[data-theme="dark"] .btn.danger{color:#1a0f0e}

/* 危险操作确认框 */
.cmask{position:fixed;inset:0;background:rgba(12,14,18,.5);z-index:9998;display:flex;align-items:center;justify-content:center;padding:24px}
.cbox{background:var(--panel);border:1px solid var(--line2);border-radius:13px;max-width:460px;width:100%;padding:18px 20px;box-shadow:0 18px 48px rgba(0,0,0,.28)}
.ctitle{font-size:14px;font-weight:600;margin-bottom:10px;color:var(--ink)}
.ctext{font-size:12.5px;line-height:1.85;color:var(--ink2);white-space:normal;word-break:break-word}
.ctext b{color:var(--danger);font-weight:600}
.cact{display:flex;justify-content:flex-end;gap:8px;margin-top:16px}
.mono{font-family:"Cascadia Mono",Consolas,monospace;font-size:11.5px}
.muted{color:var(--ink3)}
.mods{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(100%,300px),340px));gap:10px;min-width:0}
.mod{border:1px solid var(--line);border-radius:9px;padding:11px 13px;background:var(--panel);cursor:pointer;display:flex;flex-direction:column;gap:4px;min-width:0}
.mod:hover{border-color:var(--line2);box-shadow:var(--shadow)}
.mod.on{border-color:var(--accent);background:var(--accent-soft)}
.mod .nm{font-size:13px;font-weight:500}
.mod .ds{font-size:11.5px;color:var(--ink3);line-height:1.6;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}

/* ---------------------- 三阶段流水线（v0.2 新增） ---------------------- */
.projbar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow);padding:10px 14px;margin-bottom:14px}
.projbar .muted{font-size:12px}
.steps{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin-bottom:16px}
@media(max-width:820px){.steps{grid-template-columns:1fr}}
.step{display:flex;align-items:center;gap:10px;padding:11px 14px;background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);cursor:pointer;transition:border-color .15s,background .15s}
.step:hover{border-color:var(--line2)}
.step.active{border-color:var(--accent);background:var(--accent-soft);box-shadow:var(--shadow)}
.step .no{width:22px;height:22px;border-radius:50%;background:var(--hover);color:var(--ink2);display:flex;align-items:center;justify-content:center;font-size:11px;flex:none}
.step.active .no{background:var(--accent);color:#fff}
.step .grow{flex:1;min-width:0}
.step .tt{font-size:13px;font-weight:500}
.step .st{font-size:11px;color:var(--ink3);margin-top:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.step.active .st{color:#4a6bbd}
.step .dot{width:7px;height:7px;border-radius:50%;background:var(--line2);flex:none}
.step .dot.ok{background:var(--ok)}

.chips{display:flex;flex-wrap:wrap;gap:6px;margin-top:6px}
.chip{display:inline-flex;align-items:center;gap:5px;font-size:11.5px;padding:5px 10px;border-radius:20px;background:var(--soft);border:1px solid var(--line);color:var(--ink2);white-space:nowrap}
.chip.auto{background:var(--hover);color:var(--ink2);border-style:dashed}
.chip.ok{background:var(--ok-soft);border-color:#cbe6da;color:var(--ok)}
.chip.bad{background:var(--warn-soft);border-color:#f0ddbd;color:var(--warn)}
.upstream{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:14px}

.chat{display:flex;flex-direction:column;gap:10px;padding:6px 2px;min-height:220px;max-height:46vh;overflow:auto;
  /* 关掉浏览器自带的滚动锚定：流式追加文字时它会自己微调 scrollTop，
     和我们每帧的"贴底跟随"互相拉扯，肉眼就是一下一下地跳 */
  overflow-anchor:none}
.bub{max-width:84%;padding:10px 13px;border-radius:12px;font-size:13.5px;line-height:1.85;white-space:pre-wrap;word-break:break-word}
.bub.ai{background:var(--soft);border:1px solid var(--line);align-self:flex-start;border-bottom-left-radius:4px}
.bub.me{background:var(--accent-soft);border:1px solid #d6e0fb;align-self:flex-end;border-bottom-right-radius:4px;color:#1b2a52}
.bub.pending{color:var(--ink3)}
/* ── 被打回的那一版（审核没过、已退回重写）─────────────────────────
   定位是"作废记录"，不是可读的稿子：虚线框、降饱和、正文收进折叠口。
   全部走变量 —— 写死颜色在深色主题下必翻车（`.issue` 那次就是这么坏的）。 */
.bub.voided{background:var(--panel2);border:1px dashed var(--line2);max-width:84%;opacity:.92;
  /* .bub 是 pre-wrap，废稿这条的模板里有换行缩进，不关掉会渲染成一堆空行 */
  white-space:normal}
.voidhead{display:flex;align-items:center;gap:7px;flex-wrap:wrap;font-size:12px;color:var(--ink2);white-space:normal}
.voidhead .vver{color:var(--ink);font-weight:600}
.voidhead .vwhy{color:var(--ink3)}
.voidiss{margin:8px 0 0;padding:0 0 0 18px;font-size:11.5px;line-height:1.7;color:var(--danger);white-space:normal}
.voidiss li{margin:1px 0}
.voidbody{margin-top:8px;font-size:11.5px;color:var(--ink3);white-space:normal}
.voidbody summary{cursor:pointer;user-select:none}
.voidtext{margin-top:6px;max-height:180px;overflow:auto;padding:8px 10px;border-radius:7px;background:var(--soft);border:1px solid var(--line);color:var(--ink2);line-height:1.75;white-space:pre-wrap}
.bubhead{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-bottom:7px;white-space:normal}
.bubhead .tag{font-size:10.5px}
.composer{display:flex;gap:8px;align-items:stretch;margin-top:14px}
.composer textarea{flex:1}

.saved{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-top:12px;font-size:11.5px;color:var(--ink3)}
.chk{display:inline-flex;align-items:center;gap:6px;font-size:12px;color:var(--ink2);cursor:pointer;white-space:nowrap}
.chk input{width:auto;margin:0;padding:0}

textarea.manuscript{width:100%;min-height:360px;max-height:60vh;font-family:"Source Han Serif SC","Songti SC",SimSun,Georgia,serif;font-size:14.5px;line-height:1.95;background:var(--panel2);padding:16px 18px;resize:vertical;white-space:pre-wrap}
.tag.warn{background:var(--warn-soft);color:var(--warn)}
.status .tag{margin-right:6px}
/* 「正在送审」：整条流程里唯一一段正文已经吐完、屏幕上没有字节在动、只能干等的时间。
   11px 小灰 tag 和「装配 N 个模组」长得一模一样，用户看不出来它在审。
   所以放大一号 + 蓝底蓝框 + 呼吸点，让人一眼知道是"在审"而不是"卡死" */
.status .tag.rev{display:inline-flex;align-items:center;gap:7px;font-size:13px;font-weight:600;
  padding:5px 12px;border-radius:7px;background:var(--accent-soft);color:var(--accent);
  border:1px solid var(--accent-line);margin-right:10px}
.tag.rev .revdot{width:8px;height:8px;border-radius:50%;background:var(--accent);flex:none;
  animation:revpulse 1.1s ease-in-out infinite}
/* 呼吸点最低也留 0.4 不透明度：截图/截图外的任意一帧都得看得见它在闪，别闪成"消失" */
@keyframes revpulse{0%,100%{opacity:.4;transform:scale(.8)}50%{opacity:1;transform:scale(1.25)}}
.status .revby{font-size:11.5px;color:var(--ink2);align-self:center}

/* ---------------------- 模型接口管理（v0.3 新增） ---------------------- */
.pvcard{border:1px solid var(--line);border-radius:10px;padding:14px 16px;margin-bottom:12px;background:var(--panel)}
.pvhead{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.pvhead .pvname{font-size:14px;font-weight:600;border:1px solid transparent;background:transparent;padding:4px 6px;width:200px}
.pvhead .pvname:hover{border-color:var(--line)}
.pvhead .pvname:focus{background:var(--panel2);border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}
.mline{display:flex;align-items:center;gap:12px;padding:5px 6px;border-radius:6px;font-size:12.5px}
.mline:hover{background:var(--soft)}
.mline .chk:first-child{flex:1;min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}
.mline .chk:nth-of-type(2){color:var(--ink3);flex:none}
.mline-head{display:flex;font-size:11px;color:var(--ink3);padding:0 6px 5px;border-bottom:1px solid var(--line);margin-bottom:2px}
/* 每个模型的独立价格（元/百万 token）+ 一集积分预览 */
.mrow{border-bottom:1px dashed transparent}
.mprice{display:flex;align-items:center;gap:6px;flex-wrap:wrap;padding:0 6px 4px 24px;font-size:11.5px;color:var(--ink3)}
.mprice select{width:auto;max-width:160px;font-size:11.5px;padding:3px 6px}
.mprice input{width:78px;padding:3px 6px;border:1px solid var(--line);border-radius:5px;font-size:11.5px;text-align:right;background:var(--panel)}
.mprice input:focus{border-color:var(--accent);outline:none;box-shadow:0 0 0 3px var(--accent-soft)}
.mcalc{color:var(--accent);font-size:11.5px;line-height:1.8;padding:0 6px 9px 24px;font-weight:500}
.mcalc b{font-weight:600}
/* 没填价格时的警告：不显眼就等于没提示 */
.mcalc .pwarn{display:block;font-style:normal;color:#c0392b;font-size:11px;margin-top:2px}
[data-theme="dark"] .mcalc .pwarn{color:#ff8a80}
/* 拉取/检测失败时的诊断块：必须能看清「对方到底回了什么」，不能只丢一句失败 */
.pvdiag{margin-top:10px;padding:10px 12px;border-radius:8px;font-size:12px;line-height:1.7;white-space:pre-wrap;overflow-wrap:anywhere;font-family:ui-monospace,Consolas,'Courier New',monospace}
.pvdiag.bad{background:#fdf3f2;border:1px solid #f2d5d1;color:#96382f}
.pvdiag.ok{background:#f1f8f3;border:1px solid #d5e7da;color:#2e6a3e}

/* ---------- 候选池（拉回来的模型，只勾选、不改价）+ 已添加（改价在这里） ---------- */
.candhead{display:flex;align-items:baseline;gap:8px;font-size:12.5px;font-weight:600;margin:16px 0 7px}
.candhead .muted{font-weight:400;font-size:11px}
.candbox{border:1px solid var(--line);border-radius:9px;background:var(--soft);padding:9px 10px}
.candbar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:8px}
/* 全站的 input/select 都是 width:100%，这里不写回来就会一个下拉占一整行 */
.candbar select{width:auto;max-width:210px;font-size:12px;padding:3px 6px;border-radius:6px;border:1px solid var(--line2);background:var(--panel);color:var(--ink)}
.candbar input{flex:1 1 170px;min-width:120px;width:auto;font-size:12px;padding:4px 9px;border-radius:6px;border:1px solid var(--line2);background:var(--panel);color:var(--ink)}
.candbar input:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}
.candcount{margin-left:auto;font-size:11px;white-space:nowrap;color:var(--ink3)}
/* 模型可能有几百个：限高滚动 + 一行多个胶囊，别再一条一条竖着排 */
.candlist{display:flex;flex-wrap:wrap;gap:5px;max-height:260px;overflow:auto}
.candrow{display:flex;align-items:center;gap:6px;padding:3px 9px;border:1px solid var(--line2);border-radius:999px;
  background:var(--panel);font-size:11.5px;cursor:pointer;max-width:100%}
.candrow:hover{border-color:var(--accent-line)}
.candrow.on{background:var(--accent-soft);border-color:var(--accent-line)}
.candrow input{margin:0;flex:none;width:auto}
.candname{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:220px}
.candkind{font-style:normal;font-size:10px;padding:0 5px;border-radius:20px;background:var(--soft);
  color:var(--ink3);border:1px solid var(--line);flex:none}
.candempty{font-size:11.5px;color:var(--ink3);padding:6px 4px;line-height:1.7}
.addedhd{display:flex;align-items:center;gap:8px;padding:2px 6px 6px;flex-wrap:wrap}
.addedname{font-size:12.5px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* 显示名可改：左边是给用户看的名字，右边跟着上游真实 id（用户 2026-11-01 要求） */
.addedhd .renname{flex:0 1 200px;min-width:130px;font-size:12.5px;font-weight:500;padding:3px 8px;
  border-radius:6px;border:1px solid var(--line);background:var(--panel);color:var(--ink)}
.addedhd .renname::placeholder{color:var(--ink3);font-weight:400}
.addedhd .origid{font-size:11px;font-weight:400;color:var(--ink3);flex:0 1 auto;min-width:0;
  max-width:260px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.addedrow{border-bottom:1px dashed var(--line);padding-bottom:8px;margin-bottom:6px}

/* --------------------------------- 模组库 --------------------------------- */
.libgroup{margin-bottom:20px}
.libgrouph{font-size:12px;color:var(--ink3);padding-bottom:6px;border-bottom:1px solid var(--line);margin-bottom:10px}
.libgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(228px,1fr));gap:10px}
.libcard{border:1px solid var(--line);border-radius:10px;padding:10px 12px;background:var(--panel);display:flex;flex-direction:column;gap:6px}
.libcard.on{border-color:var(--accent);background:#fbfcff}
.libhead{display:flex;align-items:center;gap:6px}
.libname{font-size:13px;font-weight:500;flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.libtag{font-size:10px;padding:1px 5px;border-radius:4px;background:#E6F1FB;color:#185FA5;white-space:nowrap}
.libdesc{font-size:11.5px;color:var(--ink3);line-height:1.6;min-height:2.2em}
.libfoot{display:flex;align-items:center;gap:8px;margin-top:auto;font-size:11px}
.libhint{margin-left:auto}
.libnote{margin-top:18px;padding:10px 12px;border-radius:8px;background:var(--soft);font-size:11.5px;color:var(--ink3);line-height:1.7}
/* 后台标签上的待配置提示 */
.tdot{display:inline-block;margin-left:5px;font-size:10px;padding:1px 5px;border-radius:4px;background:#FCEBEB;color:#A32D2D;vertical-align:1px;font-weight:400}
/* 报错文案会长到两三行，得能换行、能看清 */
.toast{line-height:1.65;white-space:pre-wrap;text-align:left;box-shadow:0 10px 30px rgba(0,0,0,.18)}
/* 每条 AI 回复下面的「只存这段」：默认淡一点，指上去变清楚 */
.bubops{margin-top:10px;padding-top:8px;border-top:1px dashed rgba(0,0,0,.09);display:flex;justify-content:flex-end;opacity:.55;transition:opacity .15s}
.bub:hover .bubops,.bub:focus-within .bubops{opacity:1}
.bubops .btn{font-size:11px;padding:3px 9px}
/* 思考强度写法选择 */
.mthink{display:flex;align-items:center;gap:6px;padding:0 6px 9px 24px;font-size:11.5px;color:var(--ink3);flex-wrap:wrap}
.mthink select{width:auto;min-width:240px;font-size:11.5px;padding:3px 6px}
/* 气泡里的操作按钮：多按钮并排不换行，用户那条底色偏深要单独调色 */
.bub .bubops{flex-wrap:wrap;gap:5px}
.bub.me .bubops .btn{color:#1b2a52;border-color:rgba(27,42,82,.22);opacity:.9}
.bub .bubops .btn:hover{opacity:1}
/* 文件行上的删除键：平时很淡，指上去才明显，避免误点 */
.tree .file .filedel{margin-left:6px;padding:1px 6px;font-size:10px;opacity:0;transition:opacity .15s}
.tree .file:hover .filedel{opacity:1}
.tree .file:hover .filedel:hover{opacity:1;color:#a32d2d;border-color:#e6c7c3}

/* ------------------------------- 夜晚模式 -------------------------------- */
/*
 * 科技感真正落脚的地方。
 * 底色从 #14161a（纯灰，r=g=b）换成 #070910（带一点蓝）——
 * 中性灰在任何屏幕上都是"死"的，色相偏一点点，立刻有"设备"味。
 */
[data-theme="dark"]{
  --bg:#070910;--panel:#0d111a;--panel2:#121926;--sunken:#04060b;--soft:#0a0e17;--hover:#16202f;
  --ink:#eaf1fb;--ink2:#93a5bd;--ink3:#6b7d94;
  --line:rgba(126,170,255,.13);--line2:rgba(126,170,255,.22);
  --accent:#2ad4e8;--accent-soft:rgba(42,212,232,.10);--accent-line:rgba(42,212,232,.36);
  --ok:#43d6a4;--ok-soft:rgba(67,214,164,.12);--warn:#e3a95c;--warn-soft:rgba(227,169,92,.12);
  --danger:#f0897f;--danger-soft:rgba(240,137,127,.13);
  --shadow:inset 0 1px 0 rgba(255,255,255,.05),0 1px 2px rgba(0,0,0,.45),0 16px 36px rgba(0,0,0,.42);
  --topline:linear-gradient(90deg,rgba(42,212,232,.55),rgba(126,170,255,.14) 46%,transparent 78%);
  --btn-main:linear-gradient(135deg,#2ad4e8,#3f7dff);
  --btn-main-ink:#04141a;
  --btn-main-glow:0 0 0 1px rgba(42,212,232,.40),0 0 20px rgba(42,212,232,.22);
  --bubbg:#0f1522;--bubline:rgba(126,170,255,.16);
  --sb:rgba(126,170,255,.16);
  --chev:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'><path d='M1 1l4 4 4-4' fill='none' stroke='%236b7d94' stroke-width='1.5' stroke-linecap='round'/></svg>");
}
/*
 * 这里**只能用 background-color**。
 * 写成 background:var(--panel2) 是简写，会把下面那条 select 的箭头图
 * （background-image:var(--chev)）一起清掉 —— 深色主题下下拉就变回没三角形的白框。
 */
[data-theme="dark"] input,[data-theme="dark"] select,[data-theme="dark"] textarea{background-color:var(--panel2);color:var(--ink);border-color:var(--line2)}
[data-theme="dark"] input:focus,[data-theme="dark"] select:focus,[data-theme="dark"] textarea:focus{background-color:var(--panel)}
[data-theme="dark"] .btn{background-color:var(--panel2);color:var(--ink)}
[data-theme="dark"] .btn:hover{background-color:var(--hover);border-color:var(--ink3)}
[data-theme="dark"] .bub.me{color:#c8f6fd;border-color:var(--accent-line)}
[data-theme="dark"] .bub.me .bubops .btn{color:#c8f6fd;border-color:rgba(200,246,253,.26)}
[data-theme="dark"] .toast{background:#04060b}
[data-theme="dark"] .pvdiag.bad{background:#3a1f1d;border-color:#5a2b26;color:#f3b7b0}
[data-theme="dark"] .pvdiag.ok{background:#12332a;border-color:#1e4a3c;color:#8fdcc0}
[data-theme="dark"] .mcalc{color:#7fe8f6}
[data-theme="dark"] .step.active{background:var(--accent-soft)}
[data-theme="dark"] .mod.on{background:var(--accent-soft)}
[data-theme="dark"] .libcard.on{background:var(--accent-soft)}
[data-theme="dark"] img,[data-theme="dark"] .shot{opacity:.92}
#themeBtn{display:inline-flex;align-items:center;gap:5px;font-size:12.5px;line-height:1;padding:6px 11px;border:1px solid var(--line2);background:var(--panel2);border-radius:8px;color:var(--ink2);cursor:pointer;font-family:inherit}
#themeBtn:hover{background:var(--hover);color:var(--ink);border-color:var(--ink3)}
#themeBtn .tico{font-size:17px;line-height:1}
/* ------------------------------- 页眉广告 -------------------------------- */
.banner{display:flex;align-items:center;justify-content:center;gap:10px;flex-wrap:wrap;padding:8px 20px;background:var(--accent-soft);color:var(--accent);border-bottom:1px solid var(--line);font-size:12.5px;line-height:1.6;text-align:center}
.banner a{color:inherit;font-weight:500;text-decoration:underline;text-underline-offset:2px;white-space:nowrap}
.banner a:hover{opacity:.8}
[data-theme="dark"] .banner{background:#18213a;color:#9dbcff;border-bottom-color:#243049}

/* --------------------- 顶部紧凑条（项目 + 阶段，一行） --------------------- */
.topbar{display:flex;align-items:center;gap:8px;padding:6px 10px;background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow);margin-bottom:10px;flex-wrap:wrap}
.topbar .tb-lbl{font-size:12px}
.topbar .projsel{width:auto;min-width:170px;max-width:280px;padding:4px 8px;font-size:12.5px;height:30px}
.steppills{display:flex;gap:2px;background:var(--hover);border-radius:9px;padding:3px}
.sp{display:inline-flex;align-items:center;gap:5px;padding:4px 11px;border:0;border-radius:7px;background:transparent;font-family:inherit;font-size:12.5px;color:var(--ink2);cursor:pointer;white-space:nowrap}
.sp:hover{background:var(--panel2);color:var(--ink)}
.sp.active{background:var(--panel);color:var(--accent);font-weight:500;box-shadow:0 1px 2px rgba(20,24,31,.08)}
.sp i{font-style:normal;font-size:10px;width:15px;height:15px;border-radius:50%;background:var(--line2);color:#fff;display:inline-flex;align-items:center;justify-content:center;flex:none}
.sp.active i{background:var(--accent)}
.sp .dot{width:6px;height:6px;border-radius:50%;background:var(--line2);flex:none}
.sp .dot.ok{background:var(--ok)}
@media(max-width:1080px){.tb-ver{display:none}}

/* 聊天区和正文区都跟着窗口长，别锁在半屏高 */
.chat{max-height:calc(100vh - 340px);min-height:260px}

/* ============ 四个工作页：一排操作 + 一条对话流 + 钉底输入条 ============
   用户的原话：「这个区域我觉得都是多的，直接一个对话框最好」。
   所以页面上不再有大 textarea、不再有说明文字，内容全在对话流里，
   攒下来的稿子收成一行（要改再展开）。 */
.workflow-scroll{min-height:0;overflow:auto;padding-right:2px}
textarea.manuscript{
  /* 展开编辑时才出现，随内容自动增高（高度由 fitManuscript 写成 px），自身不滚 */
  height:auto;min-height:120px;max-height:none;overflow:hidden;resize:none;
  margin:8px 0 14px;
}
/* 讨论消息直接铺开，不再套自己的滚动条。
   注意必须保持 flex 列布局：.bub 用 align-self 决定左右对齐，块级布局会失效 */
.workflow-scroll>.talkflow{
  display:flex;flex-direction:column;gap:10px;
  max-height:none;min-height:0;overflow:visible;margin-top:8px;padding:6px 2px 2px;
}
.workflow-scroll>.talkflow:empty{display:none}

/* 稿子条：默认一行，点开才是一个可编辑的框 */
.draftstrip{border:1px solid var(--line);border-radius:10px;background:var(--soft);padding:6px 8px 2px}
.draftstrip.open{padding-bottom:4px;border-color:var(--accent);box-shadow:0 0 0 2px var(--accent-soft)}
/* 「存进我的规划」之后闪一下：内容确实进来了，别让人以为点了没反应 */
.draftstrip.flash{animation:stripflash 1.3s ease-out}
@keyframes stripflash{
  0%{box-shadow:0 0 0 4px var(--accent);border-color:var(--accent)}
  60%{box-shadow:0 0 0 4px var(--accent-soft);border-color:var(--accent)}
  100%{box-shadow:0 0 0 2px transparent}
}
/* 稿子条那一行：名字 + 字数状态 + 按钮。
   整行不再是按钮 —— 展开编辑框只能点「修改」，不小心点到空白处不会抖出一堆文字 */
.dsrow{display:flex;align-items:center;gap:8px;padding:2px 0}
.dsname{font-size:13px;font-weight:600;white-space:nowrap}
.dsmeta{font-size:11.5px;color:var(--ink3);white-space:nowrap;margin-right:auto}
.dsrow .dsbtn{flex:none}
/* 必须用主题变量：写死 #fff 的话，深色主题下会变成白底 + 浅色字，整块糊成一片白，
   用户会以为"东西没删掉、还留了个白框" */
.draftstrip textarea.manuscript{margin:4px 0 0;background:var(--panel2);color:var(--ink)}

/* ===================== 存稿记事本（左栏卡片 + 弹窗） ===================== */
.notecard{padding:12px}
.notecard h2{font-size:12.5px;margin-bottom:8px;flex-wrap:wrap;gap:4px 8px}
.notecard h2 .hint{font-size:10.5px;line-height:1.5}
.notetip{font-size:11px;line-height:1.65;color:var(--ink3);margin-bottom:10px}
.notetip b{color:var(--ink2)}
.notelast{font-size:10.5px;color:var(--ink3);margin-top:8px;word-break:break-all}

/* 本机稿件镜像：只有桌面版才渲染这块，网页版用户看不到这些字 */
.localfoot{margin-top:10px;padding-top:10px;border-top:1px dashed var(--line);display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.localchk{display:flex;align-items:center;gap:5px;font-size:11px;color:var(--ink2);cursor:pointer;white-space:nowrap}
.localchk input{width:13px;height:13px;margin:0;accent-color:var(--accent)}
.locpath{flex:1 1 100%;font-size:10px;color:var(--ink3);word-break:break-all;line-height:1.5}
.localfoot .btn{padding:2px 8px;font-size:10.5px}

.notemask{
  position:fixed;inset:0;z-index:9998;display:none;align-items:center;justify-content:center;padding:24px;
  background:rgba(20,22,26,.45);
}
.npanel{
  width:100%;max-width:760px;max-height:88vh;display:flex;flex-direction:column;
  background:var(--panel);border:1px solid var(--line);border-radius:14px;
  box-shadow:0 18px 48px rgba(0,0,0,.24);padding:16px 18px;
}
/* 深色下 --panel(#1b1e24) 和 --bg(#14161a) 几乎同色，弹窗会糊在背景里 —— 把蒙版压深、
   边框提亮，才看得出这是一层浮起来的板子 */
[data-theme="dark"] .notemask{background:rgba(6,8,11,.7)}
[data-theme="dark"] .npanel{border-color:var(--line2);box-shadow:0 20px 54px rgba(0,0,0,.62)}
.nhead{display:flex;align-items:center;gap:10px}
.nhead b{font-size:14px}
.nhead .nmuted{font-size:11.5px;color:var(--ink3);flex:1;min-width:0}
.nhead .btn{margin-left:auto}
.ntabs{display:flex;gap:4px;background:var(--hover);border-radius:9px;padding:3px;margin:12px 0 10px;align-self:flex-start}
.ntab{border:0;background:transparent;font-family:inherit;font-size:12.5px;color:var(--ink2);padding:5px 14px;border-radius:7px;cursor:pointer}
.ntab:hover{color:var(--ink)}
.ntab.on{background:var(--panel);color:var(--accent);font-weight:500;box-shadow:0 1px 2px rgba(20,24,31,.08)}
.ntarget{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:10px;font-size:12px}
.ntarget .nmuted{font-size:11px;color:var(--ink3)}
.ntarget select{width:auto;min-width:190px;max-width:100%;padding:6px 9px;font-size:12.5px}
.nfld{display:flex;align-items:center;gap:6px;margin:0}
.nfld>span{font-size:11px;color:var(--ink2);white-space:nowrap}
.nfld input{width:74px;padding:5px 8px;font-size:12px}
.ntarget .nrel{font-size:11.5px;color:var(--ink2);background:var(--soft);border:1px solid var(--line);border-radius:6px;padding:2px 7px;word-break:break-all}
#noteText{
  flex:1;min-height:240px;resize:vertical;line-height:1.8;font-size:13px;
  font-family:"Source Han Serif SC","Songti SC",SimSun,Georgia,serif;
}
.nfoot{display:flex;align-items:center;gap:10px;margin-top:10px;flex-wrap:wrap}
.nfoot .nmuted{font-size:11.5px;color:var(--ink3)}
.nok{font-size:11.5px;color:var(--ok);min-width:0;word-break:break-all}
.nwarn{font-size:11.5px;color:var(--warn);min-width:0;word-break:break-all}
.nfoot .spacer{flex:1;min-width:8px}
@media(max-width:640px){.npanel{max-height:94vh;padding:12px}#noteText{min-height:160px}}

/* ===== 左栏「本阶段」操作卡：阶段标题 / 上游状态 / 补充要求 / 生成·停止·保存 =====
   这些原来铺在对话区顶部，占掉 180~220px 高。搬到这里以后，
   右栏只剩对话流 + 钉底输入条，聊天窗口几乎吃掉整屏。 */
.stagecard{padding:12px 12px 14px}
.stagecard h2{font-size:12.5px;margin-bottom:8px;flex-wrap:wrap;gap:4px 8px}
.stagecard h2 .hint{font-size:10.5px;line-height:1.5}
/* 上游状态：窄栏里横排 chip 会挤成一团，改成逐行贴着左边 */
.stagecard .upstream{flex-direction:column;align-items:stretch;gap:5px;margin-bottom:10px}
.stagecard .upstream .chip{justify-content:flex-start;white-space:normal;line-height:1.5;font-size:11px;padding:4px 8px;border-radius:7px}
/* 操作按钮组：主按钮独占一行，其余按钮平分下一行 */
.spops{display:flex;gap:6px;flex-wrap:wrap;margin-top:10px}
.spops .btn{flex:1 1 auto;text-align:center;padding:7px 10px}
.spops .spgen{flex:1 1 100%}
.spops .sbspacer{flex:1;min-width:8px}
/* ghost 按钮在左栏只剩一行灰字，看不出能点 —— 补一层浅底浅框 */
.stagecard .spops .btn.ghost{border-color:var(--line);background:var(--panel2);color:var(--ink2)}
.stagecard .spops .btn.ghost:hover{background:var(--hover);border-color:var(--line2);color:var(--ink)}
/* 左栏收起后塞回右栏的横排紧凑版 */
.spops.horiz{flex-wrap:wrap;align-items:center;margin:0 0 10px}
.spops.horiz .btn,.spops.horiz .spgen{flex:0 0 auto}
/* 走廊的集数范围：两个窄输入并排 */
.stagecard .sbnum{flex:1 1 45%;margin:0;min-width:0}
.stagecard .sbnum>span{font-size:10.5px;margin-bottom:3px}
/* 正文页的「第几集」：一行放得下，不要占满整栏像个大文本框 */
.stagecard .epno{flex:1 1 100%;margin:0;display:flex;align-items:center;gap:8px}
.stagecard .epno>span{font-size:10.5px;margin:0;white-space:nowrap;color:var(--ink3)}
.stagecard .epno input{width:88px}
.stagecard .sbnum input{padding:5px 8px;font-size:12px}
.stagecard .chk{flex:1 1 100%;font-size:11.5px;margin:0}
/* 实时心跳条在窄栏里要整行，否则被 max-width 截断成半截数字 */
.stagecard .livebar{max-width:none;margin-top:8px;white-space:normal}
/* 「AI 参考」那一行：把黑箱打开 —— 用户得看得见"稿子只写到第 4 集"，
   才知道为什么下一轮从第 7 集开始。窄栏里靠换行排，别硬挤一行 */
.ctxline{margin:0 0 10px;font-size:10.5px;line-height:1.9;color:var(--ink3)}
.ctxline>span{color:var(--ink3);margin-right:4px}
.ctxline b{font-weight:500;color:var(--ink2);background:var(--soft);border:1px solid var(--line);border-radius:5px;padding:1px 5px;white-space:nowrap}
.ctxline i{font-style:normal;color:var(--line2);margin:0 3px}
/* 起止集与稿子实际进度对不上：这次"从第 7 集开始"的直接肇事者。
   用 warn 色是因为它不是提示，是"再点生成就要出错"的警告 */
.epgap{margin-top:8px;font-size:11px;line-height:1.7;color:var(--warn);background:var(--warn-soft);border:1px solid var(--warn);border-radius:8px;padding:7px 9px}
.epgap b{font-weight:600}
.epgap .btn{margin-top:7px;width:100%;font-size:11.5px;padding:5px 8px;color:var(--ink);background:var(--panel);border-color:var(--line2);flex:none}
.epgap .btn:hover{border-color:var(--ink3)}
/* 补充要求框在窄栏里内外边距都收一点，不然输入框只剩一百多像素 */
.stagecard details.instr{margin-bottom:8px;padding:0 10px}
.stagecard details.instr>summary{font-size:11.5px;padding:7px 0}
.stagecard details.instr textarea{font-size:12px;padding:6px 8px}

/* 右栏：顶部不再有固定元素，滚动区直接从稿子条开始，上边距收薄一点 */
.workcard{padding:12px}

/* 旧的顶部操作行（保留类名，其他页面还在用） */
.stagebar{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin:10px 0 12px}
.stagebar .sbspacer{flex:1;min-width:8px}
.stagebar .field{margin:0;flex:0 0 96px}
.stagebar .field span{font-size:11px}
.stagebar .field input{padding:6px 8px}
.stagebar .chk{font-size:12px;margin:0}

/* 钉在卡片底部的输入条：一行「输入框 + 发送 + 停止」，别竖着堆按钮占地儿 */
.workcomposer{display:flex;gap:8px;align-items:flex-end;margin-top:10px;padding-top:10px;border-top:1px solid var(--line)}
.workcomposer textarea{flex:1;resize:none;line-height:1.6;max-height:120px}
.wcside{display:flex;gap:6px;flex:none;align-items:center}
.wcside .btn{white-space:nowrap}
.wcops{display:flex;gap:8px;align-items:center;margin-top:6px;flex-wrap:wrap;min-height:24px}
/* 以前这里还有 .eyeline —— 输入框上方那句「AI 只看得见最后 1.2 万字」。
   2026-11-04 那句话下线了（改成服务端按模型窗口算，装得下就全带），
   样式一起删掉，别留个没人用的类在这儿等人接回去。 */

/* 保存按钮上的「未保存」角标：不靠 3 秒就消失的 toast 提醒用户 */
.dotdirty{
  display:inline-block;margin-left:6px;padding:0 6px;border-radius:8px;
  font-size:10.5px;font-weight:600;font-style:normal;line-height:16px;
  background:#c0392b;color:#fff;vertical-align:1px;
}
[data-theme="dark"] .dotdirty{background:#e05c4b;color:#1a1d22}

/* 框选 AI 回复后弹出的浮动标签 */
.selbar{
  position:fixed;z-index:60;display:flex;gap:2px;padding:4px;
  background:#1b1e23;border-radius:9px;box-shadow:0 6px 22px rgba(20,24,31,.28);
  animation:selin .12s ease-out;
}
.selbar button{
  border:0;background:transparent;color:#fff;font-family:inherit;font-size:12px;
  padding:6px 10px;border-radius:6px;cursor:pointer;white-space:nowrap;
}
.selbar button:hover{background:rgba(255,255,255,.16)}
.selbar button[data-sel="append"]{background:var(--accent)}
.selbar button[data-sel="append"]:hover{filter:brightness(1.1)}
@keyframes selin{from{opacity:0;transform:translateY(3px)}to{opacity:1;transform:none}}

/* 右侧工作卡撑满窗口剩余高度，聊天区和正文区吃掉全部空间，不再留白 */
.grid2.desk>div:last-child>.card{display:flex;flex-direction:column;min-height:calc(100vh - 250px)}
.grid2.desk>div:last-child>.card>*{flex:0 0 auto}
.grid2.desk>div:last-child>.card>.chat,
.grid2.desk>div:last-child>.card>textarea.manuscript{flex:1 1 auto;min-height:200px;max-height:none}

/* 关键：工作卡高度「固定」成视口剩余，不再用 min-height。
   之前用 min-height 时，卡片里的固定元素（标题/补充要求/按钮）一多就把卡片撑高，
   整个页面跟着出现滚动条。现在改成固定高 + 内部滚动，页面永远不滚。 */
.grid2.desk>div:last-child>.card{
  display:flex;flex-direction:column;
  height:calc(100vh - 268px - var(--bh));
  min-height:320px;
  overflow:hidden;
}
.grid2.desk>div:last-child>.card>.chat,
.grid2.desk>div:last-child>.card>textarea.manuscript,
.grid2.desk>div:last-child>.card>.workflow-scroll{
  flex:1 1 auto;min-height:0;max-height:none;overflow:auto;
}
.grid2.desk>div:last-child>.card>.chat{min-height:120px}
/* 左列（装配栏）也钉死高度，内容多了在自己里面滚，别把整页拉长 */
.grid2.desk>div:first-child{height:calc(100vh - 268px - var(--bh));overflow:auto;padding-right:2px}
.grid2.desk>div:first-child>.card{margin-bottom:0}
/* 阶段操作卡钉在左栏顶部：往下翻模组列表时，「生成 / 保存」永远够得着，
   不用滚回顶上找按钮。底色必须不透明，否则下面的卡片会透上来。 */
.grid2.desk>div:first-child>.card.stagecard{
  position:sticky;top:0;z-index:3;margin-bottom:12px;background:var(--panel);
}
@media(max-height:700px){
  .grid2.desk>div:first-child{height:auto;overflow:visible}
  .grid2.desk>div:last-child>.card{height:auto;min-height:0}
}

/* 「补充要求 / 本集要求」默认收起：plan 和正文阶段头部固定元素一多，
   小窗口里正文区就被挤没了。收起来能省出约 90px */
details.instr{margin-bottom:10px;border:1px solid var(--line);border-radius:8px;background:var(--panel2);padding:0 12px}
details.instr[open]{padding-bottom:10px}
details.instr>summary{cursor:pointer;font-size:12px;color:var(--ink2);padding:8px 0;list-style:none;user-select:none}
details.instr>summary::-webkit-details-marker{display:none}
details.instr>summary::before{content:'▸';display:inline-block;width:14px;color:var(--ink3);transition:transform .15s}
details.instr[open]>summary::before{content:'▾'}
details.instr>summary:hover{color:var(--ink)}
details.instr textarea{margin-top:2px}
/* 窗口真的很矮（<620）才允许整页滚动，别在正常尺寸下也让页面滚 */
body.hasbanner{--bh:38px}

@media(max-height:620px){
  .grid2.desk>div:first-child{height:auto;overflow:visible}
  .grid2.desk>div:last-child>.card{height:auto;min-height:0}
}

/* ------------------------- 标签栏移进顶栏 + 创作台撑满 ------------------------- */
.navtabs{display:flex;gap:2px;margin-left:10px}
.navtabs button{padding:5px 12px;border:0;border-radius:7px;background:transparent;font-family:inherit;font-size:12.5px;color:var(--ink2);cursor:pointer;white-space:nowrap}
.navtabs button:hover{background:var(--hover);color:var(--ink)}
.navtabs button.active{background:var(--accent-soft);color:var(--accent);font-weight:500}

/* 创作台：整页锁死一屏，主区用 flex 分配，不再靠算常数 */
body.desk-mode{height:100vh;overflow:hidden;display:flex;flex-direction:column}
body.desk-mode>header,body.desk-mode>#banner{flex:none}
body.desk-mode>main{flex:1;min-height:0;overflow:hidden;display:flex;flex-direction:column;padding:10px 22px 14px;margin:0;width:100%}
body.desk-mode>main>*{flex:0 0 auto}
body.desk-mode .grid2.desk{flex:1;min-height:0}
body.desk-mode .grid2.desk>div{min-height:0}
body.desk-mode .grid2.desk>div:first-child{height:100%;overflow:auto}
body.desk-mode .grid2.desk>div:last-child{height:100%}
body.desk-mode .grid2.desk>div:last-child>.card{height:100%;min-height:0;margin-bottom:0;display:flex;flex-direction:column;overflow:hidden}
@media(max-width:1200px){.navtabs button{padding:5px 8px;font-size:12px}}
@media(max-width:1000px){#verPill{display:none}}

/* 模型思考过程：小字灰色、可折叠，不抢正文的注意力 */
.thinkb{margin-bottom:9px;border-left:2px solid var(--line2);padding:1px 0 1px 10px}
.thinkb>summary{cursor:pointer;font-size:11.5px;color:var(--ink3);list-style:none;user-select:none}
.thinkb>summary::-webkit-details-marker{display:none}
.thinkb>summary::before{content:'▸';display:inline-block;width:12px;color:var(--ink3)}
.thinkb[open]>summary::before{content:'▾'}
.thinkb>summary:hover{color:var(--ink2)}
.thinkc{font-size:11.5px;line-height:1.8;color:var(--ink3);white-space:pre-wrap;word-break:break-word;max-height:240px;overflow:auto;margin-top:6px;padding-right:6px}
/* 还在想的时候：竖线换成强调色 + 标题后面一个呼吸点。
   目的是让"AI 活着、正在跑"这件事在屏幕上一眼可见 —— 2026-11-04 用户截图里
   生成时整片空白，他以为卡死了。正文一到就撤掉 .live。 */
.thinkb.live{border-left-color:var(--accent)}
.thinkb.live>summary{color:var(--ink2)}
.thinkb.live>summary::after{
  content:'';display:inline-block;width:5px;height:5px;margin-left:6px;border-radius:50%;
  background:var(--accent);vertical-align:middle;animation:wfthink 1.1s ease-in-out infinite;
}
@keyframes wfthink{0%,100%{opacity:.2;transform:scale(.8)}50%{opacity:1;transform:scale(1)}}

/* 「挑选保存」的列表项：一行一条，点一下就存 */
.pickitem{display:flex;align-items:center;gap:10px;padding:9px 12px;border:1px solid var(--line);border-radius:9px;background:var(--panel2);cursor:pointer;font-family:inherit;font-size:12.5px;color:var(--ink);text-align:left;width:100%}
.pickitem:hover{border-color:var(--accent);background:var(--accent-soft)}
.pickl{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.picks{font-size:11px;color:var(--ink3);white-space:nowrap;flex:none}

/* 规划阶段的讨论区：默认收起，聊过就自动展开 */
.talkbox{margin-top:14px;border:1px solid var(--line);border-radius:10px;background:var(--panel2);padding:0 12px}
.talkbox[open]{padding-bottom:12px}
.talkbox>summary{cursor:pointer;font-size:12px;color:var(--ink2);padding:10px 0;list-style:none;user-select:none}
.talkbox>summary::-webkit-details-marker{display:none}
.talkbox>summary::before{content:'▸';display:inline-block;width:14px;color:var(--ink3)}
.talkbox[open]>summary::before{content:'▾'}
.talkbox>summary:hover{color:var(--ink)}
.talkbox .chat{max-height:280px;margin-top:4px;padding:2px}
.talkbox .composer{margin-top:10px}

/* ======================= AI 实时运行状态条（防发呆） ======================= */
/* 钉在「生成 / 停止」按钮右边的细胶囊：绿=在吐字，黄=上游在想，红=久无响应 */
.livebar{display:none;align-items:center;gap:7px;padding:4px 11px;border:1px solid var(--line);
  border-radius:999px;background:var(--panel2);font-size:11px;line-height:1.5;white-space:nowrap;
  max-width:340px;overflow:hidden}
.livebar.on{display:inline-flex}
.livedot{width:8px;height:8px;border-radius:50%;flex:none}
.livedot.g{background:#22c55e;animation:lv-g 1.6s ease-out infinite}
.livedot.y{background:#f59e0b;animation:lv-y 1.3s ease-out infinite}
.livedot.r{background:#ef4444;animation:lv-r .85s ease-out infinite}
@keyframes lv-g{0%{box-shadow:0 0 0 0 rgba(34,197,94,.55)}70%{box-shadow:0 0 0 7px rgba(34,197,94,0)}100%{box-shadow:0 0 0 0 rgba(34,197,94,0)}}
@keyframes lv-y{0%{box-shadow:0 0 0 0 rgba(245,158,11,.5)}70%{box-shadow:0 0 0 6px rgba(245,158,11,0)}100%{box-shadow:0 0 0 0 rgba(245,158,11,0)}}
@keyframes lv-r{0%{box-shadow:0 0 0 0 rgba(239,68,68,.6)}70%{box-shadow:0 0 0 8px rgba(239,68,68,0)}100%{box-shadow:0 0 0 0 rgba(239,68,68,0)}}
.livelbl{font-weight:600;color:var(--ink)}
.livemeta{color:var(--ink3);font-variant-numeric:tabular-nums;overflow:hidden;text-overflow:ellipsis}
[data-theme="dark"] .livebar{background:rgba(255,255,255,.04)}
/* 点子页的聊天区下面：状态条靠右，没有运行时高度为 0，不占地方 */
.liveRow{display:flex;justify-content:flex-end;line-height:0}
.liveRow .livebar.on{line-height:1.5;margin-bottom:8px}

/* ============================== AI 模型看板 ============================== */
.mstat{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin-bottom:14px}
.mstat>div{position:relative;overflow:hidden;background:var(--panel2);border:1px solid var(--line);
  border-radius:10px;padding:12px 14px;display:flex;flex-direction:column;gap:2px}
.mstat>div::after{content:'';position:absolute;left:0;top:0;right:0;height:2px;
  background:linear-gradient(90deg,transparent,var(--accent),transparent);opacity:.5}
.mstat b{font-size:20px;font-weight:650;letter-spacing:-.4px;color:var(--ink);font-variant-numeric:tabular-nums}
.mstat span{font-size:11px;color:var(--ink3)}
.mstat>div.bad b{color:var(--danger)}

.strow{display:flex;flex-wrap:wrap;gap:8px}
.stchip{display:flex;align-items:center;gap:7px;padding:6px 11px;border-radius:8px;
  border:1px solid var(--line);background:var(--panel2);font-size:11px}
.stchip b{font-weight:600;color:var(--ink2)}
.stchip span{color:var(--ink3);font-family:ui-monospace,Consolas,monospace}
.stchip.ok{border-color:rgba(34,197,94,.35);background:rgba(34,197,94,.07)}
.stchip.ok span{color:var(--ok)}
.stchip.bad{border-color:rgba(239,68,68,.35);background:rgba(239,68,68,.07)}
.stchip.bad span{color:var(--danger)}

.mgrid2{display:grid;grid-template-columns:repeat(auto-fill,minmax(292px,1fr));gap:12px}
.mcard{position:relative;overflow:hidden;border:1px solid var(--line2);border-radius:12px;
  background:var(--panel);padding:13px 14px 11px;transition:border-color .18s,box-shadow .18s,transform .18s}
.mcard::before{content:'';position:absolute;left:0;top:0;right:0;height:2px;
  background:linear-gradient(90deg,#2f5fe0,#7c3aed,#06b6d4);opacity:.7}
.mcard.on:hover{border-color:var(--accent);box-shadow:0 6px 22px rgba(47,95,224,.14);transform:translateY(-1px)}
.mcard.off{opacity:.6}
.mcard-hd{display:flex;align-items:center;gap:8px;margin-bottom:5px}
.mname{flex:1;font-size:13px;font-weight:600;color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mstate{flex:none;font-size:10px;padding:2px 7px;border-radius:20px;border:1px solid var(--line2);color:var(--ink3)}
.mstate.g{color:var(--ok);border-color:rgba(34,197,94,.4);background:rgba(34,197,94,.08)}
.mstate.r{color:var(--danger);border-color:rgba(239,68,68,.4);background:rgba(239,68,68,.08)}
.mled{flex:none;width:9px;height:9px;border-radius:50%;background:var(--line2)}
.mled.g{background:#22c55e;box-shadow:0 0 0 3px rgba(34,197,94,.16),0 0 10px rgba(34,197,94,.7);animation:lv-g 2s ease-out infinite}
.mled.r{background:#ef4444;box-shadow:0 0 0 3px rgba(239,68,68,.16),0 0 10px rgba(239,68,68,.7);animation:lv-r 1.2s ease-out infinite}
.mled.idle{background:#3b82f6;box-shadow:0 0 0 3px rgba(59,130,246,.14)}
.mled.off{background:#9aa3af}
.mprov{font-size:11px;color:var(--ink3);margin-bottom:8px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mcost{font-size:10px;color:var(--ink3);margin:-5px 0 8px;font-variant-numeric:tabular-nums;opacity:.85}
.mbound{display:flex;flex-wrap:wrap;align-items:center;gap:5px;margin-bottom:10px;min-height:20px}
.mbound i{font-style:normal;font-size:10px;padding:2px 7px;border-radius:5px;
  background:var(--accent-soft);color:var(--accent);border:1px solid rgba(47,95,224,.18)}
.mbound .dim{font-size:10px;color:var(--ink3)}
.mgrid{display:grid;grid-template-columns:1fr 1fr;gap:7px 10px;padding:9px 0;
  border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.mgrid>div{display:flex;flex-direction:column;gap:1px;min-width:0}
.mgrid b{font-size:10px;font-weight:400;color:var(--ink3)}
.mgrid span{font-size:11px;color:var(--ink2);font-variant-numeric:tabular-nums;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mfoot{display:flex;align-items:center;justify-content:space-between;gap:8px;padding-top:8px}
.mwhen{font-size:10px;color:var(--ink3)}
.mres{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:11px}
.mres:not(:empty){margin-top:8px}
.mtag{font-size:10px;padding:2px 7px;border-radius:5px;border:1px solid var(--line2);color:var(--ink2)}
.mtag.ok{color:var(--ok);border-color:rgba(34,197,94,.4);background:rgba(34,197,94,.08)}
.mtag.bad{color:var(--danger);border-color:rgba(239,68,68,.4);background:rgba(239,68,68,.08)}
@media(max-width:720px){.mstat{grid-template-columns:repeat(2,1fr)}}
[data-theme="dark"] .mcard{background:linear-gradient(160deg,rgba(255,255,255,.05),rgba(255,255,255,.012))}
[data-theme="dark"] .mcard::before{opacity:.95}

/* 历史对话孤儿提示条：本地还有旧项目的对话时的补救入口 */
.straybar{
  position:fixed;left:50%;top:14px;transform:translateX(-50%);z-index:9000;
  display:flex;align-items:center;gap:10px;flex-wrap:wrap;max-width:min(880px,92vw);
  background:var(--panel);border:1px solid var(--line2);border-radius:10px;
  padding:10px 14px;font-size:12.5px;color:var(--ink2);
  box-shadow:0 10px 30px rgba(0,0,0,.18);
}
.straybar b{color:var(--ink)}

/* 对话空白时的状态块：带地址与本机缓存诊断 */
.chatempty{padding:26px 20px;color:var(--ink3);font-size:13px;line-height:1.95;max-width:640px}
.chatempty .ce-t{font-size:14px;color:var(--ink2);margin-bottom:5px}
.chatempty .ce-s{font-size:12.5px}
.chatempty .ce-d{margin-top:12px;font-size:11.5px}
.chatempty .ce-w{margin-top:8px;font-size:11.5px;line-height:1.85}
.chatempty code{font-family:ui-monospace,Consolas,monospace;background:rgba(127,127,127,.13);padding:1px 5px;border-radius:4px;font-size:11px}
.chatempty b{color:var(--ink2)}

/* ---------- 风控警示：必须点确认的模态框（不用 toast） ---------- */
.viomask{position:fixed;inset:0;background:rgba(20,24,31,.46);display:flex;align-items:center;justify-content:center;padding:24px;z-index:9999}
.viopanel{width:100%;max-width:540px;background:var(--panel);border:1px solid var(--line2);border-top:3px solid var(--warn);border-radius:14px;box-shadow:0 24px 60px rgba(0,0,0,.28);padding:22px 24px 18px}
.viopanel.danger{border-top-color:var(--danger)}
.viohead{display:flex;align-items:center;gap:10px;margin-bottom:14px}
.vioicon{flex:none;width:22px;height:22px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:13px;font-weight:700;background:var(--warn-soft);color:var(--warn);border:1px solid #eccf9f}
.viopanel.danger .vioicon{background:var(--danger-soft);color:var(--danger);border-color:#efc2bd}
.viotitle{font-size:15px;font-weight:600;color:var(--ink)}
.viobody{font-size:13px;line-height:1.78;color:var(--ink2)}
.viobody p{margin:0 0 9px}
.viobody p:last-child{margin-bottom:0}
.viobody b{color:var(--ink);font-weight:600}
.viofoot{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:18px;padding-top:14px;border-top:1px solid var(--line)}
.viometa{font-size:11px;color:var(--ink3)}
.viook{padding:8px 16px;border:0;border-radius:8px;background:var(--ink);color:#fff;font-size:13px;cursor:pointer}
.viopanel.danger .viook{background:var(--danger)}
.viook:hover{opacity:.88}

/* 风控：冻结中 / 已停用 / 待评定的账号整行标红，后台一眼就能看见该重点盯谁 */
tr.riskhot td{background:var(--danger-soft)}
tr.riskhot td:first-child{box-shadow:inset 3px 0 0 var(--danger);font-weight:600}

/* 阶段技能标记：本阶段唯一的模组不能移除，得让它一眼看出来是"必需"而不是"已勾选" */
.skilltag{font-size:10px;margin-left:6px;padding:1px 5px;border-radius:4px;background:var(--accent-soft);color:var(--accent);white-space:nowrap;font-weight:400}

/* 前情卡 */
.cbar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:14px}
.clist{display:flex;flex-direction:column;gap:10px}
.ccard{border:1px solid var(--line);border-radius:10px;background:var(--panel2);padding:11px 13px}
.chead{display:flex;align-items:center;gap:10px;margin-bottom:8px}
.chead .grow{flex:1}
.cep{font-size:12.5px;font-weight:600;color:var(--ink)}
.cbody{font-size:12.5px;line-height:1.75;color:var(--ink2);white-space:pre-wrap}
.ctext{font-size:12.5px;line-height:1.75;background:var(--panel)}

/* ---------------------- 重复副本提示（我的稿子 · 文件面板） ---------------------- */
/* 颜色全走变量：这条提示在深色主题下曾经是最容易被写死成浅色的一处 */
.dupwarn{border:1px solid var(--warn);background:var(--warn-soft);border-radius:9px;padding:10px 12px;margin-bottom:12px}
.duphead{font-size:12.5px;font-weight:500;color:var(--warn);margin-bottom:8px}
.duphead .muted{font-weight:400;color:var(--ink2)}
.duprow{display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding:6px 0;border-top:1px solid var(--line2);font-size:11.5px}
.duprow .mono{color:var(--ink);flex-shrink:0}
.duprow .muted{margin-right:auto;line-height:1.6}
.duptip{font-size:11px;color:var(--ink3);line-height:1.7;margin-top:8px}

/* ------------------------- 右上角「客户端有新版本」徽标 ------------------------- */
/* 只在 Electron 壳里出现（浏览器没有 WF_UPD），所以别给它做兜底显示 */
.updbadge{display:inline-flex;align-items:center;gap:6px;font-size:11.5px;line-height:1;
  padding:6px 11px;border-radius:20px;cursor:pointer;white-space:nowrap;
  border:1px solid var(--warn);background:var(--warn-soft);color:var(--warn);
  font-family:inherit;transition:filter .15s}
.updbadge:hover{filter:brightness(.97)}
/* 闪烁的小圆点：提醒"这件事还没完"，但幅度要小，别在正文旁边晃眼睛 */
.updbadge .udot{width:6px;height:6px;border-radius:50%;background:currentColor;flex:none;
  animation:updpulse 1.8s ease-in-out infinite}
@keyframes updpulse{0%,100%{opacity:1}50%{opacity:.35}}
/* 下载中 / 已下好：从"提醒"转成"可以动手了"，用主色把它推进一步 */
.updbadge[data-phase="downloaded"]{border-color:var(--accent);background:var(--accent-soft);color:var(--accent)}
.updbadge[data-phase="downloading"]{border-color:var(--line2);background:var(--panel2);color:var(--ink2)}
.updbadge[data-phase="downloading"] .udot{animation:none;opacity:.6}
.updbadge[data-phase="error"]{border-color:var(--danger);background:var(--danger-soft);color:var(--danger)}
/* 硬性更新：这一版不更能出事，所以让它比普通更新更"重"—— 实心主色，不像提示，像个按钮 */
.updbadge[data-forced="1"]{border-color:var(--accent);background:var(--accent);color:#fff}
.updbadge[data-forced="1"]:hover{filter:brightness(1.06)}
.updbadge[data-forced="1"] .udot{background:#fff}

/* ------------- 老客户端兜底条（壳版本低于服务器要求的 minVersion） ------------- */
/* 只给"自己的更新器已经坏掉"的老壳看：一条挂在页面最上面，把安装包地址直接端出来。
   新壳不会看到它 —— 人家右上角有「更新就绪」。 */
.oldcli{position:fixed;top:0;left:0;right:0;z-index:120;display:flex;align-items:center;gap:10px;
  padding:0 14px;height:40px;font-size:12.5px;line-height:1.4;
  background:var(--danger);color:#fff;box-shadow:0 2px 10px rgba(0,0,0,.18);
  -webkit-app-region:no-drag}
.oldcli b{font-weight:600;flex:none}
.oldcli span{opacity:.92;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.oldcli-go{margin-left:auto;flex:none;text-decoration:none;color:#fff;font-weight:600;
  border:1px solid rgba(255,255,255,.7);border-radius:6px;padding:5px 12px;font-size:12px;
  background:rgba(255,255,255,.14)}
.oldcli-go:hover{background:rgba(255,255,255,.26)}
.oldcli-x{flex:none;background:none;border:0;color:rgba(255,255,255,.75);font-size:12px;
  cursor:pointer;padding:4px 6px;font-family:inherit}
.oldcli-x:hover{color:#fff}
/* 把页面整体往下推，别让这条盖住标题栏（标题栏就是 header，也是拖拽区） */
body.has-oldcli{padding-top:40px}
body.has-oldcli header{top:40px}
/* 壳里这条会横在窗口最上面，右上角 152px 必须让出来 ——
   那是系统画的最小化/最大化/关闭，盖住就点不到了 */
body.inshell .oldcli{padding-right:152px}
.updmsg{position:fixed;bottom:22px;left:50%;transform:translateX(-50%);z-index:95;
  background:var(--danger-soft);color:var(--danger);border:1px solid var(--danger);
  font-size:12px;padding:9px 14px;border-radius:8px;max-width:70vw}

/* ============================================================================
   材质层（2026-10-31，分镜台试点通过后铺全站）

   这一段只管"看起来贵不贵"，不改任何布局尺寸。五条：
     ① 卡片上沿一道 1px 亮线（光从上方来）
     ② 下拉箭头自绘（系统灰三角太出戏）
     ③ 滚动条统一（深色面板里挂一条系统浅灰滚动条，前面全白做）
     ④ 内嵌面 --sunken（输入框 / 剧本框 / 槽位）
     ⑤ 数字等宽（上面 body 那条已经全局继承）

   放在 style.css 末尾：board.css / canvas.css 在这之后加载，
   分镜台和画布要覆盖其中任何一条，天然优先，不用 !important。
   ============================================================================ */

/* ① 卡片亮线：两端各收 16px、往右衰减，像灯打在板子上沿 */
.card{position:relative}
.card:before{
  content:"";position:absolute;left:16px;right:16px;top:0;height:1px;border-radius:1px;
  pointer-events:none;background:var(--topline);
}

/* ② 下拉箭头。padding-right 是给箭头让位，不给的话长选项会压到箭头上 */
select{
  -webkit-appearance:none;appearance:none;
  background-image:var(--chev);background-repeat:no-repeat;background-position:right 9px center;
  padding-right:26px;
}

/* ③ 滚动条：细、半透明、贴底色。10px 宽 + 3px 透明边 = 视觉上 4px 一根 */
::-webkit-scrollbar{width:10px;height:10px}
::-webkit-scrollbar-track{background:transparent}
::-webkit-scrollbar-thumb{background:var(--sb);border:3px solid transparent;background-clip:padding-box;border-radius:8px}
::-webkit-scrollbar-thumb:hover{background:var(--accent-line);background-clip:padding-box}
::-webkit-scrollbar-corner{background:transparent}

/* ④ 通用输入框：凹下去一格。卡在 --panel2 上分不出"这里能打字"，所以用 --sunken */
input,select,textarea{background-color:var(--sunken)}
input:focus,select:focus,textarea:focus{background-color:var(--panel)}

/* ============================================================================
   客户端：标题栏 / 身份牌 / ☰ 应用菜单（2026-10-31）

   只有真壳里才有 body.inshell —— ui.js 检测到 preload 的 WF_SHELL 才加上。
   浏览器里不会出现下面任何一种样式。

   背景：壳那边改成 titleBarStyle:'hidden' + titleBarOverlay，
   窗口标题栏不再由 Windows 画。于是 header 本身就成了标题栏：
   它能拖、它右边要给原生的最小化/最大化/关闭让出位置。
   ============================================================================ */
body.inshell header{
  -webkit-app-region:drag;          /* 按住空白处拖窗口 */
  /* 壳里显式设了 52，这里用 max() 兜住 —— env() 万一取到 0，顶栏就塌没了 */
  height:max(52px, env(titlebar-area-height, 52px));
  /* 原生三个按钮的宽度约 138px；少给一点就会被压在按钮底下点不到 */
  padding-right:148px;
}
/* 所有可点的东西退出拖拽区，否则按钮点不动（拖拽区会吞掉 mousedown） */
body.inshell header button,
body.inshell header a,
body.inshell header select,
body.inshell header input,
body.inshell header textarea{-webkit-app-region:no-drag}

/* 身份牌：本地母版 / 管理端。标题栏一藏，这是唯一能看出"我在哪一端"的地方 */
.shellid{color:var(--ink3);border-color:var(--line2);background:var(--panel2);font-size:10.5px;font-weight:500;letter-spacing:.08em;flex:none}
/* 2026-11-01 两个「管理端」入口合并：壳里的身份牌（.shellid.aside）和浏览器里的
   #adminBtn（.adminpill）长得一模一样 —— 同一个胶囊、同一个颜色，点了都去 /admin.html。
   字体大小取 11.5px 取中间值：身份牌原来 10.5、按钮原来 13，合成一个就得一致。 */
.adminpill,.shellid.aside{font-size:11.5px;font-weight:600;letter-spacing:.02em;padding:5px 11px;
  border-radius:20px;display:inline-flex;align-items:center;gap:4px;text-decoration:none;
  color:var(--accent);background:var(--accent-soft);border:1px solid var(--accent-line);cursor:pointer;
  transition:filter .14s ease,box-shadow .16s ease;white-space:nowrap}
.adminpill:hover,.shellid.aside:hover{filter:brightness(.97);box-shadow:0 2px 8px rgba(20,24,31,.1);color:var(--accent)}

/* ☰：和旁边那些 ghost 按钮一个高度，不抢戏 */
.shellmenu{display:inline-flex;align-items:center;justify-content:center;width:32px;height:28px;padding:0;flex:none;
  background:var(--panel2);border:1px solid var(--line2);border-radius:8px;color:var(--ink2);
  font-family:inherit;font-size:14px;line-height:1;cursor:pointer;transition:background .14s,border-color .14s,color .14s}
.shellmenu:hover{background:var(--hover);color:var(--ink);border-color:var(--line2)}
.shellmenu:active{background:var(--accent-soft);color:var(--accent)}

/* 下拉：面板本身也必须是 no-drag，不然点菜单项会被当成拖窗口 */
.shellpop{position:fixed;z-index:200;width:272px;padding:6px;overflow:hidden;
  background:var(--panel);border:1px solid var(--line2);border-radius:12px;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.06),0 22px 48px rgba(0,0,0,.30);
  -webkit-app-region:no-drag;animation:shellpop-in .11s ease-out}
@keyframes shellpop-in{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}
.spbody{display:flex;flex-direction:column}
.spg + .spg{margin-top:5px;padding-top:5px;border-top:1px solid var(--line)}
/* 组标题用微标签：小字号 + 大字距，跟页面里其他分类标题一个语汇 */
.sph{font-size:10px;font-weight:500;letter-spacing:.14em;color:var(--ink3);padding:5px 9px 4px}
.spi{display:flex;align-items:center;gap:8px;width:100%;padding:7px 9px;border:0;border-radius:7px;
  background:transparent;font-family:inherit;font-size:12.5px;color:var(--ink);text-align:left;cursor:pointer}
.spi:hover{background:var(--hover)}
.spi.busy{opacity:.55}
.spi.off{opacity:.38;cursor:default}
.spi.off:hover{background:transparent}
.spck{width:12px;flex:none;color:var(--accent);font-size:11px;line-height:1}
.spl{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.spa{flex:none;font-size:10.5px;color:var(--ink3);letter-spacing:.04em}
.spsep{height:1px;background:var(--line);margin:5px 9px}
/* 开关项左边那个小方框：只有"带 checked 的菜单项"才有 */
.spck.box{width:13px;height:13px;border-radius:4px;border:1px solid var(--line2);
  display:inline-flex;align-items:center;justify-content:center;font-size:9px;line-height:1}
.spck.box.on{background:var(--accent-soft);border-color:var(--accent-line);color:var(--accent)}

/* ------------------------------- 顶栏登录 ------------------------------- */
/* 没登录时右上角那枚按钮 + 点开的登录框（2026-11-01）。颜色全走变量，别写死。 */
/* 2026-11-01 二次改：登录 / 注册拆成两页，顶上两个 tab 切，不再是同页两个按钮。 */
.logincard{background:var(--panel);border-radius:14px;width:100%;max-width:380px;
  padding:18px 20px 16px;box-shadow:0 18px 48px rgba(0,0,0,.22)}
.lghead{display:flex;align-items:center;gap:10px}
.lgtabs{display:flex;gap:4px;background:var(--soft);border:1px solid var(--line);
  border-radius:10px;padding:3px;margin-right:auto;width:max-content}
.lgtab{border:0;background:transparent;color:var(--ink2);font-family:inherit;font-size:12.5px;
  padding:6px 16px;border-radius:8px;cursor:pointer;transition:background .14s ease,color .14s ease}
.lgtab:hover{color:var(--ink)}
.lgtab.on{background:var(--panel);color:var(--ink);font-weight:600;box-shadow:0 1px 3px rgba(20,24,31,.1)}
.lgx{border:0;background:transparent;color:var(--ink3);font-size:18px;line-height:1;
  width:28px;height:28px;border-radius:8px;cursor:pointer}
.lgx:hover{background:var(--hover);color:var(--ink)}
.lgsub{font-size:12px;color:var(--ink3);line-height:1.7;margin:12px 0 14px}
.lgfield{display:block;margin-bottom:10px}
.lgfield span{display:block;font-size:11.5px;color:var(--ink2);margin-bottom:5px}
.lgerr{font-size:11.5px;color:var(--danger);line-height:1.6;min-height:17px;margin:2px 0 6px}
.lgrow{display:flex;gap:8px;justify-content:flex-end}
/* 每页只有一个主按钮，让它撑满一行 —— 380 宽的卡片里孤零零靠右很难看 */
.lgrow .btn{flex:1}
/* 页脚那句「还没账号？去注册 →」：按钮长得像链接，但得挡住表单 submit */
.lgfoot{margin-top:10px;font-size:11.5px;color:var(--ink3);display:flex;align-items:center;gap:4px}
.lgswap{border:0;background:transparent;padding:0;font-family:inherit;font-size:11.5px;
  color:var(--accent);cursor:pointer;line-height:1.6}
.lgswap:hover{text-decoration:underline}

/* 用户与积分表：加 / 减 两个按钮挤在一格里，别把表格撑到要横向滚 */
.cadj{white-space:nowrap}
.cadj .btn{margin-left:4px;padding:3px 8px;font-size:11.5px}

/* ============================================================================
   思考强度 · 胶囊选择器（2026-11-02）

   用户原话：「写作的思考强度选择真的好丑，可以仿照剧本那边的款式优化」。
   以前这里是一个原生 <select> 直接摆在「本阶段装配」里，跟周围的方块、
   小标签完全不是一个风格，而且选完看不出"这一档到底什么意思"。

   做法照抄分镜台（board.css 的 .bdmodel）：外面这块画给人看，
   里面的 <select> 铺满整块、透明度 0 —— 点哪儿都能拉出系统列表，
   value / onchange 一行都不用改。原生 select 撑不开会自己截断，
   "深思 · 想得久，慢一点" 会被吃掉后半句，那就等于没得选。
   ========================================================================== */
.chipsel {
  position: relative;
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  max-width: 280px;
  margin-top: 10px;
  padding: 7px 26px 7px 11px;
  border: 1px solid var(--line2);
  border-radius: 10px;
  background: var(--panel);
  cursor: pointer;
  user-select: none;
  transition: border-color 0.14s, box-shadow 0.14s;
}
.chipsel:hover,
.chipsel:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.csname {
  flex: none;
  font-size: 12.5px;
  font-weight: 700;
  color: var(--ink);
  letter-spacing: 0.2px;
  white-space: nowrap;
}
.cstag {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 11px;
  color: var(--ink3);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cstag:not(:empty)::before {
  content: "· ";
}
.cscaret {
  position: absolute;
  right: 9px;
  top: 50%;
  transform: translateY(-50%);
  font-size: 9px;
  line-height: 1;
  color: var(--ink3);
  pointer-events: none;
}
.cssel {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  border: 0;
  padding: 0;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
}
/* 关掉思考时整块转灰：一眼看出"这一档不花时间想" */
.chipsel.off .csname,
.chipsel.off .cscaret {
  color: var(--ink3);
}

/*
 * ============================================================================
 * 十一、自绘下拉面板（2026-11-02）
 *
 * 起因：用户指着截图说「写作和分镜板块这个思考，点开以后大大的文字很丑，
 * 而且也没有科技感，选择模型打开后也一样」。
 *
 * 原生 <select> 的**展开弹层是操作系统/浏览器自己画的**，CSS 一个像素都改不了
 * （Windows 上那一条蓝底高亮、14px 大字、直角边框，跟这套界面完全两个年代）。
 * 所以只能自己画：<select> 留着当「值容器」，面板由 ui.js 生成。
 *
 * 几条定死的规矩：
 *   ① 面板挂 document.body、用 position:fixed —— 右栏和对话区都是 overflow:auto，
 *      挂里面会被裁掉一半。既然是 fixed，滚动/改尺寸就必须关闭（ui.js 里做了）。
 *   ② 字号 12.5 / 11 两档，比系统弹层小两号。这是"工具"不是"网页表单"。
 *   ③ 选中态用左边一道 2px 竖条 + 淡底，不用整块填蓝 —— 那正是难看的地方。
 *   ④ 颜色全走变量，深色主题自动跟着走，别再写死。
 * ========================================================================== */
.wfpick {
  position: fixed;
  z-index: 200;
  min-width: 172px;
  padding: 5px;
  border: 1px solid var(--line2);
  border-radius: 13px;
  background: var(--panel);
  box-shadow: 0 1px 2px rgba(16, 34, 66, 0.06), 0 14px 38px rgba(16, 34, 66, 0.16);
  transform-origin: top center;
  animation: wfpin 0.13s cubic-bezier(0.2, 0.8, 0.3, 1);
}
/* 下面放不开、翻到上面去时，动画从下往上长，方向才对得上 */
.wfpick.up {
  transform-origin: bottom center;
}
@keyframes wfpin {
  from {
    opacity: 0;
    transform: translateY(-5px) scale(0.98);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
[data-theme="dark"] .wfpick {
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.5), 0 16px 40px rgba(0, 0, 0, 0.62);
}
.wfplist {
  display: flex;
  flex-direction: column;
  gap: 1px;
  max-height: 270px;
  overflow-y: auto;
  /* 滚到底别把背后的稿子一起带着滚 */
  overscroll-behavior: contain;
  scrollbar-width: thin;
}
.wfplist::-webkit-scrollbar {
  width: 8px;
}
.wfplist::-webkit-scrollbar-track {
  background: transparent;
}
.wfplist::-webkit-scrollbar-thumb {
  background: var(--line2);
  border: 2px solid transparent;
  background-clip: content-box;
  border-radius: 8px;
}
.wfpi {
  position: relative;
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  /* 左边 12px：留给那道竖条，别让文字压上去 */
  padding: 8px 10px 8px 12px;
  border: 0;
  border-radius: 9px;
  background: transparent;
  font: inherit;
  color: var(--ink);
  text-align: left;
  cursor: pointer;
  transition: background 0.1s;
}
/* 选中项左边那道竖条：比整块填色克制，十来个模型并排时也能一眼定位 */
.wfpi::before {
  content: "";
  position: absolute;
  left: 4px;
  top: 50%;
  width: 2px;
  height: 13px;
  margin-top: -6.5px;
  border-radius: 2px;
  background: var(--accent);
  opacity: 0;
  transform: scaleY(0.4);
  transition: opacity 0.12s, transform 0.12s;
}
.wfpi.on::before {
  opacity: 1;
  transform: none;
}
.wfpi.cur,
.wfpi:focus-visible {
  outline: none;
  background: var(--accent-soft);
}
.wfpn {
  flex: none;
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: 0.2px;
  white-space: nowrap;
}
/* 已选的那档主名也跟着变强调色：牌上写的是它，面板里得对得上 */
.wfpi.on .wfpn {
  color: var(--accent);
}
.wfpt {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 11px;
  color: var(--ink3);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.wfpk {
  flex: none;
  margin-left: auto;
  font-size: 11px;
  font-weight: 700;
  color: var(--accent);
  opacity: 0;
  transition: opacity 0.12s;
}
.wfpi.on .wfpk {
  opacity: 1;
}
/* 牌被按下去的时候：边框亮起来、箭头翻上去 —— 明确"现在面板是开着的" */
.cscaret,
.bmcaret {
  transition: transform 0.15s, color 0.15s;
}
.chipsel.open,
.bdmodel.open {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.chipsel.open .cscaret,
.bdmodel.open .bmcaret {
  transform: translateY(-50%) rotate(180deg);
}
/*
 * 原生 select 只当"值容器"，指针事件必须关掉。
 *
 * 这行是踩出来的：Windows Chrome 在 **mousedown** 那一刻就弹出系统菜单，
 * click 里 preventDefault 已经晚了 → 结果自绘面板和系统菜单一起出现。
 * 关掉指针事件后点击落到外面那块牌上，closest() 照样命中，业务代码零改动。
 * 键盘可达性不靠它：pointer-events 不影响 Tab 聚焦，Enter / ↑↓ 走自绘面板。
 */
.cssel,
.bmsel {
  pointer-events: none;
}

/* ------------------------- 生成任务面板（跨页面） ------------------------- */
/*
 * 右下角一块小牌：别的板块/别的窗口正在跑的任务，这里也看得见。
 * 一定要能同时显示"在跑"和"跑完了没取回"，否则用户切回来还是不知道东西在哪。
 */
/* 贴着右下角，但**抬起来一截**：写作页和分镜台的输入框就在底部，
   压在上面会盖住"继续说点什么"那个框 —— 那是最不该被挡的地方。 */
.jobbox{
  position:fixed;right:16px;bottom:92px;z-index:60;width:322px;max-width:calc(100vw - 32px);
  border:1px solid var(--line2);border-radius:12px;background:var(--panel);
  box-shadow:var(--shadow);font-size:12px;color:var(--ink);overflow:hidden;
}
.jobhd{display:flex;align-items:center;gap:8px;padding:8px 10px;border-bottom:1px solid var(--line);background:var(--panel2)}
.jobhd>b{font-size:12px;font-weight:600}
.jobn{font-size:11px;color:var(--ink3)}
.jobfold{margin-left:auto;width:20px;height:20px;line-height:1;border:1px solid var(--line2);border-radius:6px;background:var(--panel);color:var(--ink2);cursor:pointer;font-family:inherit}
.jobfold:hover{border-color:var(--accent);color:var(--accent)}
.jobbox.min .joblist{display:none}
.joblist{max-height:264px;overflow:auto}
.jrow{display:flex;align-items:center;gap:9px;padding:8px 10px;border-bottom:1px solid var(--line)}
.jrow:last-child{border-bottom:0}
.jdot{width:6px;height:6px;border-radius:50%;background:var(--ink3);flex:none}
/* 在跑的用强调色呼吸，跟思考块同一个节拍，让人一眼看出"还活着" */
.jrow.on .jdot{background:var(--accent);animation:wfthink 1.1s ease-in-out infinite}
.jrow.bad .jdot{background:var(--danger)}
.jthumb{width:30px;height:30px;border-radius:6px;object-fit:cover;flex:none;border:1px solid var(--line)}
.jmain{flex:1;min-width:0}
.jname{font-size:12px;color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.jmeta{font-size:11px;color:var(--ink3);margin-top:1px}
.jmute{margin-left:6px;color:var(--warn)}
.jerr{font-size:11px;color:var(--danger);margin-top:2px;line-height:1.5;word-break:break-word}
.jact{display:flex;gap:6px;flex:none}
/* 小一号的按钮：面板里放不下标准尺寸 */
.jobbox .btn.sm{padding:3px 9px;font-size:11.5px;border-radius:7px}
