/* ==========================================================================
   财务模块（`/finance`）样式 —— 全部类带 `fin-` 前缀

   ⚠️ 与门户（`ptl-`）同属"独立外壳"家族：满屏、自带头部、无达播侧栏。
      区别是财务模块**有自己的左侧导航**（门户没有内部页面，只是往别处跳）。
   ⚠️ 颜色一律取设计令牌；不写死 hex。
   ⚠️ 单开一个文件（不塞进 267KB 的 pages.css）：回归面小、类名不会冲突。
   ========================================================================== */

.fin {
  min-height: 100%;
  display: flex;
  flex-direction: column;
  background: var(--color-bg);
}

/* ⚠️ 清掉 `.page` 自带内边距（独立外壳下 top 被 pages.css 改成 --space-4），
   否则头部条四周会露出一圈底色、看着像"嵌在框里"而不是通栏。
   ⚠️ 用 `:has()` 精确限定到"装着财务模块的那个 .page"—— `.page` 是全站共用容器。 */
.app-shell.is-standalone .page:has(> .fin) {
  padding: 0;
}

/* ---- 布局：内容区 ----
   ⭐ 2026-09-21：导航已搬到**应用侧栏**（`#sidebar-nav`），内容区只剩 `main`。
   ⭐⭐ 2026-09-22 深夜：财务侧栏的 **DOM 结构与样式已统一到达播/门户/系统配置同一套**
      （`.nav-group` / `.nav-group-label` / `.nav-subitems` / `.nav-item` / `.nav-icon` / `.nav-text`）。
      原来财务自造的那套 `fin-nav__*` 类**已全部删除**（连同这里约 100 行规则）。
      ⛔ 别把它加回来：加了不会有任何元素匹配（`finance.js` 的 navItemsHtml 已改用标准类），
         只会让后来者误以为还有第二套侧栏样式 —— 那正是"看着不像同一个系统"的来源。
      「导航去哪了」见 `pages/finance.js` 的 renderSidebarNav() 与 app.js 的
      renderFinanceSidebar()（一个管中部导航、一个管品牌区与底部）。
   ⚠️ 侧栏里那条竖分隔线由**侧栏自己**的 `border-right` 承担（base.css 的 `.sidebar`），
      这里**不要**再画一条 —— 否则会出现两条紧挨着的竖线（实测过）。
   ⚠️ `.fin-body` 保留：它仍是 `.fin` 的 flex 子项、承担 `flex:1` 的撑高。 */
.fin-body {
  flex: 1;
  display: flex;
  min-height: 0;
  width: 100%;
}

/* ---- 模块导航项（渲染在**应用侧栏内**，2026-09-21 起）----
   ⚠️ 这些类名保留 `fin-` 前缀（虽然现在挂在侧栏里）：它们**只属于财务模块**，
      与达播侧栏的 `.nav-item` 是两套东西（那边单行、这边两行带描述）。
      改成 `.nav-item` 会连带吃到达播的菜单样式与高亮逻辑（`[data-nav]` 那套绑定），
      反而更容易出错 —— 见 app.js 里关于"品牌区不许用 data-nav"的同类说明。
   ⚠️ 与达播菜单项的体量对齐：高度不写死（两行内容自然撑开），
      但左右内边距与圆角沿用同一套令牌（`--space-*` / `--radius-md`）。 */
/* 选中态复用全站那一套（浅蓝胶囊 + 主色字），不新造样式 */

/* ---- 侧栏里的**分组标签**（2026-09-22 新增，配合"两组菜单"改造）------------
   财务中心侧栏现在分两组：「报销管理」/「我的」。
   ⚠️ 为什么不用达播的 `.nav-group-label`（那个类已存在）：它是**可折叠按钮**
      （40px 高、base 字号、带 hover 与图标），而这里只有两组、每组项数少
      （管理组最多 6 项、我的组 1 项），多数一个折叠动作反而添乱。
      这里用"小灰字"做**纯标签**，只负责"组名在上、项在下"的视觉区隔。
   ⚠️ 整组没权限时**连这个标签一起不渲染**（见 finance.js 的 navItemsHtml）——
      留一个空组名比不显示更糟（像菜单加载失败）。 */
/* 第一组不需要上边距（否则品牌区下面会多一段空白） */

.fin-main {
  flex: 1;
  min-width: 0;
  /* ⚠️ 左右必须用 `--page-padding`(32px) —— 规范「页面内容区左右内边距 32px」。
     原值是 `--space-6`(24px)，比达播窄 8px ⇒ 同一屏幕切过去内容会"撑宽"、
     两张页面的左对齐线对不上（这是"看着不像同一个系统"最细但最持续的一种差异）。 */
  padding: var(--space-6) var(--page-padding) var(--space-8);
}
/* ⚠️ 标题用全站统一的 `.page-title`（通用巡检 `probe-all-pages.js` 查的就是它），
   本类只补外边距 —— 别自造语义类，否则该页在通用门禁上永久假红。 */

.fin-loading {
  padding: var(--space-8) 0;
  text-align: center;
  color: var(--color-meta);
  font-size: var(--font-size-sm);
}

.fin-count {
  font-size: var(--font-size-xs);
  color: var(--color-muted);
  margin-bottom: var(--space-2);
}.fin-count b { color: var(--color-fg); font-weight: var(--font-weight-semibold); }

/* ---- 标题旁的「?」使用说明（2026-09-21 乐哥）----
   ⚠️ 三个必须写对的点（每处都对应一个会**静默失效**的坑）：
     ① `.fin-help { margin-right: auto }` —— `.page-header` 是 `flex; space-between`，
        不加的话问号会被推到**页面最右边**（看着像"跑到右上角了"，而不是"标题旁边"）。
     ② `[hidden] { display: none }` 必须**显式写** —— 本元素设了 `display: inline-flex`，
        那会**盖掉** `hidden` 属性自带的 `display:none`
        ⇒ 没有说明的页面也会显示一个空问号。`.fin-help[hidden]`（0,2,0）>
        `.fin-help`（0,1,0），所以不需要 `!important`。
     ③ 面板走**绝对定位** —— 展开/收起绝不能把下面的 KPI 小片与表格整块推下去
        （那会让页面跳一下）。
   ⚠️ 浮层视觉用**浅色卡片档**（白底 + 浅描边 + 12px 圆角 + 浮起阴影），
      **不新造颜色**：与下方表格卡同一族，一眼就是"系统里的说明卡"。
      ⛔ 曾试过复用金额 tooltip 的**深色**浮层（`.af-money__tip` 那套深底反白）——
         截图实测：深色块**视觉重量压过了第一个 KPI 小片**（"替票张数"被盖住时
         看着像页面缺了一块），而且在一屏浅色的页面里显得像"另一个系统的组件"。
         ⇒ 教训：**深色浮层只适合 1~2 行的短提示**（金额 tooltip 就是），
            多行说明要用浅色卡片。
   ⚠️ 面板**盖住第一个 KPI 小片就让它盖** —— 说明是**用户主动点开**的临时层，
      用户正看着它读，此时"不遮挡下方内容"不是需求；
      而"展开时不把下方内容推下去"（不走文档流）才是必须的。
   ⚠️⚠️ 本注释**只能有一个结束标记**：我插第二批说明时多写了一个注释结束符，
      注释**提前闭合** ⇒ 后面三行变成野文本 ⇒ 紧跟着的 `.fin-help { position: relative }`
      **整条规则被吞掉**。后果是"面板定位到页面左下角、问号被 space-between 推到最右边"，
      而 CSS 不报错、门禁也不红（这正是"注释写坏结构"这类坑最难查的地方：
      **改注释也是改代码** —— 本轮 20 分钟就花在这上面）。
      ⚠️ 以及在注释里**提到那个结束符本身**时，必须拆开写（拆成星号 + 斜杠两半），
         否则你会在"解释这个 bug"的同一句话里再制造一次同样的 bug（本轮连踩两次）。 */
.fin-help {
  position: relative;
  display: inline-flex;
  align-items: center;
  align-self: center;
  /* -8px 抵消 `.page-header` 的 gap:16px ⇒ 与标题的间距收成 8px（紧贴但不贴死） */
  margin-right: auto;
  margin-left: calc(-1 * var(--space-2));
}
.fin-help[hidden] { display: none; }
.fin-help__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  padding: 0;
  border: 0;
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--color-meta);
  cursor: pointer;
}
/* 悬停 / 展开时用全站"选中态"语言（浅蓝底 + 主色字）——别新造颜色 */
.fin-help__btn:hover,
.fin-help__btn[aria-expanded="true"] {
  color: var(--color-accent-text);
  background: var(--color-accent-bg);
}
.fin-help__btn:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}
.fin-help__panel {
  position: absolute;
  top: calc(100% + var(--space-2));
  left: 0;
  z-index: 30;
  width: 400px;
  max-width: min(400px, 82vw);
  padding: var(--space-4);
  background: var(--color-surface);
  color: var(--color-fg-2);
  border: 1px solid var(--color-border-soft);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  font-size: var(--font-size-xs);
  line-height: 1.75;
  text-align: left;
  white-space: normal;      /* 标题是 nowrap 语境，这里必须**显式**放开换行 */
}
.fin-help__panel[hidden] { display: none; }
/* 窄屏：400px 定宽会超出屏幕（`max-width:82vw` 已兜底，这里再把左边缘对齐容器） */
@media (max-width: 768px) {
  .fin-help__panel { left: calc(-1 * var(--space-4)); }
}

.fin-h3 {
  margin: var(--space-5) 0 var(--space-3);
  font-size: var(--font-size-base);
  font-weight: var(--font-weight-semibold);
  color: var(--color-fg);
}

/* ---- 说明条 ---- */
.fin-note {
  padding: var(--space-3) var(--space-4);
  margin-bottom: var(--space-4);
  background: var(--color-primary-50);
  border-radius: var(--radius-md);
  font-size: var(--font-size-xs);
  line-height: 1.65;
  color: var(--color-fg-2);
}
.fin-note b { color: var(--color-accent-text); font-weight: var(--font-weight-semibold); }
.fin-note__sub { display: block; color: var(--color-muted); margin-top: 2px; }

/* ---- 单据号 ---- */
.fin-code {
  font-family: var(--font-family-mono);
  font-size: var(--font-size-xs);
  color: var(--color-fg);
}

/* ---- 状态标签 ---- */
.fin-tag {
  display: inline-block;
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-medium);
  padding: 1px 7px;
  border-radius: var(--radius-sm);
  white-space: nowrap;
}
.fin-tag--success { background: var(--color-success-bg); color: var(--color-success-text); }
.fin-tag--danger  { background: var(--color-danger-bg);  color: var(--color-danger); }
.fin-tag--warning { background: var(--color-warning-bg); color: var(--color-warning-text); }
.fin-tag--muted   { background: var(--color-gray-50);    color: var(--color-muted); }
/* ⭐ 「待付款」= **待办**，不是异常（2026-09-21 改）。
   ⚠️ 原来它用 `--danger` 红色 —— 而红色在这套色板里表示"出问题了"（已驳回、缺票号）。
      「待付款」恰恰是**一切正常、就等财务动手**的状态，也是财务每天最该去处理的一批。
      用红色会让人以为这些单有毛病、反而不敢动；也把"真正的异常（已驳回）"稀释掉了。
   ⚠️ 用主色蓝：全站"待办/需操作"的语言就是蓝（按钮、链接、选中态）。
      于是三种色各司其职 —— 蓝=**该你动** / 橙=**别人在办** / 红=**出问题了**。 */
.fin-tag--todo    { background: var(--color-primary-100); color: var(--color-primary-700); }

/* 「缺票号」提醒 —— 这是发票核验页最该被看见的东西 */
.fin-miss {
  display: inline-block;
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-medium);
  padding: 1px 7px;
  border-radius: var(--radius-sm);
  background: var(--color-warning-bg);
  color: var(--color-warning-text);
}

/* ⚠️ 这里原有 `.fin-groups`（"待付款分组 / 按人凑批次"的早期布局）——
   实测零引用（`grep -rn "fin-groups" public/js/ tests/`（含 index.html） 无结果），
   与上面那段一起删除。 */
/* ⚠️⚠️ 2026-09-21 **删掉一段死 CSS，并因此消掉一个类名撞车**：
   这里原来有一组 `.fin-group` / `.fin-group__h/n/c/a/b` + **另一个 `.fin-chip`**
   （灰底、2px 7px 内边距、4px 圆角），是早期"详情页分组标签"的样式。
   实测 `grep -rn "fin-group" public/js/ tests/`（含 index.html） **零引用** ⇒ 纯死代码。
   而那个裸 `.fin-chip` 与 **KPI 小片用的 `.fin-chip` 同名**：
     · 两处特异性都是 (0,1,0)，靠**源码先后**决定胜负（KPI 规则在后面 ⇒ 目前是它赢）；
     · 一旦有人去改那段"死"代码，会**静默影响 KPI 小片**（反之亦然）——
       这正是本项目反复强调的"同一个类名两种用途 ⇒ 必然出事"。
   ⇒ 一并删除。删除前后实测 KPI 小片的 w/h/bg/radius/padding/color **逐项一致**
     （见交付说明里的 before/after 对照），**零行为变化**。 */

/* ---- 键盘可达 ---- */

/* ---- 手机：导航在**侧栏抽屉**里，只做"单行化"适配 ----
   ⚠️⚠️ 2026-09-21 重要修正：原来这一块是「把导航从左侧竖列改成内容区**顶部横排**」
      （`flex-direction: row` + `overflow-x: auto`），因为那时导航是内容区里的独立列、
      窄屏占宽度太狠。**现在导航搬进了应用侧栏**（`#sidebar-nav`）⇒ 那套横排逻辑不成立：
        · 侧栏在手机上本来就是**抽屉**（宽 240、滑入滑出）⇒ 不存在"占太多宽度"的问题
        · 若还保留横排，4 个导航项会在 240px 抽屉里挤成一横排、还要横向滚动（很难用）
      ⇒ 那些"横排容器 / 横排时压缩每项 / 手机上只留标题 / 图标改 static"的规则**已全部删掉**。
   ⭐⭐ 2026-09-22 深夜：财务侧栏改用**达播同一套标准类**之后，这块手机适配**不再需要**——
      达播侧栏本来就有完整的窄屏规则（抽屉 + 单行菜单项），财务直接用同一套即可。
      ⛔ 不要再为财务单写手机侧栏规则：那会又分叉出第二套观感。
   ⚠️ 教训（值得记住）：**把元素从一个容器搬到另一个容器时，要连带检查它所有的
      `@media` 规则** —— 桌面规则好发现，写在文件下半部分媒体查询里的**最容易漏**。
      本轮就是靠部署脚本的静态自检把它抓出来的（判据是"行首出现该类的规则"）。
   📌 写这段注释时的二次教训：说明里**不要原样写出那对"类名 + 花括号"的字符**，
      否则静态自检（`grep`）会把这句说明当成"规则还在"而**误拦部署**。
      这里只用中文描述"横排容器那条规则"，不贴原文。 */
@media (max-width: 768px) {
  .fin-body { flex-direction: column; }
  .fin-main { padding: var(--space-4) var(--space-4) var(--space-8); }
  /* ⚠️ 原来这里有一条 `.fin-inp { width: 100% }`（窄屏搜索框占满）——
     `.fin-inp` 已随"改用标准控件"下线，而标准 `.input--search` 的窄屏规则
     components.css 里**已经有了**（`flex:1 1 auto` + `.input { width:auto !important }`）
     ⇒ 这里不再补规则。**别在本文件里写 .input--search**：pages-finance.css 是**全站引入**的
     （index.html 无条件下载），写在这儿会波及所有模块的搜索框。 */
  /* 窄屏：工具栏右侧分组改成占满一行、去掉左推（标准 .toolbar__right 是 margin-left:auto）。
     ⚠️ 类名跟着 JS 一起从 .fin-bar__right 改成了 .toolbar__right —— 只改 JS 不改 CSS
        会留下"死规则"（不报错、但窄屏布局悄悄失效）。 */
  .toolbar__right { width: 100%; margin-left: 0; }
}

/* ==========================================================================
   2026-09-20 第二轮新增：部门 tab · 审批流程条 · 报销情况旗标 · 详情页 · 发票图
   ⚠️ 颜色一律取设计令牌；不写死 hex（本项目禁硬编码颜色）
   ========================================================================== */

/* ══ 页面结构：一级 tab / 工具栏 / 二级 tab / KPI 小片（2026-09-21 定稿）═══════
   顺序：一级 tab（状态，下划线）→ 工具栏 → 二级 tab（部门，胶囊）+ KPI → 共 N 单 → 表格
   外层：整块包进 `.card`（白卡片）—— 达播台列表页的标准外壳，同时解决"tab 与工具栏重叠"。

   ⚠️⚠️ **达播台的 tab 分两级，而且是由 `app.js` 自动定形的 —— 别自己写样式对抗它**
   （2026-09-21 读代码 + 实测确认）：
      · **一级 tab** = 页面级"视图/状态大类"切换 → **下划线式**（`.table-tabs`）
      · **二级 tab** = 在当前视图内再筛（部门/岗位这类）→ **胶囊**（`.pill-filter`）
   施加者是 `app.js` 三个函数：`fixPageTabs`（页面级工具栏里的 tab）/
   `fixTableTabs`（卡内表格工具栏里的）/ `fixBareSeg`（裸在外面的）。
   它们统一把 tab 变成下划线式、并提到筛选**上面**；**但有一个明确例外**：
      `skipSeg = 页面已有 page-tabs && 卡内无 table-tabs`
      ⇒ 此时卡内的 `.pill-filter`/`.seg` **不被转换、保持胶囊**
        （原话：「页面已有 `.toolbar--has-page-tabs` ⇒ 卡内出现的 seg 只能是筛选条件」）。

   ⇒ 本页顺着框架来：
      · 状态 tab 用 `.seg`、放进页面级 `.toolbar` ⇒ 框架给下划线形态 + 独占第一行；
      · 部门筛选用 `.pill-filter`、放在卡内 `.table-toolbar` ⇒ 框架判为"筛选条件"、保持胶囊。
   ⚠️ 我第一版把状态 tab 写成 `.tabs` 且独立在卡片内 ⇒ 框架认不出它是页面级 tab
      ⇒ 部门胶囊被 `fixTableTabs` 搬出工具栏、转成下划线（类名变 `pill-filter table-tabs`）
      ⇒ 两级长得一模一样，与要求正好相反。
   ⚠️ 还有一个连带坑：KPI 的容器**不能**用 `.table-toolbar__right` ——
      框架会把这个类搬进"表格 tab 行"（实测 KPI 跑到状态 tab 那行去了）；用中性的 `.fin-chips` 就不会被搬。

   ---- 卡片外壳 ---- */
/* `.card > .tabs` / `.card > .toolbar`（左右留白 + 下边框）在 components.css 里已有，不重复定义。
   这里只补"卡片内的二级 tab 行"与"表格底部圆角"。 */
.fin-ovcard { padding: 0; overflow: hidden; }   /* overflow:hidden 让表格贴底时被卡片圆角裁齐 */
.fin-ovcard > .table-toolbar { padding: var(--space-3) var(--space-5); }
/* ⚠️ 同一页有多张表格卡时（付款管理 2 张）必须留间距 —— 实测间距是 **0px**
   （`.card + .card` 没有通用规则），两张白卡直接贴死、中间只隔着各自的 1px 描边，
   看起来像"一张卡被切开"。L4 规范：`.card` 之间 16px。 */
.fin-ovcard + .fin-ovcard { margin-top: var(--space-4); }
/* 卡片内的「共 N 单」提示行：左右留白与其它行对齐，上下收一点（它是辅助信息，不该占太多） */
.fin-ovcard > .fin-count { padding: var(--space-2) var(--space-5); margin-bottom: 0; }
/* 卡片顶部的说明条（2026-09-21：三页的说明条由"卡外灰底"移进卡内）——
   ⚠️ 为什么必须进卡内：说明条夹在工具栏与卡片之间会把两者的间距撑到 > 24px，
      框架 `markToolbarJoin` 就**不合并**了 ⇒ 这一页会长成"灰底工具栏 + 白卡表格"，
      与总览页的"工具栏并进白卡"是两种形态。放卡内则两边都合并，全模块一个样。
   ⚠️ `.fin-ovcard` 是 `padding:0`，所以这里用 margin 给左右留白（与 `.fin-count` 的 20px 对齐）。 */
.fin-ovcard > .fin-note { margin: var(--space-4) var(--space-5) 0; }
.fin-ovcard > .fin-note + .fin-count { padding-top: var(--space-3); }
/* 卡片内的"小节标题"（付款管理两张表各一个）——
   放在 `.table-toolbar` 这个标准槽位里（表格卡"表头上一行"），标题与它管的表格同卡。 */
.fin-cardttl { font-size: var(--font-size-sm); font-weight: var(--font-weight-semibold); color: var(--color-fg); }
.fin-ttl__right { margin-left: auto; display: inline-flex; align-items: center; gap: var(--space-3); }

/* ---- KPI 小片（**全模块唯一的 KPI 形态**）----
   ⚠️ 2026-09-21 三次改（乐哥：「财务中心顶部的那4个卡片，其实可以大一点，整体你看怎么弄协调些」）：
     上一版是"30px 高、数字 14px、4 个挤在左边（只占 612/1241 = 49% 宽）"，
     实测两个可量化的问题：
       ① **太小** —— 小片比表格的**表头（44px）和行（46px）都矮**，
          而它承载的是"全模块的总数"、视觉权重却最低；数字 14px 对比页面标题 24px 也压不住。
       ② **不齐** —— 右半边整块空白，与下方满宽的工具栏 / 表格左右都不对齐。
     ⇒ 改法（同时解决两条）：
       · 高 30 → **44px**（对齐全站 44px 档：表头 / 表单控件同高）
       · 数字 14 → **20px**（`--font-size-xl`，与"模块标题"同级）
       · 4 个 **等宽铺满**（grid 4×1fr）⇒ 与下方元素左右边缘对齐
       · 标签靠左、数字+说明靠右（`margin-left:auto`）⇒ 满宽但不留死白
       · 圆角 8 → **12px**（`--radius-lg`）：44px 高、满宽等分的形态已经**是卡片**，
         与下方表格卡（同为 12px）成同一族；L4 的圆角阶梯"卡片=12 / 控件=8"，
         形态变了档位跟着变 —— 这是**按规范升级**，不是放水。
         ⚠️ 配套：`verify-finance-ui-l4.js` 的 C4/C5 判据已同步改为 12px。 */
.fin-chipbar { margin-bottom: var(--space-4); }
.fin-chips {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--space-3);
}
.fin-chip {
  /* ⭐⭐⭐ 2026-09-21 **第 5 次改：横向 → 纵向两行**（乐哥：「上面那个卡片的数字，
     现在放大的数字位置很奇怪，看下整体怎么调整下」）。
     ⚠️ 先说清"奇怪"到底是什么 —— **量出来的**，不是感觉：
        88px 高、301px 宽的卡片里，标签「未结清」宽 42px、数字组「10单 ¥2.04万」宽 114px，
        而两者之间空出 **103px**（片2 是 121px、片4 是 89px）。
        也就是说**卡片 1/3 的宽度是一块毫无内容的死白**，数字被 `margin-left:auto`
        推到最右边、孤零零地飘着；高度从 44 加到 88 之后，这块空白在纵向上更显眼。
     ⇒ 根因不是对齐、是**布局形态**：单行横向排布 + 两端对齐，在"标签短、数值长"的
        情形下必然留大洞（这正是它从 44px 起就有的问题，只是矮的时候不明显）。
     ⇒ 改成**纵向两行**（这是 KPI 卡片的标准形态，也正是 88px 高度该有的用法）：
           行1：标签（14px，次级色）
           行2：数字(30px) + 单位 + 说明
        两行**左对齐** ⇒ 空白自然消失，且高度被真正用起来（不再"高而空"）。
     ⚠️ 别改回"标签左 / 数值右"的横向两端对齐 —— 它会重新制造那块死白。 */
  /* ⭐⭐⭐ 2026-09-27 **B 方案落地：改 grid + 彩色图标块**（乐哥拍板，见
     docs/UI评审修复任务-启动文档-20260926.md §三：全站 KPI 统一「彩色图标块 + 白底 + 黑粗体数字」）。
     形态：行1 = [彩色图标块 30px] [标签]，行2 = 数字组（跨两列）。
     ⚠️ 为什么从 flex-column 改 grid：图标块要与标签**同行**（这是看板 KPI 卡已确立的
        语言：图标块在左、标签紧跟其右、大数字在下一行）。flex-column 做不到"图标与标签
        同行 + 数字独占下一行"这个两行结构，grid 两列自然表达。
     ⚠️ 定位策略（**为兼容无图标调用方**）：图标块与标签**不写死 grid-column**，
        靠自然流填充（ico→(1,1)、l→(1,2)）；数字显式 `grid-column: 1 / -1` 跨两列。
        ⇒ 没传 `icon` 时第一列为空、标签自动落到 (1,1)，布局回退成旧的两行形态，零副作用。
        ⛔ 别给 `.fin-chip__l` 写死 `grid-column: 2` —— 那会让"无图标"场景的标签无故缩进。 */
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  align-content: center;
  column-gap: 10px;
  row-gap: 4px;
  /* 纵向居中：两行（图标行 + 数字行）作为一个整体在 88px 内垂直居中 */
  height: 88px;
  padding: 0 var(--space-4);
  background: var(--color-surface);
  border: 1px solid var(--color-border-soft);
  border-radius: var(--radius-lg);
  white-space: nowrap;
  min-width: 0;
}
/* 彩色图标块（B 方案核心要素）——30px 圆角方块 + 白图标，配 88px 小片。
   ⚠️ 尺寸有意比看板（44px 块 + 22px 图标）小一号：小片矮（88px vs 看板 ~130px），
      同比例缩放才协调（本项目规格：图标块与容器高度成比例，别硬套 44px）。 */
.fin-chip__ico {
  width: 30px;
  height: 30px;
  border-radius: var(--radius-md);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  flex: none;
}
/* 5 色与 pages.css 的 `.kpi-card__icon--*` 一一对应（同一组 `--kpi-icon-*` 令牌，不新造色板） */
.fin-chip__ico--blue   { background: var(--kpi-icon-blue); }
.fin-chip__ico--green  { background: var(--kpi-icon-green); }
.fin-chip__ico--orange { background: var(--kpi-icon-orange); }
.fin-chip__ico--purple { background: var(--kpi-icon-purple); }
.fin-chip__ico--pink   { background: var(--kpi-icon-pink); }
/* 警示态（warn）：**米黄底**语义变体（全站认可的"要盯的项"处理，售后分析同款）——
   白卡一排里米黄底一眼跳出来；柔底不再描边（描边会让柔底显脏，同 `.kpi-card--tone-*` 的做法）。 */
.fin-chip--warn {
  background: var(--color-warning-bg);
  border-color: transparent;
}
/* 标签：次级信息，放**上面一行** */
.fin-chip__l {
  /* ⚠️ 不写 grid-column：靠自然流落位（有图标→(1,2) / 无图标→(1,1)），见 `.fin-chip` 注释 */
  align-self: center;      /* 图标块 30px 高、标签行盒 21px ⇒ 垂直居中而非顶对齐 */
  font-size: var(--font-size-sm);
  color: var(--color-meta);
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}
.fin-chip__v {
  /* ⭐ 2026-09-27：数字组**跨两列**（从最左起排，与看板 KPI 的"大数字占满行"同一语言） */
  grid-column: 1 / -1;
  /* ⚠️ 这里原来有 `margin-left: auto`（把数值推到右端）—— 纵向布局下**必须删掉**，
     否则数值仍会被推到最右、与标签错开，死白换个形式回来。 */
  flex-shrink: 0;
  /* 数字与单位**各自居中**（2026-09-21 第 4 次改的成果，保留）：
     原来的写法是「30px 数字 + 14px 单位」同在一条基线上 ⇒ 单位跟着数字的**基线**走，
     小字贴在大字基线上、字形中心偏低 ⇒ 看起来"没上下居中"。
     ⇒ 拆成两个 flex item + `align-items: center`，各自居中。 */
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);                 /* 数字与单位贴近但不粘连 */
  font-size: var(--font-size-3xl);     /* 30px：金额分支（.af-money）继承它 */
  font-weight: var(--font-weight-semibold);
  color: var(--color-fg);
  font-variant-numeric: tabular-nums;
  min-width: 0;
  /* ⚠️⚠️ **行高必须收紧到贴近字号**（2026-09-21 实测，这是"两行版"能居中的关键）：
     默认行高是 1.5 ⇒ 30px 数字的行盒有 **45px**，而数字字形只有 22.7px
     ⇒ 行盒里上下各留 11px 空气，与上面那行（14px 标签、行盒 21px）的留白不对等
     ⇒ 整块文字（标签 + 数值）的**墨迹**并集偏上 **2.85px**（实测上下留白 12.3 / 18）。
     ⇒ 收紧行高后，数值行盒 = 33px，墨迹并集中心落到 43.6（片中心 44）⇒ 偏差 0.4px。
     ⚠️ 别用 `line-height: 1`：中文字形可能被裁（数值行里含「单」「张」等单位）。
     ⚠️ 别删这一行去"图省事"—— 删掉后 B4（上下留白对称）会立刻报红。 */
  line-height: 1.1;
}
/* 数字 / 单位 / 金额：都是 flex item，**不许被压缩**（否则窄屏会把「10单」挤变形） */
.fin-chip__v > * { flex-shrink: 0; }
.fin-chip__num { font-size: var(--font-size-3xl); font-weight: var(--font-weight-semibold); }
/* 单位比数字小一档、颜色更轻 —— 但**中心对齐**（不再贴数字基线） */
.fin-chip__unit {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-regular);
  color: var(--color-muted);
}
.fin-chip__s {
  flex-shrink: 0;
  font-size: var(--font-size-sm);
  color: var(--color-meta);
  font-variant-numeric: tabular-nums;
}
/* 有需要注意的量（未结清 / 待付款 > 0）→ 数字用警示色 */
.fin-chip--warn .fin-chip__v { color: var(--color-warning-text); }
/* 窄屏：4 等分会把每个格子挤到放不下（≥305px → ≤90px）⇒ 退成 2 列；
   高度与字号同步降档（88px×2 行在手机上占 176px，太占屏） */
@media (max-width: 768px) {
  .fin-chips { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .fin-chip { height: 64px; padding: 0 var(--space-4); }
  .fin-chip__v, .fin-chip__num { font-size: var(--font-size-2xl); }
}

/* ---- 报销单号列靠左（2026-09-21 乐哥：「报销单号靠左，金额靠右，其他居中」）----
   ⚠️ 只作用于**本表**（`.fin-ovtbl`）：全站表格规范（乐哥 2026-09-14 定稿）是
      "短文本/编号列一律居中"，这张表是**特例**；不写类名会把全站 16 张表一起改掉。
   ⚠️ 选择器必须写到 `tbody tr td` 层级：全站"全列居中"那条是
      `.table:not(:where(td .table)) > tbody > tr > td`（特异性 0,1,3），
      只写 `.fin-ovtbl td`（0,1,1）**压不过它** ⇒ 会静默不生效（看起来"改了没反应"）。
   ⚠️ 表头**保持居中** —— 与金额列同一处理（表头居中、内容按列性质对齐），
      这是项目既有约定（乐哥 2026-09-15：「其他所有的位置都不变」）。 */
.fin-ovtbl tbody tr td:first-child { text-align: left; }
/* ⚠️「N 笔」小标**不许换行**（2026-09-21）——
   原来它跟在 13 位单号后面，列一窄就被挤到第二行，把行高从 72 抬到更高、且看着像"两个单号"。
   锁 nowrap 后：单号列的最小宽度 = 单号 + 小标，布局算得准，也不会两行。 */
.fin-ovtbl .fin-badge { white-space: nowrap; }
.fin-ovtbl .fin-code { white-space: nowrap; }

/* ⭐ 列宽（2026-09-21 乐哥：「报销单号列窄一点，分给其他列」）——
   宽度由 JS 的 `<colgroup>` 给（按各列内容实测需要分配），这里只保证**固定布局**
   与"单号列不再抢空间"。用 `table-layout: fixed` 让 colgroup 真正说了算
   （auto 布局下浏览器会按内容比例重新分配，colgroup 只是"建议"）。 */
.fin-ovtbl { table-layout: fixed; }
/* ⚠️⚠️ 替票表也必须**固定布局**（2026-09-21 实测）：`table-layout:auto` 下
   「说明」列那串很长的底稿文案（「查验接口返回 HTTP 401（APIG.0303 …）」）
   会把 746px 全抢走，把「开票日期」挤到 94px ⇒ `2026-07-30` **折成两行**
   （同一张表本地 1 行、测试环境 2 行 —— 差别就是说明文案的长短）。
   ⇒ 只有"给了 colgroup 宽度"的表才加 `fin-fixtbl`；没给宽度的表保持 auto
      （否则 fixed + 无宽度会让所有列等宽，反而更差）。 */
.fin-fixtbl { table-layout: fixed; }
/* 固定布局下内容超宽会被裁 —— 给单号列与报销人列一个"至少要放得下"的兜底：
   允许它们换行而不是溢出（财务最怕看到被切掉的单号）。 */
.fin-ovtbl tbody tr td { overflow-wrap: anywhere; }
/* 首列仍是靠左（与上面那条同一意图，固定布局后需要重新声明一次以免被覆盖） */
.fin-ovtbl thead th:first-child { text-align: left; }

/* ⭐⭐ 两个状态列的「内容容器给固定宽度」——这是"开头固定位置、对齐"的实现方式
   ──────────────────────────────────────────────────────────────────────────
   乐哥原话：「报销情况，审核状态列的开头要不要固定个位置。对齐」
   实测现象：进度条左缘有 **3 种取值**（973 / 959 / 953）—— 因为整组「条 + 文字」
   被单元格**居中**，而各行文字长短不同 ⇒ 整组宽度不同 ⇒ 居中后左缘就被推来推去。

   ⚠️ 解法有两个方向，这里选后者：
     ① 把单元格改成靠左 —— 但乐哥之前定过「其他列居中」（报销单号靠左、金额靠右），
        为一个对齐去破坏既有对齐规则不划算；
     ② **给内容容器一个固定宽度**（`width`），里面再左对齐 ——
        这样"整组宽度"恒定，**居中之后左缘自然完全一致**。
   两个列都要（审核状态 / 报销情况）—— 两列结构**完全同构**
   （2026-09-21 乐哥定稿：「报销情况也按照审核状态那样子做」）。
   ⚠️ 摆放方式后来改过（乐哥当天下午又调了一次）：**标签移到最前（左）**、
      进度文字移到进度条**上面** ⇒ 对齐不再靠"条区定宽"、而是靠"标签列定宽"，
      见下面 `.pg` 的说明。 */
/* ⭐⭐ 状态块布局（两列共用）—— 乐哥 2026-09-21 下午定稿：
     原话：「把 1/4·审批完成 这个，放在那 4 个进度条上面，
            那个状态标签比如待付款那个放在所有进度的前面，
            然后高度和进度条还有进度条上面的文字整体差不大一样」

     ┌─────────────────────────────────────────┐
     │ [待付款]   4/4 · 审批完成                │  ← 上排：标签（最前/左）+ 进度文字
     │            ━━ ━━ ━━ ━━                  │  ← 下排：进度条
     └─────────────────────────────────────────┘

     实现：grid 2×2，靠**子元素顺序**摆位（标签 / 文字 / 条，见 JS 的 pgBlock）：
       [0] 标签    → 第 1 列、跨两行（垂直居中）
       [1] 进度文字 → 第 2 列第 1 行
       [2] 进度条  → 第 2 列第 2 行
     ⚠️ 第 1 列用 `auto`（按最长标签定宽）—— 现在两列的标签都是 3 个字（待付款/审批中/未开始…），
        宽度自然一致 ⇒ 第 2 列起点一致 ⇒ **文字与进度条左缘都对得齐**。
        （以前靠"条区定宽 100px"对齐，现在靠"标签列定宽"对齐，原因是条换了位置。）
     ⚠️ 行间距 3px 而不是 --space-*：这两行属于**同一个信息组**（一个状态），
        拉开会显得散、且整格变高；3px 既分得开又保持紧凑。 */
/* ⭐⭐ 2026-09-23：`fin-cell-prog` 是**并列的第二个作用域**（选择器列表，不是第二条规则）——
   见下方 `.fin-prog.fin-cell-prog` 的注释：让"没有 `.fin-ovtbl` 的表格"（审批台/我的报销）
   也能拿到同一套两行布局。声明**只有一份**，改这里两边同时生效。 */
.fin-ovtbl .pg,
.fin-cell-prog .pg {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-rows: auto auto;
  align-items: center;
  column-gap: var(--space-2);
  row-gap: 3px;
  margin-top: 0;
}
.fin-ovtbl .pg > .fin-tag,
.fin-cell-prog .pg > .fin-tag { grid-column: 1; grid-row: 1 / span 2; }
.fin-ovtbl .pg > .pg__txt,
.fin-cell-prog .pg > .pg__txt { grid-column: 2; grid-row: 1; white-space: nowrap; }
.fin-ovtbl .pg > .pg__bars,
.fin-cell-prog .pg > .pg__bars { grid-column: 2; grid-row: 2; justify-self: start; }
/* ⚠️ 审批流程未同步时的兜底：那一格只有「标签 + 文字」、没有进度条
   ⇒ 文字落回第 2 列第 1 行，形态与正常的行一致（标签仍在最前）。 */
/* ⭐⭐ 状态块：**定宽 + 居中 + 内部左对齐**（乐哥 2026-09-21 15:45）
     原话：「现在这样可以，不过居中显示吧，然后居中后，开始的位置靠左对齐」

     ⚠️⚠️ 关键坑（我第一版就是错的）：**不能再写 `width:100%`**。
        写 100% 时它会撑满单元格 ⇒ 看起来是"左对齐"、根本看不出居中
        （实测：单元格内容宽 292，容器也 292，左右各只剩 padding 的 12px）。
     ✅ 正确做法：给定宽（`160px`）⇒ 单元格是 `text-align:center`（全站规范）⇒
        容器整体**居中**；容器内部 `text-align:left` ⇒ 各行内容**起点一致**。
     为什么是 160px：实测两列内容的自然宽度是 **155px**（审核）/ **154px**（付款）——
        标签 50 + 列间距 8 + max(进度文字 98, 进度条 97)。取 160 留 5px 余量。
        两列用**同一个宽度**，视觉上更整齐。
     ⚠️ `max-width:100%` 是**窄屏降级**：窗口变窄时列宽会小于 160，
        此时退回撑满（放弃居中，但不让内容溢出/被压）。
     为什么定宽是"各行左缘一致"的前提：各行内容长短不同（`0/3 · 待统一提报` vs
        `3/3 · 付款完成`），若是自适应宽度，居中后左缘会被推来推去；
        定宽之后每行的容器左缘相同 ⇒ 内容起点自然对齐。 */
/* ⚠️ 第二条选择器是 `.fin-prog.fin-cell-prog`（**元素自身**同时带两个类），
   不是后代选择器 —— 因为 `fin-cell-prog` 就加在那个 `.fin-prog` 元素上。
   两个选择器特异性都是 (0,2,0)，声明共用同一处。 */
.fin-ovtbl .fin-prog,
.fin-prog.fin-cell-prog { display: inline-block; width: 160px; max-width: 100%; text-align: left; }

/* ⚠️ 原来这里有一套 `.fin-steps` / `.fin-step`（报销情况的"三个文字小标签"），
   2026-09-21 已随结构改造**删除** —— 报销情况改成与审核状态同构（标签 + 进度条）后，
   这两个类在 JS / CSS / 探针里都已无引用，留着只会误导后来者以为还有第二套形态。
   查证：`grep -rn "fin-step" public/ .render-check/ tests/` 无命中。 */

/* ---- 审批流程条（列表里的一行小字）---- */
/* ⭐⭐ 审批进度条（2026-09-21 重做，乐哥：「列表页的审批状态看着不直观」）
   ──────────────────────────────────────────────────────────────────────────
   形态 = 「B 的长条」+「A 的完成/当前/之后区分」+「进度数字」（乐哥拍板的组合）。
   换掉的旧实现是 4 个带底色的文字标签 + `›` 连接符，三个毛病：
     ① "正在等审"与"还没轮到"同色（都橙底）⇒ 看不出进度，只能读旁边的小字
     ② 4 个色块 + 主标签 + 小字 = 占 3 行高，整列全是色块、扫读要一个个读
     ③ 驳回后那些**永远不会执行**的节点仍是橙底"待审批" ⇒ 假信息（像流程还能走）
   ⚠️ 关键：**"还没轮到"用灰色**（`--color-gray-200`），不是 warning 橙 ——
      橙色只留给"当前正在办的那一道"，这样一眼就能看出停在哪。
   ⚠️ 段与段之间留 3px 缝：有缝才看得出"这是第几段"，无缝就成了一条进度条、数不清段数。
   ⚠️ 每段 22px 宽 × 6px 高：够看清颜色，又不至于把整列撑宽（原来 4 个节点名占满了整列）。 */
.pg { display: inline-flex; align-items: center; gap: var(--space-3); margin-top: var(--space-2); }
.pg__bars { display: inline-flex; gap: 3px; flex-shrink: 0; }
.pg__bar {
  width: 22px;
  height: 6px;
  border-radius: 3px;
  background: var(--color-gray-200);   /* 还没轮到 */
}
.pg__bar.is-done { background: var(--color-success); }
.pg__bar.is-cur  { background: var(--color-warning); }
.pg__bar.is-rej  { background: var(--color-danger); }

.pg__txt {
  font-size: var(--font-size-xs);
  color: var(--color-fg-2);
  white-space: nowrap;
}
/* 当前/驳回用更重的字色 + 加粗：让"卡在哪"成为这一格里最先被看到的信息 */
.pg__txt.is-cur  { color: var(--color-warning-text); font-weight: var(--font-weight-medium); }
.pg__txt.is-rej  { color: var(--color-danger); font-weight: var(--font-weight-medium); }
.pg__txt.is-done { color: var(--color-success-text); }

/* 窄屏：进度条小一档 + 文字不换行（手机上「报销单号」列已窄，再换行就串行了） */
@media (max-width: 768px) {
  .pg { gap: var(--space-2); }
  .pg__bar { width: 14px; }
}

/* ---- 报销情况旗标（三小格）---- */
/* ⭐ 「报销情况」三格（2026-09-20 改）
   ────────────────────────────────────────────────────────────────────────
   ⚠️⚠️ 改的原因（可计算，不是"我觉得"）：原来"已勾选"只靠**背景色**区分
      （`--color-success-bg` 绿底 vs `--color-gray-50` 灰底），而这两个底色的
      **对比度只有 1.00** —— 等于在白色卡片上放两块颜色几乎一样的浅色块，
      财务扫一眼根本分不出哪些单已经打款（而"哪些还没打款"正是他每天要看的）。
      实测：文字本身的对比度是达标的（4.57 / 4.86），所以问题不在"看不清字"，
      而在**"状态"没有足够的视觉重量**。
   ⇒ 加强三处（都不依赖配色深浅）：
      ① 已勾选加**实色描边 + 白底的字色加深**（边框是最可靠的"选中"信号）
      ② 图标本身已区分（勾 vs 时钟），再加**文字加粗**强化
      ③ 未勾选**去掉底色**只留浅描边 —— 让"没做的事"退到背景里，
         视觉重点自然落到"已完成"上（而不是两团灰绿并排） */
.fin-flags { display: inline-flex; flex-wrap: wrap; gap: 6px; }
.fin-flag {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-size: var(--font-size-xs);
  padding: 1px 7px;
  border-radius: var(--radius-sm);
  background: transparent;
  border: 1px solid var(--color-border);
  color: var(--color-muted);
  white-space: nowrap;
}
.fin-flag.is-on {
  background: var(--color-success-bg);
  border-color: var(--color-success);
  color: var(--color-success-text);
  font-weight: var(--font-weight-medium);
}

/* ---- 可点的行 ---- */
.fin-row { cursor: pointer; }
.fin-row:hover > td { background: var(--color-primary-50); }
/* ⭐ 「刚生成的提报单」整行高亮（2026-09-23 乐哥：「生成之后，生成的单在哪呢？我看不到啊」
   ⇒ 生成成功后原地切到「提报单」档，并把这一张标出来）。
   ⚠️ 照抄本项目**既有先例**（`pages.css` 的 `.table tbody tr.cm-pend-row > td`）：
      用 `--color-warning-bg-soft`（设计令牌里就是给"警示整行底"的，比 `--color-warning-bg` 更浅）
      + 一个更深的 hover 版。别自己调颜色 —— 那是"同一件事两个色值"的老问题。
   ⚠️ 背景必须写在 `> td` 上，不能写在 `<tr>` 上：单元格自带底色，tr 的底色会被盖住
      （看着像"改了没效果"）。
   ⚠️ 选择器要压过上面的 `.fin-row:hover > td`（本行同时带 `.table`/`tbody`/`tr`，
      特异性更高）；否则 hover 一下高亮就没了、移开又回来，像闪烁。 */
.table tbody tr.fin-row--new > td { background: var(--color-warning-bg-soft); }
.table tbody tr.fin-row--new:hover > td { background: var(--color-warning-bg-hover); }
/* 操作列（2026-09-21 乐哥：最后一列应该是操作）——
   ⚠️ 原来的实现是**箭头 `›`**（宽 28px）。换成文字「查看」后：
      ① 宽度必须放宽到能容下两个字，否则「查看」会被挤成两行（28px 装不下）；
      ② 颜色不再用那个"淡灰→hover 变蓝"的箭头配色，改由内层 `.fin-link` 自带
         （主色蓝 + hover 下划线），与发票核验页的「跳到所属报销单」写法一致。 */
.fin-row__go { width: 56px; white-space: nowrap; }
.fin-row__go .fin-link { font-size: var(--font-size-xs); }
.fin-row:hover .fin-row__go .fin-link { text-decoration: underline; }
.fin-link { color: var(--color-accent-text); cursor: pointer; }
.fin-link:hover { text-decoration: underline; }
/* ⚠️⚠️ `.fin-link` 用在 `<button>` 上时必须 reset（2026-09-23）——
   实测付款管理页的提报单号是 `<button class="fin-link">`，而 `.fin-link` 只写了
   `color` / `cursor` ⇒ 浏览器默认样式没被清掉：
     · `background: buttonface`（实测 `rgb(239,239,239)` **灰底**）
     · 外加默认 `border` 与 `padding`
   ⇒ 单号显示成一个"灰色小方块"，与总览页的纯文本单号（`<span class="fin-code">`）不一致。
   ⚠️ 之前只在这一个页面出现，是因为别处都写成 `<span class="fin-link">`；
      修在 CSS 里而不是改调用方 —— 这样**谁以后再写 `<button class="fin-link">` 都不会再踩**。
   ⚠️ `font: inherit` 也要（button 默认用系统 UI 字体，会与表格里其它文字不同）。 */
button.fin-link {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  color: var(--color-accent-text);
}

.fin-badge {
  display: inline-block;
  margin-left: 6px;
  font-size: var(--font-size-xs);
  padding: 0 5px;
  border-radius: var(--radius-sm);
  background: var(--color-accent-bg);
  color: var(--color-accent-text);
}
/* 「刚生成」小标 —— 必须**放在 `.fin-badge` 之后**（同特异度，靠源码顺序覆盖）。
   ⚠️ 不能写成行内 style：那会让"这个徽标长什么样"散到 JS 里，
      下次改配色要全仓搜。 */
.fin-badge--new { background: var(--color-warning-bg); color: var(--color-warning-text); }
.fin-miss {
  display: inline-block;
  font-size: var(--font-size-xs);
  padding: 1px 7px;
  border-radius: var(--radius-sm);
  background: var(--color-warning-bg);
  color: var(--color-warning-text);
}
.fin-count__hint { color: var(--color-meta); }

/* ---- 说明条：危险版（重复票号）---- */
.fin-note--danger { background: var(--color-danger-bg); color: var(--color-fg); }
.fin-note--danger b { color: var(--color-danger); }
.fin-dup { margin-top: 4px; font-size: var(--font-size-xs); }

/* ---- 详情页 ---- */
.fin-back {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  margin-bottom: var(--space-3);
  padding: 4px 10px 4px 6px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  color: var(--color-fg-2);
  font-family: inherit;
  font-size: var(--font-size-xs);
  cursor: pointer;
}
.fin-back:hover { background: var(--color-surface-2); color: var(--color-fg); }

/* ⭐⭐ 2026-09-23 下钻态（提报单里看它的某张报销单）顶部的**层级条** ——
   把"返回"按钮和一句说明放在同一行，回答"我还在提报单里吗"。
   ⚠️ 为什么需要：这一屏的页头标题是「报销单详情」（内容名实相符）、
      而侧栏高亮是「提报单」—— 两句各自都对，缺一句把它们连起来，
      用户就会以为"我又被扔到报销单那个模块了"（上一轮乐哥报的正是这个）。
   ⚠️ `.fin-back` 自带 `margin-bottom`，在层级条里要去掉，否则整条会偏高。 */
.fin-drill {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-bottom: var(--space-3);
}
.fin-drill .fin-back { margin-bottom: 0; }
.fin-drill__hint { font-size: var(--font-size-xs); color: var(--color-muted); }

/* ══ 单据详情单头（2026-09-24 重整为三层：单号+状态 / 用途 / 元信息）══════════
   ⚠️ 圆角用 `--radius-lg`(12px) 与**相邻的「全流程」卡一致** ——
      原来这里是 `--radius-md`(8px)，两张卡上下紧挨着、圆角不同看着像两套组件
      （本项目在 `.af-step-card` 上定过"卡片档 = 12px"的纪律）。 */
.fin-doc__hd {
  padding: var(--space-4);
  margin-bottom: var(--space-4);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
}
/* 第一行：单号（左） + 状态标签（右）。
   ⚠️ 状态**单独占右端**：它是整单结论，原来排在元信息行末尾、
      与"部门/时间"同级 ⇒ 扫视时最先被漏掉。 */
.fin-doc__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
}
.fin-doc__state { flex-shrink: 0; }
.fin-doc__no {
  font-size: var(--font-size-lg);
  font-weight: var(--font-weight-semibold);
  color: var(--color-fg);
  min-width: 0;                     /* 长号（30 位实例码）时不撑破右端的状态标签 */
  word-break: break-all;
}
/* 用途说明独立一行、字号比元信息大一档 —— 它是"这单干什么用的"，
   与单号是两种信息（原来挤在单号后面只差 2px，看着像同一句话折行）。 */
.fin-doc__reason {
  font-size: var(--font-size-sm);
  color: var(--color-fg-2);
  margin-top: var(--space-2);
  line-height: 1.5;
}
.fin-doc__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-4);
  margin-top: var(--space-3);
  padding-top: var(--space-3);
  /* 与用途/单号之间加一条极浅的分隔线 —— 三层结构靠它"分组"，
     比单纯加大间距更明确（间距在小字号下不够醒目）。 */
  border-top: 1px solid var(--color-border-soft);
  font-size: var(--font-size-xs);
  color: var(--color-muted);
}
.fin-doc__meta b { color: var(--color-fg); font-weight: var(--font-weight-medium); }
/* 金额：元信息行里**唯一**加重的项（财务扫这一屏第一个要找的数）。 */
.fin-doc__amt {
  font-size: var(--font-size-sm);
  color: var(--color-fg-2);
}
.fin-doc__amt b {
  color: var(--color-fg);
  font-weight: var(--font-weight-semibold);
  font-size: var(--font-size-lg);
}

/* 审批流程（4 道节点，横向排） */

.fin-paybar { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; }

/* 发票图（乐哥要的"明细下面还有对应的发票图"） */
.fin-pics {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: var(--space-3);
}
.fin-picbox {
  padding: var(--space-3);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
}
.fin-picbox__h { font-size: var(--font-size-xs); color: var(--color-fg-2); margin-bottom: 3px; }
.fin-picbox__no { font-size: var(--font-size-xs); color: var(--color-muted); font-family: var(--font-family-mono); margin-bottom: var(--space-2); }
.fin-picbox__b { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.fin-pic {
  display: block;
  width: 132px;
  text-decoration: none;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  overflow: hidden;
  background: var(--color-surface-2);
}
.fin-pic img { display: block; width: 100%; height: 96px; object-fit: cover; }
/* ⭐ 2026-09-23：发票缩略图从 `<a target="_blank">` 改成 `<button>`（点击**就地弹层看大图**，
   不再跳到浏览器新标签 —— 那是"下钻到最底层却被弹出系统"）。
   ⚠️ button 自带 padding / 字体 / 居中，**必须 reset** 回原来 `<a>` 的外观，
      否则缩略图会"胖一圈、字体变样"（这类静默外观漂移最容易漏）。
   ⚠️ 只 reset `button.fin-pic`，别碰 `.fin-pic--none`（它是 `<span>`，样式已单独覆盖）。 */
button.fin-pic {
  padding: 0;
  font: inherit;
  text-align: left;
  color: inherit;
  cursor: pointer;
}
button.fin-pic:hover { border-color: var(--color-accent); }
button.fin-pic:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 1px; }
.fin-pic__n {
  display: block;
  font-size: var(--font-size-xs);
  color: var(--color-muted);
  padding: 2px 4px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* 只有飞书文件码时不能渲染成图，给一个明确的说明块（避免显示破图） */
.fin-pic--none {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  width: auto;
  padding: 6px 10px;
  font-size: var(--font-size-xs);
  color: var(--color-muted);
  border-style: dashed;
}

/* ---- 付款：勾选栏 ---- */
.fin-ckcol { width: 40px; }

@media (max-width: 768px) {
  .fin-pics { grid-template-columns: 1fr; }
  .fin-doc__meta { gap: var(--space-3); }
}

/* ══════════════════════════════════════════════════════════════════════════
   标签栏里的「我的」（2026-09-20 乐哥「上面的标签该保留的也保留」）
   ──────────────────────────────────────────────────────────────────────────
   财务模块不渲染侧栏 ⇒ 渲染在**侧栏底部**的那个「我的」菜单没有落脚点，
   于是把它放进标签栏右侧工具组（见 app.js 的 profileHtml / bindProfileIn）。
   ⚠️ 复用 layout.css 的 .user-chip / .profile-menu **原样样式**，这里只加
      "在标签栏里" 需要的三点适配：容器定高、与左侧工具组的分隔线、间距。
      ⚠️ 不要在这里重写 .user-chip 的内部样式 —— 那会让它和达播侧栏那处
         长得不一样，而它们是**同一个组件**。
   ══════════════════════════════════════════════════════════════════════════ */
#finance-profile {
  display: flex;
  align-items: center;
  align-self: center;
  height: 40px;
  /* 与左边的搜索/通知之间划一条竖线：沿用板块切换器那条 `.gs-entry-wrap` 的
     "分组分隔"语言（左边是标签操作、右边是全站能力、最右是「我」）。 */
  margin-left: var(--space-1);
  padding-left: var(--space-3);
  border-left: 1px solid var(--color-border);
}
/* 标签栏只有 52px 高，把 chip 的上下内边距收一点，避免贴边 */
#finance-profile .user-chip {
  padding-top: 2px;
  padding-bottom: 2px;
}

/* ══════════════════════════════════════════════════════════════════════════
   审批流程 · 横向步骤条（2026-09-20 乐哥：「当前那个审批流程，太丑了」）
   ──────────────────────────────────────────────────────────────────────────
   换掉的旧实现（.fin-flow）：4 张等价卡片 + 小号 `›` 连接符，问题是没有进度感、
   连不成线、撑不满留宽、状态只靠 3px 左边框表达太隐晦。
   新实现：圆形节点 + 连通线。已通过=实心绿勾、驳回=红叉、进行中=橙圈+光晕、未开始=灰圈。

   ⚠️ 全部走设计令牌（禁裸 hex，仅 #fff/#000 例外）；字号 ≥12px（规范下限）。
   ⚠️ 连接线用 `flex:1` 自适应，**节点数是变长的**（飞书侧可改流程）
      ⇒ 不能用固定间距，否则 2 道时会留大片空白、6 道时会挤爆。
   ⚠️ 圆点 28px，连接线靠 `margin-top:13px` 与圆点垂直居中（不是 align-items:center，
      因为节点是"圆点 + 多行文字"的纵向结构，居中对齐会让线跑到文字中间）。
   ══════════════════════════════════════════════════════════════════════════ */

/* 步骤条放进标准卡片里（与页面其它区块同语言：白底 + 1px 浅描边 + 12px 圆角）。
   ⚠️ 12px 圆角 = 规范里 `.card` / `.radius-lg` 的值；旧代码里的 .fin-chain__n 用的是
      `--radius-md`(8px)，那是"按钮/输入框"档，卡片档应是 12px。 */
.af-step-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border-soft);
  border-radius: var(--radius-lg);
  padding: var(--space-6) var(--space-5);
}

/* ══ 详情页「全流程」= 审批 + 付款 **并排在同一条节点行、分两段**（2026-09-24 乐哥）══
   ──────────────────────────────────────────────────────────────────────────
   乐哥原话：「红框审批流程，我觉得是不是可以放在同一行，但是两个阶段，
             分别是提报销和报销付款，两个阶段可以不同颜色区分，
             这样的话下面明细就有更多地方展示内容了」

   ⛔ 不是"合成一条 7 步的流程"（2026-09-21 已论证：审批有否决权、付款没有，
      混成一条会让财务以为付款也要等人批）⇒ 仍是**两段**，只是横向并排。
   「两段」靠三处区分，**缺一处就会看成一条 7 步流程**：
     ① 卡头两个段标签（配色不同）  ② 节点形状（圆点 vs 方点）
     ③ 节点配色（审批绿系 vs 付款主色蓝系）

   ⚠️ 删掉了原来的 `.fin-chain__sep`（居中那条"审批通过 · 已入账"分隔行）：
      它是"上下两行"的产物，并成一行后再插一条横线会把这一块撑回两段式的高度（白改）。
      衔接关系改由 ④⑤ 之间的**桥接线** `.af-step__bar--bridge` 表达（见下）。 */
.fin-chain { display: block; }

.fin-chain__head {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-4);
  flex-wrap: wrap;      /* 窄屏时两个段标签可换行，不挤坏右侧按钮 */
}
.fin-chain__lab {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--color-fg);
  padding: 2px 10px;
  border-radius: var(--radius-sm);
  background: var(--color-success-bg);      /* 审批 = 绿系（与它的"已完成"同色语言） */
  color: var(--color-success-text);
}
.fin-chain__lab--pay { background: var(--color-accent-bg); color: var(--color-accent-text); }
.fin-chain__hint { font-size: var(--font-size-xs); color: var(--color-meta); }
.fin-chain__act { margin-left: auto; }        /* 「刷新审批进度」靠右（它属于审批那一段） */
/* 两个段标签之间的竖分隔 —— 让"这是两段"在卡头就成立（光靠间距容易被读成"审批 4 道 · 付款 3 步"一句） */
.fin-chain__vsep {
  width: 1px;
  height: 14px;
  background: var(--color-border);
  margin: 0 var(--space-2);
  flex-shrink: 0;
}

/* 一条节点行装 7 个节点（审批 4 + 付款 3）。
   ⛔⛔ 节点宽度**不能写死** —— 乐哥 2026-09-24：「后面付款提报流程要好几个哦，
      你别画少了」。付款段以后要加环节（老板批 / 财务转账 / 财务转给主管 /
      主管转给部门的人），加完就是 10~12 个节点；宽度写死的话加到第 9 个就会挤爆。
   ✅ 改成**弹性**：`flex: 1 1 84px` ⇒ 7 个节点时每个 118~124px（铺满、宽松），
      12 个节点时自动收到 84px（仍放得下 5 字的节点名）。
      实测边界：12 节点（84px 基准 + 11 条 16px 连接线 = 1184px）≤ 卡内 1206px ✅；
      再多则由下面 `.fin-chain__row` 的横向滚动兜底，**不会挤成看不清**。
   ⚠️ 审批节点原来 104px / 付款 138px：不收窄的话 4×104 + 3×138 = 830，
      连接线只剩不到 40px ⇒ "走到哪一步"的进度感会消失（连接线是进度感的主要载体）。 */
.af-step__n {
  flex: 1 1 84px;
  min-width: 72px;          /* 再压就放不下 5 字的节点名（"打款给主管"= 60px） */
  max-width: 124px;         /* 再多节点也别把它拉成大字块（视觉上会像"标题"） */
  width: auto;              /* ⛔ 不再写死宽度 */
}
/* ⚠️ 付款节点**不单独设宽度**：原来给它写 124px 是"为 3 步定制的"，
   加环节后那个数就不成立了。审批与付款的区分靠**形状（圆点/方点）+ 配色（绿/蓝）**，
   不靠宽度 —— 宽度只由"总共有几个节点"决定（弹性）。 */

/* 桥接线：审批段与付款段之间那一条。
   ⚠️ 语义 ≠ 普通连接线 —— 普通线表示"同一段内的先后"，它表示"**过了这一关才进下一段**"。
      所以：未过 = 虚线（还没轮到），已过 = 绿色实线（`.is-done`）。
   ⚠️ 用虚线的另一层作用：并成一行后，它是唯一能"分段"的视觉断点（形状上区分两段）。 */
.af-step__bar--bridge {
  background: none;
  border-top: 2px dashed var(--color-border);
  height: 0;
  margin-top: 13px;         /* 与圆点垂直居中（与普通连接线同高） */
  min-width: 28px;
  flex: 1 1 28px;
}
.af-step__bar--bridge.is-done {
  border-top-style: solid;
  border-top-color: var(--color-success);
}

/* ⚠️ 极端兜底：节点数超出卡宽时**横向滚动**（而不是挤成一团/撑破卡片）。
   · `padding: 4px 0` 是为了不被裁掉 `is-current` 那圈 4px 光晕（overflow 会裁 box-shadow）。
   · 只在真的放不下时才出现滚动条，7~12 节点都不会触发。 */
.fin-chain__row { overflow-x: auto; padding: 4px 0; }

/* 付款段 = 方点（与审批的圆点区分）。其余完全复用 `.af-step` 的结构与三态配色。
   ⛔⛔ 付款的**配色规则不在这里** —— 见文件下方「付款段配色」那一块。
      原因（本轮实测踩到）：`.af-step__n--pay.is-done .af-step__dot` 与
      `.af-step__n.is-done .af-step__dot` **特异性完全相同**（都是 3 个类），
      此时**后写的生效**。写在这一段（在审批三态规则之前）会被审批的绿**静默覆盖** ——
      现象是"付款已完成的节点还是绿的"，不报错、也不容易看出来。 */
.af-step__n--pay .af-step__dot { border-radius: var(--radius-sm); }

/* 审批段"无流程"占位节点（导入的历史数据没有审批快照时，占住审批段那一格）。
   ⚠️ 不写死宽度：它也是一个 flex 项，跟着弹性规则走（写死会在这个"只有一格"的
      情况下把它拉得特别宽，与旁边的付款节点不成比例）。 */
.af-step__n--empty { flex: 1 1 140px; max-width: 200px; }
.af-step__dot--empty {
  background: var(--color-surface-2);
  border-style: dashed;
  color: var(--color-muted);
}

.af-step { display: flex; align-items: flex-start; }

/* ⚠️ 节点宽度/伸缩只在**上面那条** `.af-step__n` 规则里定义（弹性，可容纳更多节点）。
   这里只放"内部排版"三项 —— 原来这里也写了 `width: 104px; flex-shrink: 0;`，
   两条规则同名会**后覆盖前**（CSS 后来居上），弹性的那条直接失效且不报错
   （表现是"改了 CSS 但布局没变"）。要改宽度请改上面那条。 */
.af-step__n {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}

.af-step__dot {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  background: var(--color-surface);
  color: var(--color-muted);
  border: 2px solid var(--color-border);
  box-sizing: border-box;
}

.af-step__n.is-done .af-step__dot {
  background: var(--color-success);
  border-color: var(--color-success);
  color: #fff;
}
.af-step__n.is-rejected .af-step__dot {
  background: var(--color-danger);
  border-color: var(--color-danger);
  color: #fff;
}
/* 进行中：橙色圈 + 一圈光晕。
   ⚠️ 光晕是"当前节点"最直观的表达 —— 只靠颜色深浅（橙 vs 灰）区分度不够，
      加一圈同色淡晕后视觉重量明显不同，扫一眼就知道停在哪。 */
.af-step__n.is-current .af-step__dot {
  background: var(--color-warning-bg);
  border-color: var(--color-warning);
  color: var(--color-warning-text);
  box-shadow: 0 0 0 4px var(--color-warning-bg);
}

.af-step__t {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-fg);
  margin-top: var(--space-2);
}
.af-step__n.is-current .af-step__t { color: var(--color-warning-text); }
.af-step__m {
  font-size: var(--font-size-xs);
  color: var(--color-fg-2);
  margin-top: 2px;
  /* 审批人可能很长（"张三、李四、王五"）⇒ 允许折行但不撑破节点宽度 */
  word-break: break-all;
}
.af-step__d {
  font-size: var(--font-size-xs);
  color: var(--color-muted);
  margin-top: 1px;
}
.af-step__n.is-rejected .af-step__d { color: var(--color-danger); }

/* 连接线：与圆点垂直居中（圆点 28px ⇒ 上边距 13px） */
.af-step__bar {
  flex: 1;
  height: 2px;
  min-width: 16px;
  background: var(--color-border);
  margin-top: 13px;
}
.af-step__bar.is-done { background: var(--color-success); }
/* ⚠️ 付款段的连接线（含桥接线）**不用绿** —— 桥接线的实线色在上面单独给了绿
   （它表达的是"审批这一关过了"，属于**审批的语言**，用绿是对的）。
   而付款**段内**的连接线表示"这一步办完了"，用主色蓝，与它的节点同色。 */
.af-step__bar--pay.is-done { background: var(--color-accent); }

/* ══════════════════════════════════════════════════════════════════════════
   付款段配色 = **主色蓝系**（与审批的绿系区分开）—— 乐哥要的"两个阶段不同颜色"
   ──────────────────────────────────────────────────────────────────────────
   ⚠️ 为什么付款不用绿：绿在全站语义是"已完成/通过"，而付款的"完成"与审批的"通过"
      是两件事 —— 同色会让人把两段读成一段的延续（那正是"并成一行"最需要避免的误读）。

   ⛔⛔ **这一块必须放在文件靠下的位置**（在审批三态配色之后）——
      付款的选择器 `.af-step__n--pay.is-*` 与审批的 `.af-step__n.is-*`
      **特异性完全相同**（3 个类），此时**后写的生效**。
      本轮实测踩到：先写付款蓝、后写审批绿 ⇒ 付款已完成的节点**仍然显示绿色**
      （不报错，且只有"造一张付款已完成的单"才看得出来 ——
       探针第一次跑就红了这条，靠的就是"单独跑一趟已入账单"）。
      ⇒ 若日后调整本文件的顺序，**不要把这一块移到审批配色之前**；
        真需要移，就把选择器改成 `.af-step .af-step__n--pay.is-done .af-step__dot`
        这类更高特异性的写法（但那样更脆，不推荐）。
   ========================================================================== */
.af-step__n--pay.is-done .af-step__dot {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: var(--color-accent-on);
}
.af-step__n--pay.is-current .af-step__dot {
  background: var(--color-accent-bg);
  border-color: var(--color-accent);
  color: var(--color-accent-text);
  box-shadow: 0 0 0 4px var(--color-accent-bg);
}
.af-step__n--pay.is-current .af-step__t { color: var(--color-accent-text); }
/* 付款"待办"节点的说明文字也用主色（与橙色的审批待办区分开） */
.af-step__n--pay.is-current .af-step__d { color: var(--color-accent-text); }

@media (max-width: 768px) {
  /* 窄屏：横向 4 道在手机上放不下，硬挤会把节点名压断 ⇒ 转纵向。
     纵向时隐藏"审批人/时间"（信息密度让位给可读性），状态仍靠圆点区分。 */
  .af-step-card { padding: var(--space-4) var(--space-4); }
  .af-step { flex-direction: column; }
  .af-step__n {
    flex-direction: row;
    align-items: center;
    gap: var(--space-2);
    width: 100%;
    text-align: left;
  }
  .af-step__t { margin-top: 0; }
  .af-step__m, .af-step__d { margin-top: 0; margin-left: auto; }
  .af-step__bar {
    width: 2px;
    height: 18px;
    flex: none;
    min-width: 0;
    margin: 2px 0 2px 13px;
  }
}

/* ══════════════════════════════════════════════════════════════════════════
   报销人（头像 + 姓名）—— 乐哥 2026-09-21：「报销人得和达播台一样，有飞书头像（没有的用首字）」
   ──────────────────────────────────────────────────────────────────────────
   列表里用 `.cell-person`（**达播台的标准件**，table.css 里定义，含 28px 圆形头像、
   无图时姓名字首兜底、名字与徽章同一行的排布）—— 本文件不重写它，只做两处"在财务表格里"的适配。
   ══════════════════════════════════════════════════════════════════════════ */

/* ① 列表行更紧凑一点：财务表一屏行数多，28px 头像会把行高明显顶起来。
      收 4px 后与原来无头像时的行高接近，同时保留头像的可辨识度。 */
.fin td .cell-person__avatar {
  width: 24px;
  height: 24px;
  font-size: var(--font-size-xs);
}

/* ② 详情页头部那处「报销人」是**行内**展示（`<b>` 里），不是表格单元格 ——
      `.cell-person` 是 flex 块，直接塞进 <b> 会把基线与后续文字错开。
      这里改成 inline-flex + 与文字垂直居中对齐。 */
.fin-person {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-weight: var(--font-weight-medium);
}
.fin-person .cell-person__avatar {
  width: 24px;
  height: 24px;
  font-size: var(--font-size-xs);
  vertical-align: middle;
}

/* ══════════════════════════════════════════════════════════════════════════
   统一提报 / 付款台账（2026-09-22《方案-报销流程重构》第 5~7 步）
   ──────────────────────────────────────────────────────────────────────────
   ⚠️ 全部带 `eb-` / `ebd-` 前缀，**不复用** `.fin-*` —— 那一套是列表/详情的通用件，
      本组是"勾选汇总"这类新形态（选中汇总条、生成弹窗、详情操作条），
      蹭用公共类会在别的页面上产生意外样式（本项目在 cost-chart 上定过同一条纪律）。
   ⚠️ 颜色一律走 design-tokens 变量（`--color-*` / `--space-*`），不写死色值 ——
      写死会在暗色主题下变成看不清的浅底白字。
   ══════════════════════════════════════════════════════════════════════════ */

/* ── 选中汇总条（待提报页顶部，跟着勾选实时变）──
   ⚠️ `position: sticky` 而不是 fixed：它只在**自己那一屏**可见时粘住，
      滚到列表底部时不遮挡内容（本项目在提单页的"费用汇总"上定过同一条）。 */
.eb-summary {
  position: sticky;
  top: 0;
  z-index: 2;
  margin-bottom: var(--space-3);
}
.eb-bar {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-4);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
}
.eb-bar__k { font-size: var(--font-size-sm); color: var(--color-fg-2); }
.eb-bar__u { font-size: var(--font-size-sm); color: var(--color-fg-2); margin-right: var(--space-3); }
.eb-bar__n { font-size: var(--font-size-lg); font-weight: var(--font-weight-semibold); color: var(--color-fg); }
/* ⚠️ 金额用等宽数字：一列金额上下对齐才不会跳动（本项目表格 `.is-num` 同款理由） */
.eb-bar__v {
  font-size: var(--font-size-lg);
  font-weight: var(--font-weight-semibold);
  color: var(--color-fg);
  font-variant-numeric: tabular-nums;
}
.eb-bar__btns { margin-left: auto; }

/* ── 生成弹窗 / 打款弹窗的表单块 ── */
.eb-dlg__sum {
  padding: var(--space-3);
  margin-bottom: var(--space-4);
  background: var(--color-gray-50);
  border-radius: var(--radius-sm);
  font-size: var(--font-size-sm);
  color: var(--color-fg-2);
}
.eb-dlg__sum b { color: var(--color-fg); font-variant-numeric: tabular-nums; }
/* ⚠️ 警告条用 warning 色族的**浅底**，不是纯红 —— 它是"你先看看"，不是"出错了"。
   红色留给真正的失败（本项目在状态色档上定过：danger 只给"出问题了"）。 */
/* ⛔ 2026-09-27 修：这两条原来写成 `var(--color-warning-bg));`（**多一个右括号**）⇒
   浏览器把它们当语法错误**整条丢弃** ⇒ 结果是这条「审批/风险」提示条**没有底色、没有左侧色条**，
   看起来和普通正文一样（而它是用来提醒"审批中、不能打款"的，没样式就容易被忽略）。
   ⚠️ 判据：`calc(var(--a) + var(--b))` 结尾的 `))` 是**正常**的（一个闭 var、一个闭 calc）；
      只有「**单个 var() 后面还多一个 `)`**」才是笔误 —— 别把 calc 那批一起"修"了。
   ⚠️ 同类笔误全站还有约 15 处（`pricing-compare.css` / `layout.css` / `components.css`），
      属于**别的模块**，本次**不动**（修好它们 = 那些样式会突然生效、视觉会变，得单独评估）。 */
.eb-warn {
  padding: var(--space-3);
  margin-bottom: var(--space-3);
  background: var(--color-warning-bg);
  border-left: 3px solid var(--color-warning);
  border-radius: var(--radius-sm);
  font-size: var(--font-size-sm);
  color: var(--color-fg);
}
/* 必填星号 —— 与全站其它表单一致 */
.eb-dlg .req { color: var(--color-danger); margin-left: 2px; }

/* ── 提报单详情：头部右侧的状态标签 + 操作条 ── */
.ebd-head__r { display: flex; align-items: center; gap: var(--space-3); }
.ebd-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-bottom: var(--space-4);
}

/* ── 提报单详情：费用类型构成卡（2026-09-23）─────────────────────────────
   乐哥：「费用类型，看能不搞个图表展示出来，这样老板看更直观」。
   ⚠️ 卡头**不给 `.table-toolbar`**：那个类的样式是 `justify-content: space-between`
      ⇒ 两个子元素会被推到行的两端（"标题左、说明飞最右"）。
      财务总览页的部门 tab 就因为这个"跑到标题右边"被乐哥框过（见 finance.js 的注释）。
      这里要的是"标题 + 紧跟一句说明"，所以用自己的一行 flex、`gap` 控制间距。
   ⚠️ 卡头下方的图表区留 `padding`（`CostChart` 自己不带外距）——
      不留的话环会贴着卡边。 */
.ebd-chart { padding: var(--space-4); margin-bottom: var(--space-4); }
.ebd-chart__hd {
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  margin-bottom: var(--space-3);
}
.ebd-chart__t { font-size: var(--font-size-md); font-weight: var(--font-weight-medium); color: var(--color-fg); }
.ebd-chart__h { font-size: var(--font-size-xs); color: var(--color-muted); }

/* ══════════════════════════════════════════════════════════════════════════
   费用构成卡：**并排两栏**（左=按费用类型，右=按报销人） 2026-09-23 深夜
   ──────────────────────────────────────────────────────────────────────────
   乐哥：「图表右边不是还有一片空的吗，可以做柱状图，展示每个提报人，
          报销得费用金额（里面不同费用类型用不同费用颜色占据）」
   （原来只有一张环形图，实测 1060px 宽的卡里右侧空着约 400px。）

   ⚠️⚠️ 为什么必须 `flex-wrap: wrap`：
      两栏的最小可用宽度加起来约 920px（环 180 + 列表 ~320 + 柱图 ~380 + 间距）。
      不给 wrap 时窄屏会把**环形图挤扁**（`.cc-list { min-width: 280px }` 会顶住不让，
      结果挤压环本身）—— 本项目在"并排布局点一下会多出一块"上踩过同类坑
      （见 cost-chart.css 里 `.cb-flex` 那段的说明）。
   ⚠️ 两栏的 `flex-basis` 是**实测出来的**：卡内宽约 1020px 时
      左 540 + 间距 24 + 右 440 = 1004 ⇒ 恰好并排且两边都不挤。
      改这两个数之前先量一下环右侧列表那三列（名称/金额/占比）会不会被压变形。
   ⚠️ 右栏（柱图）**不给 `max-width`**：它就是来吃"那片空"的，
      限宽等于又把空白还回去。 */
.ebd-charts { display: flex; gap: var(--space-6); align-items: flex-start; flex-wrap: wrap; }
.ebd-charts__c { min-width: 0; }
.ebd-charts__c--type { flex: 1 1 540px; }
.ebd-charts__c--who { flex: 1 1 440px; }
/* 右栏小标题（左栏的小标题由 CostChart 自己的分组标题给，两边视觉一致） */
.ebd-subhd { display: flex; align-items: baseline; gap: var(--space-3); margin-bottom: var(--space-2); }
.ebd-subhd__t { font-size: var(--font-size-sm); font-weight: var(--font-weight-medium); color: var(--color-fg); }
.ebd-subhd__h { font-size: var(--font-size-xs); color: var(--color-muted); }

/* 柱图的画布容器。
   ⚠️⚠️ **必须给固定高度**：Chart.js 用 `maintainAspectRatio: false` 时会去量父容器的高度，
      父容器 height:auto ⇒ 画布塌成 0 高 ⇒ 图看不见，而且**不报任何错**。
   ⚠️ 高度按"给柱顶合计标注 + X 轴人名 + 底部图例"留够：实测 220px 里
      绘图区约 150px，4 个人 3 个类型时柱高差异仍看得清。 */
.ebd-canvas { position: relative; height: 220px; }
/* 空态（组件缺失 / 字段不存在 / 确实为空）在容器里**居中**——
   顶在左上角会像是"图渲染失败后残留的一行字"。 */
.ebd-canvas .cc-empty { display: flex; align-items: center; justify-content: center; height: 100%; }
/* ⚠️⚠️ 「作废」用 ghost + danger 文字（不是实心红按钮）：它是破坏性但低频的动作，
   实心红会让它比「登记打款」还抢眼，反而诱导误点。
   ⛔⛔ 但**只改 `color` 不改 `background` 是个真事故**（2026-09-22 实测，截图才看出来）：
      `.btn--danger` 本身是**实心红底 + 白字**（`--button-danger-bg` = `--color-danger` = #E41E3F、
      `--button-danger-fg` = #FFFFFF）。我只覆盖了 `color` ⇒ 字也变 #E41E3F
      ⇒ **红底红字、对比度 1:1、按钮上的字完全看不见**（页面上出现一个莫名的红色方块）。
      ⚠️ 这个 bug 的隐蔽之处：文字的 `innerText` **是有的**（"作废"），
        任何"按钮里有文字吗"的断言都会通过 —— 只有**算文字色与背景色的对比度**才抓得到。
      ⇒ 三条都要写全：背景（常态）、背景（hover）、以及 `filter: none`
        （不写的话 `.btn--danger:hover` 的 `brightness(0.9)` 会把底色压暗，
          在浅红底上不易察觉但会让 hover 与常态的差别变糊）。 */
.ebd-actions .btn--danger {
  background: var(--button-ghost-bg);          /* transparent ⇒ 落在页面白底上 */
  border-color: var(--color-border);
  color: var(--color-danger);
}
/* ⚠️ 用 `:not(:disabled)` 与 components.css 里的 `.btn--danger:hover:not(:disabled)` 对齐特异性
   —— 平手时靠加载顺序（本文件在后）取胜，写成不带 `:not()` 的话会被那条反超。 */
.ebd-actions .btn--danger:hover:not(:disabled) {
  background: var(--color-danger-bg);
  border-color: var(--color-danger);
  color: var(--color-danger);
  filter: none;
}

/* ── 详情的关键信息区（键值对网格）──
   ⚠️ `auto-fill + minmax` 让窄屏自动折行，不用写媒体查询。 */
.fin-kv {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: var(--space-3) var(--space-4);
  padding: var(--space-4);
  margin-bottom: var(--space-4);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
}
.fin-kv__i { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.fin-kv__k { font-size: var(--font-size-xs); color: var(--color-fg-2); }
.fin-kv__v {
  font-size: var(--font-size-sm);
  color: var(--color-fg);
  font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
}

/* ══════════════════════════════════════════════════════════════════════════
   报销附件（发票 / 支付凭证）缩略图 —— `.ea-*`（2026-09-23）
   渲染实现见 `public/js/expense-attach.js`（**全站唯一实现**）
   ──────────────────────────────────────────────────────────────────────────
   乐哥：「提的报销单里的附件，就是发票还有付款凭证的，应该在对应的那一行
   报销明细上看吧？这样费用才能一一对应」

   ⚠️ 为什么要"分组标签 + 缩略图"两层，而不是只有一排图：
      发票和付款凭证是**两类不同的东西**（票证明花了什么钱、凭证证明这笔钱付了），
      混在一排图里财务分不清哪张是哪类 ⇒ 每组前面标一个「发票 2」「凭证 1」。
   ⚠️ 尺寸**只在这里定**（JS 只负责给语义，不给尺寸）：
      同一套缩略图要出现在两种容器里 —— 表格里（列窄）和详情页大卡里（宽），
      尺寸写进 JS 就会与别处各写一套；写在这里、用容器选择器分流。
   ⚠️ `.ea-cell` 是表格里那一格的类：给它在窄列里一个**下限宽度**，
      否则缩略图会被压成一条线（表格自动布局会优先挤"没有最小宽度"的列）。 */
.ea-wrap { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.ea-set { display: inline-flex; align-items: center; gap: 4px; }
.ea-set__lab {
  font-size: var(--font-size-xs);
  color: var(--color-muted);
  white-space: nowrap;
}
.ea-thumb {
  display: block;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface-2);
  overflow: hidden;
  cursor: pointer;
  /* ⚠️ `<button>` 自带 padding / 字体 / 居中 ⇒ 必须 reset 回"一张图"的样子，
     否则缩略图会胖一圈、边框与图片之间出现缝（这类**静默外观漂移**最难发现）。 */
  font: inherit;
  line-height: 0;
}
.ea-thumb img { display: block; width: 100%; height: 100%; object-fit: cover; }
.ea-thumb:hover { border-color: var(--color-accent); }
.ea-thumb:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 1px; }
.ea-more {
  font-size: var(--font-size-xs);
  color: var(--color-muted);
  white-space: nowrap;
}
.ea-empty, .ea-none { color: var(--color-muted); }

/* 表格里的附件格：缩略图压小一号（表格行高有限，44px 会把行撑高、整表节奏变乱） */
.table .ea-cell { min-width: 96px; }
.table .ea-thumb { width: 32px; height: 32px; }
.table .ea-set__lab { font-size: 11px; }
/* ⭐ 2026-09-24：表格这一格里**两类附件挨得太挤** —— 组内（标签↔图、图↔图）与
   组间（发票组↔凭证组）都还是详情页那套 4px/6px，而这里是**行内小图**、
   尺寸只有详情页的 0.7 倍 ⇒ 同样的间距在小尺寸下看着"糊成一坨"（实测截图），
   财务扫一行时要花时间分辨"哪几张是票、哪几张是证"。
   ⚠️ 只加大 `.ea-cell` 里的间距，**不动全局 `.ea-*`** —— 详情页那些大卡里的
      44px 图用 6px 间距是合适的，全局改会把那边也改挤。
   ⚠️ 组间(12px)必须明显大于组内(6px)：2 倍差距才看得出"这是两组"，
      1.5 倍在这种小尺寸下仍然会被读成一排。 */
.table .ea-cell .ea-wrap { gap: 12px; }
.table .ea-cell .ea-set { gap: 6px; }

/* ── 旧的单图样式（`.fin-pic*`）已由上面 `.ea-*` 取代 ──
   `.fin-pics` / `.fin-picbox*` 仍是**容器**（在 `finance.js` 的「发票 / 凭证」区用），
   但单个缩略图 `.fin-pic` 已无消费方（改为 `ExpenseAttach.thumbs()` 产出 `.ea-thumb`）。
   ⚠️ 保留 `.fin-pic--none`：它是"只有飞书文件码、页面渲不了图"那一种的**说明块**，
      在 `.ea-*` 里改成了"不渲染 + 点开时提示"，但本类可能被别处引用，故留着不删。 */

/* 「只有飞书文件码」时的文件占位按钮（页面渲不了图，但必须可点、有说明）
   —— 与图片缩略图同尺寸，视觉上不会让该组的排列错位。 */
.ea-thumb--file {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--color-muted);
  background: var(--color-surface-2);
  border-style: dashed;
}
.ea-thumb--file:hover { color: var(--color-accent); border-color: var(--color-accent); }

/* ══════════════════════════════════════════════════════════════════════════
   附件大图查看器 —— `.ea-view*`（2026-09-24）
   渲染实现见 `public/js/expense-attach.js` 的 `openViewer()`（**全站唯一实现**）
   ──────────────────────────────────────────────────────────────────────────
   乐哥：「报销详情查快附件，同一个报销明细的，能不能查看的时候左右键快速切换，
          这样就不用再一个个点开关闭看了」

   ⚠️ 为什么要"两侧悬浮箭头"而不是"底部一排按钮"：
      看大图时视线在图上，箭头贴着图左右两侧最省眼动（这也是图片查看器的通用做法）。
      同时键盘 ←→ 是主路径，箭头是给鼠标用户的等价入口。
   ⚠️ 尺寸只在这里定（JS 只给语义）—— 与 `.ea-thumb` 同一条纪律。
   ⚠️ 图片**必须** `max-height` 限制（否则竖长的发票会把弹层顶到屏幕外、
      底部条和关闭按钮都看不到）。用 vh 而不是 px，屏幕高矮都合适。
   ══════════════════════════════════════════════════════════════════════════ */
.ea-view { display: flex; flex-direction: column; gap: var(--space-3); }

/* 舞台：图 + 两侧箭头。`position: relative` 是箭头定位的锚点。 */
.ea-view__stage {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 220px;
  padding: var(--space-2);
  background: var(--color-surface-2);
  border-radius: var(--radius-md);
}
.ea-view__pic { display: flex; flex-direction: column; align-items: center; gap: var(--space-2); }
.ea-view__img {
  display: block;
  max-width: 100%;
  max-height: 62vh;          /* ⚠️ 不限制会把底部信息条顶出视口 */
  object-fit: contain;
  border-radius: var(--radius-sm);
}
/* 「只有缩略图（原件未留存）」的注明 —— 放在图下方，不遮图 */
.ea-view__note {
  font-size: var(--font-size-xs);
  color: var(--color-muted);
}

/* 「原件在飞书」的说明块：渲染不了图（文件码不是图片地址），但必须说清去哪儿看 */
.ea-view__none {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-8) var(--space-4);
  font-size: var(--font-size-sm);
  color: var(--color-fg-2);
  text-align: center;
}
.ea-view__none-sub { font-size: var(--font-size-xs); color: var(--color-muted); }

/* 两侧导航箭头。`top: 50%` + translateY 垂直居中（图高会变，不能写死 top）。 */
.ea-view__nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 36px;
  height: 36px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-full);
  color: var(--color-fg-2);
  cursor: pointer;
  box-shadow: var(--shadow-sm);
  /* ⚠️ `<button>` 自带字体 ⇒ 不 reset 图标会与别处的 icon-btn 不一致 */
  font: inherit;
}
.ea-view__nav--prev { left: var(--space-2); }
.ea-view__nav--next { right: var(--space-2); }
.ea-view__nav:hover:not(:disabled) {
  border-color: var(--color-accent);
  color: var(--color-accent-text);
}
.ea-view__nav:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 1px; }
/* 到边界：**禁用**而不是隐藏 —— 灰色箭头表达"到头了"，
   比"按钮消失"更让人确信"这一笔的附件都看过了"（财务核对怕漏看）。 */
.ea-view__nav:disabled { opacity: .35; cursor: default; box-shadow: none; }

/* 底部信息条：类型胶囊 + 文件名 + 快捷键提示 */
.ea-view__bar {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--font-size-xs);
  color: var(--color-muted);
}
.ea-view__pill {
  flex-shrink: 0;
  padding: 1px 8px;
  border-radius: var(--radius-sm);
  background: var(--color-accent-bg);
  color: var(--color-accent-text);
  font-weight: var(--font-weight-medium);
}
/* 凭证用中性色（发票才是财务第一眼要看的，与缩略图组的语言一致） */
.ea-view__pill--proof { background: var(--color-surface-2); color: var(--color-muted); }
.ea-view__name {
  color: var(--color-fg-2);
  /* 文件名可能很长（"微信支付截图-20260917-北京.jpg"）⇒ 截断而不是换行挤掉提示 */
  max-width: 46%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ea-view__hint { margin-left: auto; flex-shrink: 0; }
/* `<kbd>`：让人一眼看出"这是键盘按键"而不是正文里的箭头符号 */
.ea-view__hint kbd {
  display: inline-block;
  min-width: 18px;
  padding: 0 4px;
  border: 1px solid var(--color-border);
  border-bottom-width: 2px;
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  color: var(--color-fg-2);
  font-family: inherit;
  font-size: var(--font-size-xs);
  text-align: center;
}
/* 这一笔的说明（"第 1 笔 · 餐饮 · ¥2,680.00"）—— 切换时始终知道在看哪一笔 */
.ea-view__scope {
  font-size: var(--font-size-xs);
  color: var(--color-muted);
  padding-top: var(--space-1);
  border-top: 1px solid var(--color-border-soft);
}

/* 「在新标签打开」在"没有本地原件"时是禁用态（点了会打开空白页 ⇒ 那是假链接）。
   ⚠️ 用 `pointer-events: none` 而不只是视觉置灰 —— 假链接点了有反应比没反应更糟。 */
.btn.is-disabled { opacity: .5; pointer-events: none; }

/* 窄屏：两侧箭头会压到图上（图本身已经占满宽度）⇒ 改成静态排在图下方一行。 */
@media (max-width: 768px) {
  .ea-view__stage { flex-direction: column; gap: var(--space-2); }
  .ea-view__nav { position: static; transform: none; }
  .ea-view__nav--prev { order: 2; }
  .ea-view__nav--next { order: 3; }
  .ea-view__bar { flex-wrap: wrap; }
  .ea-view__hint { margin-left: 0; }
  .ea-view__name { max-width: 100%; }
}
