/* ============================================================================
   FinBatch（票流）样式表（唯一一份，无框架、无构建）

   这份样式搬自同族的 pdfkit，口径照旧：

   1. **宽度是本子站自己的**：内容 1120px，不与门户同宽。
   2. **主色是本子站自己的**：青蓝（`--accent`），与 pdfkit 的深靛蓝、pdfword 的朱红
      都不同——同一套账号与页头，一眼能看出在用哪个工具。
   3. **长文有测量上限**：正文段落不超过 `--prose`（68ch）。
   4. **少画框，多用留白与字号层级**：卡片不投影，提示块才带左边框。深色模式只换变量。

   移动端优先：默认单列，栅格用 `auto-fill` 自己铺开。
   ============================================================================ */

:root {
  --bg: #f4f5fb;
  --bg-soft: #fafbff;
  --card: #ffffff;
  --ink: #141824;
  --muted: #5b6478;
  /* 边框比上一版更浅：结构靠留白与字号，不靠线 */
  --line: #e7e9f3;
  --line-strong: #d3d7e6;

  --accent: #0e7490;
  --accent-dark: #0b5f76;
  --accent-soft: #e6f4f8;
  --brand: #0e7490;
  --on-accent: #ffffff;

  --teal: #0d9488;
  --ok: #0f766e;
  --ok-soft: #e6f7f4;
  --warn: #b45309;
  --warn-soft: #fff6e8;
  /* 「可以停」这一档的颜色。它只在内部看板的判据卡上出现一次，
     所以不进 `--tool-*` 那套图标调色板。 */
  --stop: #be123c;

  --radius-sm: 10px;
  --radius-md: 14px;
  --radius-lg: 18px;
  /* 只有浮起来的东西才投影：卡片与面板靠边框和留白就够了 */
  --shadow-pop: 0 24px 64px rgba(20, 24, 36, 0.24);

  /* 工具图标调色板：每个功能一个名字（`Feature.color`），用在图标那块**实底**上，
     图标本身永远是白色。
     成对的转换功能共用一族颜色（Word 蓝、Excel 绿、PPT 橙），
     用户一眼能把「进去」和「出来」联系起来。

     取值都在「白字能读」的深度上（与 `#fff` 的对比度全部 ≥ 4.5:1，
     `tests/test_pages.py` 会逐个算并把不达标的挡下来）——
     所以**明暗两种模式共用这一套**，不需要暗色覆盖：底色够深，白图标在哪种背景下都成立。

     变量名统一带 `--tool-` 前缀：`--teal` 这样的通用名在别处已经有了，
     而暗色模式会覆盖通用名——不加前缀的话，「青色图标的底」会变成浅薄荷绿，
     白图标直接糊掉（对比度 1.86:1，测试抓过一次）。 */
  --tool-indigo: #4f46e5;
  --tool-blue: #2563eb;
  --tool-sky: #0369a1;
  --tool-teal: #0f766e;
  --tool-green: #15803d;
  --tool-lime: #4d7c0f;
  --tool-amber: #b45309;
  --tool-orange: #c2410c;
  --tool-rose: #be123c;
  --tool-pink: #be185d;
  --tool-purple: #9333ea;
  --tool-slate: #475569;

  --maxw: 1120px;
  /* 正文一行的上限。页面可以很宽，一行字不能。 */
  --prose: 68ch;
  --hit: 44px;
  --hit-sm: 36px;
  --gap-section: 56px;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #0e1017;
    --bg-soft: #14171f;
    --card: #171a23;
    --ink: #e9ebf2;
    --muted: #a2aab9;
    --line: #242835;
    --line-strong: #363c4c;

    --accent: #2b9fbd;
    --accent-dark: #22809c;
    --accent-soft: #10262f;
    --brand: #86d9ee;
    --on-accent: #0b0c12;

    --teal: #2dd4bf;
    --ok: #5eead4;
    --ok-soft: #10261f;
    --warn: #fbbf24;
    --warn-soft: #2a2011;
    /* 深色下的「停/失败」色。**两套主题必须定义同一组变量**：
       只在浅色里给一个 `--stop`，深色下 `var(--stop)` 会解析失败、声明被整条丢掉——
       页面上看起来只是「那个标签没变红」，没有任何报错。`scripts/check_ui.py` 与
       `tests/test_ui_colors.py` 就是为这一类静默失效准备的。 */
    --stop: #fda4af;

    --shadow-pop: 0 24px 64px rgba(0, 0, 0, 0.6);
  }
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  font-family: "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
  font-size: 16px;
  line-height: 1.7;
  color: var(--ink);
  background: radial-gradient(circle at top right, var(--accent-soft), var(--bg) 46%);
  background-attachment: fixed;
}

a { color: var(--accent); }

/* 键盘用户必须看得见焦点在哪：只有 :focus-visible 才画环，鼠标点击不留痕。 */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 4px;
}

/* ---------------------------------------------------------------- 顶栏 --- */

.topbar {
  position: sticky;
  top: 0;
  z-index: 50;
  border-bottom: 1px solid var(--line);
  background: color-mix(in srgb, var(--card) 88%, transparent);
  backdrop-filter: blur(10px);
}

.tb-inner {
  /* 与 main 同宽：品牌名才能和正文左对齐 */
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 12px 16px;
  display: flex;
  align-items: center;
  gap: 8px;
}

.tb-wrap { position: relative; }

/* 顶部热门功能菜单。窄屏时自己横向滚动而不是折行或隐藏：
   折行会把顶栏撑成两层，隐藏则等于把入口藏了——滚动是这两者之间唯一不丢功能的做法。 */
.top-nav {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  overflow-x: auto;
  scrollbar-width: none;
}

.top-nav::-webkit-scrollbar { display: none; }

.top-nav a {
  display: inline-flex;
  align-items: center;
  height: 32px;
  padding: 0 11px;
  border-radius: 8px;
  /* 纯黑：菜单是导航，字必须一眼看清。用 `--muted` 那种偏灰的颜色当菜单文字，
     在浅色底上就已经发虚，叠加「未上线」的降透明度后基本读不出来。 */
  color: #000;
  font-size: 14px;
  font-weight: 500;
  text-decoration: none;
  white-space: nowrap;
}

/* 暗色下改成纯白：纯黑在深色底上等于看不见。
   这里要的是「最大对比度」，不是「黑」这个具体颜色。 */
@media (prefers-color-scheme: dark) {
  .top-nav a { color: #fff; }
}

.top-nav a:hover { background: var(--bg-soft); }

/* 当前所在功能：**只把文字换成主色调**，不加底色。
   加底色会读成一个按钮——顶栏右侧已经有「登录/注册」两个真按钮，
   再出现第三个方块，用户会分不清哪个是可点的主操作。
   主色调 `--brand` 在明暗模式下分别是靛蓝与浅靛蓝，与底色的对比度都在 7:1 以上。 */
.top-nav a.is-active {
  color: var(--brand);
  font-weight: 600;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  /* 纯黑：品牌名与旁边的图标是同一个整体，用主色调会把「名字」读成一个链接。
     顶栏里唯一该像链接的是菜单与按钮，品牌名不是。 */
  color: #000;
  font-size: 16px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-decoration: none;
}

/* 暗色下改成纯白，理由同上（纯黑在深色底上等于看不见） */
@media (prefers-color-scheme: dark) {
  .brand { color: #fff; }
}

/* 34px 是权衡后的值：顶栏高度由按钮的 `--hit`（44px）决定，logo 放到 44px 也不会撑高顶栏，
   但再大就会比旁边「FinBatch」这个词还抢眼，读起来像图标站而不是工具站。 */
.brand-logo { display: block; width: 34px; height: 34px; flex: none; }

.grow { flex: 1; }

/* ------------------------------------------------------------------ 按钮 --- */

/* 主按钮 44px、次级 34px：前者是「开始/下载」这种一次性动作，后者是卡片里的入口。 */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: var(--hit);
  padding: 0 18px;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: var(--accent);
  color: var(--on-accent);
  font: inherit;
  font-size: 15px;
  font-weight: 600;
  line-height: 1;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.btn:hover { background: var(--accent-dark); }

.btn.ghost {
  min-height: 36px;
  padding: 0 14px;
  font-size: 14px;
  background: transparent;
  border-color: var(--line);
  color: var(--ink);
}

.btn.ghost:hover { border-color: var(--accent); background: transparent; color: var(--brand); }

.btn.primary-action { background: var(--accent); color: var(--on-accent); }
.btn.primary-action:hover { background: var(--accent-dark); }

.btn[hidden], .btn:disabled { display: none; }

.btn:disabled,
button:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

/* ------------------------------------------------- 用户胶囊 / 头像 / 菜单 --- */

.user-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  width: auto;
  height: 36px;
  max-width: 160px;
  margin: 0;
  padding: 0 8px 0 4px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--card);
  color: var(--ink);
  font: inherit;
  font-size: 14px;
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
}

.user-chip:hover { border-color: var(--accent); }
.user-chip[hidden] { display: none; }

.user-chip .name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.user-chip .caret { width: 12px; height: 12px; flex: none; color: var(--muted); }

.avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 24px;
  height: 24px;
  overflow: hidden;
  border-radius: 999px;
  background: var(--line);
}

.avatar img { display: block; width: 100%; height: 100%; object-fit: cover; }

.avatar.lg { width: 32px; height: 32px; }

.menu {
  position: absolute;
  top: calc(100% + 6px);
  right: 16px;
  z-index: 60;
  width: min(232px, calc(100vw - 32px));
  padding: 4px 0;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--card);
  box-shadow: var(--shadow-pop);
}

.menu[hidden] { display: none; }

.menu-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px 10px;
  border-bottom: 1px solid var(--line);
}

.menu-id { min-width: 0; }

.menu-id b {
  display: block;
  overflow: hidden;
  font-size: 14px;
  font-weight: 600;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.menu-id small {
  display: block;
  overflow: hidden;
  font-size: 12px;
  color: var(--muted);
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 菜单项复位全局 button 的宽度与上边距，否则菜单里会错位 */
.menu a, .menu button {
  display: block;
  width: 100%;
  margin: 0;
  padding: 10px 12px;
  border: 0;
  background: transparent;
  color: var(--ink);
  font: inherit;
  font-size: 14px;
  text-align: left;
  text-decoration: none;
  cursor: pointer;
}

.menu a:hover, .menu button:hover { background: var(--bg); }

/* ------------------------------------------------------------------ 正文 --- */

main {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 40px 16px 64px;
}

/* 首页顶到投放区的间隙单独收窄：顶栏本身已经有一条分隔线，
   再留 40/64px 的空白，第一眼会以为页面内容还没加载出来。

   只覆盖 `padding-top`：左右与底部仍跟着 `main` 的规则走（含宽屏那条媒体查询）——
   这条选择器比媒体查询里的 `main` 更具体，所以无论源码顺序都生效。 */
body[data-page="app"] main { padding-top: 24px; }

/* 字号层级：h1 是页面唯一的大字，h2 是分区，正文 16px。 */
h1 {
  margin: 0 0 14px;
  font-size: clamp(30px, 5vw, 42px);
  line-height: 1.15;
  letter-spacing: -0.02em;
}

h2 { margin: 0 0 16px; font-size: 22px; line-height: 1.3; letter-spacing: -0.01em; }
h3 { margin: 0; font-size: 17px; line-height: 1.4; }

/* 卡片里的工具名跟着一行四列的版式收一档：268px 的格子里，
   17px 的中文名占掉太多横向空间，会让下面那句说明频繁折成三行。 */
.tool-card .card-name { font-size: 15px; }

/* 功能页与首页同宽（1120px）：owner 要求正文左右与顶栏/页脚对齐。
   之前这里把表单页收到 860px，是为了「表单不该铺满」——现在按 owner 的选择统一宽度，
   表单控件自己靠 `max-width` 控制，不再靠整页收窄。 */

/* 主页没有标题区：进来就是工具目录。 */

.crumbs {
  display: flex;
  gap: 8px;
  margin-bottom: 14px;
  color: var(--muted);
  font-size: 14px;
}

.crumbs a { text-decoration: none; }
.crumbs a:hover { text-decoration: underline; }

.tool-head {
  display: flex;
  flex-direction: row;
  align-items: flex-start;
  gap: 16px;
  margin-bottom: 24px;
}

/* 工具页的图标与标题左右排列（同卡片），文字块要能收缩 */
.head-body { min-width: 0; }
.tool-head .tagline { margin: 0 0 12px; color: var(--muted); font-size: 17px; }
.badges { display: flex; flex-wrap: wrap; gap: 6px; margin: 0; }

/* 徽标：不上传 / 基础档不上传 / 会上传 / 开发中。颜色互不混用，一眼能分清平面。 */
.badge {
  display: inline-flex;
  align-items: center;
  height: 24px;
  padding: 0 9px;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  background: transparent;
  color: var(--muted);
  font-size: 12px;
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
}

.badge.ok { border-color: var(--ok); background: var(--ok-soft); color: var(--ok); }
.badge.warn { border-color: var(--warn); background: var(--warn-soft); color: var(--warn); }
.badge.mixed { border-color: var(--teal); color: var(--teal); }
.badge.wip { border-color: var(--line-strong); color: var(--muted); }

/* -------------------------------------------------------------- 提示块 --- */

.notice {
  margin: 0 0 24px;
  padding: 16px 18px;
  border: 1px solid var(--line);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-md);
  background: var(--card);
  font-size: 15px;
}

.notice[hidden] { display: none; }
.notice.inline { margin: 14px 0 24px; }
.notice.warn { border-left-color: var(--warn); background: var(--warn-soft); }
.notice.wip { border-left-color: var(--line-strong); background: var(--bg-soft); }
.notice.wip h2 { font-size: 17px; margin-bottom: 8px; }
.notice p { margin: 0 0 8px; max-width: var(--prose); }
.notice p:last-child { margin-bottom: 0; }
.notice a.cta, .notice button.cta { margin-left: 6px; font-weight: 600; }
.notice button.cta {
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--accent);
  font: inherit;
  font-weight: 600;
  text-decoration: underline;
  cursor: pointer;
}

.error-points { margin: 6px 0 8px; padding-left: 20px; color: var(--muted); }

.muted { color: var(--muted); font-size: 14px; }

/* ------------------------------------------------------------ 功能区栅格 --- */

.group { margin: 0 0 var(--gap-section); }

/* 分类 tab：胶囊排一行，选中的那一颗用「反色」表示。
   `background: var(--ink)` + `color: var(--bg)` 是刻意的搭配——
   这两个变量在明暗模式下正好互为背景与文字色，所以不用为暗色再写一套。 */
.tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin: 0 0 30px;
}

.tab {
  display: inline-flex;
  align-items: center;
  height: 40px;
  padding: 0 18px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--card);
  color: var(--muted);
  font-size: 15px;
  text-decoration: none;
  white-space: nowrap;
}

.tab:hover { border-color: var(--line-strong); color: var(--ink); }

.tab.is-active {
  border-color: transparent;
  background: var(--ink);
  color: var(--bg);
  font-weight: 600;
}

.group-title {
  margin: 0 0 20px;
  font-size: 22px;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--ink);
}

/* 一行四个：1120px 下每格约 268px，24 个功能正好六行。
   `minmax(0, 1fr)` 而不是 `1fr`——轨道默认最小宽度是 auto，
   标题或一句话偏长时会撑破格子并挤出横向滚动条。
   窄屏按 3 → 2 → 1 递减，不写 auto-fill 是因为「一行四个」是刻意定的版式，
   不是「能塞几个塞几个」。 */
.cards {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 14px;
}

@media (max-width: 1000px) { .cards { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 760px)  { .cards { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 480px)  { .cards { grid-template-columns: minmax(0, 1fr); } }

/* 工具图标：**深色实底 + 白色图标**。图标是 Lucide 的 24×24 描边路径，
   `stroke="currentColor"`，所以字形颜色由这里的 `color` 决定（恒为白），
   底色由 `--tile` 决定；名字来自 `Feature.color`，模板只把名字放进 `data-color`。 */
.card-icon,
.head-icon {
  --tile: var(--brand);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  background: var(--tile);
  color: #fff;
}

.card-icon[data-color="indigo"], .head-icon[data-color="indigo"] { --tile: var(--tool-indigo); }
.card-icon[data-color="blue"],   .head-icon[data-color="blue"]   { --tile: var(--tool-blue); }
.card-icon[data-color="sky"],    .head-icon[data-color="sky"]    { --tile: var(--tool-sky); }
.card-icon[data-color="teal"],   .head-icon[data-color="teal"]   { --tile: var(--tool-teal); }
.card-icon[data-color="green"],  .head-icon[data-color="green"]  { --tile: var(--tool-green); }
.card-icon[data-color="lime"],   .head-icon[data-color="lime"]   { --tile: var(--tool-lime); }
.card-icon[data-color="amber"],  .head-icon[data-color="amber"]  { --tile: var(--tool-amber); }
.card-icon[data-color="orange"], .head-icon[data-color="orange"] { --tile: var(--tool-orange); }
.card-icon[data-color="rose"],   .head-icon[data-color="rose"]   { --tile: var(--tool-rose); }
.card-icon[data-color="pink"],   .head-icon[data-color="pink"]   { --tile: var(--tool-pink); }
.card-icon[data-color="purple"], .head-icon[data-color="purple"] { --tile: var(--tool-purple); }
.card-icon[data-color="slate"],  .head-icon[data-color="slate"]  { --tile: var(--tool-slate); }

.card-icon {
  width: 46px;
  height: 46px;
  border-radius: 13px;
}

/* 开发中的卡把整块图标降低不透明度：卡片上不挂文字标签了，
   这是「未实现」唯一的非文字信号；用透明度而不是换一个颜色，
   因为换颜色会和真实配色撞车（比如灰色恰好是某个功能的颜色）。 */
.tool-card.wip .card-icon { opacity: 0.5; }

/* 功能页标题旁的同款图标，稍大一号 */
.head-icon {
  width: 60px;
  height: 60px;
  border-radius: 17px;
}

.tool-icon { display: block; }

.tool-card {
  display: flex;
  /* 图标在左、文字在右：一屏 24 张卡时，横向对齐的图标比竖排更像一个目录 */
  flex-direction: row;
  align-items: flex-start;
  gap: 12px;
  padding: 16px;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--card);
  /* 整张卡可点：标题里的链接用一条看不见的覆盖层铺满卡片。
     这样卡片里不需要「开始」按钮——按钮只是把用户送到同一个地方，
     而卡片本身已经是一个链接。 */
  position: relative;
  transition: border-color 0.15s ease, background 0.15s ease;
}

/* 文字块要能收缩，否则长标题会把图标挤出卡片 */
.card-body {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.tool-card:hover { border-color: var(--line-strong); }
/* 开发中的卡不额外画框、也不挂文字角标：只把底色调淡。
   状态在工具页上仍然写明（那一页会说「引擎未就位」并停用控件）。 */
.tool-card.wip { background: var(--bg-soft); }

.tool-card .card-name a { color: var(--ink); text-decoration: none; }
.tool-card .card-name a:hover { color: var(--brand); }
/* 覆盖层：撑满卡片，让整卡可点，同时保持「一个链接、一个可聚焦元素」的无障碍语义。 */
.tool-card .card-name a::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
}

.tool-card .tagline { margin: 0; color: var(--muted); font-size: 13px; line-height: 1.55; }

/* -------------------------------------------------------------- 工作区 --- */

.workbench {
  display: flex;
  flex-direction: column;
  gap: 20px;
  margin-bottom: 40px;
}

.start-row { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }
.start-row[hidden] { display: none; }

.hint { margin: 0; color: var(--muted); font-size: 14px; }
.upload-note { margin: 0 0 24px; }

.section-title {
  margin: 4px 0 10px;
  color: var(--ink);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.02em;
}
.section-title + .hint { margin-bottom: 10px; }
.section-title:first-child { margin-top: 0; }

.result-panel {
  padding: 20px 22px 22px;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--card);
}

.result-panel-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 10px;
  margin-bottom: 14px;
}

.result-panel-head h2 {
  margin: 0;
  font-size: 17px;
  font-weight: 700;
  line-height: 1.3;
}

.result-panel-head small { color: var(--muted); }

.result-empty {
  padding: 28px 16px;
  border: 1px dashed var(--line);
  border-radius: var(--radius-md);
  background: var(--bg-soft);
  text-align: center;
}

.result-empty p { margin: 0; }
.result-empty p + p { margin-top: 6px; }

.result-empty[hidden],
#result-card[hidden] { display: none; }

.drop {
  position: relative;
  padding: 36px 20px 32px;
  border: 2px dashed var(--line-strong);
  border-radius: var(--radius-lg);
  background: var(--bg-soft);
  text-align: center;
  cursor: pointer;
  transition: border-color 0.15s ease, background-color 0.15s ease;
}

.drop:hover, .drop.over { border-color: var(--accent); background: var(--accent-soft); }

.drop input[type="file"] {
  position: absolute;
  inset: 0;
  z-index: 2;
  width: 100%;
  height: 100%;
  opacity: 0;
  cursor: pointer;
}

.drop input[type="file"]:disabled { cursor: not-allowed; }

/* 焦点落在被隐藏的 input 上时，把焦点环画到整个投放区，键盘用户才看得见 */
.drop:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }

.drop-inner {
  position: relative;
  z-index: 1;
  margin: 0;
  color: var(--muted);
  line-height: 1.7;
  pointer-events: none;
}
.drop-inner .drop-title,
.drop-inner strong {
  display: block;
  margin: 0 0 12px;
  color: var(--ink);
  font-size: 18px;
  font-weight: 700;
  line-height: 1.35;
}

/* 投放区的两张样张：发票长得像票、流水长得像表，用户不用读完标题就知道往这儿放什么。 */
.drop-samples {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: center;
  gap: 12px 16px;
  margin: 0 0 18px;
}
.drop-plus {
  align-self: center;
  color: var(--muted);
  font-size: 13px;
  font-weight: 700;
}
.drop-doc {
  margin: 0;
  width: 120px;
}
.drop-doc figcaption {
  margin-top: 8px;
  color: var(--ink);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.02em;
}
.drop-paper {
  position: relative;
  height: 132px;
  padding: 12px 12px 28px;
  overflow: hidden;
  border: 1px solid var(--line-strong);
  border-radius: 10px;
  background: var(--card);
  text-align: left;
}
.drop-paper.is-invoice { transform: rotate(-3deg); }
.drop-paper.is-statement { transform: rotate(3deg); }
.drop:hover .drop-paper,
.drop.over .drop-paper,
.drop:focus-within .drop-paper {
  transform: none;
  border-color: var(--accent);
}
.drop-paper-kicker {
  display: block;
  margin-bottom: 10px;
  color: var(--brand);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
}
.drop-paper-line,
.drop-paper-amt {
  display: block;
  height: 7px;
  margin-top: 8px;
  border-radius: 4px;
  background: var(--line);
}
.drop-paper-line.mid { width: 72%; }
.drop-paper-amt {
  width: 48%;
  margin-top: 16px;
  height: 10px;
  background: var(--accent-soft);
}
.drop-paper-table {
  display: grid;
  gap: 7px;
  margin-top: 4px;
}
.drop-paper-table i {
  display: block;
  height: 8px;
  border-radius: 3px;
  background: linear-gradient(
    90deg,
    var(--line) 0 38%,
    transparent 38% 44%,
    var(--line) 44% 68%,
    transparent 68% 74%,
    var(--accent-soft) 74% 100%
  );
}
.drop-paper-ext {
  position: absolute;
  right: 8px;
  bottom: 8px;
  padding: 2px 6px;
  border-radius: 4px;
  background: var(--accent);
  color: var(--on-accent);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.04em;
  line-height: 1.4;
}

.drop-cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--hit-sm);
  padding: 0 18px;
  margin: 0 0 10px;
  border-radius: 999px;
  background: var(--accent);
  color: var(--on-accent);
  font-size: 14px;
  font-weight: 700;
}

.drop-inner #drop-sub { display: block; }

.drop-icon {
  display: flex;
  justify-content: center;
  margin: 0 auto 12px;
  color: var(--brand);
}

.filelist-out {
  margin: 0;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--card);
  color: var(--muted);
  font-size: 14px;
  word-break: break-all;
}

.filelist-out[hidden] { display: none; }

/* 已选文件列表：顺序就是处理顺序，所以上移/下移必须是真按钮（触屏上拖拽不可靠）。 */
.picklist { margin: 0 0 8px; padding: 0; list-style: none; }

.pick-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 0;
  border-bottom: 1px solid var(--line);
  color: var(--ink);
  word-break: break-all;
}

.pick-item:last-child { border-bottom: 0; }

.pick-index {
  flex: none;
  width: 24px;
  height: 24px;
  border-radius: 999px;
  background: var(--accent-soft);
  color: var(--brand);
  font-size: 12px;
  font-weight: 700;
  line-height: 24px;
  text-align: center;
}

.pick-name { flex: 1 1 auto; min-width: 0; }
.pick-size { flex: none; color: var(--muted); font-size: 13px; }
.pick-actions { display: flex; flex: none; gap: 4px; }

.pick-btn {
  min-width: var(--hit-sm);
  height: 30px;
  padding: 0 8px;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  background: var(--bg-soft);
  color: var(--ink);
  font: inherit;
  font-size: 13px;
  line-height: 1;
  cursor: pointer;
}

.pick-btn:hover:not(:disabled) { border-color: var(--accent); color: var(--brand); }
.pick-btn:disabled { opacity: 0.4; cursor: not-allowed; }

.options {
  margin: 0;
  padding: 22px;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--card);
}

.options legend { padding: 0 8px; color: var(--muted); font-size: 14px; font-weight: 600; }.options:disabled { opacity: 0.7; }

.field { margin-bottom: 18px; }
.field:last-of-type { margin-bottom: 0; }

/* 功能用不到的选项整行藏起来（由 workbench.js 按入口登记的 options 切换） */
.field[hidden] { display: none; }

.field label { display: block; margin-bottom: 8px; font-size: 15px; font-weight: 600; }

.field input[type="text"],
.field input[type="number"] {
  width: 100%;
  min-height: var(--hit);
  padding: 10px 14px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: var(--bg-soft);
  color: var(--ink);
  font: inherit;
}

.field.check { display: flex; align-items: flex-start; gap: 10px; }
.field.check input { margin: 4px 0 0; flex: none; width: 18px; height: 18px; }
.field.check label { margin: 0; font-weight: 500; }

/* 进度与结果：框架期一直是隐藏的——没有引擎就没有进度，不画假的进度条。 */
.card {
  padding: 22px;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--card);
}

.card[hidden] { display: none; }

.job-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 14px; }
.job-head b { font-size: 17px; }
.job-head small { color: var(--muted); }

.bar { height: 8px; overflow: hidden; border-radius: 999px; background: var(--line); }

.bar > i {
  display: block;
  width: 0;
  height: 100%;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--accent), var(--teal));
  transition: width 0.4s ease;
}

.meta {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 18px;
  margin: 16px 0 0;
  padding: 0;
  list-style: none;
  color: var(--muted);
  font-size: 14px;
}

/* 引擎对这次处理的自述：「已加 3 个书签」「已是最优，压不动」都写在这里 */
.result-notes {
  margin-top: 14px;
  padding: 12px 14px;
  border-radius: var(--radius-sm);
  background: var(--bg-soft);
  color: var(--muted);
  font-size: 14px;
}

.result-notes[hidden] { display: none; }
.result-notes ul { margin: 0; padding-left: 20px; }

.actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 20px; }

.actions .secondary {
  min-height: 36px;
  padding: 0 16px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--ink);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}

.actions .secondary:hover { border-color: var(--accent); color: var(--brand); }

/* ------------------------------------------------- 隐私横幅 / 不吹的部分 --- */

/* 「这个功能不吹的部分」：照旧逐条写全，但折叠起来，不挡在做事的路上。 */
.honest { margin: 32px 0 0; }

.honest details {
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--bg-soft);
  padding: 0 22px;
}

.honest summary { padding: 16px 0; cursor: pointer; font-size: 15px; font-weight: 600; }
.honest details[open] summary { border-bottom: 1px solid var(--line); margin-bottom: 16px; }
.honest ul { margin: 0; padding: 0 0 20px 20px; max-width: var(--prose); color: var(--muted); }
.honest li { margin-bottom: 8px; }
.honest strong { color: var(--ink); }

/* ------------------------------------------------------------- 说明面板 --- */

.panel {
  margin: 0 0 32px;
  padding: 26px;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--card);
}

.panel p { margin: 0 0 12px; max-width: var(--prose); }
.panel p:last-child { margin-bottom: 0; }

/* 面板里的折叠块（「会导出哪些列」用它收起来：两张表三十多行，
   在手机上要划好几屏才能看到下面的内容）。 */
.panel details { border: 0; padding: 0; }

.panel details > summary {
  padding: 4px 0;
  font-size: 16px;
  font-weight: 600;
  cursor: pointer;
}

.panel details[open] > summary { margin-bottom: 12px; }
.panel details > summary .muted { font-weight: 400; }

.limit-now { margin-top: 12px; }

.kind-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 14px;
  margin: 12px 0 0;
}

.kind-card {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 16px;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--bg-soft);
}

.kind-card .tagline { margin: 0; color: var(--muted); font-size: 14px; }

.plan-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 14px;
  margin: 12px 0 0;
}

.plan-card {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 18px 16px 16px;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--bg-soft);
}

.plan-card h3 {
  margin: 0;
  font-size: 16px;
  font-weight: 700;
}

.plan-card.is-current {
  border-color: var(--accent);
  background: var(--accent-soft);
}

.plan-limit {
  margin: 0;
  font-size: 22px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}

.plan-meta {
  margin: 0 0 8px;
  color: var(--muted);
  font-size: 13px;
}

.plan-status {
  margin: auto 0 0;
  color: var(--brand);
  font-size: 13px;
  font-weight: 700;
}

.plan-status[hidden],
.plan-cta[hidden] { display: none; }

.plan-card .plan-cta {
  margin-top: auto;
  min-height: var(--hit-sm);
  width: 100%;
}

.steps {
  margin: 12px 0 18px;
  padding: 0;
  list-style: none;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 14px;
}

.steps li {
  padding: 16px 18px;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--bg-soft);
}

.steps .step-n {
  display: block;
  margin-bottom: 6px;
  color: var(--brand);
  font-size: 13px;
  font-weight: 700;
}

.steps strong { display: block; margin-bottom: 6px; }
.steps p { margin: 0; color: var(--muted); font-size: 14px; }

.not-found-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 16px;
}

.filelist, .keylist { margin: 8px 0 0; padding-left: 20px; font-size: 14px; }
.filelist code { word-break: break-all; }

.keylist { list-style: none; padding-left: 0; }
.keylist li { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 8px 0; border-bottom: 1px solid var(--line); }
.keylist li:last-child { border-bottom: 0; }
.keylist a { font-weight: 600; text-decoration: none; }
.keylist a:hover { text-decoration: underline; }
.keylist code { padding: 1px 6px; border-radius: 4px; background: var(--bg-soft); color: var(--muted); }

/* ---------------------------------------------------------------- 页脚 --- */

/* 三段：品牌 + 全部工具的站内目录 + 版本与账号入口，用一条细线跟正文分开。
   原来两行裸文字堆在页底，没有分界也没有层级，读起来像漏出来的旁白。 */
.page-foot {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 30px 16px 56px;
  border-top: 1px solid var(--line);
  color: var(--muted);
}

/* 品牌固定在左侧一栏，工具目录占剩下的宽度——
   工具站的名录是页脚的主体，不该被品牌挤成窄条。 */
.foot-inner {
  display: grid;
  grid-template-columns: minmax(200px, 250px) 1fr;
  gap: 30px 44px;
  align-items: start;
}

@media (max-width: 860px) {
  .foot-inner { grid-template-columns: 1fr; gap: 26px; }
}

.foot-brand { display: flex; gap: 10px; align-items: flex-start; }
/* 页脚图标略小于顶栏：那一栏是「品牌 + 目录」，图标不承担点击识别的作用。
   尺寸写在这里而不是只靠 HTML 属性，是为了两个 logo 的规格都只有一个出处。 */
.foot-logo { display: block; flex: 0 0 auto; width: 28px; height: 28px; }

.foot-brand-text strong {
  display: block;
  /* 与顶栏的品牌名同一套：纯黑（暗色下纯白）。
     同一句话在两个位置长得不一样，比两处都不好看更让人分心。 */
  color: #000;
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -0.01em;
}

@media (prefers-color-scheme: dark) {
  .foot-brand-text strong { color: #fff; }
}

.foot-brand-text p { margin: 5px 0 0; font-size: 12.5px; line-height: 1.65; }
.foot-meta { margin-top: 8px; font-size: 12px; }

/* 六个分组自动铺开：窄屏落成两列，宽屏一行放得下六列。 */
.foot-index {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 22px 24px;
}

.foot-col-title {
  margin: 0 0 9px;
  color: var(--ink);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.02em;
}

.foot-col ul { margin: 0; padding: 0; list-style: none; }

.foot-col li { margin: 0 0 7px; }

.foot-col a {
  color: var(--muted);
  font-size: 12.5px;
  line-height: 1.5;
  text-decoration: none;
}

.foot-col a:hover { color: var(--brand); }

/* ------------------------------------------------------------ 数据表与看板 --- */

/* 这个站的核心产物是一张表，所以表格样式是本子站自己的（pdfkit 里没有表，
   搬过来的样式表只到「工作区」为止）。两条口径：
   1. 数字右对齐、等宽数字：一列金额左对齐是读不出大小关系的；
   2. 行只用细横线分隔，不加斑马纹——数据密的时候，格子线比数据还抢眼。
   组与组之间才用一条淡竖线，帮眼睛把「金额」和「购销方」切开。 */
.data,
.cols {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: 13.5px;
}

.data th,
.data td,
.cols th,
.cols td {
  padding: 10px 12px;
  border-bottom: 1px solid var(--line);
  text-align: left;
  vertical-align: top;
  line-height: 1.45;
  /* 长串要能折行：户名、摘要里出现一串没有空格的字符（英文公司名、流水号、
     被打码的账号）时，不折行会把整列撑宽、进而把表推出屏幕——手机上表现为
     「文字被切掉一半，怎么划都不对」。 */
  overflow-wrap: anywhere;
}

.data thead th,
.cols thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--bg-soft);
  color: var(--muted);
  font-size: 12.5px;
  font-weight: 600;
  white-space: nowrap;
}

.data .group-row th {
  top: 0;
  z-index: 2;
  height: 32px;
  padding: 0 12px;
  border-bottom: 0;
  background: var(--accent-soft);
  color: var(--brand);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.14em;
  line-height: 32px;
  text-align: center;
}

.data thead tr:not(.group-row) th {
  top: 32px;
  border-bottom: 1px solid var(--line-strong);
}

.data tbody tr:last-child td { border-bottom: 0; }
.data tbody tr:hover { background: var(--bg-soft); }

/* 明细表按内容撑开，不够宽的列不再被 16 列平分挤扁；外层 sheet-scroll 负责横滑。 */
.data.sheet {
  width: max-content;
  min-width: 100%;
}

.data .num {
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum";
  white-space: nowrap;
}
.data .col-emphasis { font-weight: 700; }
.data .col-no {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  letter-spacing: 0.02em;
  white-space: nowrap;
}
.data .col-type { color: var(--muted); font-size: 12.5px; white-space: nowrap; }
.data .col-meta { color: var(--muted); font-size: 12.5px; }
.data .col-review { color: var(--warn); font-size: 12.5px; }
.data .empty { color: var(--muted); opacity: 0.7; }
.data .wrap-cell { max-width: 280px; overflow-wrap: anywhere; }
.data .col-party {
  min-width: 148px;
  max-width: 240px;
  overflow-wrap: break-word;
  line-height: 1.45;
}

.data .group-start { border-left: 1px solid var(--line); }
.data th.group-start:first-child,
.data td.group-start:first-child,
.data .group-row th:first-child { border-left: 0; }

.cell-pill {
  display: inline-block;
  padding: 1px 8px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 700;
  line-height: 1.65;
  white-space: nowrap;
}
.cell-pill.conf-high { background: var(--ok-soft); color: var(--ok); }
.cell-pill.conf-medium { background: var(--warn-soft); color: var(--warn); }
.cell-pill.conf-low { background: var(--warn-soft); color: var(--stop); }

td[contenteditable="true"] { border-radius: 4px; }
td[contenteditable="true"]:focus {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
  background: var(--card);
}

/* 待复核的行整行淡黄：一眼扫过去就知道哪几行需要人看，而不是逐格找标记。 */
.data tr.review { background: var(--warn-soft); }
.data tr.review:hover { background: var(--warn-soft); }

.scroll-x { overflow-x: auto; }

/* 明细表自己滚动：表头能粘在框顶，标题留在框外。 */
.sheet-scroll {
  max-width: 100%;
  max-height: min(72vh, 720px);
  overflow: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--card);
}
.sheet-scroll + .section-title { margin-top: 22px; }

/* 看板上的数字块。数字用比正文大两号的等宽字，扫一眼就能比较。 */
.stats-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 14px;
  margin: 0 0 var(--gap-section);
}

.stat {
  padding: 16px 18px;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--card);
}

.stat .label { display: block; color: var(--muted); font-size: 13px; }
.stat .value {
  display: block;
  margin-top: 6px;
  font-size: 26px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}

.stat .sub { display: block; margin-top: 4px; color: var(--muted); font-size: 12.5px; }

/* 判据卡：这张卡是要拿来做决定的，所以结论必须是一句能被引用的话。 */
.decision {
  margin: 0 0 var(--gap-section);
  padding: 22px 24px;
  border: 1px solid var(--line);
  border-left: 4px solid var(--line-strong);
  border-radius: var(--radius-md);
  background: var(--card);
}

.decision.invest { border-left-color: var(--ok); }
.decision.maintain { border-left-color: var(--warn); }
.decision.stop { border-left-color: var(--stop); }
.decision.unknown { border-left-color: var(--line-strong); }

.decision h2 { margin: 0 0 6px; }
.decision .verdict { font-size: 20px; font-weight: 700; }
.decision .why { margin: 8px 0 0; max-width: var(--prose); color: var(--muted); }

.metrics { margin: 16px 0 0; padding: 0; list-style: none; }
.metrics li {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 10px;
  padding: 8px 0;
  border-bottom: 1px solid var(--line);
}
.metrics li:last-child { border-bottom: 0; }
.metrics .name { flex: 1 1 160px; }
.metrics .actual { font-weight: 600; font-variant-numeric: tabular-nums; }
.metrics .target { color: var(--muted); font-size: 13px; }
.metrics .mark { flex: none; font-weight: 700; }
.metrics .mark.ok { color: var(--ok); }
.metrics .mark.miss { color: var(--warn); }

/* 失败清单：它不是「错误」，是产品的一部分，所以用提示块的样式，不用红色警告。 */
.failures li { margin-bottom: 6px; }

/* --------------------------------------------------------- 批次清单的状态 --- */

/* 每个文件一行状态：等待 / 读取中 / 已识别 / 需要密码 / 认不出 / 读取失败。
   颜色只区分「要不要你动手」：绿=好了、黄=要你决定、红=我们没读成。 */
.pick-status {
  flex: none;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 12.5px;
  line-height: 1.6;
  white-space: nowrap;
}

.pick-status.st-ok { background: var(--ok-soft); color: var(--ok); }
.pick-status.st-warn { background: var(--warn-soft); color: var(--warn); }
.pick-status.st-err { background: var(--warn-soft); color: var(--stop); }
.pick-status.st-idle { background: var(--bg-soft); color: var(--muted); }

/* 加密文件的密码行：输入框与按钮在一行里，窄屏自动折行。 */
.pw-form { display: flex; flex-wrap: wrap; gap: 10px; margin: 12px 0 6px; }

.pw-form input {
  min-width: 180px;
  min-height: var(--hit-sm);
  padding: 0 12px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: var(--card);
  color: var(--ink);
  font: inherit;
}

.pw-form input:focus-visible { border-color: var(--accent); }

@media (max-width: 720px) {
  .data, .cols { font-size: 13px; }
  .stat .value { font-size: 22px; }
  .drop-paper.is-invoice,
  .drop-paper.is-statement { transform: none; }
}

/* ------------------------------------------------------------ 宽屏铺开 --- */


@media (min-width: 768px) {
  main { padding: 64px 24px 96px; }
  .tb-inner { padding: 14px 24px; }
  .page-foot { padding: 30px 24px 64px; }

  .um-grid { grid-template-columns: 1fr 1fr; }
  .um-cta { flex-direction: row; }
  .um-plan { flex: 1 1 0; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; scroll-behavior: auto !important; }
  .drop-paper.is-invoice,
  .drop-paper.is-statement { transform: none; }
}
