/* 产品界面外壳样式。纸张本身的样式在 paper.css，两者不要混。
 *
 * ── 视觉系统（2026-08-27 重建）────────────────────────────────
 * 这个产品的产物是纸。界面的职责是当一张安静、精确的工作台面：
 * 纸（A4 预览）是唯一的主角，其余一切退后。由此推出整套语言——
 *
 *   色彩：无彩度的灰阶层级 + 唯一的品牌蓝。界面本身不使用第二种彩色，
 *         绿/红只作语义状态（已发布/危险），且降饱和。
 *   层级：靠字号/字重/灰度三个轴分层，不靠加框加底色。
 *   空间：区块之间优先用距离和对齐分隔；发丝线只出现在
 *         「确实需要一条物理边界」的地方（导航、面板、纸的边缘）。
 *   形状：按钮 8px 方角（2026-08-28 用户裁定弃胶囊，向现代组件库对齐：
 *         次按钮白底描边、主按钮实色，参照 shadcn/ui 的克制感）；
 *         输入类控件 8px；卡片 12px；纸接近直角（2px）——纸就是纸。
 *   投影：三档且各有含义——lift（卡片浮起）、paper（纸浮在台面上）、
 *         float（浮层）。不出现第四种。
 *   动效：只有 120~160ms 的颜色/阴影过渡和焦点环。不做入场动画。
 */

:root {
  /* 灰阶（无色相：冷静、理性，不与纸的白抢戏） */
  --bg: #f4f4f5;            /* 页面台面 */
  --bg-deep: #ececee;       /* 画布井 / 缩略图台面：比台面再深半档，纸才浮得起来 */
  --surface: #ffffff;
  --surface-2: #f4f4f5;     /* 悬停底、静默填充 */
  --border: rgba(17, 17, 20, .08);         /* 发丝线 */
  --border-strong: rgba(17, 17, 20, .16);  /* 输入框描边 */
  --text: #1a1a1e;
  --text-dim: #5d5d66;
  --text-faint: #8f8f99;

  /* 唯一的彩色。绿/红只作语义，不参与品牌表达 */
  --accent: #0a6cf5;
  --accent-deep: #0557d1;
  --accent-soft: #eef4fe;
  --danger: #d0453e;
  --danger-soft: #fdf1f0;
  --ok: #17854a;
  --ok-soft: #e9f6ee;

  --nav-h: 52px;
  --rail-w: 64px;           /* 资源区那一列竖排页签 */
  --library-w: 300px;       /* 资源区页签的内容 */
  --finder-w: 344px;        /* 右侧设置列 */
  /* 资源区开页时是开着还是收着：宽屏开着「模板」，窄一点的屏收着，把地方让给纸。
     断点只登记在 app.css 这一处，library.js 读这个值，不抄像素数。 */
  --pb-library-default: open;

  --r-ctl: 8px;             /* 输入框、面板内小件 */
  --r-card: 14px;           /* 卡片 */
  --r-pill: 980px;          /* 按钮、分段选择 */
  --radius: var(--r-ctl);   /* 旧名，个别组件还在引用 */

  --shadow-lift: 0 1px 2px rgba(17, 17, 20, .04), 0 6px 20px rgba(17, 17, 20, .06);
  --shadow-paper: 0 1px 3px rgba(17, 17, 20, .08), 0 10px 26px rgba(17, 17, 20, .07);
  --shadow-float: 0 2px 8px rgba(17, 17, 20, .08), 0 14px 36px rgba(17, 17, 20, .16);
  --shadow: var(--shadow-lift);   /* 旧名 */

  --font-ui: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Hiragino Sans',
             'Segoe UI', Roboto, sans-serif;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  background: var(--bg);
  color: var(--text);
  font: 14px/1.55 var(--font-ui);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

button, input, select, textarea { font: inherit; color: inherit; }

/* 一条顶栏 + 三栏，竖着排：三栏吃掉顶栏以外的全部高度。
   不再用 100vh 减一个写死的顶栏高——手机上顶栏折成两行，写死的数就对不上了。 */
body { display: flex; flex-direction: column; }

/* 页面自己的工具栏在 shell.js 把它收进顶栏之前不露面，免得开页时先闪一下再跳上去 */
body > [data-nav-slot] { display: none; }

::selection { background: var(--accent-soft); }

/* 键盘焦点统一一种环。鼠标点击不出环（:focus-visible 自会区分） */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ── 导航条 ─────────────────────────────────────────────────── */
.pb-nav {
  height: var(--nav-h);
  flex: none;
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 0 16px;
  background: rgba(255, 255, 255, .82);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--border);
  position: relative;
  z-index: 20;
}

.pb-nav-brand {
  font-weight: 700;
  font-size: 15px;
  letter-spacing: -.01em;
  color: var(--text);
  text-decoration: none;
}

.pb-nav-slot { flex: 1; display: flex; align-items: center; gap: 10px; min-width: 0; }

.pb-nav-lang-label { color: var(--text-faint); font-size: 12px; }

.pb-nav-lang {
  background: transparent;
  border: none;
  border-radius: var(--r-ctl);
  padding: 4px 6px;
  font-size: 12.5px;
  color: var(--text-dim);
  cursor: pointer;
}
.pb-nav-lang:hover { color: var(--text); background: var(--surface-2); }

/* ── 通用控件 ───────────────────────────────────────────────── */
/* 按钮：现代组件库式样（用户点名要这一路）——次按钮白底 + 发丝描边 + 一线投影，
   主按钮实色无边。8px 方角，36px 高。 */
.pb-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  height: 36px;
  padding: 0 14px;
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  background: var(--surface);
  color: var(--text);
  cursor: pointer;
  font-size: 13px;
  font-weight: 500;
  white-space: nowrap;
  text-decoration: none;   /* 链接元素长成按钮时不要下划线 */
  box-shadow: 0 1px 2px rgba(17, 17, 20, .05);
  transition: background-color .12s, color .12s, border-color .12s, box-shadow .15s;
}

.pb-btn:hover:not(:disabled) { background: #f7f7f8; }
.pb-btn:active:not(:disabled) { background: #f0f0f2; }
.pb-btn:disabled { opacity: .4; cursor: default; }

.pb-btn-primary {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}
.pb-btn-primary:hover:not(:disabled) { background: var(--accent-deep); border-color: var(--accent-deep); }
.pb-btn-primary:active:not(:disabled) { background: var(--accent-deep); }

.pb-btn-ghost {
  background: transparent;
  border-color: transparent;
  box-shadow: none;
  color: var(--text-dim);
  font-weight: 450;
}
.pb-btn-ghost:hover:not(:disabled) { background: var(--surface-2); color: var(--text); }

.pb-btn-danger { background: transparent; border-color: transparent; box-shadow: none; color: var(--danger); }
.pb-btn-danger:hover:not(:disabled) { background: var(--danger-soft); }

.pb-input, .pb-select, .pb-textarea {
  width: 100%;
  padding: 6px 10px;
  border: 1px solid var(--border-strong);
  border-radius: var(--r-ctl);
  background: var(--surface);
  font-size: 13px;
  transition: border-color .12s, box-shadow .12s;
}

.pb-input:focus, .pb-select:focus, .pb-textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(10, 108, 245, .13);
}

.pb-textarea { resize: vertical; min-height: 66px; line-height: 1.5; }

.pb-range { width: 100%; accent-color: var(--accent); }

.pb-color {
  width: 34px;
  height: 26px;
  padding: 2px;
  border: 1px solid var(--border-strong);
  border-radius: 6px;
  background: var(--surface);
  cursor: pointer;
}

.pb-check { display: flex; align-items: center; gap: 7px; font-size: 13px; cursor: pointer; }
.pb-check input { accent-color: var(--accent); }

/* ── 画布页：资源区 · 纸 · 设置，三栏（2026-10-24 用户裁定，Figma 式）───────── */
.pb-shell {
  flex: 1 1 auto;
  display: flex;
  min-height: 0;
}

.pb-main { flex: 1 1 auto; display: flex; flex-direction: column; min-width: 0; min-height: 0; }

/* 工具栏住在顶栏里（shell.js 把它收进 .pb-nav-slot）：顶栏只有一条，纸多出一条栏的高度。
   永远一行：换行会把「打印」挤到第二层，工具栏就不再像一件工具。
   空间不够时标题输入框先收缩（它带 flex:0 1 基准），再不够整条横滑——
   与移动端同一个模型，桌面只是极少走到滑动那一步 */
.pb-toolbar {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 7px;
  flex-wrap: nowrap;
  overflow-x: auto;
  scrollbar-width: none;
}
.pb-toolbar::-webkit-scrollbar { display: none; }
.pb-toolbar > * { flex: 0 0 auto; }

.pb-toolbar-sep { width: 1px; height: 18px; background: var(--border-strong); margin: 0 2px; }
.pb-toolbar-spacer { flex: 1 1 4px; }

/* 工具栏里的按钮走紧凑档：一行要装下撤销/重做、标题、缩放和三个动作 */
.pb-toolbar .pb-btn { height: 32px; padding: 0 11px; }

/* ── 左：资源区 ───────────────────────────────────────────────
   一列竖排页签 + 当前页签的内容（Figma 的 Assets、Canva 的左栏都是这个形状）。
   页签上一个小图标、底下一个短名字；再点一下当前页签就收起，纸那一块随之变宽。 */
.pb-library {
  flex: none;
  display: flex;
  min-height: 0;
  background: var(--surface);
  border-inline-end: 1px solid var(--border);
}

.pb-library-rail {
  flex: none;
  width: var(--rail-w);
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 10px 6px;
  overflow-y: auto;
  scrollbar-width: none;
}
.pb-library-rail::-webkit-scrollbar { display: none; }

.pb-rail-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  width: 100%;
  padding: 8px 2px 7px;
  border: 0;
  border-radius: 10px;
  background: transparent;
  color: var(--text-dim);
  font-size: 11px;
  line-height: 1.25;
  text-align: center;
  overflow-wrap: anywhere;
  cursor: pointer;
  transition: background-color .12s, color .12s;
}
/* 页签图标：图形是 assets/library-<页签>.svg，蒙版只取它的形状，颜色跟着页签的文字色走
   （与搜索框的放大镜同一套做法）。没在下面点名的页签沿用模板那一枚。 */
.pb-rail-icon {
  width: 22px;
  height: 22px;
  flex: none;
  background-color: currentColor;
  -webkit-mask: url("./assets/library-templates.svg") center / contain no-repeat;
  mask: url("./assets/library-templates.svg") center / contain no-repeat;
}
.pb-rail-btn[data-library-tab="pictures"] .pb-rail-icon {
  -webkit-mask-image: url("./assets/library-pictures.svg");
  mask-image: url("./assets/library-pictures.svg");
}
.pb-rail-btn[data-library-tab="formula"] .pb-rail-icon {
  -webkit-mask-image: url("./assets/library-formula.svg");
  mask-image: url("./assets/library-formula.svg");
}
.pb-rail-btn[data-library-tab="glyph"] .pb-rail-icon {
  -webkit-mask-image: url("./assets/library-glyph.svg");
  mask-image: url("./assets/library-glyph.svg");
}
.pb-rail-btn[data-library-tab="docs"] .pb-rail-icon {
  -webkit-mask-image: url("./assets/library-docs.svg");
  mask-image: url("./assets/library-docs.svg");
}
.pb-rail-btn:hover { background: var(--surface-2); color: var(--text); }
/* 正摆着的那一页签：品牌蓝，与「此刻摆着的那块面板」同一个语言 */
.pb-rail-btn[aria-selected="true"],
.pb-rail-btn[aria-selected="true"]:hover { background: var(--accent-soft); color: var(--accent); font-weight: 600; }
.pb-rail-label { display: block; max-width: 100%; }

.pb-library-panel {
  flex: none;
  width: var(--library-w);
  display: flex;
  flex-direction: column;
  min-height: 0;
  border-inline-start: 1px solid var(--border);
}
.pb-library-panel .pb-panel-body { flex: 1 1 auto; }

/* hidden 要真的藏得住（BUG-055 同一条）：作者样式里的 display 压过浏览器自带的 [hidden]{display:none} */
.pb-library [hidden] { display: none; }

/* ── 中：纸 ───────────────────────────────────────────────────
   画布井比台面再深半档：纸浮在上面，视线自然落到纸上。
   这一块夹在资源区与设置列中间，纸在这一块里居中。 */
.pb-canvas-wrap {
  flex: 1;
  overflow: auto;
  padding: 24px;
  display: flex;
  background: var(--bg-deep);
}

/* 居中用 margin:auto 而不是 justify-content:center——放大到比这一块还大时，
   后者会把左边那截推到滚动区外面，再也滚不回去；auto 外边距在放不下时自己变成 0。 */
#pb-canvas-space { flex: none; margin: auto; }

/* ── 右：设置 ─────────────────────────────────────────────────
   一个搜索框 + 一次一块面板（2026-10-12 的形态，2026-10-24 从纸旁边挪到右侧一列）。
   这一列自己不滚：面板再长也只在面板里滚，搜索框永远看得见，
   这一列才不会又变成一条要上下找的侧栏。 */
.pb-finder {
  flex: none;
  width: var(--finder-w);
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-height: 0;
  padding: 14px 14px 16px;
  background: var(--surface);
  border-inline-start: 1px solid var(--border);
  overflow: hidden;
}

.pb-finder-box { position: relative; flex: none; }

.pb-finder-icon {
  position: absolute;
  inset-inline-start: 13px;
  top: 13px;
  width: 16px;
  height: 16px;
  color: var(--text-faint);
  background-color: currentColor;
  -webkit-mask: url("./assets/search.svg") center / contain no-repeat;
  mask: url("./assets/search.svg") center / contain no-repeat;
  pointer-events: none;
}

/* 长得像对话框：能折行。用户把它叫作「对话框」——
   在这里说一句想调什么，而不是去翻一排控件。白色的一列上用描边，不再靠投影浮起来 */
.pb-finder-input {
  display: block;
  width: 100%;
  min-height: 46px;
  padding-block: 11px;
  padding-inline: 38px 34px;
  border: 1px solid var(--border-strong);
  border-radius: 12px;
  background: var(--surface);
  font-size: 14px;
  line-height: 1.5;
  resize: none;
  overflow: hidden;
  transition: border-color .12s, box-shadow .12s;
}
.pb-finder-input::placeholder { color: var(--text-faint); }
.pb-finder-input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(10, 108, 245, .13);
}

/* 「/」按一下就能开始打字的提示。打字时、有内容时都收起来，不跟文字挤 */
.pb-finder-kbd {
  position: absolute;
  inset-inline-end: 10px;
  top: 12px;
  min-width: 20px;
  height: 20px;
  padding: 0 5px;
  border: 1px solid var(--border-strong);
  border-radius: 5px;
  font: 11px/18px var(--font-ui);
  text-align: center;
  color: var(--text-faint);
  background: var(--surface-2);
  pointer-events: none;
}
.pb-finder-input:focus ~ .pb-finder-kbd,
.pb-finder-input:not(:placeholder-shown) ~ .pb-finder-kbd { display: none; }


/* hidden 属性要真的藏得住。作者样式里的 display（.pb-row 是 flex）压过浏览器自带的
   [hidden]{display:none}，于是「剪贴板空着时整行不出现」那颗粘贴按钮其实一直在，
   点下去什么都不发生——用例只查了 .hidden 这个属性，从没看过它是不是真的不见了（BUG-055）。
   只管这一列：别的页面（字形页的 SVG 选框）也用 hidden，全局改它会误伤。 */
.pb-finder [hidden] { display: none; }

.pb-finder-chips { flex: none; display: flex; flex-direction: column; gap: 6px; }
.pb-finder-chips:empty { display: none; }

.pb-finder-miss { margin: 0; font-size: 12.5px; line-height: 1.5; color: var(--text-dim); }

.pb-chip-row { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
/* 不许被压扁：手机上入口一行不换行，「试试」会被挤成一字一行 */
.pb-chip-label { flex: none; white-space: nowrap; font-size: 11.5px; color: var(--text-faint); }

.pb-chip {
  flex: 0 0 auto;
  height: 30px;
  padding: 0 12px;
  border: 1px solid var(--border-strong);
  border-radius: var(--r-pill);
  background: var(--surface);
  color: var(--text);
  font-size: 12.5px;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color .12s, border-color .12s, color .12s;
}
.pb-chip:hover { background: #f7f7f8; }
/* 此刻摆着的那块。用品牌蓝：它是「正在调的对象」，与作品列表的选中项同一个语言 */
.pb-chip-active,
.pb-chip-active:hover { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); font-weight: 550; }
/* 「全部设置」不是一个猜测，是一张目录：虚线框把它和上面那几个候选分开 */
.pb-chip-all { border-style: dashed; color: var(--text-dim); background: transparent; }

.pb-panel {
  flex: 0 1 auto;
  display: flex;
  flex-direction: column;
  min-height: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  overflow: hidden;
}
.pb-panel[hidden] { display: none; }

.pb-panel-head {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  padding-block: 12px 10px;
  padding-inline: 16px 10px;
  border-bottom: 1px solid var(--border);
}
.pb-panel-titles { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.pb-panel-group {
  font-size: 11px;
  font-weight: 650;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--text-faint);
}
.pb-panel-title { margin: 0; font-size: 15px; font-weight: 650; line-height: 1.35; }
.pb-panel-close { font-size: 18px; padding: 2px 8px; }

.pb-panel-body { padding: 14px 16px 16px; overflow-y: auto; overscroll-behavior: contain; min-height: 0; }

/* 这句话问的那个控件，在面板里亮一下 */
.pb-field-hit {
  background: var(--accent-soft);
  border-radius: var(--r-ctl);
  box-shadow: 0 0 0 6px var(--accent-soft);
}

.pb-btn-block { flex: 1 1 0; min-width: 0; }
.pb-stack { display: flex; flex-direction: column; gap: 8px; }
.pb-stack .pb-btn-block { flex: none; width: 100%; }

/* 格子样式小样：一眼看到长什么样，不必在下拉里一个个试 */
.pb-swatches { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px; }
.pb-swatch {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 6px 4px 5px;
  border: 1px solid var(--border);
  border-radius: var(--r-ctl);
  background: var(--surface);
  cursor: pointer;
  transition: border-color .12s, background-color .12s;
}
.pb-swatch:hover { border-color: var(--border-strong); }
.pb-swatch svg { display: block; width: 100%; height: 28px; }
.pb-swatch-name { font-size: 11.5px; line-height: 1.25; text-align: center; overflow-wrap: anywhere; }
.pb-swatch-active,
.pb-swatch-active:hover { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent) inset; color: var(--accent); }

/* 全部设置：一张按层分组的目录 */
.pb-all-group { margin-bottom: 12px; }
.pb-all-group:last-child { margin-bottom: 0; }
.pb-all-title {
  margin: 0 0 4px;
  font-size: 11px;
  font-weight: 650;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--text-faint);
}
.pb-all-item {
  display: block;
  width: 100%;
  padding: 7px 10px;
  border: none;
  border-radius: var(--r-ctl);
  background: transparent;
  text-align: start;
  font-size: 13px;
  cursor: pointer;
  transition: background-color .12s;
}
.pb-all-item:hover { background: var(--surface-2); }

.pb-doclist { margin-top: 10px; }

.pb-canvas {
  display: flex;
  flex-direction: column;
  gap: 24px;
  /* 宽度由纸张决定（而不是被容器拉伸），缩放原点固定在左上角：
     这样「缩放后占多大位置」是一道能算准的算术题，居中交给外层容器做。 */
  width: max-content;
  transform-origin: top left;
}

/* ── 面板里的控件 ───────────────────────────────────────────── */
.pb-field { margin-bottom: 12px; }
.pb-field:last-child { margin-bottom: 0; }

.pb-label {
  display: block;
  font-size: 12px;
  color: var(--text-dim);
  margin-bottom: 4px;
}

.pb-row { display: flex; gap: 8px; align-items: center; }
.pb-row > * { min-width: 0; }
.pb-row-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.pb-row-4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px; }

.pb-value {
  font-variant-numeric: tabular-nums;
  font-size: 12px;
  color: var(--text-faint);
  min-width: 40px;
  text-align: end;
}

/* ── 作品列表 ───────────────────────────────────────────────
   展示馆（2026-10-14 收掉）留下的活在这里：每份作品一张真渲染的小样、复制一份再改。 */
.pb-doclist { display: flex; flex-direction: column; gap: 6px; }

.pb-docitem {
  display: grid;
  grid-template-columns: 64px minmax(0, 1fr) auto;
  align-items: center;
  gap: 10px;
  padding: 6px 8px 6px 6px;
  border: 1px solid var(--border);
  border-radius: var(--r-ctl);
  background: var(--surface);
  cursor: pointer;
  transition: background-color .12s, border-color .12s;
}
.pb-docitem:hover { background: var(--surface-2); }
/* 选中项是界面里少数允许用品牌蓝的地方：它是「正在编辑的对象」 */
.pb-docitem-active,
.pb-docitem-active:hover { border-color: var(--accent); background: var(--accent-soft); }
.pb-docitem-active .pb-docitem-name { color: var(--accent); font-weight: 600; }

.pb-docitem-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.pb-docitem-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; }
.pb-docitem-meta { font-size: 11.5px; color: var(--text-faint); font-variant-numeric: tabular-nums; }
.pb-docitem-actions { display: flex; gap: 2px; }

/* 小样：不是截图，是同一个渲染器真渲的第一页缩进来——看到的就是纸上会印出来的。
   纸按原尺寸渲染只在最外层缩放，left/top 固定在 0，外框高度由脚本按缩放后的纸高写入 */
.pb-doc-thumb { position: relative; overflow: hidden; background: var(--bg-deep); border-radius: 4px; min-height: 40px; }
.pb-doc-thumb .pb-canvas {
  position: absolute; top: 0; display: block; gap: 0; padding: 0; transform-origin: top left;
  /* 按缩小后的纸宽（脚本写进 --pb-thumb-w）居中在卡片里；比卡片宽就贴着左边 */
  left: max(0px, calc(50% - var(--pb-thumb-w, 0px) / 2));
}
.pb-doc-thumb .pb-page { box-shadow: none; }

/* ── 模板选择 ───────────────────────────────────────────────── */
.pb-templates { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }

.pb-tpl {
  border: 1px solid var(--border);
  border-radius: var(--r-ctl);
  padding: 8px;
  cursor: pointer;
  background: var(--surface);
  text-align: start;
  display: flex;
  flex-direction: column;
  gap: 6px;
  transition: border-color .12s, background-color .12s;
}

.pb-tpl:hover { border-color: var(--border-strong); }
.pb-tpl-active,
.pb-tpl-active:hover { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent) inset; }

.pb-tpl-name { font-size: 12.5px; font-weight: 550; line-height: 1.3; }
.pb-tpl-thumb { height: 46px; border-radius: 4px; background: var(--surface-2); overflow: hidden; }
.pb-tpl-thumb svg { display: block; width: 100%; height: 100%; }

/* 格子里放了图的模板：小样是一小块白纸，格线用 1px 的缝透出底色画，不会两条边叠成粗线 */
.pb-tpl-pics {
  display: grid;
  height: calc(100% - 6px);
  margin-block: 3px;
  margin-inline: auto;
  padding: 1px;
  gap: 1px;
  background: #7d8798;
}
.pb-tpl-pics > div { min-width: 0; min-height: 0; background: #fff; }
.pb-tpl-pics img { display: block; width: 100%; height: 100%; object-fit: contain; }

/* 模板页签分两段：「我的」（加进资源的作品）在上，「内置」在下。
   「我的」的小样是真渲的第一页（与作品列表同一个渲染器），不是示意图 */
.pb-tpl-section { margin-bottom: 6px; }
.pb-mine { display: flex; flex-direction: column; gap: 8px; margin-bottom: 16px; }
.pb-mine-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-height: 28px; }
.pb-mine-head .pb-label { margin-bottom: 0; }
.pb-mine-add { height: 28px; padding: 0 8px; font-size: 12px; color: var(--accent); }
.pb-mine-empty { margin: 0; }
.pb-mine-item { position: relative; min-width: 0; }
.pb-mine-item .pb-tpl { width: 100%; }
.pb-tpl:disabled { cursor: default; }
.pb-mine-remove {
  position: absolute; top: 6px; inset-inline-end: 6px;
  color: var(--accent); background: rgba(255, 255, 255, .92);
}

/* ── 图库（画布里的一块面板） ───────────────────────────────
   一行两张：面板只有 320px，再小就是文件管理器里的邮票（2026-10-14 评审）。
   小样是一小块白纸，图按 contain 摆放，看得出它在格子里会占多大、留多少白。
   右上角那颗是「存原图」：一键、每张都有，用户要的「非常非常方便的保存」。 */
.pb-pics { display: flex; flex-direction: column; gap: 14px; margin-top: 4px; }
.pb-pics-section { display: flex; flex-direction: column; gap: 6px; }
.pb-pics-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.pb-pic { position: relative; min-width: 0; }
.pb-pic-pick {
  display: flex; flex-direction: column; gap: 5px; width: 100%; padding: 6px 6px 7px;
  border: 1px solid var(--border); border-radius: var(--r-ctl); background: var(--surface);
  color: var(--text); font: inherit; text-align: start; cursor: pointer;
  transition: border-color .12s, box-shadow .12s;
}
.pb-pic-pick:hover { border-color: var(--border-strong); box-shadow: var(--shadow-lift); }
.pb-pic-pick:active { border-color: var(--accent); }
.pb-pic-thumb { aspect-ratio: 1; background: #fff; border-radius: 4px; overflow: hidden; line-height: 0; }
.pb-pic-thumb img { width: 100%; height: 100%; object-fit: contain; display: block; }
.pb-pic-name { font-size: 12.5px; line-height: 1.3; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pb-pic-save {
  position: absolute; top: 10px; inset-inline-end: 10px;
  display: flex; align-items: center; justify-content: center; width: 26px; height: 26px;
  border-radius: 50%; background: rgba(255, 255, 255, .92); color: var(--text-dim);
  border: 1px solid var(--border); box-shadow: 0 1px 2px rgba(17, 17, 20, .08);
  transition: color .12s, border-color .12s;
}
.pb-pic-save:hover { color: var(--accent); border-color: var(--accent); }
.pb-pic-save svg { width: 15px; height: 15px; }
.pb-pics-empty { margin-top: 4px; }

/* ── 板块列表 ───────────────────────────────────────────────── */
.pb-blocklist { display: flex; flex-direction: column; gap: 3px; }

.pb-blockitem {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 6px 9px;
  border: 1px solid var(--border);
  border-radius: var(--r-ctl);
  cursor: pointer;
  font-size: 12.5px;
  background: var(--surface);
  transition: border-color .12s, background-color .12s;
}

.pb-blockitem:hover { background: var(--surface-2); }
.pb-blockitem-active,
.pb-blockitem-active:hover { border-color: var(--accent); background: var(--accent-soft); }
.pb-blockitem-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pb-blockitem-meta { color: var(--text-faint); font-size: 11.5px; font-variant-numeric: tabular-nums; }

.pb-iconbtn {
  border: none;
  background: transparent;
  cursor: pointer;
  color: var(--text-faint);
  padding: 2px 6px;
  border-radius: 6px;
  font-size: 13px;
  line-height: 1;
  transition: background-color .12s, color .12s;
}
.pb-iconbtn:hover { background: var(--surface-2); color: var(--text); }
.pb-iconbtn:disabled { opacity: .3; cursor: default; }

/* ── 字体选择 ───────────────────────────────────────────────── */
.pb-fontopt-missing { color: var(--text-faint); }

.pb-hint {
  font-size: 12px;
  color: var(--text-faint);
  line-height: 1.5;
  margin-top: 5px;
}

.pb-warn { color: var(--danger); }

.pb-empty {
  padding: 20px 6px;
  text-align: center;
  color: var(--text-faint);
  font-size: 12.5px;
  line-height: 1.6;
}

.pb-badge {
  display: inline-flex;
  align-items: center;
  padding: 3px 9px;
  border-radius: var(--r-pill);
  font-size: 11px;
  font-weight: 550;
  background: var(--surface-2);
  color: var(--text-dim);
  border: none;
}

.pb-badge-dirty { background: #fbf3e2; color: #96731d; }

/* ── 打印提示条 ─────────────────────────────────────────────── */
.pb-hintbar {
  background: #fcf8ee;
  border-bottom: 1px solid #efe6cc;
  padding: 9px 16px;
  font-size: 12.5px;
  color: #7d6425;
  display: flex;
  align-items: flex-start;
  gap: 10px;
}

.pb-hintbar ul { margin: 4px 0 0; padding-inline-start: 17px; }
.pb-hintbar li { margin: 1px 0; }
.pb-hintbar-body { flex: 1; }
.pb-hintbar strong { font-weight: 600; }

/* ── 提示条 ─────────────────────────────────────────────────── */
.pb-toast {
  position: fixed;
  left: 50%;
  bottom: 28px;
  transform: translate(-50%, 14px);
  background: #1a1a1e;
  color: #fff;
  padding: 10px 20px;
  border-radius: var(--r-pill);
  font-size: 13px;
  opacity: 0;
  pointer-events: none;
  transition: opacity .16s, transform .16s;
  z-index: 60;
  box-shadow: var(--shadow-float);
  max-width: 78vw;
}

.pb-toast-show { opacity: 1; transform: translate(-50%, 0); }
.pb-toast[data-kind='error'] { background: var(--danger); }
.pb-toast[data-kind='ok'] { background: var(--ok); }

/* ── 打印预览页（隐藏外壳，只留纸） ─────────────────────────── */
.pb-printonly { display: none; }

/* ── 自己调一个对称 X（画布里的一块面板） ───────────────────
   画布是主角：模板开关 + 一整块方形画布 + 撤销重做重置。
   点与控制柄用界面强调色，字形用符号的墨色；镜像副本空心、灰一档。
   面板只有 320px 宽，viewBox 却是 600 个单位：点的尺寸与线宽都按 --pb-glyph-k
   （一个屏幕像素等于几个单位，由脚本每次渲染写入）放大，不然在屏幕上只剩针尖。 */
.pb-seg { display: inline-flex; border: 1px solid var(--border); border-radius: 8px; overflow: hidden; }
.pb-seg-btn {
  font: inherit; font-size: 13px; padding: 0 12px; height: 34px; border: 0; cursor: pointer;
  background: var(--surface); color: var(--text-dim);
}
.pb-seg-btn + .pb-seg-btn { border-inline-start: 1px solid var(--border); }
.pb-seg-btn.pb-seg-active { background: var(--surface-2); color: var(--text); font-weight: 600; }
.pb-glyph-stage {
  display: block; width: 100%; aspect-ratio: 1; margin: 10px 0 8px;
  background: var(--surface); border: 1px solid var(--border); border-radius: 10px;
  touch-action: none; user-select: none; -webkit-user-select: none;
  --pb-glyph-k: 2;
}
.pb-glyph-stage:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.pb-glyph-stage.is-dragging { cursor: grabbing; }
.pb-glyph-grid line { stroke: var(--bg-deep); stroke-width: 1; }
.pb-glyph-sheet { fill: none; stroke: var(--border); stroke-width: 1; }
.pb-glyph-axes line { stroke: var(--border-strong); stroke-width: 1; stroke-dasharray: 6 5; }
/* 墨色不在这里写：页面按模板把 fill / stroke 写成属性，CSS 的 fill 会压过 fill="none" */
.pb-glyph-hline { stroke: var(--accent); stroke-width: calc(1 * var(--pb-glyph-k, 1)); opacity: .55; }
.pb-glyph-hline.is-shadow { stroke: var(--text-faint); opacity: .45; }
.pb-glyph-pt { cursor: grab; }
.pb-glyph-pt.is-anchor { fill: var(--surface); stroke: var(--accent); stroke-width: calc(2 * var(--pb-glyph-k, 1)); }
.pb-glyph-pt.is-handle { fill: var(--accent); stroke: var(--surface); stroke-width: calc(1.5 * var(--pb-glyph-k, 1)); }
.pb-glyph-pt.is-shadow.is-anchor { stroke: var(--text-faint); }
.pb-glyph-pt.is-shadow.is-handle { fill: var(--text-faint); }
.pb-glyph-pt.is-width { fill: var(--accent); stroke: var(--surface); stroke-width: calc(1.5 * var(--pb-glyph-k, 1)); cursor: ew-resize; }
.pb-glyph-pt.is-selected { stroke-width: calc(3.5 * var(--pb-glyph-k, 1)); }
.pb-glyph-pt.is-handle.is-selected { fill: var(--surface); }
.pb-glyph-marquee { fill: rgba(37, 99, 235, .10); stroke: var(--accent); stroke-width: calc(1 * var(--pb-glyph-k, 1)); stroke-dasharray: 4 3; }

/* ── 公式（画布里的一块面板） ──────────────────────────────
   预览区不缩放：选了 48pt 就按 48pt 显示，装不下就滚动。
   缩着看好看，但「屏幕上多大纸上就多大」这句话会当场变成假的（AGENTS.md §8.4）。 */
.pb-formula-input {
  width: 100%; resize: vertical; min-height: 92px;
  /* 等宽：反斜杠和花括号的位置要一眼看得清，比例字体下 {} 会糊成一团 */
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 14px; line-height: 1.6;
}
.pb-formula-palette { margin-top: 12px; display: flex; flex-direction: column; gap: 12px; }
.pb-formula-group .pb-label { margin-bottom: 6px; }
.pb-formula-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.pb-formula-chip {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 44px; min-height: 40px; padding: 4px 10px;
  background: var(--surface); border: 1px solid var(--border); border-radius: 8px;
  cursor: pointer; color: var(--text);
}
.pb-formula-chip:hover { background: #f7f7f8; border-color: var(--border-strong); }
.pb-formula-chip:active { background: #f0f0f2; }
.pb-formula-chips.is-wide .pb-formula-chip { min-width: 0; width: 100%; justify-content: flex-start; }
.pb-formula-chip-art { display: inline-block; line-height: 1; }
/* 面板里的式子跟着按钮走颜色；引擎给的是 currentColor，这里不必再管 */
.pb-formula-chip mjx-container { margin: 0 !important; }

.pb-formula-preview { display: flex; flex-direction: column; gap: 4px; margin-bottom: 10px; }
.pb-formula-paper {
  background: #fff; border: 1px solid var(--border); border-radius: 8px;
  min-height: 96px; padding: 14px;
  /* safe：装得下就居中，装不下就从开头排起。只写 center 的话，比框宽的式子会向两边一起溢出，
     开头那一截溢在滚动区外面，滚动条够不到——默认的 a² + b² = c² 在 48pt 下就被吃掉了开头（BUG-067） */
  display: flex; align-items: center; justify-content: safe center;
  overflow: auto;                 /* 装不下就滚动，绝不缩放 */
}
.pb-formula-render { color: #111111; }
.pb-formula-empty { margin: 0; color: var(--text-faint); font-size: 13px; text-align: center; }
/* 印出来有多大，就地写在预览旁边：屏幕上看不出毫米数（AGENTS.md §8.4）。数字与单位不是文案 */
.pb-formula-size { text-align: end; font-variant-numeric: tabular-nums; min-height: 1.2em; }
.pb-formula-chip mjx-container { margin: 0 !important; }

/* 资源区宽屏才默认开着：窄一点的屏上，开着它纸就只剩一条窄缝。收着时页签还在，点一下就开 */
@media (max-width: 1180px) {
  :root { --pb-library-default: closed; }
}

/* ══ 手机与小平板 ══════════════════════════════════════════════
   手机上三栏放不下：搜索框在纸的上面；资源区的页签挪到屏幕底部一排；
   面板（设置的、资源区的）都从底部升起，一次只升一块，由 studio.js 协调。
   不许用 display:none 解决放不下（§8.8）：每一块都还在，只是换了摆法。 */

@media (max-width: 900px) {
  :root {
    --nav-h: 48px;
    --rail-h: 58px;
  }

  /* dvh 让地址栏收起/展开时高度跟着变，100% 在手机浏览器上会算多一截 */
  body { height: 100dvh; }

  .pb-shell { flex-direction: column; }

  .pb-main {
    flex: 1;
    min-height: 0;
  }

  /* ── 顶栏折成两行：名字与语言一行，工具栏一行（横滑） ── */
  .pb-nav { flex-wrap: wrap; height: auto; min-height: var(--nav-h); column-gap: 8px; padding: 0 12px; }
  .pb-nav-brand, .pb-nav-lang { min-height: var(--nav-h); }
  .pb-nav-brand { display: inline-flex; align-items: center; }   /* 字放在这一行的中间，不贴着顶 */
  .pb-nav-slot { order: 10; flex: 1 0 100%; border-top: 1px solid var(--border); }
  .pb-toolbar { padding: 7px 0; }
  /* 横滑的前提是里面的东西不许被压扁：不写这条，
     「头洞 12.0 × 10.8 厘米」会被挤成一根竖着排的窄条 */
  .pb-toolbar .pb-badge,
  .pb-toolbar .pb-btn { white-space: nowrap; }
  .pb-toolbar-spacer { flex: 0 0 4px; }

  /* ── 设置：搜索框在纸的上面，面板从底部升起 ───────────
     面板升起后上半截还看得见纸，一边调一边看——这个产品的核心动作就是
     「看纸 + 调一个数」。面板不罩灰色遮罩：罩上了，正要看的那张纸就暗了。 */
  .pb-finder {
    order: -1;
    width: auto;
    padding: 10px 12px 8px;
    background: var(--bg-deep);
    border: 0;
    overflow: visible;
  }
  .pb-finder-input {
    border-color: transparent;
    box-shadow: var(--shadow-lift);
  }
  .pb-finder-input:focus { box-shadow: 0 0 0 3px rgba(10, 108, 245, .13), var(--shadow-lift); }
  .pb-finder-kbd { display: none; }   /* 手机上没有一个「/」键可按 */

  /* 入口一行横滑：要横滑就滑这一条，不许把整页撑宽（§8.9） */
  .pb-chip-row {
    flex-wrap: nowrap;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
  }
  .pb-chip-row::-webkit-scrollbar { display: none; }
  .pb-chip { height: 34px; }          /* 手指不是鼠标指针 */
  .pb-iconbtn { min-width: 32px; min-height: 32px; }   /* 缩放、复制、删除这些小按钮也要够手指点 */
  .pb-panel-close { min-width: 40px; min-height: 40px; }

  /* ── 资源区：页签是屏幕底部一排，内容从底部升起 ── */
  .pb-library { order: 2; flex: none; background: transparent; border: 0; }
  .pb-library-rail {
    position: fixed;
    inset-inline: 0;
    bottom: 0;
    z-index: 41;
    width: auto;
    height: calc(var(--rail-h) + env(safe-area-inset-bottom));
    flex-direction: row;
    gap: 2px;
    padding: 4px 6px env(safe-area-inset-bottom);
    background: var(--surface);
    border-top: 1px solid var(--border);
    overflow-x: auto;
    overflow-y: hidden;
  }
  .pb-rail-btn { flex: 1 0 60px; width: auto; min-height: 48px; padding: 5px 2px 4px; }

  /* 两种面板都从底部那一排页签的上面升起，一次只升一块 */
  .pb-panel,
  .pb-library-panel {
    position: fixed;
    inset-inline: 0;
    bottom: calc(var(--rail-h) + env(safe-area-inset-bottom));
    z-index: 40;
    width: auto;
    max-height: 58vh;
    max-height: 58dvh;
    background: var(--surface);
    border: 0;
    border-radius: 18px 18px 0 0;
    box-shadow: 0 -10px 32px rgba(17, 17, 20, .16);
  }

  /* 纸底下给那一排页签留出地方，纸才滚得出来；升起面板时由 studio.js 再加上面板的高度 */
  .pb-canvas-wrap { padding: 12px; padding-bottom: calc(12px + var(--rail-h) + env(safe-area-inset-bottom)); }

  .pb-nav-brand { font-size: 14px; }
  .pb-nav-lang-label { display: none; }
  /* 工具栏折到第二行之后，第一行只剩名字和语言：语言靠到行尾（以前是中间那个空槽把它推过去的） */
  .pb-nav-lang { max-width: 108px; margin-inline-start: auto; }

  .pb-hintbar { padding: 7px 12px; font-size: 12px; }
  .pb-hintbar ul { padding-inline-start: 15px; }
}

/* 很窄的屏（iPhone SE 一类）再省一点 */
@media (max-width: 400px) {
  .pb-nav-brand { display: none; }
}

/* ── 从右往左的语言（阿拉伯语 / 埃及阿拉伯语 / 乌尔都语 / 西旁遮普语 / 波斯语） ──
   界面用逻辑属性写，设了 dir 就会自己镜像；下面几处是不该跟着翻的例外。 */

/* 纸张是物理排版：A4 的左边永远是左边，不随界面语言镜像。
   打印出来的东西跟界面书写方向无关。 */
[dir="rtl"] .pb-page,
[dir="rtl"] .pb-canvas,
[dir="rtl"] .pb-doc-thumb {
  direction: ltr;
}

/* 缩放占位容器也要从左往右：纸按左上角缩放（transform-origin: top left），
   而 RTL 下没缩放的那张纸会贴着占位容器的**右**边、往左溢出，
   缩完之后整张纸向左偏出去几百像素，离开了旁边那一列。 */
[dir="rtl"] #pb-canvas-space {
  direction: ltr;
}

/* 纯数字读数（100% / 0° / 1.90）在 RTL 里仍按从左到右读。
   只作用于 .pb-value——徽章里有整句译文，强制 LTR 会把阿拉伯语的词序打乱。 */
[dir="rtl"] .pb-value {
  direction: ltr;
  text-align: start;
}

/* 滑块在 RTL 下应从右侧起算，否则拖动方向和视觉相反 */
[dir="rtl"] .pb-range {
  direction: rtl;
}

/* LaTeX 源码是代码，不是文章：跟着阿拉伯语从右往左排之后，
   \frac{a+b}{c} 会显示成 frac{a+b}{c}\ ——反斜杠被甩到末尾，
   用户照着屏幕改就再也改不对了。数字读数（40.2 × 51.0 mm）同理，
   镜像后单位会跑到最前面。两处都强制从左到右。 */
[dir="rtl"] .pb-formula-input,
[dir="rtl"] .pb-formula-size {
  direction: ltr;
  text-align: start;
}
