/* ============================================================
   tools.css — 原生融合工具样式（#view-image 单图处理 / #view-anim 动图生成）
   统一复用主站 main.css 的设计 token（--surface / --border / --text /
   --r-card / --r-btn / --shadow-1 / --icon-bg 等），保证工具与导航站
   同一套视觉语言；选择器全部限定在各自视图容器内，避免类名撞名。
   设计约定同主站：浅色、卡片 12px / 按钮 6px 圆角、系统字体、
   标题加粗、禁高饱和渐变 / glow / 厚重毛玻璃。
   ============================================================ */

#view-image, #view-anim, #view-frames { color: var(--text); }

/* 工具页内容区宽度口径（2026-10-29 统一）：跟随视口，上限 1600px。
   1920 下内容 1600 / 两侧各 160；1440 下内容约 1354 / 两侧各 43。
   原先统一 880（单图处理 960），1920 下两侧各空 520，大屏严重浪费。 */
#view-image, #view-anim, #view-frames, #view-cut, #view-convert, #view-pdfcompress,
#view-cutout { --tool-maxw: min(1600px, 94vw); }
/* 批量调整尺寸是外层容器（tab 条 + #view-resize 面板），变量必须挂在外层 ——
   挂在 #view-resize 上的话 .ia-tabs 取不到，只能写死 880，宽屏下与内容错位。
   同时要盖住 #view-resize 自己（.rsz 读的是最近祖先的变量）。
   口径与其它工具统一 1600（2026-10-29 统一化：参数栏定宽 304 后，
   预览列多出来的宽度才是可用画布，不再需要靠限宽 1280 压制） */
#view-imgadjust,
#view-imgadjust #view-resize { --tool-maxw: min(1600px, 94vw); }

/* —— 容器：内容限宽（四视图统一节奏：pad 24 / 标题块 / 内容间距 16） —— */
/* 注意：flex item 上的 auto margin 会禁用 stretch 使宽度退化为 fit-content（随文字抖动），
   必须显式 width:100% + max-width 才能稳定限宽居中（#view-anim 同样适用） */
#view-image .tool-body, #view-anim .tool-body, #view-frames .tool-body { width: 100%; max-width: var(--tool-maxw); margin: 0 auto; padding: 16px 20px 18px; }
/* 单图处理为双栏布局（预览 1fr + 侧栏 356px），宽度与其他工具统一走 --tool-maxw */

#view-image header h1, #view-anim header h1, #view-frames header h1 { font-size: var(--hx-t20); margin: 0; font-weight: 700; letter-spacing: 0.2px; }

/* —— 拖放区（与头部间距由 .tb-head 的 margin-bottom 统一保证） —— */
#view-image .drop, #view-anim .drop, #view-frames .drop {
  border: 1.5px dashed var(--border-strong);
  border-radius: var(--r-card);
  background: var(--surface);
  padding: 26px 24px 22px;
  text-align: center;
  margin: 0 0 16px;
  cursor: pointer;
  box-shadow: var(--shadow-1);
  transition: border-color 0.15s var(--ease), background 0.15s var(--ease);
}
#view-image .drop:hover, #view-anim .drop:hover, #view-frames .drop:hover { border-color: var(--text-3); }
#view-image .drop.over, #view-anim .drop.over, #view-frames .drop.over { border-color: var(--text); background: var(--icon-bg); }
#view-image .drop-icon, #view-anim .drop-icon, #view-frames .drop-icon {
  width: 44px; height: 44px; margin: 0 auto 12px;
  border-radius: var(--r-btn); background: var(--icon-bg); color: var(--icon-fg);
  display: grid; place-items: center;
}
#view-image .drop-icon svg, #view-anim .drop-icon svg, #view-frames .drop-icon svg { width: 22px; height: 22px; }
#view-image .drop-t1, #view-anim .drop-t1, #view-frames .drop-t1 { margin: 0 0 4px; font-size: var(--hx-t14); font-weight: 700; color: var(--text); }
#view-image .drop-t2, #view-anim .drop-t2, #view-frames .drop-t2 { margin: 0 0 14px; font-size: var(--hx-t12); color: var(--text-3); }

/* —— 控件（与主站同一语言：深色主按钮 / 白底描边按钮 / 6px 圆角）—— */
/* 注意：基础规则用 .btn（纯类）而非 label.btn，避免元素选择器抬高优先级压过后续 .btn-p 变体 */
#view-image .btn, #view-anim .btn, #view-frames .btn,
#view-image button, #view-anim button, #view-frames button {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  font: inherit; font-size: var(--hx-t13); line-height: 1;
  height: var(--ctl-h); padding: 0 var(--ctl-px);
  border: 1px solid var(--border); border-radius: var(--r-btn);
  background: var(--surface); color: var(--text);
  cursor: pointer;
  transition: background 0.12s var(--ease), border-color 0.12s var(--ease), color 0.12s var(--ease);
}
/* 禁用态（含常驻的重置/清空/下载）：弱化且不响应 hover */
#view-image button:disabled, #view-anim button:disabled, #view-frames button:disabled { opacity: 0.45; cursor: not-allowed; }
#view-image button:disabled:hover, #view-anim button:disabled:hover, #view-frames button:disabled:hover { background: var(--surface); border-color: var(--border); }
#view-image button:hover, #view-anim button:hover, #view-frames button:hover,
#view-image .btn:hover, #view-anim .btn:hover, #view-frames .btn:hover { background: var(--icon-bg); border-color: var(--border-strong); }
#view-image .btn-p, #view-anim .btn-p, #view-frames .btn-p { background: var(--text); border-color: var(--text); color: var(--bg); font-weight: 600; }
#view-image .btn-p:hover, #view-anim .btn-p:hover, #view-frames .btn-p:hover { background: var(--btn-p-hover); border-color: var(--btn-p-hover); color: #fff; } /* hover 底色 --btn-p-hover 亮暗都是深灰，字必须固定白（用 var(--bg) 会在暗色下深字叠深底 1.5:1） */
#view-image .btn-p:disabled, #view-anim .btn-p:disabled, #view-frames .btn-p:disabled { background: var(--border); border-color: var(--border); color: var(--text-3); cursor: not-allowed; opacity: 1; }
#view-image .btn-ghost, #view-anim .btn-ghost, #view-frames .btn-ghost { background: transparent; border-color: transparent; color: var(--text-2); }
#view-image .btn-ghost:hover, #view-anim .btn-ghost:hover, #view-frames .btn-ghost:hover { background: var(--icon-bg); border-color: transparent; color: var(--text); }
#view-image button.ghost, #view-anim button.ghost, #view-frames button.ghost { background: transparent; color: var(--text-2); }
#view-image button.ghost:hover, #view-anim button.ghost:hover, #view-frames button.ghost:hover { background: var(--icon-bg); color: var(--text); }
#view-image .btn-row-end, #view-anim .btn-row-end { justify-content: flex-end; }
#view-image .btn-danger, #view-anim .btn-danger, #view-frames .btn-danger { color: var(--danger-text); }
#view-image .btn-danger:hover, #view-anim .btn-danger:hover, #view-frames .btn-danger:hover { background: var(--danger-soft-bg); color: var(--danger-text); }
#view-image .btn-sm, #view-anim .btn-sm, #view-frames .btn-sm { height: var(--ctl-h-sm); padding: 0 10px; font-size: var(--hx-t12); }

/* 生成中（按钮旋转指示） */
#view-anim #animGen.busy { position: relative; pointer-events: none; opacity: 0.7; }
#view-anim #animGen.busy::before {
  content: ""; width: 12px; height: 12px; flex: none;
  border: 2px solid color-mix(in srgb, currentColor 30%, transparent); border-top-color: currentColor;
  border-radius: 50%; animation: tool-spin 0.7s linear infinite;
}
@keyframes tool-spin { to { transform: rotate(360deg); } }
/* 几何按钮不再有加载态：去掉转圈 / 变灰，左侧预览即时旋转 / 镜像即为反馈，
   按钮全程可点、盒模型零变化。真实像素在后台算完静默顶替，无需按钮提示。 */

/* —— 输入控件 —— */
#view-image label, #view-anim label, #view-frames label { display: block; font-size: var(--hx-t12); color: var(--text-2); margin: 7px 0 3px; }
#view-image input[type=number], #view-anim input[type=number], #view-frames input[type=number],
#view-image select, #view-anim select, #view-frames select {
  font: inherit; font-size: var(--hx-t13);
  height: var(--ctl-h); padding: 0 8px;
  border: 1px solid var(--border); border-radius: var(--r-btn);
  background: var(--surface); color: var(--text);
  outline: none;
  transition: border-color 0.15s var(--ease), box-shadow 0.15s var(--ease);
}
#view-image input[type=number]:focus, #view-anim input[type=number]:focus, #view-frames input[type=number]:focus,
#view-image select:focus, #view-anim select:focus, #view-frames select:focus { border-color: var(--text-3); box-shadow: 0 0 0 3px var(--overlay-dim); }
#view-image input[type=number], #view-anim input[type=number], #view-frames input[type=number] { width: 76px; }
/* 原生下拉弹层：深色主题下选项会继承 select 的 --text（浅色），在浏览器控件自带的浅色弹层上
   对比度过低（APNG/GIF 等项几乎看不清）。显式指定「深字 + 白底」保证各系统下都可读；
   弹层整体背景由浏览器控件决定，这里只约束选项自身文字/底色。 */
html[data-skin="helix"] select option { color: #11151c; background: #ffffff; }
#view-image input[type=range], #view-anim input[type=range] { flex: 1; min-width: 120px; accent-color: var(--text); }
#view-image .row, #view-anim .row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-bottom: 8px; }
/* 分组内最后一行不叠加底部外边距（若后面还有 hint 则不命中） */
#view-image .group .row:last-child, #view-anim .group .row:last-child, #view-frames .group .row:last-child { margin-bottom: 0; }
/* 行内标签前缀：最小列宽（容下「任意旋转」4 字）保证各行输入框左缘对齐；
   字号放大或更长标签（任意旋转）时按内容自然变宽，绝不折成两行 —— 用户已反馈过 */
#view-image .row-label { flex: none; font-size: var(--hx-t12); color: var(--text-2); width: auto; min-width: 52px; white-space: nowrap; }
/* 标签行的动作按钮统一推到行尾：形成「标签列 / 输入列 / 按钮列」三条对齐线 */
#view-image .row-label ~ button:last-child { margin-left: auto; }
/* 纯按钮行（旋转 / 镜像）：等宽铺满整行，边缘与上下行对齐 */
#view-image .btn-row > button { flex: 1 1 0; min-width: 0; }
/* 旋转快捷按钮：图标在上、文字标签在下，四颗等宽铺满整行 */
#view-image .rot-quick { gap: 8px; }
#view-image .rot-quick .im-ic {
  flex: 1 1 0; min-width: 0; height: auto; padding: 10px 4px;
  flex-direction: column; gap: 5px; font-size: var(--hx-t12); line-height: 1.15;
}
#view-image .rot-quick .im-ic svg { width: 20px; height: 20px; flex: none; }
#view-image .rot-quick .im-ic span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
/* 角度数字框后的「°」单位符号 */
#view-image .deg { flex: none; color: var(--text-2); font-size: var(--hx-t13); margin: 0 2px; }
/* 裁剪行：x/y/w/h + 应用，单行排布。注意这里**没有文字标签**——
   侧边栏展开时控件区实测仅 306px，「裁剪」标签(52px) + 4×输入 + 按钮 + 间距共需 ~360px，
   按钮被挤出容器右侧（1100px 视口下甚至出视口，用户反馈「应用按钮看不清」）。
   去掉标签后：4×52 + 52(按钮) + 5×8(gap) = 300px ≤ 306px；placeholder x/y/w/h
   与 cropHint 引导文案已说明用途。输入框用 flex:0 0 固定宽（不 grow），
   宽屏下不再被拉到 110px 与其他控件节奏一致；wrap + 按钮 margin-left:auto 兜底，
   极端窄屏时按钮优雅换行而非被裁掉 */
/* 裁剪坐标：没有「应用」按钮了，四个数字常驻 → 每个前面挂一个小写标签（x / y / w / h），
   否则满屏数字看不出哪个是宽高。2×2 栅格，字号放大也不会挤成一行 */
#view-image .crop-row { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
#view-image .crop-f { display: flex; align-items: center; gap: 6px; min-width: 0; }
#view-image .crop-f > span { flex: none; font-size: var(--hx-t12); color: var(--text-3); }
#view-image .crop-row input[type=number] { flex: 1 1 auto; min-width: 0; width: 100%; padding-left: 6px; padding-right: 6px; }
#view-image .crop-row input[type=number]::-webkit-outer-spin-button,
#view-image .crop-row input[type=number]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
#view-image .crop-row input[type=number] { -moz-appearance: textfield; appearance: textfield; }
/* 勾选行（自动裁切）：自定义对齐，替代浏览器默认基线错位 */
#view-image .chk-row .chk, #view-anim .chk-row .chk { display: flex; align-items: center; gap: 6px; margin: 0; cursor: pointer; }
#view-image .chk-row input[type=checkbox], #view-anim .chk-row input[type=checkbox] { margin: 0; accent-color: var(--text); }
/* 勾选行没有标签，缩进对齐到标签列：row-label 的 min-width 52px + .row 的 gap 8px。
   不缩进的话它顶格 0，而上下两行从 60px 起 —— 右栏会出现三条不同的左边缘
   （60 / 0 / 0），看着像没对齐的毛坯。动作行仍保持通栏：按钮需要宽度。 */
#view-image .chk-row { padding-left: 60px; }
/* 裁剪面板里的勾选行除外：那个面板全用通栏行（坐标 4 个输入框横排），
   缩进 60px 会变成一块孤零零的右移内容。必须写在本条之后才盖得住。 */
#view-image .chk-row.trim-row { padding-left: 0; }
#view-image .val, #view-anim .val { font-size: var(--hx-t12); color: var(--text); min-width: 38px; text-align: right; font-variant-numeric: tabular-nums; }
/* 无损压缩行：大小文字弱化，按钮由 .row-label ~ button:last-child 统一右贴 */
#view-image .opt-row .val { margin-left: 2px; color: var(--text-3); font-weight: 400; }
/* 压缩按钮的「当前选中档」高亮：与左侧功能列 / 对比按钮的 .is-on 同色系，表示它已落到画布上，
   且与保存弹窗的「压缩」单选保持同一语义，两边不打架 */
#view-image #applyOpt.is-on, #view-image #applyQuant.is-on {
  background: var(--accent); border-color: var(--accent); color: #fff;
}
#view-image #applyOpt.is-on:hover, #view-image #applyQuant.is-on:hover { background: var(--accent); color: #fff; }
#view-image .hint, #view-anim .hint { font-size: var(--hx-t12); color: var(--text-2); margin: 4px 0; line-height: 1.6; }
/* 提示拆两行：主句（怎么做）留在 .hint，下载体积这类「只第一次相关」的说明
   降一档到 .hint-sub，模型就绪后整行隐藏，把纵向空间还给参数。 */
#view-image .hint-sub { font-size: var(--hx-t11); color: var(--text-3); margin: -2px 0 8px; line-height: 1.5; }
#view-image .hint-sub[hidden] { display: none; }

/* —— 涂抹层（消除）——
   与图片同框、随缩放层一起 transform（它的 parent 就是 .im-inner）。
   touch-action:none 是必须的：触屏上默认手势会把拖动解释成页面滚动，
   画笔一笔都画不出来。z-index 压在两图之上、进度浮层之下。 */
#view-image .im-mask {
  position: absolute; left: 0; top: 0; width: 100%; height: 100%;
  z-index: 2; cursor: crosshair; touch-action: none;
}
#view-image .im-mask[hidden] { display: none; }
/* 画笔模式隐藏系统十字：自绘的圆环光标才是「笔刷多大」的答案，
   十字与圆环叠在一起会互相干扰（两个中心、两套指示）。框选仍用 crosshair。 */
#view-image .im-mask.is-brush { cursor: none; }
/* 圆形笔刷光标：放在 outStage（屏幕坐标）上，所以 1px 边框不被缩放的图片层拉细。
   双色描边=内白外淡黑：白线在深色图上清楚，淡黑在浅色图上兜底。 */
#view-image .im-brushcur {
  position: absolute; pointer-events: none; z-index: 3;
  border-radius: 50%; box-sizing: border-box;
  border: 1px solid rgba(255, 255, 255, 0.95);
  box-shadow: 0 0 0 1px rgba(16, 22, 32, 0.35);
}
#view-image .im-brushcur[hidden] { display: none; }
/* 消除面板动作行：清除选区（次要）+ 消除（主操作，吃掉剩余宽度） */
#view-image .ip-acts { gap: 8px; }
#view-image .ip-acts > button { flex: none; min-width: 96px; }
#view-image .ip-acts .ip-run { flex: 1 1 auto; background: var(--accent); border-color: var(--accent); color: #fff; }
#view-image .ip-acts .ip-run:hover { background: var(--accent); color: #fff; }
/* 自动矫正 / 裁掉背景：两颗并排，实心主色只给「自动矫正」，
   切纸用描边次色 —— 一行两个实心块会让主次消失，也挤得字发糊。 */
#view-image .ds-act { margin: 2px 0 0; }
#view-image .ds-act .ds-run { flex: 1 1 auto; background: var(--accent); border-color: var(--accent); color: #fff; font-weight: 600; }
#view-image .ds-act .ds-run:hover:not(:disabled) { background: var(--accent); border-color: var(--accent); color: #fff; }
#view-image .ds-act .ds-run:disabled { opacity: 0.6; cursor: default; }
#view-image .ds-act .ds-doc { flex: 1 1 auto; }
#view-image .ds-act .ds-doc:disabled { opacity: 0.6; cursor: default; }
/* 选区方式（画笔 / 框选）分段按钮：两颗等宽铺满。
   选中态用「浅底 + 主色字」而不是实心主色 —— 面板里实心主色只留给
   真正的动作按钮（立即消除 / 保存），三处一样重会让主次消失。 */
#view-image .ip-seg { display: flex; flex: 1 1 auto; gap: 4px; min-width: 0; }
#view-image .ip-seg > button { flex: 1 1 0; min-width: 0; }
#view-image .ip-seg > button.is-on {
  background: var(--accent-soft-bg); border-color: var(--accent-soft-border);
  color: var(--accent-text); font-weight: 600;
}
#view-image .ip-seg > button.is-on:hover {
  background: var(--accent-soft-bg); border-color: var(--accent-soft-border); color: var(--accent-text);
}
/* 笔刷行只在画笔模式下出现；.row 自带 display:flex 会盖掉 hidden 属性，必须显式声明 */
#view-image #ipBrushRow[hidden] { display: none; }
/* 卸载模型：次要动作，弱化成一行小字按钮，不跟主按钮抢注意力。
   [hidden] 必须显式写 —— .row 自带 display:flex，会把 hidden 属性盖掉。 */
#view-image .ip-free-row { justify-content: flex-end; }
#view-image .ip-free-row[hidden] { display: none; }
#view-image .ip-free { font-size: var(--hx-t12); color: var(--text-2); }

/* —— 清晰 · 8 项调节（照参考稿：浅灰轨道 + 白芯蓝环圆钮 + 右侧窄数字框） ——
   整行 grid：标签 52px（与 .row-label 同宽，和上面的「程度」行对齐）/ 滑块 1fr / 数字 44px。
   选择器都带 .sh-adj-row，比通用的 #view-image input[type=number] （width:76px）更具体，能压住它。 */
#view-image .ip-sub { margin: 12px 0 4px; font-size: var(--hx-t11); color: var(--text-3); }
#view-image .sh-adj { display: flex; flex-direction: column; gap: 1px; margin: 0 0 8px; }
#view-image .sh-adj-row {
  display: grid; grid-template-columns: 52px minmax(0, 1fr) 44px;
  align-items: center; gap: 8px; height: 26px;
}
#view-image .sh-adj-lab { font-size: var(--hx-t12); color: var(--text-2); white-space: nowrap; }
#view-image .sh-adj-row input[type=range] {
  -webkit-appearance: none; appearance: none;
  width: 100%; min-width: 0; height: 4px; margin: 0; padding: 0;
  border: 0; border-radius: 999px; background: var(--border); outline: none; cursor: pointer;
}
#view-image .sh-adj-row input[type=range]::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 14px; height: 14px; border-radius: 50%;
  background: var(--surface); border: 2px solid var(--accent);
  box-sizing: border-box; cursor: pointer;
}
#view-image .sh-adj-row input[type=range]::-moz-range-thumb {
  width: 14px; height: 14px; border-radius: 50%;
  background: var(--surface); border: 2px solid var(--accent);
  box-sizing: border-box; cursor: pointer;
}
#view-image .sh-adj-row input[type=number] {
  width: 100%; min-width: 0; height: 24px; padding: 0 5px;
  text-align: right; font-size: var(--hx-t12); color: var(--text);
  background: var(--surface); border: 1px solid var(--border); border-radius: 2px;
  -moz-appearance: textfield; appearance: textfield;
}
#view-image .sh-adj-row input[type=number]:focus { border-color: var(--accent); outline: none; }
#view-image .sh-adj-row input[type=number]::-webkit-outer-spin-button,
#view-image .sh-adj-row input[type=number]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

/* —— 源文件行（与处理状态合并的一行，贴在预览上方） —— */
/* 不再是独立卡片：去掉 .tl-list 的底/边框/投影/圆角与标题行的灰底分隔线，
   让它当一行普通信息坐在白卡上；芯片行（格式 / 静动 / 体积）已按用户要求移除。 */
#view-image #info {
  margin: 0; border: 0; border-radius: 0; background: transparent;
  box-shadow: none; overflow: visible;
}
#view-image #info .tl-list-hd { gap: 12px; flex-wrap: wrap; row-gap: 8px; padding: 0; background: transparent; border-bottom: 0; }
#view-image #imgLayout > .im-main { margin-top: 12px; }
#view-image #info .im-srcfile { flex: 0 1 auto; min-width: 0; display: inline-flex; align-items: baseline; }
#view-image #info #srcName { min-width: 0; max-width: 32ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#view-image #info .tl-list-hd-acts { flex: 1 1 auto; justify-content: flex-end; flex-wrap: wrap; row-gap: 6px; }
#view-image #info .tl-list-hd-acts #status { margin-right: 4px; }
/* 状态栏固定槽宽：文案长短变化不再推动右边的按钮（更换 / 重置 / 清空 / 保存）。
   槽宽 220px：够放下最长的常规文案（「已抵消回原位（4 步，无需重算）」约 187px），
   超出则省略号 + title 给全文。 */
#view-image #info .tl-list-hd-acts #status { flex: none; width: 220px; }
#view-image #status .status-tx {
  flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* 源文件操作与下载结果之间的发丝分隔（皮肤 DNA：只用 1px 线，不加底色） */
#view-image .im-actsep { width: 1px; height: 14px; background: var(--border-strong); flex: none; align-self: center; }
#view-image .tag, #view-anim .tag {
  background: var(--icon-bg); border: 1px solid var(--border);
  border-radius: 999px; padding: 2px 10px; font-size: var(--hx-t12); font-weight: 600; color: var(--text-2);
}
#view-image .muted, #view-anim .muted { color: var(--text-3); font-size: var(--hx-t12); }
#view-anim .file-info {
  display: block; background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-card); padding: 12px 14px; box-shadow: var(--shadow-1);
}
/* 空文件信息容器不占位（避免拖放区与参数面板间出现空条） */
#view-anim .file-info:empty { display: none; }
#view-anim .fi-head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin-bottom: 8px; }
#view-anim .fi-head b { font-size: var(--hx-t13); font-weight: 700; }
#view-anim .fi-list { display: flex; flex-wrap: wrap; gap: 6px; max-height: 84px; overflow: auto; }
#view-anim .fi-chip {
  background: var(--icon-bg); border: 1px solid var(--border); border-radius: var(--r-btn);
  padding: 2px 8px; font-size: var(--hx-t12); color: var(--text-2);
  max-width: 260px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* —— 主布局 ——
   动图 / 抽帧 / 单图处理都是「应用式外壳」：撑满一页、各列内部滚动；
   单图处理（#view-image）走 tl-* 统一布局，三栏由 .tl-main 承担。 */
#view-anim, #view-frames { height: 100vh; min-height: 0; display: flex; flex-direction: column; }
#view-anim .tool-body, #view-frames .tool-body {
  flex: 1; min-height: 0;
  display: flex; flex-direction: column;
}
#view-anim .tool-body, #view-frames .tool-body { overflow-y: auto; overscroll-behavior: contain; }

/* 单图处理：三栏（预览 | 参数详情 | 功能列）+ 高度自适应。
   整页高度由 helix 的 `#legacy-app #view-image{height:calc(100vh - nav)}` 锁定，
   这里把它逐层做成 flex column 并吃满：tool-body → 卡片 → 主区栅格行，
   预览舞台随之变高（此前是自然流 + max-height 上限，大屏下方空一大片）。
   参数按「功能」拆成多块面板，一次只显示当前那块；内容多时由 .tl-side-bd / .tl-stage-bd 内部滚。 */
#view-image { display: flex; flex-direction: column; min-height: 0; }
#view-image .tool-body { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
#view-image #imgLayout { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; margin-bottom: 0; }
/* 显式兜底：上面的 display:flex 会盖掉通用 [hidden]{display:none}，空态会露出空卡 */
#view-image #imgLayout[hidden] { display: none; }

#view-image .im-main {
  --tool-side: 320px; --tool-rail: 88px;
  grid-template-columns: minmax(0, 1fr) var(--tool-side, 320px) var(--tool-rail, 88px);
  /* 单行 minmax(0,1fr)：让栅格行吃满剩余高度（默认 auto 会被内容定死，卡片下方留白） */
  grid-template-rows: minmax(0, 1fr);
  flex: 1 1 auto; min-height: 0; max-height: none;
}
#view-image .im-stage { min-height: 0; }
#view-image .controls { padding-right: 0; }
/* 舞台标题行左侧：预览标题 + 撤销 / 重做 */
#view-image .im-hd-l { display: inline-flex; align-items: center; gap: 8px; min-width: 0; }
#view-image .im-hist { display: inline-flex; align-items: center; gap: 1px; flex: none; }
#view-image .im-ibtn {
  width: 24px; height: 24px; display: inline-grid; place-items: center;
  border: 1px solid transparent; border-radius: var(--r-btn);
  background: transparent; color: var(--text-2); cursor: pointer; padding: 0;
}
#view-image .im-ibtn svg { width: 15px; height: 15px; }
#view-image .im-ibtn:hover:not(:disabled) { background: var(--icon-bg); color: var(--text); border-color: var(--border); }
#view-image .im-ibtn:disabled { opacity: .35; cursor: default; }
#view-image .im-ibtn:disabled:hover { background: transparent; border-color: transparent; }
/* 舞台标题行右侧：输出徽标 + 缩放 + 对比原图 */
#view-image .im-hd-ctl { display: inline-flex; align-items: center; gap: 8px; flex: none; min-width: 0; }

/* —— 缩放控件：− 100% + —— */
#view-image .im-zoom {
  display: inline-flex; align-items: stretch; height: 24px;
  border: 1px solid var(--border); border-radius: var(--r-btn);
  overflow: hidden; background: var(--surface);
}
#view-image .im-zoom[hidden] { display: none; }
#view-image .im-zoom-b {
  width: 24px; border: 0; background: transparent; color: var(--text-2);
  font-size: 14px; line-height: 1; cursor: pointer; padding: 0;
  /* 图标字（− / +）与中间百分比同一套居中口径，否则低倍率下比数字高/低 1~2px */
  display: inline-flex; align-items: center; justify-content: center;
}
/* ⚠️ 上面「#view-image button{height:var(--ctl-h)}」(32px) 会把这三个按钮撑到 32，
   塞进 24px 的外框后被 overflow:hidden 从下往上裁掉一截，字看着比外框低 5px。
   这里把高度交还给 flex 拉伸（= 外框内容高 22px），字号行高自带居中即可。 */
#view-image .im-zoom-b,
#view-image .im-zoom-p { height: auto; min-height: 0; align-self: stretch; border-radius: 0; }
#view-image .im-zoom-b:hover:not(:disabled) { background: var(--icon-bg); color: var(--text); }
#view-image .im-zoom-b:disabled { opacity: .4; cursor: default; }
#view-image .im-zoom-p {
  min-width: 46px; border: 0; border-left: 1px solid var(--border); border-right: 1px solid var(--border);
  background: transparent; color: var(--text-2); cursor: pointer; padding: 0 8px;
  font-size: var(--hx-t12); font-variant-numeric: tabular-nums;
  /* 百分比文字在 24px 高按钮里必须精确垂直居中（button 默认行盒会偏下，用户已截图反馈） */
  display: inline-flex; align-items: center; justify-content: center; line-height: 1;
}
#view-image .im-zoom-p:hover { background: var(--icon-bg); color: var(--text); }
/* —— 对比原图：图标 + 文字，点击在「只看原图 / 只看结果」之间切换 —— */
#view-image .im-cmpbtn {
  display: inline-flex; align-items: center; gap: 5px;
  height: 24px; padding: 0 9px;
  border: 1px solid var(--border); border-radius: var(--r-btn);
  background: var(--surface); color: var(--text-2);
  font-size: var(--hx-t12); font-family: inherit; line-height: 1; cursor: pointer;
}
#view-image .im-cmpbtn svg { width: 14px; height: 14px; flex: none; }
#view-image .im-cmpbtn:hover { background: var(--icon-bg); color: var(--text); }
#view-image .im-cmpbtn.is-on { background: var(--accent); border-color: var(--accent); color: #fff; }
#view-image .im-cmpbtn.is-on svg { color: #fff; }
#view-image .im-cmpbtn[hidden] { display: none; }

/* —— 功能列：图标 + 文字的竖排小卡 —— */
/* 9 张卡（PNG 全开）≈ 568px。1440×900 栏高约 700px 放得下，更矮的屏才滚动 ——
   内容不超时 overflow 不产生滚动条，所以加它不会改变常见尺寸下的观感。
   加「抠图」后 10 张 ≈ 632px，1440×900 仍放得下，更矮的屏靠这里的滚动兜。 */
#view-image .im-rail {
  display: flex; flex-direction: column; gap: 8px; align-self: start; min-width: 0;
  max-height: 100%; overflow-y: auto; overscroll-behavior: contain;
}
#view-image .im-rail-c {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 5px;
  padding: 9px 4px; min-height: 56px;
  border: 1px solid var(--border); border-radius: var(--r-card);
  background: var(--surface); color: var(--text-2); box-shadow: var(--shadow-1);
  font-family: inherit; font-size: var(--hx-t11-5); line-height: 1.25; text-align: center;
  cursor: pointer; word-break: keep-all;
}
#view-image .im-rail-c svg { width: 18px; height: 18px; flex: none; }
#view-image .im-rail-c:hover { border-color: var(--border-strong); color: var(--text); background: var(--icon-bg); }
#view-image .im-rail-c.is-on { background: var(--accent); border-color: var(--accent); color: #fff; }
#view-image .im-rail-c.is-on:hover { background: var(--accent); color: #fff; }
/* 预留空位卡（.is-empty）已随「不再要预留位」一并删掉 —— 功能列现在只放真功能 */

/* 已选择文件后，拖放区收敛为细条，把高度让给预览与操作区（动图 / 抽帧仍在用） */
/* 收敛态：与空态保持同样的下间距 16px（此前是 8px，会造成上传瞬间下方模块跳动） */
#view-anim.loaded .drop, #view-frames.loaded .drop {
  display: flex; align-items: center; gap: 12px;
  padding: 7px 12px; margin: 0 0 16px; text-align: left;
}
#view-anim.loaded .drop .drop-icon, #view-frames.loaded .drop .drop-icon { width: 26px; height: 26px; margin: 0; flex: none; }
#view-anim.loaded .drop .drop-icon svg, #view-frames.loaded .drop .drop-icon svg { width: 15px; height: 15px; }
#view-anim.loaded .drop .drop-t1, #view-frames.loaded .drop .drop-t1 { margin: 0; font-size: var(--hx-t13); white-space: nowrap; }
#view-anim.loaded .drop .drop-t2, #view-frames.loaded .drop .drop-t2 { display: none; }
#view-anim.loaded .drop .btn, #view-frames.loaded .drop .btn { margin-left: auto; flex: none; padding: 0 12px; }

/* 载入后顶部拖放条彻底隐藏，对齐格式转换 #view-convert.loaded .drop{display:none}
   动图：源文件条已有「+ 添加」入口；单图：源文件条右侧有「更换图片」，
   两处都不需要顶部这条细拖放条冗余占位。 */
#view-anim.loaded .tool-body .drop,
#view-image.loaded .tool-body .drop { display: none; }

/* 源文件条是卡片首个模块：去掉 .tl-list 默认 14px 上外边距，避免顶部留白过大；
   并给主区补 14px 上外边距，使「源文件条 → 主区 → 生成结果」三模块间距统一（与格式转换一致） */
#view-anim #animTool > .tl-list:first-child { margin-top: 0; }
#view-anim #anMain { margin-top: var(--tool-gap, 14px); }

/* 窄屏：动图 / 抽帧退回归常文档流（各列不再内部滚动，结果/尾栏随文档流） */
@media (max-width: 960px) {
  #view-anim, #view-frames { height: auto; display: block; }
  #view-anim .tool-body, #view-frames .tool-body { display: block; overflow: visible; }
  /* 单图：主区在 900px 已由 .tl-main 堆叠成单列，退回自然流让整页自己滚
     （锁视口高会把预览反复压扁，历史上踩过）；高度锁在 helix.css 的窄屏媒体块里解除。
     功能列从竖排改横排（贴在参数卡下方），否则会变成一整列占满宽度；
     标题栏一行放不下（预览 + 撤销重做 + 徽标 + 缩放 + 对比原图），整行换成两行 */
  #view-image .tool-body { display: block; overflow: visible; }
  #view-image #imgLayout { display: block; }
  #view-image .im-main { max-height: none; grid-template-rows: none; }
  #view-image .im-stage { min-height: 260px; }
  #view-image .im-rail { flex-direction: row; flex-wrap: wrap; }
  #view-image .im-rail-c { flex: 1 1 70px; min-height: 52px; }
  #view-image .im-stagehd { flex-wrap: wrap; row-gap: 8px; }
  #view-image .im-hd-ctl { flex: 1 1 100%; justify-content: flex-end; flex-wrap: wrap; row-gap: 6px; }
  /* 合并后的源文件条：标题行在窄屏整行换成两块 —— 文件名独占第一行，
     状态下移与四个按钮同排左对齐，避免右侧操作被挤成三行 */
  #view-image #info .im-srcfile { flex: 1 1 100%; }
  #view-image #info #srcName { max-width: none; }
  #view-image #info .tl-list-hd-acts { flex: 1 1 100%; justify-content: flex-start; }
}

/* —— 参数分组卡片 —— */
#view-image .group, #view-anim .group, #view-frames .group {
  border: 1px solid var(--border); border-radius: var(--r-card);
  background: var(--surface); padding: 14px; margin-bottom: 12px;
  box-shadow: var(--shadow-1);
}
#view-image .group.enhance, #view-anim .group.enhance { background: var(--icon-bg); border-color: var(--border); }
#view-image .group h3, #view-anim .group h3, #view-frames .group h3 { margin: 0 0 10px; font-size: var(--hx-t14); font-weight: 700; }
#view-image .group.enhance h3, #view-anim .group.enhance h3 { color: var(--accent-text); }

/* 参数分组：单图的 #controls 现在住在 .tl-side 参数卡里（2026-10-30 同构格式转换），
   再套一层带边框的 .group 就是「卡里套卡」。这里把它退化成纯分组：
   无边框无阴影，靠一条发丝线分隔，h3 标题保留。 */
/* 参数面板化：一次只显示一个功能面板（功能列切换），面板内的 .group 因此不再需要分隔线 */
#view-image .controls .im-panel { display: none; }
#view-image .controls .im-panel.is-on { display: block; }
#view-image .controls .group {
  border: 0; border-radius: 0; background: transparent; box-shadow: none;
  padding: 0; margin: 0;
}
#view-image .controls .group + .group { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--border); }
#view-image .controls .group.enhance { background: transparent; }

/* —— 模块间距：文件信息条 → 参数卡片 ——
   根因：全站 .group 只声明 margin-bottom:16，.file-info 上下都没有外边距，
   两者相邻时边框直接贴死（实测 5 个视图 gap 全为 0），与其它模块 16px 节奏断裂。
   （此前没暴露是因为其它视图 file-info 后面跟的是自带 margin-top 的块级元素。）
   只在「file-info 紧邻 group」时补上间距，不动 group↔group 的既有节奏。 */
#view-anim .file-info + .group,
#view-convert .file-info + .group,
#view-pdfcompress .file-info + .group { margin-top: 16px; }
/* 分组描述并入标题行（行内灰色小字，省一行高度） */
#view-image .group-desc, #view-anim .group-desc, #view-frames .group-desc { font-size: var(--hx-t12); color: var(--text-3); font-weight: 400; margin-left: 6px; }

/* 动图参数网格 */
#view-anim .param-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px 14px; margin-top: 8px; }
#view-anim .param { display: flex; flex-direction: column; gap: 4px; }
#view-anim .param label { margin: 0; font-size: var(--hx-t12); color: var(--text-2); }
#view-anim .param select, #view-anim .param input[type=number] { width: 100%; }

/* 参数说明：ⓘ 图标 + 悬停浮层（替代原先会换行撑乱网格的 .phint 长文本） */
#view-anim .param-lab { display: flex; align-items: center; gap: 5px; min-height: 18px; }
/* label 单行 + 省略号兜底：任一格 label 换行都会把该格输入框顶低、破坏网格对齐 */
#view-anim .param-lab label { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#view-anim .param { position: relative; }
#view-anim .phint-i {
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 16px; height: 16px; padding: 0; border: 0; border-radius: 50%;
  background: none; color: var(--text-3); cursor: help;
  transition: color .15s var(--ease), background .15s var(--ease);
}
#view-anim .phint-i svg { display: block; width: var(--hx-t13); height: var(--hx-t13); }
#view-anim .phint-i:hover, #view-anim .phint-i:focus-visible { color: var(--text-2); background: var(--icon-bg); outline: none; }
#view-anim .phint-i:focus-visible { box-shadow: 0 0 0 2px var(--surface), 0 0 0 3.5px var(--text-3); }
/* 浮层锚在参数格左缘（不随 label 长度右移，故最右列也不会溢出视口）；
   max-content + max-width → 短文本贴合、超长自动换行。
   视觉规格与 #view-icons .ic-tip-b 对齐：字号 12 / text-2 / max-width 260 / shadow-2。 */
#view-anim .phint-i::after {
  content: attr(data-tip); position: absolute; top: 100%; left: 0; margin-top: 7px;
  width: max-content; max-width: min(260px, 70vw);
  padding: 8px 10px; border: 1px solid var(--border); border-radius: var(--r-btn);
  background: var(--surface); box-shadow: var(--shadow-2);
  color: var(--text-2); font-size: var(--hx-t12); font-weight: 400; line-height: 1.6;
  text-align: left; white-space: normal; overflow-wrap: anywhere;
  opacity: 0; visibility: hidden; pointer-events: none; z-index: 40;
  transition: opacity .15s var(--ease), transform .15s var(--ease), visibility .15s;
  transform: translateY(-3px);
}
#view-anim .phint-i:hover::after, #view-anim .phint-i:focus-visible::after {
  opacity: 1; visibility: visible; transform: translateY(0);
}

#view-anim .gen-row { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; margin-top: 16px; }

/* —— 预览卡片 ——
   单图处理已改用 .tl-stage（与格式转换同一张卡：hd / bd / ft 三段），
   这里只剩动图页还在用 .preview-wrap / .pv-stage 那套。 */
#view-anim .preview-wrap {
  border: 1px solid var(--border); border-radius: var(--r-card);
  background: var(--surface); padding: 12px;
  display: flex; flex-direction: column; gap: 8px;
  box-shadow: var(--shadow-1);
}
#view-anim .pv-title { font-size: var(--hx-t13); font-weight: 700; color: var(--text); display: flex; justify-content: space-between; align-items: center; gap: 8px; }
#view-anim .pv-title .badge {
  font-size: var(--hx-t11); font-weight: 600; color: var(--text-2);
  background: var(--icon-bg); border: 1px solid var(--border);
  border-radius: 999px; padding: 1px 8px;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#view-anim .pv-stage {
  position: relative; border-radius: 8px; overflow: hidden;
  background: repeating-conic-gradient(var(--checker-a) 0 25%, var(--checker-b) 0 50%) 50% / 16px 16px;
  display: flex; align-items: center; justify-content: center;
  min-height: 140px; max-height: 300px;
}
#view-anim .pv-stage img { max-width: 100%; max-height: 300px; display: block; }

/* 单图处理舞台：棋盘底走 .tl-stage-bd，内容层改「transform 缩放层」。
   缩放层 .im-inner 的宽高由 JS 写成图片原始像素，整体 translate + scale；
   两张图（结果 / 原图）绝对铺满同一盒子，任意缩放比例下对比都严格同框。
   transform-origin 固定左上，JS 以 0 0 为基准算居中 / 指针锚点缩放。 */
#view-image .h { display: none; }
#view-image .im-inner {
  position: absolute; left: 0; top: 0; transform-origin: 0 0;
  line-height: 0; will-change: transform; cursor: grab;
}
#view-image .im-inner.is-panning { cursor: grabbing; }
/* 支持裁剪的格式：拖动画面 = 画裁剪框，平移要按 Alt，所以默认不给抓手 */
#view-image .im-inner.no-pan { cursor: default; }

/* —— 进度浮层：叠在画布顶部中央，交代「正在做什么 + 百分比」——
   绝对定位是刻意的：一旦进文档流，出现 / 消失会让画布高度变化 → 触发 resize →
   重新 fit → 图跟着跳一下。浮层不占布局就没这问题。
   pointer-events 分两段：整条不吃事件（不挡拖动画面），只有取消按钮可点。 */
#view-image .im-prog {
  position: absolute; left: 50%; top: 10px; transform: translateX(-50%);
  z-index: 6; display: flex; align-items: center; gap: 8px;
  max-width: calc(100% - 20px); box-sizing: border-box;
  padding: 6px 10px; border: 1px solid var(--border); border-radius: 0;
  background: var(--surface); color: var(--text);
  font-size: var(--hx-t12); line-height: 1.4;
  font-variant-numeric: tabular-nums;
  pointer-events: none;
}
#view-image .im-prog[hidden] { display: none; }
#view-image .im-prog-tx {
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  max-width: 40ch;
}
#view-image .im-prog-pct { color: var(--text-2); flex: none; }
/* 进度条：一条 1px 发丝槽 + 实心填充（皮肤 DNA：零圆角、零投影） */
#view-image .im-prog-bar {
  flex: none; width: 84px; height: 3px; background: var(--icon-bg);
  display: block; overflow: hidden;
}
#view-image .im-prog-bar > i {
  display: block; height: 100%; width: 0; background: var(--accent);
  /* 数值每 60ms 才跳一次：给 120ms 线性过渡，肉眼看上去是连续在走，不是一格格蹦 */
  transition: width .12s linear;
}
#view-image .im-prog-x {
  pointer-events: auto; flex: none; height: 20px; padding: 0 8px;
  border: 1px solid var(--border); border-radius: 0; background: transparent;
  color: var(--text-2); font-size: var(--hx-t12); line-height: 1; cursor: pointer;
}
#view-image .im-prog-x:hover { background: var(--icon-bg); color: var(--text); }
#view-image .im-prog-x[hidden] { display: none; }
#view-image .im-img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: contain; max-width: none; max-height: none; display: block;
}
/* ⚠️ 必须写在 .im-img 之后且特异性更高：`.im-img{display:block}`(1,0,1) 会盖掉上面的
   `#view-image .h{display:none}`(1,0,1)，导致「原图」#origPreview 永远显示并压在结果之上 ——
   表现就是「镜像点了没反应」「旋转 90° 后中间多一张小图」。 */
#view-image .im-img.h { display: none; }
#view-image .im-stage-orig { pointer-events: none; }
/* 输出徽标（原尺寸 / 输出格式）挂在舞台标题行右侧，观感沿用旧的 pv-title badge */
#view-image .im-stagehd .badge {
  font-size: var(--hx-t11); font-weight: 600; color: var(--text-2);
  background: var(--icon-bg); border: 1px solid var(--border);
  border-radius: 999px; padding: 1px 8px;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#view-image .pv-meta, #view-anim .pv-meta { font-size: var(--hx-t12); color: var(--text-3); }

/* —— 生成结果一键流转到其它工具 —— */
.handoff {
  display: flex; align-items: center; flex-wrap: wrap; gap: 8px;
  margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--border);
}
.handoff .hf-label { font-size: var(--hx-t12); color: var(--text-3); flex: none; }
.handoff .btn { height: var(--ctl-h-sm); padding: 0 12px; font-size: var(--hx-t12); flex: none; }
.handoff .btn:hover { color: var(--text); border-color: var(--border-strong); }
.handoff .hf-hint { font-size: var(--hx-t11-5); color: var(--text-3); }

/* —— 结果区操作按钮行 —— */
#view-image .pv-acts, #view-anim .pv-acts { display: flex; gap: 8px; flex-wrap: wrap; }

/* —— 抽帧结果面板 ——
   （2026-10-30 动图抽帧已并入 tl-* 统一布局，这里只剩 #animMultiGrid 还在复用
   fp-cell / fp-grid / fp-idx / fp-dl 这套格子骨架；frames-panel / fp-head /
   fp-reexport 等随旧版式一起删除。） */
.fp-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(76px, 1fr)); gap: 8px;
  max-height: 264px; overflow-y: auto; scrollbar-width: thin; scrollbar-color: var(--border-strong) transparent;
}
.fp-cell {
  position: relative; border: 1px solid var(--border); border-radius: var(--r-btn);
  overflow: hidden; background: var(--icon-bg); cursor: zoom-in;
}
.fp-cell img {
  display: block; width: 100%; height: 56px; object-fit: contain;
  background: repeating-conic-gradient(var(--checker-a) 0 25%, var(--checker-b) 0 50%) 50% / 12px 12px;
}
.fp-idx, .fp-dl {
  position: absolute; top: 3px;
  font-size: var(--hx-t10); line-height: calc(14px * var(--hx-fsk, 1)); padding: 0 4px; border-radius: 3px;
  background: var(--float-bg); border: 1px solid var(--border); color: var(--text-2);
  font-variant-numeric: tabular-nums;
}
.fp-idx { left: 3px; }
.fp-dl { right: 3px; cursor: pointer; font-size: var(--hx-t11); }
.fp-dl:hover { color: var(--text); border-color: var(--border-strong); background: var(--surface); }

/* —— 三恒自动化多状态结果 ——
   复用抽帧面板的格子骨架，但组数量少（多为 2–10 组），格子放大给足预览面积；
   格底标注导出文件名，下载后能跟 ZIP 里的文件对得上号。 */
#animMultiGrid { grid-template-columns: repeat(auto-fill, minmax(132px, 1fr)); max-height: none; }
#animMultiGrid .fp-cell img { height: 84px; }
#animMultiGrid .fp-name {
  display: block; padding: 3px 6px;
  font-size: var(--hx-t10-5); line-height: 1.6; color: var(--text-3); text-align: center;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  border-top: 1px solid var(--border); background: var(--surface);
}

/* 单列生成结果也可点开大图 */
#animOut { cursor: zoom-in; }

/* —— 动图结果点击放大 lightbox ——
   复用 HELIX 弹窗令牌（--hx-*）；工具页可能被旧皮肤接管，故关键令牌带 fallback。
   z 轴取 --hx-z-dlg(200)，与站內其它弹窗同档；动图/动图以原分辨率播放。 */
.anim-lb {
  position: fixed; inset: 0; z-index: var(--hx-z-dlg, 200);
  display: flex; align-items: center; justify-content: center;
  padding: clamp(16px, 4vh, 56px) clamp(14px, 4vw, 56px);
  background: var(--hx-mask, rgba(6, 8, 13, 0.62));
  -webkit-backdrop-filter: blur(var(--hx-mask-blur, 3px));
          backdrop-filter: blur(var(--hx-mask-blur, 3px));
  cursor: zoom-out;
}
.anim-lb[hidden] { display: none; }
.anim-lb:not([hidden]) { animation: hxFade 0.18s var(--hx-ease, ease) both; }
.anim-lb-img {
  max-width: 100%; max-height: 100%;
  object-fit: contain; cursor: default;
  background: repeating-conic-gradient(rgba(255,255,255,0.07) 0 25%, rgba(0,0,0,0) 0 50%) 50% / 16px 16px;
}
.anim-lb-cap {
  position: fixed; left: 0; right: 0; bottom: 0;
  display: flex; align-items: center; justify-content: center; gap: 12px;
  padding: 11px 16px; pointer-events: none;
  font-family: var(--hx-mono); font-size: var(--hx-t12); letter-spacing: 0.02em;
  color: var(--hx-ink, #e9edf6); text-shadow: 0 1px 3px rgba(0, 0, 0, 0.7);
}
.anim-lb-cap b { font-weight: 400; color: var(--hx-acc, #5ef2d6); }
.anim-lb-x {
  position: fixed; top: 14px; right: 14px;
  width: 34px; height: 34px; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  -webkit-appearance: none; appearance: none;
  background: var(--hx-dlg-bg, rgba(8, 9, 14, 0.92));
  border: 1px solid var(--hx-dlg-line, rgba(255, 255, 255, 0.16));
  border-radius: var(--r-btn, 6px);
  color: var(--hx-dim, #9aa3b8); font-size: var(--hx-t20); line-height: 1; cursor: pointer;
  transition: border-color 0.2s, color 0.2s;
}
.anim-lb-x:hover { border-color: var(--hx-acc, #5ef2d6); color: var(--hx-acc, #5ef2d6); }
.anim-lb-x:focus-visible { outline: 1px solid var(--hx-acc, #5ef2d6); outline-offset: 2px; }

/* —— 框选裁剪 —— */
#view-image #outStage { touch-action: none; }
#view-image .pv-stage img { -webkit-user-drag: none; user-select: none; }
/* 选框：框内保持原样、框外压一层暗色（box-shadow 大扩散当遮罩，不用额外 DOM）。
   点框外不会取消选框 —— 只有底栏「重置选框」能回到整图。 */
#view-image #cropSel, #view-anim #cropSel {
  position: absolute; border: 1.5px dashed var(--text);
  background: transparent; pointer-events: none; display: none; box-sizing: border-box;
  box-shadow: 0 0 0 9999px var(--crop-mask, rgba(24, 24, 27, .38));
}
[data-theme="dark"] #view-image #cropSel,
[data-theme="dark"] #view-anim #cropSel { --crop-mask: rgba(0, 0, 0, .58); }
/* 八个调宽手柄（cropSel 内，pointer-events 单独打开） */
#view-image .crop-h {
  position: absolute; width: 8px; height: 8px;
  background: var(--surface); border: 1px solid var(--text); border-radius: 2px;
  pointer-events: auto;
}
#view-image .crop-h[data-dir=nw] { left: -4px; top: -4px; cursor: nwse-resize; }
#view-image .crop-h[data-dir=n]  { left: calc(50% - 4px); top: -4px; cursor: ns-resize; }
#view-image .crop-h[data-dir=ne] { right: -4px; top: -4px; cursor: nesw-resize; }
#view-image .crop-h[data-dir=w]  { left: -4px; top: calc(50% - 4px); cursor: ew-resize; }
#view-image .crop-h[data-dir=e]  { right: -4px; top: calc(50% - 4px); cursor: ew-resize; }
#view-image .crop-h[data-dir=sw] { left: -4px; bottom: -4px; cursor: nesw-resize; }
#view-image .crop-h[data-dir=s]  { left: calc(50% - 4px); bottom: -4px; cursor: ns-resize; }
#view-image .crop-h[data-dir=se] { right: -4px; bottom: -4px; cursor: nwse-resize; }
/* 底栏唯一按钮（重置选框）：靠左、与提示文字同一行 */
#view-image .crop-reset { flex: none; align-self: flex-start; }
/* 裁剪底栏：按钮 + 一行说明。⚠️ 显式写 [hidden]，否则下面的 display:flex 会盖掉 hidden */
#view-image #cropBar { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
#view-image #cropBar[hidden] { display: none; }
#view-image .crop-bar, #view-anim .crop-bar { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
/* 裁剪底栏现在是 .tl-stage-ft（舞台卡底栏）：没有选区时整条隐藏，不占一条空白发丝线。
   ⚠️ 必须显式写 [hidden]，上面的 display:flex 会盖掉 hidden 属性的 display:none。 */
#view-image .crop-bar[hidden] { display: none; }
#view-image #cropHint, #view-anim #cropHint { margin: 0; }

/* —— 状态条（圆点 + 文字，ok / err / busy 三态）—— */
#view-image .status, #view-anim .status, #view-frames .status {
  display: flex; align-items: center; gap: 7px;
  font-size: var(--hx-t12-5); color: var(--text-2); min-height: 18px; line-height: 1.5;
  /* 长提示（如「已就绪：N 个文件…」）在窄屏/长文本时允许折行而非撑破容器，
     避免单行溢出视口右缘（中文无空格、min-content 等于整串宽度，必须显式允许断行）。 */
  min-width: 0; overflow-wrap: anywhere; word-break: break-word;
}
#view-image .status::before, #view-anim .status::before, #view-frames .status::before {
  content: ""; width: 6px; height: 6px; border-radius: 50%;
  background: var(--text-3); flex: none;
}
#view-image .status.ok::before, #view-anim .status.ok::before, #view-frames .status.ok::before { background: var(--green); }
#view-image .status.err::before, #view-anim .status.err::before, #view-frames .status.err::before { background: var(--danger); }
#view-image .status.busy::before, #view-anim .status.busy::before, #view-frames .status.busy::before { background: var(--accent); }
#view-image .status.ok, #view-anim .status.ok, #view-frames .status.ok { color: var(--green-text); font-weight: 600; }
#view-image .status.err, #view-anim .status.err, #view-frames .status.err { color: var(--danger-text); font-weight: 600; }
#view-image .status.busy, #view-anim .status.busy, #view-frames .status.busy { color: var(--accent-text); }
/* 处理中：状态点呼吸 —— 单图处理不再用页面底部的 busybar（与状态行文案重复），
   进度反馈收敛到这一枚小圆点上 */
#view-image .status.busy::before { animation: imDotPulse 1.1s ease-in-out infinite; }
@keyframes imDotPulse {
  0%, 100% { opacity: .35; transform: scale(.8); }
  50% { opacity: 1; transform: scale(1.2); }
}

/* —— 动图专属：输出卡 —— */
#view-anim #animOutWrap { margin-top: 16px; }

/* === 动图时间剪辑 #view-cut（独立块，复用主站 design token，与 anim/frames 视觉一致） === */
#view-cut { color: var(--text); }
#view-cut .tool-body { width: 100%; max-width: var(--tool-maxw); margin: 0 auto; padding: 16px 20px 18px; }
#view-cut header h1 { font-size: var(--hx-t20); margin: 0; font-weight: 700; letter-spacing: 0.2px; }

#view-cut .drop {
  border: 1.5px dashed var(--border-strong); border-radius: var(--r-card);
  background: var(--surface); padding: 26px 24px 22px; text-align: center; margin: 0 0 16px;
  cursor: pointer; box-shadow: var(--shadow-1);
  transition: border-color 0.15s var(--ease), background 0.15s var(--ease);
}
#view-cut .drop:hover { border-color: var(--text-3); }
#view-cut .drop.over { border-color: var(--text); background: var(--icon-bg); }
#view-cut .drop-icon { width: 44px; height: 44px; margin: 0 auto 12px; border-radius: var(--r-btn); background: var(--icon-bg); color: var(--icon-fg); display: grid; place-items: center; }
#view-cut .drop-icon svg { width: 22px; height: 22px; }
#view-cut .drop-t1 { margin: 0 0 4px; font-size: var(--hx-t14); font-weight: 700; color: var(--text); }
#view-cut .drop-t2 { margin: 0 0 14px; font-size: var(--hx-t12); color: var(--text-3); }

#view-cut .btn, #view-cut button {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  font: inherit; font-size: var(--hx-t13); line-height: 1;
  height: var(--ctl-h); padding: 0 var(--ctl-px);
  border: 1px solid var(--border); border-radius: var(--r-btn);
  background: var(--surface); color: var(--text); cursor: pointer;
  transition: background 0.12s var(--ease), border-color 0.12s var(--ease), color 0.12s var(--ease);
}
#view-cut button:disabled { opacity: 0.45; cursor: not-allowed; }
#view-cut button:disabled:hover { background: var(--surface); border-color: var(--border); }
#view-cut button:hover, #view-cut .btn:hover { background: var(--icon-bg); border-color: var(--border-strong); }
#view-cut .btn-p { background: var(--text); border-color: var(--text); color: var(--bg); font-weight: 600; }
#view-cut .btn-p:hover { background: var(--btn-p-hover); border-color: var(--btn-p-hover); color: #fff; } /* hover 底色 --btn-p-hover 亮暗都是深灰，字必须固定白（用 var(--bg) 会在暗色下深字叠深底 1.5:1） */
#view-cut .btn-p:disabled { background: var(--border); border-color: var(--border); color: var(--text-3); cursor: not-allowed; opacity: 1; }
#view-cut .btn-sm { height: var(--ctl-h-sm); padding: 0 10px; font-size: var(--hx-t12); }

#view-cut label { display: block; font-size: var(--hx-t12); color: var(--text-2); margin: 7px 0 3px; }
#view-cut input[type=number], #view-cut select {
  font: inherit; font-size: var(--hx-t13); height: var(--ctl-h); padding: 0 8px;
  border: 1px solid var(--border); border-radius: var(--r-btn);
  background: var(--surface); color: var(--text); outline: none;
  transition: border-color 0.15s var(--ease), box-shadow 0.15s var(--ease);
}
#view-cut input[type=number]:focus, #view-cut select:focus { border-color: var(--text-3); box-shadow: 0 0 0 3px var(--overlay-dim); }
#view-cut .muted { color: var(--text-3); font-size: var(--hx-t12); }

#view-cut .group { border: 1px solid var(--border); border-radius: var(--r-card); background: var(--surface); padding: 14px; margin-bottom: 16px; box-shadow: var(--shadow-1); }
#view-cut .group h3 { margin: 0 0 10px; font-size: var(--hx-t14); font-weight: 700; }
#view-cut .group-desc { font-size: var(--hx-t12); color: var(--text-3); font-weight: 400; margin-left: 6px; }
#view-cut .param-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px 14px; }
#view-cut .param { display: flex; flex-direction: column; gap: 4px; }
#view-cut .param label { margin: 0; font-size: var(--hx-t12); color: var(--text-2); }
#view-cut .param select, #view-cut .param input[type=number] { width: 100%; }

#view-cut, #view-cut .tool-body { height: 100vh; min-height: 0; display: flex; flex-direction: column; }
#view-cut .tool-body { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; }

#view-cut.loaded .drop { display: flex; align-items: center; gap: 12px; padding: 7px 12px; margin: 0 0 16px; text-align: left; }
#view-cut.loaded .drop .drop-icon { width: 26px; height: 26px; margin: 0; flex: none; }
#view-cut.loaded .drop .drop-icon svg { width: 15px; height: 15px; }
#view-cut.loaded .drop .drop-t1 { margin: 0; font-size: var(--hx-t13); white-space: nowrap; }
#view-cut.loaded .drop .drop-t2 { display: none; }
#view-cut.loaded .drop .btn { margin-left: auto; flex: none; padding: 0 12px; }
@media (max-width: 960px) {
  #view-cut { height: auto; display: block; }
  #view-cut .tool-body { display: block; overflow: visible; }
}

/* 时间轴组件（帧缩略图 filmstrip：拖动选区不再盲选） */
#view-cut .timeline { margin: 4px 0; }
#view-cut .tl-track {
  position: relative; height: 58px; border: 1px solid var(--border); border-radius: var(--r-btn);
  background: var(--icon-bg); overflow: visible; user-select: none; touch-action: none; cursor: pointer;
}
/* 胶片层：缩略图 + 选区外压暗，统一裁在圆角内 */
#view-cut .tl-film { position: absolute; inset: 0; overflow: hidden; border-radius: var(--r-btn); pointer-events: none; }
/* 缩略图：每格宽度按帧实际时长占比（js 写入 left/width），图铺满格子高度 */
#view-cut .tl-ticks { position: absolute; inset: 0; }
#view-cut .tl-ticks img { position: absolute; top: 0; height: 100%; object-fit: cover; display: block; opacity: 0.88; }
/* 选区外的压暗（两侧各一块，由 js 定位），选中段保持原亮度 → 一眼看出保留了哪段 */
#view-cut .tl-dim { position: absolute; top: 0; bottom: 0; background: rgba(0, 0, 0, 0.46); }
/* 选区边界：只留一道强调色描边，不再用半透明色块盖住画面 */
#view-cut .tl-fill {
  position: absolute; top: 0; bottom: 0; z-index: 3;
  box-shadow: inset 0 0 0 1.5px var(--accent); background: transparent;
}
#view-cut .tl-handle {
  position: absolute; top: 0; bottom: 0; width: 14px; margin-left: -7px; z-index: 4;
  background: var(--surface); border: 1.5px solid var(--text); border-radius: 4px;
  cursor: ew-resize; box-shadow: var(--shadow-1);
}
#view-cut .tl-handle::after { content: ""; position: absolute; left: 50%; top: 50%; width: 2px; height: 16px; margin: -8px 0 0 -1px; background: var(--text-3); }
#view-cut .tl-playhead { position: absolute; top: -3px; bottom: -3px; width: 2px; margin-left: -1px; z-index: 5; background: var(--text); pointer-events: none; }
#view-cut .tl-playhead::after { content: ""; position: absolute; top: -5px; left: -4px; border: 5px solid transparent; border-top-color: var(--text); }
#view-cut .tl-note { font-size: var(--hx-t11); color: var(--text-3); min-height: 15px; line-height: 1.4; margin-top: 4px; }

/* === 动图时间剪辑 · tl-* 统一布局（2026-10-30，对齐「格式转换 / 动图抽帧」） ===
   预览卡 + 导出设置卡由 tool-layout.css 的 .tl-* 提供外壳；
   时间轴收进舞台底栏（.tl-stage-ft），外壳高度链 / 空态沿用本文件既有规则。 */
#view-cut #cutTool {
  display: flex; flex-direction: column;
  min-height: calc(100vh - 194px);   /* 口径同动图抽帧：138 + 收敛拖放细条 56 */
}
/* display:flex 会盖掉 UA 对 [hidden] 的 display:none（本项目高频坑），必须显式兜底 */
#view-cut #cutTool[hidden] { display: none; }
#view-cut #cutTool > .cut-main { flex: 1 1 auto; min-height: 0; }
#view-cut #cutTool > .result-bar { flex: none; }

/* 右侧导出设置卡 */
#view-cut .cut-side .param-grid { margin-top: 0; }
#view-cut .tl-param input[type=number] { width: 100%; }
#view-cut .cut-side-btns { display: flex; gap: 8px; margin-top: 14px; }
#view-cut .cut-side-btns .btn-p { flex: 1 1 auto; justify-content: center; }
#view-cut .cut-side .status { margin-top: 10px; }
#view-cut .cut-side-sub { font-size: var(--hx-t11); color: var(--text-3); font-weight: 400; letter-spacing: 0; }

/* 舞台底栏：时间轴 + 播放 / 裁剪操作 + 读数 */
#view-cut .cut-stage-ft { display: flex; flex-direction: column; gap: 2px; }
#view-cut .cut-ft-row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-top: 8px; }
#view-cut .cut-ft-row .btn { flex: none; }
#view-cut .cut-readout { font-size: var(--hx-t12); color: var(--text-3); font-variant-numeric: tabular-nums; min-width: 0; }
#view-cut .cut-readout b { color: var(--text-2); font-weight: 600; }

/* 结果条里的导出结果缩略图（GIF / APNG / WebP 动图直接播） */
#view-cut .cut-out-th {
  flex: none; height: 44px; min-width: 64px; padding: 0 4px;
  display: grid; place-items: center; overflow: hidden; border-radius: 3px;
  background-color: #fff;
  background-image:
    linear-gradient(45deg, #eceef1 25%, transparent 25%, transparent 75%, #eceef1 75%),
    linear-gradient(45deg, #eceef1 25%, transparent 25%, transparent 75%, #eceef1 75%);
  background-size: 10px 10px; background-position: 0 0, 5px 5px;
}
#view-cut .cut-out-th img { max-width: 96px; max-height: 100%; object-fit: contain; }
#view-cut .cut-hf-label { font-size: var(--hx-t12); color: var(--text-3); flex: none; margin-left: 4px; }

@media (max-width: 900px) {
  #view-cut #cutTool { min-height: 0; }   /* 窄屏退回文档流自然高度，由页面滚 */
}

#view-cut .status { display: flex; align-items: center; gap: 7px; font-size: var(--hx-t12-5); color: var(--text-2); min-height: 18px; line-height: 1.5; }
#view-cut .status::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--text-3); flex: none; }
#view-cut .status.ok::before { background: var(--green); }
#view-cut .status.err::before { background: var(--danger); }
#view-cut .status.busy::before { background: var(--accent); }
#view-cut .status.ok { color: var(--green-text); font-weight: 600; }
#view-cut .status.err { color: var(--danger-text); font-weight: 600; }
#view-cut .status.busy { color: var(--accent-text); }

/* === 格式转换 #view-convert（独立块，复用主站 design token，与 cut/anim 视觉一致） === */
#view-convert { color: var(--text); }
#view-convert .tool-body { width: 100%; max-width: var(--tool-maxw); margin: 0 auto; padding: 16px 20px 18px; }

/* 空状态：拖放框吃满一屏，与「批量调整尺寸」的空状态投放区同高（2026-10-29 用户要求统一）。
   70 = 面包屑 + 视图上内边距；有图时（.loaded）这条失效，#cvTool 自己的高度接管。 */
#view-convert:not(.loaded) .tool-body {
  display: flex; flex-direction: column;
  min-height: calc(100vh - 70px); box-sizing: border-box;
}
#view-convert:not(.loaded) #cvDrop {
  flex: 1 1 auto; display: flex; flex-direction: column;
  align-items: center; justify-content: center;
}

/* ============================================================
   空状态上传框统一：吃满一屏（2026-10-29 用户要求）
   ------------------------------------------------------------
   口径与「批量调整尺寸」「格式转换」一致：虚线框从面包屑下方一直铺到视口底部，
   不再是一个 200 多像素的小方块、下面留半屏空白。
   image / anim / frames / cut 的 .tool-body 本来就是撑满视口的 flex column，
   让 drop 变 flex:1 就够；pdfcompress 的 .tool-body 还是 block，得先变成 flex。
   所有规则都挂 :not(.loaded)：有图后整体失效，drop 回收成细条 / 回到文档流。
   ============================================================ */
#view-image:not(.loaded) .drop,
#view-anim:not(.loaded) .drop,
#view-frames:not(.loaded) .drop,
#view-cut:not(.loaded) .drop,
#view-pdfcompress:not(.loaded) .drop {
  flex: 1 1 auto; margin-bottom: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
}
#view-pdfcompress:not(.loaded) .tool-body {
  display: flex; flex-direction: column;
  min-height: calc(100vh - 70px); box-sizing: border-box;
}
#view-pdfcompress:not(.loaded) .tool-body > :not(.drop) { flex: none; }

/* 窄屏（≤960px）：image / anim / frames / cut 退回归常文档流、没有 flex 高度链，
   上面那套 flex:1 失效 → 改用 min-height 给同样的「一屏投放区」。
   Top 偏移各视图不同（有无功能条 / tab 条），按实测值分别扣。 */
@media (max-width: 960px) {
  #view-image:not(.loaded) .drop,
  #view-anim:not(.loaded) .drop,
  #view-frames:not(.loaded) .drop,
  #view-cut:not(.loaded) .drop { flex: none; min-height: calc(100vh - 106px); }
  #view-pdfcompress:not(.loaded) .drop { flex: none; min-height: calc(100vh - 158px); }
  /* 窄屏 .tool-body 不再占据视口高：否则 min-height 叠加后整页多出 70px 滚动 */
  #view-cut .tool-body { height: auto; }
}
#view-convert header h1 { font-size: var(--hx-t20); margin: 0; font-weight: 700; letter-spacing: 0.2px; }

#view-convert .drop {
  border: 1.5px dashed var(--border-strong); border-radius: var(--r-card); background: var(--surface);
  padding: 28px 16px; text-align: center; cursor: pointer; transition: border-color .15s, background .15s;
  box-shadow: var(--shadow-1);
}
#view-convert .drop:hover { border-color: var(--text-3); }
#view-convert .drop.over { border-color: var(--text); background: var(--icon-bg); }
#view-convert .drop-icon { width: 44px; height: 44px; margin: 0 auto 12px; border-radius: var(--r-btn); background: var(--icon-bg); color: var(--icon-fg); display: grid; place-items: center; }
#view-convert .drop-icon svg { width: 22px; height: 22px; }
#view-convert .drop-t1 { margin: 0 0 4px; font-size: var(--hx-t14); font-weight: 700; color: var(--text); }
#view-convert .drop-t2 { margin: 0 0 14px; font-size: var(--hx-t12); color: var(--text-3); }

#view-convert .btn, #view-convert button {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  height: var(--ctl-h); padding: 0 14px; font-size: var(--hx-t13); font-weight: 500;
  border-radius: var(--r-btn); border: 1px solid var(--border); background: var(--surface);
  color: var(--text); cursor: pointer; transition: background .12s, border-color .12s, color .12s;
}
#view-convert button:disabled { opacity: 0.45; cursor: not-allowed; }
#view-convert button:disabled:hover { background: var(--surface); border-color: var(--border); }
#view-convert button:hover, #view-convert .btn:hover { background: var(--icon-bg); border-color: var(--border-strong); }
#view-convert .btn-p { background: var(--text); border-color: var(--text); color: var(--bg); font-weight: 600; }
#view-convert .btn-p:hover { background: var(--btn-p-hover); border-color: var(--btn-p-hover); color: #fff; } /* hover 底色 --btn-p-hover 亮暗都是深灰，字必须固定白（用 var(--bg) 会在暗色下深字叠深底 1.5:1） */
#view-convert .btn-p:disabled { background: var(--border); border-color: var(--border); color: var(--text-3); cursor: not-allowed; opacity: 1; }
#view-convert .btn-sm { height: var(--ctl-h-sm); padding: 0 10px; font-size: var(--hx-t12); }
#view-convert .btn.ghost { background: transparent; border-color: transparent; color: var(--text-2); }
#view-convert .btn.ghost:hover { color: var(--text); background: var(--icon-bg); border-color: var(--border); }

#view-convert label { display: block; font-size: var(--hx-t12); color: var(--text-2); margin: 7px 0 3px; }
#view-convert input[type=number], #view-convert select {
  height: var(--ctl-h); padding: 0 10px; font-size: var(--hx-t13); color: var(--text);
  border: 1px solid var(--border); border-radius: var(--r-btn); background: var(--surface);
  outline: none; transition: border-color .12s, box-shadow .12s;
}
#view-convert input[type=number]:focus, #view-convert select:focus { border-color: var(--text-3); box-shadow: 0 0 0 3px var(--overlay-dim); }
#view-convert input[type=color] { width: 100%; height: var(--ctl-h); padding: 2px; border: 1px solid var(--border); border-radius: var(--r-btn); background: var(--surface); cursor: pointer; }
#view-convert input[type=range] { width: 100%; accent-color: var(--text); }

#view-convert .file-info { display: block; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-card); padding: 12px 14px; box-shadow: var(--shadow-1); font-size: var(--hx-t13); color: var(--text-2); }
#view-convert .file-info:empty { display: none; }

#view-convert .group { border: 1px solid var(--border); border-radius: var(--r-card); background: var(--surface); padding: 14px; margin-bottom: 16px; box-shadow: var(--shadow-1); }
#view-convert .group h3 { margin: 0 0 10px; font-size: var(--hx-t14); font-weight: 700; }
#view-convert .param-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 10px 14px; margin-top: 8px; }
#view-convert .param { display: flex; flex-direction: column; gap: 4px; }
#view-convert .param label { margin: 0; font-size: var(--hx-t12); color: var(--text-2); display: flex; justify-content: space-between; align-items: baseline; }
#view-convert .param select, #view-convert .param input { width: 100%; }
#view-convert .param input[type=number] { width: 100%; }
#view-convert .gen-row { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; margin-top: 16px; }

#view-convert .status { display: flex; align-items: center; gap: 7px; font-size: var(--hx-t12-5); color: var(--text-2); min-height: 18px; line-height: 1.5; }
#view-convert .status::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--text-3); flex: none; }
#view-convert .status.ok::before { background: var(--green); }
#view-convert .status.err::before { background: var(--danger); }
#view-convert .status.ok { color: var(--green-text); font-weight: 600; }
#view-convert .status.err { color: var(--danger-text); font-weight: 600; }

/* 结果列表 */
#view-convert .list-wrap { margin-top: 16px; border: 1px solid var(--border); border-radius: var(--r-card); background: var(--surface); box-shadow: var(--shadow-1); overflow: hidden; }
#view-convert .list-wrap.h { display: none; }
#view-convert .list-head { padding: 9px 14px; font-size: var(--hx-t12-5); font-weight: 700; color: var(--text-2); border-bottom: 1px solid var(--border); background: var(--icon-bg); }
#view-convert #cvListBody { max-height: 320px; overflow-y: auto; }
#view-convert .rrow { display: flex; align-items: center; gap: 10px; padding: 8px 14px; border-bottom: 1px solid var(--border); font-size: var(--hx-t13); }
#view-convert .rrow:last-child { border-bottom: none; }
#view-convert .rrow.err .rn { color: var(--text-3); text-decoration: line-through; }
#view-convert .rname { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#view-convert .rn { font-weight: 500; }
#view-convert .rdims { flex: none; font-size: var(--hx-t12); color: var(--text-2); white-space: nowrap; }
#view-convert .rdims .arrow { color: var(--text-3); margin: 0 4px; }
#view-convert .rdims .to { color: var(--text); font-weight: 600; }
#view-convert .fmt { flex: none; font-size: var(--hx-t10-5); font-weight: 700; letter-spacing: .4px; color: var(--text-2); background: var(--icon-bg); border: 1px solid var(--border); border-radius: 999px; padding: 1px 7px; }
#view-convert .rerr { flex: none; font-size: var(--hx-t12); color: var(--danger-text); }
#view-convert .rdl { flex: none; width: 24px; height: 24px; display: grid; place-items: center; border: 1px solid var(--border); border-radius: var(--r-btn); cursor: pointer; color: var(--text-2); font-size: var(--hx-t13); user-select: none; }
#view-convert .rdl:hover { background: var(--icon-bg); color: var(--text); border-color: var(--border-strong); }

/* 结果操作栏：外壳/间距由 .tl-result 统一提供，这里只补内部两栏 */
#view-convert .result-bar #cvZipName { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#view-convert .result-bar .btn { margin-left: auto; flex: none; }

/* 有图后顶部拖放条整块收起（2026-10-29）：整页可拖入 + 文件列表末位「+ 添加」
   两个入口已经覆盖「继续加图」，中间那条常驻的细拖放条纯属占高度。
   .loaded 由 JS 在导入后挂上，清空时摘掉 → 空状态仍有大拖放区可用。 */
#view-convert.loaded .drop { display: none; }

/* 文件列表末位「+ 添加」占位：它是虚线方块、不是按钮，
   下面 #view-convert button 的通用按钮外观会把它撑成 36px 高的实心按钮，
   必须用同优先级更高的选择器（id + class）压回来 */
#view-convert .tl-add {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 5px;
  height: auto; min-height: 86px; padding: 0;
  border: 1px dashed var(--text-3); background: transparent; color: var(--text-3);
  font-size: var(--hx-t12); font-weight: 500;
}
#view-convert .tl-add:hover { border-color: var(--text); background: var(--bg); color: var(--text); }
@media (max-width: 960px) {
  #view-convert .tool-body { padding: 16px 14px; }
  #view-convert .param-grid { grid-template-columns: 1fr 1fr; }
}

/* === PDF调整 #view-pdfcompress（独立块，镜像 convert 单元，复用主站 design token） === */
#view-pdfcompress { color: var(--text); }
#view-pdfcompress .tool-body { width: 100%; max-width: var(--tool-maxw); margin: 0 auto; padding: 16px 20px 18px; }
#view-pdfcompress header h1 { font-size: var(--hx-t20); margin: 0; font-weight: 700; letter-spacing: 0.2px; }

/* 功能条：视图顶部多功能切换（segmented，胶囊外壳 + 实心选中）
   外层 .pc-fnbar 全宽（与 .tb-head 左右边界对齐），内层 .pc-fnseg 按内容宽。
   .is-soon + .pc-soon「即将上线」留给后续待上线功能（当前两个功能均已上线）。 */
#view-pdfcompress .pc-fnbar { display: flex; align-items: center; width: 100%; margin: 14px 0 16px; }
#view-pdfcompress .pc-fnseg {
  display: flex; align-items: center; gap: 4px; flex-wrap: wrap;
  max-width: 100%; padding: 4px;
  border: 1px solid var(--border); border-radius: calc(var(--r-btn) + 4px);
  background: var(--surface); box-shadow: var(--shadow-1);
}
#view-pdfcompress .pc-fn {
  height: var(--ctl-h-sm); padding: 0 12px; font-size: var(--hx-t13); font-weight: 600;
  border: 1px solid transparent; border-radius: var(--r-btn);
  background: transparent; color: var(--text-2); white-space: nowrap;
}
#view-pdfcompress .pc-fn svg { width: var(--hx-t15); height: var(--hx-t15); flex: none; }
#view-pdfcompress .pc-fn:hover { background: var(--icon-bg); border-color: transparent; color: var(--text); }
#view-pdfcompress .pc-fn.is-on { background: var(--text); border-color: var(--text); color: var(--bg); }
#view-pdfcompress .pc-fn.is-on:hover { background: var(--btn-p-hover); border-color: var(--btn-p-hover); color: #fff; }
#view-pdfcompress .pc-fn.is-soon { color: var(--text-2); }
#view-pdfcompress .pc-fn.is-soon:hover { color: var(--text); }
#view-pdfcompress .pc-soon {
  flex: none; padding: 1px 6px; border-radius: 999px;
  font-size: var(--hx-t10-5); font-weight: 700; letter-spacing: .2px;
  color: var(--text-2); background: var(--icon-bg); border: 1px solid var(--border);
}

#view-pdfcompress .drop {
  border: 1.5px dashed var(--border-strong); border-radius: var(--r-card); background: var(--surface);
  padding: 28px 16px; text-align: center; cursor: pointer; transition: border-color .15s, background .15s;
  box-shadow: var(--shadow-1);
}
#view-pdfcompress .drop:hover { border-color: var(--text-3); }
#view-pdfcompress .drop.over { border-color: var(--text); background: var(--icon-bg); }
#view-pdfcompress .drop-icon { width: 44px; height: 44px; margin: 0 auto 12px; border-radius: var(--r-btn); background: var(--icon-bg); color: var(--icon-fg); display: grid; place-items: center; }
#view-pdfcompress .drop-icon svg { width: 22px; height: 22px; }
#view-pdfcompress .drop-t1 { margin: 0 0 4px; font-size: var(--hx-t14); font-weight: 700; color: var(--text); }
#view-pdfcompress .drop-t2 { margin: 0 0 14px; font-size: var(--hx-t12); color: var(--text-3); }

#view-pdfcompress .btn, #view-pdfcompress button {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  height: var(--ctl-h); padding: 0 14px; font-size: var(--hx-t13); font-weight: 500;
  border-radius: var(--r-btn); border: 1px solid var(--border); background: var(--surface);
  color: var(--text); cursor: pointer; transition: background .12s, border-color .12s, color .12s;
}
#view-pdfcompress button:disabled { opacity: 0.45; cursor: not-allowed; }
#view-pdfcompress button:disabled:hover { background: var(--surface); border-color: var(--border); }
#view-pdfcompress button:hover, #view-pdfcompress .btn:hover { background: var(--icon-bg); border-color: var(--border-strong); }
#view-pdfcompress .btn-p { background: var(--text); border-color: var(--text); color: var(--bg); font-weight: 600; }
#view-pdfcompress .btn-p:hover { background: var(--btn-p-hover); border-color: var(--btn-p-hover); color: #fff; } /* hover 底色 --btn-p-hover 亮暗都是深灰，字必须固定白（用 var(--bg) 会在暗色下深字叠深底 1.5:1） */
#view-pdfcompress .btn-p:disabled { background: var(--border); border-color: var(--border); color: var(--text-3); cursor: not-allowed; opacity: 1; }
#view-pdfcompress .btn-sm { height: var(--ctl-h-sm); padding: 0 10px; font-size: var(--hx-t12); }
#view-pdfcompress .btn.ghost { background: transparent; border-color: transparent; color: var(--text-2); }
#view-pdfcompress .btn.ghost:hover { color: var(--text); background: var(--icon-bg); border-color: var(--border); }

#view-pdfcompress label { display: block; font-size: var(--hx-t12); color: var(--text-2); margin: 7px 0 3px; }
#view-pdfcompress select {
  height: var(--ctl-h); padding: 0 10px; font-size: var(--hx-t13); color: var(--text);
  border: 1px solid var(--border); border-radius: var(--r-btn); background: var(--surface);
  outline: none; transition: border-color .12s, box-shadow .12s; width: 100%;
}
#view-pdfcompress select:focus { border-color: var(--text-3); box-shadow: 0 0 0 3px var(--overlay-dim); }
/* 文本 / 数字输入（导为图片的页码范围、自定义倍数）与 select 同规格 */
#view-pdfcompress input[type="text"],
#view-pdfcompress input[type="number"] {
  height: var(--ctl-h); padding: 0 10px; font-size: var(--hx-t13); font-family: inherit; color: var(--text);
  border: 1px solid var(--border); border-radius: var(--r-btn); background: var(--surface);
  outline: none; transition: border-color .12s, box-shadow .12s; width: 100%; box-sizing: border-box;
}
#view-pdfcompress input[type="text"]:focus,
#view-pdfcompress input[type="number"]:focus { border-color: var(--text-3); box-shadow: 0 0 0 3px var(--overlay-dim); }
#view-pdfcompress input::placeholder { color: var(--text-3); }

#view-pdfcompress .file-info { display: block; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-card); padding: 12px 14px; box-shadow: var(--shadow-1); font-size: var(--hx-t13); color: var(--text-2); }
#view-pdfcompress .file-info:empty { display: none; }

#view-pdfcompress .group { border: 1px solid var(--border); border-radius: var(--r-card); background: var(--surface); padding: 14px; margin-bottom: 16px; box-shadow: var(--shadow-1); }
#view-pdfcompress .group h3 { margin: 0 0 10px; font-size: var(--hx-t14); font-weight: 700; }
#view-pdfcompress .param-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(238px, 1fr)); gap: 10px 14px; margin-top: 8px; }
#view-pdfcompress .param { display: flex; flex-direction: column; gap: 4px; }
#view-pdfcompress .param label { margin: 0; font-size: var(--hx-t12); color: var(--text-2); }
#view-pdfcompress .hint { margin: 10px 0 0; font-size: var(--hx-t12); color: var(--text-3); line-height: 1.6; }
#view-pdfcompress .gen-row { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; margin-top: 16px; }

#view-pdfcompress .status { display: flex; align-items: center; gap: 7px; font-size: var(--hx-t12-5); color: var(--text-2); min-height: 18px; line-height: 1.5; }
#view-pdfcompress .status::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--text-3); flex: none; }
#view-pdfcompress .status.ok::before { background: var(--green); }
#view-pdfcompress .status.err::before { background: var(--danger); }
#view-pdfcompress .status.ok { color: var(--green-text); font-weight: 600; }
#view-pdfcompress .status.err { color: var(--danger-text); font-weight: 600; }

#view-pdfcompress .list-wrap { margin-top: 16px; border: 1px solid var(--border); border-radius: var(--r-card); background: var(--surface); box-shadow: var(--shadow-1); overflow: hidden; }
#view-pdfcompress .list-wrap.h { display: none; }
#view-pdfcompress .list-head { padding: 9px 14px; font-size: var(--hx-t12-5); font-weight: 700; color: var(--text-2); border-bottom: 1px solid var(--border); background: var(--icon-bg); }
#view-pdfcompress #pcListBody, #view-pdfcompress #pgListBody { max-height: 320px; overflow-y: auto; }
#view-pdfcompress .rrow { display: flex; align-items: center; gap: 10px; padding: 8px 14px; border-bottom: 1px solid var(--border); font-size: var(--hx-t13); }
#view-pdfcompress .rrow:last-child { border-bottom: none; }
#view-pdfcompress .rrow.err .rn { color: var(--text-3); text-decoration: line-through; }
#view-pdfcompress .rname { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#view-pdfcompress .rn { font-weight: 500; }
#view-pdfcompress .rdims { flex: none; font-size: var(--hx-t12); color: var(--text-2); white-space: nowrap; display: flex; align-items: center; gap: 6px; }
#view-pdfcompress .rdims .arrow { color: var(--text-3); }
#view-pdfcompress .rdims .to { color: var(--text); font-weight: 600; }
#view-pdfcompress .pct { font-size: var(--hx-t11); font-weight: 700; color: var(--text-3); background: var(--icon-bg); border: 1px solid var(--border); border-radius: 999px; padding: 1px 7px; }
#view-pdfcompress .pct.down { color: var(--green-text); border-color: var(--green); }
#view-pdfcompress .fmt { flex: none; font-size: var(--hx-t10-5); font-weight: 600; letter-spacing: .3px; color: var(--text-2); background: var(--icon-bg); border: 1px solid var(--border); border-radius: 999px; padding: 1px 7px; }
#view-pdfcompress .rerr { flex: none; font-size: var(--hx-t12); color: var(--danger-text); max-width: 320px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#view-pdfcompress .rdl { flex: none; width: 24px; height: 24px; display: grid; place-items: center; border: 1px solid var(--border); border-radius: var(--r-btn); cursor: pointer; color: var(--text-2); font-size: var(--hx-t13); user-select: none; }
#view-pdfcompress .rdl:hover { background: var(--icon-bg); color: var(--text); border-color: var(--border-strong); }

#view-pdfcompress .result-bar { display: flex; align-items: center; gap: 12px; margin-top: 14px; padding: 10px 14px; border: 1px solid var(--border); border-radius: var(--r-card); background: var(--surface); box-shadow: var(--shadow-1); font-size: var(--hx-t13); color: var(--text-2); flex-wrap: wrap; }
#view-pdfcompress .result-bar.h { display: none; }
#view-pdfcompress .result-bar #pcZipName, #view-pdfcompress .result-bar #pgZipName { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#view-pdfcompress .result-bar .btn { margin-left: auto; flex: none; }

#view-pdfcompress.loaded .drop { display: flex; align-items: center; gap: 12px; padding: 7px 12px; margin: 0 0 16px; text-align: left; }
#view-pdfcompress.loaded .drop .drop-icon { width: 26px; height: 26px; margin: 0; flex: none; }
#view-pdfcompress.loaded .drop .drop-icon svg { width: 15px; height: 15px; }
#view-pdfcompress.loaded .drop .drop-t1 { margin: 0; font-size: var(--hx-t13); white-space: nowrap; }
#view-pdfcompress.loaded .drop .drop-t2 { display: none; }
#view-pdfcompress.loaded .drop .btn { margin-left: auto; flex: none; padding: 0 12px; }
@media (max-width: 960px) {
  #view-pdfcompress .tool-body { padding: 16px 14px; }
}
/* 窄屏：结果行元素多（名 / 尺寸 / 格式 / 体积 / 下载），文件名单独占一行再排其余 */
@media (max-width: 640px) {
  #view-pdfcompress .rrow { flex-wrap: wrap; row-gap: 5px; }
  #view-pdfcompress .rrow .rname { flex: 1 1 100%; }
  #view-pdfcompress .rerr { max-width: 100%; }
}

/* ============================================================
   动图生成 · 同构格式转换（2026-10-30）
   结构：顶部源文件条（tl-list）+ 主区（tl-main：预览卡 + 参数卡）+ 底部生成结果（tl-list）
   —— 与 #view-convert 同一套 tl-* 骨架；本块只放动图特有的差异。
   ============================================================ */
/* 参数栏比默认 304 宽一点：这一栏要放 8 项参数，304 下 label 会被省略号吃掉 */
#view-anim .anim-main { --tool-side: 340px; }
/* 视频模式（预览卡隐藏）：参数卡定宽靠左，避免占满整行 */
#view-anim .anim-main:not(:has(#anPrev:not([hidden]))) { grid-template-columns: minmax(0, 1fr); }
#view-anim .anim-main:not(:has(#anPrev:not([hidden]))) .anim-side { width: var(--tool-side, 340px); max-width: 100%; justify-self: start; }

/* 预览卡（= .tl-stage，这里只补内部列的伸缩基线） */
#view-anim .an-prev { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; margin: 0; }
#view-anim .an-prev[hidden] { display: none; }

/* 预览底色：浅灰槽里两枚小签，选中实心（与顶部配置器 .pg-seg 同一套观感） */
#view-anim .an-bg { flex: none; display: flex; gap: 2px; padding: 2px; background: var(--icon-bg); border: 1px solid var(--border); border-radius: 3px; }
#view-anim .an-bg button { height: 20px; padding: 0 8px; border: 0; border-radius: 2px; cursor: pointer; background: transparent; color: var(--text-2); font-family: inherit; font-size: var(--hx-t11); line-height: 20px; transition: background .12s var(--ease), color .12s var(--ease); }
#view-anim .an-bg button:hover { color: var(--text); }
#view-anim .an-bg button.is-on { background: var(--accent); color: #fff; }
/* 结果 ↔ 源文件 切换（图标 + 文字，与抠图页 .cxo-cmpbtn 同一观感）
   文案 = 点它会看到的东西：看结果时写「查看源文件」，看源文件时写「查看结果」 */
#view-anim .an-viewsw { flex: none; display: inline-flex; align-items: center; gap: 5px; height: 24px; padding: 0 9px; border: 1px solid var(--border); border-radius: var(--r-btn); background: var(--surface); color: var(--text-2); font-family: inherit; font-size: var(--hx-t11-5); line-height: 1; cursor: pointer; }
#view-anim .an-viewsw svg { width: 14px; height: 14px; flex: none; }
#view-anim .an-viewsw:hover { background: var(--icon-bg); color: var(--text); }
#view-anim .an-viewsw.is-on { background: var(--accent); border-color: var(--accent); color: #fff; }
#view-anim .an-viewsw.is-on svg { color: #fff; }
#view-anim .an-viewsw[hidden] { display: none; }
#view-anim .an-viewsw:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* 舞台本体（= .tl-stage-bd，这里只补尺寸与黑底切换，棋盘底交给 tl-stage-bd） */
#view-anim .an-stage { flex: 1 1 auto; min-height: 160px; width: 100%; max-width: 100%; margin: 0 auto; display: grid; place-items: center; }
#view-anim .an-stage img { display: block; max-width: 100%; max-height: 100%; object-fit: contain; }
/* hidden 必须显式隐藏：上面的 display:block 会盖掉 hidden 属性的默认 display:none */
#view-anim .an-stage img[hidden] { display: none; }
/* 源视频预览层（视频模式）：与帧图共用同一个舞台，二者只显示其一 */
#view-anim .an-stage video { display: block; max-width: 100%; max-height: 100%; object-fit: contain; background: #000; }
#view-anim .an-stage video[hidden] { display: none; }
/* 预览底色：黑底只换背板，棋盘格与白底一起去掉（导出像素不受影响） */
#view-anim .an-stage[data-bg="black"] { background-color: #000; background-image: none; }
#view-anim .an-stage img:not([src]) { display: none; }
#view-anim .an-stage-empty { font-size: var(--hx-t12-5); color: #8a9099; line-height: 1.7; }
#view-anim .an-stage-empty[hidden] { display: none; }

/* 源文件条缩略图（复用 .tl-list-bd 的横向滚动手势） */
#view-anim .an-th { position: relative; flex: none; width: 88px; padding: 4px; border: 1px solid var(--border); border-radius: var(--r-btn); background: var(--surface); cursor: pointer; transition: border-color .12s var(--ease), box-shadow .12s var(--ease); }
#view-anim .an-th:hover { border-color: var(--border-strong); }
#view-anim .an-th.is-on { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
#view-anim .an-th-bx { height: 54px; display: grid; place-items: center; overflow: hidden; border-radius: 3px; background-color: #fff; background-image: linear-gradient(45deg, #eceef1 25%, transparent 25%, transparent 75%, #eceef1 75%), linear-gradient(45deg, #eceef1 25%, transparent 25%, transparent 75%, #eceef1 75%); background-size: 10px 10px; background-position: 0 0, 5px 5px; }
#view-anim .an-th-bx img { max-width: 100%; max-height: 54px; object-fit: contain; }
#view-anim .an-th-i { position: absolute; top: 2px; left: 2px; min-width: 15px; height: 15px; padding: 0 3px; border-radius: 3px; background: rgba(0,0,0,.55); color: #fff; font-size: var(--hx-t9-5); line-height: 15px; text-align: center; font-variant-numeric: tabular-nums; }
#view-anim .an-th-n { font-size: var(--hx-t10-5); color: var(--text-3); margin-top: 3px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 源文件移除按钮 */
#view-anim .an-th-x { position: absolute; top: 2px; right: 2px; width: 16px; height: 16px; padding: 0; border: 0; border-radius: 50%; background: rgba(0,0,0,.55); color: #fff; font-size: var(--hx-t12); line-height: 1; cursor: pointer; display: flex; align-items: center; justify-content: center; }
#view-anim .an-th-x:hover { background: #e5484d; }
/* 视频源：空盒上叠一个播放角标 */
#view-anim .an-th-vid .an-th-bx { position: relative; }
#view-anim .an-th-play { position: absolute; inset: 0; margin: auto; width: 26px; height: 26px; display: flex; align-items: center; justify-content: center; border-radius: 50%; background: rgba(0,0,0,.45); color: #fff; font-size: var(--hx-t10); }

/* 源文件条 / 生成结果条的副标题（总大小 · 模式 · 抽稀提示） */
.tl-list-sub { font-size: var(--hx-t12); color: var(--text-3); }

/* 生成结果条：内容块改纵向（结果预览比缩略图条宽），并去掉 preview-wrap 自带卡片描边（避免与 tl-list 双边框） */
#view-anim .anim-resultlist .tl-list-bd { display: block; overflow: visible; }
#view-anim .anim-resultlist .preview-wrap { border: 0; box-shadow: none; background: transparent; border-radius: 0; padding: 0; }

/* 生成结果态：动图直接铺在预览卡里播放，卡片底栏放下载与「送入其它工具」 */
#view-anim .an-prev-ft { flex: none; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding: 8px 12px; border-top: 1px solid var(--border); background: var(--bg); }
#view-anim .an-prev-ft[hidden] { display: none; }
#view-anim .an-prev-ftm { flex: 1 1 auto; min-width: 0; font-size: var(--hx-t12); color: var(--text-3); font-variant-numeric: tabular-nums; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#view-anim .an-prev-ft .btn { flex: none; }
#view-anim .an-prev-ft .an-hf { background: var(--surface); }
#view-anim .an-prev-ft .an-hf:hover { border-color: var(--border-strong); color: var(--text); }

/* 参数卡内的「生成 / 多状态 / 清空」按钮在窄栏里竖排、整宽 */
#view-anim .anim-side .gen-row { flex-direction: column; align-items: stretch; gap: 8px; margin-top: 12px; }
#view-anim .anim-side .gen-row .btn { width: 100%; justify-content: center; white-space: normal; }
#view-anim .anim-side .gen-row .status { text-align: left; }

@media (max-width: 640px) {
  #view-anim .an-stage { min-height: 200px; }
  #view-anim .an-stage img { max-height: 240px; }
  /* 头部元素多（标题 / 元信息 / 底色 / 返回）：390 下标题曾被挤成 0 宽，改为换行 */
  #view-anim .tl-stage-hd { flex-wrap: wrap; row-gap: 6px; }
  #view-anim .tl-stage-m { order: 9; flex: 1 1 100%; }
  /* 窄屏参数卡不再内部滚动，整页自然变高 */
  #view-anim .anim-side, #view-anim .anim-side .tl-side-bd { overflow: visible; }
}

/* ============================================================
   格式转换 · 布局重构（2026-10-29）
   预览置顶 + 参数在右 + 横向缩略图；拍平背景在舞台上实时可见
   ============================================================ */
#view-convert .tool-body { max-width: var(--tool-maxw); }
/* 有图时整块按视口高定高，舞台吃剩余，缩略图条 + 结果条固定在底部。
   不加这条：1920×1080 下内容到 730 就结束、下方空 350px；1366×768 下反而溢出 9px 出滚动条。
   138 = 面包屑 + 上下内边距（实测值，多 4px 就会出竖向滚动条）；
   2026-10-29 起有图后顶部拖放条整块收起，比原先的 194 少了那条的 56。 */
#view-convert #cvTool {
  display: flex; flex-direction: column;
  /* 用 min-height 而不是 height：够高就吃满（舞台 absorb 剩余），
     参数变多时（JPEG/BMP 会多出「质量 + 背景色」两项）允许整块长高、页面滚动 ——
     写死 height 的话右栏会溢出盖住下面的文件列表条（1366×768 实测踩到）。 */
  min-height: calc(100vh - 138px);
}
/* display:flex 会盖掉 UA 对 [hidden] 的 display:none（本项目高频坑），必须显式兜底 */
#view-convert #cvTool[hidden] { display: none; }
#view-convert #cvTool > .cv-main { flex: 1 1 auto; min-height: 0; }
#view-convert #cvTool > .cv-thumbsbar,
#view-convert #cvTool > .result-bar { flex: none; }
/* 预览卡 / 参数卡 / 列表条的外壳与标题行统一由 tool-layout.css 的 .tl-* 提供，
   这里只剩「格式转换」特有的部分 */
#view-convert .cv-side .param-grid { margin-top: 0; }
#view-convert .cv-side-btns { display: flex; gap: 8px; margin-top: 14px; }
#view-convert .cv-side-btns .btn-p { flex: 1 1 auto; justify-content: center; }
#view-convert .cv-side .status { margin-top: 10px; }

#view-convert .cv-th {
  position: relative; flex: none; width: 116px; padding: 5px;
  border: 1px solid var(--border); border-radius: var(--r-btn);
  background: var(--surface); cursor: pointer;
  transition: border-color .12s var(--ease), box-shadow .12s var(--ease);
}
#view-convert .cv-th:hover { border-color: var(--border-strong); }
#view-convert .cv-th.is-on { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
#view-convert .cv-th-bx {
  height: 56px; display: grid; place-items: center; overflow: hidden;
  border-radius: 3px; background-color: #fff;
  background-image:
    linear-gradient(45deg, #eceef1 25%, transparent 25%, transparent 75%, #eceef1 75%),
    linear-gradient(45deg, #eceef1 25%, transparent 25%, transparent 75%, #eceef1 75%);
  background-size: 10px 10px;
  background-position: 0 0, 5px 5px;
}
#view-convert .cv-th-bx img { max-width: 100%; max-height: 56px; object-fit: contain; }
#view-convert .cv-th-n {
  font-size: var(--hx-t11); color: var(--text-2); margin-top: 4px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#view-convert .cv-th-d {
  font-size: var(--hx-t11); color: var(--text-3); font-variant-numeric: tabular-nums;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#view-convert .cv-th-d .to { color: var(--text); font-weight: 600; }
#view-convert .cv-th-d .save { color: var(--green-text); font-weight: 600; }
#view-convert .cv-th-d .bad { color: var(--danger-text); }
#view-convert .cv-th-dl {
  position: absolute; bottom: 24px; right: 4px; width: 18px; height: 18px;
  display: grid; place-items: center; border-radius: 3px;
  background: var(--accent); color: #fff; font-size: var(--hx-t11); line-height: 1;
  opacity: 0; transition: opacity .12s var(--ease); cursor: pointer;
}
#view-convert .cv-th:hover .cv-th-dl { opacity: 1; }

/* ============================================================
   动图抽帧 · 布局重构（2026-10-30）
   与「格式转换」共用 tool-layout.css 的 tl-* 统一四件套：
   左预览舞台 + 右操作卡 + 横向帧列表条 + 底部结果条。
   外壳 / 空态 / 拖放条收敛沿用本文件既有的 #view-frames 共享规则。
   ============================================================ */
/* 有源文件时整块按视口高定高（口径同 #view-convert #cvTool 的 138px，但抽帧页
   收敛后的拖放细条没有像 convert 那样 display:none，仍占 56px → 138 + 56 = 194） */
#view-frames #framesTool {
  display: flex; flex-direction: column;
  min-height: calc(100vh - 194px);
}
/* display:flex 会盖掉 UA 对 [hidden] 的 display:none（本项目高频坑），必须显式兜底 */
#view-frames #framesTool[hidden] { display: none; }
#view-frames #framesTool > .fr-main { flex: 1 1 auto; min-height: 0; }
#view-frames #framesTool > .fr-thumbsbar,
#view-frames #framesTool > .result-bar { flex: none; }

/* 右侧操作卡：主按钮行 + 状态 + 抽稀重导出（发丝线分隔的下半段） */
#view-frames .fr-side-btns { display: flex; gap: 8px; }
#view-frames .fr-side-btns .btn-p { flex: 1 1 auto; justify-content: center; }
#view-frames .fr-side .status { margin-top: 10px; }
#view-frames .fr-reexport {
  margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--border);
  display: flex; flex-direction: column; gap: 10px;
}
#view-frames .fr-reexport-t { font-size: var(--hx-t12); color: var(--text-3); letter-spacing: .06em; }
#view-frames .fr-reexport .btn-p { width: 100%; justify-content: center; }
/* 共享规则 #view-frames input[type=number]{width:76px} 会压过 .tl-param input{width:100%}，右卡内统一满宽 */
#view-frames .tl-param input[type=number] { width: 100%; }

/* 帧缩略图：规格与「格式转换」cv-th 完全一致（116px 宽 / 5px padding / 图盒高 56px） */
#view-frames .fr-th {
  position: relative; flex: none; width: 116px; padding: 5px;
  border: 1px solid var(--border); border-radius: var(--r-btn);
  background: var(--surface); cursor: pointer;
  transition: border-color .12s var(--ease), box-shadow .12s var(--ease);
}
#view-frames .fr-th:hover { border-color: var(--border-strong); }
#view-frames .fr-th.is-on { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
#view-frames .fr-th-bx {
  height: 56px; display: grid; place-items: center; overflow: hidden;
  border-radius: 3px; background-color: #fff;
  background-image:
    linear-gradient(45deg, #eceef1 25%, transparent 25%, transparent 75%, #eceef1 75%),
    linear-gradient(45deg, #eceef1 25%, transparent 25%, transparent 75%, #eceef1 75%);
  background-size: 10px 10px;
  background-position: 0 0, 5px 5px;
}
#view-frames .fr-th-bx img { max-width: 100%; max-height: 56px; object-fit: contain; }
#view-frames .fr-th-n {
  font-size: var(--hx-t11); color: var(--text-2); margin-top: 4px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#view-frames .fr-th-d {
  font-size: var(--hx-t11); color: var(--text-3); font-variant-numeric: tabular-nums;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#view-frames .fr-th-dl {
  position: absolute; bottom: 24px; right: 4px; width: 18px; height: 18px;
  display: grid; place-items: center; border-radius: 3px;
  background: var(--accent); color: #fff; font-size: var(--hx-t11); line-height: 1;
  opacity: 0; transition: opacity .12s var(--ease); cursor: pointer;
}
#view-frames .fr-th:hover .fr-th-dl { opacity: 1; }

/* 结果条里的「继续处理」组 */
#view-frames .fr-hf-label { font-size: var(--hx-t12); color: var(--text-3); flex: none; margin-left: 4px; }
#view-frames .fr-hf-hint { font-size: var(--hx-t11-5); color: var(--text-3); }
#view-frames .result-bar .btn { flex: none; }

@media (max-width: 900px) {
  #view-frames #framesTool { min-height: 0; }   /* 窄屏退回文档流自然高度，由页面滚 */
}

@media (max-width: 900px) {
  #view-convert .cv-main { grid-template-columns: 1fr; gap: 12px; }
  #view-convert .cv-stage { min-height: 240px; }
  #view-convert .cv-stage-inner img { max-height: 280px; }
}

/* ============================================================
   保存弹窗（#view-image）—— 对齐 WPS「另存为」：左预览 + 右导出设置
   皮肤 DNA 照旧：零圆角、1px 发丝线、零投影；层次靠遮罩压暗。
   这里的设置只作用于这一次导出，不动画布、不进撤销栈。
   ============================================================ */
#view-image .im-save-mask {
  position: fixed; inset: 0; z-index: var(--hx-z-tool, 400);
  display: flex; align-items: center; justify-content: center; padding: 24px;
  overflow: auto;
  background: var(--hx-mask, rgba(6, 8, 13, 0.62));
  -webkit-backdrop-filter: blur(var(--hx-mask-blur, 3px));
  backdrop-filter: blur(var(--hx-mask-blur, 3px));
  animation: imMaskIn 0.14s var(--ease, ease) both;
}
#view-image .im-save-mask[hidden] { display: none; }
@keyframes imMaskIn { from { opacity: 0; } to { opacity: 1; } }

#view-image .im-save-dlg {
  width: min(880px, 100%); max-height: calc(100vh - 48px); flex: 0 1 auto;
  display: flex; flex-direction: column; overflow: hidden;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: 0;
  box-shadow: none;
  animation: imDlgIn 0.16s var(--ease, ease) both;
}
@keyframes imDlgIn { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }

/* —— 头 —— */
#view-image .im-save-hd {
  flex: none; height: 54px; padding: 0 14px 0 26px;
  display: flex; align-items: center; justify-content: space-between;
  border-bottom: 1px solid var(--border);
}
#view-image .im-save-t { font-size: var(--hx-t15); font-weight: 700; letter-spacing: 0.2px; }
#view-image .im-save-dlg .im-save-x,
#view-image .im-save-dlg .im-ib {
  height: 24px; padding: 0; border: 1px solid transparent; border-radius: var(--r-btn);
  background: transparent; color: var(--text-3);
}
#view-image .im-save-dlg .im-save-x { width: 30px; height: 30px; }
#view-image .im-save-dlg .im-ib { width: 30px; height: 30px; flex: none; }
#view-image .im-save-dlg .im-save-x svg { width: 17px; height: 17px; }
#view-image .im-save-dlg .im-ib svg { width: 16px; height: 16px; }
#view-image .im-save-dlg .im-save-x:hover,
#view-image .im-save-dlg .im-ib:hover { background: var(--icon-bg); border-color: var(--border); color: var(--text); }
#view-image .im-save-dlg .im-ib.is-on { color: var(--text); background: var(--icon-bg); border-color: var(--border); }

/* —— 主体：左预览 / 右表单 —— */
#view-image .im-save-bd { flex: 1; min-height: 430px; display: grid; grid-template-columns: 340px 1fr; }
#view-image .im-save-pv {
  display: flex; flex-direction: column; gap: 12px; padding: 18px;
  background: var(--icon-bg); border-right: 1px solid var(--border);
  min-height: 0;
}
/* 预览图用 absolute + inset 定位：百分比 max-height 在 grid 子项里会解析成 indefinite
   （窄屏下实测图被撑出框、只露中间一截），改成四条边钉死再 object-fit: contain */
#view-image .im-save-pvbox {
  flex: 1; min-height: 0; position: relative; display: block; padding: 0;
  background: var(--surface); border: 1px solid var(--border);
  /* 棋盘格：能一眼看出导出的图有没有透明底 */
  background-image:
    linear-gradient(45deg, var(--icon-bg) 25%, transparent 25%, transparent 75%, var(--icon-bg) 75%),
    linear-gradient(45deg, var(--icon-bg) 25%, transparent 25%, transparent 75%, var(--icon-bg) 75%);
  background-size: 16px 16px, 16px 16px;
  background-position: 0 0, 8px 8px;
  background-color: var(--surface);
  overflow: hidden;
}
#view-image .im-save-pvbox img {
  position: absolute; left: 8px; top: 8px;
  width: calc(100% - 16px); height: calc(100% - 16px);
  object-fit: contain; display: block;
}
#view-image .im-save-pvft { flex: none; font-size: var(--hx-t12); color: var(--text-3); text-align: center; line-height: 1.7; }
/* 结果图还没解码完（打开弹窗、改尺寸 / 换格式后重出图）：先给转圈，别留一块空棋盘格。
   用 ::after 而不是塞 DOM：img 换 src 时浏览器会保留旧画面，转圈叠在上面正好表示「旧的别信」。 */
#view-image .im-save-pvbox.is-loading::after {
  content: ""; position: absolute; left: 50%; top: 50%;
  width: 18px; height: 18px; margin: -9px 0 0 -9px;
  box-sizing: border-box; border-radius: 50%;
  border: 2px solid color-mix(in srgb, var(--text-3) 62%, transparent); border-top-color: var(--text);
  animation: tool-spin 0.7s linear infinite;
}

/* 顶部对齐（不是垂直居中）：设置行数随格式 / 状态增减，居中会让第一行随内容上下浮动，
   用户的视线每次都要重找「尺寸」那一行。锚定顶部后，各行位置恒定。 */
#view-image .im-save-form { padding: 24px 32px 22px; overflow: auto; min-height: 0; display: flex; flex-direction: column; }
#view-image .im-f-row { display: grid; grid-template-columns: 80px 1fr; align-items: center; gap: 18px; min-height: 48px; }
/* 动图只能原样导出：尺寸 / 压缩 / 裁边三行整块收起（display:grid 会盖掉浏览器默认的 [hidden]） */
#view-image .im-f-row[hidden] { display: none; }
#view-image .im-f-lab { font-size: var(--hx-t13); color: var(--text-3); white-space: nowrap; }
#view-image .im-f-ctl { display: flex; align-items: center; gap: 10px; min-width: 0; flex-wrap: wrap; }
#view-image .im-f-tip { margin: 4px 0 16px 98px; font-size: var(--hx-t12); color: var(--text-3); line-height: 1.7; }
/* [hidden] 必须显式写：.im-f-tip 是块级元素，一旦将来给它加 display 就会被盖掉 */
#view-image .im-f-tip[hidden] { display: none; }

/* —— 输入类控件（比工具按钮矮一档，弹窗里更紧凑）—— */
#view-image .im-save-dlg input[type="number"],
#view-image .im-save-dlg input[type="text"],
#view-image .im-save-dlg select {
  height: 34px; padding: 0 10px; box-sizing: border-box;
  font: inherit; font-size: var(--hx-t13); color: var(--text);
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-btn);
  outline: none; min-width: 0;
}
#view-image .im-save-dlg input[type="number"]:focus,
#view-image .im-save-dlg input[type="text"]:focus,
#view-image .im-save-dlg select:focus { border-color: var(--text-3); }
#view-image .im-save-dlg input:disabled,
#view-image .im-save-dlg select:disabled { opacity: 0.5; cursor: not-allowed; background: var(--icon-bg); }
#view-image .im-save-dlg input[type="number"]::-webkit-outer-spin-button,
#view-image .im-save-dlg input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
#view-image .im-save-dlg input[type="number"] { -moz-appearance: textfield; appearance: textfield; }

/* 尺寸行：宽 高 % 锁 重置
   每个「输入 + 单位」包成一对（.im-pair）：允许换行时只在成对之间断，数字和它的单位不会被拆开 */
#view-image .im-dim { flex-wrap: nowrap; gap: 4px; }
#view-image .im-dim .im-pair { display: inline-flex; align-items: center; gap: 4px; flex: none; }
#view-image .im-dim input#imSzW, #view-image .im-dim input#imSzH { width: 84px; text-align: right; }
#view-image .im-dim input#imSzPct { width: 64px; text-align: right; }
#view-image .im-dim .im-u { font-size: var(--hx-t12); color: var(--text-3); }
#view-image .im-dim .im-x { color: var(--text-3); margin: 0 2px; flex: none; }
#view-image .im-dim .im-ib { margin-left: 8px; }
#view-image .im-dim .im-ib + .im-ib { margin-left: 2px; }

/* 品质 / 体积：自绘单选（参考 WPS 的圆点 + 文字，不用胶囊按钮） */
#view-image .im-seg { display: flex; align-items: center; gap: 26px; }
#view-image .im-save-dlg .im-rd,
#view-image .im-save-dlg .im-seg label {
  display: inline-flex; align-items: center; gap: 6px; cursor: pointer;
  font-size: var(--hx-t13); color: var(--text); height: auto; padding: 0;
  border: 0; background: none; border-radius: 0;
}
#view-image .im-save-dlg .im-rd input,
#view-image .im-save-dlg .im-seg input { position: absolute; opacity: 0; pointer-events: none; }
#view-image .im-save-dlg .im-rd span::before,
#view-image .im-save-dlg .im-seg label span::before {
  content: ""; display: inline-block; vertical-align: -2px;
  width: 15px; height: 15px; margin-right: 8px; box-sizing: border-box;
  border: 1.5px solid var(--border-strong); border-radius: 50%;
  background: var(--surface);
  transition: border-color 0.12s var(--ease), box-shadow 0.12s var(--ease);
}
#view-image .im-save-dlg .im-rd input:checked + span::before,
#view-image .im-save-dlg .im-seg label input:checked + span::before {
  border-color: var(--text); box-shadow: inset 0 0 0 3px var(--surface), inset 0 0 0 8px var(--text);
}
#view-image .im-save-dlg input[type="checkbox"] + span::before { border-radius: 2px; }
#view-image .im-save-dlg input[type="checkbox"]:checked + span::before {
  border-color: var(--text); background: var(--text);
  box-shadow: inset 0 0 0 3px var(--surface);
}
#view-image .im-save-dlg .im-rd:has(input:disabled),
#view-image .im-save-dlg .im-seg label:has(input:disabled) { opacity: 0.45; cursor: not-allowed; }

#view-image .im-volbox { display: inline-flex; align-items: center; gap: 4px; }
#view-image .im-volbox input#imVolNum { width: 150px; }
#view-image .im-volbox select { width: 74px; }

/* 格式名称 + 保存位置 */
#view-image .im-name { flex: 1 1 auto; }
#view-image .im-name input#imSaveName { flex: 1 1 0; min-width: 0; }
#view-image .im-name select#imSaveExt { width: 132px; flex: none; }
#view-image .im-path { flex: 1 1 auto; flex-wrap: nowrap; }
#view-image .im-pathv {
  flex: 1 1 auto; min-width: 0; height: 34px; box-sizing: border-box;
  display: flex; align-items: center; padding: 0 10px;
  font-size: var(--hx-t13); color: var(--text-2);
  background: var(--icon-bg); border: 1px solid var(--border); border-radius: var(--r-btn);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* —— 底栏 —— */
#view-image .im-save-ft {
  flex: none; min-height: 68px; padding: 12px 24px;
  display: flex; align-items: center; gap: 12px;
  border-top: 1px solid var(--border);
}
#view-image .im-save-est {
  margin-right: auto; font-size: var(--hx-t12); color: var(--text-3);
  display: flex; align-items: center; gap: 10px; min-width: 0;
}
#view-image .im-save-est b { font-weight: 600; color: var(--text-2); }
#view-image .im-save-est .im-bad { color: var(--danger-text); }
/* 体积 / 尺寸结果没算出来时（估算、去透明边、导出）：文字前面挂一颗小转圈 */
#view-image .im-save-est.is-loading::before {
  content: ""; flex: none; width: 11px; height: 11px; box-sizing: border-box;
  border-radius: 50%;
  border: 1.5px solid color-mix(in srgb, var(--text-3) 62%, transparent); border-top-color: var(--text);
  animation: tool-spin 0.7s linear infinite;
}
#view-image .im-save-dlg .im-save-ft .btn { height: var(--ctl-h-sm); flex: none; }
#view-image .im-save-dlg button.is-busy {
  /* 这颗按钮高度是写死的（.im-save-ft .btn { height: var(--ctl-h-sm) }），
     font-size:0 不会塌陷盒模型，spinner 又用 currentColor 上色 —— 保持原样。 */
  position: relative; pointer-events: none; font-size: 0 !important; letter-spacing: 0; min-width: 92px;
}
#view-image .im-save-dlg button.is-busy::before {
  content: ""; position: absolute; left: 50%; top: 50%; width: 13px; height: 13px; margin: -6.5px 0 0 -6.5px;
  box-sizing: border-box; border-radius: 50%;
  border: 2px solid color-mix(in srgb, currentColor 28%, transparent); border-top-color: currentColor;
  animation: tool-spin 0.7s linear infinite;
}

/* 窄屏：单列，预览缩到 148px 高 */
@media (max-width: 920px) {
  #view-image .im-save-mask { padding: 12px; }
  #view-image .im-save-bd { grid-template-columns: 1fr; grid-template-rows: 200px 1fr; min-height: 0; }
  #view-image .im-save-pv { border-right: 0; border-bottom: 1px solid var(--border); padding: 12px; }
  #view-image .im-save-form { padding: 16px 18px 16px; }
  #view-image .im-f-row { grid-template-columns: 68px 1fr; gap: 12px; min-height: 44px; }
  #view-image .im-dim { flex-wrap: wrap; row-gap: 6px; }
  #view-image .im-dim .im-ib { margin-left: 8px; }
  #view-image .im-f-tip { margin-left: 80px; }
  #view-image .im-save-ft { flex-wrap: wrap; }
  #view-image .im-save-est { flex-basis: 100%; margin: 0 0 4px; }
}
#view-image .im-save-dlg .im-ib:disabled,
#view-image .im-save-dlg .im-ib:disabled:hover { background: transparent; border-color: transparent; color: var(--text-3); }

/* 放大行：方式下拉 + 倍数 + × + 应用（三档共用倍数一个输入） */
#view-image #usMode { width: 76px; flex: none; }
#view-image #us { width: 52px; flex: none; text-align: right; }
#view-image .up-x { flex: none; font-size: var(--hx-t12); color: var(--text-3); margin: 0 -4px; }
