/* audio.css — audiokit 全部音频工具页共用的样式（assets/audio/audio.css）。

   **页面的骨架（两个状态、右侧 300px 设置栏、按钮钉在栏底）和 imgkit 的工具页
   同一套**（那边是 assets/img/img.css，改编时整段搬过来，注释里还留着「图片」
   的字样当出处）；配色和控件样式照 privatepdf.io 做 —— 主色 indigo-600
   #4f39f6，见下面那组 token：
     · 还没选文件：工作区居中摆大标题 + 灰色副标题 + 一颗蓝色大按钮（「选择文件」）
       +「或者把文件拖到这里」。右栏只在选了文件之后出现。
     · 选了文件之后：工作区顶上是文件卡（名字 / 时长 · 44.1 kHz stereo · 体积），
       右侧栏里竖排设置项，主操作按钮（圆角矩形蓝按钮）钉在栏底。
       结果出来后换成播放器（每轨一行：左边控制、右边波形）。

   报错一律红的，而且文字前面都带 ⚠ 并且给底色 —— 不能只靠颜色，
   色弱的人分不出蓝按钮和红字。 */

:root {
  /* 这套色是照 privatepdf.io 抄的（它用 Tailwind v4 的默认色板）：
     整页 stone-50、卡片纯白、边框 zinc-200、正文 neutral-700、
     主色 indigo-600 #4f39f6。圆角和阴影也跟着走 —— rounded-xl 12px、
     rounded-2xl 16px、阴影是 Tailwind 那两层很浅的投影，不是大散影。 */
  --page: #fafaf9;      /* stone-50：整页底色，卡片靠它浮起来 */
  --bg: #fff;           --bg-elevated: #fff;  --bg-sunken: #f5f5f4;
  --heading: #171717;   /* 标题近黑（和首页 styles.css 同一个值） */
  --text: #404040;      --text-muted: #525252; --text-faint: #737373;
  --border: #e4e4e7;    --border-strong: #d4d4d8;
  --accent: #4f39f6;    --accent-hover: #432dd7; --accent-soft: #eef2ff;
  --ok: #16a34a;        --ok-soft: #dcfce7;
  --warn: #d97706;      --warn-soft: #fef3c7;
  --err: #dc2626;       --err-soft: #fee2e2;
  --radius: 16px;       --radius-sm: 8px; --radius-card: 20px;
  --shadow: 0 1px 3px rgba(0,0,0,.10), 0 1px 2px -1px rgba(0,0,0,.10);
  --shadow-lg: 0 10px 15px -3px rgba(0,0,0,.10), 0 4px 6px -4px rgba(0,0,0,.10);
  /* 棋盘格：透明区域的地板。深浅两套主题共用一种灰，
     反正底下是「透明」，不该跟着主题变色太多 */
  --checker: rgba(127,127,127,.16);
  --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
          "Helvetica Neue", Helvetica, Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --page: #0a0a0a; --bg: #171717; --bg-elevated: #171717; --bg-sunken: #262626;
    --heading: #f5f5f5;
    --text: #d4d4d4; --text-muted: #a3a3a3; --text-faint: #737373;
    --border: #2e2e2e; --border-strong: #404040;
    --accent: #818cf8; --accent-hover: #a5b4fc; --accent-soft: #1e1b4b;
    --ok: #4ade80; --ok-soft: #052e16;
    --warn: #fbbf24; --warn-soft: #451a03;
    --err: #f87171; --err-soft: #450a0a;
    --shadow: 0 1px 3px rgba(0,0,0,.5), 0 1px 2px -1px rgba(0,0,0,.5);
    --shadow-lg: 0 10px 15px -3px rgba(0,0,0,.5), 0 4px 6px -4px rgba(0,0,0,.5);
  }
}
:root[data-theme="dark"] {
  --page: #0a0a0a; --bg: #171717; --bg-elevated: #171717; --bg-sunken: #262626;
  --heading: #f5f5f5;
  --text: #d4d4d4; --text-muted: #a3a3a3; --text-faint: #737373;
  --border: #2e2e2e; --border-strong: #404040;
  --accent: #818cf8; --accent-hover: #a5b4fc; --accent-soft: #1e1b4b;
  --ok: #4ade80; --ok-soft: #052e16;
  --warn: #fbbf24; --warn-soft: #451a03;
  --err: #f87171; --err-soft: #450a0a;
  --shadow: 0 1px 3px rgba(0,0,0,.5), 0 1px 2px -1px rgba(0,0,0,.5);
  --shadow-lg: 0 10px 15px -3px rgba(0,0,0,.5), 0 4px 6px -4px rgba(0,0,0,.5);
}

* { box-sizing: border-box; }
/* 下面好几处靠 hidden 属性开关，而它们各自带 display:flex ——
   自定义 display 会盖掉 hidden 的 display:none，这条得压住。 */
[hidden] { display: none !important; }
html { background: var(--page); overflow-x: clip; }
body {
  margin: 0; padding: 0;
  background: none; color: var(--text);
  font: 16px/1.65 var(--sans); -webkit-font-smoothing: antialiased;
}
/* 大标题前那枚图标：由 site-nav.js 按当前页的 slug 注入（页面 HTML 里不写
   SVG），颜色是分类色。让它和文字基线对齐，别把行高撑开。
   字号字重照 privatepdf.io 的 h1（48px/800、字距 -.025em）往下收了一档：
   中文的字面比拉丁字母满，38px 的视觉重量已经对得上它的 48。 */
h1 {
  margin: 10px 0 12px; font-size: 40px; font-weight: 800;
  letter-spacing: -.025em; text-align: center;
  display: flex; align-items: center; justify-content: center; gap: 12px;
}
h1 .h1ic { display: inline-flex; flex: none; }
h1 .h1ic svg { width: 36px; height: 36px; display: block; }
.lede {
  margin: 0 auto 26px; max-width: 64ch; text-align: center;
  font-size: 19px; line-height: 1.7; color: var(--text-muted);
}
h2 { margin: 30px 0 12px; font-size: 16px; font-weight: 600; }
a { color: var(--accent); }
code, kbd { font-family: var(--mono); font-size: .9em; }
kbd {
  padding: 1px 6px; border: 1px solid var(--border-strong);
  border-radius: 5px; background: var(--bg-sunken);
}
/* 按钮照 privatepdf.io 的那两颗：
   主按钮 = indigo-600 底 + 白字 + rounded-xl(12px) + 半粗，悬停换 indigo-700
   并微微抬起；次按钮 = 白底 + 1px zinc-200 边 + 深字，悬停只压深一点底色。
   原来那套「悬停变蓝边蓝字」的写法去掉了 —— 参考站不在边框上做文章。 */
button {
  font: inherit; color: inherit; cursor: pointer;
  border: 1px solid var(--border-strong); background: var(--bg-elevated);
  border-radius: 10px; padding: 8px 15px;
  transition: background .14s, border-color .14s, box-shadow .14s, transform .14s, opacity .14s;
}
button:hover:not(:disabled) { background: var(--bg-sunken); border-color: var(--border-strong); }
button:disabled { opacity: .45; cursor: default; }
button.primary {
  background: var(--accent); border-color: var(--accent); color: #fff; font-weight: 600;
  box-shadow: var(--shadow);
}
button.primary:hover:not(:disabled) {
  background: var(--accent-hover); border-color: var(--accent-hover); color: #fff;
}
button.icon { padding: 5px 9px; font-size: 14px; line-height: 1.2; }
/* 按钮里的图标一律 17px —— 这是**兜底的那一条**，别删。
   裸 SVG 没有宽高，塞进按钮里会被撑成一大块；只有在 .ic 那个 span 里才收得住。
   这个坑前后踩过四次（水印页那两颗、认人遮盖的开始按钮、tabIcons、二维码页的
   「生成二维码」撑成一整块），所以在这儿定个默认值：
   凡是要往按钮里放图标，塞进 <span class="ic">，尺寸就归这里管。 */
button .ic { display: inline-flex; flex: none; }
button .ic svg { width: 17px; height: 17px; display: block; }
/* 选中态（页签、开关这一类）：淡靛蓝底 + 靛蓝边 + 靛蓝字 */
button.on[aria-pressed="true"], button[aria-pressed="true"] {
  background: var(--accent-soft); border-color: var(--accent); color: var(--accent); font-weight: 600;
}
button[aria-pressed="true"]:hover:not(:disabled) { background: var(--accent-soft); }
select, input[type="number"], input[type="text"] {
  font: inherit; color: inherit; background: var(--bg-elevated);
  border: 1px solid var(--border-strong); border-radius: 10px;
  padding: 7px 10px;
}
select:focus, input[type="number"]:focus, input[type="text"]:focus {
  outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent);
}
/* 滑杆：用浏览器原生的 accent-color，跟主色一致就行 —— 自己画一套
   轨道和滑块的话，三个引擎三副样子，不如交给浏览器 */
input[type="range"] { accent-color: var(--accent); }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* ================= 工具页骨架：工作区 + 右侧设置栏 ================= */
.tool { display: flex; align-items: stretch; min-height: 70vh; }
.workarea {
  flex: 1 1 auto; min-width: 0;
  display: flex; flex-direction: column;
  padding: 26px 26px 0;
}
.side {
  flex: 0 0 300px; width: 300px;
  background: var(--bg-elevated);
  border-left: 1px solid var(--border);
  display: flex; flex-direction: column;
  padding: 22px 20px 20px;
  /* 设置栏钉在视口里：页面很长（画布、一屏卡片）时，设置项和主操作按钮
     不该跟着滚走。内容多过一屏时栏内自己滚。 */
  position: sticky; top: 60px; align-self: flex-start;
  height: calc(100vh - 60px); overflow: hidden;
}
/* 侧栏没选图时整条是 hidden 的（见 core.js 的 afterChange）：不占宽度，
   也不摆一块「还没有选择图片」的空牌子。 */
.side__panel { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
/* 设置项超过一屏时，滚的是这一块 —— 主按钮在下面钉着，永远看得见、点得到。
   这里**不能**用「负外边距 + 等量内边距」那种给滚动条让位的写法：
   内容框会被撑得比可见区宽十几个像素，一行行 width:100% 的滑杆就会顶出去
   一截（实测出来的：滑杆右端和值被切在屏幕外面）。宽度就让它等于内容宽。 */
.side__body { flex: 1 1 auto; overflow-y: auto; min-height: 0; }
.side__panel h2 { margin: 0 0 18px; font-size: 24px; font-weight: 700; letter-spacing: -.02em; }
.side .opts { flex-direction: column; align-items: stretch; gap: 14px; }
/* min-width:0 是必需的：flex 项默认「不能小于内容的最小宽度」，而侧栏里
   偏偏有 <input type="file"> 这种自带两三百像素最小宽度的控件 —— 不压住的话
   整格会被它撑得比侧栏还宽，滑杆和值一起顶出屏幕（实测出来的）。 */
.side .opts > * { min-width: 0; }
/* 光有 min-width:0 还不够，还得给一格上限。滑杆那一行的宽度是这么绕起来的：
   一行 = 标签 + 滑杆 + 数字框 + 单位，加起来两百七八十像素；这一行的
   「理想宽度」会被 flex 取成整行的宽，行又按格子的宽算，格子再按行算 ——
   几行读数变宽之后（数字框比原来的读数宽），这一圈就转出一个比侧栏还宽的
   结果，单位那个「%」被切在屏幕外。max-width 把这一圈打断：格子就按侧栏的
   宽算，行再按格子算，多出来的宽度由滑杆自己缩（它 min-width 是 0，缩得动）。 */
.side .opts > * { max-width: 100%; }
.side .range { max-width: 100%; }
.side .opt input[type="text"], .side .opt select, .side .opt input[type="number"],
.side .opt input[type="file"] { width: 100%; max-width: 100%; }
.side .opt .inline { justify-content: space-between; }
.side .fields { grid-template-columns: 1fr; }
/* 主操作按钮钉在栏底：不管上面有几种设置，它都在同一个位置。 */
.side__foot { margin-top: auto; padding-top: 16px; }
.side__body + .side__foot { border-top: 1px solid var(--border); }
.side__foot .primary {
  width: 100%; height: 56px; border-radius: 12px;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 19px; font-weight: 600; letter-spacing: .01em;
}
.side__foot .hint { margin: 8px 0 0; text-align: center; }
/* 侧栏底部那两颗按钮也要能带图标（二维码页的「下载 PNG / 下载 SVG」）：
   图标一律 17px，和工具条上那几颗一个尺寸。少了这一条会两种坏法都出现 ——
   .primary 是 inline-flex，里面的裸 SVG 被压成 0px；.zipbtn 不是 flex，
   同一个 SVG 又被撑成两百多像素的一大块（都是实测出来的）。 */
.side__foot button { display: inline-flex; align-items: center; justify-content: center; gap: 8px; }
.side__foot button .ic { display: inline-flex; flex: none; }
.side__foot button .ic svg { width: 17px; height: 17px; display: block; }

/* 空状态：工作区居中摆标题 + 那颗大按钮 */
.welcome { flex: 1 1 auto; display: flex; flex-direction: column; align-items: center; padding-top: 6px; }
.workspace { flex: 1 1 auto; min-width: 0; }
.wstools { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 18px; min-height: 46px; }
.wstools .grow { flex: 1 1 auto; }
/* 工作区顶上那三颗（打包下载 ZIP / 清空 / 添加图片）：**尺寸必须一样**。
   曾经不一样过 —— 「添加图片」自己写了 font-size: 13px，另外两颗继承正文
   （16px），并排一站高矮不齐。现在三颗都走这里这一套：同样的内边距、
   同样的字号（继承）、同样 17px 的图标。

   2026-10-07 上色：用户说这三颗「太素了，容易被忽略」。上色的规矩不是
   「都染成蓝的」，而是按重要性分三层，颜色本身带信息：
     · 打包下载 ZIP —— **有东西可下的时候**才整颗变实心靛蓝（白字白图标），
       没结果时（disabled）保持安静：这时候那片蓝是在说「现在可以拿了」；
     · 添加图片 —— 淡靛蓝底 + 靛蓝边，一眼看得见，但不跟主操作抢；
     · 清空 —— 中性，悬停才泛红：它是个「别乱点」的动作。 */
.addbtn, .wstools > button {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 8px 15px;
}
.addbtn .ic, .wstools > button .ic { display: inline-flex; flex: none; color: var(--text-muted); }
.addbtn .ic svg, .wstools > button .ic svg { width: 17px; height: 17px; display: block; }

/* 打包下载 ZIP：等它真能下载了再亮起来 */
#zipBtn:not(:disabled) {
  background: var(--accent); border-color: var(--accent); color: #fff;
  font-weight: 600; box-shadow: var(--shadow);
}
#zipBtn:not(:disabled) .ic { color: #fff; }
#zipBtn:not(:disabled):hover {
  background: var(--accent-hover); border-color: var(--accent-hover); color: #fff;
}
/* 添加图片：淡底的那一颗（主色，但不实心） */
.addbtn {
  background: var(--accent-soft);
  border-color: color-mix(in srgb, var(--accent) 38%, transparent);
  color: var(--accent); font-weight: 600;
}
.addbtn .ic { color: var(--accent); }
.addbtn:hover:not(:disabled) {
  background: color-mix(in srgb, var(--accent) 15%, var(--bg-elevated));
  border-color: var(--accent); color: var(--accent);
}
/* 清空：平时中性，悬停泛红（红色的意思是「这一步不好撤销」） */
#clearBtn:hover:not(:disabled) {
  background: var(--err-soft); color: var(--err);
  border-color: color-mix(in srgb, var(--err) 45%, transparent);
}
#clearBtn:hover:not(:disabled) .ic { color: var(--err); }

/* ---------- 拖放区 ---------- */
/* 拖放区：照 privatepdf.io 那个虚线框做 —— 白底 + 2px 淡靛蓝虚线 + 16px 圆角，
   中间一颗 indigo-600 的大按钮。拖进来的时候虚线和底色一起变深。 */
.drop {
  display: flex; flex-direction: column; align-items: center; gap: 16px;
  padding: 30px 20px 34px; margin: 0 auto 20px; max-width: 760px;
  cursor: pointer; text-align: center;
  background: var(--bg-elevated);
  border: 2px dashed color-mix(in srgb, var(--accent) 35%, transparent);
  border-radius: 16px;
  transition: background .15s, border-color .15s;
}
.drop.over {
  border-color: var(--accent);
  background: var(--accent-soft);
}
.drop__btn {
  /* 尺寸照 privatepdf.io/merge 那颗「Select PDF files」来的（实测 285×68、
     内边距 20/48、圆角 12）—— 用户 2026-10-07 让按它调。中文只有四个字，
     光靠内边距撑不到那个宽度，所以再加一条 min-width。 */
  display: inline-block; padding: 20px 48px; min-width: 285px;
  border-radius: 12px; line-height: 1.4;
  background: var(--accent); color: #fff;
  font-size: 20px; font-weight: 600;
  box-shadow: var(--shadow);
  transition: background .14s, box-shadow .14s, transform .14s;
}
/* 悬停抬一点点 + 阴影加大（参考站是 hover:-translate-y-1 + shadow-xl，
   这里抬 1px 就够 —— 它那颗按钮在一屏正中，我们这颗在表单里） */
.drop:hover .drop__btn, .drop.over .drop__btn {
  background: var(--accent-hover);
  box-shadow: var(--shadow-lg);
  transform: translateY(-1px);
}
.drop__sub { color: var(--text-muted); font-size: 15px; }
.drop__sub kbd { font-size: .92em; }

/* 宽 × 高 两个格子：各带一个标题，中间一个 ×。
   （只写 placeholder 的话，一填上数字就分不出哪个是宽哪个是高。） */
.whrow { display: flex; align-items: flex-end; gap: 9px; }
.whrow__f { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: 5px; }
.whrow__f > span { font-size: 13.5px; font-weight: 600; color: var(--text-muted); }
.whrow__f > span i { font-style: normal; font-weight: 400; color: var(--text-faint); }
.whrow__f input { width: 100%; }
.whrow__x { flex: none; padding-bottom: 9px; color: var(--text-faint); font-size: 14px; }

/* ---------- 设置面板 ---------- */
.panel {
  background: var(--bg-elevated); border-radius: var(--radius);
  box-shadow: var(--shadow); padding: 18px 20px; margin-bottom: 22px;
}
.opts { display: flex; flex-wrap: wrap; gap: 18px 26px; align-items: flex-end; }
.opts + .opts { margin-top: 18px; }
.opt { display: flex; flex-direction: column; gap: 6px; }
.opt > span { font-size: 13.5px; color: var(--text-muted); }
.opt .inline { display: flex; align-items: center; gap: 8px; }
.opt input[type="number"] { width: 92px; }
.opt input[type="range"] { width: 100%; accent-color: var(--accent); }
.opt .qval { font-variant-numeric: tabular-nums; min-width: 3.2em; font-size: 13.5px; }
.opt input[type="color"] {
  width: 46px; height: 34px; padding: 2px; background: var(--bg-elevated);
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm); cursor: pointer;
}
/* 一行滑杆：左边标签、中间滑杆、右边当前值 —— 侧栏里最常用的一格 */
.range { display: flex; align-items: center; gap: 9px; width: 100%; }
.range > span:first-child { flex: 0 0 auto; font-size: 14px; color: var(--text-muted); min-width: 4.2em; }
/* width:auto 得写死：上面 `.opt input[type="range"] { width:100% }` 那条
   在侧栏里会让滑杆顶出容器（100% 是不含左右标签的宽度）。 */
.range input[type="range"] { flex: 1 1 auto; width: auto; min-width: 0; margin: 0; accent-color: var(--accent); }
.range .qval { flex: 0 0 auto; font-size: 13.5px; color: var(--text-faint); min-width: 2.8em; text-align: right; }
/* 能直接敲的读数（<input type="number">）：窄一点、靠右对齐。
   里层要盖掉 `.side .opt input[type="number"] { width: 100% }` 那条，
   不然它会把整行撑满、把滑杆挤没（选择器多一层 .range 就是为了赢它）。
   宽度只留得下 4 个字符（-100 / 240 这种最长的值）—— 侧栏窄，
   读数多占一分，滑杆就少一分，滑杆太短就拖不准了。
   两条选择器：多数行在 .opt 里，抠图那页有几条是 .opts 直接下面的。 */
.side .opt .range .qval--edit,
.side .opts > .range .qval--edit {
  width: 4.1em; min-width: 0; padding: 3px 5px;
  font-size: 13px; text-align: right; color: var(--text);
}
.range .qval-unit { flex: none; font-size: 13.5px; color: var(--text-faint); }

/* ---------- 单张压缩页：右边那三行数 ---------- */
/* 「原图 174 KB / 压缩后 47 KB / 省下 73%」—— 这一页的全部结论就在这三个数上，
   所以给它一块自己的底，别混在一堆设置项里当小字看 */
.cs-live {
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--bg-sunken);
  padding: 12px 14px; display: flex; flex-direction: column; gap: 6px;
}
.cs-live__row { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.cs-live__row span { font-size: 13.5px; color: var(--text-muted); }
.cs-live__row b {
  font-size: 15px; font-weight: 700; color: var(--text);
  font-variant-numeric: tabular-nums;
}
.cs-live__row b.to { color: var(--accent); }
.cs-live__save {
  margin-top: 2px; padding-top: 8px; border-top: 1px dashed var(--border);
  font-size: 13.5px; font-weight: 600; color: var(--text-muted);
}
.cs-live__save.ok { color: var(--ok); }
.cs-live__save.warn { color: var(--warn); }
.hint { font-size: 14px; color: var(--text-muted); line-height: 1.6; }
.hint.err { color: var(--err); }
.hint.ok { color: var(--ok); }

/* ---------- 缩略图卡片 ---------- */
/* 卡片墙是**等宽不等高**（同 pinterest 那种瀑布流）：横图占的地方矮、
   竖图占的地方高，不用被塞进统一高度的框里。顺序是竖着读的 ——
   第一列排满再到第二列（CSS 多列就是这个读法，跟 DOM 顺序一致）。
   换成多列之后 grid 那套用不上了，靠 column-width 决定分几列。 */
.grid { column-width: 190px; column-gap: 16px; }
.item {
  display: flex; flex-direction: column; gap: 8px; padding: 12px;
  background: var(--bg-elevated); border-radius: var(--radius); box-shadow: var(--shadow);
  /* 卡片本身别被拆到两列去（多列布局里的经典坑） */
  break-inside: avoid; -webkit-column-break-inside: avoid;
  margin-bottom: 16px; width: 100%;
}
/* 棋盘格衬底：透明区域得能看出来，白底上会以为是白的 */
.thumb, .checker {
  background-color: var(--bg-sunken);
  background-image:
    linear-gradient(45deg, var(--checker) 25%, transparent 25%, transparent 75%, var(--checker) 75%),
    linear-gradient(45deg, var(--checker) 25%, transparent 25%, transparent 75%, var(--checker) 75%);
  background-size: 16px 16px; background-position: 0 0, 8px 8px;
}
.thumb {
  display: grid; place-items: center; overflow: hidden;
  border-radius: var(--radius-sm);
  /* 高度跟着图走（瀑布流的关键）：以前钉死 148px，横图竖图都得挤进同一个框。
     竖得太离谱的（9:16 那种）还是给个上限，一张图不该占掉两屏。 */
  max-height: 420px;
}
.thumb canvas, .thumb img { max-width: 100%; max-height: 420px; display: block; border-radius: 3px; }
/* 卡片上能按住拖的页面（批量裁剪）：抓手光标；触摸时别把拖动当成页面滚动。
   类名是 ops.js 给 .grid 加的，别的页面不受影响。 */
.grid.cb-drag .thumb { position: relative; }
.grid.cb-drag .thumb canvas { cursor: grab; touch-action: none; }
.grid.cb-drag .thumb canvas:active { cursor: grabbing; }
/* 单独挪过的那张，缩略图右上角挂一个退回统一位置的 ↺ */
.cb-reset {
  position: absolute; top: 6px; right: 6px; width: 26px; height: 26px; padding: 0;
  display: grid; place-items: center; cursor: pointer; line-height: 1;
  font-size: 15px; color: var(--text); border-radius: 50%;
  background: color-mix(in srgb, var(--bg-elevated) 90%, transparent);
  border: 1px solid var(--border-strong);
}
.cb-reset:hover { color: var(--accent); border-color: var(--accent); }
.item .name { font-size: 14.5px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.item .meta { font-size: 13.5px; color: var(--text-muted); font-variant-numeric: tabular-nums; }
/* 文件体积：文件名下面单独一行（比尺寸那行浅一档，它是辅助信息） */
.item .size { font-size: 13.5px; color: var(--text-faint); font-variant-numeric: tabular-nums; }
.item .meta .down { color: var(--ok); }
/* 右边改了设置，卡片上这行当场跟着变：「1600 × 1200 → 800 × 600」。
   箭头后面那截用主色加粗 —— 它才是「这一改会发生什么」。 */
.item .meta .to { color: var(--accent); font-weight: 700; }
.item .meta .bad, .item .meta .bad * { color: var(--err); }
.item .res {
  font-size: 13.5px; color: var(--text-muted); font-variant-numeric: tabular-nums;
  border-top: 1px dashed var(--border); padding-top: 7px;
}
.item .res b { color: var(--ok); }
.item .res .warn { color: var(--err); }
.item .ops { display: flex; gap: 6px; margin-top: auto; }
/* 正在预览的那一张（裁剪页点卡片换预览）：描一圈主色的边 */
.item.on { box-shadow: 0 0 0 2px var(--accent), var(--shadow); cursor: pointer; }
.item .thumb { cursor: pointer; }
.item .ops button { padding: 6px 11px; font-size: 14px; }
.item .ops .dl { color: var(--accent); border-color: var(--accent); }
.item .ops .dl:hover { background: var(--accent); color: #fff; }

.status { margin: 14px 0 0; font-size: 14.5px; color: var(--text-muted); }
.status.err { color: var(--err); }
.empty { color: var(--text-muted); font-size: 15px; }

/* 「刚处理完什么」那条：一条就够，不必再摆一张结果卡片 */
.result {
  display: flex; flex-wrap: wrap; gap: 8px 12px; align-items: center;
  margin-top: 16px; padding: 13px 16px; border-radius: var(--radius);
  background: var(--accent-soft); font-size: 14.5px;
}
.result .nm { font-weight: 600; }
.result .meta { color: var(--text-muted); flex: 1 1 260px; }
.result .meta b { color: var(--text); }
.result .stale { color: var(--warn); font-size: 13.5px; }
.result button { padding: 6px 13px; font-size: 14px; background: var(--bg-elevated); }

/* ---------- 广告位 ----------
   位置和尺寸对着 iLoveIMG 的横幅来：工具页最下面、页脚正上方，一条 970×90
   居中横幅；窄屏收成 320×100。现在放的是占位框（本站不接广告脚本）。
   要接 Google AdSense：
   ① 在各页 <head> 里加 <script async src=".../adsbygoogle.js?client=ca-pub-XXXX">；
   ② 把下面这个 div 换成
      <ins class="adsbygoogle" style="display:block" data-ad-client="ca-pub-XXXX"
           data-ad-slot="XXXX" data-ad-format="horizontal"></ins> 并 push({})。 */
.adslot {
  display: flex; align-items: center; justify-content: center;
  width: 100%; max-width: 970px; height: 90px;
  margin: 26px auto 0; padding: 0 8px;
  border: 1px dashed var(--border-strong); border-radius: var(--radius-sm);
  color: var(--text-faint); font-size: 13px; letter-spacing: .1em;
}
.adslot span { pointer-events: none; }
/* 加进文件之后广告位挪到工作区顶部，间距也要跟着翻过来 */
.adslot--top { margin: 0 auto 20px; }
@media (max-width: 760px) {
  .adslot { max-width: 320px; height: 100px; }
}

/* ---------- 细页脚 ---------- */
/* 它是 body 的直接子元素，宽度 100% 就够整幅 —— 原来那条
   `calc(50% - 50vw)` + `100vw` 的「破框」写法把滚动条宽度也算进去，
   整页会横向溢出十几个像素（toolSkill 里记过这个坑，实测定罪到它）。 */
.page-foot {
  margin: 26px 0 0; width: 100%; box-sizing: border-box;
  padding: 18px 24px; background: var(--bg-elevated);
  border-top: 1px solid var(--border);
  font-size: 14px; color: var(--text-faint); text-align: center;
}
.page-foot a { color: var(--text-muted); }

/* ---------- 档位卡片（压缩页的三档 + 大小那栏） ---------- */
.levels { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.levels label {
  display: flex; align-items: center; gap: 10px; cursor: pointer;
  padding: 9px 12px; border-radius: var(--radius-sm);
  border: 1px solid var(--border-strong); background: var(--bg-elevated);
  transition: border-color .12s, background .12s;
}
.levels label:hover { border-color: var(--accent); }
.levels input[type="radio"] { accent-color: var(--accent); margin: 0; flex: none; }
.levels .lv { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1 1 auto; }
.levels .lvt { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.levels .lv b { font-size: 15px; font-weight: 600; }
.levels .lv em { font-style: normal; font-size: 13px; color: var(--text-muted); }
.levels .sz { flex: none; font-size: 13px; color: var(--text-faint); font-variant-numeric: tabular-nums; text-align: right; }
.levels input:checked ~ .sz { color: var(--accent); font-weight: 600; }
.levels .sz.warn, .levels input:checked ~ .sz.warn { color: var(--err); }
.levels label:has(input:checked) { border-color: var(--accent); background: var(--accent-soft); }

/* ---------- 页签（切方法用） ---------- */
.tabs { display: flex; gap: 6px; }
.tabs button {
  flex: 1 1 0; font: inherit; font-size: 13.5px; cursor: pointer;
  padding: 7px 4px; line-height: 1.3; white-space: nowrap;
  background: var(--bg-sunken); color: var(--text-muted);
  border: 1px solid transparent; border-radius: var(--radius-sm);
  transition: background .12s, color .12s, border-color .12s;
}
/* 页签上带了图标的话，图标和文字排一行 —— 不写这条，SVG 没有宽高属性，
   在 flex 容器里会撑成一整块（实测：图标变成一百多像素，整个面板都顶歪了） */
.tabs button { display: inline-flex; align-items: center; justify-content: center; gap: 6px; }
.tabs button svg { width: 16px; height: 16px; flex: none; }
.tabs button:hover { color: var(--text); }
.tabs button[aria-pressed="true"] {
  background: var(--accent-soft); color: var(--accent); font-weight: 600;
  border-color: color-mix(in srgb, var(--accent) 35%, transparent);
}

/* 「怎么塞进这个尺寸」那三颗（批量裁剪页）：标签是四个字，侧栏 259px 一行
   排不下三颗带图标的页签 —— 让它换行，别把最后一颗挤出屏幕。 */
#cbFit { flex-wrap: wrap; }

/* 一排小圆钮（比例、预设尺寸这类） */
.chiprow { display: flex; flex-wrap: wrap; gap: 6px; }
.chiprow button { padding: 6px 11px; font-size: 13.5px; line-height: 1.4; }

/* 九宫格：选「裁哪一块」（批量裁剪页）。纯色方块，选中的那块染色 ——
   不画箭头或人脸，摆了九个人也认不出哪个是哪个，位置本身就是意思。 */
.anchor { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; width: 104px; }
.anchor button {
  aspect-ratio: 1; padding: 0; cursor: pointer;
  background: var(--bg-sunken); border: 1px solid var(--border-strong);
  border-radius: 5px; transition: background .12s, border-color .12s;
}
.anchor button:hover { border-color: var(--accent); }
.anchor button[aria-pressed="true"] {
  background: var(--accent); border-color: var(--accent);
  box-shadow: inset 0 0 0 2px var(--bg-elevated);
}

/* 一行勾选框 */
.perm { display: flex; flex-wrap: wrap; gap: 6px 14px; }
.perm label { display: flex; align-items: center; gap: 6px; font-size: 14.5px; cursor: pointer; white-space: nowrap; }
.perm input[type="checkbox"], .perm input[type="radio"] { accent-color: var(--accent); margin: 0; }

/* =====================================================================
   画布类页面（裁剪 / 修图 / 抠图 / 人脸模糊 / 加水印）共用的舞台
   ===================================================================== */
/* 舞台限高：一张竖版大图按适应宽度画出来能有一千多像素高，不限高的话
   工具栏会被顶到屏幕外，摆一样东西要来回滚。限高之后画布在框里自己滚。
   78vh 是量出来的：抠图和修图都是「盯着边缘看」的活，预览面积给足，
   工具栏（60px 顶栏 + 一条工具条）之后剩下的高度基本都给它。 */
.stage-wrap {
  position: relative; margin-bottom: 16px;
  max-height: 78vh; overflow: auto; scrollbar-gutter: stable;
  display: flex; justify-content: center;
}
.stage {
  position: relative; margin: 0 auto;
  background: var(--bg-elevated); border-radius: var(--radius);
  box-shadow: var(--shadow-lg); overflow: hidden; line-height: 0;
  align-self: flex-start;
  /* 棋盘格：抠图那页的透明底靠它看出来 */
  background-image:
    linear-gradient(45deg, var(--checker) 25%, transparent 25%, transparent 75%, var(--checker) 75%),
    linear-gradient(45deg, var(--checker) 25%, transparent 25%, transparent 75%, var(--checker) 75%);
  background-size: 16px 16px; background-position: 0 0, 8px 8px;
}
.stage canvas { display: block; max-width: 100%; height: auto; touch-action: none; }
.stage.busy { opacity: .55; }
.stage .hintline {
  position: absolute; left: 0; right: 0; top: 0; padding: 8px 12px;
  font: 500 12.5px/1.4 var(--sans); color: var(--text-muted);
  background: color-mix(in srgb, var(--bg-elevated) 85%, transparent);
  pointer-events: none;
}
/* 覆盖层：画布上面那一层，裁剪框、人脸框、笔刷光标都摆在这里。
   **它本身不吃指针事件**（pointer-events:none）—— 抠图、画框这些页面
   的拖拽是画布自己在监听；层里那些要拖的东西（框、把手）再单独打开。
   忘了这条的后果：画布上的 pointerdown 永远收不到，笔刷像死了一样。 */
.overlay { position: absolute; inset: 0; line-height: 1.4; pointer-events: none; }
.overlay .cropbox, .overlay .facebox, .overlay .cmp-handle { pointer-events: auto; }

/* 工具条（画布页顶部那一排按钮） */
.toolbar {
  display: flex; flex-wrap: wrap; gap: 14px 20px; align-items: flex-end;
  background: var(--bg-elevated); border-radius: var(--radius);
  box-shadow: var(--shadow); padding: 12px 15px; margin-bottom: 14px;
}
.toolbar .group { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
/* 分组标题原来是一行很淡的小灰字，扫过去根本看不见 —— 压深、加粗，
   它才是「这一排按钮是干什么的」那句话。 */
.toolbar .group > span { font-size: 13.5px; font-weight: 600; color: var(--text); }
.toolbar .btns { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
.toolbar .btns button { display: inline-flex; align-items: center; gap: 6px; padding: 8px 13px; font-size: 14px; white-space: nowrap; }
.toolbar .btns button svg { width: 16px; height: 16px; display: block; }
/* 「怎么抠」那一组是这一步的主开关：给它一条分界线，页签也做大一号 */
.toolbar .group--how { padding-right: 18px; border-right: 1px solid var(--border); }
/* 页签上的图标要和文字排一行、留一点缝 */
.tabs--big button {
  font-size: 15px; padding: 9px 16px;
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
}
.tabs--big button svg { width: 17px; height: 17px; flex: none; }
.tabs--big { gap: 8px; }
.toolbar .grow { flex: 1 1 auto; }
/* 工具条上的文件名（单张压缩页那颗）：一行显示完，长了就省略号。
   名字里本来就有括弧和空格，一折行就和旁边的按钮分成两行，
   「这张图」和这个名字就分家了。 */
.toolbar .filetag {
  max-width: 44ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.side .toolbar { flex-direction: column; align-items: stretch; gap: 14px; background: none; box-shadow: none; padding: 0; margin: 0 0 4px; }
.side .toolbar .group { width: 100%; }
.side .toolbar .btns button { flex: 1 1 auto; justify-content: center; }

/* 编辑器那七个工具：侧栏只有 260px 宽，横着一排七个按钮每个都塞不下，
   排成四列两行 —— 字不折行，也点得准。
   每格只有五十来像素宽，图标和文字横着排就要挤出去，所以竖着摞：
   图标在上、两个字在下（像工具盘那样，也省宽度）。 */
#edTools { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px; }
#edTools button { flex: none; flex-direction: column; gap: 3px; padding: 6px 2px; }
#edTools button svg { width: 17px; height: 17px; }

/* 画布上的缩放/状态角标 */
.stageinfo {
  position: absolute; right: 10px; bottom: 10px; z-index: 3;
  padding: 3px 9px; border-radius: 99px;
  background: color-mix(in srgb, var(--bg-elevated) 88%, transparent);
  color: var(--text-muted); font: 500 11.5px/1.6 var(--sans);
  font-variant-numeric: tabular-nums; pointer-events: none;
}

/* ---------- 裁剪框（裁剪 / 修图两页共用） ---------- */
.cropbox {
  position: absolute; cursor: move; touch-action: none;
  outline: 1px solid rgba(255,255,255,.9);
  box-shadow: 0 0 0 9999px rgba(20,20,22,.45);
}
.cropbox .thirds { position: absolute; inset: 0; pointer-events: none; }
.cropbox .thirds::before, .cropbox .thirds::after {
  content: ""; position: absolute; background: rgba(255,255,255,.45);
}
.cropbox .thirds::before { left: 33.33%; right: 33.33%; top: 0; bottom: 0; border-left: 1px solid rgba(255,255,255,.45); border-right: 1px solid rgba(255,255,255,.45); background: none; }
.cropbox .thirds::after { top: 33.33%; bottom: 33.33%; left: 0; right: 0; border-top: 1px solid rgba(255,255,255,.45); border-bottom: 1px solid rgba(255,255,255,.45); background: none; }
.cropbox .hd {
  position: absolute; width: 14px; height: 14px; z-index: 2;
  background: #fff; border: 1px solid rgba(20,20,22,.5); border-radius: 3px;
  box-shadow: 0 1px 3px rgba(0,0,0,.35);
}
.cropbox .hd-nw { left: -7px; top: -7px; cursor: nwse-resize; }
.cropbox .hd-n  { left: 50%; top: -7px; margin-left: -7px; cursor: ns-resize; }
.cropbox .hd-ne { right: -7px; top: -7px; cursor: nesw-resize; }
.cropbox .hd-w  { left: -7px; top: 50%; margin-top: -7px; cursor: ew-resize; }
.cropbox .hd-e  { right: -7px; top: 50%; margin-top: -7px; cursor: ew-resize; }
.cropbox .hd-sw { left: -7px; bottom: -7px; cursor: nesw-resize; }
.cropbox .hd-s  { left: 50%; bottom: -7px; margin-left: -7px; cursor: ns-resize; }
.cropbox .hd-se { right: -7px; bottom: -7px; cursor: nwse-resize; }
.cropbox .size {
  /* 摆在框内左下角：摆到框外下面会和舞台右下角那枚「原尺寸 → 裁出多少」
     的角标叠在一起（两个都是黑底小胶囊，叠上去就不认识了） */
  position: absolute; left: 6px; bottom: 6px;
  padding: 2px 9px; border-radius: 99px; white-space: nowrap;
  background: rgba(20,20,22,.72); color: #fff;
  font: 500 11.5px/1.7 var(--sans); font-variant-numeric: tabular-nums;
}
/* 裁剪框在「还没画出来」的时候不显示 */
.overlay .cropbox[hidden] { display: none; }

/* ---------- 人脸框（人脸模糊页） ---------- */
.facebox {
  position: absolute; cursor: move; touch-action: none;
  border: 2px solid var(--accent); border-radius: 6px;
  background: color-mix(in srgb, var(--accent) 12%, transparent);
}
.facebox .lb {
  position: absolute; left: -2px; top: -20px; padding: 0 7px;
  background: var(--accent); color: #fff; border-radius: 5px 5px 0 0;
  font: 600 11px/1.7 var(--sans); white-space: nowrap;
}
.facebox .del {
  position: absolute; right: -9px; top: -9px; width: 18px; height: 18px;
  border-radius: 50%; border: 0; padding: 0; background: var(--accent); color: #fff;
  display: grid; place-items: center; cursor: pointer;
}
.facebox .del svg { width: 10px; height: 10px; display: block; stroke: currentColor; stroke-width: 2; fill: none; }
.facebox .rz {
  position: absolute; right: -6px; bottom: -6px; width: 12px; height: 12px;
  background: var(--accent); border: 2px solid #fff; border-radius: 3px;
  cursor: nwse-resize; box-shadow: 0 1px 3px rgba(0,0,0,.3);
}

/* 画笔模式下光标换成那个圆圈：系统的箭头光标留着会挡住落笔点 */
body.ed-brush .stage, body.ed-brush .stage canvas { cursor: none; }

/* =====================================================================
   抠图页的对比视图：上层画布 + 可拖的分割线
   ===================================================================== */
/* 结果画布压在原图上，靠 clip-path 只露右边那截（对比模式的开关）。
   **它不吃指针事件**：点选、取色、笔刷都是底下那张 canvas 在处理，
   这层要是收事件，所有点击都会被它截胡（踩过一次：点哪儿都没反应）。 */
.stage-top { position: absolute; left: 0; top: 0; pointer-events: none; }
/* 分割线：一条白线 + 一个圆手柄，两只箭头。手柄要够大够好抓（44px），
   但线本身只有 3px —— 和参考站那种「一条线一个圆」一个意思 */
.cmp-handle {
  position: absolute; top: 0; bottom: 0; width: 3px; margin-left: -1.5px;
  background: #fff; box-shadow: 0 0 0 1px rgba(20,20,22,.28);
  cursor: ew-resize; pointer-events: auto; z-index: 4;
}
.cmp-handle::after {
  content: ""; position: absolute; left: 50%; top: 50%;
  width: 44px; height: 44px; margin: -22px 0 0 -22px;
  border-radius: 50%; background: #fff;
  box-shadow: 0 2px 10px rgba(20,20,22,.35), 0 0 0 1px rgba(20,20,22,.12);
}
.cmp-handle .arw {
  position: absolute; top: 50%; margin-top: -9px; z-index: 1;
  font: 700 13px/1 var(--sans); color: var(--text-muted);
}
.cmp-handle .arw:first-of-type { left: -34px; }
.cmp-handle .arw:last-of-type { right: -34px; }
.cmp-handle:focus-visible { outline: none; }
.cmp-handle:focus-visible::after { box-shadow: 0 0 0 3px var(--accent), 0 2px 10px rgba(20,20,22,.35); }

/* 点选主体 / 按颜色时在图上留的记号：一个白圈红心的小点 */
/* 第一次打开时的指路牌：浮在画面下方，告诉人「在图上点一下」。
   要点：**pointer-events: none** —— 它盖在画布上，吃指针的话用户就点不动画布了
   （这个坑在 .overlay 上踩过一次）。图里那只手会一下一下地戳，比纯文字更容易懂。 */
.firstcue {
  position: absolute; left: 50%; bottom: 20px; transform: translateX(-50%);
  display: flex; align-items: center; gap: 12px;
  max-width: min(94%, 560px); padding: 11px 18px 11px 14px;
  border-radius: 14px;
  background: color-mix(in srgb, var(--bg-elevated) 94%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 45%, transparent);
  box-shadow: var(--shadow-lg);
  pointer-events: none; z-index: 6;
  animation: cue-in .24s ease-out;
}
.firstcue__hand { font-size: 26px; line-height: 1; animation: cue-tap 1.6s ease-in-out infinite; }
.firstcue__t { min-width: 0; font-size: 14px; line-height: 1.5; color: var(--text-muted); }
.firstcue__t b { display: block; font-size: 16px; color: var(--heading); margin-bottom: 1px; }
@keyframes cue-in { from { opacity: 0; transform: translate(-50%, 8px); } }
@keyframes cue-tap { 0%, 100% { transform: translateY(0); } 45% { transform: translateY(-7px); } }

#rbMarks { position: absolute; inset: 0; pointer-events: none; }
#rbMarks .mark {
  position: absolute; width: 16px; height: 16px; margin: -8px 0 0 -8px;
  border-radius: 50%; border: 2px solid #fff; background: #d93025;
  box-shadow: 0 1px 4px rgba(0,0,0,.4);
}
#rbMarks .mark--pick { background: var(--accent); }

/* 点下去到「认出来」之间的等待标记：转着圈的环 + 一圈圈荡开的光晕。
   为什么要有它：第一次点要先让模型「读懂」这张图（一两秒起，第一次还得
   先把模型取回来），这期间画布上什么都没有的话，人只会以为没点上，
   然后一下一下地戳。
   动画只用 transform（转、扩散）—— 它由合成器管，主线程被推理占住的
   时候照样转；要是写成改 border-color 那种，主线程一忙就定住了，
   等于没动画。 */
#rbMarks .mark--busy {
  width: 26px; height: 26px; margin: -13px 0 0 -13px;
  /* 底下垫一层暗色：照片有亮有暗，环得在两种底上都看得清。
     浅色轨道 + 深蓝的转动段，深色照片上白的那截显眼，
     浅色照片上蓝的那截显眼。 */
  background: rgba(16, 18, 22, .38);
  border: 3px solid rgba(255, 255, 255, .62);
  border-top-color: var(--accent);
  box-shadow: 0 1px 6px rgba(0, 0, 0, .4);
  animation: mark-spin .9s linear infinite;
  will-change: transform;
}
#rbMarks .mark--busy::after {
  content: ''; position: absolute; inset: -3px;
  border-radius: 50%;
  border: 2px solid color-mix(in srgb, var(--accent) 85%, transparent);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .5);
  animation: mark-ripple 1.4s ease-out infinite;
}
@keyframes mark-spin { to { transform: rotate(360deg); } }
@keyframes mark-ripple {
  0%   { transform: scale(.7); opacity: .9; }
  100% { transform: scale(2.1); opacity: 0; }
}

/* ---------- 画笔光标（抠图 / 修图） ---------- */
.brush-cursor {
  position: absolute; border-radius: 50%; pointer-events: none; z-index: 5;
  border: 1.5px solid rgba(255,255,255,.95);
  box-shadow: 0 0 0 1px rgba(20,20,22,.55) inset, 0 0 0 1px rgba(20,20,22,.55);
  transform: translate(-50%, -50%);
}

.linkbtn {
  border: 0; background: none; padding: 0; color: var(--accent);
  font: inherit; text-decoration: underline; cursor: pointer;
}
.linkbtn:hover { color: var(--accent-hover); }


/* =====================================================================
   抠图页侧栏里的「按刚点的那几处重来一遍」
   =====================================================================
   它是这一栏里唯一的**动作**（其余都是设置项），之前跟滑杆长一个样
   —— 白底灰边，夹在说明文字中间，没人会注意到它。现在按「次级动作」
   处理：描边用主色、字用主色加粗，hover 才填实。
   另外「还没点过任何一处」的时候它是灰的：点完第一下才亮起来，
   亮起来这个动作本身就是提示。 */
#rbAgain {
  display: flex; align-items: center; justify-content: center; gap: 7px;
  width: 100%; padding: 9px 12px;
  border-color: var(--accent); color: var(--accent); font-weight: 600;
}
#rbAgain:hover:not(:disabled) { background: var(--accent); color: #fff; }
#rbAgain:disabled {
  border-color: var(--border-strong); color: var(--text-muted);
  font-weight: 400; opacity: 1;
}
/* 图标是站点那套自绘 SVG（icons.js 的 ui('redo')），15px 正好压在字前面 */
#rbAgain svg { width: 15px; height: 15px; flex: none; }

/* =====================================================================
   抠图页的缩略图条：一次开了好几张图，靠它来回切
   ===================================================================== */
.rbbar { margin: 10px 0 4px; display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.rbthumbs { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.rbthumb {
  position: relative; width: 64px; height: 64px; padding: 0; flex: none;
  border-radius: 10px; overflow: hidden; cursor: pointer;
  border: 2px solid var(--border-strong); background: var(--bg-sunken);
  display: grid; place-items: center;
}
.rbthumb canvas, .rbthumb img { max-width: 100%; max-height: 100%; display: block; }
.rbthumb:hover { border-color: var(--accent); }
.rbthumb.on { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-soft); }
/* 抠过的图右上角点一个小蓝点：一眼看出哪几张已经动过手 */
.rbthumb.done::after {
  content: ""; position: absolute; right: 4px; top: 4px; width: 9px; height: 9px;
  border-radius: 50%; background: var(--accent); border: 1.5px solid #fff;
}
.rbthumb .x {
  position: absolute; right: 0; top: 0; width: 18px; height: 18px; line-height: 16px;
  font-size: 13px; color: #fff; background: rgba(20,20,22,.55);
  border-bottom-left-radius: 8px; opacity: 0; transition: opacity .12s;
}
.rbthumb:hover .x { opacity: 1; }
.rbthumb .x:hover { background: var(--err); }
.rbthumb--add {
  border-style: dashed; color: var(--text-muted); font-size: 22px;
  background: var(--bg-elevated);
}
.rbthumb--add:hover { color: var(--accent); }

/* 侧栏底下那两个按钮：主按钮在上，打包在下面一行（侧栏只有 260 宽） */
.side__foot .zipbtn { width: 100%; margin-top: 8px; }

/* ---------- 引擎状态条（要联网取模型的两页） ---------- */
.engine {
  display: flex; flex-direction: column; gap: 8px;
  margin: 16px 0 0; padding: 12px 15px;
  background: var(--bg-elevated); border-radius: var(--radius);
  box-shadow: var(--shadow); font-size: 14.5px;
}
.engine__text { color: var(--text-muted); overflow-wrap: anywhere; }
.engine--busy .engine__text { color: var(--text); }
.engine--ok { background: var(--ok-soft); }
.engine--ok .engine__text { color: var(--ok); font-weight: 600; }
.engine--bad { background: var(--err-soft); }
.engine--bad .engine__text { color: var(--err); font-weight: 600; }
.engine__bar { height: 6px; border-radius: 99px; overflow: hidden; background: var(--bg-sunken); }
.engine__bar i { display: block; height: 100%; width: 0; background: var(--accent); border-radius: 99px; transition: width .18s linear; }
.engine button { align-self: flex-start; }

/* ---------- 小件 ---------- */
.swatchrow { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.swatchrow .lab { font-size: 13px; color: var(--text-muted); }
.swatch {
  width: 24px; height: 24px; padding: 0; border-radius: 6px;
  border: 2px solid transparent; box-shadow: inset 0 0 0 1px rgba(0,0,0,.12); cursor: pointer;
}
.swatch[aria-pressed="true"] { border-color: var(--accent); }
.badge-inline {
  display: inline-block; font-size: 12px; font-weight: 600; padding: 1px 7px;
  border-radius: 99px; background: var(--bg-sunken); color: var(--text-muted);
  margin-left: 6px; vertical-align: 1px;
}
/* 侧栏里那几行「这个工具做不到什么」：不是卡片，是一行小字 */
.limits { margin: 14px 0 0; padding: 12px 14px; border-radius: var(--radius-sm); background: var(--bg-sunken); }
.limits b { display: block; font-size: 13.5px; margin-bottom: 6px; color: var(--text); }
.limits ul { margin: 0; padding-left: 18px; }
.limits li { font-size: 13px; color: var(--text-muted); line-height: 1.6; }

/* 画布页的「还没选文件」和别的页共用 .welcome；这一句是它下面那行补充 */
/* 每个工具页顶上那枚小徽章：「100% 私有 & 本地处理」。
   照 privatepdf.io 工具页顶上那枚（100% PRIVATE & LOCAL）做的 ——
   淡靛蓝底 + 靛蓝字 + 全圆角 + 一颗会呼吸的小圆点，压在标题上面。
   html-to-image 那页没有 .welcome 包着，徽章直接放在 h1 前面，
   所以这条不挂在 .welcome 下面。 */
.pgbadge {
  display: inline-flex; align-items: center; gap: 8px;
  margin: 0 0 18px; padding: 6px 13px 6px 11px;
  border-radius: 999px;
  background: var(--accent-soft); color: var(--accent);
  border: 1px solid color-mix(in srgb, var(--accent) 20%, transparent);
  font-size: 13px; font-weight: 700; letter-spacing: .01em;
  white-space: nowrap;
}
.pgbadge i {
  position: relative; width: 7px; height: 7px; border-radius: 50%;
  background: currentColor; flex: none;
}
/* 荡开的那圈：只用 transform/opacity，主线程忙的时候也照转 */
.pgbadge i::after {
  content: ''; position: absolute; inset: 0; border-radius: 50%;
  background: currentColor; animation: pgbadge-ping 1.9s cubic-bezier(0, 0, .2, 1) infinite;
}
@keyframes pgbadge-ping {
  0%        { transform: scale(1);   opacity: .55; }
  70%, 100% { transform: scale(2.6); opacity: 0; }
}
/* HTML 转图片那页的 h1 在 .workarea 里直接排，徽章跟着它居中 */
.workarea > .pgbadge { display: flex; width: fit-content; margin: 0 auto 18px; }

.welcome .sub { font-size: 14px; color: var(--text-faint); margin-top: 6px; }

/* =====================================================================
   工具页底下那两屏（assets/site/tool-info.js 插进来的）
   =====================================================================
   第一屏「怎么用」：左边一句导语 + 三步，右边一张功能要点卡。
   第二屏「还想做点别的」：最相关的三件工具。
   两屏都在广告位下面、页脚上面，宽度不跟着侧栏缩（它们在 .tool 外面）。
   ---------- */
.toolinfo { border-top: 1px solid var(--border); padding: 62px 0 66px; }
.toolinfo__in {
  max-width: 1080px; margin: 0 auto; padding: 0 26px;
  display: flex; gap: 54px; align-items: flex-start;
}
.toolinfo__how { flex: 1 1 auto; min-width: 0; }
.toolinfo h2 {
  font-size: 28px; font-weight: 800; letter-spacing: -.02em;
  line-height: 1.25; margin: 0 0 16px;
}
.toolinfo__lede {
  font-size: 17px; line-height: 1.8; color: var(--text-muted);
  margin: 0 0 34px; text-wrap: pretty;
}

.howsteps { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 26px; }
.howsteps li { display: flex; gap: 16px; }
/* 序号用圆圈，和 hero 那份清单一个路数；主色淡底 + 主色字 */
.howsteps__n {
  width: 34px; height: 34px; flex: none; border-radius: 50%;
  background: var(--accent-soft); color: var(--accent);
  display: grid; place-items: center;
  font-size: 16px; font-weight: 800; font-variant-numeric: tabular-nums;
}
.howsteps__b { min-width: 0; padding-top: 3px; }
.howsteps__b b { display: block; font-size: 17px; margin-bottom: 5px; }
.howsteps__b p { margin: 0; font-size: 14.5px; line-height: 1.7; color: var(--text-muted); }

.toolinfo__feats {
  flex: 0 0 372px; padding: 26px 28px 28px;
  background: var(--bg-elevated); border: 1px solid var(--border);
  border-radius: var(--radius-card); box-shadow: var(--shadow);
}
.toolinfo__feats h3 { font-size: 17.5px; font-weight: 800; margin: 0 0 20px; }
.toolinfo__feats ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 17px; }
.toolinfo__feats li { display: flex; gap: 11px; font-size: 14px; line-height: 1.7; color: var(--text-muted); }
/* 绿勾用 --ok（这份表里那支绿；首页的 styles.css 里叫 --local，同一个意思）。
   注意别写成 --local —— 这份表里没有那个名字，var() 会失效、颜色悄悄回退成
   正文色，勾就成了一团深灰（踩过）。
   勾那一笔用页面底色挖空 —— 浅色主题下是白勾、暗色下是深勾，
   不用按主题写两份图标。 */
.toolinfo__feats svg { width: 19px; height: 19px; flex: none; color: var(--ok); margin-top: 2px; }
.toolinfo__feats svg circle { fill: currentColor; }
.toolinfo__feats svg path { stroke: var(--bg-elevated); }
.toolinfo__feats b { color: var(--text); font-weight: 700; }

/* ---------- 第二屏：最相关的三件工具 ---------- */
/* 底色比整页亮一档（暗色下就是深一档）：翻到这里像换了一屏，
   和上面「工具本体」在视觉上分家。 */
.moretools {
  border-top: 1px solid var(--border);
  background: var(--bg-elevated); padding: 58px 0 68px;
}
.moretools__in { max-width: 1080px; margin: 0 auto; padding: 0 26px; }
/* 标题在左、去全站列表的链接在右，一行排开 */
.moretools__head {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 20px; flex-wrap: wrap; margin-bottom: 30px;
}
.moretools h2 { font-size: 27px; font-weight: 800; letter-spacing: -.02em; margin: 0 0 10px; }
.moretools__sub { font-size: 15px; color: var(--text-muted); margin: 0; }
.moretools__all {
  display: inline-flex; align-items: center; gap: 7px; flex: none;
  font-size: 14px; font-weight: 600; color: var(--accent); padding-bottom: 2px;
}
.moretools__all svg { width: 16px; height: 16px; transition: transform .14s; }
.moretools__all:hover svg { transform: translateX(3px); }
.moretools__grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
/* 每张卡就是一整块可点的区域：图标 + 名字 + 一句说明 + 右边一个箭头 */
.mtcard {
  display: flex; align-items: center; gap: 13px;
  padding: 17px 18px; border-radius: var(--radius);
  background: var(--bg); border: 1px solid var(--border);
  color: inherit; transition: border-color .14s, box-shadow .14s, transform .14s;
}
.mtcard:hover {
  color: inherit; border-color: var(--accent);
  box-shadow: 0 6px 20px rgba(22, 22, 22, .09); transform: translateY(-2px);
}
.mtcard__ic {
  width: 40px; height: 40px; flex: none; border-radius: 11px;
  display: grid; place-items: center;
  background: color-mix(in srgb, var(--tile, var(--accent)) 12%, transparent);
  color: var(--tile, var(--accent));
}
.mtcard__ic svg { width: 21px; height: 21px; }
.mtcard__b { min-width: 0; flex: 1 1 auto; }
.mtcard__b b { display: block; font-size: 15px; font-weight: 700; color: var(--heading); margin-bottom: 3px; }
.mtcard__b span { display: block; font-size: 13px; line-height: 1.55; color: var(--text-muted); }
.mtcard__go { flex: none; color: var(--text-faint); transition: color .14s, transform .14s; }
.mtcard__go svg { width: 17px; height: 17px; display: block; }
.mtcard:hover .mtcard__go { color: var(--accent); transform: translateX(3px); }

/* ---------- 窄屏 ---------- */
@media (max-width: 900px) {
  .tool { flex-direction: column; min-height: 0; }
  .workarea { padding: 18px 16px 0; }
  .side {
    width: auto; flex: none; border-left: 0;
    position: static; align-self: stretch;
    height: auto; overflow: visible;
    border-top: 1px solid var(--border); padding: 18px 16px 22px;
  }
  h1 { font-size: 28px; }
  h1 .h1ic svg { width: 28px; height: 28px; }
  .lede { font-size: 15.5px; }
  .stage-wrap { max-height: 56vh; }
  /* 底下那两屏：要点卡挪到正文下面，相关工具并成一列 */
  .toolinfo { padding: 42px 0 46px; }
  .toolinfo__in { flex-direction: column; gap: 30px; padding: 0 16px; }
  .toolinfo h2, .moretools h2 { font-size: 22px; }
  .toolinfo__lede { font-size: 15px; margin-bottom: 26px; }
  .toolinfo__feats { flex: none; width: 100%; padding: 22px 20px 24px; }
  .moretools { padding: 42px 0 48px; }
  .moretools__in { padding: 0 16px; }
  .moretools__grid { grid-template-columns: 1fr; }
}

/* 打印：屏幕上那些操作件都不进纸里。**下面那两屏说明（怎么用 / 还想做点别的）
   也不进** —— 用户打照片的时候，PDF 里连着功能说明一起印出来了。 */
@media print {
  .drop, .panel, .side, .wstools, .toolbar, .result, .adslot, .page-foot,
  .toolinfo, .moretools { display: none; }
}



/* ---------- 加水印页：图上那个能拖/能转/能拉大小的框 ---------- */
/* 框本身不接指针（不然它会把画布的拖动挡掉），只有三个把手接 —— 
   和 .overlay 那一套一样。 */
.wmbox {
  position: absolute; pointer-events: none;
  border: 1.5px dashed rgba(255,255,255,.95);
  box-shadow: 0 0 0 1px rgba(0,0,0,.35), inset 0 0 0 1px rgba(0,0,0,.25);
  transform-origin: 50% 50%;
}
.wmbox .h {
  position: absolute; pointer-events: auto;
  width: 15px; height: 15px; border-radius: 50%;
  background: #fff; border: 1.5px solid var(--accent);
  box-shadow: 0 1px 4px rgba(0,0,0,.35);
}
/* 转角度：框上面那个圆把手（底下连一小截线，看着像「长在框上」） */
.wmbox .h-rot { left: 50%; top: -27px; margin-left: -7.5px; cursor: grab; }
.wmbox .h-rot::after {
  content: ''; position: absolute; left: 50%; top: 15px; margin-left: -1px;
  width: 2px; height: 12px; background: rgba(255,255,255,.95);
  box-shadow: 0 0 0 .5px rgba(0,0,0,.3);
}
/* 拉大小：右下角那个方块 */
.wmbox .h-scale { right: -8px; bottom: -8px; border-radius: 4px; cursor: nwse-resize; }
/* 删掉这一条：左上角那颗小叉 */
.wmbox .h-del {
  left: -9px; top: -9px; padding: 0; font-size: 11px; line-height: 1;
  display: grid; place-items: center; color: var(--err); cursor: pointer;
}
.wmbox--logo { border-style: solid; }

/* 水印列表：一条一行，选中的描主色边 */
.wmlist { display: flex; flex-direction: column; gap: 6px; }
.wmrow {
  display: flex; align-items: center; gap: 8px; cursor: pointer;
  padding: 7px 9px; border-radius: var(--radius-sm);
  border: 1px solid var(--border); background: var(--bg-elevated);
  font-size: 13.5px;
}
.wmrow:hover { border-color: var(--accent); }
.wmrow.on { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); font-weight: 600; }
.wmrow__t { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wmrow__x {
  flex: none; width: 24px; height: 24px; padding: 0; display: grid; place-items: center;
  border: 0; background: none; color: var(--text-faint); font-size: 12px;
}
.wmrow__x:hover { color: var(--err); background: var(--bg-sunken); }
#wmAnchor { width: 96px; }

/* ---------- 人脸模糊页：右边那两页签 + 「认人遮盖」 ---------- */
/* 两页签：框选遮盖 / 认人遮盖。侧栏 259px 宽，两颗正好一行。 */
#bfTabs { margin-bottom: 14px; }
#bfTabs button svg { width: 16px; height: 16px; flex: none; }

/* 参考照片：上面那张小图是**取到的那张脸**（不是原照片），
   右边一句话说明取的是哪张 —— 认错人了得一眼看得出来。 */
.whoref {
  display: flex; align-items: center; gap: 10px; margin: 8px 0 2px;
  padding: 8px; border-radius: var(--radius-sm);
  border: 1px solid var(--border); background: var(--bg-sunken);
}
.whoref img {
  flex: none; width: 56px; height: 56px; object-fit: cover;
  border-radius: var(--radius-sm); background: var(--bg-elevated);
}
.whoref span { font-size: 12.5px; line-height: 1.5; color: var(--text-muted); overflow-wrap: anywhere; }

/* 四步的进度：真是一步一步走的（认脸 → 抠脸 → 关键点摆正 → 算特征） */
.steps { list-style: none; margin: 10px 0 0; padding: 0; font-size: 13.5px; }
.steps li { position: relative; padding: 3px 0 3px 20px; color: var(--text-faint); line-height: 1.5; }
.steps li::before {
  content: ''; position: absolute; left: 4px; top: 9px;
  width: 7px; height: 7px; border-radius: 50%; background: var(--border-strong);
}
.steps li.busy { color: var(--text); font-weight: 600; }
.steps li.busy::before { background: var(--accent); animation: bfpulse 1s ease-in-out infinite; }
.steps li.done { color: var(--text-muted); }
.steps li.done::before { background: var(--ok); }
.steps li.bad { color: var(--err); font-weight: 600; }
.steps li.bad::before { background: var(--err); }
@keyframes bfpulse { 50% { opacity: .35; } }

/* 认人的结果：一张脸一行，缩略图 + 相似度 + 判成谁。点一下改判。 */
.wholist { display: flex; flex-direction: column; gap: 6px; margin-top: 10px; }
.wholist:empty { margin-top: 0; }
.whorow {
  display: flex; align-items: center; gap: 8px; width: 100%; text-align: left;
  padding: 5px 8px; border-radius: var(--radius-sm); cursor: pointer;
  border: 1px solid var(--border); background: var(--bg-elevated); font-size: 13px;
}
.whorow img { flex: none; width: 34px; height: 34px; object-fit: cover; border-radius: 5px; background: var(--bg-sunken); }
.whorow .pct { flex: none; font-weight: 700; font-variant-numeric: tabular-nums; }
.whorow .tag { flex: 1 1 auto; min-width: 0; color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.whorow .st { flex: none; font-weight: 600; color: var(--text-faint); }
.whorow.hit .pct { color: var(--accent); }
.whorow.on { border-color: color-mix(in srgb, var(--accent) 45%, transparent); background: var(--accent-soft); }
.whorow.on .st { color: var(--accent); }

/* ---------- 人脸搜索页：点卡片放大看 ---------- */
/* 浮层铺满屏幕，中间那张图按窗口大小摆；图本身在 canvas 里（位图乘了 dpr），
   框是画在图上的 —— 所以放大之后框也跟着放大，不是叠一层 DOM。 */
.bigview {
  position: fixed; inset: 0; z-index: 60;
  display: flex; align-items: center; justify-content: center;
  padding: 24px; background: rgba(24, 24, 27, .72);
  -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
}
.bigview[hidden] { display: none; }
.bigview__box {
  position: relative; max-width: 100%; max-height: 100%;
  display: flex; flex-direction: column; align-items: center; gap: 12px;
  background: var(--bg-elevated); border-radius: var(--radius);
  box-shadow: 0 18px 50px rgba(0,0,0,.4); padding: 14px;
}
.bigview__box canvas {
  display: block; max-width: 100%; max-height: 72vh;
  border-radius: var(--radius-sm); background: var(--bg-sunken);
}
.bigview__cap { max-width: 780px; font-size: 13.5px; line-height: 1.6; color: var(--text-muted); text-align: center; }
.bigview__cap b { color: var(--text); overflow-wrap: anywhere; }
.bigview__x {
  position: absolute; right: -10px; top: -10px; z-index: 1;
  width: 30px; height: 30px; padding: 0; border-radius: 50%;
  display: grid; place-items: center; font-size: 17px; line-height: 1;
  background: var(--accent); border: 0; color: #fff; cursor: pointer;
}
.bigview__x:hover { background: #432dd7; }

/* 卡片上「找到 TA」那几个字：卡片本来就窄，别让结论被挤成两行 */
#list .item .meta b { color: var(--accent); }

/* 人脸模糊页：卡片墙上「现在正在修的那张」描一圈主色 */
#list .item.sel { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: var(--radius); }
#list .item.sel .name { color: var(--accent); }

/* 图片编辑页的裁剪框：框外面压一层暗的（框本身加一圈巨大的外阴影，
   被 .stage 的 overflow:hidden 裁在画布里）。
   只给编辑页用 —— 单张裁剪那页的观感已经定过，不动它。 */
[data-img-page="editor"] .cropbox { box-shadow: 0 0 0 9999px rgba(24, 24, 27, .45); }

/* 水印页「加一条」那两颗（文字 / 图片 logo）：两列等宽。
   原来是 .inline 的 space-between + 内容宽度，两颗按钮一大一小、
   还看不出是能点的（用户 2026-10-07 报的）。 */
#wmAddRow { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
#wmAddRow button { justify-content: center; }

/* ---------- 照片排版打印：那张纸 ---------- */
/* 纸上的一切都按**毫米**排（.sheet 的宽高是 mm×MM 算出来的 px），
   整张再 transform 缩放到窗口里看 —— 屏幕上的比例就是印出来的比例。 */
.papertop { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 0 0 10px; }
.papertop .grow { flex: 1 1 auto; }
.pager { display: inline-flex; align-items: center; gap: 6px; }
.pager button { padding: 3px 10px; font-size: 15px; line-height: 1; }
.pager span { font-size: 13.5px; font-variant-numeric: tabular-nums; color: var(--text-muted); }
.paperwrap { display: flex; justify-content: center; align-items: flex-start; overflow: hidden; }
.paperscale { transform-origin: top center; }
.sheet {
  display: grid; box-sizing: border-box; background: #fff;
  border-radius: 3px; box-shadow: 0 8px 28px rgba(0, 0, 0, .18);
}
.pcell { position: relative; overflow: hidden; border-radius: 3px; background: var(--bg-sunken); }
.pcell img { width: 100%; height: 100%; object-fit: contain; display: block; }
.pcell.cover img { object-fit: cover; }
/* 空格子：斜纹，一眼看出这儿还空着 */
.pcell.empty {
  background: repeating-linear-gradient(45deg,
    color-mix(in srgb, var(--border) 55%, transparent) 0 6px, transparent 6px 12px);
  border: 1px dashed var(--border-strong);
}
/* 点了第一张、等着换位置的那个格子 */
.pcell.picked { outline: 3px solid var(--accent); outline-offset: -3px; }
.pcell .pdel {
  position: absolute; right: 5px; top: 5px; width: 22px; height: 22px; padding: 0;
  display: grid; place-items: center; border: 0; border-radius: 50%;
  background: rgba(24, 24, 27, .62); color: #fff; font-size: 15px; line-height: 1;
  opacity: 0; transition: opacity .12s;
}
.pcell:hover .pdel, .pcell:focus-within .pdel { opacity: 1; }
.pcell .pdel:hover { background: var(--err); }
/* 第几张：左下角一枚小号（对着一页一页排的时候有用） */
.pcell .pnum {
  position: absolute; left: 5px; bottom: 5px; padding: 1px 6px; border-radius: 99px;
  background: rgba(24, 24, 27, .55); color: #fff; font: 600 11.5px/1.6 var(--sans);
  font-variant-numeric: tabular-nums;
}

/* 打印：只印那张纸（屏幕上一次只摆一页，打印区里是全部页，见 photo-print.js） */
#printArea { display: none; }
@media print {
  @page { margin: 0; }
  body { background: #fff !important; }
  /* 纸上只留排好的那几页：body 底下除了 .tool 那一坨，别的（页脚、
     「怎么用」和「还想做点别的」那两屏说明）一律不印。 */
  body > *:not(.tool) { display: none !important; }
  [data-site-nav], .welcome, .wstools, .papertop, .side, .adslot, .page-foot,
  .status, .paperwrap, .toolinfo, .moretools { display: none !important; }
  .tool, .workarea, .workspace { display: block !important; margin: 0 !important; padding: 0 !important; }
  #printArea { display: block !important; }
  #printArea .sheet {
    box-shadow: none; border-radius: 0; break-after: page; page-break-after: always;
  }
  #printArea .sheet:last-child { break-after: auto; page-break-after: auto; }
  #printArea .pdel, #printArea .pnum { display: none !important; }
  #printArea .pcell.empty { background: none; border: 0; }
}

/* ---------- 二维码生成 ---------- */
/* 首屏那个表单：和 .drop 一样的存在感，但装的是输入框不是拖放区 */
.qrform {
  width: min(620px, 100%); margin: 26px auto 0; padding: 18px;
  background: var(--bg-elevated); border-radius: var(--radius);
  box-shadow: var(--shadow-lg); text-align: left;
}
.qrform textarea {
  width: 100%; font: inherit; font-size: 15px; padding: 10px 12px; resize: vertical;
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  background: var(--bg); color: inherit;
}
.qrform .tabs { margin-bottom: 14px; }
.qrform .opt { margin-bottom: 10px; }
.qrform .opt > span { display: block; margin-bottom: 4px; }
.qrform input[type="text"] {
  width: 100%; font: inherit; font-size: 15px; padding: 9px 12px;
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  background: var(--bg); color: inherit;
}
/* 首屏那颗「生成二维码」：整宽的一颗，图标和文字居中并排 */
.qrform button.primary {
  width: 100%; margin-top: 14px;
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
}
.qrform .hint { display: block; margin-top: 10px; }

/* 生成好的码：白底卡片，扫的时候对比度高一点 */
.qrbox {
  display: inline-block; padding: 18px; background: #fff; border-radius: var(--radius);
  box-shadow: var(--shadow-lg); line-height: 0;
}
.qrbox canvas { display: block; max-width: 100%; height: auto; }

/* ---------- GIF 压缩：左右两个「正在动」的对照框 ---------- */
.gfpair { display: flex; gap: 18px; align-items: flex-start; flex-wrap: wrap; justify-content: center; }
.gffig { margin: 0; flex: 1 1 320px; max-width: 520px; }
.gfbox {
  display: flex; align-items: center; justify-content: center; min-height: 200px; max-height: 62vh;
  padding: 12px; background: var(--bg-elevated); border-radius: var(--radius);
  box-shadow: var(--shadow); overflow: hidden;
}
.gfbox img { max-width: 100%; max-height: calc(62vh - 24px); display: block; border-radius: var(--radius-sm); }
.gffig figcaption {
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
  margin-top: 8px; font-size: 13.5px; color: var(--text-muted);
}
.gffig figcaption b { color: var(--text); font-size: 14.5px; }
.gfempty {
  color: var(--text-faint); font-size: 14px; text-align: center;
  border: 2px dashed var(--border-strong); border-radius: var(--radius); padding: 44px 18px;
}

/* =====================================================================
   播放器（assets/audio/player.js 生成的结构；2026-10 改版）
   =====================================================================
   每轨一行：左边控制列（色点·轨名·独奏·静音·音量·下载），右边波形。
   走带和导出工具条在整摞波形的上面。颜色从行上的 --stem 变量来。 */
.player { margin-top: 16px; display: flex; flex-direction: column; gap: 10px; }
.player__bar {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 10px 14px; background: var(--bg-elevated);
  border-radius: var(--radius); box-shadow: var(--shadow);
}
.player__bar .grow { flex: 1 1 auto; }
.player__time { font-variant-numeric: tabular-nums; font-size: 14.5px; color: var(--text); }
.player__time i { font-style: normal; color: var(--text-faint); }
.player__master { display: inline-flex; align-items: center; gap: 7px; color: var(--text-muted); }
.player__master svg { width: 17px; height: 17px; display: block; }
.player__master input { width: 96px; }

/* 工具条右侧那组导出工具（页面塞进来的 toolbarExtra）：
   格式选择 + 下载按钮 + 「换个文件」。窄屏会整组换行。 */
.playerx { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.playerx label { display: inline-flex; align-items: center; gap: 7px; font-size: 13.5px; color: var(--text-muted); }
.playerx select { padding: 6px 10px; }
.playerx .primary {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 8px 16px; border-radius: 10px; font-size: 14.5px;
}
.playerx .primary svg { width: 16px; height: 16px; display: block; }
.playerx .again { font-size: 13.5px; }

.player__rows { position: relative; display: flex; flex-direction: column; gap: 8px; }
.prow {
  display: flex; align-items: center; gap: 12px;
  background: var(--bg-elevated); border-radius: var(--radius-sm);
  padding: 8px 12px; box-shadow: var(--shadow);
}
.prow:hover { box-shadow: var(--shadow-lg); }
.pctl { flex: 0 0 360px; display: flex; align-items: center; gap: 7px; min-width: 0; }
.pctl__dot { width: 10px; height: 10px; border-radius: 50%; background: var(--stem, var(--accent)); flex: none; }
.pctl__name {
  flex: 1 1 auto; min-width: 0; font-size: 15px; font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.pctl__name i { font-style: normal; font-weight: 400; font-size: 12.5px; color: var(--text-faint); margin-left: 6px; }
.pctl input[type="range"] { flex: 0 0 56px; width: 56px; margin: 0; accent-color: var(--stem, var(--accent)); }
.plane { flex: 1 1 auto; min-width: 0; }
.plane canvas { display: block; width: 100%; height: 56px; touch-action: none; }
/* 波形整条都可以点着走带（控制列不算） */
.prow { cursor: crosshair; }
.prow .pctl { cursor: default; }
.playhead {
  position: absolute; top: 2px; bottom: 2px; width: 2px; margin-left: -1px;
  background: var(--accent); border-radius: 2px; pointer-events: none;
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--bg-elevated) 60%, transparent);
}
@media (max-width: 900px) {
  .prow { flex-wrap: wrap; }
  .pctl { flex: 1 1 100%; }
  .plane { flex: 1 1 100%; }
  .playhead { display: none; }   /* 换行之后走带线对不上，藏掉 */
}

/* 播放器上的小圆钮（播放/循环/每轨的 S、M、下载） */
.pb {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  padding: 8px 11px; border-radius: 10px;
  background: var(--bg-elevated); border: 1px solid var(--border-strong);
}
.pb svg { width: 16px; height: 16px; display: block; }
.pb:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.pb.on { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); }
.pb--main {
  width: 46px; height: 46px; border-radius: 50%; padding: 0;
  background: var(--accent); border-color: var(--accent); color: #fff;
  box-shadow: var(--shadow);
}
.pb--main:hover:not(:disabled) { background: var(--accent-hover); border-color: var(--accent-hover); color: #fff; }
.pb--main svg { width: 20px; height: 20px; }
.pb--sm { padding: 6px 9px; font-size: 13px; font-weight: 700; min-width: 34px; }
.pb--sm svg { width: 15px; height: 15px; }
.pb--dl { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 45%, transparent); }
.pb--dl span { font-size: 13px; }
/* 「试听」开关：带文字，别用图标打哑谜（用户反馈图标按钮看不懂还多余）。
   不换行 + 不许被挤 —— 窄了会把「试听」两个字竖过来排（实测踩过） */
.pb--solo { padding: 6px 13px; font-size: 13.5px; font-weight: 600; white-space: nowrap; }
.pctl .pb { flex: none; }

/* 处理进度（工作区里那一块）：数字 + 条 + 一句在跑什么 */
.progressbox { margin-top: 16px; padding: 16px 18px; background: var(--bg-elevated); border-radius: var(--radius); box-shadow: var(--shadow); }
.progressbox__head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-bottom: 10px; }
.progressbox__head b { font-size: 15.5px; }
.progressbox__head span { font-size: 13.5px; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.progressbox__bar { height: 8px; border-radius: 99px; overflow: hidden; background: var(--bg-sunken); }
.progressbox__bar i { display: block; height: 100%; width: 0; background: linear-gradient(90deg, var(--accent), #7c3aed); border-radius: 99px; transition: width .2s linear; }
.progressbox__sub { margin-top: 8px; font-size: 13px; color: var(--text-faint); }
.progressbox__cancel { margin-top: 12px; }

/* 文件卡：选了文件还没开工时那头一行 */
.filecard {
  display: flex; align-items: center; gap: 14px; padding: 14px 16px;
  background: var(--bg-elevated); border-radius: var(--radius); box-shadow: var(--shadow);
  margin-bottom: 14px;
}
.filecard__ic {
  width: 44px; height: 44px; flex: none; border-radius: 12px;
  display: grid; place-items: center;
  background: var(--accent-soft); color: var(--accent);
}
.filecard__ic svg { width: 22px; height: 22px; }
.filecard__b { min-width: 0; flex: 1 1 auto; }
.filecard__b b { display: block; font-size: 15.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.filecard__b span { font-size: 13.5px; color: var(--text-muted); }

/* 导出条：格式 / 位深（或码率）/ 下载按钮 一行排开 */
.exportbar {
  display: flex; align-items: flex-end; gap: 16px; flex-wrap: wrap;
  margin-top: 14px; padding: 15px 17px;
  background: var(--bg-elevated); border-radius: var(--radius); box-shadow: var(--shadow);
}
.exportbar .opt { min-width: 0; }
.exportbar .grow { flex: 1 1 auto; }
.exportbar .primary { height: 44px; padding: 0 22px; border-radius: 12px; font-size: 16px; display: inline-flex; align-items: center; gap: 8px; }
.exportbar .primary svg { width: 17px; height: 17px; }
