/* [layout.css] source: Pro.html lines 135-260, 369-450, 451-539 (verbatim) */
body{
  font-family:'Segoe UI','PingFang SC','Microsoft YaHei',system-ui,sans-serif;
  background:
    radial-gradient(1200px 600px at 85% -10%, rgba(124,108,255,.14), transparent 60%),
    radial-gradient(900px 500px at -10% 110%, rgba(0,217,255,.10), transparent 60%),
    linear-gradient(180deg,var(--bg0),var(--bg1));
  /* 主题跟随：用主题色重新派生环境光（不支持 color-mix 时沿用上面那行） */
  background:
    radial-gradient(1200px 600px at 85% -10%, rgba(var(--acc2-rgb),.16), transparent 60%),
    radial-gradient(900px 500px at -10% 110%, rgba(var(--acc-rgb),.12), transparent 60%),
    linear-gradient(180deg,var(--bg0),var(--bg1));
  color:var(--txt); overflow:hidden;
}
button{font-family:inherit;color:inherit}
input,select{font-family:inherit;color:inherit}
/* 全局焦点环（键盘可达性） */
:focus-visible{outline:2px solid var(--ring);outline-offset:2px}
::selection{background:rgba(0,217,255,.3)}
::selection{background:rgba(var(--acc-rgb),.34)}
::-webkit-scrollbar{width:10px;height:10px}
::-webkit-scrollbar-thumb{background:var(--line2);border-radius:8px;border:2px solid transparent;background-clip:content-box}
::-webkit-scrollbar-thumb:hover{background:var(--acc);background-clip:content-box;border:2px solid transparent}
::-webkit-scrollbar-track{background:transparent}

/* ---------- 顶栏 ---------- */
/* z-index 必须**高于** .side（同为 40 时，DOM 里靠后的侧栏会盖住顶栏里展开的菜单）。
   顶栏自己就是一个层叠上下文（position:relative + z-index），它内部 .menu 的 z-index:100
   只在顶栏内部有意义 —— 所以想"菜单压过侧栏"，只能把整个顶栏抬到侧栏之上。
   两者在几何上不重叠：.wrap 有 height:calc(100% - 56px)、.side 是它内部的绝对定位层，
   展开的侧栏从顶栏下沿开始，所以抬高顶栏不会挡住侧栏。 */
.topbar{
  height:56px;display:flex;align-items:center;gap:14px;padding:0 14px;
  background:linear-gradient(180deg,rgba(16,24,40,.92),rgba(11,16,29,.9));
  background:var(--glass);backdrop-filter:blur(var(--glass-blur));-webkit-backdrop-filter:blur(var(--glass-blur));
  border-bottom:1px solid var(--line);box-shadow:var(--shadow-1);position:relative;z-index:60;
}
.brand{display:flex;align-items:center;gap:9px;min-width:190px;cursor:pointer;user-select:none}
.logo{width:30px;height:30px;border-radius:var(--r-sm);background:var(--grad);display:flex;align-items:center;justify-content:center;
  box-shadow:0 0 18px rgba(var(--acc-rgb),.45);font-size:16px}
.brand b{font-size:15px;letter-spacing:.4px;white-space:nowrap}
.badge{font-size:9px;padding:2px 7px;border-radius:20px;background:linear-gradient(100deg,#ff7ac8,#ff6b81);
  color:#1a0b12;font-weight:800;letter-spacing:1px;box-shadow:0 0 12px rgba(255,107,129,.4)}
.sep{width:1px;height:24px;background:var(--hair-2);flex:none}

/* transport */
.transport{display:flex;align-items:center;gap:10px}
/* FEAT-V6/T5 批 2：按钮高度统一 3 档（--h-lg 40 / --h 32 / --h-sm 26）；
   hover 只改颜色（--sig 描边 + --hover 底 + --txt 文字），不再位移/缩放 —— 位移会让按钮内文字重栅格化发虚。 */
.playBtn{width:40px;height:40px;border-radius:var(--r-sm);border:none;cursor:pointer;display:flex;align-items:center;justify-content:center;position:relative;
  background:var(--grad);transition:background-color var(--dur-fast) var(--ease-out),border-color var(--dur-fast) var(--ease-out),color var(--dur-fast) var(--ease-out),box-shadow var(--dur-fast) var(--ease-out),filter var(--dur-fast) var(--ease-out);flex:none}
.playBtn:hover{filter:brightness(1.08)}
.playBtn:active{filter:brightness(.94)}
/* 播放中的"呼吸环"：keyframes 已上移到 theme.css（.vz-play 共用），这里只挂主应用的按钮 */
.playBtn::after{content:'';position:absolute;inset:-2px;border:2px solid var(--sig);border-radius:var(--r-sm);
  opacity:0;pointer-events:none}
.playBtn.playing::after,
.playBtn:has(#stopIco:not([style*="none"]))::after{animation:playRipple calc(var(--dur-enter) * 3) var(--ease-in-out) infinite}
.playBtn svg{width:18px;height:18px;fill:var(--on-acc)}
/* 批 C 第三部分：走带区只留"操作状态"（位置已并入进度行）—— 单行状态给到 10px 与 --mut，太细会看不见 */
.posBox{min-width:78px;text-align:center;display:flex;flex-direction:column;justify-content:center}
.posSub{font-size:var(--fs-label);color:var(--mut);letter-spacing:var(--ls-tech);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* 位置并入进度行后的样式：同一行的等宽小标签（去掉原来的 16px + 辉光，那是"独立锚点"时的规格） */
.seekBar .posMain{flex:none;min-width:56px;font:700 12px var(--mono);color:var(--mut);letter-spacing:.5px;text-shadow:none;user-select:none}
.metroBtn{height:var(--h);padding:0 12px;border-radius:var(--r-sm);border:1px solid var(--hair-2);background:var(--card);
  color:var(--mut);cursor:pointer;font-size:var(--fs-body);transition:background-color var(--dur-fast) var(--ease-out),border-color var(--dur-fast) var(--ease-out),color var(--dur-fast) var(--ease-out),box-shadow var(--dur-fast) var(--ease-out);display:flex;gap:6px;align-items:center}
.metroBtn:hover{background:var(--hover);border-color:var(--sig);color:var(--txt)}
.metroBtn.on{border-color:rgba(var(--good-rgb),.6);color:var(--good);
  box-shadow:0 0 12px rgba(var(--good-rgb),.25);background:rgba(var(--good-rgb),.1)}

.ctrls{display:flex;align-items:center;gap:16px;flex:1;flex-wrap:wrap;min-width:0}
.knobGrp{display:flex;flex-direction:column;gap:2px;min-width:0}
.knobTop{display:flex;align-items:baseline;gap:6px;font-size:var(--fs-label);color:var(--mut);letter-spacing:var(--ls-wide)}
.knobTop .v{font:600 12px var(--mono);color:var(--txt)}
.rangeW{position:relative;width:120px;height:18px;display:flex;align-items:center}
/* 滑块（任务 5）：轨 4px 方角、无辉光；拇指 12px 方形（2px 圆角）信号色实底；已取值段 --sig；
   只有滑块保留 scale（需要触感），且只作用于拇指。 */
input[type=range]{-webkit-appearance:none;appearance:none;width:100%;height:4px;border-radius:var(--r-xs);
  background:linear-gradient(90deg,var(--sig),var(--sig)) 0/var(--fill,50%) 100% no-repeat,var(--ctl-bg2);
  outline:none;cursor:pointer}
input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;width:12px;height:12px;border-radius:var(--r-xs);
  background:var(--sig);border:none;transition:transform var(--dur-instant) var(--ease-out)}
input[type=range]::-webkit-slider-thumb:hover{transform:scale(1.1)}
input[type=range]:active::-webkit-slider-thumb{transform:scale(1.15)}
input[type=range]::-moz-range-thumb{width:12px;height:12px;border-radius:var(--r-xs);background:var(--sig);border:none}
input[type=range]:focus-visible{outline:2px solid var(--ring);outline-offset:2px}
input[type=range]:disabled{opacity:.5;cursor:not-allowed}
/* 输入（任务 3）：32 高 / --ctl-bg2 底 / 1px --hair-2 边；focus = --sig 边 + 2px 内环（去掉 3px 外发光） */
.numInp,.tname,.seedRow input{height:var(--h);background:var(--ctl-bg2);border:1px solid var(--hair-2);border-radius:var(--r-xs);color:var(--txt);
  transition:background-color var(--dur-fast) var(--ease-out),border-color var(--dur-fast) var(--ease-out),color var(--dur-fast) var(--ease-out),box-shadow var(--dur-fast) var(--ease-out)}
.numInp{width:52px;font:600 var(--fs-body) var(--mono);text-align:center;padding:0 4px}
.numInp:hover,.tname:hover,.seedRow input:hover{border-color:var(--sig)}
.numInp:focus,.tname:focus,.seedRow input:focus{outline:none;border-color:var(--sig);box-shadow:inset 0 0 0 2px rgba(var(--acc-rgb),.35)}
/* 下拉（任务 4）：统一 32 高 + appearance:none + 自绘 5px×2 三角（纯 CSS 渐变，不引图片）
   —— 选择器必须排除时间线的选中格：.pc 也会带 .sel（area 选区高亮），
      若被这条共享规则命中，格子会吃到 padding:0 24px 0 8px + 1px 全边框 →
      在 box-sizing:border-box 下内容盒被压到 0、border-box 反被撑到固定 34px 并溢出轨道，
      表现为“选中的音符被拉长 / 选区看着多出好几格”，且该宽度与 --cw 无关（缩放时格数还会变）。 */
.stepsSel,.sel:not(.pc),.miniSel{height:var(--h);background-color:var(--ctl-bg2);border:1px solid var(--hair-2);border-radius:var(--r-xs);
  padding:0 24px 0 8px;font-size:var(--fs-body);color:var(--txt);cursor:pointer;font-family:inherit;
  -webkit-appearance:none;appearance:none;
  background-image:linear-gradient(45deg,transparent 50%,var(--mut) 50%),linear-gradient(135deg,var(--mut) 50%,transparent 50%);
  background-position:right 11px center,right 7px center;background-size:5px 5px,5px 5px;background-repeat:no-repeat;
  transition:background-color var(--dur-fast) var(--ease-out),border-color var(--dur-fast) var(--ease-out),color var(--dur-fast) var(--ease-out),box-shadow var(--dur-fast) var(--ease-out)}
.stepsSel:hover,.sel:not(.pc):hover,.miniSel:hover{border-color:var(--sig)}
.stepsSel:focus,.sel:not(.pc):focus,.miniSel:focus{outline:none;border-color:var(--sig);box-shadow:inset 0 0 0 2px rgba(var(--acc-rgb),.35)}

.acts{display:flex;gap:8px;align-items:center;flex:none}
.btn{height:var(--h);padding:0 13px;border-radius:var(--r-sm);border:1px solid var(--hair-2);background:var(--card);color:var(--txt);
  cursor:pointer;font-size:var(--fs-body);display:inline-flex;align-items:center;gap:6px;white-space:nowrap;
  transition:background-color var(--dur-fast) var(--ease-out),border-color var(--dur-fast) var(--ease-out),color var(--dur-fast) var(--ease-out),box-shadow var(--dur-fast) var(--ease-out)}
.btn:hover{background:var(--hover);border-color:var(--sig);color:var(--txt)}
.btn:active{background:rgba(var(--txt-rgb),.1)}
.btn.acc{background:var(--grad);border:none;color:var(--on-acc);font-weight:700}
.btn.acc:hover{filter:brightness(1.08);color:var(--on-acc);box-shadow:0 4px 16px rgba(var(--acc-rgb),.45)}
.btn.danger:hover{border-color:var(--bad);color:var(--bad);box-shadow:0 0 10px rgba(var(--bad-rgb),.18)}
.btn.sm{height:var(--h-sm);padding:0 9px;font-size:11.5px}
.btn.on{border-color:var(--sig);color:var(--sig);background:rgba(var(--acc-rgb),.1)}
.btn:disabled{opacity:.45;cursor:not-allowed}
/* ---------- 自动保存状态指示（顶栏）----------
   状态点用颜色区分：pending=琥珀（有改动待保存）、saved=绿、error=红、idle=灰。
   文案由 js 写；这里只负责"看得见"和不易误读的对比度。 */
.saveBtn{display:inline-flex;align-items:center;gap:6px;max-width:190px}
.saveBtn #saveTxt{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.saveDot{width:7px;height:7px;border-radius:50%;flex:none;background:var(--dim);
  transition:background-color var(--dur-fast) var(--ease-out),box-shadow var(--dur-fast) var(--ease-out)}
.saveBtn[data-state="pending"] .saveDot{background:var(--warn);box-shadow:0 0 7px rgba(232,177,63,.55)}
.saveBtn[data-state="saved"] .saveDot{background:var(--good);box-shadow:0 0 7px rgba(53,201,143,.5)}
.saveBtn[data-state="error"] .saveDot{background:var(--bad);box-shadow:0 0 8px rgba(229,72,77,.6)}
.saveBtn[data-state="error"]{border-color:var(--bad);color:var(--bad)}
.saveMenuHead{padding:7px 10px 4px;font-size:10.5px;color:var(--dim);line-height:1.6;border-bottom:1px solid var(--hair)}
.mi[data-sact="now"] .ic{-webkit-mask-image:var(--ic-bookmark);mask-image:var(--ic-bookmark)}
.mi[data-sact="lib"] .ic{-webkit-mask-image:var(--ic-save);mask-image:var(--ic-save)}
.mi[data-sact="history"] .ic{-webkit-mask-image:var(--ic-restore);mask-image:var(--ic-restore)}
.menuWrap{position:relative}
/* 菜单：进入 280ms（--dur-base/--ease-out），退出 200ms（--dur-fast/--ease-in ≈ 进入 × 0.75）。
   display 用 allow-discrete 参与过渡，配合 @starting-style 才能"关也有动画"（元素在过渡结束后才真正 display:none）。 */
.menu{position:absolute;right:0;top:38px;min-width:210px;background:var(--ctl-bg);border:1px solid var(--line2);border-radius:var(--r);
  padding:6px;box-shadow:var(--shadow-2),var(--glow);z-index:100;display:none;opacity:0;transform:scale(.96) translateY(-4px);
  transform-origin:top right;
  transition:opacity var(--dur-fast) var(--ease-in),transform var(--dur-fast) var(--ease-in),display var(--dur-fast) allow-discrete}
.menu.open{display:block;opacity:1;transform:none;
  transition:opacity var(--dur-base) var(--ease-out),transform var(--dur-base) var(--ease-out),display var(--dur-base) allow-discrete;
  background:var(--glass);backdrop-filter:blur(var(--glass-blur));-webkit-backdrop-filter:blur(var(--glass-blur))}
@starting-style{.menu.open{opacity:0;transform:scale(.96) translateY(-4px)}}
/* 批 C 第三部分：嵌在 stageTop 行内的菜单（编辑 ▾）—— 从按钮下沿展开，而不是固定的 38px */
.menuBelow{top:calc(100% + 4px)}
.mi{display:flex;gap:9px;align-items:center;width:100%;background:none;border:none;color:var(--txt);padding:8px 10px;
  border-radius:var(--r-xs);cursor:pointer;font-size:var(--fs-body);text-align:left;
  transition:background-color var(--dur-fast) var(--ease-out),border-color var(--dur-fast) var(--ease-out),color var(--dur-fast) var(--ease-out),box-shadow var(--dur-fast) var(--ease-out)}
.mi:hover{background:var(--hover);color:var(--txt)}
.mi .ic{width:22px;text-align:center}
.mi small{color:var(--dim);margin-left:auto}

.vizBox{width:130px;height:40px;flex:none;display:flex;align-items:flex-end;gap:2px;padding:4px;border:1px solid var(--line);border-radius:var(--r-sm);background:var(--well)}
.vizBox canvas{width:100%;height:100%;display:block}

/* ---------- 布局 ---------- */
body{overflow-x:hidden}      /* 收起时侧栏停在视口右侧之外，不该产生横向滚动条 */
.wrap{height:calc(100% - 56px);display:flex;min-height:0;position:relative}   /* 侧栏浮动覆盖的定位基准 */
.stage{flex:1;display:flex;flex-direction:column;min-width:0}
/* 侧栏 = 浮动覆盖层（Figma 式）：绝对定位盖在主区上方，**不改主区宽度**（收起时主区直接多出 352px）。
   展开 280ms/--ease-out、收起 200ms/--ease-in（与批 3 的"退出 = 进入 × 0.75"一致）；
   展开时加 --shadow-2 表示"浮在上方"。收起的侧栏 visibility:hidden（0s + 延迟切换），
   这样它的控件不会在收起状态下被 Tab 聚焦到，同时收起动画仍然看得见。 */
.side{position:absolute;top:0;right:0;bottom:0;width:352px;z-index:40;  border-left:1px solid var(--line);
  background:linear-gradient(180deg,rgba(14,21,38,.6),rgba(11,16,29,.55));
  background:var(--glass);backdrop-filter:blur(var(--glass-blur));-webkit-backdrop-filter:blur(var(--glass-blur));
  box-shadow:none;
  display:flex;flex-direction:column;min-height:0;
  visibility:hidden;transform:translateX(100%);
  transition:transform var(--dur-fast) var(--ease-in),box-shadow var(--dur-fast) var(--ease-in),
    visibility 0s var(--ease-linear) var(--dur-fast)}
.side.open{visibility:visible;transform:translateX(0);box-shadow:var(--shadow-2);
  transition:transform var(--dur-base) var(--ease-out),box-shadow var(--dur-base) var(--ease-out),visibility 0s var(--ease-linear)}
@media(max-width:1200px){.side{width:320px}.brand b{display:none}.vizBox{display:none}.knobGrp .rangeW{width:84px}}

.sideTabs{display:flex;gap:4px;padding:10px 10px 0;background:var(--glass);
  backdrop-filter:blur(var(--glass-blur));-webkit-backdrop-filter:blur(var(--glass-blur))}
.stab{flex:1;height:var(--h);border-radius:var(--r-sm) var(--r-sm) 0 0;background:transparent;border:1px solid transparent;border-bottom:none;
  color:var(--mut);cursor:pointer;font-size:var(--fs-body);display:flex;align-items:center;justify-content:center;gap:7px;
  transition:background-color var(--dur-fast) var(--ease-out),border-color var(--dur-fast) var(--ease-out),color var(--dur-fast) var(--ease-out),box-shadow var(--dur-fast) var(--ease-out)}
.stab:hover{color:var(--txt);background:var(--hover)}
.stab.on{background:var(--sel-bg);color:var(--txt);border-color:var(--line)}
.sideBody{flex:1;overflow-y:auto;padding:14px;background:var(--glass);border-top:1px solid var(--line);min-height:0;
  position:relative;                     /* 批 C 第四部分：旧内容影子层的定位基准 */
  backdrop-filter:blur(var(--glass-blur));-webkit-backdrop-filter:blur(var(--glass-blur))}
/* 面板切换的"旧内容淡出"：绝对定位叠在新内容上，200ms 左移淡出后由 JS 移除 */
.panelGhost{
  position:absolute;left:0;right:0;top:0;z-index:2;
  padding:14px;background:var(--glass);pointer-events:none;overflow:hidden;
  animation:ghostOut var(--dur-fast) var(--ease-in) both;
}
@keyframes ghostOut{from{opacity:1;transform:translateX(0)}to{opacity:0;transform:translateX(-8px)}}
/* 数字 tick 的输入框变体（批 C 第四部分）：#bpmNum 是 <input>，整框上滑会像"控件在抖"，
   所以输入框只做透明度呼吸，位移留给纯文本元素。 */
input.numTick{animation:numTickSoft var(--dur-fast) var(--ease-out)}
input.numTickAlt{animation:numTickSoftAlt var(--dur-fast) var(--ease-out)}
@keyframes numTickSoft{from{opacity:.55}to{opacity:1}}
@keyframes numTickSoftAlt{from{opacity:.55}to{opacity:1}}
.hidden{display:none!important}

/* ---------- 侧栏样式 ---------- */
.h2{font-size:12.5px;color:var(--mut);letter-spacing:1px;margin:14px 0 8px;display:flex;align-items:center;gap:8px}
.h2:first-child{margin-top:0}
.h2::after{content:'';flex:1;height:1px;background:linear-gradient(90deg,var(--line2),transparent)}
/* ---------- 批 C 第三部分：低频块折叠 ----------
   .foldH 是原生 <button>（Tab 可达 / 回车空格可切），只是穿上了 .h2 的排版；
   折叠体用 grid-template-rows 1fr→0fr 过渡（高度不能过渡，这是规范给的替代做法）。 */
.fold .foldH{width:100%;margin:0 0 8px;padding:0;background:none;border:none;text-align:left;cursor:pointer;
  font-family:inherit;font-size:inherit;font-weight:inherit;letter-spacing:inherit;color:inherit}
.fold .foldH:hover{color:var(--txt)}
.fold .foldH:focus-visible{outline:2px solid var(--ring);outline-offset:2px}
.fold .foldH .ico-caret{width:11px;height:11px;flex:none;color:var(--mut);
  transition:transform var(--dur-base) var(--ease-out)}
.fold .foldH:hover .ico-caret{color:var(--acc)}
.fold.collapsed .foldH .ico-caret{transform:rotate(-90deg)}
.foldBody{display:grid;grid-template-rows:1fr;transition:grid-template-rows var(--dur-base) var(--ease-out)}
.fold.collapsed .foldBody{grid-template-rows:0fr}
.foldInner{overflow:hidden;min-height:0}
.chips{display:flex;flex-wrap:wrap;gap:6px}
.chip{padding:7px 11px;border-radius:var(--r-sm);border:1px solid var(--hair-2);background:var(--card2);color:var(--mut);
  cursor:pointer;font-size:var(--fs-body);display:flex;align-items:center;gap:6px;
  transition:background-color var(--dur-fast) var(--ease-out),border-color var(--dur-fast) var(--ease-out),color var(--dur-fast) var(--ease-out),box-shadow var(--dur-fast) var(--ease-out)}
.chip:hover{color:var(--txt);border-color:var(--sig);background:var(--hover)}
.chip.on{background:linear-gradient(100deg,rgba(var(--acc2-rgb),.25),rgba(var(--acc-rgb),.22));
  border-color:var(--sig);color:var(--on-txt);box-shadow:0 0 10px rgba(var(--acc-rgb),.15)}
.chip .e{font-size:14px}
.chip small{opacity:.75}

.mood{display:grid;gap:9px;margin:4px 0 2px}
.moodRow{display:flex;align-items:center;gap:10px}
.moodRow label{width:44px;font-size:11px;color:var(--mut);flex:none}
.moodRow input{flex:1}
.moodRow .mv{font:600 11px var(--mono);color:var(--txt);width:34px;text-align:right;flex:none}

.field{display:flex;align-items:center;gap:8px;margin:7px 0}
.field>label{width:62px;font-size:11.5px;color:var(--mut);flex:none}
/* .sel / .miniSel / .stepsSel 的统一外观已在上方"下拉（任务 4）"里合并定义，这里只留布局 */
.sel{flex:1}
.seedRow{display:flex;gap:6px}
.seedRow input{flex:1}
.seedRow .btn{flex:none}

.aiMain{margin-top:12px}
.bigBtn{width:100%;height:var(--h-lg);border-radius:var(--r-sm);border:none;cursor:pointer;font-size:var(--fs-h2);font-weight:800;letter-spacing:var(--ls-tech);
  background:var(--grad);color:var(--on-acc);transition:filter var(--dur-fast) var(--ease-out);display:flex;align-items:center;justify-content:center;gap:9px}
.bigBtn:hover{filter:brightness(1.08)}
.bigBtn:active{filter:brightness(.94)}
.bigBtn.ghost{background:var(--card2);color:var(--txt);border:1px solid var(--hair-2);box-shadow:none;height:var(--h-lg);font-size:var(--fs-body)}
.progress{display:flex;flex-direction:column;gap:8px;margin-top:14px}
.pbRow{display:flex;align-items:center;gap:9px}
.pbRow .lb{font-size:var(--fs-label);color:var(--dim);width:88px;flex:none;letter-spacing:var(--ls-wide)}
/* 进度条（任务 7）：6px 方条 / --grad 填充 / 去辉光 / 顶部 1px 高光 */
.pb{flex:1;height:6px;border-radius:var(--r-xs);background:var(--ctl-bg2);overflow:hidden}
.pb i{display:block;height:100%;width:0%;border-radius:var(--r-xs);background:var(--grad);
  box-shadow:inset 0 1px 0 rgba(var(--txt-rgb),.25);transition:width var(--dur-base) var(--ease-out)}
.pbRow .pct{font:600 10px var(--mono);color:var(--acc);width:34px;text-align:right}

.insBox{border:1px solid transparent;border-radius:var(--r);
  background:linear-gradient(180deg,rgba(var(--txt-rgb),.03),transparent);
  background-color:var(--card);background-clip:padding-box;
  padding:10px;margin-bottom:10px;position:relative;box-shadow:var(--shadow-1),var(--glow)}
.insHead{display:flex;align-items:center;gap:9px;margin-bottom:8px}
.insHead .tgIcon{width:26px;height:26px}
.insHead .tt{font-size:12px;color:var(--mut);flex:1}
.sliderLine{display:flex;align-items:center;gap:8px;margin:6px 0}
.sliderLine label{width:58px;font-size:11px;color:var(--mut);flex:none}
.sliderLine input{flex:1}
.sliderLine .v{font:600 10.5px var(--mono);color:var(--txt);width:44px;text-align:right;flex:none}
.dblRow{display:flex;gap:8px}
.dblRow>div{flex:1}
.noteRow{display:flex;align-items:center;gap:8px;margin:6px 0}
.noteRow label{width:58px;font-size:11px;color:var(--mut);flex:none}
.noteRow input{flex:1}
.rowBtns{display:flex;gap:6px;margin-top:10px;flex-wrap:wrap}
.rowBtns .btn{flex:1}

.kitList{margin:6px 0}
.kitRow{display:flex;align-items:center;gap:8px;padding:5px 4px;border-bottom:1px dashed var(--grid-line2)}
.kitRow .sw{width:16px;height:16px;border-radius:4px;flex:none}
.kitRow span{font-size:11.5px;color:var(--mut);flex:1}
.kitRow .test{height:var(--h-sm);min-width:44px;font-size:10px;padding:0 8px}

/* ---------- 钢琴键盘 ---------- */
.pianoBar{height:104px;border-top:1px solid var(--line);background:linear-gradient(180deg,var(--piano),var(--piano2));
  display:flex;flex-direction:column;align-items:center;padding:6px 14px;gap:5px;flex:none;position:relative;z-index:20}
.pKeys{display:flex;height:70px;position:relative;gap:0;margin:0 auto;max-width:100%}
.wkey{width:var(--kw,30px);height:70px;background:linear-gradient(180deg,#f6f8ff,#c8d2e6);border:1px solid #93a4c4;border-radius:0 0 var(--r-xs) var(--r-xs);
  cursor:pointer;position:relative;transition:transform var(--dur-instant) var(--ease-out),background-color var(--dur-instant) var(--ease-out);display:flex;align-items:flex-end;justify-content:center;padding-bottom:4px;
  font:700 9px var(--mono);color:#5b6d92;flex:none;user-select:none}
.wkey:hover{background:#fff}
.wkey.down{background:var(--grad);transform:translateY(2px)}.bkey{position:absolute;width:calc(var(--kw,30px)*.62);height:44px;background:linear-gradient(180deg,#1c2742,#0a0f1e);border-radius:0 0 5px 5px;cursor:pointer;
  z-index:3;border:1px solid #000;display:flex;align-items:flex-end;justify-content:center;padding-bottom:3px;
  font:700 8px var(--mono);color:#7fa3c9;user-select:none}
.bkey.down{background:var(--grad);transform:translateY(2px)}
/* 3 个八度（22 个白键）在窄容器里键宽会低到 12~15px：白键上的音名会互相压字，
   此时只保留每个 C 的名字（.narrow 由 sizePianoKeys() 按实际键宽加/去，不改任何既有 class 命名）。 */
.pKeys.narrow .wkey:not(.C){font-size:0}
.pinfo{display:flex;align-items:center;justify-content:center;gap:14px;font-size:10.5px;color:var(--dim)}
.pinfo kbd{background:var(--ctl-bg2);border:1px solid var(--line2);border-bottom-width:2px;border-radius:5px;padding:1px 6px;font:600 10px var(--mono);color:var(--mut)}

/* ---------- toast ---------- */
#toasts{position:fixed;bottom:18px;left:50%;transform:translateX(-50%);z-index:200;display:flex;flex-direction:column;gap:8px;align-items:center;pointer-events:none}
/* 退出动画由 util.js 内联设置（inline style 不能被普通规则覆盖）→ 这里用 !important 把 "all .3s" 收成白名单，
   只留 opacity/transform，避免 transition:all 让每次移除都触发全属性比对。 */
.toast{background:var(--ctl-bg);border:1px solid var(--acc);border-radius:var(--r-sm);padding:9px 18px;font-size:12.5px;color:var(--txt);
  box-shadow:var(--shadow-3);display:flex;gap:9px;align-items:center;animation:toastIn var(--dur-fast) var(--ease-out);
  transition:opacity var(--dur-fast) var(--ease-out),transform var(--dur-base) var(--ease-out) !important;
  backdrop-filter:blur(var(--glass-blur));-webkit-backdrop-filter:blur(var(--glass-blur))}
.toast.err{border-color:var(--bad)}
.toast.ok{border-color:var(--good)}
@keyframes toastIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}

.small{font-size:11px;color:var(--dim);line-height:1.8}
.kv{display:flex;justify-content:space-between;padding:2px 0;font-size:11.5px}
.kv b{font:600 11px var(--mono);color:var(--txt)}
.divider{height:1px;background:var(--line);margin:12px 0}

/* AI 一键成曲完成时的高亮反馈：改成"内描边"闪烁（原来的外发光 + 30px 辉光属批 1 已废弃的观感） */
.genFlash{animation:flash var(--dur-slow) var(--ease-out)}
@keyframes flash{from{box-shadow:inset 0 0 0 2px var(--acc3)}to{box-shadow:inset 0 0 0 0 rgba(0,0,0,0)}}
.miniSel{ /* 外观见任务 4 的合并规则 */ }
.miniLbl{font-size:var(--fs-label);color:var(--dim);letter-spacing:var(--ls-wide);margin-left:8px}
.keyBar{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.bigNum{font:700 20px var(--mono);color:var(--acc);text-shadow:0 0 12px rgba(var(--acc-rgb),.4)}
.ghostBtn{background:none;border:none;color:var(--mut);cursor:pointer;font-size:16px;padding:2px 6px;border-radius:var(--r-xs);transition:background-color var(--dur-fast) var(--ease-out),color var(--dur-fast) var(--ease-out)}
.ghostBtn:hover{color:var(--txt);background:var(--hover)}
.tag-mini{font-size:9.5px;color:var(--dim);font-family:var(--mono)}
.helpLine{display:flex;gap:10px;font-size:11px;color:var(--dim);padding:3px 0;align-items:center}
.helpLine kbd{background:var(--ctl-bg2);border:1px solid var(--line2);border-bottom-width:2px;border-radius:5px;padding:0 6px;font:600 10px var(--mono);color:var(--mut);min-width:20px;text-align:center;display:inline-block}
.aiChipRow{display:flex;gap:6px;margin:8px 0}
.modeNote{font-size:11px;color:var(--dim);background:rgba(var(--acc2-rgb),.08);border:1px dashed rgba(var(--acc2-rgb),.35);border-radius:var(--r-sm);padding:7px 9px;line-height:1.7}
/* AI 作曲栏的免责声明（用户要求写明"这不是真 AI"）。
   刻意做得比 .small 更弱、但有左边框便于扫读：它是说明性文字，不该抢「一键成曲」的注意力，
   也不能小到看不见 —— 11px/1.75 + --dim 与 .small 同量级，靠边框与背景区分层级。 */
.aiNote{font-size:11px;color:var(--dim);line-height:1.75;margin-top:10px;padding:8px 10px;
  background:var(--well);border-left:2px solid var(--hair-2);border-radius:0 var(--r-xs) var(--r-xs) 0}
.aiNote b{color:var(--txt)}
.aiNote .ico{width:13px;height:13px;vertical-align:-2px;color:var(--warn,#e0a33a)}
/* ---- 播放进度条（可拖拽） ---- */
.seekBar{display:flex;align-items:center;gap:12px;padding:6px 16px 2px;position:relative;z-index:30}
.seekTrack{flex:1;height:22px;background:transparent;cursor:pointer;position:relative;touch-action:none}
/* 播放进度：轨 4px 方角、填充 --sig、滑块与 range 拇指同款（12px 方形、无辉光） */
.seekTrack::before{content:'';position:absolute;left:0;right:0;top:9px;height:4px;border-radius:var(--r-xs);background:var(--ctl-bg2);box-shadow:inset 0 0 0 1px var(--hair-2)}
.seekFill{position:absolute;left:0;top:9px;height:4px;border-radius:var(--r-xs);width:0%;background:var(--sig)}
.seekKnob{position:absolute;top:5px;width:12px;height:12px;border-radius:var(--r-xs);background:var(--sig);border:none;left:0;margin-left:-6px;transform:none;transition:transform var(--dur-instant) var(--ease-out)}
.seekKnob.drag{transform:scale(1.15)}
.seekLbl{font:600 11px var(--mono);color:var(--mut);min-width:96px;text-align:right;user-select:none;white-space:nowrap}
/* 时间线缩放（视图级，不改变曲长） */
.zoomGrp{display:inline-flex;align-items:center;gap:3px;border:1px solid var(--line2);border-radius:var(--r-sm);padding:2px 5px;background:var(--card)}
.zoomGrp button{width:var(--h-sm);height:var(--h-sm);padding:0;border-radius:var(--r-xs);border:1px solid transparent;background:transparent;color:var(--mut);cursor:pointer;font-size:13px;line-height:1;display:inline-flex;align-items:center;justify-content:center;
  transition:background-color var(--dur-fast) var(--ease-out),border-color var(--dur-fast) var(--ease-out),color var(--dur-fast) var(--ease-out),box-shadow var(--dur-fast) var(--ease-out)}
.zoomGrp button:hover{color:var(--txt);background:var(--hover)}     /* hover 只改背景（不位移、不改边框） */
.zoomGrp .zv{font:600 11px var(--mono);color:var(--acc);min-width:38px;text-align:center;user-select:none}
.zoomGrp .fit{color:var(--dim)}
.zoomGrp .fit:hover{color:var(--acc)}
/* 选中的工具/开关：信号色实底 + 反色文字（批 C 后补，原来是一圈半透明内描边） */
.zoomGrp button.on{background:var(--sig);color:var(--on-acc)}
.zoomGrp button:disabled{opacity:.35;cursor:not-allowed}
/* 纯图标按钮（.icoBtn：撤销/重做等）：方形的 28px，图标居中 */
.btn.icoBtn{padding:0;width:var(--h);justify-content:center}
.toolGrp{background:var(--card)}
.toolGrp button{font-size:12px;width:24px}
/* 区域选择（复制/粘贴/量化/细分）高亮 —— 两段式：
   ① 逐格只留浅黄底色（不再逐格描黄框：选区覆盖整轨所有行，逐格描边会被读成“一堆格子”而不是“一段范围”）；
   ② 范围边界交给轨道体 .tgBody 上的 ::before 竖带（左右两条线 + 更淡的底，高度=整轨行高），
      位置/宽度由 JS 写在 --selFrom / --selN 两个 CSS 变量上（见 ui/timeline.js 的 paintSelBand）。
   ③ 描边宽度一律 clamp(1px, --cw*.12, 3px)：跟着格子宽度缩放 —— 128 小节缩到 cw=4px 时细而不糊、
      短曲放大到 cw=30px 时也不会显得只有一根发丝。 */
.pc.sel{background:rgba(255,208,90,.13);z-index:2}
.mel .pc.sel,.drum .pc.sel{background:rgba(255,208,90,.13)}
/* 网格线兜底（A 方案）：竖线不再只靠 .pc 的 border-right 画 —— 轨道体再加一层竖向网格背景，
   周期 = 格宽、相位 = 左侧名称列宽、颜色 = --grid-line。
   ★ 这里刻意**不引用任何自定义属性**：
     实测（headless Edge 153 / 主页面 32 小节 2.2 万元素）往一个元素上写自定义属性，
     浏览器会保守地把**整棵子树**标记为样式失效，哪怕没有任何规则消费这个值：
       · 写 --cgw 到 4 个 .tgBody → +强制布局 229ms
       · 写 background-size 到同样 4 个 .tgBody → 1.2ms
       · 写自定义属性到 :root → 898ms（整页）
     所以格宽/相位由 JS 直接写成**具体属性的像素值**（ui/timeline.js 的 applyGridVars）。
     选区竖带的位移/宽度同理：--selFrom/--selN 仍然是变量，但只在选区变化时写一次，
     而且每次都会把 --scw 一起落盘（缩放后由 applyGridVars 刷新）。
   只画竖线：横线仍由 .pc 的 border-bottom 负责（行数固定、永远全渲染，不存在缺行问题）。 */
.tgBody{position:relative;
  background-image:linear-gradient(90deg,var(--grid-line) 0 1px,transparent 1px);
  background-repeat:repeat}
.tgBody::before{
  /* top/bottom 与 timeline.css 的 .tgBody{padding:2px 0 6px} 对齐，让竖带正好覆盖整片琴键行 */
  content:'';position:absolute;top:2px;bottom:6px;display:none;pointer-events:none;z-index:1;
  left:calc(var(--labW) + var(--selFrom,0) * var(--scw,24px));
  width:calc(var(--selN,0) * var(--scw,24px));
  background:rgba(255,208,90,.07);
  border-left:1px solid rgba(255,208,90,.85);
  border-right:1px solid rgba(255,208,90,.85);
}
.tgBody.selOn::before{display:block}
.tgBody.selCutL::before{border-left-color:transparent} /* 选区左端在当前渲染窗口之外：不画假边界 */
.tgBody.selCutR::before{border-right-color:transparent}
/* 选中音符不再套逐格描边：延音音符在 pat 里是相邻多格，逐格描边并排会读成“2 倍宽的一圈框”；
   “范围”由上面的竖带表达、“选中”由浅黄底色表达，已经够用，所以这里只留一条 playCol 的抑制规则。 */
.pc.sel.playCol{outline:none}
/* 量化结果闪亮反馈：内描边 + 底色调（去掉 8px 外发光与 brightness 滤镜 —— 那是整格重绘最贵的一笔）；
   时长用 --dur-flash（1200ms）：这是"看得清哪几个音被移动了"的功能性动画，比 --dur-slow 长。 */
@keyframes qFlash{0%{box-shadow:inset 0 0 0 3px var(--good);background:rgba(var(--good-rgb),.4)}70%{box-shadow:inset 0 0 0 3px var(--good);background:rgba(var(--good-rgb),.26)}100%{box-shadow:inset 0 0 0 0 rgba(0,0,0,0)}}
.pc.qflash{animation:qFlash var(--dur-flash) var(--ease-out)}
.qEst{font-size:10.5px;color:var(--good);white-space:nowrap;letter-spacing:.2px}
/* 节奏细分（精确时值音符）标记：按格内真实位置与实际时值画细条（跨格自动分段） */
.pc.tribar{box-shadow:inset 0 0 0 1px rgba(var(--good-rgb),.3)}
.pc.tribar::after{content:'';position:absolute;top:1px;height:3px;border-radius:2px;left:var(--tx,0%);width:var(--tw,0%);
  background:linear-gradient(90deg,rgba(var(--good-rgb),.9),rgba(var(--acc-rgb),.85));
  box-shadow:0 0 5px rgba(var(--good-rgb),.7);pointer-events:none}
.pc.tribar.on::after{top:2px}
/* 复制/粘贴按钮组 */
.clipGrp button{font-size:13px;width:26px}
.clipGrp .zv{min-width:0;max-width:150px;text-align:left;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* 侧栏快速返回顶部 / 键盘演奏辅助 */
.toStartBtn{height:var(--h);padding:0 10px;border-radius:var(--r-sm);border:1px solid var(--hair-2);background:var(--card);color:var(--mut);
  cursor:pointer;font-size:11.5px;display:inline-flex;align-items:center;gap:5px;
  transition:background-color var(--dur-fast) var(--ease-out),border-color var(--dur-fast) var(--ease-out),color var(--dur-fast) var(--ease-out),box-shadow var(--dur-fast) var(--ease-out)}
.toStartBtn:hover{background:var(--hover);border-color:var(--sig);color:var(--txt)}
.toStartBtn:active{background:rgba(var(--txt-rgb),.1)}
.btn:focus-visible,.hchip:focus-visible,.stab:focus-visible,.playBtn:focus-visible,.toStartBtn:focus-visible,
.mi:focus-visible,.zoomGrp button:focus-visible,.chip:focus-visible{outline:2px solid var(--ring);outline-offset:2px}

/* ---------- 主题切换（顶栏圆形色板按钮 + 菜单） ---------- */
.themeBtn{width:var(--h);padding:0;justify-content:center;border-radius:var(--r-sm)}
.themePanel{min-width:186px}
.themeMi{position:relative}
.themeMi.on{background:rgba(var(--acc-rgb),.16);color:var(--txt);box-shadow:inset 0 0 0 1px rgba(var(--acc-rgb),.45)}
.themeMi .tdot{width:16px;height:16px;border-radius:50%;flex:none;border:1px solid var(--line2);box-shadow:0 0 6px rgba(0,0,0,.35)}
.tdot[data-k="studio"]{background:#18d1ff}
.tdot[data-k="midnight"]{background:#5a7cff}
.tdot[data-k="cyber"]{background:#00e5b0}
.tdot[data-k="sunrise"]{background:#ff7a2f}
.tdot[data-k="cream"]{background:#6a3fd0}
.tdot[data-k="forest"]{background:#35cf5f}
/* 播放中呼吸光晕：靠 #stopIco 的内联 display 判断，避免改 JS */
.playBtn:has(#stopIco:not([style*="none"])){/* 状态动画已并入 .playBtn::after（见 playRipple），此处不再重复定义 */}

/* ============================================================================
   8. 图标线性化（FEAT-V6/T5 批 2）—— 全站 emoji → 1.5px 线性 SVG
   ----------------------------------------------------------------------------
   实现：CSS mask + 内联 SVG data-URI（无图片/字体/网络请求）；原 emoji 用 font-size:0 隐藏。
   · A 类（元素本身只放图标、且自身背景不随 hover 变化）→ 直接把元素当图标盒；
   · B 类（logo）→ 保留渐变方块，图标画在 ::before 上（白色线性声波）；
   · C 类（图标按钮）→ 图标画在 ::before（背景随 hover 变化，不能直接 mask 元素，否则 hover 底色会把图标吃掉）；
   · D 类（emoji 与文字在同一个文本节点里）→ font-size:0 隐掉原文，
     ::before 画图标、::after 用 content 补回标签文字。
     注意：D 类的标签文字在 CSS 里留了一份，改按钮文案时要同步这里
     （"只改 CSS、不改 DOM/JS"的必然代价）。
   ============================================================================ */
:root{
  /* 兜底：四向加号（找不到具体图标时用它，至少不是方块） */
  --ic-dot:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M12 5v14M5 12h14'/></svg>");
  /* 视图缩放（#zoomOut / #zoomIn / #zoomFit） */
  --ic-minus:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M5 12h14'/></svg>");
  --ic-plus:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M12 5v14M5 12h14'/></svg>");
  --ic-expand:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M4 12h16M8 8l-4 4 4 4M16 8l4 4-4 4'/></svg>");
  /* 可视化入口（vizlink.js 生成的 .mi[data-act="visualize"]） */
  --ic-chart:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M4 4v16h16M8 20v-5M12 20v-9M16 20v-6'/></svg>");
  /* —— JS 侧 icon() 专用（本轮新增：侧栏 AI 面板 / 作品库 / 帮助 / toast / 进度） —— */
  --ic-home:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M4 11l8-7 8 7v8a1 1 0 0 1-1 1h-4v-6H9v6H5a1 1 0 0 1-1-1z'/></svg>");
  --ic-play:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M8 5l11 7-11 7z'/></svg>");
  --ic-close:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M6 6l12 12M18 6L6 18'/></svg>");
  --ic-pencil:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M4 20h4l10-10-4-4L4 16zM14 6l4 4'/></svg>");
  --ic-music:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M9 18a2 2 0 1 1-4 0 2 2 0 0 1 4 0zM19 16a2 2 0 1 1-4 0 2 2 0 0 1 4 0zM9 18V6l10-2v12'/></svg>");
  --ic-palette:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M12 21a9 9 0 1 1 9-9c0 2-1.6 2.6-3 3-1.2.4-2 .9-2 2 0 1.3-.6 4-4 4zM8 9h.01M12 7h.01M16 9h.01M7.5 13h.01'/></svg>");
  --ic-check:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M5 13l4 4L19 7'/></svg>");
  --ic-cross:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M7 7l10 10M17 7L7 17'/></svg>");
  --ic-warn:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M12 4l9 16H3zM12 10v4M12 17h.01'/></svg>");
  --ic-undo:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M9 7L4 12l5 5M4 12h9a6 6 0 0 1 6 6'/></svg>");
  --ic-redo:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M15 7l5 5-5 5M20 12h-9a6 6 0 0 0-6 6'/></svg>");
  --ic-flame:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M12 3c3 4 6 5.5 6 9a6 6 0 0 1-12 0c0-2 1-3.4 2.5-5 .3 1.2.9 2 1.7 2.4C10.6 8 11 5.6 12 3z'/></svg>");
  --ic-sun-dim:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M12 16a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM12 3v2M12 19v2M3 12h2M19 12h2M5.6 5.6l1.4 1.4M17 17l1.4 1.4M18.4 5.6L17 7M7 17l-1.4 1.4'/></svg>");
  --ic-dna:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M7 3c0 6 10 6 10 12M17 3c0 6-10 6-10 12M7 21c0-1 0-1.6.1-2.4M17 21c0-5.4-4-6.6-6.6-8.6M9.4 5.4c.6-.4 1.3-.8 2.6-.8M12.6 19.4c-1.3 0-2-.4-2.6-.8'/></svg>");
  --ic-coffee:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M4 9h12v6a4 4 0 0 1-4 4H8a4 4 0 0 1-4-4zM16 10h1.5a2.5 2.5 0 0 1 0 5H16M7 5.5C7 4.6 8 4.4 8 3.5M11 5.5c0-.9 1-1.1 1-2'/></svg>");
  --ic-speaker:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M11 5L6 9H3v6h3l5 4zM15.5 9.5a3.5 3.5 0 0 1 0 5M18 7a7 7 0 0 1 0 10'/></svg>");
  --ic-city:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M4 21V8l6-4v17M10 21V11l8-4v14M4 21h16M6.5 10h1M6.5 13h1M6.5 16h1M13 12h1M13 15h1M13 18h1'/></svg>");
  --ic-sax:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M8 3h5l-1 8a5 5 0 0 0 5 5v5a4 4 0 0 1-4-4M5 3h3M8 15h4'/></svg>");
  --ic-galaxy:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M12 20a8 8 0 1 0-8-8M4 12c0-4.4 4-7 8-7M12 4h.01M19 6h.01M20 14h.01M8 19h.01'/></svg>");
  --ic-pin:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M9 4h6l-1 5 3 3v2H7v-2l3-3zM12 14v6'/></svg>");
  --ic-headphones:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M4 15v-3a8 8 0 0 1 16 0v3M4 15h3v5H5a1 1 0 0 1-1-1zM20 15h-3v5h2a1 1 0 0 0 1-1z'/></svg>");
  --ic-follow:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M4 12h9M10 9l3 3-3 3M17 5v14M20 12h.01'/></svg>");
  --ic-guitar:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M8 16.5a4.5 4.5 0 1 0 0-9 4.5 4.5 0 0 0 0 9zM11.5 11.5L20 3M17 3h3v3'/></svg>");
  /* —— 鼓组 8 行（theory.js 的 KIT[].icon 用这里的名字） —— */
  --ic-kick:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M12 20a6 6 0 1 0 0-12 6 6 0 0 0 0 12zM12 14h.01M12 8V3l3 2'/></svg>");
  --ic-snare:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M5 12h14v3a4 4 0 0 1-4 4H9a4 4 0 0 1-4-4zM7 9l9-5M16 9L7 4'/></svg>");
  --ic-clap:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M8 20v-8a1.5 1.5 0 0 1 3 0V9a1.5 1.5 0 0 1 3 0v3a1.5 1.5 0 0 1 3 0v5a3 3 0 0 1-3 3zM4 8v5M20 8v5'/></svg>");
  --ic-hhc:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M4 10h16M6 12.5h12M12 12.5V19M8 19h8'/></svg>");
  --ic-hho:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M3 6.5h18M6 14h12M12 14v5M8 19h8'/></svg>");
  --ic-tom:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M5 9h14v3a4 4 0 0 1-4 4H9a4 4 0 0 1-4-4zM9 16v4M15 16v4'/></svg>");
  --ic-rim:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M12 20a6.5 6.5 0 1 0 0-13 6.5 6.5 0 0 0 0 13zM8 8L6 5.5M16 8l2-2.5M12 7V4'/></svg>");
  --ic-crash:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M3 10.5l18-3.5M5 10.5a7 2.4 0 0 0 14 0M12 12.9V19M8.5 19h7'/></svg>");
  --ic-caret:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M6 10l6 6 6-6'/></svg>");
  /* 品牌 / 空态 */
  --ic-wave:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M4 12h3l2-6 3 12 2.5-8 2 5h3.5'/></svg>");
  --ic-note:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M4 8h16M4 12h16M4 16h16M15 16V5l4-1'/></svg>");
  /* 走带 */
  --ic-loop:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M5 10a5 5 0 0 1 5-5h9M19 14a5 5 0 0 1-5 5H5'/><path d='M16 2l3 3-3 3M8 16l-3 3 3 3'/></svg>");
  --ic-metro:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M9 20l3-15 3 15zM6 20h12M12 9l4 5'/></svg>");
  --ic-start:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M6 5v14M19 5l-9 7 9 7z'/></svg>");
  /* 顶栏工具 */
  --ic-faders:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M6 4v6M6 14v6M12 4v10M12 18v2M18 4v2M18 10v10M4 12h4M10 16h4M16 8h4'/></svg>");
  --ic-sparkle:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M11 3l1.7 4.8L17.5 9.5l-4.8 1.7L11 16l-1.7-4.8L4.5 9.5l4.8-1.7z'/><path d='M18 15l.8 2.2L21 18l-2.2.8L18 21l-.8-2.2L15 18l2.2-.8z'/></svg>");
  --ic-contrast:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M12 21a9 9 0 1 0 0-18 9 9 0 0 0 0 18z'/><path d='M12 3v18'/><path d='M12 3a9 9 0 0 1 0 18'/></svg>");
  --ic-panel:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M4 5h16v14H4zM10 5v14'/></svg>");
  --ic-menu:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M4 7h16M4 12h16M4 17h16'/></svg>");
  /* 加轨 */
  --ic-mic:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M12 3a3 3 0 0 1 3 3v6a3 3 0 0 1-6 0V6a3 3 0 0 1 3-3zM5 11a7 7 0 0 0 14 0M12 18v3'/></svg>");
  --ic-waves:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M3 9c2-3 4-3 6 0s4 3 6 0 4-3 6 0M3 15c2-3 4-3 6 0s4 3 6 0 4-3 6 0'/></svg>");
  --ic-mist:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M4 14h10a3 3 0 1 0-1-5.8A4 4 0 0 0 5 9a3 3 0 0 0-1 5zM7 18h10M9 21h7'/></svg>");
  --ic-keys:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M4 6h16v12H4zM9 6v7M15 6v7'/></svg>");
  --ic-low:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M3 15c3-8 6-8 9 0s6 8 9 0'/></svg>");
  --ic-drum:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M8 8l3 4M16 8l-3 4'/><path d='M5 14a7 5 0 0 0 14 0a7 5 0 0 0-14 0z'/></svg>");
  /* 文件 */
  --ic-save:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M5 5h11l3 3v11H5zM9 5v5h6V5M8 13h8v6H8z'/></svg>");
  --ic-folder:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M4 7a2 2 0 0 1 2-2h3l2 2h7a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2z'/></svg>");
  --ic-bookmark:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M7 4h10v16l-5-4-5 4z'/></svg>");
  --ic-restore:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M20 12a8 8 0 1 1-2.3-5.7M20 4v4h-4'/></svg>");
  --ic-tape:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M4 7h16v10H4z'/><path d='M7 12a1.8 1.8 0 1 0 3.6 0 1.8 1.8 0 1 0-3.6 0zM13.4 12a1.8 1.8 0 1 0 3.6 0 1.8 1.8 0 1 0-3.6 0zM8 17h8'/></svg>");
  --ic-download:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M12 4v10M8 10l4 4 4-4M4 18h16'/></svg>");
  --ic-link:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M10 14a4 4 0 0 1 0-6l2-2a4 4 0 0 1 6 6l-1 1M14 10a4 4 0 0 1 0 6l-2 2a4 4 0 0 1-6-6l1-1'/></svg>");
  --ic-help:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M12 21a9 9 0 1 0 0-18 9 9 0 0 0 0 18zM9.5 9.5a2.5 2.5 0 1 1 3.6 2.3c-.7.4-1.1 1-1.1 1.8M12 17h.01'/></svg>");
  --ic-trash:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M5 7h14M9 7V4h6v3M7 7l1 13h8l1-13M10 11v6M14 11v6'/></svg>");
  /* 编辑工具 */
  --ic-brush:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M5 19l1-4 9-9 3 3-9 9zM14 6l3 3'/></svg>");
  --ic-eraser:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M9 18l-4-4 8-8 5 5-7 7zM6 20h13'/></svg>");
  --ic-marquee:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M5 5h5M14 5h5M19 5v5M19 14v5M19 19h-5M10 19H5M5 19v-5M5 10V5'/></svg>");
  --ic-copy:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M9 9h10v10H9zM6 15H5V5h10v1'/></svg>");
  --ic-paste:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M8 6h8v14H8zM10 4h4v3h-4z'/></svg>");
  --ic-target:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M12 21a9 9 0 1 0 0-18 9 9 0 0 0 0 18zM12 16a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM12 13a1 1 0 1 0 0-2 1 1 0 0 0 0 2z'/></svg>");
  --ic-quaver:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M9 16.5a2.5 2.5 0 1 0 5 0 2.5 2.5 0 1 0-5 0zM14 16.5V6l5-1'/></svg>");
  --ic-dice:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M5 5h14v14H5zM9 9h.01M15 9h.01M12 12h.01M9 15h.01M15 15h.01'/></svg>");
  --ic-shuffle:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M4 7h4l8 10h4M4 17h4l2-2.5M16 7h4M18 5l2 2-2 2M18 15l2 2-2 2'/></svg>");
  --ic-broom:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M14 4l6 6M11 7l6 6M9 9l6 6-5 5-6-6zM7 15l-3 5 5-3'/></svg>");
  --ic-clapper:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M4 9h16v10H4zM4 9l3-5h13l-2 5M8 4l2 5M13 4l2 5'/></svg>");
  /* 侧栏 tab */
  --ic-books:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M5 4h6v16H5zM13 4h6v16h-6zM7 8h2M15 8h2'/></svg>");
  /* 主题模式 */
  --ic-moon:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M20 14a8 8 0 1 1-9-11 6.5 6.5 0 0 0 9 11z'/></svg>");
  --ic-sun:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M12 17a5 5 0 1 0 0-10 5 5 0 0 0 0 10zM12 2v2M12 20v2M2 12h2M20 12h2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M19.1 4.9l-1.4 1.4M6.3 17.7l-1.4 1.4'/></svg>");
  --ic-gear:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM12 3v3M12 18v3M3 12h3M18 12h3M5.6 5.6l2.1 2.1M16.3 16.3l2.1 2.1M18.4 5.6l-2.1 2.1M7.7 16.3l-2.1 2.1'/></svg>");
}
/* —— A 类：元素本身就是图标盒（无 hover 背景） —— */
.mi .ic{font-size:0;display:inline-block;width:18px;height:18px;flex:none;background-color:currentColor;
  -webkit-mask:var(--ic-dot) center/contain no-repeat;mask:var(--ic-dot) center/contain no-repeat}
.emptyTip .big{font-size:0;display:inline-block;width:52px;height:52px;background-color:var(--acc);
  -webkit-mask:var(--ic-note) center/contain no-repeat;mask:var(--ic-note) center/contain no-repeat}
/* —— B 类：logo（保留渐变方块，图标画在 ::before） —— */
.logo{font-size:0}
.logo::before{content:'';width:20px;height:20px;background-color:var(--on-acc);
  -webkit-mask:var(--ic-wave) center/contain no-repeat;mask:var(--ic-wave) center/contain no-repeat}
/* —— C 类：图标按钮（hover 会改底色，图标必须画在 ::before） —— */
.zoomGrp>button,#themeBtn,#sideToggle{font-size:0}
.zoomGrp>button::before,#themeBtn::before,#sideToggle::before,.metroBtn::before{
  content:'';display:block;width:18px;height:18px;flex:none;background-color:currentColor;
  -webkit-mask:var(--ic-dot) center/contain no-repeat;mask:var(--ic-dot) center/contain no-repeat}
/* 走带两个按钮：原文是 emoji + <span> 文字，隐掉 emoji、恢复 span 字号，图标用 ::before */
.metroBtn{font-size:0}
.metroBtn>span{font-size:var(--fs-body)}
/* —— D 类：emoji 与文字同一文本节点 → ::before 图标 + ::after 补标签 —— */
#toStartBtn,#eqBtn,#aiBtn,#menuBtn,#rhythmBtn,#humanBtn,#randPatchBtn,#clearSelBtn,#demoBtn,#zoomFit,
.stab[data-tab="ai"],.stab[data-tab="track"],.stab[data-tab="lib"]{font-size:0}
#toStartBtn::before,#eqBtn::before,#aiBtn::before,#menuBtn::before,#rhythmBtn::before,
#humanBtn::before,#randPatchBtn::before,#clearSelBtn::before,#demoBtn::before,#zoomFit::before,
.stab[data-tab="ai"]::before,.stab[data-tab="track"]::before,.stab[data-tab="lib"]::before{
  content:'';display:block;width:18px;height:18px;flex:none;background-color:currentColor;
  -webkit-mask:var(--ic-dot) center/contain no-repeat;mask:var(--ic-dot) center/contain no-repeat}
#toStartBtn::after,#eqBtn::after,#aiBtn::after,#menuBtn::after,#rhythmBtn::after,
#humanBtn::after,#randPatchBtn::after,#clearSelBtn::after,#demoBtn::after,#zoomFit::after,
.stab[data-tab="ai"]::after,.stab[data-tab="track"]::after,.stab[data-tab="lib"]::after{font-size:var(--fs-body);white-space:nowrap}
/* —— 图标指派（覆盖 mask-image；有些同时覆盖尺寸） —— */
#loopBtn::before{-webkit-mask-image:var(--ic-loop);mask-image:var(--ic-loop)}
#metroBtn::before{-webkit-mask-image:var(--ic-metro);mask-image:var(--ic-metro)}
#toStartBtn::before{-webkit-mask-image:var(--ic-start);mask-image:var(--ic-start)}
#eqBtn::before{-webkit-mask-image:var(--ic-faders);mask-image:var(--ic-faders)}
.stab[data-tab="ai"]::before{-webkit-mask-image:var(--ic-sparkle);mask-image:var(--ic-sparkle)}
#quantBtn{display:inline-flex;align-items:center;gap:6px}

#zoomOut::before{-webkit-mask-image:var(--ic-minus);mask-image:var(--ic-minus)}
#zoomIn::before{-webkit-mask-image:var(--ic-plus);mask-image:var(--ic-plus)}
#zoomFit::before{-webkit-mask-image:var(--ic-expand);mask-image:var(--ic-expand)}
.stab[data-tab="track"]::before{-webkit-mask-image:var(--ic-faders);mask-image:var(--ic-faders)}
.stab[data-tab="lib"]::before{-webkit-mask-image:var(--ic-books);mask-image:var(--ic-books)}
#aiBtn::before{-webkit-mask-image:var(--ic-sparkle);mask-image:var(--ic-sparkle)}
#themeBtn::before{-webkit-mask-image:var(--ic-contrast);mask-image:var(--ic-contrast)}
#sideToggle::before{-webkit-mask-image:var(--ic-panel);mask-image:var(--ic-panel)}
#menuBtn::before{-webkit-mask-image:var(--ic-menu);mask-image:var(--ic-menu)}
#toolPaint::before{-webkit-mask-image:var(--ic-brush);mask-image:var(--ic-brush)}
#toolErase::before{-webkit-mask-image:var(--ic-eraser);mask-image:var(--ic-eraser)}
#toolSel::before{-webkit-mask-image:var(--ic-marquee);mask-image:var(--ic-marquee)}
#copyBtn::before{-webkit-mask-image:var(--ic-copy);mask-image:var(--ic-copy)}
#pasteBtn::before{-webkit-mask-image:var(--ic-paste);mask-image:var(--ic-paste)}
#rhythmBtn::before{-webkit-mask-image:var(--ic-quaver);mask-image:var(--ic-quaver)}
#humanBtn::before{-webkit-mask-image:var(--ic-dice);mask-image:var(--ic-dice)}
#randPatchBtn::before{-webkit-mask-image:var(--ic-shuffle);mask-image:var(--ic-shuffle)}
#clearSelBtn::before{-webkit-mask-image:var(--ic-broom);mask-image:var(--ic-broom)}
#demoBtn::before{-webkit-mask-image:var(--ic-clapper);mask-image:var(--ic-clapper)}
.mi[data-act="addLead"] .ic{-webkit-mask-image:var(--ic-mic);mask-image:var(--ic-mic)}
.mi[data-act="addArp"] .ic{-webkit-mask-image:var(--ic-waves);mask-image:var(--ic-waves)}
.mi[data-act="addPad"] .ic{-webkit-mask-image:var(--ic-mist);mask-image:var(--ic-mist)}
.mi[data-act="addChord"] .ic{-webkit-mask-image:var(--ic-keys);mask-image:var(--ic-keys)}
.mi[data-act="addBass"] .ic{-webkit-mask-image:var(--ic-low);mask-image:var(--ic-low)}
.mi[data-act="addDrum"] .ic{-webkit-mask-image:var(--ic-drum);mask-image:var(--ic-drum)}
.mi[data-act="saveFile"] .ic{-webkit-mask-image:var(--ic-save);mask-image:var(--ic-save)}
.mi[data-act="loadFile"] .ic{-webkit-mask-image:var(--ic-folder);mask-image:var(--ic-folder)}
.mi[data-act="quickSave"] .ic{-webkit-mask-image:var(--ic-bookmark);mask-image:var(--ic-bookmark)}
.mi[data-act="quickLoad"] .ic{-webkit-mask-image:var(--ic-restore);mask-image:var(--ic-restore)}
.mi[data-act="exportWav"] .ic{-webkit-mask-image:var(--ic-tape);mask-image:var(--ic-tape)}
.mi[data-act="exportMidi"] .ic{-webkit-mask-image:var(--ic-keys);mask-image:var(--ic-keys)}
.mi[data-act="importMidi"] .ic{-webkit-mask-image:var(--ic-download);mask-image:var(--ic-download)}
.mi[data-act="shareLink"] .ic{-webkit-mask-image:var(--ic-link);mask-image:var(--ic-link)}
.mi[data-act="help"] .ic{-webkit-mask-image:var(--ic-help);mask-image:var(--ic-help)}
.mi[data-act="clearAll"] .ic{-webkit-mask-image:var(--ic-trash);mask-image:var(--ic-trash)}
.mi[data-act="visualize"] .ic{-webkit-mask-image:var(--ic-chart);mask-image:var(--ic-chart)}
.themeMi[data-mode="dark"] .ic{-webkit-mask-image:var(--ic-moon);mask-image:var(--ic-moon)}
.themeMi[data-mode="light"] .ic{-webkit-mask-image:var(--ic-sun);mask-image:var(--ic-sun)}
.themeMi[data-mode="system"] .ic{-webkit-mask-image:var(--ic-gear);mask-image:var(--ic-gear)}
/* —— D 类标签（与 index.html 的按钮文案一一对应；改文案需同步这里） —— */
#toStartBtn::after{content:'开头'}
#eqBtn::after{content:'EQ'}
#aiBtn::after{content:'AI 作曲'}
#menuBtn::after{content:'菜单'}
#rhythmBtn::after{content:'应用细分'}
#humanBtn::after{content:'人性化力度'}
#randPatchBtn::after{content:'随机音色'}
#clearSelBtn::after{content:'清空选中轨'}
#demoBtn::after{content:'加载示例工程'}
#zoomFit{gap:4px}
#zoomFit::after{content:'适配';font-size:10px}
/* —— E 类：.btn 里的符号字形（源码是文本字符 − / ＋ / ⌖，不是 emoji 但也需线性化） —— */
#pianoOctDown,#pianoOctUp,#pianoAlign{font-size:0;gap:5px}
#pianoOctDown::before,#pianoOctUp::before,#pianoAlign::before{
  content:'';display:block;width:16px;height:16px;flex:none;background-color:currentColor;
  -webkit-mask:var(--ic-dot) center/contain no-repeat;mask:var(--ic-dot) center/contain no-repeat}
#pianoOctDown::before{-webkit-mask-image:var(--ic-minus);mask-image:var(--ic-minus)}
#pianoOctUp::before{-webkit-mask-image:var(--ic-plus);mask-image:var(--ic-plus)}
#pianoAlign::before{-webkit-mask-image:var(--ic-target);mask-image:var(--ic-target)}
#pianoAlign::after{content:'对准音区';font-size:11.5px;white-space:nowrap}

/* ============================================================================
   9. .ico —— JS 侧线性图标（配合 js/core/util.js 的 icon(name)）
   · 结构：<span class="ico ico-home" aria-hidden="true">，内容为空，图形全靠 mask；
   · 颜色：background-color:currentColor → 跟随所在元素的状态色（hover/on/禁用它自己会变）；
   · 尺寸：默认 18px；下面的"上下文尺寸"按所在容器字号缩到 11–15px，避免撑高小字行；
   · 图形本体复用上面的 --ic-* 变量（不重复内联 SVG，改一处即可）。
   ============================================================================ */
.ico{display:inline-block;width:18px;height:18px;flex:none;vertical-align:-4px;background-color:currentColor;
  -webkit-mask-size:contain;mask-size:contain;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;
  -webkit-mask-position:center;mask-position:center}
/* 上下文尺寸 */
.btn .ico,.bigBtn .ico{width:15px;height:15px;vertical-align:-3px}
.h2 .ico{width:14px;height:14px;vertical-align:-2px}
.chip .e .ico{width:14px;height:14px}
.moodRow label .ico{width:12px;height:12px;vertical-align:-2px}
.roleTag .ico{width:11px;height:11px;vertical-align:-1px}
.kitRow span .ico{width:13px;height:13px;vertical-align:-2px}
.small .ico,.modeNote .ico,.helpLine .ico,.sliderLine label .ico{width:13px;height:13px;vertical-align:-2px}
.helpLine kbd .ico{width:12px;height:12px;vertical-align:-1px}
.hint .ico,.pinfo .ico{width:13px;height:13px;vertical-align:-2px}
.toast .ico{width:14px;height:14px;vertical-align:-2px;margin-right:7px}
#epTxt .ico{width:13px;height:13px;vertical-align:-2px;margin-right:6px}
#epPct .ico{width:12px;height:12px;vertical-align:-2px;margin-right:5px}
#errbar .ico{width:14px;height:14px;vertical-align:-2px;margin-right:7px}
/* 时间线里的图标（角色标 / 鼓行标签 / 折叠箭头 / 量化预估） */
.tgIcon .ico{width:13px;height:13px}
.lab .ico{width:13px;height:13px;vertical-align:-2px}
.collapse .ico{width:12px;height:12px;vertical-align:-1px}
.qEst .ico{width:11px;height:11px;vertical-align:-1px;margin-left:3px}
#posSub .ico{width:12px;height:12px;vertical-align:-2px;margin-right:4px}
/* 图标名 → 图形（全部复用 --ic-*） */
.ico-dot{-webkit-mask-image:var(--ic-dot);mask-image:var(--ic-dot)}
.ico-minus{-webkit-mask-image:var(--ic-minus);mask-image:var(--ic-minus)}
.ico-plus{-webkit-mask-image:var(--ic-plus);mask-image:var(--ic-plus)}
.ico-expand{-webkit-mask-image:var(--ic-expand);mask-image:var(--ic-expand)}
.ico-chart{-webkit-mask-image:var(--ic-chart);mask-image:var(--ic-chart)}
.ico-home{-webkit-mask-image:var(--ic-home);mask-image:var(--ic-home)}
.ico-play{-webkit-mask-image:var(--ic-play);mask-image:var(--ic-play)}
.ico-close{-webkit-mask-image:var(--ic-close);mask-image:var(--ic-close)}
.ico-pencil{-webkit-mask-image:var(--ic-pencil);mask-image:var(--ic-pencil)}
.ico-music{-webkit-mask-image:var(--ic-music);mask-image:var(--ic-music)}
.ico-palette{-webkit-mask-image:var(--ic-palette);mask-image:var(--ic-palette)}
.ico-check{-webkit-mask-image:var(--ic-check);mask-image:var(--ic-check)}
.ico-cross{-webkit-mask-image:var(--ic-cross);mask-image:var(--ic-cross)}
.ico-warn{-webkit-mask-image:var(--ic-warn);mask-image:var(--ic-warn)}
.ico-undo{-webkit-mask-image:var(--ic-undo);mask-image:var(--ic-undo)}
.ico-redo{-webkit-mask-image:var(--ic-redo);mask-image:var(--ic-redo)}
.ico-flame{-webkit-mask-image:var(--ic-flame);mask-image:var(--ic-flame)}
.ico-sun-dim{-webkit-mask-image:var(--ic-sun-dim);mask-image:var(--ic-sun-dim)}
.ico-dna{-webkit-mask-image:var(--ic-dna);mask-image:var(--ic-dna)}
.ico-coffee{-webkit-mask-image:var(--ic-coffee);mask-image:var(--ic-coffee)}
.ico-speaker{-webkit-mask-image:var(--ic-speaker);mask-image:var(--ic-speaker)}
.ico-city{-webkit-mask-image:var(--ic-city);mask-image:var(--ic-city)}
.ico-sax{-webkit-mask-image:var(--ic-sax);mask-image:var(--ic-sax)}
.ico-galaxy{-webkit-mask-image:var(--ic-galaxy);mask-image:var(--ic-galaxy)}
.ico-pin{-webkit-mask-image:var(--ic-pin);mask-image:var(--ic-pin)}
.ico-headphones{-webkit-mask-image:var(--ic-headphones);mask-image:var(--ic-headphones)}
.ico-follow{-webkit-mask-image:var(--ic-follow);mask-image:var(--ic-follow)}
.ico-guitar{-webkit-mask-image:var(--ic-guitar);mask-image:var(--ic-guitar)}
.ico-kick{-webkit-mask-image:var(--ic-kick);mask-image:var(--ic-kick)}
.ico-snare{-webkit-mask-image:var(--ic-snare);mask-image:var(--ic-snare)}
.ico-clap{-webkit-mask-image:var(--ic-clap);mask-image:var(--ic-clap)}
.ico-hhc{-webkit-mask-image:var(--ic-hhc);mask-image:var(--ic-hhc)}
.ico-hho{-webkit-mask-image:var(--ic-hho);mask-image:var(--ic-hho)}
.ico-tom{-webkit-mask-image:var(--ic-tom);mask-image:var(--ic-tom)}
.ico-rim{-webkit-mask-image:var(--ic-rim);mask-image:var(--ic-rim)}
.ico-crash{-webkit-mask-image:var(--ic-crash);mask-image:var(--ic-crash)}
.ico-caret{-webkit-mask-image:var(--ic-caret);mask-image:var(--ic-caret)}
.ico-wave{-webkit-mask-image:var(--ic-wave);mask-image:var(--ic-wave)}
.ico-note{-webkit-mask-image:var(--ic-note);mask-image:var(--ic-note)}
.ico-loop{-webkit-mask-image:var(--ic-loop);mask-image:var(--ic-loop)}
.ico-metro{-webkit-mask-image:var(--ic-metro);mask-image:var(--ic-metro)}
.ico-start{-webkit-mask-image:var(--ic-start);mask-image:var(--ic-start)}
.ico-faders{-webkit-mask-image:var(--ic-faders);mask-image:var(--ic-faders)}
.ico-sparkle{-webkit-mask-image:var(--ic-sparkle);mask-image:var(--ic-sparkle)}
.ico-contrast{-webkit-mask-image:var(--ic-contrast);mask-image:var(--ic-contrast)}
.ico-panel{-webkit-mask-image:var(--ic-panel);mask-image:var(--ic-panel)}
.ico-menu{-webkit-mask-image:var(--ic-menu);mask-image:var(--ic-menu)}
.ico-mic{-webkit-mask-image:var(--ic-mic);mask-image:var(--ic-mic)}
.ico-waves{-webkit-mask-image:var(--ic-waves);mask-image:var(--ic-waves)}
.ico-mist{-webkit-mask-image:var(--ic-mist);mask-image:var(--ic-mist)}
.ico-keys{-webkit-mask-image:var(--ic-keys);mask-image:var(--ic-keys)}
.ico-low{-webkit-mask-image:var(--ic-low);mask-image:var(--ic-low)}
.ico-drum{-webkit-mask-image:var(--ic-drum);mask-image:var(--ic-drum)}
.ico-save{-webkit-mask-image:var(--ic-save);mask-image:var(--ic-save)}
.ico-folder{-webkit-mask-image:var(--ic-folder);mask-image:var(--ic-folder)}
.ico-bookmark{-webkit-mask-image:var(--ic-bookmark);mask-image:var(--ic-bookmark)}
.ico-restore{-webkit-mask-image:var(--ic-restore);mask-image:var(--ic-restore)}
.ico-tape{-webkit-mask-image:var(--ic-tape);mask-image:var(--ic-tape)}
.ico-download{-webkit-mask-image:var(--ic-download);mask-image:var(--ic-download)}
.ico-link{-webkit-mask-image:var(--ic-link);mask-image:var(--ic-link)}
.ico-help{-webkit-mask-image:var(--ic-help);mask-image:var(--ic-help)}
.ico-trash{-webkit-mask-image:var(--ic-trash);mask-image:var(--ic-trash)}
.ico-brush{-webkit-mask-image:var(--ic-brush);mask-image:var(--ic-brush)}
.ico-eraser{-webkit-mask-image:var(--ic-eraser);mask-image:var(--ic-eraser)}
.ico-marquee{-webkit-mask-image:var(--ic-marquee);mask-image:var(--ic-marquee)}
.ico-copy{-webkit-mask-image:var(--ic-copy);mask-image:var(--ic-copy)}
.ico-paste{-webkit-mask-image:var(--ic-paste);mask-image:var(--ic-paste)}
.ico-target{-webkit-mask-image:var(--ic-target);mask-image:var(--ic-target)}
.ico-quaver{-webkit-mask-image:var(--ic-quaver);mask-image:var(--ic-quaver)}
.ico-dice{-webkit-mask-image:var(--ic-dice);mask-image:var(--ic-dice)}
.ico-shuffle{-webkit-mask-image:var(--ic-shuffle);mask-image:var(--ic-shuffle)}
.ico-broom{-webkit-mask-image:var(--ic-broom);mask-image:var(--ic-broom)}
.ico-clapper{-webkit-mask-image:var(--ic-clapper);mask-image:var(--ic-clapper)}
.ico-books{-webkit-mask-image:var(--ic-books);mask-image:var(--ic-books)}
.ico-moon{-webkit-mask-image:var(--ic-moon);mask-image:var(--ic-moon)}
.ico-sun{-webkit-mask-image:var(--ic-sun);mask-image:var(--ic-sun)}
.ico-gear{-webkit-mask-image:var(--ic-gear);mask-image:var(--ic-gear)}

/* ============================================================================
   10. 动效系统（FEAT-V6/T5 批 3）
   · 时长/缓动一律来自 theme.css 的 --dur-* / --ease-* token；
   · 只动 transform / opacity（两处刻意的例外：按钮按下与闪烁反馈用 box-shadow，
     进度条填充用 width —— 见汇报"偏差"）；
   · 所有无限循环动画都会被 prefers-reduced-motion 关掉（功能性动画除外，见 theme.css）。
   ============================================================================ */

/* —— 1. 侧栏面板切换：内容从 +8px 淡入 280ms ——
   旧内容的"-8px 淡出"需要 JS 保留旧节点（innerHTML 一换旧节点就没了），故本轮只做入场；
   三个内容相同、名字不同的 keyframes 是必须的：animation-name 变化才会重播动画 ——
   于是"切 tab"播一次，而 renderInspector() 在编辑过程中的重复渲染（同一个 tab）不会反复播。 */
#sideBody{animation:panelInAi var(--dur-base) var(--ease-out)}
.side:has(.stab[data-tab="track"].on) #sideBody{animation-name:panelInTrack}
.side:has(.stab[data-tab="lib"].on) #sideBody{animation-name:panelInLib}
@keyframes panelInAi{from{opacity:0;transform:translateX(8px)}to{opacity:1;transform:none}}
@keyframes panelInTrack{from{opacity:0;transform:translateX(8px)}to{opacity:1;transform:none}}
@keyframes panelInLib{from{opacity:0;transform:translateX(8px)}to{opacity:1;transform:none}}

/* —— 4. Tab 下划线平滑移动 ——
   三个 tab 是 flex:1 等宽，所以滑动量可以直接用 translateX(百分比) 算出来，不需要 JS 量 offsetLeft：
   滑块自身的宽度 = (100% - 左右 padding 20px - 两个 gap 8px)/3，位移 = n × (自身宽 + gap 4px)。
   .stab.on 原来那条 inset 顶部高光由它接替（同一视觉，但改成"滑过去"而不是"闪现"）。 */
.sideTabs{position:relative}
.sideTabs::after{content:'';position:absolute;top:10px;left:10px;width:calc((100% - 28px)/3);height:2px;border-radius:var(--r-xs);
  background:var(--sig);pointer-events:none;transform:translateX(0);
  transition:transform var(--dur-base) var(--ease-in-out)}
.side:has(.stab[data-tab="track"].on) .sideTabs::after{transform:translateX(calc(100% + 4px))}
.side:has(.stab[data-tab="lib"].on) .sideTabs::after{transform:translateX(calc(200% + 8px))}

/* —— 8. 列表交错进入 / 5. 数字上滑 / 7. 加载旋转弧与微光 ——
   这些工具的 keyframes 与交错规则已上移到 theme.css（批 A：主应用与可视化页共用），
   这里只保留主应用自己的挂载点。 */
#epBar{position:relative;overflow:hidden;transition:width var(--dur-base) var(--ease-out)}
.pb i{position:relative;overflow:hidden}
#epBar::after,.pb i::after{content:'';position:absolute;top:0;bottom:0;width:55%;
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.55),transparent);
  animation:sheen calc(var(--dur-flash) * 2) var(--ease-in-out) infinite}
#epTxt::before{content:'';display:inline-block;width:11px;height:11px;margin-right:7px;vertical-align:-1px;
  border:1.5px solid rgba(var(--txt-rgb),.25);border-top-color:var(--acc);border-radius:50%;
  animation:spin var(--dur-flash) var(--ease-linear) infinite}

/* —— 10. 鹰角风粒子呼吸（可选动效）——
   .brand 区域 4 颗极淡光点缓慢飘散；z-index:-1 让它们落在 logo/标题文字**之下**
   （.brand 自身背景透明，所以负层级不会把它挡掉）；只动 transform + opacity，
   一个来回 ≈ 14 × --dur-enter ≈ 7.8s，reduced-motion 下整条关掉。 */
.brand{position:relative}
.brand::after{content:'';position:absolute;inset:-8px -12px;z-index:-1;pointer-events:none;
  background:
    radial-gradient(2px 2px at 14% 72%,rgba(var(--acc-rgb),.55),transparent 70%),
    radial-gradient(1.5px 1.5px at 38% 26%,rgba(var(--acc-rgb),.40),transparent 70%),
    radial-gradient(2px 2px at 62% 80%,rgba(var(--acc-rgb),.32),transparent 70%),
    radial-gradient(1.5px 1.5px at 88% 20%,rgba(var(--acc-rgb),.45),transparent 70%);
  animation:drift calc(var(--dur-enter) * 14) var(--ease-out-quint) infinite alternate}
@keyframes drift{from{transform:translate3d(0,0,0);opacity:.28}to{transform:translate3d(-7px,-5px,0);opacity:.72}}

/* ============================================================================
   11. 帮助弹窗（批 C 第二部分）：标记由 showHelp() 生成，样式收在这里（JS 不再写内联样式）。
   分层入场：遮罩 420ms 先到，卡片延迟 60ms 再 scale(.94)+淡入。
   用 animation 而不是 @starting-style：弹窗是点击时新建插入的，animation 插入即播最稳。
   ============================================================================ */
.modal-overlay{
  position:fixed;inset:0;z-index:300;display:flex;align-items:center;justify-content:center;
  background:rgba(2,5,12,.72);
  -webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);
  animation:modalScrimIn var(--dur-slow) var(--ease-out) both;
}
.modal-card{
  width:min(640px,94vw);max-height:88vh;overflow:auto;
  background:var(--panel);border:1px solid var(--line2);border-radius:var(--r);
  padding:24px;box-shadow:var(--shadow-3);
  animation:modalCardIn var(--dur-slow) var(--ease-out) 60ms both;
}
@keyframes modalScrimIn{from{opacity:0}to{opacity:1}}
@keyframes modalCardIn{from{opacity:0;transform:scale(.94)}to{opacity:1;transform:none}}
/* 关闭：遮罩与卡片反向淡出（200ms/--ease-in），JS 用 animationend 收尾后移除节点 */
.modal-overlay.closing{animation:modalScrimOut var(--dur-fast) var(--ease-in) both}
.modal-overlay.closing .modal-card{animation:modalCardOut var(--dur-fast) var(--ease-in) both}
@keyframes modalScrimOut{from{opacity:1}to{opacity:0}}
@keyframes modalCardOut{from{opacity:1;transform:none}to{opacity:0;transform:scale(.96)}}

.stab[data-tab="ai"]::after{content:'AI 作曲'}
.stab[data-tab="track"]::after{content:'轨道 / 混音'}
.stab[data-tab="lib"]::after{content:'作品库'}

