:root {
  /* 暗色骨架（Nocturne 收钝版）+ V2 钢蓝强调。
     2026-10-19 从「电光青 #00e5ff」换成钢蓝 #1F63C8 系：饱和度 0.84、色相 216° 偏冷，
     白底对比 5.71（过 AA 正文）——界面与谱面从此共用一个强调色，
     不再需要「界面亮青 + 谱面深青」两套（原来青色打白纸只有 1.5:1，高亮会糊）。
     暗底上钢蓝提亮一档 #5B9BEF 保持可读，色相不动。 */
  --bg: #000000;
  --paper: #0c0e11;
  --ink: #ffffff;
  --muted: #9aa3ad;
  --muted-strong: #c5ccd4;
  --line: #262b31;
  --line-strong: #3a4149;
  --soft: #14171b;
  --panel: #0f1114;
  --preview: #0a0c0e;
  --accent: #5b9bef;                       /* 文字/图标/播放高亮的亮钢蓝：深底上要提亮才看得见 */
  --accent-solid: #1f63c8;                 /* 按钮与徽章实底专用：压深一档才配得上白字 */
  --accent-strong: #7db3f4;
  --accent-soft: rgba(91, 155, 239, .12);
  --success: #2ee6a8;
  --warning: #ffc857;
  --danger: #ff5c5c;
  --ok-soft: rgba(46, 230, 168, .1);
  --ok-border: rgba(46, 230, 168, .3);
  --ok-ring: rgba(46, 230, 168, .14);
  --busy-soft: rgba(255, 200, 87, .1);
  --busy-border: rgba(255, 200, 87, .3);
  --err-soft: rgba(255, 92, 92, .1);
  --err-border: rgba(255, 92, 92, .35);
  --shadow-1: 0 1px 2px rgba(0, 0, 0, .45), 0 10px 30px rgba(0, 0, 0, .35);
  --shadow-2: 0 18px 42px rgba(0, 0, 0, .6), 0 3px 10px rgba(0, 0, 0, .45);
  --radius: 12px;
  --radius-sm: 10px;
  --radius-xs: 8px;
  --focus-ring: 0 0 0 3px rgba(91, 155, 239, .3);
  --on-accent: #ffffff;                  /* 主按钮文字：钢蓝实底上一律配白 */
  --logo-plate: #ffffff;                 /* 页头 logo 的底：两种主题下都保持白（字标/徽标是深墨+蓝，压在深底上会看不见） */
  --ease: cubic-bezier(.2, .7, .3, 1);
  /* 谱面元素 —— 纸与墨，屏幕 / 导出 / 打印三端共用
     （collectCSS() 把 styles.css 整份连同 :root 内联进导出的 SVG，所以改这里三端一起变） */
  --score-paper: #ffffff;
  --score-ink: #16181c;
  --score-ink-soft: #40474f;
  --score-ink-faint: #6b727d;
  /* 播放高亮 / 和弦名：与界面同一个钢蓝。白谱面上 5.71:1，不再分深浅两档 */
  --score-accent: #1f63c8;
  /* 界面层的散装底色也收进令牌（明暗各给一套值），light 才有得覆写 */
  --scrim-1: rgba(0, 0, 0, .9);        /* 顶栏 */
  --scrim-2: rgba(0, 0, 0, .85);       /* 画布工具条 */
  --scrim-3: rgba(0, 0, 0, .7);        /* 播放时间线坞 */
  --canvas-grad: linear-gradient(180deg, #101318 0%, #0a0c0e 100%);
  --hover-soft: #1a1e24;               /* ghost / 图标按钮 hover */
  --toggle-off: #3a4149;               /* 开关关态 */
  --track: #1c2127;                    /* 播放进度轨 */
  --track-fill: #262b31;               /* 滑杆未填充段 */
  --settings-bg: rgba(12, 14, 17, .97);
  --edge-hi: rgba(255, 255, 255, .045);  /* 面板/拖放面顶部一道极淡的高光边（材质感，不是彩色光晕） */
  --accent-hover: #7db3f4;               /* 主按钮 hover：暗底上提亮一档 */
  --shadow-hero: 0 24px 60px rgba(0, 0, 0, .55), 0 2px 8px rgba(0, 0, 0, .40);  /* 首屏那张卡的投影，比 --shadow-1 重一档 */
  --canvas-haze: radial-gradient(120% 55% at 50% 0%, rgba(255, 255, 255, .035), transparent 62%);  /* 画布顶部一层中性提亮（给"桌面"一点光，不是彩色光晕） */
}

/* ===== 明暗模式：浅色主题 =====
   只覆写界面（chrome）变量；--score-* 纸墨三端共用，两种主题下一律不动
   （collectCSS() 把本文件连同 :root 内联进导出 SVG，SVG 里没有 html[data-theme]，
   导出 / 打印的谱面观感因此不受界面主题影响）。
   2026-10-19 V2「中性克制」：中性五色承担 95% 界面，钢蓝 #1F63C8 是唯一强调色，
   只出现在当前播放音符、进度条、可点击文字、步骤进行中——「异常才配拥有颜色」反推：
   默认态一律无色，勾选/选中也保持墨黑（勾选 ≠ 当前）。 */
:root[data-theme="light"] {
  /* 2026-10-20 参考 deepseek.com/harness 的观感：底色从冷灰 #f5f5f7 换成暖纸白 #f8f7f6，
     描边换成更细更淡的一档（rgba 墨 8%），卡片圆角放大到 24 —— 白卡浮在暖纸上、几乎没有边框，
     这是那套界面"干净但不冷"的关键；冷灰 + 深边框会显得像后台系统。 */
  --bg: #f8f7f6;
  --paper: #ffffff;
  --ink: #1d1d1f;
  --muted: #6f6a66;
  --muted-strong: #48433f;
  --line: #e4e0dc;
  --line-strong: #cdc7c1;
  --soft: #f3f1ee;
  --panel: #ffffff;
  --preview: #f8f7f6;
  --accent: #1f63c8;
  --accent-solid: #1f63c8;                 /* 按钮与徽章实底专用：浅色主题与 --accent 同值，语义分开将来可独立调 */
  --accent-strong: #1a56b0;
  --accent-soft: rgba(31, 99, 200, .08);
  --success: #248a3d;
  --warning: #9a5b12;
  --danger: #c6302b;
  --ok-soft: rgba(36, 138, 61, .08);
  --ok-border: rgba(36, 138, 61, .26);
  --ok-ring: rgba(36, 138, 61, .12);
  --busy-soft: rgba(154, 91, 18, .08);
  --busy-border: rgba(154, 91, 18, .26);
  --err-soft: rgba(198, 48, 43, .07);
  --err-border: rgba(198, 48, 43, .26);
  --shadow-1: 0 1px 2px rgba(29, 29, 31, .06), 0 8px 24px rgba(29, 29, 31, .07);
  --shadow-2: 0 14px 34px rgba(29, 29, 31, .12), 0 3px 8px rgba(29, 29, 31, .08);
  --focus-ring: 0 0 0 3px rgba(31, 99, 200, .25);
  --on-accent: #ffffff;                  /* 主按钮文字：浅底深钢蓝上的白 */
  --scrim-1: rgba(248, 247, 246, .72);   /* 顶栏：磨砂玻璃，跟暖纸底色同一支 */
  --scrim-2: rgba(255, 255, 255, .85);   /* 画布工具条 */
  --scrim-3: rgba(255, 255, 255, .92);   /* 播放时间线坞 */
  --canvas-grad: linear-gradient(180deg, #ffffff 0%, #f5f5f7 100%);
  --hover-soft: #ececf0;
  --toggle-off: #c7c7cc;
  --track: #e3e3e8;
  --track-fill: #d2d2d7;
  --settings-bg: rgba(255, 255, 255, .97);
  --edge-hi: rgba(255, 255, 255, .9);
  --accent-hover: #1a56b0;
  --shadow-hero: 0 24px 60px rgba(29, 29, 31, .10), 0 2px 8px rgba(29, 29, 31, .06);
  --canvas-haze: radial-gradient(120% 55% at 50% 0%, rgba(255, 255, 255, .55), transparent 62%);
}

* { box-sizing: border-box; }

html, body { margin: 0; min-height: 100%; }

body {
  font-family: Inter, ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
  color: var(--ink);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}

button, input, select { font: inherit; }
button { cursor: pointer; }
button:disabled { cursor: default; }

/* 键盘可达性：全站统一焦点环（鼠标点击不显示，键盘导航显示） */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 4px;
}

.app-shell { min-height: 100vh; }

/* ===== 顶栏 ===== */
.topbar {
  height: 60px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 0 24px;
  background: var(--scrim-1);
  border-bottom: 1px solid var(--line);
  backdrop-filter: blur(20px) saturate(1.6);
  -webkit-backdrop-filter: blur(20px) saturate(1.6);
  position: sticky;
  top: 0;
  flex: 0 0 auto;
  z-index: 20;
}

.brand { display: flex; align-items: center; gap: 12px; min-width: 0; }
.brand-mark {
  width: 34px; height: 34px; border-radius: 10px;
  display: grid; place-items: center;
  background: var(--accent-solid);
  color: var(--on-accent);
  font: 700 19px/1 Georgia, serif;
  flex: 0 0 auto;
}
.brand-title { font-weight: 760; font-size: 17px; letter-spacing: .04em; line-height: 1.2; color: var(--ink); }
.brand-subtitle { color: var(--muted); font-size: 11px; margin-top: 3px; }

.top-actions { display: flex; gap: 10px; align-items: center; }
.export-wrap { position: relative; }

/* 来源信息带：顶栏中间一列。曲名加粗当主，作曲/文件名做胶囊——
   信息全部来自页面现有元素（titleInput / composerInput / fileMetaText），只读镜像。
   中性色，不抢强调色；空谱时整条 hidden。 */
.source-strip {
  display: flex; align-items: center; gap: 8px;
  min-width: 0; flex: 1 1 auto;
  justify-content: center;
  padding: 0 16px;
}
.source-strip[hidden] { display: none; }
.src-title {
  font-size: 13px; font-weight: 600; color: var(--ink);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  max-width: 260px;
}
.src-chip {
  font-size: 11px; color: var(--muted);
  background: var(--soft);
  border-radius: 999px;
  padding: 3px 10px;
  white-space: nowrap;
  flex: 0 0 auto;
}
.src-chip[hidden] { display: none; }
.src-file { font-variant-numeric: tabular-nums; }
@media screen and (max-width: 1180px) {
  .source-strip { justify-content: flex-start; padding: 0 12px; }
  .src-title { max-width: 150px; }
}
@media screen and (max-width: 900px) {
  .source-strip { display: none; }
}

.export-menu {
  position: absolute;
  right: 0;
  top: calc(100% + 8px);
  min-width: 218px;
  background: var(--scrim-2);
  backdrop-filter: blur(24px) saturate(1.6);
  -webkit-backdrop-filter: blur(24px) saturate(1.6);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-2);
  padding: 6px;
  z-index: 50;
  animation: menuIn .18s var(--ease);
}
@keyframes menuIn {
  from { opacity: 0; transform: translateY(-4px) scale(.98); }
  to { opacity: 1; transform: none; }
}
.export-menu button {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 8px 10px;
  border: 0;
  border-radius: 7px;
  background: transparent;
  color: var(--ink);
  text-align: left;
  font-size: 13px;
  cursor: pointer;
}
.export-menu button:hover { background: var(--soft); }
.export-menu .menu-icon {
  width: 28px; height: 28px;
  display: grid; place-items: center;
  border-radius: 7px;
  background: var(--soft);
  font-size: 13px;
  flex: 0 0 auto;
}
.export-menu .menu-item-copy { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.export-menu .menu-item-copy strong { font-size: 12.5px; font-weight: 620; }
.export-menu .menu-item-copy small { font-size: 10.5px; color: var(--muted); white-space: nowrap; }

.button {
  border: 0; border-radius: 999px; padding: 10px 18px;
  font-weight: 600; font-size: 13px;
  transition: transform .18s var(--ease), background .15s var(--ease), box-shadow .15s var(--ease), opacity .15s var(--ease);
}
.button:hover:not(:disabled) { transform: translateY(-1px); }
.button:active:not(:disabled) { transform: scale(.965); }
.button:disabled { opacity: .4; }
/* 不可用态不能只靠 opacity：钢蓝 40% 压在浅底上糊成一片淡蓝，白字基本读不出来（首屏的「导出」就是这样）。
   换成中性的灰底灰字——一眼看出"还不能点"，但字是清楚的。 */
.button:disabled,
.button.dark:disabled,
.button.ghost:disabled {
  opacity: 1;
  background: var(--soft);
  color: var(--muted);
  border: 1px solid var(--line);
  transform: none;
}
.button.ghost { background: var(--soft); color: var(--ink); }
.button.ghost:hover:not(:disabled) { background: var(--hover-soft); }
.button.dark { background: var(--accent-solid); color: var(--on-accent); }
.button.dark:hover:not(:disabled) { background: var(--accent-strong); }
/* 明暗切换：深色时显示太阳（点了去浅色），浅色时显示月亮 */
.theme-btn { min-width: 40px; padding: 10px 12px; display: inline-flex; align-items: center; justify-content: center; }
.theme-btn svg { display: block; }
:root[data-theme="dark"] .theme-btn .icon-moon { display: none; }
:root[data-theme="light"] .theme-btn .icon-sun { display: none; }
.button.pulse { animation: exportPulse 1.5s ease 3; }
@keyframes exportPulse {
  50% { box-shadow: 0 0 0 6px var(--accent-soft); transform: translateY(-1px); }
}

/* ===== 主工作区 ===== */
.workspace {
  display: grid;
  grid-template-columns: 316px minmax(0, 1fr);
  gap: 18px;
  padding: 18px;
  min-height: calc(100vh - 108px);
}

.control-panel {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 20px;
  align-self: start;
  position: sticky;
  top: 90px;
  max-height: calc(100vh - 108px);
  overflow: auto;
  box-shadow: var(--shadow-1);
}

.panel-section { padding: 0 0 18px; margin: 0 0 18px; border-bottom: 1px solid var(--line); }
.panel-section:last-child { border-bottom: 0; margin-bottom: 0; padding-bottom: 0; }
.panel-section.compact { padding-bottom: 6px; }

.section-kicker {
  font-size: 11.5px;
  letter-spacing: .08em;
  color: var(--muted);
  font-weight: 760;
  margin-bottom: 12px;
  display: flex;
  align-items: center;
  gap: 7px;
}
.section-kicker::before {
  content: "";
  width: 3px; height: 12px;
  border-radius: 2px;
  background: var(--accent);
}

/* ===== 上传区 ===== */
.drop-zone {
  min-height: 128px;
  border: 1.5px dashed var(--line-strong);
  border-radius: 14px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
  gap: 4px;
  background: var(--soft);
  transition: border-color .18s var(--ease), background .18s var(--ease), transform .18s var(--ease);
  padding: 16px;
}
.drop-zone:hover, .drop-zone.dragging {
  border-color: var(--accent);
  background: var(--accent-soft);
}
.drop-zone.dragging { transform: scale(1.015); }
.drop-icon {
  font: 700 30px/1 Georgia, serif;
  margin-bottom: 4px;
  color: var(--muted-strong);
  transition: transform .18s var(--ease);
}
.drop-zone:hover .drop-icon, .drop-zone.dragging .drop-icon { transform: translateY(-2px); }
.drop-zone strong { font-size: 13px; }
.drop-zone span, .drop-zone em { font-size: 11px; color: var(--muted); font-style: normal; }
.drop-zone em { margin-top: 3px; color: var(--accent); font-weight: 550; }

.engine-row { margin-top: 12px; display: flex; flex-direction: column; gap: 8px; }
.engine-hint { margin: 0; font-size: 10.5px; color: var(--muted); line-height: 1.45; }

.file-meta {
  margin-top: 12px; padding: 9px 10px 9px 12px; border-radius: var(--radius-xs);
  font-size: 11px; background: var(--soft); color: var(--muted-strong);
  display: flex; align-items: center; gap: 8px;
  border: 1px solid var(--line);
}
.replace-btn {
  flex: 0 0 auto;
  border: 1px solid var(--line-strong);
  background: var(--panel);
  color: var(--muted-strong);
  border-radius: 7px;
  padding: 4px 10px;
  font-size: 10.5px;
  transition: border-color .15s var(--ease), color .15s var(--ease);
}
.replace-btn:hover { border-color: var(--accent); color: var(--accent); }

/* 多图选择列表 */
.multi-files {
  margin-top: 10px; padding: 9px 11px; border-radius: var(--radius-xs);
  font-size: 11px; background: var(--soft); border: 1px solid var(--line);
}
.multi-files-title { color: var(--muted-strong); font-weight: 600; margin-bottom: 6px; }
.multi-files-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 3px; }
.multi-files-list li {
  display: flex; align-items: center; gap: 7px; font-size: 10.5px; color: var(--muted);
}
.multi-files-list li::before { content: "♪"; color: var(--accent); font-size: 10px; }

/* ===== 表单字段 ===== */
.field { display: flex; flex-direction: column; gap: 6px; margin-top: 12px; flex: 1; }
.field > span { font-size: 11px; color: var(--muted); font-weight: 650; }
.field input, .field select {
  height: 38px; width: 100%;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-xs);
  padding: 0 11px;
  color: var(--ink);
  background: var(--panel);
  outline: 0;
  transition: border-color .15s var(--ease), box-shadow .15s var(--ease);
}
.field input:hover, .field select:hover { border-color: var(--line-strong); }
.field input:focus, .field select:focus {
  border-color: var(--accent);
  box-shadow: var(--focus-ring);
}
.field select:disabled { background: var(--soft); color: var(--muted); cursor: default; }

/* ===== 开关行 ===== */
.toggle-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 14px;
  padding: 9px 8px;
  margin: 0 -8px;
  border-radius: 9px;
  transition: background .15s var(--ease);
}
.toggle-row:hover { background: var(--soft); }
.toggle-row span { display: flex; flex-direction: column; gap: 2px; }
.toggle-row strong { font-size: 12px; font-weight: 620; }
.toggle-row small { font-size: 10px; color: var(--muted); }
.toggle-row input {
  appearance: none;
  width: 35px; height: 20px;
  background: var(--toggle-off);
  border-radius: 999px;
  position: relative;
  flex: 0 0 auto;
  transition: background .18s var(--ease);
  margin: 0;
}
.toggle-row input::after {
  content: "";
  position: absolute;
  width: 16px; height: 16px;
  left: 2px; top: 2px;
  border-radius: 50%;
  background: white;
  box-shadow: 0 1px 3px rgba(0,0,0,.22);
  transition: transform .18s var(--ease);
}
.toggle-row input:checked { background: var(--ink); }
.toggle-row input:checked::after { transform: translateX(15px); }
.toggle-row input:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

/* ===== 状态胶囊 ===== */
.status-box {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--muted-strong);
  font-size: 12px;
  padding: 7px 13px;
  border-radius: 999px;
  background: var(--soft);
  border: 1px solid transparent;
  white-space: nowrap;
  max-width: 320px;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: background .2s var(--ease), color .2s var(--ease), border-color .2s var(--ease);
}
.status-box.busy { background: var(--busy-soft); color: var(--warning); border-color: var(--busy-border); }
.status-box.ok { background: var(--ok-soft); color: var(--success); border-color: var(--ok-border); }
.status-box.error { background: var(--err-soft); color: var(--danger); border-color: var(--err-border); }
.retry-btn {
  flex: 0 0 auto;
  border: 1px solid rgba(255,92,92,.4);
  background: var(--panel);
  color: var(--danger);
  border-radius: 7px;
  padding: 2px 10px;
  font-size: 11px;
  transition: background .15s var(--ease), border-color .15s var(--ease);
}
.retry-btn:hover { background: rgba(255, 92, 92, .08); border-color: rgba(255,92,92,.6); }
.status-dot { width: 7px; height: 7px; border-radius: 50%; background: #4a5560; flex: 0 0 auto; }
.status-box.ok .status-dot { background: var(--success); box-shadow: 0 0 0 3px var(--ok-ring); }
.status-box.busy .status-dot { background: var(--warning); animation: pulse 1s infinite; }
.status-box.error .status-dot { background: var(--danger); }

@media screen and (max-width: 720px) {
  .status-box { max-width: 150px; }
}
@keyframes pulse { 50% { opacity: .35; } }

/* ===== 预览面板 ===== */
.preview-panel {
  min-width: 0;
  border-radius: var(--radius);
  background: var(--preview);
  border: 1px solid var(--line);
  overflow: hidden;
  position: relative;
  display: flex;
  flex-direction: column;
}

.preview-toolbar {
  height: 52px;
  flex: 0 0 auto;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  padding: 0 16px;
  background: var(--soft);
  border-bottom: 1px solid var(--line);
}
.preview-label { font-size: 12px; font-weight: 720; }
.score-stats { margin-left: 8px; font-size: 10px; color: var(--muted); }

.preview-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}
.preview-actions .group {
  display: flex;
  align-items: center;
  gap: 4px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-xs);
  padding: 2px 4px;
}
.preview-actions .group + .group { margin-left: 2px; }

.legend { display: flex; gap: 14px; font-size: 9px; color: var(--muted); align-items: center; margin-left: auto; }
.legend span { display: inline-flex; align-items: center; gap: 4px; }
.legend-dot { width: 4px; height: 4px; border-radius: 50%; background: var(--muted); display: inline-block; }
.legend-line { width: 11px; height: 1px; background: var(--muted); display: inline-block; }
.legend-arc { width: 12px; height: 6px; border-top: 1px solid var(--muted); border-radius: 50%; display: inline-block; }

/* 播放控制 */
.play-control { display: flex; align-items: center; gap: 4px; }
.play-btn {
  border: 0;
  background: transparent;
  border-radius: 6px;
  width: 28px; height: 26px;
  font-size: 12px;
  color: var(--ink);
  display: grid; place-items: center;
  transition: background .15s var(--ease), color .15s var(--ease);
}
.play-btn:hover:not(:disabled) { background: var(--soft); }
.play-btn:disabled { opacity: .35; }
.play-btn.playing { color: var(--accent); }
.tempo-select {
  border: 0;
  background: transparent;
  font-size: 11px;
  color: var(--muted);
  outline: 0;
  cursor: pointer;
  padding: 3px;
  border-radius: 5px;
}
.tempo-select:hover { background: var(--soft); }

.engine-btn {
  border: 0;
  background: transparent;
  border-radius: 6px;
  padding: 5px 10px;
  font-size: 11px;
  color: var(--muted);
  white-space: nowrap;
  transition: background .15s var(--ease), color .15s var(--ease);
}
.engine-btn:hover { background: var(--soft); }
.engine-btn.active { background: var(--accent-solid); color: var(--on-accent); font-weight: 650; }

/* 缩放 */
.zoom-control { display: flex; align-items: center; gap: 2px; }
.zoom-control button {
  border: 0;
  background: transparent;
  width: 24px; height: 24px;
  border-radius: 6px;
  font-size: 13px;
  line-height: 1;
  color: var(--ink);
  transition: background .15s var(--ease);
}
.zoom-control button:hover:not(:disabled) { background: var(--soft); }
.zoom-control button:disabled { opacity: .35; }
.zoom-label { font-size: 10px; color: var(--muted); min-width: 36px; text-align: center; font-variant-numeric: tabular-nums; }
.zoom-fit { width: auto !important; padding: 0 9px; font-size: 10px !important; }


/* ===== 空状态（2026-10-14 v4：照同类工具的做法重排）=====
   参考都是真实产品，逐个截图看过：
     · CloudConvert 首页 / 工具页：左对齐大标题 + 2~3 行说明，下面一张**居中投放卡**
       （约 670×280，1px 细边、比底色略亮），卡里是「图标 → 粗行 → 弱行 → 实心品牌按钮」，
       卡下再放两栏能力区
     · Convertio：居中主张 + 大面板投放区，里面一个大实心按钮 + 小字限制行
       （"1 GB 最大文件大小"），下面三栏能力行（图标 + 标签）
     · remove.bg：左侧超大标题 + 右侧白卡，卡里一个大胶囊按钮 + 小字「或者拖放一个文件」
   三家的共识，也是这版改的依据：
     ① 投放面里必须有**真正的实心主按钮**当视觉锚点，拖放是第二路径、用小字说
     ② 能力信息放投放面**下面**，不要塞进侧边面板（我上一版就是塞侧边，没人这么做）
     ③ 强调色只用在主按钮（+ 服务状态点），别到处铺
   所以：改回居中一列，去掉 eyebrow 与右侧三步面板，加上三栏能力行。
   空着的时候左轨和右检查器都没有意义，整幅画布仍归空状态
   （见下面 .workspace:has(#emptyState:not(.hidden))）。 */
.empty-state {
  flex: 1 1 auto;
  display: flex; flex-direction: column; align-items: center;
  /* safe center：内容放得下就垂直居中，放不下（矮视口）就从头排——
     否则 flex 居中会把超出部分往上/往下各溢出半截，标题被裁掉（1440×900 实测）。 */
  justify-content: safe center;
  width: 100%; max-width: 900px;
  min-height: min(560px, 72vh);
  margin: 16px auto;
  padding: 36px 32px 32px;
  text-align: center;
  color: var(--muted);
  /* 矮屏幕（笔记本 768/800 高）上内容比一屏高：这一层自己滚，别让下面那条能力带被裁掉 */
  overflow-y: auto;
  overscroll-behavior: contain;
}
/* 标题用谱面自己那套衬线（Georgia/宋体栈）——界面和谱面才像同一个产品，
   而不是"雅黑面板 + 宋体谱"。中文衬线在大字号下要正字距（CJK 收紧会糊），别用负值。 */
.empty-heading {
  margin: 0;
  font-family: "Source Han Serif SC", "Noto Serif SC", "Songti SC", "STSong", SimSun, Georgia, "Times New Roman", serif;
  color: var(--ink); font-size: clamp(32px, 3.6vw, 48px); font-weight: 600; letter-spacing: .01em; line-height: 1.14;
}
/* 大标题 = 字标图 + 标语 + 副标题（2026-10-20）。字标两版按主题切背景图，只下载命中的那一张；
   aspect-ratio 让宽度定了高度就跟着对，不用写死 px。
   标语是这一屏的正题（衬线、跟品牌同一套字），副标题（那一句愿景）落在 .empty-sub 里，小一号、灰色。 */
.empty-heading-brand { display: flex; flex-direction: column; align-items: center; gap: 20px; line-height: 1.2; }
.hero-wordmark {
  display: block;
  width: clamp(232px, 33vw, 384px);
  aspect-ratio: 1648 / 225;
  background: url("./assets/logo/zhuanpu-work.png") no-repeat center / contain;
}
:root[data-theme="dark"] .hero-wordmark { background-image: url("./assets/logo/zhuanpu-work-dark.png"); }
.hero-slogan {
  color: var(--ink);
  font-size: clamp(22px, 2.2vw, 30px);
  font-weight: 600;
  letter-spacing: .05em;
}

/* 作业台（2026-10-20 重排）：两个开关 + 引擎 + 投放面装进同一张卡。
   上一版是"四张卡先选方向，再滚到下面找上传"——一次意图要点两下，主按钮还掉在首屏外；
   现在默认值就是最常见那条路（五线谱 → 简谱、引擎自动），不碰开关也能直接传。
   分段的选中态沿用站内语言（淡蓝底 + 钢蓝细边），不另起炉灶。 */
.workbench {
  width: 100%; max-width: 760px;
  margin-top: 30px;
  padding: 26px 28px 28px;
  border: 1px solid var(--line);
  border-radius: 24px;
  background: var(--panel);
  box-shadow: var(--shadow-hero), inset 0 1px 0 var(--edge-hi);
  text-align: left;
}
/* 亮色下卡片几乎不要边框：暖纸上浮一张白卡，靠投影和 24px 圆角立住（参考站的做法） */
:root[data-theme="light"] .workbench {
  border-color: rgba(26, 22, 21, .07);
  box-shadow: 0 1px 2px rgba(26, 22, 21, .04), 0 16px 44px rgba(26, 22, 21, .07);
}
.wb-row { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-start; gap: 14px 24px; }
.wb-group { display: flex; align-items: center; gap: 10px; }
.wb-label { flex: 0 0 auto; color: var(--muted); font-size: 12.5px; letter-spacing: .02em; }

.seg {
  display: inline-flex; gap: 2px; padding: 3px;
  border: 1px solid var(--line); border-radius: 12px;
  background: var(--soft);
}
.seg-item {
  position: relative;
  padding: 7px 14px; border-radius: 9px;
  color: var(--muted); font-size: 13px; font-weight: 560;
  cursor: pointer; white-space: nowrap;
  transition: background .15s var(--ease), color .15s var(--ease), box-shadow .15s var(--ease);
}
.seg-item input { position: absolute; opacity: 0; pointer-events: none; }
.seg-item:hover { color: var(--ink); }
.seg-item:has(input:checked) {
  background: var(--hover-soft); color: var(--ink); font-weight: 650;
  box-shadow: inset 0 0 0 1px var(--line-strong);
}
.seg-item:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }

/* 识别引擎：只有五线谱这一路有得挑（数字简谱走专用识别），选简谱时整排收起（app2.js 切 .hidden）。
   标签和芯片同一行——它是"再挑一个"的附加项，不该像主开关那样占一整行高度。 */
.wb-engine { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; margin-top: 16px; padding-top: 16px; border-top: 1px solid var(--line); }
.engine-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.chip {
  position: relative; display: inline-flex; align-items: baseline; gap: 5px;
  padding: 7px 13px; border: 1px solid var(--line); border-radius: 999px;
  color: var(--muted); font-size: 13px; cursor: pointer;
  transition: border-color .15s var(--ease), color .15s var(--ease), background .15s var(--ease);
}
.chip input { position: absolute; opacity: 0; pointer-events: none; }
.chip:hover { border-color: var(--line-strong); color: var(--ink); }
.chip:has(input:checked) { border-color: var(--accent); background: var(--accent-soft); color: var(--ink); }
.chip:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }
.engine-hint { flex: 1 0 100%; margin: 2px 0 0; max-width: 46em; color: var(--muted-strong); font-size: 12.5px; line-height: 1.6; }
.engine-hint.warn { color: var(--warning); }

/* 投放面：作业台里的虚线区（拖放目标的常规语言）。它是拖放目标但**不是按钮**——
   按钮套按钮，键盘与读屏都会乱；开文件选择交给里面那个按钮。 */
.empty-drop {
  margin-top: 16px;
  width: 100%; min-height: 120px;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: 18px 20px;
  border: 1px dashed var(--line); border-radius: 14px;
  background: var(--soft);
  text-align: center;
  transition: border-color .18s var(--ease), background .18s var(--ease);
}
.empty-drop.dragging { border-color: var(--accent); border-style: solid; background: var(--accent-soft); }
.empty-drop-icon { width: 24px; height: 24px; margin-bottom: 10px; fill: none; stroke: var(--muted-strong); stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
/* 主按钮：站内 .button.dark（强调色实心）加一档尺寸；特异性要压过文件后面那段 .button */
.empty-drop .empty-pick { min-height: 46px; padding: 0 30px; font-size: 15px; font-weight: 640; }
.empty-drop-hint { margin: 11px 0 0; font-size: 12.5px; }
/* 手机上"拖到这里 / Ctrl+O"是句废话：换成一句它真能做的事（相册、文件） */
.hint-touch { display: none; }
@media (hover: none), (max-width: 720px) {
  .hint-pointer { display: none; }
  .hint-touch { display: inline; }
}
.empty-kbd { margin-left: 6px; padding: 2px 7px; border: 1px solid var(--line); border-radius: 6px; font-size: 11px; }
.empty-drop-formats { margin: 6px 0 0; font-size: 12px; text-wrap: pretty; }
.empty-drop-note { margin: 4px 0 0; max-width: 34em; font-size: 12px; line-height: 1.6; text-wrap: pretty; }

/* 手机：开关竖排（标签在左、分段在右），投放面收窄省高度 */
@media screen and (max-width: 720px) {
  .workbench { margin-top: 22px; padding: 16px 14px 18px; }
  .wb-row { flex-direction: column; align-items: stretch; gap: 12px; }
  .wb-group { justify-content: space-between; }
  .seg-item { padding: 8px 12px; }
  .empty-drop { min-height: 140px; padding: 20px 14px; }
  .empty-drop .empty-pick { width: 100%; max-width: 300px; }
  .empty-drop-formats, .empty-drop-note { font-size: 12px; }
  .engine-note { display: none; }        /* 手机上省两行：说明已经写了每个引擎适合什么 */
}

/* 能力三栏（参考 Convertio 的三栏能力行）：细分割线把宽度用掉，别让三块小字飘在中间。
   宽度跟作业台对齐（760），否则上面窄下面宽，整列读起来是散的。 */
.empty-facts {
  display: grid; grid-template-columns: 1fr 1fr 1.22fr;
  width: 100%; max-width: 900px; margin: 26px auto 0; padding: 22px 0 0; list-style: none; text-align: left;
  border-top: 1px solid var(--line);
}
.empty-facts li { padding: 0 24px; }
.empty-facts li:first-child { padding-left: 0; }
.empty-facts li:last-child { padding-right: 0; }
.empty-facts li + li { border-left: 1px solid var(--line); }
.empty-facts svg { width: 20px; height: 20px; fill: none; stroke: var(--muted-strong); stroke-width: 1.25; stroke-linecap: round; stroke-linejoin: round; }
.empty-facts strong { display: block; margin-top: 10px; color: var(--ink); font-size: 13.5px; font-weight: 650; }
.empty-facts small { display: block; margin-top: 5px; font-size: 12px; line-height: 1.55; text-wrap: pretty; }

/* 状态行贴着作业台放（服务是否就绪、今天还剩几次），离动作近一点 */
.empty-status { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 12px; margin: 16px 0 0; }
.empty-status .omr-badge { margin-top: 0; }
.empty-quota { font-size: 12px; color: var(--muted); }
/* 底轨在空态是收起的，识别进度 / 报错的出口在这里（见下面 .app-shell:has(...) 那条） */
.empty-status-line { font-size: 12.5px; }
.empty-status-line.busy { color: var(--warning); }
.empty-status-line.ok { color: var(--success); }
.empty-status-line.error { color: var(--danger); }

/* ===== 页底正文（折线之下，给人和搜索引擎看；打印不进纸）=====
   工具本体占整屏，这段接着往下排：本站只有一个页面，可爬的字基本都在这里。
   版心 760px 是正文可读宽度，跟上面的工具画布（1120px）故意不同宽。 */
.site-foot { border-top: 1px solid var(--line); background: var(--bg); }
.site-foot-inner { max-width: 760px; margin: 0 auto; padding: 48px 24px 64px; color: var(--muted); font-size: 13px; line-height: 1.85; }
.site-foot h2 { margin: 0 0 14px; color: var(--ink); font-size: 18px; font-weight: 700; letter-spacing: -.02em; }
.site-foot h3 { margin: 32px 0 12px; color: var(--ink); font-size: 14px; font-weight: 660; }
.site-foot p { margin: 0; }
.site-faq { margin: 0; }
.site-faq dt { margin-top: 16px; color: var(--ink); font-size: 13px; font-weight: 640; }
.site-faq dd { margin: 6px 0 0; }
.site-foot-brand { margin-top: 36px; padding-top: 20px; border-top: 1px solid var(--line); font-size: 12px; }

.omr-badge {
  margin-top: 18px;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 6px 14px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 550;
  border: 1px solid transparent;
}
.omr-dot { width: 7px; height: 7px; border-radius: 50%; background: #4a5560; flex: 0 0 auto; }
.omr-badge.checking { background: var(--soft); color: var(--muted); }
.omr-badge.checking .omr-dot { animation: pulse 1s infinite; }
.omr-badge.ok { background: var(--soft); color: var(--muted-strong); border-color: var(--line); }
.omr-badge.ok .omr-dot { background: var(--success); box-shadow: 0 0 0 3px rgba(46,230,168,.14); }
.omr-badge.warn { background: rgba(255, 92, 92, .1); color: var(--danger); border-color: rgba(255, 92, 92, .35); }
.omr-badge.warn .omr-dot { background: var(--danger); box-shadow: 0 0 0 3px rgba(255,92,92,.14); }

/* ===== 简谱预览（多页并排网格，一次性看清所有谱子） ===== */
.score-preview {
  flex: 1 1 auto;
  padding: 24px;
  overflow-x: auto;
  overflow-y: auto;
  display: grid;
  /* 响应式：每页保持 A4 比例；单页满尺寸(≤793px)，面板够宽就并排 2~3 页（每页≥560px 可读） */
  grid-template-columns: repeat(auto-fit, minmax(560px, 1fr));
  justify-items: center;
  align-items: start;
  gap: 28px;
  align-content: start;
}
/* 列数由 JS 按预览面板宽度设定（applyGridColumns），面板越宽每行并排越多页 */

/* ===== jpfun 引擎渲染的页（#scorePreview 里 .jp-page）=====
   与自研渲染同一张"白纸"令牌：jpfun 的页 SVG **自带白底**吗？没有——它只有音符墨迹，
   所以在暗色主题下必须由容器给白纸，否则就是黑底黑字。尺寸规则照抄 .paper-page：
   jpfun 的页固定 A4（794×1123，正好是 210:297），页面边距已经排进 SVG 里，容器不再加 padding。 */
.jp-page {
  position: relative;
  width: 100%;
  aspect-ratio: 210 / 297;
  max-width: 793px;
  min-width: 0;
  margin: 0 auto;
  box-sizing: border-box;
  background: var(--score-paper);
  box-shadow: var(--shadow-2);
  border-radius: 4px;
  overflow: hidden;
  flex: 0 0 auto;
  content-visibility: auto;
  contain-intrinsic-size: 793px 1122px;
}
.jp-page svg { display: block; width: 100%; height: 100%; }

/* 看五线谱时给画布多留一点顶部空间：那一版由 Verovio 印谱头（标题/作者）在页面最上沿，
   而画布右上角有浮动工具条，不留这一段标题会被压住（简谱页头顶留白本来就宽，不用这段）。 */
html[data-output="staff"] .score-preview { padding-top: 64px; }

/* 五线谱的页走的就是 .jp-page（Verovio 的 svg 由 jpfun-view 原样塞进去），所以这里不再有
   .staff-page 那套样式——两份排版共用同一张白纸、同一道投影。 */

/* jpfun 引擎注入的覆盖层三件套（jpfun-view.js 建的是 div，不是 SVG，但同样有条基态契约）：
   .jp-overlay 整页透明承接层；.jp-hot 每个音符一个热区（坐标来自 noteBoxes）；
   .jp-line 播放竖线。三者的 outline/background/位置全部由 JS 写内联，
   CSS 这边只保证：① 未初始化时不露任何痕迹（基态全透明）；
   ② 播放线与高亮的颜色走钢蓝——jpfun-view.js 里硬编码的是旧品牌朱橘 #E64614，
   用 !important 压内联（内联未写 !important，级联上必赢），不动引擎文件。 */
.jp-page .jp-overlay { pointer-events: none; }
.jp-page .jp-hot { outline: none; background: transparent; }
.jp-page .jp-line { background: var(--score-accent); }
.jp-page .jp-hot[style*="outline"] { outline-color: var(--score-accent) !important; }
.jp-page .jp-hot[style*="background"] { background-color: var(--accent-soft) !important; }

.hidden { display: none !important; }

/* ===== 处理中遮罩层 ===== */
.processing-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, .72);
  backdrop-filter: blur(2px);
  z-index: 10;
  animation: overlayIn .16s var(--ease);
}
@keyframes overlayIn {
  from { opacity: 0; }
  to { opacity: 1; }
}
.processing-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  background: var(--panel);
  padding: 28px 38px;
  border-radius: var(--radius);
  box-shadow: var(--shadow-2);
  min-width: 360px;
  max-width: 92vw;
  border: 1px solid var(--line);
  animation: cardIn .18s var(--ease);
}
@keyframes cardIn {
  from { opacity: 0; transform: translateY(6px) scale(.98); }
  to { opacity: 1; transform: none; }
}
.step-track { display: flex; gap: 8px; align-items: flex-start; }
.step-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  flex: 1;
  min-width: 0;
}
.step-dot {
  width: 26px; height: 26px;
  border-radius: 50%;
  background: var(--soft);
  color: var(--muted);
  display: grid;
  place-items: center;
  font-size: 11px;
  font-weight: 700;
  transition: all .25s var(--ease);
  flex: 0 0 auto;
}
.step-label { font-size: 10px; color: var(--muted); white-space: nowrap; transition: color .25s var(--ease); }
.step-item.active .step-dot { background: var(--accent); color: #fff; box-shadow: 0 0 0 4px var(--accent-soft); }
.step-item.active .step-label { color: var(--accent); font-weight: 650; }
.step-item.done .step-dot { background: var(--success); color: #fff; }
.step-item.done .step-label { color: var(--success); }
.step-item.done .step-dot::after { content: '✓'; }
.step-item.done .step-dot { font-size: 0; }

.progress-bar {
  width: 100%;
  height: 6px;
  border-radius: 999px;
  background: var(--line);
  overflow: hidden;
}
.progress-fill {
  height: 100%;
  border-radius: 999px;
  background: var(--accent);
}
  transition: width .4s var(--ease);
}
@keyframes progressFlow {
  from { background-position: 200% 0; }
  to { background-position: -200% 0; }
}
.processing-text { font-size: 13px; color: #5e636a; text-align: center; }

/* ===== 播放时间线 ===== */
.play-timeline {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 9px 14px;
  margin: 0 0 12px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  flex: 0 0 auto;
}
.play-bar {
  position: relative;
  flex: 1;
  height: 22px;
  display: flex;
  align-items: center;
  cursor: pointer;
}
.play-bar::before {
  content: '';
  position: absolute;
  left: 0; right: 0;
  height: 4px;
  background: var(--track);
  border-radius: 2px;
}
.play-progress {
  position: absolute;
  left: 0;
  height: 4px;
  width: 0%;
  background: var(--accent);
  border-radius: 2px;
  /* 播放时由 rAF 每帧直写宽度：不加 transition，避免追赶滞后 */
}
.play-knob {
  position: absolute;
  left: 0%;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--accent);
  transform: translateX(-50%);
  box-shadow: 0 1px 3px rgba(0,0,0,.3);
  display: none;
  /* 播放时由 rAF 每帧直写 left：不加 transition，避免追赶滞后 */
}
.play-bar:hover .play-knob, .play-timeline.playing .play-knob { display: block; }
.play-knob.dragging { display: block; }
.play-time {
  font-size: 11px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  min-width: 86px;
  text-align: right;
}
.play-measure {
  font-size: 11px;
  color: var(--accent);
  background: var(--accent-soft);
  border-radius: 999px;
  padding: 3px 10px;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

@media screen and (max-width: 980px) {
  .workspace { grid-template-columns: 1fr; }
  .control-panel { position: static; max-height: none; }
  .legend { display: none; }
}

@media screen and (max-width: 640px) {
  .zoom-control { display: none; }
  .engine-btn { padding: 5px 7px; }
  .preview-actions { gap: 6px; }
  .play-measure { display: none; }
  .topbar { padding: 0 16px; }
  .brand-subtitle { display: none; }
  .processing-card { min-width: 0; width: 92vw; padding: 22px 18px; }
  .step-label { font-size: 9px; }
}

/* ===== 2026-09-09 layout rebuild =====
   编辑器工作台：左侧负责输入与设置，右侧只负责预览与播放。 */
/* Nocturne Black：哑光黑底 + 高亮白谱面 + 电光青强调 */
html { background: var(--bg); }
body {
  min-width: 320px;
  background: var(--bg);
  color: var(--ink);
  font-family: "PingFang SC", "Microsoft YaHei", "Hiragino Sans GB", ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  font-feature-settings: "tnum";
}

/* 顶部：品牌、当前状态、全局动作三段分层 */
.topbar {
  height: 64px;
  padding: 0 clamp(18px, 2.4vw, 36px);
  gap: 24px;
  background: var(--scrim-1);
  border-bottom-color: var(--line);
  z-index: 30;
  flex: 0 0 auto;
}
.brand { gap: 12px; }
.brand-mark {
  width: 40px;
  height: 40px;
  border-radius: 12px;
  background: var(--accent-solid);
  color: var(--on-accent);
}
.brand-title { font-size: 18px; font-weight: 800; letter-spacing: .04em; color: var(--ink); }
.brand-subtitle { margin-top: 3px; color: var(--muted); font-size: 11px; }
.topbar::after { content: none; }
.top-actions { gap: 8px; }
.status-box, .button { min-height: 38px; }
.status-box {
  max-width: 270px;
  padding: 8px 12px;
  gap: 8px;
  border-color: var(--line);
  background: var(--soft);
  color: var(--muted-strong);
  font-size: 11px;
}
.status-box.ok { background: rgba(46, 230, 168, .1); color: var(--success); border-color: rgba(46, 230, 168, .3); }
.status-box.busy { background: rgba(255, 200, 87, .1); color: var(--warning); border-color: rgba(255, 200, 87, .3); }
.status-box.error { background: rgba(255, 92, 92, .1); color: var(--danger); border-color: rgba(255, 92, 92, .3); }
.status-box .status-dot { background: currentColor; opacity: .55; }
.status-box.ok .status-dot { background: var(--success); box-shadow: 0 0 0 3px var(--ok-ring); }
.status-box.busy .status-dot { background: var(--warning); animation: pulse 1s infinite; }
.status-box.error .status-dot { background: var(--danger); }
.button {
  border-radius: var(--radius-sm);
  padding: 9px 14px;
  font-size: 12px;
  font-weight: 700;
}
.button.ghost { color: var(--muted-strong); background: var(--soft); border: 1px solid var(--line); }
.button.ghost:hover:not(:disabled) { background: var(--hover-soft); border-color: var(--line-strong); }
.button.dark { background: var(--accent-solid); color: var(--on-accent); }
.button.dark:hover:not(:disabled) { background: var(--accent-strong); }
.export-menu {
  top: calc(100% + 8px);
  min-width: 232px;
  padding: 6px;
  border-color: var(--line);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-2);
  background: var(--panel);
}
.export-menu button { min-height: 44px; padding: 8px 10px; border-radius: 8px; color: var(--ink); }
.export-menu button:hover { background: var(--soft); }
.export-menu .menu-icon { width: 30px; height: 30px; border-radius: 8px; background: var(--soft); }
.export-menu .menu-item-copy small { color: var(--muted); }

/* 工作区：左侧稳定、右侧占据主视觉 */
.workspace {
  display: grid;
  grid-template-columns: minmax(300px, 336px) minmax(0, 1fr);
  gap: 18px;
  align-items: start;
  padding: 20px clamp(18px, 2.4vw, 36px) 24px;
  min-height: calc(100vh - 108px);
}
.control-panel {
  position: sticky;
  top: 92px;
  min-width: 0;
  max-height: calc(100vh - 112px);
  overflow: auto;
  padding: 22px 20px 24px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--scrim-2);
  box-shadow: var(--shadow-1);
  scrollbar-width: thin;
  scrollbar-color: #cbd4e2 transparent;
}
.control-panel::-webkit-scrollbar { width: 8px; }
.control-panel::-webkit-scrollbar-thumb { background: #cbd4e2; border: 2px solid transparent; border-radius: 999px; background-clip: padding-box; }
.panel-intro { padding: 0 2px 20px; }
.panel-eyebrow, .preview-eyebrow {
  color: var(--accent);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: .12em;
  text-transform: uppercase;
}
.panel-intro h1 { margin: 7px 0 5px; color: var(--ink); font-size: 20px; line-height: 1.25; letter-spacing: -.02em; }
.panel-intro p { margin: 0; color: var(--muted); font-size: 11px; line-height: 1.55; }
.panel-section { margin: 0; padding: 18px 0 20px; border-bottom: 1px solid var(--line); }
.panel-section:first-child { padding-top: 0; }
.panel-section:last-child { padding-bottom: 0; border-bottom: 0; }
.section-heading { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: 13px; }
.section-kicker { margin: 0; color: var(--ink); font-size: 11px; font-weight: 800; letter-spacing: .04em; line-height: 1.35; }
.section-kicker::before { display: none; }
.section-note { margin: 4px 0 0; color: var(--muted); font-size: 10px; line-height: 1.45; }

/* 来源模块：大动作明确，其余信息逐层收纳 */
.drop-zone {
  min-height: 130px;
  padding: 16px 14px;
  gap: 5px;
  border: 1px dashed #b9c6de;
  border-radius: 12px;
  background: linear-gradient(180deg, #131720 0%, #0e1116 100%);
}
.drop-zone:hover, .drop-zone.dragging { background: var(--accent-soft); border-color: var(--accent); }
.drop-icon { margin-bottom: 3px; color: var(--accent); font-size: 28px; }
.drop-zone strong { font-size: 12px; }
.drop-zone span, .drop-zone em { max-width: 230px; font-size: 10px; line-height: 1.45; }
.drop-zone em { color: var(--accent); }
.engine-row { margin-top: 12px; gap: 9px; }
.engine-hint { margin: 0; font-size: 10px; line-height: 1.45; }
.file-meta, .multi-files {
  background: var(--soft);
  border-color: var(--line);
  border-radius: var(--radius-xs);
}
.file-meta { margin-top: 10px; padding: 9px 10px; font-size: 10.5px; }
#fileMetaText { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.multi-files { margin-top: 8px; padding: 9px 10px; font-size: 10.5px; }

/* 字段：统一高度，双列只用于信息密度确实合理的区域 */
.field-grid { display: grid; gap: 11px; }
.metadata-section .field-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.field { gap: 5px; margin-top: 0; min-width: 0; }
.field > span { color: var(--muted-strong); font-size: 10.5px; font-weight: 700; }
.field input, .field select {
  width: 100%;
  height: 38px;
  padding: 0 10px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-xs);
  background: var(--panel);
  color: var(--ink);
  font-size: 12px;
}
.field input:hover, .field select:hover { border-color: #aeb8c8; }
.field input:focus, .field select:focus { border-color: var(--accent); box-shadow: var(--focus-ring); }
.field select:disabled { background: var(--soft); color: var(--muted); }

/* 显示选项：连续列表，而不是六段孤立表单 */
.toggle-list { display: flex; flex-direction: column; gap: 2px; }
.toggle-row {
  min-height: 50px;
  margin: 0;
  padding: 8px 0;
  gap: 14px;
  border-radius: 9px;
}
.toggle-row:hover { padding-left: 8px; padding-right: 8px; margin-left: -8px; margin-right: -8px; background: var(--soft); }
.toggle-row span { gap: 2px; min-width: 0; }
.toggle-row strong { color: var(--ink); font-size: 11.5px; line-height: 1.3; }
.toggle-row small { color: var(--muted); font-size: 9.5px; line-height: 1.35; }
.toggle-row input { width: 35px; height: 20px; flex: 0 0 auto; background: var(--toggle-off); }
.toggle-row input:checked { background: var(--accent); }

/* 右侧预览：工具栏和画布分离，谱面永远是中心 */
.preview-panel {
  min-width: 0;
  height: calc(100vh - 112px);
  min-height: 720px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--preview);
  box-shadow: var(--shadow-1);
  overflow: hidden;
  position: relative;
  display: flex;
  flex-direction: column;
}
.preview-toolbar {
  min-height: 76px;
  height: auto;
  display: grid;
  grid-template-columns: minmax(150px, 1fr) minmax(0, auto);
  align-items: center;
  gap: 18px;
  padding: 13px 16px 13px 18px;
  background: var(--scrim-2);
  border-bottom-color: var(--line);
}
.preview-heading { min-width: 0; }
.preview-title-line { display: flex; align-items: baseline; gap: 8px; margin-top: 5px; min-width: 0; }
.preview-label { font-size: 14px; font-weight: 800; letter-spacing: -.01em; }
.score-stats { margin-left: 0; color: var(--muted); font-size: 10.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.preview-actions { justify-content: flex-end; gap: 6px; flex-wrap: wrap; }
.preview-actions .group {
  min-height: 36px;
  gap: 2px;
  padding: 3px 4px;
  border-color: var(--line);
  border-radius: 9px;
  background: var(--soft);
}
.play-control { gap: 1px; }
.play-btn { width: 29px; height: 29px; color: var(--muted-strong); border-radius: 7px; }
.play-btn:hover:not(:disabled), .zoom-control button:hover:not(:disabled), .engine-btn:hover { background: var(--hover-soft); }
.play-btn.playing { color: var(--accent); }
.tempo-select { height: 29px; padding: 3px 4px; color: var(--muted); font-size: 10.5px; }
.layout-switch { gap: 2px; }
.engine-btn { min-height: 29px; padding: 5px 9px; color: var(--muted); font-size: 10.5px; border-radius: 7px; }
.engine-btn.active { background: var(--accent-solid); color: var(--on-accent); }
.zoom-control button { width: 27px; height: 29px; }
.zoom-label { min-width: 40px; color: var(--muted); font-size: 10px; }
.zoom-fit { padding: 0 8px; font-size: 10px !important; }
.legend { gap: 9px; margin-left: 2px; color: #8792a3; font-size: 9px; white-space: nowrap; }
.legend span { white-space: nowrap; }

.preview-canvas {
  position: relative;
  display: flex;
  flex: 1 1 auto;
  min-height: 0;
  flex-direction: column;
  overflow: hidden;
  background:
    linear-gradient(rgba(255,255,255,.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,.04) 1px, transparent 1px),
    var(--preview);
  background-size: 28px 28px;
}

/* 空状态与谱面内容共用画布空间（空状态自身的样式在文件前段的"欢迎页"那段） */
.empty-state, .score-preview { min-height: 0; }
.score-preview {
  flex: 1 1 auto;
  padding: 28px 28px 48px;
  grid-template-columns: repeat(auto-fit, minmax(480px, 1fr));
  grid-auto-rows: max-content;
  gap: 24px;
  overflow: auto;
  align-content: start;
}

/* 时间线是画布底座，而不是一块普通内容 */
.timeline-dock {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: 0 0 auto;
  padding: 8px 16px 10px;
  background: var(--scrim-3);
  border-top: 1px solid rgba(207, 215, 227, .9);
}
.timeline-dock:has(.play-timeline.hidden) { display: none; }
.timeline-label { color: #78869a; font-size: 10px; font-weight: 700; white-space: nowrap; }
.play-timeline {
  flex: 1 1 auto;
  gap: 10px;
  margin: 0;
  padding: 6px 10px;
  border-color: var(--line);
  border-radius: 9px;
  background: var(--scrim-3);
}
.play-time { min-width: 82px; color: var(--muted); font-size: 10.5px; }
.play-measure { padding: 3px 9px; color: var(--accent); background: var(--accent-soft); font-size: 10.5px; }

/* 播放同步钢琴：88 键横向缩放，小屏幕可左右滚动查看 */
.piano-dock {
  flex: 0 0 auto;
  padding: 10px 18px 12px;
  background: var(--scrim-3);
  border-top: 1px solid rgba(207, 215, 227, .82);
}
.piano-dock-heading { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 8px; }
.piano-dock-title { color: #526176; font-size: 10.5px; font-weight: 800; }
.piano-dock-hint { margin-top: 2px; color: #8a96a6; font-size: 9px; }
.piano-dock-status { max-width: 55%; overflow: hidden; color: var(--accent); font-size: 9px; font-weight: 700; text-overflow: ellipsis; white-space: nowrap; }
.piano-scroll { overflow-x: auto; overflow-y: hidden; padding: 0 1px 3px; scrollbar-width: thin; }
.piano-keyboard {
  --white-key-width: calc(100% / 52);
  --black-key-width: calc(var(--white-key-width) * .62);
  position: relative;
  display: flex;
  width: 100%;
  min-width: 820px;
  height: 98px;
  padding: 0 1px 1px;
  border: 1px solid #9ca8b8;
  border-radius: 5px;
  background: #8793a4;
  box-shadow: 0 4px 9px rgba(27, 40, 61, .15);
}
.piano-key { user-select: none; }
.piano-key-white {
  position: relative;
  flex: 1 1 0;
  min-width: 0;
  height: 100%;
  border-right: 1px solid #c4cad2;
  border-radius: 0 0 3px 3px;
  background: linear-gradient(90deg, #fff 0%, #f7f8fa 78%, #dce1e7 100%);
  box-shadow: inset 0 -4px 0 rgba(73, 87, 105, .12);
}
.piano-key-white:first-child { border-radius: 3px 0 3px 3px; }
.piano-key-white:last-of-type { border-right: 0; border-radius: 0 3px 3px 3px; }
.piano-key-white span { position: absolute; right: 2px; bottom: 4px; left: 2px; overflow: hidden; color: #8b96a5; font: 600 7px/1 Inter, sans-serif; text-align: center; text-overflow: ellipsis; white-space: nowrap; }
.piano-key-black {
  position: absolute;
  z-index: 2;
  top: 0;
  width: var(--black-key-width);
  height: 61%;
  transform: translateX(-50%);
  border: 1px solid #1c2330;
  border-top: 0;
  border-radius: 0 0 3px 3px;
  background: linear-gradient(90deg, #111722 0%, #303a4b 55%, #0b1018 100%);
  box-shadow: 0 3px 3px rgba(12, 18, 29, .36);
}
.piano-key-black span { display: none; }
.piano-key.playing { background: var(--accent); color: #fff; box-shadow: none; }
.piano-key-black.playing { border-color: var(--accent); background: var(--accent); box-shadow: none; }

.processing-overlay { background: rgba(0, 0, 0, .76); }
.processing-card { min-width: 340px; padding: 24px 30px; border-radius: var(--radius); box-shadow: var(--shadow-2); }
.progress-fill { background: var(--accent); }

/* 响应式：空间不足时让左侧设置先落到预览上方 */
@media screen and (max-width: 1360px) {
  .workspace { grid-template-columns: minmax(292px, 316px) minmax(0, 1fr); padding-left: 16px; padding-right: 16px; }
  .legend { display: none; }
  .preview-toolbar { gap: 12px; }
}
@media screen and (max-width: 1160px) {
  .workspace { grid-template-columns: 292px minmax(0, 1fr); gap: 14px; }
  .control-panel { padding-left: 16px; padding-right: 16px; }
  .preview-toolbar { grid-template-columns: 1fr; align-items: start; }
  .preview-actions { justify-content: flex-start; }
}
@media screen and (max-width: 980px) {
  .workspace { grid-template-columns: 1fr; gap: 14px; padding: 14px; }
  .control-panel { position: static; max-height: none; }
  .preview-panel { height: auto; min-height: 740px; }
  .preview-toolbar { grid-template-columns: minmax(0, 1fr) auto; align-items: center; }
  .score-preview { grid-template-columns: minmax(0, 1fr); }
}
@media screen and (max-width: 720px) {
  .topbar { height: auto; min-height: 68px; padding: 10px 14px; }
  .top-actions { max-width: 100%; }
  .status-box { max-width: 155px; }
  .preview-toolbar { grid-template-columns: 1fr; align-items: start; padding: 12px; }
  .preview-actions { width: 100%; justify-content: flex-start; }
  .zoom-control { display: none; }
  .score-preview { padding: 14px; gap: 16px; }
  .play-measure { display: none; }
}
@media screen and (max-width: 520px) {
  .topbar { align-items: center; flex-wrap: wrap; }
  .brand-subtitle { display: none; }
  .top-actions { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; flex: 1 1 100%; min-width: 0; width: 100%; margin-left: 0; gap: 5px; }
  .top-actions .status-box { min-width: 0; max-width: none; }
  .status-box { padding-left: 8px; padding-right: 8px; }
  .top-actions .button { padding-left: 9px; padding-right: 9px; }
  .workspace { padding: 10px; }
  .control-panel { padding: 18px 14px 20px; }
  .metadata-section .field-grid { grid-template-columns: 1fr; }
  .engine-row { align-items: stretch; flex-direction: column; }
  .engine-row .button { width: 100%; }
  .preview-panel { min-height: 640px; }
  .preview-toolbar { padding: 11px 10px; }
  .preview-actions { gap: 5px; }
  .preview-actions .group { flex: 0 0 auto; }
  .layout-switch { margin-left: 0; }
  .timeline-dock { padding-left: 10px; padding-right: 10px; }
  .piano-dock { padding-left: 10px; padding-right: 10px; }
  .piano-keyboard { min-width: 720px; height: 86px; }
  .timeline-label { display: none; }
  .empty-state { padding: 30px 20px; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    scroll-behavior: auto !important;
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}

/* ===== 2026-09-09 editor workspace v2 =====
   真正的三栏编辑器：来源 / 画布 / 检查器。这里故意覆盖上一轮的两栏布局，
   让三个区域承担不同任务，避免所有控件继续堆在同一张卡片里。 */
.workspace {
  grid-template-columns: 272px minmax(620px, 1fr) 312px;
  grid-template-areas: "source preview settings";
  gap: 14px;
  padding: 16px clamp(16px, 2vw, 28px) 22px;
  align-items: stretch;
  min-height: calc(100vh - 108px);
}
.source-panel { grid-area: source; }
.preview-panel { grid-area: preview; }
.settings-panel { grid-area: settings; }

/* 左栏是工作流入口：深色与中间画布形成明确分区。
   色值全部收进本面板的局部变量 --src-*（深色为默认值），浅色主题在本段末尾统一换肤 */
.source-panel {
  --src-fg: #f6f8ff;
  --src-hi: #ffffff;
  --src-mut: #b4c0d5;
  --src-mut-2: #9cacc7;
  --src-lbl: #c8d2e5;
  --src-dim: #8998b2;
  --src-dim-2: #71829f;
  --src-step: #91a1bc;
  --src-step-n: #93a4c2;
  --src-step-hi: #c0cbe0;
  --src-line: #33424a;
  --src-border: #14262c;
  --src-div: rgba(213, 225, 255, .14);
  --src-acc: #7db3f4;
  --src-acc-2: #5b9bef;
  --src-acc-3: #a8c8f7;
  --src-btn-ink: #0a1628;
  --src-btn-hover: #7db3f4;
  --src-panel-bg:
    linear-gradient(170deg, #101318 0%, #0a0c0e 62%, #06080a 100%);
  --src-shadow: 0 18px 42px rgba(13, 25, 48, .18);
  --src-dz-border: rgba(91, 155, 239, .45);
  --src-dz-bg: linear-gradient(160deg, rgba(91, 155, 239, .10), rgba(18, 20, 24, .72));
  --src-dz-bg-hi: linear-gradient(160deg, rgba(91, 155, 239, .18), rgba(18, 20, 24, .8));
  --src-input-bg: rgba(6, 14, 30, .34);
  --src-chip-bg: rgba(6, 14, 30, .28);
  --src-chip-border: rgba(91, 155, 239, .15);
  --src-ghost: rgba(255, 255, 255, .1);
  --src-ghost-hi: rgba(255, 255, 255, .16);
  --src-ghost-border: rgba(91, 155, 239, .2);
  --src-ghost-border-hi: rgba(91, 155, 239, .4);
  --src-flow-border: rgba(91, 155, 239, .14);
  --src-flow-bg: rgba(4, 12, 16, .35);
  --src-focus: 0 0 0 3px rgba(91, 155, 239, .25);
  position: sticky;
  top: 88px;
  height: calc(100vh - 104px);
  max-height: none;
  overflow: auto;
  padding: 22px 18px 18px;
  color: var(--src-fg);
  border: 1px solid var(--src-border);
  border-radius: 18px;
  background: var(--src-panel-bg);
  box-shadow: var(--src-shadow);
  scrollbar-color: var(--src-line) transparent;
}
.source-panel::-webkit-scrollbar { width: 8px; }
.source-panel::-webkit-scrollbar-thumb { background: var(--src-line); border: 2px solid transparent; border-radius: 999px; background-clip: padding-box; }
.source-panel .panel-intro { padding: 0 2px 18px; }
.source-panel .panel-eyebrow { color: var(--src-acc-2); }
.source-panel .panel-intro h1 { color: var(--src-hi); font-size: 21px; letter-spacing: -.03em; }
.source-panel .panel-intro p { color: var(--src-mut); }
.source-panel .panel-section { border-bottom-color: var(--src-div); }
.source-panel .section-kicker { color: var(--src-hi); }
.source-panel .section-note { color: var(--src-mut-2); }
.source-panel .drop-zone {
  min-height: 146px;
  border-color: var(--src-dz-border);
  background: var(--src-dz-bg);
  color: var(--src-hi);
}
.source-panel .drop-zone:hover,
.source-panel .drop-zone.dragging { border-color: var(--src-acc-3); background: var(--src-dz-bg-hi); }
.source-panel .drop-zone span { color: var(--src-lbl); }
.source-panel .drop-zone em { color: var(--src-acc); }
.source-panel .drop-icon { color: var(--src-acc); }
.source-panel .field > span { color: var(--src-lbl); }
.source-panel select,
.source-panel input[type="text"] {
  color: var(--src-fg);
  border-color: var(--src-ghost-border);
  background: var(--src-input-bg);
}
.source-panel select:focus,
.source-panel input[type="text"]:focus { border-color: var(--src-acc); box-shadow: var(--src-focus); }
.source-panel input::placeholder { color: var(--src-dim); }
.source-panel .file-meta,
.source-panel .multi-files { color: var(--src-lbl); border-color: var(--src-chip-border); background: var(--src-chip-bg); }
.source-panel .file-meta strong,
.source-panel .multi-files-title { color: var(--src-hi); }
.source-panel .engine-hint { color: var(--src-mut-2); }
.source-panel .button.ghost { color: var(--src-lbl); background: var(--src-ghost); border-color: var(--src-ghost-border); }
.source-panel .button.ghost:hover:not(:disabled) { background: var(--src-ghost-hi); border-color: var(--src-ghost-border-hi); }
.source-panel .button.dark { color: var(--src-btn-ink); background: var(--src-acc-2); }
.source-panel .button.dark:hover:not(:disabled) { background: var(--src-btn-hover); }

/* 流程提示改成纵向轨道，直接对应左栏的三步任务 */
.source-flow { display: flex; flex-direction: column; gap: 0; margin: 0 2px 18px; padding: 13px 12px; border: 1px solid var(--src-flow-border); border-radius: 13px; background: var(--src-flow-bg); }
.flow-step { display: grid; grid-template-columns: 25px minmax(0, 1fr); column-gap: 9px; align-items: center; min-height: 42px; color: var(--src-step); }
.flow-step > span { grid-row: span 2; display: grid; place-items: center; width: 25px; height: 25px; border: 1px solid var(--src-line); border-radius: 50%; color: var(--src-step-n); font-size: 11px; font-weight: 800; }
.flow-step strong { color: var(--src-step-hi); font-size: 11px; line-height: 1.2; }
.flow-step small { color: var(--src-dim-2); font-size: 9px; line-height: 1.3; }
.flow-step.active > span { border-color: var(--src-acc); background: var(--src-acc); color: var(--src-btn-ink); box-shadow: 0 0 0 4px var(--accent-soft); }
.flow-step.active strong { color: var(--src-hi); }
.flow-line { width: 1px; height: 13px; margin: 0 0 0 12px; background: var(--src-line); }

/* 浅色主题：只换 --src-* 的值，左栏结构与间距一条不动 */
:root[data-theme="light"] .source-panel {
  --src-fg: #1b2229;
  --src-hi: #101418;
  --src-mut: #4d5762;
  --src-mut-2: #5f6a76;
  --src-lbl: #3d4650;
  --src-dim: #77828f;
  --src-dim-2: #6b7684;
  --src-step: #5f6a76;
  --src-step-n: #5f6a76;
  --src-step-hi: #2a323b;
  --src-line: #d7dde3;
  --src-border: #e2e7ec;
  --src-div: rgba(20, 23, 27, .12);
  --src-acc: #1f63c8;
  --src-acc-2: #1a56b0;
  --src-acc-3: #1a56b0;
  --src-btn-ink: #ffffff;
  --src-btn-hover: #1a56b0;
  --src-panel-bg: linear-gradient(170deg, #ffffff 0%, #f7f9fb 60%, #eef2f5 100%);
  --src-shadow: 0 14px 34px rgba(20, 23, 27, .10);
  --src-dz-border: rgba(0, 136, 155, .45);
  --src-dz-bg: linear-gradient(160deg, rgba(0, 136, 155, .10), rgba(255, 255, 255, .70));
  --src-dz-bg-hi: linear-gradient(160deg, rgba(0, 136, 155, .18), rgba(255, 255, 255, .85));
  --src-input-bg: rgba(255, 255, 255, .9);
  --src-chip-bg: rgba(255, 255, 255, .75);
  --src-chip-border: rgba(0, 136, 155, .25);
  --src-ghost: rgba(0, 0, 0, .05);
  --src-ghost-hi: rgba(0, 0, 0, .09);
  --src-ghost-border: rgba(0, 136, 155, .30);
  --src-ghost-border-hi: rgba(0, 136, 155, .5);
  --src-flow-border: rgba(0, 136, 155, .20);
  --src-flow-bg: rgba(0, 136, 155, .05);
  --src-focus: 0 0 0 3px rgba(0, 136, 155, .18);
}

/* 中间画布是真正的主区域，减少边缘装饰，增加留白 */
.preview-panel {
  min-width: 0;
  height: calc(100vh - 104px);
  min-height: 680px;
  border-radius: 18px;
  border-color: var(--line);
  background: var(--preview);
  box-shadow: 0 14px 34px rgba(23, 32, 51, .07);
}
.preview-toolbar { min-height: 68px; padding: 14px 18px; background: var(--scrim-2); border-bottom-color: var(--line); }
.preview-actions { gap: 7px; }
.preview-heading { min-width: 150px; }
.preview-title-line { gap: 8px; }
.preview-label { font-size: 15px; letter-spacing: -.02em; }
.preview-canvas { background-image: var(--canvas-haze), var(--canvas-grad); background-repeat: no-repeat; }
.score-preview { padding: 22px 24px 36px; gap: 22px; }
.timeline-dock { padding: 12px 18px 16px; border-top-color: var(--line); background: var(--scrim-3); }

/* 右栏是检查器：独立滚动，不再和导入区抢空间 */
.settings-panel {
  position: sticky;
  top: 88px;
  height: calc(100vh - 104px);
  max-height: none;
  min-width: 0;
  overflow: auto;
  padding: 22px 18px 16px;
  border: 1px solid var(--line);
  border-radius: 18px;
  background: var(--settings-bg);
  box-shadow: var(--shadow-1);
  scrollbar-width: thin;
  scrollbar-color: #cbd4e2 transparent;
}
.settings-panel::-webkit-scrollbar { width: 8px; }
.settings-panel::-webkit-scrollbar-thumb { background: #cbd4e2; border: 2px solid transparent; border-radius: 999px; background-clip: padding-box; }
.settings-head { padding: 0 2px 18px; }
.settings-head h2 { margin: 7px 0 5px; color: var(--ink); font-size: 20px; line-height: 1.25; letter-spacing: -.03em; }
.settings-head p { margin: 0; color: var(--muted); font-size: 11px; line-height: 1.5; }
.settings-stack { display: flex; flex-direction: column; }
.settings-panel .panel-section { padding: 18px 0; }
.settings-panel .panel-section:first-child { padding-top: 0; }
.settings-panel .panel-section:last-child { padding-bottom: 0; }
.settings-panel .field-grid { grid-template-columns: 1fr; }
.settings-panel .field input,
.settings-panel .field select { width: 100%; }
.settings-panel .toggle-list { gap: 0; }
.settings-panel .toggle-row { min-height: 56px; padding: 10px 0; border-bottom: 1px solid var(--line); }
.settings-panel .toggle-row:last-child { border-bottom: 0; }
.settings-footer { display: flex; align-items: center; gap: 8px; margin-top: 18px; padding: 11px 12px; border: 1px solid var(--line); border-radius: 10px; color: var(--muted); background: var(--soft); font-size: 10px; line-height: 1.4; }
.settings-footer-dot { width: 7px; height: 7px; flex: 0 0 auto; border-radius: 50%; background: #5ab582; box-shadow: 0 0 0 3px rgba(90, 181, 130, .14); }

/* 1180px 以下保留两栏，但把设置检查器完整落到画布下方 */
@media screen and (max-width: 1420px) {
  .workspace { grid-template-columns: 250px minmax(520px, 1fr) 286px; gap: 12px; padding-left: 14px; padding-right: 14px; }
  .source-panel, .settings-panel { padding-left: 15px; padding-right: 15px; }
  .legend { display: none; }
}
@media screen and (max-width: 1180px) {
  .workspace {
    grid-template-columns: 260px minmax(0, 1fr);
    grid-template-areas: "source preview" "settings settings";
    align-items: start;
  }
  .source-panel, .settings-panel { position: static; height: auto; max-height: none; }
  .source-panel { min-height: 0; }
  .settings-panel { display: grid; grid-template-columns: 210px minmax(0, 1fr) 230px; gap: 18px; align-items: start; }
  .settings-head { padding-bottom: 0; }
  .settings-stack { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px; }
  .settings-stack .display-section { grid-column: 1 / -1; }
  .settings-footer { margin-top: 0; }
  .preview-panel { height: calc(100vh - 104px); }
}
@media screen and (max-width: 980px) {
  .workspace {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "source" "preview" "settings";
    padding: 12px;
  }
  .source-panel, .settings-panel { position: static; height: auto; }
  .source-panel { padding: 20px; }
  .source-flow { flex-direction: row; align-items: stretch; padding: 10px; }
  .flow-step { flex: 1 1 0; grid-template-columns: 25px minmax(0, 1fr); min-width: 0; }
  .flow-line { width: auto; height: 1px; flex: 0 0 16px; margin: 12px 6px 0; }
  .preview-panel { height: auto; min-height: 720px; }
  .settings-panel { display: block; }
  .settings-head { padding-bottom: 14px; }
  .settings-stack { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px; }
  .settings-stack .display-section { grid-column: 1 / -1; }
  .settings-footer { margin-top: 18px; }
}
@media screen and (max-width: 720px) {
  .workspace { padding: 9px; gap: 9px; }
  .source-panel, .settings-panel { padding: 16px 14px; border-radius: 15px; }
  .source-flow { display: none; }
  .settings-stack { display: block; }
  .settings-panel .panel-section { padding: 15px 0; }
  .preview-panel { min-height: 620px; border-radius: 15px; }
  .preview-toolbar { padding: 12px; }
  .preview-actions { flex-wrap: wrap; }
  .score-preview { padding: 14px 10px 24px; }
}
/* 左右两栏面板不进纸，画布独占整页（整段打印样式已统一挪到文件末尾） */

/* ===== 2026-09-09 检查器控件 v3 =====
   二选一不该藏进下拉：分段控件一眼看全、一次点中；
   滑杆去掉浏览器默认蓝，统一进设计色板；开关表达依赖关系。 */

/* 记谱方式：分段选择器 */
.segmented { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.segment {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 9px 11px;
  border: 1px solid var(--line-strong);
  border-radius: 10px;
  background: var(--panel);
  cursor: pointer;
  transition: border-color .15s var(--ease), background .15s var(--ease), box-shadow .15s var(--ease);
}
.segment input { position: absolute; opacity: 0; pointer-events: none; }
.segment:hover { border-color: #a9b6cc; }
.segment-title { color: var(--ink); font-size: 12px; font-weight: 750; line-height: 1.3; }
.segment-hint { color: var(--muted); font-size: 9.5px; line-height: 1.35; }
.segment:has(input:checked) {
  border-color: var(--accent);
  background: var(--accent-soft);
  box-shadow: inset 0 0 0 1px var(--accent);
}
.segment:has(input:checked) .segment-title { color: var(--accent-strong); }
.segment:has(input:checked) .segment-hint { color: #5c77c9; }
.segment:has(input:checked)::after {
  content: "✓";
  position: absolute;
  top: 7px;
  right: 9px;
  color: var(--accent);
  font-size: 11px;
  font-weight: 800;
}
.segment:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }

.notation-section .bpm-field { margin-top: 12px; }

/* 版式滑杆：细轨道 + 已填充进度 + 白底描边滑块 */
.slider-field + .slider-field { margin-top: 14px; }
.slider-head { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 5px; }
.slider-head > span { color: var(--muted-strong); font-size: 10.5px; font-weight: 700; }
.slider-head output {
  padding: 1px 7px;
  border-radius: 6px;
  background: var(--soft);
  color: var(--ink);
  font-size: 11px;
  font-weight: 750;
  font-variant-numeric: tabular-nums;
}
.settings-panel input[type="range"] {
  appearance: none;
  -webkit-appearance: none;
  width: 100%;
  height: 20px;
  margin: 0;
  background: transparent;
  cursor: pointer;
}
.settings-panel input[type="range"]::-webkit-slider-runnable-track {
  height: 4px;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--accent) var(--fill, 50%), var(--track-fill) var(--fill, 50%));
}
.settings-panel input[type="range"]::-webkit-slider-thumb { 
  -webkit-appearance: none;
  appearance: none;
  width: 14px;
  height: 14px;
  margin-top: -5px;
  border: 1.5px solid var(--accent);
  border-radius: 50%;
  background: #eef2f6;
  box-shadow: 0 1px 4px rgba(23, 32, 51, .18);
  transition: transform .12s var(--ease), box-shadow .12s var(--ease);
}
.settings-panel input[type="range"]:hover::-webkit-slider-thumb { transform: scale(1.15); }
.settings-panel input[type="range"]:active::-webkit-slider-thumb { transform: scale(1.2); box-shadow: 0 0 0 5px rgba(0, 229, 255, .16); }
.settings-panel input[type="range"]:focus-visible { outline: none; }
.settings-panel input[type="range"]:focus-visible::-webkit-slider-thumb { box-shadow: var(--focus-ring); }
.settings-panel input[type="range"]::-moz-range-track { height: 4px; border-radius: 999px; background: var(--track-fill); }
.settings-panel input[type="range"]::-moz-range-progress { height: 4px; border-radius: 999px; background: var(--accent); }
.settings-panel input[type="range"]::-moz-range-thumb {
  width: 13px;
  height: 13px;
  border: 1.5px solid var(--accent);
  border-radius: 50%;
  background: #eef2f6;
  box-shadow: 0 1px 4px rgba(0, 0, 0, .4);
}
.slider-scale { display: flex; justify-content: space-between; margin-top: 2px; color: #9aa6b8; font-size: 9px; }

/* ===== v3 · 工作台布局（方案 C，2026-10-13）=====
   命令栏 + 左文件轨 + 画布 + 右折叠检查器 + 底部统一轨。
   整段写在所有屏幕规则之后、打印段之前：同优先级后写的赢，覆盖 v1/v2 同名规则；
   打印仍以文件末尾的 @media print 为准。窄屏阶梯也在本段自带，旧阶梯已被压住。 */
body { overflow: hidden; }
.app-shell { display: flex; flex-direction: column; height: 100vh; overflow: hidden; }

/* 命令栏：一行放下身份与两个动作。64px 是给 40px 徽章 + 38px 按钮留出的呼吸高度
   （早前压到 48px，控件上下只剩 4px，紧贴边缘），左右 padding 同步放大。
   flex:0 0 auto 是必须的：app-shell 是 100vh 的 flex 纵向容器，flex-shrink 默认 1，
   workspace 内容一多就会把顶栏压扁（实测被啃到 41px，logo 上下贴边）。 */
.topbar { height: 64px; padding: 0 clamp(18px, 2.4vw, 36px); gap: 14px; flex: 0 0 auto; }
.topbar .brand-subtitle { display: none; }
.brand-title { font-size: 15.5px; }
/* 品牌字标（2026-10-19 新 logo）：方块里是从字标裁出来的「z.」，右边整条 zhuanpu.work。
   图都是 tools/make-logo.py 从设计稿抠的透明 PNG（拼写已修 wrok→work），明暗各一版；
   背景图写法不是省事——只下载命中的那一张，比摆两条 <img> 少一半流量。 */
.brand-mark {
  background: var(--logo-plate);
  border: 1px solid var(--line);
  padding: 0;
}
.brand-mark img { width: 30px; height: auto; display: block; }
.brand-wordmark {
  display: block; width: 148px; height: 20px;
  background: url("./assets/logo/zhuanpu-work.png") no-repeat left center / contain;
}
:root[data-theme="dark"] .brand-wordmark { background-image: url("./assets/logo/zhuanpu-work-dark.png"); }
.top-actions { margin-left: auto; }

/* 工作区：三列各自独立滚动，谁也不再 sticky */
.workspace {
  display: grid;
  grid-template-columns: 214px minmax(0, 1fr) 272px;
  grid-template-areas: "source preview settings";
  gap: 12px;
  padding: 12px 14px;
  min-height: 0;
  height: auto;
  flex: 1 1 auto;
}
.control-panel, .settings-panel {
  position: static;
  top: auto;
  align-self: stretch;
  max-height: none;
  height: 100%;
  min-height: 0;
  overflow: auto;
}

/* 左轨：小标签 + 文件卡 + 谱页列表 + 拖放卡 + 示例 */
.source-panel { padding: 14px 12px 16px; }
.source-panel .panel-intro, .source-panel .source-flow { display: none; }
.src-label { font-size: 10.5px; letter-spacing: .14em; font-weight: 780; color: var(--muted); margin: 2px 2px 12px; }
.source-panel .file-meta, .source-panel .multi-files { margin-bottom: 10px; }
.page-list:not(.hidden) { display: flex; flex-direction: column; gap: 8px; margin-bottom: 4px; }
.page-item {
  display: flex; gap: 9px; align-items: center;
  width: 100%; text-align: left;
  padding: 7px 8px; border: 1px solid var(--line); border-radius: 11px;
  background: var(--soft); color: var(--ink);
  font: inherit; cursor: pointer;
  transition: border-color .15s var(--ease), background .15s var(--ease);
}
.page-item:hover { border-color: var(--accent); background: var(--accent-soft); }
.page-item .mini { position: relative; width: 34px; height: 46px; flex: 0 0 auto; background: var(--score-paper, #fff); border-radius: 2px; overflow: hidden; box-shadow: 0 1px 3px rgba(0, 0, 0, .35); }
.page-item .mini::before, .page-item .mini::after { content: ""; position: absolute; left: 4px; right: 4px; height: 1.5px; background: var(--score-ink, #16181c); }
.page-item .mini::before { top: 13px; }
.page-item .mini::after { top: 30px; }
.page-item .mini i { position: absolute; left: 4px; right: 4px; top: 18px; height: 8px; background: repeating-linear-gradient(90deg, var(--score-ink, #16181c) 0 3px, transparent 3px 6px); opacity: .7; }
.page-item .tt, .page-item .ts { display: block; }
.page-item .tt { font-size: 12px; font-weight: 680; }
.page-item .ts { font-size: 10.5px; color: var(--muted); margin-top: 2px; }
.source-panel .drop-zone { margin-top: 10px; min-height: 132px; }

/* 画布：唯一主角；工具条缩成右上角浮动条 */
.preview-panel { height: 100%; min-height: 0; overflow: hidden; display: flex; flex-direction: column; }
.preview-canvas { position: relative; }
.canvas-float {
  position: absolute; top: 12px; right: 16px; z-index: 6;
  display: flex; gap: 6px; align-items: center;
  padding: 5px 7px; border: 1px solid var(--line); border-radius: 12px;
  background: var(--panel); box-shadow: var(--shadow-1);
  backdrop-filter: blur(10px);
}
.canvas-float .group { display: flex; align-items: center; gap: 2px; border: 0; background: none; box-shadow: none; padding: 0; }
/* 还没上传时（空状态）工具条没意义——缩放/排布都作用于谱面，空画布上点了没反应 */
.preview-canvas:has(#emptyState:not(.hidden)) .canvas-float { display: none; }
/* 空状态：整幅画布归那一块大拖放区，左轨与右检查器都收起来（检查器上的调性/速度/版式
   没谱可调；左轨的文件卡也还没有文件）。手机上也一样，特异性压过窄屏阶梯。 */
.app-shell:has(#emptyState:not(.hidden)) .footrail { display: none; }

.workspace:has(#emptyState:not(.hidden)):not(:has(#startRecognizeBtn:not(.hidden))) {
  grid-template-columns: minmax(0, 1fr); grid-template-areas: "preview";
}
.workspace:has(#emptyState:not(.hidden)):not(:has(#startRecognizeBtn:not(.hidden))) .source-panel,
.workspace:has(#emptyState:not(.hidden)) .settings-panel { display: none; }
/* 例外：已经选了待识别的文件（"开始识别"按钮亮着）时左轨要露出来——多图合并得先让人看列表
   再点开始，那套 UI 就在左轨里；检查器仍然收着。 */
.workspace:has(#emptyState:not(.hidden)):has(#startRecognizeBtn:not(.hidden)) {
  grid-template-columns: 214px minmax(0, 1fr); grid-template-areas: "source preview";
}

/* 右：折叠检查器 */
.settings-panel { padding: 4px 10px 14px; }
.settings-head, .settings-stack { display: block; }
.settings-panel .acc { border-bottom: 1px solid var(--line); }
.settings-panel .acc > summary {
  list-style: none; cursor: pointer;
  display: flex; justify-content: space-between; align-items: center; gap: 8px;
  padding: 12px 6px; font-size: 12.5px; font-weight: 720; color: var(--ink);
}
.settings-panel .acc > summary::-webkit-details-marker { display: none; }
.settings-panel .acc > summary::after { content: "▾"; font-size: 10px; color: var(--muted); transition: transform .15s var(--ease); }
.settings-panel .acc[open] > summary::after { transform: rotate(180deg); }
.settings-panel .acc-in { padding: 0 6px 14px; }
.settings-panel .acc .panel-section { border-bottom: 0; margin: 0; padding: 0; }
.settings-panel .acc .section-kicker { display: none; }  /* 与 summary 重复 */
.settings-panel .acc .section-note { font-size: 11.5px; margin-bottom: 10px; }
.settings-panel .settings-footer { margin-top: 12px; }
.settings-panel .legend { display: flex; }   /* 旧规则在 ≤1420 会把图例整个藏掉，这里按面板收回 */
.legend-block { flex-direction: column; align-items: flex-start; gap: 9px; font-size: 11.5px; color: var(--muted); }

/* 底部统一轨：走带 + 统计 + 试听开关 + 状态 */
.footrail {
  flex: 0 0 auto;
  display: flex; align-items: center; gap: 14px;
  height: 44px; padding: 0 14px;
  border-top: 1px solid var(--line);
  background: var(--panel);
  position: relative; z-index: 16;
  font-size: 12px;
}
.footrail .group.play-control { flex: 0 0 auto; }
.footrail .timeline-dock {
  display: flex; align-items: center; gap: 10px;
  flex: 1 1 auto; max-width: 560px; min-width: 0;
  padding: 0; margin: 0; background: transparent; border: 0; box-shadow: none;
}
.footrail .play-timeline:not(.hidden) { display: flex; align-items: center; gap: 10px; flex: 1; min-width: 0; }
.rail-stats { font-size: 11.5px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 300px; }
.rail-spacer { flex: 1 1 auto; }
/* 底轨上的开关（钢琴）。**和状态胶囊同一套形制**：无边框圆胶囊 + --soft 底 + 次要文字色，
   开态沿用状态胶囊那套"淡色底 + 强调色文字"（而不是自成一格的方角描边块——
   它俩在底轨上紧挨着，形制不一致看着就是两块不同的东西）。 */
.rail-chip {
  display: inline-flex; align-items: center; justify-content: center;
  flex: 0 0 auto; min-height: 38px;   /* 与状态胶囊同高，两颗胶囊并排才齐 */
  border: 1px solid transparent; border-radius: 999px;
  background: var(--soft); color: var(--muted-strong);
  padding: 7px 13px; font-size: 12px; font-weight: 620; cursor: pointer;
  transition: background .2s var(--ease), color .2s var(--ease), border-color .2s var(--ease);
}
.rail-chip:hover { background: var(--hover-soft); color: var(--ink); }
.rail-chip[aria-pressed="true"] { background: var(--accent-soft); color: var(--accent); border-color: transparent; }
.footrail .status-box { flex: 0 0 auto; margin: 0; max-width: 46%; }

/* 窄屏阶梯（本段自带，压住旧阶梯） */
@media screen and (max-width: 1420px) {
  .workspace { grid-template-columns: 196px minmax(0, 1fr) 250px; }
}
@media screen and (max-width: 1180px) {
  body { overflow: auto; }
  .app-shell { height: auto; overflow: visible; }
  .workspace { grid-template-columns: minmax(0, 1fr); grid-template-areas: "preview" "source" "settings"; height: auto; }
  .control-panel, .settings-panel, .preview-panel { height: auto; overflow: visible; min-height: 0; }
  .preview-panel { min-height: 68vh; }
  .preview-canvas { overflow: visible; }
  .settings-panel { display: block; }
  .footrail { position: sticky; bottom: 0; }
}
@media screen and (max-width: 720px) {
  .workspace { padding: 10px; gap: 10px; }
  .canvas-float { top: 8px; right: 8px; }
  .footrail { gap: 8px; padding: 0 10px; }
  .rail-stats { display: none; }
}

/* ===== 次数包（顶栏胶囊 + 面板，2026-10-13）=====
   颜色一律走令牌，明暗两套主题都跟着变；面板是 native <dialog>，
   遮罩用 ::backdrop，弹在浏览器最上层（不受 .preview-canvas 的 overflow 影响）。 */
.pay-pill { display: inline-flex; align-items: center; }
.pay-pill.hidden { display: none; }

.pay-dialog {
  width: min(92vw, 380px);
  padding: 0;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--panel);
  color: var(--ink);
  box-shadow: var(--shadow-2);
}
.pay-dialog::backdrop { background: rgba(0, 0, 0, .55); }
:root[data-theme="light"] .pay-dialog::backdrop { background: rgba(20, 23, 27, .35); }

.pay-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; padding: 16px 18px 12px;
}
.pay-head h2 { margin: 0; font-size: 15px; font-weight: 680; }
.pay-close {
  border: 0; background: transparent; color: var(--muted);
  font-size: 20px; line-height: 1; padding: 4px 6px; border-radius: var(--radius-xs);
}
.pay-close:hover { background: var(--soft); color: var(--ink); }

.pay-body { padding: 0 18px 18px; }
.pay-balance { display: flex; align-items: baseline; gap: 6px; margin: 0; }
.pay-balance strong { font-size: 34px; font-weight: 700; letter-spacing: -.02em; }
.pay-balance span { font-size: 13px; color: var(--muted); }
.pay-detail { margin: 6px 0 14px; font-size: 12px; color: var(--muted); }

.pay-packs { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.pay-pack {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 10px 12px; border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--soft);
}
.pay-pack-label { display: flex; flex-direction: column; gap: 2px; }
.pay-pack-label strong { font-size: 13.5px; font-weight: 640; }
.pay-pack-label small { font-size: 12px; color: var(--muted); }

.pay-note { margin: 12px 0 0; font-size: 12px; color: var(--muted); min-height: 16px; }
.pay-note.ok { color: var(--success); }
.pay-note.warn { color: var(--warning); }
.pay-note.error { color: var(--danger); }
.pay-note a { color: var(--accent); }
.pay-fineprint { margin: 14px 0 0; font-size: 11.5px; color: var(--muted); }

/* ===== 手机（≤720px）针对性重排（2026-10-13）=====
   旧窄屏阶梯（editor v2 那几段）只零散改了几个属性，手机上留下三个真问题：
   ① 顶栏被撑成两行（`.top-actions` 还留着旧阶梯的 `width:100%` + `flex:1 1 100%`，
      品牌被挤成两行文字）；
   ② 画布工具条浮在谱面标题上（一浮就压住第一行）；
   ③ 底轨被挤到时间线只剩 38px，拖都拖不动。
   这一段按手机重排；桌面（>720px）一行都不受影响。 */
@media screen and (max-width: 720px) {
  /* ① 命令栏：一行放下 品牌 + 次数 + 导出 + 主题（放不下时先挤次数胶囊，别的都别换行） */
  .topbar {
    height: auto; min-height: 52px; padding: 6px 10px; gap: 8px;
    flex-wrap: nowrap; align-items: center;
  }
  .brand { gap: 8px; min-width: 0; }
  .brand-mark { width: 30px; height: 30px; border-radius: 9px; }
  .brand-mark img { width: 22px; }
  .brand-wordmark { width: 120px; height: 16.5px; }
  .brand-title { font-size: 14px; letter-spacing: .02em; white-space: nowrap; }
  .top-actions {
    display: flex; flex-wrap: nowrap; gap: 6px;
    /* width:auto 是必须的：≤520 那段旧阶梯留了 width:100%，会把这一行撑成"品牌被挤 + 按钮靠右" */
    width: auto; flex: 0 1 auto; min-width: 0; margin-left: auto;
  }
  .top-actions .button { padding: 8px 10px; min-height: 36px; font-size: 12.5px; }
  .theme-btn { min-width: 36px; padding: 8px; }
  .pay-pill { min-width: 0; }
  .pay-pill span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

  /* ② 工作区：导入 → 画布 → 调整。手机第一屏要看得见「上传」，
     示例谱排在上传卡下面（桌面那套"左轨常驻"在手机上没这个空间）。 */
  .workspace { grid-template-areas: "source" "preview" "settings"; padding: 8px; gap: 8px; }
  .source-panel { padding: 10px 10px 12px; }
  .source-panel .drop-zone { min-height: 96px; margin-top: 8px; }
  .drop-zone .drop-icon { font-size: 20px; }
  /* 谱页横滑一行：手机上纵向最贵，别让两页卡占 130px */
  .page-list:not(.hidden) { flex-direction: row; gap: 8px; overflow-x: auto; padding-bottom: 2px; }
  .page-item { width: auto; flex: 0 0 auto; padding: 8px 10px; }

  /* ③ 画布：工具条改成谱面上方一行（浮动条在手机上必然压住标题/第一行） */
  .preview-panel { min-height: 56vh; }
  .canvas-float { position: static; align-self: flex-end; margin: 0 8px 8px; }
  .canvas-float button { min-width: 34px; min-height: 34px; }
  .zoom-fit, .layout-btn { padding: 0 10px; }
  .score-preview { padding: 0 8px 12px; }

  /* ④ 底轨：改成两行网格——第一行 走带 + 时间线（终于拖得动），
     第二行 状态（独占左侧大半行，报错不再被截成半句）+ 钢琴。
     用网格而不是 flex-wrap：flex 里"整行"要靠 flex-basis:100%，会把钢琴挤到第三行去。
     iPhone 底部安全区让开，否则最后一行压在小白条上。 */
  .footrail {
    display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-areas: "play time time" "status status chip";
    align-items: center; height: auto; gap: 6px 8px;
    padding: 6px 10px calc(6px + env(safe-area-inset-bottom, 0px));
  }
  .footrail .group.play-control { grid-area: play; }
  .footrail .timeline-dock { grid-area: time; gap: 6px; max-width: none; min-width: 0; }
  .footrail .play-timeline:not(.hidden) { gap: 6px; }
  .play-btn { min-width: 36px; min-height: 36px; }
  .play-measure { display: none; }        /* 手机这一行放不下小节号，宽度留给进度条 */
  .play-time { font-size: 11px; }
  .rail-spacer, .rail-stats { display: none; }
  .rail-chip { grid-area: chip; padding: 8px 12px; }
  .footrail .status-box { grid-area: status; max-width: none; min-width: 0; }
  .footrail .status-box #statusText { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

  /* ⑤ 检查器 / 钢琴键盘 / 空状态：点得着、别占太多高度 */
  .settings-panel { padding: 0 10px 12px; }
  .settings-panel .acc > summary { padding: 14px 8px; font-size: 13.5px; }
  .settings-panel .acc-in { padding: 0 8px 14px; }
  .piano-dock { padding: 8px 10px 10px; }
  .piano-keyboard { min-width: 660px; height: 76px; }
  /* 空状态：手机上就是这一屏（顶栏 52 + 底轨 ~93 + 边距），别在下面留一条白；
     三栏能力行塌成一列，投放面压矮一点 */
  .empty-state {
    padding: 24px 14px 26px; margin: 8px auto;
    min-height: calc(100vh - 168px);
    min-height: calc(100dvh - 168px);
  }
  .empty-heading { font-size: 28px; }
  .empty-sub { margin-top: 12px; font-size: 15px; }
  .empty-drop { min-height: 230px; margin-top: 22px; padding: 28px 18px; border-radius: 14px; }
  .empty-drop-icon { margin-bottom: 16px; }
  .empty-drop .empty-pick { min-height: 44px; padding: 0 24px; }
  .empty-kbd { display: none; }   /* 手机上没有 Ctrl/⌘ */
  /* 三栏塌成一列：分割线得跟着从竖线换成横线，不然左边留一截秃竖线 */
  .empty-facts { grid-template-columns: minmax(0, 1fr); margin-top: 28px; padding-top: 24px; }
  .empty-facts li { padding: 0; }
  .empty-facts li + li { border-left: 0; border-top: 1px solid var(--line); margin-top: 18px; padding-top: 18px; }
  .site-foot-inner { padding: 32px 16px 48px; }
}

/* ===== 打印 / 导出 PDF（「导出 → PDF」走 window.print()）=====
   整段必须留在文件最末：CSS 按源码顺序取胜，v2 布局（.workspace / .preview-panel /
   .score-preview 的 padding、height、grid-template-areas 等）写在前面的 @media print
   会被这些屏幕规则覆盖——以前就是这么坏的：print 的 .workspace{padding:0}、
   .preview-panel{height:auto}、.score-preview{padding:0} 全被盖掉，纸上留下屏幕版的
   内边距和视口高度。以前靠带 !important 的反色规则才活了下来，那段反色随
   2026-10-12 白纸黑谱的改动一并删掉（屏上已是白纸，纸上不再需要反转）。
   加规则一律加进这一段，别再在文件中间新开 @media print。 */
@media print {
  @page { size: A4 landscape; margin: 10mm; }
  body { background: white; }

  /* ① 只留画布：顶栏、工具条、播放条、钢琴键盘、两栏面板、底轨与浮动条都不进纸 */
  .topbar, .control-panel, .preview-toolbar, .timeline-dock, .piano-dock, .empty-state { display: none !important; }
  .source-panel, .settings-panel, .source-flow, .settings-footer { display: none !important; }
  .footrail, .canvas-float, .page-list, .site-foot { display: none !important; }

  /* ② 画布铺满、可换行分页 */
  .workspace { display: block; padding: 0; grid-template-areas: "preview"; }
  .preview-panel { height: auto; min-height: 0; border: 0; background: white; overflow: visible; box-shadow: none; }
  .preview-canvas { display: block; overflow: visible; background: white; }
  .score-preview { padding: 0; overflow: visible; display: block; zoom: 1 !important; }

  /* ③ 每页纸一张，页与页之间强制分页 */
  /* jpfun 引擎的页：A4 尺寸与页边距都已经排进 SVG，纸上不再加内边距 */
  .jp-page { width: 100%; max-width: none; aspect-ratio: auto; margin: 0 0 4mm; border-radius: 0; box-shadow: none; page-break-after: always; break-after: page; }
  .jp-page:last-child { page-break-after: auto; break-after: auto; }
  .play-timeline { display: none !important; }

  /* ④ 纸与墨全部由 :root 的 --score-* 决定（2026-10-12 起是白纸黑谱），
        屏上和纸上取同一组值，这里不再需要反色。纸以外的画布留白由 ② 负责。 */
}
