/* ==================================================================
 * app.css —— filmstudio 界面层
 *
 * 设计方向 Editorial / Organic：暖纸底 + 印刷色（陶土朱 / 橄榄 / 芥末），
 * 宋体标题、细墨线、书脊标记。禁用纯黑与紫（见 js/theme.js 说明）。
 * ⚠️ :root 里的颜色是 js/theme.js 的镜像，测试会逐字比对，别单独改一边。
 *
 * ----------------------------------------------------------------
 * 2026-10-13 界面改版（三件事，都不是"换个皮"）
 *
 * ① 视觉层级：原来卡片标题 13px 比正文 14px 还小，一页读完抓不到结构。
 *    现在有完整的字号/间距令牌（--fs-* / --sp-*），卡片标题 16px 加重、
 *    每块内容前有一条"眉标"（eyebrow），宣传片页的四个卡片带大号步骤数字。
 * ② 无障碍：WCAG 2.1 AA 实测修订 ——
 *    · --ink-3 原来 #9A8C7C 在卡片上只有 3.22:1（低于正文 4.5:1），改 #7E7062（4.72:1）；
 *    · 表单控件边界原来 1.7:1，低于非文本对比 3:1（1.4.11），新增 --field-line #8F8066（3.14:1）；
 *    · 主按钮从 --accent（白字 4.34:1）改 --accent-deep（6.20:1）；
 *    · 补齐 :focus-visible（原来 chip / 圆点 / 场景卡片 / summary 都没有焦点环）、
 *      跳过导航、aria 状态同步、prefers-reduced-motion。
 * ③ 交互：宣传片页 4 个大卡片原来要滚很久 —— 加吸顶步骤导航（滚动联动高亮）、
 *    长说明折进 <details>、预览卡片吸顶、预览可全屏放大；空列表有引导文案。
 * ================================================================== */
:root{
  /* —— 纸面 —— */
  --paper:#F7F2E9;      --card:#FFFDF8;      --trough:#EFE7D9;  --trough-deep:#E5DAC7;
  /* —— 墨（深棕）—— */
  --ink:#33291F;        --ink-2:#6E6053;     --ink-3:#7E7062;
  /* —— 线 —— */
  --rule:#E2D6C0;       --rule-2:#D3C3A8;
  /* —— 语义 —— */
  --accent:#C05A38;     --accent-deep:#9E4526; --olive:#4E6B45;
  --brick:#B23A2C;      --gold:#B8892B;

  /* —— 无障碍补充（UI 专用，canvas 用不到）——
   * field-line：交互控件边界，实测 3.14:1 on trough（WCAG 1.4.11 要求 ≥3:1）
   * focus：焦点环，用 accentDeep（6.20:1 on card）而不是浅色 accent */
  --field-line:#8F8066;
  --focus:#9E4526;

  /* —— 字体：标题走宋体（印刷感），正文走苹方，数据走等宽 —— */
  --serif:"Songti SC","STSong","Source Han Serif SC","Noto Serif CJK SC","SimSun",serif;
  --sans:"PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif;
  --mono:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;

  /* —— 字号刻度（5 档，别再随手写 11.5px）—— */
  --fs-xs:11.5px;     /* 角标 / 脚注 */
  --fs-sm:12.5px;     /* 状态行 / 说明 */
  --fs-md:13.5px;     /* 控件 / 段落 */
  --fs-body:15px;     /* 正文 */
  --fs-h2:16px;       /* 卡片标题 */
  --fs-h1:21px;       /* 顶栏标题 */
  --fs-display:24px;  /* 区块大标题 */

  /* —— 间距刻度 —— */
  --sp-1:4px; --sp-2:8px; --sp-3:12px; --sp-4:16px; --sp-5:20px; --sp-6:28px;

  /* 顶栏 / 步骤条的实际高度：吸顶元素与锚点偏移都靠它们对齐。
     CSS 给桌面默认值，js/ui.js 加载后按实测值改写（手机上顶栏会换行，写死必然错位）。 */
  --topbar-h:64px;
  --steps-h:0px;

  /* 输入框/下拉的宽度上限。268px 不是随便定的：最长的下拉选项
     「简笔画（剪影 · 平涂 + 单一外轮廓，认型不复杂）」按 13.5px 量约 324px，
     原来 240px 会被 Chrome 从中间硬切，用户看到半句话。选项文字已同步缩短，
     这里再给足余量。 */
  --field-cap:268px;

  --r-sm:3px; --r-md:5px; --r-pill:999px;
  --sh-1:0 1px 2px rgba(51,41,31,.04), 0 8px 20px -14px rgba(51,41,31,.18);
  --sh-2:0 2px 6px rgba(51,41,31,.08), 0 16px 32px -18px rgba(51,41,31,.26);
  --ease:cubic-bezier(.16,1,.3,1);
}

*{box-sizing:border-box}
html,body{margin:0;padding:0}
html{scroll-behavior:smooth}
body{
  background:var(--paper);
  color:var(--ink);
  font:var(--fs-body)/1.62 var(--sans);
  min-height:100vh; padding-bottom:40px;
  -webkit-text-size-adjust:100%;
  background-image:
    /* 极淡的纸纹：两道斜向暖色高光，避免大片纯色死板 */
    radial-gradient(900px 380px at 8% -8%, rgba(192,90,56,.055) 0%, transparent 62%),
    radial-gradient(760px 320px at 96% 4%, rgba(78,107,69,.05) 0%, transparent 60%);
  background-attachment:fixed;
}
.mono{font-family:var(--mono)}
.dim{color:var(--ink-2)}
/* 状态文字（模型清单那一行的小字）：跟 .hint 一个语义色，但走等宽 */
.mono.ok{color:var(--olive)}
.mono.bad{color:var(--brick)}

/* 只给读屏用的文字 */
.sr-only{
  position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);white-space:nowrap;border:0;
}

/* 跳过导航（键盘用户第一下 Tab 就能跳过顶栏） */
.skip{
  position:absolute;left:-9999px;top:0;z-index:120;
  background:var(--accent-deep);color:#FFFDF8;padding:10px 16px;
  border-radius:0 0 var(--r-md) 0;font-size:var(--fs-md);text-decoration:none;
}
.skip:focus{left:0}

/* 滚动条（暖色化，别是系统灰） */
::-webkit-scrollbar{width:10px;height:10px}
::-webkit-scrollbar-track{background:#EFE7D9}
::-webkit-scrollbar-thumb{background:#D3C3A8;border-radius:6px;border:2px solid #EFE7D9}
::-webkit-scrollbar-thumb:hover{background:#BFAF92}

/* 统一的焦点环：以前只有部分控件有，chip / 圆点 / 场景卡片 / summary 全部漏掉 */
:where(a,button,input,select,textarea,summary,[tabindex]):focus-visible{
  outline:2px solid var(--focus);outline-offset:2px;border-radius:var(--r-sm);
}
:where(button,input,select,textarea,summary){accent-color:var(--accent)}

/* ---------- 顶栏 ---------- */
.topbar{
  display:flex;align-items:center;justify-content:space-between;gap:18px;flex-wrap:wrap;
  padding:14px 24px 12px;
  background:rgba(255,253,248,.92); backdrop-filter:blur(8px);
  border-bottom:1px solid var(--rule-2);
  position:sticky; top:0; z-index:20;
  box-shadow:0 1px 0 rgba(51,41,31,.06);
}
.topbar::after{ /* 底边一道陶土色印刷基线，右下角渐隐 —— 打破水平直线 */
  content:''; display:block; position:absolute; left:0; right:0; bottom:-1px; height:2px;
  background:linear-gradient(90deg,var(--accent) 0%,var(--accent) 62%,rgba(192,90,56,0) 100%);
}
.brand{display:flex;align-items:center;gap:12px;min-width:0}
.logo{
  width:38px;height:38px;border-radius:10px;display:grid;place-items:center;flex:none;
  background:var(--accent);color:#FFFDF8;
  box-shadow:0 1px 0 rgba(255,255,255,.35) inset, 0 2px 6px rgba(158,69,38,.28);
}
.logo svg{width:21px;height:21px;display:block}
.topbar h1{
  margin:0;font-family:var(--serif);font-size:var(--fs-h1);font-weight:700;
  letter-spacing:.6px;color:var(--ink);line-height:1.2;
}
.sub{margin:2px 0 0;font-size:var(--fs-xs);color:var(--ink-2);letter-spacing:.2px}

/* 标签页＝印刷书脊标签 */
.tabs{display:flex;gap:0;background:transparent;padding:0}
/* ⚠️ 这里不能设 gap（2026-10-12 实测）：「诗境」外链页签在 <nav class="tabs"> 之外，
   topbar-nav 的 gap:10px 会加在它前面，造成页签间距 6px / 16px 明显不等。
   间距统一由 .tab{margin-right:6px} 管，容器 gap 必须为 0 */
.topbar-nav{display:flex;align-items:center}
.tab-ext{text-decoration:none;margin-right:0}
/* 外链页签（诗境）：与页内两个书脊页签完全同形 */
.tab{
  border:1px solid var(--rule-2);border-bottom:0;background:transparent;
  color:var(--ink-2);padding:9px 20px;font-family:var(--serif);
  font-size:var(--fs-md);letter-spacing:.8px;cursor:pointer;
  transition:color .22s var(--ease), background-color .22s var(--ease);
  /* 2026-10-12：去掉斜角切边——斜边（9px）比页签间距（6px）还宽，
     相邻页签的视觉间距一边 15px 一边 3px，用户反馈「3 个间距不一样」。
     直边后三个页签间距严格相等 */
  margin-right:6px;
}
.tab:first-child{margin-left:0}
.tab:hover{color:var(--accent-deep);background:rgba(192,90,56,.06)}
/* 激活页签＝同款轮廓 + 加粗墨字 + 陶土底线（三个页签完全同形，只有颜色区分状态） */
.tab[aria-selected="true"]{
  color:var(--ink);font-weight:700;
  box-shadow:inset 0 -3px 0 var(--accent);
}

main{max-width:1240px;margin:0 auto;padding:22px 22px 0}
.panel{display:none;animation:rise .45s var(--ease)}
.panel.active{display:block}
@keyframes rise{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}

/* ---------- 区块引导（眉标 + 大标题 + 一句话）----------
 * 以前两个 tab 之间没有任何"这里是干什么的"，全靠读卡片标题拼。
 * 眉标走等宽小字 + 陶土色短横线，跟卡片标题区分开。 */
.panel-head{max-width:64ch;margin:6px 0 var(--sp-5)}
.panel-head .eyebrow{
  margin:0 0 6px;display:flex;align-items:center;gap:8px;
  font-family:var(--mono);font-size:var(--fs-xs);letter-spacing:1.4px;
  color:var(--accent-deep);text-transform:uppercase;
}
.panel-head .eyebrow::before{content:'';width:18px;height:2px;background:var(--accent);flex:none}
.panel-head h2{
  margin:0;font-family:var(--serif);font-size:var(--fs-display);font-weight:700;
  letter-spacing:.4px;line-height:1.28;
}
.panel-head .lede{margin:6px 0 0;font-size:var(--fs-md);color:var(--ink-2);line-height:1.7}

/* ---------- 步骤导航（宣传片页吸顶）----------
 * 四个卡片一屏放不下，原来只能靠滚。现在顶栏下方一条吸顶进度条，
 * 点一下跳过去，滚到哪里高亮哪里（JS 在 js/ui.js，纯增强，没有也不影响用）。 */
/* ⚠️ top 必须等于顶栏高度：顶栏也是 sticky（z-index 20），写 top:0 会被它整个盖住——
 *    手机上实测就是这么消失的（顶栏 123px 高，步骤条钻到它下面去了）。 */
.steps{
  position:sticky;top:var(--topbar-h);z-index:15;
  display:flex;gap:var(--sp-2);align-items:center;
  margin:0 0 var(--sp-4);padding:8px 10px;
  background:rgba(247,242,233,.94);backdrop-filter:blur(6px);
  border:1px solid var(--rule);border-radius:var(--r-md);
  overflow-x:auto;
}
.step-btn{
  display:flex;align-items:center;gap:7px;flex:1 1 auto;justify-content:center;
  appearance:none;border:0;background:transparent;cursor:pointer;
  padding:7px 10px;border-radius:var(--r-sm);
  font:inherit;font-size:var(--fs-md);color:var(--ink-2);white-space:nowrap;
  transition:color .18s var(--ease), background-color .18s var(--ease);
}
.step-btn b{
  font-family:var(--mono);font-size:var(--fs-xs);font-weight:700;
  width:20px;height:20px;border-radius:50%;display:grid;place-items:center;flex:none;
  background:var(--trough-deep);color:var(--ink-2);border:1px solid var(--rule-2);
}
.step-btn:hover{color:var(--ink);background:var(--trough)}
.step-btn.on{color:var(--ink);font-weight:600}
.step-btn.on b{background:var(--accent);color:#FFFDF8;border-color:var(--accent)}

/* 锚点滚动时别被吸顶顶栏 + 步骤条盖住（顶栏高 + 步骤条高 + 余量） */
[id^="step-"]{scroll-margin-top:calc(var(--topbar-h) + var(--steps-h) + 14px)}

/* ⚠️ 尾部留白不是装饰，是步骤条能对上号的前提：
 *    「节奏 / 导出」两块比视口矮，页面滚到底它们也顶不到阈值线 ——
 *    实测点「2 节奏」时整页已滚到底，step-2 的 top 还在 354px（阈值 147），
 *    高亮只能卡在前一块上。留出接近一屏的余量，最后两步才能各自滚到顶部。
 *    （这个坑是 headless 实测出来的，肉眼只会觉得"高亮偶尔不听话"。） */
#panel-film .grid-2>.col{padding-bottom:min(56vh,560px)}

/* 主栅格：7:5 不对称 —— 左工作区，右预览抽屉，中缝靠竖墨线分栏 */
.grid-2{display:grid;grid-template-columns:minmax(0,1.66fr) minmax(0,1fr);gap:0 26px;align-items:start}
.grid-2>.col:nth-child(2){
  border-left:1px solid var(--rule);
  padding-left:26px; position:relative;
  /* 右列拉伸到整行高度（左列有多高它就有多高）—— 这是预览能一直吸顶的前提，见下面 .sticky-wrap 的注释 */
  align-self:stretch;
}
.grid-2>.col:nth-child(2)::before{ /* 中缝顶端的书脊小方块 */
  content:'';position:absolute;left:-1px;top:-6px;width:3px;height:26px;background:var(--accent);
}
@media(max-width:1000px){
  .grid-2{grid-template-columns:1fr;gap:0}
  .grid-2>.col:nth-child(2){border-left:0;padding-left:0;margin-top:8px}
  .grid-2>.col:nth-child(2)::before{display:none}
}

/* ---------- 卡片 ---------- */
.card{
  background:var(--card);border:1px solid var(--rule);border-radius:var(--r-md);
  padding:17px 19px;margin-bottom:18px;position:relative;
  box-shadow:var(--sh-1);
  transition:border-color .25s var(--ease), box-shadow .25s var(--ease);
}
.card::before{ /* 书脊：左上角一道 3px 陶土短线 */
  content:'';position:absolute;left:-1px;top:16px;width:3px;height:22px;
  background:var(--accent);opacity:.8;
}
.card:hover{border-color:var(--rule-2);box-shadow:var(--sh-2)}
/* 预览区吸顶：滚到下面填文案 / 定节奏时，画面一直看得见。
 * ⚠️ 三个实测踩到的坑，别照"常识"改回去：
 *   ① 吸顶元素的**可移动范围由包含块的内容盒决定**，给列加 padding-bottom 完全不延长吸附距离：
 *      右列是 grid item，`align-items:start` 时它只有内容那么高，实测只吸了 190px
 *      （offsetTop 卡死在 193px）就跟着页面滑走。正解：右列 `align-self:stretch` 撑满整行，
 *      再把两张卡片包进这一个吸顶容器；
 *   ② 吸附终点是右列内容盒底部（约在「导出」那一步之前）。想让预览跟到页面最底，
 *      得往右列塞真实内容 —— 试过塞占位块，因为右列是拉伸的、内容多少不影响高度，实测无效，
 *      所以没留这段死代码；
 *   ③ top 要同时让开顶栏和步骤条，两个高度都是实测值（--topbar-h / --steps-h，见 js/ui.js）。 */
@media(min-width:1001px){
  .sticky-wrap{position:sticky;top:calc(var(--topbar-h) + var(--steps-h,0px) + 10px);z-index:10}
}

/* 卡片头：标题 16px 重字重（原来 13px 比正文还小），右边放操作 */
.card-hd{
  display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3);
  flex-wrap:wrap;margin-bottom:var(--sp-3);
  padding-bottom:10px;border-bottom:1px solid var(--rule);
}
.card-hd h2{
  margin:0;font-family:var(--serif);font-size:var(--fs-h2);font-weight:700;
  letter-spacing:.3px;color:var(--ink);display:flex;align-items:center;gap:9px;
}
.card-hd h2::before{ /* 印刷色短线，替掉以前的「· 」前缀 */
  content:'';width:4px;height:15px;border-radius:1px;background:var(--accent);flex:none;
}
.card-hd h2 .card-no{ /* 步骤大号数字：0 文案 / 1 填内容 / 2 定节奏 / 3 导出 */
  font-family:var(--mono);font-size:var(--fs-h2);font-weight:700;color:var(--accent);
  letter-spacing:0;line-height:1;
}
.card-hd .hint{margin:0}
.col{min-width:0}

/* ---------- 折叠说明 / 速查 ----------
 * 原来十几段 300 字的"为什么这么做"全铺在界面上，把控件都压没了。
 * 能操作的提示留在外面，解释性的折进 <details>。 */
.note{margin-top:10px;border-top:1px dashed var(--rule-2);padding-top:9px}
.note>summary{
  cursor:pointer;list-style:none;display:flex;align-items:center;gap:6px;
  font-size:var(--fs-sm);color:var(--ink-2);
}
.note>summary::-webkit-details-marker{display:none}
.note>summary::before{
  content:'';width:6px;height:6px;border-right:1.5px solid var(--ink-3);border-bottom:1.5px solid var(--ink-3);
  transform:rotate(-45deg);transition:transform .2s;flex:none;margin-left:2px;
}
.note[open]>summary::before{transform:rotate(45deg)}
.note>summary:hover{color:var(--ink)}
.note[open]>summary{color:var(--ink);font-weight:600}
.note>.hint{margin-top:8px}

/* 整卡折叠（乐谱格式速查）：标题本身就是开关 */
details.card>summary{list-style:none;cursor:pointer}
details.card>summary::-webkit-details-marker{display:none}
details.card>summary.card-hd{margin-bottom:0;border-bottom:0;padding-bottom:0}
details.card[open]>summary.card-hd{margin-bottom:var(--sp-3);border-bottom:1px solid var(--rule);padding-bottom:10px}
details.card>summary.card-hd::after{
  content:'展开';font-family:var(--mono);font-size:var(--fs-xs);color:var(--ink-2);font-weight:400;
}
details.card[open]>summary.card-hd::after{content:'收起'}

textarea,#stage,#wave,#timeline,canvas{max-width:100%}
textarea{
  width:100%;background:var(--trough);color:var(--ink);border:1px solid var(--field-line);border-radius:var(--r-md);
  padding:11px 12px;font-family:var(--mono);font-size:var(--fs-sm);line-height:1.6;resize:vertical;
  transition:border-color .22s var(--ease), box-shadow .22s var(--ease), background-color .22s;
}
textarea:focus,#stage:focus{
  outline:none;
  border-color:var(--accent-deep);
  background:var(--card);
  box-shadow:0 0 0 3px rgba(158,69,38,.18);
}

#wave{width:100%;height:150px;display:block;background:var(--trough);border:1px solid var(--rule-2);border-radius:var(--r-md)}
#stage{
  width:100%;aspect-ratio:16/9;display:block;background:#E9E0CE;border:1px solid var(--rule-2);border-radius:var(--r-md);
}
/* 3D：GL 画布给 WebGL 当离屏画板，真正给眼睛看的是 stage（3D 帧 + 字幕都合成在它上面）。
   ⚠️ 这里绝不能写 display:block —— 作者样式会盖掉 hidden 属性，
      那块没画过东西的 GL 画布（alpha:false，默认就是不透明黑）就一直盖在预览区上 = 黑屏。 */
#stage-wrap{position:relative;line-height:0}
#gl{position:absolute;left:0;top:0;width:100%;height:100%;display:block;border-radius:var(--r-md)}
#gl[hidden]{display:none}   /* 优先级要压过上面那行 display:block */

/* 预览全屏：预览卡片在窄列里只有 400 多 px，字幕根本看不清。
   放大后按 16:9 居中铺满视口，Esc 退出（js/ui.js）。 */
#stage-wrap.full{
  position:fixed;inset:0;z-index:100;line-height:0;
  background:#2A231C;
  display:flex;align-items:center;justify-content:center;padding:28px;
}
#stage-wrap.full #stage{
  width:auto;height:auto;max-width:100%;max-height:100%;
  box-shadow:0 24px 60px -20px rgba(51,41,31,.7);
}
#stage-wrap.full #gl{display:none}
.zoom-close{
  display:none;position:absolute;right:16px;top:14px;
  appearance:none;border:1px solid rgba(255,253,248,.35);background:rgba(42,35,28,.7);
  color:#F7F2E9;font:inherit;font-size:var(--fs-md);padding:8px 14px;border-radius:var(--r-md);cursor:pointer;
  line-height:1.35;   /* 父级 #stage-wrap 是 line-height:0（画布排版用），这里得撑回来 */
}
#stage-wrap.full .zoom-close{display:block}
body.zoomed{overflow:hidden}

.f3d-panel{
  border:1px solid var(--rule);border-left:3px solid var(--olive);
  border-radius:var(--r-md);background:var(--trough);padding:12px 14px;margin:var(--sp-3) 0;
}
.f3d-panel .mf-rec{margin-top:10px}
#timeline{width:100%;height:90px;display:block;background:var(--trough);border:1px solid var(--rule-2);border-radius:var(--r-md)}
canvas{cursor:crosshair}

/* ---------- 说明文字 / 代码块 ---------- */
.hint{margin-top:9px;font-size:var(--fs-sm);color:var(--ink-2);line-height:1.7}
.hint b{color:var(--ink);font-weight:600}
.hint.ok{color:var(--olive)}
.hint.bad{color:var(--brick)}
.code{
  margin:0;background:var(--trough);border:1px solid var(--rule-2);border-radius:var(--r-md);padding:11px 13px;
  font-family:var(--mono);font-size:var(--fs-sm);color:var(--ink);overflow-x:auto;line-height:1.6;
}
.tips{margin:8px 0 0;padding-left:18px;color:var(--ink-2);font-size:var(--fs-md)}
.tips li{margin:3px 0}
code{font-family:var(--mono);background:var(--trough-deep);border:1px solid var(--rule);border-radius:var(--r-sm);padding:1px 5px;color:var(--accent-deep);font-size:.94em}

/* ---------- 控件 ---------- */
.btn{
  background:var(--card);color:var(--ink);border:1px solid var(--field-line);border-radius:var(--r-md);
  padding:8px 14px;font-size:var(--fs-md);font-family:inherit;cursor:pointer;white-space:nowrap;
  min-height:36px;display:inline-flex;align-items:center;justify-content:center;gap:5px;
  transition:background-color .16s var(--ease), border-color .16s var(--ease), color .16s var(--ease);
}
.btn:hover{background:var(--trough);border-color:var(--ink-3)}
.btn:active{transform:translateY(1px)}
.btn.primary{background:var(--accent-deep);color:#FFFDF8;border-color:var(--accent-deep);font-weight:600}
.btn.primary:hover{background:var(--accent);border-color:var(--accent)}
.btn.ghost{background:transparent;color:var(--ink-2);border-color:transparent;text-decoration:underline;text-decoration-color:var(--rule-2);text-underline-offset:3px}
.btn.ghost:hover{background:var(--trough);text-decoration-color:var(--accent);color:var(--ink)}
.btn[disabled]{opacity:.45;cursor:not-allowed}
.btn-row{display:flex;gap:var(--sp-2);flex-wrap:wrap;margin-top:var(--sp-3);align-items:center}
.btn-row.inline{align-items:center;margin-top:9px}
.btn-row.wrap .btn{flex:1 1 auto;min-width:126px}
.row-gap{display:flex;gap:var(--sp-2);flex-wrap:wrap}

.chip{
  background:var(--card);border:1px solid var(--rule-2);color:var(--ink-2);border-radius:var(--r-pill);
  padding:5px 13px;font-size:var(--fs-sm);cursor:pointer;font-family:inherit;
  transition:color .16s var(--ease), border-color .16s var(--ease), background-color .16s var(--ease);
}
.chip:hover{color:var(--accent-deep);border-color:var(--accent);background:rgba(192,90,56,.06)}

/* 字段行：标签在上、控件在下（原来 label 里外两套字号混着用） */
.field-row{display:flex;gap:var(--sp-4);flex-wrap:wrap;align-items:flex-end}
label{font-size:var(--fs-sm);color:var(--ink-2);display:flex;flex-direction:column;gap:5px}
.fl{font-size:var(--fs-sm);color:var(--ink-2);display:block;margin-bottom:11px}
/* 控件宽度上限走变量：手机上一行只有一个控件，让它铺满更好按（媒体查询里改 --field-cap 即可，
 * 比在媒体查询里重写一堆选择器可靠 —— 属性选择器的优先级会压过后写的规则）。 */
.fl input[type=text],.fl input:not([type]),.fl input[type=password],.fl select,
.field-row select,.field-row input[type=text],.field-row input[type=number],.field-row input:not([type]){
  background:var(--trough);border:1px solid var(--field-line);color:var(--ink);border-radius:var(--r-md);
  padding:7px 10px;font-size:var(--fs-md);font-family:inherit;width:100%;max-width:var(--field-cap);
}
/* 行内字段：「长度 [12] 小节」这种带单位后缀的，别让 select 掉到下一行去 */
.fi{
  display:flex;flex-direction:row!important;align-items:center;gap:6px;
  color:var(--ink-2);font-size:var(--fs-sm);margin-bottom:11px;
}
.fi select,.fi input{width:auto;max-width:130px;flex:0 0 auto}
.fl input:focus,.fl select:focus,.field-row input:focus,.field-row select:focus{
  outline:none;border-color:var(--accent-deep);background:var(--card);box-shadow:0 0 0 3px rgba(158,69,38,.16);
}
.sw-model-select{margin-top:5px}
select{appearance:none;padding-right:26px;cursor:pointer;
  background-image:linear-gradient(45deg,transparent 50%,var(--ink-3) 50%),linear-gradient(135deg,var(--ink-3) 50%,transparent 50%);
  background-position:calc(100% - 14px) 52%,calc(100% - 9px) 52%;background-size:5px 5px,5px 5px;background-repeat:no-repeat;
}
input[type=range]{width:100%;max-width:220px}
.chk{display:flex;flex-direction:row!important;align-items:center;gap:7px;color:var(--ink);font-size:var(--fs-md);white-space:nowrap;padding-bottom:8px}
.chk input[type=checkbox]{width:16px;height:16px}

.progress{height:5px;background:var(--trough-deep);border:1px solid var(--rule);border-radius:3px;margin-top:var(--sp-3);overflow:hidden}
.progress-bar{height:100%;width:0;background:linear-gradient(90deg,var(--accent),var(--olive));transition:width .1s linear}

/* ---------- 段落卡片 ---------- */
.scenes{display:flex;flex-direction:column;gap:6px;margin:6px 0 10px}
/* 空列表引导（原来是一块空白，用户不知道下一步点哪） */
.scenes:empty::after{
  content:'还没有段落 —— 点下面的「加一段」，或把整篇文案粘到上面点「粘贴全文自动分段」';
  display:block;padding:16px;text-align:center;font-size:var(--fs-md);color:var(--ink-2);
  border:1px dashed var(--rule-2);border-radius:var(--r-md);background:var(--trough);
}
.scene{
  background:var(--trough);border:1px solid var(--rule);border-radius:var(--r-md);
  padding:6px 10px;display:flex;gap:var(--sp-2);align-items:center;
  transition:border-color .18s, background-color .18s;
}
.scene:hover{border-color:var(--rule-2);background:#EFE6D4}
.scene:focus-within{border-color:var(--accent)}
.scene .idx{
  flex:0 0 auto;width:26px;height:26px;border-radius:var(--r-sm);display:grid;place-items:center;
  background:var(--card);color:var(--ink-2);font-family:var(--mono);font-size:var(--fs-xs);
  border:1px solid var(--rule-2);font-weight:600;
}
.scene .body{flex:1 1 auto;display:flex;gap:10px;min-width:0;align-items:center}
.scene .body input{
  background:transparent;border:1px solid transparent;border-radius:var(--r-sm);color:var(--ink);
  padding:6px 8px;font-size:var(--fs-md);font-family:inherit;
  /* ⚠️ min-width:0 不能省：input 的 min-width:auto 会解析成"内容最小宽度"
   *（≈默认 size=20 字符 ≈170px），flex 项就压不下去 ——
   * 实测 390px 手机上这一行会把整页撑到 575px，浏览器只好整体缩到 68%。
   * 这是**改版前就存在**的问题（原版 HEAD 同样 573px）。 */
  min-width:0;max-width:none;
  transition:background-color .15s, border-color .15s;
}
.scene .body input:first-child{flex:0 0 35%;font-weight:600}
.scene .body input:last-child{flex:1 1 auto;color:var(--ink-2)}
.scene .body input:focus{background:var(--card);border-color:var(--accent-deep);outline:none;color:var(--ink)}
.scene .del{
  flex:0 0 auto;background:transparent;border:0;color:var(--ink-2);cursor:pointer;
  padding:4px 8px;font-size:17px;line-height:1;border-radius:var(--r-sm);
  transition:color .15s, background-color .15s;
}
.scene .del:hover{color:var(--brick);background:rgba(178,58,44,.08)}

/* ---------- 图形/源码 切换 ---------- */
.seg{display:flex;gap:0;background:var(--trough);border:1px solid var(--rule-2);border-radius:var(--r-md);padding:2px}
.seg-btn{
  border:0;background:transparent;color:var(--ink-2);padding:6px 13px;border-radius:var(--r-sm);
  font-size:var(--fs-sm);cursor:pointer;font-family:inherit;display:inline-flex;align-items:center;gap:5px;
  transition:color .16s var(--ease), background-color .16s var(--ease);
}
.seg-btn.active{background:var(--card);color:var(--ink);font-weight:600;box-shadow:0 1px 2px rgba(51,41,31,.12)}
.seg-btn:not(.active):hover{color:var(--accent-deep)}

/* ---------- 钢琴卷帘 ---------- */
.roll-bar{display:flex;gap:var(--sp-3);flex-wrap:wrap;align-items:flex-end;margin-bottom:10px}
.roll-bar label{font-size:var(--fs-xs);flex-direction:row;align-items:center;gap:6px}
.roll-bar input[type=number],.roll-bar select{
  background:var(--trough);border:1px solid var(--field-line);color:var(--ink);border-radius:var(--r-md);
  padding:5px 8px;font-size:var(--fs-sm);font-family:var(--mono);width:82px;
}
.roll-bar select{width:78px}
.roll-wrap{overflow-x:auto;border:1px solid var(--rule-2);border-radius:var(--r-md);background:var(--trough)}
#roll{display:block;touch-action:none}

.roll-tracks{display:flex;flex-direction:column;gap:6px;margin-top:10px}
.trow{
  display:flex;align-items:center;gap:var(--sp-2);background:var(--card);border:1px solid var(--rule);
  border-left:3px solid var(--ink-3);border-radius:var(--r-md);padding:5px 8px;transition:.16s;
}
.trow.on{border-color:var(--accent);background:#FBEEE6;border-left-color:var(--accent)}
.trow input.tn{
  background:transparent;border:1px solid transparent;border-radius:var(--r-sm);color:var(--ink);
  padding:4px 7px;font-size:var(--fs-sm);font-family:inherit;width:110px;flex:0 0 auto;
}
.trow input.tn:focus{background:var(--trough);border-color:var(--accent-deep);outline:none}
.trow select{
  flex:1 1 auto;min-width:0;width:auto;
  background:var(--trough);border:1px solid var(--field-line);color:var(--ink);border-radius:var(--r-md);
  padding:5px 24px 5px 8px;font-size:var(--fs-sm);
}
.trow .tdel{background:transparent;border:0;color:var(--ink-2);cursor:pointer;font-size:17px;padding:2px 7px;border-radius:var(--r-sm)}
.trow .tdel:hover{color:var(--brick);background:rgba(178,58,44,.08)}
.tadd{padding:5px 10px;font-size:var(--fs-sm)}

.roll-ops{display:flex;gap:7px;align-items:center;flex-wrap:wrap;margin-top:10px}
.roll-ops #roll-selinfo{font-size:var(--fs-sm);margin-right:auto}

/* ---------- 记录条（配乐说明 / 分镜摘要）----------
 * ⚠️ .mf-head / .mf-grid / .mf-chip / .mf-ops 是 main.js 的 mfShow() 用 innerHTML 拼的，
 *    以前 app.css 里一条规则都没有 —— 「这首曲子采了什么」整块是没样式的裸文字。
 *    现在按"素材标签 + 变形摘要"两行排版。 */
.mf-rec{
  margin-top:var(--sp-3);border:1px solid var(--rule);border-left:3px solid var(--gold);
  border-radius:var(--r-md);background:var(--trough);padding:11px 13px;
}
.mf-head{
  font-family:var(--mono);font-size:var(--fs-sm);color:var(--ink);line-height:1.6;
  padding-bottom:8px;margin-bottom:8px;border-bottom:1px dashed var(--rule-2);
}
.mf-grid{display:flex;flex-wrap:wrap;gap:6px}
.mf-chip{
  display:inline-flex;align-items:center;gap:5px;
  background:var(--card);border:1px solid var(--rule-2);border-radius:var(--r-pill);
  padding:3px 10px;font-size:var(--fs-xs);color:var(--ink-2);
}
.mf-chip b{color:var(--ink);font-weight:600}
.mf-ops{margin-top:9px;font-size:var(--fs-sm);color:var(--ink-2);line-height:1.7}
.mf-ops b{color:var(--ink)}

/* ---------- 折叠区（API 设置 / 说明）---------- */
.fold{border:1px solid var(--rule);border-radius:var(--r-md);background:var(--trough);margin-top:var(--sp-3);padding:8px 13px}
.fold>summary{cursor:pointer;font-size:var(--fs-sm);color:var(--ink-2);list-style:none;display:flex;align-items:center;gap:6px}
.fold>summary::-webkit-details-marker{display:none}
.fold>summary::before{content:'';width:0;height:0;border-left:5px solid var(--accent);border-top:4px solid transparent;border-bottom:4px solid transparent;transition:transform .2s}
.fold[open]>summary::before{transform:rotate(90deg)}
.fold>summary:hover{color:var(--ink)}
.fold-body{padding-top:11px}
.fold-body .field-row{gap:var(--sp-3)}

#f-scrub{width:100%;margin-top:10px}
#f-scene-dots{display:flex;gap:5px;margin-top:10px;flex-wrap:wrap;align-items:center}
/* 圆点是按钮（原来 div 点得动但键盘摸不到） */
.dot{
  appearance:none;border:0;padding:0;cursor:pointer;
  width:26px;height:6px;border-radius:3px;background:var(--rule-2);
  transition:width .2s var(--ease), background-color .2s var(--ease);
}
.dot.on{background:var(--accent);width:38px}
.dot:hover{background:var(--ink-3)}

/* ---------- 图标（内联 SVG sprite，零依赖；不用 emoji） ---------- */
.ico{
  width:13px;height:13px;flex:0 0 auto;vertical-align:-2px;overflow:visible;
  fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;
}
.btn .ico,.chip .ico,.tadd .ico{margin-right:1px}
.card-hd h2 .ico{width:15px;height:15px;color:var(--accent)}
.icon-btn{padding:6px 10px;min-height:32px}

/* ---------- 页脚 ---------- */
.foot{
  max-width:1240px;margin:var(--sp-6) auto 0;padding:14px 24px 0;border-top:1px solid var(--rule-2);
  color:var(--ink-2);font-size:var(--fs-xs);display:flex;justify-content:space-between;gap:var(--sp-3);flex-wrap:wrap;
}
.foot span:last-child{border:1px solid var(--rule);border-radius:var(--r-sm);padding:2px 8px;background:var(--card)}

/* ================================================================
 *  [hidden] 必须真的隐藏（2026-10-05 修）
 *
 *  截图里「3D 画质」在画面引擎=2D 时也露出来了。原因：
 *  `label{display:flex}` 和 `.fl{display:block}` 都是**类/元素选择器**，
 *  优先级高于 UA 样式表里的 `[hidden]{display:none}` —— 于是 hidden 属性
 *  被「display 声明」盖掉，元素照样显示。
 *  这不是某个控件的偶发问题，而是**所有用 hidden 控制的行**都会中招
 *  （3D 导演面板、场景行、字幕时间码…）。
 *  正解：全局加一条 `!important`（`!important` 才是这里唯一该用的场合——
 *  它要压的正是「别的选择器自带 display」这一类冲突）。
 * ================================================================ */
[hidden]{display:none !important}

/* ---- 场景面板：每段一个卡片，点卡片左边切换当前段 ---- */
.scenes2d{display:flex;gap:6px;flex-wrap:wrap;margin-top:8px}
/* 这些卡片现在由 JS 建成 <button>（键盘能用），所以要清掉按钮默认样式 */
.scenes2d .s2d{
  display:flex;align-items:center;gap:6px;appearance:none;font-family:inherit;text-align:left;
  padding:6px 10px;border:1px solid var(--rule-2);border-radius:var(--r-md);
  background:var(--trough);font-size:var(--fs-sm);color:var(--ink-2);cursor:pointer;
  max-width:220px;user-select:none;
  transition:border-color .16s var(--ease), color .16s var(--ease), background-color .16s var(--ease);
}
.scenes2d .s2d:hover{border-color:var(--accent);color:var(--ink)}
.scenes2d .s2d.on,
.scenes2d .s2d[aria-pressed="true"]{border-color:var(--accent);background:rgba(192,90,56,.07);color:var(--ink);font-weight:600}
.scenes2d .s2d .n{font-family:var(--mono);font-size:var(--fs-xs);color:var(--ink-2);flex:none}
.scenes2d .s2d .nm{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.scenes2d .s2d .ai{color:var(--accent-deep);font-size:var(--fs-xs);flex:none;font-weight:700}

/* ================================================================
 *  响应式 / 输入方式 / 动效偏好
 * ================================================================ */
@media(max-width:640px){
  :root{--field-cap:100%}   /* 手机上一行就一个控件，铺满更好按 */
  body{font-size:14.5px}
  main{padding:16px 14px 0}
  .topbar{padding:12px 14px 10px}
  .topbar .sub{display:none}          /* 手机上省下一行，顶栏别占半屏 */
  .topbar h1{font-size:18px}
  .panel-head h2{font-size:21px}
  .card{padding:14px;margin-bottom:14px}
  .foot{padding:12px 14px 0}
  /* 段落行改成上下两行：手机上两个输入框并排只剩 100 多 px，
     小标题和正文都看不清，不如各给一整行。 */
  .scene{flex-wrap:wrap}
  .scene .body{flex:1 1 100%;flex-direction:column;align-items:stretch;gap:2px}
  .scene .body input:first-child,.scene .body input:last-child{flex:0 0 auto;width:100%}
}

/* ---------- 手机（≤480px）：顶栏三个页签是最后一个溢出点 ----------
 * 360px 屏上品牌 + 3 页签 ≈ 336px 必溢出 → 页签缩字号缩内边距，
 * 实在不够就横向滚（滚动条藏掉，滑一下就到「诗境」） */
@media(max-width:480px){
  .topbar{gap:8px}
  .brand .logo{width:32px;height:32px}
  .topbar h1{font-size:15.5px;white-space:nowrap}
  /* 导航占满第二行：诗境页「品牌 274px + 返回工坊 118px」= 410px 超 362px 可用宽，
     撑宽整页导致下面所有行（chip / 按钮）跟着右缘裁切 —— 换行后互不牵连 */
  .topbar-nav{flex-basis:100%}
  .tabs{overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:none;max-width:100%}
  .tabs::-webkit-scrollbar{display:none}
  .tab{padding:8px 14px;font-size:15px;letter-spacing:.4px}
  main{padding:14px 12px 0}
  .panel-head h2{font-size:19px}
  .card-hd h2{font-size:16.5px}
  .step-btn{padding:8px 9px;font-size:13.5px;gap:5px}
  .step-btn b{width:18px;height:18px}
  /* 按钮允许换行：.btn 的 white-space:nowrap 让「再来一首（保证不重复）」的
     min-content = 整行 202px，加上 min-width:126px 的兄弟 = 336px > 326px 容器，
     实测右缘裁切 10px。允许折行后 min-content 缩到最宽词，整行必然放得下 */
  .btn{white-space:normal;line-height:1.3;padding:8px 12px;font-size:13.5px}
  /* 兜底：残余 1-2px 的取整溢出不许再把页面撑宽 */
  html,body{overflow-x:hidden}
}

/* 触控：按钮别小于 44px（Apple/Google 都这么建议），圆点给粗手指留高度 */
@media(pointer:coarse){
  .btn,.seg-btn,.chip,.step-btn,.tab{min-height:44px}
  .dot{height:9px;width:30px}
  .dot.on{width:44px}
}

/* 系统里关了动效就别再动 */
@media(prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;transition-duration:.001ms!important}
}
