/* ============================================================
   FILE_PROCESSOR archetype — 共享 composition 层（Phase 20A1B）

   消费者（仅此两页）：
     tools/archive-converter/   tools/img-to-pdf/
   以及它们各自的 8 份 locale 派生页。

   ⚠️ 这一层**只做 composition**：它不定义颜色 / 圆角 / 阴影 / 字号 / 控件基样式。
      视觉值一律来自 tokens.css · workspace-ui.css · product-page.css · tool-landing.css。
      唯一的例外是品牌金（见文件末尾），那是 logo 资产，不是"又发明一套颜色"。

   archetype 解剖（两页逐块对应，不是 archive 一套、img-to-pdf 再抄一套）：
     Tool Hero      .pp-hero            卡片外，与 surface 左边缘同线
     Main Surface   .yqw-surface
       Input+Work   .fp-listbox         空态是拖放区；有内容后变成带固定 Add 行的容器
       Completion   .fp-complete        output options + primary action 同一区域
       Feedback     .fp-feedback        status / 进度 / 计数，只向下生长
     Editorial      main[data-product-page]   Product Page V2 的既有组件

   ⚠️ Work Item 是 **slot 不是固定 markup**（20A1B §9.1）：
      archive 是文件行、img-to-pdf 是缩略图网格。archetype 只约定
      **容器契约**（滚动归属 / 间距 / 动作对齐 / 响应式），不约定条目长什么样。
   ============================================================ */

/* ── Shell：流式，服从 product-page.css 的页面 gutter 权威 ──── */
html.is-standalone body.fp-page { display: block; padding: 0; overflow-y: auto; }
.fp-shell {
  width: 100%;
  max-width: calc(var(--pp-max) + 2 * var(--pp-inline));
  margin: 0 auto;
  padding-inline: var(--pp-inline);
  padding-bottom: 8px;
}
html.is-standalone .fp-shell {
  margin: 0 auto;
  padding-left: var(--pp-inline);
  padding-right: var(--pp-inline);
}
.fp-hero { max-width: calc(var(--pp-max) + 2 * var(--pp-inline)); }
.fp-surface { display: flex; flex-direction: column; gap: var(--yqw-gap-section, 20px); }

/* ── 整页纵向 rhythm 由一处决定，不让每段自己 margin-top ──── */
.fp-shell .pp-hero { padding-top: 40px; padding-bottom: 24px; }
html.is-standalone main.fp-editorial { padding-top: 40px; }
@media (max-width: 640px) {
  .fp-shell .pp-hero { padding-top: 28px; padding-bottom: 18px; }
  html.is-standalone main.fp-editorial { padding-top: 28px; }
}

/* assurance 行搬进 Hero：文案与元素都没动，只换位置与层级。
   ⚠️ 元素必须仍是 <p class="tl-assure">：本地化渲染器靠它做锚点替换内文。 */
.fp-shell .fp-trust,
.pp-hero .fp-trust {
  max-width: none; margin: 14px 0 0; padding: 0;
  text-align: left; font-size: 13px; line-height: 1.6; color: var(--yq-text-3);
}

/* ── Input Zone + Work List 合成一个容器 ─────────────────────
   空态：一整块拖放区。有内容：同一容器变成带固定 Add 行的列表框。
   ⚠️ Add 行**就是原来那个拖放区元素**（archive 是 <label for>，
      img-to-pdf 是带 click→picker 的 <div>），不是新造的按钮 ——
      新造按钮就得把拖放区藏掉，drag & drop 会跟着消失。
   ⚠️ 1× 的定义是"**不让卡片变高**"：列表高 = 空态拖放区高 − Add 行 − 上下两条边框。
      这条关系**只写在这里**，JS 不重算像素（两边各算一次必然漂移）。 */
.fp-listbox {
  --fp-dz-min: clamp(200px, 30vh, 300px);
  --fp-addrow-h: 56px;
  --fp-list-h: calc(var(--fp-dz-min) - var(--fp-addrow-h) - 2px);
  display: flex; flex-direction: column; min-width: 0;
}
.fp-addrow { display: flex; align-items: center; gap: 12px; min-width: 0; }
.fp-listbox .fp-dz { flex: 1; min-width: 0; }
/* ⚠️ 必须压得过页内那条 legacy `#dropZone{margin-bottom:16px}`（ID 选择器，1,0,0）——
   否则空态比列表态高出 16px，"1× 不改变卡片高度"会差十几个像素。 */
.fp-listbox #dropZone, .fp-listbox #dropzone { margin: 0; }
.fp-hscale { display: none; flex: none; gap: 4px; padding-right: 12px; }
.fp-hbtn {
  height: 28px; min-width: 34px; padding: 0 8px;
  background: transparent; border: 1px solid transparent; border-radius: var(--yq-r-ctl);
  color: var(--yq-text-3); font-size: 12px; font-weight: 600; font-variant-numeric: tabular-nums;
}
.fp-hbtn:hover { background: var(--yq-bg-quiet); color: var(--yq-text-1); }
.fp-hbtn[aria-pressed="true"] {
  background: var(--yq-bg-quiet); border-color: var(--yq-border-strong); color: var(--yq-text-1);
}
.fp-work-scroll { display: none; }

/* 空态 */
.fp-shell:not(.has-files) .fp-listbox .fp-dz { --yqw-dropzone-min: var(--fp-dz-min); }

/* 有内容 */
.fp-shell.has-files .fp-listbox {
  border: 1px solid var(--yq-border);
  border-radius: var(--yq-r-card);
  background: var(--yq-bg-card, #fff);
  overflow: hidden;
}
.fp-shell.has-files .fp-addrow {
  height: var(--fp-addrow-h); flex: none;
  border-bottom: 1px solid var(--yq-border);
}
.fp-shell.has-files .fp-listbox .fp-dz {
  --yqw-dropzone-min: 0;
  flex-direction: row; align-items: center; justify-content: flex-start;
  gap: 8px; height: 100%; padding: 0 14px;
  border: 0; border-radius: 0; background: transparent; text-align: left;
  min-height: 0;
}
.fp-shell.has-files .fp-listbox .fp-dz:hover { background: var(--yq-bg-quiet); }
.fp-shell.has-files .fp-listbox .fp-dz.dragover { background: var(--yq-primary-weak); }
.fp-shell.has-files .fp-listbox .fp-dz svg { width: 18px; height: 18px; flex: none; }
.fp-shell.has-files .fp-dz .yq-dz-title { font-size: 14px; font-weight: 600; }
.fp-shell.has-files .fp-dz .yq-dz-hint { font-size: 12px; color: var(--yq-text-3); }
.fp-shell.has-files .fp-hscale { display: flex; }
.fp-shell.has-files .fp-work-scroll {
  display: block;
  height: calc(var(--fp-list-h) * var(--fp-hscale-k, 1));
  overflow-y: auto;
  padding: 8px;
}
/* ⚠️ 外壳属性叫 data-fp-hsize，按钮上的叫 data-fp-hscale —— **刻意不同名**：
   同名时 `[data-fp-hscale="1"]` 会同时选中外壳与按钮，而外壳在文档里更靠前。 */
.fp-shell.has-files[data-fp-hsize="2"] { --fp-hscale-k: 2; }
.fp-shell.has-files[data-fp-hsize="4"] { --fp-hscale-k: 4; }

/* Work Item slot —— archive 的文件行 */
.fp-listbox .file-list:not(:empty) { margin-bottom: 0; }
.fp-listbox .file-item {
  gap: 12px; padding: 10px 12px; margin-bottom: 4px;
  border: 0; background: var(--yq-bg-quiet); border-radius: var(--yq-r-sm);
}
.fp-listbox .file-item:last-child { margin-bottom: 0; }
.fp-listbox .file-name { font-size: 14px; min-width: 0; }
.fp-listbox .file-size, .fp-listbox .file-remove { flex: none; }
.fp-listbox .file-remove { width: 28px; height: 28px; }
/* Work Item slot —— img-to-pdf 的缩略图网格：容器契约交给 .fp-work-scroll，
   条目自己的排布（5 列、拖拽、旋转按钮）仍归那一页自己。
   ⚠️ 网格里那张「+」占位卡是这一页**原有的第二个 Add 入口**。
      archetype 里 Add 行已经承担了这件事，两个入口并存会让"第一行固定是 Add"
      这条契约形同虚设，所以在 archetype 里收起它。
      它的 click / drop 处理器仍在，只是不再可达 —— 能力集中在 Add 行那一份。 */
.fp-listbox .yq-add-tile { display: none; }
.fp-listbox .preview-grid {
  max-height: none; overflow: visible; padding-right: 0; margin-bottom: 0;
  scrollbar-gutter: auto;
}

/* ── Completion ────────────────────────────────────────────── */
.fp-complete {
  display: flex; align-items: flex-end; gap: 16px; flex-wrap: wrap;
  padding-top: 4px;
}
.fp-complete .options, .fp-complete .ctl-row { display: contents; }
.fp-field { display: flex; flex-direction: column; gap: 6px; flex: none; }
.fp-complete .yq-field { display: flex; flex-direction: column; gap: 6px; flex: none; }
.fp-complete .yq-label { font-size: 13px; color: var(--yq-text-2); }
/* ⚠️ 必须压得过页内那条 legacy `#formatSel{width:190px}`（ID 选择器，1,0,0）——
   否则 archive 的字段是 190 而 img-to-pdf 是 168，同一个 archetype 两个宽度。 */
.fp-complete .yq-select,
.fp-complete #formatSel { width: var(--yqw-field-w); max-width: 100%; min-width: 0; }
.fp-complete .yq-select-trigger { height: var(--yqw-h-select); }
.fp-spacer { flex: 1 1 auto; }
.fp-secondary { display: flex; align-items: center; gap: 12px; flex: none; }
/* ⚠️ 结构性排除：`.fp-secondary .yq-btn`(0,2,0) 比 `.fp-btn-secondary`(0,1,0) 特异度高，
   不排除的话 Clear 会被按回 32px（与 Convert 差 14px）。 */
.fp-secondary .yq-btn:not(.fp-btn-secondary) { height: 32px; }
/* Clear 与 Convert 成对：同高同宽、贴在它左边、白底 + 一条边框。
   它是"另一个选择"，不是"更弱的 Convert"，所以给完整体量、只在颜色退一档。 */
.fp-btn-secondary {
  height: 46px; width: var(--yqw-field-w); flex: none;
  background: var(--yq-bg-card, #fff);
  border: 1px solid var(--yq-border-strong);
  border-radius: 10px;
  color: var(--yq-text-1); font-size: 15px; font-weight: 600;
}
.fp-btn-secondary:hover:not(:disabled) { background: var(--yq-bg-quiet); }
.fp-btn-secondary:disabled {
  color: var(--yq-text-3); border-color: var(--yq-border); background: var(--yq-bg-card, #fff);
}
.fp-cta.yq-btn--cta {
  width: auto; min-width: var(--yqw-field-w); height: 46px; flex: none;
  font-size: 15px; font-weight: 600;
}

/* ── Feedback：只向下生长，不压缩上面的工作区 ───────────────── */
.fp-feedback { display: flex; flex-direction: column; gap: 8px; }
.fp-feedback .status { text-align: left; margin: 0; min-height: 0; font-size: 13px; line-height: 1.5; }
.fp-feedback .status:empty { display: none; }
.fp-feedback .status:not(:empty) {
  padding: 10px 14px; border-radius: var(--yq-r-sm);
  background: var(--yq-bg-quiet); color: var(--yq-text-2);
}
.fp-feedback .status.success { background: var(--yq-success-weak, var(--yq-bg-quiet)); color: var(--yq-success); }
.fp-feedback .status.error { background: var(--yq-danger-weak, var(--yq-bg-quiet)); color: var(--yq-danger); }
.fp-feedback .tip { text-align: left; margin: 0; }
/* img-to-pdf 的进度条与计数行：空态没有意义，跟着 has-files 一起出现 */
.fp-shell:not(.has-files) .fp-meta { display: none; }
.fp-meta { display: flex; flex-direction: column; gap: 8px; }
.fp-meta .yq-meta-row { margin: 0; }

/* ── Editorial：整页用 Product Page V2 的既有组件 ──────────────
   §12：不新造重复 editorial 组件。这里只有两条 composition 规则。 */
.fp-spec-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (max-width: 860px) { .fp-spec-grid { grid-template-columns: minmax(0, 1fr); } }
/* ⚠️ 步骤卡里的 <strong> 是**句中的行内强调**（"Choose the **target format**:"），
   不是卡片标题。product-page.css 的 `.pp-step strong{display:block}` 会把一句话
   拦腰切成三行。规格卡相反 —— 它的 <strong> 确实是前置标题，那里保留 block。 */
.pp-steps .pp-step strong { display: inline; margin: 0; font-size: inherit; font-weight: 600; }
/* Private by design 用 .pp-format-group 而不是 .pp-card，同样是为了避开那条
   strong{display:block}：它会把句中的强调拽成独立一行。两者卡片视觉本来就同源。 */
.fp-callout p { margin: 0; color: var(--yq-text-2); line-height: 1.65; }
.fp-callout p + p { margin-top: 10px; }

/* ── 响应式 ────────────────────────────────────────────────── */
@media (max-width: 760px) {
  .fp-complete { align-items: stretch; gap: 12px; }
  .fp-field, .fp-complete .yq-field { width: 100%; }
  .fp-complete .yq-select, .fp-complete #formatSel { width: 100%; }
  .fp-spacer { display: none; }
  .fp-secondary { width: 100%; flex-direction: column; }
  .fp-btn-secondary { width: 100%; }
  .fp-cta.yq-btn--cta { width: 100%; min-width: 0; }
  .fp-shell.has-files .fp-dz .yq-dz-hint { display: none; }
}

/* ============================================================
   Gold「All tools」—— G1 Warm Gold + Dark Ink（20A1B §19–§22）

   ⚠️ **只作用于 FILE_PROCESSOR 页面**（body.fp-page），不改全局 header 规则。
      全站铺开是 GLOBAL_HEADER_GOLD_ROLLOUT，另立一轮。
   ⚠️ 金色取自 logo 资产本身：logo_192.png 逐行采样
      顶 #F2D57D · 中 #E8C86C · 底 #C7A344，与项目文档记的
      #E8CD76→#C49E3E 同一族。这不是新发明的颜色。
   ⚠️ 文字是**深墨**不是白色：实测白字在这条金底上只有 1.56–2.53，
      远低于 AA 的 4.5；深墨 #2A2205 实测 6.58–10.97，整条渐变都过。
      三个候选（实心金/浅金/金边）全部量过，G1 在"过 AA + 与 logo 同源 +
      在白 header 上真的醒目"三项上同时成立。
   ============================================================ */
body.fp-page {
  --fp-gold-top: #F2D57D;
  --fp-gold-mid: #E8C86C;
  --fp-gold-bot: #C7A344;
  --fp-gold-edge: #B8902F;
  --fp-gold-ink: #2A2205;
}
body.fp-page .tl-nav {
  display: inline-flex; align-items: center;
  height: 32px; padding: 0 14px;
  background: linear-gradient(180deg, var(--fp-gold-top) 0%, var(--fp-gold-bot) 100%);
  border: 1px solid var(--fp-gold-edge);
  border-radius: var(--yq-r-ctl);
  color: var(--fp-gold-ink);
  font-size: 13px; font-weight: 600;
  white-space: nowrap;
}
body.fp-page .tl-nav:hover {
  background: linear-gradient(180deg, var(--fp-gold-mid) 0%, #BE9835 100%);
  color: #221B04;
}
body.fp-page .tl-actions { gap: 10px; }
/* 品牌 lockup 在这两页不承担"回首页"（Founder 决定：落地页用户多半不是
   从官网来的）。导航交给上面那个金色按钮；footer 仍有真实的 home link。 */
body.fp-page .tl-brand { cursor: default; user-select: none; }
/* 诊断入口（Export logs）默认收起，左上角 logo 连点 10 下解锁。
   ⚠️ 用 display:none 而不是 opacity/visibility —— 后者仍在 Tab 键路径上。 */
.fp-shell .fp-diag { display: none; }
.fp-shell.fp-diag-on .fp-diag { display: inline-flex; }
@media (max-width: 640px) {
  body.fp-page .tl-nav { padding: 0 12px; }
  body.fp-page .tl-actions { gap: 8px; }
}
