/* 分镜台 —— 左剧本 / 右对话。
   整页占满视口，左右各自滚，不整页滚（不然写着写着头就飞了）。 */

.bdbody {
  height: 100vh;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
.bdbody > header {
  flex: none;
}

/*
 * 高度用 flex 撑，不再写 calc(100vh - 52px)。
 * 集数条是「变高」的（窄屏换行、集多到要横滚），写死一个高度迟早把内容顶出屏幕。
 */
.bdwrap {
  display: flex;
  flex: 1 1 auto;
  min-height: 0;
  height: auto;
  gap: 0;
}

/* ------------------------------- 集：当前在第几集 ------------------------------- */

/*
 * 分镜台最要紧的一条是「每集是一个独立页面」。
 * 但"独立"靠的是数据（每集各存一份 history），不靠把 60 个集号摊在顶上 ——
 * 60 集的剧一排标签根本放不下，所以这里用下拉，只显示当前那一集。
 */
.epbar {
  flex: none;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 5px 18px 6px;
  background: var(--panel2);
  border-bottom: 1px solid var(--line);
}
.eplab {
  font-size: 11px;
  color: var(--ink3);
  flex: none;
  letter-spacing: 1px;
}
/* 集标题可能带名字（「第3集 荒宅 · 5 条」），太窄会截成省略号，读不出是第几集 */
.epsel {
  width: auto;
  max-width: 300px;
  min-width: 132px;
  padding: 5px 8px;
  font-size: 12px;
  height: 28px;
  background: var(--panel);
  border: 1px solid var(--line2);
  border-radius: 7px;
  flex: none;
}
/* 下拉旁边那句常驻小字：这一集是空的，还是已经聊过几条 */
.eptip {
  font-size: 11px;
  color: var(--ink3);
  flex: none;
  margin-left: 2px;
}

/* 顶栏里的下拉：比默认窄一点，别把顶栏挤爆 */
.hsel {
  width: auto;
  max-width: 210px;
  padding: 5px 8px;
  font-size: 12px;
  background: var(--panel2);
  border: 1px solid var(--line2);
  border-radius: 7px;
  height: 28px;
}
#modBtn b {
  color: var(--accent);
  font-weight: 600;
}

/* ------------------------------- 左：剧本 ------------------------------- */

/*
 * 左栏宽度：这是"实时对照"用的，不是拿来遣词造句的 ——
 * 用户的原话是"那个正文只是用来实时对照用的，不需要那么大"。
 * 42% 在 1920 屏上要吃掉 800px，对话区被挤得只剩 1100，十列表格横滚得更厉害。
 * 现在 30%（上限 520）够看清一行台词，剩下的全给右边。
 */
.bdleft {
  width: 30%;
  min-width: 264px;
  max-width: 520px;
  display: flex;
  flex-direction: column;
  border-right: 1px solid var(--line);
  background: var(--panel);
  min-height: 0;
}

/*
 * 收起剧本：十列分镜表在 825px 里要横滚 170px，读一行左右拖一次很烦。
 * 收起后对话区拿到整屏 1500px，960px 的表一眼看完 —— 这是看表时最常用的姿态。
 * 用 display:none 而不是 width:0：textarea 在 0 宽容器里会算出怪尺寸，回展开时容易塌。
 */
.bdwrap.folded .bdleft {
  width: 34px;
  min-width: 34px;
  max-width: 34px;
  flex: none;
  border-right: 1px solid var(--line);
  background: var(--panel2);
}
.bdwrap.folded .bdleft > *:not(.unfold) {
  display: none;
}
.unfold {
  display: none;
  flex: 1 1 auto;
  width: 100%;
  border: none;
  background: transparent;
  color: var(--ink3);
  font-size: 12px;
  letter-spacing: 2px;
  writing-mode: vertical-rl;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  padding: 10px 0;
}
.bdwrap.folded .bdleft .unfold {
  display: flex;
}
.unfold:hover {
  color: var(--accent);
  background: var(--accent-soft);
}

.bdbar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 9px 12px;
  border-bottom: 1px solid var(--line);
  background: var(--panel2);
  flex: none;
}
.bdbar b {
  font-size: 12px;
  font-weight: 600;
}
.epin {
  width: 96px;
  padding: 4px 8px;
  font-size: 12px;
  height: 26px;
}

#script {
  flex: 1 1 auto;
  min-height: 0;
  border: none;
  border-radius: 0;
  background: var(--panel);
  padding: 14px 16px;
  font-size: 13px;
  line-height: 1.85;
  resize: none;
  overflow-y: auto;
}
#script:focus {
  box-shadow: none;
  border: none;
  background: var(--panel);
}

.bdfoot {
  flex: none;
  padding: 7px 12px;
  border-top: 1px solid var(--line);
  background: var(--panel2);
}

/*
 * 本次装载：模组 / 视觉基底。
 *
 * 用户原话：「应该学习一下剧本撰写的那个格式，那个给人感觉很舒服」。
 * 所以这里不另造一套：外框直接用 .card，标题用 h2 + .hint，槽位用 .slot/.idx/.nm/.mt，
 * 和写作页「本阶段装配」是同一批公共组件 —— 看起来才像同一个产品里的东西。
 *
 * 唯一要补的是：左栏底色本来就是 --panel（跟卡片同色），卡片会糊掉。
 * 所以这一段垫一层 --bg，让卡片重新浮起来，跟右边对话区一个道理。
 */
.bdload {
  /*
   * 固定高度、内部滚动（2026-11-02 用户要求）。
   *
   * 原话：「左下角的装载区域，考虑到以后可能会装载更多的模组内容，
   * 需要在不改变原来大小的情况下改成可以滚动的，这样就不会占其他区域的格式了」。
   *
   * 264px 是它装 2 个模组时的自然高度（量过截图，卡本体 ≈215px + 上下内边距）。
   * 模组加到 10 个、20 个，这块都不再长，多出来的内容自己在里面滚 ——
   * 上面的剧本区和右边的对话区一个字都不会被挤。
   *
   * flex 用 0 1 auto 而不是 none：窗口特别矮时允许它继续缩，缩到底才滚，
   * 否则小窗口下它会把剧本区顶成一条缝。
   */
  flex: 0 1 auto;
  min-height: 0;
  max-height: 264px;
  overflow-y: auto;
  padding: 10px 12px 12px;
  border-top: 1px solid var(--line);
  background: var(--bg);
}
/* 外层已经滚了，里面这层就别再滚 —— 两层滚动条会让人不知道自己在拖哪一个 */
.bdload #loadSlots {
  max-height: none;
  overflow: visible;
}
.bdcard {
  margin: 0;
  padding: 13px 14px 11px;
}
.bdcard h2 {
  margin-bottom: 9px;
}
.bdsub {
  font-size: 11px;
  color: var(--ink3);
  margin: 0 0 7px;
}
.bdsub b {
  color: var(--accent);
  font-weight: 600;
  margin-left: 6px;
}

/* ---------------------------------------------------------------------------
 * 模型选择器（2026-11-02：顶栏 → 「集」这一行空着的地方）
 *
 * 用户先让搬到装载卡，看过之后否掉了：「这样改整体就占频了，退回之前的格式」，
 * 指着「集 / 第1集 / 新页面·从头开始」右边那片空白说放这儿。
 * 也对 —— 这一行本来就空着一大片，模型又是「这一轮」的状态，跟「第几集」同级，
 * 塞进来一分地方都不多占，装载卡也回到原来的高度。
 *
 * 做法没变：外面这块 .bdmodel 画给人看，里面的 <select> 铺满、透明度 0。
 * 原生 select 撑不开会自己截断，「deepseek-flash · 我的接口 · 不扣积分」
 * 会变成「deepseek-fla…」，两个 gemini 长得一模一样，等于没得选。
 * ------------------------------------------------------------------------- */
.bdmodel {
  position: relative;
  flex: 0 1 auto;
  display: flex;
  align-items: center;
  gap: 7px;
  min-width: 0;
  max-width: 400px;
  /* 右边留出 caret 的位置，不然省略号会跟箭头打架 */
  padding: 4px 26px 4px 10px;
  border: 1px solid var(--accent-line);
  border-radius: 8px;
  background: var(--accent-soft);
  cursor: pointer;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.bdmodel:hover,
.bdmodel:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.bmdot {
  flex: none;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
/* 自带接口不扣积分 —— 绿点，一眼看出这次花不花钱 */
.bdmodel.own {
  border-color: rgba(18, 121, 90, 0.35);
  background: var(--ok-soft);
}
.bdmodel.own .bmdot {
  background: var(--ok);
  box-shadow: 0 0 0 3px var(--ok-soft);
}
.bmname {
  flex: 0 1 auto;
  min-width: 0;
  font-size: 12.5px;
  font-weight: 700;
  color: var(--ink);
  letter-spacing: 0.2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.bmtag {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 11px;
  color: var(--ink3);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.bmtag:not(:empty)::before {
  content: "· ";
  color: var(--ink3);
}
.bmcaret {
  position: absolute;
  right: 9px;
  top: 50%;
  transform: translateY(-50%);
  font-size: 9px;
  line-height: 1;
  color: var(--accent);
  opacity: 0.85;
}
.bdmodel.own .bmcaret {
  color: var(--ok);
}
/* 思考强度那块：比模型牌窄，也不抢绿点/强调色 —— 它是"这一轮的深度"，
   不是"这次花不花钱"。所以用中性色，只有真的关掉思考时才转灰。 */
.bdthink {
  border-color: var(--line);
  background: var(--panel);
  max-width: 190px;
  padding-right: 22px;
}
.bdthink .bmcaret {
  color: var(--ink3);
  right: 7px;
}
.bdthink .bmname {
  font-weight: 600;
  font-size: 12px;
}
.bdthink .bmtag {
  font-size: 10.5px;
}
.bdthink.off {
  opacity: 0.8;
}
.bdthink.off .bmname {
  color: var(--ink3);
}
.bdthink[hidden] {
  display: none;
}
.bmsel {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  opacity: 0;
  cursor: pointer;
  /* 16px 是移动端最低值，小了 iOS 一聚焦就整页放大 */
  font-size: 16px;
  appearance: none;
}
/* 勾了很多模组时槽位会长过剧本，给个上限自己滚，别把正文挤没 */
#loadSlots {
  max-height: 176px;
  overflow-y: auto;
  margin-bottom: 8px;
}
#loadSlots:empty {
  display: none;
}
/* 空列表时撑一条虚线，比一行灰字显眼，又不占地方 */
.bdempty {
  border: 1px dashed var(--line2);
  border-radius: 8px;
  padding: 10px 12px;
  font-size: 11.5px;
  color: var(--ink3);
  margin-bottom: 8px;
}
.bdload .slot.click {
  cursor: pointer;
}
.bdload .slot.click:hover {
  border-color: var(--accent);
}
.bdload .slot.click:focus-visible {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.bdload .lgo {
  color: var(--ink3);
  font-size: 15px;
  line-height: 1;
}
/* 合计那一行：跟卡片里其他块一样用上边框隔开 */
.bdfoot2 {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 11px;
  padding-top: 10px;
  border-top: 1px solid var(--line);
}
.bdfoot2 .btn.sm {
  padding: 4px 10px;
}
.bdfoot2 .muted {
  font-size: 11px;
}

/* ------------------------------- 右：对话 ------------------------------- */

.bdright {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  min-height: 0;
  background: var(--bg);
}

/*
 * 注意：这个页面同时引了 style.css，里面有一条 .chat{display:flex;flex-direction:column;
 * max-height:46vh;gap:10px} —— 那是写作线对话卡用的。
 * 落在这里会出两个毛病：① .msg 变成 flex item，宽度只按内容算，气泡怎么都撑不满；
 * ② 高度被锁在 46vh，下半截空白。所以这几项必须显式重置，不能只靠"后加载覆盖"
 * （那条规则里 display/flex-direction/gap/max-height 我们一个都没写，就全被它接管了）。
 */
.chat {
  display: block;
  max-height: none;
  gap: 0;
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  padding: 18px 22px 8px;
  scroll-behavior: smooth;
}

.msg {
  display: flex;
  gap: 10px;
  margin-bottom: 16px;
  align-items: flex-start;
  /* 「复制 / 删 / 改」是绝对定位的，锚点必须是自己 —— 少了这一行，
     按钮会挂到滚动容器的右上角，鼠标划到消息上什么也看不到 */
  position: relative;
}
.msg .av {
  width: 26px;
  height: 26px;
  border-radius: 7px;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  font-weight: 600;
  background: var(--soft);
  color: var(--ink3);
  border: 1px solid var(--line);
  margin-top: 2px;
}
.msg.me {
  flex-direction: row-reverse;
}
.msg.me .av {
  background: var(--accent-soft);
  color: var(--accent);
  border-color: var(--accent-line);
}
.bub {
  max-width: min(860px, 88%);
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 12px 15px;
  line-height: 1.8;
  font-size: 13px;
  overflow-wrap: anywhere;
  box-shadow: var(--shadow);
}
.msg.me .bub {
  background: var(--accent-soft);
  border-color: var(--accent-line);
  white-space: pre-wrap;
}
/*
 * 助手的气泡一律吃满整行 —— 不再按「有没有表格」区别对待。
 *
 * 原来的逻辑是：渲染完看一眼有没有表格 / 提示词框，有就加 .wide 放宽，没有就按
 * min(860px, 88%) 收着。于是纯文字的长回复（规划、节奏方案、修改意见）全被卡在 88%，
 * 右边留一大片空地 —— 用户原话：「你这个对话框，AI 回复内容空间利用率太低」。
 *
 * 只给 .bub 写 max-width 是不够的：`.msg` 是 display:flex，`.bub` 是它的 flex item，
 * flex item 的实际宽度**只按内容算**，max-width 只能往下压、不能往上撑。
 * 想让它占满必须显式给 flex: 1 1 auto。
 *
 * 只对助手生效：自己的话（.msg.me）保持右边贴边、宽度随内容，那是聊天软件的通行写法。
 */
.msg:not(.me) .bub {
  flex: 1 1 auto;
  min-width: 0;
  /* 36px = 左边那个头像 26 + 间距 10，留出来，别把对话区顶出横向滚动条 */
  max-width: calc(100% - 36px);
}
.bub.err {
  background: var(--danger-soft);
  border-color: #f0c9c5;
  color: var(--danger);
}
.bub .note {
  font-size: 11px;
  color: var(--warn);
  border-left: 2px solid var(--warn);
  padding-left: 8px;
  margin: 8px 0 0;
}

/* 模型吐出来的 Markdown：分镜是十列表格，表格必须好看，不然没法读 */
.bub h1,
.bub h2,
.bub h3,
.bub h4 {
  font-size: 13px;
  margin: 14px 0 7px;
  font-weight: 600;
}
.bub h1:first-child,
.bub h2:first-child,
.bub h3:first-child,
.bub p:first-child {
  margin-top: 0;
}
.bub p {
  margin: 0 0 9px;
}
.bub p:last-child {
  margin-bottom: 0;
}
.bub ul,
.bub ol {
  margin: 0 0 9px;
  padding-left: 20px;
}
.bub li {
  margin: 2px 0;
}
.bub strong {
  font-weight: 600;
}
.bub code {
  background: var(--soft);
  border: 1px solid var(--line);
  border-radius: 4px;
  padding: 0 4px;
  font-size: 12px;
}
.bub pre {
  background: var(--soft);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 10px 12px;
  overflow-x: auto;
  font-size: 12px;
  line-height: 1.7;
}
.bub pre code {
  border: none;
  background: none;
  padding: 0;
}

/*
 * 表格：分镜表动辄十列（镜号/时长/景别/机位/画面/动作/光影/声音/台词/提示词）。
 * 关键不是"多好看"，而是**别把十列硬塞进气泡宽度**——塞进去每列只剩四十来像素，
 * 中文变成一列一个字竖着排，整张表就废了。
 * 所以：表格按 100% 铺满，但每列给 min-width 撑住，装不下就由 .tblwrap 横滚。
 */
.tblwrap {
  overflow-x: auto;
  overscroll-behavior-x: contain;
  margin: 0 0 10px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--panel);
}
.tblwrap::-webkit-scrollbar {
  height: 9px;
}
.tblwrap::-webkit-scrollbar-thumb {
  background: var(--line);
  border-radius: 5px;
}
.tblwrap::-webkit-scrollbar-track {
  background: transparent;
}
.bub table {
  border-collapse: collapse;
  width: 100%;
  font-size: 12px;
}
.bub th,
.bub td {
  border-right: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  padding: 6px 9px;
  text-align: left;
  vertical-align: top;
  line-height: 1.65;
  /* 撑住列宽：十列 × 92px ≈ 920px，比对话区宽，于是横滚而不是压缩 */
  min-width: 92px;
  /* 提示词那种超长英文串要能断，否则一列能把整张表撑到天边 */
  overflow-wrap: anywhere;
}
.bub th {
  background: var(--panel2);
  font-weight: 600;
  white-space: nowrap;
  position: sticky;
  top: 0;
}
.bub tr:last-child td {
  border-bottom: none;
}
.bub th:last-child,
.bub td:last-child {
  border-right: none;
}

.typing::after {
  content: '▌';
  color: var(--accent);
  animation: blink 1s steps(2) infinite;
}
@keyframes blink {
  50% {
    opacity: 0;
  }
}

/* ------------------------------- 输入区 ------------------------------- */

.dock {
  flex: none;
  border-top: 1px solid var(--line);
  background: var(--panel);
  padding: 10px 14px 8px;
}
.dockrow {
  display: flex;
  gap: 8px;
  align-items: flex-end;
}
#ask {
  flex: 1 1 auto;
  resize: none;
  min-height: 46px;
  max-height: 180px;
  line-height: 1.6;
}
.dockside {
  display: flex;
  flex-direction: column;
  gap: 6px;
  flex: none;
}
.dockside .btn {
  width: 66px;
}
.dockrow.tools {
  align-items: center;
  margin-top: 7px;
}

/* ------------------------------- 模组抽屉 ------------------------------- */

.modpanel {
  position: fixed;
  top: 52px;
  right: 0;
  bottom: 0;
  width: 400px;
  max-width: 92vw;
  background: var(--panel);
  border-left: 1px solid var(--line);
  box-shadow: -8px 0 24px rgba(20, 24, 31, 0.08);
  transform: translateX(102%);
  transition: transform 0.18s ease;
  z-index: 40;
  display: flex;
  flex-direction: column;
  padding: 16px;
}
.modpanel.open {
  transform: none;
}
.modpanel h3 {
  margin: 0 0 6px;
  font-size: 13px;
}
.modpanel > p {
  margin: 0 0 12px;
  font-size: 11px;
  line-height: 1.7;
}
.modlist {
  flex: 1 1 auto;
  overflow-y: auto;
  border-top: 1px solid var(--line);
  padding-top: 10px;
}
.moditem {
  display: flex;
  gap: 9px;
  padding: 8px 6px;
  border-radius: 8px;
  cursor: pointer;
  align-items: flex-start;
}
.moditem:hover {
  background: var(--hover);
}
.moditem input {
  width: auto;
  margin-top: 3px;
  flex: none;
}
.moditem .nm {
  font-size: 12px;
  font-weight: 500;
}
/* 每个模组旁边挂一个重量标签：分镜这套单块 69k token，不看数字勾就是盲选 */
.moditem .mtok {
  display: inline-block;
  font-size: 10px;
  font-weight: 400;
  color: var(--ink3);
  background: var(--soft);
  border: 1px solid var(--line);
  border-radius: 4px;
  padding: 0 5px;
  margin-left: 3px;
  white-space: nowrap;
  vertical-align: 1px;
}
.moditem .ds {
  font-size: 11px;
  color: var(--ink3);
  margin-top: 2px;
  line-height: 1.5;
}
.modfoot {
  flex: none;
  display: flex;
  align-items: center;
  gap: 8px;
  padding-top: 10px;
  border-top: 1px solid var(--line);
}
/* 勾超了（合计超过窗口）就红起来，别等发出去被服务端打回 */
#modChars.over {
  color: var(--danger);
  font-weight: 500;
}

/* ------------------------------- 帮助 ------------------------------- */

.bdhelp {
  position: fixed;
  inset: 0;
  background: rgba(20, 24, 31, 0.32);
  display: none;
  z-index: 50;
  padding: 8vh 16px;
}
.bdhelp.open {
  display: block;
}
.bdhelp > * {
  max-width: 640px;
  margin: 0 auto;
}
.bdhelp {
  overflow-y: auto;
}
.bdhelp h3,
.bdhelp ol,
.bdhelp p {
  background: var(--panel);
  padding-left: 22px;
  padding-right: 22px;
}
.bdhelp h3 {
  margin: 0 auto;
  padding-top: 18px;
  border-radius: 12px 12px 0 0;
  font-size: 14px;
}
.bdhelp ol {
  margin: 0 auto;
  padding-bottom: 6px;
  line-height: 2;
}
.bdhelp p {
  margin: 0 auto;
  padding-bottom: 18px;
  border-radius: 0 0 12px 12px;
}

.muted {
  color: var(--ink3);
  font-size: 11px;
}

/* 窄屏：上下叠，剧本只留一小块 */
@media (max-width: 900px) {
  .bdwrap {
    flex-direction: column;
  }
  .bdleft {
    width: auto;
    max-width: none;
    height: 34%;
    min-height: 0;
    border-right: none;
    border-bottom: 1px solid var(--line);
  }
  .bdright {
    height: 66%;
  }
  .msg .bub {
    max-width: 100%;
  }
}

/* ---------------------- 消息上的「删 / 改 / 重出」 ---------------------- */

/*
 * 平时不显示，鼠标移到那条消息上才浮出来。
 * 分镜对话动辄二三十条，按钮常驻会把气泡边缘糊满，反而看不清内容。
 *
 * .msg 要 width:fit-content —— 它是 flex 容器，默认撑满整行，
 * 按钮用 right:8px 定位就会跑到对话区最右边，离气泡十万八千里。
 * 收成内容宽之后，按钮才贴得住气泡右上角；自己说的话用 margin-left:auto 靠右。
 */
.msg {
  position: relative;
  width: fit-content;
  max-width: 100%;
}
/*
 * 但助手那条必须吃满整行 —— 这就是「AI 回复内容空间利用率太低」的真正原因。
 *
 * 上面那条 fit-content 让整行只有内容那么宽（实测 1356 的内容区里只占了 881），
 * 气泡再怎么 flex 也只能填满这 881，右边那 475px 就永远空着。
 *
 * 放成 100% 之后，按钮依然贴得住：助手的气泡左边让了头像 36px、右边正好到行尾，
 * 所以 right:6px 落点还是气泡的右上角。
 */
.msg:not(.me) {
  width: 100%;
}
.msg.me {
  margin-left: auto;
}
.msgops {
  position: absolute;
  top: -10px;
  right: 6px;
  display: flex;
  gap: 4px;
  /* 不再藏起来只等 hover：用户找了两回都说"没有删除键"。
     常态半透明挂着、鼠标划上来实色 —— 一眼看得见，又不至于每条都像贴了张标签。 */
  opacity: 0.72;
  transition: opacity 0.12s;
  z-index: 3;
}
.msg.me .msgops {
  right: auto;
  left: 6px;
}
.msg:hover .msgops {
  opacity: 1;
  pointer-events: auto;
}
.opbtn {
  font-size: 11px;
  line-height: 1;
  height: 22px;
  padding: 0 7px;
  border-radius: 5px;
  border: 1px solid var(--line);
  background: var(--panel);
  color: var(--ink3);
  cursor: pointer;
  box-shadow: 0 1px 3px rgba(20, 24, 31, 0.06);
}
.opbtn:hover {
  color: var(--ink);
  border-color: var(--ink3);
}
.opbtn[data-act='del']:hover {
  color: var(--danger);
  border-color: var(--danger);
  background: var(--danger-soft);
}

/* ---------------------- 集数：旧的 select 已下线 ---------------------- */

/* 集标题可能带名字（「第3集 荒宅」），太窄会截成省略号，读不出是第几集 */
#epName {
  font-size: 12px;
  font-weight: 600;
  max-width: 42%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ---------------------- 可整段复制的提示词框 ---------------------- */

/*
 * 从 Cherry Studio 那套借来的形态：这是"要拿走的东西"，不是"要读的东西"。
 * 所以它不长在正文里，是一个自己的边框 + 自己的标题栏 + 右上角一个复制按钮。
 * 模型吐 ```prompt 围栏时出现；没吐的时候前端会按横线 + 关键词兜底认一次。
 */
.pbox {
  margin: 10px 0;
  border: 1px solid var(--line2);
  /* 左边一道实色竖条：这是"要整段拿走的一块"，不是普通正文。
     光靠浅底色在白色气泡里几乎看不出来，必须有一条硬边把界线画出来。 */
  border-left: 3px solid var(--accent);
  border-radius: 9px;
  background: var(--soft);
  box-shadow: inset 0 1px 0 var(--panel);
  overflow: hidden;
}
.pbd {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 8px 6px 11px;
  background: var(--hover);
  border-bottom: 1px solid var(--line2);
}
.pbn {
  font-size: 11.5px;
  font-weight: 600;
  color: var(--ink2);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.pbc {
  font-size: 10px;
  color: var(--ink3);
  flex: none;
  margin-left: auto;
}
.pbcopy {
  font-family: inherit;
  font-size: 11px;
  line-height: 1;
  height: 22px;
  padding: 0 9px;
  border-radius: 5px;
  border: 1px solid var(--line2);
  background: var(--panel);
  color: var(--ink2);
  cursor: pointer;
  flex: none;
}
.pbcopy:hover {
  color: var(--accent);
  border-color: var(--accent-line);
  background: var(--accent-soft);
}
.pbcopy.ok {
  color: var(--ok);
  border-color: #bfe0d3;
  background: var(--ok-soft);
}
/* 覆盖 .bub pre 的代码块底：这类"要求"多是中文，等宽字体会很难读 */
.bub .pbtext {
  margin: 0;
  padding: 10px 12px;
  max-height: 560px;
  overflow: auto;
  font-family: inherit;
  font-size: 12.5px;
  line-height: 1.85;
  white-space: pre-wrap;
  word-break: break-word;
  background: transparent;
  border: none;
  border-radius: 0;
}

/* ---------------------- 参考图：待发缩略图 + 拖拽层 ---------------------- */

.atts {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  padding: 0 0 8px;
}
.atts:empty {
  display: none;
}
.att {
  position: relative;
  width: 62px;
  height: 62px;
  border-radius: 8px;
  overflow: hidden;
  border: 1px solid var(--line2);
  background: var(--soft);
  flex: none;
}
.att img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.att button {
  position: absolute;
  top: 2px;
  right: 2px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: none;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  font-size: 11px;
  line-height: 1;
  cursor: pointer;
  padding: 0;
}
.att button:hover {
  background: var(--danger);
}

/* 拖拽提示层。pointer-events:none 是必须的 —— 否则它自己会把 drop 事件吃掉 */
.dropmask {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: none;
  align-items: center;
  justify-content: center;
  background: rgba(20, 24, 31, 0.42);
  pointer-events: none;
}
.dropmask.on {
  display: flex;
}
.dmi {
  border: 2px dashed var(--accent-line);
  background: var(--panel);
  color: var(--accent);
  border-radius: 14px;
  padding: 24px 32px;
  font-size: 14px;
  font-weight: 600;
  box-shadow: 0 18px 48px rgba(0, 0, 0, 0.2);
}

/* 历史里的参考图：小方块，点开看大图 */
.bubimgs {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 0 0 8px;
}
.bubimgs img {
  width: 92px;
  height: 92px;
  object-fit: cover;
  border-radius: 7px;
  border: 1px solid var(--line2);
  display: block;
  cursor: zoom-in;
  background: var(--soft);
}
.bubimgs img:hover {
  border-color: var(--accent);
}

/* ---------------------- 视觉基底抽屉 ---------------------- */

.vistext {
  flex: 1 1 auto;
  min-height: 0;
  width: 100%;
  resize: none;
  font-size: 12.5px;
  line-height: 1.85;
  padding: 11px 12px;
  margin-bottom: 10px;
}

/* ==========================================================================
   科技感改版 —— 分镜台试点（2026-10-31）
   ==========================================================================

   用户原话：「整个程序的配色和科技感有没有更好的设计方案，现在看着太 LOW 了」；
   看了三版纯配色方案之后又补一句：「我觉得科技感不够」。

   所以这一段**不是换颜色**，是换材质。纯换色最多救回三成，剩下七成在这五件事上：

   ① 排印层级 —— 原来卡片标题 13、正文 13、各种小字 12，全挤在同一个音量上，
      看着像一份没排过版的文档。现在压成三级：块标题 12.5/600 + 字距、
      正文 13/400、微标签 11/500 + .06em 字距。
   ② 三层背景 —— 原来只有 --bg / --panel 两层，而且 #script 用的就是 --panel，
      跟左栏底色一模一样，剧本框看不出是个"能打字的框"。补一层 --sunken 给所有
      内嵌区（剧本框 / 输入框 / 模组槽位），嵌套关系一眼能读出来。
   ③ hairline 边框 —— 实心 #2a2f37 的边框像 Word 2003。改成半透明 rgba，
      压在深底上会自己融进去，不切硬边；层次靠明度差，不靠描边。
   ④ 卡片顶部内高光 —— 最便宜也最有效的一条：inset 0 1px 0 rgba(255,255,255,.05)
      让面板像一块真有光源照着的板子，而不是一张贴纸。
   ⑤ 等宽数字 —— token、集号、积分、耗时全部 tabular-nums 对齐。
      数字一歪，"精密工具"的感觉立刻没了。

   最后一条纪律：**光只给两处** —— 主按钮、顶栏一道 1px 亮线。
   上一版赛博方案把发光铺到卡片、按钮、标签上，到处亮等于哪里都不亮。

   作用域：整段挂在 body.bdbody 下（board.html 的 body 类名）。
   写作页 / 画布 / 管理端一个像素都不动 —— 试点看好再铺。
   ========================================================================== */

/* ------------------------- 一、色板：已上提到 style.css ------------------------- */
/*
 * 这一段原来在这里拷了一份完整色板（--bg/--panel/--sunken/--topline/--chev …）。
 * 2026-10-31 用户要求「所有板块都采纳这个感觉」，色板已经提到 style.css 的 :root 和
 * [data-theme="dark"] 里，成为全站唯一来源。**不要在这里再写一遍** ——
 * 两份定义一改就飘，而且分镜台会跟写作页慢慢长成两个产品。
 *
 * 分镜台只保留分镜台特有的那些规则，从下一节开始。
 */


/* ------------------------- 二、顶栏：全页仅有的两处光之一 ------------------------- */

.bdbody > header {
  background: var(--panel);
  border-bottom: 1px solid var(--line);
}
/*
 * 顶栏底色**必须是纯色 --panel**，不能是渐变。
 *
 * 客户端里 header 就是窗口标题栏，最右边那 138px 被系统的窗口按钮覆盖着，
 * 而按钮区的底色只能给一个纯色（setTitleBarOverlay 的 color）。
 * 这里一旦用渐变，纯色那块和渐变那块就接出可见的断痕 —— 实拍图里右边一截偏暗。
 * 所以深色主题下也老老实实 --panel，装饰只留底下那道渐隐亮线（它到 46% 就淡没了，
 * 不会被覆盖区截断）。
 */
[data-theme='dark'] .bdbody > header {
  /* 顶栏往下压一道影：不然它和集数条糊成一片横条，读不出"这是页头" */
  box-shadow: 0 6px 22px rgba(0, 0, 0, 0.4);
}
/* header 本来就是 position:sticky（positioned），:after 能直接挂上去 —— 别改成 relative，
   那会把粘性顶栏一起废掉 */
.bdbody > header:after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 1px;
  pointer-events: none;
  background: var(--topline);
}

/* 顶栏里那两个下拉：收窄内边距、统一 8px 圆角，跟按钮一个模具 */
/*
 * 下拉箭头改成自绘 SVG。
 * 系统默认那个箭头是 Windows 的灰三角加一圈立体阴影，深色底下尤其出戏 ——
 * 整页其他地方都收干净了，就它一个还在 2010 年。
 */
.bdbody .hsel,
.bdbody .epsel {
  -webkit-appearance: none;
  appearance: none;
  background-color: var(--panel2);
  background-image: var(--chev);
  background-repeat: no-repeat;
  background-position: right 9px center;
  border: 1px solid var(--line2);
  border-radius: 8px;
  color: var(--ink);
  font-size: 12px;
  height: 28px;
  padding-right: 26px;
}
.bdbody .hsel:focus,
.bdbody .epsel:focus {
  border-color: var(--accent-line);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.bdbody .pill {
  border-radius: 999px;
  border: 1px solid var(--line2);
  background: var(--panel2);
  color: var(--ink2);
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: 0.05em;
  padding: 3px 9px;
}
.bdbody .pill.hot {
  color: var(--accent);
  border-color: var(--accent-line);
  background: var(--accent-soft);
}
/* 用户名前面来一道竖线：把「项目/模型/额度」这堆操作和「我是谁」分开 */
.bdbody .who {
  font-size: 11.5px;
  color: var(--ink3);
  letter-spacing: 0.02em;
  padding-left: 11px;
  border-left: 1px solid var(--line);
}
/*
 * 品牌后面那个「分镜」。原来是 11px 灰字，跟旁边的按钮糊在一起。
 * 改成一枚小牌：极小的字号 + 大字距 + accent 细边 —— 这是全页最小的一块彩色，
 * 正好当"你现在在哪个板块"的定位点。
 */
.bdbody .brand i {
  font-style: normal;
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.16em;
  color: var(--accent);
  background: var(--accent-soft);
  border: 1px solid var(--accent-line);
  border-radius: 5px;
  padding: 2px 6px 2px 7px;
  margin-left: 5px;
  line-height: 1;
}

/* --------------------------- 三、集数条：第二排，压低 --------------------------- */

.bdbody .epbar {
  background: var(--panel2);
  border-bottom: 1px solid var(--line);
  padding: 6px 18px 7px;
}
.bdbody .eplab {
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: 0.14em;
  color: var(--ink3);
}
/*
 * 注意：这里只能用 background-color。
 * 写成 background:var(--panel) 是简写，会把上面那条规则设的箭头图（background-image）
 * 一起清掉 —— 下拉就会变回一个没有三角形的白框。
 */
.bdbody .epsel {
  background-color: var(--panel);
}
.bdbody .eptip {
  font-size: 11px;
  letter-spacing: 0.03em;
  color: var(--ink3);
}

/* --------------------- 四、左栏：剧本框变成"内嵌的书写面" --------------------- */

/*
 * 这是三层背景真正起作用的地方：
 * 左栏是 --panel（板子），剧本框是 --sunken（凹进去的书写面），
 * 一眼就能看出"这一大块是可以打字的"，而不是一段排版好的说明文字。
 */
.bdbody .bdleft {
  background: var(--panel);
  border-right: 1px solid var(--line);
}
.bdbody .bdbar {
  background: transparent;
  border-bottom: 1px solid var(--line);
  padding: 9px 12px;
}
.bdbody .bdbar b {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.03em;
}
.bdbody #script {
  background: var(--sunken);
  padding: 15px 18px;
  font-size: 13px;
  line-height: 1.9;
}
body.bdbody #script {
  box-shadow: inset 0 1px 2px rgba(16, 34, 66, 0.055), inset 0 0 0 1px rgba(255, 255, 255, 0.6);
}
[data-theme='dark'] body.bdbody #script {
  box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.35), inset 0 0 0 1px rgba(255, 255, 255, 0.018);
}
/* 原有一条 #script:focus{box-shadow:none;background:var(--panel)} 会把凹面顶平，
   这里按 id 加成重新压回去，只留一圈 accent 细边表示"在编辑" */
.bdbody #script:focus {
  background: var(--sunken);
  border: none;
  box-shadow: inset 0 0 0 1px var(--accent-line);
}

/* ---------------------------- 五、卡片：一块有光的板 ---------------------------- */

.bdbody .card {
  position: relative;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.02), rgba(255, 255, 255, 0) 46%), var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}
/* 顶上 1px 亮线，两端各收 16px、往右衰减 —— 像灯打在板子的上沿 */
.bdbody .card:before {
  content: '';
  position: absolute;
  left: 16px;
  right: 16px;
  top: 0;
  height: 1px;
  border-radius: 1px;
  pointer-events: none;
  background: var(--topline);
}
.bdbody .bdload {
  background: var(--bg);
  border-top: 1px solid var(--line);
}
.bdbody .bdcard {
  padding: 14px 15px 12px;
}
.bdbody .bdcard h2 {
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0.07em;
  margin-bottom: 3px;
}
.bdbody .bdcard h2 .hint {
  font-size: 10.5px;
  font-weight: 400;
  letter-spacing: 0.02em;
}
.bdbody .bdsub {
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: 0.07em;
  color: var(--ink3);
  margin: 0 0 9px;
}
.bdbody .bdsub b {
  color: var(--accent);
  font-weight: 600;
  letter-spacing: 0;
}
.bdbody .bdload .slot {
  gap: 10px;
  padding: 9px 10px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--sunken);
}
/* 序号从圆形换成小方牌：圆点在中文界面里太"软"，方牌配等宽数字才像仪表 */
.bdbody .bdload .slot .idx {
  width: 22px;
  height: 22px;
  border-radius: 6px;
  background: var(--accent-soft);
  border: 1px solid var(--accent-line);
  color: var(--accent);
  font-size: 11px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.bdbody .bdload .slot .nm {
  font-size: 12.5px;
  font-weight: 500;
  letter-spacing: 0.01em;
}
.bdbody .bdload .slot .mt {
  font-size: 10.5px;
  letter-spacing: 0.05em;
  color: var(--ink3);
  margin-top: 3px;
}
.bdbody .bdload .slot.click:hover {
  background: var(--panel2);
  border-color: var(--accent-line);
}
.bdbody .bdfoot2 {
  border-top: 1px solid var(--line);
  margin-top: 12px;
  padding-top: 11px;
}

/* ------------------------------ 六、对话气泡 ------------------------------ */

/*
 * 对话区底板：只留一团从正上方打下来的顶光，**不铺点阵**。
 *
 * 试过 22px 的点阵网格（透明度 4.5%），单看确实有"刻度感"，
 * 但压在两三千字的中文正文下面会变成一层噪点 —— 尤其是 Chromium 给渐变做抖动之后，
 * 点阵上会出现一团一团的明暗斑。写字的地方，底纹只许有一个方向的光，不许有图案。
 */
[data-theme='dark'] .bdbody .bdright {
  background:
    radial-gradient(680px 260px at 50% -6%, rgba(42, 212, 232, 0.055), transparent 70%),
    var(--bg);
}

.bdbody .chat {
  padding: 20px 24px 10px;
}
.bdbody .msg {
  gap: 12px;
  margin-bottom: 18px;
}
.bdbody .msg .av {
  width: 26px;
  height: 26px;
  border-radius: 7px;
  background: var(--sunken);
  border: 1px solid var(--line);
  color: var(--ink3);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.02em;
}
body.bdbody .msg .av {
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.7);
}
[data-theme='dark'] body.bdbody .msg .av {
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);
}
.bdbody .msg.me .av {
  background: var(--accent-soft);
  color: var(--accent);
  border-color: var(--accent-line);
}
.bdbody .bub {
  padding: 13px 16px;
  border-radius: 12px;
  border: 1px solid var(--bubline);
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.018), rgba(255, 255, 255, 0) 40%), var(--bubbg);
}
body.bdbody .bub {
  box-shadow: inset 0 1px 0 #fff, 0 1px 2px rgba(16, 34, 66, 0.05);
}
[data-theme='dark'] body.bdbody .bub {
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.045), 0 2px 8px rgba(0, 0, 0, 0.3);
}
.bdbody .bub .note {
  border-radius: 8px;
}
/* 气泡里的一级/二级标题也给一点字距，中文长句成段时更透气 */
.bdbody .bub h1,
.bdbody .bub h2,
.bdbody .bub h3,
.bdbody .bub h4 {
  letter-spacing: 0.02em;
}

/* ------------------------------ 七、输入区 ------------------------------ */

.bdbody .dock {
  background: var(--panel);
  border-top: 1px solid var(--line);
  padding: 12px 16px 9px;
}
.bdbody #ask {
  background: var(--sunken);
  border: 1px solid var(--line2);
  border-radius: 10px;
  padding: 11px 13px;
  font-size: 13px;
}
body.bdbody #ask {
  box-shadow: inset 0 1px 2px rgba(16, 34, 66, 0.055);
}
[data-theme='dark'] body.bdbody #ask {
  box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.3);
}
.bdbody #ask:focus {
  background: var(--sunken);
  border-color: var(--accent-line);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

/* ---------------------- 八、按钮：全页只有主按钮发光 ---------------------- */

.bdbody .btn {
  border-radius: 8px;
  border: 1px solid var(--line2);
  background: var(--panel2);
  color: var(--ink);
  transition: background 0.14s ease, border-color 0.14s ease, color 0.14s ease, box-shadow 0.16s ease;
}
.bdbody .btn:hover {
  background: var(--hover);
  border-color: var(--line2);
  color: var(--ink);
}
.bdbody .btn.ghost {
  border-color: transparent;
  background: transparent;
  color: var(--ink2);
}
.bdbody .btn.ghost:hover {
  background: var(--hover);
  color: var(--ink);
}
.bdbody .btn.sm {
  border-radius: 7px;
}
.bdbody .btn.primary {
  background: var(--btn-main);
  border-color: transparent;
  color: var(--btn-main-ink);
  font-weight: 600;
  letter-spacing: 0.02em;
  box-shadow: var(--btn-main-glow);
}
.bdbody .btn.primary:hover {
  background: var(--btn-main);
  filter: brightness(1.08);
}

/* ------------------------------ 九、滚动条 ------------------------------ */

/*
 * 不处理这一条，前面全白做：深色面板里挂一条系统浅灰滚动条
 * （装载区那条细白杠就是这么来的），一眼就露馅。
 */
.bdbody ::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}
.bdbody ::-webkit-scrollbar-track {
  background: transparent;
}
.bdbody ::-webkit-scrollbar-thumb {
  background: var(--sb);
  border: 3px solid transparent;
  background-clip: padding-box;
  border-radius: 8px;
}
.bdbody ::-webkit-scrollbar-thumb:hover {
  background: var(--accent-line);
  background-clip: padding-box;
}
.bdbody ::-webkit-scrollbar-corner {
  background: transparent;
}

/* --------------------------- 十、模组抽屉同材质 --------------------------- */

.bdbody .modpanel {
  background: var(--panel);
  border-left: 1px solid var(--line);
}
[data-theme='dark'] .bdbody .modpanel {
  box-shadow: -10px 0 40px rgba(0, 0, 0, 0.55);
}
.bdbody .modpanel h3 {
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0.06em;
}
.bdbody .vistext {
  background: var(--sunken);
  border: 1px solid var(--line2);
  border-radius: 10px;
}
.bdbody .bdhelp {
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

/* ---------------------- 十一、思考过程（流式时可见） ---------------------- */
/*
 * 2026-11-02 用户要求：「发出去之后要有思考过程，思考结束它消失、出现结果」。
 *
 * 面板挂在 .bub 外面（.msg 里、气泡前面），因为气泡内容每 110ms 会被重写一次。
 * 正文一到 JS 直接把整块 remove()，这里不需要做淡出之类的收尾动画 ——
 * 真要做也是 transition 结束再删，反而会让"结果出现"晚一拍，不如直接收。
 */
.thinklive {
  flex: 1 1 auto;
  min-width: 0;
  max-width: 100%;
  border: 1px solid var(--line2);
  border-left: 3px solid var(--accent-line);
  border-radius: 10px;
  background: var(--sunken);
  padding: 9px 12px 10px;
  margin-bottom: 8px;
}
.tkhead {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--ink2);
  letter-spacing: 0.02em;
}
.tkdot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
  animation: tkpulse 1.1s ease-in-out infinite;
}
@keyframes tkpulse {
  0%, 100% { opacity: 0.25; transform: scale(0.85); }
  50% { opacity: 1; transform: scale(1); }
}
.tkcount {
  margin-left: auto;
  font-size: 10.5px;
  font-weight: 400;
  color: var(--ink3);
  font-variant-numeric: tabular-nums;
}
.tkbody {
  margin-top: 7px;
  max-height: 232px;
  overflow-y: auto;
  white-space: pre-wrap;
  word-break: break-word;
  font-size: 12px;
  line-height: 1.72;
  color: var(--ink3);
  /* 等宽会中文发虚，思考过程用正文字体更好读 */
  letter-spacing: 0.01em;
}
/* 失败时保留这块，但把"活着"的感觉收掉：不闪、改成告警色 */
.thinklive.dead {
  border-left-color: var(--warn);
}
.thinklive.dead .tkdot {
  animation: none;
  background: var(--warn);
  opacity: 0.9;
}
.thinklive.dead .tkhead {
  color: var(--warn);
}

/* 思考面板和气泡要**上下排**：.msg 是 flex row（头像 | 气泡），
   多插一个子元素会变成第三列，所以 send() 里先包一层 .msgcol。 */
.msgcol {
  flex: 1 1 auto;
  min-width: 0;
  max-width: calc(100% - 36px);
  display: flex;
  flex-direction: column;
}
.msgcol .bub {
  max-width: 100%;
}
