/* pdf.css — pdftools 的 PDF 操作页共用的样式（assets/pdf/pdf.css）。

   用它的有三拨页面：
     · core.js 那 15 个操作页（图片→PDF、合并、拆分、旋转、压缩、加密、解锁、
       信息、加页码、水印、修复、提取文字、PDF→图片、提取图片、表单填写）；
     · editor.js 那 4 个可视化页（编辑、签名、涂黑、裁剪）；
     · organize.js / compare.js 两个独立页（整理页面、PDF 对比）。
   所以文件后半段是可视化编辑器和缩略图网格那几块新组件的样式。

   加载顺序固定为「本文件 → assets/site/site-nav.css」：后者在 </head> 前，
   也就是在各页自己的样式之后，同优先级下它赢 —— 和别的工具站一条规矩。

   **页面的骨架（两个状态、右侧 300px 设置栏、按钮钉在栏底）是对着 iLovePDF 的
   工具页做的**，配色和按钮形状后来换成了 iLoveIMG 那一套（见下面 :root 的注释）：
     · 还没选文件：工作区居中摆大标题 + 灰色副标题 + 一颗蓝色大按钮（「选择 PDF 文件」）
       +「或者把文件拖到这里」。这一版**没有右侧栏** —— 右栏只在选了文件之后出现。
     · 选了文件之后：工作区顶上一条工具条（圆形「+」挂数量角标、打包、清空），
       下面是文件/结果卡片；设置项在右侧栏里竖排，主操作按钮（圆角矩形蓝按钮）
       钉在栏底，和 iLovePDF 的「Merge PDF」同一个位置。
   广告位在工作区最下面（970×90 的 leaderboard，位置和尺寸都对着它量过）。

   主色是那支蓝。报错仍然是红的，所以凡是报错，文字前面都带 ⚠ 并且给底色 ——
   不能只靠颜色，色弱的人分不出蓝按钮和红字。 */

:root {
  /* 配色和按钮样式对着 iLoveIMG 来的（2026-10）：
     强调色是那支蓝 #4d90fe，正文 #33333b / 次级 #707078，卡片是
     大圆角 + 一层很软的影子（0 5px 30px，他们那一套）。红色只剩报错用 ——
     以前强调和报错都是红的，两者在一屏里分不出来。 */
  --page: #f5f5fa;      /* 整页底色：卡片靠它浮起来（iLoveIMG 同款灰） */
  --bg: #fff;           --bg-elevated: #fff;  --bg-sunken: #f5f5fa;
  --heading: #33333b;   /* 标题；和 --text 分开是为了跟入口页一个取值 */
  --text: #33333b;      --text-muted: #707078; --text-faint: #a3a3ad;
  --border: #e8e8f0;    --border-strong: #d6d6df;
  --accent: #4d90fe;    --accent-hover: #3d82f0; --accent-soft: #eaf2ff;
  --ok: #0d7a45;        --ok-soft: #e4f6ec;
  --warn: #a9660a;      --warn-soft: #fdf1dd;
  --err: #d93025;       --err-soft: #fce8e6;
  /* 「纯本地 / 需联网 / 发送数据」三种标记的颜色，和入口页那套一致 */
  --local: #0d7a45;     --local-soft: #e4f6ec;
  --cdn: #a9660a;       --cdn-soft: #fdf1dd;
  --network: #d93025;   --network-soft: #fce8e6;
  --radius: 16px;       --radius-sm: 8px; --radius-card: 20px;
  --shadow: 0 5px 30px rgba(22,22,22,.10);
  --shadow-lg: 0 8px 30px rgba(22,22,22,.18);
  --sans: -apple-system, BlinkMacSystemFont, "PingFang SC", "Noto Sans SC",
          "Hiragino Sans GB", "Microsoft YaHei", "Segoe UI", Roboto, sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --page: #101114; --bg: #1c1d21; --bg-elevated: #1c1d21; --bg-sunken: #26272c;
    --heading: #e8e9eb; --text: #e8e9eb;
    --text-muted: #9a9ba1; --text-faint: #6f7076;
    --border: #2a2b30; --border-strong: #3d3e44;
    --accent: #6aa9ff; --accent-hover: #8cbcff; --accent-soft: #16243b;
    --local: #4ecb8c; --local-soft: #12291d;
    --cdn: #e0a44e;   --cdn-soft: #2b2216;
    --network: #ef8a7a; --network-soft: #2c1a18;
    --ok: #4ecb8c; --ok-soft: #12291d;
    --warn: #e0a44e; --warn-soft: #2b2216;
    --err: #ef8a7a; --err-soft: #2c1a18;
    --shadow: 0 0 10px rgba(0,0,0,.45);
    --shadow-lg: 0 8px 24px rgba(0,0,0,.55);
  }
}
:root[data-theme="dark"] {
  --page: #101114; --bg: #1c1d21; --bg-elevated: #1c1d21; --bg-sunken: #26272c;
  --heading: #e8e9eb; --text: #e8e9eb;
  --text-muted: #9a9ba1; --text-faint: #6f7076;
  --border: #2a2b30; --border-strong: #3d3e44;
  --accent: #6aa9ff; --accent-hover: #8cbcff; --accent-soft: #16243b;
  --local: #4ecb8c; --local-soft: #12291d;
  --cdn: #e0a44e;   --cdn-soft: #2b2216;
  --network: #ef8a7a; --network-soft: #2c1a18;
  --ok: #4ecb8c; --ok-soft: #12291d;
  --warn: #e0a44e; --warn-soft: #2b2216;
  --err: #ef8a7a; --err-soft: #2c1a18;
  --shadow: 0 0 10px rgba(0,0,0,.45);
  --shadow-lg: 0 8px 24px rgba(0,0,0,.55);
}

* { box-sizing: border-box; }
/* 下面好几处靠 hidden 属性开关，而它们各自带 display:flex ——
   自定义 display 会盖掉 hidden 的 display:none，这条得压住。 */
[hidden] { display: none !important; }
/* 整页的灰底铺在 html 上、正文列居中：内容是卡片，卡片靠灰底浮起来 ——
   这是 iLovePDF 工具页最显眼的一条。 */
html { background: var(--page); overflow-x: clip; }
body {
  margin: 0; padding: 0;
  background: none; color: var(--text);
  font: 15px/1.65 var(--sans); -webkit-font-smoothing: antialiased;
}
/* 大标题前那枚图标：由 site-nav.js 按当前页的 slug 注入（页面 HTML 里不写
   SVG），颜色是分类色。让它和文字基线对齐，别把行高撑开。 */
h1 {
  margin: 10px 0 12px; font-size: 38px; font-weight: 700;
  letter-spacing: -.02em; text-align: center;
  display: flex; align-items: center; justify-content: center; gap: 12px;
}
/* 大标题前那枚图标：由 site-nav.js 按当前页的 slug 注入（22 个页面共用一份
   SVG，不在 HTML 里各写一遍），颜色是分类色。 */
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: 17px; 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);
}
button {
  font: inherit; color: inherit; cursor: pointer;
  border: 1px solid var(--border-strong); background: var(--bg-elevated);
  border-radius: var(--radius-sm); padding: 8px 15px;
  transition: background .14s, border-color .14s, opacity .14s;
}
button:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
button:disabled { opacity: .45; cursor: default; }
button.primary {
  background: var(--accent); border-color: var(--accent); color: #fff; font-weight: 600;
}
button.primary:hover:not(:disabled) { background: var(--accent-hover); border-color: var(--accent-hover); color: #fff; }
button.icon {
  padding: 5px 9px; font-size: 13px; line-height: 1.2;
}
select, input[type="number"] {
  font: inherit; color: inherit; background: var(--bg-elevated);
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  padding: 7px 10px;
}
:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* ================= 工具页骨架：工作区 + 右侧设置栏 =================
   空状态**没有右侧栏**（和 iLovePDF 一样，它的 .tool__sidebar 在没选文件时是 0×0），
   工作区占满整宽、内容居中；加了文件之后右侧栏才出现。 */
/* 左边是干活的地方（选文件 / 摆文件 / 出结果），右边 300px 是设置和主操作按钮 ——
   和 iLovePDF 一样：两栏从顶栏下面一直拉到工作区底部，灰底衬白卡。
   空状态和有文件状态共用这两个容器，只是里面换内容。 */
.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;
  /* 设置栏钉在视口里：页面很长（画布、一屏卡片）时，
     设置项和主操作按钮不该跟着滚走 —— iLovePDF 的右侧栏也是全程可见的。
     内容多过一屏时栏内自己滚。 */
  position: sticky; top: 60px; align-self: flex-start;
  height: calc(100vh - 60px); overflow: hidden;
}
.side__empty {
  margin: auto 0; text-align: center; color: var(--text-faint); font-size: 13.5px;
  display: flex; flex-direction: column; gap: 6px;
}
.side__empty b { color: var(--text-muted); font-size: 15px; font-weight: 600; }
.side__panel { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
/* 设置项超过一屏时，滚的是这一块 —— 主按钮在下面钉着，永远看得见、点得到。
   负外边距是给滚动条让位：不留的话，出现滚动条时右侧的内容会被压掉几像素。 */
.side__body { flex: 1 1 auto; overflow-y: auto; min-height: 0; margin: 0 -6px; padding: 0 6px; }
.side__panel h2 {
  margin: 0 0 18px; font-size: 22px; font-weight: 700; letter-spacing: -.02em;
}
/* 设置项在窄栏里一律竖排（横着铺会把一栏撑爆） */
.side .opts { flex-direction: column; align-items: stretch; gap: 14px; }
.side .opt input[type="text"], .side .opt select, .side .opt input[type="password"],
.side .opt input[type="number"] { width: 100%; }
.side .opt .inline { justify-content: space-between; }
.side .fields { grid-template-columns: 1fr; }
/* 主操作按钮钉在栏底：不管上面有几种设置，它都在同一个位置。
   参考站（iLovePDF）原本是胶囊 + 圆圈箭头，换成 iLoveIMG 这套之后
   就是一颗干净的圆角矩形蓝按钮。 */
.side__foot { margin-top: auto; padding-top: 16px; }
.side__body + .side__foot { border-top: 1px solid var(--border); }
.side__foot .primary {
  /* iLoveIMG 的按钮是干净的圆角矩形：没有胶囊、没有圆圈箭头 */
  width: 100%; height: 56px; border-radius: 12px;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 17px; font-weight: 600; letter-spacing: .01em;
}

/* 空状态：工作区居中摆标题 + 那颗大按钮 */
.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; }
/* 「再加文件」按钮：蓝色圆角矩形主按钮 + 加号图标 + 文字。
   2026-10 从 iLovePDF 那种圆形「+」改过来 —— 圆形按钮和这一排的
   Download ZIP / Clear 不是一个形状体系，光一个加号也说不清是干嘛的。
   数字角标（列表里有几份）保留；窄屏只留图标（见文件尾的媒体查询）。 */
.addbtn {
  position: relative; flex: none;
  display: inline-flex; align-items: center; gap: 7px;
  background: var(--accent); border-color: var(--accent); color: #fff;
  font-weight: 600; padding: 8px 14px 8px 11px;
}
.addbtn:hover:not(:disabled) { background: var(--accent-hover); border-color: var(--accent-hover); color: #fff; }
.addbtn .aic { display: block; width: 16px; height: 16px; flex: none; }
.addbtn .aic svg { display: block; width: 16px; height: 16px; }
.addbtn .n {
  position: absolute; right: -6px; top: -7px; min-width: 21px; height: 21px;
  padding: 0 5px; border-radius: 999px; background: var(--bg-elevated);
  border: 2px solid var(--accent); color: var(--accent);
  font-size: 11px; font-weight: 700; display: grid; place-items: center;
  font-variant-numeric: tabular-nums;
}

/* ---------- 拖放区 ---------- */
/* 上传区不是一个大虚线框，而是一颗居中的大按钮 + 一行小字 ——
   和 iLovePDF 一样。整块区域都是投放目标（点它、往里拖、粘图片都行），
   拖动经过时用虚线光晕提示「可以放这儿」。 */
.drop {
  display: flex; flex-direction: column; align-items: center; gap: 14px;
  padding: 12px 20px 34px; margin: 0 auto 20px; max-width: 760px;
  cursor: pointer; text-align: center;
  border-radius: 16px; outline-offset: 10px;
  transition: background .15s;
}
.drop.over { outline: 2px dashed var(--accent); background: var(--accent-soft); }
.drop__btn {
  display: inline-block; padding: 22px 46px; border-radius: 12px;
  background: var(--accent); color: #fff;
  font-size: 22px; font-weight: 600; letter-spacing: .01em;
  box-shadow: 0 3px 6px rgba(0, 0, 0, .14);
  transition: background .14s, box-shadow .14s, transform .14s;
}
.drop:hover .drop__btn, .drop.over .drop__btn {
  background: var(--accent-hover);
  box-shadow: 0 5px 12px rgba(0, 0, 0, .18);
}
.drop__sub { color: var(--text-muted); font-size: 14px; }
.drop__sub kbd { font-size: .92em; }

/* ---------- 设置面板 ---------- */
.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: 12px; color: var(--text-muted); }
.opt .inline { display: flex; align-items: center; gap: 8px; }
.opt input[type="number"] { width: 92px; }
.opt input[type="range"] { width: 150px; accent-color: var(--accent); }
.opt .qval { font-variant-numeric: tabular-nums; min-width: 3.2em; font-size: 13px; }
.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;
}
.actions {
  display: flex; flex-wrap: wrap; gap: 10px; align-items: center;
  margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--border);
}
.actions .grow { flex: 1 1 auto; }
.hint { font-size: 12.5px; color: var(--text-muted); }
.hint.err { color: var(--err); }

/* ---------- 结果 ---------- */
.grid { display: grid; gap: 16px; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); }
.item {
  display: flex; flex-direction: column; gap: 9px; padding: 12px;
  background: var(--bg-elevated); border-radius: var(--radius); box-shadow: var(--shadow);
}
/* 棋盘格衬底：PNG / WebP 的透明区域得能看出来，白底上会以为是白的 */
.thumb {
  aspect-ratio: 3 / 4; display: grid; place-items: center; overflow: hidden;
  border-radius: var(--radius-sm); background-color: var(--bg-sunken);
  background-image:
    linear-gradient(45deg, rgba(127,127,127,.16) 25%, transparent 25%, transparent 75%, rgba(127,127,127,.16) 75%),
    linear-gradient(45deg, rgba(127,127,127,.16) 25%, transparent 25%, transparent 75%, rgba(127,127,127,.16) 75%);
  background-size: 16px 16px; background-position: 0 0, 8px 8px;
}
/* 首页预览：一小张「纸」，描一道细边、落一点影，和白底卡片分得开 */
.thumb img {
  max-width: 100%; max-height: 100%; display: block;
  border-radius: 3px; box-shadow: 0 1px 4px rgba(16,17,20,.18);
}
.item .name {
  font-size: 13px; font-weight: 600; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap;
}
.item .meta { font-size: 12px; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.item .meta .down { color: var(--ok); }
.item .meta .bad { color: var(--err); }
.item button { padding: 6px 10px; font-size: 13px; }

.status { margin: 14px 0 0; font-size: 13.5px; color: var(--text-muted); }
.status.err { color: var(--err); }
.empty { color: var(--text-muted); font-size: 14px; }
/* 广告位下面原来有一张「说明卡片」（.notes：本工具做不到什么、有什么代价）。
   2026-10 整块去掉了 —— 一屏里既说「文件不上传」（页脚也写着）、又把每条边界
   再列一遍，信息过载。那些话没有消失，只是搬到了真正用得上的地方：文件读进来
   时侧栏那行提示（core.js 的 HINT）、结果卡片上的说明、出错时的那句话。
   这里留个记号，免得以后有人照着旧版页面把 .notes 又加回来。 */

/* 广告位：位置和尺寸对着 iLovePDF 的 leaderboard 来 ——
   工具页最下面、页脚正上方，一条 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: 12px; letter-spacing: .1em;
}
.adslot span { pointer-events: none; }
/* 加进文件之后广告位挪到工作区顶部，间距也要跟着翻过来 */
.adslot--top { margin: 0 auto 20px; }
@media (max-width: 760px) {
  .adslot { max-width: 320px; height: 100px; }
}

/* ================= 广告位下面那两屏（guide.js 渲染） =================
   对着 privatepdf.io 的工具页做的：先教怎么用（三步骤 + 功能点），
   再摆一排最相关的工具把人留住。整幅宽铺在 .tool 下面 —— 不进工作区那一栏，
   那边右边还飘着 300px 设置栏，正文挤在旁边很别扭。 */
.guide { padding: 8px 26px 48px; }
.guide__wrap { max-width: 1080px; margin: 0 auto; }
.guide__how {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 400px);
  gap: 56px; align-items: start; padding: 34px 0 6px;
}
.guide h2 {
  margin: 0 0 14px; font-size: 28px; font-weight: 700;
  letter-spacing: -.02em; color: var(--heading);
}
.guide__lede {
  margin: 0 0 30px; max-width: 46ch; text-wrap: pretty;
  font-size: 15.5px; line-height: 1.75; color: var(--text-muted);
}

/* 三步骤：编号圆点 + 标题 + 一句说明 */
.gsteps { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 24px; }
.gstep { display: flex; gap: 14px; }
.gstep__n {
  flex: none; width: 34px; height: 34px; border-radius: 50%;
  background: var(--accent-soft); color: var(--accent);
  display: grid; place-items: center; font-size: 15px; font-weight: 700;
}
.gstep__b b { display: block; margin-bottom: 3px; font-size: 16px; color: var(--heading); }
.gstep__b p { margin: 0; font-size: 14.5px; line-height: 1.65; color: var(--text-muted); }

/* 功能点：一张卡，四行「小标题 + 说明」，前面一个绿勾 */
.gfeats {
  background: var(--bg-elevated); border: 1px solid var(--border);
  border-radius: var(--radius-card); padding: 24px 24px 20px;
  box-shadow: var(--shadow);
}
.gfeats h3 { margin: 0 0 16px; font-size: 17px; color: var(--heading); }
.gfeats ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 14px; }
.gfeats li { display: flex; gap: 10px; }
.gfeats li p { margin: 0; font-size: 14px; line-height: 1.6; color: var(--text-muted); }
.gfeats li b { color: var(--heading); }
/* 勾用「纯本地」那个绿：这一站的好消息一律是绿的，红只留给「不对」 */
.gfeat__ck { flex: none; margin-top: 1px; }
.gfeat__ck svg { display: block; width: 18px; height: 18px; color: var(--local); }

/* 下一屏：一排相关工具 */
.guide__more { margin-top: 54px; text-align: center; }
.guide__more h2 { margin-bottom: 8px; }
.guide__sub { margin: 0 0 24px; font-size: 14px; color: var(--text-faint); }
.gcards {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 14px; text-align: left;
}
.gcard {
  display: flex; gap: 12px; align-items: flex-start;
  background: var(--bg-elevated); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 16px 16px 14px;
  color: inherit; transition: border-color .14s, box-shadow .14s, transform .14s;
}
.gcard:hover {
  color: inherit; border-color: var(--accent);
  box-shadow: var(--shadow); transform: translateY(-2px);
}
.gcard__ic { flex: none; color: var(--tile, var(--text-muted)); }
.gcard__ic svg { display: block; width: 26px; height: 26px; }
.gcard__b { min-width: 0; }
.gcard__b b { display: block; font-size: 15px; color: var(--heading); }
.gcard__b p {
  margin: 4px 0 0; font-size: 13px; line-height: 1.55; color: var(--text-muted);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}

@media (max-width: 980px) {
  .guide__how { grid-template-columns: 1fr; gap: 34px; padding-top: 26px; }
  .guide__lede { max-width: none; }
  .gcards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 620px) {
  .guide { padding: 8px 16px 38px; }
  .guide h2 { font-size: 23px; }
  .gcards { grid-template-columns: 1fr; }
}

/* 细页脚：整行铺满的一条浅色带，只有一行字 —— 和 iLovePDF 一样。
   它本来就是 body 的直接子元素（不在任何居中的列里），所以不用「负外边距 + 100vw」
   那套破框技巧 —— 那套会让元素比可视宽多出一个滚动条的宽度（实测 1429 vs 1440），
   横向多出 11px。 */
.page-foot {
  margin: 0; width: 100%;
  padding: 18px 24px; background: var(--bg-elevated);
  border-top: 1px solid var(--border);
  font-size: 12.5px; color: var(--text-faint); text-align: center;
}
.page-foot a { color: var(--text-muted); }

/* ---------- 密码框：左边一把锁 + 右边一个红方块眼睛 ---------- */
/* 和 iLovePDF 的 Protect 页同一个样子：输入框通栏，左端一枚锁，右端一个红色方块的
   眼睛开关（点一下在密文和明文之间切）。开关是真 <button>，键盘也能按到。 */
.pw { position: relative; display: block; }
.pw input[type="password"], .pw input[type="text"] {
  width: 100%; height: 52px; font-size: 15px; color: var(--text);
  padding: 0 56px 0 44px;
}
.pw__ic {
  position: absolute; left: 14px; top: 50%; transform: translateY(-50%);
  color: var(--text-faint); pointer-events: none; display: flex;
}
.pw__ic svg { width: 20px; height: 20px; display: block; }
.pw__eye {
  position: absolute; right: 0; top: 0; bottom: 0; width: 50px; padding: 0;
  border: 0; border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  background: var(--accent); color: #fff; cursor: pointer;
  display: grid; place-items: center;
  transition: background .14s;
}
.pw__eye:hover, .pw__eye.on { background: var(--accent-hover); color: #fff; }
.pw__eye svg { width: 22px; height: 22px; display: block; }

/* ---------- 文本框与勾选框：页码、元数据、密码几页都用得到 ---------- */
/* 页码表达式、元数据、密码、水印文字都是文本框，外观跟上面那个 select 规则保持一致 */
input[type="text"], input[type="password"] {
  font: inherit; color: inherit; background: var(--bg-elevated);
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  padding: 7px 10px;
}
/* 一行摆开的勾选框（裁剪的「应用到所有页」、拆分的「合成一份」、表单字段那些） */
.perm label {
  display: flex; align-items: center; gap: 5px;
  font-size: 13px; cursor: pointer; white-space: nowrap;
}
.perm input[type="checkbox"] { accent-color: var(--accent); margin: 0; }
/* 逐页尺寸、写入了哪些字段：多行文本，一行放不下 */
.item .detail {
  font-size: 11.5px; color: var(--text-faint); line-height: 1.5;
  font-variant-numeric: tabular-nums; white-space: pre-line; overflow-wrap: anywhere;
}
/* PDF 的缩略图：我们不在本地渲染首页（那要把 pdf.js 也拉下来，为了几张小图不值得），
   所以画一张「纸」—— 白底、细边、右上角折起来，和 iLovePDF 的文件卡同一个形状。
   图片文件那一类走的是真预览（.thumb 里的 img）。 */
.thumb.doc {
  background-color: #fff; background-image: none;
  border: 1px solid var(--border);
  position: relative; color: #b9b9c2;
  font-size: 11px; font-weight: 700; letter-spacing: .12em;
}
.thumb.doc::after {
  content: ""; position: absolute; right: -1px; top: -1px;
  width: 26px; height: 26px;
  background: linear-gradient(225deg, var(--bg-sunken) 48%, transparent 50%);
  border-left: 1px solid var(--border); border-bottom: 1px solid var(--border);
}

/* =====================================================================
   可视化编辑器（editor.js：编辑 / 签名 / 涂黑 / 裁剪四页共用）
   ===================================================================== */

/* 工具栏：左列是工具按钮，右列是翻页与缩放 */
.toolbar {
  display: flex; flex-wrap: wrap; gap: 14px 22px; align-items: flex-end;
  background: var(--bg-elevated); border-radius: var(--radius);
  box-shadow: var(--shadow); padding: 14px 16px; margin-bottom: 14px;
}
.toolbar .group { display: flex; flex-direction: column; gap: 6px; }
.toolbar .group > span { font-size: 12px; color: var(--text-muted); }
.toolbar .btns { display: flex; gap: 6px; flex-wrap: wrap; }
.toolbar .btns button[aria-pressed="true"] {
  background: var(--accent-soft); border-color: var(--accent); color: var(--accent); font-weight: 600;
}
.toolbar .pager { display: flex; align-items: center; gap: 6px; font-size: 13px; }
.toolbar .pager .num { font-variant-numeric: tabular-nums; min-width: 5.5em; text-align: center; }

/* 舞台：页面画布居中，上面浮着可拖拽的覆盖层 */
/* 舞台限高：A4 竖版按「适应宽度」画出来有 1400px 高，不限高的话工具栏和属性栏
   会被顶到屏幕外，摆一样东西要来回滚。限高之后画布在框里自己滚。
   scrollbar-gutter: stable 让滚动条的位置永远留着 —— 不留的话，
   有没有滚动条会让 clientWidth 差十几像素，fit 宽度跟着变，画布高度在临界点上
   会来回抖。 */
.stage-wrap {
  position: relative; margin-bottom: 18px;
  max-height: 74vh; overflow: auto; scrollbar-gutter: stable;
}
.stage {
  position: relative; margin: 0 auto; max-width: 100%;
  background: var(--bg-elevated); border-radius: var(--radius);
  box-shadow: var(--shadow-lg); overflow: hidden; line-height: 0;
}
.stage canvas { display: block; max-width: 100%; height: auto; }
.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;
}
.overlay { position: absolute; inset: 0; line-height: 1.4; }

/* 覆盖层里的一件东西：文本框 / 图片 / 色块。selected 才显示边角和手柄 */
.ov-item {
  position: absolute; cursor: move; user-select: none;
  outline: 1px solid color-mix(in srgb, var(--accent) 55%, transparent);
  outline-offset: 0;
}
.ov-item.selected { outline: 2px solid var(--accent); }
.ov-item .cap {
  position: absolute; left: 0; top: -20px; padding: 1px 6px; border-radius: 5px 5px 0 0;
  background: var(--accent); color: #fff; font: 500 11px/1.5 var(--sans);
  white-space: nowrap; display: none;
}
.ov-item.selected .cap { display: block; }
/* 右上角那个「删掉这一处」：里面的叉是 SVG 画的 —— 用「×」这个字符，
   不同系统上的基线和字重都不一样，塞进小圆里永远是歪的（用户报回来的就是这个）。 */
.ov-item .del {
  position: absolute; right: -10px; top: -10px; width: 20px; height: 20px;
  border-radius: 50%; border: 0; padding: 0; background: var(--accent); color: #fff;
  display: none; place-items: center; cursor: pointer;
  box-shadow: 0 1px 4px rgba(16,17,20,.35);
  transition: background .12s, transform .12s;
}
.ov-item .del:hover { background: var(--accent-hover); transform: scale(1.08); }
.ov-item .del svg {
  width: 11px; height: 11px; display: block;
  stroke: currentColor; stroke-width: 1.9; stroke-linecap: round; fill: none;
}
.ov-item.selected .del { display: grid; }

/* 缩放把手：上下左右四条边各一个，加右下角一个（右下角两个方向一起调）。
   以前只有右下角那一个 —— 想「只调高一点」做不到，宽度会跟着变。 */
.ov-item .rz {
  position: absolute; display: none; background: var(--accent);
  border: 2px solid var(--bg-elevated); border-radius: 3px;
  box-shadow: 0 1px 4px rgba(16,17,20,.3);
}
.ov-item.selected .rz { display: block; }
.ov-item .rz-n, .ov-item .rz-s { left: 50%; width: 18px; height: 10px; margin-left: -9px; cursor: ns-resize; }
.ov-item .rz-n { top: -6px; }
.ov-item .rz-s { bottom: -6px; }
.ov-item .rz-w, .ov-item .rz-e { top: 50%; width: 10px; height: 18px; margin-top: -9px; cursor: ew-resize; }
.ov-item .rz-w { left: -6px; }
.ov-item .rz-e { right: -6px; }
.ov-item .rz-se { right: -6px; bottom: -6px; width: 12px; height: 12px; cursor: nwse-resize; }

/* 小框（.tiny，由 editor.js 按屏幕上的实际大小打标）：标签藏掉、叉和手柄缩一圈。
   一个 35×22 的小文本框上摆 20px 的叉加五个手柄，会把框里的字全盖住。 */
.ov-item.tiny .cap { display: none; }
.ov-item.tiny .del { width: 16px; height: 16px; right: -8px; top: -8px; }
.ov-item.tiny .del svg { width: 9px; height: 9px; }
.ov-item.tiny .rz-n, .ov-item.tiny .rz-s { width: 14px; height: 8px; margin-left: -7px; }
.ov-item.tiny .rz-n { top: -4px; }
.ov-item.tiny .rz-s { bottom: -4px; }
.ov-item.tiny .rz-w, .ov-item.tiny .rz-e { width: 8px; height: 14px; margin-top: -7px; }
.ov-item.tiny .rz-w { left: -4px; }
.ov-item.tiny .rz-e { right: -4px; }
.ov-item.tiny .rz-se { width: 10px; height: 10px; right: -4px; bottom: -4px; }
.ov-item .txt { width: 100%; height: 100%; overflow: hidden; white-space: pre-wrap; }
.ov-item img { width: 100%; height: 100%; display: block; pointer-events: none; }
/* 涂黑框内部就是纯黑，白块是纯白：两种都用同一个 .box，只是颜色不同 */
.ov-item .box { width: 100%; height: 100%; }

/* =====================================================================
   表单填写（forms.js）：输入框直接盖在纸面上
   ===================================================================== */
/* 控件按「这一页」分组：一次全建好，换页只是把那一组显示出来 ——
   换页不重建，上一页填的字也不会丢。 */
.ffpage { position: absolute; inset: 0; display: none; }
.ffpage.on { display: block; }
/* 盖在纸上的输入框：白纸上的红框，一眼看得出哪儿能填。
   字体、颜色写死不跟主题走 —— 底下那张纸永远是白的。 */
.ff {
  position: absolute; margin: 0; padding: 0 3px; box-sizing: border-box;
  border: 1px solid color-mix(in srgb, var(--accent) 45%, transparent);
  border-radius: 2px; background: rgba(77, 144, 254, .08);
  color: #111; font: 13px/1.2 var(--sans);
  min-width: 8px; min-height: 8px;
}
.ff:hover { border-color: var(--accent); }
.ff:focus {
  background: rgba(255, 255, 255, .96); border-color: var(--accent);
  outline: 2px solid color-mix(in srgb, var(--accent) 35%, transparent); outline-offset: 0;
}
.ff:disabled { border-style: dashed; background: rgba(20, 20, 22, .07); cursor: not-allowed; }
.ff-check, .ff-radio {
  padding: 0; accent-color: var(--accent); background: rgba(77, 144, 254, .08);
}
.ff-check { appearance: auto; }
.ff-choice { padding: 0 2px; }
/* 没有可填字段的那句话：摆在工作区里（原来在侧栏） */
.ffempty {
  margin: 0 0 18px; padding: 14px 16px; border-radius: var(--radius);
  background: var(--bg-elevated); box-shadow: var(--shadow);
  font-size: 14px; color: var(--text-muted);
}

/* 裁剪页：整页压暗，只留中间那个亮框 */
.overlay.crop { background: rgba(20,20,22,.45); }
.overlay.crop .ov-item { outline: 2px dashed #fff; box-shadow: 0 0 0 9999px rgba(20,20,22,.45); }
.overlay.crop .ov-item.selected { outline-style: solid; }

/* 右侧属性栏：选中一件东西后才出现 */
.props {
  display: flex; flex-wrap: wrap; gap: 14px 22px; align-items: flex-end;
  background: var(--bg-elevated); border-radius: var(--radius);
  box-shadow: var(--shadow); padding: 14px 16px; margin-bottom: 14px;
}
.props .row { display: flex; flex-wrap: wrap; gap: 14px 22px; align-items: flex-end; width: 100%; }

/* 编辑器那几页：工具条和属性栏在 300px 的侧栏里要竖着排
   （它们本来是横着铺满整页的，直接塞进侧栏会挤成一团） */
.side .toolbar, .side .props {
  flex-direction: column; align-items: stretch; gap: 16px;
  background: none; box-shadow: none; padding: 0; margin: 0 0 4px;
}
.side .toolbar .group, .side .props .row { width: 100%; flex-direction: column; align-items: stretch; gap: 10px; }
.side .toolbar .btns { flex-wrap: wrap; }
.side .toolbar .pager { flex-wrap: wrap; }
.side .props .hint { display: block; }

/* ---------- 签名板 ---------- */
.sig-pad {
  position: relative; background: var(--bg-elevated); border-radius: var(--radius);
  box-shadow: var(--shadow); padding: 12px; margin-bottom: 14px;
}
.sig-pad canvas {
  display: block; width: 100%; height: 180px; touch-action: none; cursor: crosshair;
  background:
    linear-gradient(var(--bg-sunken), var(--bg-sunken)) padding-box,
    repeating-linear-gradient(0deg, transparent 0 44px, var(--border) 44px 45px) border-box;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
}
.sig-pad .padbar { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-top: 10px; }
.sig-pad .padbar .grow { flex: 1 1 auto; }
/* 那条虚线是「签名该压着它写」的基线：锚在画布上，不锚在工具栏的底部 ——
   工具栏多一行（姓名 / 日期 / 图章那一排），线就跑到别处去了。 */
.sig-pad .padcv { position: relative; }
.sig-pad .base {
  position: absolute; left: 10px; right: 10px; bottom: 34px;
  border-bottom: 1px dashed var(--border-strong);
  pointer-events: none;
}
/* 姓名 / 首字母 / 日期 / 图章那一排：和上面那排同高，标签在输入框左边 */
.sig-pad .padinfo label {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 13px; color: var(--text-muted);
}
.sig-pad .padinfo input[type="text"], .sig-pad .padinfo input[type="date"] {
  width: auto; padding: 5px 8px; font-size: 13px;
}
.sig-pad .padinfo select { width: auto; padding: 4px 6px; font-size: 12.5px; }

/* ================= 签名页：空状态下的入口 + 侧栏那一块 =================
   签名板是弹层（见下），所以空状态那一屏和侧栏各放一个「设置签名」的按钮，
   状态文字三处同步（sign-pdf.html 的 setState）。 */
.sigstart {
  display: flex; align-items: center; justify-content: center; gap: 12px;
  flex-wrap: wrap; margin: 0 auto 16px;
}
.sigstart .hint { margin: 0; }
.signblock {
  display: flex; flex-direction: column; gap: 12px;
  padding-bottom: 16px; margin-bottom: 16px;
  border-bottom: 1px solid var(--border);
}
.signrow { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.signrow .hint { margin: 0; }
.signblock .opt { display: flex; flex-direction: column; align-items: stretch; gap: 5px; }
.signblock .opt > span { font-size: 13px; color: var(--text-muted); }
.signblock .opt input[type="text"], .signblock .opt input[type="date"],
.signblock .opt select { width: 100%; padding: 7px 9px; font-size: 13.5px; }

/* ================= 设置签名弹层里的那几块（sign-pdf.html） ================= */
/* 头像 + 姓名 + 首字母：和 iLovePDF 那个「Set your signature details」同一排 */
.sigid {
  display: flex; align-items: flex-end; gap: 14px; flex-wrap: wrap;
  padding-bottom: 16px; border-bottom: 1px solid var(--border);
}
.sigid__avatar {
  width: 36px; height: 36px; flex: none; border-radius: 50%;
  border: 2px solid var(--accent);
  background: var(--bg-sunken) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238f8f8f' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='12' cy='8.5' r='3.6'/%3E%3Cpath d='M4.8 20c.7-3.7 3.6-5.6 7.2-5.6s6.5 1.9 7.2 5.6'/%3E%3C/svg%3E") center / 20px no-repeat;
}
.sigid__f {
  display: flex; flex-direction: column; gap: 5px;
  flex: 1 1 240px; min-width: 0;
  font-size: 13px; color: var(--text-muted);
}
.sigid__f--i { flex: 0 1 130px; }
.sigid__f input { padding: 9px 11px; font-size: 15px; width: 100%; }

/* 三个页签：签名 / 首字母 / 图章 */
.sigtabs { display: flex; gap: 4px; margin: 16px 0 0; border-bottom: 1px solid var(--border); }
.sigtab {
  border: 0; border-bottom: 3px solid transparent; border-radius: 0;
  background: none; padding: 9px 14px; font-size: 14.5px; font-weight: 600;
  color: var(--text-muted); display: inline-flex; align-items: center; gap: 7px;
}
.sigtab:hover:not(:disabled) { color: var(--text); border-color: transparent; border-bottom-color: var(--border-strong); }
.sigtab[aria-selected="true"] { color: var(--text); border-bottom-color: var(--accent); }
.sigtab__ic { font-size: 15px; }

/* 左边那条「怎么做」的竖排小工具条 + 右边的内容区 */
.sigbody { display: flex; align-items: stretch; margin-top: 14px; }
.sigmode {
  display: flex; flex-direction: column; gap: 6px; flex: none;
  padding: 8px 7px; background: var(--bg-sunken);
  border-radius: var(--radius-sm) 0 0 var(--radius-sm);
}
.sigmode button {
  width: 38px; height: 38px; padding: 0; line-height: 1;
  display: grid; place-items: center; font-size: 17px;
  border-color: transparent; background: none;
}
.sigmode svg { width: 19px; height: 19px; display: block; }
.sigmode button[aria-pressed="true"] {
  background: var(--bg-elevated); border-color: var(--border-strong); color: var(--accent);
}
.sigpane {
  flex: 1 1 auto; min-width: 0;
  border: 1px solid var(--border); border-left: 0;
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}
/* 图章那一页没有「怎么做」那一条（只能传图），内容区自己把边框补圆 */
.sigbody--solo .sigpane { border-left: 1px solid var(--border); border-radius: var(--radius-sm); }
.sigpane__box { padding: 14px; }

/* 打字：每种字体把你的名字排一遍，选中哪个用哪个 */
.sigfonts { display: flex; flex-direction: column; max-height: 236px; overflow-y: auto; }
.sigfont {
  display: flex; align-items: center; gap: 12px;
  padding: 7px 10px; border-bottom: 1px solid var(--border); cursor: pointer;
}
.sigfont:last-child { border-bottom: 0; }
.sigfont:hover { background: var(--bg-sunken); }
.sigfont:has(input:checked) { background: var(--accent-soft); }
.sigfont input { flex: none; width: 17px; height: 17px; accent-color: var(--accent); }
.sigfont span {
  flex: 1 1 auto; min-width: 0; font-size: 26px; line-height: 1.4;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.sigfont em { flex: none; font-style: normal; font-size: 11.5px; color: var(--text-faint); }

/* 传图：点按钮或拖进来 */
.sigdrop {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 10px; min-height: 200px; margin: 14px; padding: 24px 18px;
  border: 2px dashed var(--border-strong); border-radius: var(--radius-sm); text-align: center;
}
.sigdrop.over { border-color: var(--accent); background: var(--accent-soft); }
.sigdrop__btn {
  padding: 11px 22px; font-weight: 600; border-radius: 10px;
  color: var(--accent); border-color: var(--accent); background: var(--bg-elevated);
}
.sigdrop__btn:hover:not(:disabled) { background: var(--accent); color: #fff; }
.sigdrop__hint { font-size: 13.5px; color: var(--text-muted); }
.sigdrop__fmt { font-size: 12.5px; color: var(--text-faint); }

/* 颜色：四个圆点 */
.sigcolors { display: flex; align-items: center; gap: 10px; margin-top: 14px; font-size: 13px; color: var(--text-muted); }
.sigcolors__l { margin-right: 2px; }
.sigcol {
  width: 22px; height: 22px; padding: 0; border-radius: 50%;
  border: 2px solid transparent; box-shadow: inset 0 0 0 2px var(--bg-elevated);
}
.sigcol[aria-pressed="true"] { border-color: var(--text); }

/* 设置签名那个弹层：手写要一块像样的地方，侧栏里放不下 */
.sigsheet {
  position: fixed; inset: 0; z-index: 60;
  /* 上面留出顶栏那 60px —— 顶栏是 Shadow DOM 里的一层，z-index 比这里高，
     不留出来的话弹层最上面（标题那一行）会被它盖住。 */
  padding: 74px 20px 20px;
  display: flex; align-items: center; justify-content: center;
  background: rgba(20, 20, 22, .45);
}
.sigsheet__box {
  width: min(680px, 100%); max-height: calc(100vh - 96px);
  /* 竖着排：中间那块（页签下面）自己滚，颜色和「用这个签名」钉在底下 ——
     窄屏上弹层比屏幕高时，按钮不该被挤到看不见的地方。 */
  display: flex; flex-direction: column;
  background: var(--bg-elevated); border-radius: var(--radius);
  box-shadow: var(--shadow-lg); padding: 18px 20px 20px;
}
.sigbody { flex: 1 1 auto; min-height: 0; }
.sigpane { overflow: auto; }
.sigsheet__box h3 { margin: 0 0 14px; font-size: 19px; }
.sigsheet .sig-pad { box-shadow: none; padding: 0; margin: 0; }
.sigsheet__foot { display: flex; align-items: center; gap: 12px; margin-top: 14px; flex-wrap: wrap; }
.sigsheet__foot .grow { flex: 1 1 auto; }
.sigsheet__foot .hint { margin: 0; }

/* =====================================================================
   缩略图网格（organize.js 整理页面）
   ===================================================================== */
.pages {
  display: grid; gap: 14px;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  margin-bottom: 18px;
}
.pcard {
  position: relative; background: var(--bg-elevated); border-radius: var(--radius);
  box-shadow: var(--shadow); padding: 8px; display: flex; flex-direction: column; gap: 6px;
  transition: box-shadow .14s, transform .14s, opacity .14s;
}
/* 拖动中：网格里留一个虚线空位（落点在哪儿一眼看得出），手里那张看 .ghost */
.pcard.dragging {
  opacity: .35; box-shadow: none;
  outline: 2px dashed var(--border-strong); outline-offset: -2px;
}
.pcard.over { box-shadow: 0 0 0 2px var(--accent), var(--shadow-lg); }
.pcard.gone { opacity: .38; }
/* 跟着指针走的那张虚影：克隆一份卡片本体，fixed 定位，位置由 JS 每帧写 transform。
   稍微转一点点 + 大一点的影子 —— 看着像「手里拿着的一张纸」。
   z-index 和站点弹层同一层（60）：要盖在卡片和广告位上面，但不必压过顶栏。 */
.pcard.ghost {
  position: fixed; left: 0; top: 0; z-index: 60; margin: 0;
  pointer-events: none; opacity: .96;
  rotate: -1.6deg;
  box-shadow: var(--shadow-lg);
  /* 卡片本体那套 `transition: ... transform .14s` 是给「实时换位」用的，
     克隆过来的虚影不能要：它一插进 DOM 就在 (0,0)，第一帧从那儿过渡到指针
     位置，看着就是「卡片从左上角飞过来」。松手那一下的飞行是 JS 里临时
     写 inline transition 的，不受这条影响。 */
  transition: none;
}
/* 拖着的时候整个页面都是「抓」的手型（指针被网格捕获了，卡片上那句 cursor 不生效） */
body.dragging-card, body.dragging-card * { cursor: grabbing !important; }
.pcard .pv {
  position: relative; aspect-ratio: 3 / 4; display: grid; place-items: center;
  overflow: hidden; border-radius: var(--radius-sm); background: var(--bg-sunken);
}
.pcard .pv canvas, .pcard .pv img { max-width: 100%; max-height: 100%; display: block; }
.pcard .pv .spin {
  position: absolute; inset: auto 0 0 0; font: 500 11px/1.6 var(--sans);
  color: var(--text-muted); text-align: center; background: color-mix(in srgb, var(--bg-sunken) 80%, transparent);
}
.pcard .no {
  font-size: 12px; color: var(--text-muted); text-align: center;
  font-variant-numeric: tabular-nums;
}
.pcard .ops { display: flex; gap: 4px; justify-content: center; }
.pcard .ops button { padding: 3px 7px; font-size: 12px; line-height: 1.4; }
.pcard .grip {
  position: absolute; left: 50%; top: 12px; transform: translateX(-50%);
  padding: 1px 8px; border-radius: 99px; cursor: grab;
  background: color-mix(in srgb, var(--bg-elevated) 86%, transparent);
  color: var(--text-faint); font-size: 12px; letter-spacing: .1em;
  opacity: 0; transition: opacity .12s;
}
.pcard:hover .grip { opacity: 1; }
.pcard .flag {
  position: absolute; right: 12px; top: 12px; z-index: 1;
  font-size: 11px; font-weight: 600; padding: 1px 7px; border-radius: 99px;
  background: var(--accent); color: #fff;
}

/* =====================================================================
   合并页的文件列表（core.js 的 renderMerge）
   一行一份文件：左边抓手 + 序号 + 首页缩略图 + 文件名，右边转角度和删除。
   iLovePDF 的合并页就是这个形状 —— 顺序是这一页唯一要紧的东西，
   所以不能像别的页面那样只摆一排小卡片。
   ===================================================================== */
.mlist { display: flex; flex-direction: column; gap: 10px; margin-bottom: 18px; }
.mlist .mresult { margin-bottom: 4px; }
.mrow {
  display: flex; align-items: center; gap: 12px;
  background: var(--bg-elevated); border-radius: var(--radius);
  box-shadow: var(--shadow); padding: 10px 12px;
  cursor: grab; touch-action: none;   /* 拖动是我们自己实现的（指针），别让页面跟着滚 */
  transition: box-shadow .14s, opacity .14s;
}
.mrow:active { cursor: grabbing; }
.mrow.dragging { opacity: .45; box-shadow: var(--shadow-lg); }
.mrow .grip { flex: none; color: var(--text-faint); display: grid; place-items: center; }
.mrow .grip svg { width: 18px; height: 18px; display: block; }
.mrow .no {
  flex: none; width: 1.4em; text-align: right; font-size: 12px;
  color: var(--text-faint); font-variant-numeric: tabular-nums;
}
.mrow .mthumb {
  flex: none; width: 46px; height: 60px; border-radius: 6px; overflow: hidden;
  background: var(--bg-sunken); border: 1px solid var(--border);
  display: grid; place-items: center; font-size: 11px; color: var(--text-faint);
}
.mrow .mthumb img { max-width: 100%; max-height: 100%; display: block; }
.mrow .mname {
  flex: 1 1 auto; min-width: 0; font-size: 13.5px;
  overflow-wrap: anywhere; line-height: 1.4;
}
.mrow .mmeta { display: block; font-size: 11.5px; color: var(--text-faint); }
.mrow .flag {
  flex: none; font-size: 11px; font-weight: 600; padding: 1px 7px; border-radius: 99px;
  background: var(--accent-soft); color: var(--accent);
}
.mrow .mops { display: flex; gap: 4px; flex: none; }
.mrow .mops button {
  padding: 4px 8px; line-height: 1; display: grid; place-items: center;
}
.mrow .mops button svg { width: 15px; height: 15px; display: block; }
.mrow .mops button.danger:hover { color: var(--accent); border-color: var(--accent); }
#sortBtn { display: inline-flex; align-items: center; gap: 6px; }
#sortBtn svg { width: 15px; height: 15px; display: block; }
@media (max-width: 560px) {
  .mrow { flex-wrap: wrap; }
  .mrow .mname { flex: 1 1 100%; order: 5; }
}

/* =====================================================================
   Office 转 PDF：引擎状态条 + 「这个站点跑不了」的说明（office.js）
   这一页和别的页面不一样 —— 它得先下载一整套排版引擎，所以「现在在干什么、
   还要多久」必须在页面上看得见，不能只写在一行小字里。
   ===================================================================== */
.engine {
  display: flex; flex-direction: column; gap: 8px;
  margin: 18px 0 0; padding: 12px 15px;
  background: var(--bg-elevated); border-radius: var(--radius);
  box-shadow: var(--shadow); font-size: 13.5px;
}
.engine__text { color: var(--text-muted); overflow-wrap: anywhere; }
.engine--busy .engine__text { color: var(--text); }
.engine--ok   { background: var(--local-soft); }
.engine--ok .engine__text { color: var(--local); font-weight: 600; }
.engine--bad  { background: var(--network-soft); }
.engine--bad .engine__text { color: var(--network); 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;
}
#releaseBtn { align-self: flex-start; }

/* =====================================================================
   拆分页：切法页签 + 缩略图选页（split.js）
   ===================================================================== */
/* 三个切法并排，选中的那个是实心红字 —— 和 iLovePDF 那排 Range / Extract /
   Size 页签同一个意思：一眼看出现在是哪一种切法。 */
.tabs { display: flex; gap: 6px; }
.tabs button {
  flex: 1 1 0; font: inherit; font-size: 12.5px; cursor: pointer;
  padding: 7px 4px; line-height: 1.3;
  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;
}
.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);
}

/* 「自定义范围 / 每 N 页一份」两个单选并排；数字框就在字里行间 */
.seg { display: flex; gap: 14px; flex-wrap: wrap; }
.seg label { display: flex; align-items: center; gap: 5px; font-size: 13px; cursor: pointer; }
.seg input[type="radio"] { accent-color: var(--accent); margin: 0; }
/* 侧栏里 .side .opt input[type="number"] 是「占满一行」的写法（页边距那种一格
   一行的设置），这里这个数字框是夹在字中间的，得压回去 */
.side .seg input[type="number"] { width: 58px; }

/* ---- 范围行（拆分页的「自定义范围」）----
   一行一段「第 [a] 到 [b] 页」，左边手柄拖着换顺序，顺序就是输出顺序。
   侧栏内容宽只有 260px，所以每一格都得数着给：手柄 13 + 序号 15 + 三个字
   标签 + 两个 46px 的数字框 + 一个 22px 的 ×。类名没用 .mrow —— 那是合并页
   的宽行（带 46×60 缩略图那套），一个样式两处用迟早打架。 */
.rlist { display: flex; flex-direction: column; gap: 6px; }
.rlist:empty { display: none; }
.rrow {
  display: flex; align-items: center; gap: 5px;
  padding: 4px 6px; background: var(--bg-elevated);
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  cursor: grab; touch-action: none;   /* 拖拽靠指针事件，别让页面跟着一起滚 */
}
.rrow input { touch-action: auto; }   /* 但手指落在输入框上时还是要能滚页面 */
.rrow.dragging { border-color: var(--accent); cursor: grabbing; }
.rrow .grip { flex: 0 0 auto; display: flex; color: var(--text-faint); }
.rrow .grip svg { width: 13px; height: 13px; display: block; }
.rrow .rno {
  flex: 0 0 auto; min-width: 15px; text-align: center;
  font-size: 11px; color: var(--text-faint); font-variant-numeric: tabular-nums;
}
.rrow .rlab { flex: 0 0 auto; font-size: 12px; color: var(--text-muted); }
/* 58px 是量出来的：260px 内容宽减去手柄/序号/三个字/删除按钮和间隙，剩给两个
   数字框的就是这些 —— 再窄就装不下三位数（右边还有一排 spinner 占着十几个像素） */
.side .opt .rrow input[type="number"] {
  width: 58px; padding: 4px 2px; text-align: center;
  font-variant-numeric: tabular-nums;
}
.rrow .rdel {
  flex: 0 0 auto; margin-left: auto; width: 22px; height: 22px; padding: 0;
  font-size: 15px; line-height: 1; color: var(--text-faint);
  background: transparent; border-color: transparent;
}
.rrow .rdel:hover:not(:disabled) { color: var(--err); border-color: var(--err); }
/* 要的页超出这份 PDF：这一行现在切不出来。只染个色加个悬停说明 ——
   值不改（悄悄改用户填的数最糟），真到切的时候 jobSplit 还会报一次正经的错 */
.rrow.bad { border-color: var(--err); }
.rrow.bad .rnum { color: var(--err); }
/* 「＋ 添加范围」：一颗描边小按钮 */
.rangadd {
  align-self: center; margin-top: 2px; padding: 6px 16px; font-size: 12.5px;
  color: var(--accent); background: transparent;
  border: 1px solid color-mix(in srgb, var(--accent) 45%, transparent);
  border-radius: 10px;
}
.rangadd:hover:not(:disabled) { background: var(--accent-soft); }

/* 「将生成 N 个文件」——拆分页上最该看清的一句话，给它一点重量 */
#planState { font-weight: 600; color: var(--text); }
#planState:empty { display: none; }
/* 「压缩后约 1.2 MB」——压缩页上最该看清的一句话，同理 */
#cmpEst { font-weight: 600; color: var(--accent); }
#cmpEst:empty { display: none; }

/* 压缩档位那四张卡片：对着 iLovePDF 的 option__select__item 做 ——
   整行可点、选中的那张用主色描边 + 淡底，右边那一列是这一档压完的大小。 */
.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: 13.5px; font-weight: 600; }
.levels .lv em { font-style: normal; font-size: 11.5px; color: var(--text-muted); }
.levels .sz {
  flex: none; font-size: 12px; 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 { color: var(--err); }
.levels input:checked ~ .sz.warn { color: var(--err); }
.levels label:has(input:checked) {
  border-color: var(--accent); background: var(--accent-soft);
}

/* 选页：滚进视野才画的缩略图。和整理页那套 .pcard 是一回事，但这里的卡片
   只干一件事 —— 点一下选中、再点一下取消，没有拖拽也没有操作按钮。 */
.pickbox { margin-bottom: 18px; }
.pickbar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 10px; }
.pickbar .hint { margin: 0; }
.pickbar .grow { flex: 1 1 auto; }
.pickbar button { padding: 5px 12px; font-size: 12.5px; }
/* 「每行 N 页」：和旁边两个按钮同高同字号，比侧栏那套小一号 */
.pickbar select { width: auto; padding: 4px 6px; font-size: 12.5px; }
.pickbar .pgcols {
  display: flex; align-items: center; gap: 4px;
  font-size: 12.5px; color: var(--text-muted);
}
/* 一行几页由上面那个选择器定（split.js 把 --pcols 写在 #pgrid 的行内样式上），
   4 是拿不到它时的兜底 —— 原来的 auto-fill 在宽屏上一行能挤下十几张，小到看不清。
   minmax 的下限写 0 而不是 auto：画布的 min-content 会把格子撑到缩不回去。 */
.pgrid {
  display: grid; gap: 10px;
  grid-template-columns: repeat(var(--pcols, 4), minmax(0, 1fr));
  /* 列数少了别把卡片撑成半屏 —— 说到底它是个缩略图，一页铺满 500px 只是空。
     这里收窄的是网格本身（不是画布），画布照着格子画，格子多大图就多大，正好。
     左对齐，和上面的工具条、文件卡、提示语一条线。 */
  max-width: calc(var(--pcols, 4) * 320px + (var(--pcols, 4) - 1) * 10px);
}
/* 窄屏不看这个设置：4 列在手机上每格只剩 70px，看也看不清 —— 回到按宽度自适应。
   那个「每行几页」也一起收起来，省得上面写着 4、下面其实是 3 列。
   得写在上面那条后面（同特异性，靠源顺序取胜）。 */
@media (max-width: 620px) {
  .pgrid { grid-template-columns: repeat(auto-fill, minmax(94px, 1fr)); }
  .pickbar .pgcols { display: none; }
}
.pg {
  position: relative; font: inherit; cursor: pointer; padding: 5px;
  background: var(--bg-elevated); border-radius: var(--radius-sm);
  border: 2px solid transparent; box-shadow: var(--shadow);
  display: flex; flex-direction: column; gap: 3px;
  transition: border-color .12s, transform .12s;
}
.pg:hover { transform: translateY(-1px); border-color: var(--border-strong); }
.pg .pv {
  position: relative; aspect-ratio: 3 / 4; display: grid; place-items: center;
  overflow: hidden; border-radius: 4px; background: var(--bg-sunken);
}
/* 画布总是撑满格子，图本身按原比例居中（object-fit）—— 早先写死 max-width /
   max-height 时，浏览器缩放在卡片上放大，画布还停在旧尺寸上不跟着长。位图按多大
   画是 split.js 的事（按格子宽度），这里只管把它摆对。 */
.pg .pv canvas { width: 100%; height: 100%; object-fit: contain; display: block; }
.pg .pv .spin {
  position: absolute; inset: auto 0 0 0; text-align: center; font-size: 11px;
  color: var(--text-faint); background: color-mix(in srgb, var(--bg-sunken) 80%, transparent);
}
.pg .no {
  font-size: 11px; color: var(--text-faint); text-align: center;
  font-variant-numeric: tabular-nums;
}
.pg.on { border-color: var(--accent); }
.pg.on .no { color: var(--accent); font-weight: 600; }
/* 角上是「落在第几段」而不是一个勾：一段出一份文件（不勾合成时），
   这个数字就是它进第几个文件 —— 和侧栏第几行范围是同一套编号 */
.pg .tick {
  position: absolute; right: 7px; top: 7px; z-index: 1;
  min-width: 18px; height: 18px; padding: 0 5px; border-radius: 99px;
  background: var(--accent); color: #fff;
  font-size: 11px; font-weight: 600; line-height: 18px; text-align: center;
  font-variant-numeric: tabular-nums;
}

/* =====================================================================
   水印页的效果预览（watermark.js）
   ===================================================================== */
/* 预览的卡片只给人看，点不动 —— 拆分的选页器那张卡片是能点的，这里不是。
   认 .pickbox--view 这个类，不要认 #pagesBox：两个页面的壳是同一个 id。 */
.pickbox--view .pg { cursor: default; }
.pickbox--view .pg:hover { transform: none; border-color: transparent; }
/* 盖在缩略图上那一层。位置和大小由 watermark.js 按 pt→px 算好写进来的：
   宽度跟着缩略图里那张图的实际显示尺寸走（object-fit: contain 之后的那块）。 */
.pg .wmov { position: absolute; pointer-events: none; z-index: 1; }
/* 不在「盖哪几页」范围里的页：整张压暗 + 角上一个标记 —— 一眼看得出哪几页没盖 */
.pg.off .pv { opacity: .35; }
.pg .wkhit {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); z-index: 2;
  padding: 2px 8px; border-radius: 99px; white-space: nowrap;
  background: var(--bg-elevated); color: var(--text-muted);
  border: 1px solid var(--border-strong);
  font-size: 11px;
}

/* =====================================================================
   PDF 对比（compare.js）
   ===================================================================== */
.cmp-pair { display: grid; gap: 14px; grid-template-columns: 1fr 1fr; margin-bottom: 14px; }
@media (max-width: 720px) { .cmp-pair { grid-template-columns: 1fr; } }
/* 对比页的两个选择区：和上传区一个样子（白卡片 + 红按钮），
   只是并排两个 —— 一边 A 一边 B。 */
.cmp-side {
  position: relative; cursor: pointer; text-align: center;
  background: var(--bg-elevated); border-radius: var(--radius); box-shadow: var(--shadow);
  padding: 20px 16px 18px; font-size: 13px;
  border: 2px dashed transparent;
  transition: border-color .14s, background .14s;
}
.cmp-side:hover, .cmp-side.over { border-color: var(--accent); background: var(--accent-soft); }
.cmp-side__btn {
  display: inline-block; margin-bottom: 10px; padding: 11px 26px; border-radius: 8px;
  background: var(--accent); color: #fff; font-size: 15px; font-weight: 700;
}
.cmp-side:hover .cmp-side__btn, .cmp-side.over .cmp-side__btn { background: var(--accent-hover); }
.cmp-side .nm { font-weight: 600; margin-bottom: 3px; word-break: break-all; }
.cmp-side .mt { color: var(--text-muted); font-size: 12px; }
.cmp-side.bad .nm { color: var(--err); }
.cmp-side #rmA, .cmp-side #rmB { position: absolute; right: 10px; top: 10px; }
.cmp-side:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.cmp-grid { display: grid; gap: 14px; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); }
.cmp-card {
  background: var(--bg-elevated); border-radius: var(--radius); box-shadow: var(--shadow);
  padding: 10px; display: flex; flex-direction: column; gap: 8px;
}
.cmp-card .pair { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
.cmp-card .pair figure { margin: 0; }
.cmp-card .pair figcaption { font-size: 11px; color: var(--text-faint); margin-bottom: 3px; }
.cmp-card .pair canvas { width: 100%; height: auto; display: block; border-radius: 6px; border: 1px solid var(--border); }
.cmp-card .verdict { font-size: 12.5px; }
.cmp-card .verdict.same { color: var(--ok); }
.cmp-card .verdict.diff { color: var(--err); font-weight: 600; }
.cmp-card .verdict.miss { color: var(--warn); }

/* =====================================================================
   表单填写（fill-forms）与其它小件
   ===================================================================== */
.fields { display: grid; gap: 12px 22px; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); }
.fields .opt input[type="text"], .fields .opt select { width: 100%; }
.fields .opt .perm { display: flex; gap: 12px; }
.badge-inline {
  display: inline-block; font-size: 11px; font-weight: 600; padding: 1px 7px;
  border-radius: 99px; background: var(--bg-sunken); color: var(--text-muted);
  margin-left: 6px; vertical-align: 1px;
}

/* 编辑器 / 整理页的「刚生成了什么」条：一条就够，不必再摆一张结果卡片 */
.result {
  display: flex; flex-wrap: wrap; gap: 4px 12px; align-items: center;
  margin-top: 14px; padding: 12px 15px; border-radius: var(--radius);
  background: var(--accent-soft); font-size: 13.5px;
}
.result .nm { font-weight: 600; }
.result .meta { color: var(--text-muted); flex: 1 1 260px; }
.result button { padding: 5px 12px; font-size: 13px; background: var(--bg-elevated); }

/* 窄屏：两栏变一栏，设置栏落到工作区下面（iLovePDF 在手机上也是这么叠的） */
@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;   /* 忘了这条的话，桌面那条 align-self:flex-start 会把它缩成一条 */
    height: auto; overflow: visible;
    border-top: 1px solid var(--border); padding: 18px 16px 22px;
  }
  .side__empty { margin: 8px 0 12px; }
}

@media print { .drop, .panel, .side, .wstools, .toolbar, .props, .result, .adslot, .page-foot { display: none; } }

/* 窄屏：再加文件按钮只留加号图标 */
@media (max-width: 560px) {
  .addbtn { padding: 8px 11px; gap: 0; }
  .addbtn .lbl { display: none; }
}
